diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-10-07 17:49:05 +0900 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-10-07 17:49:05 +0900 |
commit | 0b8e74c6f44094189dbe78baf4101acc7570c6af (patch) | |
tree | 6440561d09fb71ba5928664604ec92f29940be6b /drivers | |
parent | 7f60ba388f5b9dd8b0da463b394412dace3ab814 (diff) | |
parent | bd0d10498826ed150da5e4c45baf8b9c7088fb71 (diff) | |
download | lwn-0b8e74c6f44094189dbe78baf4101acc7570c6af.tar.gz lwn-0b8e74c6f44094189dbe78baf4101acc7570c6af.zip |
Merge branch 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media
Pull media updates from Mauro Carvalho Chehab:
"The first part of the media updates for Kernel 3.7.
This series contain:
- A major tree renaming patch series: now, drivers are organized
internally by their used bus, instead of by V4L2 and/or DVB API,
providing a cleaner driver location for hybrid drivers that
implement both APIs, and allowing to cleanup the Kconfig items and
make them more intuitive for the end user;
- Media Kernel developers are typically very lazy with their duties
of keeping the MAINTAINERS entries for their drivers updated. As
now the tree is more organized, we're doing an effort to add/update
those entries for the drivers that aren't currently orphan;
- Several DVB USB drivers got moved to a new DVB USB v2 core; the new
core fixes several bugs (as the existing one that got bitroted).
Now, suspend/resume finally started to work fine (at least with
some devices - we should expect more work with regards to it);
- added multistream support for DVB-T2, and unified the API for
DVB-S2 and ISDB-S. Backward binary support is preserved;
- as usual, a few new drivers, some V4L2 core improvements and lots
of drivers improvements and fixes.
There are some points to notice on this series:
1) you should expect a trivial merge conflict on your tree, with the
removal of Documentation/feature-removal-schedule.txt: this series
would be adding two additional entries there. I opted to not
rebase it due to this recent change;
2) With regards to the PCTV 520e udev-related breakage, I opted to
fix it in a way that the patches can be backported to 3.5 even
without your firmware fix patch. This way, Greg doesn't need to
rush backporting your patch (as there are still the firmware cache
and firmware path customization issues to be addressed there).
I'll send later a patch (likely after the end of the merge window)
reverting the rest of the DRX-K async firmware request, fully
restoring its original behaviour to allow media drivers to
initialize everything serialized as before for 3.7 and upper.
3) I'm planning to work on this weekend to test the DMABUF patches
for V4L2. The patches are on my queue for several Kernel cycles,
but, up to now, there is/was no way to test the series locally.
I have some concerns about this particular changeset with regards
to security issues, and with regards to the replacement of the old
VIDIOC_OVERLAY ioctl's that is broken on modern systems, due to
GPU drivers change. The Overlay API allows direct PCI2PCI
transfers from a media capture card into the GPU framebuffer, but
its API is crappy. Also, the only existing X11 driver that
implements it requires a XV extension that is not available
anymore on modern drivers. The DMABUF can do the same thing, but
with it is promising to be a properly-designed API. If I can
successfully test this series and be happy with it, I should be
asking you to pull them next week."
* 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (717 commits)
em28xx: regression fix: use DRX-K sync firmware requests on em28xx
drxk: allow loading firmware synchrousnously
em28xx: Make all em28xx extensions to be initialized asynchronously
[media] tda18271: properly report read errors in tda18271_get_id
[media] tda18271: delay IR & RF calibration until init() if delay_cal is set
[media] MAINTAINERS: add Michael Krufky as tda827x maintainer
[media] MAINTAINERS: add Michael Krufky as tda8290 maintainer
[media] MAINTAINERS: add Michael Krufky as cxusb maintainer
[media] MAINTAINERS: add Michael Krufky as lg2160 maintainer
[media] MAINTAINERS: add Michael Krufky as lgdt3305 maintainer
[media] MAINTAINERS: add Michael Krufky as mxl111sf maintainer
[media] MAINTAINERS: add Michael Krufky as mxl5007t maintainer
[media] MAINTAINERS: add Michael Krufky as tda18271 maintainer
[media] s5p-tv: Report only multi-plane capabilities in vidioc_querycap
[media] s5p-mfc: Fix misplaced return statement in s5p_mfc_suspend()
[media] exynos-gsc: Add missing static storage class specifiers
[media] exynos-gsc: Remove <linux/version.h> header file inclusion
[media] s5p-fimc: Fix incorrect condition in fimc_lite_reqbufs()
[media] s5p-tv: Fix potential NULL pointer dereference error
[media] s5k6aa: Fix possible NULL pointer dereference
...
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpio/gpio-bt8xx.c | 2 | ||||
-rw-r--r-- | drivers/media/Kconfig | 53 | ||||
-rw-r--r-- | drivers/media/Makefile | 23 | ||||
-rw-r--r-- | drivers/media/common/Kconfig | 12 | ||||
-rw-r--r-- | drivers/media/common/Makefile | 7 | ||||
-rw-r--r-- | drivers/media/common/b2c2/Kconfig | 28 | ||||
-rw-r--r-- | drivers/media/common/b2c2/Makefile | 8 | ||||
-rw-r--r-- | drivers/media/common/b2c2/flexcop-common.h (renamed from drivers/media/dvb/b2c2/flexcop-common.h) | 0 | ||||
-rw-r--r-- | drivers/media/common/b2c2/flexcop-eeprom.c (renamed from drivers/media/dvb/b2c2/flexcop-eeprom.c) | 0 | ||||
-rw-r--r-- | drivers/media/common/b2c2/flexcop-fe-tuner.c (renamed from drivers/media/dvb/b2c2/flexcop-fe-tuner.c) | 0 | ||||
-rw-r--r-- | drivers/media/common/b2c2/flexcop-hw-filter.c (renamed from drivers/media/dvb/b2c2/flexcop-hw-filter.c) | 0 | ||||
-rw-r--r-- | drivers/media/common/b2c2/flexcop-i2c.c (renamed from drivers/media/dvb/b2c2/flexcop-i2c.c) | 0 | ||||
-rw-r--r-- | drivers/media/common/b2c2/flexcop-misc.c (renamed from drivers/media/dvb/b2c2/flexcop-misc.c) | 0 | ||||
-rw-r--r-- | drivers/media/common/b2c2/flexcop-reg.h (renamed from drivers/media/dvb/b2c2/flexcop-reg.h) | 0 | ||||
-rw-r--r-- | drivers/media/common/b2c2/flexcop-sram.c (renamed from drivers/media/dvb/b2c2/flexcop-sram.c) | 0 | ||||
-rw-r--r-- | drivers/media/common/b2c2/flexcop.c (renamed from drivers/media/dvb/b2c2/flexcop.c) | 1 | ||||
-rw-r--r-- | drivers/media/common/b2c2/flexcop.h (renamed from drivers/media/dvb/b2c2/flexcop.h) | 0 | ||||
-rw-r--r-- | drivers/media/common/b2c2/flexcop_ibi_value_be.h (renamed from drivers/media/dvb/b2c2/flexcop_ibi_value_be.h) | 0 | ||||
-rw-r--r-- | drivers/media/common/b2c2/flexcop_ibi_value_le.h (renamed from drivers/media/dvb/b2c2/flexcop_ibi_value_le.h) | 0 | ||||
-rw-r--r-- | drivers/media/common/saa7146/Kconfig | 9 | ||||
-rw-r--r-- | drivers/media/common/saa7146/Makefile | 5 | ||||
-rw-r--r-- | drivers/media/common/saa7146/saa7146_core.c (renamed from drivers/media/common/saa7146_core.c) | 8 | ||||
-rw-r--r-- | drivers/media/common/saa7146/saa7146_fops.c (renamed from drivers/media/common/saa7146_fops.c) | 55 | ||||
-rw-r--r-- | drivers/media/common/saa7146/saa7146_hlp.c (renamed from drivers/media/common/saa7146_hlp.c) | 0 | ||||
-rw-r--r-- | drivers/media/common/saa7146/saa7146_i2c.c (renamed from drivers/media/common/saa7146_i2c.c) | 0 | ||||
-rw-r--r-- | drivers/media/common/saa7146/saa7146_vbi.c (renamed from drivers/media/common/saa7146_vbi.c) | 0 | ||||
-rw-r--r-- | drivers/media/common/saa7146/saa7146_video.c (renamed from drivers/media/common/saa7146_video.c) | 2 | ||||
-rw-r--r-- | drivers/media/common/siano/Kconfig | 17 | ||||
-rw-r--r-- | drivers/media/common/siano/Makefile (renamed from drivers/media/dvb/siano/Makefile) | 6 | ||||
-rw-r--r-- | drivers/media/common/siano/sms-cards.c (renamed from drivers/media/dvb/siano/sms-cards.c) | 0 | ||||
-rw-r--r-- | drivers/media/common/siano/sms-cards.h (renamed from drivers/media/dvb/siano/sms-cards.h) | 0 | ||||
-rw-r--r-- | drivers/media/common/siano/smscoreapi.c (renamed from drivers/media/dvb/siano/smscoreapi.c) | 0 | ||||
-rw-r--r-- | drivers/media/common/siano/smscoreapi.h (renamed from drivers/media/dvb/siano/smscoreapi.h) | 0 | ||||
-rw-r--r-- | drivers/media/common/siano/smsdvb.c (renamed from drivers/media/dvb/siano/smsdvb.c) | 0 | ||||
-rw-r--r-- | drivers/media/common/siano/smsendian.c (renamed from drivers/media/dvb/siano/smsendian.c) | 0 | ||||
-rw-r--r-- | drivers/media/common/siano/smsendian.h (renamed from drivers/media/dvb/siano/smsendian.h) | 0 | ||||
-rw-r--r-- | drivers/media/common/siano/smsir.c (renamed from drivers/media/dvb/siano/smsir.c) | 0 | ||||
-rw-r--r-- | drivers/media/common/siano/smsir.h (renamed from drivers/media/dvb/siano/smsir.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-core/Kconfig | 29 | ||||
-rw-r--r-- | drivers/media/dvb-core/Makefile (renamed from drivers/media/dvb/dvb-core/Makefile) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-core/demux.h (renamed from drivers/media/dvb/dvb-core/demux.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-core/dmxdev.c (renamed from drivers/media/dvb/dvb-core/dmxdev.c) | 4 | ||||
-rw-r--r-- | drivers/media/dvb-core/dmxdev.h (renamed from drivers/media/dvb/dvb-core/dmxdev.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-core/dvb-usb-ids.h (renamed from drivers/media/dvb/dvb-usb/dvb-usb-ids.h) | 3 | ||||
-rw-r--r-- | drivers/media/dvb-core/dvb_ca_en50221.c (renamed from drivers/media/dvb/dvb-core/dvb_ca_en50221.c) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-core/dvb_ca_en50221.h (renamed from drivers/media/dvb/dvb-core/dvb_ca_en50221.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-core/dvb_demux.c (renamed from drivers/media/dvb/dvb-core/dvb_demux.c) | 29 | ||||
-rw-r--r-- | drivers/media/dvb-core/dvb_demux.h (renamed from drivers/media/dvb/dvb-core/dvb_demux.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-core/dvb_filter.c (renamed from drivers/media/dvb/dvb-core/dvb_filter.c) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-core/dvb_filter.h (renamed from drivers/media/dvb/dvb-core/dvb_filter.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-core/dvb_frontend.c (renamed from drivers/media/dvb/dvb-core/dvb_frontend.c) | 368 | ||||
-rw-r--r-- | drivers/media/dvb-core/dvb_frontend.h (renamed from drivers/media/dvb/dvb-core/dvb_frontend.h) | 12 | ||||
-rw-r--r-- | drivers/media/dvb-core/dvb_math.c (renamed from drivers/media/dvb/dvb-core/dvb_math.c) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-core/dvb_math.h (renamed from drivers/media/dvb/dvb-core/dvb_math.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-core/dvb_net.c (renamed from drivers/media/dvb/dvb-core/dvb_net.c) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-core/dvb_net.h (renamed from drivers/media/dvb/dvb-core/dvb_net.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-core/dvb_ringbuffer.c (renamed from drivers/media/dvb/dvb-core/dvb_ringbuffer.c) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-core/dvb_ringbuffer.h (renamed from drivers/media/dvb/dvb-core/dvb_ringbuffer.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-core/dvbdev.c (renamed from drivers/media/dvb/dvb-core/dvbdev.c) | 2 | ||||
-rw-r--r-- | drivers/media/dvb-core/dvbdev.h (renamed from drivers/media/dvb/dvb-core/dvbdev.h) | 26 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/Kconfig (renamed from drivers/media/dvb/frontends/Kconfig) | 195 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/Makefile (renamed from drivers/media/dvb/frontends/Makefile) | 12 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/a8293.c (renamed from drivers/media/dvb/frontends/a8293.c) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/a8293.h (renamed from drivers/media/dvb/frontends/a8293.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/af9013.c (renamed from drivers/media/dvb/frontends/af9013.c) | 158 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/af9013.h (renamed from drivers/media/dvb/frontends/af9013.h) | 2 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/af9013_priv.h (renamed from drivers/media/dvb/frontends/af9013_priv.h) | 15 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/af9033.c (renamed from drivers/media/dvb/frontends/af9033.c) | 96 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/af9033.h (renamed from drivers/media/dvb/frontends/af9033.h) | 3 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/af9033_priv.h (renamed from drivers/media/dvb/frontends/af9033_priv.h) | 37 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/atbm8830.c (renamed from drivers/media/dvb/frontends/atbm8830.c) | 2 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/atbm8830.h (renamed from drivers/media/dvb/frontends/atbm8830.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/atbm8830_priv.h (renamed from drivers/media/dvb/frontends/atbm8830_priv.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/au8522.h (renamed from drivers/media/dvb/frontends/au8522.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/au8522_common.c (renamed from drivers/media/dvb/frontends/au8522_common.c) | 22 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/au8522_decoder.c (renamed from drivers/media/dvb/frontends/au8522_decoder.c) | 11 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/au8522_dig.c (renamed from drivers/media/dvb/frontends/au8522_dig.c) | 98 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/au8522_priv.h (renamed from drivers/media/dvb/frontends/au8522_priv.h) | 29 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/bcm3510.c (renamed from drivers/media/dvb/frontends/bcm3510.c) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/bcm3510.h (renamed from drivers/media/dvb/frontends/bcm3510.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/bcm3510_priv.h (renamed from drivers/media/dvb/frontends/bcm3510_priv.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/bsbe1-d01a.h (renamed from drivers/media/dvb/frontends/bsbe1-d01a.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/bsbe1.h (renamed from drivers/media/dvb/frontends/bsbe1.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/bsru6.h (renamed from drivers/media/dvb/frontends/bsru6.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/cx22700.c (renamed from drivers/media/dvb/frontends/cx22700.c) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/cx22700.h (renamed from drivers/media/dvb/frontends/cx22700.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/cx22702.c (renamed from drivers/media/dvb/frontends/cx22702.c) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/cx22702.h (renamed from drivers/media/dvb/frontends/cx22702.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/cx24110.c (renamed from drivers/media/dvb/frontends/cx24110.c) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/cx24110.h (renamed from drivers/media/dvb/frontends/cx24110.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/cx24113.c (renamed from drivers/media/dvb/frontends/cx24113.c) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/cx24113.h (renamed from drivers/media/dvb/frontends/cx24113.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/cx24116.c (renamed from drivers/media/dvb/frontends/cx24116.c) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/cx24116.h (renamed from drivers/media/dvb/frontends/cx24116.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/cx24123.c (renamed from drivers/media/dvb/frontends/cx24123.c) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/cx24123.h (renamed from drivers/media/dvb/frontends/cx24123.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/cxd2820r.h (renamed from drivers/media/dvb/frontends/cxd2820r.h) | 14 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/cxd2820r_c.c (renamed from drivers/media/dvb/frontends/cxd2820r_c.c) | 31 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/cxd2820r_core.c (renamed from drivers/media/dvb/frontends/cxd2820r_core.c) | 211 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/cxd2820r_priv.h (renamed from drivers/media/dvb/frontends/cxd2820r_priv.h) | 22 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/cxd2820r_t.c (renamed from drivers/media/dvb/frontends/cxd2820r_t.c) | 34 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/cxd2820r_t2.c (renamed from drivers/media/dvb/frontends/cxd2820r_t2.c) | 31 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/dib0070.c (renamed from drivers/media/dvb/frontends/dib0070.c) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/dib0070.h (renamed from drivers/media/dvb/frontends/dib0070.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/dib0090.c (renamed from drivers/media/dvb/frontends/dib0090.c) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/dib0090.h (renamed from drivers/media/dvb/frontends/dib0090.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/dib3000.h (renamed from drivers/media/dvb/frontends/dib3000.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/dib3000mb.c (renamed from drivers/media/dvb/frontends/dib3000mb.c) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/dib3000mb_priv.h (renamed from drivers/media/dvb/frontends/dib3000mb_priv.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/dib3000mc.c (renamed from drivers/media/dvb/frontends/dib3000mc.c) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/dib3000mc.h (renamed from drivers/media/dvb/frontends/dib3000mc.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/dib7000m.c (renamed from drivers/media/dvb/frontends/dib7000m.c) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/dib7000m.h (renamed from drivers/media/dvb/frontends/dib7000m.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/dib7000p.c (renamed from drivers/media/dvb/frontends/dib7000p.c) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/dib7000p.h (renamed from drivers/media/dvb/frontends/dib7000p.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/dib8000.c (renamed from drivers/media/dvb/frontends/dib8000.c) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/dib8000.h (renamed from drivers/media/dvb/frontends/dib8000.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/dib9000.c (renamed from drivers/media/dvb/frontends/dib9000.c) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/dib9000.h (renamed from drivers/media/dvb/frontends/dib9000.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/dibx000_common.c (renamed from drivers/media/dvb/frontends/dibx000_common.c) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/dibx000_common.h (renamed from drivers/media/dvb/frontends/dibx000_common.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/drxd.h (renamed from drivers/media/dvb/frontends/drxd.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/drxd_firm.c (renamed from drivers/media/dvb/frontends/drxd_firm.c) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/drxd_firm.h (renamed from drivers/media/dvb/frontends/drxd_firm.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/drxd_hard.c (renamed from drivers/media/dvb/frontends/drxd_hard.c) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/drxd_map_firm.h (renamed from drivers/media/dvb/frontends/drxd_map_firm.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/drxk.h (renamed from drivers/media/dvb/frontends/drxk.h) | 2 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/drxk_hard.c (renamed from drivers/media/dvb/frontends/drxk_hard.c) | 20 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/drxk_hard.h (renamed from drivers/media/dvb/frontends/drxk_hard.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/drxk_map.h (renamed from drivers/media/dvb/frontends/drxk_map.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/ds3000.c (renamed from drivers/media/dvb/frontends/ds3000.c) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/ds3000.h (renamed from drivers/media/dvb/frontends/ds3000.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/dvb-pll.c (renamed from drivers/media/dvb/frontends/dvb-pll.c) | 26 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/dvb-pll.h (renamed from drivers/media/dvb/frontends/dvb-pll.h) | 1 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/dvb_dummy_fe.c (renamed from drivers/media/dvb/frontends/dvb_dummy_fe.c) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/dvb_dummy_fe.h (renamed from drivers/media/dvb/frontends/dvb_dummy_fe.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/ec100.c (renamed from drivers/media/dvb/frontends/ec100.c) | 60 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/ec100.h (renamed from drivers/media/dvb/frontends/ec100.h) | 2 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/eds1547.h (renamed from drivers/media/dvb/frontends/eds1547.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/hd29l2.c (renamed from drivers/media/dvb/frontends/hd29l2.c) | 75 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/hd29l2.h (renamed from drivers/media/dvb/frontends/hd29l2.h) | 2 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/hd29l2_priv.h (renamed from drivers/media/dvb/frontends/hd29l2_priv.h) | 13 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/isl6405.c (renamed from drivers/media/dvb/frontends/isl6405.c) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/isl6405.h (renamed from drivers/media/dvb/frontends/isl6405.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/isl6421.c (renamed from drivers/media/dvb/frontends/isl6421.c) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/isl6421.h (renamed from drivers/media/dvb/frontends/isl6421.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/isl6423.c (renamed from drivers/media/dvb/frontends/isl6423.c) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/isl6423.h (renamed from drivers/media/dvb/frontends/isl6423.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/it913x-fe-priv.h (renamed from drivers/media/dvb/frontends/it913x-fe-priv.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/it913x-fe.c (renamed from drivers/media/dvb/frontends/it913x-fe.c) | 2 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/it913x-fe.h (renamed from drivers/media/dvb/frontends/it913x-fe.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/itd1000.c (renamed from drivers/media/dvb/frontends/itd1000.c) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/itd1000.h (renamed from drivers/media/dvb/frontends/itd1000.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/itd1000_priv.h (renamed from drivers/media/dvb/frontends/itd1000_priv.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/ix2505v.c (renamed from drivers/media/dvb/frontends/ix2505v.c) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/ix2505v.h (renamed from drivers/media/dvb/frontends/ix2505v.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/l64781.c (renamed from drivers/media/dvb/frontends/l64781.c) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/l64781.h (renamed from drivers/media/dvb/frontends/l64781.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/lg2160.c (renamed from drivers/media/dvb/frontends/lg2160.c) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/lg2160.h (renamed from drivers/media/dvb/frontends/lg2160.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/lgdt3305.c (renamed from drivers/media/dvb/frontends/lgdt3305.c) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/lgdt3305.h (renamed from drivers/media/dvb/frontends/lgdt3305.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/lgdt330x.c (renamed from drivers/media/dvb/frontends/lgdt330x.c) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/lgdt330x.h (renamed from drivers/media/dvb/frontends/lgdt330x.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/lgdt330x_priv.h (renamed from drivers/media/dvb/frontends/lgdt330x_priv.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/lgs8gl5.c (renamed from drivers/media/dvb/frontends/lgs8gl5.c) | 2 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/lgs8gl5.h (renamed from drivers/media/dvb/frontends/lgs8gl5.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/lgs8gxx.c (renamed from drivers/media/dvb/frontends/lgs8gxx.c) | 2 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/lgs8gxx.h (renamed from drivers/media/dvb/frontends/lgs8gxx.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/lgs8gxx_priv.h (renamed from drivers/media/dvb/frontends/lgs8gxx_priv.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/lnbh24.h (renamed from drivers/media/dvb/frontends/lnbh24.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/lnbp21.c (renamed from drivers/media/dvb/frontends/lnbp21.c) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/lnbp21.h (renamed from drivers/media/dvb/frontends/lnbp21.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/lnbp22.c (renamed from drivers/media/dvb/frontends/lnbp22.c) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/lnbp22.h (renamed from drivers/media/dvb/frontends/lnbp22.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/m88rs2000.c (renamed from drivers/media/dvb/frontends/m88rs2000.c) | 2 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/m88rs2000.h (renamed from drivers/media/dvb/frontends/m88rs2000.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/mb86a16.c (renamed from drivers/media/dvb/frontends/mb86a16.c) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/mb86a16.h (renamed from drivers/media/dvb/frontends/mb86a16.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/mb86a16_priv.h (renamed from drivers/media/dvb/frontends/mb86a16_priv.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/mb86a20s.c (renamed from drivers/media/dvb/frontends/mb86a20s.c) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/mb86a20s.h (renamed from drivers/media/dvb/frontends/mb86a20s.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/mt312.c (renamed from drivers/media/dvb/frontends/mt312.c) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/mt312.h (renamed from drivers/media/dvb/frontends/mt312.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/mt312_priv.h (renamed from drivers/media/dvb/frontends/mt312_priv.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/mt352.c (renamed from drivers/media/dvb/frontends/mt352.c) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/mt352.h (renamed from drivers/media/dvb/frontends/mt352.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/mt352_priv.h (renamed from drivers/media/dvb/frontends/mt352_priv.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/nxt200x.c (renamed from drivers/media/dvb/frontends/nxt200x.c) | 64 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/nxt200x.h (renamed from drivers/media/dvb/frontends/nxt200x.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/nxt6000.c (renamed from drivers/media/dvb/frontends/nxt6000.c) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/nxt6000.h (renamed from drivers/media/dvb/frontends/nxt6000.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/nxt6000_priv.h (renamed from drivers/media/dvb/frontends/nxt6000_priv.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/or51132.c (renamed from drivers/media/dvb/frontends/or51132.c) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/or51132.h (renamed from drivers/media/dvb/frontends/or51132.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/or51211.c (renamed from drivers/media/dvb/frontends/or51211.c) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/or51211.h (renamed from drivers/media/dvb/frontends/or51211.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/rtl2830.c (renamed from drivers/media/dvb/frontends/rtl2830.c) | 124 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/rtl2830.h (renamed from drivers/media/dvb/frontends/rtl2830.h) | 9 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/rtl2830_priv.h (renamed from drivers/media/dvb/frontends/rtl2830_priv.h) | 13 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/rtl2832.c (renamed from drivers/media/dvb/frontends/rtl2832.c) | 301 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/rtl2832.h (renamed from drivers/media/dvb/frontends/rtl2832.h) | 13 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/rtl2832_priv.h (renamed from drivers/media/dvb/frontends/rtl2832_priv.h) | 112 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/s5h1409.c (renamed from drivers/media/dvb/frontends/s5h1409.c) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/s5h1409.h (renamed from drivers/media/dvb/frontends/s5h1409.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/s5h1411.c (renamed from drivers/media/dvb/frontends/s5h1411.c) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/s5h1411.h (renamed from drivers/media/dvb/frontends/s5h1411.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/s5h1420.c (renamed from drivers/media/dvb/frontends/s5h1420.c) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/s5h1420.h (renamed from drivers/media/dvb/frontends/s5h1420.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/s5h1420_priv.h (renamed from drivers/media/dvb/frontends/s5h1420_priv.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/s5h1432.c (renamed from drivers/media/dvb/frontends/s5h1432.c) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/s5h1432.h (renamed from drivers/media/dvb/frontends/s5h1432.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/s921.c (renamed from drivers/media/dvb/frontends/s921.c) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/s921.h (renamed from drivers/media/dvb/frontends/s921.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/si21xx.c (renamed from drivers/media/dvb/frontends/si21xx.c) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/si21xx.h (renamed from drivers/media/dvb/frontends/si21xx.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/sp8870.c (renamed from drivers/media/dvb/frontends/sp8870.c) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/sp8870.h (renamed from drivers/media/dvb/frontends/sp8870.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/sp887x.c (renamed from drivers/media/dvb/frontends/sp887x.c) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/sp887x.h (renamed from drivers/media/dvb/frontends/sp887x.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/stb0899_algo.c (renamed from drivers/media/dvb/frontends/stb0899_algo.c) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/stb0899_cfg.h (renamed from drivers/media/dvb/frontends/stb0899_cfg.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/stb0899_drv.c (renamed from drivers/media/dvb/frontends/stb0899_drv.c) | 1 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/stb0899_drv.h (renamed from drivers/media/dvb/frontends/stb0899_drv.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/stb0899_priv.h (renamed from drivers/media/dvb/frontends/stb0899_priv.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/stb0899_reg.h (renamed from drivers/media/dvb/frontends/stb0899_reg.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/stb6000.c (renamed from drivers/media/dvb/frontends/stb6000.c) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/stb6000.h (renamed from drivers/media/dvb/frontends/stb6000.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/stb6100.c (renamed from drivers/media/dvb/frontends/stb6100.c) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/stb6100.h (renamed from drivers/media/dvb/frontends/stb6100.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/stb6100_cfg.h (renamed from drivers/media/dvb/frontends/stb6100_cfg.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/stb6100_proc.h (renamed from drivers/media/dvb/frontends/stb6100_proc.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/stv0288.c (renamed from drivers/media/dvb/frontends/stv0288.c) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/stv0288.h (renamed from drivers/media/dvb/frontends/stv0288.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/stv0297.c (renamed from drivers/media/dvb/frontends/stv0297.c) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/stv0297.h (renamed from drivers/media/dvb/frontends/stv0297.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/stv0299.c (renamed from drivers/media/dvb/frontends/stv0299.c) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/stv0299.h (renamed from drivers/media/dvb/frontends/stv0299.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/stv0367.c (renamed from drivers/media/dvb/frontends/stv0367.c) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/stv0367.h (renamed from drivers/media/dvb/frontends/stv0367.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/stv0367_priv.h (renamed from drivers/media/dvb/frontends/stv0367_priv.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/stv0367_regs.h (renamed from drivers/media/dvb/frontends/stv0367_regs.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/stv0900.h (renamed from drivers/media/dvb/frontends/stv0900.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/stv0900_core.c (renamed from drivers/media/dvb/frontends/stv0900_core.c) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/stv0900_init.h (renamed from drivers/media/dvb/frontends/stv0900_init.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/stv0900_priv.h (renamed from drivers/media/dvb/frontends/stv0900_priv.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/stv0900_reg.h (renamed from drivers/media/dvb/frontends/stv0900_reg.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/stv0900_sw.c (renamed from drivers/media/dvb/frontends/stv0900_sw.c) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/stv090x.c (renamed from drivers/media/dvb/frontends/stv090x.c) | 32 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/stv090x.h (renamed from drivers/media/dvb/frontends/stv090x.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/stv090x_priv.h (renamed from drivers/media/dvb/frontends/stv090x_priv.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/stv090x_reg.h (renamed from drivers/media/dvb/frontends/stv090x_reg.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/stv6110.c (renamed from drivers/media/dvb/frontends/stv6110.c) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/stv6110.h (renamed from drivers/media/dvb/frontends/stv6110.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/stv6110x.c (renamed from drivers/media/dvb/frontends/stv6110x.c) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/stv6110x.h (renamed from drivers/media/dvb/frontends/stv6110x.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/stv6110x_priv.h (renamed from drivers/media/dvb/frontends/stv6110x_priv.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/stv6110x_reg.h (renamed from drivers/media/dvb/frontends/stv6110x_reg.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/tda10021.c (renamed from drivers/media/dvb/frontends/tda10021.c) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/tda10023.c (renamed from drivers/media/dvb/frontends/tda10023.c) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/tda1002x.h (renamed from drivers/media/dvb/frontends/tda1002x.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/tda10048.c (renamed from drivers/media/dvb/frontends/tda10048.c) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/tda10048.h (renamed from drivers/media/dvb/frontends/tda10048.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/tda1004x.c (renamed from drivers/media/dvb/frontends/tda1004x.c) | 8 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/tda1004x.h (renamed from drivers/media/dvb/frontends/tda1004x.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/tda10071.c (renamed from drivers/media/dvb/frontends/tda10071.c) | 7 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/tda10071.h (renamed from drivers/media/dvb/frontends/tda10071.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/tda10071_priv.h (renamed from drivers/media/dvb/frontends/tda10071_priv.h) | 2 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/tda10086.c (renamed from drivers/media/dvb/frontends/tda10086.c) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/tda10086.h (renamed from drivers/media/dvb/frontends/tda10086.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/tda18271c2dd.c (renamed from drivers/media/dvb/frontends/tda18271c2dd.c) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/tda18271c2dd.h (renamed from drivers/media/dvb/frontends/tda18271c2dd.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/tda18271c2dd_maps.h (renamed from drivers/media/dvb/frontends/tda18271c2dd_maps.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/tda665x.c (renamed from drivers/media/dvb/frontends/tda665x.c) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/tda665x.h (renamed from drivers/media/dvb/frontends/tda665x.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/tda8083.c (renamed from drivers/media/dvb/frontends/tda8083.c) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/tda8083.h (renamed from drivers/media/dvb/frontends/tda8083.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/tda8261.c (renamed from drivers/media/dvb/frontends/tda8261.c) | 28 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/tda8261.h (renamed from drivers/media/dvb/frontends/tda8261.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/tda8261_cfg.h (renamed from drivers/media/dvb/frontends/tda8261_cfg.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/tda826x.c (renamed from drivers/media/dvb/frontends/tda826x.c) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/tda826x.h (renamed from drivers/media/dvb/frontends/tda826x.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/tdhd1.h (renamed from drivers/media/dvb/frontends/tdhd1.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/tua6100.c (renamed from drivers/media/dvb/frontends/tua6100.c) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/tua6100.h (renamed from drivers/media/dvb/frontends/tua6100.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/ves1820.c (renamed from drivers/media/dvb/frontends/ves1820.c) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/ves1820.h (renamed from drivers/media/dvb/frontends/ves1820.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/ves1x93.c (renamed from drivers/media/dvb/frontends/ves1x93.c) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/ves1x93.h (renamed from drivers/media/dvb/frontends/ves1x93.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/z0194a.h (renamed from drivers/media/dvb/frontends/z0194a.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/zl10036.c (renamed from drivers/media/dvb/frontends/zl10036.c) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/zl10036.h (renamed from drivers/media/dvb/frontends/zl10036.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/zl10039.c (renamed from drivers/media/dvb/frontends/zl10039.c) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/zl10039.h (renamed from drivers/media/dvb/frontends/zl10039.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/zl10353.c (renamed from drivers/media/dvb/frontends/zl10353.c) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/zl10353.h (renamed from drivers/media/dvb/frontends/zl10353.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/zl10353_priv.h (renamed from drivers/media/dvb/frontends/zl10353_priv.h) | 0 | ||||
-rw-r--r-- | drivers/media/dvb/Kconfig | 91 | ||||
-rw-r--r-- | drivers/media/dvb/Makefile | 21 | ||||
-rw-r--r-- | drivers/media/dvb/b2c2/Kconfig | 45 | ||||
-rw-r--r-- | drivers/media/dvb/b2c2/Makefile | 16 | ||||
-rw-r--r-- | drivers/media/dvb/bt8xx/Kconfig | 22 | ||||
-rw-r--r-- | drivers/media/dvb/bt8xx/Makefile | 6 | ||||
-rw-r--r-- | drivers/media/dvb/dm1105/Makefile | 3 | ||||
-rw-r--r-- | drivers/media/dvb/dvb-usb/Kconfig | 440 | ||||
-rw-r--r-- | drivers/media/dvb/dvb-usb/Makefile | 121 | ||||
-rw-r--r-- | drivers/media/dvb/dvb-usb/af9015.c | 1952 | ||||
-rw-r--r-- | drivers/media/dvb/dvb-usb/it913x.c | 931 | ||||
-rw-r--r-- | drivers/media/dvb/dvb-usb/mxl111sf.c | 1835 | ||||
-rw-r--r-- | drivers/media/dvb/frontends/ec100_priv.h | 39 | ||||
-rw-r--r-- | drivers/media/dvb/ngene/Kconfig | 13 | ||||
-rw-r--r-- | drivers/media/dvb/pluto2/Makefile | 3 | ||||
-rw-r--r-- | drivers/media/dvb/siano/Kconfig | 34 | ||||
-rw-r--r-- | drivers/media/dvb/ttusb-budget/Makefile | 3 | ||||
-rw-r--r-- | drivers/media/firewire/Kconfig (renamed from drivers/media/dvb/firewire/Kconfig) | 0 | ||||
-rw-r--r-- | drivers/media/firewire/Makefile (renamed from drivers/media/dvb/firewire/Makefile) | 4 | ||||
-rw-r--r-- | drivers/media/firewire/firedtv-avc.c (renamed from drivers/media/dvb/firewire/firedtv-avc.c) | 0 | ||||
-rw-r--r-- | drivers/media/firewire/firedtv-ci.c (renamed from drivers/media/dvb/firewire/firedtv-ci.c) | 0 | ||||
-rw-r--r-- | drivers/media/firewire/firedtv-dvb.c (renamed from drivers/media/dvb/firewire/firedtv-dvb.c) | 0 | ||||
-rw-r--r-- | drivers/media/firewire/firedtv-fe.c (renamed from drivers/media/dvb/firewire/firedtv-fe.c) | 0 | ||||
-rw-r--r-- | drivers/media/firewire/firedtv-fw.c (renamed from drivers/media/dvb/firewire/firedtv-fw.c) | 0 | ||||
-rw-r--r-- | drivers/media/firewire/firedtv-rc.c (renamed from drivers/media/dvb/firewire/firedtv-rc.c) | 0 | ||||
-rw-r--r-- | drivers/media/firewire/firedtv.h (renamed from drivers/media/dvb/firewire/firedtv.h) | 0 | ||||
-rw-r--r-- | drivers/media/i2c/Kconfig | 591 | ||||
-rw-r--r-- | drivers/media/i2c/Makefile | 67 | ||||
-rw-r--r-- | drivers/media/i2c/ad9389b.c | 1328 | ||||
-rw-r--r-- | drivers/media/i2c/adp1653.c (renamed from drivers/media/video/adp1653.c) | 2 | ||||
-rw-r--r-- | drivers/media/i2c/adv7170.c (renamed from drivers/media/video/adv7170.c) | 0 | ||||
-rw-r--r-- | drivers/media/i2c/adv7175.c (renamed from drivers/media/video/adv7175.c) | 0 | ||||
-rw-r--r-- | drivers/media/i2c/adv7180.c (renamed from drivers/media/video/adv7180.c) | 0 | ||||
-rw-r--r-- | drivers/media/i2c/adv7183.c (renamed from drivers/media/video/adv7183.c) | 0 | ||||
-rw-r--r-- | drivers/media/i2c/adv7183_regs.h (renamed from drivers/media/video/adv7183_regs.h) | 0 | ||||
-rw-r--r-- | drivers/media/i2c/adv7343.c (renamed from drivers/media/video/adv7343.c) | 0 | ||||
-rw-r--r-- | drivers/media/i2c/adv7343_regs.h (renamed from drivers/media/video/adv7343_regs.h) | 0 | ||||
-rw-r--r-- | drivers/media/i2c/adv7393.c (renamed from drivers/media/video/adv7393.c) | 0 | ||||
-rw-r--r-- | drivers/media/i2c/adv7393_regs.h (renamed from drivers/media/video/adv7393_regs.h) | 0 | ||||
-rw-r--r-- | drivers/media/i2c/adv7604.c | 1959 | ||||
-rw-r--r-- | drivers/media/i2c/ak881x.c (renamed from drivers/media/video/ak881x.c) | 0 | ||||
-rw-r--r-- | drivers/media/i2c/aptina-pll.c (renamed from drivers/media/video/aptina-pll.c) | 0 | ||||
-rw-r--r-- | drivers/media/i2c/aptina-pll.h (renamed from drivers/media/video/aptina-pll.h) | 0 | ||||
-rw-r--r-- | drivers/media/i2c/as3645a.c (renamed from drivers/media/video/as3645a.c) | 2 | ||||
-rw-r--r-- | drivers/media/i2c/bt819.c (renamed from drivers/media/video/bt819.c) | 0 | ||||
-rw-r--r-- | drivers/media/i2c/bt856.c (renamed from drivers/media/video/bt856.c) | 0 | ||||
-rw-r--r-- | drivers/media/i2c/bt866.c (renamed from drivers/media/video/bt866.c) | 0 | ||||
-rw-r--r-- | drivers/media/i2c/btcx-risc.c (renamed from drivers/media/video/btcx-risc.c) | 0 | ||||
-rw-r--r-- | drivers/media/i2c/btcx-risc.h (renamed from drivers/media/video/btcx-risc.h) | 0 | ||||
-rw-r--r-- | drivers/media/i2c/cs5345.c (renamed from drivers/media/video/cs5345.c) | 0 | ||||
-rw-r--r-- | drivers/media/i2c/cs53l32a.c (renamed from drivers/media/video/cs53l32a.c) | 0 | ||||
-rw-r--r-- | drivers/media/i2c/cx2341x.c (renamed from drivers/media/video/cx2341x.c) | 0 | ||||
-rw-r--r-- | drivers/media/i2c/cx25840/Kconfig (renamed from drivers/media/video/cx25840/Kconfig) | 0 | ||||
-rw-r--r-- | drivers/media/i2c/cx25840/Makefile (renamed from drivers/media/video/cx25840/Makefile) | 2 | ||||
-rw-r--r-- | drivers/media/i2c/cx25840/cx25840-audio.c (renamed from drivers/media/video/cx25840/cx25840-audio.c) | 0 | ||||
-rw-r--r-- | drivers/media/i2c/cx25840/cx25840-core.c (renamed from drivers/media/video/cx25840/cx25840-core.c) | 0 | ||||
-rw-r--r-- | drivers/media/i2c/cx25840/cx25840-core.h (renamed from drivers/media/video/cx25840/cx25840-core.h) | 0 | ||||
-rw-r--r-- | drivers/media/i2c/cx25840/cx25840-firmware.c (renamed from drivers/media/video/cx25840/cx25840-firmware.c) | 15 | ||||
-rw-r--r-- | drivers/media/i2c/cx25840/cx25840-ir.c (renamed from drivers/media/video/cx25840/cx25840-ir.c) | 0 | ||||
-rw-r--r-- | drivers/media/i2c/cx25840/cx25840-vbi.c (renamed from drivers/media/video/cx25840/cx25840-vbi.c) | 3 | ||||
-rw-r--r-- | drivers/media/i2c/ir-kbd-i2c.c (renamed from drivers/media/video/ir-kbd-i2c.c) | 0 | ||||
-rw-r--r-- | drivers/media/i2c/ks0127.c (renamed from drivers/media/video/ks0127.c) | 13 | ||||
-rw-r--r-- | drivers/media/i2c/ks0127.h (renamed from drivers/media/video/ks0127.h) | 0 | ||||
-rw-r--r-- | drivers/media/i2c/m52790.c (renamed from drivers/media/video/m52790.c) | 0 | ||||
-rw-r--r-- | drivers/media/i2c/m5mols/Kconfig (renamed from drivers/media/video/m5mols/Kconfig) | 0 | ||||
-rw-r--r-- | drivers/media/i2c/m5mols/Makefile (renamed from drivers/media/video/m5mols/Makefile) | 0 | ||||
-rw-r--r-- | drivers/media/i2c/m5mols/m5mols.h (renamed from drivers/media/video/m5mols/m5mols.h) | 22 | ||||
-rw-r--r-- | drivers/media/i2c/m5mols/m5mols_capture.c (renamed from drivers/media/video/m5mols/m5mols_capture.c) | 0 | ||||
-rw-r--r-- | drivers/media/i2c/m5mols/m5mols_controls.c (renamed from drivers/media/video/m5mols/m5mols_controls.c) | 4 | ||||
-rw-r--r-- | drivers/media/i2c/m5mols/m5mols_core.c (renamed from drivers/media/video/m5mols/m5mols_core.c) | 90 | ||||
-rw-r--r-- | drivers/media/i2c/m5mols/m5mols_reg.h (renamed from drivers/media/video/m5mols/m5mols_reg.h) | 0 | ||||
-rw-r--r-- | drivers/media/i2c/msp3400-driver.c (renamed from drivers/media/video/msp3400-driver.c) | 40 | ||||
-rw-r--r-- | drivers/media/i2c/msp3400-driver.h (renamed from drivers/media/video/msp3400-driver.h) | 0 | ||||
-rw-r--r-- | drivers/media/i2c/msp3400-kthreads.c (renamed from drivers/media/video/msp3400-kthreads.c) | 0 | ||||
-rw-r--r-- | drivers/media/i2c/mt9m032.c (renamed from drivers/media/video/mt9m032.c) | 2 | ||||
-rw-r--r-- | drivers/media/i2c/mt9p031.c (renamed from drivers/media/video/mt9p031.c) | 12 | ||||
-rw-r--r-- | drivers/media/i2c/mt9t001.c (renamed from drivers/media/video/mt9t001.c) | 0 | ||||
-rw-r--r-- | drivers/media/i2c/mt9v011.c (renamed from drivers/media/video/mt9v011.c) | 0 | ||||
-rw-r--r-- | drivers/media/i2c/mt9v032.c (renamed from drivers/media/video/mt9v032.c) | 100 | ||||
-rw-r--r-- | drivers/media/i2c/noon010pc30.c (renamed from drivers/media/video/noon010pc30.c) | 0 | ||||
-rw-r--r-- | drivers/media/i2c/ov7670.c (renamed from drivers/media/video/ov7670.c) | 0 | ||||
-rw-r--r-- | drivers/media/i2c/s5k4ecgx.c | 1036 | ||||
-rw-r--r-- | drivers/media/i2c/s5k6aa.c (renamed from drivers/media/video/s5k6aa.c) | 20 | ||||
-rw-r--r-- | drivers/media/i2c/saa6588.c (renamed from drivers/media/video/saa6588.c) | 0 | ||||
-rw-r--r-- | drivers/media/i2c/saa7110.c (renamed from drivers/media/video/saa7110.c) | 0 | ||||
-rw-r--r-- | drivers/media/i2c/saa7115.c (renamed from drivers/media/video/saa7115.c) | 3 | ||||
-rw-r--r-- | drivers/media/i2c/saa711x_regs.h (renamed from drivers/media/video/saa711x_regs.h) | 0 | ||||
-rw-r--r-- | drivers/media/i2c/saa7127.c (renamed from drivers/media/video/saa7127.c) | 7 | ||||
-rw-r--r-- | drivers/media/i2c/saa717x.c (renamed from drivers/media/video/saa717x.c) | 0 | ||||
-rw-r--r-- | drivers/media/i2c/saa7185.c (renamed from drivers/media/video/saa7185.c) | 0 | ||||
-rw-r--r-- | drivers/media/i2c/saa7191.c (renamed from drivers/media/video/saa7191.c) | 0 | ||||
-rw-r--r-- | drivers/media/i2c/saa7191.h (renamed from drivers/media/video/saa7191.h) | 0 | ||||
-rw-r--r-- | drivers/media/i2c/smiapp-pll.c (renamed from drivers/media/video/smiapp-pll.c) | 2 | ||||
-rw-r--r-- | drivers/media/i2c/smiapp-pll.h (renamed from drivers/media/video/smiapp-pll.h) | 2 | ||||
-rw-r--r-- | drivers/media/i2c/smiapp/Kconfig (renamed from drivers/media/video/smiapp/Kconfig) | 0 | ||||
-rw-r--r-- | drivers/media/i2c/smiapp/Makefile (renamed from drivers/media/video/smiapp/Makefile) | 2 | ||||
-rw-r--r-- | drivers/media/i2c/smiapp/smiapp-core.c (renamed from drivers/media/video/smiapp/smiapp-core.c) | 83 | ||||
-rw-r--r-- | drivers/media/i2c/smiapp/smiapp-limits.c (renamed from drivers/media/video/smiapp/smiapp-limits.c) | 2 | ||||
-rw-r--r-- | drivers/media/i2c/smiapp/smiapp-limits.h (renamed from drivers/media/video/smiapp/smiapp-limits.h) | 2 | ||||
-rw-r--r-- | drivers/media/i2c/smiapp/smiapp-quirk.c (renamed from drivers/media/video/smiapp/smiapp-quirk.c) | 22 | ||||
-rw-r--r-- | drivers/media/i2c/smiapp/smiapp-quirk.h (renamed from drivers/media/video/smiapp/smiapp-quirk.h) | 2 | ||||
-rw-r--r-- | drivers/media/i2c/smiapp/smiapp-reg-defs.h (renamed from drivers/media/video/smiapp/smiapp-reg-defs.h) | 2 | ||||
-rw-r--r-- | drivers/media/i2c/smiapp/smiapp-reg.h (renamed from drivers/media/video/smiapp/smiapp-reg.h) | 2 | ||||
-rw-r--r-- | drivers/media/i2c/smiapp/smiapp-regs.c (renamed from drivers/media/video/smiapp/smiapp-regs.c) | 2 | ||||
-rw-r--r-- | drivers/media/i2c/smiapp/smiapp-regs.h (renamed from drivers/media/video/smiapp/smiapp-regs.h) | 0 | ||||
-rw-r--r-- | drivers/media/i2c/smiapp/smiapp.h (renamed from drivers/media/video/smiapp/smiapp.h) | 2 | ||||
-rw-r--r-- | drivers/media/i2c/soc_camera/Kconfig | 89 | ||||
-rw-r--r-- | drivers/media/i2c/soc_camera/Makefile | 14 | ||||
-rw-r--r-- | drivers/media/i2c/soc_camera/imx074.c (renamed from drivers/media/video/imx074.c) | 30 | ||||
-rw-r--r-- | drivers/media/i2c/soc_camera/mt9m001.c (renamed from drivers/media/video/mt9m001.c) | 28 | ||||
-rw-r--r-- | drivers/media/i2c/soc_camera/mt9m111.c (renamed from drivers/media/video/mt9m111.c) | 118 | ||||
-rw-r--r-- | drivers/media/i2c/soc_camera/mt9t031.c (renamed from drivers/media/video/mt9t031.c) | 50 | ||||
-rw-r--r-- | drivers/media/i2c/soc_camera/mt9t112.c (renamed from drivers/media/video/mt9t112.c) | 25 | ||||
-rw-r--r-- | drivers/media/i2c/soc_camera/mt9v022.c (renamed from drivers/media/video/mt9v022.c) | 52 | ||||
-rw-r--r-- | drivers/media/i2c/soc_camera/ov2640.c (renamed from drivers/media/video/ov2640.c) | 20 | ||||
-rw-r--r-- | drivers/media/i2c/soc_camera/ov5642.c (renamed from drivers/media/video/ov5642.c) | 51 | ||||
-rw-r--r-- | drivers/media/i2c/soc_camera/ov6650.c (renamed from drivers/media/video/ov6650.c) | 60 | ||||
-rw-r--r-- | drivers/media/i2c/soc_camera/ov772x.c (renamed from drivers/media/video/ov772x.c) | 447 | ||||
-rw-r--r-- | drivers/media/i2c/soc_camera/ov9640.c (renamed from drivers/media/video/ov9640.c) | 27 | ||||
-rw-r--r-- | drivers/media/i2c/soc_camera/ov9640.h (renamed from drivers/media/video/ov9640.h) | 0 | ||||
-rw-r--r-- | drivers/media/i2c/soc_camera/ov9740.c (renamed from drivers/media/video/ov9740.c) | 47 | ||||
-rw-r--r-- | drivers/media/i2c/soc_camera/rj54n1cb0c.c (renamed from drivers/media/video/rj54n1cb0c.c) | 31 | ||||
-rw-r--r-- | drivers/media/i2c/soc_camera/tw9910.c (renamed from drivers/media/video/tw9910.c) | 21 | ||||
-rw-r--r-- | drivers/media/i2c/sr030pc30.c (renamed from drivers/media/video/sr030pc30.c) | 0 | ||||
-rw-r--r-- | drivers/media/i2c/tcm825x.c (renamed from drivers/media/video/tcm825x.c) | 2 | ||||
-rw-r--r-- | drivers/media/i2c/tcm825x.h (renamed from drivers/media/video/tcm825x.h) | 2 | ||||
-rw-r--r-- | drivers/media/i2c/tda7432.c (renamed from drivers/media/video/tda7432.c) | 0 | ||||
-rw-r--r-- | drivers/media/i2c/tda9840.c (renamed from drivers/media/video/tda9840.c) | 0 | ||||
-rw-r--r-- | drivers/media/i2c/tea6415c.c (renamed from drivers/media/video/tea6415c.c) | 4 | ||||
-rw-r--r-- | drivers/media/i2c/tea6415c.h (renamed from drivers/media/video/tea6415c.h) | 0 | ||||
-rw-r--r-- | drivers/media/i2c/tea6420.c (renamed from drivers/media/video/tea6420.c) | 0 | ||||
-rw-r--r-- | drivers/media/i2c/tea6420.h (renamed from drivers/media/video/tea6420.h) | 0 | ||||
-rw-r--r-- | drivers/media/i2c/ths7303.c (renamed from drivers/media/video/ths7303.c) | 0 | ||||
-rw-r--r-- | drivers/media/i2c/tlv320aic23b.c (renamed from drivers/media/video/tlv320aic23b.c) | 0 | ||||
-rw-r--r-- | drivers/media/i2c/tvaudio.c (renamed from drivers/media/video/tvaudio.c) | 17 | ||||
-rw-r--r-- | drivers/media/i2c/tveeprom.c (renamed from drivers/media/video/tveeprom.c) | 0 | ||||
-rw-r--r-- | drivers/media/i2c/tvp514x.c (renamed from drivers/media/video/tvp514x.c) | 2 | ||||
-rw-r--r-- | drivers/media/i2c/tvp514x_regs.h (renamed from drivers/media/video/tvp514x_regs.h) | 2 | ||||
-rw-r--r-- | drivers/media/i2c/tvp5150.c (renamed from drivers/media/video/tvp5150.c) | 4 | ||||
-rw-r--r-- | drivers/media/i2c/tvp5150_reg.h (renamed from drivers/media/video/tvp5150_reg.h) | 0 | ||||
-rw-r--r-- | drivers/media/i2c/tvp7002.c (renamed from drivers/media/video/tvp7002.c) | 0 | ||||
-rw-r--r-- | drivers/media/i2c/tvp7002_reg.h (renamed from drivers/media/video/tvp7002_reg.h) | 0 | ||||
-rw-r--r-- | drivers/media/i2c/upd64031a.c (renamed from drivers/media/video/upd64031a.c) | 0 | ||||
-rw-r--r-- | drivers/media/i2c/upd64083.c (renamed from drivers/media/video/upd64083.c) | 0 | ||||
-rw-r--r-- | drivers/media/i2c/vp27smpx.c (renamed from drivers/media/video/vp27smpx.c) | 0 | ||||
-rw-r--r-- | drivers/media/i2c/vpx3220.c (renamed from drivers/media/video/vpx3220.c) | 0 | ||||
-rw-r--r-- | drivers/media/i2c/vs6624.c (renamed from drivers/media/video/vs6624.c) | 0 | ||||
-rw-r--r-- | drivers/media/i2c/vs6624_regs.h (renamed from drivers/media/video/vs6624_regs.h) | 0 | ||||
-rw-r--r-- | drivers/media/i2c/wm8739.c (renamed from drivers/media/video/wm8739.c) | 0 | ||||
-rw-r--r-- | drivers/media/i2c/wm8775.c (renamed from drivers/media/video/wm8775.c) | 0 | ||||
-rw-r--r-- | drivers/media/media-device.c | 4 | ||||
-rw-r--r-- | drivers/media/media-devnode.c | 14 | ||||
-rw-r--r-- | drivers/media/mmc/Kconfig | 2 | ||||
-rw-r--r-- | drivers/media/mmc/Makefile | 1 | ||||
-rw-r--r-- | drivers/media/mmc/siano/Kconfig | 10 | ||||
-rw-r--r-- | drivers/media/mmc/siano/Makefile | 6 | ||||
-rw-r--r-- | drivers/media/mmc/siano/smssdio.c (renamed from drivers/media/dvb/siano/smssdio.c) | 0 | ||||
-rw-r--r-- | drivers/media/parport/Kconfig | 52 | ||||
-rw-r--r-- | drivers/media/parport/Makefile | 4 | ||||
-rw-r--r-- | drivers/media/parport/bw-qcam.c (renamed from drivers/media/video/bw-qcam.c) | 0 | ||||
-rw-r--r-- | drivers/media/parport/c-qcam.c (renamed from drivers/media/video/c-qcam.c) | 0 | ||||
-rw-r--r-- | drivers/media/parport/pms.c (renamed from drivers/media/video/pms.c) | 0 | ||||
-rw-r--r-- | drivers/media/parport/w9966.c (renamed from drivers/media/video/w9966.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/Kconfig | 47 | ||||
-rw-r--r-- | drivers/media/pci/Makefile | 26 | ||||
-rw-r--r-- | drivers/media/pci/b2c2/Kconfig | 15 | ||||
-rw-r--r-- | drivers/media/pci/b2c2/Makefile | 9 | ||||
-rw-r--r-- | drivers/media/pci/b2c2/flexcop-dma.c (renamed from drivers/media/dvb/b2c2/flexcop-dma.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/b2c2/flexcop-pci.c (renamed from drivers/media/dvb/b2c2/flexcop-pci.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/bt8xx/Kconfig | 43 | ||||
-rw-r--r-- | drivers/media/pci/bt8xx/Makefile | 11 | ||||
-rw-r--r-- | drivers/media/pci/bt8xx/bt848.h (renamed from drivers/media/video/bt8xx/bt848.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/bt8xx/bt878.c (renamed from drivers/media/dvb/bt8xx/bt878.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/bt8xx/bt878.h (renamed from drivers/media/dvb/bt8xx/bt878.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/bt8xx/bttv-audio-hook.c (renamed from drivers/media/video/bt8xx/bttv-audio-hook.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/bt8xx/bttv-audio-hook.h (renamed from drivers/media/video/bt8xx/bttv-audio-hook.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/bt8xx/bttv-cards.c (renamed from drivers/media/video/bt8xx/bttv-cards.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/bt8xx/bttv-driver.c (renamed from drivers/media/video/bt8xx/bttv-driver.c) | 16 | ||||
-rw-r--r-- | drivers/media/pci/bt8xx/bttv-gpio.c (renamed from drivers/media/video/bt8xx/bttv-gpio.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/bt8xx/bttv-i2c.c (renamed from drivers/media/video/bt8xx/bttv-i2c.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/bt8xx/bttv-if.c (renamed from drivers/media/video/bt8xx/bttv-if.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/bt8xx/bttv-input.c (renamed from drivers/media/video/bt8xx/bttv-input.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/bt8xx/bttv-risc.c (renamed from drivers/media/video/bt8xx/bttv-risc.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/bt8xx/bttv-vbi.c (renamed from drivers/media/video/bt8xx/bttv-vbi.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/bt8xx/bttv.h (renamed from drivers/media/video/bt8xx/bttv.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/bt8xx/bttvp.h (renamed from drivers/media/video/bt8xx/bttvp.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/bt8xx/dst.c (renamed from drivers/media/dvb/bt8xx/dst.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/bt8xx/dst_ca.c (renamed from drivers/media/dvb/bt8xx/dst_ca.c) | 3 | ||||
-rw-r--r-- | drivers/media/pci/bt8xx/dst_ca.h (renamed from drivers/media/dvb/bt8xx/dst_ca.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/bt8xx/dst_common.h (renamed from drivers/media/dvb/bt8xx/dst_common.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/bt8xx/dst_priv.h (renamed from drivers/media/dvb/bt8xx/dst_priv.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/bt8xx/dvb-bt8xx.c (renamed from drivers/media/dvb/bt8xx/dvb-bt8xx.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/bt8xx/dvb-bt8xx.h (renamed from drivers/media/dvb/bt8xx/dvb-bt8xx.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/cx18/Kconfig (renamed from drivers/media/video/cx18/Kconfig) | 14 | ||||
-rw-r--r-- | drivers/media/pci/cx18/Makefile (renamed from drivers/media/video/cx18/Makefile) | 6 | ||||
-rw-r--r-- | drivers/media/pci/cx18/cx18-alsa-main.c (renamed from drivers/media/video/cx18/cx18-alsa-main.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/cx18/cx18-alsa-mixer.c (renamed from drivers/media/video/cx18/cx18-alsa-mixer.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/cx18/cx18-alsa-mixer.h (renamed from drivers/media/video/cx18/cx18-alsa-mixer.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/cx18/cx18-alsa-pcm.c (renamed from drivers/media/video/cx18/cx18-alsa-pcm.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/cx18/cx18-alsa-pcm.h (renamed from drivers/media/video/cx18/cx18-alsa-pcm.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/cx18/cx18-alsa.h (renamed from drivers/media/video/cx18/cx18-alsa.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/cx18/cx18-audio.c (renamed from drivers/media/video/cx18/cx18-audio.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/cx18/cx18-audio.h (renamed from drivers/media/video/cx18/cx18-audio.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/cx18/cx18-av-audio.c (renamed from drivers/media/video/cx18/cx18-av-audio.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/cx18/cx18-av-core.c (renamed from drivers/media/video/cx18/cx18-av-core.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/cx18/cx18-av-core.h (renamed from drivers/media/video/cx18/cx18-av-core.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/cx18/cx18-av-firmware.c (renamed from drivers/media/video/cx18/cx18-av-firmware.c) | 2 | ||||
-rw-r--r-- | drivers/media/pci/cx18/cx18-av-vbi.c (renamed from drivers/media/video/cx18/cx18-av-vbi.c) | 4 | ||||
-rw-r--r-- | drivers/media/pci/cx18/cx18-cards.c (renamed from drivers/media/video/cx18/cx18-cards.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/cx18/cx18-cards.h (renamed from drivers/media/video/cx18/cx18-cards.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/cx18/cx18-controls.c (renamed from drivers/media/video/cx18/cx18-controls.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/cx18/cx18-controls.h (renamed from drivers/media/video/cx18/cx18-controls.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/cx18/cx18-driver.c (renamed from drivers/media/video/cx18/cx18-driver.c) | 1 | ||||
-rw-r--r-- | drivers/media/pci/cx18/cx18-driver.h (renamed from drivers/media/video/cx18/cx18-driver.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/cx18/cx18-dvb.c (renamed from drivers/media/video/cx18/cx18-dvb.c) | 6 | ||||
-rw-r--r-- | drivers/media/pci/cx18/cx18-dvb.h (renamed from drivers/media/video/cx18/cx18-dvb.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/cx18/cx18-fileops.c (renamed from drivers/media/video/cx18/cx18-fileops.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/cx18/cx18-fileops.h (renamed from drivers/media/video/cx18/cx18-fileops.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/cx18/cx18-firmware.c (renamed from drivers/media/video/cx18/cx18-firmware.c) | 10 | ||||
-rw-r--r-- | drivers/media/pci/cx18/cx18-firmware.h (renamed from drivers/media/video/cx18/cx18-firmware.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/cx18/cx18-gpio.c (renamed from drivers/media/video/cx18/cx18-gpio.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/cx18/cx18-gpio.h (renamed from drivers/media/video/cx18/cx18-gpio.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/cx18/cx18-i2c.c (renamed from drivers/media/video/cx18/cx18-i2c.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/cx18/cx18-i2c.h (renamed from drivers/media/video/cx18/cx18-i2c.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/cx18/cx18-io.c (renamed from drivers/media/video/cx18/cx18-io.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/cx18/cx18-io.h (renamed from drivers/media/video/cx18/cx18-io.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/cx18/cx18-ioctl.c (renamed from drivers/media/video/cx18/cx18-ioctl.c) | 8 | ||||
-rw-r--r-- | drivers/media/pci/cx18/cx18-ioctl.h (renamed from drivers/media/video/cx18/cx18-ioctl.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/cx18/cx18-irq.c (renamed from drivers/media/video/cx18/cx18-irq.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/cx18/cx18-irq.h (renamed from drivers/media/video/cx18/cx18-irq.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/cx18/cx18-mailbox.c (renamed from drivers/media/video/cx18/cx18-mailbox.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/cx18/cx18-mailbox.h (renamed from drivers/media/video/cx18/cx18-mailbox.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/cx18/cx18-queue.c (renamed from drivers/media/video/cx18/cx18-queue.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/cx18/cx18-queue.h (renamed from drivers/media/video/cx18/cx18-queue.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/cx18/cx18-scb.c (renamed from drivers/media/video/cx18/cx18-scb.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/cx18/cx18-scb.h (renamed from drivers/media/video/cx18/cx18-scb.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/cx18/cx18-streams.c (renamed from drivers/media/video/cx18/cx18-streams.c) | 15 | ||||
-rw-r--r-- | drivers/media/pci/cx18/cx18-streams.h (renamed from drivers/media/video/cx18/cx18-streams.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/cx18/cx18-vbi.c (renamed from drivers/media/video/cx18/cx18-vbi.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/cx18/cx18-vbi.h (renamed from drivers/media/video/cx18/cx18-vbi.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/cx18/cx18-version.h (renamed from drivers/media/video/cx18/cx18-version.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/cx18/cx18-video.c (renamed from drivers/media/video/cx18/cx18-video.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/cx18/cx18-video.h (renamed from drivers/media/video/cx18/cx18-video.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/cx18/cx23418.h (renamed from drivers/media/video/cx18/cx23418.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/cx23885/Kconfig | 50 | ||||
-rw-r--r-- | drivers/media/pci/cx23885/Makefile (renamed from drivers/media/video/cx23885/Makefile) | 8 | ||||
-rw-r--r-- | drivers/media/pci/cx23885/altera-ci.c (renamed from drivers/media/video/cx23885/altera-ci.c) | 4 | ||||
-rw-r--r-- | drivers/media/pci/cx23885/altera-ci.h (renamed from drivers/media/video/cx23885/altera-ci.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/cx23885/cimax2.c (renamed from drivers/media/video/cx23885/cimax2.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/cx23885/cimax2.h (renamed from drivers/media/video/cx23885/cimax2.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/cx23885/cx23885-417.c (renamed from drivers/media/video/cx23885/cx23885-417.c) | 2 | ||||
-rw-r--r-- | drivers/media/pci/cx23885/cx23885-alsa.c (renamed from drivers/media/video/cx23885/cx23885-alsa.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/cx23885/cx23885-av.c (renamed from drivers/media/video/cx23885/cx23885-av.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/cx23885/cx23885-av.h (renamed from drivers/media/video/cx23885/cx23885-av.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/cx23885/cx23885-cards.c (renamed from drivers/media/video/cx23885/cx23885-cards.c) | 16 | ||||
-rw-r--r-- | drivers/media/pci/cx23885/cx23885-core.c (renamed from drivers/media/video/cx23885/cx23885-core.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/cx23885/cx23885-dvb.c (renamed from drivers/media/video/cx23885/cx23885-dvb.c) | 59 | ||||
-rw-r--r-- | drivers/media/pci/cx23885/cx23885-f300.c (renamed from drivers/media/video/cx23885/cx23885-f300.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/cx23885/cx23885-f300.h (renamed from drivers/media/video/cx23885/cx23885-f300.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/cx23885/cx23885-i2c.c (renamed from drivers/media/video/cx23885/cx23885-i2c.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/cx23885/cx23885-input.c (renamed from drivers/media/video/cx23885/cx23885-input.c) | 9 | ||||
-rw-r--r-- | drivers/media/pci/cx23885/cx23885-input.h (renamed from drivers/media/video/cx23885/cx23885-input.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/cx23885/cx23885-ioctl.c (renamed from drivers/media/video/cx23885/cx23885-ioctl.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/cx23885/cx23885-ioctl.h (renamed from drivers/media/video/cx23885/cx23885-ioctl.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/cx23885/cx23885-ir.c (renamed from drivers/media/video/cx23885/cx23885-ir.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/cx23885/cx23885-ir.h (renamed from drivers/media/video/cx23885/cx23885-ir.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/cx23885/cx23885-reg.h (renamed from drivers/media/video/cx23885/cx23885-reg.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/cx23885/cx23885-vbi.c (renamed from drivers/media/video/cx23885/cx23885-vbi.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/cx23885/cx23885-video.c (renamed from drivers/media/video/cx23885/cx23885-video.c) | 2 | ||||
-rw-r--r-- | drivers/media/pci/cx23885/cx23885.h (renamed from drivers/media/video/cx23885/cx23885.h) | 1 | ||||
-rw-r--r-- | drivers/media/pci/cx23885/cx23888-ir.c (renamed from drivers/media/video/cx23885/cx23888-ir.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/cx23885/cx23888-ir.h (renamed from drivers/media/video/cx23885/cx23888-ir.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/cx23885/netup-eeprom.c (renamed from drivers/media/video/cx23885/netup-eeprom.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/cx23885/netup-eeprom.h (renamed from drivers/media/video/cx23885/netup-eeprom.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/cx23885/netup-init.c (renamed from drivers/media/video/cx23885/netup-init.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/cx23885/netup-init.h (renamed from drivers/media/video/cx23885/netup-init.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/cx25821/Kconfig (renamed from drivers/media/video/cx25821/Kconfig) | 0 | ||||
-rw-r--r-- | drivers/media/pci/cx25821/Makefile (renamed from drivers/media/video/cx25821/Makefile) | 8 | ||||
-rw-r--r-- | drivers/media/pci/cx25821/cx25821-alsa.c (renamed from drivers/media/video/cx25821/cx25821-alsa.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/cx25821/cx25821-audio-upstream.c (renamed from drivers/media/video/cx25821/cx25821-audio-upstream.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/cx25821/cx25821-audio-upstream.h (renamed from drivers/media/video/cx25821/cx25821-audio-upstream.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/cx25821/cx25821-audio.h (renamed from drivers/media/video/cx25821/cx25821-audio.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/cx25821/cx25821-biffuncs.h (renamed from drivers/media/video/cx25821/cx25821-biffuncs.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/cx25821/cx25821-cards.c (renamed from drivers/media/video/cx25821/cx25821-cards.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/cx25821/cx25821-core.c (renamed from drivers/media/video/cx25821/cx25821-core.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/cx25821/cx25821-gpio.c (renamed from drivers/media/video/cx25821/cx25821-gpio.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/cx25821/cx25821-i2c.c (renamed from drivers/media/video/cx25821/cx25821-i2c.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/cx25821/cx25821-medusa-defines.h (renamed from drivers/media/video/cx25821/cx25821-medusa-defines.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/cx25821/cx25821-medusa-reg.h (renamed from drivers/media/video/cx25821/cx25821-medusa-reg.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/cx25821/cx25821-medusa-video.c (renamed from drivers/media/video/cx25821/cx25821-medusa-video.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/cx25821/cx25821-medusa-video.h (renamed from drivers/media/video/cx25821/cx25821-medusa-video.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/cx25821/cx25821-reg.h (renamed from drivers/media/video/cx25821/cx25821-reg.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/cx25821/cx25821-sram.h (renamed from drivers/media/video/cx25821/cx25821-sram.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/cx25821/cx25821-video-upstream-ch2.c (renamed from drivers/media/video/cx25821/cx25821-video-upstream-ch2.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/cx25821/cx25821-video-upstream-ch2.h (renamed from drivers/media/video/cx25821/cx25821-video-upstream-ch2.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/cx25821/cx25821-video-upstream.c (renamed from drivers/media/video/cx25821/cx25821-video-upstream.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/cx25821/cx25821-video-upstream.h (renamed from drivers/media/video/cx25821/cx25821-video-upstream.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/cx25821/cx25821-video.c (renamed from drivers/media/video/cx25821/cx25821-video.c) | 2 | ||||
-rw-r--r-- | drivers/media/pci/cx25821/cx25821-video.h (renamed from drivers/media/video/cx25821/cx25821-video.h) | 2 | ||||
-rw-r--r-- | drivers/media/pci/cx25821/cx25821.h (renamed from drivers/media/video/cx25821/cx25821.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/cx88/Kconfig (renamed from drivers/media/video/cx88/Kconfig) | 36 | ||||
-rw-r--r-- | drivers/media/pci/cx88/Makefile (renamed from drivers/media/video/cx88/Makefile) | 8 | ||||
-rw-r--r-- | drivers/media/pci/cx88/cx88-alsa.c (renamed from drivers/media/video/cx88/cx88-alsa.c) | 2 | ||||
-rw-r--r-- | drivers/media/pci/cx88/cx88-blackbird.c (renamed from drivers/media/video/cx88/cx88-blackbird.c) | 2 | ||||
-rw-r--r-- | drivers/media/pci/cx88/cx88-cards.c (renamed from drivers/media/video/cx88/cx88-cards.c) | 4 | ||||
-rw-r--r-- | drivers/media/pci/cx88/cx88-core.c (renamed from drivers/media/video/cx88/cx88-core.c) | 2 | ||||
-rw-r--r-- | drivers/media/pci/cx88/cx88-dsp.c (renamed from drivers/media/video/cx88/cx88-dsp.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/cx88/cx88-dvb.c (renamed from drivers/media/video/cx88/cx88-dvb.c) | 2 | ||||
-rw-r--r-- | drivers/media/pci/cx88/cx88-i2c.c (renamed from drivers/media/video/cx88/cx88-i2c.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/cx88/cx88-input.c (renamed from drivers/media/video/cx88/cx88-input.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/cx88/cx88-mpeg.c (renamed from drivers/media/video/cx88/cx88-mpeg.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/cx88/cx88-reg.h (renamed from drivers/media/video/cx88/cx88-reg.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/cx88/cx88-tvaudio.c (renamed from drivers/media/video/cx88/cx88-tvaudio.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/cx88/cx88-vbi.c (renamed from drivers/media/video/cx88/cx88-vbi.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/cx88/cx88-video.c (renamed from drivers/media/video/cx88/cx88-video.c) | 2 | ||||
-rw-r--r-- | drivers/media/pci/cx88/cx88-vp3054-i2c.c (renamed from drivers/media/video/cx88/cx88-vp3054-i2c.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/cx88/cx88-vp3054-i2c.h (renamed from drivers/media/video/cx88/cx88-vp3054-i2c.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/cx88/cx88.h (renamed from drivers/media/video/cx88/cx88.h) | 2 | ||||
-rw-r--r-- | drivers/media/pci/ddbridge/Kconfig (renamed from drivers/media/dvb/ddbridge/Kconfig) | 10 | ||||
-rw-r--r-- | drivers/media/pci/ddbridge/Makefile (renamed from drivers/media/dvb/ddbridge/Makefile) | 6 | ||||
-rw-r--r-- | drivers/media/pci/ddbridge/ddbridge-core.c (renamed from drivers/media/dvb/ddbridge/ddbridge-core.c) | 15 | ||||
-rw-r--r-- | drivers/media/pci/ddbridge/ddbridge-regs.h (renamed from drivers/media/dvb/ddbridge/ddbridge-regs.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/ddbridge/ddbridge.h (renamed from drivers/media/dvb/ddbridge/ddbridge.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/dm1105/Kconfig (renamed from drivers/media/dvb/dm1105/Kconfig) | 14 | ||||
-rw-r--r-- | drivers/media/pci/dm1105/Makefile | 3 | ||||
-rw-r--r-- | drivers/media/pci/dm1105/dm1105.c (renamed from drivers/media/dvb/dm1105/dm1105.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/ivtv/Kconfig (renamed from drivers/media/video/ivtv/Kconfig) | 16 | ||||
-rw-r--r-- | drivers/media/pci/ivtv/Makefile (renamed from drivers/media/video/ivtv/Makefile) | 10 | ||||
-rw-r--r-- | drivers/media/pci/ivtv/ivtv-alsa-main.c | 303 | ||||
-rw-r--r-- | drivers/media/pci/ivtv/ivtv-alsa-mixer.c | 175 | ||||
-rw-r--r-- | drivers/media/pci/ivtv/ivtv-alsa-mixer.h | 23 | ||||
-rw-r--r-- | drivers/media/pci/ivtv/ivtv-alsa-pcm.c | 356 | ||||
-rw-r--r-- | drivers/media/pci/ivtv/ivtv-alsa-pcm.h | 27 | ||||
-rw-r--r-- | drivers/media/pci/ivtv/ivtv-alsa.h | 75 | ||||
-rw-r--r-- | drivers/media/pci/ivtv/ivtv-cards.c (renamed from drivers/media/video/ivtv/ivtv-cards.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/ivtv/ivtv-cards.h (renamed from drivers/media/video/ivtv/ivtv-cards.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/ivtv/ivtv-controls.c (renamed from drivers/media/video/ivtv/ivtv-controls.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/ivtv/ivtv-controls.h (renamed from drivers/media/video/ivtv/ivtv-controls.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/ivtv/ivtv-driver.c (renamed from drivers/media/video/ivtv/ivtv-driver.c) | 38 | ||||
-rw-r--r-- | drivers/media/pci/ivtv/ivtv-driver.h (renamed from drivers/media/video/ivtv/ivtv-driver.h) | 11 | ||||
-rw-r--r-- | drivers/media/pci/ivtv/ivtv-fileops.c (renamed from drivers/media/video/ivtv/ivtv-fileops.c) | 61 | ||||
-rw-r--r-- | drivers/media/pci/ivtv/ivtv-fileops.h (renamed from drivers/media/video/ivtv/ivtv-fileops.h) | 4 | ||||
-rw-r--r-- | drivers/media/pci/ivtv/ivtv-firmware.c (renamed from drivers/media/video/ivtv/ivtv-firmware.c) | 4 | ||||
-rw-r--r-- | drivers/media/pci/ivtv/ivtv-firmware.h (renamed from drivers/media/video/ivtv/ivtv-firmware.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/ivtv/ivtv-gpio.c (renamed from drivers/media/video/ivtv/ivtv-gpio.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/ivtv/ivtv-gpio.h (renamed from drivers/media/video/ivtv/ivtv-gpio.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/ivtv/ivtv-i2c.c (renamed from drivers/media/video/ivtv/ivtv-i2c.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/ivtv/ivtv-i2c.h (renamed from drivers/media/video/ivtv/ivtv-i2c.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/ivtv/ivtv-ioctl.c (renamed from drivers/media/video/ivtv/ivtv-ioctl.c) | 108 | ||||
-rw-r--r-- | drivers/media/pci/ivtv/ivtv-ioctl.h (renamed from drivers/media/video/ivtv/ivtv-ioctl.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/ivtv/ivtv-irq.c (renamed from drivers/media/video/ivtv/ivtv-irq.c) | 50 | ||||
-rw-r--r-- | drivers/media/pci/ivtv/ivtv-irq.h (renamed from drivers/media/video/ivtv/ivtv-irq.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/ivtv/ivtv-mailbox.c (renamed from drivers/media/video/ivtv/ivtv-mailbox.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/ivtv/ivtv-mailbox.h (renamed from drivers/media/video/ivtv/ivtv-mailbox.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/ivtv/ivtv-queue.c (renamed from drivers/media/video/ivtv/ivtv-queue.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/ivtv/ivtv-queue.h (renamed from drivers/media/video/ivtv/ivtv-queue.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/ivtv/ivtv-routing.c (renamed from drivers/media/video/ivtv/ivtv-routing.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/ivtv/ivtv-routing.h (renamed from drivers/media/video/ivtv/ivtv-routing.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/ivtv/ivtv-streams.c (renamed from drivers/media/video/ivtv/ivtv-streams.c) | 51 | ||||
-rw-r--r-- | drivers/media/pci/ivtv/ivtv-streams.h (renamed from drivers/media/video/ivtv/ivtv-streams.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/ivtv/ivtv-udma.c (renamed from drivers/media/video/ivtv/ivtv-udma.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/ivtv/ivtv-udma.h (renamed from drivers/media/video/ivtv/ivtv-udma.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/ivtv/ivtv-vbi.c (renamed from drivers/media/video/ivtv/ivtv-vbi.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/ivtv/ivtv-vbi.h (renamed from drivers/media/video/ivtv/ivtv-vbi.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/ivtv/ivtv-version.h (renamed from drivers/media/video/ivtv/ivtv-version.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/ivtv/ivtv-yuv.c (renamed from drivers/media/video/ivtv/ivtv-yuv.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/ivtv/ivtv-yuv.h (renamed from drivers/media/video/ivtv/ivtv-yuv.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/ivtv/ivtvfb.c (renamed from drivers/media/video/ivtv/ivtvfb.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/mantis/Kconfig (renamed from drivers/media/dvb/mantis/Kconfig) | 20 | ||||
-rw-r--r-- | drivers/media/pci/mantis/Makefile (renamed from drivers/media/dvb/mantis/Makefile) | 2 | ||||
-rw-r--r-- | drivers/media/pci/mantis/hopper_cards.c (renamed from drivers/media/dvb/mantis/hopper_cards.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/mantis/hopper_vp3028.c (renamed from drivers/media/dvb/mantis/hopper_vp3028.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/mantis/hopper_vp3028.h (renamed from drivers/media/dvb/mantis/hopper_vp3028.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/mantis/mantis_ca.c (renamed from drivers/media/dvb/mantis/mantis_ca.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/mantis/mantis_ca.h (renamed from drivers/media/dvb/mantis/mantis_ca.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/mantis/mantis_cards.c (renamed from drivers/media/dvb/mantis/mantis_cards.c) | 2 | ||||
-rw-r--r-- | drivers/media/pci/mantis/mantis_common.h (renamed from drivers/media/dvb/mantis/mantis_common.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/mantis/mantis_core.c (renamed from drivers/media/dvb/mantis/mantis_core.c) | 2 | ||||
-rw-r--r-- | drivers/media/pci/mantis/mantis_core.h (renamed from drivers/media/dvb/mantis/mantis_core.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/mantis/mantis_dma.c (renamed from drivers/media/dvb/mantis/mantis_dma.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/mantis/mantis_dma.h (renamed from drivers/media/dvb/mantis/mantis_dma.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/mantis/mantis_dvb.c (renamed from drivers/media/dvb/mantis/mantis_dvb.c) | 6 | ||||
-rw-r--r-- | drivers/media/pci/mantis/mantis_dvb.h (renamed from drivers/media/dvb/mantis/mantis_dvb.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/mantis/mantis_evm.c (renamed from drivers/media/dvb/mantis/mantis_evm.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/mantis/mantis_hif.c (renamed from drivers/media/dvb/mantis/mantis_hif.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/mantis/mantis_hif.h (renamed from drivers/media/dvb/mantis/mantis_hif.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/mantis/mantis_i2c.c (renamed from drivers/media/dvb/mantis/mantis_i2c.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/mantis/mantis_i2c.h (renamed from drivers/media/dvb/mantis/mantis_i2c.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/mantis/mantis_input.c (renamed from drivers/media/dvb/mantis/mantis_input.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/mantis/mantis_ioc.c (renamed from drivers/media/dvb/mantis/mantis_ioc.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/mantis/mantis_ioc.h (renamed from drivers/media/dvb/mantis/mantis_ioc.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/mantis/mantis_link.h (renamed from drivers/media/dvb/mantis/mantis_link.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/mantis/mantis_pci.c (renamed from drivers/media/dvb/mantis/mantis_pci.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/mantis/mantis_pci.h (renamed from drivers/media/dvb/mantis/mantis_pci.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/mantis/mantis_pcmcia.c (renamed from drivers/media/dvb/mantis/mantis_pcmcia.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/mantis/mantis_reg.h (renamed from drivers/media/dvb/mantis/mantis_reg.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/mantis/mantis_uart.c (renamed from drivers/media/dvb/mantis/mantis_uart.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/mantis/mantis_uart.h (renamed from drivers/media/dvb/mantis/mantis_uart.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/mantis/mantis_vp1033.c (renamed from drivers/media/dvb/mantis/mantis_vp1033.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/mantis/mantis_vp1033.h (renamed from drivers/media/dvb/mantis/mantis_vp1033.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/mantis/mantis_vp1034.c (renamed from drivers/media/dvb/mantis/mantis_vp1034.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/mantis/mantis_vp1034.h (renamed from drivers/media/dvb/mantis/mantis_vp1034.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/mantis/mantis_vp1041.c (renamed from drivers/media/dvb/mantis/mantis_vp1041.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/mantis/mantis_vp1041.h (renamed from drivers/media/dvb/mantis/mantis_vp1041.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/mantis/mantis_vp2033.c (renamed from drivers/media/dvb/mantis/mantis_vp2033.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/mantis/mantis_vp2033.h (renamed from drivers/media/dvb/mantis/mantis_vp2033.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/mantis/mantis_vp2040.c (renamed from drivers/media/dvb/mantis/mantis_vp2040.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/mantis/mantis_vp2040.h (renamed from drivers/media/dvb/mantis/mantis_vp2040.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/mantis/mantis_vp3028.c (renamed from drivers/media/dvb/mantis/mantis_vp3028.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/mantis/mantis_vp3028.h (renamed from drivers/media/dvb/mantis/mantis_vp3028.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/mantis/mantis_vp3030.c (renamed from drivers/media/dvb/mantis/mantis_vp3030.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/mantis/mantis_vp3030.h (renamed from drivers/media/dvb/mantis/mantis_vp3030.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/meye/Kconfig | 13 | ||||
-rw-r--r-- | drivers/media/pci/meye/Makefile | 1 | ||||
-rw-r--r-- | drivers/media/pci/meye/meye.c (renamed from drivers/media/video/meye.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/meye/meye.h (renamed from drivers/media/video/meye.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/ngene/Kconfig | 13 | ||||
-rw-r--r-- | drivers/media/pci/ngene/Makefile (renamed from drivers/media/dvb/ngene/Makefile) | 6 | ||||
-rw-r--r-- | drivers/media/pci/ngene/ngene-cards.c (renamed from drivers/media/dvb/ngene/ngene-cards.c) | 263 | ||||
-rw-r--r-- | drivers/media/pci/ngene/ngene-core.c (renamed from drivers/media/dvb/ngene/ngene-core.c) | 14 | ||||
-rw-r--r-- | drivers/media/pci/ngene/ngene-dvb.c (renamed from drivers/media/dvb/ngene/ngene-dvb.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/ngene/ngene-i2c.c (renamed from drivers/media/dvb/ngene/ngene-i2c.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/ngene/ngene.h (renamed from drivers/media/dvb/ngene/ngene.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/pluto2/Kconfig (renamed from drivers/media/dvb/pluto2/Kconfig) | 0 | ||||
-rw-r--r-- | drivers/media/pci/pluto2/Makefile | 3 | ||||
-rw-r--r-- | drivers/media/pci/pluto2/pluto2.c (renamed from drivers/media/dvb/pluto2/pluto2.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/pt1/Kconfig (renamed from drivers/media/dvb/pt1/Kconfig) | 0 | ||||
-rw-r--r-- | drivers/media/pci/pt1/Makefile (renamed from drivers/media/dvb/pt1/Makefile) | 2 | ||||
-rw-r--r-- | drivers/media/pci/pt1/pt1.c (renamed from drivers/media/dvb/pt1/pt1.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/pt1/va1j5jf8007s.c (renamed from drivers/media/dvb/pt1/va1j5jf8007s.c) | 11 | ||||
-rw-r--r-- | drivers/media/pci/pt1/va1j5jf8007s.h (renamed from drivers/media/dvb/pt1/va1j5jf8007s.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/pt1/va1j5jf8007t.c (renamed from drivers/media/dvb/pt1/va1j5jf8007t.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/pt1/va1j5jf8007t.h (renamed from drivers/media/dvb/pt1/va1j5jf8007t.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/saa7134/Kconfig (renamed from drivers/media/video/saa7134/Kconfig) | 40 | ||||
-rw-r--r-- | drivers/media/pci/saa7134/Makefile (renamed from drivers/media/video/saa7134/Makefile) | 10 | ||||
-rw-r--r-- | drivers/media/pci/saa7134/saa6752hs.c (renamed from drivers/media/video/saa7134/saa6752hs.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/saa7134/saa7134-alsa.c (renamed from drivers/media/video/saa7134/saa7134-alsa.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/saa7134/saa7134-cards.c (renamed from drivers/media/video/saa7134/saa7134-cards.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/saa7134/saa7134-core.c (renamed from drivers/media/video/saa7134/saa7134-core.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/saa7134/saa7134-dvb.c (renamed from drivers/media/video/saa7134/saa7134-dvb.c) | 4 | ||||
-rw-r--r-- | drivers/media/pci/saa7134/saa7134-empress.c (renamed from drivers/media/video/saa7134/saa7134-empress.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/saa7134/saa7134-i2c.c (renamed from drivers/media/video/saa7134/saa7134-i2c.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/saa7134/saa7134-input.c (renamed from drivers/media/video/saa7134/saa7134-input.c) | 10 | ||||
-rw-r--r-- | drivers/media/pci/saa7134/saa7134-reg.h (renamed from drivers/media/video/saa7134/saa7134-reg.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/saa7134/saa7134-ts.c (renamed from drivers/media/video/saa7134/saa7134-ts.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/saa7134/saa7134-tvaudio.c (renamed from drivers/media/video/saa7134/saa7134-tvaudio.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/saa7134/saa7134-vbi.c (renamed from drivers/media/video/saa7134/saa7134-vbi.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/saa7134/saa7134-video.c (renamed from drivers/media/video/saa7134/saa7134-video.c) | 38 | ||||
-rw-r--r-- | drivers/media/pci/saa7134/saa7134.h (renamed from drivers/media/video/saa7134/saa7134.h) | 1 | ||||
-rw-r--r-- | drivers/media/pci/saa7146/Kconfig | 38 | ||||
-rw-r--r-- | drivers/media/pci/saa7146/Makefile | 5 | ||||
-rw-r--r-- | drivers/media/pci/saa7146/hexium_gemini.c (renamed from drivers/media/video/hexium_gemini.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/saa7146/hexium_orion.c (renamed from drivers/media/video/hexium_orion.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/saa7146/mxb.c (renamed from drivers/media/video/mxb.c) | 2 | ||||
-rw-r--r-- | drivers/media/pci/saa7164/Kconfig (renamed from drivers/media/video/saa7164/Kconfig) | 8 | ||||
-rw-r--r-- | drivers/media/pci/saa7164/Makefile (renamed from drivers/media/video/saa7164/Makefile) | 8 | ||||
-rw-r--r-- | drivers/media/pci/saa7164/saa7164-api.c (renamed from drivers/media/video/saa7164/saa7164-api.c) | 15 | ||||
-rw-r--r-- | drivers/media/pci/saa7164/saa7164-buffer.c (renamed from drivers/media/video/saa7164/saa7164-buffer.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/saa7164/saa7164-bus.c (renamed from drivers/media/video/saa7164/saa7164-bus.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/saa7164/saa7164-cards.c (renamed from drivers/media/video/saa7164/saa7164-cards.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/saa7164/saa7164-cmd.c (renamed from drivers/media/video/saa7164/saa7164-cmd.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/saa7164/saa7164-core.c (renamed from drivers/media/video/saa7164/saa7164-core.c) | 46 | ||||
-rw-r--r-- | drivers/media/pci/saa7164/saa7164-dvb.c (renamed from drivers/media/video/saa7164/saa7164-dvb.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/saa7164/saa7164-encoder.c (renamed from drivers/media/video/saa7164/saa7164-encoder.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/saa7164/saa7164-fw.c (renamed from drivers/media/video/saa7164/saa7164-fw.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/saa7164/saa7164-i2c.c (renamed from drivers/media/video/saa7164/saa7164-i2c.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/saa7164/saa7164-reg.h (renamed from drivers/media/video/saa7164/saa7164-reg.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/saa7164/saa7164-types.h (renamed from drivers/media/video/saa7164/saa7164-types.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/saa7164/saa7164-vbi.c (renamed from drivers/media/video/saa7164/saa7164-vbi.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/saa7164/saa7164.h (renamed from drivers/media/video/saa7164/saa7164.h) | 1 | ||||
-rw-r--r-- | drivers/media/pci/sta2x11/Kconfig | 12 | ||||
-rw-r--r-- | drivers/media/pci/sta2x11/Makefile | 1 | ||||
-rw-r--r-- | drivers/media/pci/sta2x11/sta2x11_vip.c (renamed from drivers/media/video/sta2x11_vip.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/sta2x11/sta2x11_vip.h (renamed from drivers/media/video/sta2x11_vip.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/ttpci/Kconfig (renamed from drivers/media/dvb/ttpci/Kconfig) | 84 | ||||
-rw-r--r-- | drivers/media/pci/ttpci/Makefile (renamed from drivers/media/dvb/ttpci/Makefile) | 4 | ||||
-rw-r--r-- | drivers/media/pci/ttpci/av7110.c (renamed from drivers/media/dvb/ttpci/av7110.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/ttpci/av7110.h (renamed from drivers/media/dvb/ttpci/av7110.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/ttpci/av7110_av.c (renamed from drivers/media/dvb/ttpci/av7110_av.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/ttpci/av7110_av.h (renamed from drivers/media/dvb/ttpci/av7110_av.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/ttpci/av7110_ca.c (renamed from drivers/media/dvb/ttpci/av7110_ca.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/ttpci/av7110_ca.h (renamed from drivers/media/dvb/ttpci/av7110_ca.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/ttpci/av7110_hw.c (renamed from drivers/media/dvb/ttpci/av7110_hw.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/ttpci/av7110_hw.h (renamed from drivers/media/dvb/ttpci/av7110_hw.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/ttpci/av7110_ipack.c (renamed from drivers/media/dvb/ttpci/av7110_ipack.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/ttpci/av7110_ipack.h (renamed from drivers/media/dvb/ttpci/av7110_ipack.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/ttpci/av7110_ir.c (renamed from drivers/media/dvb/ttpci/av7110_ir.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/ttpci/av7110_v4l.c (renamed from drivers/media/dvb/ttpci/av7110_v4l.c) | 2 | ||||
-rw-r--r-- | drivers/media/pci/ttpci/budget-av.c (renamed from drivers/media/dvb/ttpci/budget-av.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/ttpci/budget-ci.c (renamed from drivers/media/dvb/ttpci/budget-ci.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/ttpci/budget-core.c (renamed from drivers/media/dvb/ttpci/budget-core.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/ttpci/budget-patch.c (renamed from drivers/media/dvb/ttpci/budget-patch.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/ttpci/budget.c (renamed from drivers/media/dvb/ttpci/budget.c) | 60 | ||||
-rw-r--r-- | drivers/media/pci/ttpci/budget.h (renamed from drivers/media/dvb/ttpci/budget.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/ttpci/ttpci-eeprom.c (renamed from drivers/media/dvb/ttpci/ttpci-eeprom.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/ttpci/ttpci-eeprom.h (renamed from drivers/media/dvb/ttpci/ttpci-eeprom.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/zoran/Kconfig (renamed from drivers/media/video/zoran/Kconfig) | 30 | ||||
-rw-r--r-- | drivers/media/pci/zoran/Makefile (renamed from drivers/media/video/zoran/Makefile) | 0 | ||||
-rw-r--r-- | drivers/media/pci/zoran/videocodec.c (renamed from drivers/media/video/zoran/videocodec.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/zoran/videocodec.h (renamed from drivers/media/video/zoran/videocodec.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/zoran/zoran.h (renamed from drivers/media/video/zoran/zoran.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/zoran/zoran_card.c (renamed from drivers/media/video/zoran/zoran_card.c) | 4 | ||||
-rw-r--r-- | drivers/media/pci/zoran/zoran_card.h (renamed from drivers/media/video/zoran/zoran_card.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/zoran/zoran_device.c (renamed from drivers/media/video/zoran/zoran_device.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/zoran/zoran_device.h (renamed from drivers/media/video/zoran/zoran_device.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/zoran/zoran_driver.c (renamed from drivers/media/video/zoran/zoran_driver.c) | 8 | ||||
-rw-r--r-- | drivers/media/pci/zoran/zoran_procfs.c (renamed from drivers/media/video/zoran/zoran_procfs.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/zoran/zoran_procfs.h (renamed from drivers/media/video/zoran/zoran_procfs.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/zoran/zr36016.c (renamed from drivers/media/video/zoran/zr36016.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/zoran/zr36016.h (renamed from drivers/media/video/zoran/zr36016.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/zoran/zr36050.c (renamed from drivers/media/video/zoran/zr36050.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/zoran/zr36050.h (renamed from drivers/media/video/zoran/zr36050.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/zoran/zr36057.h (renamed from drivers/media/video/zoran/zr36057.h) | 0 | ||||
-rw-r--r-- | drivers/media/pci/zoran/zr36060.c (renamed from drivers/media/video/zoran/zr36060.c) | 0 | ||||
-rw-r--r-- | drivers/media/pci/zoran/zr36060.h (renamed from drivers/media/video/zoran/zr36060.h) | 0 | ||||
-rw-r--r-- | drivers/media/platform/Kconfig | 223 | ||||
-rw-r--r-- | drivers/media/platform/Makefile | 50 | ||||
-rw-r--r-- | drivers/media/platform/arv.c (renamed from drivers/media/video/arv.c) | 0 | ||||
-rw-r--r-- | drivers/media/platform/blackfin/Kconfig (renamed from drivers/media/video/blackfin/Kconfig) | 0 | ||||
-rw-r--r-- | drivers/media/platform/blackfin/Makefile (renamed from drivers/media/video/blackfin/Makefile) | 0 | ||||
-rw-r--r-- | drivers/media/platform/blackfin/bfin_capture.c (renamed from drivers/media/video/blackfin/bfin_capture.c) | 18 | ||||
-rw-r--r-- | drivers/media/platform/blackfin/ppi.c (renamed from drivers/media/video/blackfin/ppi.c) | 0 | ||||
-rw-r--r-- | drivers/media/platform/coda.c | 2049 | ||||
-rw-r--r-- | drivers/media/platform/coda.h | 238 | ||||
-rw-r--r-- | drivers/media/platform/davinci/Kconfig (renamed from drivers/media/video/davinci/Kconfig) | 4 | ||||
-rw-r--r-- | drivers/media/platform/davinci/Makefile (renamed from drivers/media/video/davinci/Makefile) | 0 | ||||
-rw-r--r-- | drivers/media/platform/davinci/ccdc_hw_device.h (renamed from drivers/media/video/davinci/ccdc_hw_device.h) | 0 | ||||
-rw-r--r-- | drivers/media/platform/davinci/dm355_ccdc.c (renamed from drivers/media/video/davinci/dm355_ccdc.c) | 2 | ||||
-rw-r--r-- | drivers/media/platform/davinci/dm355_ccdc_regs.h (renamed from drivers/media/video/davinci/dm355_ccdc_regs.h) | 0 | ||||
-rw-r--r-- | drivers/media/platform/davinci/dm644x_ccdc.c (renamed from drivers/media/video/davinci/dm644x_ccdc.c) | 2 | ||||
-rw-r--r-- | drivers/media/platform/davinci/dm644x_ccdc_regs.h (renamed from drivers/media/video/davinci/dm644x_ccdc_regs.h) | 0 | ||||
-rw-r--r-- | drivers/media/platform/davinci/isif.c (renamed from drivers/media/video/davinci/isif.c) | 2 | ||||
-rw-r--r-- | drivers/media/platform/davinci/isif_regs.h (renamed from drivers/media/video/davinci/isif_regs.h) | 0 | ||||
-rw-r--r-- | drivers/media/platform/davinci/vpbe.c (renamed from drivers/media/video/davinci/vpbe.c) | 0 | ||||
-rw-r--r-- | drivers/media/platform/davinci/vpbe_display.c (renamed from drivers/media/video/davinci/vpbe_display.c) | 25 | ||||
-rw-r--r-- | drivers/media/platform/davinci/vpbe_osd.c (renamed from drivers/media/video/davinci/vpbe_osd.c) | 0 | ||||
-rw-r--r-- | drivers/media/platform/davinci/vpbe_osd_regs.h (renamed from drivers/media/video/davinci/vpbe_osd_regs.h) | 0 | ||||
-rw-r--r-- | drivers/media/platform/davinci/vpbe_venc.c (renamed from drivers/media/video/davinci/vpbe_venc.c) | 0 | ||||
-rw-r--r-- | drivers/media/platform/davinci/vpbe_venc_regs.h (renamed from drivers/media/video/davinci/vpbe_venc_regs.h) | 0 | ||||
-rw-r--r-- | drivers/media/platform/davinci/vpfe_capture.c (renamed from drivers/media/video/davinci/vpfe_capture.c) | 19 | ||||
-rw-r--r-- | drivers/media/platform/davinci/vpif.c (renamed from drivers/media/video/davinci/vpif.c) | 18 | ||||
-rw-r--r-- | drivers/media/platform/davinci/vpif.h (renamed from drivers/media/video/davinci/vpif.h) | 4 | ||||
-rw-r--r-- | drivers/media/platform/davinci/vpif_capture.c (renamed from drivers/media/video/davinci/vpif_capture.c) | 146 | ||||
-rw-r--r-- | drivers/media/platform/davinci/vpif_capture.h (renamed from drivers/media/video/davinci/vpif_capture.h) | 4 | ||||
-rw-r--r-- | drivers/media/platform/davinci/vpif_display.c (renamed from drivers/media/video/davinci/vpif_display.c) | 141 | ||||
-rw-r--r-- | drivers/media/platform/davinci/vpif_display.h (renamed from drivers/media/video/davinci/vpif_display.h) | 4 | ||||
-rw-r--r-- | drivers/media/platform/davinci/vpss.c (renamed from drivers/media/video/davinci/vpss.c) | 2 | ||||
-rw-r--r-- | drivers/media/platform/exynos-gsc/Makefile | 3 | ||||
-rw-r--r-- | drivers/media/platform/exynos-gsc/gsc-core.c | 1252 | ||||
-rw-r--r-- | drivers/media/platform/exynos-gsc/gsc-core.h | 527 | ||||
-rw-r--r-- | drivers/media/platform/exynos-gsc/gsc-m2m.c | 770 | ||||
-rw-r--r-- | drivers/media/platform/exynos-gsc/gsc-regs.c | 425 | ||||
-rw-r--r-- | drivers/media/platform/exynos-gsc/gsc-regs.h | 172 | ||||
-rw-r--r-- | drivers/media/platform/fsl-viu.c (renamed from drivers/media/video/fsl-viu.c) | 29 | ||||
-rw-r--r-- | drivers/media/platform/indycam.c (renamed from drivers/media/video/indycam.c) | 0 | ||||
-rw-r--r-- | drivers/media/platform/indycam.h (renamed from drivers/media/video/indycam.h) | 0 | ||||
-rw-r--r-- | drivers/media/platform/m2m-deinterlace.c | 1124 | ||||
-rw-r--r-- | drivers/media/platform/marvell-ccic/Kconfig (renamed from drivers/media/video/marvell-ccic/Kconfig) | 0 | ||||
-rw-r--r-- | drivers/media/platform/marvell-ccic/Makefile (renamed from drivers/media/video/marvell-ccic/Makefile) | 0 | ||||
-rw-r--r-- | drivers/media/platform/marvell-ccic/cafe-driver.c (renamed from drivers/media/video/marvell-ccic/cafe-driver.c) | 0 | ||||
-rw-r--r-- | drivers/media/platform/marvell-ccic/mcam-core.c (renamed from drivers/media/video/marvell-ccic/mcam-core.c) | 0 | ||||
-rw-r--r-- | drivers/media/platform/marvell-ccic/mcam-core.h (renamed from drivers/media/video/marvell-ccic/mcam-core.h) | 0 | ||||
-rw-r--r-- | drivers/media/platform/marvell-ccic/mmp-driver.c (renamed from drivers/media/video/marvell-ccic/mmp-driver.c) | 0 | ||||
-rw-r--r-- | drivers/media/platform/mem2mem_testdev.c (renamed from drivers/media/video/mem2mem_testdev.c) | 44 | ||||
-rw-r--r-- | drivers/media/platform/mx2_emmaprp.c (renamed from drivers/media/video/mx2_emmaprp.c) | 78 | ||||
-rw-r--r-- | drivers/media/platform/omap/Kconfig (renamed from drivers/media/video/omap/Kconfig) | 0 | ||||
-rw-r--r-- | drivers/media/platform/omap/Makefile (renamed from drivers/media/video/omap/Makefile) | 2 | ||||
-rw-r--r-- | drivers/media/platform/omap/omap_vout.c (renamed from drivers/media/video/omap/omap_vout.c) | 5 | ||||
-rw-r--r-- | drivers/media/platform/omap/omap_vout_vrfb.c (renamed from drivers/media/video/omap/omap_vout_vrfb.c) | 0 | ||||
-rw-r--r-- | drivers/media/platform/omap/omap_vout_vrfb.h (renamed from drivers/media/video/omap/omap_vout_vrfb.h) | 0 | ||||
-rw-r--r-- | drivers/media/platform/omap/omap_voutdef.h (renamed from drivers/media/video/omap/omap_voutdef.h) | 0 | ||||
-rw-r--r-- | drivers/media/platform/omap/omap_voutlib.c (renamed from drivers/media/video/omap/omap_voutlib.c) | 0 | ||||
-rw-r--r-- | drivers/media/platform/omap/omap_voutlib.h (renamed from drivers/media/video/omap/omap_voutlib.h) | 0 | ||||
-rw-r--r-- | drivers/media/platform/omap24xxcam-dma.c (renamed from drivers/media/video/omap24xxcam-dma.c) | 2 | ||||
-rw-r--r-- | drivers/media/platform/omap24xxcam.c (renamed from drivers/media/video/omap24xxcam.c) | 2 | ||||
-rw-r--r-- | drivers/media/platform/omap24xxcam.h (renamed from drivers/media/video/omap24xxcam.h) | 2 | ||||
-rw-r--r-- | drivers/media/platform/omap3isp/Makefile (renamed from drivers/media/video/omap3isp/Makefile) | 0 | ||||
-rw-r--r-- | drivers/media/platform/omap3isp/cfa_coef_table.h (renamed from drivers/media/video/omap3isp/cfa_coef_table.h) | 16 | ||||
-rw-r--r-- | drivers/media/platform/omap3isp/gamma_table.h (renamed from drivers/media/video/omap3isp/gamma_table.h) | 0 | ||||
-rw-r--r-- | drivers/media/platform/omap3isp/isp.c (renamed from drivers/media/video/omap3isp/isp.c) | 53 | ||||
-rw-r--r-- | drivers/media/platform/omap3isp/isp.h (renamed from drivers/media/video/omap3isp/isp.h) | 11 | ||||
-rw-r--r-- | drivers/media/platform/omap3isp/ispccdc.c (renamed from drivers/media/video/omap3isp/ispccdc.c) | 238 | ||||
-rw-r--r-- | drivers/media/platform/omap3isp/ispccdc.h (renamed from drivers/media/video/omap3isp/ispccdc.h) | 37 | ||||
-rw-r--r-- | drivers/media/platform/omap3isp/ispccp2.c (renamed from drivers/media/video/omap3isp/ispccp2.c) | 0 | ||||
-rw-r--r-- | drivers/media/platform/omap3isp/ispccp2.h (renamed from drivers/media/video/omap3isp/ispccp2.h) | 0 | ||||
-rw-r--r-- | drivers/media/platform/omap3isp/ispcsi2.c (renamed from drivers/media/video/omap3isp/ispcsi2.c) | 27 | ||||
-rw-r--r-- | drivers/media/platform/omap3isp/ispcsi2.h (renamed from drivers/media/video/omap3isp/ispcsi2.h) | 0 | ||||
-rw-r--r-- | drivers/media/platform/omap3isp/ispcsiphy.c (renamed from drivers/media/video/omap3isp/ispcsiphy.c) | 0 | ||||
-rw-r--r-- | drivers/media/platform/omap3isp/ispcsiphy.h (renamed from drivers/media/video/omap3isp/ispcsiphy.h) | 0 | ||||
-rw-r--r-- | drivers/media/platform/omap3isp/isph3a.h (renamed from drivers/media/video/omap3isp/isph3a.h) | 0 | ||||
-rw-r--r-- | drivers/media/platform/omap3isp/isph3a_aewb.c (renamed from drivers/media/video/omap3isp/isph3a_aewb.c) | 10 | ||||
-rw-r--r-- | drivers/media/platform/omap3isp/isph3a_af.c (renamed from drivers/media/video/omap3isp/isph3a_af.c) | 10 | ||||
-rw-r--r-- | drivers/media/platform/omap3isp/isphist.c (renamed from drivers/media/video/omap3isp/isphist.c) | 6 | ||||
-rw-r--r-- | drivers/media/platform/omap3isp/isphist.h (renamed from drivers/media/video/omap3isp/isphist.h) | 0 | ||||
-rw-r--r-- | drivers/media/platform/omap3isp/isppreview.c (renamed from drivers/media/video/omap3isp/isppreview.c) | 707 | ||||
-rw-r--r-- | drivers/media/platform/omap3isp/isppreview.h (renamed from drivers/media/video/omap3isp/isppreview.h) | 1 | ||||
-rw-r--r-- | drivers/media/platform/omap3isp/ispqueue.c (renamed from drivers/media/video/omap3isp/ispqueue.c) | 15 | ||||
-rw-r--r-- | drivers/media/platform/omap3isp/ispqueue.h (renamed from drivers/media/video/omap3isp/ispqueue.h) | 0 | ||||
-rw-r--r-- | drivers/media/platform/omap3isp/ispreg.h (renamed from drivers/media/video/omap3isp/ispreg.h) | 0 | ||||
-rw-r--r-- | drivers/media/platform/omap3isp/ispresizer.c (renamed from drivers/media/video/omap3isp/ispresizer.c) | 8 | ||||
-rw-r--r-- | drivers/media/platform/omap3isp/ispresizer.h (renamed from drivers/media/video/omap3isp/ispresizer.h) | 0 | ||||
-rw-r--r-- | drivers/media/platform/omap3isp/ispstat.c (renamed from drivers/media/video/omap3isp/ispstat.c) | 4 | ||||
-rw-r--r-- | drivers/media/platform/omap3isp/ispstat.h (renamed from drivers/media/video/omap3isp/ispstat.h) | 4 | ||||
-rw-r--r-- | drivers/media/platform/omap3isp/ispvideo.c (renamed from drivers/media/video/omap3isp/ispvideo.c) | 66 | ||||
-rw-r--r-- | drivers/media/platform/omap3isp/ispvideo.h (renamed from drivers/media/video/omap3isp/ispvideo.h) | 6 | ||||
-rw-r--r-- | drivers/media/platform/omap3isp/luma_enhance_table.h (renamed from drivers/media/video/omap3isp/luma_enhance_table.h) | 0 | ||||
-rw-r--r-- | drivers/media/platform/omap3isp/noise_filter_table.h (renamed from drivers/media/video/omap3isp/noise_filter_table.h) | 0 | ||||
-rw-r--r-- | drivers/media/platform/s5p-fimc/Kconfig (renamed from drivers/media/video/s5p-fimc/Kconfig) | 2 | ||||
-rw-r--r-- | drivers/media/platform/s5p-fimc/Makefile (renamed from drivers/media/video/s5p-fimc/Makefile) | 0 | ||||
-rw-r--r-- | drivers/media/platform/s5p-fimc/fimc-capture.c (renamed from drivers/media/video/s5p-fimc/fimc-capture.c) | 58 | ||||
-rw-r--r-- | drivers/media/platform/s5p-fimc/fimc-core.c (renamed from drivers/media/video/s5p-fimc/fimc-core.c) | 0 | ||||
-rw-r--r-- | drivers/media/platform/s5p-fimc/fimc-core.h (renamed from drivers/media/video/s5p-fimc/fimc-core.h) | 7 | ||||
-rw-r--r-- | drivers/media/platform/s5p-fimc/fimc-lite-reg.c (renamed from drivers/media/video/s5p-fimc/fimc-lite-reg.c) | 8 | ||||
-rw-r--r-- | drivers/media/platform/s5p-fimc/fimc-lite-reg.h (renamed from drivers/media/video/s5p-fimc/fimc-lite-reg.h) | 0 | ||||
-rw-r--r-- | drivers/media/platform/s5p-fimc/fimc-lite.c (renamed from drivers/media/video/s5p-fimc/fimc-lite.c) | 70 | ||||
-rw-r--r-- | drivers/media/platform/s5p-fimc/fimc-lite.h (renamed from drivers/media/video/s5p-fimc/fimc-lite.h) | 6 | ||||
-rw-r--r-- | drivers/media/platform/s5p-fimc/fimc-m2m.c (renamed from drivers/media/video/s5p-fimc/fimc-m2m.c) | 47 | ||||
-rw-r--r-- | drivers/media/platform/s5p-fimc/fimc-mdevice.c (renamed from drivers/media/video/s5p-fimc/fimc-mdevice.c) | 79 | ||||
-rw-r--r-- | drivers/media/platform/s5p-fimc/fimc-mdevice.h (renamed from drivers/media/video/s5p-fimc/fimc-mdevice.h) | 14 | ||||
-rw-r--r-- | drivers/media/platform/s5p-fimc/fimc-reg.c (renamed from drivers/media/video/s5p-fimc/fimc-reg.c) | 6 | ||||
-rw-r--r-- | drivers/media/platform/s5p-fimc/fimc-reg.h (renamed from drivers/media/video/s5p-fimc/fimc-reg.h) | 0 | ||||
-rw-r--r-- | drivers/media/platform/s5p-fimc/mipi-csis.c (renamed from drivers/media/video/s5p-fimc/mipi-csis.c) | 160 | ||||
-rw-r--r-- | drivers/media/platform/s5p-fimc/mipi-csis.h (renamed from drivers/media/video/s5p-fimc/mipi-csis.h) | 0 | ||||
-rw-r--r-- | drivers/media/platform/s5p-g2d/Makefile (renamed from drivers/media/video/s5p-g2d/Makefile) | 0 | ||||
-rw-r--r-- | drivers/media/platform/s5p-g2d/g2d-hw.c (renamed from drivers/media/video/s5p-g2d/g2d-hw.c) | 0 | ||||
-rw-r--r-- | drivers/media/platform/s5p-g2d/g2d-regs.h (renamed from drivers/media/video/s5p-g2d/g2d-regs.h) | 0 | ||||
-rw-r--r-- | drivers/media/platform/s5p-g2d/g2d.c (renamed from drivers/media/video/s5p-g2d/g2d.c) | 32 | ||||
-rw-r--r-- | drivers/media/platform/s5p-g2d/g2d.h (renamed from drivers/media/video/s5p-g2d/g2d.h) | 0 | ||||
-rw-r--r-- | drivers/media/platform/s5p-jpeg/Makefile (renamed from drivers/media/video/s5p-jpeg/Makefile) | 0 | ||||
-rw-r--r-- | drivers/media/platform/s5p-jpeg/jpeg-core.c (renamed from drivers/media/video/s5p-jpeg/jpeg-core.c) | 41 | ||||
-rw-r--r-- | drivers/media/platform/s5p-jpeg/jpeg-core.h (renamed from drivers/media/video/s5p-jpeg/jpeg-core.h) | 2 | ||||
-rw-r--r-- | drivers/media/platform/s5p-jpeg/jpeg-hw.h (renamed from drivers/media/video/s5p-jpeg/jpeg-hw.h) | 2 | ||||
-rw-r--r-- | drivers/media/platform/s5p-jpeg/jpeg-regs.h (renamed from drivers/media/video/s5p-jpeg/jpeg-regs.h) | 2 | ||||
-rw-r--r-- | drivers/media/platform/s5p-mfc/Makefile (renamed from drivers/media/video/s5p-mfc/Makefile) | 0 | ||||
-rw-r--r-- | drivers/media/platform/s5p-mfc/regs-mfc.h (renamed from drivers/media/video/s5p-mfc/regs-mfc.h) | 0 | ||||
-rw-r--r-- | drivers/media/platform/s5p-mfc/s5p_mfc.c (renamed from drivers/media/video/s5p-mfc/s5p_mfc.c) | 127 | ||||
-rw-r--r-- | drivers/media/platform/s5p-mfc/s5p_mfc_cmd.c (renamed from drivers/media/video/s5p-mfc/s5p_mfc_cmd.c) | 2 | ||||
-rw-r--r-- | drivers/media/platform/s5p-mfc/s5p_mfc_cmd.h (renamed from drivers/media/video/s5p-mfc/s5p_mfc_cmd.h) | 2 | ||||
-rw-r--r-- | drivers/media/platform/s5p-mfc/s5p_mfc_common.h (renamed from drivers/media/video/s5p-mfc/s5p_mfc_common.h) | 10 | ||||
-rw-r--r-- | drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c (renamed from drivers/media/video/s5p-mfc/s5p_mfc_ctrl.c) | 10 | ||||
-rw-r--r-- | drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.h (renamed from drivers/media/video/s5p-mfc/s5p_mfc_ctrl.h) | 2 | ||||
-rw-r--r-- | drivers/media/platform/s5p-mfc/s5p_mfc_debug.h (renamed from drivers/media/video/s5p-mfc/s5p_mfc_debug.h) | 2 | ||||
-rw-r--r-- | drivers/media/platform/s5p-mfc/s5p_mfc_dec.c (renamed from drivers/media/video/s5p-mfc/s5p_mfc_dec.c) | 34 | ||||
-rw-r--r-- | drivers/media/platform/s5p-mfc/s5p_mfc_dec.h (renamed from drivers/media/video/s5p-mfc/s5p_mfc_dec.h) | 2 | ||||
-rw-r--r-- | drivers/media/platform/s5p-mfc/s5p_mfc_enc.c (renamed from drivers/media/video/s5p-mfc/s5p_mfc_enc.c) | 142 | ||||
-rw-r--r-- | drivers/media/platform/s5p-mfc/s5p_mfc_enc.h (renamed from drivers/media/video/s5p-mfc/s5p_mfc_enc.h) | 2 | ||||
-rw-r--r-- | drivers/media/platform/s5p-mfc/s5p_mfc_intr.c (renamed from drivers/media/video/s5p-mfc/s5p_mfc_intr.c) | 2 | ||||
-rw-r--r-- | drivers/media/platform/s5p-mfc/s5p_mfc_intr.h (renamed from drivers/media/video/s5p-mfc/s5p_mfc_intr.h) | 2 | ||||
-rw-r--r-- | drivers/media/platform/s5p-mfc/s5p_mfc_opr.c (renamed from drivers/media/video/s5p-mfc/s5p_mfc_opr.c) | 50 | ||||
-rw-r--r-- | drivers/media/platform/s5p-mfc/s5p_mfc_opr.h (renamed from drivers/media/video/s5p-mfc/s5p_mfc_opr.h) | 2 | ||||
-rw-r--r-- | drivers/media/platform/s5p-mfc/s5p_mfc_pm.c (renamed from drivers/media/video/s5p-mfc/s5p_mfc_pm.c) | 2 | ||||
-rw-r--r-- | drivers/media/platform/s5p-mfc/s5p_mfc_pm.h (renamed from drivers/media/video/s5p-mfc/s5p_mfc_pm.h) | 2 | ||||
-rw-r--r-- | drivers/media/platform/s5p-mfc/s5p_mfc_shm.c (renamed from drivers/media/video/s5p-mfc/s5p_mfc_shm.c) | 2 | ||||
-rw-r--r-- | drivers/media/platform/s5p-mfc/s5p_mfc_shm.h (renamed from drivers/media/video/s5p-mfc/s5p_mfc_shm.h) | 2 | ||||
-rw-r--r-- | drivers/media/platform/s5p-tv/Kconfig (renamed from drivers/media/video/s5p-tv/Kconfig) | 2 | ||||
-rw-r--r-- | drivers/media/platform/s5p-tv/Makefile (renamed from drivers/media/video/s5p-tv/Makefile) | 2 | ||||
-rw-r--r-- | drivers/media/platform/s5p-tv/hdmi_drv.c (renamed from drivers/media/video/s5p-tv/hdmi_drv.c) | 6 | ||||
-rw-r--r-- | drivers/media/platform/s5p-tv/hdmiphy_drv.c (renamed from drivers/media/video/s5p-tv/hdmiphy_drv.c) | 0 | ||||
-rw-r--r-- | drivers/media/platform/s5p-tv/mixer.h (renamed from drivers/media/video/s5p-tv/mixer.h) | 0 | ||||
-rw-r--r-- | drivers/media/platform/s5p-tv/mixer_drv.c (renamed from drivers/media/video/s5p-tv/mixer_drv.c) | 8 | ||||
-rw-r--r-- | drivers/media/platform/s5p-tv/mixer_grp_layer.c (renamed from drivers/media/video/s5p-tv/mixer_grp_layer.c) | 0 | ||||
-rw-r--r-- | drivers/media/platform/s5p-tv/mixer_reg.c (renamed from drivers/media/video/s5p-tv/mixer_reg.c) | 0 | ||||
-rw-r--r-- | drivers/media/platform/s5p-tv/mixer_video.c (renamed from drivers/media/video/s5p-tv/mixer_video.c) | 41 | ||||
-rw-r--r-- | drivers/media/platform/s5p-tv/mixer_vp_layer.c (renamed from drivers/media/video/s5p-tv/mixer_vp_layer.c) | 0 | ||||
-rw-r--r-- | drivers/media/platform/s5p-tv/regs-hdmi.h (renamed from drivers/media/video/s5p-tv/regs-hdmi.h) | 0 | ||||
-rw-r--r-- | drivers/media/platform/s5p-tv/regs-mixer.h (renamed from drivers/media/video/s5p-tv/regs-mixer.h) | 0 | ||||
-rw-r--r-- | drivers/media/platform/s5p-tv/regs-sdo.h (renamed from drivers/media/video/s5p-tv/regs-sdo.h) | 2 | ||||
-rw-r--r-- | drivers/media/platform/s5p-tv/regs-vp.h (renamed from drivers/media/video/s5p-tv/regs-vp.h) | 0 | ||||
-rw-r--r-- | drivers/media/platform/s5p-tv/sdo_drv.c (renamed from drivers/media/video/s5p-tv/sdo_drv.c) | 10 | ||||
-rw-r--r-- | drivers/media/platform/s5p-tv/sii9234_drv.c (renamed from drivers/media/video/s5p-tv/sii9234_drv.c) | 17 | ||||
-rw-r--r-- | drivers/media/platform/sh_vou.c (renamed from drivers/media/video/sh_vou.c) | 30 | ||||
-rw-r--r-- | drivers/media/platform/soc_camera/Kconfig | 87 | ||||
-rw-r--r-- | drivers/media/platform/soc_camera/Makefile | 14 | ||||
-rw-r--r-- | drivers/media/platform/soc_camera/atmel-isi.c (renamed from drivers/media/video/atmel-isi.c) | 0 | ||||
-rw-r--r-- | drivers/media/platform/soc_camera/mx1_camera.c (renamed from drivers/media/video/mx1_camera.c) | 0 | ||||
-rw-r--r-- | drivers/media/platform/soc_camera/mx2_camera.c (renamed from drivers/media/video/mx2_camera.c) | 193 | ||||
-rw-r--r-- | drivers/media/platform/soc_camera/mx3_camera.c (renamed from drivers/media/video/mx3_camera.c) | 4 | ||||
-rw-r--r-- | drivers/media/platform/soc_camera/omap1_camera.c (renamed from drivers/media/video/omap1_camera.c) | 2 | ||||
-rw-r--r-- | drivers/media/platform/soc_camera/pxa_camera.c (renamed from drivers/media/video/pxa_camera.c) | 0 | ||||
-rw-r--r-- | drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c (renamed from drivers/media/video/sh_mobile_ceu_camera.c) | 4 | ||||
-rw-r--r-- | drivers/media/platform/soc_camera/sh_mobile_csi2.c (renamed from drivers/media/video/sh_mobile_csi2.c) | 0 | ||||
-rw-r--r-- | drivers/media/platform/soc_camera/soc_camera.c (renamed from drivers/media/video/soc_camera.c) | 205 | ||||
-rw-r--r-- | drivers/media/platform/soc_camera/soc_camera_platform.c (renamed from drivers/media/video/soc_camera_platform.c) | 11 | ||||
-rw-r--r-- | drivers/media/platform/soc_camera/soc_mediabus.c (renamed from drivers/media/video/soc_mediabus.c) | 0 | ||||
-rw-r--r-- | drivers/media/platform/timblogiw.c (renamed from drivers/media/video/timblogiw.c) | 0 | ||||
-rw-r--r-- | drivers/media/platform/via-camera.c (renamed from drivers/media/video/via-camera.c) | 0 | ||||
-rw-r--r-- | drivers/media/platform/via-camera.h (renamed from drivers/media/video/via-camera.h) | 0 | ||||
-rw-r--r-- | drivers/media/platform/vino.c (renamed from drivers/media/video/vino.c) | 2 | ||||
-rw-r--r-- | drivers/media/platform/vino.h (renamed from drivers/media/video/vino.h) | 0 | ||||
-rw-r--r-- | drivers/media/platform/vivi.c (renamed from drivers/media/video/vivi.c) | 56 | ||||
-rw-r--r-- | drivers/media/radio/radio-keene.c | 2 | ||||
-rw-r--r-- | drivers/media/radio/radio-miropcm20.c | 2 | ||||
-rw-r--r-- | drivers/media/radio/radio-mr800.c | 5 | ||||
-rw-r--r-- | drivers/media/radio/radio-sf16fmi.c | 2 | ||||
-rw-r--r-- | drivers/media/radio/radio-shark.c | 44 | ||||
-rw-r--r-- | drivers/media/radio/radio-shark2.c | 52 | ||||
-rw-r--r-- | drivers/media/radio/radio-si4713.c | 11 | ||||
-rw-r--r-- | drivers/media/radio/radio-tea5764.c | 15 | ||||
-rw-r--r-- | drivers/media/radio/radio-tea5777.c | 205 | ||||
-rw-r--r-- | drivers/media/radio/radio-tea5777.h | 3 | ||||
-rw-r--r-- | drivers/media/radio/radio-timb.c | 10 | ||||
-rw-r--r-- | drivers/media/radio/radio-wl1273.c | 32 | ||||
-rw-r--r-- | drivers/media/radio/saa7706h.c | 15 | ||||
-rw-r--r-- | drivers/media/radio/si470x/radio-si470x-common.c | 7 | ||||
-rw-r--r-- | drivers/media/radio/si470x/radio-si470x-i2c.c | 23 | ||||
-rw-r--r-- | drivers/media/radio/si4713-i2c.c | 4 | ||||
-rw-r--r-- | drivers/media/radio/wl128x/fmdrv_v4l2.c | 47 | ||||
-rw-r--r-- | drivers/media/rc/Kconfig | 32 | ||||
-rw-r--r-- | drivers/media/rc/Makefile | 2 | ||||
-rw-r--r-- | drivers/media/rc/ati_remote.c | 15 | ||||
-rw-r--r-- | drivers/media/rc/fintek-cir.c | 11 | ||||
-rw-r--r-- | drivers/media/rc/iguanair.c | 247 | ||||
-rw-r--r-- | drivers/media/rc/ir-lirc-codec.c | 35 | ||||
-rw-r--r-- | drivers/media/rc/ir-nec-decoder.c | 4 | ||||
-rw-r--r-- | drivers/media/rc/ir-raw.c | 6 | ||||
-rw-r--r-- | drivers/media/rc/ir-rx51.c | 498 | ||||
-rw-r--r-- | drivers/media/rc/ite-cir.c | 2 | ||||
-rw-r--r-- | drivers/media/rc/keymaps/rc-tt-1500.c | 2 | ||||
-rw-r--r-- | drivers/media/rc/mceusb.c | 30 | ||||
-rw-r--r-- | drivers/media/rc/rc-loopback.c | 12 | ||||
-rw-r--r-- | drivers/media/rc/redrat3.c | 5 | ||||
-rw-r--r-- | drivers/media/rc/ttusbir.c | 447 | ||||
-rw-r--r-- | drivers/media/rc/winbond-cir.c | 49 | ||||
-rw-r--r-- | drivers/media/tuners/Kconfig (renamed from drivers/media/common/tuners/Kconfig) | 105 | ||||
-rw-r--r-- | drivers/media/tuners/Makefile (renamed from drivers/media/common/tuners/Makefile) | 6 | ||||
-rw-r--r-- | drivers/media/tuners/e4000.c | 409 | ||||
-rw-r--r-- | drivers/media/tuners/e4000.h | 52 | ||||
-rw-r--r-- | drivers/media/tuners/e4000_priv.h | 147 | ||||
-rw-r--r-- | drivers/media/tuners/fc0011.c (renamed from drivers/media/common/tuners/fc0011.c) | 0 | ||||
-rw-r--r-- | drivers/media/tuners/fc0011.h (renamed from drivers/media/common/tuners/fc0011.h) | 0 | ||||
-rw-r--r-- | drivers/media/tuners/fc0012-priv.h (renamed from drivers/media/common/tuners/fc0012-priv.h) | 0 | ||||
-rw-r--r-- | drivers/media/tuners/fc0012.c (renamed from drivers/media/common/tuners/fc0012.c) | 0 | ||||
-rw-r--r-- | drivers/media/tuners/fc0012.h (renamed from drivers/media/common/tuners/fc0012.h) | 0 | ||||
-rw-r--r-- | drivers/media/tuners/fc0013-priv.h (renamed from drivers/media/common/tuners/fc0013-priv.h) | 0 | ||||
-rw-r--r-- | drivers/media/tuners/fc0013.c (renamed from drivers/media/common/tuners/fc0013.c) | 0 | ||||
-rw-r--r-- | drivers/media/tuners/fc0013.h (renamed from drivers/media/common/tuners/fc0013.h) | 0 | ||||
-rw-r--r-- | drivers/media/tuners/fc001x-common.h (renamed from drivers/media/common/tuners/fc001x-common.h) | 0 | ||||
-rw-r--r-- | drivers/media/tuners/fc2580.c | 529 | ||||
-rw-r--r-- | drivers/media/tuners/fc2580.h | 52 | ||||
-rw-r--r-- | drivers/media/tuners/fc2580_priv.h | 134 | ||||
-rw-r--r-- | drivers/media/tuners/max2165.c (renamed from drivers/media/common/tuners/max2165.c) | 0 | ||||
-rw-r--r-- | drivers/media/tuners/max2165.h (renamed from drivers/media/common/tuners/max2165.h) | 0 | ||||
-rw-r--r-- | drivers/media/tuners/max2165_priv.h (renamed from drivers/media/common/tuners/max2165_priv.h) | 0 | ||||
-rw-r--r-- | drivers/media/tuners/mc44s803.c (renamed from drivers/media/common/tuners/mc44s803.c) | 9 | ||||
-rw-r--r-- | drivers/media/tuners/mc44s803.h (renamed from drivers/media/common/tuners/mc44s803.h) | 0 | ||||
-rw-r--r-- | drivers/media/tuners/mc44s803_priv.h (renamed from drivers/media/common/tuners/mc44s803_priv.h) | 0 | ||||
-rw-r--r-- | drivers/media/tuners/mt2060.c (renamed from drivers/media/common/tuners/mt2060.c) | 0 | ||||
-rw-r--r-- | drivers/media/tuners/mt2060.h (renamed from drivers/media/common/tuners/mt2060.h) | 0 | ||||
-rw-r--r-- | drivers/media/tuners/mt2060_priv.h (renamed from drivers/media/common/tuners/mt2060_priv.h) | 0 | ||||
-rw-r--r-- | drivers/media/tuners/mt2063.c (renamed from drivers/media/common/tuners/mt2063.c) | 0 | ||||
-rw-r--r-- | drivers/media/tuners/mt2063.h (renamed from drivers/media/common/tuners/mt2063.h) | 0 | ||||
-rw-r--r-- | drivers/media/tuners/mt20xx.c (renamed from drivers/media/common/tuners/mt20xx.c) | 0 | ||||
-rw-r--r-- | drivers/media/tuners/mt20xx.h (renamed from drivers/media/common/tuners/mt20xx.h) | 0 | ||||
-rw-r--r-- | drivers/media/tuners/mt2131.c (renamed from drivers/media/common/tuners/mt2131.c) | 0 | ||||
-rw-r--r-- | drivers/media/tuners/mt2131.h (renamed from drivers/media/common/tuners/mt2131.h) | 0 | ||||
-rw-r--r-- | drivers/media/tuners/mt2131_priv.h (renamed from drivers/media/common/tuners/mt2131_priv.h) | 0 | ||||
-rw-r--r-- | drivers/media/tuners/mt2266.c (renamed from drivers/media/common/tuners/mt2266.c) | 0 | ||||
-rw-r--r-- | drivers/media/tuners/mt2266.h (renamed from drivers/media/common/tuners/mt2266.h) | 0 | ||||
-rw-r--r-- | drivers/media/tuners/mxl5005s.c (renamed from drivers/media/common/tuners/mxl5005s.c) | 11 | ||||
-rw-r--r-- | drivers/media/tuners/mxl5005s.h (renamed from drivers/media/common/tuners/mxl5005s.h) | 0 | ||||
-rw-r--r-- | drivers/media/tuners/mxl5007t.c (renamed from drivers/media/common/tuners/mxl5007t.c) | 0 | ||||
-rw-r--r-- | drivers/media/tuners/mxl5007t.h (renamed from drivers/media/common/tuners/mxl5007t.h) | 0 | ||||
-rw-r--r-- | drivers/media/tuners/qt1010.c (renamed from drivers/media/common/tuners/qt1010.c) | 66 | ||||
-rw-r--r-- | drivers/media/tuners/qt1010.h (renamed from drivers/media/common/tuners/qt1010.h) | 0 | ||||
-rw-r--r-- | drivers/media/tuners/qt1010_priv.h (renamed from drivers/media/common/tuners/qt1010_priv.h) | 0 | ||||
-rw-r--r-- | drivers/media/tuners/tda18212.c (renamed from drivers/media/common/tuners/tda18212.c) | 37 | ||||
-rw-r--r-- | drivers/media/tuners/tda18212.h (renamed from drivers/media/common/tuners/tda18212.h) | 0 | ||||
-rw-r--r-- | drivers/media/tuners/tda18218.c (renamed from drivers/media/common/tuners/tda18218.c) | 52 | ||||
-rw-r--r-- | drivers/media/tuners/tda18218.h (renamed from drivers/media/common/tuners/tda18218.h) | 0 | ||||
-rw-r--r-- | drivers/media/tuners/tda18218_priv.h (renamed from drivers/media/common/tuners/tda18218_priv.h) | 13 | ||||
-rw-r--r-- | drivers/media/tuners/tda18271-common.c (renamed from drivers/media/common/tuners/tda18271-common.c) | 10 | ||||
-rw-r--r-- | drivers/media/tuners/tda18271-fe.c (renamed from drivers/media/common/tuners/tda18271-fe.c) | 19 | ||||
-rw-r--r-- | drivers/media/tuners/tda18271-maps.c (renamed from drivers/media/common/tuners/tda18271-maps.c) | 0 | ||||
-rw-r--r-- | drivers/media/tuners/tda18271-priv.h (renamed from drivers/media/common/tuners/tda18271-priv.h) | 0 | ||||
-rw-r--r-- | drivers/media/tuners/tda18271.h (renamed from drivers/media/common/tuners/tda18271.h) | 5 | ||||
-rw-r--r-- | drivers/media/tuners/tda827x.c (renamed from drivers/media/common/tuners/tda827x.c) | 0 | ||||
-rw-r--r-- | drivers/media/tuners/tda827x.h (renamed from drivers/media/common/tuners/tda827x.h) | 0 | ||||
-rw-r--r-- | drivers/media/tuners/tda8290.c (renamed from drivers/media/common/tuners/tda8290.c) | 0 | ||||
-rw-r--r-- | drivers/media/tuners/tda8290.h (renamed from drivers/media/common/tuners/tda8290.h) | 0 | ||||
-rw-r--r-- | drivers/media/tuners/tda9887.c (renamed from drivers/media/common/tuners/tda9887.c) | 0 | ||||
-rw-r--r-- | drivers/media/tuners/tda9887.h (renamed from drivers/media/common/tuners/tda9887.h) | 0 | ||||
-rw-r--r-- | drivers/media/tuners/tea5761.c (renamed from drivers/media/common/tuners/tea5761.c) | 0 | ||||
-rw-r--r-- | drivers/media/tuners/tea5761.h (renamed from drivers/media/common/tuners/tea5761.h) | 0 | ||||
-rw-r--r-- | drivers/media/tuners/tea5767.c (renamed from drivers/media/common/tuners/tea5767.c) | 0 | ||||
-rw-r--r-- | drivers/media/tuners/tea5767.h (renamed from drivers/media/common/tuners/tea5767.h) | 0 | ||||
-rw-r--r-- | drivers/media/tuners/tua9001.c (renamed from drivers/media/common/tuners/tua9001.c) | 105 | ||||
-rw-r--r-- | drivers/media/tuners/tua9001.h (renamed from drivers/media/common/tuners/tua9001.h) | 20 | ||||
-rw-r--r-- | drivers/media/tuners/tua9001_priv.h (renamed from drivers/media/common/tuners/tua9001_priv.h) | 0 | ||||
-rw-r--r-- | drivers/media/tuners/tuner-i2c.h (renamed from drivers/media/common/tuners/tuner-i2c.h) | 0 | ||||
-rw-r--r-- | drivers/media/tuners/tuner-simple.c (renamed from drivers/media/common/tuners/tuner-simple.c) | 0 | ||||
-rw-r--r-- | drivers/media/tuners/tuner-simple.h (renamed from drivers/media/common/tuners/tuner-simple.h) | 0 | ||||
-rw-r--r-- | drivers/media/tuners/tuner-types.c (renamed from drivers/media/common/tuners/tuner-types.c) | 0 | ||||
-rw-r--r-- | drivers/media/tuners/tuner-xc2028-types.h (renamed from drivers/media/common/tuners/tuner-xc2028-types.h) | 0 | ||||
-rw-r--r-- | drivers/media/tuners/tuner-xc2028.c (renamed from drivers/media/common/tuners/tuner-xc2028.c) | 7 | ||||
-rw-r--r-- | drivers/media/tuners/tuner-xc2028.h (renamed from drivers/media/common/tuners/tuner-xc2028.h) | 0 | ||||
-rw-r--r-- | drivers/media/tuners/xc4000.c (renamed from drivers/media/common/tuners/xc4000.c) | 3 | ||||
-rw-r--r-- | drivers/media/tuners/xc4000.h (renamed from drivers/media/common/tuners/xc4000.h) | 0 | ||||
-rw-r--r-- | drivers/media/tuners/xc5000.c (renamed from drivers/media/common/tuners/xc5000.c) | 161 | ||||
-rw-r--r-- | drivers/media/tuners/xc5000.h (renamed from drivers/media/common/tuners/xc5000.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/Kconfig | 54 | ||||
-rw-r--r-- | drivers/media/usb/Makefile | 22 | ||||
-rw-r--r-- | drivers/media/usb/au0828/Kconfig (renamed from drivers/media/video/au0828/Kconfig) | 11 | ||||
-rw-r--r-- | drivers/media/usb/au0828/Makefile (renamed from drivers/media/video/au0828/Makefile) | 6 | ||||
-rw-r--r-- | drivers/media/usb/au0828/au0828-cards.c (renamed from drivers/media/video/au0828/au0828-cards.c) | 4 | ||||
-rw-r--r-- | drivers/media/usb/au0828/au0828-cards.h (renamed from drivers/media/video/au0828/au0828-cards.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/au0828/au0828-core.c (renamed from drivers/media/video/au0828/au0828-core.c) | 59 | ||||
-rw-r--r-- | drivers/media/usb/au0828/au0828-dvb.c (renamed from drivers/media/video/au0828/au0828-dvb.c) | 54 | ||||
-rw-r--r-- | drivers/media/usb/au0828/au0828-i2c.c (renamed from drivers/media/video/au0828/au0828-i2c.c) | 21 | ||||
-rw-r--r-- | drivers/media/usb/au0828/au0828-reg.h (renamed from drivers/media/video/au0828/au0828-reg.h) | 1 | ||||
-rw-r--r-- | drivers/media/usb/au0828/au0828-vbi.c (renamed from drivers/media/video/au0828/au0828-vbi.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/au0828/au0828-video.c (renamed from drivers/media/video/au0828/au0828-video.c) | 78 | ||||
-rw-r--r-- | drivers/media/usb/au0828/au0828.h (renamed from drivers/media/video/au0828/au0828.h) | 2 | ||||
-rw-r--r-- | drivers/media/usb/b2c2/Kconfig | 15 | ||||
-rw-r--r-- | drivers/media/usb/b2c2/Makefile | 5 | ||||
-rw-r--r-- | drivers/media/usb/b2c2/flexcop-usb.c (renamed from drivers/media/dvb/b2c2/flexcop-usb.c) | 5 | ||||
-rw-r--r-- | drivers/media/usb/b2c2/flexcop-usb.h (renamed from drivers/media/dvb/b2c2/flexcop-usb.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/cpia2/Kconfig (renamed from drivers/media/video/cpia2/Kconfig) | 0 | ||||
-rw-r--r-- | drivers/media/usb/cpia2/Makefile (renamed from drivers/media/video/cpia2/Makefile) | 0 | ||||
-rw-r--r-- | drivers/media/usb/cpia2/cpia2.h (renamed from drivers/media/video/cpia2/cpia2.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/cpia2/cpia2_core.c (renamed from drivers/media/video/cpia2/cpia2_core.c) | 6 | ||||
-rw-r--r-- | drivers/media/usb/cpia2/cpia2_registers.h (renamed from drivers/media/video/cpia2/cpia2_registers.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/cpia2/cpia2_usb.c (renamed from drivers/media/video/cpia2/cpia2_usb.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/cpia2/cpia2_v4l.c (renamed from drivers/media/video/cpia2/cpia2_v4l.c) | 44 | ||||
-rw-r--r-- | drivers/media/usb/cx231xx/Kconfig (renamed from drivers/media/video/cx231xx/Kconfig) | 8 | ||||
-rw-r--r-- | drivers/media/usb/cx231xx/Makefile (renamed from drivers/media/video/cx231xx/Makefile) | 11 | ||||
-rw-r--r-- | drivers/media/usb/cx231xx/cx231xx-417.c (renamed from drivers/media/video/cx231xx/cx231xx-417.c) | 2 | ||||
-rw-r--r-- | drivers/media/usb/cx231xx/cx231xx-audio.c (renamed from drivers/media/video/cx231xx/cx231xx-audio.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/cx231xx/cx231xx-avcore.c (renamed from drivers/media/video/cx231xx/cx231xx-avcore.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/cx231xx/cx231xx-cards.c (renamed from drivers/media/video/cx231xx/cx231xx-cards.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/cx231xx/cx231xx-conf-reg.h (renamed from drivers/media/video/cx231xx/cx231xx-conf-reg.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/cx231xx/cx231xx-core.c (renamed from drivers/media/video/cx231xx/cx231xx-core.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/cx231xx/cx231xx-dif.h (renamed from drivers/media/video/cx231xx/cx231xx-dif.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/cx231xx/cx231xx-dvb.c (renamed from drivers/media/video/cx231xx/cx231xx-dvb.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/cx231xx/cx231xx-i2c.c (renamed from drivers/media/video/cx231xx/cx231xx-i2c.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/cx231xx/cx231xx-input.c (renamed from drivers/media/video/cx231xx/cx231xx-input.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/cx231xx/cx231xx-pcb-cfg.c (renamed from drivers/media/video/cx231xx/cx231xx-pcb-cfg.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/cx231xx/cx231xx-pcb-cfg.h (renamed from drivers/media/video/cx231xx/cx231xx-pcb-cfg.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/cx231xx/cx231xx-reg.h (renamed from drivers/media/video/cx231xx/cx231xx-reg.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/cx231xx/cx231xx-vbi.c (renamed from drivers/media/video/cx231xx/cx231xx-vbi.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/cx231xx/cx231xx-vbi.h (renamed from drivers/media/video/cx231xx/cx231xx-vbi.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/cx231xx/cx231xx-video.c (renamed from drivers/media/video/cx231xx/cx231xx-video.c) | 51 | ||||
-rw-r--r-- | drivers/media/usb/cx231xx/cx231xx.h (renamed from drivers/media/video/cx231xx/cx231xx.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb-v2/Kconfig | 149 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb-v2/Makefile | 49 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb-v2/af9015.c | 1454 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb-v2/af9015.h (renamed from drivers/media/dvb/dvb-usb/af9015.h) | 55 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb-v2/af9035.c (renamed from drivers/media/dvb/dvb-usb/af9035.c) | 884 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb-v2/af9035.h (renamed from drivers/media/dvb/dvb-usb/af9035.h) | 10 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb-v2/anysee.c (renamed from drivers/media/dvb/dvb-usb/anysee.c) | 671 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb-v2/anysee.h (renamed from drivers/media/dvb/dvb-usb/anysee.h) | 10 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb-v2/au6610.c (renamed from drivers/media/dvb/dvb-usb/au6610.c) | 123 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb-v2/au6610.h (renamed from drivers/media/dvb/dvb-usb/au6610.h) | 13 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb-v2/az6007.c (renamed from drivers/media/dvb/dvb-usb/az6007.c) | 410 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb-v2/ce6230.c (renamed from drivers/media/dvb/dvb-usb/ce6230.c) | 188 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb-v2/ce6230.h (renamed from drivers/media/dvb/dvb-usb/ce6230.h) | 33 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb-v2/cypress_firmware.c | 134 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb-v2/cypress_firmware.h | 31 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb-v2/dvb_usb.h | 403 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb-v2/dvb_usb_common.h | 35 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb-v2/dvb_usb_core.c | 1049 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb-v2/dvb_usb_urb.c | 77 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb-v2/ec168.c (renamed from drivers/media/dvb/dvb-usb/ec168.c) | 326 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb-v2/ec168.h (renamed from drivers/media/dvb/dvb-usb/ec168.h) | 24 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb-v2/gl861.c (renamed from drivers/media/dvb/dvb-usb/gl861.c) | 132 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb-v2/gl861.h (renamed from drivers/media/dvb/dvb-usb/gl861.h) | 5 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb-v2/it913x.c | 799 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb-v2/lmedm04.c (renamed from drivers/media/dvb/dvb-usb/lmedm04.c) | 586 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb-v2/lmedm04.h (renamed from drivers/media/dvb/dvb-usb/lmedm04.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb-v2/mxl111sf-demod.c (renamed from drivers/media/dvb/dvb-usb/mxl111sf-demod.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb-v2/mxl111sf-demod.h (renamed from drivers/media/dvb/dvb-usb/mxl111sf-demod.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb-v2/mxl111sf-gpio.c (renamed from drivers/media/dvb/dvb-usb/mxl111sf-gpio.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb-v2/mxl111sf-gpio.h (renamed from drivers/media/dvb/dvb-usb/mxl111sf-gpio.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb-v2/mxl111sf-i2c.c (renamed from drivers/media/dvb/dvb-usb/mxl111sf-i2c.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb-v2/mxl111sf-i2c.h (renamed from drivers/media/dvb/dvb-usb/mxl111sf-i2c.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb-v2/mxl111sf-phy.c (renamed from drivers/media/dvb/dvb-usb/mxl111sf-phy.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb-v2/mxl111sf-phy.h (renamed from drivers/media/dvb/dvb-usb/mxl111sf-phy.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb-v2/mxl111sf-reg.h (renamed from drivers/media/dvb/dvb-usb/mxl111sf-reg.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.c (renamed from drivers/media/dvb/dvb-usb/mxl111sf-tuner.c) | 2 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.h (renamed from drivers/media/dvb/dvb-usb/mxl111sf-tuner.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb-v2/mxl111sf.c | 1431 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb-v2/mxl111sf.h (renamed from drivers/media/dvb/dvb-usb/mxl111sf.h) | 22 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb-v2/rtl28xxu.c (renamed from drivers/media/dvb/dvb-usb/rtl28xxu.c) | 1152 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb-v2/rtl28xxu.h (renamed from drivers/media/dvb/dvb-usb/rtl28xxu.h) | 29 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb-v2/usb_urb.c | 358 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb/Kconfig | 313 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb/Makefile | 83 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb/a800.c (renamed from drivers/media/dvb/dvb-usb/a800.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb/af9005-fe.c (renamed from drivers/media/dvb/dvb-usb/af9005-fe.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb/af9005-remote.c (renamed from drivers/media/dvb/dvb-usb/af9005-remote.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb/af9005-script.h (renamed from drivers/media/dvb/dvb-usb/af9005-script.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb/af9005.c (renamed from drivers/media/dvb/dvb-usb/af9005.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb/af9005.h (renamed from drivers/media/dvb/dvb-usb/af9005.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb/az6027.c (renamed from drivers/media/dvb/dvb-usb/az6027.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb/az6027.h (renamed from drivers/media/dvb/dvb-usb/az6027.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb/cinergyT2-core.c (renamed from drivers/media/dvb/dvb-usb/cinergyT2-core.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb/cinergyT2-fe.c (renamed from drivers/media/dvb/dvb-usb/cinergyT2-fe.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb/cinergyT2.h (renamed from drivers/media/dvb/dvb-usb/cinergyT2.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb/cxusb.c (renamed from drivers/media/dvb/dvb-usb/cxusb.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb/cxusb.h (renamed from drivers/media/dvb/dvb-usb/cxusb.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb/dib0700.h (renamed from drivers/media/dvb/dvb-usb/dib0700.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb/dib0700_core.c (renamed from drivers/media/dvb/dvb-usb/dib0700_core.c) | 6 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb/dib0700_devices.c (renamed from drivers/media/dvb/dvb-usb/dib0700_devices.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb/dib07x0.h (renamed from drivers/media/dvb/dvb-usb/dib07x0.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb/dibusb-common.c (renamed from drivers/media/dvb/dvb-usb/dibusb-common.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb/dibusb-mb.c (renamed from drivers/media/dvb/dvb-usb/dibusb-mb.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb/dibusb-mc.c (renamed from drivers/media/dvb/dvb-usb/dibusb-mc.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb/dibusb.h (renamed from drivers/media/dvb/dvb-usb/dibusb.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb/digitv.c (renamed from drivers/media/dvb/dvb-usb/digitv.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb/digitv.h (renamed from drivers/media/dvb/dvb-usb/digitv.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb/dtt200u-fe.c (renamed from drivers/media/dvb/dvb-usb/dtt200u-fe.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb/dtt200u.c (renamed from drivers/media/dvb/dvb-usb/dtt200u.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb/dtt200u.h (renamed from drivers/media/dvb/dvb-usb/dtt200u.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb/dtv5100.c (renamed from drivers/media/dvb/dvb-usb/dtv5100.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb/dtv5100.h (renamed from drivers/media/dvb/dvb-usb/dtv5100.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb/dvb-usb-common.h (renamed from drivers/media/dvb/dvb-usb/dvb-usb-common.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb/dvb-usb-dvb.c (renamed from drivers/media/dvb/dvb-usb/dvb-usb-dvb.c) | 1 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb/dvb-usb-firmware.c (renamed from drivers/media/dvb/dvb-usb/dvb-usb-firmware.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb/dvb-usb-i2c.c (renamed from drivers/media/dvb/dvb-usb/dvb-usb-i2c.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb/dvb-usb-init.c (renamed from drivers/media/dvb/dvb-usb/dvb-usb-init.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb/dvb-usb-remote.c (renamed from drivers/media/dvb/dvb-usb/dvb-usb-remote.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb/dvb-usb-urb.c (renamed from drivers/media/dvb/dvb-usb/dvb-usb-urb.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb/dvb-usb.h (renamed from drivers/media/dvb/dvb-usb/dvb-usb.h) | 2 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb/dw2102.c (renamed from drivers/media/dvb/dvb-usb/dw2102.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb/dw2102.h (renamed from drivers/media/dvb/dvb-usb/dw2102.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb/friio-fe.c (renamed from drivers/media/dvb/dvb-usb/friio-fe.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb/friio.c (renamed from drivers/media/dvb/dvb-usb/friio.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb/friio.h (renamed from drivers/media/dvb/dvb-usb/friio.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb/gp8psk-fe.c (renamed from drivers/media/dvb/dvb-usb/gp8psk-fe.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb/gp8psk.c (renamed from drivers/media/dvb/dvb-usb/gp8psk.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb/gp8psk.h (renamed from drivers/media/dvb/dvb-usb/gp8psk.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb/m920x.c (renamed from drivers/media/dvb/dvb-usb/m920x.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb/m920x.h (renamed from drivers/media/dvb/dvb-usb/m920x.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb/nova-t-usb2.c (renamed from drivers/media/dvb/dvb-usb/nova-t-usb2.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb/opera1.c (renamed from drivers/media/dvb/dvb-usb/opera1.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb/pctv452e.c (renamed from drivers/media/dvb/dvb-usb/pctv452e.c) | 7 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb/technisat-usb2.c (renamed from drivers/media/dvb/dvb-usb/technisat-usb2.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb/ttusb2.c (renamed from drivers/media/dvb/dvb-usb/ttusb2.c) | 2 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb/ttusb2.h (renamed from drivers/media/dvb/dvb-usb/ttusb2.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb/umt-010.c (renamed from drivers/media/dvb/dvb-usb/umt-010.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb/usb-urb.c (renamed from drivers/media/dvb/dvb-usb/usb-urb.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb/vp702x-fe.c (renamed from drivers/media/dvb/dvb-usb/vp702x-fe.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb/vp702x.c (renamed from drivers/media/dvb/dvb-usb/vp702x.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb/vp702x.h (renamed from drivers/media/dvb/dvb-usb/vp702x.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb/vp7045-fe.c (renamed from drivers/media/dvb/dvb-usb/vp7045-fe.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb/vp7045.c (renamed from drivers/media/dvb/dvb-usb/vp7045.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/dvb-usb/vp7045.h (renamed from drivers/media/dvb/dvb-usb/vp7045.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/em28xx/Kconfig (renamed from drivers/media/video/em28xx/Kconfig) | 28 | ||||
-rw-r--r-- | drivers/media/usb/em28xx/Makefile (renamed from drivers/media/video/em28xx/Makefile) | 10 | ||||
-rw-r--r-- | drivers/media/usb/em28xx/em28xx-audio.c (renamed from drivers/media/video/em28xx/em28xx-audio.c) | 1 | ||||
-rw-r--r-- | drivers/media/usb/em28xx/em28xx-cards.c (renamed from drivers/media/video/em28xx/em28xx-cards.c) | 22 | ||||
-rw-r--r-- | drivers/media/usb/em28xx/em28xx-core.c (renamed from drivers/media/video/em28xx/em28xx-core.c) | 4 | ||||
-rw-r--r-- | drivers/media/usb/em28xx/em28xx-dvb.c (renamed from drivers/media/video/em28xx/em28xx-dvb.c) | 60 | ||||
-rw-r--r-- | drivers/media/usb/em28xx/em28xx-i2c.c (renamed from drivers/media/video/em28xx/em28xx-i2c.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/em28xx/em28xx-input.c (renamed from drivers/media/video/em28xx/em28xx-input.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/em28xx/em28xx-reg.h (renamed from drivers/media/video/em28xx/em28xx-reg.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/em28xx/em28xx-vbi.c (renamed from drivers/media/video/em28xx/em28xx-vbi.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/em28xx/em28xx-video.c (renamed from drivers/media/video/em28xx/em28xx-video.c) | 56 | ||||
-rw-r--r-- | drivers/media/usb/em28xx/em28xx.h (renamed from drivers/media/video/em28xx/em28xx.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/gspca/Kconfig (renamed from drivers/media/video/gspca/Kconfig) | 6 | ||||
-rw-r--r-- | drivers/media/usb/gspca/Makefile (renamed from drivers/media/video/gspca/Makefile) | 0 | ||||
-rw-r--r-- | drivers/media/usb/gspca/autogain_functions.c (renamed from drivers/media/video/gspca/autogain_functions.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/gspca/autogain_functions.h (renamed from drivers/media/video/gspca/autogain_functions.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/gspca/benq.c (renamed from drivers/media/video/gspca/benq.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/gspca/conex.c (renamed from drivers/media/video/gspca/conex.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/gspca/cpia1.c (renamed from drivers/media/video/gspca/cpia1.c) | 2 | ||||
-rw-r--r-- | drivers/media/usb/gspca/etoms.c (renamed from drivers/media/video/gspca/etoms.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/gspca/finepix.c (renamed from drivers/media/video/gspca/finepix.c) | 18 | ||||
-rw-r--r-- | drivers/media/usb/gspca/gl860/Kconfig (renamed from drivers/media/video/gspca/gl860/Kconfig) | 0 | ||||
-rw-r--r-- | drivers/media/usb/gspca/gl860/Makefile (renamed from drivers/media/video/gspca/gl860/Makefile) | 2 | ||||
-rw-r--r-- | drivers/media/usb/gspca/gl860/gl860-mi1320.c (renamed from drivers/media/video/gspca/gl860/gl860-mi1320.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/gspca/gl860/gl860-mi2020.c (renamed from drivers/media/video/gspca/gl860/gl860-mi2020.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/gspca/gl860/gl860-ov2640.c (renamed from drivers/media/video/gspca/gl860/gl860-ov2640.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/gspca/gl860/gl860-ov9655.c (renamed from drivers/media/video/gspca/gl860/gl860-ov9655.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/gspca/gl860/gl860.c (renamed from drivers/media/video/gspca/gl860/gl860.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/gspca/gl860/gl860.h (renamed from drivers/media/video/gspca/gl860/gl860.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/gspca/gspca.c (renamed from drivers/media/video/gspca/gspca.c) | 14 | ||||
-rw-r--r-- | drivers/media/usb/gspca/gspca.h (renamed from drivers/media/video/gspca/gspca.h) | 8 | ||||
-rw-r--r-- | drivers/media/usb/gspca/jeilinj.c (renamed from drivers/media/video/gspca/jeilinj.c) | 2 | ||||
-rw-r--r-- | drivers/media/usb/gspca/jl2005bcd.c (renamed from drivers/media/video/gspca/jl2005bcd.c) | 18 | ||||
-rw-r--r-- | drivers/media/usb/gspca/jpeg.h (renamed from drivers/media/video/gspca/jpeg.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/gspca/kinect.c (renamed from drivers/media/video/gspca/kinect.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/gspca/konica.c (renamed from drivers/media/video/gspca/konica.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/gspca/m5602/Kconfig (renamed from drivers/media/video/gspca/m5602/Kconfig) | 0 | ||||
-rw-r--r-- | drivers/media/usb/gspca/m5602/Makefile (renamed from drivers/media/video/gspca/m5602/Makefile) | 2 | ||||
-rw-r--r-- | drivers/media/usb/gspca/m5602/m5602_bridge.h (renamed from drivers/media/video/gspca/m5602/m5602_bridge.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/gspca/m5602/m5602_core.c (renamed from drivers/media/video/gspca/m5602/m5602_core.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/gspca/m5602/m5602_mt9m111.c (renamed from drivers/media/video/gspca/m5602/m5602_mt9m111.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/gspca/m5602/m5602_mt9m111.h (renamed from drivers/media/video/gspca/m5602/m5602_mt9m111.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/gspca/m5602/m5602_ov7660.c (renamed from drivers/media/video/gspca/m5602/m5602_ov7660.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/gspca/m5602/m5602_ov7660.h (renamed from drivers/media/video/gspca/m5602/m5602_ov7660.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/gspca/m5602/m5602_ov9650.c (renamed from drivers/media/video/gspca/m5602/m5602_ov9650.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/gspca/m5602/m5602_ov9650.h (renamed from drivers/media/video/gspca/m5602/m5602_ov9650.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/gspca/m5602/m5602_po1030.c (renamed from drivers/media/video/gspca/m5602/m5602_po1030.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/gspca/m5602/m5602_po1030.h (renamed from drivers/media/video/gspca/m5602/m5602_po1030.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/gspca/m5602/m5602_s5k4aa.c (renamed from drivers/media/video/gspca/m5602/m5602_s5k4aa.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/gspca/m5602/m5602_s5k4aa.h (renamed from drivers/media/video/gspca/m5602/m5602_s5k4aa.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/gspca/m5602/m5602_s5k83a.c (renamed from drivers/media/video/gspca/m5602/m5602_s5k83a.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/gspca/m5602/m5602_s5k83a.h (renamed from drivers/media/video/gspca/m5602/m5602_s5k83a.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/gspca/m5602/m5602_sensor.h (renamed from drivers/media/video/gspca/m5602/m5602_sensor.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/gspca/mars.c (renamed from drivers/media/video/gspca/mars.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/gspca/mr97310a.c (renamed from drivers/media/video/gspca/mr97310a.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/gspca/nw80x.c (renamed from drivers/media/video/gspca/nw80x.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/gspca/ov519.c (renamed from drivers/media/video/gspca/ov519.c) | 18 | ||||
-rw-r--r-- | drivers/media/usb/gspca/ov534.c (renamed from drivers/media/video/gspca/ov534.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/gspca/ov534_9.c (renamed from drivers/media/video/gspca/ov534_9.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/gspca/pac207.c (renamed from drivers/media/video/gspca/pac207.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/gspca/pac7302.c (renamed from drivers/media/video/gspca/pac7302.c) | 47 | ||||
-rw-r--r-- | drivers/media/usb/gspca/pac7311.c (renamed from drivers/media/video/gspca/pac7311.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/gspca/pac_common.h (renamed from drivers/media/video/gspca/pac_common.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/gspca/se401.c (renamed from drivers/media/video/gspca/se401.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/gspca/se401.h (renamed from drivers/media/video/gspca/se401.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/gspca/sn9c2028.c (renamed from drivers/media/video/gspca/sn9c2028.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/gspca/sn9c2028.h (renamed from drivers/media/video/gspca/sn9c2028.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/gspca/sn9c20x.c (renamed from drivers/media/video/gspca/sn9c20x.c) | 2 | ||||
-rw-r--r-- | drivers/media/usb/gspca/sonixb.c (renamed from drivers/media/video/gspca/sonixb.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/gspca/sonixj.c (renamed from drivers/media/video/gspca/sonixj.c) | 2 | ||||
-rw-r--r-- | drivers/media/usb/gspca/spca1528.c (renamed from drivers/media/video/gspca/spca1528.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/gspca/spca500.c (renamed from drivers/media/video/gspca/spca500.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/gspca/spca501.c (renamed from drivers/media/video/gspca/spca501.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/gspca/spca505.c (renamed from drivers/media/video/gspca/spca505.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/gspca/spca506.c (renamed from drivers/media/video/gspca/spca506.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/gspca/spca508.c (renamed from drivers/media/video/gspca/spca508.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/gspca/spca561.c (renamed from drivers/media/video/gspca/spca561.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/gspca/sq905.c (renamed from drivers/media/video/gspca/sq905.c) | 19 | ||||
-rw-r--r-- | drivers/media/usb/gspca/sq905c.c (renamed from drivers/media/video/gspca/sq905c.c) | 25 | ||||
-rw-r--r-- | drivers/media/usb/gspca/sq930x.c (renamed from drivers/media/video/gspca/sq930x.c) | 10 | ||||
-rw-r--r-- | drivers/media/usb/gspca/stk014.c (renamed from drivers/media/video/gspca/stk014.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/gspca/stv0680.c (renamed from drivers/media/video/gspca/stv0680.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/gspca/stv06xx/Kconfig (renamed from drivers/media/video/gspca/stv06xx/Kconfig) | 0 | ||||
-rw-r--r-- | drivers/media/usb/gspca/stv06xx/Makefile (renamed from drivers/media/video/gspca/stv06xx/Makefile) | 2 | ||||
-rw-r--r-- | drivers/media/usb/gspca/stv06xx/stv06xx.c (renamed from drivers/media/video/gspca/stv06xx/stv06xx.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/gspca/stv06xx/stv06xx.h (renamed from drivers/media/video/gspca/stv06xx/stv06xx.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/gspca/stv06xx/stv06xx_hdcs.c (renamed from drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/gspca/stv06xx/stv06xx_hdcs.h (renamed from drivers/media/video/gspca/stv06xx/stv06xx_hdcs.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/gspca/stv06xx/stv06xx_pb0100.c (renamed from drivers/media/video/gspca/stv06xx/stv06xx_pb0100.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/gspca/stv06xx/stv06xx_pb0100.h (renamed from drivers/media/video/gspca/stv06xx/stv06xx_pb0100.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/gspca/stv06xx/stv06xx_sensor.h (renamed from drivers/media/video/gspca/stv06xx/stv06xx_sensor.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/gspca/stv06xx/stv06xx_st6422.c (renamed from drivers/media/video/gspca/stv06xx/stv06xx_st6422.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/gspca/stv06xx/stv06xx_st6422.h (renamed from drivers/media/video/gspca/stv06xx/stv06xx_st6422.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/gspca/stv06xx/stv06xx_vv6410.c (renamed from drivers/media/video/gspca/stv06xx/stv06xx_vv6410.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/gspca/stv06xx/stv06xx_vv6410.h (renamed from drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/gspca/sunplus.c (renamed from drivers/media/video/gspca/sunplus.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/gspca/t613.c (renamed from drivers/media/video/gspca/t613.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/gspca/topro.c (renamed from drivers/media/video/gspca/topro.c) | 2 | ||||
-rw-r--r-- | drivers/media/usb/gspca/tv8532.c (renamed from drivers/media/video/gspca/tv8532.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/gspca/vc032x.c (renamed from drivers/media/video/gspca/vc032x.c) | 7 | ||||
-rw-r--r-- | drivers/media/usb/gspca/vicam.c (renamed from drivers/media/video/gspca/vicam.c) | 17 | ||||
-rw-r--r-- | drivers/media/usb/gspca/w996Xcf.c (renamed from drivers/media/video/gspca/w996Xcf.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/gspca/xirlink_cit.c (renamed from drivers/media/video/gspca/xirlink_cit.c) | 4 | ||||
-rw-r--r-- | drivers/media/usb/gspca/zc3xx-reg.h (renamed from drivers/media/video/gspca/zc3xx-reg.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/gspca/zc3xx.c (renamed from drivers/media/video/gspca/zc3xx.c) | 17 | ||||
-rw-r--r-- | drivers/media/usb/hdpvr/Kconfig (renamed from drivers/media/video/hdpvr/Kconfig) | 0 | ||||
-rw-r--r-- | drivers/media/usb/hdpvr/Makefile (renamed from drivers/media/video/hdpvr/Makefile) | 2 | ||||
-rw-r--r-- | drivers/media/usb/hdpvr/hdpvr-control.c (renamed from drivers/media/video/hdpvr/hdpvr-control.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/hdpvr/hdpvr-core.c (renamed from drivers/media/video/hdpvr/hdpvr-core.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/hdpvr/hdpvr-i2c.c (renamed from drivers/media/video/hdpvr/hdpvr-i2c.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/hdpvr/hdpvr-video.c (renamed from drivers/media/video/hdpvr/hdpvr-video.c) | 2 | ||||
-rw-r--r-- | drivers/media/usb/hdpvr/hdpvr.h (renamed from drivers/media/video/hdpvr/hdpvr.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/pvrusb2/Kconfig (renamed from drivers/media/video/pvrusb2/Kconfig) | 14 | ||||
-rw-r--r-- | drivers/media/usb/pvrusb2/Makefile (renamed from drivers/media/video/pvrusb2/Makefile) | 8 | ||||
-rw-r--r-- | drivers/media/usb/pvrusb2/pvrusb2-audio.c (renamed from drivers/media/video/pvrusb2/pvrusb2-audio.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/pvrusb2/pvrusb2-audio.h (renamed from drivers/media/video/pvrusb2/pvrusb2-audio.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/pvrusb2/pvrusb2-context.c (renamed from drivers/media/video/pvrusb2/pvrusb2-context.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/pvrusb2/pvrusb2-context.h (renamed from drivers/media/video/pvrusb2/pvrusb2-context.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/pvrusb2/pvrusb2-cs53l32a.c (renamed from drivers/media/video/pvrusb2/pvrusb2-cs53l32a.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/pvrusb2/pvrusb2-cs53l32a.h (renamed from drivers/media/video/pvrusb2/pvrusb2-cs53l32a.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/pvrusb2/pvrusb2-ctrl.c (renamed from drivers/media/video/pvrusb2/pvrusb2-ctrl.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/pvrusb2/pvrusb2-ctrl.h (renamed from drivers/media/video/pvrusb2/pvrusb2-ctrl.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/pvrusb2/pvrusb2-cx2584x-v4l.c (renamed from drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/pvrusb2/pvrusb2-cx2584x-v4l.h (renamed from drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/pvrusb2/pvrusb2-debug.h (renamed from drivers/media/video/pvrusb2/pvrusb2-debug.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/pvrusb2/pvrusb2-debugifc.c (renamed from drivers/media/video/pvrusb2/pvrusb2-debugifc.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/pvrusb2/pvrusb2-debugifc.h (renamed from drivers/media/video/pvrusb2/pvrusb2-debugifc.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/pvrusb2/pvrusb2-devattr.c (renamed from drivers/media/video/pvrusb2/pvrusb2-devattr.c) | 17 | ||||
-rw-r--r-- | drivers/media/usb/pvrusb2/pvrusb2-devattr.h (renamed from drivers/media/video/pvrusb2/pvrusb2-devattr.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/pvrusb2/pvrusb2-dvb.c (renamed from drivers/media/video/pvrusb2/pvrusb2-dvb.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/pvrusb2/pvrusb2-dvb.h (renamed from drivers/media/video/pvrusb2/pvrusb2-dvb.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/pvrusb2/pvrusb2-eeprom.c (renamed from drivers/media/video/pvrusb2/pvrusb2-eeprom.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/pvrusb2/pvrusb2-eeprom.h (renamed from drivers/media/video/pvrusb2/pvrusb2-eeprom.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/pvrusb2/pvrusb2-encoder.c (renamed from drivers/media/video/pvrusb2/pvrusb2-encoder.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/pvrusb2/pvrusb2-encoder.h (renamed from drivers/media/video/pvrusb2/pvrusb2-encoder.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/pvrusb2/pvrusb2-fx2-cmd.h (renamed from drivers/media/video/pvrusb2/pvrusb2-fx2-cmd.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/pvrusb2/pvrusb2-hdw-internal.h (renamed from drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/pvrusb2/pvrusb2-hdw.c (renamed from drivers/media/video/pvrusb2/pvrusb2-hdw.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/pvrusb2/pvrusb2-hdw.h (renamed from drivers/media/video/pvrusb2/pvrusb2-hdw.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/pvrusb2/pvrusb2-i2c-core.c (renamed from drivers/media/video/pvrusb2/pvrusb2-i2c-core.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/pvrusb2/pvrusb2-i2c-core.h (renamed from drivers/media/video/pvrusb2/pvrusb2-i2c-core.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/pvrusb2/pvrusb2-io.c (renamed from drivers/media/video/pvrusb2/pvrusb2-io.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/pvrusb2/pvrusb2-io.h (renamed from drivers/media/video/pvrusb2/pvrusb2-io.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/pvrusb2/pvrusb2-ioread.c (renamed from drivers/media/video/pvrusb2/pvrusb2-ioread.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/pvrusb2/pvrusb2-ioread.h (renamed from drivers/media/video/pvrusb2/pvrusb2-ioread.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/pvrusb2/pvrusb2-main.c (renamed from drivers/media/video/pvrusb2/pvrusb2-main.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/pvrusb2/pvrusb2-std.c (renamed from drivers/media/video/pvrusb2/pvrusb2-std.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/pvrusb2/pvrusb2-std.h (renamed from drivers/media/video/pvrusb2/pvrusb2-std.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/pvrusb2/pvrusb2-sysfs.c (renamed from drivers/media/video/pvrusb2/pvrusb2-sysfs.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/pvrusb2/pvrusb2-sysfs.h (renamed from drivers/media/video/pvrusb2/pvrusb2-sysfs.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/pvrusb2/pvrusb2-util.h (renamed from drivers/media/video/pvrusb2/pvrusb2-util.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/pvrusb2/pvrusb2-v4l2.c (renamed from drivers/media/video/pvrusb2/pvrusb2-v4l2.c) | 4 | ||||
-rw-r--r-- | drivers/media/usb/pvrusb2/pvrusb2-v4l2.h (renamed from drivers/media/video/pvrusb2/pvrusb2-v4l2.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/pvrusb2/pvrusb2-video-v4l.c (renamed from drivers/media/video/pvrusb2/pvrusb2-video-v4l.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/pvrusb2/pvrusb2-video-v4l.h (renamed from drivers/media/video/pvrusb2/pvrusb2-video-v4l.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/pvrusb2/pvrusb2-wm8775.c (renamed from drivers/media/video/pvrusb2/pvrusb2-wm8775.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/pvrusb2/pvrusb2-wm8775.h (renamed from drivers/media/video/pvrusb2/pvrusb2-wm8775.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/pvrusb2/pvrusb2.h (renamed from drivers/media/video/pvrusb2/pvrusb2.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/pwc/Kconfig (renamed from drivers/media/video/pwc/Kconfig) | 0 | ||||
-rw-r--r-- | drivers/media/usb/pwc/Makefile (renamed from drivers/media/video/pwc/Makefile) | 2 | ||||
-rw-r--r-- | drivers/media/usb/pwc/philips.txt (renamed from drivers/media/video/pwc/philips.txt) | 0 | ||||
-rw-r--r-- | drivers/media/usb/pwc/pwc-ctrl.c (renamed from drivers/media/video/pwc/pwc-ctrl.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/pwc/pwc-dec1.c (renamed from drivers/media/video/pwc/pwc-dec1.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/pwc/pwc-dec1.h (renamed from drivers/media/video/pwc/pwc-dec1.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/pwc/pwc-dec23.c (renamed from drivers/media/video/pwc/pwc-dec23.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/pwc/pwc-dec23.h (renamed from drivers/media/video/pwc/pwc-dec23.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/pwc/pwc-if.c (renamed from drivers/media/video/pwc/pwc-if.c) | 3 | ||||
-rw-r--r-- | drivers/media/usb/pwc/pwc-kiara.c (renamed from drivers/media/video/pwc/pwc-kiara.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/pwc/pwc-kiara.h (renamed from drivers/media/video/pwc/pwc-kiara.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/pwc/pwc-misc.c (renamed from drivers/media/video/pwc/pwc-misc.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/pwc/pwc-nala.h (renamed from drivers/media/video/pwc/pwc-nala.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/pwc/pwc-timon.c (renamed from drivers/media/video/pwc/pwc-timon.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/pwc/pwc-timon.h (renamed from drivers/media/video/pwc/pwc-timon.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/pwc/pwc-uncompress.c (renamed from drivers/media/video/pwc/pwc-uncompress.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/pwc/pwc-v4l.c (renamed from drivers/media/video/pwc/pwc-v4l.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/pwc/pwc.h (renamed from drivers/media/video/pwc/pwc.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/s2255/Kconfig | 9 | ||||
-rw-r--r-- | drivers/media/usb/s2255/Makefile | 2 | ||||
-rw-r--r-- | drivers/media/usb/s2255/s2255drv.c (renamed from drivers/media/video/s2255drv.c) | 45 | ||||
-rw-r--r-- | drivers/media/usb/siano/Kconfig | 10 | ||||
-rw-r--r-- | drivers/media/usb/siano/Makefile | 6 | ||||
-rw-r--r-- | drivers/media/usb/siano/smsusb.c (renamed from drivers/media/dvb/siano/smsusb.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/sn9c102/Kconfig (renamed from drivers/media/video/sn9c102/Kconfig) | 0 | ||||
-rw-r--r-- | drivers/media/usb/sn9c102/Makefile (renamed from drivers/media/video/sn9c102/Makefile) | 0 | ||||
-rw-r--r-- | drivers/media/usb/sn9c102/sn9c102.h (renamed from drivers/media/video/sn9c102/sn9c102.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/sn9c102/sn9c102_config.h (renamed from drivers/media/video/sn9c102/sn9c102_config.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/sn9c102/sn9c102_core.c (renamed from drivers/media/video/sn9c102/sn9c102_core.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/sn9c102/sn9c102_devtable.h (renamed from drivers/media/video/sn9c102/sn9c102_devtable.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/sn9c102/sn9c102_hv7131d.c (renamed from drivers/media/video/sn9c102/sn9c102_hv7131d.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/sn9c102/sn9c102_hv7131r.c (renamed from drivers/media/video/sn9c102/sn9c102_hv7131r.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/sn9c102/sn9c102_mi0343.c (renamed from drivers/media/video/sn9c102/sn9c102_mi0343.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/sn9c102/sn9c102_mi0360.c (renamed from drivers/media/video/sn9c102/sn9c102_mi0360.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/sn9c102/sn9c102_mt9v111.c (renamed from drivers/media/video/sn9c102/sn9c102_mt9v111.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/sn9c102/sn9c102_ov7630.c (renamed from drivers/media/video/sn9c102/sn9c102_ov7630.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/sn9c102/sn9c102_ov7660.c (renamed from drivers/media/video/sn9c102/sn9c102_ov7660.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/sn9c102/sn9c102_pas106b.c (renamed from drivers/media/video/sn9c102/sn9c102_pas106b.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/sn9c102/sn9c102_pas202bcb.c (renamed from drivers/media/video/sn9c102/sn9c102_pas202bcb.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/sn9c102/sn9c102_sensor.h (renamed from drivers/media/video/sn9c102/sn9c102_sensor.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/sn9c102/sn9c102_tas5110c1b.c (renamed from drivers/media/video/sn9c102/sn9c102_tas5110c1b.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/sn9c102/sn9c102_tas5110d.c (renamed from drivers/media/video/sn9c102/sn9c102_tas5110d.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/sn9c102/sn9c102_tas5130d1b.c (renamed from drivers/media/video/sn9c102/sn9c102_tas5130d1b.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/stk1160/Kconfig | 20 | ||||
-rw-r--r-- | drivers/media/usb/stk1160/Makefile | 11 | ||||
-rw-r--r-- | drivers/media/usb/stk1160/stk1160-ac97.c | 152 | ||||
-rw-r--r-- | drivers/media/usb/stk1160/stk1160-core.c | 430 | ||||
-rw-r--r-- | drivers/media/usb/stk1160/stk1160-i2c.c | 294 | ||||
-rw-r--r-- | drivers/media/usb/stk1160/stk1160-reg.h | 93 | ||||
-rw-r--r-- | drivers/media/usb/stk1160/stk1160-v4l.c | 739 | ||||
-rw-r--r-- | drivers/media/usb/stk1160/stk1160-video.c | 522 | ||||
-rw-r--r-- | drivers/media/usb/stk1160/stk1160.h | 208 | ||||
-rw-r--r-- | drivers/media/usb/stkwebcam/Kconfig | 13 | ||||
-rw-r--r-- | drivers/media/usb/stkwebcam/Makefile | 4 | ||||
-rw-r--r-- | drivers/media/usb/stkwebcam/stk-sensor.c (renamed from drivers/media/video/stk-sensor.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/stkwebcam/stk-webcam.c (renamed from drivers/media/video/stk-webcam.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/stkwebcam/stk-webcam.h (renamed from drivers/media/video/stk-webcam.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/tlg2300/Kconfig (renamed from drivers/media/video/tlg2300/Kconfig) | 0 | ||||
-rw-r--r-- | drivers/media/usb/tlg2300/Makefile | 9 | ||||
-rw-r--r-- | drivers/media/usb/tlg2300/pd-alsa.c (renamed from drivers/media/video/tlg2300/pd-alsa.c) | 4 | ||||
-rw-r--r-- | drivers/media/usb/tlg2300/pd-common.h (renamed from drivers/media/video/tlg2300/pd-common.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/tlg2300/pd-dvb.c (renamed from drivers/media/video/tlg2300/pd-dvb.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/tlg2300/pd-main.c (renamed from drivers/media/video/tlg2300/pd-main.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/tlg2300/pd-radio.c (renamed from drivers/media/video/tlg2300/pd-radio.c) | 2 | ||||
-rw-r--r-- | drivers/media/usb/tlg2300/pd-video.c (renamed from drivers/media/video/tlg2300/pd-video.c) | 2 | ||||
-rw-r--r-- | drivers/media/usb/tlg2300/vendorcmds.h (renamed from drivers/media/video/tlg2300/vendorcmds.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/tm6000/Kconfig (renamed from drivers/media/video/tm6000/Kconfig) | 0 | ||||
-rw-r--r-- | drivers/media/usb/tm6000/Makefile (renamed from drivers/media/video/tm6000/Makefile) | 8 | ||||
-rw-r--r-- | drivers/media/usb/tm6000/tm6000-alsa.c (renamed from drivers/media/video/tm6000/tm6000-alsa.c) | 3 | ||||
-rw-r--r-- | drivers/media/usb/tm6000/tm6000-cards.c (renamed from drivers/media/video/tm6000/tm6000-cards.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/tm6000/tm6000-core.c (renamed from drivers/media/video/tm6000/tm6000-core.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/tm6000/tm6000-dvb.c (renamed from drivers/media/video/tm6000/tm6000-dvb.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/tm6000/tm6000-i2c.c (renamed from drivers/media/video/tm6000/tm6000-i2c.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/tm6000/tm6000-input.c (renamed from drivers/media/video/tm6000/tm6000-input.c) | 3 | ||||
-rw-r--r-- | drivers/media/usb/tm6000/tm6000-regs.h (renamed from drivers/media/video/tm6000/tm6000-regs.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/tm6000/tm6000-stds.c (renamed from drivers/media/video/tm6000/tm6000-stds.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/tm6000/tm6000-usb-isoc.h (renamed from drivers/media/video/tm6000/tm6000-usb-isoc.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/tm6000/tm6000-video.c (renamed from drivers/media/video/tm6000/tm6000-video.c) | 54 | ||||
-rw-r--r-- | drivers/media/usb/tm6000/tm6000.h (renamed from drivers/media/video/tm6000/tm6000.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/ttusb-budget/Kconfig (renamed from drivers/media/dvb/ttusb-budget/Kconfig) | 14 | ||||
-rw-r--r-- | drivers/media/usb/ttusb-budget/Makefile | 3 | ||||
-rw-r--r-- | drivers/media/usb/ttusb-budget/dvb-ttusb-budget.c (renamed from drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/ttusb-dec/Kconfig (renamed from drivers/media/dvb/ttusb-dec/Kconfig) | 0 | ||||
-rw-r--r-- | drivers/media/usb/ttusb-dec/Makefile (renamed from drivers/media/dvb/ttusb-dec/Makefile) | 2 | ||||
-rw-r--r-- | drivers/media/usb/ttusb-dec/ttusb_dec.c (renamed from drivers/media/dvb/ttusb-dec/ttusb_dec.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/ttusb-dec/ttusbdecfe.c (renamed from drivers/media/dvb/ttusb-dec/ttusbdecfe.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/ttusb-dec/ttusbdecfe.h (renamed from drivers/media/dvb/ttusb-dec/ttusbdecfe.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/usbvision/Kconfig (renamed from drivers/media/video/usbvision/Kconfig) | 2 | ||||
-rw-r--r-- | drivers/media/usb/usbvision/Makefile (renamed from drivers/media/video/usbvision/Makefile) | 4 | ||||
-rw-r--r-- | drivers/media/usb/usbvision/usbvision-cards.c (renamed from drivers/media/video/usbvision/usbvision-cards.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/usbvision/usbvision-cards.h (renamed from drivers/media/video/usbvision/usbvision-cards.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/usbvision/usbvision-core.c (renamed from drivers/media/video/usbvision/usbvision-core.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/usbvision/usbvision-i2c.c (renamed from drivers/media/video/usbvision/usbvision-i2c.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/usbvision/usbvision-video.c (renamed from drivers/media/video/usbvision/usbvision-video.c) | 44 | ||||
-rw-r--r-- | drivers/media/usb/usbvision/usbvision.h (renamed from drivers/media/video/usbvision/usbvision.h) | 0 | ||||
-rw-r--r-- | drivers/media/usb/uvc/Kconfig (renamed from drivers/media/video/uvc/Kconfig) | 0 | ||||
-rw-r--r-- | drivers/media/usb/uvc/Makefile (renamed from drivers/media/video/uvc/Makefile) | 0 | ||||
-rw-r--r-- | drivers/media/usb/uvc/uvc_ctrl.c (renamed from drivers/media/video/uvc/uvc_ctrl.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/uvc/uvc_debugfs.c (renamed from drivers/media/video/uvc/uvc_debugfs.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/uvc/uvc_driver.c (renamed from drivers/media/video/uvc/uvc_driver.c) | 42 | ||||
-rw-r--r-- | drivers/media/usb/uvc/uvc_entity.c (renamed from drivers/media/video/uvc/uvc_entity.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/uvc/uvc_isight.c (renamed from drivers/media/video/uvc/uvc_isight.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/uvc/uvc_queue.c (renamed from drivers/media/video/uvc/uvc_queue.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/uvc/uvc_status.c (renamed from drivers/media/video/uvc/uvc_status.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/uvc/uvc_v4l2.c (renamed from drivers/media/video/uvc/uvc_v4l2.c) | 0 | ||||
-rw-r--r-- | drivers/media/usb/uvc/uvc_video.c (renamed from drivers/media/video/uvc/uvc_video.c) | 30 | ||||
-rw-r--r-- | drivers/media/usb/uvc/uvcvideo.h (renamed from drivers/media/video/uvc/uvcvideo.h) | 9 | ||||
-rw-r--r-- | drivers/media/usb/zr364xx/Kconfig | 14 | ||||
-rw-r--r-- | drivers/media/usb/zr364xx/Makefile | 2 | ||||
-rw-r--r-- | drivers/media/usb/zr364xx/zr364xx.c (renamed from drivers/media/video/zr364xx.c) | 0 | ||||
-rw-r--r-- | drivers/media/v4l2-core/Kconfig | 81 | ||||
-rw-r--r-- | drivers/media/v4l2-core/Makefile | 35 | ||||
-rw-r--r-- | drivers/media/v4l2-core/tuner-core.c (renamed from drivers/media/video/tuner-core.c) | 0 | ||||
-rw-r--r-- | drivers/media/v4l2-core/v4l2-common.c (renamed from drivers/media/video/v4l2-common.c) | 362 | ||||
-rw-r--r-- | drivers/media/v4l2-core/v4l2-compat-ioctl32.c (renamed from drivers/media/video/v4l2-compat-ioctl32.c) | 65 | ||||
-rw-r--r-- | drivers/media/v4l2-core/v4l2-ctrls.c (renamed from drivers/media/video/v4l2-ctrls.c) | 201 | ||||
-rw-r--r-- | drivers/media/v4l2-core/v4l2-dev.c (renamed from drivers/media/video/v4l2-dev.c) | 277 | ||||
-rw-r--r-- | drivers/media/v4l2-core/v4l2-device.c (renamed from drivers/media/video/v4l2-device.c) | 2 | ||||
-rw-r--r-- | drivers/media/v4l2-core/v4l2-event.c (renamed from drivers/media/video/v4l2-event.c) | 4 | ||||
-rw-r--r-- | drivers/media/v4l2-core/v4l2-fh.c (renamed from drivers/media/video/v4l2-fh.c) | 0 | ||||
-rw-r--r-- | drivers/media/v4l2-core/v4l2-int-device.c (renamed from drivers/media/video/v4l2-int-device.c) | 0 | ||||
-rw-r--r-- | drivers/media/v4l2-core/v4l2-ioctl.c (renamed from drivers/media/video/v4l2-ioctl.c) | 242 | ||||
-rw-r--r-- | drivers/media/v4l2-core/v4l2-mem2mem.c (renamed from drivers/media/video/v4l2-mem2mem.c) | 6 | ||||
-rw-r--r-- | drivers/media/v4l2-core/v4l2-subdev.c (renamed from drivers/media/video/v4l2-subdev.c) | 6 | ||||
-rw-r--r-- | drivers/media/v4l2-core/videobuf-core.c (renamed from drivers/media/video/videobuf-core.c) | 0 | ||||
-rw-r--r-- | drivers/media/v4l2-core/videobuf-dma-contig.c (renamed from drivers/media/video/videobuf-dma-contig.c) | 0 | ||||
-rw-r--r-- | drivers/media/v4l2-core/videobuf-dma-sg.c (renamed from drivers/media/video/videobuf-dma-sg.c) | 0 | ||||
-rw-r--r-- | drivers/media/v4l2-core/videobuf-dvb.c (renamed from drivers/media/video/videobuf-dvb.c) | 11 | ||||
-rw-r--r-- | drivers/media/v4l2-core/videobuf-vmalloc.c (renamed from drivers/media/video/videobuf-vmalloc.c) | 0 | ||||
-rw-r--r-- | drivers/media/v4l2-core/videobuf2-core.c (renamed from drivers/media/video/videobuf2-core.c) | 44 | ||||
-rw-r--r-- | drivers/media/v4l2-core/videobuf2-dma-contig.c (renamed from drivers/media/video/videobuf2-dma-contig.c) | 0 | ||||
-rw-r--r-- | drivers/media/v4l2-core/videobuf2-dma-sg.c (renamed from drivers/media/video/videobuf2-dma-sg.c) | 0 | ||||
-rw-r--r-- | drivers/media/v4l2-core/videobuf2-memops.c (renamed from drivers/media/video/videobuf2-memops.c) | 0 | ||||
-rw-r--r-- | drivers/media/v4l2-core/videobuf2-vmalloc.c (renamed from drivers/media/video/videobuf2-vmalloc.c) | 1 | ||||
-rw-r--r-- | drivers/media/video/Kconfig | 1263 | ||||
-rw-r--r-- | drivers/media/video/Makefile | 218 | ||||
-rw-r--r-- | drivers/media/video/bt8xx/Kconfig | 27 | ||||
-rw-r--r-- | drivers/media/video/bt8xx/Makefile | 13 | ||||
-rw-r--r-- | drivers/media/video/cx23885/Kconfig | 46 | ||||
-rw-r--r-- | drivers/media/video/tlg2300/Makefile | 9 | ||||
-rw-r--r-- | drivers/staging/media/Kconfig | 2 | ||||
-rw-r--r-- | drivers/staging/media/Makefile | 1 | ||||
-rw-r--r-- | drivers/staging/media/as102/Makefile | 2 | ||||
-rw-r--r-- | drivers/staging/media/cxd2099/Makefile | 6 | ||||
-rw-r--r-- | drivers/staging/media/cxd2099/cxd2099.c | 13 | ||||
-rw-r--r-- | drivers/staging/media/dt3155v4l/dt3155v4l.c | 29 | ||||
-rw-r--r-- | drivers/staging/media/easycap/Kconfig | 30 | ||||
-rw-r--r-- | drivers/staging/media/easycap/Makefile | 10 | ||||
-rw-r--r-- | drivers/staging/media/easycap/README | 141 | ||||
-rw-r--r-- | drivers/staging/media/easycap/easycap.h | 567 | ||||
-rw-r--r-- | drivers/staging/media/easycap/easycap_ioctl.c | 2443 | ||||
-rw-r--r-- | drivers/staging/media/easycap/easycap_low.c | 968 | ||||
-rw-r--r-- | drivers/staging/media/easycap/easycap_main.c | 4239 | ||||
-rw-r--r-- | drivers/staging/media/easycap/easycap_settings.c | 696 | ||||
-rw-r--r-- | drivers/staging/media/easycap/easycap_sound.c | 750 | ||||
-rw-r--r-- | drivers/staging/media/easycap/easycap_testcard.c | 155 | ||||
-rw-r--r-- | drivers/staging/media/go7007/Makefile | 6 | ||||
-rw-r--r-- | drivers/staging/media/go7007/go7007-v4l2.c | 4 | ||||
-rw-r--r-- | drivers/staging/media/lirc/Kconfig | 6 | ||||
-rw-r--r-- | drivers/staging/media/lirc/Makefile | 1 | ||||
-rw-r--r-- | drivers/staging/media/lirc/lirc_ene0100.h | 169 | ||||
-rw-r--r-- | drivers/staging/media/lirc/lirc_igorplugusb.c | 4 | ||||
-rw-r--r-- | drivers/staging/media/lirc/lirc_ttusbir.c | 376 | ||||
-rw-r--r-- | drivers/staging/media/lirc/lirc_zilog.c | 3 |
1565 files changed, 34840 insertions, 25084 deletions
diff --git a/drivers/gpio/gpio-bt8xx.c b/drivers/gpio/gpio-bt8xx.c index aba97abda77c..7d9d7cb35f28 100644 --- a/drivers/gpio/gpio-bt8xx.c +++ b/drivers/gpio/gpio-bt8xx.c @@ -50,7 +50,7 @@ #include <linux/slab.h> /* Steal the hardware definitions from the bttv driver. */ -#include "../media/video/bt8xx/bt848.h" +#include "../media/pci/bt8xx/bt848.h" #define BT8XXGPIO_NR_GPIOS 24 /* We have 24 GPIO pins */ diff --git a/drivers/media/Kconfig b/drivers/media/Kconfig index d941581ab921..dd13e3a4c272 100644 --- a/drivers/media/Kconfig +++ b/drivers/media/Kconfig @@ -99,11 +99,6 @@ config VIDEO_DEV depends on MEDIA_CAMERA_SUPPORT || MEDIA_ANALOG_TV_SUPPORT || MEDIA_RADIO_SUPPORT default y -config VIDEO_V4L2_COMMON - tristate - depends on (I2C || I2C=n) && VIDEO_DEV - default (I2C || I2C=n) && VIDEO_DEV - config VIDEO_V4L2_SUBDEV_API bool "V4L2 sub-device userspace API (EXPERIMENTAL)" depends on VIDEO_DEV && MEDIA_CONTROLLER && EXPERIMENTAL @@ -113,6 +108,8 @@ config VIDEO_V4L2_SUBDEV_API This API is mostly used by camera interfaces in embedded platforms. +source "drivers/media/v4l2-core/Kconfig" + # # DVB Core # Only enables if one of DTV is selected @@ -138,28 +135,54 @@ config DVB_NET You may want to disable the network support on embedded devices. If unsure say Y. +source "drivers/media/dvb-core/Kconfig" + comment "Media drivers" -source "drivers/media/common/Kconfig" source "drivers/media/rc/Kconfig" # -# Tuner drivers for DVB and V4L +# V4L platform/mem2mem drivers # -source "drivers/media/common/tuners/Kconfig" +source "drivers/media/usb/Kconfig" +source "drivers/media/pci/Kconfig" +source "drivers/media/platform/Kconfig" +source "drivers/media/mmc/Kconfig" +source "drivers/media/parport/Kconfig" +source "drivers/media/radio/Kconfig" + +comment "Supported FireWire (IEEE 1394) Adapters" + depends on DVB_CORE && FIREWIRE +source "drivers/media/firewire/Kconfig" + +# Common driver options +source "drivers/media/common/Kconfig" # -# Video/Radio/Hybrid adapters +# Ancillary drivers (tuners, i2c, frontends) # -source "drivers/media/video/Kconfig" +config MEDIA_SUBDRV_AUTOSELECT + bool "Autoselect analog and hybrid tuner modules to build" + depends on MEDIA_TUNER + default y + help + By default, a TV driver auto-selects all possible tuners + thar could be used by the driver. -source "drivers/media/radio/Kconfig" + This is generally the right thing to do, except when there + are strict constraints with regards to the kernel size. -# -# DVB adapters -# + Use this option with care, as deselecting tuner drivers which + are in fact necessary will result in TV devices which cannot + be tuned due to lack of the tuning driver. + + If unsure say Y. + +comment "Media ancillary drivers (tuners, sensors, i2c, frontends)" -source "drivers/media/dvb/Kconfig" +source "drivers/media/i2c/Kconfig" +source "drivers/media/tuners/Kconfig" +source "drivers/media/dvb-frontends/Kconfig" endif # MEDIA_SUPPORT diff --git a/drivers/media/Makefile b/drivers/media/Makefile index 64755c99ded2..620f275a45c9 100644 --- a/drivers/media/Makefile +++ b/drivers/media/Makefile @@ -4,11 +4,30 @@ media-objs := media-device.o media-devnode.o media-entity.o +# +# I2C drivers should come before other drivers, otherwise they'll fail +# when compiled as builtin drivers +# +obj-y += i2c/ tuners/ +obj-$(CONFIG_DVB_CORE) += dvb-frontends/ + +# +# Now, let's link-in the media core +# ifeq ($(CONFIG_MEDIA_CONTROLLER),y) obj-$(CONFIG_MEDIA_SUPPORT) += media.o endif -obj-y += common/ rc/ video/ +obj-$(CONFIG_VIDEO_DEV) += v4l2-core/ +obj-$(CONFIG_DVB_CORE) += dvb-core/ +# There are both core and drivers at RC subtree - merge before drivers +obj-y += rc/ + +# +# Finally, merge the drivers that require the core +# + +obj-y += common/ platform/ pci/ usb/ mmc/ firewire/ parport/ obj-$(CONFIG_VIDEO_DEV) += radio/ -obj-$(CONFIG_DVB_CORE) += dvb/ + diff --git a/drivers/media/common/Kconfig b/drivers/media/common/Kconfig index 769c6f8142d2..121b0110af3c 100644 --- a/drivers/media/common/Kconfig +++ b/drivers/media/common/Kconfig @@ -1,9 +1,3 @@ -config VIDEO_SAA7146 - tristate - depends on I2C && PCI - -config VIDEO_SAA7146_VV - tristate - depends on VIDEO_V4L2 - select VIDEOBUF_DMA_SG - select VIDEO_SAA7146 +source "drivers/media/common/b2c2/Kconfig" +source "drivers/media/common/saa7146/Kconfig" +source "drivers/media/common/siano/Kconfig" diff --git a/drivers/media/common/Makefile b/drivers/media/common/Makefile index e3ec9639321b..b8e2e3a33a31 100644 --- a/drivers/media/common/Makefile +++ b/drivers/media/common/Makefile @@ -1,6 +1 @@ -saa7146-objs := saa7146_i2c.o saa7146_core.o -saa7146_vv-objs := saa7146_fops.o saa7146_video.o saa7146_hlp.o saa7146_vbi.o - -obj-y += tuners/ -obj-$(CONFIG_VIDEO_SAA7146) += saa7146.o -obj-$(CONFIG_VIDEO_SAA7146_VV) += saa7146_vv.o +obj-y += b2c2/ saa7146/ siano/ diff --git a/drivers/media/common/b2c2/Kconfig b/drivers/media/common/b2c2/Kconfig new file mode 100644 index 000000000000..1df9e578daa5 --- /dev/null +++ b/drivers/media/common/b2c2/Kconfig @@ -0,0 +1,28 @@ +config DVB_B2C2_FLEXCOP + tristate + depends on DVB_CORE && I2C + depends on DVB_B2C2_FLEXCOP_PCI || DVB_B2C2_FLEXCOP_USB + default y + select DVB_PLL if MEDIA_SUBDRV_AUTOSELECT + select DVB_STV0299 if MEDIA_SUBDRV_AUTOSELECT + select DVB_MT352 if MEDIA_SUBDRV_AUTOSELECT + select DVB_MT312 if MEDIA_SUBDRV_AUTOSELECT + select DVB_NXT200X if MEDIA_SUBDRV_AUTOSELECT + select DVB_STV0297 if MEDIA_SUBDRV_AUTOSELECT + select DVB_BCM3510 if MEDIA_SUBDRV_AUTOSELECT + select DVB_LGDT330X if MEDIA_SUBDRV_AUTOSELECT + select DVB_S5H1420 if MEDIA_SUBDRV_AUTOSELECT + select DVB_TUNER_ITD1000 if MEDIA_SUBDRV_AUTOSELECT + select DVB_ISL6421 if MEDIA_SUBDRV_AUTOSELECT + select DVB_CX24123 if MEDIA_SUBDRV_AUTOSELECT + select MEDIA_TUNER_SIMPLE if MEDIA_SUBDRV_AUTOSELECT + select DVB_TUNER_CX24113 if MEDIA_SUBDRV_AUTOSELECT + help + Support for the digital TV receiver chip made by B2C2 Inc. included in + Technisats PCI cards and USB boxes. + + Say Y if you own such a device and want to use it. + +# Selected via the PCI or USB flexcop drivers +config DVB_B2C2_FLEXCOP_DEBUG + bool diff --git a/drivers/media/common/b2c2/Makefile b/drivers/media/common/b2c2/Makefile new file mode 100644 index 000000000000..24993a5b38ba --- /dev/null +++ b/drivers/media/common/b2c2/Makefile @@ -0,0 +1,8 @@ +b2c2-flexcop-objs += flexcop.o flexcop-fe-tuner.o flexcop-i2c.o +b2c2-flexcop-objs += flexcop-sram.o flexcop-eeprom.o flexcop-misc.o +b2c2-flexcop-objs += flexcop-hw-filter.o +obj-$(CONFIG_DVB_B2C2_FLEXCOP) += b2c2-flexcop.o + +ccflags-y += -Idrivers/media/dvb-core/ +ccflags-y += -Idrivers/media/dvb-frontends/ +ccflags-y += -Idrivers/media/tuners/ diff --git a/drivers/media/dvb/b2c2/flexcop-common.h b/drivers/media/common/b2c2/flexcop-common.h index 437912e49824..437912e49824 100644 --- a/drivers/media/dvb/b2c2/flexcop-common.h +++ b/drivers/media/common/b2c2/flexcop-common.h diff --git a/drivers/media/dvb/b2c2/flexcop-eeprom.c b/drivers/media/common/b2c2/flexcop-eeprom.c index a25373a9bd84..a25373a9bd84 100644 --- a/drivers/media/dvb/b2c2/flexcop-eeprom.c +++ b/drivers/media/common/b2c2/flexcop-eeprom.c diff --git a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c b/drivers/media/common/b2c2/flexcop-fe-tuner.c index 850a6c606750..850a6c606750 100644 --- a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c +++ b/drivers/media/common/b2c2/flexcop-fe-tuner.c diff --git a/drivers/media/dvb/b2c2/flexcop-hw-filter.c b/drivers/media/common/b2c2/flexcop-hw-filter.c index 77e45475f4c7..77e45475f4c7 100644 --- a/drivers/media/dvb/b2c2/flexcop-hw-filter.c +++ b/drivers/media/common/b2c2/flexcop-hw-filter.c diff --git a/drivers/media/dvb/b2c2/flexcop-i2c.c b/drivers/media/common/b2c2/flexcop-i2c.c index 965d5eb33752..965d5eb33752 100644 --- a/drivers/media/dvb/b2c2/flexcop-i2c.c +++ b/drivers/media/common/b2c2/flexcop-i2c.c diff --git a/drivers/media/dvb/b2c2/flexcop-misc.c b/drivers/media/common/b2c2/flexcop-misc.c index f06f3a9070f5..f06f3a9070f5 100644 --- a/drivers/media/dvb/b2c2/flexcop-misc.c +++ b/drivers/media/common/b2c2/flexcop-misc.c diff --git a/drivers/media/dvb/b2c2/flexcop-reg.h b/drivers/media/common/b2c2/flexcop-reg.h index dc4528dcbb98..dc4528dcbb98 100644 --- a/drivers/media/dvb/b2c2/flexcop-reg.h +++ b/drivers/media/common/b2c2/flexcop-reg.h diff --git a/drivers/media/dvb/b2c2/flexcop-sram.c b/drivers/media/common/b2c2/flexcop-sram.c index f2199e43e803..f2199e43e803 100644 --- a/drivers/media/dvb/b2c2/flexcop-sram.c +++ b/drivers/media/common/b2c2/flexcop-sram.c diff --git a/drivers/media/dvb/b2c2/flexcop.c b/drivers/media/common/b2c2/flexcop.c index b1e8c99f469b..412c5daf2b48 100644 --- a/drivers/media/dvb/b2c2/flexcop.c +++ b/drivers/media/common/b2c2/flexcop.c @@ -43,6 +43,7 @@ #endif int b2c2_flexcop_debug; +EXPORT_SYMBOL_GPL(b2c2_flexcop_debug); module_param_named(debug, b2c2_flexcop_debug, int, 0644); MODULE_PARM_DESC(debug, "set debug level (1=info,2=tuner,4=i2c,8=ts," diff --git a/drivers/media/dvb/b2c2/flexcop.h b/drivers/media/common/b2c2/flexcop.h index 897b10c85ad9..897b10c85ad9 100644 --- a/drivers/media/dvb/b2c2/flexcop.h +++ b/drivers/media/common/b2c2/flexcop.h diff --git a/drivers/media/dvb/b2c2/flexcop_ibi_value_be.h b/drivers/media/common/b2c2/flexcop_ibi_value_be.h index 8f64bdbd72bb..8f64bdbd72bb 100644 --- a/drivers/media/dvb/b2c2/flexcop_ibi_value_be.h +++ b/drivers/media/common/b2c2/flexcop_ibi_value_be.h diff --git a/drivers/media/dvb/b2c2/flexcop_ibi_value_le.h b/drivers/media/common/b2c2/flexcop_ibi_value_le.h index c75830d7d942..c75830d7d942 100644 --- a/drivers/media/dvb/b2c2/flexcop_ibi_value_le.h +++ b/drivers/media/common/b2c2/flexcop_ibi_value_le.h diff --git a/drivers/media/common/saa7146/Kconfig b/drivers/media/common/saa7146/Kconfig new file mode 100644 index 000000000000..769c6f8142d2 --- /dev/null +++ b/drivers/media/common/saa7146/Kconfig @@ -0,0 +1,9 @@ +config VIDEO_SAA7146 + tristate + depends on I2C && PCI + +config VIDEO_SAA7146_VV + tristate + depends on VIDEO_V4L2 + select VIDEOBUF_DMA_SG + select VIDEO_SAA7146 diff --git a/drivers/media/common/saa7146/Makefile b/drivers/media/common/saa7146/Makefile new file mode 100644 index 000000000000..3219b00a8771 --- /dev/null +++ b/drivers/media/common/saa7146/Makefile @@ -0,0 +1,5 @@ +saa7146-objs := saa7146_i2c.o saa7146_core.o +saa7146_vv-objs := saa7146_fops.o saa7146_video.o saa7146_hlp.o saa7146_vbi.o + +obj-$(CONFIG_VIDEO_SAA7146) += saa7146.o +obj-$(CONFIG_VIDEO_SAA7146_VV) += saa7146_vv.o diff --git a/drivers/media/common/saa7146_core.c b/drivers/media/common/saa7146/saa7146_core.c index d6b1cf66042d..bb6ee5191eb1 100644 --- a/drivers/media/common/saa7146_core.c +++ b/drivers/media/common/saa7146/saa7146_core.c @@ -23,9 +23,6 @@ #include <media/saa7146.h> #include <linux/module.h> -LIST_HEAD(saa7146_devices); -DEFINE_MUTEX(saa7146_devices_lock); - static int saa7146_num; unsigned int saa7146_debug; @@ -482,8 +479,6 @@ static int saa7146_init_one(struct pci_dev *pci, const struct pci_device_id *ent set it explicitly. */ pci_set_drvdata(pci, &dev->v4l2_dev); - INIT_LIST_HEAD(&dev->item); - list_add_tail(&dev->item,&saa7146_devices); saa7146_num++; err = 0; @@ -545,7 +540,6 @@ static void saa7146_remove_one(struct pci_dev *pdev) iounmap(dev->mem); pci_release_region(pdev, 0); - list_del(&dev->item); pci_disable_device(pdev); kfree(dev); @@ -592,8 +586,6 @@ EXPORT_SYMBOL_GPL(saa7146_setgpio); EXPORT_SYMBOL_GPL(saa7146_i2c_adapter_prepare); EXPORT_SYMBOL_GPL(saa7146_debug); -EXPORT_SYMBOL_GPL(saa7146_devices); -EXPORT_SYMBOL_GPL(saa7146_devices_lock); MODULE_AUTHOR("Michael Hunold <michael@mihu.de>"); MODULE_DESCRIPTION("driver for generic saa7146-based hardware"); diff --git a/drivers/media/common/saa7146_fops.c b/drivers/media/common/saa7146/saa7146_fops.c index 0cdbd742974a..b3890bd49df6 100644 --- a/drivers/media/common/saa7146_fops.c +++ b/drivers/media/common/saa7146/saa7146_fops.c @@ -201,7 +201,7 @@ static int fops_open(struct file *file) DEB_EE("file:%p, dev:%s\n", file, video_device_node_name(vdev)); - if (mutex_lock_interruptible(&saa7146_devices_lock)) + if (mutex_lock_interruptible(vdev->lock)) return -ERESTARTSYS; DEB_D("using: %p\n", dev); @@ -253,7 +253,7 @@ out: kfree(fh); file->private_data = NULL; } - mutex_unlock(&saa7146_devices_lock); + mutex_unlock(vdev->lock); return result; } @@ -265,7 +265,7 @@ static int fops_release(struct file *file) DEB_EE("file:%p\n", file); - if (mutex_lock_interruptible(&saa7146_devices_lock)) + if (mutex_lock_interruptible(vdev->lock)) return -ERESTARTSYS; if (vdev->vfl_type == VFL_TYPE_VBI) { @@ -283,7 +283,7 @@ static int fops_release(struct file *file) file->private_data = NULL; kfree(fh); - mutex_unlock(&saa7146_devices_lock); + mutex_unlock(vdev->lock); return 0; } @@ -293,6 +293,7 @@ static int fops_mmap(struct file *file, struct vm_area_struct * vma) struct video_device *vdev = video_devdata(file); struct saa7146_fh *fh = file->private_data; struct videobuf_queue *q; + int res; switch (vdev->vfl_type) { case VFL_TYPE_GRABBER: { @@ -314,10 +315,14 @@ static int fops_mmap(struct file *file, struct vm_area_struct * vma) return 0; } - return videobuf_mmap_mapper(q,vma); + if (mutex_lock_interruptible(vdev->lock)) + return -ERESTARTSYS; + res = videobuf_mmap_mapper(q, vma); + mutex_unlock(vdev->lock); + return res; } -static unsigned int fops_poll(struct file *file, struct poll_table_struct *wait) +static unsigned int __fops_poll(struct file *file, struct poll_table_struct *wait) { struct video_device *vdev = video_devdata(file); struct saa7146_fh *fh = file->private_data; @@ -356,10 +361,22 @@ static unsigned int fops_poll(struct file *file, struct poll_table_struct *wait) return res; } +static unsigned int fops_poll(struct file *file, struct poll_table_struct *wait) +{ + struct video_device *vdev = video_devdata(file); + unsigned int res; + + mutex_lock(vdev->lock); + res = __fops_poll(file, wait); + mutex_unlock(vdev->lock); + return res; +} + static ssize_t fops_read(struct file *file, char __user *data, size_t count, loff_t *ppos) { struct video_device *vdev = video_devdata(file); struct saa7146_fh *fh = file->private_data; + int ret; switch (vdev->vfl_type) { case VFL_TYPE_GRABBER: @@ -373,8 +390,13 @@ static ssize_t fops_read(struct file *file, char __user *data, size_t count, lof DEB_EE("V4L2_BUF_TYPE_VBI_CAPTURE: file:%p, data:%p, count:%lu\n", file, data, (unsigned long)count); */ - if (fh->dev->ext_vv_data->capabilities & V4L2_CAP_VBI_CAPTURE) - return saa7146_vbi_uops.read(file,data,count,ppos); + if (fh->dev->ext_vv_data->capabilities & V4L2_CAP_VBI_CAPTURE) { + if (mutex_lock_interruptible(vdev->lock)) + return -ERESTARTSYS; + ret = saa7146_vbi_uops.read(file, data, count, ppos); + mutex_unlock(vdev->lock); + return ret; + } return -EINVAL; default: BUG(); @@ -386,15 +408,20 @@ static ssize_t fops_write(struct file *file, const char __user *data, size_t cou { struct video_device *vdev = video_devdata(file); struct saa7146_fh *fh = file->private_data; + int ret; switch (vdev->vfl_type) { case VFL_TYPE_GRABBER: return -EINVAL; case VFL_TYPE_VBI: - if (fh->dev->ext_vv_data->vbi_fops.write) - return fh->dev->ext_vv_data->vbi_fops.write(file, data, count, ppos); - else - return -EINVAL; + if (fh->dev->ext_vv_data->vbi_fops.write) { + if (mutex_lock_interruptible(vdev->lock)) + return -ERESTARTSYS; + ret = fh->dev->ext_vv_data->vbi_fops.write(file, data, count, ppos); + mutex_unlock(vdev->lock); + return ret; + } + return -EINVAL; default: BUG(); return -EINVAL; @@ -584,10 +611,6 @@ int saa7146_register_device(struct video_device **vid, struct saa7146_dev* dev, else vfd->ioctl_ops = &dev->ext_vv_data->vbi_ops; vfd->release = video_device_release; - /* Locking in file operations other than ioctl should be done by - the driver, not the V4L2 core. - This driver needs auditing so that this flag can be removed. */ - set_bit(V4L2_FL_LOCK_ALL_FOPS, &vfd->flags); vfd->lock = &dev->v4l2_lock; vfd->v4l2_dev = &dev->v4l2_dev; vfd->tvnorms = 0; diff --git a/drivers/media/common/saa7146_hlp.c b/drivers/media/common/saa7146/saa7146_hlp.c index be746d1aee9a..be746d1aee9a 100644 --- a/drivers/media/common/saa7146_hlp.c +++ b/drivers/media/common/saa7146/saa7146_hlp.c diff --git a/drivers/media/common/saa7146_i2c.c b/drivers/media/common/saa7146/saa7146_i2c.c index 22027198129d..22027198129d 100644 --- a/drivers/media/common/saa7146_i2c.c +++ b/drivers/media/common/saa7146/saa7146_i2c.c diff --git a/drivers/media/common/saa7146_vbi.c b/drivers/media/common/saa7146/saa7146_vbi.c index 1e71e374bbfe..1e71e374bbfe 100644 --- a/drivers/media/common/saa7146_vbi.c +++ b/drivers/media/common/saa7146/saa7146_vbi.c diff --git a/drivers/media/common/saa7146_video.c b/drivers/media/common/saa7146/saa7146_video.c index 6d14785d4747..4143d61f79b1 100644 --- a/drivers/media/common/saa7146_video.c +++ b/drivers/media/common/saa7146/saa7146_video.c @@ -479,7 +479,7 @@ static int vidioc_g_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *f return 0; } -static int vidioc_s_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *fb) +static int vidioc_s_fbuf(struct file *file, void *fh, const struct v4l2_framebuffer *fb) { struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; struct saa7146_vv *vv = dev->vv_data; diff --git a/drivers/media/common/siano/Kconfig b/drivers/media/common/siano/Kconfig new file mode 100644 index 000000000000..425aeadfb49d --- /dev/null +++ b/drivers/media/common/siano/Kconfig @@ -0,0 +1,17 @@ +# +# Siano Mobile Silicon Digital TV device configuration +# + +config SMS_SIANO_MDTV + tristate + depends on DVB_CORE && RC_CORE && HAS_DMA + depends on SMS_USB_DRV || SMS_SDIO_DRV + default y + ---help--- + Choose Y or M here if you have MDTV receiver with a Siano chipset. + + To compile this driver as a module, choose M here + (The module will be called smsmdtv). + + Further documentation on this driver can be found on the WWW + at http://www.siano-ms.com/ diff --git a/drivers/media/dvb/siano/Makefile b/drivers/media/common/siano/Makefile index f233b57c86fb..2a09279e0648 100644 --- a/drivers/media/dvb/siano/Makefile +++ b/drivers/media/common/siano/Makefile @@ -1,11 +1,7 @@ - smsmdtv-objs := smscoreapi.o sms-cards.o smsendian.o smsir.o obj-$(CONFIG_SMS_SIANO_MDTV) += smsmdtv.o smsdvb.o -obj-$(CONFIG_SMS_USB_DRV) += smsusb.o -obj-$(CONFIG_SMS_SDIO_DRV) += smssdio.o - -ccflags-y += -Idrivers/media/dvb/dvb-core +ccflags-y += -Idrivers/media/dvb-core ccflags-y += $(extra-cflags-y) $(extra-cflags-m) diff --git a/drivers/media/dvb/siano/sms-cards.c b/drivers/media/common/siano/sms-cards.c index 680c781c8dd6..680c781c8dd6 100644 --- a/drivers/media/dvb/siano/sms-cards.c +++ b/drivers/media/common/siano/sms-cards.c diff --git a/drivers/media/dvb/siano/sms-cards.h b/drivers/media/common/siano/sms-cards.h index d8cdf756f7cf..d8cdf756f7cf 100644 --- a/drivers/media/dvb/siano/sms-cards.h +++ b/drivers/media/common/siano/sms-cards.h diff --git a/drivers/media/dvb/siano/smscoreapi.c b/drivers/media/common/siano/smscoreapi.c index 9cc55546cc30..9cc55546cc30 100644 --- a/drivers/media/dvb/siano/smscoreapi.c +++ b/drivers/media/common/siano/smscoreapi.c diff --git a/drivers/media/dvb/siano/smscoreapi.h b/drivers/media/common/siano/smscoreapi.h index c592ae090397..c592ae090397 100644 --- a/drivers/media/dvb/siano/smscoreapi.h +++ b/drivers/media/common/siano/smscoreapi.h diff --git a/drivers/media/dvb/siano/smsdvb.c b/drivers/media/common/siano/smsdvb.c index aa77e54a8fae..aa77e54a8fae 100644 --- a/drivers/media/dvb/siano/smsdvb.c +++ b/drivers/media/common/siano/smsdvb.c diff --git a/drivers/media/dvb/siano/smsendian.c b/drivers/media/common/siano/smsendian.c index e2657c2f0109..e2657c2f0109 100644 --- a/drivers/media/dvb/siano/smsendian.c +++ b/drivers/media/common/siano/smsendian.c diff --git a/drivers/media/dvb/siano/smsendian.h b/drivers/media/common/siano/smsendian.h index 1624d6fd367b..1624d6fd367b 100644 --- a/drivers/media/dvb/siano/smsendian.h +++ b/drivers/media/common/siano/smsendian.h diff --git a/drivers/media/dvb/siano/smsir.c b/drivers/media/common/siano/smsir.c index 37bc5c4b8ad8..37bc5c4b8ad8 100644 --- a/drivers/media/dvb/siano/smsir.c +++ b/drivers/media/common/siano/smsir.c diff --git a/drivers/media/dvb/siano/smsir.h b/drivers/media/common/siano/smsir.h index ae92b3a8587e..ae92b3a8587e 100644 --- a/drivers/media/dvb/siano/smsir.h +++ b/drivers/media/common/siano/smsir.h diff --git a/drivers/media/dvb-core/Kconfig b/drivers/media/dvb-core/Kconfig new file mode 100644 index 000000000000..fa7a2490ed5f --- /dev/null +++ b/drivers/media/dvb-core/Kconfig @@ -0,0 +1,29 @@ +# +# DVB device configuration +# + +config DVB_MAX_ADAPTERS + int "maximum number of DVB/ATSC adapters" + depends on DVB_CORE + default 8 + range 1 255 + help + Maximum number of DVB/ATSC adapters. Increasing this number + increases the memory consumption of the DVB subsystem even + if a much lower number of DVB/ATSC adapters is present. + Only values in the range 4-32 are tested. + + If you are unsure about this, use the default value 8 + +config DVB_DYNAMIC_MINORS + bool "Dynamic DVB minor allocation" + depends on DVB_CORE + default n + help + If you say Y here, the DVB subsystem will use dynamic minor + allocation for any device that uses the DVB major number. + This means that you can have more than 4 of a single type + of device (like demuxes and frontends) per adapter, but udev + will be required to manage the device nodes. + + If you are unsure about this, say N here. diff --git a/drivers/media/dvb/dvb-core/Makefile b/drivers/media/dvb-core/Makefile index 8f22bcd7c1f9..8f22bcd7c1f9 100644 --- a/drivers/media/dvb/dvb-core/Makefile +++ b/drivers/media/dvb-core/Makefile diff --git a/drivers/media/dvb/dvb-core/demux.h b/drivers/media/dvb-core/demux.h index eb91fd808c16..eb91fd808c16 100644 --- a/drivers/media/dvb/dvb-core/demux.h +++ b/drivers/media/dvb-core/demux.h diff --git a/drivers/media/dvb/dvb-core/dmxdev.c b/drivers/media/dvb-core/dmxdev.c index 73970cd97af1..889c9c16c6df 100644 --- a/drivers/media/dvb/dvb-core/dmxdev.c +++ b/drivers/media/dvb-core/dmxdev.c @@ -370,9 +370,7 @@ static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len, return 0; } del_timer(&dmxdevfilter->timer); - dprintk("dmxdev: section callback %02x %02x %02x %02x %02x %02x\n", - buffer1[0], buffer1[1], - buffer1[2], buffer1[3], buffer1[4], buffer1[5]); + dprintk("dmxdev: section callback %*ph\n", 6, buffer1); ret = dvb_dmxdev_buffer_write(&dmxdevfilter->buffer, buffer1, buffer1_len); if (ret == buffer1_len) { diff --git a/drivers/media/dvb/dvb-core/dmxdev.h b/drivers/media/dvb-core/dmxdev.h index 02ebe28f830d..02ebe28f830d 100644 --- a/drivers/media/dvb/dvb-core/dmxdev.h +++ b/drivers/media/dvb-core/dmxdev.h diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb-core/dvb-usb-ids.h index 26c44818a5ab..58e0220447c0 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/drivers/media/dvb-core/dvb-usb-ids.h @@ -24,6 +24,7 @@ #define USB_VID_COMPRO_UNK 0x145f #define USB_VID_CONEXANT 0x0572 #define USB_VID_CYPRESS 0x04b4 +#define USB_VID_DEXATEK 0x1d19 #define USB_VID_DIBCOM 0x10b8 #define USB_VID_DPOSH 0x1498 #define USB_VID_DVICO 0x0fe9 @@ -82,6 +83,7 @@ #define USB_PID_AFATECH_AF9035_1003 0x1003 #define USB_PID_AFATECH_AF9035_9035 0x9035 #define USB_PID_TREKSTOR_DVBT 0x901b +#define USB_PID_TREKSTOR_TERRES_2_0 0xC803 #define USB_VID_ALINK_DTU 0xf170 #define USB_PID_ANSONIC_DVBT_USB 0x6000 #define USB_PID_ANYSEE 0x861f @@ -327,6 +329,7 @@ #define USB_PID_ASUS_U3000 0x171f #define USB_PID_ASUS_U3000H 0x1736 #define USB_PID_ASUS_U3100 0x173f +#define USB_PID_ASUS_U3100MINI_PLUS 0x1779 #define USB_PID_YUAN_EC372S 0x1edc #define USB_PID_YUAN_STK7700PH 0x1f08 #define USB_PID_YUAN_PD378S 0x2edc diff --git a/drivers/media/dvb/dvb-core/dvb_ca_en50221.c b/drivers/media/dvb-core/dvb_ca_en50221.c index 9be65a3b931f..9be65a3b931f 100644 --- a/drivers/media/dvb/dvb-core/dvb_ca_en50221.c +++ b/drivers/media/dvb-core/dvb_ca_en50221.c diff --git a/drivers/media/dvb/dvb-core/dvb_ca_en50221.h b/drivers/media/dvb-core/dvb_ca_en50221.h index 7df2e141187a..7df2e141187a 100644 --- a/drivers/media/dvb/dvb-core/dvb_ca_en50221.h +++ b/drivers/media/dvb-core/dvb_ca_en50221.h diff --git a/drivers/media/dvb/dvb-core/dvb_demux.c b/drivers/media/dvb-core/dvb_demux.c index d82469f842e2..d319717eb535 100644 --- a/drivers/media/dvb/dvb-core/dvb_demux.c +++ b/drivers/media/dvb-core/dvb_demux.c @@ -50,6 +50,11 @@ module_param(dvb_demux_speedcheck, int, 0644); MODULE_PARM_DESC(dvb_demux_speedcheck, "enable transport stream speed check"); +static int dvb_demux_feed_err_pkts = 1; +module_param(dvb_demux_feed_err_pkts, int, 0644); +MODULE_PARM_DESC(dvb_demux_feed_err_pkts, + "when set to 0, drop packets with the TEI bit set (1 by default)"); + #define dprintk_tscheck(x...) do { \ if (dvb_demux_tscheck && printk_ratelimit()) \ printk(x); \ @@ -419,21 +424,25 @@ static void dvb_dmx_swfilter_packet(struct dvb_demux *demux, const u8 *buf) printk(KERN_INFO "TS speed %llu Kbits/sec \n", div64_u64(speed_bytes, speed_timedelta)); - }; + } demux->speed_last_time = cur_time; demux->speed_pkts_cnt = 0; - }; - }; + } + } + if (buf[1] & 0x80) { + dprintk_tscheck("TEI detected. " + "PID=0x%x data1=0x%x\n", + pid, buf[1]); + /* data in this packet cant be trusted - drop it unless + * module option dvb_demux_feed_err_pkts is set */ + if (!dvb_demux_feed_err_pkts) + return; + } else /* if TEI bit is set, pid may be wrong- skip pkt counter */ if (demux->cnt_storage && dvb_demux_tscheck) { /* check pkt counter */ if (pid < MAX_PID) { - if (buf[1] & 0x80) - dprintk_tscheck("TEI detected. " - "PID=0x%x data1=0x%x\n", - pid, buf[1]); - if ((buf[3] & 0xf) != demux->cnt_storage[pid]) dprintk_tscheck("TS packet counter mismatch. " "PID=0x%x expected 0x%x " @@ -442,9 +451,9 @@ static void dvb_dmx_swfilter_packet(struct dvb_demux *demux, const u8 *buf) buf[3] & 0xf); demux->cnt_storage[pid] = ((buf[3] & 0xf) + 1)&0xf; - }; + } /* end check */ - }; + } list_for_each_entry(feed, &demux->feed_list, list_head) { if ((feed->pid != pid) && (feed->pid != 0x2000)) diff --git a/drivers/media/dvb/dvb-core/dvb_demux.h b/drivers/media/dvb-core/dvb_demux.h index fa7188a253aa..fa7188a253aa 100644 --- a/drivers/media/dvb/dvb-core/dvb_demux.h +++ b/drivers/media/dvb-core/dvb_demux.h diff --git a/drivers/media/dvb/dvb-core/dvb_filter.c b/drivers/media/dvb-core/dvb_filter.c index 772003fb1821..772003fb1821 100644 --- a/drivers/media/dvb/dvb-core/dvb_filter.c +++ b/drivers/media/dvb-core/dvb_filter.c diff --git a/drivers/media/dvb/dvb-core/dvb_filter.h b/drivers/media/dvb-core/dvb_filter.h index 375e3be184b1..375e3be184b1 100644 --- a/drivers/media/dvb/dvb-core/dvb_filter.h +++ b/drivers/media/dvb-core/dvb_filter.h diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb-core/dvb_frontend.c index aebcdf221dda..8f58f241c10d 100644 --- a/drivers/media/dvb/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb-core/dvb_frontend.c @@ -66,8 +66,6 @@ MODULE_PARM_DESC(dvb_powerdown_on_sleep, "0: do not power down, 1: turn LNB volt module_param(dvb_mfe_wait_time, int, 0644); MODULE_PARM_DESC(dvb_mfe_wait_time, "Wait up to <mfe_wait_time> seconds on open() for multi-frontend to become available (default:5 seconds)"); -#define dprintk if (dvb_frontend_debug) printk - #define FESTATE_IDLE 1 #define FESTATE_RETUNE 2 #define FESTATE_TUNING_FAST 4 @@ -179,7 +177,7 @@ static enum dvbv3_emulation_type dvbv3_type(u32 delivery_system) case SYS_DVBT: case SYS_DVBT2: case SYS_ISDBT: - case SYS_DMBTH: + case SYS_DTMB: return DVBV3_OFDM; case SYS_ATSC: case SYS_ATSCMH: @@ -207,7 +205,7 @@ static void dvb_frontend_add_event(struct dvb_frontend *fe, fe_status_t status) struct dvb_frontend_event *e; int wp; - dprintk ("%s\n", __func__); + dev_dbg(fe->dvb->device, "%s:\n", __func__); if ((status & FE_HAS_LOCK) && has_get_frontend(fe)) dtv_get_frontend(fe, &fepriv->parameters_out); @@ -237,7 +235,7 @@ static int dvb_frontend_get_event(struct dvb_frontend *fe, struct dvb_frontend_private *fepriv = fe->frontend_priv; struct dvb_fe_events *events = &fepriv->events; - dprintk ("%s\n", __func__); + dev_dbg(fe->dvb->device, "%s:\n", __func__); if (events->overflow) { events->overflow = 0; @@ -282,10 +280,9 @@ static void dvb_frontend_clear_events(struct dvb_frontend *fe) static void dvb_frontend_init(struct dvb_frontend *fe) { - dprintk ("DVB: initialising adapter %i frontend %i (%s)...\n", - fe->dvb->num, - fe->id, - fe->ops.info.name); + dev_dbg(fe->dvb->device, + "%s: initialising adapter %i frontend %i (%s)...\n", + __func__, fe->dvb->num, fe->id, fe->ops.info.name); if (fe->ops.init) fe->ops.init(fe); @@ -310,8 +307,9 @@ EXPORT_SYMBOL(dvb_frontend_reinitialise); static void dvb_frontend_swzigzag_update_delay(struct dvb_frontend_private *fepriv, int locked) { int q2; + struct dvb_frontend *fe = fepriv->dvbdev->priv; - dprintk ("%s\n", __func__); + dev_dbg(fe->dvb->device, "%s:\n", __func__); if (locked) (fepriv->quality) = (fepriv->quality * 220 + 36*256) / 256; @@ -403,10 +401,11 @@ static int dvb_frontend_swzigzag_autotune(struct dvb_frontend *fe, int check_wra return 1; } - dprintk("%s: drift:%i inversion:%i auto_step:%i " - "auto_sub_step:%i started_auto_step:%i\n", - __func__, fepriv->lnb_drift, fepriv->inversion, - fepriv->auto_step, fepriv->auto_sub_step, fepriv->started_auto_step); + dev_dbg(fe->dvb->device, "%s: drift:%i inversion:%i auto_step:%i " \ + "auto_sub_step:%i started_auto_step:%i\n", + __func__, fepriv->lnb_drift, fepriv->inversion, + fepriv->auto_step, fepriv->auto_sub_step, + fepriv->started_auto_step); /* set the frontend itself */ c->frequency += fepriv->lnb_drift; @@ -605,7 +604,7 @@ static int dvb_frontend_thread(void *data) bool re_tune = false; - dprintk("%s\n", __func__); + dev_dbg(fe->dvb->device, "%s:\n", __func__); fepriv->check_wrapped = 0; fepriv->quality = 0; @@ -651,10 +650,10 @@ restart: algo = fe->ops.get_frontend_algo(fe); switch (algo) { case DVBFE_ALGO_HW: - dprintk("%s: Frontend ALGO = DVBFE_ALGO_HW\n", __func__); + dev_dbg(fe->dvb->device, "%s: Frontend ALGO = DVBFE_ALGO_HW\n", __func__); if (fepriv->state & FESTATE_RETUNE) { - dprintk("%s: Retune requested, FESTATE_RETUNE\n", __func__); + dev_dbg(fe->dvb->device, "%s: Retune requested, FESTATE_RETUNE\n", __func__); re_tune = true; fepriv->state = FESTATE_TUNED; } else { @@ -665,19 +664,19 @@ restart: fe->ops.tune(fe, re_tune, fepriv->tune_mode_flags, &fepriv->delay, &s); if (s != fepriv->status && !(fepriv->tune_mode_flags & FE_TUNE_MODE_ONESHOT)) { - dprintk("%s: state changed, adding current state\n", __func__); + dev_dbg(fe->dvb->device, "%s: state changed, adding current state\n", __func__); dvb_frontend_add_event(fe, s); fepriv->status = s; } break; case DVBFE_ALGO_SW: - dprintk("%s: Frontend ALGO = DVBFE_ALGO_SW\n", __func__); + dev_dbg(fe->dvb->device, "%s: Frontend ALGO = DVBFE_ALGO_SW\n", __func__); dvb_frontend_swzigzag(fe); break; case DVBFE_ALGO_CUSTOM: - dprintk("%s: Frontend ALGO = DVBFE_ALGO_CUSTOM, state=%d\n", __func__, fepriv->state); + dev_dbg(fe->dvb->device, "%s: Frontend ALGO = DVBFE_ALGO_CUSTOM, state=%d\n", __func__, fepriv->state); if (fepriv->state & FESTATE_RETUNE) { - dprintk("%s: Retune requested, FESTAT_RETUNE\n", __func__); + dev_dbg(fe->dvb->device, "%s: Retune requested, FESTAT_RETUNE\n", __func__); fepriv->state = FESTATE_TUNED; } /* Case where we are going to search for a carrier @@ -713,7 +712,7 @@ restart: } break; default: - dprintk("%s: UNDEFINED ALGO !\n", __func__); + dev_dbg(fe->dvb->device, "%s: UNDEFINED ALGO !\n", __func__); break; } } else { @@ -750,7 +749,7 @@ static void dvb_frontend_stop(struct dvb_frontend *fe) { struct dvb_frontend_private *fepriv = fe->frontend_priv; - dprintk ("%s\n", __func__); + dev_dbg(fe->dvb->device, "%s:\n", __func__); fepriv->exit = DVB_FE_NORMAL_EXIT; mb(); @@ -765,7 +764,8 @@ static void dvb_frontend_stop(struct dvb_frontend *fe) /* paranoia check in case a signal arrived */ if (fepriv->thread) - printk("dvb_frontend_stop: warning: thread %p won't exit\n", + dev_warn(fe->dvb->device, + "dvb_frontend_stop: warning: thread %p won't exit\n", fepriv->thread); } @@ -818,7 +818,7 @@ static int dvb_frontend_start(struct dvb_frontend *fe) struct dvb_frontend_private *fepriv = fe->frontend_priv; struct task_struct *fe_thread; - dprintk ("%s\n", __func__); + dev_dbg(fe->dvb->device, "%s:\n", __func__); if (fepriv->thread) { if (fepriv->exit == DVB_FE_NO_EXIT) @@ -841,7 +841,9 @@ static int dvb_frontend_start(struct dvb_frontend *fe) "kdvb-ad-%i-fe-%i", fe->dvb->num,fe->id); if (IS_ERR(fe_thread)) { ret = PTR_ERR(fe_thread); - printk("dvb_frontend_start: failed to start kthread (%d)\n", ret); + dev_warn(fe->dvb->device, + "dvb_frontend_start: failed to start kthread (%d)\n", + ret); up(&fepriv->sem); return ret; } @@ -862,8 +864,8 @@ static void dvb_frontend_get_frequency_limits(struct dvb_frontend *fe, *freq_max = min(fe->ops.info.frequency_max, fe->ops.tuner_ops.info.frequency_max); if (*freq_min == 0 || *freq_max == 0) - printk(KERN_WARNING "DVB: adapter %i frontend %u frequency limits undefined - fix the driver\n", - fe->dvb->num,fe->id); + dev_warn(fe->dvb->device, "DVB: adapter %i frontend %u frequency limits undefined - fix the driver\n", + fe->dvb->num, fe->id); } static int dvb_frontend_check_parameters(struct dvb_frontend *fe) @@ -876,8 +878,9 @@ static int dvb_frontend_check_parameters(struct dvb_frontend *fe) dvb_frontend_get_frequency_limits(fe, &freq_min, &freq_max); if ((freq_min && c->frequency < freq_min) || (freq_max && c->frequency > freq_max)) { - printk(KERN_WARNING "DVB: adapter %i frontend %i frequency %u out of range (%u..%u)\n", - fe->dvb->num, fe->id, c->frequency, freq_min, freq_max); + dev_warn(fe->dvb->device, "DVB: adapter %i frontend %i frequency %u out of range (%u..%u)\n", + fe->dvb->num, fe->id, c->frequency, + freq_min, freq_max); return -EINVAL; } @@ -892,10 +895,10 @@ static int dvb_frontend_check_parameters(struct dvb_frontend *fe) c->symbol_rate < fe->ops.info.symbol_rate_min) || (fe->ops.info.symbol_rate_max && c->symbol_rate > fe->ops.info.symbol_rate_max)) { - printk(KERN_WARNING "DVB: adapter %i frontend %i symbol rate %u out of range (%u..%u)\n", - fe->dvb->num, fe->id, c->symbol_rate, - fe->ops.info.symbol_rate_min, - fe->ops.info.symbol_rate_max); + dev_warn(fe->dvb->device, "DVB: adapter %i frontend %i symbol rate %u out of range (%u..%u)\n", + fe->dvb->num, fe->id, c->symbol_rate, + fe->ops.info.symbol_rate_min, + fe->ops.info.symbol_rate_max); return -EINVAL; } default: @@ -917,8 +920,8 @@ static int dvb_frontend_clear_cache(struct dvb_frontend *fe) c->state = DTV_CLEAR; - dprintk("%s() Clearing cache for delivery system %d\n", __func__, - c->delivery_system); + dev_dbg(fe->dvb->device, "%s: Clearing cache for delivery system %d\n", + __func__, c->delivery_system); c->transmission_mode = TRANSMISSION_MODE_AUTO; c->bandwidth_hz = 0; /* AUTO */ @@ -946,8 +949,7 @@ static int dvb_frontend_clear_cache(struct dvb_frontend *fe) c->layer[i].segment_count = 0; } - c->isdbs_ts_id = 0; - c->dvbt2_plp_id = 0; + c->stream_id = NO_STREAM_ID_FILTER; switch (c->delivery_system) { case SYS_DVBS: @@ -997,6 +999,7 @@ static struct dtv_cmds_h dtv_cmds[DTV_MAX_COMMAND + 1] = { _DTV_CMD(DTV_CODE_RATE_LP, 1, 0), _DTV_CMD(DTV_GUARD_INTERVAL, 1, 0), _DTV_CMD(DTV_TRANSMISSION_MODE, 1, 0), + _DTV_CMD(DTV_INTERLEAVING, 1, 0), _DTV_CMD(DTV_ISDBT_PARTIAL_RECEPTION, 1, 0), _DTV_CMD(DTV_ISDBT_SOUND_BROADCASTING, 1, 0), @@ -1017,8 +1020,9 @@ static struct dtv_cmds_h dtv_cmds[DTV_MAX_COMMAND + 1] = { _DTV_CMD(DTV_ISDBT_LAYERC_SEGMENT_COUNT, 1, 0), _DTV_CMD(DTV_ISDBT_LAYERC_TIME_INTERLEAVING, 1, 0), - _DTV_CMD(DTV_ISDBS_TS_ID, 1, 0), - _DTV_CMD(DTV_DVBT2_PLP_ID, 1, 0), + _DTV_CMD(DTV_STREAM_ID, 1, 0), + _DTV_CMD(DTV_DVBT2_PLP_ID_LEGACY, 1, 0), + _DTV_CMD(DTV_LNA, 1, 0), /* Get */ _DTV_CMD(DTV_DISEQC_SLAVE_REPLY, 0, 1), @@ -1028,6 +1032,7 @@ static struct dtv_cmds_h dtv_cmds[DTV_MAX_COMMAND + 1] = { _DTV_CMD(DTV_GUARD_INTERVAL, 0, 0), _DTV_CMD(DTV_TRANSMISSION_MODE, 0, 0), _DTV_CMD(DTV_HIERARCHY, 0, 0), + _DTV_CMD(DTV_INTERLEAVING, 0, 0), _DTV_CMD(DTV_ENUM_DELSYS, 0, 0), @@ -1051,35 +1056,31 @@ static struct dtv_cmds_h dtv_cmds[DTV_MAX_COMMAND + 1] = { _DTV_CMD(DTV_ATSCMH_SCCC_CODE_MODE_D, 0, 0), }; -static void dtv_property_dump(struct dtv_property *tvp) +static void dtv_property_dump(struct dvb_frontend *fe, struct dtv_property *tvp) { int i; if (tvp->cmd <= 0 || tvp->cmd > DTV_MAX_COMMAND) { - printk(KERN_WARNING "%s: tvp.cmd = 0x%08x undefined\n", - __func__, tvp->cmd); + dev_warn(fe->dvb->device, "%s: tvp.cmd = 0x%08x undefined\n", + __func__, tvp->cmd); return; } - dprintk("%s() tvp.cmd = 0x%08x (%s)\n" - ,__func__ - ,tvp->cmd - ,dtv_cmds[ tvp->cmd ].name); - - if(dtv_cmds[ tvp->cmd ].buffer) { + dev_dbg(fe->dvb->device, "%s: tvp.cmd = 0x%08x (%s)\n", __func__, + tvp->cmd, dtv_cmds[tvp->cmd].name); - dprintk("%s() tvp.u.buffer.len = 0x%02x\n" - ,__func__ - ,tvp->u.buffer.len); + if (dtv_cmds[tvp->cmd].buffer) { + dev_dbg(fe->dvb->device, "%s: tvp.u.buffer.len = 0x%02x\n", + __func__, tvp->u.buffer.len); for(i = 0; i < tvp->u.buffer.len; i++) - dprintk("%s() tvp.u.buffer.data[0x%02x] = 0x%02x\n" - ,__func__ - ,i - ,tvp->u.buffer.data[i]); - - } else - dprintk("%s() tvp.u.data = 0x%08x\n", __func__, tvp->u.data); + dev_dbg(fe->dvb->device, + "%s: tvp.u.buffer.data[0x%02x] = 0x%02x\n", + __func__, i, tvp->u.buffer.data[i]); + } else { + dev_dbg(fe->dvb->device, "%s: tvp.u.data = 0x%08x\n", __func__, + tvp->u.data); + } } /* Synchronise the legacy tuning parameters into the cache, so that demodulator @@ -1095,18 +1096,19 @@ static int dtv_property_cache_sync(struct dvb_frontend *fe, switch (dvbv3_type(c->delivery_system)) { case DVBV3_QPSK: - dprintk("%s() Preparing QPSK req\n", __func__); + dev_dbg(fe->dvb->device, "%s: Preparing QPSK req\n", __func__); c->symbol_rate = p->u.qpsk.symbol_rate; c->fec_inner = p->u.qpsk.fec_inner; break; case DVBV3_QAM: - dprintk("%s() Preparing QAM req\n", __func__); + dev_dbg(fe->dvb->device, "%s: Preparing QAM req\n", __func__); c->symbol_rate = p->u.qam.symbol_rate; c->fec_inner = p->u.qam.fec_inner; c->modulation = p->u.qam.modulation; break; case DVBV3_OFDM: - dprintk("%s() Preparing OFDM req\n", __func__); + dev_dbg(fe->dvb->device, "%s: Preparing OFDM req\n", __func__); + switch (p->u.ofdm.bandwidth) { case BANDWIDTH_10_MHZ: c->bandwidth_hz = 10000000; @@ -1138,7 +1140,7 @@ static int dtv_property_cache_sync(struct dvb_frontend *fe, c->hierarchy = p->u.ofdm.hierarchy_information; break; case DVBV3_ATSC: - dprintk("%s() Preparing ATSC req\n", __func__); + dev_dbg(fe->dvb->device, "%s: Preparing ATSC req\n", __func__); c->modulation = p->u.vsb.modulation; if (c->delivery_system == SYS_ATSCMH) break; @@ -1148,9 +1150,9 @@ static int dtv_property_cache_sync(struct dvb_frontend *fe, c->delivery_system = SYS_DVBC_ANNEX_B; break; case DVBV3_UNKNOWN: - printk(KERN_ERR - "%s: doesn't know how to handle a DVBv3 call to delivery system %i\n", - __func__, c->delivery_system); + dev_err(fe->dvb->device, + "%s: doesn't know how to handle a DVBv3 call to delivery system %i\n", + __func__, c->delivery_system); return -EINVAL; } @@ -1170,24 +1172,23 @@ static int dtv_property_legacy_params_sync(struct dvb_frontend *fe, switch (dvbv3_type(c->delivery_system)) { case DVBV3_UNKNOWN: - printk(KERN_ERR - "%s: doesn't know how to handle a DVBv3 call to delivery system %i\n", - __func__, c->delivery_system); + dev_err(fe->dvb->device, + "%s: doesn't know how to handle a DVBv3 call to delivery system %i\n", + __func__, c->delivery_system); return -EINVAL; case DVBV3_QPSK: - dprintk("%s() Preparing QPSK req\n", __func__); + dev_dbg(fe->dvb->device, "%s: Preparing QPSK req\n", __func__); p->u.qpsk.symbol_rate = c->symbol_rate; p->u.qpsk.fec_inner = c->fec_inner; break; case DVBV3_QAM: - dprintk("%s() Preparing QAM req\n", __func__); + dev_dbg(fe->dvb->device, "%s: Preparing QAM req\n", __func__); p->u.qam.symbol_rate = c->symbol_rate; p->u.qam.fec_inner = c->fec_inner; p->u.qam.modulation = c->modulation; break; case DVBV3_OFDM: - dprintk("%s() Preparing OFDM req\n", __func__); - + dev_dbg(fe->dvb->device, "%s: Preparing OFDM req\n", __func__); switch (c->bandwidth_hz) { case 10000000: p->u.ofdm.bandwidth = BANDWIDTH_10_MHZ; @@ -1219,7 +1220,7 @@ static int dtv_property_legacy_params_sync(struct dvb_frontend *fe, p->u.ofdm.hierarchy_information = c->hierarchy; break; case DVBV3_ATSC: - dprintk("%s() Preparing VSB req\n", __func__); + dev_dbg(fe->dvb->device, "%s: Preparing VSB req\n", __func__); p->u.vsb.modulation = c->modulation; break; } @@ -1326,6 +1327,9 @@ static int dtv_property_process_get(struct dvb_frontend *fe, case DTV_HIERARCHY: tvp->u.data = c->hierarchy; break; + case DTV_INTERLEAVING: + tvp->u.data = c->interleaving; + break; /* ISDB-T Support here */ case DTV_ISDBT_PARTIAL_RECEPTION: @@ -1382,11 +1386,11 @@ static int dtv_property_process_get(struct dvb_frontend *fe, case DTV_ISDBT_LAYERC_TIME_INTERLEAVING: tvp->u.data = c->layer[2].interleaving; break; - case DTV_ISDBS_TS_ID: - tvp->u.data = c->isdbs_ts_id; - break; - case DTV_DVBT2_PLP_ID: - tvp->u.data = c->dvbt2_plp_id; + + /* Multistream support */ + case DTV_STREAM_ID: + case DTV_DVBT2_PLP_ID_LEGACY: + tvp->u.data = c->stream_id; break; /* ATSC-MH */ @@ -1447,7 +1451,7 @@ static int dtv_property_process_get(struct dvb_frontend *fe, return r; } - dtv_property_dump(tvp); + dtv_property_dump(fe, tvp); return 0; } @@ -1492,8 +1496,9 @@ static int set_delivery_system(struct dvb_frontend *fe, u32 desired_system) * DVBv3 system that matches the delivery system. */ if (is_dvbv3_delsys(c->delivery_system)) { - dprintk("%s() Using delivery system to %d\n", - __func__, c->delivery_system); + dev_dbg(fe->dvb->device, + "%s: Using delivery system to %d\n", + __func__, c->delivery_system); return 0; } type = dvbv3_type(c->delivery_system); @@ -1511,8 +1516,8 @@ static int set_delivery_system(struct dvb_frontend *fe, u32 desired_system) desired_system = SYS_DVBT; break; default: - dprintk("%s(): This frontend doesn't support DVBv3 calls\n", - __func__); + dev_dbg(fe->dvb->device, "%s: This frontend doesn't support DVBv3 calls\n", + __func__); return -EINVAL; } /* @@ -1534,8 +1539,8 @@ static int set_delivery_system(struct dvb_frontend *fe, u32 desired_system) ncaps++; } if (delsys == SYS_UNDEFINED) { - dprintk("%s() Couldn't find a delivery system that matches %d\n", - __func__, desired_system); + dev_dbg(fe->dvb->device, "%s: Couldn't find a delivery system that matches %d\n", + __func__, desired_system); } } else { /* @@ -1548,8 +1553,9 @@ static int set_delivery_system(struct dvb_frontend *fe, u32 desired_system) while (fe->ops.delsys[ncaps] && ncaps < MAX_DELSYS) { if (fe->ops.delsys[ncaps] == desired_system) { c->delivery_system = desired_system; - dprintk("%s() Changing delivery system to %d\n", - __func__, desired_system); + dev_dbg(fe->dvb->device, + "%s: Changing delivery system to %d\n", + __func__, desired_system); return 0; } ncaps++; @@ -1563,8 +1569,9 @@ static int set_delivery_system(struct dvb_frontend *fe, u32 desired_system) * DVBv3 delivery systems */ if (!is_dvbv3_delsys(desired_system)) { - dprintk("%s() can't use a DVBv3 FE_SET_FRONTEND call on this frontend\n", - __func__); + dev_dbg(fe->dvb->device, + "%s: can't use a DVBv3 FE_SET_FRONTEND call on this frontend\n", + __func__); return -EINVAL; } @@ -1581,8 +1588,9 @@ static int set_delivery_system(struct dvb_frontend *fe, u32 desired_system) } /* There's nothing compatible with the desired delivery system */ if (delsys == SYS_UNDEFINED) { - dprintk("%s() Incompatible DVBv3 FE_SET_FRONTEND call for this frontend\n", - __func__); + dev_dbg(fe->dvb->device, + "%s: Incompatible DVBv3 FE_SET_FRONTEND call for this frontend\n", + __func__); return -EINVAL; } } @@ -1593,13 +1601,14 @@ static int set_delivery_system(struct dvb_frontend *fe, u32 desired_system) * The DVBv3 or DVBv5 call is requesting a different system. So, * emulation is needed. * - * Emulate newer delivery systems like ISDBT, DVBT and DMBTH + * Emulate newer delivery systems like ISDBT, DVBT and DTMB * for older DVBv5 applications. The emulation will try to use * the auto mode for most things, and will assume that the desired * delivery system is the last one at the ops.delsys[] array */ - dprintk("%s() Using delivery system %d emulated as if it were a %d\n", - __func__, delsys, desired_system); + dev_dbg(fe->dvb->device, + "%s: Using delivery system %d emulated as if it were a %d\n", + __func__, delsys, desired_system); /* * For now, handles ISDB-T calls. More code may be needed here for the @@ -1607,8 +1616,10 @@ static int set_delivery_system(struct dvb_frontend *fe, u32 desired_system) */ if (type == DVBV3_OFDM) { if (c->delivery_system == SYS_ISDBT) { - dprintk("%s() Using defaults for SYS_ISDBT\n", - __func__); + dev_dbg(fe->dvb->device, + "%s: Using defaults for SYS_ISDBT\n", + __func__); + if (!c->bandwidth_hz) c->bandwidth_hz = 6000000; @@ -1626,7 +1637,8 @@ static int set_delivery_system(struct dvb_frontend *fe, u32 desired_system) } } } - dprintk("change delivery system on cache to %d\n", c->delivery_system); + dev_dbg(fe->dvb->device, "%s: change delivery system on cache to %d\n", + __func__, c->delivery_system); return 0; } @@ -1659,7 +1671,8 @@ static int dtv_property_process_set(struct dvb_frontend *fe, * ioctl. */ c->state = tvp->cmd; - dprintk("%s() Finalised property cache\n", __func__); + dev_dbg(fe->dvb->device, "%s: Finalised property cache\n", + __func__); r = dtv_set_frontend(fe); break; @@ -1715,6 +1728,13 @@ static int dtv_property_process_set(struct dvb_frontend *fe, case DTV_HIERARCHY: c->hierarchy = tvp->u.data; break; + case DTV_INTERLEAVING: + c->interleaving = tvp->u.data; + break; + case DTV_LNA: + if (fe->ops.set_lna) + r = fe->ops.set_lna(fe, tvp->u.data); + break; /* ISDB-T Support here */ case DTV_ISDBT_PARTIAL_RECEPTION: @@ -1771,11 +1791,11 @@ static int dtv_property_process_set(struct dvb_frontend *fe, case DTV_ISDBT_LAYERC_TIME_INTERLEAVING: c->layer[2].interleaving = tvp->u.data; break; - case DTV_ISDBS_TS_ID: - c->isdbs_ts_id = tvp->u.data; - break; - case DTV_DVBT2_PLP_ID: - c->dvbt2_plp_id = tvp->u.data; + + /* Multistream support */ + case DTV_STREAM_ID: + case DTV_DVBT2_PLP_ID_LEGACY: + c->stream_id = tvp->u.data; break; /* ATSC-MH */ @@ -1800,10 +1820,9 @@ static int dvb_frontend_ioctl(struct file *file, struct dvb_frontend *fe = dvbdev->priv; struct dtv_frontend_properties *c = &fe->dtv_property_cache; struct dvb_frontend_private *fepriv = fe->frontend_priv; - int err = -EOPNOTSUPP; - - dprintk("%s (%d)\n", __func__, _IOC_NR(cmd)); + int err = -ENOTTY; + dev_dbg(fe->dvb->device, "%s: (%d)\n", __func__, _IOC_NR(cmd)); if (fepriv->exit != DVB_FE_NO_EXIT) return -ENODEV; @@ -1839,13 +1858,13 @@ static int dvb_frontend_ioctl_properties(struct file *file, struct dtv_property *tvp = NULL; int i; - dprintk("%s\n", __func__); + dev_dbg(fe->dvb->device, "%s:\n", __func__); if(cmd == FE_SET_PROPERTY) { tvps = (struct dtv_properties __user *)parg; - dprintk("%s() properties.num = %d\n", __func__, tvps->num); - dprintk("%s() properties.props = %p\n", __func__, tvps->props); + dev_dbg(fe->dvb->device, "%s: properties.num = %d\n", __func__, tvps->num); + dev_dbg(fe->dvb->device, "%s: properties.props = %p\n", __func__, tvps->props); /* Put an arbitrary limit on the number of messages that can * be sent at once */ @@ -1871,14 +1890,14 @@ static int dvb_frontend_ioctl_properties(struct file *file, } if (c->state == DTV_TUNE) - dprintk("%s() Property cache is full, tuning\n", __func__); + dev_dbg(fe->dvb->device, "%s: Property cache is full, tuning\n", __func__); } else if(cmd == FE_GET_PROPERTY) { tvps = (struct dtv_properties __user *)parg; - dprintk("%s() properties.num = %d\n", __func__, tvps->num); - dprintk("%s() properties.props = %p\n", __func__, tvps->props); + dev_dbg(fe->dvb->device, "%s: properties.num = %d\n", __func__, tvps->num); + dev_dbg(fe->dvb->device, "%s: properties.props = %p\n", __func__, tvps->props); /* Put an arbitrary limit on the number of messages that can * be sent at once */ @@ -1919,7 +1938,7 @@ static int dvb_frontend_ioctl_properties(struct file *file, } } else - err = -EOPNOTSUPP; + err = -ENOTTY; out: kfree(tvp); @@ -2012,7 +2031,7 @@ static int dtv_set_frontend(struct dvb_frontend *fe) case SYS_DVBT: case SYS_DVBT2: case SYS_ISDBT: - case SYS_DMBTH: + case SYS_DTMB: fepriv->min_delay = HZ / 20; fepriv->step_size = fe->ops.info.frequency_stepsize * 2; fepriv->max_drift = (fe->ops.info.frequency_stepsize * 2) + 1; @@ -2052,18 +2071,7 @@ static int dvb_frontend_ioctl_legacy(struct file *file, struct dvb_frontend *fe = dvbdev->priv; struct dvb_frontend_private *fepriv = fe->frontend_priv; struct dtv_frontend_properties *c = &fe->dtv_property_cache; - int cb_err, err = -EOPNOTSUPP; - - if (fe->dvb->fe_ioctl_override) { - cb_err = fe->dvb->fe_ioctl_override(fe, cmd, parg, - DVB_FE_IOCTL_PRE); - if (cb_err < 0) - return cb_err; - if (cb_err > 0) - return 0; - /* fe_ioctl_override returning 0 allows - * dvb-core to continue handling the ioctl */ - } + int err = -ENOTTY; switch (cmd) { case FE_GET_INFO: { @@ -2097,13 +2105,13 @@ static int dvb_frontend_ioctl_legacy(struct file *file, info->type = FE_OFDM; break; default: - printk(KERN_ERR - "%s: doesn't know how to handle a DVBv3 call to delivery system %i\n", - __func__, c->delivery_system); + dev_err(fe->dvb->device, + "%s: doesn't know how to handle a DVBv3 call to delivery system %i\n", + __func__, c->delivery_system); fe->ops.info.type = FE_OFDM; } - dprintk("current delivery system on cache: %d, V3 type: %d\n", - c->delivery_system, fe->ops.info.type); + dev_dbg(fe->dvb->device, "%s: current delivery system on cache: %d, V3 type: %d\n", + __func__, c->delivery_system, fe->ops.info.type); /* Force the CAN_INVERSION_AUTO bit on. If the frontend doesn't * do it, it is done for it. */ @@ -2128,27 +2136,43 @@ static int dvb_frontend_ioctl_legacy(struct file *file, err = fe->ops.read_status(fe, status); break; } + case FE_READ_BER: - if (fe->ops.read_ber) - err = fe->ops.read_ber(fe, (__u32*) parg); + if (fe->ops.read_ber) { + if (fepriv->thread) + err = fe->ops.read_ber(fe, (__u32 *) parg); + else + err = -EAGAIN; + } break; case FE_READ_SIGNAL_STRENGTH: - if (fe->ops.read_signal_strength) - err = fe->ops.read_signal_strength(fe, (__u16*) parg); + if (fe->ops.read_signal_strength) { + if (fepriv->thread) + err = fe->ops.read_signal_strength(fe, (__u16 *) parg); + else + err = -EAGAIN; + } break; case FE_READ_SNR: - if (fe->ops.read_snr) - err = fe->ops.read_snr(fe, (__u16*) parg); + if (fe->ops.read_snr) { + if (fepriv->thread) + err = fe->ops.read_snr(fe, (__u16 *) parg); + else + err = -EAGAIN; + } break; case FE_READ_UNCORRECTED_BLOCKS: - if (fe->ops.read_ucblocks) - err = fe->ops.read_ucblocks(fe, (__u32*) parg); + if (fe->ops.read_ucblocks) { + if (fepriv->thread) + err = fe->ops.read_ucblocks(fe, (__u32 *) parg); + else + err = -EAGAIN; + } break; - case FE_DISEQC_RESET_OVERLOAD: if (fe->ops.diseqc_reset_overload) { err = fe->ops.diseqc_reset_overload(fe); @@ -2287,13 +2311,6 @@ static int dvb_frontend_ioctl_legacy(struct file *file, break; }; - if (fe->dvb->fe_ioctl_override) { - cb_err = fe->dvb->fe_ioctl_override(fe, cmd, parg, - DVB_FE_IOCTL_POST); - if (cb_err < 0) - return cb_err; - } - return err; } @@ -2304,7 +2321,7 @@ static unsigned int dvb_frontend_poll(struct file *file, struct poll_table_struc struct dvb_frontend *fe = dvbdev->priv; struct dvb_frontend_private *fepriv = fe->frontend_priv; - dprintk ("%s\n", __func__); + dev_dbg_ratelimited(fe->dvb->device, "%s:\n", __func__); poll_wait (file, &fepriv->events.wait_queue, wait); @@ -2322,7 +2339,7 @@ static int dvb_frontend_open(struct inode *inode, struct file *file) struct dvb_adapter *adapter = fe->dvb; int ret; - dprintk ("%s\n", __func__); + dev_dbg(fe->dvb->device, "%s:\n", __func__); if (fepriv->exit == DVB_FE_DEVICE_REMOVED) return -ENODEV; @@ -2417,7 +2434,7 @@ static int dvb_frontend_release(struct inode *inode, struct file *file) struct dvb_frontend_private *fepriv = fe->frontend_priv; int ret; - dprintk ("%s\n", __func__); + dev_dbg(fe->dvb->device, "%s:\n", __func__); if ((file->f_flags & O_ACCMODE) != O_RDONLY) { fepriv->release_jiffies = jiffies; @@ -2449,6 +2466,44 @@ static const struct file_operations dvb_frontend_fops = { .llseek = noop_llseek, }; +int dvb_frontend_suspend(struct dvb_frontend *fe) +{ + int ret = 0; + + dev_dbg(fe->dvb->device, "%s: adap=%d fe=%d\n", __func__, fe->dvb->num, + fe->id); + + if (fe->ops.tuner_ops.sleep) + ret = fe->ops.tuner_ops.sleep(fe); + + if (fe->ops.sleep) + ret = fe->ops.sleep(fe); + + return ret; +} +EXPORT_SYMBOL(dvb_frontend_suspend); + +int dvb_frontend_resume(struct dvb_frontend *fe) +{ + struct dvb_frontend_private *fepriv = fe->frontend_priv; + int ret = 0; + + dev_dbg(fe->dvb->device, "%s: adap=%d fe=%d\n", __func__, fe->dvb->num, + fe->id); + + if (fe->ops.init) + ret = fe->ops.init(fe); + + if (fe->ops.tuner_ops.init) + ret = fe->ops.tuner_ops.init(fe); + + fepriv->state = FESTATE_RETUNE; + dvb_frontend_wakeup(fe); + + return ret; +} +EXPORT_SYMBOL(dvb_frontend_resume); + int dvb_register_frontend(struct dvb_adapter* dvb, struct dvb_frontend* fe) { @@ -2461,7 +2516,7 @@ int dvb_register_frontend(struct dvb_adapter* dvb, .kernel_ioctl = dvb_frontend_ioctl }; - dprintk ("%s\n", __func__); + dev_dbg(dvb->device, "%s:\n", __func__); if (mutex_lock_interruptible(&frontend_mutex)) return -ERESTARTSYS; @@ -2480,10 +2535,9 @@ int dvb_register_frontend(struct dvb_adapter* dvb, fe->dvb = dvb; fepriv->inversion = INVERSION_OFF; - printk ("DVB: registering adapter %i frontend %i (%s)...\n", - fe->dvb->num, - fe->id, - fe->ops.info.name); + dev_info(fe->dvb->device, + "DVB: registering adapter %i frontend %i (%s)...\n", + fe->dvb->num, fe->id, fe->ops.info.name); dvb_register_device (fe->dvb, &fepriv->dvbdev, &dvbdev_template, fe, DVB_DEVICE_FRONTEND); @@ -2504,7 +2558,7 @@ EXPORT_SYMBOL(dvb_register_frontend); int dvb_unregister_frontend(struct dvb_frontend* fe) { struct dvb_frontend_private *fepriv = fe->frontend_priv; - dprintk ("%s\n", __func__); + dev_dbg(fe->dvb->device, "%s:\n", __func__); mutex_lock(&frontend_mutex); dvb_frontend_stop (fe); diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.h b/drivers/media/dvb-core/dvb_frontend.h index 7c64c09103a9..44a445cee74f 100644 --- a/drivers/media/dvb/dvb-core/dvb_frontend.h +++ b/drivers/media/dvb-core/dvb_frontend.h @@ -303,6 +303,7 @@ struct dvb_frontend_ops { int (*dishnetwork_send_legacy_command)(struct dvb_frontend* fe, unsigned long cmd); int (*i2c_gate_ctrl)(struct dvb_frontend* fe, int enable); int (*ts_bus_ctrl)(struct dvb_frontend* fe, int acquire); + int (*set_lna)(struct dvb_frontend *, int); /* These callbacks are for devices that implement their own * tuning algorithms, rather than a simple swzigzag @@ -354,6 +355,8 @@ struct dtv_frontend_properties { fe_delivery_system_t delivery_system; + enum fe_interleaving interleaving; + /* ISDB-T specifics */ u8 isdbt_partial_reception; u8 isdbt_sb_mode; @@ -368,11 +371,8 @@ struct dtv_frontend_properties { u8 interleaving; } layer[3]; - /* ISDB-T specifics */ - u32 isdbs_ts_id; - - /* DVB-T2 specifics */ - u32 dvbt2_plp_id; + /* Multistream specifics */ + u32 stream_id; /* ATSC-MH specifics */ u8 atscmh_fic_ver; @@ -416,6 +416,8 @@ extern int dvb_unregister_frontend(struct dvb_frontend *fe); extern void dvb_frontend_detach(struct dvb_frontend *fe); extern void dvb_frontend_reinitialise(struct dvb_frontend *fe); +extern int dvb_frontend_suspend(struct dvb_frontend *fe); +extern int dvb_frontend_resume(struct dvb_frontend *fe); extern void dvb_frontend_sleep_until(struct timeval *waketime, u32 add_usec); extern s32 timeval_usec_diff(struct timeval lasttime, struct timeval curtime); diff --git a/drivers/media/dvb/dvb-core/dvb_math.c b/drivers/media/dvb-core/dvb_math.c index beb7c93aa6cb..beb7c93aa6cb 100644 --- a/drivers/media/dvb/dvb-core/dvb_math.c +++ b/drivers/media/dvb-core/dvb_math.c diff --git a/drivers/media/dvb/dvb-core/dvb_math.h b/drivers/media/dvb-core/dvb_math.h index aecc867e9404..aecc867e9404 100644 --- a/drivers/media/dvb/dvb-core/dvb_math.h +++ b/drivers/media/dvb-core/dvb_math.h diff --git a/drivers/media/dvb/dvb-core/dvb_net.c b/drivers/media/dvb-core/dvb_net.c index c2117688aa23..c2117688aa23 100644 --- a/drivers/media/dvb/dvb-core/dvb_net.c +++ b/drivers/media/dvb-core/dvb_net.c diff --git a/drivers/media/dvb/dvb-core/dvb_net.h b/drivers/media/dvb-core/dvb_net.h index 1e53acd50cf4..1e53acd50cf4 100644 --- a/drivers/media/dvb/dvb-core/dvb_net.h +++ b/drivers/media/dvb-core/dvb_net.h diff --git a/drivers/media/dvb/dvb-core/dvb_ringbuffer.c b/drivers/media/dvb-core/dvb_ringbuffer.c index a5712cd7c65f..a5712cd7c65f 100644 --- a/drivers/media/dvb/dvb-core/dvb_ringbuffer.c +++ b/drivers/media/dvb-core/dvb_ringbuffer.c diff --git a/drivers/media/dvb/dvb-core/dvb_ringbuffer.h b/drivers/media/dvb-core/dvb_ringbuffer.h index 41f04dae69b6..41f04dae69b6 100644 --- a/drivers/media/dvb/dvb-core/dvb_ringbuffer.h +++ b/drivers/media/dvb-core/dvb_ringbuffer.h diff --git a/drivers/media/dvb/dvb-core/dvbdev.c b/drivers/media/dvb-core/dvbdev.c index 39eab73b01ae..d33101aaf0b5 100644 --- a/drivers/media/dvb/dvb-core/dvbdev.c +++ b/drivers/media/dvb-core/dvbdev.c @@ -420,7 +420,7 @@ int dvb_usercopy(struct file *file, /* call driver */ mutex_lock(&dvbdev_mutex); if ((err = func(file, cmd, parg)) == -ENOIOCTLCMD) - err = -EINVAL; + err = -ENOTTY; mutex_unlock(&dvbdev_mutex); if (err < 0) diff --git a/drivers/media/dvb/dvb-core/dvbdev.h b/drivers/media/dvb-core/dvbdev.h index fcc6ae98745e..93a9470d3f0c 100644 --- a/drivers/media/dvb/dvb-core/dvbdev.h +++ b/drivers/media/dvb-core/dvbdev.h @@ -71,32 +71,6 @@ struct dvb_adapter { int mfe_shared; /* indicates mutually exclusive frontends */ struct dvb_device *mfe_dvbdev; /* frontend device in use */ struct mutex mfe_lock; /* access lock for thread creation */ - - /* Allow the adapter/bridge driver to perform an action before and/or - * after the core handles an ioctl: - * - * DVB_FE_IOCTL_PRE indicates that the ioctl has not yet been handled. - * DVB_FE_IOCTL_POST indicates that the ioctl has been handled. - * - * When DVB_FE_IOCTL_PRE is passed to the callback as the stage arg: - * - * return 0 to allow dvb-core to handle the ioctl. - * return a positive int to prevent dvb-core from handling the ioctl, - * and exit without error. - * return a negative int to prevent dvb-core from handling the ioctl, - * and return that value as an error. - * - * When DVB_FE_IOCTL_POST is passed to the callback as the stage arg: - * - * return 0 to allow the dvb_frontend ioctl handler to exit normally. - * return a negative int to cause the dvb_frontend ioctl handler to - * return that value as an error. - */ -#define DVB_FE_IOCTL_PRE 0 -#define DVB_FE_IOCTL_POST 1 - int (*fe_ioctl_override)(struct dvb_frontend *fe, - unsigned int cmd, void *parg, - unsigned int stage); }; diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb-frontends/Kconfig index a08c2152d0ee..5efec73a32d2 100644 --- a/drivers/media/dvb/frontends/Kconfig +++ b/drivers/media/dvb-frontends/Kconfig @@ -1,20 +1,5 @@ -config DVB_FE_CUSTOMISE - bool "Customise the frontend modules to build" - depends on DVB_CORE - depends on EXPERT - default y if EXPERT - help - This allows the user to select/deselect frontend drivers for their - hardware from the build. - - Use this option with care as deselecting frontends which are in fact - necessary will result in DVB devices which cannot be tuned due to lack - of driver support. - - If unsure say N. - menu "Customise DVB Frontends" - visible if DVB_FE_CUSTOMISE + visible if !MEDIA_SUBDRV_AUTOSELECT comment "Multistandard (satellite) frontends" depends on DVB_CORE @@ -22,7 +7,7 @@ comment "Multistandard (satellite) frontends" config DVB_STB0899 tristate "STB0899 based" depends on DVB_CORE && I2C - default m if DVB_FE_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help A DVB-S/S2/DSS Multistandard demodulator. Say Y when you want to support this demodulator based frontends @@ -30,7 +15,7 @@ config DVB_STB0899 config DVB_STB6100 tristate "STB6100 based tuners" depends on DVB_CORE && I2C - default m if DVB_FE_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help A Silicon tuner from ST used in conjunction with the STB0899 demodulator. Say Y when you want to support this tuner. @@ -38,7 +23,7 @@ config DVB_STB6100 config DVB_STV090x tristate "STV0900/STV0903(A/B) based" depends on DVB_CORE && I2C - default m if DVB_FE_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help DVB-S/S2/DSS Multistandard Professional/Broadcast demodulators. Say Y when you want to support these frontends. @@ -46,7 +31,7 @@ config DVB_STV090x config DVB_STV6110x tristate "STV6110/(A) based tuners" depends on DVB_CORE && I2C - default m if DVB_FE_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help A Silicon tuner that supports DVB-S and DVB-S2 modes @@ -56,7 +41,7 @@ comment "Multistandard (cable + terrestrial) frontends" config DVB_DRXK tristate "Micronas DRXK based" depends on DVB_CORE && I2C - default m if DVB_FE_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help Micronas DRX-K DVB-C/T demodulator. @@ -65,7 +50,7 @@ config DVB_DRXK config DVB_TDA18271C2DD tristate "NXP TDA18271C2 silicon tuner" depends on DVB_CORE && I2C - default m if DVB_FE_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help NXP TDA18271 silicon tuner. @@ -77,119 +62,119 @@ comment "DVB-S (satellite) frontends" config DVB_CX24110 tristate "Conexant CX24110 based" depends on DVB_CORE && I2C - default m if DVB_FE_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help A DVB-S tuner module. Say Y when you want to support this frontend. config DVB_CX24123 tristate "Conexant CX24123 based" depends on DVB_CORE && I2C - default m if DVB_FE_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help A DVB-S tuner module. Say Y when you want to support this frontend. config DVB_MT312 tristate "Zarlink VP310/MT312/ZL10313 based" depends on DVB_CORE && I2C - default m if DVB_FE_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help A DVB-S tuner module. Say Y when you want to support this frontend. config DVB_ZL10036 tristate "Zarlink ZL10036 silicon tuner" depends on DVB_CORE && I2C - default m if DVB_FE_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help A DVB-S tuner module. Say Y when you want to support this frontend. config DVB_ZL10039 tristate "Zarlink ZL10039 silicon tuner" depends on DVB_CORE && I2C - default m if DVB_FE_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help A DVB-S tuner module. Say Y when you want to support this frontend. config DVB_S5H1420 tristate "Samsung S5H1420 based" depends on DVB_CORE && I2C - default m if DVB_FE_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help A DVB-S tuner module. Say Y when you want to support this frontend. config DVB_STV0288 tristate "ST STV0288 based" depends on DVB_CORE && I2C - default m if DVB_FE_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help A DVB-S tuner module. Say Y when you want to support this frontend. config DVB_STB6000 tristate "ST STB6000 silicon tuner" depends on DVB_CORE && I2C - default m if DVB_FE_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help A DVB-S silicon tuner module. Say Y when you want to support this tuner. config DVB_STV0299 tristate "ST STV0299 based" depends on DVB_CORE && I2C - default m if DVB_FE_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help A DVB-S tuner module. Say Y when you want to support this frontend. config DVB_STV6110 tristate "ST STV6110 silicon tuner" depends on DVB_CORE && I2C - default m if DVB_FE_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help A DVB-S silicon tuner module. Say Y when you want to support this tuner. config DVB_STV0900 tristate "ST STV0900 based" depends on DVB_CORE && I2C - default m if DVB_FE_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help A DVB-S/S2 demodulator. Say Y when you want to support this frontend. config DVB_TDA8083 tristate "Philips TDA8083 based" depends on DVB_CORE && I2C - default m if DVB_FE_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help A DVB-S tuner module. Say Y when you want to support this frontend. config DVB_TDA10086 tristate "Philips TDA10086 based" depends on DVB_CORE && I2C - default m if DVB_FE_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help A DVB-S tuner module. Say Y when you want to support this frontend. config DVB_TDA8261 tristate "Philips TDA8261 based" depends on DVB_CORE && I2C - default m if DVB_FE_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help A DVB-S tuner module. Say Y when you want to support this frontend. config DVB_VES1X93 tristate "VLSI VES1893 or VES1993 based" depends on DVB_CORE && I2C - default m if DVB_FE_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help A DVB-S tuner module. Say Y when you want to support this frontend. config DVB_TUNER_ITD1000 tristate "Integrant ITD1000 Zero IF tuner for DVB-S/DSS" depends on DVB_CORE && I2C - default m if DVB_FE_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help A DVB-S tuner module. Say Y when you want to support this frontend. config DVB_TUNER_CX24113 tristate "Conexant CX24113/CX24128 tuner for DVB-S/DSS" depends on DVB_CORE && I2C - default m if DVB_FE_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help A DVB-S tuner module. Say Y when you want to support this frontend. @@ -197,42 +182,42 @@ config DVB_TUNER_CX24113 config DVB_TDA826X tristate "Philips TDA826X silicon tuner" depends on DVB_CORE && I2C - default m if DVB_FE_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help A DVB-S silicon tuner module. Say Y when you want to support this tuner. config DVB_TUA6100 tristate "Infineon TUA6100 PLL" depends on DVB_CORE && I2C - default m if DVB_FE_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help A DVB-S PLL chip. config DVB_CX24116 tristate "Conexant CX24116 based" depends on DVB_CORE && I2C - default m if DVB_FE_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help A DVB-S/S2 tuner module. Say Y when you want to support this frontend. config DVB_SI21XX tristate "Silicon Labs SI21XX based" depends on DVB_CORE && I2C - default m if DVB_FE_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help A DVB-S tuner module. Say Y when you want to support this frontend. config DVB_DS3000 tristate "Montage Tehnology DS3000 based" depends on DVB_CORE && I2C - default m if DVB_FE_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help A DVB-S/S2 tuner module. Say Y when you want to support this frontend. config DVB_MB86A16 tristate "Fujitsu MB86A16 based" depends on DVB_CORE && I2C - default m if DVB_FE_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help A DVB-S/DSS Direct Conversion reveiver. Say Y when you want to support this frontend. @@ -240,7 +225,7 @@ config DVB_MB86A16 config DVB_TDA10071 tristate "NXP TDA10071" depends on DVB_CORE && I2C - default m if DVB_FE_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help Say Y when you want to support this frontend. @@ -250,7 +235,7 @@ comment "DVB-T (terrestrial) frontends" config DVB_SP8870 tristate "Spase sp8870 based" depends on DVB_CORE && I2C - default m if DVB_FE_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help A DVB-T tuner module. Say Y when you want to support this frontend. @@ -262,7 +247,7 @@ config DVB_SP8870 config DVB_SP887X tristate "Spase sp887x based" depends on DVB_CORE && I2C - default m if DVB_FE_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help A DVB-T tuner module. Say Y when you want to support this frontend. @@ -274,28 +259,28 @@ config DVB_SP887X config DVB_CX22700 tristate "Conexant CX22700 based" depends on DVB_CORE && I2C - default m if DVB_FE_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help A DVB-T tuner module. Say Y when you want to support this frontend. config DVB_CX22702 tristate "Conexant cx22702 demodulator (OFDM)" depends on DVB_CORE && I2C - default m if DVB_FE_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help A DVB-T tuner module. Say Y when you want to support this frontend. config DVB_S5H1432 tristate "Samsung s5h1432 demodulator (OFDM)" depends on DVB_CORE && I2C - default m if DVB_FE_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help A DVB-T tuner module. Say Y when you want to support this frontend. config DVB_DRXD tristate "Micronas DRXD driver" depends on DVB_CORE && I2C - default m if DVB_FE_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help A DVB-T tuner module. Say Y when you want to support this frontend. @@ -306,14 +291,14 @@ config DVB_DRXD config DVB_L64781 tristate "LSI L64781" depends on DVB_CORE && I2C - default m if DVB_FE_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help A DVB-T tuner module. Say Y when you want to support this frontend. config DVB_TDA1004X tristate "Philips TDA10045H/TDA10046H based" depends on DVB_CORE && I2C - default m if DVB_FE_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help A DVB-T tuner module. Say Y when you want to support this frontend. @@ -326,28 +311,28 @@ config DVB_TDA1004X config DVB_NXT6000 tristate "NxtWave Communications NXT6000 based" depends on DVB_CORE && I2C - default m if DVB_FE_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help A DVB-T tuner module. Say Y when you want to support this frontend. config DVB_MT352 tristate "Zarlink MT352 based" depends on DVB_CORE && I2C - default m if DVB_FE_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help A DVB-T tuner module. Say Y when you want to support this frontend. config DVB_ZL10353 tristate "Zarlink ZL10353 based" depends on DVB_CORE && I2C - default m if DVB_FE_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help A DVB-T tuner module. Say Y when you want to support this frontend. config DVB_DIB3000MB tristate "DiBcom 3000M-B" depends on DVB_CORE && I2C - default m if DVB_FE_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help A DVB-T tuner module. Designed for mobile usage. Say Y when you want to support this frontend. @@ -355,7 +340,7 @@ config DVB_DIB3000MB config DVB_DIB3000MC tristate "DiBcom 3000P/M-C" depends on DVB_CORE && I2C - default m if DVB_FE_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help A DVB-T tuner module. Designed for mobile usage. Say Y when you want to support this frontend. @@ -363,7 +348,7 @@ config DVB_DIB3000MC config DVB_DIB7000M tristate "DiBcom 7000MA/MB/PA/PB/MC" depends on DVB_CORE && I2C - default m if DVB_FE_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help A DVB-T tuner module. Designed for mobile usage. Say Y when you want to support this frontend. @@ -371,7 +356,7 @@ config DVB_DIB7000M config DVB_DIB7000P tristate "DiBcom 7000PC" depends on DVB_CORE && I2C - default m if DVB_FE_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help A DVB-T tuner module. Designed for mobile usage. Say Y when you want to support this frontend. @@ -379,7 +364,7 @@ config DVB_DIB7000P config DVB_DIB9000 tristate "DiBcom 9000" depends on DVB_CORE && I2C - default m if DVB_FE_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help A DVB-T tuner module. Designed for mobile usage. Say Y when you want to support this frontend. @@ -387,56 +372,56 @@ config DVB_DIB9000 config DVB_TDA10048 tristate "Philips TDA10048HN based" depends on DVB_CORE && I2C - default m if DVB_FE_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help A DVB-T tuner module. Say Y when you want to support this frontend. config DVB_AF9013 tristate "Afatech AF9013 demodulator" depends on DVB_CORE && I2C - default m if DVB_FE_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help Say Y when you want to support this frontend. config DVB_EC100 tristate "E3C EC100" depends on DVB_CORE && I2C - default m if DVB_FE_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help Say Y when you want to support this frontend. config DVB_HD29L2 tristate "HDIC HD29L2" depends on DVB_CORE && I2C - default m if DVB_FE_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help Say Y when you want to support this frontend. config DVB_STV0367 tristate "ST STV0367 based" depends on DVB_CORE && I2C - default m if DVB_FE_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help A DVB-T/C tuner module. Say Y when you want to support this frontend. config DVB_CXD2820R tristate "Sony CXD2820R" depends on DVB_CORE && I2C - default m if DVB_FE_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help Say Y when you want to support this frontend. config DVB_RTL2830 tristate "Realtek RTL2830 DVB-T" depends on DVB_CORE && I2C - default m if DVB_FE_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help Say Y when you want to support this frontend. config DVB_RTL2832 tristate "Realtek RTL2832 DVB-T" depends on DVB_CORE && I2C - default m if DVB_FE_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help Say Y when you want to support this frontend. @@ -446,28 +431,28 @@ comment "DVB-C (cable) frontends" config DVB_VES1820 tristate "VLSI VES1820 based" depends on DVB_CORE && I2C - default m if DVB_FE_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help A DVB-C tuner module. Say Y when you want to support this frontend. config DVB_TDA10021 tristate "Philips TDA10021 based" depends on DVB_CORE && I2C - default m if DVB_FE_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help A DVB-C tuner module. Say Y when you want to support this frontend. config DVB_TDA10023 tristate "Philips TDA10023 based" depends on DVB_CORE && I2C - default m if DVB_FE_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help A DVB-C tuner module. Say Y when you want to support this frontend. config DVB_STV0297 tristate "ST STV0297 based" depends on DVB_CORE && I2C - default m if DVB_FE_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help A DVB-C tuner module. Say Y when you want to support this frontend. @@ -477,7 +462,7 @@ comment "ATSC (North American/Korean Terrestrial/Cable DTV) frontends" config DVB_NXT200X tristate "NxtWave Communications NXT2002/NXT2004 based" depends on DVB_CORE && I2C - default m if DVB_FE_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want to support this frontend. @@ -491,7 +476,7 @@ config DVB_NXT200X config DVB_OR51211 tristate "Oren OR51211 based" depends on DVB_CORE && I2C - default m if DVB_FE_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help An ATSC 8VSB tuner module. Say Y when you want to support this frontend. @@ -503,7 +488,7 @@ config DVB_OR51211 config DVB_OR51132 tristate "Oren OR51132 based" depends on DVB_CORE && I2C - default m if DVB_FE_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want to support this frontend. @@ -518,7 +503,7 @@ config DVB_OR51132 config DVB_BCM3510 tristate "Broadcom BCM3510" depends on DVB_CORE && I2C - default m if DVB_FE_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help An ATSC 8VSB/16VSB and QAM64/256 tuner module. Say Y when you want to support this frontend. @@ -526,7 +511,7 @@ config DVB_BCM3510 config DVB_LGDT330X tristate "LG Electronics LGDT3302/LGDT3303 based" depends on DVB_CORE && I2C - default m if DVB_FE_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want to support this frontend. @@ -534,7 +519,7 @@ config DVB_LGDT330X config DVB_LGDT3305 tristate "LG Electronics LGDT3304 and LGDT3305 based" depends on DVB_CORE && I2C - default m if DVB_FE_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want to support this frontend. @@ -542,7 +527,7 @@ config DVB_LGDT3305 config DVB_LG2160 tristate "LG Electronics LG216x based" depends on DVB_CORE && I2C - default m if DVB_FE_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help An ATSC/MH demodulator module. Say Y when you want to support this frontend. @@ -550,7 +535,7 @@ config DVB_LG2160 config DVB_S5H1409 tristate "Samsung S5H1409 based" depends on DVB_CORE && I2C - default m if DVB_FE_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want to support this frontend. @@ -563,7 +548,7 @@ config DVB_AU8522_DTV tristate "Auvitek AU8522 based DTV demod" depends on DVB_CORE && I2C select DVB_AU8522 - default m if DVB_FE_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help An ATSC 8VSB, QAM64/256 & NTSC demodulator module. Say Y when you want to enable DTV demodulation support for this frontend. @@ -572,7 +557,7 @@ config DVB_AU8522_V4L tristate "Auvitek AU8522 based ATV demod" depends on VIDEO_V4L2 && I2C select DVB_AU8522 - default m if DVB_FE_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help An ATSC 8VSB, QAM64/256 & NTSC demodulator module. Say Y when you want to enable ATV demodulation support for this frontend. @@ -580,7 +565,7 @@ config DVB_AU8522_V4L config DVB_S5H1411 tristate "Samsung S5H1411 based" depends on DVB_CORE && I2C - default m if DVB_FE_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want to support this frontend. @@ -591,7 +576,7 @@ comment "ISDB-T (terrestrial) frontends" config DVB_S921 tristate "Sharp S921 frontend" depends on DVB_CORE && I2C - default m if DVB_FE_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help AN ISDB-T DQPSK, QPSK, 16QAM and 64QAM 1seg tuner module. Say Y when you want to support this frontend. @@ -599,7 +584,7 @@ config DVB_S921 config DVB_DIB8000 tristate "DiBcom 8000MB/MC" depends on DVB_CORE && I2C - default m if DVB_FE_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help A driver for DiBcom's DiB8000 ISDB-T/ISDB-Tsb demodulator. Say Y when you want to support this frontend. @@ -607,7 +592,7 @@ config DVB_DIB8000 config DVB_MB86A20S tristate "Fujitsu mb86a20s" depends on DVB_CORE && I2C - default m if DVB_FE_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help A driver for Fujitsu mb86a20s ISDB-T/ISDB-Tsb demodulator. Say Y when you want to support this frontend. @@ -618,7 +603,7 @@ comment "Digital terrestrial only tuners/PLL" config DVB_PLL tristate "Generic I2C PLL based tuners" depends on DVB_CORE && I2C - default m if DVB_FE_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help This module drives a number of tuners based on PLL chips with a common I2C interface. Say Y when you want to support these tuners. @@ -626,7 +611,7 @@ config DVB_PLL config DVB_TUNER_DIB0070 tristate "DiBcom DiB0070 silicon base-band tuner" depends on I2C - default m if DVB_FE_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help A driver for the silicon baseband tuner DiB0070 from DiBcom. This device is only used inside a SiP called together with a @@ -635,7 +620,7 @@ config DVB_TUNER_DIB0070 config DVB_TUNER_DIB0090 tristate "DiBcom DiB0090 silicon base-band tuner" depends on I2C - default m if DVB_FE_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help A driver for the silicon baseband tuner DiB0090 from DiBcom. This device is only used inside a SiP called together with a @@ -647,14 +632,14 @@ comment "SEC control devices for DVB-S" config DVB_LNBP21 tristate "LNBP21/LNBH24 SEC controllers" depends on DVB_CORE && I2C - default m if DVB_FE_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help An SEC control chips. config DVB_LNBP22 tristate "LNBP22 SEC controllers" depends on DVB_CORE && I2C - default m if DVB_FE_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help LNB power supply and control voltage regulator chip with step-up converter @@ -664,33 +649,33 @@ config DVB_LNBP22 config DVB_ISL6405 tristate "ISL6405 SEC controller" depends on DVB_CORE && I2C - default m if DVB_FE_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help An SEC control chip. config DVB_ISL6421 tristate "ISL6421 SEC controller" depends on DVB_CORE && I2C - default m if DVB_FE_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help An SEC control chip. config DVB_ISL6423 tristate "ISL6423 SEC controller" depends on DVB_CORE && I2C - default m if DVB_FE_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help A SEC controller chip from Intersil config DVB_A8293 tristate "Allegro A8293" depends on DVB_CORE && I2C - default m if DVB_FE_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT config DVB_LGS8GL5 tristate "Silicon Legend LGS-8GL5 demodulator (OFDM)" depends on DVB_CORE && I2C - default m if DVB_FE_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help A DMB-TH tuner module. Say Y when you want to support this frontend. @@ -698,21 +683,21 @@ config DVB_LGS8GXX tristate "Legend Silicon LGS8913/LGS8GL5/LGS8GXX DMB-TH demodulator" depends on DVB_CORE && I2C select FW_LOADER - default m if DVB_FE_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help A DMB-TH tuner module. Say Y when you want to support this frontend. config DVB_ATBM8830 tristate "AltoBeam ATBM8830/8831 DMB-TH demodulator" depends on DVB_CORE && I2C - default m if DVB_FE_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help A DMB-TH tuner module. Say Y when you want to support this frontend. config DVB_TDA665x tristate "TDA665x tuner" depends on DVB_CORE && I2C - default m if DVB_FE_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help Support for tuner modules based on Philips TDA6650/TDA6651 chips. Say Y when you want to support this chip. @@ -723,14 +708,14 @@ config DVB_TDA665x config DVB_IX2505V tristate "Sharp IX2505V silicon tuner" depends on DVB_CORE && I2C - default m if DVB_FE_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help A DVB-S tuner module. Say Y when you want to support this frontend. config DVB_IT913X_FE tristate "it913x frontend and it9137 tuner" depends on DVB_CORE && I2C - default m if DVB_FE_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help A DVB-T tuner module. Say Y when you want to support this frontend. @@ -738,7 +723,7 @@ config DVB_IT913X_FE config DVB_M88RS2000 tristate "M88RS2000 DVB-S demodulator and tuner" depends on DVB_CORE && I2C - default m if DVB_FE_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help A DVB-S tuner module. Say Y when you want to support this frontend. @@ -746,7 +731,7 @@ config DVB_M88RS2000 config DVB_AF9033 tristate "Afatech AF9033 DVB-T demodulator" depends on DVB_CORE && I2C - default m if DVB_FE_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT comment "Tools to develop new frontends" diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb-frontends/Makefile index 185bb8b51952..7eb73bbd2e26 100644 --- a/drivers/media/dvb/frontends/Makefile +++ b/drivers/media/dvb-frontends/Makefile @@ -2,13 +2,13 @@ # Makefile for the kernel DVB frontend device drivers. # -ccflags-y += -I$(srctree)/drivers/media/dvb/dvb-core/ -ccflags-y += -I$(srctree)/drivers/media/common/tuners/ +ccflags-y += -I$(srctree)/drivers/media/dvb-core/ +ccflags-y += -I$(srctree)/drivers/media/tuners/ -stb0899-objs = stb0899_drv.o stb0899_algo.o -stv0900-objs = stv0900_core.o stv0900_sw.o -drxd-objs = drxd_firm.o drxd_hard.o -cxd2820r-objs = cxd2820r_core.o cxd2820r_c.o cxd2820r_t.o cxd2820r_t2.o +stb0899-objs := stb0899_drv.o stb0899_algo.o +stv0900-objs := stv0900_core.o stv0900_sw.o +drxd-objs := drxd_firm.o drxd_hard.o +cxd2820r-objs := cxd2820r_core.o cxd2820r_c.o cxd2820r_t.o cxd2820r_t2.o drxk-objs := drxk_hard.o obj-$(CONFIG_DVB_PLL) += dvb-pll.o diff --git a/drivers/media/dvb/frontends/a8293.c b/drivers/media/dvb-frontends/a8293.c index cff44a389b40..cff44a389b40 100644 --- a/drivers/media/dvb/frontends/a8293.c +++ b/drivers/media/dvb-frontends/a8293.c diff --git a/drivers/media/dvb/frontends/a8293.h b/drivers/media/dvb-frontends/a8293.h index ed29e5504f76..ed29e5504f76 100644 --- a/drivers/media/dvb/frontends/a8293.h +++ b/drivers/media/dvb-frontends/a8293.h diff --git a/drivers/media/dvb/frontends/af9013.c b/drivers/media/dvb-frontends/af9013.c index 5bc570d77846..e9f04a36577b 100644 --- a/drivers/media/dvb/frontends/af9013.c +++ b/drivers/media/dvb-frontends/af9013.c @@ -24,10 +24,6 @@ #include "af9013_priv.h" -int af9013_debug; -module_param_named(debug, af9013_debug, int, 0644); -MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); - struct af9013_state { struct i2c_adapter *i2c; struct dvb_frontend fe; @@ -73,7 +69,8 @@ static int af9013_wr_regs_i2c(struct af9013_state *priv, u8 mbox, u16 reg, if (ret == 1) { ret = 0; } else { - warn("i2c wr failed=%d reg=%04x len=%d", ret, reg, len); + dev_warn(&priv->i2c->dev, "%s: i2c wr failed=%d reg=%04x " \ + "len=%d\n", KBUILD_MODNAME, ret, reg, len); ret = -EREMOTEIO; } return ret; @@ -107,7 +104,8 @@ static int af9013_rd_regs_i2c(struct af9013_state *priv, u8 mbox, u16 reg, if (ret == 2) { ret = 0; } else { - warn("i2c rd failed=%d reg=%04x len=%d", ret, reg, len); + dev_warn(&priv->i2c->dev, "%s: i2c rd failed=%d reg=%04x " \ + "len=%d\n", KBUILD_MODNAME, ret, reg, len); ret = -EREMOTEIO; } return ret; @@ -220,7 +218,8 @@ static int af9013_set_gpio(struct af9013_state *state, u8 gpio, u8 gpioval) u8 pos; u16 addr; - dbg("%s: gpio=%d gpioval=%02x", __func__, gpio, gpioval); + dev_dbg(&state->i2c->dev, "%s: gpio=%d gpioval=%02x\n", + __func__, gpio, gpioval); /* * GPIO0 & GPIO1 0xd735 @@ -238,7 +237,8 @@ static int af9013_set_gpio(struct af9013_state *state, u8 gpio, u8 gpioval) break; default: - err("invalid gpio:%d\n", gpio); + dev_err(&state->i2c->dev, "%s: invalid gpio=%d\n", + KBUILD_MODNAME, gpio); ret = -EINVAL; goto err; }; @@ -261,15 +261,15 @@ static int af9013_set_gpio(struct af9013_state *state, u8 gpio, u8 gpioval) return ret; err: - dbg("%s: failed=%d", __func__, ret); + dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret); return ret; } -static u32 af913_div(u32 a, u32 b, u32 x) +static u32 af9013_div(struct af9013_state *state, u32 a, u32 b, u32 x) { u32 r = 0, c = 0, i; - dbg("%s: a=%d b=%d x=%d", __func__, a, b, x); + dev_dbg(&state->i2c->dev, "%s: a=%d b=%d x=%d\n", __func__, a, b, x); if (a > b) { c = a / b; @@ -286,7 +286,9 @@ static u32 af913_div(u32 a, u32 b, u32 x) } r = (c << (u32)x) + r; - dbg("%s: a=%d b=%d x=%d r=%x", __func__, a, b, x, r); + dev_dbg(&state->i2c->dev, "%s: a=%d b=%d x=%d r=%d r=%x\n", + __func__, a, b, x, r, r); + return r; } @@ -295,7 +297,7 @@ static int af9013_power_ctrl(struct af9013_state *state, u8 onoff) int ret, i; u8 tmp; - dbg("%s: onoff=%d", __func__, onoff); + dev_dbg(&state->i2c->dev, "%s: onoff=%d\n", __func__, onoff); /* enable reset */ ret = af9013_wr_reg_bits(state, 0xd417, 4, 1, 1); @@ -340,7 +342,7 @@ static int af9013_power_ctrl(struct af9013_state *state, u8 onoff) return ret; err: - dbg("%s: failed=%d", __func__, ret); + dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret); return ret; } @@ -349,7 +351,7 @@ static int af9013_statistics_ber_unc_start(struct dvb_frontend *fe) struct af9013_state *state = fe->demodulator_priv; int ret; - dbg("%s", __func__); + dev_dbg(&state->i2c->dev, "%s:\n", __func__); /* reset and start BER counter */ ret = af9013_wr_reg_bits(state, 0xd391, 4, 1, 1); @@ -358,7 +360,7 @@ static int af9013_statistics_ber_unc_start(struct dvb_frontend *fe) return ret; err: - dbg("%s: failed=%d", __func__, ret); + dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret); return ret; } @@ -368,7 +370,7 @@ static int af9013_statistics_ber_unc_result(struct dvb_frontend *fe) int ret; u8 buf[5]; - dbg("%s", __func__); + dev_dbg(&state->i2c->dev, "%s:\n", __func__); /* check if error bit count is ready */ ret = af9013_rd_reg_bits(state, 0xd391, 4, 1, &buf[0]); @@ -376,7 +378,7 @@ static int af9013_statistics_ber_unc_result(struct dvb_frontend *fe) goto err; if (!buf[0]) { - dbg("%s: not ready", __func__); + dev_dbg(&state->i2c->dev, "%s: not ready\n", __func__); return 0; } @@ -389,7 +391,7 @@ static int af9013_statistics_ber_unc_result(struct dvb_frontend *fe) return ret; err: - dbg("%s: failed=%d", __func__, ret); + dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret); return ret; } @@ -398,7 +400,7 @@ static int af9013_statistics_snr_start(struct dvb_frontend *fe) struct af9013_state *state = fe->demodulator_priv; int ret; - dbg("%s", __func__); + dev_dbg(&state->i2c->dev, "%s:\n", __func__); /* start SNR meas */ ret = af9013_wr_reg_bits(state, 0xd2e1, 3, 1, 1); @@ -407,7 +409,7 @@ static int af9013_statistics_snr_start(struct dvb_frontend *fe) return ret; err: - dbg("%s: failed=%d", __func__, ret); + dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret); return ret; } @@ -419,7 +421,7 @@ static int af9013_statistics_snr_result(struct dvb_frontend *fe) u32 snr_val; const struct af9013_snr *uninitialized_var(snr_lut); - dbg("%s", __func__); + dev_dbg(&state->i2c->dev, "%s:\n", __func__); /* check if SNR ready */ ret = af9013_rd_reg_bits(state, 0xd2e1, 3, 1, &tmp); @@ -427,7 +429,7 @@ static int af9013_statistics_snr_result(struct dvb_frontend *fe) goto err; if (!tmp) { - dbg("%s: not ready", __func__); + dev_dbg(&state->i2c->dev, "%s: not ready\n", __func__); return 0; } @@ -471,7 +473,7 @@ static int af9013_statistics_snr_result(struct dvb_frontend *fe) return ret; err: - dbg("%s: failed=%d", __func__, ret); + dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret); return ret; } @@ -482,7 +484,7 @@ static int af9013_statistics_signal_strength(struct dvb_frontend *fe) u8 buf[2], rf_gain, if_gain; int signal_strength; - dbg("%s", __func__); + dev_dbg(&state->i2c->dev, "%s:\n", __func__); if (!state->signal_strength_en) return 0; @@ -508,7 +510,7 @@ static int af9013_statistics_signal_strength(struct dvb_frontend *fe) return ret; err: - dbg("%s: failed=%d", __func__, ret); + dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret); return ret; } @@ -578,8 +580,8 @@ static int af9013_set_frontend(struct dvb_frontend *fe) u8 buf[6]; u32 if_frequency, freq_cw; - dbg("%s: frequency=%d bandwidth_hz=%d", __func__, - c->frequency, c->bandwidth_hz); + dev_dbg(&state->i2c->dev, "%s: frequency=%d bandwidth_hz=%d\n", + __func__, c->frequency, c->bandwidth_hz); /* program tuner */ if (fe->ops.tuner_ops.set_params) @@ -606,6 +608,9 @@ static int af9013_set_frontend(struct dvb_frontend *fe) else if_frequency = state->config.if_frequency; + dev_dbg(&state->i2c->dev, "%s: if_frequency=%d\n", + __func__, if_frequency); + sampling_freq = if_frequency; while (sampling_freq > (state->config.clock / 2)) @@ -618,7 +623,8 @@ static int af9013_set_frontend(struct dvb_frontend *fe) spec_inv = !state->config.spec_inv; } - freq_cw = af913_div(sampling_freq, state->config.clock, 23); + freq_cw = af9013_div(state, sampling_freq, state->config.clock, + 23); if (spec_inv) freq_cw = 0x800000 - freq_cw; @@ -676,7 +682,8 @@ static int af9013_set_frontend(struct dvb_frontend *fe) buf[0] |= (1 << 0); break; default: - dbg("%s: invalid transmission_mode", __func__); + dev_dbg(&state->i2c->dev, "%s: invalid transmission_mode\n", + __func__); auto_mode = 1; } @@ -696,7 +703,8 @@ static int af9013_set_frontend(struct dvb_frontend *fe) buf[0] |= (3 << 2); break; default: - dbg("%s: invalid guard_interval", __func__); + dev_dbg(&state->i2c->dev, "%s: invalid guard_interval\n", + __func__); auto_mode = 1; } @@ -716,7 +724,7 @@ static int af9013_set_frontend(struct dvb_frontend *fe) buf[0] |= (3 << 4); break; default: - dbg("%s: invalid hierarchy", __func__); + dev_dbg(&state->i2c->dev, "%s: invalid hierarchy\n", __func__); auto_mode = 1; }; @@ -733,7 +741,7 @@ static int af9013_set_frontend(struct dvb_frontend *fe) buf[1] |= (2 << 6); break; default: - dbg("%s: invalid modulation", __func__); + dev_dbg(&state->i2c->dev, "%s: invalid modulation\n", __func__); auto_mode = 1; } @@ -759,7 +767,8 @@ static int af9013_set_frontend(struct dvb_frontend *fe) buf[2] |= (4 << 0); break; default: - dbg("%s: invalid code_rate_HP", __func__); + dev_dbg(&state->i2c->dev, "%s: invalid code_rate_HP\n", + __func__); auto_mode = 1; } @@ -784,7 +793,8 @@ static int af9013_set_frontend(struct dvb_frontend *fe) case FEC_NONE: break; default: - dbg("%s: invalid code_rate_LP", __func__); + dev_dbg(&state->i2c->dev, "%s: invalid code_rate_LP\n", + __func__); auto_mode = 1; } @@ -798,7 +808,8 @@ static int af9013_set_frontend(struct dvb_frontend *fe) buf[1] |= (2 << 2); break; default: - dbg("%s: invalid bandwidth_hz", __func__); + dev_dbg(&state->i2c->dev, "%s: invalid bandwidth_hz\n", + __func__); ret = -EINVAL; goto err; } @@ -813,7 +824,7 @@ static int af9013_set_frontend(struct dvb_frontend *fe) if (ret) goto err; - dbg("%s: auto params", __func__); + dev_dbg(&state->i2c->dev, "%s: auto params\n", __func__); } else { /* set easy mode flag */ ret = af9013_wr_reg(state, 0xaefd, 1); @@ -824,7 +835,7 @@ static int af9013_set_frontend(struct dvb_frontend *fe) if (ret) goto err; - dbg("%s: manual params", __func__); + dev_dbg(&state->i2c->dev, "%s: manual params\n", __func__); } /* tune */ @@ -838,7 +849,7 @@ static int af9013_set_frontend(struct dvb_frontend *fe) return ret; err: - dbg("%s: failed=%d", __func__, ret); + dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret); return ret; } @@ -849,7 +860,7 @@ static int af9013_get_frontend(struct dvb_frontend *fe) int ret; u8 buf[3]; - dbg("%s", __func__); + dev_dbg(&state->i2c->dev, "%s:\n", __func__); ret = af9013_rd_regs(state, 0xd3c0, buf, 3); if (ret) @@ -955,7 +966,7 @@ static int af9013_get_frontend(struct dvb_frontend *fe) return ret; err: - dbg("%s: failed=%d", __func__, ret); + dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret); return ret; } @@ -1005,7 +1016,7 @@ static int af9013_read_status(struct dvb_frontend *fe, fe_status_t *status) return ret; err: - dbg("%s: failed=%d", __func__, ret); + dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret); return ret; } @@ -1045,7 +1056,7 @@ static int af9013_init(struct dvb_frontend *fe) u32 adc_cw; const struct af9013_reg_bit *init; - dbg("%s", __func__); + dev_dbg(&state->i2c->dev, "%s:\n", __func__); /* power on */ ret = af9013_power_ctrl(state, 1); @@ -1077,11 +1088,12 @@ static int af9013_init(struct dvb_frontend *fe) tmp = 3; break; default: - err("invalid clock"); + dev_err(&state->i2c->dev, "%s: invalid clock\n", + KBUILD_MODNAME); return -EINVAL; } - adc_cw = af913_div(state->config.clock, 1000000ul, 19); + adc_cw = af9013_div(state, state->config.clock, 1000000ul, 19); buf[0] = (adc_cw >> 0) & 0xff; buf[1] = (adc_cw >> 8) & 0xff; buf[2] = (adc_cw >> 16) & 0xff; @@ -1137,7 +1149,7 @@ static int af9013_init(struct dvb_frontend *fe) goto err; /* load OFSM settings */ - dbg("%s: load ofsm settings", __func__); + dev_dbg(&state->i2c->dev, "%s: load ofsm settings\n", __func__); len = ARRAY_SIZE(ofsm_init); init = ofsm_init; for (i = 0; i < len; i++) { @@ -1148,7 +1160,8 @@ static int af9013_init(struct dvb_frontend *fe) } /* load tuner specific settings */ - dbg("%s: load tuner specific settings", __func__); + dev_dbg(&state->i2c->dev, "%s: load tuner specific settings\n", + __func__); switch (state->config.tuner) { case AF9013_TUNER_MXL5003D: len = ARRAY_SIZE(tuner_init_mxl5003d); @@ -1259,7 +1272,7 @@ static int af9013_init(struct dvb_frontend *fe) return ret; err: - dbg("%s: failed=%d", __func__, ret); + dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret); return ret; } @@ -1268,7 +1281,7 @@ static int af9013_sleep(struct dvb_frontend *fe) struct af9013_state *state = fe->demodulator_priv; int ret; - dbg("%s", __func__); + dev_dbg(&state->i2c->dev, "%s:\n", __func__); /* stop statistics polling */ cancel_delayed_work_sync(&state->statistics_work); @@ -1285,7 +1298,7 @@ static int af9013_sleep(struct dvb_frontend *fe) return ret; err: - dbg("%s: failed=%d", __func__, ret); + dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret); return ret; } @@ -1294,7 +1307,7 @@ static int af9013_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) int ret; struct af9013_state *state = fe->demodulator_priv; - dbg("%s: enable=%d", __func__, enable); + dev_dbg(&state->i2c->dev, "%s: enable=%d\n", __func__, enable); /* gate already open or close */ if (state->i2c_gate_state == enable) @@ -1311,7 +1324,7 @@ static int af9013_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) return ret; err: - dbg("%s: failed=%d", __func__, ret); + dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret); return ret; } @@ -1330,7 +1343,7 @@ static int af9013_download_firmware(struct af9013_state *state) u16 checksum = 0; u8 val; u8 fw_params[4]; - u8 *fw_file = AF9013_DEFAULT_FIRMWARE; + u8 *fw_file = AF9013_FIRMWARE; msleep(100); /* check whether firmware is already running */ @@ -1338,25 +1351,28 @@ static int af9013_download_firmware(struct af9013_state *state) if (ret) goto err; else - dbg("%s: firmware status=%02x", __func__, val); + dev_dbg(&state->i2c->dev, "%s: firmware status=%02x\n", + __func__, val); if (val == 0x0c) /* fw is running, no need for download */ goto exit; - info("found a '%s' in cold state, will try to load a firmware", - af9013_ops.info.name); + dev_info(&state->i2c->dev, "%s: found a '%s' in cold state, will try " \ + "to load a firmware\n", + KBUILD_MODNAME, af9013_ops.info.name); /* request the firmware, this will block and timeout */ ret = request_firmware(&fw, fw_file, state->i2c->dev.parent); if (ret) { - err("did not find the firmware file. (%s) " - "Please see linux/Documentation/dvb/ for more details" \ - " on firmware-problems. (%d)", - fw_file, ret); + dev_info(&state->i2c->dev, "%s: did not find the firmware " \ + "file. (%s) Please see linux/Documentation/dvb/ for " \ + "more details on firmware-problems. (%d)\n", + KBUILD_MODNAME, fw_file, ret); goto err; } - info("downloading firmware from file '%s'", fw_file); + dev_info(&state->i2c->dev, "%s: downloading firmware from file '%s'\n", + KBUILD_MODNAME, fw_file); /* calc checksum */ for (i = 0; i < fw->size; i++) @@ -1384,7 +1400,9 @@ static int af9013_download_firmware(struct af9013_state *state) FW_ADDR + fw->size - remaining, (u8 *) &fw->data[fw->size - remaining], len); if (ret) { - err("firmware download failed:%d", ret); + dev_err(&state->i2c->dev, + "%s: firmware download failed=%d\n", + KBUILD_MODNAME, ret); goto err_release; } } @@ -1402,17 +1420,20 @@ static int af9013_download_firmware(struct af9013_state *state) if (ret) goto err_release; - dbg("%s: firmware status=%02x", __func__, val); + dev_dbg(&state->i2c->dev, "%s: firmware status=%02x\n", + __func__, val); if (val == 0x0c || val == 0x04) /* success or fail */ break; } if (val == 0x04) { - err("firmware did not run"); + dev_err(&state->i2c->dev, "%s: firmware did not run\n", + KBUILD_MODNAME); ret = -ENODEV; } else if (val != 0x0c) { - err("firmware boot timeout"); + dev_err(&state->i2c->dev, "%s: firmware boot timeout\n", + KBUILD_MODNAME); ret = -ENODEV; } @@ -1421,7 +1442,8 @@ err_release: err: exit: if (!ret) - info("found a '%s' in warm state.", af9013_ops.info.name); + dev_info(&state->i2c->dev, "%s: found a '%s' in warm state\n", + KBUILD_MODNAME, af9013_ops.info.name); return ret; } @@ -1453,7 +1475,8 @@ struct dvb_frontend *af9013_attach(const struct af9013_config *config, if (ret) goto err; - info("firmware version %d.%d.%d.%d", buf[0], buf[1], buf[2], buf[3]); + dev_info(&state->i2c->dev, "%s: firmware version %d.%d.%d.%d\n", + KBUILD_MODNAME, buf[0], buf[1], buf[2], buf[3]); /* set GPIOs */ for (i = 0; i < sizeof(state->config.gpio); i++) { @@ -1522,3 +1545,4 @@ static struct dvb_frontend_ops af9013_ops = { MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>"); MODULE_DESCRIPTION("Afatech AF9013 DVB-T demodulator driver"); MODULE_LICENSE("GPL"); +MODULE_FIRMWARE(AF9013_FIRMWARE); diff --git a/drivers/media/dvb/frontends/af9013.h b/drivers/media/dvb-frontends/af9013.h index b973fc5a0384..dc837d91327a 100644 --- a/drivers/media/dvb/frontends/af9013.h +++ b/drivers/media/dvb-frontends/af9013.h @@ -110,7 +110,7 @@ extern struct dvb_frontend *af9013_attach(const struct af9013_config *config, static inline struct dvb_frontend *af9013_attach( const struct af9013_config *config, struct i2c_adapter *i2c) { - printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); + pr_warn("%s: driver disabled by Kconfig\n", __func__); return NULL; } #endif /* CONFIG_DVB_AF9013 */ diff --git a/drivers/media/dvb/frontends/af9013_priv.h b/drivers/media/dvb-frontends/af9013_priv.h index fa848af6e9b4..8b9392cfc00d 100644 --- a/drivers/media/dvb/frontends/af9013_priv.h +++ b/drivers/media/dvb-frontends/af9013_priv.h @@ -29,20 +29,7 @@ #include "af9013.h" #include <linux/firmware.h> -#define LOG_PREFIX "af9013" - -#undef dbg -#define dbg(f, arg...) \ - if (af9013_debug) \ - printk(KERN_INFO LOG_PREFIX": " f "\n" , ## arg) -#undef err -#define err(f, arg...) printk(KERN_ERR LOG_PREFIX": " f "\n" , ## arg) -#undef info -#define info(f, arg...) printk(KERN_INFO LOG_PREFIX": " f "\n" , ## arg) -#undef warn -#define warn(f, arg...) printk(KERN_WARNING LOG_PREFIX": " f "\n" , ## arg) - -#define AF9013_DEFAULT_FIRMWARE "dvb-fe-af9013.fw" +#define AF9013_FIRMWARE "dvb-fe-af9013.fw" struct af9013_reg_bit { u16 addr; diff --git a/drivers/media/dvb/frontends/af9033.c b/drivers/media/dvb-frontends/af9033.c index a38998286260..8162d939c4b2 100644 --- a/drivers/media/dvb/frontends/af9033.c +++ b/drivers/media/dvb-frontends/af9033.c @@ -59,8 +59,8 @@ static int af9033_wr_regs(struct af9033_state *state, u32 reg, const u8 *val, if (ret == 1) { ret = 0; } else { - printk(KERN_WARNING "%s: i2c wr failed=%d reg=%06x len=%d\n", - __func__, ret, reg, len); + dev_warn(&state->i2c->dev, "%s: i2c wr failed=%d reg=%06x " \ + "len=%d\n", KBUILD_MODNAME, ret, reg, len); ret = -EREMOTEIO; } @@ -91,8 +91,8 @@ static int af9033_rd_regs(struct af9033_state *state, u32 reg, u8 *val, int len) if (ret == 2) { ret = 0; } else { - printk(KERN_WARNING "%s: i2c rd failed=%d reg=%06x len=%d\n", - __func__, ret, reg, len); + dev_warn(&state->i2c->dev, "%s: i2c rd failed=%d reg=%06x " \ + "len=%d\n", KBUILD_MODNAME, ret, reg, len); ret = -EREMOTEIO; } @@ -156,11 +156,11 @@ static int af9033_rd_reg_mask(struct af9033_state *state, u32 reg, u8 *val, return 0; } -static u32 af9033_div(u32 a, u32 b, u32 x) +static u32 af9033_div(struct af9033_state *state, u32 a, u32 b, u32 x) { u32 r = 0, c = 0, i; - pr_debug("%s: a=%d b=%d x=%d\n", __func__, a, b, x); + dev_dbg(&state->i2c->dev, "%s: a=%d b=%d x=%d\n", __func__, a, b, x); if (a > b) { c = a / b; @@ -177,7 +177,8 @@ static u32 af9033_div(u32 a, u32 b, u32 x) } r = (c << (u32)x) + r; - pr_debug("%s: a=%d b=%d x=%d r=%d r=%x\n", __func__, a, b, x, r, r); + dev_dbg(&state->i2c->dev, "%s: a=%d b=%d x=%d r=%d r=%x\n", + __func__, a, b, x, r, r); return r; } @@ -225,14 +226,14 @@ static int af9033_init(struct dvb_frontend *fe) }; /* program clock control */ - clock_cw = af9033_div(state->cfg.clock, 1000000ul, 19ul); + clock_cw = af9033_div(state, state->cfg.clock, 1000000ul, 19ul); buf[0] = (clock_cw >> 0) & 0xff; buf[1] = (clock_cw >> 8) & 0xff; buf[2] = (clock_cw >> 16) & 0xff; buf[3] = (clock_cw >> 24) & 0xff; - pr_debug("%s: clock=%d clock_cw=%08x\n", __func__, state->cfg.clock, - clock_cw); + dev_dbg(&state->i2c->dev, "%s: clock=%d clock_cw=%08x\n", + __func__, state->cfg.clock, clock_cw); ret = af9033_wr_regs(state, 0x800025, buf, 4); if (ret < 0) @@ -244,13 +245,13 @@ static int af9033_init(struct dvb_frontend *fe) break; } - adc_cw = af9033_div(clock_adc_lut[i].adc, 1000000ul, 19ul); + adc_cw = af9033_div(state, clock_adc_lut[i].adc, 1000000ul, 19ul); buf[0] = (adc_cw >> 0) & 0xff; buf[1] = (adc_cw >> 8) & 0xff; buf[2] = (adc_cw >> 16) & 0xff; - pr_debug("%s: adc=%d adc_cw=%06x\n", __func__, clock_adc_lut[i].adc, - adc_cw); + dev_dbg(&state->i2c->dev, "%s: adc=%d adc_cw=%06x\n", + __func__, clock_adc_lut[i].adc, adc_cw); ret = af9033_wr_regs(state, 0x80f1cd, buf, 3); if (ret < 0) @@ -284,7 +285,7 @@ static int af9033_init(struct dvb_frontend *fe) } /* load OFSM settings */ - pr_debug("%s: load ofsm settings\n", __func__); + dev_dbg(&state->i2c->dev, "%s: load ofsm settings\n", __func__); len = ARRAY_SIZE(ofsm_init); init = ofsm_init; for (i = 0; i < len; i++) { @@ -294,7 +295,7 @@ static int af9033_init(struct dvb_frontend *fe) } /* load tuner specific settings */ - pr_debug("%s: load tuner specific settings\n", + dev_dbg(&state->i2c->dev, "%s: load tuner specific settings\n", __func__); switch (state->cfg.tuner) { case AF9033_TUNER_TUA9001: @@ -313,9 +314,13 @@ static int af9033_init(struct dvb_frontend *fe) len = ARRAY_SIZE(tuner_init_tda18218); init = tuner_init_tda18218; break; + case AF9033_TUNER_FC2580: + len = ARRAY_SIZE(tuner_init_fc2580); + init = tuner_init_fc2580; + break; default: - pr_debug("%s: unsupported tuner ID=%d\n", __func__, - state->cfg.tuner); + dev_dbg(&state->i2c->dev, "%s: unsupported tuner ID=%d\n", + __func__, state->cfg.tuner); ret = -ENODEV; goto err; } @@ -331,7 +336,7 @@ static int af9033_init(struct dvb_frontend *fe) return 0; err: - pr_debug("%s: failed=%d\n", __func__, ret); + dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret); return ret; } @@ -358,7 +363,7 @@ static int af9033_sleep(struct dvb_frontend *fe) usleep_range(200, 10000); } - pr_debug("%s: loop=%d\n", __func__, i); + dev_dbg(&state->i2c->dev, "%s: loop=%d\n", __func__, i); if (i == 0) { ret = -ETIMEDOUT; @@ -384,7 +389,7 @@ static int af9033_sleep(struct dvb_frontend *fe) return 0; err: - pr_debug("%s: failed=%d\n", __func__, ret); + dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret); return ret; } @@ -407,8 +412,8 @@ static int af9033_set_frontend(struct dvb_frontend *fe) u8 tmp, buf[3], bandwidth_reg_val; u32 if_frequency, freq_cw, adc_freq; - pr_debug("%s: frequency=%d bandwidth_hz=%d\n", __func__, c->frequency, - c->bandwidth_hz); + dev_dbg(&state->i2c->dev, "%s: frequency=%d bandwidth_hz=%d\n", + __func__, c->frequency, c->bandwidth_hz); /* check bandwidth */ switch (c->bandwidth_hz) { @@ -422,7 +427,8 @@ static int af9033_set_frontend(struct dvb_frontend *fe) bandwidth_reg_val = 0x02; break; default: - pr_debug("%s: invalid bandwidth_hz\n", __func__); + dev_dbg(&state->i2c->dev, "%s: invalid bandwidth_hz\n", + __func__); ret = -EINVAL; goto err; } @@ -467,7 +473,7 @@ static int af9033_set_frontend(struct dvb_frontend *fe) else if_frequency *= -1; - freq_cw = af9033_div(if_frequency, adc_freq, 23ul); + freq_cw = af9033_div(state, if_frequency, adc_freq, 23ul); if (spec_inv == -1) freq_cw *= -1; @@ -522,7 +528,7 @@ static int af9033_set_frontend(struct dvb_frontend *fe) return 0; err: - pr_debug("%s: failed=%d\n", __func__, ret); + dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret); return ret; } @@ -534,7 +540,7 @@ static int af9033_get_frontend(struct dvb_frontend *fe) int ret; u8 buf[8]; - pr_debug("%s\n", __func__); + dev_dbg(&state->i2c->dev, "%s:\n", __func__); /* read all needed registers */ ret = af9033_rd_regs(state, 0x80f900, buf, sizeof(buf)); @@ -649,7 +655,7 @@ static int af9033_get_frontend(struct dvb_frontend *fe) return 0; err: - pr_debug("%s: failed=%d\n", __func__, ret); + dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret); return ret; } @@ -695,7 +701,7 @@ static int af9033_read_status(struct dvb_frontend *fe, fe_status_t *status) return 0; err: - pr_debug("%s: failed=%d\n", __func__, ret); + dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret); return ret; } @@ -749,7 +755,7 @@ static int af9033_read_snr(struct dvb_frontend *fe, u16 *snr) return 0; err: - pr_debug("%s: failed=%d\n", __func__, ret); + dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret); return ret; } @@ -771,7 +777,7 @@ static int af9033_read_signal_strength(struct dvb_frontend *fe, u16 *strength) return 0; err: - pr_debug("%s: failed=%d\n", __func__, ret); + dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret); return ret; } @@ -815,7 +821,8 @@ static int af9033_update_ch_stat(struct af9033_state *state) return 0; err: - pr_debug("%s: failed=%d\n", __func__, ret); + dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret); + return ret; } @@ -852,7 +859,7 @@ static int af9033_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) struct af9033_state *state = fe->demodulator_priv; int ret; - pr_debug("%s: enable=%d\n", __func__, enable); + dev_dbg(&state->i2c->dev, "%s: enable=%d\n", __func__, enable); ret = af9033_wr_reg_mask(state, 0x00fa04, enable, 0x01); if (ret < 0) @@ -861,7 +868,7 @@ static int af9033_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) return 0; err: - pr_debug("%s: failed=%d\n", __func__, ret); + dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret); return ret; } @@ -875,7 +882,7 @@ struct dvb_frontend *af9033_attach(const struct af9033_config *config, struct af9033_state *state; u8 buf[8]; - pr_debug("%s:\n", __func__); + dev_dbg(&i2c->dev, "%s:\n", __func__); /* allocate memory for the internal state */ state = kzalloc(sizeof(struct af9033_state), GFP_KERNEL); @@ -887,9 +894,9 @@ struct dvb_frontend *af9033_attach(const struct af9033_config *config, memcpy(&state->cfg, config, sizeof(struct af9033_config)); if (state->cfg.clock != 12000000) { - printk(KERN_INFO "af9033: unsupported clock=%d, only " \ - "12000000 Hz is supported currently\n", - state->cfg.clock); + dev_err(&state->i2c->dev, "%s: af9033: unsupported clock=%d, " \ + "only 12000000 Hz is supported currently\n", + KBUILD_MODNAME, state->cfg.clock); goto err; } @@ -902,9 +909,18 @@ struct dvb_frontend *af9033_attach(const struct af9033_config *config, if (ret < 0) goto err; - printk(KERN_INFO "af9033: firmware version: LINK=%d.%d.%d.%d " \ - "OFDM=%d.%d.%d.%d\n", buf[0], buf[1], buf[2], buf[3], - buf[4], buf[5], buf[6], buf[7]); + dev_info(&state->i2c->dev, "%s: firmware version: LINK=%d.%d.%d.%d " \ + "OFDM=%d.%d.%d.%d\n", KBUILD_MODNAME, buf[0], buf[1], + buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]); + + /* sleep */ + ret = af9033_wr_reg(state, 0x80004c, 1); + if (ret < 0) + goto err; + + ret = af9033_wr_reg(state, 0x800000, 0); + if (ret < 0) + goto err; /* configure internal TS mode */ switch (state->cfg.ts_mode) { diff --git a/drivers/media/dvb/frontends/af9033.h b/drivers/media/dvb-frontends/af9033.h index 9e302c3f0f7d..bfa4313fde21 100644 --- a/drivers/media/dvb/frontends/af9033.h +++ b/drivers/media/dvb-frontends/af9033.h @@ -42,6 +42,7 @@ struct af9033_config { #define AF9033_TUNER_FC0011 0x28 /* Fitipower FC0011 */ #define AF9033_TUNER_MXL5007T 0xa0 /* MaxLinear MxL5007T */ #define AF9033_TUNER_TDA18218 0xa1 /* NXP TDA 18218HN */ +#define AF9033_TUNER_FC2580 0x32 /* FCI FC2580 */ u8 tuner; /* @@ -67,7 +68,7 @@ extern struct dvb_frontend *af9033_attach(const struct af9033_config *config, static inline struct dvb_frontend *af9033_attach( const struct af9033_config *config, struct i2c_adapter *i2c) { - printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); + pr_warn("%s: driver disabled by Kconfig\n", __func__); return NULL; } #endif diff --git a/drivers/media/dvb/frontends/af9033_priv.h b/drivers/media/dvb-frontends/af9033_priv.h index 0b783b9ed75e..34dddcd77538 100644 --- a/drivers/media/dvb/frontends/af9033_priv.h +++ b/drivers/media/dvb-frontends/af9033_priv.h @@ -466,5 +466,42 @@ static const struct reg_val tuner_init_tda18218[] = { {0x80f1e6, 0x00}, }; +/* FCI FC2580 tuner init */ +static const struct reg_val tuner_init_fc2580[] = { + { 0x800046, 0x32 }, + { 0x800057, 0x01 }, + { 0x800058, 0x00 }, + { 0x80005f, 0x00 }, + { 0x800060, 0x00 }, + { 0x800071, 0x05 }, + { 0x800072, 0x02 }, + { 0x800074, 0x01 }, + { 0x800079, 0x01 }, + { 0x800093, 0x00 }, + { 0x800094, 0x00 }, + { 0x800095, 0x00 }, + { 0x800096, 0x05 }, + { 0x8000b3, 0x01 }, + { 0x8000c3, 0x01 }, + { 0x8000c4, 0x00 }, + { 0x80f007, 0x00 }, + { 0x80f00c, 0x19 }, + { 0x80f00d, 0x1A }, + { 0x80f00e, 0x00 }, + { 0x80f00f, 0x02 }, + { 0x80f010, 0x00 }, + { 0x80f011, 0x02 }, + { 0x80f012, 0x00 }, + { 0x80f013, 0x02 }, + { 0x80f014, 0x00 }, + { 0x80f015, 0x02 }, + { 0x80f01f, 0x96 }, + { 0x80f020, 0x00 }, + { 0x80f029, 0x96 }, + { 0x80f02a, 0x00 }, + { 0x80f077, 0x01 }, + { 0x80f1e6, 0x01 }, +}; + #endif /* AF9033_PRIV_H */ diff --git a/drivers/media/dvb/frontends/atbm8830.c b/drivers/media/dvb-frontends/atbm8830.c index a2261ea2cf82..4e11dc4b1335 100644 --- a/drivers/media/dvb/frontends/atbm8830.c +++ b/drivers/media/dvb-frontends/atbm8830.c @@ -428,7 +428,7 @@ static int atbm8830_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) } static struct dvb_frontend_ops atbm8830_ops = { - .delsys = { SYS_DMBTH }, + .delsys = { SYS_DTMB }, .info = { .name = "AltoBeam ATBM8830/8831 DMB-TH", .frequency_min = 474000000, diff --git a/drivers/media/dvb/frontends/atbm8830.h b/drivers/media/dvb-frontends/atbm8830.h index 024273374bd8..024273374bd8 100644 --- a/drivers/media/dvb/frontends/atbm8830.h +++ b/drivers/media/dvb-frontends/atbm8830.h diff --git a/drivers/media/dvb/frontends/atbm8830_priv.h b/drivers/media/dvb-frontends/atbm8830_priv.h index d460058d497e..d460058d497e 100644 --- a/drivers/media/dvb/frontends/atbm8830_priv.h +++ b/drivers/media/dvb-frontends/atbm8830_priv.h diff --git a/drivers/media/dvb/frontends/au8522.h b/drivers/media/dvb-frontends/au8522.h index 565dcf31af57..565dcf31af57 100644 --- a/drivers/media/dvb/frontends/au8522.h +++ b/drivers/media/dvb-frontends/au8522.h diff --git a/drivers/media/dvb/frontends/au8522_common.c b/drivers/media/dvb-frontends/au8522_common.c index 5cfe151ee394..3559ff230045 100644 --- a/drivers/media/dvb/frontends/au8522_common.c +++ b/drivers/media/dvb-frontends/au8522_common.c @@ -26,8 +26,6 @@ #include "dvb_frontend.h" #include "au8522_priv.h" -MODULE_LICENSE("GPL"); - static int debug; #define dprintk(arg...)\ @@ -101,6 +99,19 @@ int au8522_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) } EXPORT_SYMBOL(au8522_i2c_gate_ctrl); +int au8522_analog_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) +{ + struct au8522_state *state = fe->demodulator_priv; + + dprintk("%s(%d)\n", __func__, enable); + + if (enable) + return au8522_writereg(state, 0x106, 1); + else + return au8522_writereg(state, 0x106, 0); +} +EXPORT_SYMBOL(au8522_analog_i2c_gate_ctrl); + /* Reset the demod hardware and reset all of the configuration registers to a default state. */ int au8522_get_state(struct au8522_state **state, struct i2c_adapter *i2c, @@ -257,3 +268,10 @@ int au8522_sleep(struct dvb_frontend *fe) return 0; } EXPORT_SYMBOL(au8522_sleep); + +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "Enable verbose debug messages"); + +MODULE_DESCRIPTION("Auvitek AU8522 QAM-B/ATSC Demodulator driver"); +MODULE_AUTHOR("Steven Toth"); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/dvb/frontends/au8522_decoder.c b/drivers/media/dvb-frontends/au8522_decoder.c index 55b6390198e3..5243ba6295cc 100644 --- a/drivers/media/dvb/frontends/au8522_decoder.c +++ b/drivers/media/dvb-frontends/au8522_decoder.c @@ -257,9 +257,11 @@ static void setup_decoder_defaults(struct au8522_state *state, u8 input_mode) au8522_writereg(state, AU8522_TVDED_DBG_MODE_REG060H, AU8522_TVDED_DBG_MODE_REG060H_CVBS); au8522_writereg(state, AU8522_TVDEC_FORMAT_CTRL1_REG061H, - AU8522_TVDEC_FORMAT_CTRL1_REG061H_CVBS13); + AU8522_TVDEC_FORMAT_CTRL1_REG061H_FIELD_LEN_525 | + AU8522_TVDEC_FORMAT_CTRL1_REG061H_LINE_LEN_63_492 | + AU8522_TVDEC_FORMAT_CTRL1_REG061H_SUBCARRIER_NTSC_MN); au8522_writereg(state, AU8522_TVDEC_FORMAT_CTRL2_REG062H, - AU8522_TVDEC_FORMAT_CTRL2_REG062H_CVBS13); + AU8522_TVDEC_FORMAT_CTRL2_REG062H_STD_NTSC); au8522_writereg(state, AU8522_TVDEC_VCR_DET_LLIM_REG063H, AU8522_TVDEC_VCR_DET_LLIM_REG063H_CVBS); au8522_writereg(state, AU8522_TVDEC_VCR_DET_HLIM_REG064H, @@ -657,11 +659,6 @@ static int au8522_s_video_routing(struct v4l2_subdev *sd, au8522_reset(sd, 0); - /* Jam open the i2c gate to the tuner. We do this here to handle the - case where the user went into digital mode (causing the gate to be - closed), and then came back to analog mode */ - au8522_writereg(state, 0x106, 1); - if (input == AU8522_COMPOSITE_CH1) { au8522_setup_cvbs_mode(state); } else if (input == AU8522_SVIDEO_CH13) { diff --git a/drivers/media/dvb/frontends/au8522_dig.c b/drivers/media/dvb-frontends/au8522_dig.c index 5fc70d6cd04f..a68974f6d708 100644 --- a/drivers/media/dvb/frontends/au8522_dig.c +++ b/drivers/media/dvb-frontends/au8522_dig.c @@ -157,54 +157,54 @@ static struct mse2snr_tab qam64_mse2snr_tab[] = { /* QAM256 SNR lookup table */ static struct mse2snr_tab qam256_mse2snr_tab[] = { - { 16, 0 }, - { 17, 400 }, - { 18, 398 }, - { 19, 396 }, - { 20, 394 }, - { 21, 392 }, - { 22, 390 }, - { 23, 388 }, - { 24, 386 }, - { 25, 384 }, - { 26, 382 }, - { 27, 380 }, - { 28, 379 }, - { 29, 378 }, - { 30, 377 }, - { 31, 376 }, - { 32, 375 }, - { 33, 374 }, - { 34, 373 }, - { 35, 372 }, - { 36, 371 }, - { 37, 370 }, - { 38, 362 }, - { 39, 354 }, - { 40, 346 }, - { 41, 338 }, - { 42, 330 }, - { 43, 328 }, - { 44, 326 }, - { 45, 324 }, - { 46, 322 }, - { 47, 320 }, - { 48, 319 }, - { 49, 318 }, - { 50, 317 }, - { 51, 316 }, - { 52, 315 }, - { 53, 314 }, - { 54, 313 }, - { 55, 312 }, - { 56, 311 }, - { 57, 310 }, - { 58, 308 }, - { 59, 306 }, - { 60, 304 }, - { 61, 302 }, - { 62, 300 }, - { 63, 298 }, + { 15, 0 }, + { 16, 400 }, + { 17, 398 }, + { 18, 396 }, + { 19, 394 }, + { 20, 392 }, + { 21, 390 }, + { 22, 388 }, + { 23, 386 }, + { 24, 384 }, + { 25, 382 }, + { 26, 380 }, + { 27, 379 }, + { 28, 378 }, + { 29, 377 }, + { 30, 376 }, + { 31, 375 }, + { 32, 374 }, + { 33, 373 }, + { 34, 372 }, + { 35, 371 }, + { 36, 370 }, + { 37, 362 }, + { 38, 354 }, + { 39, 346 }, + { 40, 338 }, + { 41, 330 }, + { 42, 328 }, + { 43, 326 }, + { 44, 324 }, + { 45, 322 }, + { 46, 320 }, + { 47, 319 }, + { 48, 318 }, + { 49, 317 }, + { 50, 316 }, + { 51, 315 }, + { 52, 314 }, + { 53, 313 }, + { 54, 312 }, + { 55, 311 }, + { 56, 310 }, + { 57, 308 }, + { 58, 306 }, + { 59, 304 }, + { 60, 302 }, + { 61, 300 }, + { 62, 298 }, { 65, 295 }, { 68, 294 }, { 70, 293 }, @@ -777,6 +777,8 @@ struct dvb_frontend *au8522_attach(const struct au8522_config *config, sizeof(struct dvb_frontend_ops)); state->frontend.demodulator_priv = state; + state->frontend.ops.analog_ops.i2c_gate_ctrl = au8522_analog_i2c_gate_ctrl; + if (au8522_init(&state->frontend) != 0) { printk(KERN_ERR "%s: Failed to initialize correctly\n", __func__); diff --git a/drivers/media/dvb/frontends/au8522_priv.h b/drivers/media/dvb-frontends/au8522_priv.h index 6e4a438732b5..0529699a27bd 100644 --- a/drivers/media/dvb/frontends/au8522_priv.h +++ b/drivers/media/dvb-frontends/au8522_priv.h @@ -82,6 +82,7 @@ int au8522_get_state(struct au8522_state **state, struct i2c_adapter *i2c, u8 client_address); void au8522_release_state(struct au8522_state *state); int au8522_i2c_gate_ctrl(struct dvb_frontend *fe, int enable); +int au8522_analog_i2c_gate_ctrl(struct dvb_frontend *fe, int enable); int au8522_led_ctrl(struct au8522_state *state, int led); /* REGISTERS */ @@ -325,6 +326,31 @@ int au8522_led_ctrl(struct au8522_state *state, int led); /**************************************************************/ +/* Format control 1 */ + +/* VCR Mode 7-6 */ +#define AU8522_TVDEC_FORMAT_CTRL1_REG061H_VCR_MODE_YES 0x80 +#define AU8522_TVDEC_FORMAT_CTRL1_REG061H_VCR_MODE_NO 0x40 +#define AU8522_TVDEC_FORMAT_CTRL1_REG061H_VCR_MODE_AUTO 0x00 +/* Field len 5-4 */ +#define AU8522_TVDEC_FORMAT_CTRL1_REG061H_FIELD_LEN_625 0x20 +#define AU8522_TVDEC_FORMAT_CTRL1_REG061H_FIELD_LEN_525 0x10 +#define AU8522_TVDEC_FORMAT_CTRL1_REG061H_FIELD_LEN_AUTO 0x00 +/* Line len (us) 3-2 */ +#define AU8522_TVDEC_FORMAT_CTRL1_REG061H_LINE_LEN_64_000 0x0b +#define AU8522_TVDEC_FORMAT_CTRL1_REG061H_LINE_LEN_63_492 0x08 +#define AU8522_TVDEC_FORMAT_CTRL1_REG061H_LINE_LEN_63_556 0x04 +/* Subcarrier freq 1-0 */ +#define AU8522_TVDEC_FORMAT_CTRL1_REG061H_SUBCARRIER_NTSC_AUTO 0x03 +#define AU8522_TVDEC_FORMAT_CTRL1_REG061H_SUBCARRIER_NTSC_443 0x02 +#define AU8522_TVDEC_FORMAT_CTRL1_REG061H_SUBCARRIER_NTSC_MN 0x01 +#define AU8522_TVDEC_FORMAT_CTRL1_REG061H_SUBCARRIER_NTSC_50 0x00 + +/* Format control 2 */ +#define AU8522_TVDEC_FORMAT_CTRL2_REG062H_STD_AUTODETECT 0x00 +#define AU8522_TVDEC_FORMAT_CTRL2_REG062H_STD_NTSC 0x01 + + #define AU8522_INPUT_CONTROL_REG081H_ATSC 0xC4 #define AU8522_INPUT_CONTROL_REG081H_ATVRF 0xC4 #define AU8522_INPUT_CONTROL_REG081H_ATVRF13 0xC4 @@ -385,9 +411,6 @@ int au8522_led_ctrl(struct au8522_state *state, int led); #define AU8522_TVDEC_COMB_MODE_REG015H_CVBS 0x00 #define AU8522_REG016H_CVBS 0x00 #define AU8522_TVDED_DBG_MODE_REG060H_CVBS 0x00 -#define AU8522_TVDEC_FORMAT_CTRL1_REG061H_CVBS 0x0B -#define AU8522_TVDEC_FORMAT_CTRL1_REG061H_CVBS13 0x03 -#define AU8522_TVDEC_FORMAT_CTRL2_REG062H_CVBS13 0x00 #define AU8522_TVDEC_VCR_DET_LLIM_REG063H_CVBS 0x19 #define AU8522_REG0F9H_AUDIO 0x20 #define AU8522_TVDEC_VCR_DET_HLIM_REG064H_CVBS 0xA7 diff --git a/drivers/media/dvb/frontends/bcm3510.c b/drivers/media/dvb-frontends/bcm3510.c index 033cd7ad3ca2..033cd7ad3ca2 100644 --- a/drivers/media/dvb/frontends/bcm3510.c +++ b/drivers/media/dvb-frontends/bcm3510.c diff --git a/drivers/media/dvb/frontends/bcm3510.h b/drivers/media/dvb-frontends/bcm3510.h index f4575c0cc446..f4575c0cc446 100644 --- a/drivers/media/dvb/frontends/bcm3510.h +++ b/drivers/media/dvb-frontends/bcm3510.h diff --git a/drivers/media/dvb/frontends/bcm3510_priv.h b/drivers/media/dvb-frontends/bcm3510_priv.h index 3bb1bc2a04f0..3bb1bc2a04f0 100644 --- a/drivers/media/dvb/frontends/bcm3510_priv.h +++ b/drivers/media/dvb-frontends/bcm3510_priv.h diff --git a/drivers/media/dvb/frontends/bsbe1-d01a.h b/drivers/media/dvb-frontends/bsbe1-d01a.h index 7ed3c424178c..7ed3c424178c 100644 --- a/drivers/media/dvb/frontends/bsbe1-d01a.h +++ b/drivers/media/dvb-frontends/bsbe1-d01a.h diff --git a/drivers/media/dvb/frontends/bsbe1.h b/drivers/media/dvb-frontends/bsbe1.h index 53e4d0dbb745..53e4d0dbb745 100644 --- a/drivers/media/dvb/frontends/bsbe1.h +++ b/drivers/media/dvb-frontends/bsbe1.h diff --git a/drivers/media/dvb/frontends/bsru6.h b/drivers/media/dvb-frontends/bsru6.h index c2a578e1314d..c2a578e1314d 100644 --- a/drivers/media/dvb/frontends/bsru6.h +++ b/drivers/media/dvb-frontends/bsru6.h diff --git a/drivers/media/dvb/frontends/cx22700.c b/drivers/media/dvb-frontends/cx22700.c index f2a90f990ce3..f2a90f990ce3 100644 --- a/drivers/media/dvb/frontends/cx22700.c +++ b/drivers/media/dvb-frontends/cx22700.c diff --git a/drivers/media/dvb/frontends/cx22700.h b/drivers/media/dvb-frontends/cx22700.h index 4757a930ca05..4757a930ca05 100644 --- a/drivers/media/dvb/frontends/cx22700.h +++ b/drivers/media/dvb-frontends/cx22700.h diff --git a/drivers/media/dvb/frontends/cx22702.c b/drivers/media/dvb-frontends/cx22702.c index edc8eafc5c09..edc8eafc5c09 100644 --- a/drivers/media/dvb/frontends/cx22702.c +++ b/drivers/media/dvb-frontends/cx22702.c diff --git a/drivers/media/dvb/frontends/cx22702.h b/drivers/media/dvb-frontends/cx22702.h index f154e1f428eb..f154e1f428eb 100644 --- a/drivers/media/dvb/frontends/cx22702.h +++ b/drivers/media/dvb-frontends/cx22702.h diff --git a/drivers/media/dvb/frontends/cx24110.c b/drivers/media/dvb-frontends/cx24110.c index 3180f5b2a6a6..3180f5b2a6a6 100644 --- a/drivers/media/dvb/frontends/cx24110.c +++ b/drivers/media/dvb-frontends/cx24110.c diff --git a/drivers/media/dvb/frontends/cx24110.h b/drivers/media/dvb-frontends/cx24110.h index fdcceee91f3a..fdcceee91f3a 100644 --- a/drivers/media/dvb/frontends/cx24110.h +++ b/drivers/media/dvb-frontends/cx24110.h diff --git a/drivers/media/dvb/frontends/cx24113.c b/drivers/media/dvb-frontends/cx24113.c index 3883c3b31aef..3883c3b31aef 100644 --- a/drivers/media/dvb/frontends/cx24113.c +++ b/drivers/media/dvb-frontends/cx24113.c diff --git a/drivers/media/dvb/frontends/cx24113.h b/drivers/media/dvb-frontends/cx24113.h index 01eb7b9c28f4..01eb7b9c28f4 100644 --- a/drivers/media/dvb/frontends/cx24113.h +++ b/drivers/media/dvb-frontends/cx24113.h diff --git a/drivers/media/dvb/frontends/cx24116.c b/drivers/media/dvb-frontends/cx24116.c index b48879186537..b48879186537 100644 --- a/drivers/media/dvb/frontends/cx24116.c +++ b/drivers/media/dvb-frontends/cx24116.c diff --git a/drivers/media/dvb/frontends/cx24116.h b/drivers/media/dvb-frontends/cx24116.h index 7d90ab949c03..7d90ab949c03 100644 --- a/drivers/media/dvb/frontends/cx24116.h +++ b/drivers/media/dvb-frontends/cx24116.h diff --git a/drivers/media/dvb/frontends/cx24123.c b/drivers/media/dvb-frontends/cx24123.c index 7e28b4ee7d4f..7e28b4ee7d4f 100644 --- a/drivers/media/dvb/frontends/cx24123.c +++ b/drivers/media/dvb-frontends/cx24123.c diff --git a/drivers/media/dvb/frontends/cx24123.h b/drivers/media/dvb-frontends/cx24123.h index 51ae866e9fed..51ae866e9fed 100644 --- a/drivers/media/dvb/frontends/cx24123.h +++ b/drivers/media/dvb-frontends/cx24123.h diff --git a/drivers/media/dvb/frontends/cxd2820r.h b/drivers/media/dvb-frontends/cxd2820r.h index 5aa306ebb7ef..6acc21c581c5 100644 --- a/drivers/media/dvb/frontends/cxd2820r.h +++ b/drivers/media/dvb-frontends/cxd2820r.h @@ -62,14 +62,6 @@ struct cxd2820r_config { * Values: 0, 1 */ bool spec_inv; - - /* GPIOs for all used modes. - * Default: none, disabled - * Values: <see above> - */ - u8 gpio_dvbt[3]; - u8 gpio_dvbt2[3]; - u8 gpio_dvbc[3]; }; @@ -77,12 +69,14 @@ struct cxd2820r_config { (defined(CONFIG_DVB_CXD2820R_MODULE) && defined(MODULE)) extern struct dvb_frontend *cxd2820r_attach( const struct cxd2820r_config *config, - struct i2c_adapter *i2c + struct i2c_adapter *i2c, + int *gpio_chip_base ); #else static inline struct dvb_frontend *cxd2820r_attach( const struct cxd2820r_config *config, - struct i2c_adapter *i2c + struct i2c_adapter *i2c, + int *gpio_chip_base ) { printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); diff --git a/drivers/media/dvb/frontends/cxd2820r_c.c b/drivers/media/dvb-frontends/cxd2820r_c.c index ed3b0ba624de..125a44041011 100644 --- a/drivers/media/dvb/frontends/cxd2820r_c.c +++ b/drivers/media/dvb-frontends/cxd2820r_c.c @@ -47,12 +47,8 @@ int cxd2820r_set_frontend_c(struct dvb_frontend *fe) { 0x10070, priv->cfg.ts_mode, 0xff }, }; - dbg("%s: RF=%d SR=%d", __func__, c->frequency, c->symbol_rate); - - /* update GPIOs */ - ret = cxd2820r_gpio(fe); - if (ret) - goto error; + dev_dbg(&priv->i2c->dev, "%s: frequency=%d symbol_rate=%d\n", __func__, + c->frequency, c->symbol_rate); /* program tuner */ if (fe->ops.tuner_ops.set_params) @@ -78,7 +74,7 @@ int cxd2820r_set_frontend_c(struct dvb_frontend *fe) } else if_freq = 0; - dbg("%s: if_freq=%d", __func__, if_freq); + dev_dbg(&priv->i2c->dev, "%s: if_freq=%d\n", __func__, if_freq); num = if_freq / 1000; /* Hz => kHz */ num *= 0x4000; @@ -100,7 +96,7 @@ int cxd2820r_set_frontend_c(struct dvb_frontend *fe) return ret; error: - dbg("%s: failed:%d", __func__, ret); + dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); return ret; } @@ -150,7 +146,7 @@ int cxd2820r_get_frontend_c(struct dvb_frontend *fe) return ret; error: - dbg("%s: failed:%d", __func__, ret); + dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); return ret; } @@ -184,7 +180,7 @@ int cxd2820r_read_ber_c(struct dvb_frontend *fe, u32 *ber) return ret; error: - dbg("%s: failed:%d", __func__, ret); + dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); return ret; } @@ -214,7 +210,7 @@ int cxd2820r_read_signal_strength_c(struct dvb_frontend *fe, return ret; error: - dbg("%s: failed:%d", __func__, ret); + dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); return ret; } @@ -251,7 +247,7 @@ int cxd2820r_read_snr_c(struct dvb_frontend *fe, u16 *snr) return ret; error: - dbg("%s: failed:%d", __func__, ret); + dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); return ret; } @@ -283,11 +279,12 @@ int cxd2820r_read_status_c(struct dvb_frontend *fe, fe_status_t *status) } } - dbg("%s: lock=%02x %02x", __func__, buf[0], buf[1]); + dev_dbg(&priv->i2c->dev, "%s: lock=%02x %02x\n", __func__, buf[0], + buf[1]); return ret; error: - dbg("%s: failed:%d", __func__, ret); + dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); return ret; } @@ -302,7 +299,7 @@ int cxd2820r_init_c(struct dvb_frontend *fe) return ret; error: - dbg("%s: failed:%d", __func__, ret); + dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); return ret; } @@ -318,7 +315,7 @@ int cxd2820r_sleep_c(struct dvb_frontend *fe) { 0x00080, 0x00, 0xff }, }; - dbg("%s", __func__); + dev_dbg(&priv->i2c->dev, "%s\n", __func__); priv->delivery_system = SYS_UNDEFINED; @@ -331,7 +328,7 @@ int cxd2820r_sleep_c(struct dvb_frontend *fe) return ret; error: - dbg("%s: failed:%d", __func__, ret); + dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); return ret; } diff --git a/drivers/media/dvb/frontends/cxd2820r_core.c b/drivers/media/dvb-frontends/cxd2820r_core.c index 3bba37d74f57..42648643693e 100644 --- a/drivers/media/dvb/frontends/cxd2820r_core.c +++ b/drivers/media/dvb-frontends/cxd2820r_core.c @@ -21,10 +21,6 @@ #include "cxd2820r_priv.h" -int cxd2820r_debug; -module_param_named(debug, cxd2820r_debug, int, 0644); -MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); - /* write multiple registers */ static int cxd2820r_wr_regs_i2c(struct cxd2820r_priv *priv, u8 i2c, u8 reg, u8 *val, int len) @@ -47,7 +43,8 @@ static int cxd2820r_wr_regs_i2c(struct cxd2820r_priv *priv, u8 i2c, u8 reg, if (ret == 1) { ret = 0; } else { - warn("i2c wr failed ret:%d reg:%02x len:%d", ret, reg, len); + dev_warn(&priv->i2c->dev, "%s: i2c wr failed=%d reg=%02x " \ + "len=%d\n", KBUILD_MODNAME, ret, reg, len); ret = -EREMOTEIO; } return ret; @@ -78,7 +75,8 @@ static int cxd2820r_rd_regs_i2c(struct cxd2820r_priv *priv, u8 i2c, u8 reg, memcpy(val, buf, len); ret = 0; } else { - warn("i2c rd failed ret:%d reg:%02x len:%d", ret, reg, len); + dev_warn(&priv->i2c->dev, "%s: i2c rd failed=%d reg=%02x " \ + "len=%d\n", KBUILD_MODNAME, ret, reg, len); ret = -EREMOTEIO; } @@ -170,27 +168,14 @@ int cxd2820r_wr_reg_mask(struct cxd2820r_priv *priv, u32 reg, u8 val, return cxd2820r_wr_reg(priv, reg, val); } -int cxd2820r_gpio(struct dvb_frontend *fe) +int cxd2820r_gpio(struct dvb_frontend *fe, u8 *gpio) { struct cxd2820r_priv *priv = fe->demodulator_priv; int ret, i; - u8 *gpio, tmp0, tmp1; - dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system); + u8 tmp0, tmp1; - switch (fe->dtv_property_cache.delivery_system) { - case SYS_DVBT: - gpio = priv->cfg.gpio_dvbt; - break; - case SYS_DVBT2: - gpio = priv->cfg.gpio_dvbt2; - break; - case SYS_DVBC_ANNEX_AC: - gpio = priv->cfg.gpio_dvbc; - break; - default: - ret = -EINVAL; - goto error; - } + dev_dbg(&priv->i2c->dev, "%s: delsys=%d\n", __func__, + fe->dtv_property_cache.delivery_system); /* update GPIOs only when needed */ if (!memcmp(gpio, priv->gpio, sizeof(priv->gpio))) @@ -217,10 +202,12 @@ int cxd2820r_gpio(struct dvb_frontend *fe) else tmp1 |= (0 << (0 + i)); - dbg("%s: GPIO i=%d %02x %02x", __func__, i, tmp0, tmp1); + dev_dbg(&priv->i2c->dev, "%s: gpio i=%d %02x %02x\n", __func__, + i, tmp0, tmp1); } - dbg("%s: wr gpio=%02x %02x", __func__, tmp0, tmp1); + dev_dbg(&priv->i2c->dev, "%s: wr gpio=%02x %02x\n", __func__, tmp0, + tmp1); /* write bits [7:2] */ ret = cxd2820r_wr_reg_mask(priv, 0x00089, tmp0, 0xfc); @@ -236,7 +223,7 @@ int cxd2820r_gpio(struct dvb_frontend *fe) return ret; error: - dbg("%s: failed:%d", __func__, ret); + dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); return ret; } @@ -248,10 +235,13 @@ u32 cxd2820r_div_u64_round_closest(u64 dividend, u32 divisor) static int cxd2820r_set_frontend(struct dvb_frontend *fe) { + struct cxd2820r_priv *priv = fe->demodulator_priv; struct dtv_frontend_properties *c = &fe->dtv_property_cache; int ret; - dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system); + dev_dbg(&priv->i2c->dev, "%s: delsys=%d\n", __func__, + fe->dtv_property_cache.delivery_system); + switch (c->delivery_system) { case SYS_DVBT: ret = cxd2820r_init_t(fe); @@ -278,7 +268,8 @@ static int cxd2820r_set_frontend(struct dvb_frontend *fe) goto err; break; default: - dbg("%s: error state=%d", __func__, fe->dtv_property_cache.delivery_system); + dev_dbg(&priv->i2c->dev, "%s: error state=%d\n", __func__, + fe->dtv_property_cache.delivery_system); ret = -EINVAL; break; } @@ -287,9 +278,12 @@ err: } static int cxd2820r_read_status(struct dvb_frontend *fe, fe_status_t *status) { + struct cxd2820r_priv *priv = fe->demodulator_priv; int ret; - dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system); + dev_dbg(&priv->i2c->dev, "%s: delsys=%d\n", __func__, + fe->dtv_property_cache.delivery_system); + switch (fe->dtv_property_cache.delivery_system) { case SYS_DVBT: ret = cxd2820r_read_status_t(fe, status); @@ -312,7 +306,8 @@ static int cxd2820r_get_frontend(struct dvb_frontend *fe) struct cxd2820r_priv *priv = fe->demodulator_priv; int ret; - dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system); + dev_dbg(&priv->i2c->dev, "%s: delsys=%d\n", __func__, + fe->dtv_property_cache.delivery_system); if (priv->delivery_system == SYS_UNDEFINED) return 0; @@ -336,9 +331,12 @@ static int cxd2820r_get_frontend(struct dvb_frontend *fe) static int cxd2820r_read_ber(struct dvb_frontend *fe, u32 *ber) { + struct cxd2820r_priv *priv = fe->demodulator_priv; int ret; - dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system); + dev_dbg(&priv->i2c->dev, "%s: delsys=%d\n", __func__, + fe->dtv_property_cache.delivery_system); + switch (fe->dtv_property_cache.delivery_system) { case SYS_DVBT: ret = cxd2820r_read_ber_t(fe, ber); @@ -358,9 +356,12 @@ static int cxd2820r_read_ber(struct dvb_frontend *fe, u32 *ber) static int cxd2820r_read_signal_strength(struct dvb_frontend *fe, u16 *strength) { + struct cxd2820r_priv *priv = fe->demodulator_priv; int ret; - dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system); + dev_dbg(&priv->i2c->dev, "%s: delsys=%d\n", __func__, + fe->dtv_property_cache.delivery_system); + switch (fe->dtv_property_cache.delivery_system) { case SYS_DVBT: ret = cxd2820r_read_signal_strength_t(fe, strength); @@ -380,9 +381,12 @@ static int cxd2820r_read_signal_strength(struct dvb_frontend *fe, u16 *strength) static int cxd2820r_read_snr(struct dvb_frontend *fe, u16 *snr) { + struct cxd2820r_priv *priv = fe->demodulator_priv; int ret; - dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system); + dev_dbg(&priv->i2c->dev, "%s: delsys=%d\n", __func__, + fe->dtv_property_cache.delivery_system); + switch (fe->dtv_property_cache.delivery_system) { case SYS_DVBT: ret = cxd2820r_read_snr_t(fe, snr); @@ -402,9 +406,12 @@ static int cxd2820r_read_snr(struct dvb_frontend *fe, u16 *snr) static int cxd2820r_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) { + struct cxd2820r_priv *priv = fe->demodulator_priv; int ret; - dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system); + dev_dbg(&priv->i2c->dev, "%s: delsys=%d\n", __func__, + fe->dtv_property_cache.delivery_system); + switch (fe->dtv_property_cache.delivery_system) { case SYS_DVBT: ret = cxd2820r_read_ucblocks_t(fe, ucblocks); @@ -429,9 +436,12 @@ static int cxd2820r_init(struct dvb_frontend *fe) static int cxd2820r_sleep(struct dvb_frontend *fe) { + struct cxd2820r_priv *priv = fe->demodulator_priv; int ret; - dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system); + dev_dbg(&priv->i2c->dev, "%s: delsys=%d\n", __func__, + fe->dtv_property_cache.delivery_system); + switch (fe->dtv_property_cache.delivery_system) { case SYS_DVBT: ret = cxd2820r_sleep_t(fe); @@ -452,9 +462,12 @@ static int cxd2820r_sleep(struct dvb_frontend *fe) static int cxd2820r_get_tune_settings(struct dvb_frontend *fe, struct dvb_frontend_tune_settings *s) { + struct cxd2820r_priv *priv = fe->demodulator_priv; int ret; - dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system); + dev_dbg(&priv->i2c->dev, "%s: delsys=%d\n", __func__, + fe->dtv_property_cache.delivery_system); + switch (fe->dtv_property_cache.delivery_system) { case SYS_DVBT: ret = cxd2820r_get_tune_settings_t(fe, s); @@ -478,7 +491,9 @@ static enum dvbfe_search cxd2820r_search(struct dvb_frontend *fe) struct dtv_frontend_properties *c = &fe->dtv_property_cache; int ret, i; fe_status_t status = 0; - dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system); + + dev_dbg(&priv->i2c->dev, "%s: delsys=%d\n", __func__, + fe->dtv_property_cache.delivery_system); /* switch between DVB-T and DVB-T2 when tune fails */ if (priv->last_tune_failed) { @@ -520,7 +535,7 @@ static enum dvbfe_search cxd2820r_search(struct dvb_frontend *fe) /* wait frontend lock */ for (; i > 0; i--) { - dbg("%s: LOOP=%d", __func__, i); + dev_dbg(&priv->i2c->dev, "%s: loop=%d\n", __func__, i); msleep(50); ret = cxd2820r_read_status(fe, &status); if (ret) @@ -540,7 +555,7 @@ static enum dvbfe_search cxd2820r_search(struct dvb_frontend *fe) } error: - dbg("%s: failed:%d", __func__, ret); + dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); return DVBFE_ALGO_SEARCH_ERROR; } @@ -552,8 +567,19 @@ static int cxd2820r_get_frontend_algo(struct dvb_frontend *fe) static void cxd2820r_release(struct dvb_frontend *fe) { struct cxd2820r_priv *priv = fe->demodulator_priv; - dbg("%s", __func__); + int uninitialized_var(ret); /* silence compiler warning */ + dev_dbg(&priv->i2c->dev, "%s\n", __func__); + +#ifdef CONFIG_GPIOLIB + /* remove GPIOs */ + if (priv->gpio_chip.label) { + ret = gpiochip_remove(&priv->gpio_chip); + if (ret) + dev_err(&priv->i2c->dev, "%s: gpiochip_remove() " \ + "failed=%d\n", KBUILD_MODNAME, ret); + } +#endif kfree(priv); return; } @@ -561,12 +587,56 @@ static void cxd2820r_release(struct dvb_frontend *fe) static int cxd2820r_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) { struct cxd2820r_priv *priv = fe->demodulator_priv; - dbg("%s: %d", __func__, enable); + + dev_dbg(&priv->i2c->dev, "%s: %d\n", __func__, enable); /* Bit 0 of reg 0xdb in bank 0x00 controls I2C repeater */ return cxd2820r_wr_reg_mask(priv, 0xdb, enable ? 1 : 0, 0x1); } +#ifdef CONFIG_GPIOLIB +static int cxd2820r_gpio_direction_output(struct gpio_chip *chip, unsigned nr, + int val) +{ + struct cxd2820r_priv *priv = + container_of(chip, struct cxd2820r_priv, gpio_chip); + u8 gpio[GPIO_COUNT]; + + dev_dbg(&priv->i2c->dev, "%s: nr=%d val=%d\n", __func__, nr, val); + + memcpy(gpio, priv->gpio, sizeof(gpio)); + gpio[nr] = CXD2820R_GPIO_E | CXD2820R_GPIO_O | (val << 2); + + return cxd2820r_gpio(&priv->fe, gpio); +} + +static void cxd2820r_gpio_set(struct gpio_chip *chip, unsigned nr, int val) +{ + struct cxd2820r_priv *priv = + container_of(chip, struct cxd2820r_priv, gpio_chip); + u8 gpio[GPIO_COUNT]; + + dev_dbg(&priv->i2c->dev, "%s: nr=%d val=%d\n", __func__, nr, val); + + memcpy(gpio, priv->gpio, sizeof(gpio)); + gpio[nr] = CXD2820R_GPIO_E | CXD2820R_GPIO_O | (val << 2); + + (void) cxd2820r_gpio(&priv->fe, gpio); + + return; +} + +static int cxd2820r_gpio_get(struct gpio_chip *chip, unsigned nr) +{ + struct cxd2820r_priv *priv = + container_of(chip, struct cxd2820r_priv, gpio_chip); + + dev_dbg(&priv->i2c->dev, "%s: nr=%d\n", __func__, nr); + + return (priv->gpio[nr] >> 2) & 0x01; +} +#endif + static const struct dvb_frontend_ops cxd2820r_ops = { .delsys = { SYS_DVBT, SYS_DVBT2, SYS_DVBC_ANNEX_A }, /* default: DVB-T/T2 */ @@ -613,29 +683,70 @@ static const struct dvb_frontend_ops cxd2820r_ops = { }; struct dvb_frontend *cxd2820r_attach(const struct cxd2820r_config *cfg, - struct i2c_adapter *i2c) + struct i2c_adapter *i2c, int *gpio_chip_base +) { - struct cxd2820r_priv *priv = NULL; + struct cxd2820r_priv *priv; int ret; - u8 tmp; + u8 tmp, gpio[GPIO_COUNT]; - priv = kzalloc(sizeof (struct cxd2820r_priv), GFP_KERNEL); - if (!priv) + priv = kzalloc(sizeof(struct cxd2820r_priv), GFP_KERNEL); + if (!priv) { + ret = -ENOMEM; + dev_err(&i2c->dev, "%s: kzalloc() failed\n", + KBUILD_MODNAME); goto error; + } priv->i2c = i2c; - memcpy(&priv->cfg, cfg, sizeof (struct cxd2820r_config)); + memcpy(&priv->cfg, cfg, sizeof(struct cxd2820r_config)); + memcpy(&priv->fe.ops, &cxd2820r_ops, sizeof(struct dvb_frontend_ops)); + priv->fe.demodulator_priv = priv; priv->bank[0] = priv->bank[1] = 0xff; ret = cxd2820r_rd_reg(priv, 0x000fd, &tmp); - dbg("%s: chip id=%02x", __func__, tmp); + dev_dbg(&priv->i2c->dev, "%s: chip id=%02x\n", __func__, tmp); if (ret || tmp != 0xe1) goto error; - memcpy(&priv->fe.ops, &cxd2820r_ops, sizeof (struct dvb_frontend_ops)); - priv->fe.demodulator_priv = priv; + if (gpio_chip_base) { +#ifdef CONFIG_GPIOLIB + /* add GPIOs */ + priv->gpio_chip.label = KBUILD_MODNAME; + priv->gpio_chip.dev = &priv->i2c->dev; + priv->gpio_chip.owner = THIS_MODULE; + priv->gpio_chip.direction_output = + cxd2820r_gpio_direction_output; + priv->gpio_chip.set = cxd2820r_gpio_set; + priv->gpio_chip.get = cxd2820r_gpio_get; + priv->gpio_chip.base = -1; /* dynamic allocation */ + priv->gpio_chip.ngpio = GPIO_COUNT; + priv->gpio_chip.can_sleep = 1; + ret = gpiochip_add(&priv->gpio_chip); + if (ret) + goto error; + + dev_dbg(&priv->i2c->dev, "%s: gpio_chip.base=%d\n", __func__, + priv->gpio_chip.base); + + *gpio_chip_base = priv->gpio_chip.base; +#else + /* + * Use static GPIO configuration if GPIOLIB is undefined. + * This is fallback condition. + */ + gpio[0] = (*gpio_chip_base >> 0) & 0x07; + gpio[1] = (*gpio_chip_base >> 3) & 0x07; + gpio[2] = 0; + ret = cxd2820r_gpio(&priv->fe, gpio); + if (ret) + goto error; +#endif + } + return &priv->fe; error: + dev_dbg(&i2c->dev, "%s: failed=%d\n", __func__, ret); kfree(priv); return NULL; } diff --git a/drivers/media/dvb/frontends/cxd2820r_priv.h b/drivers/media/dvb-frontends/cxd2820r_priv.h index 9a9822cad9cd..7ff5f60c83e1 100644 --- a/drivers/media/dvb/frontends/cxd2820r_priv.h +++ b/drivers/media/dvb-frontends/cxd2820r_priv.h @@ -26,19 +26,7 @@ #include "dvb_frontend.h" #include "dvb_math.h" #include "cxd2820r.h" - -#define LOG_PREFIX "cxd2820r" - -#undef dbg -#define dbg(f, arg...) \ - if (cxd2820r_debug) \ - printk(KERN_INFO LOG_PREFIX": " f "\n" , ## arg) -#undef err -#define err(f, arg...) printk(KERN_ERR LOG_PREFIX": " f "\n" , ## arg) -#undef info -#define info(f, arg...) printk(KERN_INFO LOG_PREFIX": " f "\n" , ## arg) -#undef warn -#define warn(f, arg...) printk(KERN_WARNING LOG_PREFIX": " f "\n" , ## arg) +#include <linux/gpio.h> struct reg_val_mask { u32 reg; @@ -54,7 +42,11 @@ struct cxd2820r_priv { bool ber_running; u8 bank[2]; - u8 gpio[3]; +#define GPIO_COUNT 3 + u8 gpio[GPIO_COUNT]; +#ifdef CONFIG_GPIOLIB + struct gpio_chip gpio_chip; +#endif fe_delivery_system_t delivery_system; bool last_tune_failed; /* for switch between T and T2 tune */ @@ -64,7 +56,7 @@ struct cxd2820r_priv { extern int cxd2820r_debug; -int cxd2820r_gpio(struct dvb_frontend *fe); +int cxd2820r_gpio(struct dvb_frontend *fe, u8 *gpio); int cxd2820r_wr_reg_mask(struct cxd2820r_priv *priv, u32 reg, u8 val, u8 mask); diff --git a/drivers/media/dvb/frontends/cxd2820r_t.c b/drivers/media/dvb-frontends/cxd2820r_t.c index 1a026239cdcc..fa184ca2dd68 100644 --- a/drivers/media/dvb/frontends/cxd2820r_t.c +++ b/drivers/media/dvb-frontends/cxd2820r_t.c @@ -54,7 +54,8 @@ int cxd2820r_set_frontend_t(struct dvb_frontend *fe) { 0x00427, 0x41, 0xff }, }; - dbg("%s: RF=%d BW=%d", __func__, c->frequency, c->bandwidth_hz); + dev_dbg(&priv->i2c->dev, "%s: frequency=%d bandwidth_hz=%d\n", __func__, + c->frequency, c->bandwidth_hz); switch (c->bandwidth_hz) { case 6000000: @@ -73,11 +74,6 @@ int cxd2820r_set_frontend_t(struct dvb_frontend *fe) return -EINVAL; } - /* update GPIOs */ - ret = cxd2820r_gpio(fe); - if (ret) - goto error; - /* program tuner */ if (fe->ops.tuner_ops.set_params) fe->ops.tuner_ops.set_params(fe); @@ -102,7 +98,7 @@ int cxd2820r_set_frontend_t(struct dvb_frontend *fe) } else if_freq = 0; - dbg("%s: if_freq=%d", __func__, if_freq); + dev_dbg(&priv->i2c->dev, "%s: if_freq=%d\n", __func__, if_freq); num = if_freq / 1000; /* Hz => kHz */ num *= 0x1000000; @@ -137,7 +133,7 @@ int cxd2820r_set_frontend_t(struct dvb_frontend *fe) return ret; error: - dbg("%s: failed:%d", __func__, ret); + dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); return ret; } @@ -254,7 +250,7 @@ int cxd2820r_get_frontend_t(struct dvb_frontend *fe) return ret; error: - dbg("%s: failed:%d", __func__, ret); + dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); return ret; } @@ -288,7 +284,7 @@ int cxd2820r_read_ber_t(struct dvb_frontend *fe, u32 *ber) return ret; error: - dbg("%s: failed:%d", __func__, ret); + dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); return ret; } @@ -312,7 +308,7 @@ int cxd2820r_read_signal_strength_t(struct dvb_frontend *fe, return ret; error: - dbg("%s: failed:%d", __func__, ret); + dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); return ret; } @@ -336,11 +332,12 @@ int cxd2820r_read_snr_t(struct dvb_frontend *fe, u16 *snr) else *snr = 0; - dbg("%s: dBx10=%d val=%04x", __func__, *snr, tmp); + dev_dbg(&priv->i2c->dev, "%s: dBx10=%d val=%04x\n", __func__, *snr, + tmp); return ret; error: - dbg("%s: failed:%d", __func__, ret); + dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); return ret; } @@ -389,12 +386,11 @@ int cxd2820r_read_status_t(struct dvb_frontend *fe, fe_status_t *status) } } - dbg("%s: lock=%02x %02x %02x %02x", __func__, - buf[0], buf[1], buf[2], buf[3]); + dev_dbg(&priv->i2c->dev, "%s: lock=%*ph\n", __func__, 4, buf); return ret; error: - dbg("%s: failed:%d", __func__, ret); + dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); return ret; } @@ -409,7 +405,7 @@ int cxd2820r_init_t(struct dvb_frontend *fe) return ret; error: - dbg("%s: failed:%d", __func__, ret); + dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); return ret; } @@ -425,7 +421,7 @@ int cxd2820r_sleep_t(struct dvb_frontend *fe) { 0x00080, 0x00, 0xff }, }; - dbg("%s", __func__); + dev_dbg(&priv->i2c->dev, "%s\n", __func__); priv->delivery_system = SYS_UNDEFINED; @@ -438,7 +434,7 @@ int cxd2820r_sleep_t(struct dvb_frontend *fe) return ret; error: - dbg("%s: failed:%d", __func__, ret); + dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); return ret; } diff --git a/drivers/media/dvb/frontends/cxd2820r_t2.c b/drivers/media/dvb-frontends/cxd2820r_t2.c index 3a5759e0d235..e82d82a7a2eb 100644 --- a/drivers/media/dvb/frontends/cxd2820r_t2.c +++ b/drivers/media/dvb-frontends/cxd2820r_t2.c @@ -68,7 +68,8 @@ int cxd2820r_set_frontend_t2(struct dvb_frontend *fe) { 0x027ef, 0x10, 0x18 }, }; - dbg("%s: RF=%d BW=%d", __func__, c->frequency, c->bandwidth_hz); + dev_dbg(&priv->i2c->dev, "%s: frequency=%d bandwidth_hz=%d\n", __func__, + c->frequency, c->bandwidth_hz); switch (c->bandwidth_hz) { case 5000000: @@ -91,11 +92,6 @@ int cxd2820r_set_frontend_t2(struct dvb_frontend *fe) return -EINVAL; } - /* update GPIOs */ - ret = cxd2820r_gpio(fe); - if (ret) - goto error; - /* program tuner */ if (fe->ops.tuner_ops.set_params) fe->ops.tuner_ops.set_params(fe); @@ -119,7 +115,7 @@ int cxd2820r_set_frontend_t2(struct dvb_frontend *fe) } else if_freq = 0; - dbg("%s: if_freq=%d", __func__, if_freq); + dev_dbg(&priv->i2c->dev, "%s: if_freq=%d\n", __func__, if_freq); num = if_freq / 1000; /* Hz => kHz */ num *= 0x1000000; @@ -150,7 +146,7 @@ int cxd2820r_set_frontend_t2(struct dvb_frontend *fe) return ret; error: - dbg("%s: failed:%d", __func__, ret); + dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); return ret; } @@ -266,7 +262,7 @@ int cxd2820r_get_frontend_t2(struct dvb_frontend *fe) return ret; error: - dbg("%s: failed:%d", __func__, ret); + dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); return ret; } @@ -291,11 +287,11 @@ int cxd2820r_read_status_t2(struct dvb_frontend *fe, fe_status_t *status) } } - dbg("%s: lock=%02x", __func__, buf[0]); + dev_dbg(&priv->i2c->dev, "%s: lock=%02x\n", __func__, buf[0]); return ret; error: - dbg("%s: failed:%d", __func__, ret); + dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); return ret; } @@ -322,7 +318,7 @@ int cxd2820r_read_ber_t2(struct dvb_frontend *fe, u32 *ber) return ret; error: - dbg("%s: failed:%d", __func__, ret); + dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); return ret; } @@ -346,7 +342,7 @@ int cxd2820r_read_signal_strength_t2(struct dvb_frontend *fe, return ret; error: - dbg("%s: failed:%d", __func__, ret); + dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); return ret; } @@ -370,11 +366,12 @@ int cxd2820r_read_snr_t2(struct dvb_frontend *fe, u16 *snr) else *snr = 0; - dbg("%s: dBx10=%d val=%04x", __func__, *snr, tmp); + dev_dbg(&priv->i2c->dev, "%s: dBx10=%d val=%04x\n", __func__, *snr, + tmp); return ret; error: - dbg("%s: failed:%d", __func__, ret); + dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); return ret; } @@ -398,7 +395,7 @@ int cxd2820r_sleep_t2(struct dvb_frontend *fe) { 0x00080, 0x00, 0xff }, }; - dbg("%s", __func__); + dev_dbg(&priv->i2c->dev, "%s\n", __func__); for (i = 0; i < ARRAY_SIZE(tab); i++) { ret = cxd2820r_wr_reg_mask(priv, tab[i].reg, tab[i].val, @@ -411,7 +408,7 @@ int cxd2820r_sleep_t2(struct dvb_frontend *fe) return ret; error: - dbg("%s: failed:%d", __func__, ret); + dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); return ret; } diff --git a/drivers/media/dvb/frontends/dib0070.c b/drivers/media/dvb-frontends/dib0070.c index 3b024bfe980a..3b024bfe980a 100644 --- a/drivers/media/dvb/frontends/dib0070.c +++ b/drivers/media/dvb-frontends/dib0070.c diff --git a/drivers/media/dvb/frontends/dib0070.h b/drivers/media/dvb-frontends/dib0070.h index 45c31fae3967..45c31fae3967 100644 --- a/drivers/media/dvb/frontends/dib0070.h +++ b/drivers/media/dvb-frontends/dib0070.h diff --git a/drivers/media/dvb/frontends/dib0090.c b/drivers/media/dvb-frontends/dib0090.c index d9fe60b4be48..d9fe60b4be48 100644 --- a/drivers/media/dvb/frontends/dib0090.c +++ b/drivers/media/dvb-frontends/dib0090.c diff --git a/drivers/media/dvb/frontends/dib0090.h b/drivers/media/dvb-frontends/dib0090.h index 781dc49de45b..781dc49de45b 100644 --- a/drivers/media/dvb/frontends/dib0090.h +++ b/drivers/media/dvb-frontends/dib0090.h diff --git a/drivers/media/dvb/frontends/dib3000.h b/drivers/media/dvb-frontends/dib3000.h index 404f63a6f26b..404f63a6f26b 100644 --- a/drivers/media/dvb/frontends/dib3000.h +++ b/drivers/media/dvb-frontends/dib3000.h diff --git a/drivers/media/dvb/frontends/dib3000mb.c b/drivers/media/dvb-frontends/dib3000mb.c index af91e0c92339..af91e0c92339 100644 --- a/drivers/media/dvb/frontends/dib3000mb.c +++ b/drivers/media/dvb-frontends/dib3000mb.c diff --git a/drivers/media/dvb/frontends/dib3000mb_priv.h b/drivers/media/dvb-frontends/dib3000mb_priv.h index 9dc235aa44b7..9dc235aa44b7 100644 --- a/drivers/media/dvb/frontends/dib3000mb_priv.h +++ b/drivers/media/dvb-frontends/dib3000mb_priv.h diff --git a/drivers/media/dvb/frontends/dib3000mc.c b/drivers/media/dvb-frontends/dib3000mc.c index ffad181a9692..ffad181a9692 100644 --- a/drivers/media/dvb/frontends/dib3000mc.c +++ b/drivers/media/dvb-frontends/dib3000mc.c diff --git a/drivers/media/dvb/frontends/dib3000mc.h b/drivers/media/dvb-frontends/dib3000mc.h index d75ffad2d752..d75ffad2d752 100644 --- a/drivers/media/dvb/frontends/dib3000mc.h +++ b/drivers/media/dvb-frontends/dib3000mc.h diff --git a/drivers/media/dvb/frontends/dib7000m.c b/drivers/media/dvb-frontends/dib7000m.c index 148bf79236fb..148bf79236fb 100644 --- a/drivers/media/dvb/frontends/dib7000m.c +++ b/drivers/media/dvb-frontends/dib7000m.c diff --git a/drivers/media/dvb/frontends/dib7000m.h b/drivers/media/dvb-frontends/dib7000m.h index 81fcf2241c64..81fcf2241c64 100644 --- a/drivers/media/dvb/frontends/dib7000m.h +++ b/drivers/media/dvb-frontends/dib7000m.h diff --git a/drivers/media/dvb/frontends/dib7000p.c b/drivers/media/dvb-frontends/dib7000p.c index 3e1eefada0e8..3e1eefada0e8 100644 --- a/drivers/media/dvb/frontends/dib7000p.c +++ b/drivers/media/dvb-frontends/dib7000p.c diff --git a/drivers/media/dvb/frontends/dib7000p.h b/drivers/media/dvb-frontends/dib7000p.h index b61b03a6e1ed..b61b03a6e1ed 100644 --- a/drivers/media/dvb/frontends/dib7000p.h +++ b/drivers/media/dvb-frontends/dib7000p.h diff --git a/drivers/media/dvb/frontends/dib8000.c b/drivers/media/dvb-frontends/dib8000.c index 1f3bcb5a1de8..1f3bcb5a1de8 100644 --- a/drivers/media/dvb/frontends/dib8000.c +++ b/drivers/media/dvb-frontends/dib8000.c diff --git a/drivers/media/dvb/frontends/dib8000.h b/drivers/media/dvb-frontends/dib8000.h index 39591bb172c1..39591bb172c1 100644 --- a/drivers/media/dvb/frontends/dib8000.h +++ b/drivers/media/dvb-frontends/dib8000.h diff --git a/drivers/media/dvb/frontends/dib9000.c b/drivers/media/dvb-frontends/dib9000.c index 6201c59a78dd..6201c59a78dd 100644 --- a/drivers/media/dvb/frontends/dib9000.c +++ b/drivers/media/dvb-frontends/dib9000.c diff --git a/drivers/media/dvb/frontends/dib9000.h b/drivers/media/dvb-frontends/dib9000.h index b5781a48034c..b5781a48034c 100644 --- a/drivers/media/dvb/frontends/dib9000.h +++ b/drivers/media/dvb-frontends/dib9000.h diff --git a/drivers/media/dvb/frontends/dibx000_common.c b/drivers/media/dvb-frontends/dibx000_common.c index 43be7238311e..43be7238311e 100644 --- a/drivers/media/dvb/frontends/dibx000_common.c +++ b/drivers/media/dvb-frontends/dibx000_common.c diff --git a/drivers/media/dvb/frontends/dibx000_common.h b/drivers/media/dvb-frontends/dibx000_common.h index 5f484881d7b1..5f484881d7b1 100644 --- a/drivers/media/dvb/frontends/dibx000_common.h +++ b/drivers/media/dvb-frontends/dibx000_common.h diff --git a/drivers/media/dvb/frontends/drxd.h b/drivers/media/dvb-frontends/drxd.h index 216c8c3702f8..216c8c3702f8 100644 --- a/drivers/media/dvb/frontends/drxd.h +++ b/drivers/media/dvb-frontends/drxd.h diff --git a/drivers/media/dvb/frontends/drxd_firm.c b/drivers/media/dvb-frontends/drxd_firm.c index 5418b0b1dadc..5418b0b1dadc 100644 --- a/drivers/media/dvb/frontends/drxd_firm.c +++ b/drivers/media/dvb-frontends/drxd_firm.c diff --git a/drivers/media/dvb/frontends/drxd_firm.h b/drivers/media/dvb-frontends/drxd_firm.h index 41597e89941c..41597e89941c 100644 --- a/drivers/media/dvb/frontends/drxd_firm.h +++ b/drivers/media/dvb-frontends/drxd_firm.h diff --git a/drivers/media/dvb/frontends/drxd_hard.c b/drivers/media/dvb-frontends/drxd_hard.c index f380eb43e9d5..f380eb43e9d5 100644 --- a/drivers/media/dvb/frontends/drxd_hard.c +++ b/drivers/media/dvb-frontends/drxd_hard.c diff --git a/drivers/media/dvb/frontends/drxd_map_firm.h b/drivers/media/dvb-frontends/drxd_map_firm.h index 6bc553abf215..6bc553abf215 100644 --- a/drivers/media/dvb/frontends/drxd_map_firm.h +++ b/drivers/media/dvb-frontends/drxd_map_firm.h diff --git a/drivers/media/dvb/frontends/drxk.h b/drivers/media/dvb-frontends/drxk.h index d615d7d055a2..94fecfbf14c1 100644 --- a/drivers/media/dvb/frontends/drxk.h +++ b/drivers/media/dvb-frontends/drxk.h @@ -28,6 +28,7 @@ * A value of 0 (default) or lower indicates that * the correct number of parameters will be * automatically detected. + * @load_firmware_sync: Force the firmware load to be synchronous. * * On the *_gpio vars, bit 0 is UIO-1, bit 1 is UIO-2 and bit 2 is * UIO-3. @@ -39,6 +40,7 @@ struct drxk_config { bool parallel_ts; bool dynamic_clk; bool enable_merr_cfg; + bool load_firmware_sync; bool antenna_dvbt; u16 antenna_gpio; diff --git a/drivers/media/dvb/frontends/drxk_hard.c b/drivers/media/dvb-frontends/drxk_hard.c index 1ab8154542da..8b4c6d5f8f36 100644 --- a/drivers/media/dvb/frontends/drxk_hard.c +++ b/drivers/media/dvb-frontends/drxk_hard.c @@ -6609,15 +6609,25 @@ struct dvb_frontend *drxk_attach(const struct drxk_config *config, /* Load firmware and initialize DRX-K */ if (state->microcode_name) { - status = request_firmware_nowait(THIS_MODULE, 1, + if (config->load_firmware_sync) { + const struct firmware *fw = NULL; + + status = request_firmware(&fw, state->microcode_name, + state->i2c->dev.parent); + if (status < 0) + fw = NULL; + load_firmware_cb(fw, state); + } else { + status = request_firmware_nowait(THIS_MODULE, 1, state->microcode_name, state->i2c->dev.parent, GFP_KERNEL, state, load_firmware_cb); - if (status < 0) { - printk(KERN_ERR - "drxk: failed to request a firmware\n"); - return NULL; + if (status < 0) { + printk(KERN_ERR + "drxk: failed to request a firmware\n"); + return NULL; + } } } else if (init_drxk(state) < 0) goto error; diff --git a/drivers/media/dvb/frontends/drxk_hard.h b/drivers/media/dvb-frontends/drxk_hard.h index 6bb9fc4a7b96..6bb9fc4a7b96 100644 --- a/drivers/media/dvb/frontends/drxk_hard.h +++ b/drivers/media/dvb-frontends/drxk_hard.h diff --git a/drivers/media/dvb/frontends/drxk_map.h b/drivers/media/dvb-frontends/drxk_map.h index 23e16c12f234..23e16c12f234 100644 --- a/drivers/media/dvb/frontends/drxk_map.h +++ b/drivers/media/dvb-frontends/drxk_map.h diff --git a/drivers/media/dvb/frontends/ds3000.c b/drivers/media/dvb-frontends/ds3000.c index 4c8ac2657c4a..4c8ac2657c4a 100644 --- a/drivers/media/dvb/frontends/ds3000.c +++ b/drivers/media/dvb-frontends/ds3000.c diff --git a/drivers/media/dvb/frontends/ds3000.h b/drivers/media/dvb-frontends/ds3000.h index 1b736888ea37..1b736888ea37 100644 --- a/drivers/media/dvb/frontends/ds3000.h +++ b/drivers/media/dvb-frontends/ds3000.h diff --git a/drivers/media/dvb/frontends/dvb-pll.c b/drivers/media/dvb-frontends/dvb-pll.c index 1ab34838221c..6d8fe8843237 100644 --- a/drivers/media/dvb/frontends/dvb-pll.c +++ b/drivers/media/dvb-frontends/dvb-pll.c @@ -116,6 +116,31 @@ static struct dvb_pll_desc dvb_pll_thomson_dtt759x = { }, }; +static void thomson_dtt7520x_bw(struct dvb_frontend *fe, u8 *buf) +{ + u32 bw = fe->dtv_property_cache.bandwidth_hz; + if (bw == 8000000) + buf[3] ^= 0x10; +} + +static struct dvb_pll_desc dvb_pll_thomson_dtt7520x = { + .name = "Thomson dtt7520x", + .min = 185000000, + .max = 900000000, + .set = thomson_dtt7520x_bw, + .iffreq = 36166667, + .count = 7, + .entries = { + { 305000000, 166667, 0xb4, 0x12 }, + { 405000000, 166667, 0xbc, 0x12 }, + { 445000000, 166667, 0xbc, 0x12 }, + { 465000000, 166667, 0xf4, 0x18 }, + { 735000000, 166667, 0xfc, 0x18 }, + { 835000000, 166667, 0xbc, 0x18 }, + { 999999999, 166667, 0xfc, 0x18 }, + }, +}; + static struct dvb_pll_desc dvb_pll_lg_z201 = { .name = "LG z201", .min = 174000000, @@ -513,6 +538,7 @@ static struct dvb_pll_desc *pll_list[] = { [DVB_PLL_UNDEFINED] = NULL, [DVB_PLL_THOMSON_DTT7579] = &dvb_pll_thomson_dtt7579, [DVB_PLL_THOMSON_DTT759X] = &dvb_pll_thomson_dtt759x, + [DVB_PLL_THOMSON_DTT7520X] = &dvb_pll_thomson_dtt7520x, [DVB_PLL_LG_Z201] = &dvb_pll_lg_z201, [DVB_PLL_UNKNOWN_1] = &dvb_pll_unknown_1, [DVB_PLL_TUA6010XS] = &dvb_pll_tua6010xs, diff --git a/drivers/media/dvb/frontends/dvb-pll.h b/drivers/media/dvb-frontends/dvb-pll.h index 086964344c38..4de754f76ce9 100644 --- a/drivers/media/dvb/frontends/dvb-pll.h +++ b/drivers/media/dvb-frontends/dvb-pll.h @@ -27,6 +27,7 @@ #define DVB_PLL_SAMSUNG_TBDU18132 16 #define DVB_PLL_SAMSUNG_TBMU24112 17 #define DVB_PLL_TDEE4 18 +#define DVB_PLL_THOMSON_DTT7520X 19 /** * Attach a dvb-pll to the supplied frontend structure. diff --git a/drivers/media/dvb/frontends/dvb_dummy_fe.c b/drivers/media/dvb-frontends/dvb_dummy_fe.c index dcfc902c8678..dcfc902c8678 100644 --- a/drivers/media/dvb/frontends/dvb_dummy_fe.c +++ b/drivers/media/dvb-frontends/dvb_dummy_fe.c diff --git a/drivers/media/dvb/frontends/dvb_dummy_fe.h b/drivers/media/dvb-frontends/dvb_dummy_fe.h index 1fcb987d6386..1fcb987d6386 100644 --- a/drivers/media/dvb/frontends/dvb_dummy_fe.h +++ b/drivers/media/dvb-frontends/dvb_dummy_fe.h diff --git a/drivers/media/dvb/frontends/ec100.c b/drivers/media/dvb-frontends/ec100.c index c56fddbf53b7..9d424809d06b 100644 --- a/drivers/media/dvb/frontends/ec100.c +++ b/drivers/media/dvb-frontends/ec100.c @@ -20,13 +20,8 @@ */ #include "dvb_frontend.h" -#include "ec100_priv.h" #include "ec100.h" -int ec100_debug; -module_param_named(debug, ec100_debug, int, 0644); -MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); - struct ec100_state { struct i2c_adapter *i2c; struct dvb_frontend frontend; @@ -38,23 +33,33 @@ struct ec100_state { /* write single register */ static int ec100_write_reg(struct ec100_state *state, u8 reg, u8 val) { + int ret; u8 buf[2] = {reg, val}; - struct i2c_msg msg = { - .addr = state->config.demod_address, - .flags = 0, - .len = 2, - .buf = buf}; - - if (i2c_transfer(state->i2c, &msg, 1) != 1) { - warn("I2C write failed reg:%02x", reg); - return -EREMOTEIO; + struct i2c_msg msg[1] = { + { + .addr = state->config.demod_address, + .flags = 0, + .len = sizeof(buf), + .buf = buf, + } + }; + + ret = i2c_transfer(state->i2c, msg, 1); + if (ret == 1) { + ret = 0; + } else { + dev_warn(&state->i2c->dev, "%s: i2c wr failed=%d reg=%02x\n", + KBUILD_MODNAME, ret, reg); + ret = -EREMOTEIO; } - return 0; + + return ret; } /* read single register */ static int ec100_read_reg(struct ec100_state *state, u8 reg, u8 *val) { + int ret; struct i2c_msg msg[2] = { { .addr = state->config.demod_address, @@ -69,11 +74,16 @@ static int ec100_read_reg(struct ec100_state *state, u8 reg, u8 *val) } }; - if (i2c_transfer(state->i2c, msg, 2) != 2) { - warn("I2C read failed reg:%02x", reg); - return -EREMOTEIO; + ret = i2c_transfer(state->i2c, msg, 2); + if (ret == 2) { + ret = 0; + } else { + dev_warn(&state->i2c->dev, "%s: i2c rd failed=%d reg=%02x\n", + KBUILD_MODNAME, ret, reg); + ret = -EREMOTEIO; } - return 0; + + return ret; } static int ec100_set_frontend(struct dvb_frontend *fe) @@ -83,8 +93,8 @@ static int ec100_set_frontend(struct dvb_frontend *fe) int ret; u8 tmp, tmp2; - deb_info("%s: freq:%d bw:%d\n", __func__, c->frequency, - c->bandwidth_hz); + dev_dbg(&state->i2c->dev, "%s: frequency=%d bandwidth_hz=%d\n", + __func__, c->frequency, c->bandwidth_hz); /* program tuner */ if (fe->ops.tuner_ops.set_params) @@ -150,7 +160,7 @@ static int ec100_set_frontend(struct dvb_frontend *fe) return ret; error: - deb_info("%s: failed:%d\n", __func__, ret); + dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret); return ret; } @@ -196,7 +206,7 @@ static int ec100_read_status(struct dvb_frontend *fe, fe_status_t *status) return ret; error: - deb_info("%s: failed:%d\n", __func__, ret); + dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret); return ret; } @@ -228,7 +238,7 @@ static int ec100_read_ber(struct dvb_frontend *fe, u32 *ber) return ret; error: - deb_info("%s: failed:%d\n", __func__, ret); + dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret); return ret; } @@ -248,7 +258,7 @@ static int ec100_read_signal_strength(struct dvb_frontend *fe, u16 *strength) return ret; error: - deb_info("%s: failed:%d\n", __func__, ret); + dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret); return ret; } diff --git a/drivers/media/dvb/frontends/ec100.h b/drivers/media/dvb-frontends/ec100.h index ee8e52417958..b8479719d7f1 100644 --- a/drivers/media/dvb/frontends/ec100.h +++ b/drivers/media/dvb-frontends/ec100.h @@ -38,7 +38,7 @@ extern struct dvb_frontend *ec100_attach(const struct ec100_config *config, static inline struct dvb_frontend *ec100_attach( const struct ec100_config *config, struct i2c_adapter *i2c) { - printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); + pr_warn("%s: driver disabled by Kconfig\n", __func__); return NULL; } #endif diff --git a/drivers/media/dvb/frontends/eds1547.h b/drivers/media/dvb-frontends/eds1547.h index c983f2f85802..c983f2f85802 100644 --- a/drivers/media/dvb/frontends/eds1547.h +++ b/drivers/media/dvb-frontends/eds1547.h diff --git a/drivers/media/dvb/frontends/hd29l2.c b/drivers/media/dvb-frontends/hd29l2.c index a00318190837..d7b9d549156d 100644 --- a/drivers/media/dvb/frontends/hd29l2.c +++ b/drivers/media/dvb-frontends/hd29l2.c @@ -22,10 +22,6 @@ #include "hd29l2_priv.h" -int hd29l2_debug; -module_param_named(debug, hd29l2_debug, int, 0644); -MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); - /* write multiple registers */ static int hd29l2_wr_regs(struct hd29l2_priv *priv, u8 reg, u8 *val, int len) { @@ -48,7 +44,9 @@ static int hd29l2_wr_regs(struct hd29l2_priv *priv, u8 reg, u8 *val, int len) if (ret == 1) { ret = 0; } else { - warn("i2c wr failed=%d reg=%02x len=%d", ret, reg, len); + dev_warn(&priv->i2c->dev, + "%s: i2c wr failed=%d reg=%02x len=%d\n", + KBUILD_MODNAME, ret, reg, len); ret = -EREMOTEIO; } @@ -78,7 +76,9 @@ static int hd29l2_rd_regs(struct hd29l2_priv *priv, u8 reg, u8 *val, int len) if (ret == 2) { ret = 0; } else { - warn("i2c rd failed=%d reg=%02x len=%d", ret, reg, len); + dev_warn(&priv->i2c->dev, + "%s: i2c rd failed=%d reg=%02x len=%d\n", + KBUILD_MODNAME, ret, reg, len); ret = -EREMOTEIO; } @@ -160,7 +160,7 @@ static int hd29l2_soft_reset(struct hd29l2_priv *priv) return 0; err: - dbg("%s: failed=%d", __func__, ret); + dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); return ret; } @@ -170,7 +170,7 @@ static int hd29l2_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) struct hd29l2_priv *priv = fe->demodulator_priv; u8 tmp; - dbg("%s: enable=%d", __func__, enable); + dev_dbg(&priv->i2c->dev, "%s: enable=%d\n", __func__, enable); /* set tuner address for demod */ if (!priv->tuner_i2c_addr_programmed && enable) { @@ -199,11 +199,11 @@ static int hd29l2_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) usleep_range(5000, 10000); } - dbg("%s: loop=%d", __func__, i); + dev_dbg(&priv->i2c->dev, "%s: loop=%d\n", __func__, i); return ret; err: - dbg("%s: failed=%d", __func__, ret); + dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); return ret; } @@ -238,7 +238,7 @@ static int hd29l2_read_status(struct dvb_frontend *fe, fe_status_t *status) return 0; err: - dbg("%s: failed=%d", __func__, ret); + dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); return ret; } @@ -270,7 +270,7 @@ static int hd29l2_read_snr(struct dvb_frontend *fe, u16 *snr) return 0; err: - dbg("%s: failed=%d", __func__, ret); + dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); return ret; } @@ -295,7 +295,7 @@ static int hd29l2_read_signal_strength(struct dvb_frontend *fe, u16 *strength) return 0; err: - dbg("%s: failed=%d", __func__, ret); + dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); return ret; } @@ -322,7 +322,7 @@ static int hd29l2_read_ber(struct dvb_frontend *fe, u32 *ber) return 0; err: - dbg("%s: failed=%d", __func__, ret); + dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); return ret; } @@ -344,11 +344,12 @@ static enum dvbfe_search hd29l2_search(struct dvb_frontend *fe) u32 if_freq, if_ctl; bool auto_mode; - dbg("%s: delivery_system=%d frequency=%d bandwidth_hz=%d " \ - "modulation=%d inversion=%d fec_inner=%d guard_interval=%d", - __func__, - c->delivery_system, c->frequency, c->bandwidth_hz, - c->modulation, c->inversion, c->fec_inner, c->guard_interval); + dev_dbg(&priv->i2c->dev, "%s: delivery_system=%d frequency=%d " \ + "bandwidth_hz=%d modulation=%d inversion=%d " \ + "fec_inner=%d guard_interval=%d\n", __func__, + c->delivery_system, c->frequency, c->bandwidth_hz, + c->modulation, c->inversion, c->fec_inner, + c->guard_interval); /* as for now we detect always params automatically */ auto_mode = true; @@ -394,7 +395,8 @@ static enum dvbfe_search hd29l2_search(struct dvb_frontend *fe) if (ret) goto err; - dbg("%s: if_freq=%d if_ctl=%x", __func__, if_freq, if_ctl); + dev_dbg(&priv->i2c->dev, "%s: if_freq=%d if_ctl=%x\n", + __func__, if_freq, if_ctl); if (auto_mode) { /* @@ -437,7 +439,7 @@ static enum dvbfe_search hd29l2_search(struct dvb_frontend *fe) break; } - dbg("%s: loop=%d", __func__, i); + dev_dbg(&priv->i2c->dev, "%s: loop=%d\n", __func__, i); if (i == 0) /* detection failed */ @@ -477,7 +479,8 @@ static enum dvbfe_search hd29l2_search(struct dvb_frontend *fe) /* ensure modulation validy */ /* 0=QAM4_NR, 1=QAM4, 2=QAM16, 3=QAM32, 4=QAM64 */ if (modulation > (ARRAY_SIZE(reg_mod_vals_tab[0].val) - 1)) { - dbg("%s: modulation=%d not valid", __func__, modulation); + dev_dbg(&priv->i2c->dev, "%s: modulation=%d not valid\n", + __func__, modulation); goto err; } @@ -499,12 +502,14 @@ static enum dvbfe_search hd29l2_search(struct dvb_frontend *fe) if (ret) goto err; - dbg("%s: modulation=%d guard_interval=%d carrier=%d", - __func__, modulation, guard_interval, carrier); + dev_dbg(&priv->i2c->dev, + "%s: modulation=%d guard_interval=%d carrier=%d\n", + __func__, modulation, guard_interval, carrier); if ((carrier == HD29L2_CARRIER_MULTI) && (modulation == HD29L2_QAM64) && (guard_interval == HD29L2_PN945)) { - dbg("%s: C=3780 && QAM64 && PN945", __func__); + dev_dbg(&priv->i2c->dev, "%s: C=3780 && QAM64 && PN945\n", + __func__); ret = hd29l2_wr_reg(priv, 0x42, 0x33); if (ret) @@ -535,14 +540,14 @@ static enum dvbfe_search hd29l2_search(struct dvb_frontend *fe) break; } - dbg("%s: loop=%d", __func__, i); + dev_dbg(&priv->i2c->dev, "%s: loop=%d\n", __func__, i); if (i == 0) return DVBFE_ALGO_SEARCH_AGAIN; return DVBFE_ALGO_SEARCH_SUCCESS; err: - dbg("%s: failed=%d", __func__, ret); + dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); return DVBFE_ALGO_SEARCH_ERROR; } @@ -704,14 +709,14 @@ static int hd29l2_get_frontend(struct dvb_frontend *fe) if_ctl = (buf[0] << 16) | ((buf[1] - 7) << 8) | buf[2]; - dbg("%s: %s %s %s | %s %s %s | %s %s | NCO=%06x", __func__, - str_constellation, str_code_rate, str_constellation_code_rate, - str_guard_interval, str_carrier, str_guard_interval_carrier, - str_interleave, str_interleave_, if_ctl); - + dev_dbg(&priv->i2c->dev, "%s: %s %s %s | %s %s %s | %s %s | NCO=%06x\n", + __func__, str_constellation, str_code_rate, + str_constellation_code_rate, str_guard_interval, + str_carrier, str_guard_interval_carrier, str_interleave, + str_interleave_, if_ctl); return 0; err: - dbg("%s: failed=%d", __func__, ret); + dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); return ret; } @@ -730,7 +735,7 @@ static int hd29l2_init(struct dvb_frontend *fe) { 0x10, 0x38 }, }; - dbg("%s:", __func__); + dev_dbg(&priv->i2c->dev, "%s:\n", __func__); /* reset demod */ /* it is recommended to HW reset chip using RST_N pin */ @@ -774,7 +779,7 @@ static int hd29l2_init(struct dvb_frontend *fe) return ret; err: - dbg("%s: failed=%d", __func__, ret); + dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); return ret; } diff --git a/drivers/media/dvb/frontends/hd29l2.h b/drivers/media/dvb-frontends/hd29l2.h index a7a64431364d..4ad00d79aa77 100644 --- a/drivers/media/dvb/frontends/hd29l2.h +++ b/drivers/media/dvb-frontends/hd29l2.h @@ -58,7 +58,7 @@ extern struct dvb_frontend *hd29l2_attach(const struct hd29l2_config *config, static inline struct dvb_frontend *hd29l2_attach( const struct hd29l2_config *config, struct i2c_adapter *i2c) { - printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); + pr_warn("%s: driver disabled by Kconfig\n", __func__); return NULL; } #endif diff --git a/drivers/media/dvb/frontends/hd29l2_priv.h b/drivers/media/dvb-frontends/hd29l2_priv.h index ba16dc3ec2bd..4d571a2282d4 100644 --- a/drivers/media/dvb/frontends/hd29l2_priv.h +++ b/drivers/media/dvb-frontends/hd29l2_priv.h @@ -28,19 +28,6 @@ #include "dvb_math.h" #include "hd29l2.h" -#define LOG_PREFIX "hd29l2" - -#undef dbg -#define dbg(f, arg...) \ - if (hd29l2_debug) \ - printk(KERN_INFO LOG_PREFIX": " f "\n" , ## arg) -#undef err -#define err(f, arg...) printk(KERN_ERR LOG_PREFIX": " f "\n" , ## arg) -#undef info -#define info(f, arg...) printk(KERN_INFO LOG_PREFIX": " f "\n" , ## arg) -#undef warn -#define warn(f, arg...) printk(KERN_WARNING LOG_PREFIX": " f "\n" , ## arg) - #define HD29L2_XTAL 30400000 /* Hz */ diff --git a/drivers/media/dvb/frontends/isl6405.c b/drivers/media/dvb-frontends/isl6405.c index 33d33f4d8867..33d33f4d8867 100644 --- a/drivers/media/dvb/frontends/isl6405.c +++ b/drivers/media/dvb-frontends/isl6405.c diff --git a/drivers/media/dvb/frontends/isl6405.h b/drivers/media/dvb-frontends/isl6405.h index 1c793d37576b..1c793d37576b 100644 --- a/drivers/media/dvb/frontends/isl6405.h +++ b/drivers/media/dvb-frontends/isl6405.h diff --git a/drivers/media/dvb/frontends/isl6421.c b/drivers/media/dvb-frontends/isl6421.c index 684c8ec166cb..684c8ec166cb 100644 --- a/drivers/media/dvb/frontends/isl6421.c +++ b/drivers/media/dvb-frontends/isl6421.c diff --git a/drivers/media/dvb/frontends/isl6421.h b/drivers/media/dvb-frontends/isl6421.h index 47e4518a042d..47e4518a042d 100644 --- a/drivers/media/dvb/frontends/isl6421.h +++ b/drivers/media/dvb-frontends/isl6421.h diff --git a/drivers/media/dvb/frontends/isl6423.c b/drivers/media/dvb-frontends/isl6423.c index dca5bebfeeb5..dca5bebfeeb5 100644 --- a/drivers/media/dvb/frontends/isl6423.c +++ b/drivers/media/dvb-frontends/isl6423.c diff --git a/drivers/media/dvb/frontends/isl6423.h b/drivers/media/dvb-frontends/isl6423.h index e1a37fba01ca..e1a37fba01ca 100644 --- a/drivers/media/dvb/frontends/isl6423.h +++ b/drivers/media/dvb-frontends/isl6423.h diff --git a/drivers/media/dvb/frontends/it913x-fe-priv.h b/drivers/media/dvb-frontends/it913x-fe-priv.h index eb6fd8aebdb3..eb6fd8aebdb3 100644 --- a/drivers/media/dvb/frontends/it913x-fe-priv.h +++ b/drivers/media/dvb-frontends/it913x-fe-priv.h diff --git a/drivers/media/dvb/frontends/it913x-fe.c b/drivers/media/dvb-frontends/it913x-fe.c index 708cbf197913..6e1c6eb340b7 100644 --- a/drivers/media/dvb/frontends/it913x-fe.c +++ b/drivers/media/dvb-frontends/it913x-fe.c @@ -199,7 +199,7 @@ static int it913x_init_tuner(struct it913x_fe_state *state) if (reg < 0) return -ENODEV; - else if (reg < sizeof(nv)) + else if (reg < ARRAY_SIZE(nv)) nv_val = nv[reg]; else nv_val = 2; diff --git a/drivers/media/dvb/frontends/it913x-fe.h b/drivers/media/dvb-frontends/it913x-fe.h index 07fa4594c12b..07fa4594c12b 100644 --- a/drivers/media/dvb/frontends/it913x-fe.h +++ b/drivers/media/dvb-frontends/it913x-fe.h diff --git a/drivers/media/dvb/frontends/itd1000.c b/drivers/media/dvb-frontends/itd1000.c index 316457584fe7..316457584fe7 100644 --- a/drivers/media/dvb/frontends/itd1000.c +++ b/drivers/media/dvb-frontends/itd1000.c diff --git a/drivers/media/dvb/frontends/itd1000.h b/drivers/media/dvb-frontends/itd1000.h index 5e18df071b88..5e18df071b88 100644 --- a/drivers/media/dvb/frontends/itd1000.h +++ b/drivers/media/dvb-frontends/itd1000.h diff --git a/drivers/media/dvb/frontends/itd1000_priv.h b/drivers/media/dvb-frontends/itd1000_priv.h index 08ca851223c9..08ca851223c9 100644 --- a/drivers/media/dvb/frontends/itd1000_priv.h +++ b/drivers/media/dvb-frontends/itd1000_priv.h diff --git a/drivers/media/dvb/frontends/ix2505v.c b/drivers/media/dvb-frontends/ix2505v.c index bc5a82082aaa..bc5a82082aaa 100644 --- a/drivers/media/dvb/frontends/ix2505v.c +++ b/drivers/media/dvb-frontends/ix2505v.c diff --git a/drivers/media/dvb/frontends/ix2505v.h b/drivers/media/dvb-frontends/ix2505v.h index 67e89d616d50..67e89d616d50 100644 --- a/drivers/media/dvb/frontends/ix2505v.h +++ b/drivers/media/dvb-frontends/ix2505v.h diff --git a/drivers/media/dvb/frontends/l64781.c b/drivers/media/dvb-frontends/l64781.c index 36fcf559e361..36fcf559e361 100644 --- a/drivers/media/dvb/frontends/l64781.c +++ b/drivers/media/dvb-frontends/l64781.c diff --git a/drivers/media/dvb/frontends/l64781.h b/drivers/media/dvb-frontends/l64781.h index 1305a9e7fb0b..1305a9e7fb0b 100644 --- a/drivers/media/dvb/frontends/l64781.h +++ b/drivers/media/dvb-frontends/l64781.h diff --git a/drivers/media/dvb/frontends/lg2160.c b/drivers/media/dvb-frontends/lg2160.c index cc11260e99df..cc11260e99df 100644 --- a/drivers/media/dvb/frontends/lg2160.c +++ b/drivers/media/dvb-frontends/lg2160.c diff --git a/drivers/media/dvb/frontends/lg2160.h b/drivers/media/dvb-frontends/lg2160.h index 9e2c0f41199a..9e2c0f41199a 100644 --- a/drivers/media/dvb/frontends/lg2160.h +++ b/drivers/media/dvb-frontends/lg2160.h diff --git a/drivers/media/dvb/frontends/lgdt3305.c b/drivers/media/dvb-frontends/lgdt3305.c index 1d2c47378cf8..1d2c47378cf8 100644 --- a/drivers/media/dvb/frontends/lgdt3305.c +++ b/drivers/media/dvb-frontends/lgdt3305.c diff --git a/drivers/media/dvb/frontends/lgdt3305.h b/drivers/media/dvb-frontends/lgdt3305.h index 02172eca4d47..02172eca4d47 100644 --- a/drivers/media/dvb/frontends/lgdt3305.h +++ b/drivers/media/dvb-frontends/lgdt3305.h diff --git a/drivers/media/dvb/frontends/lgdt330x.c b/drivers/media/dvb-frontends/lgdt330x.c index e046622df0e4..e046622df0e4 100644 --- a/drivers/media/dvb/frontends/lgdt330x.c +++ b/drivers/media/dvb-frontends/lgdt330x.c diff --git a/drivers/media/dvb/frontends/lgdt330x.h b/drivers/media/dvb-frontends/lgdt330x.h index 9012504f0f2d..9012504f0f2d 100644 --- a/drivers/media/dvb/frontends/lgdt330x.h +++ b/drivers/media/dvb-frontends/lgdt330x.h diff --git a/drivers/media/dvb/frontends/lgdt330x_priv.h b/drivers/media/dvb-frontends/lgdt330x_priv.h index 38c76695abfe..38c76695abfe 100644 --- a/drivers/media/dvb/frontends/lgdt330x_priv.h +++ b/drivers/media/dvb-frontends/lgdt330x_priv.h diff --git a/drivers/media/dvb/frontends/lgs8gl5.c b/drivers/media/dvb-frontends/lgs8gl5.c index 2cec8041a106..416cce3fefc7 100644 --- a/drivers/media/dvb/frontends/lgs8gl5.c +++ b/drivers/media/dvb-frontends/lgs8gl5.c @@ -412,7 +412,7 @@ EXPORT_SYMBOL(lgs8gl5_attach); static struct dvb_frontend_ops lgs8gl5_ops = { - .delsys = { SYS_DMBTH }, + .delsys = { SYS_DTMB }, .info = { .name = "Legend Silicon LGS-8GL5 DMB-TH", .frequency_min = 474000000, diff --git a/drivers/media/dvb/frontends/lgs8gl5.h b/drivers/media/dvb-frontends/lgs8gl5.h index d14176787a7d..d14176787a7d 100644 --- a/drivers/media/dvb/frontends/lgs8gl5.h +++ b/drivers/media/dvb-frontends/lgs8gl5.h diff --git a/drivers/media/dvb/frontends/lgs8gxx.c b/drivers/media/dvb-frontends/lgs8gxx.c index c2ea2749ebed..3c92f36ea5c7 100644 --- a/drivers/media/dvb/frontends/lgs8gxx.c +++ b/drivers/media/dvb-frontends/lgs8gxx.c @@ -995,7 +995,7 @@ static int lgs8gxx_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) } static struct dvb_frontend_ops lgs8gxx_ops = { - .delsys = { SYS_DMBTH }, + .delsys = { SYS_DTMB }, .info = { .name = "Legend Silicon LGS8913/LGS8GXX DMB-TH", .frequency_min = 474000000, diff --git a/drivers/media/dvb/frontends/lgs8gxx.h b/drivers/media/dvb-frontends/lgs8gxx.h index 33c3c5e162fa..33c3c5e162fa 100644 --- a/drivers/media/dvb/frontends/lgs8gxx.h +++ b/drivers/media/dvb-frontends/lgs8gxx.h diff --git a/drivers/media/dvb/frontends/lgs8gxx_priv.h b/drivers/media/dvb-frontends/lgs8gxx_priv.h index 8ef376f1414d..8ef376f1414d 100644 --- a/drivers/media/dvb/frontends/lgs8gxx_priv.h +++ b/drivers/media/dvb-frontends/lgs8gxx_priv.h diff --git a/drivers/media/dvb/frontends/lnbh24.h b/drivers/media/dvb-frontends/lnbh24.h index c059b165318f..c059b165318f 100644 --- a/drivers/media/dvb/frontends/lnbh24.h +++ b/drivers/media/dvb-frontends/lnbh24.h diff --git a/drivers/media/dvb/frontends/lnbp21.c b/drivers/media/dvb-frontends/lnbp21.c index 13437259eeac..13437259eeac 100644 --- a/drivers/media/dvb/frontends/lnbp21.c +++ b/drivers/media/dvb-frontends/lnbp21.c diff --git a/drivers/media/dvb/frontends/lnbp21.h b/drivers/media/dvb-frontends/lnbp21.h index fcdf1c650dde..fcdf1c650dde 100644 --- a/drivers/media/dvb/frontends/lnbp21.h +++ b/drivers/media/dvb-frontends/lnbp21.h diff --git a/drivers/media/dvb/frontends/lnbp22.c b/drivers/media/dvb-frontends/lnbp22.c index 84ad0390a4a1..84ad0390a4a1 100644 --- a/drivers/media/dvb/frontends/lnbp22.c +++ b/drivers/media/dvb-frontends/lnbp22.c diff --git a/drivers/media/dvb/frontends/lnbp22.h b/drivers/media/dvb-frontends/lnbp22.h index 63e2dec7e68a..63e2dec7e68a 100644 --- a/drivers/media/dvb/frontends/lnbp22.h +++ b/drivers/media/dvb-frontends/lnbp22.h diff --git a/drivers/media/dvb/frontends/m88rs2000.c b/drivers/media/dvb-frontends/m88rs2000.c index 312588e84dae..633815ed90ca 100644 --- a/drivers/media/dvb/frontends/m88rs2000.c +++ b/drivers/media/dvb-frontends/m88rs2000.c @@ -481,7 +481,7 @@ static int m88rs2000_read_status(struct dvb_frontend *fe, fe_status_t *status) if ((reg & 0x7) == 0x7) { *status = FE_HAS_CARRIER | FE_HAS_SIGNAL | FE_HAS_VITERBI - | FE_HAS_LOCK; + | FE_HAS_SYNC | FE_HAS_LOCK; if (state->config->set_ts_params) state->config->set_ts_params(fe, CALL_IS_READ); } diff --git a/drivers/media/dvb/frontends/m88rs2000.h b/drivers/media/dvb-frontends/m88rs2000.h index 59acdb696873..59acdb696873 100644 --- a/drivers/media/dvb/frontends/m88rs2000.h +++ b/drivers/media/dvb-frontends/m88rs2000.h diff --git a/drivers/media/dvb/frontends/mb86a16.c b/drivers/media/dvb-frontends/mb86a16.c index 9ae40abfd71a..9ae40abfd71a 100644 --- a/drivers/media/dvb/frontends/mb86a16.c +++ b/drivers/media/dvb-frontends/mb86a16.c diff --git a/drivers/media/dvb/frontends/mb86a16.h b/drivers/media/dvb-frontends/mb86a16.h index 6ea8c376394f..6ea8c376394f 100644 --- a/drivers/media/dvb/frontends/mb86a16.h +++ b/drivers/media/dvb-frontends/mb86a16.h diff --git a/drivers/media/dvb/frontends/mb86a16_priv.h b/drivers/media/dvb-frontends/mb86a16_priv.h index 360a35acfe84..360a35acfe84 100644 --- a/drivers/media/dvb/frontends/mb86a16_priv.h +++ b/drivers/media/dvb-frontends/mb86a16_priv.h diff --git a/drivers/media/dvb/frontends/mb86a20s.c b/drivers/media/dvb-frontends/mb86a20s.c index fade566927c3..fade566927c3 100644 --- a/drivers/media/dvb/frontends/mb86a20s.c +++ b/drivers/media/dvb-frontends/mb86a20s.c diff --git a/drivers/media/dvb/frontends/mb86a20s.h b/drivers/media/dvb-frontends/mb86a20s.h index bf22e77888b9..bf22e77888b9 100644 --- a/drivers/media/dvb/frontends/mb86a20s.h +++ b/drivers/media/dvb-frontends/mb86a20s.h diff --git a/drivers/media/dvb/frontends/mt312.c b/drivers/media/dvb-frontends/mt312.c index e20bf13aa860..e20bf13aa860 100644 --- a/drivers/media/dvb/frontends/mt312.c +++ b/drivers/media/dvb-frontends/mt312.c diff --git a/drivers/media/dvb/frontends/mt312.h b/drivers/media/dvb-frontends/mt312.h index 29e3bb5496b8..29e3bb5496b8 100644 --- a/drivers/media/dvb/frontends/mt312.h +++ b/drivers/media/dvb-frontends/mt312.h diff --git a/drivers/media/dvb/frontends/mt312_priv.h b/drivers/media/dvb-frontends/mt312_priv.h index a3959f94d639..a3959f94d639 100644 --- a/drivers/media/dvb/frontends/mt312_priv.h +++ b/drivers/media/dvb-frontends/mt312_priv.h diff --git a/drivers/media/dvb/frontends/mt352.c b/drivers/media/dvb-frontends/mt352.c index 2c3b50e828d7..2c3b50e828d7 100644 --- a/drivers/media/dvb/frontends/mt352.c +++ b/drivers/media/dvb-frontends/mt352.c diff --git a/drivers/media/dvb/frontends/mt352.h b/drivers/media/dvb-frontends/mt352.h index ca2562d6f289..ca2562d6f289 100644 --- a/drivers/media/dvb/frontends/mt352.h +++ b/drivers/media/dvb-frontends/mt352.h diff --git a/drivers/media/dvb/frontends/mt352_priv.h b/drivers/media/dvb-frontends/mt352_priv.h index 44ad0d4c8f12..44ad0d4c8f12 100644 --- a/drivers/media/dvb/frontends/mt352_priv.h +++ b/drivers/media/dvb-frontends/mt352_priv.h diff --git a/drivers/media/dvb/frontends/nxt200x.c b/drivers/media/dvb-frontends/nxt200x.c index 49ca78d883b1..8e288940a61f 100644 --- a/drivers/media/dvb/frontends/nxt200x.c +++ b/drivers/media/dvb-frontends/nxt200x.c @@ -37,6 +37,8 @@ * /usr/lib/hotplug/firmware/ or /lib/firmware/ * (depending on configuration of firmware hotplug). */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #define NXT2002_DEFAULT_FIRMWARE "dvb-fe-nxt2002.fw" #define NXT2004_DEFAULT_FIRMWARE "dvb-fe-nxt2004.fw" #define CRC_CCIT_MASK 0x1021 @@ -62,10 +64,7 @@ struct nxt200x_state { }; static int debug; -#define dprintk(args...) \ - do { \ - if (debug) printk(KERN_DEBUG "nxt200x: " args); \ - } while (0) +#define dprintk(args...) do { if (debug) pr_debug(args); } while (0) static int i2c_writebytes (struct nxt200x_state* state, u8 addr, u8 *buf, u8 len) { @@ -73,7 +72,7 @@ static int i2c_writebytes (struct nxt200x_state* state, u8 addr, u8 *buf, u8 len struct i2c_msg msg = { .addr = addr, .flags = 0, .buf = buf, .len = len }; if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) { - printk (KERN_WARNING "nxt200x: %s: i2c write error (addr 0x%02x, err == %i)\n", + pr_warn("%s: i2c write error (addr 0x%02x, err == %i)\n", __func__, addr, err); return -EREMOTEIO; } @@ -86,7 +85,7 @@ static int i2c_readbytes(struct nxt200x_state *state, u8 addr, u8 *buf, u8 len) struct i2c_msg msg = { .addr = addr, .flags = I2C_M_RD, .buf = buf, .len = len }; if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) { - printk (KERN_WARNING "nxt200x: %s: i2c read error (addr 0x%02x, err == %i)\n", + pr_warn("%s: i2c read error (addr 0x%02x, err == %i)\n", __func__, addr, err); return -EREMOTEIO; } @@ -104,7 +103,7 @@ static int nxt200x_writebytes (struct nxt200x_state* state, u8 reg, memcpy(&buf2[1], buf, len); if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) { - printk (KERN_WARNING "nxt200x: %s: i2c write error (addr 0x%02x, err == %i)\n", + pr_warn("%s: i2c write error (addr 0x%02x, err == %i)\n", __func__, state->config->demod_address, err); return -EREMOTEIO; } @@ -121,7 +120,7 @@ static int nxt200x_readbytes(struct nxt200x_state *state, u8 reg, u8 *buf, u8 le int err; if ((err = i2c_transfer (state->i2c, msg, 2)) != 2) { - printk (KERN_WARNING "nxt200x: %s: i2c read error (addr 0x%02x, err == %i)\n", + pr_warn("%s: i2c read error (addr 0x%02x, err == %i)\n", __func__, state->config->demod_address, err); return -EREMOTEIO; } @@ -199,7 +198,7 @@ static int nxt200x_writereg_multibyte (struct nxt200x_state* state, u8 reg, u8* break; } - printk(KERN_WARNING "nxt200x: Error writing multireg register 0x%02X\n",reg); + pr_warn("Error writing multireg register 0x%02X\n", reg); return 0; } @@ -281,7 +280,8 @@ static void nxt200x_microcontroller_stop (struct nxt200x_state* state) counter++; } - printk(KERN_WARNING "nxt200x: Timeout waiting for nxt200x to stop. This is ok after firmware upload.\n"); + pr_warn("Timeout waiting for nxt200x to stop. This is ok after " + "firmware upload.\n"); return; } @@ -320,7 +320,7 @@ static void nxt2004_microcontroller_init (struct nxt200x_state* state) counter++; } - printk(KERN_WARNING "nxt200x: Timeout waiting for nxt2004 to init.\n"); + pr_warn("Timeout waiting for nxt2004 to init.\n"); return; } @@ -331,14 +331,14 @@ static int nxt200x_writetuner (struct nxt200x_state* state, u8* data) dprintk("%s\n", __func__); - dprintk("Tuner Bytes: %02X %02X %02X %02X\n", data[1], data[2], data[3], data[4]); + dprintk("Tuner Bytes: %*ph\n", 4, data + 1); /* if NXT2004, write directly to tuner. if NXT2002, write through NXT chip. * direct write is required for Philips TUV1236D and ALPS TDHU2 */ switch (state->demod_chip) { case NXT2004: if (i2c_writebytes(state, data[0], data+1, 4)) - printk(KERN_WARNING "nxt200x: error writing to tuner\n"); + pr_warn("error writing to tuner\n"); /* wait until we have a lock */ while (count < 20) { i2c_readbytes(state, data[0], &buf, 1); @@ -347,7 +347,7 @@ static int nxt200x_writetuner (struct nxt200x_state* state, u8* data) msleep(100); count++; } - printk("nxt2004: timeout waiting for tuner lock\n"); + pr_warn("timeout waiting for tuner lock\n"); break; case NXT2002: /* set the i2c transfer speed to the tuner */ @@ -376,7 +376,7 @@ static int nxt200x_writetuner (struct nxt200x_state* state, u8* data) msleep(100); count++; } - printk("nxt2002: timeout error writing tuner\n"); + pr_warn("timeout error writing to tuner\n"); break; default: return -EINVAL; @@ -878,22 +878,24 @@ static int nxt2002_init(struct dvb_frontend* fe) u8 buf[2]; /* request the firmware, this will block until someone uploads it */ - printk("nxt2002: Waiting for firmware upload (%s)...\n", NXT2002_DEFAULT_FIRMWARE); + pr_debug("%s: Waiting for firmware upload (%s)...\n", + __func__, NXT2002_DEFAULT_FIRMWARE); ret = request_firmware(&fw, NXT2002_DEFAULT_FIRMWARE, state->i2c->dev.parent); - printk("nxt2002: Waiting for firmware upload(2)...\n"); + pr_debug("%s: Waiting for firmware upload(2)...\n", __func__); if (ret) { - printk("nxt2002: No firmware uploaded (timeout or file not found?)\n"); + pr_err("%s: No firmware uploaded (timeout or file not found?)" + "\n", __func__); return ret; } ret = nxt2002_load_firmware(fe, fw); release_firmware(fw); if (ret) { - printk("nxt2002: Writing firmware to device failed\n"); + pr_err("%s: Writing firmware to device failed\n", __func__); return ret; } - printk("nxt2002: Firmware upload complete\n"); + pr_info("%s: Firmware upload complete\n", __func__); /* Put the micro into reset */ nxt200x_microcontroller_stop(state); @@ -943,22 +945,24 @@ static int nxt2004_init(struct dvb_frontend* fe) nxt200x_writebytes(state, 0x1E, buf, 1); /* request the firmware, this will block until someone uploads it */ - printk("nxt2004: Waiting for firmware upload (%s)...\n", NXT2004_DEFAULT_FIRMWARE); + pr_debug("%s: Waiting for firmware upload (%s)...\n", + __func__, NXT2004_DEFAULT_FIRMWARE); ret = request_firmware(&fw, NXT2004_DEFAULT_FIRMWARE, state->i2c->dev.parent); - printk("nxt2004: Waiting for firmware upload(2)...\n"); + pr_debug("%s: Waiting for firmware upload(2)...\n", __func__); if (ret) { - printk("nxt2004: No firmware uploaded (timeout or file not found?)\n"); + pr_err("%s: No firmware uploaded (timeout or file not found?)" + "\n", __func__); return ret; } ret = nxt2004_load_firmware(fe, fw); release_firmware(fw); if (ret) { - printk("nxt2004: Writing firmware to device failed\n"); + pr_err("%s: Writing firmware to device failed\n", __func__); return ret; } - printk("nxt2004: Firmware upload complete\n"); + pr_info("%s: Firmware upload complete\n", __func__); /* ensure transfer is complete */ buf[0] = 0x01; @@ -1157,18 +1161,17 @@ struct dvb_frontend* nxt200x_attach(const struct nxt200x_config* config, /* read card id */ nxt200x_readbytes(state, 0x00, buf, 5); - dprintk("NXT info: %02X %02X %02X %02X %02X\n", - buf[0], buf[1], buf[2], buf[3], buf[4]); + dprintk("NXT info: %*ph\n", 5, buf); /* set demod chip */ switch (buf[0]) { case 0x04: state->demod_chip = NXT2002; - printk("nxt200x: NXT2002 Detected\n"); + pr_info("NXT2002 Detected\n"); break; case 0x05: state->demod_chip = NXT2004; - printk("nxt200x: NXT2004 Detected\n"); + pr_info("NXT2004 Detected\n"); break; default: goto error; @@ -1197,8 +1200,7 @@ struct dvb_frontend* nxt200x_attach(const struct nxt200x_config* config, error: kfree(state); - printk("Unknown/Unsupported NXT chip: %02X %02X %02X %02X %02X\n", - buf[0], buf[1], buf[2], buf[3], buf[4]); + pr_err("Unknown/Unsupported NXT chip: %*ph\n", 5, buf); return NULL; } diff --git a/drivers/media/dvb/frontends/nxt200x.h b/drivers/media/dvb-frontends/nxt200x.h index f3c84583770f..f3c84583770f 100644 --- a/drivers/media/dvb/frontends/nxt200x.h +++ b/drivers/media/dvb-frontends/nxt200x.h diff --git a/drivers/media/dvb/frontends/nxt6000.c b/drivers/media/dvb-frontends/nxt6000.c index 90ae6c72c0e3..90ae6c72c0e3 100644 --- a/drivers/media/dvb/frontends/nxt6000.c +++ b/drivers/media/dvb-frontends/nxt6000.c diff --git a/drivers/media/dvb/frontends/nxt6000.h b/drivers/media/dvb-frontends/nxt6000.h index 878eb38a075e..878eb38a075e 100644 --- a/drivers/media/dvb/frontends/nxt6000.h +++ b/drivers/media/dvb-frontends/nxt6000.h diff --git a/drivers/media/dvb/frontends/nxt6000_priv.h b/drivers/media/dvb-frontends/nxt6000_priv.h index 0422e580038a..0422e580038a 100644 --- a/drivers/media/dvb/frontends/nxt6000_priv.h +++ b/drivers/media/dvb-frontends/nxt6000_priv.h diff --git a/drivers/media/dvb/frontends/or51132.c b/drivers/media/dvb-frontends/or51132.c index 5ef921823c15..5ef921823c15 100644 --- a/drivers/media/dvb/frontends/or51132.c +++ b/drivers/media/dvb-frontends/or51132.c diff --git a/drivers/media/dvb/frontends/or51132.h b/drivers/media/dvb-frontends/or51132.h index 1b8e04d973c8..1b8e04d973c8 100644 --- a/drivers/media/dvb/frontends/or51132.h +++ b/drivers/media/dvb-frontends/or51132.h diff --git a/drivers/media/dvb/frontends/or51211.c b/drivers/media/dvb-frontends/or51211.c index c625b57b4333..c625b57b4333 100644 --- a/drivers/media/dvb/frontends/or51211.c +++ b/drivers/media/dvb-frontends/or51211.c diff --git a/drivers/media/dvb/frontends/or51211.h b/drivers/media/dvb-frontends/or51211.h index 3ce0508b898e..3ce0508b898e 100644 --- a/drivers/media/dvb/frontends/or51211.h +++ b/drivers/media/dvb-frontends/or51211.h diff --git a/drivers/media/dvb/frontends/rtl2830.c b/drivers/media/dvb-frontends/rtl2830.c index 93612ebac519..b0f6ec03d1eb 100644 --- a/drivers/media/dvb/frontends/rtl2830.c +++ b/drivers/media/dvb-frontends/rtl2830.c @@ -27,12 +27,8 @@ #include "rtl2830_priv.h" -int rtl2830_debug; -module_param_named(debug, rtl2830_debug, int, 0644); -MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); - /* write multiple hardware registers */ -static int rtl2830_wr(struct rtl2830_priv *priv, u8 reg, u8 *val, int len) +static int rtl2830_wr(struct rtl2830_priv *priv, u8 reg, const u8 *val, int len) { int ret; u8 buf[1+len]; @@ -52,7 +48,8 @@ static int rtl2830_wr(struct rtl2830_priv *priv, u8 reg, u8 *val, int len) if (ret == 1) { ret = 0; } else { - warn("i2c wr failed=%d reg=%02x len=%d", ret, reg, len); + dev_warn(&priv->i2c->dev, "%s: i2c wr failed=%d reg=%02x " \ + "len=%d\n", KBUILD_MODNAME, ret, reg, len); ret = -EREMOTEIO; } return ret; @@ -80,14 +77,16 @@ static int rtl2830_rd(struct rtl2830_priv *priv, u8 reg, u8 *val, int len) if (ret == 2) { ret = 0; } else { - warn("i2c rd failed=%d reg=%02x len=%d", ret, reg, len); + dev_warn(&priv->i2c->dev, "%s: i2c rd failed=%d reg=%02x " \ + "len=%d\n", KBUILD_MODNAME, ret, reg, len); ret = -EREMOTEIO; } return ret; } /* write multiple registers */ -static int rtl2830_wr_regs(struct rtl2830_priv *priv, u16 reg, u8 *val, int len) +static int rtl2830_wr_regs(struct rtl2830_priv *priv, u16 reg, const u8 *val, + int len) { int ret; u8 reg2 = (reg >> 0) & 0xff; @@ -124,14 +123,6 @@ static int rtl2830_rd_regs(struct rtl2830_priv *priv, u16 reg, u8 *val, int len) return rtl2830_rd(priv, reg2, val, len); } -#if 0 /* currently not used */ -/* write single register */ -static int rtl2830_wr_reg(struct rtl2830_priv *priv, u16 reg, u8 val) -{ - return rtl2830_wr_regs(priv, reg, &val, 1); -} -#endif - /* read single register */ static int rtl2830_rd_reg(struct rtl2830_priv *priv, u16 reg, u8 *val) { @@ -184,9 +175,6 @@ static int rtl2830_init(struct dvb_frontend *fe) { struct rtl2830_priv *priv = fe->demodulator_priv; int ret, i; - u64 num; - u8 buf[3], tmp; - u32 if_ctl; struct rtl2830_reg_val_mask tab[] = { { 0x00d, 0x01, 0x03 }, { 0x00d, 0x10, 0x10 }, @@ -242,26 +230,6 @@ static int rtl2830_init(struct dvb_frontend *fe) if (ret) goto err; - num = priv->cfg.if_dvbt % priv->cfg.xtal; - num *= 0x400000; - num = div_u64(num, priv->cfg.xtal); - num = -num; - if_ctl = num & 0x3fffff; - dbg("%s: if_ctl=%08x", __func__, if_ctl); - - ret = rtl2830_rd_reg_mask(priv, 0x119, &tmp, 0xc0); /* b[7:6] */ - if (ret) - goto err; - - buf[0] = tmp << 6; - buf[0] = (if_ctl >> 16) & 0x3f; - buf[1] = (if_ctl >> 8) & 0xff; - buf[2] = (if_ctl >> 0) & 0xff; - - ret = rtl2830_wr_regs(priv, 0x119, buf, 3); - if (ret) - goto err; - /* TODO: spec init */ /* soft reset */ @@ -277,7 +245,7 @@ static int rtl2830_init(struct dvb_frontend *fe) return ret; err: - dbg("%s: failed=%d", __func__, ret); + dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); return ret; } @@ -303,7 +271,10 @@ static int rtl2830_set_frontend(struct dvb_frontend *fe) struct rtl2830_priv *priv = fe->demodulator_priv; struct dtv_frontend_properties *c = &fe->dtv_property_cache; int ret, i; - static u8 bw_params1[3][34] = { + u64 num; + u8 buf[3], tmp; + u32 if_ctl, if_frequency; + static const u8 bw_params1[3][34] = { { 0x1f, 0xf0, 0x1f, 0xf0, 0x1f, 0xfa, 0x00, 0x17, 0x00, 0x41, 0x00, 0x64, 0x00, 0x67, 0x00, 0x38, 0x1f, 0xde, 0x1f, 0x7a, @@ -321,15 +292,15 @@ static int rtl2830_set_frontend(struct dvb_frontend *fe) 0x04, 0x24, 0x04, 0xdb, /* 8 MHz */ }, }; - static u8 bw_params2[3][6] = { - {0xc3, 0x0c, 0x44, 0x33, 0x33, 0x30,}, /* 6 MHz */ - {0xb8, 0xe3, 0x93, 0x99, 0x99, 0x98,}, /* 7 MHz */ - {0xae, 0xba, 0xf3, 0x26, 0x66, 0x64,}, /* 8 MHz */ + static const u8 bw_params2[3][6] = { + {0xc3, 0x0c, 0x44, 0x33, 0x33, 0x30}, /* 6 MHz */ + {0xb8, 0xe3, 0x93, 0x99, 0x99, 0x98}, /* 7 MHz */ + {0xae, 0xba, 0xf3, 0x26, 0x66, 0x64}, /* 8 MHz */ }; - - dbg("%s: frequency=%d bandwidth_hz=%d inversion=%d", __func__, - c->frequency, c->bandwidth_hz, c->inversion); + dev_dbg(&priv->i2c->dev, + "%s: frequency=%d bandwidth_hz=%d inversion=%d\n", + __func__, c->frequency, c->bandwidth_hz, c->inversion); /* program tuner */ if (fe->ops.tuner_ops.set_params) @@ -346,7 +317,7 @@ static int rtl2830_set_frontend(struct dvb_frontend *fe) i = 2; break; default: - dbg("invalid bandwidth"); + dev_dbg(&priv->i2c->dev, "%s: invalid bandwidth\n", __func__); return -EINVAL; } @@ -354,6 +325,36 @@ static int rtl2830_set_frontend(struct dvb_frontend *fe) if (ret) goto err; + /* program if frequency */ + if (fe->ops.tuner_ops.get_if_frequency) + ret = fe->ops.tuner_ops.get_if_frequency(fe, &if_frequency); + else + ret = -EINVAL; + + if (ret < 0) + goto err; + + num = if_frequency % priv->cfg.xtal; + num *= 0x400000; + num = div_u64(num, priv->cfg.xtal); + num = -num; + if_ctl = num & 0x3fffff; + dev_dbg(&priv->i2c->dev, "%s: if_frequency=%d if_ctl=%08x\n", + __func__, if_frequency, if_ctl); + + ret = rtl2830_rd_reg_mask(priv, 0x119, &tmp, 0xc0); /* b[7:6] */ + if (ret) + goto err; + + buf[0] = tmp << 6; + buf[0] |= (if_ctl >> 16) & 0x3f; + buf[1] = (if_ctl >> 8) & 0xff; + buf[2] = (if_ctl >> 0) & 0xff; + + ret = rtl2830_wr_regs(priv, 0x119, buf, 3); + if (ret) + goto err; + /* 1/2 split I2C write */ ret = rtl2830_wr_regs(priv, 0x11c, &bw_params1[i][0], 17); if (ret) @@ -370,7 +371,7 @@ static int rtl2830_set_frontend(struct dvb_frontend *fe) return ret; err: - dbg("%s: failed=%d", __func__, ret); + dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); return ret; } @@ -392,7 +393,7 @@ static int rtl2830_get_frontend(struct dvb_frontend *fe) if (ret) goto err; - dbg("%s: TPS=%02x %02x %02x", __func__, buf[0], buf[1], buf[2]); + dev_dbg(&priv->i2c->dev, "%s: TPS=%*ph\n", __func__, 3, buf); switch ((buf[0] >> 2) & 3) { case 0: @@ -482,7 +483,7 @@ static int rtl2830_get_frontend(struct dvb_frontend *fe) return 0; err: - dbg("%s: failed=%d", __func__, ret); + dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); return ret; } @@ -510,7 +511,7 @@ static int rtl2830_read_status(struct dvb_frontend *fe, fe_status_t *status) return ret; err: - dbg("%s: failed=%d", __func__, ret); + dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); return ret; } @@ -559,7 +560,7 @@ static int rtl2830_read_snr(struct dvb_frontend *fe, u16 *snr) return 0; err: - dbg("%s: failed=%d", __func__, ret); + dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); return ret; } @@ -580,7 +581,7 @@ static int rtl2830_read_ber(struct dvb_frontend *fe, u32 *ber) return 0; err: - dbg("%s: failed=%d", __func__, ret); + dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); return ret; } @@ -616,7 +617,7 @@ static int rtl2830_read_signal_strength(struct dvb_frontend *fe, u16 *strength) return 0; err: - dbg("%s: failed=%d", __func__, ret); + dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); return ret; } @@ -640,11 +641,12 @@ static int rtl2830_tuner_i2c_xfer(struct i2c_adapter *i2c_adap, ret = i2c_transfer(priv->i2c, msg, num); if (ret < 0) - warn("tuner i2c failed=%d", ret); + dev_warn(&priv->i2c->dev, "%s: tuner i2c failed=%d\n", + KBUILD_MODNAME, ret); return ret; err: - dbg("%s: failed=%d", __func__, ret); + dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); return ret; } @@ -700,7 +702,9 @@ struct dvb_frontend *rtl2830_attach(const struct rtl2830_config *cfg, priv->tuner_i2c_adapter.algo_data = NULL; i2c_set_adapdata(&priv->tuner_i2c_adapter, priv); if (i2c_add_adapter(&priv->tuner_i2c_adapter) < 0) { - err("tuner I2C bus could not be initialized"); + dev_err(&i2c->dev, + "%s: tuner i2c bus could not be initialized\n", + KBUILD_MODNAME); goto err; } @@ -708,7 +712,7 @@ struct dvb_frontend *rtl2830_attach(const struct rtl2830_config *cfg, return &priv->fe; err: - dbg("%s: failed=%d", __func__, ret); + dev_dbg(&i2c->dev, "%s: failed=%d\n", __func__, ret); kfree(priv); return NULL; } diff --git a/drivers/media/dvb/frontends/rtl2830.h b/drivers/media/dvb-frontends/rtl2830.h index 1c6ee91749c2..f4349a1fc03e 100644 --- a/drivers/media/dvb/frontends/rtl2830.h +++ b/drivers/media/dvb-frontends/rtl2830.h @@ -47,13 +47,6 @@ struct rtl2830_config { bool spec_inv; /* - * IFs for all used modes. - * Hz - * 4570000, 4571429, 36000000, 36125000, 36166667, 44000000 - */ - u32 if_dvbt; - - /* */ u8 vtop; @@ -82,7 +75,7 @@ static inline struct dvb_frontend *rtl2830_attach( struct i2c_adapter *i2c ) { - printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); + pr_warn("%s: driver disabled by Kconfig\n", __func__); return NULL; } diff --git a/drivers/media/dvb/frontends/rtl2830_priv.h b/drivers/media/dvb-frontends/rtl2830_priv.h index 9b20557ccf6c..fab10ecb3c3b 100644 --- a/drivers/media/dvb/frontends/rtl2830_priv.h +++ b/drivers/media/dvb-frontends/rtl2830_priv.h @@ -25,19 +25,6 @@ #include "dvb_math.h" #include "rtl2830.h" -#define LOG_PREFIX "rtl2830" - -#undef dbg -#define dbg(f, arg...) \ - if (rtl2830_debug) \ - printk(KERN_INFO LOG_PREFIX": " f "\n" , ## arg) -#undef err -#define err(f, arg...) printk(KERN_ERR LOG_PREFIX": " f "\n" , ## arg) -#undef info -#define info(f, arg...) printk(KERN_INFO LOG_PREFIX": " f "\n" , ## arg) -#undef warn -#define warn(f, arg...) printk(KERN_WARNING LOG_PREFIX": " f "\n" , ## arg) - struct rtl2830_priv { struct i2c_adapter *i2c; struct dvb_frontend fe; diff --git a/drivers/media/dvb/frontends/rtl2832.c b/drivers/media/dvb-frontends/rtl2832.c index 28269ccaeab7..80c8e5f1182f 100644 --- a/drivers/media/dvb/frontends/rtl2832.c +++ b/drivers/media/dvb-frontends/rtl2832.c @@ -19,6 +19,7 @@ */ #include "rtl2832_priv.h" +#include "dvb_math.h" #include <linux/bitops.h> int rtl2832_debug; @@ -178,7 +179,8 @@ static int rtl2832_wr(struct rtl2832_priv *priv, u8 reg, u8 *val, int len) if (ret == 1) { ret = 0; } else { - warn("i2c wr failed=%d reg=%02x len=%d", ret, reg, len); + dev_warn(&priv->i2c->dev, "%s: i2c wr failed=%d reg=%02x " \ + "len=%d\n", KBUILD_MODNAME, ret, reg, len); ret = -EREMOTEIO; } return ret; @@ -206,10 +208,11 @@ static int rtl2832_rd(struct rtl2832_priv *priv, u8 reg, u8 *val, int len) if (ret == 2) { ret = 0; } else { - warn("i2c rd failed=%d reg=%02x len=%d", ret, reg, len); + dev_warn(&priv->i2c->dev, "%s: i2c rd failed=%d reg=%02x " \ + "len=%d\n", KBUILD_MODNAME, ret, reg, len); ret = -EREMOTEIO; -} -return ret; + } + return ret; } /* write multiple registers */ @@ -218,7 +221,6 @@ static int rtl2832_wr_regs(struct rtl2832_priv *priv, u8 reg, u8 page, u8 *val, { int ret; - /* switch bank if needed */ if (page != priv->page) { ret = rtl2832_wr(priv, 0x00, &page, 1); @@ -298,7 +300,7 @@ int rtl2832_rd_demod_reg(struct rtl2832_priv *priv, int reg, u32 *val) return ret; err: - dbg("%s: failed=%d", __func__, ret); + dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); return ret; } @@ -350,18 +352,17 @@ int rtl2832_wr_demod_reg(struct rtl2832_priv *priv, int reg, u32 val) return ret; err: - dbg("%s: failed=%d", __func__, ret); + dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); return ret; } - static int rtl2832_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) { int ret; struct rtl2832_priv *priv = fe->demodulator_priv; - dbg("%s: enable=%d", __func__, enable); + dev_dbg(&priv->i2c->dev, "%s: enable=%d\n", __func__, enable); /* gate already open or close */ if (priv->i2c_gate_state == enable) @@ -375,19 +376,17 @@ static int rtl2832_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) return ret; err: - dbg("%s: failed=%d", __func__, ret); + dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); return ret; } - - static int rtl2832_init(struct dvb_frontend *fe) { struct rtl2832_priv *priv = fe->demodulator_priv; - int i, ret; - + int i, ret, len; u8 en_bbin; u64 pset_iffreq; + const struct rtl2832_reg_value *init; /* initialization values for the demodulator registers */ struct rtl2832_reg_value rtl2832_initial_regs[] = { @@ -434,40 +433,9 @@ static int rtl2832_init(struct dvb_frontend *fe) {DVBT_TRK_KC_I2, 0x5}, {DVBT_CR_THD_SET2, 0x1}, {DVBT_SPEC_INV, 0x0}, - {DVBT_DAGC_TRG_VAL, 0x5a}, - {DVBT_AGC_TARG_VAL_0, 0x0}, - {DVBT_AGC_TARG_VAL_8_1, 0x5a}, - {DVBT_AAGC_LOOP_GAIN, 0x16}, - {DVBT_LOOP_GAIN2_3_0, 0x6}, - {DVBT_LOOP_GAIN2_4, 0x1}, - {DVBT_LOOP_GAIN3, 0x16}, - {DVBT_VTOP1, 0x35}, - {DVBT_VTOP2, 0x21}, - {DVBT_VTOP3, 0x21}, - {DVBT_KRF1, 0x0}, - {DVBT_KRF2, 0x40}, - {DVBT_KRF3, 0x10}, - {DVBT_KRF4, 0x10}, - {DVBT_IF_AGC_MIN, 0x80}, - {DVBT_IF_AGC_MAX, 0x7f}, - {DVBT_RF_AGC_MIN, 0x80}, - {DVBT_RF_AGC_MAX, 0x7f}, - {DVBT_POLAR_RF_AGC, 0x0}, - {DVBT_POLAR_IF_AGC, 0x0}, - {DVBT_AD7_SETTING, 0xe9bf}, - {DVBT_EN_GI_PGA, 0x0}, - {DVBT_THD_LOCK_UP, 0x0}, - {DVBT_THD_LOCK_DW, 0x0}, - {DVBT_THD_UP1, 0x11}, - {DVBT_THD_DW1, 0xef}, - {DVBT_INTER_CNT_LEN, 0xc}, - {DVBT_GI_PGA_STATE, 0x0}, - {DVBT_EN_AGC_PGA, 0x1}, - {DVBT_IF_AGC_MAN, 0x0}, }; - - dbg("%s", __func__); + dev_dbg(&priv->i2c->dev, "%s:\n", __func__); en_bbin = (priv->cfg.if_dvbt == 0 ? 0x1 : 0x0); @@ -480,8 +448,6 @@ static int rtl2832_init(struct dvb_frontend *fe) pset_iffreq = div_u64(pset_iffreq, priv->cfg.xtal); pset_iffreq = pset_iffreq & 0x3fffff; - - for (i = 0; i < ARRAY_SIZE(rtl2832_initial_regs); i++) { ret = rtl2832_wr_demod_reg(priv, rtl2832_initial_regs[i].reg, rtl2832_initial_regs[i].value); @@ -489,6 +455,34 @@ static int rtl2832_init(struct dvb_frontend *fe) goto err; } + /* load tuner specific settings */ + dev_dbg(&priv->i2c->dev, "%s: load settings for tuner=%02x\n", + __func__, priv->cfg.tuner); + switch (priv->cfg.tuner) { + case RTL2832_TUNER_FC0012: + case RTL2832_TUNER_FC0013: + len = ARRAY_SIZE(rtl2832_tuner_init_fc0012); + init = rtl2832_tuner_init_fc0012; + break; + case RTL2832_TUNER_TUA9001: + len = ARRAY_SIZE(rtl2832_tuner_init_tua9001); + init = rtl2832_tuner_init_tua9001; + break; + case RTL2832_TUNER_E4000: + len = ARRAY_SIZE(rtl2832_tuner_init_e4000); + init = rtl2832_tuner_init_e4000; + break; + default: + ret = -EINVAL; + goto err; + } + + for (i = 0; i < len; i++) { + ret = rtl2832_wr_demod_reg(priv, init[i].reg, init[i].value); + if (ret) + goto err; + } + /* if frequency settings */ ret = rtl2832_wr_demod_reg(priv, DVBT_EN_BBIN, en_bbin); if (ret) @@ -503,7 +497,7 @@ static int rtl2832_init(struct dvb_frontend *fe) return ret; err: - dbg("%s: failed=%d", __func__, ret); + dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); return ret; } @@ -511,7 +505,7 @@ static int rtl2832_sleep(struct dvb_frontend *fe) { struct rtl2832_priv *priv = fe->demodulator_priv; - dbg("%s", __func__); + dev_dbg(&priv->i2c->dev, "%s:\n", __func__); priv->sleeping = true; return 0; } @@ -519,7 +513,9 @@ static int rtl2832_sleep(struct dvb_frontend *fe) int rtl2832_get_tune_settings(struct dvb_frontend *fe, struct dvb_frontend_tune_settings *s) { - dbg("%s", __func__); + struct rtl2832_priv *priv = fe->demodulator_priv; + + dev_dbg(&priv->i2c->dev, "%s:\n", __func__); s->min_delay_ms = 1000; s->step_size = fe->ops.info.frequency_stepsize * 2; s->max_drift = (fe->ops.info.frequency_stepsize * 2) + 1; @@ -533,8 +529,6 @@ static int rtl2832_set_frontend(struct dvb_frontend *fe) int ret, i, j; u64 bw_mode, num, num2; u32 resamp_ratio, cfreq_off_ratio; - - static u8 bw_params[3][32] = { /* 6 MHz bandwidth */ { @@ -562,15 +556,14 @@ static int rtl2832_set_frontend(struct dvb_frontend *fe) }; - dbg("%s: frequency=%d bandwidth_hz=%d inversion=%d", __func__, - c->frequency, c->bandwidth_hz, c->inversion); - + dev_dbg(&priv->i2c->dev, "%s: frequency=%d bandwidth_hz=%d " \ + "inversion=%d\n", __func__, c->frequency, + c->bandwidth_hz, c->inversion); /* program tuner */ if (fe->ops.tuner_ops.set_params) fe->ops.tuner_ops.set_params(fe); - switch (c->bandwidth_hz) { case 6000000: i = 0; @@ -585,7 +578,7 @@ static int rtl2832_set_frontend(struct dvb_frontend *fe) bw_mode = 64000000; break; default: - dbg("invalid bandwidth"); + dev_dbg(&priv->i2c->dev, "%s: invalid bandwidth\n", __func__); return -EINVAL; } @@ -632,7 +625,119 @@ static int rtl2832_set_frontend(struct dvb_frontend *fe) return ret; err: - info("%s: failed=%d", __func__, ret); + dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); + return ret; +} + +static int rtl2832_get_frontend(struct dvb_frontend *fe) +{ + struct rtl2832_priv *priv = fe->demodulator_priv; + struct dtv_frontend_properties *c = &fe->dtv_property_cache; + int ret; + u8 buf[3]; + + if (priv->sleeping) + return 0; + + ret = rtl2832_rd_regs(priv, 0x3c, 3, buf, 2); + if (ret) + goto err; + + ret = rtl2832_rd_reg(priv, 0x51, 3, &buf[2]); + if (ret) + goto err; + + dev_dbg(&priv->i2c->dev, "%s: TPS=%*ph\n", __func__, 3, buf); + + switch ((buf[0] >> 2) & 3) { + case 0: + c->modulation = QPSK; + break; + case 1: + c->modulation = QAM_16; + break; + case 2: + c->modulation = QAM_64; + break; + } + + switch ((buf[2] >> 2) & 1) { + case 0: + c->transmission_mode = TRANSMISSION_MODE_2K; + break; + case 1: + c->transmission_mode = TRANSMISSION_MODE_8K; + } + + switch ((buf[2] >> 0) & 3) { + case 0: + c->guard_interval = GUARD_INTERVAL_1_32; + break; + case 1: + c->guard_interval = GUARD_INTERVAL_1_16; + break; + case 2: + c->guard_interval = GUARD_INTERVAL_1_8; + break; + case 3: + c->guard_interval = GUARD_INTERVAL_1_4; + break; + } + + switch ((buf[0] >> 4) & 7) { + case 0: + c->hierarchy = HIERARCHY_NONE; + break; + case 1: + c->hierarchy = HIERARCHY_1; + break; + case 2: + c->hierarchy = HIERARCHY_2; + break; + case 3: + c->hierarchy = HIERARCHY_4; + break; + } + + switch ((buf[1] >> 3) & 7) { + case 0: + c->code_rate_HP = FEC_1_2; + break; + case 1: + c->code_rate_HP = FEC_2_3; + break; + case 2: + c->code_rate_HP = FEC_3_4; + break; + case 3: + c->code_rate_HP = FEC_5_6; + break; + case 4: + c->code_rate_HP = FEC_7_8; + break; + } + + switch ((buf[1] >> 0) & 7) { + case 0: + c->code_rate_LP = FEC_1_2; + break; + case 1: + c->code_rate_LP = FEC_2_3; + break; + case 2: + c->code_rate_LP = FEC_3_4; + break; + case 3: + c->code_rate_LP = FEC_5_6; + break; + case 4: + c->code_rate_LP = FEC_7_8; + break; + } + + return 0; +err: + dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); return ret; } @@ -643,8 +748,7 @@ static int rtl2832_read_status(struct dvb_frontend *fe, fe_status_t *status) u32 tmp; *status = 0; - - dbg("%s", __func__); + dev_dbg(&priv->i2c->dev, "%s:\n", __func__); if (priv->sleeping) return 0; @@ -664,33 +768,72 @@ static int rtl2832_read_status(struct dvb_frontend *fe, fe_status_t *status) return ret; err: - info("%s: failed=%d", __func__, ret); + dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); return ret; } static int rtl2832_read_snr(struct dvb_frontend *fe, u16 *snr) { - *snr = 0; + struct rtl2832_priv *priv = fe->demodulator_priv; + int ret, hierarchy, constellation; + u8 buf[2], tmp; + u16 tmp16; +#define CONSTELLATION_NUM 3 +#define HIERARCHY_NUM 4 + static const u32 snr_constant[CONSTELLATION_NUM][HIERARCHY_NUM] = { + { 85387325, 85387325, 85387325, 85387325 }, + { 86676178, 86676178, 87167949, 87795660 }, + { 87659938, 87659938, 87885178, 88241743 }, + }; + + /* reports SNR in resolution of 0.1 dB */ + + ret = rtl2832_rd_reg(priv, 0x3c, 3, &tmp); + if (ret) + goto err; + + constellation = (tmp >> 2) & 0x03; /* [3:2] */ + if (constellation > CONSTELLATION_NUM - 1) + goto err; + + hierarchy = (tmp >> 4) & 0x07; /* [6:4] */ + if (hierarchy > HIERARCHY_NUM - 1) + goto err; + + ret = rtl2832_rd_regs(priv, 0x0c, 4, buf, 2); + if (ret) + goto err; + + tmp16 = buf[0] << 8 | buf[1]; + + if (tmp16) + *snr = (snr_constant[constellation][hierarchy] - + intlog10(tmp16)) / ((1 << 24) / 100); + else + *snr = 0; + return 0; +err: + dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); + return ret; } static int rtl2832_read_ber(struct dvb_frontend *fe, u32 *ber) { - *ber = 0; - return 0; -} + struct rtl2832_priv *priv = fe->demodulator_priv; + int ret; + u8 buf[2]; -static int rtl2832_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) -{ - *ucblocks = 0; - return 0; -} + ret = rtl2832_rd_regs(priv, 0x4e, 3, buf, 2); + if (ret) + goto err; + *ber = buf[0] << 8 | buf[1]; -static int rtl2832_read_signal_strength(struct dvb_frontend *fe, u16 *strength) -{ - *strength = 0; return 0; +err: + dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); + return ret; } static struct dvb_frontend_ops rtl2832_ops; @@ -699,7 +842,7 @@ static void rtl2832_release(struct dvb_frontend *fe) { struct rtl2832_priv *priv = fe->demodulator_priv; - dbg("%s", __func__); + dev_dbg(&priv->i2c->dev, "%s:\n", __func__); kfree(priv); } @@ -710,7 +853,7 @@ struct dvb_frontend *rtl2832_attach(const struct rtl2832_config *cfg, int ret = 0; u8 tmp; - dbg("%s", __func__); + dev_dbg(&i2c->dev, "%s:\n", __func__); /* allocate memory for the internal state */ priv = kzalloc(sizeof(struct rtl2832_priv), GFP_KERNEL); @@ -736,7 +879,7 @@ struct dvb_frontend *rtl2832_attach(const struct rtl2832_config *cfg, return &priv->fe; err: - dbg("%s: failed=%d", __func__, ret); + dev_dbg(&i2c->dev, "%s: failed=%d\n", __func__, ret); kfree(priv); return NULL; } @@ -774,12 +917,12 @@ static struct dvb_frontend_ops rtl2832_ops = { .get_tune_settings = rtl2832_get_tune_settings, .set_frontend = rtl2832_set_frontend, + .get_frontend = rtl2832_get_frontend, .read_status = rtl2832_read_status, .read_snr = rtl2832_read_snr, .read_ber = rtl2832_read_ber, - .read_ucblocks = rtl2832_read_ucblocks, - .read_signal_strength = rtl2832_read_signal_strength, + .i2c_gate_ctrl = rtl2832_i2c_gate_ctrl, }; diff --git a/drivers/media/dvb/frontends/rtl2832.h b/drivers/media/dvb-frontends/rtl2832.h index d94dc9a3fa62..785a466eb065 100644 --- a/drivers/media/dvb/frontends/rtl2832.h +++ b/drivers/media/dvb-frontends/rtl2832.h @@ -44,28 +44,29 @@ struct rtl2832_config { u32 if_dvbt; /* + * tuner + * XXX: This must be keep sync with dvb_usb_rtl28xxu demod driver. */ +#define RTL2832_TUNER_TUA9001 0x24 +#define RTL2832_TUNER_FC0012 0x26 +#define RTL2832_TUNER_E4000 0x27 +#define RTL2832_TUNER_FC0013 0x29 u8 tuner; }; - #if defined(CONFIG_DVB_RTL2832) || \ (defined(CONFIG_DVB_RTL2832_MODULE) && defined(MODULE)) extern struct dvb_frontend *rtl2832_attach( const struct rtl2832_config *cfg, struct i2c_adapter *i2c ); - -extern struct i2c_adapter *rtl2832_get_tuner_i2c_adapter( - struct dvb_frontend *fe -); #else static inline struct dvb_frontend *rtl2832_attach( const struct rtl2832_config *config, struct i2c_adapter *i2c ) { - printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); + pr_warn("%s: driver disabled by Kconfig\n", __func__); return NULL; } #endif diff --git a/drivers/media/dvb/frontends/rtl2832_priv.h b/drivers/media/dvb-frontends/rtl2832_priv.h index 0ce9502da8ba..7d97ce9d2193 100644 --- a/drivers/media/dvb/frontends/rtl2832_priv.h +++ b/drivers/media/dvb-frontends/rtl2832_priv.h @@ -24,21 +24,6 @@ #include "dvb_frontend.h" #include "rtl2832.h" -#define LOG_PREFIX "rtl2832" - -#undef dbg -#define dbg(f, arg...) \ -do { \ - if (rtl2832_debug) \ - printk(KERN_INFO LOG_PREFIX": " f "\n" , ## arg); \ -} while (0) -#undef err -#define err(f, arg...) printk(KERN_ERR LOG_PREFIX": " f "\n" , ## arg) -#undef info -#define info(f, arg...) printk(KERN_INFO LOG_PREFIX": " f "\n" , ## arg) -#undef warn -#define warn(f, arg...) printk(KERN_WARNING LOG_PREFIX": " f "\n" , ## arg) - struct rtl2832_priv { struct i2c_adapter *i2c; struct dvb_frontend fe; @@ -257,4 +242,101 @@ enum DVBT_REG_BIT_NAME { DVBT_REG_BIT_NAME_ITEM_TERMINATOR, }; +static const struct rtl2832_reg_value rtl2832_tuner_init_tua9001[] = { + {DVBT_DAGC_TRG_VAL, 0x39}, + {DVBT_AGC_TARG_VAL_0, 0x0}, + {DVBT_AGC_TARG_VAL_8_1, 0x5a}, + {DVBT_AAGC_LOOP_GAIN, 0x16}, + {DVBT_LOOP_GAIN2_3_0, 0x6}, + {DVBT_LOOP_GAIN2_4, 0x1}, + {DVBT_LOOP_GAIN3, 0x16}, + {DVBT_VTOP1, 0x35}, + {DVBT_VTOP2, 0x21}, + {DVBT_VTOP3, 0x21}, + {DVBT_KRF1, 0x0}, + {DVBT_KRF2, 0x40}, + {DVBT_KRF3, 0x10}, + {DVBT_KRF4, 0x10}, + {DVBT_IF_AGC_MIN, 0x80}, + {DVBT_IF_AGC_MAX, 0x7f}, + {DVBT_RF_AGC_MIN, 0x9c}, + {DVBT_RF_AGC_MAX, 0x7f}, + {DVBT_POLAR_RF_AGC, 0x0}, + {DVBT_POLAR_IF_AGC, 0x0}, + {DVBT_AD7_SETTING, 0xe9f4}, + {DVBT_OPT_ADC_IQ, 0x1}, + {DVBT_AD_AVI, 0x0}, + {DVBT_AD_AVQ, 0x0}, +}; + +static const struct rtl2832_reg_value rtl2832_tuner_init_fc0012[] = { + {DVBT_DAGC_TRG_VAL, 0x5a}, + {DVBT_AGC_TARG_VAL_0, 0x0}, + {DVBT_AGC_TARG_VAL_8_1, 0x5a}, + {DVBT_AAGC_LOOP_GAIN, 0x16}, + {DVBT_LOOP_GAIN2_3_0, 0x6}, + {DVBT_LOOP_GAIN2_4, 0x1}, + {DVBT_LOOP_GAIN3, 0x16}, + {DVBT_VTOP1, 0x35}, + {DVBT_VTOP2, 0x21}, + {DVBT_VTOP3, 0x21}, + {DVBT_KRF1, 0x0}, + {DVBT_KRF2, 0x40}, + {DVBT_KRF3, 0x10}, + {DVBT_KRF4, 0x10}, + {DVBT_IF_AGC_MIN, 0x80}, + {DVBT_IF_AGC_MAX, 0x7f}, + {DVBT_RF_AGC_MIN, 0x80}, + {DVBT_RF_AGC_MAX, 0x7f}, + {DVBT_POLAR_RF_AGC, 0x0}, + {DVBT_POLAR_IF_AGC, 0x0}, + {DVBT_AD7_SETTING, 0xe9bf}, + {DVBT_EN_GI_PGA, 0x0}, + {DVBT_THD_LOCK_UP, 0x0}, + {DVBT_THD_LOCK_DW, 0x0}, + {DVBT_THD_UP1, 0x11}, + {DVBT_THD_DW1, 0xef}, + {DVBT_INTER_CNT_LEN, 0xc}, + {DVBT_GI_PGA_STATE, 0x0}, + {DVBT_EN_AGC_PGA, 0x1}, + {DVBT_IF_AGC_MAN, 0x0}, +}; + +static const struct rtl2832_reg_value rtl2832_tuner_init_e4000[] = { + {DVBT_DAGC_TRG_VAL, 0x5a}, + {DVBT_AGC_TARG_VAL_0, 0x0}, + {DVBT_AGC_TARG_VAL_8_1, 0x5a}, + {DVBT_AAGC_LOOP_GAIN, 0x18}, + {DVBT_LOOP_GAIN2_3_0, 0x8}, + {DVBT_LOOP_GAIN2_4, 0x1}, + {DVBT_LOOP_GAIN3, 0x18}, + {DVBT_VTOP1, 0x35}, + {DVBT_VTOP2, 0x21}, + {DVBT_VTOP3, 0x21}, + {DVBT_KRF1, 0x0}, + {DVBT_KRF2, 0x40}, + {DVBT_KRF3, 0x10}, + {DVBT_KRF4, 0x10}, + {DVBT_IF_AGC_MIN, 0x80}, + {DVBT_IF_AGC_MAX, 0x7f}, + {DVBT_RF_AGC_MIN, 0x80}, + {DVBT_RF_AGC_MAX, 0x7f}, + {DVBT_POLAR_RF_AGC, 0x0}, + {DVBT_POLAR_IF_AGC, 0x0}, + {DVBT_AD7_SETTING, 0xe9d4}, + {DVBT_EN_GI_PGA, 0x0}, + {DVBT_THD_LOCK_UP, 0x0}, + {DVBT_THD_LOCK_DW, 0x0}, + {DVBT_THD_UP1, 0x14}, + {DVBT_THD_DW1, 0xec}, + {DVBT_INTER_CNT_LEN, 0xc}, + {DVBT_GI_PGA_STATE, 0x0}, + {DVBT_EN_AGC_PGA, 0x1}, + {DVBT_REG_GPE, 0x1}, + {DVBT_REG_GPO, 0x1}, + {DVBT_REG_MONSEL, 0x1}, + {DVBT_REG_MON, 0x1}, + {DVBT_REG_4MSEL, 0x0}, +}; + #endif /* RTL2832_PRIV_H */ diff --git a/drivers/media/dvb/frontends/s5h1409.c b/drivers/media/dvb-frontends/s5h1409.c index f71b06221e14..f71b06221e14 100644 --- a/drivers/media/dvb/frontends/s5h1409.c +++ b/drivers/media/dvb-frontends/s5h1409.c diff --git a/drivers/media/dvb/frontends/s5h1409.h b/drivers/media/dvb-frontends/s5h1409.h index 91f2ebd1a534..91f2ebd1a534 100644 --- a/drivers/media/dvb/frontends/s5h1409.h +++ b/drivers/media/dvb-frontends/s5h1409.h diff --git a/drivers/media/dvb/frontends/s5h1411.c b/drivers/media/dvb-frontends/s5h1411.c index 6cc4b7a9dd60..6cc4b7a9dd60 100644 --- a/drivers/media/dvb/frontends/s5h1411.c +++ b/drivers/media/dvb-frontends/s5h1411.c diff --git a/drivers/media/dvb/frontends/s5h1411.h b/drivers/media/dvb-frontends/s5h1411.h index 45ec0f82989c..45ec0f82989c 100644 --- a/drivers/media/dvb/frontends/s5h1411.h +++ b/drivers/media/dvb-frontends/s5h1411.h diff --git a/drivers/media/dvb/frontends/s5h1420.c b/drivers/media/dvb-frontends/s5h1420.c index e2fec9ebf947..e2fec9ebf947 100644 --- a/drivers/media/dvb/frontends/s5h1420.c +++ b/drivers/media/dvb-frontends/s5h1420.c diff --git a/drivers/media/dvb/frontends/s5h1420.h b/drivers/media/dvb-frontends/s5h1420.h index ff308136d865..ff308136d865 100644 --- a/drivers/media/dvb/frontends/s5h1420.h +++ b/drivers/media/dvb-frontends/s5h1420.h diff --git a/drivers/media/dvb/frontends/s5h1420_priv.h b/drivers/media/dvb-frontends/s5h1420_priv.h index d9c58d281816..d9c58d281816 100644 --- a/drivers/media/dvb/frontends/s5h1420_priv.h +++ b/drivers/media/dvb-frontends/s5h1420_priv.h diff --git a/drivers/media/dvb/frontends/s5h1432.c b/drivers/media/dvb-frontends/s5h1432.c index 8352ce1c9556..8352ce1c9556 100644 --- a/drivers/media/dvb/frontends/s5h1432.c +++ b/drivers/media/dvb-frontends/s5h1432.c diff --git a/drivers/media/dvb/frontends/s5h1432.h b/drivers/media/dvb-frontends/s5h1432.h index b57438c32546..b57438c32546 100644 --- a/drivers/media/dvb/frontends/s5h1432.h +++ b/drivers/media/dvb-frontends/s5h1432.h diff --git a/drivers/media/dvb/frontends/s921.c b/drivers/media/dvb-frontends/s921.c index cd2288c07147..cd2288c07147 100644 --- a/drivers/media/dvb/frontends/s921.c +++ b/drivers/media/dvb-frontends/s921.c diff --git a/drivers/media/dvb/frontends/s921.h b/drivers/media/dvb-frontends/s921.h index f220d8299c81..f220d8299c81 100644 --- a/drivers/media/dvb/frontends/s921.h +++ b/drivers/media/dvb-frontends/s921.h diff --git a/drivers/media/dvb/frontends/si21xx.c b/drivers/media/dvb-frontends/si21xx.c index a68a64800df7..a68a64800df7 100644 --- a/drivers/media/dvb/frontends/si21xx.c +++ b/drivers/media/dvb-frontends/si21xx.c diff --git a/drivers/media/dvb/frontends/si21xx.h b/drivers/media/dvb-frontends/si21xx.h index 141b5b8a5f63..141b5b8a5f63 100644 --- a/drivers/media/dvb/frontends/si21xx.h +++ b/drivers/media/dvb-frontends/si21xx.h diff --git a/drivers/media/dvb/frontends/sp8870.c b/drivers/media/dvb-frontends/sp8870.c index e37274c8f14e..e37274c8f14e 100644 --- a/drivers/media/dvb/frontends/sp8870.c +++ b/drivers/media/dvb-frontends/sp8870.c diff --git a/drivers/media/dvb/frontends/sp8870.h b/drivers/media/dvb-frontends/sp8870.h index a764a793c7d8..a764a793c7d8 100644 --- a/drivers/media/dvb/frontends/sp8870.h +++ b/drivers/media/dvb-frontends/sp8870.h diff --git a/drivers/media/dvb/frontends/sp887x.c b/drivers/media/dvb-frontends/sp887x.c index f4096ccb226e..f4096ccb226e 100644 --- a/drivers/media/dvb/frontends/sp887x.c +++ b/drivers/media/dvb-frontends/sp887x.c diff --git a/drivers/media/dvb/frontends/sp887x.h b/drivers/media/dvb-frontends/sp887x.h index 04eff6e0eef3..04eff6e0eef3 100644 --- a/drivers/media/dvb/frontends/sp887x.h +++ b/drivers/media/dvb-frontends/sp887x.h diff --git a/drivers/media/dvb/frontends/stb0899_algo.c b/drivers/media/dvb-frontends/stb0899_algo.c index 117a56926dca..117a56926dca 100644 --- a/drivers/media/dvb/frontends/stb0899_algo.c +++ b/drivers/media/dvb-frontends/stb0899_algo.c diff --git a/drivers/media/dvb/frontends/stb0899_cfg.h b/drivers/media/dvb-frontends/stb0899_cfg.h index 0867906d3ff3..0867906d3ff3 100644 --- a/drivers/media/dvb/frontends/stb0899_cfg.h +++ b/drivers/media/dvb-frontends/stb0899_cfg.h diff --git a/drivers/media/dvb/frontends/stb0899_drv.c b/drivers/media/dvb-frontends/stb0899_drv.c index 5d7f8a9b451b..79e29de87fb7 100644 --- a/drivers/media/dvb/frontends/stb0899_drv.c +++ b/drivers/media/dvb-frontends/stb0899_drv.c @@ -1563,6 +1563,7 @@ static int stb0899_get_frontend(struct dvb_frontend *fe) dprintk(state->verbose, FE_DEBUG, 1, "Get params"); p->symbol_rate = internal->srate; + p->frequency = internal->freq; return 0; } diff --git a/drivers/media/dvb/frontends/stb0899_drv.h b/drivers/media/dvb-frontends/stb0899_drv.h index 98b200ce0c34..98b200ce0c34 100644 --- a/drivers/media/dvb/frontends/stb0899_drv.h +++ b/drivers/media/dvb-frontends/stb0899_drv.h diff --git a/drivers/media/dvb/frontends/stb0899_priv.h b/drivers/media/dvb-frontends/stb0899_priv.h index 82395b912815..82395b912815 100644 --- a/drivers/media/dvb/frontends/stb0899_priv.h +++ b/drivers/media/dvb-frontends/stb0899_priv.h diff --git a/drivers/media/dvb/frontends/stb0899_reg.h b/drivers/media/dvb-frontends/stb0899_reg.h index ba1ed56304a0..ba1ed56304a0 100644 --- a/drivers/media/dvb/frontends/stb0899_reg.h +++ b/drivers/media/dvb-frontends/stb0899_reg.h diff --git a/drivers/media/dvb/frontends/stb6000.c b/drivers/media/dvb-frontends/stb6000.c index a0c3c526b132..a0c3c526b132 100644 --- a/drivers/media/dvb/frontends/stb6000.c +++ b/drivers/media/dvb-frontends/stb6000.c diff --git a/drivers/media/dvb/frontends/stb6000.h b/drivers/media/dvb-frontends/stb6000.h index 7be479c22d5b..7be479c22d5b 100644 --- a/drivers/media/dvb/frontends/stb6000.h +++ b/drivers/media/dvb-frontends/stb6000.h diff --git a/drivers/media/dvb/frontends/stb6100.c b/drivers/media/dvb-frontends/stb6100.c index 2e93e65d2cdb..2e93e65d2cdb 100644 --- a/drivers/media/dvb/frontends/stb6100.c +++ b/drivers/media/dvb-frontends/stb6100.c diff --git a/drivers/media/dvb/frontends/stb6100.h b/drivers/media/dvb-frontends/stb6100.h index 2ab096614b3f..2ab096614b3f 100644 --- a/drivers/media/dvb/frontends/stb6100.h +++ b/drivers/media/dvb-frontends/stb6100.h diff --git a/drivers/media/dvb/frontends/stb6100_cfg.h b/drivers/media/dvb-frontends/stb6100_cfg.h index 6314d18c797a..6314d18c797a 100644 --- a/drivers/media/dvb/frontends/stb6100_cfg.h +++ b/drivers/media/dvb-frontends/stb6100_cfg.h diff --git a/drivers/media/dvb/frontends/stb6100_proc.h b/drivers/media/dvb-frontends/stb6100_proc.h index 112163a48622..112163a48622 100644 --- a/drivers/media/dvb/frontends/stb6100_proc.h +++ b/drivers/media/dvb-frontends/stb6100_proc.h diff --git a/drivers/media/dvb/frontends/stv0288.c b/drivers/media/dvb-frontends/stv0288.c index 632b25156e4c..632b25156e4c 100644 --- a/drivers/media/dvb/frontends/stv0288.c +++ b/drivers/media/dvb-frontends/stv0288.c diff --git a/drivers/media/dvb/frontends/stv0288.h b/drivers/media/dvb-frontends/stv0288.h index f2b53db0606d..f2b53db0606d 100644 --- a/drivers/media/dvb/frontends/stv0288.h +++ b/drivers/media/dvb-frontends/stv0288.h diff --git a/drivers/media/dvb/frontends/stv0297.c b/drivers/media/dvb-frontends/stv0297.c index d40f226160ef..d40f226160ef 100644 --- a/drivers/media/dvb/frontends/stv0297.c +++ b/drivers/media/dvb-frontends/stv0297.c diff --git a/drivers/media/dvb/frontends/stv0297.h b/drivers/media/dvb-frontends/stv0297.h index 3f8f9468f387..3f8f9468f387 100644 --- a/drivers/media/dvb/frontends/stv0297.h +++ b/drivers/media/dvb-frontends/stv0297.h diff --git a/drivers/media/dvb/frontends/stv0299.c b/drivers/media/dvb-frontends/stv0299.c index 057b5f8effc0..057b5f8effc0 100644 --- a/drivers/media/dvb/frontends/stv0299.c +++ b/drivers/media/dvb-frontends/stv0299.c diff --git a/drivers/media/dvb/frontends/stv0299.h b/drivers/media/dvb-frontends/stv0299.h index ba219b767a69..ba219b767a69 100644 --- a/drivers/media/dvb/frontends/stv0299.h +++ b/drivers/media/dvb-frontends/stv0299.h diff --git a/drivers/media/dvb/frontends/stv0367.c b/drivers/media/dvb-frontends/stv0367.c index 2a8aaeb1112d..2a8aaeb1112d 100644 --- a/drivers/media/dvb/frontends/stv0367.c +++ b/drivers/media/dvb-frontends/stv0367.c diff --git a/drivers/media/dvb/frontends/stv0367.h b/drivers/media/dvb-frontends/stv0367.h index 93cc4a57eea0..93cc4a57eea0 100644 --- a/drivers/media/dvb/frontends/stv0367.h +++ b/drivers/media/dvb-frontends/stv0367.h diff --git a/drivers/media/dvb/frontends/stv0367_priv.h b/drivers/media/dvb-frontends/stv0367_priv.h index 995db0689ddd..995db0689ddd 100644 --- a/drivers/media/dvb/frontends/stv0367_priv.h +++ b/drivers/media/dvb-frontends/stv0367_priv.h diff --git a/drivers/media/dvb/frontends/stv0367_regs.h b/drivers/media/dvb-frontends/stv0367_regs.h index a96fbdc7e25e..a96fbdc7e25e 100644 --- a/drivers/media/dvb/frontends/stv0367_regs.h +++ b/drivers/media/dvb-frontends/stv0367_regs.h diff --git a/drivers/media/dvb/frontends/stv0900.h b/drivers/media/dvb-frontends/stv0900.h index 91c7ee8b2313..91c7ee8b2313 100644 --- a/drivers/media/dvb/frontends/stv0900.h +++ b/drivers/media/dvb-frontends/stv0900.h diff --git a/drivers/media/dvb/frontends/stv0900_core.c b/drivers/media/dvb-frontends/stv0900_core.c index 7f1badaf0d03..7f1badaf0d03 100644 --- a/drivers/media/dvb/frontends/stv0900_core.c +++ b/drivers/media/dvb-frontends/stv0900_core.c diff --git a/drivers/media/dvb/frontends/stv0900_init.h b/drivers/media/dvb-frontends/stv0900_init.h index b684df9995d8..b684df9995d8 100644 --- a/drivers/media/dvb/frontends/stv0900_init.h +++ b/drivers/media/dvb-frontends/stv0900_init.h diff --git a/drivers/media/dvb/frontends/stv0900_priv.h b/drivers/media/dvb-frontends/stv0900_priv.h index e0ea74c8e093..e0ea74c8e093 100644 --- a/drivers/media/dvb/frontends/stv0900_priv.h +++ b/drivers/media/dvb-frontends/stv0900_priv.h diff --git a/drivers/media/dvb/frontends/stv0900_reg.h b/drivers/media/dvb-frontends/stv0900_reg.h index 731afe93a823..731afe93a823 100644 --- a/drivers/media/dvb/frontends/stv0900_reg.h +++ b/drivers/media/dvb-frontends/stv0900_reg.h diff --git a/drivers/media/dvb/frontends/stv0900_sw.c b/drivers/media/dvb-frontends/stv0900_sw.c index 4af20780fb9c..4af20780fb9c 100644 --- a/drivers/media/dvb/frontends/stv0900_sw.c +++ b/drivers/media/dvb-frontends/stv0900_sw.c diff --git a/drivers/media/dvb/frontends/stv090x.c b/drivers/media/dvb-frontends/stv090x.c index ea86a5603e57..13caec013902 100644 --- a/drivers/media/dvb/frontends/stv090x.c +++ b/drivers/media/dvb-frontends/stv090x.c @@ -3425,6 +3425,33 @@ err: return -1; } +static int stv090x_set_mis(struct stv090x_state *state, int mis) +{ + u32 reg; + + if (mis < 0 || mis > 255) { + dprintk(FE_DEBUG, 1, "Disable MIS filtering"); + reg = STV090x_READ_DEMOD(state, PDELCTRL1); + STV090x_SETFIELD_Px(reg, FILTER_EN_FIELD, 0x00); + if (STV090x_WRITE_DEMOD(state, PDELCTRL1, reg) < 0) + goto err; + } else { + dprintk(FE_DEBUG, 1, "Enable MIS filtering - %d", mis); + reg = STV090x_READ_DEMOD(state, PDELCTRL1); + STV090x_SETFIELD_Px(reg, FILTER_EN_FIELD, 0x01); + if (STV090x_WRITE_DEMOD(state, PDELCTRL1, reg) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, ISIENTRY, mis) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, ISIBITENA, 0xff) < 0) + goto err; + } + return 0; +err: + dprintk(FE_ERROR, 1, "I/O error"); + return -1; +} + static enum dvbfe_search stv090x_search(struct dvb_frontend *fe) { struct stv090x_state *state = fe->demodulator_priv; @@ -3447,6 +3474,8 @@ static enum dvbfe_search stv090x_search(struct dvb_frontend *fe) state->search_range = 5000000; } + stv090x_set_mis(state, props->stream_id); + if (stv090x_algo(state) == STV090x_RANGEOK) { dprintk(FE_DEBUG, 1, "Search success!"); return DVBFE_ALGO_SEARCH_SUCCESS; @@ -4798,6 +4827,9 @@ struct dvb_frontend *stv090x_attach(const struct stv090x_config *config, } } + if (state->internal->dev_ver >= 0x30) + state->frontend.ops.info.caps |= FE_CAN_MULTISTREAM; + /* workaround for stuck DiSEqC output */ if (config->diseqc_envelope_mode) stv090x_send_diseqc_burst(&state->frontend, SEC_MINI_A); diff --git a/drivers/media/dvb/frontends/stv090x.h b/drivers/media/dvb-frontends/stv090x.h index 29cdc2b71314..29cdc2b71314 100644 --- a/drivers/media/dvb/frontends/stv090x.h +++ b/drivers/media/dvb-frontends/stv090x.h diff --git a/drivers/media/dvb/frontends/stv090x_priv.h b/drivers/media/dvb-frontends/stv090x_priv.h index 5b780c80d496..5b780c80d496 100644 --- a/drivers/media/dvb/frontends/stv090x_priv.h +++ b/drivers/media/dvb-frontends/stv090x_priv.h diff --git a/drivers/media/dvb/frontends/stv090x_reg.h b/drivers/media/dvb-frontends/stv090x_reg.h index 93741ee14297..93741ee14297 100644 --- a/drivers/media/dvb/frontends/stv090x_reg.h +++ b/drivers/media/dvb-frontends/stv090x_reg.h diff --git a/drivers/media/dvb/frontends/stv6110.c b/drivers/media/dvb-frontends/stv6110.c index 20b5fa92c53e..20b5fa92c53e 100644 --- a/drivers/media/dvb/frontends/stv6110.c +++ b/drivers/media/dvb-frontends/stv6110.c diff --git a/drivers/media/dvb/frontends/stv6110.h b/drivers/media/dvb-frontends/stv6110.h index fe71bba6a26e..fe71bba6a26e 100644 --- a/drivers/media/dvb/frontends/stv6110.h +++ b/drivers/media/dvb-frontends/stv6110.h diff --git a/drivers/media/dvb/frontends/stv6110x.c b/drivers/media/dvb-frontends/stv6110x.c index f36cab12bdc7..f36cab12bdc7 100644 --- a/drivers/media/dvb/frontends/stv6110x.c +++ b/drivers/media/dvb-frontends/stv6110x.c diff --git a/drivers/media/dvb/frontends/stv6110x.h b/drivers/media/dvb-frontends/stv6110x.h index 47516753929a..47516753929a 100644 --- a/drivers/media/dvb/frontends/stv6110x.h +++ b/drivers/media/dvb-frontends/stv6110x.h diff --git a/drivers/media/dvb/frontends/stv6110x_priv.h b/drivers/media/dvb-frontends/stv6110x_priv.h index 0ec936a660a7..0ec936a660a7 100644 --- a/drivers/media/dvb/frontends/stv6110x_priv.h +++ b/drivers/media/dvb-frontends/stv6110x_priv.h diff --git a/drivers/media/dvb/frontends/stv6110x_reg.h b/drivers/media/dvb-frontends/stv6110x_reg.h index 93e5c70e5fd8..93e5c70e5fd8 100644 --- a/drivers/media/dvb/frontends/stv6110x_reg.h +++ b/drivers/media/dvb-frontends/stv6110x_reg.h diff --git a/drivers/media/dvb/frontends/tda10021.c b/drivers/media/dvb-frontends/tda10021.c index 1bff7f457e19..1bff7f457e19 100644 --- a/drivers/media/dvb/frontends/tda10021.c +++ b/drivers/media/dvb-frontends/tda10021.c diff --git a/drivers/media/dvb/frontends/tda10023.c b/drivers/media/dvb-frontends/tda10023.c index ca1e0d54b69a..ca1e0d54b69a 100644 --- a/drivers/media/dvb/frontends/tda10023.c +++ b/drivers/media/dvb-frontends/tda10023.c diff --git a/drivers/media/dvb/frontends/tda1002x.h b/drivers/media/dvb-frontends/tda1002x.h index 04d19418bf20..04d19418bf20 100644 --- a/drivers/media/dvb/frontends/tda1002x.h +++ b/drivers/media/dvb-frontends/tda1002x.h diff --git a/drivers/media/dvb/frontends/tda10048.c b/drivers/media/dvb-frontends/tda10048.c index 71fb63299de7..71fb63299de7 100644 --- a/drivers/media/dvb/frontends/tda10048.c +++ b/drivers/media/dvb-frontends/tda10048.c diff --git a/drivers/media/dvb/frontends/tda10048.h b/drivers/media/dvb-frontends/tda10048.h index fb2ef5ac9487..fb2ef5ac9487 100644 --- a/drivers/media/dvb/frontends/tda10048.h +++ b/drivers/media/dvb-frontends/tda10048.h diff --git a/drivers/media/dvb/frontends/tda1004x.c b/drivers/media/dvb-frontends/tda1004x.c index 35d72b46aa1e..a2631be7ffac 100644 --- a/drivers/media/dvb/frontends/tda1004x.c +++ b/drivers/media/dvb-frontends/tda1004x.c @@ -329,6 +329,7 @@ static int tda1004x_do_upload(struct tda1004x_state *state, tda1004x_write_byteI(state, dspCodeCounterReg, 0); fw_msg.addr = state->config->demod_address; + i2c_lock_adapter(state->i2c); buf[0] = dspCodeInReg; while (pos != len) { // work out how much to send this time @@ -339,15 +340,18 @@ static int tda1004x_do_upload(struct tda1004x_state *state, // send the chunk memcpy(buf + 1, mem + pos, tx_size); fw_msg.len = tx_size + 1; - if (i2c_transfer(state->i2c, &fw_msg, 1) != 1) { + if (__i2c_transfer(state->i2c, &fw_msg, 1) != 1) { printk(KERN_ERR "tda1004x: Error during firmware upload\n"); + i2c_unlock_adapter(state->i2c); return -EIO; } pos += tx_size; dprintk("%s: fw_pos=0x%x\n", __func__, pos); } - // give the DSP a chance to settle 03/10/05 Hac + i2c_unlock_adapter(state->i2c); + + /* give the DSP a chance to settle 03/10/05 Hac */ msleep(100); return 0; diff --git a/drivers/media/dvb/frontends/tda1004x.h b/drivers/media/dvb-frontends/tda1004x.h index 4e27ffb0f14e..4e27ffb0f14e 100644 --- a/drivers/media/dvb/frontends/tda1004x.h +++ b/drivers/media/dvb-frontends/tda1004x.h diff --git a/drivers/media/dvb/frontends/tda10071.c b/drivers/media/dvb-frontends/tda10071.c index 703c3d05f9f4..a83bf6802345 100644 --- a/drivers/media/dvb/frontends/tda10071.c +++ b/drivers/media/dvb-frontends/tda10071.c @@ -257,7 +257,7 @@ static int tda10071_set_voltage(struct dvb_frontend *fe, __func__); ret = -EINVAL; goto error; - }; + } cmd.args[0] = CMD_LNB_SET_DC_LEVEL; cmd.args[1] = 0; @@ -369,7 +369,7 @@ static int tda10071_diseqc_recv_slave_reply(struct dvb_frontend *fe, if (ret) goto error; - reply->msg_len = tmp & 0x1f; /* [4:0] */; + reply->msg_len = tmp & 0x1f; /* [4:0] */ if (reply->msg_len > sizeof(reply->msg)) reply->msg_len = sizeof(reply->msg); /* truncate API max */ @@ -850,7 +850,7 @@ static int tda10071_init(struct dvb_frontend *fe) struct tda10071_cmd cmd; int ret, i, len, remaining, fw_size; const struct firmware *fw; - u8 *fw_file = TDA10071_DEFAULT_FIRMWARE; + u8 *fw_file = TDA10071_FIRMWARE; u8 tmp, buf[4]; struct tda10071_reg_val_mask tab[] = { { 0xcd, 0x00, 0x07 }, @@ -1282,3 +1282,4 @@ static struct dvb_frontend_ops tda10071_ops = { MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>"); MODULE_DESCRIPTION("NXP TDA10071 DVB-S/S2 demodulator driver"); MODULE_LICENSE("GPL"); +MODULE_FIRMWARE(TDA10071_FIRMWARE); diff --git a/drivers/media/dvb/frontends/tda10071.h b/drivers/media/dvb-frontends/tda10071.h index 21163c4b555c..21163c4b555c 100644 --- a/drivers/media/dvb/frontends/tda10071.h +++ b/drivers/media/dvb-frontends/tda10071.h diff --git a/drivers/media/dvb/frontends/tda10071_priv.h b/drivers/media/dvb-frontends/tda10071_priv.h index 0fa85cfa70c2..4baf14bfb65a 100644 --- a/drivers/media/dvb/frontends/tda10071_priv.h +++ b/drivers/media/dvb-frontends/tda10071_priv.h @@ -77,7 +77,7 @@ struct tda10071_reg_val_mask { }; /* firmware filename */ -#define TDA10071_DEFAULT_FIRMWARE "dvb-fe-tda10071.fw" +#define TDA10071_FIRMWARE "dvb-fe-tda10071.fw" /* firmware commands */ #define CMD_DEMOD_INIT 0x10 diff --git a/drivers/media/dvb/frontends/tda10086.c b/drivers/media/dvb-frontends/tda10086.c index fcfe2e080cb0..fcfe2e080cb0 100644 --- a/drivers/media/dvb/frontends/tda10086.c +++ b/drivers/media/dvb-frontends/tda10086.c diff --git a/drivers/media/dvb/frontends/tda10086.h b/drivers/media/dvb-frontends/tda10086.h index 61148c558d8d..61148c558d8d 100644 --- a/drivers/media/dvb/frontends/tda10086.h +++ b/drivers/media/dvb-frontends/tda10086.h diff --git a/drivers/media/dvb/frontends/tda18271c2dd.c b/drivers/media/dvb-frontends/tda18271c2dd.c index ad7c72e8f517..ad7c72e8f517 100644 --- a/drivers/media/dvb/frontends/tda18271c2dd.c +++ b/drivers/media/dvb-frontends/tda18271c2dd.c diff --git a/drivers/media/dvb/frontends/tda18271c2dd.h b/drivers/media/dvb-frontends/tda18271c2dd.h index 1389c74e12ce..1389c74e12ce 100644 --- a/drivers/media/dvb/frontends/tda18271c2dd.h +++ b/drivers/media/dvb-frontends/tda18271c2dd.h diff --git a/drivers/media/dvb/frontends/tda18271c2dd_maps.h b/drivers/media/dvb-frontends/tda18271c2dd_maps.h index b87661b9df14..b87661b9df14 100644 --- a/drivers/media/dvb/frontends/tda18271c2dd_maps.h +++ b/drivers/media/dvb-frontends/tda18271c2dd_maps.h diff --git a/drivers/media/dvb/frontends/tda665x.c b/drivers/media/dvb-frontends/tda665x.c index 2c1c759a4f42..2c1c759a4f42 100644 --- a/drivers/media/dvb/frontends/tda665x.c +++ b/drivers/media/dvb-frontends/tda665x.c diff --git a/drivers/media/dvb/frontends/tda665x.h b/drivers/media/dvb-frontends/tda665x.h index ec7927aa75ae..ec7927aa75ae 100644 --- a/drivers/media/dvb/frontends/tda665x.h +++ b/drivers/media/dvb-frontends/tda665x.h diff --git a/drivers/media/dvb/frontends/tda8083.c b/drivers/media/dvb-frontends/tda8083.c index 15912c96926a..15912c96926a 100644 --- a/drivers/media/dvb/frontends/tda8083.c +++ b/drivers/media/dvb-frontends/tda8083.c diff --git a/drivers/media/dvb/frontends/tda8083.h b/drivers/media/dvb-frontends/tda8083.h index 5a03c14a10e8..5a03c14a10e8 100644 --- a/drivers/media/dvb/frontends/tda8083.h +++ b/drivers/media/dvb-frontends/tda8083.h diff --git a/drivers/media/dvb/frontends/tda8261.c b/drivers/media/dvb-frontends/tda8261.c index 53c7d8f1df28..19c488814e5c 100644 --- a/drivers/media/dvb/frontends/tda8261.c +++ b/drivers/media/dvb-frontends/tda8261.c @@ -43,7 +43,7 @@ static int tda8261_read(struct tda8261_state *state, u8 *buf) struct i2c_msg msg = { .addr = config->addr, .flags = I2C_M_RD,.buf = buf, .len = 1 }; if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) - printk("%s: read error, err=%d\n", __func__, err); + pr_err("%s: read error, err=%d\n", __func__, err); return err; } @@ -55,7 +55,7 @@ static int tda8261_write(struct tda8261_state *state, u8 *buf) struct i2c_msg msg = { .addr = config->addr, .flags = 0, .buf = buf, .len = 4 }; if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) - printk("%s: write error, err=%d\n", __func__, err); + pr_err("%s: write error, err=%d\n", __func__, err); return err; } @@ -69,11 +69,11 @@ static int tda8261_get_status(struct dvb_frontend *fe, u32 *status) *status = 0; if ((err = tda8261_read(state, &result)) < 0) { - printk("%s: I/O Error\n", __func__); + pr_err("%s: I/O Error\n", __func__); return err; } if ((result >> 6) & 0x01) { - printk("%s: Tuner Phase Locked\n", __func__); + pr_debug("%s: Tuner Phase Locked\n", __func__); *status = 1; } @@ -98,7 +98,7 @@ static int tda8261_get_state(struct dvb_frontend *fe, tstate->bandwidth = 40000000; /* FIXME! need to calculate Bandwidth */ break; default: - printk("%s: Unknown parameter (param=%d)\n", __func__, param); + pr_err("%s: Unknown parameter (param=%d)\n", __func__, param); err = -EINVAL; break; } @@ -124,11 +124,11 @@ static int tda8261_set_state(struct dvb_frontend *fe, */ frequency = tstate->frequency; if ((frequency < 950000) || (frequency > 2150000)) { - printk("%s: Frequency beyond limits, frequency=%d\n", __func__, frequency); + pr_warn("%s: Frequency beyond limits, frequency=%d\n", __func__, frequency); return -EINVAL; } N = (frequency + (div_tab[config->step_size] - 1)) / div_tab[config->step_size]; - printk("%s: Step size=%d, Divider=%d, PG=0x%02x (%d)\n", + pr_debug("%s: Step size=%d, Divider=%d, PG=0x%02x (%d)\n", __func__, config->step_size, div_tab[config->step_size], N, N); buf[0] = (N >> 8) & 0xff; @@ -144,25 +144,25 @@ static int tda8261_set_state(struct dvb_frontend *fe, /* Set params */ if ((err = tda8261_write(state, buf)) < 0) { - printk("%s: I/O Error\n", __func__); + pr_err("%s: I/O Error\n", __func__); return err; } /* sleep for some time */ - printk("%s: Waiting to Phase LOCK\n", __func__); + pr_debug("%s: Waiting to Phase LOCK\n", __func__); msleep(20); /* check status */ if ((err = tda8261_get_status(fe, &status)) < 0) { - printk("%s: I/O Error\n", __func__); + pr_err("%s: I/O Error\n", __func__); return err; } if (status == 1) { - printk("%s: Tuner Phase locked: status=%d\n", __func__, status); + pr_debug("%s: Tuner Phase locked: status=%d\n", __func__, status); state->frequency = frequency; /* cache successful state */ } else { - printk("%s: No Phase lock: status=%d\n", __func__, status); + pr_debug("%s: No Phase lock: status=%d\n", __func__, status); } } else { - printk("%s: Unknown parameter (param=%d)\n", __func__, param); + pr_err("%s: Unknown parameter (param=%d)\n", __func__, param); return -EINVAL; } @@ -214,7 +214,7 @@ struct dvb_frontend *tda8261_attach(struct dvb_frontend *fe, // printk("%s: Attaching %s TDA8261 8PSK/QPSK tuner\n", // __func__, fe->ops.tuner_ops.tuner_name); - printk("%s: Attaching TDA8261 8PSK/QPSK tuner\n", __func__); + pr_info("%s: Attaching TDA8261 8PSK/QPSK tuner\n", __func__); return fe; diff --git a/drivers/media/dvb/frontends/tda8261.h b/drivers/media/dvb-frontends/tda8261.h index 006e45351b94..006e45351b94 100644 --- a/drivers/media/dvb/frontends/tda8261.h +++ b/drivers/media/dvb-frontends/tda8261.h diff --git a/drivers/media/dvb/frontends/tda8261_cfg.h b/drivers/media/dvb-frontends/tda8261_cfg.h index 1af1ee49b542..1af1ee49b542 100644 --- a/drivers/media/dvb/frontends/tda8261_cfg.h +++ b/drivers/media/dvb-frontends/tda8261_cfg.h diff --git a/drivers/media/dvb/frontends/tda826x.c b/drivers/media/dvb-frontends/tda826x.c index 04bbcc24de0a..04bbcc24de0a 100644 --- a/drivers/media/dvb/frontends/tda826x.c +++ b/drivers/media/dvb-frontends/tda826x.c diff --git a/drivers/media/dvb/frontends/tda826x.h b/drivers/media/dvb-frontends/tda826x.h index 89e97926ab23..89e97926ab23 100644 --- a/drivers/media/dvb/frontends/tda826x.h +++ b/drivers/media/dvb-frontends/tda826x.h diff --git a/drivers/media/dvb/frontends/tdhd1.h b/drivers/media/dvb-frontends/tdhd1.h index 17750985db0c..17750985db0c 100644 --- a/drivers/media/dvb/frontends/tdhd1.h +++ b/drivers/media/dvb-frontends/tdhd1.h diff --git a/drivers/media/dvb/frontends/tua6100.c b/drivers/media/dvb-frontends/tua6100.c index 029384d1fddd..029384d1fddd 100644 --- a/drivers/media/dvb/frontends/tua6100.c +++ b/drivers/media/dvb-frontends/tua6100.c diff --git a/drivers/media/dvb/frontends/tua6100.h b/drivers/media/dvb-frontends/tua6100.h index f83dbd5e42ae..f83dbd5e42ae 100644 --- a/drivers/media/dvb/frontends/tua6100.h +++ b/drivers/media/dvb-frontends/tua6100.h diff --git a/drivers/media/dvb/frontends/ves1820.c b/drivers/media/dvb-frontends/ves1820.c index bb42b563c42d..bb42b563c42d 100644 --- a/drivers/media/dvb/frontends/ves1820.c +++ b/drivers/media/dvb-frontends/ves1820.c diff --git a/drivers/media/dvb/frontends/ves1820.h b/drivers/media/dvb-frontends/ves1820.h index e902ed634ec3..e902ed634ec3 100644 --- a/drivers/media/dvb/frontends/ves1820.h +++ b/drivers/media/dvb-frontends/ves1820.h diff --git a/drivers/media/dvb/frontends/ves1x93.c b/drivers/media/dvb-frontends/ves1x93.c index 9c17eacaec24..9c17eacaec24 100644 --- a/drivers/media/dvb/frontends/ves1x93.c +++ b/drivers/media/dvb-frontends/ves1x93.c diff --git a/drivers/media/dvb/frontends/ves1x93.h b/drivers/media/dvb-frontends/ves1x93.h index 8a5a49e808f6..8a5a49e808f6 100644 --- a/drivers/media/dvb/frontends/ves1x93.h +++ b/drivers/media/dvb-frontends/ves1x93.h diff --git a/drivers/media/dvb/frontends/z0194a.h b/drivers/media/dvb-frontends/z0194a.h index 96d86d6eb473..96d86d6eb473 100644 --- a/drivers/media/dvb/frontends/z0194a.h +++ b/drivers/media/dvb-frontends/z0194a.h diff --git a/drivers/media/dvb/frontends/zl10036.c b/drivers/media/dvb-frontends/zl10036.c index 0903d461b8fa..0903d461b8fa 100644 --- a/drivers/media/dvb/frontends/zl10036.c +++ b/drivers/media/dvb-frontends/zl10036.c diff --git a/drivers/media/dvb/frontends/zl10036.h b/drivers/media/dvb-frontends/zl10036.h index d84b8f8215e9..d84b8f8215e9 100644 --- a/drivers/media/dvb/frontends/zl10036.h +++ b/drivers/media/dvb-frontends/zl10036.h diff --git a/drivers/media/dvb/frontends/zl10039.c b/drivers/media/dvb-frontends/zl10039.c index eff9c5fde50a..eff9c5fde50a 100644 --- a/drivers/media/dvb/frontends/zl10039.c +++ b/drivers/media/dvb-frontends/zl10039.c diff --git a/drivers/media/dvb/frontends/zl10039.h b/drivers/media/dvb-frontends/zl10039.h index 5eee7ea162a1..5eee7ea162a1 100644 --- a/drivers/media/dvb/frontends/zl10039.h +++ b/drivers/media/dvb-frontends/zl10039.h diff --git a/drivers/media/dvb/frontends/zl10353.c b/drivers/media/dvb-frontends/zl10353.c index 82946cd517f5..82946cd517f5 100644 --- a/drivers/media/dvb/frontends/zl10353.c +++ b/drivers/media/dvb-frontends/zl10353.c diff --git a/drivers/media/dvb/frontends/zl10353.h b/drivers/media/dvb-frontends/zl10353.h index 6e3ca9eed048..6e3ca9eed048 100644 --- a/drivers/media/dvb/frontends/zl10353.h +++ b/drivers/media/dvb-frontends/zl10353.h diff --git a/drivers/media/dvb/frontends/zl10353_priv.h b/drivers/media/dvb-frontends/zl10353_priv.h index e0dd1d3e09dd..e0dd1d3e09dd 100644 --- a/drivers/media/dvb/frontends/zl10353_priv.h +++ b/drivers/media/dvb-frontends/zl10353_priv.h diff --git a/drivers/media/dvb/Kconfig b/drivers/media/dvb/Kconfig deleted file mode 100644 index f6e40b3a44cc..000000000000 --- a/drivers/media/dvb/Kconfig +++ /dev/null @@ -1,91 +0,0 @@ -# -# DVB device configuration -# - -config DVB_MAX_ADAPTERS - int "maximum number of DVB/ATSC adapters" - depends on DVB_CORE - default 8 - range 1 255 - help - Maximum number of DVB/ATSC adapters. Increasing this number - increases the memory consumption of the DVB subsystem even - if a much lower number of DVB/ATSC adapters is present. - Only values in the range 4-32 are tested. - - If you are unsure about this, use the default value 8 - -config DVB_DYNAMIC_MINORS - bool "Dynamic DVB minor allocation" - depends on DVB_CORE - default n - help - If you say Y here, the DVB subsystem will use dynamic minor - allocation for any device that uses the DVB major number. - This means that you can have more than 4 of a single type - of device (like demuxes and frontends) per adapter, but udev - will be required to manage the device nodes. - - If you are unsure about this, say N here. - -menuconfig DVB_CAPTURE_DRIVERS - bool "DVB/ATSC adapters" - depends on DVB_CORE - default y - ---help--- - Say Y to select Digital TV adapters - -if DVB_CAPTURE_DRIVERS && DVB_CORE - -comment "Supported SAA7146 based PCI Adapters" - depends on DVB_CORE && PCI && I2C -source "drivers/media/dvb/ttpci/Kconfig" - -comment "Supported USB Adapters" - depends on DVB_CORE && USB && I2C -source "drivers/media/dvb/dvb-usb/Kconfig" -source "drivers/media/dvb/ttusb-budget/Kconfig" -source "drivers/media/dvb/ttusb-dec/Kconfig" -source "drivers/media/dvb/siano/Kconfig" - -comment "Supported FlexCopII (B2C2) Adapters" - depends on DVB_CORE && (PCI || USB) && I2C -source "drivers/media/dvb/b2c2/Kconfig" - -comment "Supported BT878 Adapters" - depends on DVB_CORE && PCI && I2C -source "drivers/media/dvb/bt8xx/Kconfig" - -comment "Supported Pluto2 Adapters" - depends on DVB_CORE && PCI && I2C -source "drivers/media/dvb/pluto2/Kconfig" - -comment "Supported SDMC DM1105 Adapters" - depends on DVB_CORE && PCI && I2C -source "drivers/media/dvb/dm1105/Kconfig" - -comment "Supported FireWire (IEEE 1394) Adapters" - depends on DVB_CORE && FIREWIRE -source "drivers/media/dvb/firewire/Kconfig" - -comment "Supported Earthsoft PT1 Adapters" - depends on DVB_CORE && PCI && I2C -source "drivers/media/dvb/pt1/Kconfig" - -comment "Supported Mantis Adapters" - depends on DVB_CORE && PCI && I2C - source "drivers/media/dvb/mantis/Kconfig" - -comment "Supported nGene Adapters" - depends on DVB_CORE && PCI && I2C - source "drivers/media/dvb/ngene/Kconfig" - -comment "Supported ddbridge ('Octopus') Adapters" - depends on DVB_CORE && PCI && I2C - source "drivers/media/dvb/ddbridge/Kconfig" - -comment "Supported DVB Frontends" - depends on DVB_CORE -source "drivers/media/dvb/frontends/Kconfig" - -endif # DVB_CAPTURE_DRIVERS diff --git a/drivers/media/dvb/Makefile b/drivers/media/dvb/Makefile deleted file mode 100644 index b2cefe637a64..000000000000 --- a/drivers/media/dvb/Makefile +++ /dev/null @@ -1,21 +0,0 @@ -# -# Makefile for the kernel multimedia device drivers. -# - -obj-y := dvb-core/ \ - frontends/ \ - ttpci/ \ - ttusb-dec/ \ - ttusb-budget/ \ - b2c2/ \ - bt8xx/ \ - dvb-usb/ \ - pluto2/ \ - siano/ \ - dm1105/ \ - pt1/ \ - mantis/ \ - ngene/ \ - ddbridge/ - -obj-$(CONFIG_DVB_FIREDTV) += firewire/ diff --git a/drivers/media/dvb/b2c2/Kconfig b/drivers/media/dvb/b2c2/Kconfig deleted file mode 100644 index 9e5781400744..000000000000 --- a/drivers/media/dvb/b2c2/Kconfig +++ /dev/null @@ -1,45 +0,0 @@ -config DVB_B2C2_FLEXCOP - tristate "Technisat/B2C2 FlexCopII(b) and FlexCopIII adapters" - depends on DVB_CORE && I2C - select DVB_PLL if !DVB_FE_CUSTOMISE - select DVB_STV0299 if !DVB_FE_CUSTOMISE - select DVB_MT352 if !DVB_FE_CUSTOMISE - select DVB_MT312 if !DVB_FE_CUSTOMISE - select DVB_NXT200X if !DVB_FE_CUSTOMISE - select DVB_STV0297 if !DVB_FE_CUSTOMISE - select DVB_BCM3510 if !DVB_FE_CUSTOMISE - select DVB_LGDT330X if !DVB_FE_CUSTOMISE - select DVB_S5H1420 if !DVB_FE_CUSTOMISE - select DVB_TUNER_ITD1000 if !DVB_FE_CUSTOMISE - select DVB_ISL6421 if !DVB_FE_CUSTOMISE - select DVB_CX24123 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMISE - select DVB_TUNER_CX24113 if !DVB_FE_CUSTOMISE - help - Support for the digital TV receiver chip made by B2C2 Inc. included in - Technisats PCI cards and USB boxes. - - Say Y if you own such a device and want to use it. - -config DVB_B2C2_FLEXCOP_PCI - tristate "Technisat/B2C2 Air/Sky/Cable2PC PCI" - depends on DVB_B2C2_FLEXCOP && PCI && I2C - help - Support for the Air/Sky/CableStar2 PCI card (DVB/ATSC) by Technisat/B2C2. - - Say Y if you own such a device and want to use it. - -config DVB_B2C2_FLEXCOP_USB - tristate "Technisat/B2C2 Air/Sky/Cable2PC USB" - depends on DVB_B2C2_FLEXCOP && USB && I2C - help - Support for the Air/Sky/Cable2PC USB1.1 box (DVB/ATSC) by Technisat/B2C2, - - Say Y if you own such a device and want to use it. - -config DVB_B2C2_FLEXCOP_DEBUG - bool "Enable debug for the B2C2 FlexCop drivers" - depends on DVB_B2C2_FLEXCOP - help - Say Y if you want to enable the module option to control debug messages - of all B2C2 FlexCop drivers. diff --git a/drivers/media/dvb/b2c2/Makefile b/drivers/media/dvb/b2c2/Makefile deleted file mode 100644 index 3d04a8dba99e..000000000000 --- a/drivers/media/dvb/b2c2/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -b2c2-flexcop-objs = flexcop.o flexcop-fe-tuner.o flexcop-i2c.o \ - flexcop-sram.o flexcop-eeprom.o flexcop-misc.o flexcop-hw-filter.o -obj-$(CONFIG_DVB_B2C2_FLEXCOP) += b2c2-flexcop.o - -ifneq ($(CONFIG_DVB_B2C2_FLEXCOP_PCI),) -b2c2-flexcop-objs += flexcop-dma.o -endif - -b2c2-flexcop-pci-objs = flexcop-pci.o -obj-$(CONFIG_DVB_B2C2_FLEXCOP_PCI) += b2c2-flexcop-pci.o - -b2c2-flexcop-usb-objs = flexcop-usb.o -obj-$(CONFIG_DVB_B2C2_FLEXCOP_USB) += b2c2-flexcop-usb.o - -ccflags-y += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/ -ccflags-y += -Idrivers/media/common/tuners/ diff --git a/drivers/media/dvb/bt8xx/Kconfig b/drivers/media/dvb/bt8xx/Kconfig deleted file mode 100644 index 8668e634c7ec..000000000000 --- a/drivers/media/dvb/bt8xx/Kconfig +++ /dev/null @@ -1,22 +0,0 @@ -config DVB_BT8XX - tristate "BT8xx based PCI cards" - depends on DVB_CORE && PCI && I2C && VIDEO_BT848 - select DVB_MT352 if !DVB_FE_CUSTOMISE - select DVB_SP887X if !DVB_FE_CUSTOMISE - select DVB_NXT6000 if !DVB_FE_CUSTOMISE - select DVB_CX24110 if !DVB_FE_CUSTOMISE - select DVB_OR51211 if !DVB_FE_CUSTOMISE - select DVB_LGDT330X if !DVB_FE_CUSTOMISE - select DVB_ZL10353 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMISE - help - Support for PCI cards based on the Bt8xx PCI bridge. Examples are - the Nebula cards, the Pinnacle PCTV cards, the Twinhan DST cards, - the pcHDTV HD2000 cards, the DViCO FusionHDTV Lite cards, and - some AVerMedia cards. - - Since these cards have no MPEG decoder onboard, they transmit - only compressed MPEG data over the PCI bus, so you need - an external software decoder to watch TV on your computer. - - Say Y if you own such a device and want to use it. diff --git a/drivers/media/dvb/bt8xx/Makefile b/drivers/media/dvb/bt8xx/Makefile deleted file mode 100644 index 0713b3af2050..000000000000 --- a/drivers/media/dvb/bt8xx/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -obj-$(CONFIG_DVB_BT8XX) += bt878.o dvb-bt8xx.o dst.o dst_ca.o - -ccflags-y += -Idrivers/media/dvb/dvb-core -ccflags-y += -Idrivers/media/dvb/frontends -ccflags-y += -Idrivers/media/video/bt8xx -ccflags-y += -Idrivers/media/common/tuners diff --git a/drivers/media/dvb/dm1105/Makefile b/drivers/media/dvb/dm1105/Makefile deleted file mode 100644 index 95a008b71fe5..000000000000 --- a/drivers/media/dvb/dm1105/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -obj-$(CONFIG_DVB_DM1105) += dm1105.o - -ccflags-y += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig deleted file mode 100644 index c2161565023a..000000000000 --- a/drivers/media/dvb/dvb-usb/Kconfig +++ /dev/null @@ -1,440 +0,0 @@ -config DVB_USB - tristate "Support for various USB DVB devices" - depends on DVB_CORE && USB && I2C && RC_CORE - help - By enabling this you will be able to choose the various supported - USB1.1 and USB2.0 DVB devices. - - Almost every USB device needs a firmware, please look into - <file:Documentation/dvb/README.dvb-usb>. - - For a complete list of supported USB devices see the LinuxTV DVB Wiki: - <http://www.linuxtv.org/wiki/index.php/DVB_USB> - - Say Y if you own a USB DVB device. - -config DVB_USB_DEBUG - bool "Enable extended debug support for all DVB-USB devices" - depends on DVB_USB - help - Say Y if you want to enable debugging. See modinfo dvb-usb (and the - appropriate drivers) for debug levels. - -config DVB_USB_A800 - tristate "AVerMedia AverTV DVB-T USB 2.0 (A800)" - depends on DVB_USB - select DVB_DIB3000MC - select DVB_PLL if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMISE - help - Say Y here to support the AVerMedia AverTV DVB-T USB 2.0 (A800) receiver. - -config DVB_USB_DIBUSB_MB - tristate "DiBcom USB DVB-T devices (based on the DiB3000M-B) (see help for device list)" - depends on DVB_USB - select DVB_PLL if !DVB_FE_CUSTOMISE - select DVB_DIB3000MB - select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMISE - help - Support for USB 1.1 and 2.0 DVB-T receivers based on reference designs made by - DiBcom (<http://www.dibcom.fr>) equipped with a DiB3000M-B demodulator. - - For an up-to-date list of devices supported by this driver, have a look - on the Linux-DVB Wiki at www.linuxtv.org. - - Say Y if you own such a device and want to use it. You should build it as - a module. - -config DVB_USB_DIBUSB_MB_FAULTY - bool "Support faulty USB IDs" - depends on DVB_USB_DIBUSB_MB - help - Support for faulty USB IDs due to an invalid EEPROM on some Artec devices. - -config DVB_USB_DIBUSB_MC - tristate "DiBcom USB DVB-T devices (based on the DiB3000M-C/P) (see help for device list)" - depends on DVB_USB - select DVB_DIB3000MC - select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMISE - help - Support for USB2.0 DVB-T receivers based on reference designs made by - DiBcom (<http://www.dibcom.fr>) equipped with a DiB3000M-C/P demodulator. - - For an up-to-date list of devices supported by this driver, have a look - on the Linux-DVB Wiki at www.linuxtv.org. - - Say Y if you own such a device and want to use it. You should build it as - a module. - -config DVB_USB_DIB0700 - tristate "DiBcom DiB0700 USB DVB devices (see help for supported devices)" - depends on DVB_USB - select DVB_DIB7000P if !DVB_FE_CUSTOMISE - select DVB_DIB7000M if !DVB_FE_CUSTOMISE - select DVB_DIB8000 if !DVB_FE_CUSTOMISE - select DVB_DIB3000MC if !DVB_FE_CUSTOMISE - select DVB_S5H1411 if !DVB_FE_CUSTOMISE - select DVB_LGDT3305 if !DVB_FE_CUSTOMISE - select DVB_TUNER_DIB0070 if !DVB_FE_CUSTOMISE - select DVB_TUNER_DIB0090 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMISE - select MEDIA_TUNER_MT2266 if !MEDIA_TUNER_CUSTOMISE - select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMISE - select MEDIA_TUNER_XC5000 if !MEDIA_TUNER_CUSTOMISE - select MEDIA_TUNER_XC4000 if !MEDIA_TUNER_CUSTOMISE - select MEDIA_TUNER_MXL5007T if !MEDIA_TUNER_CUSTOMISE - help - Support for USB2.0/1.1 DVB receivers based on the DiB0700 USB bridge. The - USB bridge is also present in devices having the DiB7700 DVB-T-USB - silicon. This chip can be found in devices offered by Hauppauge, - Avermedia and other big and small companies. - - For an up-to-date list of devices supported by this driver, have a look - on the LinuxTV Wiki at www.linuxtv.org. - - Say Y if you own such a device and want to use it. You should build it as - a module. - -config DVB_USB_UMT_010 - tristate "HanfTek UMT-010 DVB-T USB2.0 support" - depends on DVB_USB - select DVB_PLL if !DVB_FE_CUSTOMISE - select DVB_DIB3000MC - select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMISE - select DVB_MT352 if !DVB_FE_CUSTOMISE - help - Say Y here to support the HanfTek UMT-010 USB2.0 stick-sized DVB-T receiver. - -config DVB_USB_CXUSB - tristate "Conexant USB2.0 hybrid reference design support" - depends on DVB_USB - select DVB_PLL if !DVB_FE_CUSTOMISE - select DVB_CX22702 if !DVB_FE_CUSTOMISE - select DVB_LGDT330X if !DVB_FE_CUSTOMISE - select DVB_MT352 if !DVB_FE_CUSTOMISE - select DVB_ZL10353 if !DVB_FE_CUSTOMISE - select DVB_DIB7000P if !DVB_FE_CUSTOMISE - select DVB_TUNER_DIB0070 if !DVB_FE_CUSTOMISE - select DVB_ATBM8830 if !DVB_FE_CUSTOMISE - select DVB_LGS8GXX if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMISE - select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMISE - select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMISE - select MEDIA_TUNER_MAX2165 if !MEDIA_TUNER_CUSTOMISE - help - Say Y here to support the Conexant USB2.0 hybrid reference design. - Currently, only DVB and ATSC modes are supported, analog mode - shall be added in the future. Devices that require this module: - - Medion MD95700 hybrid USB2.0 device. - DViCO FusionHDTV (Bluebird) USB2.0 devices - -config DVB_USB_M920X - tristate "Uli m920x DVB-T USB2.0 support" - depends on DVB_USB - select DVB_MT352 if !DVB_FE_CUSTOMISE - select DVB_TDA1004X if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMISE - select MEDIA_TUNER_TDA827X if !MEDIA_TUNER_CUSTOMISE - select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMISE - help - Say Y here to support the MSI Mega Sky 580 USB2.0 DVB-T receiver. - Currently, only devices with a product id of - "DTV USB MINI" (in cold state) are supported. - Firmware required. - -config DVB_USB_GL861 - tristate "Genesys Logic GL861 USB2.0 support" - depends on DVB_USB - select DVB_ZL10353 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMISE - help - Say Y here to support the MSI Megasky 580 (55801) DVB-T USB2.0 - receiver with USB ID 0db0:5581. - -config DVB_USB_AU6610 - tristate "Alcor Micro AU6610 USB2.0 support" - depends on DVB_USB - select DVB_ZL10353 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMISE - help - Say Y here to support the Sigmatek DVB-110 DVB-T USB2.0 receiver. - -config DVB_USB_DIGITV - tristate "Nebula Electronics uDigiTV DVB-T USB2.0 support" - depends on DVB_USB - select DVB_PLL if !DVB_FE_CUSTOMISE - select DVB_NXT6000 if !DVB_FE_CUSTOMISE - select DVB_MT352 if !DVB_FE_CUSTOMISE - help - Say Y here to support the Nebula Electronics uDigitV USB2.0 DVB-T receiver. - -config DVB_USB_VP7045 - tristate "TwinhanDTV Alpha/MagicBoxII, DNTV tinyUSB2, Beetle USB2.0 support" - depends on DVB_USB - help - Say Y here to support the - - TwinhanDTV Alpha (stick) (VP-7045), - TwinhanDTV MagicBox II (VP-7046), - DigitalNow TinyUSB 2 DVB-t, - DigitalRise USB 2.0 Ter (Beetle) and - TYPHOON DVB-T USB DRIVE - - DVB-T USB2.0 receivers. - -config DVB_USB_VP702X - tristate "TwinhanDTV StarBox and clones DVB-S USB2.0 support" - depends on DVB_USB - help - Say Y here to support the - - TwinhanDTV StarBox, - DigitalRise USB Starbox and - TYPHOON DVB-S USB 2.0 BOX - - DVB-S USB2.0 receivers. - -config DVB_USB_GP8PSK - tristate "GENPIX 8PSK->USB module support" - depends on DVB_USB - help - Say Y here to support the - GENPIX 8psk module - - DVB-S USB2.0 receivers. - -config DVB_USB_NOVA_T_USB2 - tristate "Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 support" - depends on DVB_USB - select DVB_DIB3000MC - select DVB_PLL if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMISE - help - Say Y here to support the Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 receiver. - -config DVB_USB_TTUSB2 - tristate "Pinnacle 400e DVB-S USB2.0 support" - depends on DVB_USB - select DVB_TDA10086 if !DVB_FE_CUSTOMISE - select DVB_LNBP21 if !DVB_FE_CUSTOMISE - select DVB_TDA826X if !DVB_FE_CUSTOMISE - help - Say Y here to support the Pinnacle 400e DVB-S USB2.0 receiver. The - firmware protocol used by this module is similar to the one used by the - old ttusb-driver - that's why the module is called dvb-usb-ttusb2. - -config DVB_USB_DTT200U - tristate "WideView WT-200U and WT-220U (pen) DVB-T USB2.0 support (Yakumo/Hama/Typhoon/Yuan)" - depends on DVB_USB - help - Say Y here to support the WideView/Yakumo/Hama/Typhoon/Yuan DVB-T USB2.0 receiver. - - The receivers are also known as DTT200U (Yakumo) and UB300 (Yuan). - - The WT-220U and its clones are pen-sized. - -config DVB_USB_OPERA1 - tristate "Opera1 DVB-S USB2.0 receiver" - depends on DVB_USB - select DVB_STV0299 if !DVB_FE_CUSTOMISE - select DVB_PLL if !DVB_FE_CUSTOMISE - help - Say Y here to support the Opera DVB-S USB2.0 receiver. - -config DVB_USB_AF9005 - tristate "Afatech AF9005 DVB-T USB1.1 support" - depends on DVB_USB && EXPERIMENTAL - select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMISE - select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMISE - help - Say Y here to support the Afatech AF9005 based DVB-T USB1.1 receiver - and the TerraTec Cinergy T USB XE (Rev.1) - -config DVB_USB_AF9005_REMOTE - tristate "Afatech AF9005 default remote control support" - depends on DVB_USB_AF9005 - help - Say Y here to support the default remote control decoding for the - Afatech AF9005 based receiver. - -config DVB_USB_PCTV452E - tristate "Pinnacle PCTV HDTV Pro USB device/TT Connect S2-3600" - depends on DVB_USB - select TTPCI_EEPROM - select DVB_LNBP22 if !DVB_FE_CUSTOMISE - select DVB_STB0899 if !DVB_FE_CUSTOMISE - select DVB_STB6100 if !DVB_FE_CUSTOMISE - help - Support for external USB adapter designed by Pinnacle, - shipped under the brand name 'PCTV HDTV Pro USB'. - Also supports TT Connect S2-3600/3650 cards. - Say Y if you own such a device and want to use it. - -config DVB_USB_DW2102 - tristate "DvbWorld & TeVii DVB-S/S2 USB2.0 support" - depends on DVB_USB - select DVB_PLL if !DVB_FE_CUSTOMISE - select DVB_STV0299 if !DVB_FE_CUSTOMISE - select DVB_STV0288 if !DVB_FE_CUSTOMISE - select DVB_STB6000 if !DVB_FE_CUSTOMISE - select DVB_CX24116 if !DVB_FE_CUSTOMISE - select DVB_SI21XX if !DVB_FE_CUSTOMISE - select DVB_TDA10023 if !DVB_FE_CUSTOMISE - select DVB_MT312 if !DVB_FE_CUSTOMISE - select DVB_ZL10039 if !DVB_FE_CUSTOMISE - select DVB_DS3000 if !DVB_FE_CUSTOMISE - select DVB_STB6100 if !DVB_FE_CUSTOMISE - select DVB_STV6110 if !DVB_FE_CUSTOMISE - select DVB_STV0900 if !DVB_FE_CUSTOMISE - help - Say Y here to support the DvbWorld, TeVii, Prof DVB-S/S2 USB2.0 - receivers. - -config DVB_USB_CINERGY_T2 - tristate "Terratec CinergyT2/qanu USB 2.0 DVB-T receiver" - depends on DVB_USB - help - Support for "TerraTec CinergyT2" USB2.0 Highspeed DVB Receivers - - Say Y if you own such a device and want to use it. - -config DVB_USB_ANYSEE - tristate "Anysee DVB-T/C USB2.0 support" - depends on DVB_USB - select DVB_PLL if !DVB_FE_CUSTOMISE - select DVB_MT352 if !DVB_FE_CUSTOMISE - select DVB_ZL10353 if !DVB_FE_CUSTOMISE - select DVB_TDA10023 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_TDA18212 if !MEDIA_TUNER_CUSTOMISE - select DVB_CX24116 if !DVB_FE_CUSTOMISE - select DVB_STV0900 if !DVB_FE_CUSTOMISE - select DVB_STV6110 if !DVB_FE_CUSTOMISE - select DVB_ISL6423 if !DVB_FE_CUSTOMISE - select DVB_CXD2820R if !DVB_FE_CUSTOMISE - help - Say Y here to support the Anysee E30, Anysee E30 Plus or - Anysee E30 C Plus DVB USB2.0 receiver. - -config DVB_USB_DTV5100 - tristate "AME DTV-5100 USB2.0 DVB-T support" - depends on DVB_USB - select DVB_ZL10353 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMISE - help - Say Y here to support the AME DTV-5100 USB2.0 DVB-T receiver. - -config DVB_USB_AF9015 - tristate "Afatech AF9015 DVB-T USB2.0 support" - depends on DVB_USB - select DVB_AF9013 - select DVB_PLL if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMISE - select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMISE - select MEDIA_TUNER_TDA18271 if !MEDIA_TUNER_CUSTOMISE - select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMISE - select MEDIA_TUNER_MC44S803 if !MEDIA_TUNER_CUSTOMISE - select MEDIA_TUNER_TDA18218 if !MEDIA_TUNER_CUSTOMISE - select MEDIA_TUNER_MXL5007T if !MEDIA_TUNER_CUSTOMISE - help - Say Y here to support the Afatech AF9015 based DVB-T USB2.0 receiver - -config DVB_USB_CE6230 - tristate "Intel CE6230 DVB-T USB2.0 support" - depends on DVB_USB - select DVB_ZL10353 - select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMISE - help - Say Y here to support the Intel CE6230 DVB-T USB2.0 receiver - -config DVB_USB_FRIIO - tristate "Friio ISDB-T USB2.0 Receiver support" - depends on DVB_USB - help - Say Y here to support the Japanese DTV receiver Friio. - -config DVB_USB_EC168 - tristate "E3C EC168 DVB-T USB2.0 support" - depends on DVB_USB - select DVB_EC100 - select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMISE - help - Say Y here to support the E3C EC168 DVB-T USB2.0 receiver. - -config DVB_USB_AZ6007 - tristate "AzureWave 6007 and clones DVB-T/C USB2.0 support" - depends on DVB_USB - select DVB_DRXK if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_MT2063 if !DVB_FE_CUSTOMISE - help - Say Y here to support theAfatech AF9005 based DVB-T/DVB-C receivers. - -config DVB_USB_AZ6027 - tristate "Azurewave DVB-S/S2 USB2.0 AZ6027 support" - depends on DVB_USB - select DVB_STB0899 if !DVB_FE_CUSTOMISE - select DVB_STB6100 if !DVB_FE_CUSTOMISE - help - Say Y here to support the AZ6027 device - -config DVB_USB_LME2510 - tristate "LME DM04/QQBOX DVB-S USB2.0 support" - depends on DVB_USB - select DVB_TDA10086 if !DVB_FE_CUSTOMISE - select DVB_TDA826X if !DVB_FE_CUSTOMISE - select DVB_STV0288 if !DVB_FE_CUSTOMISE - select DVB_IX2505V if !DVB_FE_CUSTOMISE - select DVB_STV0299 if !DVB_FE_CUSTOMISE - select DVB_PLL if !DVB_FE_CUSTOMISE - select DVB_M88RS2000 if !DVB_FE_CUSTOMISE - help - Say Y here to support the LME DM04/QQBOX DVB-S USB2.0 . - -config DVB_USB_TECHNISAT_USB2 - tristate "Technisat DVB-S/S2 USB2.0 support" - depends on DVB_USB - select DVB_STV090x if !DVB_FE_CUSTOMISE - select DVB_STV6110x if !DVB_FE_CUSTOMISE - help - Say Y here to support the Technisat USB2 DVB-S/S2 device - -config DVB_USB_IT913X - tristate "it913x driver" - depends on DVB_USB - select DVB_IT913X_FE - help - Say Y here to support the it913x device - -config DVB_USB_MXL111SF - tristate "MxL111SF DTV USB2.0 support" - depends on DVB_USB - select DVB_LGDT3305 if !DVB_FE_CUSTOMISE - select DVB_LG2160 if !DVB_FE_CUSTOMISE - select VIDEO_TVEEPROM - help - Say Y here to support the MxL111SF USB2.0 DTV receiver. - -config DVB_USB_RTL28XXU - tristate "Realtek RTL28xxU DVB USB support" - depends on DVB_USB && EXPERIMENTAL - select DVB_RTL2830 - select DVB_RTL2832 - select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMISE - select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMISE - select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMISE - select MEDIA_TUNER_FC0012 if !MEDIA_TUNER_CUSTOMISE - select MEDIA_TUNER_FC0013 if !MEDIA_TUNER_CUSTOMISE - help - Say Y here to support the Realtek RTL28xxU DVB USB receiver. - -config DVB_USB_AF9035 - tristate "Afatech AF9035 DVB-T USB2.0 support" - depends on DVB_USB - select DVB_AF9033 - select MEDIA_TUNER_TUA9001 if !MEDIA_TUNER_CUSTOMISE - select MEDIA_TUNER_FC0011 if !MEDIA_TUNER_CUSTOMISE - select MEDIA_TUNER_MXL5007T if !MEDIA_TUNER_CUSTOMISE - select MEDIA_TUNER_TDA18218 if !MEDIA_TUNER_CUSTOMISE - help - Say Y here to support the Afatech AF9035 based DVB USB receiver. - diff --git a/drivers/media/dvb/dvb-usb/Makefile b/drivers/media/dvb/dvb-usb/Makefile deleted file mode 100644 index b667ac39a4e3..000000000000 --- a/drivers/media/dvb/dvb-usb/Makefile +++ /dev/null @@ -1,121 +0,0 @@ -dvb-usb-objs = dvb-usb-firmware.o dvb-usb-init.o dvb-usb-urb.o dvb-usb-i2c.o dvb-usb-dvb.o dvb-usb-remote.o usb-urb.o -obj-$(CONFIG_DVB_USB) += dvb-usb.o - -dvb-usb-vp7045-objs = vp7045.o vp7045-fe.o -obj-$(CONFIG_DVB_USB_VP7045) += dvb-usb-vp7045.o - -dvb-usb-vp702x-objs = vp702x.o vp702x-fe.o -obj-$(CONFIG_DVB_USB_VP702X) += dvb-usb-vp702x.o - -dvb-usb-gp8psk-objs = gp8psk.o gp8psk-fe.o -obj-$(CONFIG_DVB_USB_GP8PSK) += dvb-usb-gp8psk.o - -dvb-usb-dtt200u-objs = dtt200u.o dtt200u-fe.o -obj-$(CONFIG_DVB_USB_DTT200U) += dvb-usb-dtt200u.o - -dvb-usb-dibusb-common-objs = dibusb-common.o - -dvb-usb-a800-objs = a800.o -obj-$(CONFIG_DVB_USB_A800) += dvb-usb-dibusb-common.o dvb-usb-a800.o - -dvb-usb-dibusb-mb-objs = dibusb-mb.o -obj-$(CONFIG_DVB_USB_DIBUSB_MB) += dvb-usb-dibusb-common.o dvb-usb-dibusb-mb.o - -dvb-usb-dibusb-mc-objs = dibusb-mc.o -obj-$(CONFIG_DVB_USB_DIBUSB_MC) += dvb-usb-dibusb-common.o dvb-usb-dibusb-mc.o - -dvb-usb-nova-t-usb2-objs = nova-t-usb2.o -obj-$(CONFIG_DVB_USB_NOVA_T_USB2) += dvb-usb-dibusb-common.o dvb-usb-nova-t-usb2.o - -dvb-usb-umt-010-objs = umt-010.o -obj-$(CONFIG_DVB_USB_UMT_010) += dvb-usb-dibusb-common.o dvb-usb-umt-010.o - -dvb-usb-m920x-objs = m920x.o -obj-$(CONFIG_DVB_USB_M920X) += dvb-usb-m920x.o - -dvb-usb-gl861-objs = gl861.o -obj-$(CONFIG_DVB_USB_GL861) += dvb-usb-gl861.o - -dvb-usb-au6610-objs = au6610.o -obj-$(CONFIG_DVB_USB_AU6610) += dvb-usb-au6610.o - -dvb-usb-digitv-objs = digitv.o -obj-$(CONFIG_DVB_USB_DIGITV) += dvb-usb-digitv.o - -dvb-usb-cxusb-objs = cxusb.o -obj-$(CONFIG_DVB_USB_CXUSB) += dvb-usb-cxusb.o - -dvb-usb-ttusb2-objs = ttusb2.o -obj-$(CONFIG_DVB_USB_TTUSB2) += dvb-usb-ttusb2.o - -dvb-usb-dib0700-objs = dib0700_core.o dib0700_devices.o -obj-$(CONFIG_DVB_USB_DIB0700) += dvb-usb-dib0700.o - -dvb-usb-opera-objs = opera1.o -obj-$(CONFIG_DVB_USB_OPERA1) += dvb-usb-opera.o - -dvb-usb-af9005-objs = af9005.o af9005-fe.o -obj-$(CONFIG_DVB_USB_AF9005) += dvb-usb-af9005.o - -dvb-usb-af9005-remote-objs = af9005-remote.o -obj-$(CONFIG_DVB_USB_AF9005_REMOTE) += dvb-usb-af9005-remote.o - -dvb-usb-anysee-objs = anysee.o -obj-$(CONFIG_DVB_USB_ANYSEE) += dvb-usb-anysee.o - -dvb-usb-pctv452e-objs = pctv452e.o -obj-$(CONFIG_DVB_USB_PCTV452E) += dvb-usb-pctv452e.o - -dvb-usb-dw2102-objs = dw2102.o -obj-$(CONFIG_DVB_USB_DW2102) += dvb-usb-dw2102.o - -dvb-usb-dtv5100-objs = dtv5100.o -obj-$(CONFIG_DVB_USB_DTV5100) += dvb-usb-dtv5100.o - -dvb-usb-af9015-objs = af9015.o -obj-$(CONFIG_DVB_USB_AF9015) += dvb-usb-af9015.o - -dvb-usb-cinergyT2-objs = cinergyT2-core.o cinergyT2-fe.o -obj-$(CONFIG_DVB_USB_CINERGY_T2) += dvb-usb-cinergyT2.o - -dvb-usb-ce6230-objs = ce6230.o -obj-$(CONFIG_DVB_USB_CE6230) += dvb-usb-ce6230.o - -dvb-usb-friio-objs = friio.o friio-fe.o -obj-$(CONFIG_DVB_USB_FRIIO) += dvb-usb-friio.o - -dvb-usb-ec168-objs = ec168.o -obj-$(CONFIG_DVB_USB_EC168) += dvb-usb-ec168.o - -dvb-usb-az6007-objs = az6007.o -obj-$(CONFIG_DVB_USB_AZ6007) += dvb-usb-az6007.o - -dvb-usb-az6027-objs = az6027.o -obj-$(CONFIG_DVB_USB_AZ6027) += dvb-usb-az6027.o - -dvb-usb-lmedm04-objs = lmedm04.o -obj-$(CONFIG_DVB_USB_LME2510) += dvb-usb-lmedm04.o - -dvb-usb-technisat-usb2-objs = technisat-usb2.o -obj-$(CONFIG_DVB_USB_TECHNISAT_USB2) += dvb-usb-technisat-usb2.o - -dvb-usb-it913x-objs := it913x.o -obj-$(CONFIG_DVB_USB_IT913X) += dvb-usb-it913x.o - -dvb-usb-mxl111sf-objs = mxl111sf.o mxl111sf-phy.o mxl111sf-i2c.o mxl111sf-gpio.o -obj-$(CONFIG_DVB_USB_MXL111SF) += dvb-usb-mxl111sf.o -obj-$(CONFIG_DVB_USB_MXL111SF) += mxl111sf-demod.o -obj-$(CONFIG_DVB_USB_MXL111SF) += mxl111sf-tuner.o - -dvb-usb-rtl28xxu-objs = rtl28xxu.o -obj-$(CONFIG_DVB_USB_RTL28XXU) += dvb-usb-rtl28xxu.o - -dvb-usb-af9035-objs = af9035.o -obj-$(CONFIG_DVB_USB_AF9035) += dvb-usb-af9035.o - -ccflags-y += -I$(srctree)/drivers/media/dvb/dvb-core -ccflags-y += -I$(srctree)/drivers/media/dvb/frontends/ -# due to tuner-xc3028 -ccflags-y += -I$(srctree)/drivers/media/common/tuners -ccflags-y += -I$(srctree)/drivers/media/dvb/ttpci - diff --git a/drivers/media/dvb/dvb-usb/af9015.c b/drivers/media/dvb/dvb-usb/af9015.c deleted file mode 100644 index 677fed79b01e..000000000000 --- a/drivers/media/dvb/dvb-usb/af9015.c +++ /dev/null @@ -1,1952 +0,0 @@ -/* - * DVB USB Linux driver for Afatech AF9015 DVB-T USB2.0 receiver - * - * Copyright (C) 2007 Antti Palosaari <crope@iki.fi> - * - * Thanks to Afatech who kindly provided information. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include <linux/hash.h> -#include <linux/slab.h> - -#include "af9015.h" -#include "af9013.h" -#include "mt2060.h" -#include "qt1010.h" -#include "tda18271.h" -#include "mxl5005s.h" -#include "mc44s803.h" -#include "tda18218.h" -#include "mxl5007t.h" - -static int dvb_usb_af9015_debug; -module_param_named(debug, dvb_usb_af9015_debug, int, 0644); -MODULE_PARM_DESC(debug, "set debugging level" DVB_USB_DEBUG_STATUS); -static int dvb_usb_af9015_remote; -module_param_named(remote, dvb_usb_af9015_remote, int, 0644); -MODULE_PARM_DESC(remote, "select remote"); -DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); - -static DEFINE_MUTEX(af9015_usb_mutex); - -static struct af9015_config af9015_config; -static struct dvb_usb_device_properties af9015_properties[3]; -static int af9015_properties_count = ARRAY_SIZE(af9015_properties); - -static struct af9013_config af9015_af9013_config[] = { - { - .i2c_addr = AF9015_I2C_DEMOD, - .ts_mode = AF9013_TS_USB, - .api_version = { 0, 1, 9, 0 }, - .gpio[0] = AF9013_GPIO_HI, - .gpio[3] = AF9013_GPIO_TUNER_ON, - - }, { - .ts_mode = AF9013_TS_SERIAL, - .api_version = { 0, 1, 9, 0 }, - .gpio[0] = AF9013_GPIO_TUNER_ON, - .gpio[1] = AF9013_GPIO_LO, - } -}; - -static int af9015_rw_udev(struct usb_device *udev, struct req_t *req) -{ -#define BUF_LEN 63 -#define REQ_HDR_LEN 8 /* send header size */ -#define ACK_HDR_LEN 2 /* rece header size */ - int act_len, ret; - u8 buf[BUF_LEN]; - u8 write = 1; - u8 msg_len = REQ_HDR_LEN; - static u8 seq; /* packet sequence number */ - - if (mutex_lock_interruptible(&af9015_usb_mutex) < 0) - return -EAGAIN; - - buf[0] = req->cmd; - buf[1] = seq++; - buf[2] = req->i2c_addr; - buf[3] = req->addr >> 8; - buf[4] = req->addr & 0xff; - buf[5] = req->mbox; - buf[6] = req->addr_len; - buf[7] = req->data_len; - - switch (req->cmd) { - case GET_CONFIG: - case READ_MEMORY: - case RECONNECT_USB: - write = 0; - break; - case READ_I2C: - write = 0; - buf[2] |= 0x01; /* set I2C direction */ - case WRITE_I2C: - buf[0] = READ_WRITE_I2C; - break; - case WRITE_MEMORY: - if (((req->addr & 0xff00) == 0xff00) || - ((req->addr & 0xff00) == 0xae00)) - buf[0] = WRITE_VIRTUAL_MEMORY; - case WRITE_VIRTUAL_MEMORY: - case COPY_FIRMWARE: - case DOWNLOAD_FIRMWARE: - case BOOT: - break; - default: - err("unknown command:%d", req->cmd); - ret = -1; - goto error_unlock; - } - - /* buffer overflow check */ - if ((write && (req->data_len > BUF_LEN - REQ_HDR_LEN)) || - (!write && (req->data_len > BUF_LEN - ACK_HDR_LEN))) { - err("too much data; cmd:%d len:%d", req->cmd, req->data_len); - ret = -EINVAL; - goto error_unlock; - } - - /* write requested */ - if (write) { - memcpy(&buf[REQ_HDR_LEN], req->data, req->data_len); - msg_len += req->data_len; - } - - deb_xfer(">>> "); - debug_dump(buf, msg_len, deb_xfer); - - /* send req */ - ret = usb_bulk_msg(udev, usb_sndbulkpipe(udev, 0x02), buf, msg_len, - &act_len, AF9015_USB_TIMEOUT); - if (ret) - err("bulk message failed:%d (%d/%d)", ret, msg_len, act_len); - else - if (act_len != msg_len) - ret = -1; /* all data is not send */ - if (ret) - goto error_unlock; - - /* no ack for those packets */ - if (req->cmd == DOWNLOAD_FIRMWARE || req->cmd == RECONNECT_USB) - goto exit_unlock; - - /* write receives seq + status = 2 bytes - read receives seq + status + data = 2 + N bytes */ - msg_len = ACK_HDR_LEN; - if (!write) - msg_len += req->data_len; - - ret = usb_bulk_msg(udev, usb_rcvbulkpipe(udev, 0x81), buf, msg_len, - &act_len, AF9015_USB_TIMEOUT); - if (ret) { - err("recv bulk message failed:%d", ret); - ret = -1; - goto error_unlock; - } - - deb_xfer("<<< "); - debug_dump(buf, act_len, deb_xfer); - - /* check status */ - if (buf[1]) { - err("command failed:%d", buf[1]); - ret = -1; - goto error_unlock; - } - - /* read request, copy returned data to return buf */ - if (!write) - memcpy(req->data, &buf[ACK_HDR_LEN], req->data_len); - -error_unlock: -exit_unlock: - mutex_unlock(&af9015_usb_mutex); - - return ret; -} - -static int af9015_ctrl_msg(struct dvb_usb_device *d, struct req_t *req) -{ - return af9015_rw_udev(d->udev, req); -} - -static int af9015_write_regs(struct dvb_usb_device *d, u16 addr, u8 *val, - u8 len) -{ - struct req_t req = {WRITE_MEMORY, AF9015_I2C_DEMOD, addr, 0, 0, len, - val}; - return af9015_ctrl_msg(d, &req); -} - -static int af9015_write_reg(struct dvb_usb_device *d, u16 addr, u8 val) -{ - return af9015_write_regs(d, addr, &val, 1); -} - -static int af9015_read_regs(struct dvb_usb_device *d, u16 addr, u8 *val, u8 len) -{ - struct req_t req = {READ_MEMORY, AF9015_I2C_DEMOD, addr, 0, 0, len, - val}; - return af9015_ctrl_msg(d, &req); -} - -static int af9015_read_reg(struct dvb_usb_device *d, u16 addr, u8 *val) -{ - return af9015_read_regs(d, addr, val, 1); -} - -static int af9015_write_reg_i2c(struct dvb_usb_device *d, u8 addr, u16 reg, - u8 val) -{ - struct req_t req = {WRITE_I2C, addr, reg, 1, 1, 1, &val}; - - if (addr == af9015_af9013_config[0].i2c_addr || - addr == af9015_af9013_config[1].i2c_addr) - req.addr_len = 3; - - return af9015_ctrl_msg(d, &req); -} - -static int af9015_read_reg_i2c(struct dvb_usb_device *d, u8 addr, u16 reg, - u8 *val) -{ - struct req_t req = {READ_I2C, addr, reg, 0, 1, 1, val}; - - if (addr == af9015_af9013_config[0].i2c_addr || - addr == af9015_af9013_config[1].i2c_addr) - req.addr_len = 3; - - return af9015_ctrl_msg(d, &req); -} - -static int af9015_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], - int num) -{ - struct dvb_usb_device *d = i2c_get_adapdata(adap); - int ret = 0, i = 0; - u16 addr; - u8 uninitialized_var(mbox), addr_len; - struct req_t req; - -/* -The bus lock is needed because there is two tuners both using same I2C-address. -Due to that the only way to select correct tuner is use demodulator I2C-gate. - -................................................ -. AF9015 includes integrated AF9013 demodulator. -. ____________ ____________ . ____________ -.| uC | | demod | . | tuner | -.|------------| |------------| . |------------| -.| AF9015 | | AF9013/5 | . | MXL5003 | -.| |--+----I2C-------|-----/ -----|-.-----I2C-------| | -.| | | | addr 0x38 | . | addr 0xc6 | -.|____________| | |____________| . |____________| -.................|.............................. - | ____________ ____________ - | | demod | | tuner | - | |------------| |------------| - | | AF9013 | | MXL5003 | - +----I2C-------|-----/ -----|-------I2C-------| | - | addr 0x3a | | addr 0xc6 | - |____________| |____________| -*/ - if (mutex_lock_interruptible(&d->i2c_mutex) < 0) - return -EAGAIN; - - while (i < num) { - if (msg[i].addr == af9015_af9013_config[0].i2c_addr || - msg[i].addr == af9015_af9013_config[1].i2c_addr) { - addr = msg[i].buf[0] << 8; - addr += msg[i].buf[1]; - mbox = msg[i].buf[2]; - addr_len = 3; - } else { - addr = msg[i].buf[0]; - addr_len = 1; - /* mbox is don't care in that case */ - } - - if (num > i + 1 && (msg[i+1].flags & I2C_M_RD)) { - if (msg[i].len > 3 || msg[i+1].len > 61) { - ret = -EOPNOTSUPP; - goto error; - } - if (msg[i].addr == af9015_af9013_config[0].i2c_addr) - req.cmd = READ_MEMORY; - else - req.cmd = READ_I2C; - req.i2c_addr = msg[i].addr; - req.addr = addr; - req.mbox = mbox; - req.addr_len = addr_len; - req.data_len = msg[i+1].len; - req.data = &msg[i+1].buf[0]; - ret = af9015_ctrl_msg(d, &req); - i += 2; - } else if (msg[i].flags & I2C_M_RD) { - if (msg[i].len > 61) { - ret = -EOPNOTSUPP; - goto error; - } - if (msg[i].addr == - af9015_af9013_config[0].i2c_addr) { - ret = -EINVAL; - goto error; - } - req.cmd = READ_I2C; - req.i2c_addr = msg[i].addr; - req.addr = addr; - req.mbox = mbox; - req.addr_len = addr_len; - req.data_len = msg[i].len; - req.data = &msg[i].buf[0]; - ret = af9015_ctrl_msg(d, &req); - i += 1; - } else { - if (msg[i].len > 21) { - ret = -EOPNOTSUPP; - goto error; - } - if (msg[i].addr == af9015_af9013_config[0].i2c_addr) - req.cmd = WRITE_MEMORY; - else - req.cmd = WRITE_I2C; - req.i2c_addr = msg[i].addr; - req.addr = addr; - req.mbox = mbox; - req.addr_len = addr_len; - req.data_len = msg[i].len-addr_len; - req.data = &msg[i].buf[addr_len]; - ret = af9015_ctrl_msg(d, &req); - i += 1; - } - if (ret) - goto error; - - } - ret = i; - -error: - mutex_unlock(&d->i2c_mutex); - - return ret; -} - -static u32 af9015_i2c_func(struct i2c_adapter *adapter) -{ - return I2C_FUNC_I2C; -} - -static struct i2c_algorithm af9015_i2c_algo = { - .master_xfer = af9015_i2c_xfer, - .functionality = af9015_i2c_func, -}; - -static int af9015_do_reg_bit(struct dvb_usb_device *d, u16 addr, u8 bit, u8 op) -{ - int ret; - u8 val, mask = 0x01; - - ret = af9015_read_reg(d, addr, &val); - if (ret) - return ret; - - mask <<= bit; - if (op) { - /* set bit */ - val |= mask; - } else { - /* clear bit */ - mask ^= 0xff; - val &= mask; - } - - return af9015_write_reg(d, addr, val); -} - -static int af9015_set_reg_bit(struct dvb_usb_device *d, u16 addr, u8 bit) -{ - return af9015_do_reg_bit(d, addr, bit, 1); -} - -static int af9015_clear_reg_bit(struct dvb_usb_device *d, u16 addr, u8 bit) -{ - return af9015_do_reg_bit(d, addr, bit, 0); -} - -static int af9015_init_endpoint(struct dvb_usb_device *d) -{ - int ret; - u16 frame_size; - u8 packet_size; - deb_info("%s: USB speed:%d\n", __func__, d->udev->speed); - - /* Windows driver uses packet count 21 for USB1.1 and 348 for USB2.0. - We use smaller - about 1/4 from the original, 5 and 87. */ -#define TS_PACKET_SIZE 188 - -#define TS_USB20_PACKET_COUNT 87 -#define TS_USB20_FRAME_SIZE (TS_PACKET_SIZE*TS_USB20_PACKET_COUNT) - -#define TS_USB11_PACKET_COUNT 5 -#define TS_USB11_FRAME_SIZE (TS_PACKET_SIZE*TS_USB11_PACKET_COUNT) - -#define TS_USB20_MAX_PACKET_SIZE 512 -#define TS_USB11_MAX_PACKET_SIZE 64 - - if (d->udev->speed == USB_SPEED_FULL) { - frame_size = TS_USB11_FRAME_SIZE/4; - packet_size = TS_USB11_MAX_PACKET_SIZE/4; - } else { - frame_size = TS_USB20_FRAME_SIZE/4; - packet_size = TS_USB20_MAX_PACKET_SIZE/4; - } - - ret = af9015_set_reg_bit(d, 0xd507, 2); /* assert EP4 reset */ - if (ret) - goto error; - ret = af9015_set_reg_bit(d, 0xd50b, 1); /* assert EP5 reset */ - if (ret) - goto error; - ret = af9015_clear_reg_bit(d, 0xdd11, 5); /* disable EP4 */ - if (ret) - goto error; - ret = af9015_clear_reg_bit(d, 0xdd11, 6); /* disable EP5 */ - if (ret) - goto error; - ret = af9015_set_reg_bit(d, 0xdd11, 5); /* enable EP4 */ - if (ret) - goto error; - if (af9015_config.dual_mode) { - ret = af9015_set_reg_bit(d, 0xdd11, 6); /* enable EP5 */ - if (ret) - goto error; - } - ret = af9015_clear_reg_bit(d, 0xdd13, 5); /* disable EP4 NAK */ - if (ret) - goto error; - if (af9015_config.dual_mode) { - ret = af9015_clear_reg_bit(d, 0xdd13, 6); /* disable EP5 NAK */ - if (ret) - goto error; - } - /* EP4 xfer length */ - ret = af9015_write_reg(d, 0xdd88, frame_size & 0xff); - if (ret) - goto error; - ret = af9015_write_reg(d, 0xdd89, frame_size >> 8); - if (ret) - goto error; - /* EP5 xfer length */ - ret = af9015_write_reg(d, 0xdd8a, frame_size & 0xff); - if (ret) - goto error; - ret = af9015_write_reg(d, 0xdd8b, frame_size >> 8); - if (ret) - goto error; - ret = af9015_write_reg(d, 0xdd0c, packet_size); /* EP4 packet size */ - if (ret) - goto error; - ret = af9015_write_reg(d, 0xdd0d, packet_size); /* EP5 packet size */ - if (ret) - goto error; - ret = af9015_clear_reg_bit(d, 0xd507, 2); /* negate EP4 reset */ - if (ret) - goto error; - if (af9015_config.dual_mode) { - ret = af9015_clear_reg_bit(d, 0xd50b, 1); /* negate EP5 reset */ - if (ret) - goto error; - } - - /* enable / disable mp2if2 */ - if (af9015_config.dual_mode) - ret = af9015_set_reg_bit(d, 0xd50b, 0); - else - ret = af9015_clear_reg_bit(d, 0xd50b, 0); - -error: - if (ret) - err("endpoint init failed:%d", ret); - return ret; -} - -static int af9015_copy_firmware(struct dvb_usb_device *d) -{ - int ret; - u8 fw_params[4]; - u8 val, i; - struct req_t req = {COPY_FIRMWARE, 0, 0x5100, 0, 0, sizeof(fw_params), - fw_params }; - deb_info("%s:\n", __func__); - - fw_params[0] = af9015_config.firmware_size >> 8; - fw_params[1] = af9015_config.firmware_size & 0xff; - fw_params[2] = af9015_config.firmware_checksum >> 8; - fw_params[3] = af9015_config.firmware_checksum & 0xff; - - /* wait 2nd demodulator ready */ - msleep(100); - - ret = af9015_read_reg_i2c(d, - af9015_af9013_config[1].i2c_addr, 0x98be, &val); - if (ret) - goto error; - else - deb_info("%s: firmware status:%02x\n", __func__, val); - - if (val == 0x0c) /* fw is running, no need for download */ - goto exit; - - /* set I2C master clock to fast (to speed up firmware copy) */ - ret = af9015_write_reg(d, 0xd416, 0x04); /* 0x04 * 400ns */ - if (ret) - goto error; - - msleep(50); - - /* copy firmware */ - ret = af9015_ctrl_msg(d, &req); - if (ret) - err("firmware copy cmd failed:%d", ret); - deb_info("%s: firmware copy done\n", __func__); - - /* set I2C master clock back to normal */ - ret = af9015_write_reg(d, 0xd416, 0x14); /* 0x14 * 400ns */ - if (ret) - goto error; - - /* request boot firmware */ - ret = af9015_write_reg_i2c(d, af9015_af9013_config[1].i2c_addr, - 0xe205, 1); - deb_info("%s: firmware boot cmd status:%d\n", __func__, ret); - if (ret) - goto error; - - for (i = 0; i < 15; i++) { - msleep(100); - - /* check firmware status */ - ret = af9015_read_reg_i2c(d, - af9015_af9013_config[1].i2c_addr, 0x98be, &val); - deb_info("%s: firmware status cmd status:%d fw status:%02x\n", - __func__, ret, val); - if (ret) - goto error; - - if (val == 0x0c || val == 0x04) /* success or fail */ - break; - } - - if (val == 0x04) { - err("firmware did not run"); - ret = -1; - } else if (val != 0x0c) { - err("firmware boot timeout"); - ret = -1; - } - -error: -exit: - return ret; -} - -/* hash (and dump) eeprom */ -static int af9015_eeprom_hash(struct usb_device *udev) -{ - static const unsigned int eeprom_size = 256; - unsigned int reg; - int ret; - u8 val, *eeprom; - struct req_t req = {READ_I2C, AF9015_I2C_EEPROM, 0, 0, 1, 1, &val}; - - eeprom = kmalloc(eeprom_size, GFP_KERNEL); - if (eeprom == NULL) - return -ENOMEM; - - for (reg = 0; reg < eeprom_size; reg++) { - req.addr = reg; - ret = af9015_rw_udev(udev, &req); - if (ret) - goto free; - eeprom[reg] = val; - } - - if (dvb_usb_af9015_debug & 0x01) - print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, eeprom, - eeprom_size); - - BUG_ON(eeprom_size % 4); - - af9015_config.eeprom_sum = 0; - for (reg = 0; reg < eeprom_size / sizeof(u32); reg++) { - af9015_config.eeprom_sum *= GOLDEN_RATIO_PRIME_32; - af9015_config.eeprom_sum += le32_to_cpu(((u32 *)eeprom)[reg]); - } - - deb_info("%s: eeprom sum=%.8x\n", __func__, af9015_config.eeprom_sum); - - ret = 0; -free: - kfree(eeprom); - return ret; -} - -static int af9015_init(struct dvb_usb_device *d) -{ - int ret; - deb_info("%s:\n", __func__); - - /* init RC canary */ - ret = af9015_write_reg(d, 0x98e9, 0xff); - if (ret) - goto error; - - ret = af9015_init_endpoint(d); - if (ret) - goto error; - -error: - return ret; -} - -static int af9015_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff) -{ - int ret; - deb_info("%s: onoff:%d\n", __func__, onoff); - - if (onoff) - ret = af9015_set_reg_bit(adap->dev, 0xd503, 0); - else - ret = af9015_clear_reg_bit(adap->dev, 0xd503, 0); - - return ret; -} - -static int af9015_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid, - int onoff) -{ - int ret; - u8 idx; - - deb_info("%s: set pid filter, index %d, pid %x, onoff %d\n", - __func__, index, pid, onoff); - - ret = af9015_write_reg(adap->dev, 0xd505, (pid & 0xff)); - if (ret) - goto error; - - ret = af9015_write_reg(adap->dev, 0xd506, (pid >> 8)); - if (ret) - goto error; - - idx = ((index & 0x1f) | (1 << 5)); - ret = af9015_write_reg(adap->dev, 0xd504, idx); - -error: - return ret; -} - -static int af9015_download_firmware(struct usb_device *udev, - const struct firmware *fw) -{ - int i, len, remaining, ret; - struct req_t req = {DOWNLOAD_FIRMWARE, 0, 0, 0, 0, 0, NULL}; - u16 checksum = 0; - - deb_info("%s:\n", __func__); - - /* calc checksum */ - for (i = 0; i < fw->size; i++) - checksum += fw->data[i]; - - af9015_config.firmware_size = fw->size; - af9015_config.firmware_checksum = checksum; - - #define FW_ADDR 0x5100 /* firmware start address */ - #define LEN_MAX 55 /* max packet size */ - for (remaining = fw->size; remaining > 0; remaining -= LEN_MAX) { - len = remaining; - if (len > LEN_MAX) - len = LEN_MAX; - - req.data_len = len; - req.data = (u8 *) &fw->data[fw->size - remaining]; - req.addr = FW_ADDR + fw->size - remaining; - - ret = af9015_rw_udev(udev, &req); - if (ret) { - err("firmware download failed:%d", ret); - goto error; - } - } - - /* firmware loaded, request boot */ - req.cmd = BOOT; - ret = af9015_rw_udev(udev, &req); - if (ret) { - err("firmware boot failed:%d", ret); - goto error; - } - -error: - return ret; -} - -struct af9015_rc_setup { - unsigned int id; - char *rc_codes; -}; - -static char *af9015_rc_setup_match(unsigned int id, - const struct af9015_rc_setup *table) -{ - for (; table->rc_codes; table++) - if (table->id == id) - return table->rc_codes; - return NULL; -} - -static const struct af9015_rc_setup af9015_rc_setup_modparam[] = { - { AF9015_REMOTE_A_LINK_DTU_M, RC_MAP_ALINK_DTU_M }, - { AF9015_REMOTE_MSI_DIGIVOX_MINI_II_V3, RC_MAP_MSI_DIGIVOX_II }, - { AF9015_REMOTE_MYGICTV_U718, RC_MAP_TOTAL_MEDIA_IN_HAND }, - { AF9015_REMOTE_DIGITTRADE_DVB_T, RC_MAP_DIGITTRADE }, - { AF9015_REMOTE_AVERMEDIA_KS, RC_MAP_AVERMEDIA_RM_KS }, - { } -}; - -static const struct af9015_rc_setup af9015_rc_setup_hashes[] = { - { 0xb8feb708, RC_MAP_MSI_DIGIVOX_II }, - { 0xa3703d00, RC_MAP_ALINK_DTU_M }, - { 0x9b7dc64e, RC_MAP_TOTAL_MEDIA_IN_HAND }, /* MYGICTV U718 */ - { 0x5d49e3db, RC_MAP_DIGITTRADE }, /* LC-Power LC-USB-DVBT */ - { } -}; - -static const struct af9015_rc_setup af9015_rc_setup_usbids[] = { - { (USB_VID_TERRATEC << 16) | USB_PID_TERRATEC_CINERGY_T_STICK_RC, - RC_MAP_TERRATEC_SLIM_2 }, - { (USB_VID_TERRATEC << 16) | USB_PID_TERRATEC_CINERGY_T_STICK_DUAL_RC, - RC_MAP_TERRATEC_SLIM }, - { (USB_VID_VISIONPLUS << 16) | USB_PID_AZUREWAVE_AD_TU700, - RC_MAP_AZUREWAVE_AD_TU700 }, - { (USB_VID_VISIONPLUS << 16) | USB_PID_TINYTWIN, - RC_MAP_AZUREWAVE_AD_TU700 }, - { (USB_VID_MSI_2 << 16) | USB_PID_MSI_DIGI_VOX_MINI_III, - RC_MAP_MSI_DIGIVOX_III }, - { (USB_VID_MSI_2 << 16) | USB_PID_MSI_DIGIVOX_DUO, - RC_MAP_MSI_DIGIVOX_III }, - { (USB_VID_LEADTEK << 16) | USB_PID_WINFAST_DTV_DONGLE_GOLD, - RC_MAP_LEADTEK_Y04G0051 }, - { (USB_VID_LEADTEK << 16) | USB_PID_WINFAST_DTV2000DS, - RC_MAP_LEADTEK_Y04G0051 }, - { (USB_VID_AVERMEDIA << 16) | USB_PID_AVERMEDIA_VOLAR_X, - RC_MAP_AVERMEDIA_M135A }, - { (USB_VID_AFATECH << 16) | USB_PID_TREKSTOR_DVBT, - RC_MAP_TREKSTOR }, - { (USB_VID_KWORLD_2 << 16) | USB_PID_TINYTWIN_2, - RC_MAP_DIGITALNOW_TINYTWIN }, - { (USB_VID_GTEK << 16) | USB_PID_TINYTWIN_3, - RC_MAP_DIGITALNOW_TINYTWIN }, - { (USB_VID_KWORLD_2 << 16) | USB_PID_SVEON_STV22, - RC_MAP_MSI_DIGIVOX_III }, - { } -}; - -static void af9015_set_remote_config(struct usb_device *udev, - struct dvb_usb_device_properties *props) -{ - u16 vid = le16_to_cpu(udev->descriptor.idVendor); - u16 pid = le16_to_cpu(udev->descriptor.idProduct); - - /* try to load remote based module param */ - props->rc.core.rc_codes = af9015_rc_setup_match( - dvb_usb_af9015_remote, af9015_rc_setup_modparam); - - /* try to load remote based eeprom hash */ - if (!props->rc.core.rc_codes) - props->rc.core.rc_codes = af9015_rc_setup_match( - af9015_config.eeprom_sum, af9015_rc_setup_hashes); - - /* try to load remote based USB ID */ - if (!props->rc.core.rc_codes) - props->rc.core.rc_codes = af9015_rc_setup_match( - (vid << 16) | pid, af9015_rc_setup_usbids); - - /* try to load remote based USB iManufacturer string */ - if (!props->rc.core.rc_codes && vid == USB_VID_AFATECH) { - /* Check USB manufacturer and product strings and try - to determine correct remote in case of chip vendor - reference IDs are used. - DO NOT ADD ANYTHING NEW HERE. Use hashes instead. */ - char manufacturer[10]; - memset(manufacturer, 0, sizeof(manufacturer)); - usb_string(udev, udev->descriptor.iManufacturer, - manufacturer, sizeof(manufacturer)); - if (!strcmp("MSI", manufacturer)) { - /* iManufacturer 1 MSI - iProduct 2 MSI K-VOX */ - props->rc.core.rc_codes = af9015_rc_setup_match( - AF9015_REMOTE_MSI_DIGIVOX_MINI_II_V3, - af9015_rc_setup_modparam); - } - } - - /* finally load "empty" just for leaving IR receiver enabled */ - if (!props->rc.core.rc_codes) - props->rc.core.rc_codes = RC_MAP_EMPTY; - - return; -} - -static int af9015_read_config(struct usb_device *udev) -{ - int ret; - u8 val, i, offset = 0; - struct req_t req = {READ_I2C, AF9015_I2C_EEPROM, 0, 0, 1, 1, &val}; - - /* IR remote controller */ - req.addr = AF9015_EEPROM_IR_MODE; - /* first message will timeout often due to possible hw bug */ - for (i = 0; i < 4; i++) { - ret = af9015_rw_udev(udev, &req); - if (!ret) - break; - } - if (ret) - goto error; - - ret = af9015_eeprom_hash(udev); - if (ret) - goto error; - - deb_info("%s: IR mode=%d\n", __func__, val); - for (i = 0; i < af9015_properties_count; i++) { - if (val == AF9015_IR_MODE_DISABLED) - af9015_properties[i].rc.core.rc_codes = NULL; - else - af9015_set_remote_config(udev, &af9015_properties[i]); - } - - /* TS mode - one or two receivers */ - req.addr = AF9015_EEPROM_TS_MODE; - ret = af9015_rw_udev(udev, &req); - if (ret) - goto error; - af9015_config.dual_mode = val; - deb_info("%s: TS mode=%d\n", __func__, af9015_config.dual_mode); - - /* Set adapter0 buffer size according to USB port speed, adapter1 buffer - size can be static because it is enabled only USB2.0 */ - for (i = 0; i < af9015_properties_count; i++) { - /* USB1.1 set smaller buffersize and disable 2nd adapter */ - if (udev->speed == USB_SPEED_FULL) { - af9015_properties[i].adapter[0].fe[0].stream.u.bulk.buffersize - = TS_USB11_FRAME_SIZE; - /* disable 2nd adapter because we don't have - PID-filters */ - af9015_config.dual_mode = 0; - } else { - af9015_properties[i].adapter[0].fe[0].stream.u.bulk.buffersize - = TS_USB20_FRAME_SIZE; - } - } - - if (af9015_config.dual_mode) { - /* read 2nd demodulator I2C address */ - req.addr = AF9015_EEPROM_DEMOD2_I2C; - ret = af9015_rw_udev(udev, &req); - if (ret) - goto error; - af9015_af9013_config[1].i2c_addr = val; - - /* enable 2nd adapter */ - for (i = 0; i < af9015_properties_count; i++) - af9015_properties[i].num_adapters = 2; - - } else { - /* disable 2nd adapter */ - for (i = 0; i < af9015_properties_count; i++) - af9015_properties[i].num_adapters = 1; - } - - for (i = 0; i < af9015_properties[0].num_adapters; i++) { - if (i == 1) - offset = AF9015_EEPROM_OFFSET; - /* xtal */ - req.addr = AF9015_EEPROM_XTAL_TYPE1 + offset; - ret = af9015_rw_udev(udev, &req); - if (ret) - goto error; - switch (val) { - case 0: - af9015_af9013_config[i].clock = 28800000; - break; - case 1: - af9015_af9013_config[i].clock = 20480000; - break; - case 2: - af9015_af9013_config[i].clock = 28000000; - break; - case 3: - af9015_af9013_config[i].clock = 25000000; - break; - }; - deb_info("%s: [%d] xtal=%d set clock=%d\n", __func__, i, - val, af9015_af9013_config[i].clock); - - /* IF frequency */ - req.addr = AF9015_EEPROM_IF1H + offset; - ret = af9015_rw_udev(udev, &req); - if (ret) - goto error; - - af9015_af9013_config[i].if_frequency = val << 8; - - req.addr = AF9015_EEPROM_IF1L + offset; - ret = af9015_rw_udev(udev, &req); - if (ret) - goto error; - - af9015_af9013_config[i].if_frequency += val; - af9015_af9013_config[i].if_frequency *= 1000; - deb_info("%s: [%d] IF frequency=%d\n", __func__, i, - af9015_af9013_config[0].if_frequency); - - /* MT2060 IF1 */ - req.addr = AF9015_EEPROM_MT2060_IF1H + offset; - ret = af9015_rw_udev(udev, &req); - if (ret) - goto error; - af9015_config.mt2060_if1[i] = val << 8; - req.addr = AF9015_EEPROM_MT2060_IF1L + offset; - ret = af9015_rw_udev(udev, &req); - if (ret) - goto error; - af9015_config.mt2060_if1[i] += val; - deb_info("%s: [%d] MT2060 IF1=%d\n", __func__, i, - af9015_config.mt2060_if1[i]); - - /* tuner */ - req.addr = AF9015_EEPROM_TUNER_ID1 + offset; - ret = af9015_rw_udev(udev, &req); - if (ret) - goto error; - switch (val) { - case AF9013_TUNER_ENV77H11D5: - case AF9013_TUNER_MT2060: - case AF9013_TUNER_QT1010: - case AF9013_TUNER_UNKNOWN: - case AF9013_TUNER_MT2060_2: - case AF9013_TUNER_TDA18271: - case AF9013_TUNER_QT1010A: - case AF9013_TUNER_TDA18218: - af9015_af9013_config[i].spec_inv = 1; - break; - case AF9013_TUNER_MXL5003D: - case AF9013_TUNER_MXL5005D: - case AF9013_TUNER_MXL5005R: - case AF9013_TUNER_MXL5007T: - af9015_af9013_config[i].spec_inv = 0; - break; - case AF9013_TUNER_MC44S803: - af9015_af9013_config[i].gpio[1] = AF9013_GPIO_LO; - af9015_af9013_config[i].spec_inv = 1; - break; - default: - warn("tuner id=%d not supported, please report!", val); - return -ENODEV; - }; - - af9015_af9013_config[i].tuner = val; - deb_info("%s: [%d] tuner id=%d\n", __func__, i, val); - } - -error: - if (ret) - err("eeprom read failed=%d", ret); - - /* AverMedia AVerTV Volar Black HD (A850) device have bad EEPROM - content :-( Override some wrong values here. Ditto for the - AVerTV Red HD+ (A850T) device. */ - if (le16_to_cpu(udev->descriptor.idVendor) == USB_VID_AVERMEDIA && - ((le16_to_cpu(udev->descriptor.idProduct) == - USB_PID_AVERMEDIA_A850) || - (le16_to_cpu(udev->descriptor.idProduct) == - USB_PID_AVERMEDIA_A850T))) { - deb_info("%s: AverMedia A850: overriding config\n", __func__); - /* disable dual mode */ - af9015_config.dual_mode = 0; - /* disable 2nd adapter */ - for (i = 0; i < af9015_properties_count; i++) - af9015_properties[i].num_adapters = 1; - - /* set correct IF */ - af9015_af9013_config[0].if_frequency = 4570000; - } - - return ret; -} - -static int af9015_identify_state(struct usb_device *udev, - struct dvb_usb_device_properties *props, - struct dvb_usb_device_description **desc, - int *cold) -{ - int ret; - u8 reply; - struct req_t req = {GET_CONFIG, 0, 0, 0, 0, 1, &reply}; - - ret = af9015_rw_udev(udev, &req); - if (ret) - return ret; - - deb_info("%s: reply:%02x\n", __func__, reply); - if (reply == 0x02) - *cold = 0; - else - *cold = 1; - - return ret; -} - -static int af9015_rc_query(struct dvb_usb_device *d) -{ - struct af9015_state *priv = d->priv; - int ret; - u8 buf[17]; - - /* read registers needed to detect remote controller code */ - ret = af9015_read_regs(d, 0x98d9, buf, sizeof(buf)); - if (ret) - goto error; - - /* If any of these are non-zero, assume invalid data */ - if (buf[1] || buf[2] || buf[3]) - return ret; - - /* Check for repeat of previous code */ - if ((priv->rc_repeat != buf[6] || buf[0]) && - !memcmp(&buf[12], priv->rc_last, 4)) { - deb_rc("%s: key repeated\n", __func__); - rc_keydown(d->rc_dev, priv->rc_keycode, 0); - priv->rc_repeat = buf[6]; - return ret; - } - - /* Only process key if canary killed */ - if (buf[16] != 0xff && buf[0] != 0x01) { - deb_rc("%s: key pressed %02x %02x %02x %02x\n", __func__, - buf[12], buf[13], buf[14], buf[15]); - - /* Reset the canary */ - ret = af9015_write_reg(d, 0x98e9, 0xff); - if (ret) - goto error; - - /* Remember this key */ - memcpy(priv->rc_last, &buf[12], 4); - if (buf[14] == (u8) ~buf[15]) { - if (buf[12] == (u8) ~buf[13]) { - /* NEC */ - priv->rc_keycode = buf[12] << 8 | buf[14]; - } else { - /* NEC extended*/ - priv->rc_keycode = buf[12] << 16 | - buf[13] << 8 | buf[14]; - } - } else { - /* 32 bit NEC */ - priv->rc_keycode = buf[12] << 24 | buf[13] << 16 | - buf[14] << 8 | buf[15]; - } - rc_keydown(d->rc_dev, priv->rc_keycode, 0); - } else { - deb_rc("%s: no key press\n", __func__); - /* Invalidate last keypress */ - /* Not really needed, but helps with debug */ - priv->rc_last[2] = priv->rc_last[3]; - } - - priv->rc_repeat = buf[6]; - -error: - if (ret) - err("%s: failed:%d", __func__, ret); - - return ret; -} - -/* override demod callbacks for resource locking */ -static int af9015_af9013_set_frontend(struct dvb_frontend *fe) -{ - int ret; - struct dvb_usb_adapter *adap = fe->dvb->priv; - struct af9015_state *priv = adap->dev->priv; - - if (mutex_lock_interruptible(&adap->dev->usb_mutex)) - return -EAGAIN; - - ret = priv->set_frontend[adap->id](fe); - - mutex_unlock(&adap->dev->usb_mutex); - - return ret; -} - -/* override demod callbacks for resource locking */ -static int af9015_af9013_read_status(struct dvb_frontend *fe, - fe_status_t *status) -{ - int ret; - struct dvb_usb_adapter *adap = fe->dvb->priv; - struct af9015_state *priv = adap->dev->priv; - - if (mutex_lock_interruptible(&adap->dev->usb_mutex)) - return -EAGAIN; - - ret = priv->read_status[adap->id](fe, status); - - mutex_unlock(&adap->dev->usb_mutex); - - return ret; -} - -/* override demod callbacks for resource locking */ -static int af9015_af9013_init(struct dvb_frontend *fe) -{ - int ret; - struct dvb_usb_adapter *adap = fe->dvb->priv; - struct af9015_state *priv = adap->dev->priv; - - if (mutex_lock_interruptible(&adap->dev->usb_mutex)) - return -EAGAIN; - - ret = priv->init[adap->id](fe); - - mutex_unlock(&adap->dev->usb_mutex); - - return ret; -} - -/* override demod callbacks for resource locking */ -static int af9015_af9013_sleep(struct dvb_frontend *fe) -{ - int ret; - struct dvb_usb_adapter *adap = fe->dvb->priv; - struct af9015_state *priv = adap->dev->priv; - - if (mutex_lock_interruptible(&adap->dev->usb_mutex)) - return -EAGAIN; - - ret = priv->sleep[adap->id](fe); - - mutex_unlock(&adap->dev->usb_mutex); - - return ret; -} - -/* override tuner callbacks for resource locking */ -static int af9015_tuner_init(struct dvb_frontend *fe) -{ - int ret; - struct dvb_usb_adapter *adap = fe->dvb->priv; - struct af9015_state *priv = adap->dev->priv; - - if (mutex_lock_interruptible(&adap->dev->usb_mutex)) - return -EAGAIN; - - ret = priv->tuner_init[adap->id](fe); - - mutex_unlock(&adap->dev->usb_mutex); - - return ret; -} - -/* override tuner callbacks for resource locking */ -static int af9015_tuner_sleep(struct dvb_frontend *fe) -{ - int ret; - struct dvb_usb_adapter *adap = fe->dvb->priv; - struct af9015_state *priv = adap->dev->priv; - - if (mutex_lock_interruptible(&adap->dev->usb_mutex)) - return -EAGAIN; - - ret = priv->tuner_sleep[adap->id](fe); - - mutex_unlock(&adap->dev->usb_mutex); - - return ret; -} - - -static int af9015_af9013_frontend_attach(struct dvb_usb_adapter *adap) -{ - int ret; - struct af9015_state *state = adap->dev->priv; - - if (adap->id == 1) { - /* copy firmware to 2nd demodulator */ - if (af9015_config.dual_mode) { - ret = af9015_copy_firmware(adap->dev); - if (ret) { - err("firmware copy to 2nd frontend " \ - "failed, will disable it"); - af9015_config.dual_mode = 0; - return -ENODEV; - } - } else { - return -ENODEV; - } - } - - /* attach demodulator */ - adap->fe_adap[0].fe = dvb_attach(af9013_attach, - &af9015_af9013_config[adap->id], &adap->dev->i2c_adap); - - /* - * AF9015 firmware does not like if it gets interrupted by I2C adapter - * request on some critical phases. During normal operation I2C adapter - * is used only 2nd demodulator and tuner on dual tuner devices. - * Override demodulator callbacks and use mutex for limit access to - * those "critical" paths to keep AF9015 happy. - * Note: we abuse unused usb_mutex here. - */ - if (adap->fe_adap[0].fe) { - state->set_frontend[adap->id] = - adap->fe_adap[0].fe->ops.set_frontend; - adap->fe_adap[0].fe->ops.set_frontend = - af9015_af9013_set_frontend; - - state->read_status[adap->id] = - adap->fe_adap[0].fe->ops.read_status; - adap->fe_adap[0].fe->ops.read_status = - af9015_af9013_read_status; - - state->init[adap->id] = adap->fe_adap[0].fe->ops.init; - adap->fe_adap[0].fe->ops.init = af9015_af9013_init; - - state->sleep[adap->id] = adap->fe_adap[0].fe->ops.sleep; - adap->fe_adap[0].fe->ops.sleep = af9015_af9013_sleep; - } - - return adap->fe_adap[0].fe == NULL ? -ENODEV : 0; -} - -static struct mt2060_config af9015_mt2060_config = { - .i2c_address = 0xc0, - .clock_out = 0, -}; - -static struct qt1010_config af9015_qt1010_config = { - .i2c_address = 0xc4, -}; - -static struct tda18271_config af9015_tda18271_config = { - .gate = TDA18271_GATE_DIGITAL, - .small_i2c = TDA18271_16_BYTE_CHUNK_INIT, -}; - -static struct mxl5005s_config af9015_mxl5003_config = { - .i2c_address = 0xc6, - .if_freq = IF_FREQ_4570000HZ, - .xtal_freq = CRYSTAL_FREQ_16000000HZ, - .agc_mode = MXL_SINGLE_AGC, - .tracking_filter = MXL_TF_DEFAULT, - .rssi_enable = MXL_RSSI_ENABLE, - .cap_select = MXL_CAP_SEL_ENABLE, - .div_out = MXL_DIV_OUT_4, - .clock_out = MXL_CLOCK_OUT_DISABLE, - .output_load = MXL5005S_IF_OUTPUT_LOAD_200_OHM, - .top = MXL5005S_TOP_25P2, - .mod_mode = MXL_DIGITAL_MODE, - .if_mode = MXL_ZERO_IF, - .AgcMasterByte = 0x00, -}; - -static struct mxl5005s_config af9015_mxl5005_config = { - .i2c_address = 0xc6, - .if_freq = IF_FREQ_4570000HZ, - .xtal_freq = CRYSTAL_FREQ_16000000HZ, - .agc_mode = MXL_SINGLE_AGC, - .tracking_filter = MXL_TF_OFF, - .rssi_enable = MXL_RSSI_ENABLE, - .cap_select = MXL_CAP_SEL_ENABLE, - .div_out = MXL_DIV_OUT_4, - .clock_out = MXL_CLOCK_OUT_DISABLE, - .output_load = MXL5005S_IF_OUTPUT_LOAD_200_OHM, - .top = MXL5005S_TOP_25P2, - .mod_mode = MXL_DIGITAL_MODE, - .if_mode = MXL_ZERO_IF, - .AgcMasterByte = 0x00, -}; - -static struct mc44s803_config af9015_mc44s803_config = { - .i2c_address = 0xc0, - .dig_out = 1, -}; - -static struct tda18218_config af9015_tda18218_config = { - .i2c_address = 0xc0, - .i2c_wr_max = 21, /* max wr bytes AF9015 I2C adap can handle at once */ -}; - -static struct mxl5007t_config af9015_mxl5007t_config = { - .xtal_freq_hz = MxL_XTAL_24_MHZ, - .if_freq_hz = MxL_IF_4_57_MHZ, -}; - -static int af9015_tuner_attach(struct dvb_usb_adapter *adap) -{ - int ret; - struct af9015_state *state = adap->dev->priv; - deb_info("%s:\n", __func__); - - switch (af9015_af9013_config[adap->id].tuner) { - case AF9013_TUNER_MT2060: - case AF9013_TUNER_MT2060_2: - ret = dvb_attach(mt2060_attach, adap->fe_adap[0].fe, - &adap->dev->i2c_adap, &af9015_mt2060_config, - af9015_config.mt2060_if1[adap->id]) - == NULL ? -ENODEV : 0; - break; - case AF9013_TUNER_QT1010: - case AF9013_TUNER_QT1010A: - ret = dvb_attach(qt1010_attach, adap->fe_adap[0].fe, - &adap->dev->i2c_adap, - &af9015_qt1010_config) == NULL ? -ENODEV : 0; - break; - case AF9013_TUNER_TDA18271: - ret = dvb_attach(tda18271_attach, adap->fe_adap[0].fe, 0xc0, - &adap->dev->i2c_adap, - &af9015_tda18271_config) == NULL ? -ENODEV : 0; - break; - case AF9013_TUNER_TDA18218: - ret = dvb_attach(tda18218_attach, adap->fe_adap[0].fe, - &adap->dev->i2c_adap, - &af9015_tda18218_config) == NULL ? -ENODEV : 0; - break; - case AF9013_TUNER_MXL5003D: - ret = dvb_attach(mxl5005s_attach, adap->fe_adap[0].fe, - &adap->dev->i2c_adap, - &af9015_mxl5003_config) == NULL ? -ENODEV : 0; - break; - case AF9013_TUNER_MXL5005D: - case AF9013_TUNER_MXL5005R: - ret = dvb_attach(mxl5005s_attach, adap->fe_adap[0].fe, - &adap->dev->i2c_adap, - &af9015_mxl5005_config) == NULL ? -ENODEV : 0; - break; - case AF9013_TUNER_ENV77H11D5: - ret = dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, 0xc0, - &adap->dev->i2c_adap, - DVB_PLL_TDA665X) == NULL ? -ENODEV : 0; - break; - case AF9013_TUNER_MC44S803: - ret = dvb_attach(mc44s803_attach, adap->fe_adap[0].fe, - &adap->dev->i2c_adap, - &af9015_mc44s803_config) == NULL ? -ENODEV : 0; - break; - case AF9013_TUNER_MXL5007T: - ret = dvb_attach(mxl5007t_attach, adap->fe_adap[0].fe, - &adap->dev->i2c_adap, - 0xc0, &af9015_mxl5007t_config) == NULL ? -ENODEV : 0; - break; - case AF9013_TUNER_UNKNOWN: - default: - ret = -ENODEV; - err("Unknown tuner id:%d", - af9015_af9013_config[adap->id].tuner); - } - - if (adap->fe_adap[0].fe->ops.tuner_ops.init) { - state->tuner_init[adap->id] = - adap->fe_adap[0].fe->ops.tuner_ops.init; - adap->fe_adap[0].fe->ops.tuner_ops.init = af9015_tuner_init; - } - - if (adap->fe_adap[0].fe->ops.tuner_ops.sleep) { - state->tuner_sleep[adap->id] = - adap->fe_adap[0].fe->ops.tuner_ops.sleep; - adap->fe_adap[0].fe->ops.tuner_ops.sleep = af9015_tuner_sleep; - } - - return ret; -} - -enum af9015_usb_table_entry { - AFATECH_9015, - AFATECH_9016, - WINFAST_DTV_GOLD, - PINNACLE_PCTV_71E, - KWORLD_PLUSTV_399U, - TINYTWIN, - AZUREWAVE_TU700, - TERRATEC_AF9015, - KWORLD_PLUSTV_PC160, - AVERTV_VOLAR_X, - XTENSIONS_380U, - MSI_DIGIVOX_DUO, - AVERTV_VOLAR_X_REV2, - TELESTAR_STARSTICK_2, - AVERMEDIA_A309_USB, - MSI_DIGIVOX_MINI_III, - KWORLD_E396, - KWORLD_E39B, - KWORLD_E395, - TREKSTOR_DVBT, - AVERTV_A850, - AVERTV_A805, - CONCEPTRONIC_CTVDIGRCU, - KWORLD_MC810, - GENIUS_TVGO_DVB_T03, - KWORLD_399U_2, - KWORLD_PC160_T, - SVEON_STV20, - TINYTWIN_2, - WINFAST_DTV2000DS, - KWORLD_UB383_T, - KWORLD_E39A, - AVERMEDIA_A815M, - CINERGY_T_STICK_RC, - CINERGY_T_DUAL_RC, - AVERTV_A850T, - TINYTWIN_3, - SVEON_STV22, -}; - -static struct usb_device_id af9015_usb_table[] = { - [AFATECH_9015] = { - USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9015_9015)}, - [AFATECH_9016] = { - USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9015_9016)}, - [WINFAST_DTV_GOLD] = { - USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV_DONGLE_GOLD)}, - [PINNACLE_PCTV_71E] = { - USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV71E)}, - [KWORLD_PLUSTV_399U] = { - USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_399U)}, - [TINYTWIN] = { - USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_TINYTWIN)}, - [AZUREWAVE_TU700] = { - USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_AZUREWAVE_AD_TU700)}, - [TERRATEC_AF9015] = { - USB_DEVICE(USB_VID_TERRATEC, - USB_PID_TERRATEC_CINERGY_T_USB_XE_REV2)}, - [KWORLD_PLUSTV_PC160] = { - USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_PC160_2T)}, - [AVERTV_VOLAR_X] = { - USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR_X)}, - [XTENSIONS_380U] = { - USB_DEVICE(USB_VID_XTENSIONS, USB_PID_XTENSIONS_XD_380)}, - [MSI_DIGIVOX_DUO] = { - USB_DEVICE(USB_VID_MSI_2, USB_PID_MSI_DIGIVOX_DUO)}, - [AVERTV_VOLAR_X_REV2] = { - USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR_X_2)}, - [TELESTAR_STARSTICK_2] = { - USB_DEVICE(USB_VID_TELESTAR, USB_PID_TELESTAR_STARSTICK_2)}, - [AVERMEDIA_A309_USB] = { - USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A309)}, - [MSI_DIGIVOX_MINI_III] = { - USB_DEVICE(USB_VID_MSI_2, USB_PID_MSI_DIGI_VOX_MINI_III)}, - [KWORLD_E396] = { - USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_395U)}, - [KWORLD_E39B] = { - USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_395U_2)}, - [KWORLD_E395] = { - USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_395U_3)}, - [TREKSTOR_DVBT] = { - USB_DEVICE(USB_VID_AFATECH, USB_PID_TREKSTOR_DVBT)}, - [AVERTV_A850] = { - USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A850)}, - [AVERTV_A805] = { - USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A805)}, - [CONCEPTRONIC_CTVDIGRCU] = { - USB_DEVICE(USB_VID_KWORLD_2, USB_PID_CONCEPTRONIC_CTVDIGRCU)}, - [KWORLD_MC810] = { - USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_MC810)}, - [GENIUS_TVGO_DVB_T03] = { - USB_DEVICE(USB_VID_KYE, USB_PID_GENIUS_TVGO_DVB_T03)}, - [KWORLD_399U_2] = { - USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_399U_2)}, - [KWORLD_PC160_T] = { - USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_PC160_T)}, - [SVEON_STV20] = { - USB_DEVICE(USB_VID_KWORLD_2, USB_PID_SVEON_STV20)}, - [TINYTWIN_2] = { - USB_DEVICE(USB_VID_KWORLD_2, USB_PID_TINYTWIN_2)}, - [WINFAST_DTV2000DS] = { - USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV2000DS)}, - [KWORLD_UB383_T] = { - USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_UB383_T)}, - [KWORLD_E39A] = { - USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_395U_4)}, - [AVERMEDIA_A815M] = { - USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A815M)}, - [CINERGY_T_STICK_RC] = { - USB_DEVICE(USB_VID_TERRATEC, - USB_PID_TERRATEC_CINERGY_T_STICK_RC)}, - [CINERGY_T_DUAL_RC] = { - USB_DEVICE(USB_VID_TERRATEC, - USB_PID_TERRATEC_CINERGY_T_STICK_DUAL_RC)}, - [AVERTV_A850T] = { - USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A850T)}, - [TINYTWIN_3] = { - USB_DEVICE(USB_VID_GTEK, USB_PID_TINYTWIN_3)}, - [SVEON_STV22] = { - USB_DEVICE(USB_VID_KWORLD_2, USB_PID_SVEON_STV22)}, - { } -}; -MODULE_DEVICE_TABLE(usb, af9015_usb_table); - -#define AF9015_RC_INTERVAL 500 -static struct dvb_usb_device_properties af9015_properties[] = { - { - .caps = DVB_USB_IS_AN_I2C_ADAPTER, - - .usb_ctrl = DEVICE_SPECIFIC, - .download_firmware = af9015_download_firmware, - .firmware = "dvb-usb-af9015.fw", - .no_reconnect = 1, - - .size_of_priv = sizeof(struct af9015_state), - - .num_adapters = 2, - .adapter = { - { - .num_frontends = 1, - .fe = { - { - .caps = DVB_USB_ADAP_HAS_PID_FILTER | - DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, - - .pid_filter_count = 32, - .pid_filter = af9015_pid_filter, - .pid_filter_ctrl = af9015_pid_filter_ctrl, - - .frontend_attach = af9015_af9013_frontend_attach, - .tuner_attach = af9015_tuner_attach, - .stream = { - .type = USB_BULK, - .count = 6, - .endpoint = 0x84, - }, - } - }, - }, - { - .num_frontends = 1, - .fe = { - { - .frontend_attach = af9015_af9013_frontend_attach, - .tuner_attach = af9015_tuner_attach, - .stream = { - .type = USB_BULK, - .count = 6, - .endpoint = 0x85, - .u = { - .bulk = { - .buffersize = TS_USB20_FRAME_SIZE, - } - } - }, - } - }, - } - }, - - .identify_state = af9015_identify_state, - - .rc.core = { - .protocol = RC_TYPE_NEC, - .module_name = "af9015", - .rc_query = af9015_rc_query, - .rc_interval = AF9015_RC_INTERVAL, - .allowed_protos = RC_TYPE_NEC, - }, - - .i2c_algo = &af9015_i2c_algo, - - .num_device_descs = 12, /* check max from dvb-usb.h */ - .devices = { - { - .name = "Afatech AF9015 DVB-T USB2.0 stick", - .cold_ids = { - &af9015_usb_table[AFATECH_9015], - &af9015_usb_table[AFATECH_9016], - }, - }, { - .name = "Leadtek WinFast DTV Dongle Gold", - .cold_ids = { - &af9015_usb_table[WINFAST_DTV_GOLD], - }, - }, { - .name = "Pinnacle PCTV 71e", - .cold_ids = { - &af9015_usb_table[PINNACLE_PCTV_71E], - }, - }, { - .name = "KWorld PlusTV Dual DVB-T Stick " \ - "(DVB-T 399U)", - .cold_ids = { - &af9015_usb_table[KWORLD_PLUSTV_399U], - &af9015_usb_table[KWORLD_399U_2], - }, - }, { - .name = "DigitalNow TinyTwin DVB-T Receiver", - .cold_ids = { - &af9015_usb_table[TINYTWIN], - &af9015_usb_table[TINYTWIN_2], - &af9015_usb_table[TINYTWIN_3], - }, - }, { - .name = "TwinHan AzureWave AD-TU700(704J)", - .cold_ids = { - &af9015_usb_table[AZUREWAVE_TU700], - }, - }, { - .name = "TerraTec Cinergy T USB XE", - .cold_ids = { - &af9015_usb_table[TERRATEC_AF9015], - }, - }, { - .name = "KWorld PlusTV Dual DVB-T PCI " \ - "(DVB-T PC160-2T)", - .cold_ids = { - &af9015_usb_table[KWORLD_PLUSTV_PC160], - }, - }, { - .name = "AVerMedia AVerTV DVB-T Volar X", - .cold_ids = { - &af9015_usb_table[AVERTV_VOLAR_X], - }, - }, { - .name = "TerraTec Cinergy T Stick RC", - .cold_ids = { - &af9015_usb_table[CINERGY_T_STICK_RC], - }, - }, { - .name = "TerraTec Cinergy T Stick Dual RC", - .cold_ids = { - &af9015_usb_table[CINERGY_T_DUAL_RC], - }, - }, { - .name = "AverMedia AVerTV Red HD+ (A850T)", - .cold_ids = { - &af9015_usb_table[AVERTV_A850T], - }, - }, - } - }, { - .caps = DVB_USB_IS_AN_I2C_ADAPTER, - - .usb_ctrl = DEVICE_SPECIFIC, - .download_firmware = af9015_download_firmware, - .firmware = "dvb-usb-af9015.fw", - .no_reconnect = 1, - - .size_of_priv = sizeof(struct af9015_state), - - .num_adapters = 2, - .adapter = { - { - .num_frontends = 1, - .fe = { - { - .caps = DVB_USB_ADAP_HAS_PID_FILTER | - DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, - - .pid_filter_count = 32, - .pid_filter = af9015_pid_filter, - .pid_filter_ctrl = af9015_pid_filter_ctrl, - - .frontend_attach = af9015_af9013_frontend_attach, - .tuner_attach = af9015_tuner_attach, - .stream = { - .type = USB_BULK, - .count = 6, - .endpoint = 0x84, - }, - } - }, - }, - { - .num_frontends = 1, - .fe = { - { - .frontend_attach = af9015_af9013_frontend_attach, - .tuner_attach = af9015_tuner_attach, - .stream = { - .type = USB_BULK, - .count = 6, - .endpoint = 0x85, - .u = { - .bulk = { - .buffersize = TS_USB20_FRAME_SIZE, - } - } - }, - } - }, - } - }, - - .identify_state = af9015_identify_state, - - .rc.core = { - .protocol = RC_TYPE_NEC, - .module_name = "af9015", - .rc_query = af9015_rc_query, - .rc_interval = AF9015_RC_INTERVAL, - .allowed_protos = RC_TYPE_NEC, - }, - - .i2c_algo = &af9015_i2c_algo, - - .num_device_descs = 10, /* check max from dvb-usb.h */ - .devices = { - { - .name = "Xtensions XD-380", - .cold_ids = { - &af9015_usb_table[XTENSIONS_380U], - }, - }, { - .name = "MSI DIGIVOX Duo", - .cold_ids = { - &af9015_usb_table[MSI_DIGIVOX_DUO], - }, - }, { - .name = "Fujitsu-Siemens Slim Mobile USB DVB-T", - .cold_ids = { - &af9015_usb_table[AVERTV_VOLAR_X_REV2], - }, - }, { - .name = "Telestar Starstick 2", - .cold_ids = { - &af9015_usb_table[TELESTAR_STARSTICK_2], - }, - }, { - .name = "AVerMedia A309", - .cold_ids = { - &af9015_usb_table[AVERMEDIA_A309_USB], - }, - }, { - .name = "MSI Digi VOX mini III", - .cold_ids = { - &af9015_usb_table[MSI_DIGIVOX_MINI_III], - }, - }, { - .name = "KWorld USB DVB-T TV Stick II " \ - "(VS-DVB-T 395U)", - .cold_ids = { - &af9015_usb_table[KWORLD_E396], - &af9015_usb_table[KWORLD_E39B], - &af9015_usb_table[KWORLD_E395], - &af9015_usb_table[KWORLD_E39A], - }, - }, { - .name = "TrekStor DVB-T USB Stick", - .cold_ids = { - &af9015_usb_table[TREKSTOR_DVBT], - }, - }, { - .name = "AverMedia AVerTV Volar Black HD " \ - "(A850)", - .cold_ids = { - &af9015_usb_table[AVERTV_A850], - }, - }, { - .name = "Sveon STV22 Dual USB DVB-T Tuner HDTV", - .cold_ids = { - &af9015_usb_table[SVEON_STV22], - }, - }, - } - }, { - .caps = DVB_USB_IS_AN_I2C_ADAPTER, - - .usb_ctrl = DEVICE_SPECIFIC, - .download_firmware = af9015_download_firmware, - .firmware = "dvb-usb-af9015.fw", - .no_reconnect = 1, - - .size_of_priv = sizeof(struct af9015_state), - - .num_adapters = 2, - .adapter = { - { - .num_frontends = 1, - .fe = { - { - .caps = DVB_USB_ADAP_HAS_PID_FILTER | - DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, - - .pid_filter_count = 32, - .pid_filter = af9015_pid_filter, - .pid_filter_ctrl = af9015_pid_filter_ctrl, - - .frontend_attach = af9015_af9013_frontend_attach, - .tuner_attach = af9015_tuner_attach, - .stream = { - .type = USB_BULK, - .count = 6, - .endpoint = 0x84, - }, - } - }, - }, - { - .num_frontends = 1, - .fe = { - { - .frontend_attach = af9015_af9013_frontend_attach, - .tuner_attach = af9015_tuner_attach, - .stream = { - .type = USB_BULK, - .count = 6, - .endpoint = 0x85, - .u = { - .bulk = { - .buffersize = TS_USB20_FRAME_SIZE, - } - } - }, - } - }, - } - }, - - .identify_state = af9015_identify_state, - - .rc.core = { - .protocol = RC_TYPE_NEC, - .module_name = "af9015", - .rc_query = af9015_rc_query, - .rc_interval = AF9015_RC_INTERVAL, - .allowed_protos = RC_TYPE_NEC, - }, - - .i2c_algo = &af9015_i2c_algo, - - .num_device_descs = 9, /* check max from dvb-usb.h */ - .devices = { - { - .name = "AverMedia AVerTV Volar GPS 805 (A805)", - .cold_ids = { - &af9015_usb_table[AVERTV_A805], - }, - }, { - .name = "Conceptronic USB2.0 DVB-T CTVDIGRCU " \ - "V3.0", - .cold_ids = { - &af9015_usb_table[CONCEPTRONIC_CTVDIGRCU], - }, - }, { - .name = "KWorld Digial MC-810", - .cold_ids = { - &af9015_usb_table[KWORLD_MC810], - }, - }, { - .name = "Genius TVGo DVB-T03", - .cold_ids = { - &af9015_usb_table[GENIUS_TVGO_DVB_T03], - }, - }, { - .name = "KWorld PlusTV DVB-T PCI Pro Card " \ - "(DVB-T PC160-T)", - .cold_ids = { - &af9015_usb_table[KWORLD_PC160_T], - }, - }, { - .name = "Sveon STV20 Tuner USB DVB-T HDTV", - .cold_ids = { - &af9015_usb_table[SVEON_STV20], - }, - }, { - .name = "Leadtek WinFast DTV2000DS", - .cold_ids = { - &af9015_usb_table[WINFAST_DTV2000DS], - }, - }, { - .name = "KWorld USB DVB-T Stick Mobile " \ - "(UB383-T)", - .cold_ids = { - &af9015_usb_table[KWORLD_UB383_T], - }, - }, { - .name = "AverMedia AVerTV Volar M (A815Mac)", - .cold_ids = { - &af9015_usb_table[AVERMEDIA_A815M], - }, - }, - } - }, -}; - -static int af9015_usb_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - int ret = 0; - struct dvb_usb_device *d = NULL; - struct usb_device *udev = interface_to_usbdev(intf); - u8 i; - - deb_info("%s: interface:%d\n", __func__, - intf->cur_altsetting->desc.bInterfaceNumber); - - /* interface 0 is used by DVB-T receiver and - interface 1 is for remote controller (HID) */ - if (intf->cur_altsetting->desc.bInterfaceNumber == 0) { - ret = af9015_read_config(udev); - if (ret) - return ret; - - for (i = 0; i < af9015_properties_count; i++) { - ret = dvb_usb_device_init(intf, &af9015_properties[i], - THIS_MODULE, &d, adapter_nr); - if (!ret) - break; - if (ret != -ENODEV) - return ret; - } - if (ret) - return ret; - - if (d) - ret = af9015_init(d); - } - - return ret; -} - -/* usb specific object needed to register this driver with the usb subsystem */ -static struct usb_driver af9015_usb_driver = { - .name = "dvb_usb_af9015", - .probe = af9015_usb_probe, - .disconnect = dvb_usb_device_exit, - .id_table = af9015_usb_table, -}; - -module_usb_driver(af9015_usb_driver); - -MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>"); -MODULE_DESCRIPTION("Afatech AF9015 driver"); -MODULE_LICENSE("GPL"); diff --git a/drivers/media/dvb/dvb-usb/it913x.c b/drivers/media/dvb/dvb-usb/it913x.c deleted file mode 100644 index 6244fe9d1a3a..000000000000 --- a/drivers/media/dvb/dvb-usb/it913x.c +++ /dev/null @@ -1,931 +0,0 @@ -/* DVB USB compliant linux driver for IT9137 - * - * Copyright (C) 2011 Malcolm Priestley (tvboxspy@gmail.com) - * IT9137 (C) ITE Tech Inc. - * - * 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. - * - * 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. - * - * - * see Documentation/dvb/README.dvb-usb for more information - * see Documentation/dvb/it9137.txt for firmware information - * - */ -#define DVB_USB_LOG_PREFIX "it913x" - -#include <linux/usb.h> -#include <linux/usb/input.h> -#include <media/rc-core.h> - -#include "dvb-usb.h" -#include "it913x-fe.h" - -/* debug */ -static int dvb_usb_it913x_debug; -#define l_dprintk(var, level, args...) do { \ - if ((var >= level)) \ - printk(KERN_DEBUG DVB_USB_LOG_PREFIX ": " args); \ -} while (0) - -#define deb_info(level, args...) l_dprintk(dvb_usb_it913x_debug, level, args) -#define debug_data_snipet(level, name, p) \ - deb_info(level, name" (%02x%02x%02x%02x%02x%02x%02x%02x)", \ - *p, *(p+1), *(p+2), *(p+3), *(p+4), \ - *(p+5), *(p+6), *(p+7)); - - -module_param_named(debug, dvb_usb_it913x_debug, int, 0644); -MODULE_PARM_DESC(debug, "set debugging level (1=info (or-able))." - DVB_USB_DEBUG_STATUS); - -static int pid_filter; -module_param_named(pid, pid_filter, int, 0644); -MODULE_PARM_DESC(pid, "set default 0=on 1=off"); - -static int dvb_usb_it913x_firmware; -module_param_named(firmware, dvb_usb_it913x_firmware, int, 0644); -MODULE_PARM_DESC(firmware, "set firmware 0=auto 1=IT9137 2=IT9135V1"); - - -int cmd_counter; - -DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); - -struct it913x_state { - u8 id; - struct ite_config it913x_config; - u8 pid_filter_onoff; -}; - -struct ite_config it913x_config; - -#define IT913X_RETRY 10 -#define IT913X_SND_TIMEOUT 100 -#define IT913X_RCV_TIMEOUT 200 - -static int it913x_bulk_write(struct usb_device *dev, - u8 *snd, int len, u8 pipe) -{ - int ret, actual_l, i; - - for (i = 0; i < IT913X_RETRY; i++) { - ret = usb_bulk_msg(dev, usb_sndbulkpipe(dev, pipe), - snd, len , &actual_l, IT913X_SND_TIMEOUT); - if (ret != -EBUSY && ret != -ETIMEDOUT) - break; - } - - if (len != actual_l && ret == 0) - ret = -EAGAIN; - - return ret; -} - -static int it913x_bulk_read(struct usb_device *dev, - u8 *rev, int len, u8 pipe) -{ - int ret, actual_l, i; - - for (i = 0; i < IT913X_RETRY; i++) { - ret = usb_bulk_msg(dev, usb_rcvbulkpipe(dev, pipe), - rev, len , &actual_l, IT913X_RCV_TIMEOUT); - if (ret != -EBUSY && ret != -ETIMEDOUT) - break; - } - - if (len != actual_l && ret == 0) - ret = -EAGAIN; - - return ret; -} - -static u16 check_sum(u8 *p, u8 len) -{ - u16 sum = 0; - u8 i = 1; - while (i < len) - sum += (i++ & 1) ? (*p++) << 8 : *p++; - return ~sum; -} - -static int it913x_usb_talk(struct usb_device *udev, u8 mode, u8 pro, - u8 cmd, u32 reg, u8 addr, u8 *data, u8 len) -{ - int ret = 0, i, buf_size = 1; - u8 *buff; - u8 rlen; - u16 chk_sum; - - buff = kzalloc(256, GFP_KERNEL); - if (!buff) { - info("USB Buffer Failed"); - return -ENOMEM; - } - - buff[buf_size++] = pro; - buff[buf_size++] = cmd; - buff[buf_size++] = cmd_counter; - - switch (mode) { - case READ_LONG: - case WRITE_LONG: - buff[buf_size++] = len; - buff[buf_size++] = 2; - buff[buf_size++] = (reg >> 24); - buff[buf_size++] = (reg >> 16) & 0xff; - buff[buf_size++] = (reg >> 8) & 0xff; - buff[buf_size++] = reg & 0xff; - break; - case READ_SHORT: - buff[buf_size++] = addr; - break; - case WRITE_SHORT: - buff[buf_size++] = len; - buff[buf_size++] = addr; - buff[buf_size++] = (reg >> 8) & 0xff; - buff[buf_size++] = reg & 0xff; - break; - case READ_DATA: - case WRITE_DATA: - break; - case WRITE_CMD: - mode = 7; - break; - default: - kfree(buff); - return -EINVAL; - } - - if (mode & 1) { - for (i = 0; i < len ; i++) - buff[buf_size++] = data[i]; - } - chk_sum = check_sum(&buff[1], buf_size); - - buff[buf_size++] = chk_sum >> 8; - buff[0] = buf_size; - buff[buf_size++] = (chk_sum & 0xff); - - ret = it913x_bulk_write(udev, buff, buf_size , 0x02); - if (ret < 0) - goto error; - - ret = it913x_bulk_read(udev, buff, (mode & 1) ? - 5 : len + 5 , 0x01); - if (ret < 0) - goto error; - - rlen = (mode & 0x1) ? 0x1 : len; - - if (mode & 1) - ret = buff[2]; - else - memcpy(data, &buff[3], rlen); - - cmd_counter++; - -error: kfree(buff); - - return ret; -} - -static int it913x_io(struct usb_device *udev, u8 mode, u8 pro, - u8 cmd, u32 reg, u8 addr, u8 *data, u8 len) -{ - int ret, i; - - for (i = 0; i < IT913X_RETRY; i++) { - ret = it913x_usb_talk(udev, mode, pro, - cmd, reg, addr, data, len); - if (ret != -EAGAIN) - break; - } - - return ret; -} - -static int it913x_wr_reg(struct usb_device *udev, u8 pro, u32 reg , u8 data) -{ - int ret; - u8 b[1]; - b[0] = data; - ret = it913x_io(udev, WRITE_LONG, pro, - CMD_DEMOD_WRITE, reg, 0, b, sizeof(b)); - - return ret; -} - -static int it913x_read_reg(struct usb_device *udev, u32 reg) -{ - int ret; - u8 data[1]; - - ret = it913x_io(udev, READ_LONG, DEV_0, - CMD_DEMOD_READ, reg, 0, &data[0], 1); - - return (ret < 0) ? ret : data[0]; -} - -static u32 it913x_query(struct usb_device *udev, u8 pro) -{ - int ret, i; - u8 data[4]; - u8 ver; - - for (i = 0; i < 5; i++) { - ret = it913x_io(udev, READ_LONG, pro, CMD_DEMOD_READ, - 0x1222, 0, &data[0], 3); - ver = data[0]; - if (ver > 0 && ver < 3) - break; - msleep(100); - } - - if (ver < 1 || ver > 2) { - info("Failed to identify chip version applying 1"); - it913x_config.chip_ver = 0x1; - it913x_config.chip_type = 0x9135; - return 0; - } - - it913x_config.chip_ver = ver; - it913x_config.chip_type = (u16)(data[2] << 8) + data[1]; - - info("Chip Version=%02x Chip Type=%04x", it913x_config.chip_ver, - it913x_config.chip_type); - - ret |= it913x_io(udev, READ_SHORT, pro, - CMD_QUERYINFO, 0, 0x1, &data[0], 4); - - it913x_config.firmware = (data[0] << 24) + (data[1] << 16) + - (data[2] << 8) + data[3]; - - return (ret < 0) ? 0 : it913x_config.firmware; -} - -static int it913x_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff) -{ - struct it913x_state *st = adap->dev->priv; - struct usb_device *udev = adap->dev->udev; - int ret; - u8 pro = (adap->id == 0) ? DEV_0_DMOD : DEV_1_DMOD; - - mutex_lock(&adap->dev->i2c_mutex); - - deb_info(1, "PID_C (%02x)", onoff); - - ret = it913x_wr_reg(udev, pro, PID_EN, st->pid_filter_onoff); - - mutex_unlock(&adap->dev->i2c_mutex); - return ret; -} - -static int it913x_pid_filter(struct dvb_usb_adapter *adap, - int index, u16 pid, int onoff) -{ - struct it913x_state *st = adap->dev->priv; - struct usb_device *udev = adap->dev->udev; - int ret; - u8 pro = (adap->id == 0) ? DEV_0_DMOD : DEV_1_DMOD; - - mutex_lock(&adap->dev->i2c_mutex); - - deb_info(1, "PID_F (%02x)", onoff); - - ret = it913x_wr_reg(udev, pro, PID_LSB, (u8)(pid & 0xff)); - - ret |= it913x_wr_reg(udev, pro, PID_MSB, (u8)(pid >> 8)); - - ret |= it913x_wr_reg(udev, pro, PID_INX_EN, (u8)onoff); - - ret |= it913x_wr_reg(udev, pro, PID_INX, (u8)(index & 0x1f)); - - if (udev->speed == USB_SPEED_HIGH && pid == 0x2000) { - ret |= it913x_wr_reg(udev, pro, PID_EN, !onoff); - st->pid_filter_onoff = !onoff; - } else - st->pid_filter_onoff = - adap->fe_adap[adap->active_fe].pid_filtering; - - mutex_unlock(&adap->dev->i2c_mutex); - return 0; -} - - -static int it913x_return_status(struct usb_device *udev) -{ - u32 firm = 0; - - firm = it913x_query(udev, DEV_0); - if (firm > 0) - info("Firmware Version %d", firm); - - return (firm > 0) ? firm : 0; -} - -static int it913x_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], - int num) -{ - struct dvb_usb_device *d = i2c_get_adapdata(adap); - static u8 data[256]; - int ret; - u32 reg; - u8 pro; - - mutex_lock(&d->i2c_mutex); - - debug_data_snipet(1, "Message out", msg[0].buf); - deb_info(2, "num of messages %d address %02x", num, msg[0].addr); - - pro = (msg[0].addr & 0x2) ? DEV_0_DMOD : 0x0; - pro |= (msg[0].addr & 0x20) ? DEV_1 : DEV_0; - memcpy(data, msg[0].buf, msg[0].len); - reg = (data[0] << 24) + (data[1] << 16) + - (data[2] << 8) + data[3]; - if (num == 2) { - ret = it913x_io(d->udev, READ_LONG, pro, - CMD_DEMOD_READ, reg, 0, data, msg[1].len); - memcpy(msg[1].buf, data, msg[1].len); - } else - ret = it913x_io(d->udev, WRITE_LONG, pro, CMD_DEMOD_WRITE, - reg, 0, &data[4], msg[0].len - 4); - - mutex_unlock(&d->i2c_mutex); - - return ret; -} - -static u32 it913x_i2c_func(struct i2c_adapter *adapter) -{ - return I2C_FUNC_I2C; -} - -static struct i2c_algorithm it913x_i2c_algo = { - .master_xfer = it913x_i2c_xfer, - .functionality = it913x_i2c_func, -}; - -/* Callbacks for DVB USB */ -#define IT913X_POLL 250 -static int it913x_rc_query(struct dvb_usb_device *d) -{ - u8 ibuf[4]; - int ret; - u32 key; - /* Avoid conflict with frontends*/ - mutex_lock(&d->i2c_mutex); - - ret = it913x_io(d->udev, READ_LONG, PRO_LINK, CMD_IR_GET, - 0, 0, &ibuf[0], sizeof(ibuf)); - - if ((ibuf[2] + ibuf[3]) == 0xff) { - key = ibuf[2]; - key += ibuf[0] << 16; - key += ibuf[1] << 8; - deb_info(1, "NEC Extended Key =%08x", key); - if (d->rc_dev != NULL) - rc_keydown(d->rc_dev, key, 0); - } - - mutex_unlock(&d->i2c_mutex); - - return ret; -} - -/* Firmware sets raw */ -const char fw_it9135_v1[] = "dvb-usb-it9135-01.fw"; -const char fw_it9135_v2[] = "dvb-usb-it9135-02.fw"; -const char fw_it9137[] = "dvb-usb-it9137-01.fw"; - -static int ite_firmware_select(struct usb_device *udev, - struct dvb_usb_device_properties *props) -{ - int sw; - /* auto switch */ - if (le16_to_cpu(udev->descriptor.idVendor) == USB_VID_KWORLD_2) - sw = IT9137_FW; - else if (it913x_config.chip_ver == 1) - sw = IT9135_V1_FW; - else - sw = IT9135_V2_FW; - - /* force switch */ - if (dvb_usb_it913x_firmware != IT9135_AUTO) - sw = dvb_usb_it913x_firmware; - - switch (sw) { - case IT9135_V1_FW: - it913x_config.firmware_ver = 1; - it913x_config.adc_x2 = 1; - it913x_config.read_slevel = false; - props->firmware = fw_it9135_v1; - break; - case IT9135_V2_FW: - it913x_config.firmware_ver = 1; - it913x_config.adc_x2 = 1; - it913x_config.read_slevel = false; - props->firmware = fw_it9135_v2; - switch (it913x_config.tuner_id_0) { - case IT9135_61: - case IT9135_62: - break; - default: - info("Unknown tuner ID applying default 0x60"); - case IT9135_60: - it913x_config.tuner_id_0 = IT9135_60; - } - break; - case IT9137_FW: - default: - it913x_config.firmware_ver = 0; - it913x_config.adc_x2 = 0; - it913x_config.read_slevel = true; - props->firmware = fw_it9137; - } - - return 0; -} - -static void it913x_select_remote(struct usb_device *udev, - struct dvb_usb_device_properties *props) -{ - switch (le16_to_cpu(udev->descriptor.idProduct)) { - case USB_PID_ITETECH_IT9135_9005: - props->rc.core.rc_codes = RC_MAP_IT913X_V2; - return; - default: - props->rc.core.rc_codes = RC_MAP_IT913X_V1; - } - return; -} - -#define TS_MPEG_PKT_SIZE 188 -#define EP_LOW 21 -#define TS_BUFFER_SIZE_PID (EP_LOW*TS_MPEG_PKT_SIZE) -#define EP_HIGH 348 -#define TS_BUFFER_SIZE_MAX (EP_HIGH*TS_MPEG_PKT_SIZE) - -static int it913x_select_config(struct usb_device *udev, - struct dvb_usb_device_properties *props) -{ - int ret = 0, reg; - bool proprietary_ir = false; - - if (it913x_config.chip_ver == 0x02 - && it913x_config.chip_type == 0x9135) - reg = it913x_read_reg(udev, 0x461d); - else - reg = it913x_read_reg(udev, 0x461b); - - if (reg < 0) - return reg; - - if (reg == 0) { - it913x_config.dual_mode = 0; - it913x_config.tuner_id_0 = IT9135_38; - proprietary_ir = true; - } else { - /* TS mode */ - reg = it913x_read_reg(udev, 0x49c5); - if (reg < 0) - return reg; - it913x_config.dual_mode = reg; - - /* IR mode type */ - reg = it913x_read_reg(udev, 0x49ac); - if (reg < 0) - return reg; - if (reg == 5) { - info("Remote propriety (raw) mode"); - proprietary_ir = true; - } else if (reg == 1) { - info("Remote HID mode NOT SUPPORTED"); - proprietary_ir = false; - props->rc.core.rc_codes = NULL; - } else - props->rc.core.rc_codes = NULL; - - /* Tuner_id */ - reg = it913x_read_reg(udev, 0x49d0); - if (reg < 0) - return reg; - it913x_config.tuner_id_0 = reg; - } - - if (proprietary_ir) - it913x_select_remote(udev, props); - - if (udev->speed != USB_SPEED_HIGH) { - props->adapter[0].fe[0].pid_filter_count = 5; - info("USB 1 low speed mode - connect to USB 2 port"); - if (pid_filter > 0) - pid_filter = 0; - if (it913x_config.dual_mode) { - it913x_config.dual_mode = 0; - info("Dual mode not supported in USB 1"); - } - } else /* For replugging */ - if(props->adapter[0].fe[0].pid_filter_count == 5) - props->adapter[0].fe[0].pid_filter_count = 31; - - /* Select Stream Buffer Size and pid filter option*/ - if (pid_filter) { - props->adapter[0].fe[0].stream.u.bulk.buffersize = - TS_BUFFER_SIZE_MAX; - props->adapter[0].fe[0].caps &= - ~DVB_USB_ADAP_NEED_PID_FILTERING; - } else - props->adapter[0].fe[0].stream.u.bulk.buffersize = - TS_BUFFER_SIZE_PID; - - if (it913x_config.dual_mode) { - props->adapter[1].fe[0].stream.u.bulk.buffersize = - props->adapter[0].fe[0].stream.u.bulk.buffersize; - props->num_adapters = 2; - if (pid_filter) - props->adapter[1].fe[0].caps = - props->adapter[0].fe[0].caps; - } else - props->num_adapters = 1; - - info("Dual mode=%x Tuner Type=%x", it913x_config.dual_mode, - it913x_config.tuner_id_0); - - ret = ite_firmware_select(udev, props); - - return ret; -} - -static int it913x_identify_state(struct usb_device *udev, - struct dvb_usb_device_properties *props, - struct dvb_usb_device_description **desc, - int *cold) -{ - int ret = 0, firm_no; - u8 reg; - - firm_no = it913x_return_status(udev); - - /* Read and select config */ - ret = it913x_select_config(udev, props); - if (ret < 0) - return ret; - - if (firm_no > 0) { - *cold = 0; - return 0; - } - - if (it913x_config.dual_mode) { - it913x_config.tuner_id_1 = it913x_read_reg(udev, 0x49e0); - ret = it913x_wr_reg(udev, DEV_0, GPIOH1_EN, 0x1); - ret |= it913x_wr_reg(udev, DEV_0, GPIOH1_ON, 0x1); - ret |= it913x_wr_reg(udev, DEV_0, GPIOH1_O, 0x1); - msleep(50); - ret |= it913x_wr_reg(udev, DEV_0, GPIOH1_O, 0x0); - msleep(50); - reg = it913x_read_reg(udev, GPIOH1_O); - if (reg == 0) { - ret |= it913x_wr_reg(udev, DEV_0, GPIOH1_O, 0x1); - ret |= it913x_return_status(udev); - if (ret != 0) - ret = it913x_wr_reg(udev, DEV_0, - GPIOH1_O, 0x0); - } - } - - reg = it913x_read_reg(udev, IO_MUX_POWER_CLK); - - if (it913x_config.dual_mode) { - ret |= it913x_wr_reg(udev, DEV_0, 0x4bfb, CHIP2_I2C_ADDR); - if (it913x_config.firmware_ver == 1) - ret |= it913x_wr_reg(udev, DEV_0, 0xcfff, 0x1); - else - ret |= it913x_wr_reg(udev, DEV_0, CLK_O_EN, 0x1); - } else { - ret |= it913x_wr_reg(udev, DEV_0, 0x4bfb, 0x0); - if (it913x_config.firmware_ver == 1) - ret |= it913x_wr_reg(udev, DEV_0, 0xcfff, 0x0); - else - ret |= it913x_wr_reg(udev, DEV_0, CLK_O_EN, 0x0); - } - - *cold = 1; - - return (ret < 0) ? -ENODEV : 0; -} - -static int it913x_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) -{ - struct it913x_state *st = adap->dev->priv; - int ret = 0; - u8 pro = (adap->id == 0) ? DEV_0_DMOD : DEV_1_DMOD; - - deb_info(1, "STM (%02x)", onoff); - - if (!onoff) { - mutex_lock(&adap->dev->i2c_mutex); - - ret = it913x_wr_reg(adap->dev->udev, pro, PID_RST, 0x1); - - mutex_unlock(&adap->dev->i2c_mutex); - st->pid_filter_onoff = - adap->fe_adap[adap->active_fe].pid_filtering; - - } - - return ret; -} - -static int it913x_download_firmware(struct usb_device *udev, - const struct firmware *fw) -{ - int ret = 0, i = 0, pos = 0; - u8 packet_size, min_pkt; - u8 *fw_data; - - ret = it913x_wr_reg(udev, DEV_0, I2C_CLK, I2C_CLK_100); - - info("FRM Starting Firmware Download"); - - /* Multi firmware loader */ - /* This uses scatter write firmware headers */ - /* The firmware must start with 03 XX 00 */ - /* and be the extact firmware length */ - - if (it913x_config.chip_ver == 2) - min_pkt = 0x11; - else - min_pkt = 0x19; - - while (i <= fw->size) { - if (((fw->data[i] == 0x3) && (fw->data[i + 2] == 0x0)) - || (i == fw->size)) { - packet_size = i - pos; - if ((packet_size > min_pkt) || (i == fw->size)) { - fw_data = (u8 *)(fw->data + pos); - pos += packet_size; - if (packet_size > 0) { - ret = it913x_io(udev, WRITE_DATA, - DEV_0, CMD_SCATTER_WRITE, 0, - 0, fw_data, packet_size); - if (ret < 0) - break; - } - udelay(1000); - } - } - i++; - } - - if (ret < 0) - info("FRM Firmware Download Failed (%d)" , ret); - else - info("FRM Firmware Download Completed - Resetting Device"); - - msleep(30); - - ret = it913x_io(udev, WRITE_CMD, DEV_0, CMD_BOOT, 0, 0, NULL, 0); - if (ret < 0) - info("FRM Device not responding to reboot"); - - ret = it913x_return_status(udev); - if (ret == 0) { - info("FRM Failed to reboot device"); - return -ENODEV; - } - - msleep(30); - - ret = it913x_wr_reg(udev, DEV_0, I2C_CLK, I2C_CLK_400); - - msleep(30); - - /* Tuner function */ - if (it913x_config.dual_mode) - ret |= it913x_wr_reg(udev, DEV_0_DMOD , 0xec4c, 0xa0); - else - ret |= it913x_wr_reg(udev, DEV_0_DMOD , 0xec4c, 0x68); - - if ((it913x_config.chip_ver == 1) && - (it913x_config.chip_type == 0x9135)) { - ret |= it913x_wr_reg(udev, DEV_0, PADODPU, 0x0); - ret |= it913x_wr_reg(udev, DEV_0, AGC_O_D, 0x0); - if (it913x_config.dual_mode) { - ret |= it913x_wr_reg(udev, DEV_1, PADODPU, 0x0); - ret |= it913x_wr_reg(udev, DEV_1, AGC_O_D, 0x0); - } - } - - return (ret < 0) ? -ENODEV : 0; -} - -static int it913x_name(struct dvb_usb_adapter *adap) -{ - const char *desc = adap->dev->desc->name; - char *fe_name[] = {"_1", "_2", "_3", "_4"}; - char *name = adap->fe_adap[0].fe->ops.info.name; - - strlcpy(name, desc, 128); - strlcat(name, fe_name[adap->id], 128); - - return 0; -} - -static int it913x_frontend_attach(struct dvb_usb_adapter *adap) -{ - struct usb_device *udev = adap->dev->udev; - struct it913x_state *st = adap->dev->priv; - int ret = 0; - u8 adap_addr = I2C_BASE_ADDR + (adap->id << 5); - u16 ep_size = adap->props.fe[0].stream.u.bulk.buffersize / 4; - u8 pkt_size = 0x80; - - if (adap->dev->udev->speed != USB_SPEED_HIGH) - pkt_size = 0x10; - - it913x_config.adf = it913x_read_reg(udev, IO_MUX_POWER_CLK); - - if (adap->id == 0) - memcpy(&st->it913x_config, &it913x_config, - sizeof(struct ite_config)); - - adap->fe_adap[0].fe = dvb_attach(it913x_fe_attach, - &adap->dev->i2c_adap, adap_addr, &st->it913x_config); - - if (adap->id == 0 && adap->fe_adap[0].fe) { - ret = it913x_wr_reg(udev, DEV_0_DMOD, MP2_SW_RST, 0x1); - ret = it913x_wr_reg(udev, DEV_0_DMOD, MP2IF2_SW_RST, 0x1); - ret = it913x_wr_reg(udev, DEV_0, EP0_TX_EN, 0x0f); - ret = it913x_wr_reg(udev, DEV_0, EP0_TX_NAK, 0x1b); - ret = it913x_wr_reg(udev, DEV_0, EP0_TX_EN, 0x2f); - ret = it913x_wr_reg(udev, DEV_0, EP4_TX_LEN_LSB, - ep_size & 0xff); - ret = it913x_wr_reg(udev, DEV_0, EP4_TX_LEN_MSB, ep_size >> 8); - ret = it913x_wr_reg(udev, DEV_0, EP4_MAX_PKT, pkt_size); - } else if (adap->id == 1 && adap->fe_adap[0].fe) { - ret = it913x_wr_reg(udev, DEV_0, EP0_TX_EN, 0x6f); - ret = it913x_wr_reg(udev, DEV_0, EP5_TX_LEN_LSB, - ep_size & 0xff); - ret = it913x_wr_reg(udev, DEV_0, EP5_TX_LEN_MSB, ep_size >> 8); - ret = it913x_wr_reg(udev, DEV_0, EP5_MAX_PKT, pkt_size); - ret = it913x_wr_reg(udev, DEV_0_DMOD, MP2IF2_EN, 0x1); - ret = it913x_wr_reg(udev, DEV_1_DMOD, MP2IF_SERIAL, 0x1); - ret = it913x_wr_reg(udev, DEV_1, TOP_HOSTB_SER_MODE, 0x1); - ret = it913x_wr_reg(udev, DEV_0_DMOD, TSIS_ENABLE, 0x1); - ret = it913x_wr_reg(udev, DEV_0_DMOD, MP2_SW_RST, 0x0); - ret = it913x_wr_reg(udev, DEV_0_DMOD, MP2IF2_SW_RST, 0x0); - ret = it913x_wr_reg(udev, DEV_0_DMOD, MP2IF2_HALF_PSB, 0x0); - ret = it913x_wr_reg(udev, DEV_0_DMOD, MP2IF_STOP_EN, 0x1); - ret = it913x_wr_reg(udev, DEV_1_DMOD, MPEG_FULL_SPEED, 0x0); - ret = it913x_wr_reg(udev, DEV_1_DMOD, MP2IF_STOP_EN, 0x0); - } else - return -ENODEV; - - ret = it913x_name(adap); - - return ret; -} - -/* DVB USB Driver */ -static struct dvb_usb_device_properties it913x_properties; - -static int it913x_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - cmd_counter = 0; - if (0 == dvb_usb_device_init(intf, &it913x_properties, - THIS_MODULE, NULL, adapter_nr)) { - info("DEV registering device driver"); - return 0; - } - - info("DEV it913x Error"); - return -ENODEV; - -} - -static struct usb_device_id it913x_table[] = { - { USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_UB499_2T_T09) }, - { USB_DEVICE(USB_VID_ITETECH, USB_PID_ITETECH_IT9135) }, - { USB_DEVICE(USB_VID_KWORLD_2, USB_PID_SVEON_STV22_IT9137) }, - { USB_DEVICE(USB_VID_ITETECH, USB_PID_ITETECH_IT9135_9005) }, - { USB_DEVICE(USB_VID_ITETECH, USB_PID_ITETECH_IT9135_9006) }, - {} /* Terminating entry */ -}; - -MODULE_DEVICE_TABLE(usb, it913x_table); - -static struct dvb_usb_device_properties it913x_properties = { - .caps = DVB_USB_IS_AN_I2C_ADAPTER, - .usb_ctrl = DEVICE_SPECIFIC, - .download_firmware = it913x_download_firmware, - .firmware = "dvb-usb-it9137-01.fw", - .no_reconnect = 1, - .size_of_priv = sizeof(struct it913x_state), - .num_adapters = 2, - .adapter = { - { - .num_frontends = 1, - .fe = {{ - .caps = DVB_USB_ADAP_HAS_PID_FILTER| - DVB_USB_ADAP_NEED_PID_FILTERING| - DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, - .streaming_ctrl = it913x_streaming_ctrl, - .pid_filter_count = 31, - .pid_filter = it913x_pid_filter, - .pid_filter_ctrl = it913x_pid_filter_ctrl, - .frontend_attach = it913x_frontend_attach, - /* parameter for the MPEG2-data transfer */ - .stream = { - .type = USB_BULK, - .count = 10, - .endpoint = 0x04, - .u = {/* Keep Low if PID filter on */ - .bulk = { - .buffersize = - TS_BUFFER_SIZE_PID, - } - } - } - }}, - }, - { - .num_frontends = 1, - .fe = {{ - .caps = DVB_USB_ADAP_HAS_PID_FILTER| - DVB_USB_ADAP_NEED_PID_FILTERING| - DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, - .streaming_ctrl = it913x_streaming_ctrl, - .pid_filter_count = 31, - .pid_filter = it913x_pid_filter, - .pid_filter_ctrl = it913x_pid_filter_ctrl, - .frontend_attach = it913x_frontend_attach, - /* parameter for the MPEG2-data transfer */ - .stream = { - .type = USB_BULK, - .count = 5, - .endpoint = 0x05, - .u = { - .bulk = { - .buffersize = - TS_BUFFER_SIZE_PID, - } - } - } - }}, - } - }, - .identify_state = it913x_identify_state, - .rc.core = { - .protocol = RC_TYPE_NEC, - .module_name = "it913x", - .rc_query = it913x_rc_query, - .rc_interval = IT913X_POLL, - .allowed_protos = RC_TYPE_NEC, - .rc_codes = RC_MAP_IT913X_V1, - }, - .i2c_algo = &it913x_i2c_algo, - .num_device_descs = 5, - .devices = { - { "Kworld UB499-2T T09(IT9137)", - { &it913x_table[0], NULL }, - }, - { "ITE 9135 Generic", - { &it913x_table[1], NULL }, - }, - { "Sveon STV22 Dual DVB-T HDTV(IT9137)", - { &it913x_table[2], NULL }, - }, - { "ITE 9135(9005) Generic", - { &it913x_table[3], NULL }, - }, - { "ITE 9135(9006) Generic", - { &it913x_table[4], NULL }, - }, - } -}; - -static struct usb_driver it913x_driver = { - .name = "it913x", - .probe = it913x_probe, - .disconnect = dvb_usb_device_exit, - .id_table = it913x_table, -}; - -module_usb_driver(it913x_driver); - -MODULE_AUTHOR("Malcolm Priestley <tvboxspy@gmail.com>"); -MODULE_DESCRIPTION("it913x USB 2 Driver"); -MODULE_VERSION("1.28"); -MODULE_LICENSE("GPL"); diff --git a/drivers/media/dvb/dvb-usb/mxl111sf.c b/drivers/media/dvb/dvb-usb/mxl111sf.c deleted file mode 100644 index cd842798f5af..000000000000 --- a/drivers/media/dvb/dvb-usb/mxl111sf.c +++ /dev/null @@ -1,1835 +0,0 @@ -/* - * Copyright (C) 2010 Michael Krufky (mkrufky@kernellabs.com) - * - * 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, version 2. - * - * see Documentation/dvb/README.dvb-usb for more information - */ - -#include <linux/vmalloc.h> -#include <linux/i2c.h> - -#include "mxl111sf.h" -#include "mxl111sf-reg.h" -#include "mxl111sf-phy.h" -#include "mxl111sf-i2c.h" -#include "mxl111sf-gpio.h" - -#include "mxl111sf-demod.h" -#include "mxl111sf-tuner.h" - -#include "lgdt3305.h" -#include "lg2160.h" - -int dvb_usb_mxl111sf_debug; -module_param_named(debug, dvb_usb_mxl111sf_debug, int, 0644); -MODULE_PARM_DESC(debug, "set debugging level " - "(1=info, 2=xfer, 4=i2c, 8=reg, 16=adv (or-able))."); - -int dvb_usb_mxl111sf_isoc; -module_param_named(isoc, dvb_usb_mxl111sf_isoc, int, 0644); -MODULE_PARM_DESC(isoc, "enable usb isoc xfer (0=bulk, 1=isoc)."); - -int dvb_usb_mxl111sf_spi; -module_param_named(spi, dvb_usb_mxl111sf_spi, int, 0644); -MODULE_PARM_DESC(spi, "use spi rather than tp for data xfer (0=tp, 1=spi)."); - -#define ANT_PATH_AUTO 0 -#define ANT_PATH_EXTERNAL 1 -#define ANT_PATH_INTERNAL 2 - -int dvb_usb_mxl111sf_rfswitch = -#if 0 - ANT_PATH_AUTO; -#else - ANT_PATH_EXTERNAL; -#endif - -module_param_named(rfswitch, dvb_usb_mxl111sf_rfswitch, int, 0644); -MODULE_PARM_DESC(rfswitch, "force rf switch position (0=auto, 1=ext, 2=int)."); - -DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); - -#define deb_info(args...) dprintk(dvb_usb_mxl111sf_debug, 0x13, args) -#define deb_reg(args...) dprintk(dvb_usb_mxl111sf_debug, 0x08, args) -#define deb_adv(args...) dprintk(dvb_usb_mxl111sf_debug, MXL_ADV_DBG, args) - -int mxl111sf_ctrl_msg(struct dvb_usb_device *d, - u8 cmd, u8 *wbuf, int wlen, u8 *rbuf, int rlen) -{ - int wo = (rbuf == NULL || rlen == 0); /* write-only */ - int ret; - u8 sndbuf[1+wlen]; - - deb_adv("%s(wlen = %d, rlen = %d)\n", __func__, wlen, rlen); - - memset(sndbuf, 0, 1+wlen); - - sndbuf[0] = cmd; - memcpy(&sndbuf[1], wbuf, wlen); - - ret = (wo) ? dvb_usb_generic_write(d, sndbuf, 1+wlen) : - dvb_usb_generic_rw(d, sndbuf, 1+wlen, rbuf, rlen, 0); - mxl_fail(ret); - - return ret; -} - -/* ------------------------------------------------------------------------ */ - -#define MXL_CMD_REG_READ 0xaa -#define MXL_CMD_REG_WRITE 0x55 - -int mxl111sf_read_reg(struct mxl111sf_state *state, u8 addr, u8 *data) -{ - u8 buf[2]; - int ret; - - ret = mxl111sf_ctrl_msg(state->d, MXL_CMD_REG_READ, &addr, 1, buf, 2); - if (mxl_fail(ret)) { - mxl_debug("error reading reg: 0x%02x", addr); - goto fail; - } - - if (buf[0] == addr) - *data = buf[1]; - else { - err("invalid response reading reg: 0x%02x != 0x%02x, 0x%02x", - addr, buf[0], buf[1]); - ret = -EINVAL; - } - - deb_reg("R: (0x%02x, 0x%02x)\n", addr, *data); -fail: - return ret; -} - -int mxl111sf_write_reg(struct mxl111sf_state *state, u8 addr, u8 data) -{ - u8 buf[] = { addr, data }; - int ret; - - deb_reg("W: (0x%02x, 0x%02x)\n", addr, data); - - ret = mxl111sf_ctrl_msg(state->d, MXL_CMD_REG_WRITE, buf, 2, NULL, 0); - if (mxl_fail(ret)) - err("error writing reg: 0x%02x, val: 0x%02x", addr, data); - return ret; -} - -/* ------------------------------------------------------------------------ */ - -int mxl111sf_write_reg_mask(struct mxl111sf_state *state, - u8 addr, u8 mask, u8 data) -{ - int ret; - u8 val; - - if (mask != 0xff) { - ret = mxl111sf_read_reg(state, addr, &val); -#if 1 - /* dont know why this usually errors out on the first try */ - if (mxl_fail(ret)) - err("error writing addr: 0x%02x, mask: 0x%02x, " - "data: 0x%02x, retrying...", addr, mask, data); - - ret = mxl111sf_read_reg(state, addr, &val); -#endif - if (mxl_fail(ret)) - goto fail; - } - val &= ~mask; - val |= data; - - ret = mxl111sf_write_reg(state, addr, val); - mxl_fail(ret); -fail: - return ret; -} - -/* ------------------------------------------------------------------------ */ - -int mxl111sf_ctrl_program_regs(struct mxl111sf_state *state, - struct mxl111sf_reg_ctrl_info *ctrl_reg_info) -{ - int i, ret = 0; - - for (i = 0; ctrl_reg_info[i].addr | - ctrl_reg_info[i].mask | - ctrl_reg_info[i].data; i++) { - - ret = mxl111sf_write_reg_mask(state, - ctrl_reg_info[i].addr, - ctrl_reg_info[i].mask, - ctrl_reg_info[i].data); - if (mxl_fail(ret)) { - err("failed on reg #%d (0x%02x)", i, - ctrl_reg_info[i].addr); - break; - } - } - return ret; -} - -/* ------------------------------------------------------------------------ */ - -static int mxl1x1sf_get_chip_info(struct mxl111sf_state *state) -{ - int ret; - u8 id, ver; - char *mxl_chip, *mxl_rev; - - if ((state->chip_id) && (state->chip_ver)) - return 0; - - ret = mxl111sf_read_reg(state, CHIP_ID_REG, &id); - if (mxl_fail(ret)) - goto fail; - state->chip_id = id; - - ret = mxl111sf_read_reg(state, TOP_CHIP_REV_ID_REG, &ver); - if (mxl_fail(ret)) - goto fail; - state->chip_ver = ver; - - switch (id) { - case 0x61: - mxl_chip = "MxL101SF"; - break; - case 0x63: - mxl_chip = "MxL111SF"; - break; - default: - mxl_chip = "UNKNOWN MxL1X1"; - break; - } - switch (ver) { - case 0x36: - state->chip_rev = MXL111SF_V6; - mxl_rev = "v6"; - break; - case 0x08: - state->chip_rev = MXL111SF_V8_100; - mxl_rev = "v8_100"; - break; - case 0x18: - state->chip_rev = MXL111SF_V8_200; - mxl_rev = "v8_200"; - break; - default: - state->chip_rev = 0; - mxl_rev = "UNKNOWN REVISION"; - break; - } - info("%s detected, %s (0x%x)", mxl_chip, mxl_rev, ver); -fail: - return ret; -} - -#define get_chip_info(state) \ -({ \ - int ___ret; \ - ___ret = mxl1x1sf_get_chip_info(state); \ - if (mxl_fail(___ret)) { \ - mxl_debug("failed to get chip info" \ - " on first probe attempt"); \ - ___ret = mxl1x1sf_get_chip_info(state); \ - if (mxl_fail(___ret)) \ - err("failed to get chip info during probe"); \ - else \ - mxl_debug("probe needed a retry " \ - "in order to succeed."); \ - } \ - ___ret; \ -}) - -/* ------------------------------------------------------------------------ */ - -static int mxl111sf_power_ctrl(struct dvb_usb_device *d, int onoff) -{ - /* power control depends on which adapter is being woken: - * save this for init, instead, via mxl111sf_adap_fe_init */ - return 0; -} - -static int mxl111sf_adap_fe_init(struct dvb_frontend *fe) -{ - struct dvb_usb_adapter *adap = fe->dvb->priv; - struct dvb_usb_device *d = adap->dev; - struct mxl111sf_state *state = d->priv; - struct mxl111sf_adap_state *adap_state = adap->fe_adap[fe->id].priv; - - int err; - - /* exit if we didnt initialize the driver yet */ - if (!state->chip_id) { - mxl_debug("driver not yet initialized, exit."); - goto fail; - } - - deb_info("%s()\n", __func__); - - mutex_lock(&state->fe_lock); - - state->alt_mode = adap_state->alt_mode; - - if (usb_set_interface(adap->dev->udev, 0, state->alt_mode) < 0) - err("set interface failed"); - - err = mxl1x1sf_soft_reset(state); - mxl_fail(err); - err = mxl111sf_init_tuner_demod(state); - mxl_fail(err); - err = mxl1x1sf_set_device_mode(state, adap_state->device_mode); - - mxl_fail(err); - mxl111sf_enable_usb_output(state); - mxl_fail(err); - mxl1x1sf_top_master_ctrl(state, 1); - mxl_fail(err); - - if ((MXL111SF_GPIO_MOD_DVBT != adap_state->gpio_mode) && - (state->chip_rev > MXL111SF_V6)) { - mxl111sf_config_pin_mux_modes(state, - PIN_MUX_TS_SPI_IN_MODE_1); - mxl_fail(err); - } - err = mxl111sf_init_port_expander(state); - if (!mxl_fail(err)) { - state->gpio_mode = adap_state->gpio_mode; - err = mxl111sf_gpio_mode_switch(state, state->gpio_mode); - mxl_fail(err); -#if 0 - err = fe->ops.init(fe); -#endif - msleep(100); /* add short delay after enabling - * the demod before touching it */ - } - - return (adap_state->fe_init) ? adap_state->fe_init(fe) : 0; -fail: - return -ENODEV; -} - -static int mxl111sf_adap_fe_sleep(struct dvb_frontend *fe) -{ - struct dvb_usb_adapter *adap = fe->dvb->priv; - struct dvb_usb_device *d = adap->dev; - struct mxl111sf_state *state = d->priv; - struct mxl111sf_adap_state *adap_state = adap->fe_adap[fe->id].priv; - int err; - - /* exit if we didnt initialize the driver yet */ - if (!state->chip_id) { - mxl_debug("driver not yet initialized, exit."); - goto fail; - } - - deb_info("%s()\n", __func__); - - err = (adap_state->fe_sleep) ? adap_state->fe_sleep(fe) : 0; - - mutex_unlock(&state->fe_lock); - - return err; -fail: - return -ENODEV; -} - - -static int mxl111sf_ep6_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) -{ - struct dvb_usb_device *d = adap->dev; - struct mxl111sf_state *state = d->priv; - struct mxl111sf_adap_state *adap_state = adap->fe_adap[adap->active_fe].priv; - int ret = 0; - - deb_info("%s(%d)\n", __func__, onoff); - - if (onoff) { - ret = mxl111sf_enable_usb_output(state); - mxl_fail(ret); - ret = mxl111sf_config_mpeg_in(state, 1, 1, - adap_state->ep6_clockphase, - 0, 0); - mxl_fail(ret); -#if 0 - } else { - ret = mxl111sf_disable_656_port(state); - mxl_fail(ret); -#endif - } - - return ret; -} - -static int mxl111sf_ep5_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) -{ - struct dvb_usb_device *d = adap->dev; - struct mxl111sf_state *state = d->priv; - int ret = 0; - - deb_info("%s(%d)\n", __func__, onoff); - - if (onoff) { - ret = mxl111sf_enable_usb_output(state); - mxl_fail(ret); - - ret = mxl111sf_init_i2s_port(state, 200); - mxl_fail(ret); - ret = mxl111sf_config_i2s(state, 0, 15); - mxl_fail(ret); - } else { - ret = mxl111sf_disable_i2s_port(state); - mxl_fail(ret); - } - if (state->chip_rev > MXL111SF_V6) - ret = mxl111sf_config_spi(state, onoff); - mxl_fail(ret); - - return ret; -} - -static int mxl111sf_ep4_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) -{ - struct dvb_usb_device *d = adap->dev; - struct mxl111sf_state *state = d->priv; - int ret = 0; - - deb_info("%s(%d)\n", __func__, onoff); - - if (onoff) { - ret = mxl111sf_enable_usb_output(state); - mxl_fail(ret); - } - - return ret; -} - -/* ------------------------------------------------------------------------ */ - -static struct lgdt3305_config hauppauge_lgdt3305_config = { - .i2c_addr = 0xb2 >> 1, - .mpeg_mode = LGDT3305_MPEG_SERIAL, - .tpclk_edge = LGDT3305_TPCLK_RISING_EDGE, - .tpvalid_polarity = LGDT3305_TP_VALID_HIGH, - .deny_i2c_rptr = 1, - .spectral_inversion = 0, - .qam_if_khz = 6000, - .vsb_if_khz = 6000, -}; - -static int mxl111sf_lgdt3305_frontend_attach(struct dvb_usb_adapter *adap) -{ - struct dvb_usb_device *d = adap->dev; - struct mxl111sf_state *state = d->priv; - int fe_id = adap->num_frontends_initialized; - struct mxl111sf_adap_state *adap_state = adap->fe_adap[fe_id].priv; - int ret; - - deb_adv("%s()\n", __func__); - - /* save a pointer to the dvb_usb_device in device state */ - state->d = d; - adap_state->alt_mode = (dvb_usb_mxl111sf_isoc) ? 2 : 1; - state->alt_mode = adap_state->alt_mode; - - if (usb_set_interface(adap->dev->udev, 0, state->alt_mode) < 0) - err("set interface failed"); - - state->gpio_mode = MXL111SF_GPIO_MOD_ATSC; - adap_state->gpio_mode = state->gpio_mode; - adap_state->device_mode = MXL_TUNER_MODE; - adap_state->ep6_clockphase = 1; - - ret = mxl1x1sf_soft_reset(state); - if (mxl_fail(ret)) - goto fail; - ret = mxl111sf_init_tuner_demod(state); - if (mxl_fail(ret)) - goto fail; - - ret = mxl1x1sf_set_device_mode(state, adap_state->device_mode); - if (mxl_fail(ret)) - goto fail; - - ret = mxl111sf_enable_usb_output(state); - if (mxl_fail(ret)) - goto fail; - ret = mxl1x1sf_top_master_ctrl(state, 1); - if (mxl_fail(ret)) - goto fail; - - ret = mxl111sf_init_port_expander(state); - if (mxl_fail(ret)) - goto fail; - ret = mxl111sf_gpio_mode_switch(state, state->gpio_mode); - if (mxl_fail(ret)) - goto fail; - - adap->fe_adap[fe_id].fe = dvb_attach(lgdt3305_attach, - &hauppauge_lgdt3305_config, - &adap->dev->i2c_adap); - if (adap->fe_adap[fe_id].fe) { - adap_state->fe_init = adap->fe_adap[fe_id].fe->ops.init; - adap->fe_adap[fe_id].fe->ops.init = mxl111sf_adap_fe_init; - adap_state->fe_sleep = adap->fe_adap[fe_id].fe->ops.sleep; - adap->fe_adap[fe_id].fe->ops.sleep = mxl111sf_adap_fe_sleep; - return 0; - } - ret = -EIO; -fail: - return ret; -} - -static struct lg2160_config hauppauge_lg2160_config = { - .lg_chip = LG2160, - .i2c_addr = 0x1c >> 1, - .deny_i2c_rptr = 1, - .spectral_inversion = 0, - .if_khz = 6000, -}; - -static int mxl111sf_lg2160_frontend_attach(struct dvb_usb_adapter *adap) -{ - struct dvb_usb_device *d = adap->dev; - struct mxl111sf_state *state = d->priv; - int fe_id = adap->num_frontends_initialized; - struct mxl111sf_adap_state *adap_state = adap->fe_adap[fe_id].priv; - int ret; - - deb_adv("%s()\n", __func__); - - /* save a pointer to the dvb_usb_device in device state */ - state->d = d; - adap_state->alt_mode = (dvb_usb_mxl111sf_isoc) ? 2 : 1; - state->alt_mode = adap_state->alt_mode; - - if (usb_set_interface(adap->dev->udev, 0, state->alt_mode) < 0) - err("set interface failed"); - - state->gpio_mode = MXL111SF_GPIO_MOD_MH; - adap_state->gpio_mode = state->gpio_mode; - adap_state->device_mode = MXL_TUNER_MODE; - adap_state->ep6_clockphase = 1; - - ret = mxl1x1sf_soft_reset(state); - if (mxl_fail(ret)) - goto fail; - ret = mxl111sf_init_tuner_demod(state); - if (mxl_fail(ret)) - goto fail; - - ret = mxl1x1sf_set_device_mode(state, adap_state->device_mode); - if (mxl_fail(ret)) - goto fail; - - ret = mxl111sf_enable_usb_output(state); - if (mxl_fail(ret)) - goto fail; - ret = mxl1x1sf_top_master_ctrl(state, 1); - if (mxl_fail(ret)) - goto fail; - - ret = mxl111sf_init_port_expander(state); - if (mxl_fail(ret)) - goto fail; - ret = mxl111sf_gpio_mode_switch(state, state->gpio_mode); - if (mxl_fail(ret)) - goto fail; - - ret = get_chip_info(state); - if (mxl_fail(ret)) - goto fail; - - adap->fe_adap[fe_id].fe = dvb_attach(lg2160_attach, - &hauppauge_lg2160_config, - &adap->dev->i2c_adap); - if (adap->fe_adap[fe_id].fe) { - adap_state->fe_init = adap->fe_adap[fe_id].fe->ops.init; - adap->fe_adap[fe_id].fe->ops.init = mxl111sf_adap_fe_init; - adap_state->fe_sleep = adap->fe_adap[fe_id].fe->ops.sleep; - adap->fe_adap[fe_id].fe->ops.sleep = mxl111sf_adap_fe_sleep; - return 0; - } - ret = -EIO; -fail: - return ret; -} - -static struct lg2160_config hauppauge_lg2161_1019_config = { - .lg_chip = LG2161_1019, - .i2c_addr = 0x1c >> 1, - .deny_i2c_rptr = 1, - .spectral_inversion = 0, - .if_khz = 6000, - .output_if = 2, /* LG2161_OIF_SPI_MAS */ -}; - -static struct lg2160_config hauppauge_lg2161_1040_config = { - .lg_chip = LG2161_1040, - .i2c_addr = 0x1c >> 1, - .deny_i2c_rptr = 1, - .spectral_inversion = 0, - .if_khz = 6000, - .output_if = 4, /* LG2161_OIF_SPI_MAS */ -}; - -static int mxl111sf_lg2161_frontend_attach(struct dvb_usb_adapter *adap) -{ - struct dvb_usb_device *d = adap->dev; - struct mxl111sf_state *state = d->priv; - int fe_id = adap->num_frontends_initialized; - struct mxl111sf_adap_state *adap_state = adap->fe_adap[fe_id].priv; - int ret; - - deb_adv("%s()\n", __func__); - - /* save a pointer to the dvb_usb_device in device state */ - state->d = d; - adap_state->alt_mode = (dvb_usb_mxl111sf_isoc) ? 2 : 1; - state->alt_mode = adap_state->alt_mode; - - if (usb_set_interface(adap->dev->udev, 0, state->alt_mode) < 0) - err("set interface failed"); - - state->gpio_mode = MXL111SF_GPIO_MOD_MH; - adap_state->gpio_mode = state->gpio_mode; - adap_state->device_mode = MXL_TUNER_MODE; - adap_state->ep6_clockphase = 1; - - ret = mxl1x1sf_soft_reset(state); - if (mxl_fail(ret)) - goto fail; - ret = mxl111sf_init_tuner_demod(state); - if (mxl_fail(ret)) - goto fail; - - ret = mxl1x1sf_set_device_mode(state, adap_state->device_mode); - if (mxl_fail(ret)) - goto fail; - - ret = mxl111sf_enable_usb_output(state); - if (mxl_fail(ret)) - goto fail; - ret = mxl1x1sf_top_master_ctrl(state, 1); - if (mxl_fail(ret)) - goto fail; - - ret = mxl111sf_init_port_expander(state); - if (mxl_fail(ret)) - goto fail; - ret = mxl111sf_gpio_mode_switch(state, state->gpio_mode); - if (mxl_fail(ret)) - goto fail; - - ret = get_chip_info(state); - if (mxl_fail(ret)) - goto fail; - - adap->fe_adap[fe_id].fe = dvb_attach(lg2160_attach, - (MXL111SF_V8_200 == state->chip_rev) ? - &hauppauge_lg2161_1040_config : - &hauppauge_lg2161_1019_config, - &adap->dev->i2c_adap); - if (adap->fe_adap[fe_id].fe) { - adap_state->fe_init = adap->fe_adap[fe_id].fe->ops.init; - adap->fe_adap[fe_id].fe->ops.init = mxl111sf_adap_fe_init; - adap_state->fe_sleep = adap->fe_adap[fe_id].fe->ops.sleep; - adap->fe_adap[fe_id].fe->ops.sleep = mxl111sf_adap_fe_sleep; - return 0; - } - ret = -EIO; -fail: - return ret; -} - -static struct lg2160_config hauppauge_lg2161_1019_ep6_config = { - .lg_chip = LG2161_1019, - .i2c_addr = 0x1c >> 1, - .deny_i2c_rptr = 1, - .spectral_inversion = 0, - .if_khz = 6000, - .output_if = 1, /* LG2161_OIF_SERIAL_TS */ -}; - -static struct lg2160_config hauppauge_lg2161_1040_ep6_config = { - .lg_chip = LG2161_1040, - .i2c_addr = 0x1c >> 1, - .deny_i2c_rptr = 1, - .spectral_inversion = 0, - .if_khz = 6000, - .output_if = 7, /* LG2161_OIF_SERIAL_TS */ -}; - -static int mxl111sf_lg2161_ep6_frontend_attach(struct dvb_usb_adapter *adap) -{ - struct dvb_usb_device *d = adap->dev; - struct mxl111sf_state *state = d->priv; - int fe_id = adap->num_frontends_initialized; - struct mxl111sf_adap_state *adap_state = adap->fe_adap[fe_id].priv; - int ret; - - deb_adv("%s()\n", __func__); - - /* save a pointer to the dvb_usb_device in device state */ - state->d = d; - adap_state->alt_mode = (dvb_usb_mxl111sf_isoc) ? 2 : 1; - state->alt_mode = adap_state->alt_mode; - - if (usb_set_interface(adap->dev->udev, 0, state->alt_mode) < 0) - err("set interface failed"); - - state->gpio_mode = MXL111SF_GPIO_MOD_MH; - adap_state->gpio_mode = state->gpio_mode; - adap_state->device_mode = MXL_TUNER_MODE; - adap_state->ep6_clockphase = 0; - - ret = mxl1x1sf_soft_reset(state); - if (mxl_fail(ret)) - goto fail; - ret = mxl111sf_init_tuner_demod(state); - if (mxl_fail(ret)) - goto fail; - - ret = mxl1x1sf_set_device_mode(state, adap_state->device_mode); - if (mxl_fail(ret)) - goto fail; - - ret = mxl111sf_enable_usb_output(state); - if (mxl_fail(ret)) - goto fail; - ret = mxl1x1sf_top_master_ctrl(state, 1); - if (mxl_fail(ret)) - goto fail; - - ret = mxl111sf_init_port_expander(state); - if (mxl_fail(ret)) - goto fail; - ret = mxl111sf_gpio_mode_switch(state, state->gpio_mode); - if (mxl_fail(ret)) - goto fail; - - ret = get_chip_info(state); - if (mxl_fail(ret)) - goto fail; - - adap->fe_adap[fe_id].fe = dvb_attach(lg2160_attach, - (MXL111SF_V8_200 == state->chip_rev) ? - &hauppauge_lg2161_1040_ep6_config : - &hauppauge_lg2161_1019_ep6_config, - &adap->dev->i2c_adap); - if (adap->fe_adap[fe_id].fe) { - adap_state->fe_init = adap->fe_adap[fe_id].fe->ops.init; - adap->fe_adap[fe_id].fe->ops.init = mxl111sf_adap_fe_init; - adap_state->fe_sleep = adap->fe_adap[fe_id].fe->ops.sleep; - adap->fe_adap[fe_id].fe->ops.sleep = mxl111sf_adap_fe_sleep; - return 0; - } - ret = -EIO; -fail: - return ret; -} - -static struct mxl111sf_demod_config mxl_demod_config = { - .read_reg = mxl111sf_read_reg, - .write_reg = mxl111sf_write_reg, - .program_regs = mxl111sf_ctrl_program_regs, -}; - -static int mxl111sf_attach_demod(struct dvb_usb_adapter *adap) -{ - struct dvb_usb_device *d = adap->dev; - struct mxl111sf_state *state = d->priv; - int fe_id = adap->num_frontends_initialized; - struct mxl111sf_adap_state *adap_state = adap->fe_adap[fe_id].priv; - int ret; - - deb_adv("%s()\n", __func__); - - /* save a pointer to the dvb_usb_device in device state */ - state->d = d; - adap_state->alt_mode = (dvb_usb_mxl111sf_isoc) ? 1 : 2; - state->alt_mode = adap_state->alt_mode; - - if (usb_set_interface(adap->dev->udev, 0, state->alt_mode) < 0) - err("set interface failed"); - - state->gpio_mode = MXL111SF_GPIO_MOD_DVBT; - adap_state->gpio_mode = state->gpio_mode; - adap_state->device_mode = MXL_SOC_MODE; - adap_state->ep6_clockphase = 1; - - ret = mxl1x1sf_soft_reset(state); - if (mxl_fail(ret)) - goto fail; - ret = mxl111sf_init_tuner_demod(state); - if (mxl_fail(ret)) - goto fail; - - ret = mxl1x1sf_set_device_mode(state, adap_state->device_mode); - if (mxl_fail(ret)) - goto fail; - - ret = mxl111sf_enable_usb_output(state); - if (mxl_fail(ret)) - goto fail; - ret = mxl1x1sf_top_master_ctrl(state, 1); - if (mxl_fail(ret)) - goto fail; - - /* dont care if this fails */ - mxl111sf_init_port_expander(state); - - adap->fe_adap[fe_id].fe = dvb_attach(mxl111sf_demod_attach, state, - &mxl_demod_config); - if (adap->fe_adap[fe_id].fe) { - adap_state->fe_init = adap->fe_adap[fe_id].fe->ops.init; - adap->fe_adap[fe_id].fe->ops.init = mxl111sf_adap_fe_init; - adap_state->fe_sleep = adap->fe_adap[fe_id].fe->ops.sleep; - adap->fe_adap[fe_id].fe->ops.sleep = mxl111sf_adap_fe_sleep; - return 0; - } - ret = -EIO; -fail: - return ret; -} - -static inline int mxl111sf_set_ant_path(struct mxl111sf_state *state, - int antpath) -{ - return mxl111sf_idac_config(state, 1, 1, - (antpath == ANT_PATH_INTERNAL) ? - 0x3f : 0x00, 0); -} - -#define DbgAntHunt(x, pwr0, pwr1, pwr2, pwr3) \ - err("%s(%d) FINAL input set to %s rxPwr:%d|%d|%d|%d\n", \ - __func__, __LINE__, \ - (ANT_PATH_EXTERNAL == x) ? "EXTERNAL" : "INTERNAL", \ - pwr0, pwr1, pwr2, pwr3) - -#define ANT_HUNT_SLEEP 90 -#define ANT_EXT_TWEAK 0 - -static int mxl111sf_ant_hunt(struct dvb_frontend *fe) -{ - struct dvb_usb_adapter *adap = fe->dvb->priv; - struct dvb_usb_device *d = adap->dev; - struct mxl111sf_state *state = d->priv; - - int antctrl = dvb_usb_mxl111sf_rfswitch; - - u16 rxPwrA, rxPwr0, rxPwr1, rxPwr2; - - /* FIXME: must force EXTERNAL for QAM - done elsewhere */ - mxl111sf_set_ant_path(state, antctrl == ANT_PATH_AUTO ? - ANT_PATH_EXTERNAL : antctrl); - - if (antctrl == ANT_PATH_AUTO) { -#if 0 - msleep(ANT_HUNT_SLEEP); -#endif - fe->ops.tuner_ops.get_rf_strength(fe, &rxPwrA); - - mxl111sf_set_ant_path(state, ANT_PATH_EXTERNAL); - msleep(ANT_HUNT_SLEEP); - fe->ops.tuner_ops.get_rf_strength(fe, &rxPwr0); - - mxl111sf_set_ant_path(state, ANT_PATH_EXTERNAL); - msleep(ANT_HUNT_SLEEP); - fe->ops.tuner_ops.get_rf_strength(fe, &rxPwr1); - - mxl111sf_set_ant_path(state, ANT_PATH_INTERNAL); - msleep(ANT_HUNT_SLEEP); - fe->ops.tuner_ops.get_rf_strength(fe, &rxPwr2); - - if (rxPwr1+ANT_EXT_TWEAK >= rxPwr2) { - /* return with EXTERNAL enabled */ - mxl111sf_set_ant_path(state, ANT_PATH_EXTERNAL); - DbgAntHunt(ANT_PATH_EXTERNAL, rxPwrA, - rxPwr0, rxPwr1, rxPwr2); - } else { - /* return with INTERNAL enabled */ - DbgAntHunt(ANT_PATH_INTERNAL, rxPwrA, - rxPwr0, rxPwr1, rxPwr2); - } - } - return 0; -} - -static struct mxl111sf_tuner_config mxl_tuner_config = { - .if_freq = MXL_IF_6_0, /* applies to external IF output, only */ - .invert_spectrum = 0, - .read_reg = mxl111sf_read_reg, - .write_reg = mxl111sf_write_reg, - .program_regs = mxl111sf_ctrl_program_regs, - .top_master_ctrl = mxl1x1sf_top_master_ctrl, - .ant_hunt = mxl111sf_ant_hunt, -}; - -static int mxl111sf_attach_tuner(struct dvb_usb_adapter *adap) -{ - struct dvb_usb_device *d = adap->dev; - struct mxl111sf_state *state = d->priv; - int fe_id = adap->num_frontends_initialized; - - deb_adv("%s()\n", __func__); - - if (NULL != dvb_attach(mxl111sf_tuner_attach, - adap->fe_adap[fe_id].fe, state, - &mxl_tuner_config)) - return 0; - - return -EIO; -} - -static int mxl111sf_fe_ioctl_override(struct dvb_frontend *fe, - unsigned int cmd, void *parg, - unsigned int stage) -{ - int err = 0; - - switch (stage) { - case DVB_FE_IOCTL_PRE: - - switch (cmd) { - case FE_READ_SIGNAL_STRENGTH: - err = fe->ops.tuner_ops.get_rf_strength(fe, parg); - /* If no error occurs, prevent dvb-core from handling - * this IOCTL, otherwise return the error */ - if (0 == err) - err = 1; - break; - } - break; - - case DVB_FE_IOCTL_POST: - /* no post-ioctl handling required */ - break; - } - return err; -}; - -static u32 mxl111sf_i2c_func(struct i2c_adapter *adapter) -{ - return I2C_FUNC_I2C; -} - -struct i2c_algorithm mxl111sf_i2c_algo = { - .master_xfer = mxl111sf_i2c_xfer, - .functionality = mxl111sf_i2c_func, -#ifdef NEED_ALGO_CONTROL - .algo_control = dummy_algo_control, -#endif -}; - -static struct dvb_usb_device_properties mxl111sf_dvbt_bulk_properties; -static struct dvb_usb_device_properties mxl111sf_dvbt_isoc_properties; -static struct dvb_usb_device_properties mxl111sf_atsc_bulk_properties; -static struct dvb_usb_device_properties mxl111sf_atsc_isoc_properties; -static struct dvb_usb_device_properties mxl111sf_atsc_mh_bulk_properties; -static struct dvb_usb_device_properties mxl111sf_atsc_mh_isoc_properties; -static struct dvb_usb_device_properties mxl111sf_mh_bulk_properties; -static struct dvb_usb_device_properties mxl111sf_mh_isoc_properties; -static struct dvb_usb_device_properties mxl111sf_mercury_spi_bulk_properties; -static struct dvb_usb_device_properties mxl111sf_mercury_spi_isoc_properties; -static struct dvb_usb_device_properties mxl111sf_mercury_tp_bulk_properties; -static struct dvb_usb_device_properties mxl111sf_mercury_tp_isoc_properties; -static struct dvb_usb_device_properties mxl111sf_mercury_mh_spi_bulk_properties; -static struct dvb_usb_device_properties mxl111sf_mercury_mh_spi_isoc_properties; -static struct dvb_usb_device_properties mxl111sf_mercury_mh_tp_bulk_properties; -static struct dvb_usb_device_properties mxl111sf_mercury_mh_tp_isoc_properties; - -static int mxl111sf_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - struct dvb_usb_device *d = NULL; - - deb_adv("%s()\n", __func__); - - if (((dvb_usb_mxl111sf_isoc) && - (0 == dvb_usb_device_init(intf, - &mxl111sf_dvbt_isoc_properties, - THIS_MODULE, &d, adapter_nr) || - 0 == dvb_usb_device_init(intf, - &mxl111sf_atsc_isoc_properties, - THIS_MODULE, &d, adapter_nr) || - 0 == dvb_usb_device_init(intf, - &mxl111sf_atsc_mh_isoc_properties, - THIS_MODULE, &d, adapter_nr) || - 0 == dvb_usb_device_init(intf, - &mxl111sf_mh_isoc_properties, - THIS_MODULE, &d, adapter_nr) || - ((dvb_usb_mxl111sf_spi) && - (0 == dvb_usb_device_init(intf, - &mxl111sf_mercury_spi_isoc_properties, - THIS_MODULE, &d, adapter_nr) || - 0 == dvb_usb_device_init(intf, - &mxl111sf_mercury_mh_spi_isoc_properties, - THIS_MODULE, &d, adapter_nr))) || - 0 == dvb_usb_device_init(intf, - &mxl111sf_mercury_tp_isoc_properties, - THIS_MODULE, &d, adapter_nr) || - 0 == dvb_usb_device_init(intf, - &mxl111sf_mercury_mh_tp_isoc_properties, - THIS_MODULE, &d, adapter_nr))) || - 0 == dvb_usb_device_init(intf, - &mxl111sf_dvbt_bulk_properties, - THIS_MODULE, &d, adapter_nr) || - 0 == dvb_usb_device_init(intf, - &mxl111sf_atsc_bulk_properties, - THIS_MODULE, &d, adapter_nr) || - 0 == dvb_usb_device_init(intf, - &mxl111sf_atsc_mh_bulk_properties, - THIS_MODULE, &d, adapter_nr) || - 0 == dvb_usb_device_init(intf, - &mxl111sf_mh_bulk_properties, - THIS_MODULE, &d, adapter_nr) || - ((dvb_usb_mxl111sf_spi) && - (0 == dvb_usb_device_init(intf, - &mxl111sf_mercury_spi_bulk_properties, - THIS_MODULE, &d, adapter_nr) || - 0 == dvb_usb_device_init(intf, - &mxl111sf_mercury_mh_spi_bulk_properties, - THIS_MODULE, &d, adapter_nr))) || - 0 == dvb_usb_device_init(intf, - &mxl111sf_mercury_tp_bulk_properties, - THIS_MODULE, &d, adapter_nr) || - 0 == dvb_usb_device_init(intf, - &mxl111sf_mercury_mh_tp_bulk_properties, - THIS_MODULE, &d, adapter_nr) || 0) { - - struct mxl111sf_state *state = d->priv; - static u8 eeprom[256]; - struct i2c_client c; - int ret; - - ret = get_chip_info(state); - if (mxl_fail(ret)) - err("failed to get chip info during probe"); - - mutex_init(&state->fe_lock); - - if (state->chip_rev > MXL111SF_V6) - mxl111sf_config_pin_mux_modes(state, - PIN_MUX_TS_SPI_IN_MODE_1); - - c.adapter = &d->i2c_adap; - c.addr = 0xa0 >> 1; - - ret = tveeprom_read(&c, eeprom, sizeof(eeprom)); - if (mxl_fail(ret)) - return 0; - tveeprom_hauppauge_analog(&c, &state->tv, - (0x84 == eeprom[0xa0]) ? - eeprom + 0xa0 : eeprom + 0x80); -#if 0 - switch (state->tv.model) { - case 117001: - case 126001: - case 138001: - break; - default: - printk(KERN_WARNING "%s: warning: " - "unknown hauppauge model #%d\n", - __func__, state->tv.model); - } -#endif - return 0; - } - err("Your device is not yet supported by this driver. " - "See kernellabs.com for more info"); - return -EINVAL; -} - -static struct usb_device_id mxl111sf_table[] = { -/* 0 */ { USB_DEVICE(USB_VID_HAUPPAUGE, 0xc600) }, /* ATSC+ IR */ - { USB_DEVICE(USB_VID_HAUPPAUGE, 0xc601) }, /* ATSC */ - { USB_DEVICE(USB_VID_HAUPPAUGE, 0xc602) }, /* + */ - { USB_DEVICE(USB_VID_HAUPPAUGE, 0xc603) }, /* ATSC+ */ - { USB_DEVICE(USB_VID_HAUPPAUGE, 0xc604) }, /* DVBT */ -/* 5 */ { USB_DEVICE(USB_VID_HAUPPAUGE, 0xc609) }, /* ATSC IR */ - { USB_DEVICE(USB_VID_HAUPPAUGE, 0xc60a) }, /* + IR */ - { USB_DEVICE(USB_VID_HAUPPAUGE, 0xc60b) }, /* ATSC+ IR */ - { USB_DEVICE(USB_VID_HAUPPAUGE, 0xc60c) }, /* DVBT IR */ - { USB_DEVICE(USB_VID_HAUPPAUGE, 0xc653) }, /* ATSC+ */ -/*10 */ { USB_DEVICE(USB_VID_HAUPPAUGE, 0xc65b) }, /* ATSC+ IR */ - { USB_DEVICE(USB_VID_HAUPPAUGE, 0xb700) }, /* ATSC+ sw */ - { USB_DEVICE(USB_VID_HAUPPAUGE, 0xb701) }, /* ATSC sw */ - { USB_DEVICE(USB_VID_HAUPPAUGE, 0xb702) }, /* + sw */ - { USB_DEVICE(USB_VID_HAUPPAUGE, 0xb703) }, /* ATSC+ sw */ -/*15 */ { USB_DEVICE(USB_VID_HAUPPAUGE, 0xb704) }, /* DVBT sw */ - { USB_DEVICE(USB_VID_HAUPPAUGE, 0xb753) }, /* ATSC+ sw */ - { USB_DEVICE(USB_VID_HAUPPAUGE, 0xb763) }, /* ATSC+ no */ - { USB_DEVICE(USB_VID_HAUPPAUGE, 0xb764) }, /* DVBT no */ - { USB_DEVICE(USB_VID_HAUPPAUGE, 0xd853) }, /* ATSC+ sw */ -/*20 */ { USB_DEVICE(USB_VID_HAUPPAUGE, 0xd854) }, /* DVBT sw */ - { USB_DEVICE(USB_VID_HAUPPAUGE, 0xd863) }, /* ATSC+ no */ - { USB_DEVICE(USB_VID_HAUPPAUGE, 0xd864) }, /* DVBT no */ - { USB_DEVICE(USB_VID_HAUPPAUGE, 0xd8d3) }, /* ATSC+ sw */ - { USB_DEVICE(USB_VID_HAUPPAUGE, 0xd8d4) }, /* DVBT sw */ -/*25 */ { USB_DEVICE(USB_VID_HAUPPAUGE, 0xd8e3) }, /* ATSC+ no */ - { USB_DEVICE(USB_VID_HAUPPAUGE, 0xd8e4) }, /* DVBT no */ - { USB_DEVICE(USB_VID_HAUPPAUGE, 0xd8ff) }, /* ATSC+ */ - { USB_DEVICE(USB_VID_HAUPPAUGE, 0xc612) }, /* + */ - { USB_DEVICE(USB_VID_HAUPPAUGE, 0xc613) }, /* ATSC+ */ -/*30 */ { USB_DEVICE(USB_VID_HAUPPAUGE, 0xc61a) }, /* + IR */ - { USB_DEVICE(USB_VID_HAUPPAUGE, 0xc61b) }, /* ATSC+ IR */ - { USB_DEVICE(USB_VID_HAUPPAUGE, 0xb757) }, /* ATSC+DVBT sw */ - { USB_DEVICE(USB_VID_HAUPPAUGE, 0xb767) }, /* ATSC+DVBT no */ - {} /* Terminating entry */ -}; -MODULE_DEVICE_TABLE(usb, mxl111sf_table); - - -#define MXL111SF_EP4_BULK_STREAMING_CONFIG \ - .size_of_priv = sizeof(struct mxl111sf_adap_state), \ - .streaming_ctrl = mxl111sf_ep4_streaming_ctrl, \ - .stream = { \ - .type = USB_BULK, \ - .count = 5, \ - .endpoint = 0x04, \ - .u = { \ - .bulk = { \ - .buffersize = 8192, \ - } \ - } \ - } - -/* FIXME: works for v6 but not v8 silicon */ -#define MXL111SF_EP4_ISOC_STREAMING_CONFIG \ - .size_of_priv = sizeof(struct mxl111sf_adap_state), \ - .streaming_ctrl = mxl111sf_ep4_streaming_ctrl, \ - .stream = { \ - .type = USB_ISOC, \ - .count = 5, \ - .endpoint = 0x04, \ - .u = { \ - .isoc = { \ - .framesperurb = 96, \ - /* FIXME: v6 SILICON: */ \ - .framesize = 564, \ - .interval = 1, \ - } \ - } \ - } - -#define MXL111SF_EP5_BULK_STREAMING_CONFIG \ - .size_of_priv = sizeof(struct mxl111sf_adap_state), \ - .streaming_ctrl = mxl111sf_ep5_streaming_ctrl, \ - .stream = { \ - .type = USB_BULK, \ - .count = 5, \ - .endpoint = 0x05, \ - .u = { \ - .bulk = { \ - .buffersize = 8192, \ - } \ - } \ - } - -#define MXL111SF_EP5_ISOC_STREAMING_CONFIG \ - .size_of_priv = sizeof(struct mxl111sf_adap_state), \ - .streaming_ctrl = mxl111sf_ep5_streaming_ctrl, \ - .stream = { \ - .type = USB_ISOC, \ - .count = 5, \ - .endpoint = 0x05, \ - .u = { \ - .isoc = { \ - .framesperurb = 96, \ - .framesize = 200, \ - .interval = 1, \ - } \ - } \ - } - -#define MXL111SF_EP6_BULK_STREAMING_CONFIG \ - .size_of_priv = sizeof(struct mxl111sf_adap_state), \ - .streaming_ctrl = mxl111sf_ep6_streaming_ctrl, \ - .stream = { \ - .type = USB_BULK, \ - .count = 5, \ - .endpoint = 0x06, \ - .u = { \ - .bulk = { \ - .buffersize = 8192, \ - } \ - } \ - } - -/* FIXME */ -#define MXL111SF_EP6_ISOC_STREAMING_CONFIG \ - .size_of_priv = sizeof(struct mxl111sf_adap_state), \ - .streaming_ctrl = mxl111sf_ep6_streaming_ctrl, \ - .stream = { \ - .type = USB_ISOC, \ - .count = 5, \ - .endpoint = 0x06, \ - .u = { \ - .isoc = { \ - .framesperurb = 24, \ - .framesize = 3072, \ - .interval = 1, \ - } \ - } \ - } - -#define MXL111SF_DEFAULT_DEVICE_PROPERTIES \ - .caps = DVB_USB_IS_AN_I2C_ADAPTER, \ - .usb_ctrl = DEVICE_SPECIFIC, \ - /* use usb alt setting 1 for EP4 ISOC transfer (dvb-t), \ - EP6 BULK transfer (atsc/qam), \ - use usb alt setting 2 for EP4 BULK transfer (dvb-t), \ - EP6 ISOC transfer (atsc/qam), \ - */ \ - .power_ctrl = mxl111sf_power_ctrl, \ - .i2c_algo = &mxl111sf_i2c_algo, \ - .generic_bulk_ctrl_endpoint = MXL_EP2_REG_WRITE, \ - .generic_bulk_ctrl_endpoint_response = MXL_EP1_REG_READ, \ - .size_of_priv = sizeof(struct mxl111sf_state) - -static struct dvb_usb_device_properties mxl111sf_dvbt_bulk_properties = { - MXL111SF_DEFAULT_DEVICE_PROPERTIES, - - .num_adapters = 1, - .adapter = { - { - .fe_ioctl_override = mxl111sf_fe_ioctl_override, - .num_frontends = 1, - .fe = {{ - .frontend_attach = mxl111sf_attach_demod, - .tuner_attach = mxl111sf_attach_tuner, - - MXL111SF_EP4_BULK_STREAMING_CONFIG, - } }, - }, - }, - .num_device_descs = 3, - .devices = { - { "Hauppauge 126xxx DVBT (bulk)", - { NULL }, - { &mxl111sf_table[4], &mxl111sf_table[8], - NULL }, - }, - { "Hauppauge 117xxx DVBT (bulk)", - { NULL }, - { &mxl111sf_table[15], &mxl111sf_table[18], - NULL }, - }, - { "Hauppauge 138xxx DVBT (bulk)", - { NULL }, - { &mxl111sf_table[20], &mxl111sf_table[22], - &mxl111sf_table[24], &mxl111sf_table[26], - NULL }, - }, - } -}; - -static struct dvb_usb_device_properties mxl111sf_dvbt_isoc_properties = { - MXL111SF_DEFAULT_DEVICE_PROPERTIES, - - .num_adapters = 1, - .adapter = { - { - .fe_ioctl_override = mxl111sf_fe_ioctl_override, - .num_frontends = 1, - .fe = {{ - .frontend_attach = mxl111sf_attach_demod, - .tuner_attach = mxl111sf_attach_tuner, - - MXL111SF_EP4_ISOC_STREAMING_CONFIG, - } }, - }, - }, - .num_device_descs = 3, - .devices = { - { "Hauppauge 126xxx DVBT (isoc)", - { NULL }, - { &mxl111sf_table[4], &mxl111sf_table[8], - NULL }, - }, - { "Hauppauge 117xxx DVBT (isoc)", - { NULL }, - { &mxl111sf_table[15], &mxl111sf_table[18], - NULL }, - }, - { "Hauppauge 138xxx DVBT (isoc)", - { NULL }, - { &mxl111sf_table[20], &mxl111sf_table[22], - &mxl111sf_table[24], &mxl111sf_table[26], - NULL }, - }, - } -}; - -static struct dvb_usb_device_properties mxl111sf_atsc_bulk_properties = { - MXL111SF_DEFAULT_DEVICE_PROPERTIES, - - .num_adapters = 1, - .adapter = { - { - .fe_ioctl_override = mxl111sf_fe_ioctl_override, - .num_frontends = 1, - .fe = {{ - .frontend_attach = mxl111sf_lgdt3305_frontend_attach, - .tuner_attach = mxl111sf_attach_tuner, - - MXL111SF_EP6_BULK_STREAMING_CONFIG, - }}, - }, - }, - .num_device_descs = 2, - .devices = { - { "Hauppauge 126xxx ATSC (bulk)", - { NULL }, - { &mxl111sf_table[1], &mxl111sf_table[5], - NULL }, - }, - { "Hauppauge 117xxx ATSC (bulk)", - { NULL }, - { &mxl111sf_table[12], - NULL }, - }, - } -}; - -static struct dvb_usb_device_properties mxl111sf_atsc_isoc_properties = { - MXL111SF_DEFAULT_DEVICE_PROPERTIES, - - .num_adapters = 1, - .adapter = { - { - .fe_ioctl_override = mxl111sf_fe_ioctl_override, - .num_frontends = 1, - .fe = {{ - .frontend_attach = mxl111sf_lgdt3305_frontend_attach, - .tuner_attach = mxl111sf_attach_tuner, - - MXL111SF_EP6_ISOC_STREAMING_CONFIG, - }}, - }, - }, - .num_device_descs = 2, - .devices = { - { "Hauppauge 126xxx ATSC (isoc)", - { NULL }, - { &mxl111sf_table[1], &mxl111sf_table[5], - NULL }, - }, - { "Hauppauge 117xxx ATSC (isoc)", - { NULL }, - { &mxl111sf_table[12], - NULL }, - }, - } -}; - -static struct dvb_usb_device_properties mxl111sf_mh_bulk_properties = { - MXL111SF_DEFAULT_DEVICE_PROPERTIES, - - .num_adapters = 1, - .adapter = { - { - .fe_ioctl_override = mxl111sf_fe_ioctl_override, - .num_frontends = 1, - .fe = {{ - .caps = DVB_USB_ADAP_RECEIVES_RAW_PAYLOAD, - - .frontend_attach = mxl111sf_lg2160_frontend_attach, - .tuner_attach = mxl111sf_attach_tuner, - - MXL111SF_EP5_BULK_STREAMING_CONFIG, - }}, - }, - }, - .num_device_descs = 2, - .devices = { - { "HCW 126xxx (bulk)", - { NULL }, - { &mxl111sf_table[2], &mxl111sf_table[6], - NULL }, - }, - { "HCW 117xxx (bulk)", - { NULL }, - { &mxl111sf_table[13], - NULL }, - }, - } -}; - -static struct dvb_usb_device_properties mxl111sf_mh_isoc_properties = { - MXL111SF_DEFAULT_DEVICE_PROPERTIES, - - .num_adapters = 1, - .adapter = { - { - .fe_ioctl_override = mxl111sf_fe_ioctl_override, - .num_frontends = 1, - .fe = {{ - .caps = DVB_USB_ADAP_RECEIVES_RAW_PAYLOAD, - - .frontend_attach = mxl111sf_lg2160_frontend_attach, - .tuner_attach = mxl111sf_attach_tuner, - - MXL111SF_EP5_ISOC_STREAMING_CONFIG, - }}, - }, - }, - .num_device_descs = 2, - .devices = { - { "HCW 126xxx (isoc)", - { NULL }, - { &mxl111sf_table[2], &mxl111sf_table[6], - NULL }, - }, - { "HCW 117xxx (isoc)", - { NULL }, - { &mxl111sf_table[13], - NULL }, - }, - } -}; - -static struct dvb_usb_device_properties mxl111sf_atsc_mh_bulk_properties = { - MXL111SF_DEFAULT_DEVICE_PROPERTIES, - - .num_adapters = 1, - .adapter = { - { - .fe_ioctl_override = mxl111sf_fe_ioctl_override, - .num_frontends = 3, - .fe = {{ - .frontend_attach = mxl111sf_lgdt3305_frontend_attach, - .tuner_attach = mxl111sf_attach_tuner, - - MXL111SF_EP6_BULK_STREAMING_CONFIG, - }, - { - .frontend_attach = mxl111sf_attach_demod, - .tuner_attach = mxl111sf_attach_tuner, - - MXL111SF_EP4_BULK_STREAMING_CONFIG, - }, - { - .caps = DVB_USB_ADAP_RECEIVES_RAW_PAYLOAD, - - .frontend_attach = mxl111sf_lg2160_frontend_attach, - .tuner_attach = mxl111sf_attach_tuner, - - MXL111SF_EP5_BULK_STREAMING_CONFIG, - }}, - }, - }, - .num_device_descs = 2, - .devices = { - { "Hauppauge 126xxx ATSC+ (bulk)", - { NULL }, - { &mxl111sf_table[0], &mxl111sf_table[3], - &mxl111sf_table[7], &mxl111sf_table[9], - &mxl111sf_table[10], NULL }, - }, - { "Hauppauge 117xxx ATSC+ (bulk)", - { NULL }, - { &mxl111sf_table[11], &mxl111sf_table[14], - &mxl111sf_table[16], &mxl111sf_table[17], - &mxl111sf_table[32], &mxl111sf_table[33], - NULL }, - }, - } -}; - -static struct dvb_usb_device_properties mxl111sf_atsc_mh_isoc_properties = { - MXL111SF_DEFAULT_DEVICE_PROPERTIES, - - .num_adapters = 1, - .adapter = { - { - .fe_ioctl_override = mxl111sf_fe_ioctl_override, - .num_frontends = 3, - .fe = {{ - .frontend_attach = mxl111sf_lgdt3305_frontend_attach, - .tuner_attach = mxl111sf_attach_tuner, - - MXL111SF_EP6_ISOC_STREAMING_CONFIG, - }, - { - .frontend_attach = mxl111sf_attach_demod, - .tuner_attach = mxl111sf_attach_tuner, - - MXL111SF_EP4_ISOC_STREAMING_CONFIG, - }, - { - .caps = DVB_USB_ADAP_RECEIVES_RAW_PAYLOAD, - - .frontend_attach = mxl111sf_lg2160_frontend_attach, - .tuner_attach = mxl111sf_attach_tuner, - - MXL111SF_EP5_ISOC_STREAMING_CONFIG, - }}, - }, - }, - .num_device_descs = 2, - .devices = { - { "Hauppauge 126xxx ATSC+ (isoc)", - { NULL }, - { &mxl111sf_table[0], &mxl111sf_table[3], - &mxl111sf_table[7], &mxl111sf_table[9], - &mxl111sf_table[10], NULL }, - }, - { "Hauppauge 117xxx ATSC+ (isoc)", - { NULL }, - { &mxl111sf_table[11], &mxl111sf_table[14], - &mxl111sf_table[16], &mxl111sf_table[17], - &mxl111sf_table[32], &mxl111sf_table[33], - NULL }, - }, - } -}; - -static struct dvb_usb_device_properties mxl111sf_mercury_spi_bulk_properties = { - MXL111SF_DEFAULT_DEVICE_PROPERTIES, - - .num_adapters = 1, - .adapter = { - { - .fe_ioctl_override = mxl111sf_fe_ioctl_override, - .num_frontends = 3, - .fe = {{ - .frontend_attach = mxl111sf_lgdt3305_frontend_attach, - .tuner_attach = mxl111sf_attach_tuner, - - MXL111SF_EP6_BULK_STREAMING_CONFIG, - }, - { - .frontend_attach = mxl111sf_attach_demod, - .tuner_attach = mxl111sf_attach_tuner, - - MXL111SF_EP4_BULK_STREAMING_CONFIG, - }, - { - .caps = DVB_USB_ADAP_RECEIVES_RAW_PAYLOAD, - - .frontend_attach = mxl111sf_lg2161_frontend_attach, - .tuner_attach = mxl111sf_attach_tuner, - - MXL111SF_EP5_BULK_STREAMING_CONFIG, - }}, - }, - }, - .num_device_descs = 2, - .devices = { - { "Hauppauge Mercury (spi-bulk)", - { NULL }, - { &mxl111sf_table[19], &mxl111sf_table[21], - &mxl111sf_table[23], &mxl111sf_table[25], - NULL }, - }, - { "Hauppauge WinTV-Aero-M (spi-bulk)", - { NULL }, - { &mxl111sf_table[29], &mxl111sf_table[31], - NULL }, - }, - } -}; - -static struct dvb_usb_device_properties mxl111sf_mercury_spi_isoc_properties = { - MXL111SF_DEFAULT_DEVICE_PROPERTIES, - - .num_adapters = 1, - .adapter = { - { - .fe_ioctl_override = mxl111sf_fe_ioctl_override, - .num_frontends = 3, - .fe = {{ - .frontend_attach = mxl111sf_lgdt3305_frontend_attach, - .tuner_attach = mxl111sf_attach_tuner, - - MXL111SF_EP6_ISOC_STREAMING_CONFIG, - }, - { - .frontend_attach = mxl111sf_attach_demod, - .tuner_attach = mxl111sf_attach_tuner, - - MXL111SF_EP4_ISOC_STREAMING_CONFIG, - }, - { - .caps = DVB_USB_ADAP_RECEIVES_RAW_PAYLOAD, - - .frontend_attach = mxl111sf_lg2161_frontend_attach, - .tuner_attach = mxl111sf_attach_tuner, - - MXL111SF_EP5_ISOC_STREAMING_CONFIG, - }}, - }, - }, - .num_device_descs = 2, - .devices = { - { "Hauppauge Mercury (spi-isoc)", - { NULL }, - { &mxl111sf_table[19], &mxl111sf_table[21], - &mxl111sf_table[23], &mxl111sf_table[25], - NULL }, - }, - { "Hauppauge WinTV-Aero-M (spi-isoc)", - { NULL }, - { &mxl111sf_table[29], &mxl111sf_table[31], - NULL }, - }, - } -}; - -static struct dvb_usb_device_properties mxl111sf_mercury_tp_bulk_properties = { - MXL111SF_DEFAULT_DEVICE_PROPERTIES, - - .num_adapters = 1, - .adapter = { - { - .fe_ioctl_override = mxl111sf_fe_ioctl_override, - .num_frontends = 3, - .fe = {{ - .frontend_attach = mxl111sf_lgdt3305_frontend_attach, - .tuner_attach = mxl111sf_attach_tuner, - - MXL111SF_EP6_BULK_STREAMING_CONFIG, - }, - { - .frontend_attach = mxl111sf_attach_demod, - .tuner_attach = mxl111sf_attach_tuner, - - MXL111SF_EP4_BULK_STREAMING_CONFIG, - }, - { - .caps = DVB_USB_ADAP_RECEIVES_RAW_PAYLOAD, - - .frontend_attach = mxl111sf_lg2161_ep6_frontend_attach, - .tuner_attach = mxl111sf_attach_tuner, - - MXL111SF_EP6_BULK_STREAMING_CONFIG, - }}, - }, - }, - .num_device_descs = 2, - .devices = { - { "Hauppauge Mercury (tp-bulk)", - { NULL }, - { &mxl111sf_table[19], &mxl111sf_table[21], - &mxl111sf_table[23], &mxl111sf_table[25], - &mxl111sf_table[27], NULL }, - }, - { "Hauppauge WinTV-Aero-M", - { NULL }, - { &mxl111sf_table[29], &mxl111sf_table[31], - NULL }, - }, - } -}; - -static struct dvb_usb_device_properties mxl111sf_mercury_tp_isoc_properties = { - MXL111SF_DEFAULT_DEVICE_PROPERTIES, - - .num_adapters = 1, - .adapter = { - { - .fe_ioctl_override = mxl111sf_fe_ioctl_override, - .num_frontends = 3, - .fe = {{ - .frontend_attach = mxl111sf_lgdt3305_frontend_attach, - .tuner_attach = mxl111sf_attach_tuner, - - MXL111SF_EP6_ISOC_STREAMING_CONFIG, - }, - { - .frontend_attach = mxl111sf_attach_demod, - .tuner_attach = mxl111sf_attach_tuner, - - MXL111SF_EP4_ISOC_STREAMING_CONFIG, - }, - { - .caps = DVB_USB_ADAP_RECEIVES_RAW_PAYLOAD, - - .frontend_attach = mxl111sf_lg2161_ep6_frontend_attach, - .tuner_attach = mxl111sf_attach_tuner, - - MXL111SF_EP6_ISOC_STREAMING_CONFIG, - }}, - }, - }, - .num_device_descs = 2, - .devices = { - { "Hauppauge Mercury (tp-isoc)", - { NULL }, - { &mxl111sf_table[19], &mxl111sf_table[21], - &mxl111sf_table[23], &mxl111sf_table[25], - &mxl111sf_table[27], NULL }, - }, - { "Hauppauge WinTV-Aero-M (tp-isoc)", - { NULL }, - { &mxl111sf_table[29], &mxl111sf_table[31], - NULL }, - }, - } -}; - -static -struct dvb_usb_device_properties mxl111sf_mercury_mh_tp_bulk_properties = { - MXL111SF_DEFAULT_DEVICE_PROPERTIES, - - .num_adapters = 1, - .adapter = { - { - .fe_ioctl_override = mxl111sf_fe_ioctl_override, - .num_frontends = 2, - .fe = {{ - .frontend_attach = mxl111sf_attach_demod, - .tuner_attach = mxl111sf_attach_tuner, - - MXL111SF_EP4_BULK_STREAMING_CONFIG, - }, - { - .caps = DVB_USB_ADAP_RECEIVES_RAW_PAYLOAD, - - .frontend_attach = mxl111sf_lg2161_ep6_frontend_attach, - .tuner_attach = mxl111sf_attach_tuner, - - MXL111SF_EP6_BULK_STREAMING_CONFIG, - }}, - }, - }, - .num_device_descs = 1, - .devices = { - { "Hauppauge 126xxx (tp-bulk)", - { NULL }, - { &mxl111sf_table[28], &mxl111sf_table[30], - NULL }, - }, - } -}; - -static -struct dvb_usb_device_properties mxl111sf_mercury_mh_tp_isoc_properties = { - MXL111SF_DEFAULT_DEVICE_PROPERTIES, - - .num_adapters = 1, - .adapter = { - { - .fe_ioctl_override = mxl111sf_fe_ioctl_override, - .num_frontends = 2, - .fe = {{ - .frontend_attach = mxl111sf_attach_demod, - .tuner_attach = mxl111sf_attach_tuner, - - MXL111SF_EP4_ISOC_STREAMING_CONFIG, - }, - { - .caps = DVB_USB_ADAP_RECEIVES_RAW_PAYLOAD, - - .frontend_attach = mxl111sf_lg2161_ep6_frontend_attach, - .tuner_attach = mxl111sf_attach_tuner, - - MXL111SF_EP6_ISOC_STREAMING_CONFIG, - }}, - }, - }, - .num_device_descs = 1, - .devices = { - { "Hauppauge 126xxx (tp-isoc)", - { NULL }, - { &mxl111sf_table[28], &mxl111sf_table[30], - NULL }, - }, - } -}; - -static -struct dvb_usb_device_properties mxl111sf_mercury_mh_spi_bulk_properties = { - MXL111SF_DEFAULT_DEVICE_PROPERTIES, - - .num_adapters = 1, - .adapter = { - { - .fe_ioctl_override = mxl111sf_fe_ioctl_override, - .num_frontends = 2, - .fe = {{ - .frontend_attach = mxl111sf_attach_demod, - .tuner_attach = mxl111sf_attach_tuner, - - MXL111SF_EP4_BULK_STREAMING_CONFIG, - }, - { - .caps = DVB_USB_ADAP_RECEIVES_RAW_PAYLOAD, - - .frontend_attach = mxl111sf_lg2161_frontend_attach, - .tuner_attach = mxl111sf_attach_tuner, - - MXL111SF_EP5_BULK_STREAMING_CONFIG, - }}, - }, - }, - .num_device_descs = 1, - .devices = { - { "Hauppauge 126xxx (spi-bulk)", - { NULL }, - { &mxl111sf_table[28], &mxl111sf_table[30], - NULL }, - }, - } -}; - -static -struct dvb_usb_device_properties mxl111sf_mercury_mh_spi_isoc_properties = { - MXL111SF_DEFAULT_DEVICE_PROPERTIES, - - .num_adapters = 1, - .adapter = { - { - .fe_ioctl_override = mxl111sf_fe_ioctl_override, - .num_frontends = 2, - .fe = {{ - .frontend_attach = mxl111sf_attach_demod, - .tuner_attach = mxl111sf_attach_tuner, - - MXL111SF_EP4_ISOC_STREAMING_CONFIG, - }, - { - .caps = DVB_USB_ADAP_RECEIVES_RAW_PAYLOAD, - - .frontend_attach = mxl111sf_lg2161_frontend_attach, - .tuner_attach = mxl111sf_attach_tuner, - - MXL111SF_EP5_ISOC_STREAMING_CONFIG, - }}, - }, - }, - .num_device_descs = 1, - .devices = { - { "Hauppauge 126xxx (spi-isoc)", - { NULL }, - { &mxl111sf_table[28], &mxl111sf_table[30], - NULL }, - }, - } -}; - -static struct usb_driver mxl111sf_driver = { - .name = "dvb_usb_mxl111sf", - .probe = mxl111sf_probe, - .disconnect = dvb_usb_device_exit, - .id_table = mxl111sf_table, -}; - -module_usb_driver(mxl111sf_driver); - -MODULE_AUTHOR("Michael Krufky <mkrufky@kernellabs.com>"); -MODULE_DESCRIPTION("Driver for MaxLinear MxL111SF"); -MODULE_VERSION("1.0"); -MODULE_LICENSE("GPL"); - -/* - * Local variables: - * c-basic-offset: 8 - * End: - */ diff --git a/drivers/media/dvb/frontends/ec100_priv.h b/drivers/media/dvb/frontends/ec100_priv.h deleted file mode 100644 index 5c990144bc47..000000000000 --- a/drivers/media/dvb/frontends/ec100_priv.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * E3C EC100 demodulator driver - * - * Copyright (C) 2009 Antti Palosaari <crope@iki.fi> - * - * 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 EC100_PRIV -#define EC100_PRIV - -#define LOG_PREFIX "ec100" - -#define dprintk(var, level, args...) \ - do { if ((var & level)) printk(args); } while (0) - -#define deb_info(args...) dprintk(ec100_debug, 0x01, args) - -#undef err -#define err(f, arg...) printk(KERN_ERR LOG_PREFIX": " f "\n" , ## arg) -#undef info -#define info(f, arg...) printk(KERN_INFO LOG_PREFIX": " f "\n" , ## arg) -#undef warn -#define warn(f, arg...) printk(KERN_WARNING LOG_PREFIX": " f "\n" , ## arg) - -#endif /* EC100_PRIV */ diff --git a/drivers/media/dvb/ngene/Kconfig b/drivers/media/dvb/ngene/Kconfig deleted file mode 100644 index 64c84702ba5c..000000000000 --- a/drivers/media/dvb/ngene/Kconfig +++ /dev/null @@ -1,13 +0,0 @@ -config DVB_NGENE - tristate "Micronas nGene support" - depends on DVB_CORE && PCI && I2C - select DVB_LNBP21 if !DVB_FE_CUSTOMISE - select DVB_STV6110x if !DVB_FE_CUSTOMISE - select DVB_STV090x if !DVB_FE_CUSTOMISE - select DVB_LGDT330X if !DVB_FE_CUSTOMISE - select DVB_DRXK if !DVB_FE_CUSTOMISE - select DVB_TDA18271C2DD if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_MT2131 if !MEDIA_TUNER_CUSTOMISE - ---help--- - Support for Micronas PCI express cards with nGene bridge. - diff --git a/drivers/media/dvb/pluto2/Makefile b/drivers/media/dvb/pluto2/Makefile deleted file mode 100644 index 700822350ec5..000000000000 --- a/drivers/media/dvb/pluto2/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -obj-$(CONFIG_DVB_PLUTO2) += pluto2.o - -ccflags-y += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/ diff --git a/drivers/media/dvb/siano/Kconfig b/drivers/media/dvb/siano/Kconfig deleted file mode 100644 index bc6456eb2c4f..000000000000 --- a/drivers/media/dvb/siano/Kconfig +++ /dev/null @@ -1,34 +0,0 @@ -# -# Siano Mobile Silicon Digital TV device configuration -# - -config SMS_SIANO_MDTV - tristate "Siano SMS1xxx based MDTV receiver" - depends on DVB_CORE && RC_CORE && HAS_DMA - ---help--- - Choose Y or M here if you have MDTV receiver with a Siano chipset. - - To compile this driver as a module, choose M here - (The module will be called smsmdtv). - - Further documentation on this driver can be found on the WWW - at http://www.siano-ms.com/ - -if SMS_SIANO_MDTV -menu "Siano module components" - -# Hardware interfaces support - -config SMS_USB_DRV - tristate "USB interface support" - depends on DVB_CORE && USB - ---help--- - Choose if you would like to have Siano's support for USB interface - -config SMS_SDIO_DRV - tristate "SDIO interface support" - depends on DVB_CORE && MMC - ---help--- - Choose if you would like to have Siano's support for SDIO interface -endmenu -endif # SMS_SIANO_MDTV diff --git a/drivers/media/dvb/ttusb-budget/Makefile b/drivers/media/dvb/ttusb-budget/Makefile deleted file mode 100644 index 8d6c4acb7f1d..000000000000 --- a/drivers/media/dvb/ttusb-budget/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -obj-$(CONFIG_DVB_TTUSB_BUDGET) += dvb-ttusb-budget.o - -ccflags-y += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends diff --git a/drivers/media/dvb/firewire/Kconfig b/drivers/media/firewire/Kconfig index f3e9448c3955..f3e9448c3955 100644 --- a/drivers/media/dvb/firewire/Kconfig +++ b/drivers/media/firewire/Kconfig diff --git a/drivers/media/dvb/firewire/Makefile b/drivers/media/firewire/Makefile index 357b3aab186b..239481344d7c 100644 --- a/drivers/media/dvb/firewire/Makefile +++ b/drivers/media/firewire/Makefile @@ -1,6 +1,6 @@ obj-$(CONFIG_DVB_FIREDTV) += firedtv.o -firedtv-y := firedtv-avc.o firedtv-ci.o firedtv-dvb.o firedtv-fe.o firedtv-fw.o +firedtv-y += firedtv-avc.o firedtv-ci.o firedtv-dvb.o firedtv-fe.o firedtv-fw.o firedtv-$(CONFIG_DVB_FIREDTV_INPUT) += firedtv-rc.o -ccflags-y += -Idrivers/media/dvb/dvb-core +ccflags-y += -Idrivers/media/dvb-core diff --git a/drivers/media/dvb/firewire/firedtv-avc.c b/drivers/media/firewire/firedtv-avc.c index d1a1a1324ef8..d1a1a1324ef8 100644 --- a/drivers/media/dvb/firewire/firedtv-avc.c +++ b/drivers/media/firewire/firedtv-avc.c diff --git a/drivers/media/dvb/firewire/firedtv-ci.c b/drivers/media/firewire/firedtv-ci.c index e5ebdbfe8c19..e5ebdbfe8c19 100644 --- a/drivers/media/dvb/firewire/firedtv-ci.c +++ b/drivers/media/firewire/firedtv-ci.c diff --git a/drivers/media/dvb/firewire/firedtv-dvb.c b/drivers/media/firewire/firedtv-dvb.c index eb7496eab130..eb7496eab130 100644 --- a/drivers/media/dvb/firewire/firedtv-dvb.c +++ b/drivers/media/firewire/firedtv-dvb.c diff --git a/drivers/media/dvb/firewire/firedtv-fe.c b/drivers/media/firewire/firedtv-fe.c index 6fe9793b98b3..6fe9793b98b3 100644 --- a/drivers/media/dvb/firewire/firedtv-fe.c +++ b/drivers/media/firewire/firedtv-fe.c diff --git a/drivers/media/dvb/firewire/firedtv-fw.c b/drivers/media/firewire/firedtv-fw.c index e24ec539a5fd..e24ec539a5fd 100644 --- a/drivers/media/dvb/firewire/firedtv-fw.c +++ b/drivers/media/firewire/firedtv-fw.c diff --git a/drivers/media/dvb/firewire/firedtv-rc.c b/drivers/media/firewire/firedtv-rc.c index f82d4a93feb3..f82d4a93feb3 100644 --- a/drivers/media/dvb/firewire/firedtv-rc.c +++ b/drivers/media/firewire/firedtv-rc.c diff --git a/drivers/media/dvb/firewire/firedtv.h b/drivers/media/firewire/firedtv.h index 4fdcd8cb7530..4fdcd8cb7530 100644 --- a/drivers/media/dvb/firewire/firedtv.h +++ b/drivers/media/firewire/firedtv.h diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig new file mode 100644 index 000000000000..24d78e28e493 --- /dev/null +++ b/drivers/media/i2c/Kconfig @@ -0,0 +1,591 @@ +# +# Generic video config states +# + +config VIDEO_BTCX + depends on PCI + tristate + +config VIDEO_TVEEPROM + tristate + depends on I2C + +# +# Multimedia Video device configuration +# + +if VIDEO_V4L2 + +config VIDEO_IR_I2C + tristate "I2C module for IR" if !MEDIA_SUBDRV_AUTOSELECT + depends on I2C && RC_CORE + default y + ---help--- + Most boards have an IR chip directly connected via GPIO. However, + some video boards have the IR connected via I2C bus. + + If your board doesn't have an I2C IR chip, you may disable this + option. + + In doubt, say Y. + +# +# Encoder / Decoder module configuration +# + +menu "Encoders, decoders, sensors and other helper chips" + visible if !MEDIA_SUBDRV_AUTOSELECT + +comment "Audio decoders, processors and mixers" + +config VIDEO_TVAUDIO + tristate "Simple audio decoder chips" + depends on VIDEO_V4L2 && I2C + ---help--- + Support for several audio decoder chips found on some bt8xx boards: + Philips: tda9840, tda9873h, tda9874h/a, tda9850, tda985x, tea6300, + tea6320, tea6420, tda8425, ta8874z. + Microchip: pic16c54 based design on ProVideo PV951 board. + + To compile this driver as a module, choose M here: the + module will be called tvaudio. + +config VIDEO_TDA7432 + tristate "Philips TDA7432 audio processor" + depends on VIDEO_V4L2 && I2C + ---help--- + Support for tda7432 audio decoder chip found on some bt8xx boards. + + To compile this driver as a module, choose M here: the + module will be called tda7432. + +config VIDEO_TDA9840 + tristate "Philips TDA9840 audio processor" + depends on I2C + ---help--- + Support for tda9840 audio decoder chip found on some Zoran boards. + + To compile this driver as a module, choose M here: the + module will be called tda9840. + +config VIDEO_TEA6415C + tristate "Philips TEA6415C audio processor" + depends on I2C + ---help--- + Support for tea6415c audio decoder chip found on some bt8xx boards. + + To compile this driver as a module, choose M here: the + module will be called tea6415c. + +config VIDEO_TEA6420 + tristate "Philips TEA6420 audio processor" + depends on I2C + ---help--- + Support for tea6420 audio decoder chip found on some bt8xx boards. + + To compile this driver as a module, choose M here: the + module will be called tea6420. + +config VIDEO_MSP3400 + tristate "Micronas MSP34xx audio decoders" + depends on VIDEO_V4L2 && I2C + ---help--- + Support for the Micronas MSP34xx series of audio decoders. + + To compile this driver as a module, choose M here: the + module will be called msp3400. + +config VIDEO_CS5345 + tristate "Cirrus Logic CS5345 audio ADC" + depends on VIDEO_V4L2 && I2C + ---help--- + Support for the Cirrus Logic CS5345 24-bit, 192 kHz + stereo A/D converter. + + To compile this driver as a module, choose M here: the + module will be called cs5345. + +config VIDEO_CS53L32A + tristate "Cirrus Logic CS53L32A audio ADC" + depends on VIDEO_V4L2 && I2C + ---help--- + Support for the Cirrus Logic CS53L32A low voltage + stereo A/D converter. + + To compile this driver as a module, choose M here: the + module will be called cs53l32a. + +config VIDEO_TLV320AIC23B + tristate "Texas Instruments TLV320AIC23B audio codec" + depends on VIDEO_V4L2 && I2C + ---help--- + Support for the Texas Instruments TLV320AIC23B audio codec. + + To compile this driver as a module, choose M here: the + module will be called tlv320aic23b. + +config VIDEO_WM8775 + tristate "Wolfson Microelectronics WM8775 audio ADC with input mixer" + depends on VIDEO_V4L2 && I2C + ---help--- + Support for the Wolfson Microelectronics WM8775 high + performance stereo A/D Converter with a 4 channel input mixer. + + To compile this driver as a module, choose M here: the + module will be called wm8775. + +config VIDEO_WM8739 + tristate "Wolfson Microelectronics WM8739 stereo audio ADC" + depends on VIDEO_V4L2 && I2C + ---help--- + Support for the Wolfson Microelectronics WM8739 + stereo A/D Converter. + + To compile this driver as a module, choose M here: the + module will be called wm8739. + +config VIDEO_VP27SMPX + tristate "Panasonic VP27s internal MPX" + depends on VIDEO_V4L2 && I2C + ---help--- + Support for the internal MPX of the Panasonic VP27s tuner. + + To compile this driver as a module, choose M here: the + module will be called vp27smpx. + +comment "RDS decoders" + +config VIDEO_SAA6588 + tristate "SAA6588 Radio Chip RDS decoder support" + depends on VIDEO_V4L2 && I2C + + help + Support for this Radio Data System (RDS) decoder. This allows + seeing radio station identification transmitted using this + standard. + + To compile this driver as a module, choose M here: the + module will be called saa6588. + +comment "Video decoders" + +config VIDEO_ADV7180 + tristate "Analog Devices ADV7180 decoder" + depends on VIDEO_V4L2 && I2C + ---help--- + Support for the Analog Devices ADV7180 video decoder. + + To compile this driver as a module, choose M here: the + module will be called adv7180. + +config VIDEO_ADV7183 + tristate "Analog Devices ADV7183 decoder" + depends on VIDEO_V4L2 && I2C + ---help--- + V4l2 subdevice driver for the Analog Devices + ADV7183 video decoder. + + To compile this driver as a module, choose M here: the + module will be called adv7183. + +config VIDEO_ADV7604 + tristate "Analog Devices ADV7604 decoder" + depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API + ---help--- + Support for the Analog Devices ADV7604 video decoder. + + This is a Analog Devices Component/Graphics Digitizer + with 4:1 Multiplexed HDMI Receiver. + + To compile this driver as a module, choose M here: the + module will be called adv7604. + +config VIDEO_BT819 + tristate "BT819A VideoStream decoder" + depends on VIDEO_V4L2 && I2C + ---help--- + Support for BT819A video decoder. + + To compile this driver as a module, choose M here: the + module will be called bt819. + +config VIDEO_BT856 + tristate "BT856 VideoStream decoder" + depends on VIDEO_V4L2 && I2C + ---help--- + Support for BT856 video decoder. + + To compile this driver as a module, choose M here: the + module will be called bt856. + +config VIDEO_BT866 + tristate "BT866 VideoStream decoder" + depends on VIDEO_V4L2 && I2C + ---help--- + Support for BT866 video decoder. + + To compile this driver as a module, choose M here: the + module will be called bt866. + +config VIDEO_KS0127 + tristate "KS0127 video decoder" + depends on VIDEO_V4L2 && I2C + ---help--- + Support for KS0127 video decoder. + + This chip is used on AverMedia AVS6EYES Zoran-based MJPEG + cards. + + To compile this driver as a module, choose M here: the + module will be called ks0127. + +config VIDEO_SAA7110 + tristate "Philips SAA7110 video decoder" + depends on VIDEO_V4L2 && I2C + ---help--- + Support for the Philips SAA7110 video decoders. + + To compile this driver as a module, choose M here: the + module will be called saa7110. + +config VIDEO_SAA711X + tristate "Philips SAA7111/3/4/5 video decoders" + depends on VIDEO_V4L2 && I2C + ---help--- + Support for the Philips SAA7111/3/4/5 video decoders. + + To compile this driver as a module, choose M here: the + module will be called saa7115. + +config VIDEO_SAA7191 + tristate "Philips SAA7191 video decoder" + depends on VIDEO_V4L2 && I2C + ---help--- + Support for the Philips SAA7191 video decoder. + + To compile this driver as a module, choose M here: the + module will be called saa7191. + +config VIDEO_TVP514X + tristate "Texas Instruments TVP514x video decoder" + depends on VIDEO_V4L2 && I2C + ---help--- + This is a Video4Linux2 sensor-level driver for the TI TVP5146/47 + decoder. It is currently working with the TI OMAP3 camera + controller. + + To compile this driver as a module, choose M here: the + module will be called tvp514x. + +config VIDEO_TVP5150 + tristate "Texas Instruments TVP5150 video decoder" + depends on VIDEO_V4L2 && I2C + ---help--- + Support for the Texas Instruments TVP5150 video decoder. + + To compile this driver as a module, choose M here: the + module will be called tvp5150. + +config VIDEO_TVP7002 + tristate "Texas Instruments TVP7002 video decoder" + depends on VIDEO_V4L2 && I2C + ---help--- + Support for the Texas Instruments TVP7002 video decoder. + + To compile this driver as a module, choose M here: the + module will be called tvp7002. + +config VIDEO_VPX3220 + tristate "vpx3220a, vpx3216b & vpx3214c video decoders" + depends on VIDEO_V4L2 && I2C + ---help--- + Support for VPX322x video decoders. + + To compile this driver as a module, choose M here: the + module will be called vpx3220. + +comment "Video and audio decoders" + +config VIDEO_SAA717X + tristate "Philips SAA7171/3/4 audio/video decoders" + depends on VIDEO_V4L2 && I2C + ---help--- + Support for the Philips SAA7171/3/4 audio/video decoders. + + To compile this driver as a module, choose M here: the + module will be called saa717x. + +source "drivers/media/i2c/cx25840/Kconfig" + +comment "MPEG video encoders" + +config VIDEO_CX2341X + tristate "Conexant CX2341x MPEG encoders" + depends on VIDEO_V4L2 + ---help--- + Support for the Conexant CX23416 MPEG encoders + and CX23415 MPEG encoder/decoders. + + This module currently supports the encoding functions only. + + To compile this driver as a module, choose M here: the + module will be called cx2341x. + +comment "Video encoders" + +config VIDEO_SAA7127 + tristate "Philips SAA7127/9 digital video encoders" + depends on VIDEO_V4L2 && I2C + ---help--- + Support for the Philips SAA7127/9 digital video encoders. + + To compile this driver as a module, choose M here: the + module will be called saa7127. + +config VIDEO_SAA7185 + tristate "Philips SAA7185 video encoder" + depends on VIDEO_V4L2 && I2C + ---help--- + Support for the Philips SAA7185 video encoder. + + To compile this driver as a module, choose M here: the + module will be called saa7185. + +config VIDEO_ADV7170 + tristate "Analog Devices ADV7170 video encoder" + depends on VIDEO_V4L2 && I2C + ---help--- + Support for the Analog Devices ADV7170 video encoder driver + + To compile this driver as a module, choose M here: the + module will be called adv7170. + +config VIDEO_ADV7175 + tristate "Analog Devices ADV7175 video encoder" + depends on VIDEO_V4L2 && I2C + ---help--- + Support for the Analog Devices ADV7175 video encoder driver + + To compile this driver as a module, choose M here: the + module will be called adv7175. + +config VIDEO_ADV7343 + tristate "ADV7343 video encoder" + depends on I2C + help + Support for Analog Devices I2C bus based ADV7343 encoder. + + To compile this driver as a module, choose M here: the + module will be called adv7343. + +config VIDEO_ADV7393 + tristate "ADV7393 video encoder" + depends on I2C + help + Support for Analog Devices I2C bus based ADV7393 encoder. + + To compile this driver as a module, choose M here: the + module will be called adv7393. + +config VIDEO_AD9389B + tristate "Analog Devices AD9389B encoder" + depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API + ---help--- + Support for the Analog Devices AD9389B video encoder. + + This is a Analog Devices HDMI transmitter. + + To compile this driver as a module, choose M here: the + module will be called ad9389b. + +config VIDEO_AK881X + tristate "AK8813/AK8814 video encoders" + depends on I2C + help + Video output driver for AKM AK8813 and AK8814 TV encoders + +comment "Camera sensor devices" + +config VIDEO_APTINA_PLL + tristate + +config VIDEO_SMIAPP_PLL + tristate + +config VIDEO_OV7670 + tristate "OmniVision OV7670 sensor support" + depends on I2C && VIDEO_V4L2 + depends on MEDIA_CAMERA_SUPPORT + ---help--- + This is a Video4Linux2 sensor-level driver for the OmniVision + OV7670 VGA camera. It currently only works with the M88ALP01 + controller. + +config VIDEO_VS6624 + tristate "ST VS6624 sensor support" + depends on VIDEO_V4L2 && I2C + depends on MEDIA_CAMERA_SUPPORT + ---help--- + This is a Video4Linux2 sensor-level driver for the ST VS6624 + camera. + + To compile this driver as a module, choose M here: the + module will be called vs6624. + +config VIDEO_MT9M032 + tristate "MT9M032 camera sensor support" + depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API + depends on MEDIA_CAMERA_SUPPORT + select VIDEO_APTINA_PLL + ---help--- + This driver supports MT9M032 camera sensors from Aptina, monochrome + models only. + +config VIDEO_MT9P031 + tristate "Aptina MT9P031 support" + depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API + depends on MEDIA_CAMERA_SUPPORT + select VIDEO_APTINA_PLL + ---help--- + This is a Video4Linux2 sensor-level driver for the Aptina + (Micron) mt9p031 5 Mpixel camera. + +config VIDEO_MT9T001 + tristate "Aptina MT9T001 support" + depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API + depends on MEDIA_CAMERA_SUPPORT + ---help--- + This is a Video4Linux2 sensor-level driver for the Aptina + (Micron) mt0t001 3 Mpixel camera. + +config VIDEO_MT9V011 + tristate "Micron mt9v011 sensor support" + depends on I2C && VIDEO_V4L2 + depends on MEDIA_CAMERA_SUPPORT + ---help--- + This is a Video4Linux2 sensor-level driver for the Micron + mt0v011 1.3 Mpixel camera. It currently only works with the + em28xx driver. + +config VIDEO_MT9V032 + tristate "Micron MT9V032 sensor support" + depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API + depends on MEDIA_CAMERA_SUPPORT + ---help--- + This is a Video4Linux2 sensor-level driver for the Micron + MT9V032 752x480 CMOS sensor. + +config VIDEO_TCM825X + tristate "TCM825x camera sensor support" + depends on I2C && VIDEO_V4L2 + depends on MEDIA_CAMERA_SUPPORT + ---help--- + This is a driver for the Toshiba TCM825x VGA camera sensor. + It is used for example in Nokia N800. + +config VIDEO_SR030PC30 + tristate "Siliconfile SR030PC30 sensor support" + depends on I2C && VIDEO_V4L2 + depends on MEDIA_CAMERA_SUPPORT + ---help--- + This driver supports SR030PC30 VGA camera from Siliconfile + +config VIDEO_NOON010PC30 + tristate "Siliconfile NOON010PC30 sensor support" + depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API + depends on MEDIA_CAMERA_SUPPORT + ---help--- + This driver supports NOON010PC30 CIF camera from Siliconfile + +source "drivers/media/i2c/m5mols/Kconfig" + +config VIDEO_S5K6AA + tristate "Samsung S5K6AAFX sensor support" + depends on MEDIA_CAMERA_SUPPORT + depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API + ---help--- + This is a V4L2 sensor-level driver for Samsung S5K6AA(FX) 1.3M + camera sensor with an embedded SoC image signal processor. + +config VIDEO_S5K4ECGX + tristate "Samsung S5K4ECGX sensor support" + depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API + ---help--- + This is a V4L2 sensor-level driver for Samsung S5K4ECGX 5M + camera sensor with an embedded SoC image signal processor. + +source "drivers/media/i2c/smiapp/Kconfig" + +comment "Flash devices" + +config VIDEO_ADP1653 + tristate "ADP1653 flash support" + depends on I2C && VIDEO_V4L2 && MEDIA_CONTROLLER + depends on MEDIA_CAMERA_SUPPORT + ---help--- + This is a driver for the ADP1653 flash controller. It is used for + example in Nokia N900. + +config VIDEO_AS3645A + tristate "AS3645A flash driver support" + depends on I2C && VIDEO_V4L2 && MEDIA_CONTROLLER + depends on MEDIA_CAMERA_SUPPORT + ---help--- + This is a driver for the AS3645A and LM3555 flash controllers. It has + build in control for flash, torch and indicator LEDs. + +comment "Video improvement chips" + +config VIDEO_UPD64031A + tristate "NEC Electronics uPD64031A Ghost Reduction" + depends on VIDEO_V4L2 && I2C + ---help--- + Support for the NEC Electronics uPD64031A Ghost Reduction + video chip. It is most often found in NTSC TV cards made for + Japan and is used to reduce the 'ghosting' effect that can + be present in analog TV broadcasts. + + To compile this driver as a module, choose M here: the + module will be called upd64031a. + +config VIDEO_UPD64083 + tristate "NEC Electronics uPD64083 3-Dimensional Y/C separation" + depends on VIDEO_V4L2 && I2C + ---help--- + Support for the NEC Electronics uPD64083 3-Dimensional Y/C + separation video chip. It is used to improve the quality of + the colors of a composite signal. + + To compile this driver as a module, choose M here: the + module will be called upd64083. + +comment "Miscelaneous helper chips" + +config VIDEO_THS7303 + tristate "THS7303 Video Amplifier" + depends on I2C + help + Support for TI THS7303 video amplifier + + To compile this driver as a module, choose M here: the + module will be called ths7303. + +config VIDEO_M52790 + tristate "Mitsubishi M52790 A/V switch" + depends on VIDEO_V4L2 && I2C + ---help--- + Support for the Mitsubishi M52790 A/V switch. + + To compile this driver as a module, choose M here: the + module will be called m52790. +endmenu + +menu "Sensors used on soc_camera driver" + +if SOC_CAMERA + source "drivers/media/i2c/soc_camera/Kconfig" +endif + +endmenu + +endif diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile new file mode 100644 index 000000000000..b1d62dfd49b8 --- /dev/null +++ b/drivers/media/i2c/Makefile @@ -0,0 +1,67 @@ +msp3400-objs := msp3400-driver.o msp3400-kthreads.o +obj-$(CONFIG_VIDEO_MSP3400) += msp3400.o + +obj-$(CONFIG_VIDEO_SMIAPP) += smiapp/ +obj-$(CONFIG_VIDEO_CX25840) += cx25840/ +obj-$(CONFIG_VIDEO_M5MOLS) += m5mols/ +obj-y += soc_camera/ + +obj-$(CONFIG_VIDEO_APTINA_PLL) += aptina-pll.o +obj-$(CONFIG_VIDEO_TVAUDIO) += tvaudio.o +obj-$(CONFIG_VIDEO_TDA7432) += tda7432.o +obj-$(CONFIG_VIDEO_SAA6588) += saa6588.o +obj-$(CONFIG_VIDEO_TDA9840) += tda9840.o +obj-$(CONFIG_VIDEO_TEA6415C) += tea6415c.o +obj-$(CONFIG_VIDEO_TEA6420) += tea6420.o +obj-$(CONFIG_VIDEO_SAA7110) += saa7110.o +obj-$(CONFIG_VIDEO_SAA711X) += saa7115.o +obj-$(CONFIG_VIDEO_SAA717X) += saa717x.o +obj-$(CONFIG_VIDEO_SAA7127) += saa7127.o +obj-$(CONFIG_VIDEO_SAA7185) += saa7185.o +obj-$(CONFIG_VIDEO_SAA7191) += saa7191.o +obj-$(CONFIG_VIDEO_ADV7170) += adv7170.o +obj-$(CONFIG_VIDEO_ADV7175) += adv7175.o +obj-$(CONFIG_VIDEO_ADV7180) += adv7180.o +obj-$(CONFIG_VIDEO_ADV7183) += adv7183.o +obj-$(CONFIG_VIDEO_ADV7343) += adv7343.o +obj-$(CONFIG_VIDEO_ADV7393) += adv7393.o +obj-$(CONFIG_VIDEO_ADV7604) += adv7604.o +obj-$(CONFIG_VIDEO_AD9389B) += ad9389b.o +obj-$(CONFIG_VIDEO_VPX3220) += vpx3220.o +obj-$(CONFIG_VIDEO_VS6624) += vs6624.o +obj-$(CONFIG_VIDEO_BT819) += bt819.o +obj-$(CONFIG_VIDEO_BT856) += bt856.o +obj-$(CONFIG_VIDEO_BT866) += bt866.o +obj-$(CONFIG_VIDEO_KS0127) += ks0127.o +obj-$(CONFIG_VIDEO_THS7303) += ths7303.o +obj-$(CONFIG_VIDEO_TVP5150) += tvp5150.o +obj-$(CONFIG_VIDEO_TVP514X) += tvp514x.o +obj-$(CONFIG_VIDEO_TVP7002) += tvp7002.o +obj-$(CONFIG_VIDEO_CS5345) += cs5345.o +obj-$(CONFIG_VIDEO_CS53L32A) += cs53l32a.o +obj-$(CONFIG_VIDEO_M52790) += m52790.o +obj-$(CONFIG_VIDEO_TLV320AIC23B) += tlv320aic23b.o +obj-$(CONFIG_VIDEO_WM8775) += wm8775.o +obj-$(CONFIG_VIDEO_WM8739) += wm8739.o +obj-$(CONFIG_VIDEO_VP27SMPX) += vp27smpx.o +obj-$(CONFIG_VIDEO_UPD64031A) += upd64031a.o +obj-$(CONFIG_VIDEO_UPD64083) += upd64083.o +obj-$(CONFIG_VIDEO_OV7670) += ov7670.o +obj-$(CONFIG_VIDEO_TCM825X) += tcm825x.o +obj-$(CONFIG_VIDEO_TVEEPROM) += tveeprom.o +obj-$(CONFIG_VIDEO_MT9M032) += mt9m032.o +obj-$(CONFIG_VIDEO_MT9P031) += mt9p031.o +obj-$(CONFIG_VIDEO_MT9T001) += mt9t001.o +obj-$(CONFIG_VIDEO_MT9V011) += mt9v011.o +obj-$(CONFIG_VIDEO_MT9V032) += mt9v032.o +obj-$(CONFIG_VIDEO_SR030PC30) += sr030pc30.o +obj-$(CONFIG_VIDEO_NOON010PC30) += noon010pc30.o +obj-$(CONFIG_VIDEO_S5K6AA) += s5k6aa.o +obj-$(CONFIG_VIDEO_S5K4ECGX) += s5k4ecgx.o +obj-$(CONFIG_VIDEO_ADP1653) += adp1653.o +obj-$(CONFIG_VIDEO_AS3645A) += as3645a.o +obj-$(CONFIG_VIDEO_SMIAPP_PLL) += smiapp-pll.o +obj-$(CONFIG_VIDEO_BTCX) += btcx-risc.o +obj-$(CONFIG_VIDEO_CX2341X) += cx2341x.o +obj-$(CONFIG_VIDEO_AK881X) += ak881x.o +obj-$(CONFIG_VIDEO_IR_I2C) += ir-kbd-i2c.o diff --git a/drivers/media/i2c/ad9389b.c b/drivers/media/i2c/ad9389b.c new file mode 100644 index 000000000000..c2886b6a727d --- /dev/null +++ b/drivers/media/i2c/ad9389b.c @@ -0,0 +1,1328 @@ +/* + * Analog Devices AD9389B/AD9889B video encoder driver + * + * Copyright 2012 Cisco Systems, Inc. and/or its affiliates. All rights reserved. + * + * This program is free software; you may redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* + * References (c = chapter, p = page): + * REF_01 - Analog Devices, Programming Guide, AD9889B/AD9389B, + * HDMI Transitter, Rev. A, October 2010 + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/slab.h> +#include <linux/i2c.h> +#include <linux/delay.h> +#include <linux/videodev2.h> +#include <linux/workqueue.h> +#include <linux/v4l2-dv-timings.h> +#include <media/v4l2-device.h> +#include <media/v4l2-chip-ident.h> +#include <media/v4l2-common.h> +#include <media/v4l2-ctrls.h> +#include <media/ad9389b.h> + +static int debug; +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "debug level (0-2)"); + +MODULE_DESCRIPTION("Analog Devices AD9389B/AD9889B video encoder driver"); +MODULE_AUTHOR("Hans Verkuil <hans.verkuil@cisco.com>"); +MODULE_AUTHOR("Martin Bugge <marbugge@cisco.com>"); +MODULE_LICENSE("GPL"); + +#define MASK_AD9389B_EDID_RDY_INT 0x04 +#define MASK_AD9389B_MSEN_INT 0x40 +#define MASK_AD9389B_HPD_INT 0x80 + +#define MASK_AD9389B_HPD_DETECT 0x40 +#define MASK_AD9389B_MSEN_DETECT 0x20 +#define MASK_AD9389B_EDID_RDY 0x10 + +#define EDID_MAX_RETRIES (8) +#define EDID_DELAY 250 +#define EDID_MAX_SEGM 8 + +/* +********************************************************************** +* +* Arrays with configuration parameters for the AD9389B +* +********************************************************************** +*/ + +struct i2c_reg_value { + u8 reg; + u8 value; +}; + +struct ad9389b_state_edid { + /* total number of blocks */ + u32 blocks; + /* Number of segments read */ + u32 segments; + u8 data[EDID_MAX_SEGM * 256]; + /* Number of EDID read retries left */ + unsigned read_retries; +}; + +struct ad9389b_state { + struct ad9389b_platform_data pdata; + struct v4l2_subdev sd; + struct media_pad pad; + struct v4l2_ctrl_handler hdl; + int chip_revision; + /* Is the ad9389b powered on? */ + bool power_on; + /* Did we receive hotplug and rx-sense signals? */ + bool have_monitor; + /* timings from s_dv_timings */ + struct v4l2_dv_timings dv_timings; + /* controls */ + struct v4l2_ctrl *hdmi_mode_ctrl; + struct v4l2_ctrl *hotplug_ctrl; + struct v4l2_ctrl *rx_sense_ctrl; + struct v4l2_ctrl *have_edid0_ctrl; + struct v4l2_ctrl *rgb_quantization_range_ctrl; + struct i2c_client *edid_i2c_client; + struct ad9389b_state_edid edid; + /* Running counter of the number of detected EDIDs (for debugging) */ + unsigned edid_detect_counter; + struct workqueue_struct *work_queue; + struct delayed_work edid_handler; /* work entry */ +}; + +static void ad9389b_check_monitor_present_status(struct v4l2_subdev *sd); +static bool ad9389b_check_edid_status(struct v4l2_subdev *sd); +static void ad9389b_setup(struct v4l2_subdev *sd); +static int ad9389b_s_i2s_clock_freq(struct v4l2_subdev *sd, u32 freq); +static int ad9389b_s_clock_freq(struct v4l2_subdev *sd, u32 freq); + +static inline struct ad9389b_state *get_ad9389b_state(struct v4l2_subdev *sd) +{ + return container_of(sd, struct ad9389b_state, sd); +} + +static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl) +{ + return &container_of(ctrl->handler, struct ad9389b_state, hdl)->sd; +} + +/* ------------------------ I2C ----------------------------------------------- */ + +static int ad9389b_rd(struct v4l2_subdev *sd, u8 reg) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + + return i2c_smbus_read_byte_data(client, reg); +} + +static int ad9389b_wr(struct v4l2_subdev *sd, u8 reg, u8 val) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + int ret; + int i; + + for (i = 0; i < 3; i++) { + ret = i2c_smbus_write_byte_data(client, reg, val); + if (ret == 0) + return 0; + } + v4l2_err(sd, "I2C Write Problem\n"); + return ret; +} + +/* To set specific bits in the register, a clear-mask is given (to be AND-ed), + and then the value-mask (to be OR-ed). */ +static inline void ad9389b_wr_and_or(struct v4l2_subdev *sd, u8 reg, + u8 clr_mask, u8 val_mask) +{ + ad9389b_wr(sd, reg, (ad9389b_rd(sd, reg) & clr_mask) | val_mask); +} + +static void ad9389b_edid_rd(struct v4l2_subdev *sd, u16 len, u8 *buf) +{ + struct ad9389b_state *state = get_ad9389b_state(sd); + int i; + + v4l2_dbg(1, debug, sd, "%s:\n", __func__); + + for (i = 0; i < len; i++) + buf[i] = i2c_smbus_read_byte_data(state->edid_i2c_client, i); +} + +static inline bool ad9389b_have_hotplug(struct v4l2_subdev *sd) +{ + return ad9389b_rd(sd, 0x42) & MASK_AD9389B_HPD_DETECT; +} + +static inline bool ad9389b_have_rx_sense(struct v4l2_subdev *sd) +{ + return ad9389b_rd(sd, 0x42) & MASK_AD9389B_MSEN_DETECT; +} + +static void ad9389b_csc_conversion_mode(struct v4l2_subdev *sd, u8 mode) +{ + ad9389b_wr_and_or(sd, 0x17, 0xe7, (mode & 0x3)<<3); + ad9389b_wr_and_or(sd, 0x18, 0x9f, (mode & 0x3)<<5); +} + +static void ad9389b_csc_coeff(struct v4l2_subdev *sd, + u16 A1, u16 A2, u16 A3, u16 A4, + u16 B1, u16 B2, u16 B3, u16 B4, + u16 C1, u16 C2, u16 C3, u16 C4) +{ + /* A */ + ad9389b_wr_and_or(sd, 0x18, 0xe0, A1>>8); + ad9389b_wr(sd, 0x19, A1); + ad9389b_wr_and_or(sd, 0x1A, 0xe0, A2>>8); + ad9389b_wr(sd, 0x1B, A2); + ad9389b_wr_and_or(sd, 0x1c, 0xe0, A3>>8); + ad9389b_wr(sd, 0x1d, A3); + ad9389b_wr_and_or(sd, 0x1e, 0xe0, A4>>8); + ad9389b_wr(sd, 0x1f, A4); + + /* B */ + ad9389b_wr_and_or(sd, 0x20, 0xe0, B1>>8); + ad9389b_wr(sd, 0x21, B1); + ad9389b_wr_and_or(sd, 0x22, 0xe0, B2>>8); + ad9389b_wr(sd, 0x23, B2); + ad9389b_wr_and_or(sd, 0x24, 0xe0, B3>>8); + ad9389b_wr(sd, 0x25, B3); + ad9389b_wr_and_or(sd, 0x26, 0xe0, B4>>8); + ad9389b_wr(sd, 0x27, B4); + + /* C */ + ad9389b_wr_and_or(sd, 0x28, 0xe0, C1>>8); + ad9389b_wr(sd, 0x29, C1); + ad9389b_wr_and_or(sd, 0x2A, 0xe0, C2>>8); + ad9389b_wr(sd, 0x2B, C2); + ad9389b_wr_and_or(sd, 0x2C, 0xe0, C3>>8); + ad9389b_wr(sd, 0x2D, C3); + ad9389b_wr_and_or(sd, 0x2E, 0xe0, C4>>8); + ad9389b_wr(sd, 0x2F, C4); +} + +static void ad9389b_csc_rgb_full2limit(struct v4l2_subdev *sd, bool enable) +{ + if (enable) { + u8 csc_mode = 0; + + ad9389b_csc_conversion_mode(sd, csc_mode); + ad9389b_csc_coeff(sd, + 4096-564, 0, 0, 256, + 0, 4096-564, 0, 256, + 0, 0, 4096-564, 256); + /* enable CSC */ + ad9389b_wr_and_or(sd, 0x3b, 0xfe, 0x1); + /* AVI infoframe: Limited range RGB (16-235) */ + ad9389b_wr_and_or(sd, 0xcd, 0xf9, 0x02); + } else { + /* disable CSC */ + ad9389b_wr_and_or(sd, 0x3b, 0xfe, 0x0); + /* AVI infoframe: Full range RGB (0-255) */ + ad9389b_wr_and_or(sd, 0xcd, 0xf9, 0x04); + } +} + +static void ad9389b_set_IT_content_AVI_InfoFrame(struct v4l2_subdev *sd) +{ + struct ad9389b_state *state = get_ad9389b_state(sd); + + if (state->dv_timings.bt.standards & V4L2_DV_BT_STD_CEA861) { + /* CEA format, not IT */ + ad9389b_wr_and_or(sd, 0xcd, 0xbf, 0x00); + } else { + /* IT format */ + ad9389b_wr_and_or(sd, 0xcd, 0xbf, 0x40); + } +} + +static int ad9389b_set_rgb_quantization_mode(struct v4l2_subdev *sd, struct v4l2_ctrl *ctrl) +{ + struct ad9389b_state *state = get_ad9389b_state(sd); + + switch (ctrl->val) { + case V4L2_DV_RGB_RANGE_AUTO: + /* automatic */ + if (state->dv_timings.bt.standards & V4L2_DV_BT_STD_CEA861) { + /* cea format, RGB limited range (16-235) */ + ad9389b_csc_rgb_full2limit(sd, true); + } else { + /* not cea format, RGB full range (0-255) */ + ad9389b_csc_rgb_full2limit(sd, false); + } + break; + case V4L2_DV_RGB_RANGE_LIMITED: + /* RGB limited range (16-235) */ + ad9389b_csc_rgb_full2limit(sd, true); + break; + case V4L2_DV_RGB_RANGE_FULL: + /* RGB full range (0-255) */ + ad9389b_csc_rgb_full2limit(sd, false); + break; + default: + return -EINVAL; + } + return 0; +} + +static void ad9389b_set_manual_pll_gear(struct v4l2_subdev *sd, u32 pixelclock) +{ + u8 gear; + + /* Workaround for TMDS PLL problem + * The TMDS PLL in AD9389b change gear when the chip is heated above a + * certain temperature. The output is disabled when the PLL change gear + * so the monitor has to lock on the signal again. A workaround for + * this is to use the manual PLL gears. This is a solution from Analog + * Devices that is not documented in the datasheets. + * 0x98 [7] = enable manual gearing. 0x98 [6:4] = gear + * + * The pixel frequency ranges are based on readout of the gear the + * automatic gearing selects for different pixel clocks + * (read from 0x9e [3:1]). + */ + + if (pixelclock > 140000000) + gear = 0xc0; /* 4th gear */ + else if (pixelclock > 117000000) + gear = 0xb0; /* 3rd gear */ + else if (pixelclock > 87000000) + gear = 0xa0; /* 2nd gear */ + else if (pixelclock > 60000000) + gear = 0x90; /* 1st gear */ + else + gear = 0x80; /* 0th gear */ + + ad9389b_wr_and_or(sd, 0x98, 0x0f, gear); +} + +/* ------------------------------ CTRL OPS ------------------------------ */ + +static int ad9389b_s_ctrl(struct v4l2_ctrl *ctrl) +{ + struct v4l2_subdev *sd = to_sd(ctrl); + struct ad9389b_state *state = get_ad9389b_state(sd); + + v4l2_dbg(1, debug, sd, + "%s: ctrl id: %d, ctrl->val %d\n", __func__, ctrl->id, ctrl->val); + + if (state->hdmi_mode_ctrl == ctrl) { + /* Set HDMI or DVI-D */ + ad9389b_wr_and_or(sd, 0xaf, 0xfd, + ctrl->val == V4L2_DV_TX_MODE_HDMI ? 0x02 : 0x00); + return 0; + } + if (state->rgb_quantization_range_ctrl == ctrl) + return ad9389b_set_rgb_quantization_mode(sd, ctrl); + return -EINVAL; +} + +static const struct v4l2_ctrl_ops ad9389b_ctrl_ops = { + .s_ctrl = ad9389b_s_ctrl, +}; + +/* ---------------------------- CORE OPS ------------------------------------------- */ + +#ifdef CONFIG_VIDEO_ADV_DEBUG +static int ad9389b_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + + if (!v4l2_chip_match_i2c_client(client, ®->match)) + return -EINVAL; + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + reg->val = ad9389b_rd(sd, reg->reg & 0xff); + reg->size = 1; + return 0; +} + +static int ad9389b_s_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + + if (!v4l2_chip_match_i2c_client(client, ®->match)) + return -EINVAL; + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + ad9389b_wr(sd, reg->reg & 0xff, reg->val & 0xff); + return 0; +} +#endif + +static int ad9389b_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + + return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_AD9389B, 0); +} + +static int ad9389b_log_status(struct v4l2_subdev *sd) +{ + struct ad9389b_state *state = get_ad9389b_state(sd); + struct ad9389b_state_edid *edid = &state->edid; + + static const char * const states[] = { + "in reset", + "reading EDID", + "idle", + "initializing HDCP", + "HDCP enabled", + "initializing HDCP repeater", + "6", "7", "8", "9", "A", "B", "C", "D", "E", "F" + }; + static const char * const errors[] = { + "no error", + "bad receiver BKSV", + "Ri mismatch", + "Pj mismatch", + "i2c error", + "timed out", + "max repeater cascade exceeded", + "hash check failed", + "too many devices", + "9", "A", "B", "C", "D", "E", "F" + }; + + u8 manual_gear; + + v4l2_info(sd, "chip revision %d\n", state->chip_revision); + v4l2_info(sd, "power %s\n", state->power_on ? "on" : "off"); + v4l2_info(sd, "%s hotplug, %s Rx Sense, %s EDID (%d block(s))\n", + (ad9389b_rd(sd, 0x42) & MASK_AD9389B_HPD_DETECT) ? + "detected" : "no", + (ad9389b_rd(sd, 0x42) & MASK_AD9389B_MSEN_DETECT) ? + "detected" : "no", + edid->segments ? "found" : "no", edid->blocks); + if (state->have_monitor) { + v4l2_info(sd, "%s output %s\n", + (ad9389b_rd(sd, 0xaf) & 0x02) ? + "HDMI" : "DVI-D", + (ad9389b_rd(sd, 0xa1) & 0x3c) ? + "disabled" : "enabled"); + } + v4l2_info(sd, "ad9389b: %s\n", (ad9389b_rd(sd, 0xb8) & 0x40) ? + "encrypted" : "no encryption"); + v4l2_info(sd, "state: %s, error: %s, detect count: %u, msk/irq: %02x/%02x\n", + states[ad9389b_rd(sd, 0xc8) & 0xf], + errors[ad9389b_rd(sd, 0xc8) >> 4], + state->edid_detect_counter, + ad9389b_rd(sd, 0x94), ad9389b_rd(sd, 0x96)); + manual_gear = ad9389b_rd(sd, 0x98) & 0x80; + v4l2_info(sd, "ad9389b: RGB quantization: %s range\n", + ad9389b_rd(sd, 0x3b) & 0x01 ? "limited" : "full"); + v4l2_info(sd, "ad9389b: %s gear %d\n", + manual_gear ? "manual" : "automatic", + manual_gear ? ((ad9389b_rd(sd, 0x98) & 0x70) >> 4) : + ((ad9389b_rd(sd, 0x9e) & 0x0e) >> 1)); + if (state->have_monitor) { + if (ad9389b_rd(sd, 0xaf) & 0x02) { + /* HDMI only */ + u8 manual_cts = ad9389b_rd(sd, 0x0a) & 0x80; + u32 N = (ad9389b_rd(sd, 0x01) & 0xf) << 16 | + ad9389b_rd(sd, 0x02) << 8 | + ad9389b_rd(sd, 0x03); + u8 vic_detect = ad9389b_rd(sd, 0x3e) >> 2; + u8 vic_sent = ad9389b_rd(sd, 0x3d) & 0x3f; + u32 CTS; + + if (manual_cts) + CTS = (ad9389b_rd(sd, 0x07) & 0xf) << 16 | + ad9389b_rd(sd, 0x08) << 8 | + ad9389b_rd(sd, 0x09); + else + CTS = (ad9389b_rd(sd, 0x04) & 0xf) << 16 | + ad9389b_rd(sd, 0x05) << 8 | + ad9389b_rd(sd, 0x06); + N = (ad9389b_rd(sd, 0x01) & 0xf) << 16 | + ad9389b_rd(sd, 0x02) << 8 | + ad9389b_rd(sd, 0x03); + + v4l2_info(sd, "ad9389b: CTS %s mode: N %d, CTS %d\n", + manual_cts ? "manual" : "automatic", N, CTS); + + v4l2_info(sd, "ad9389b: VIC: detected %d, sent %d\n", + vic_detect, vic_sent); + } + } + if (state->dv_timings.type == V4L2_DV_BT_656_1120) { + struct v4l2_bt_timings *bt = bt = &state->dv_timings.bt; + u32 frame_width = bt->width + bt->hfrontporch + + bt->hsync + bt->hbackporch; + u32 frame_height = bt->height + bt->vfrontporch + + bt->vsync + bt->vbackporch; + u32 frame_size = frame_width * frame_height; + + v4l2_info(sd, "timings: %ux%u%s%u (%ux%u). Pix freq. = %u Hz. Polarities = 0x%x\n", + bt->width, bt->height, bt->interlaced ? "i" : "p", + frame_size > 0 ? (unsigned)bt->pixelclock / frame_size : 0, + frame_width, frame_height, + (unsigned)bt->pixelclock, bt->polarities); + } else { + v4l2_info(sd, "no timings set\n"); + } + return 0; +} + +/* Power up/down ad9389b */ +static int ad9389b_s_power(struct v4l2_subdev *sd, int on) +{ + struct ad9389b_state *state = get_ad9389b_state(sd); + struct ad9389b_platform_data *pdata = &state->pdata; + const int retries = 20; + int i; + + v4l2_dbg(1, debug, sd, "%s: power %s\n", __func__, on ? "on" : "off"); + + state->power_on = on; + + if (!on) { + /* Power down */ + ad9389b_wr_and_or(sd, 0x41, 0xbf, 0x40); + return true; + } + + /* Power up */ + /* The ad9389b does not always come up immediately. + Retry multiple times. */ + for (i = 0; i < retries; i++) { + ad9389b_wr_and_or(sd, 0x41, 0xbf, 0x0); + if ((ad9389b_rd(sd, 0x41) & 0x40) == 0) + break; + ad9389b_wr_and_or(sd, 0x41, 0xbf, 0x40); + msleep(10); + } + if (i == retries) { + v4l2_dbg(1, debug, sd, "failed to powerup the ad9389b\n"); + ad9389b_s_power(sd, 0); + return false; + } + if (i > 1) + v4l2_dbg(1, debug, sd, + "needed %d retries to powerup the ad9389b\n", i); + + /* Select chip: AD9389B */ + ad9389b_wr_and_or(sd, 0xba, 0xef, 0x10); + + /* Reserved registers that must be set according to REF_01 p. 11*/ + ad9389b_wr_and_or(sd, 0x98, 0xf0, 0x07); + ad9389b_wr(sd, 0x9c, 0x38); + ad9389b_wr_and_or(sd, 0x9d, 0xfc, 0x01); + + /* Differential output drive strength */ + if (pdata->diff_data_drive_strength > 0) + ad9389b_wr(sd, 0xa2, pdata->diff_data_drive_strength); + else + ad9389b_wr(sd, 0xa2, 0x87); + + if (pdata->diff_clk_drive_strength > 0) + ad9389b_wr(sd, 0xa3, pdata->diff_clk_drive_strength); + else + ad9389b_wr(sd, 0xa3, 0x87); + + ad9389b_wr(sd, 0x0a, 0x01); + ad9389b_wr(sd, 0xbb, 0xff); + + /* Set number of attempts to read the EDID */ + ad9389b_wr(sd, 0xc9, 0xf); + return true; +} + +/* Enable interrupts */ +static void ad9389b_set_isr(struct v4l2_subdev *sd, bool enable) +{ + u8 irqs = MASK_AD9389B_HPD_INT | MASK_AD9389B_MSEN_INT; + u8 irqs_rd; + int retries = 100; + + /* The datasheet says that the EDID ready interrupt should be + disabled if there is no hotplug. */ + if (!enable) + irqs = 0; + else if (ad9389b_have_hotplug(sd)) + irqs |= MASK_AD9389B_EDID_RDY_INT; + + /* + * This i2c write can fail (approx. 1 in 1000 writes). But it + * is essential that this register is correct, so retry it + * multiple times. + * + * Note that the i2c write does not report an error, but the readback + * clearly shows the wrong value. + */ + do { + ad9389b_wr(sd, 0x94, irqs); + irqs_rd = ad9389b_rd(sd, 0x94); + } while (retries-- && irqs_rd != irqs); + + if (irqs_rd != irqs) + v4l2_err(sd, "Could not set interrupts: hw failure?\n"); +} + +/* Interrupt handler */ +static int ad9389b_isr(struct v4l2_subdev *sd, u32 status, bool *handled) +{ + u8 irq_status; + + /* disable interrupts to prevent a race condition */ + ad9389b_set_isr(sd, false); + irq_status = ad9389b_rd(sd, 0x96); + /* clear detected interrupts */ + ad9389b_wr(sd, 0x96, irq_status); + + if (irq_status & (MASK_AD9389B_HPD_INT | MASK_AD9389B_MSEN_INT)) + ad9389b_check_monitor_present_status(sd); + if (irq_status & MASK_AD9389B_EDID_RDY_INT) + ad9389b_check_edid_status(sd); + + /* enable interrupts */ + ad9389b_set_isr(sd, true); + *handled = true; + return 0; +} + +static const struct v4l2_subdev_core_ops ad9389b_core_ops = { + .log_status = ad9389b_log_status, + .g_chip_ident = ad9389b_g_chip_ident, +#ifdef CONFIG_VIDEO_ADV_DEBUG + .g_register = ad9389b_g_register, + .s_register = ad9389b_s_register, +#endif + .s_power = ad9389b_s_power, + .interrupt_service_routine = ad9389b_isr, +}; + +/* ------------------------------ PAD OPS ------------------------------ */ + +static int ad9389b_get_edid(struct v4l2_subdev *sd, struct v4l2_subdev_edid *edid) +{ + struct ad9389b_state *state = get_ad9389b_state(sd); + + if (edid->pad != 0) + return -EINVAL; + if (edid->blocks == 0 || edid->blocks > 256) + return -EINVAL; + if (!edid->edid) + return -EINVAL; + if (!state->edid.segments) { + v4l2_dbg(1, debug, sd, "EDID segment 0 not found\n"); + return -ENODATA; + } + if (edid->start_block >= state->edid.segments * 2) + return -E2BIG; + if (edid->blocks + edid->start_block >= state->edid.segments * 2) + edid->blocks = state->edid.segments * 2 - edid->start_block; + memcpy(edid->edid, &state->edid.data[edid->start_block * 128], + 128 * edid->blocks); + return 0; +} + +static const struct v4l2_subdev_pad_ops ad9389b_pad_ops = { + .get_edid = ad9389b_get_edid, +}; + +/* ------------------------------ VIDEO OPS ------------------------------ */ + +/* Enable/disable ad9389b output */ +static int ad9389b_s_stream(struct v4l2_subdev *sd, int enable) +{ + struct ad9389b_state *state = get_ad9389b_state(sd); + + v4l2_dbg(1, debug, sd, "%s: %sable\n", __func__, (enable ? "en" : "dis")); + + ad9389b_wr_and_or(sd, 0xa1, ~0x3c, (enable ? 0 : 0x3c)); + if (enable) { + ad9389b_check_monitor_present_status(sd); + } else { + ad9389b_s_power(sd, 0); + state->have_monitor = false; + } + return 0; +} + +static const struct v4l2_dv_timings ad9389b_timings[] = { + V4L2_DV_BT_CEA_720X480P59_94, + V4L2_DV_BT_CEA_720X576P50, + V4L2_DV_BT_CEA_1280X720P24, + V4L2_DV_BT_CEA_1280X720P25, + V4L2_DV_BT_CEA_1280X720P30, + V4L2_DV_BT_CEA_1280X720P50, + V4L2_DV_BT_CEA_1280X720P60, + V4L2_DV_BT_CEA_1920X1080P24, + V4L2_DV_BT_CEA_1920X1080P25, + V4L2_DV_BT_CEA_1920X1080P30, + V4L2_DV_BT_CEA_1920X1080P50, + V4L2_DV_BT_CEA_1920X1080P60, + + V4L2_DV_BT_DMT_640X350P85, + V4L2_DV_BT_DMT_640X400P85, + V4L2_DV_BT_DMT_720X400P85, + V4L2_DV_BT_DMT_640X480P60, + V4L2_DV_BT_DMT_640X480P72, + V4L2_DV_BT_DMT_640X480P75, + V4L2_DV_BT_DMT_640X480P85, + V4L2_DV_BT_DMT_800X600P56, + V4L2_DV_BT_DMT_800X600P60, + V4L2_DV_BT_DMT_800X600P72, + V4L2_DV_BT_DMT_800X600P75, + V4L2_DV_BT_DMT_800X600P85, + V4L2_DV_BT_DMT_848X480P60, + V4L2_DV_BT_DMT_1024X768P60, + V4L2_DV_BT_DMT_1024X768P70, + V4L2_DV_BT_DMT_1024X768P75, + V4L2_DV_BT_DMT_1024X768P85, + V4L2_DV_BT_DMT_1152X864P75, + V4L2_DV_BT_DMT_1280X768P60_RB, + V4L2_DV_BT_DMT_1280X768P60, + V4L2_DV_BT_DMT_1280X768P75, + V4L2_DV_BT_DMT_1280X768P85, + V4L2_DV_BT_DMT_1280X800P60_RB, + V4L2_DV_BT_DMT_1280X800P60, + V4L2_DV_BT_DMT_1280X800P75, + V4L2_DV_BT_DMT_1280X800P85, + V4L2_DV_BT_DMT_1280X960P60, + V4L2_DV_BT_DMT_1280X960P85, + V4L2_DV_BT_DMT_1280X1024P60, + V4L2_DV_BT_DMT_1280X1024P75, + V4L2_DV_BT_DMT_1280X1024P85, + V4L2_DV_BT_DMT_1360X768P60, + V4L2_DV_BT_DMT_1400X1050P60_RB, + V4L2_DV_BT_DMT_1400X1050P60, + V4L2_DV_BT_DMT_1400X1050P75, + V4L2_DV_BT_DMT_1400X1050P85, + V4L2_DV_BT_DMT_1440X900P60_RB, + V4L2_DV_BT_DMT_1440X900P60, + V4L2_DV_BT_DMT_1600X1200P60, + V4L2_DV_BT_DMT_1680X1050P60_RB, + V4L2_DV_BT_DMT_1680X1050P60, + V4L2_DV_BT_DMT_1792X1344P60, + V4L2_DV_BT_DMT_1856X1392P60, + V4L2_DV_BT_DMT_1920X1200P60_RB, + V4L2_DV_BT_DMT_1366X768P60, + V4L2_DV_BT_DMT_1920X1080P60, + {}, +}; + +static int ad9389b_s_dv_timings(struct v4l2_subdev *sd, + struct v4l2_dv_timings *timings) +{ + struct ad9389b_state *state = get_ad9389b_state(sd); + int i; + + v4l2_dbg(1, debug, sd, "%s:\n", __func__); + + /* quick sanity check */ + if (timings->type != V4L2_DV_BT_656_1120) + return -EINVAL; + + if (timings->bt.interlaced) + return -EINVAL; + if (timings->bt.pixelclock < 27000000 || + timings->bt.pixelclock > 170000000) + return -EINVAL; + + /* Fill the optional fields .standards and .flags in struct v4l2_dv_timings + if the format is listed in ad9389b_timings[] */ + for (i = 0; ad9389b_timings[i].bt.width; i++) { + if (v4l_match_dv_timings(timings, &ad9389b_timings[i], 0)) { + *timings = ad9389b_timings[i]; + break; + } + } + + timings->bt.flags &= ~V4L2_DV_FL_REDUCED_FPS; + + /* save timings */ + state->dv_timings = *timings; + + /* update quantization range based on new dv_timings */ + ad9389b_set_rgb_quantization_mode(sd, state->rgb_quantization_range_ctrl); + + /* update PLL gear based on new dv_timings */ + if (state->pdata.tmds_pll_gear == AD9389B_TMDS_PLL_GEAR_SEMI_AUTOMATIC) + ad9389b_set_manual_pll_gear(sd, (u32)timings->bt.pixelclock); + + /* update AVI infoframe */ + ad9389b_set_IT_content_AVI_InfoFrame(sd); + + return 0; +} + +static int ad9389b_g_dv_timings(struct v4l2_subdev *sd, + struct v4l2_dv_timings *timings) +{ + struct ad9389b_state *state = get_ad9389b_state(sd); + + v4l2_dbg(1, debug, sd, "%s:\n", __func__); + + if (!timings) + return -EINVAL; + + *timings = state->dv_timings; + + return 0; +} + +static int ad9389b_enum_dv_timings(struct v4l2_subdev *sd, + struct v4l2_enum_dv_timings *timings) +{ + if (timings->index >= ARRAY_SIZE(ad9389b_timings)) + return -EINVAL; + + memset(timings->reserved, 0, sizeof(timings->reserved)); + timings->timings = ad9389b_timings[timings->index]; + return 0; +} + +static int ad9389b_dv_timings_cap(struct v4l2_subdev *sd, + struct v4l2_dv_timings_cap *cap) +{ + cap->type = V4L2_DV_BT_656_1120; + cap->bt.max_width = 1920; + cap->bt.max_height = 1200; + cap->bt.min_pixelclock = 27000000; + cap->bt.max_pixelclock = 170000000; + cap->bt.standards = V4L2_DV_BT_STD_CEA861 | V4L2_DV_BT_STD_DMT | + V4L2_DV_BT_STD_GTF | V4L2_DV_BT_STD_CVT; + cap->bt.capabilities = V4L2_DV_BT_CAP_PROGRESSIVE | + V4L2_DV_BT_CAP_REDUCED_BLANKING | V4L2_DV_BT_CAP_CUSTOM; + return 0; +} + +static const struct v4l2_subdev_video_ops ad9389b_video_ops = { + .s_stream = ad9389b_s_stream, + .s_dv_timings = ad9389b_s_dv_timings, + .g_dv_timings = ad9389b_g_dv_timings, + .enum_dv_timings = ad9389b_enum_dv_timings, + .dv_timings_cap = ad9389b_dv_timings_cap, +}; + +static int ad9389b_s_audio_stream(struct v4l2_subdev *sd, int enable) +{ + v4l2_dbg(1, debug, sd, "%s: %sable\n", __func__, (enable ? "en" : "dis")); + + if (enable) + ad9389b_wr_and_or(sd, 0x45, 0x3f, 0x80); + else + ad9389b_wr_and_or(sd, 0x45, 0x3f, 0x40); + + return 0; +} + +static int ad9389b_s_clock_freq(struct v4l2_subdev *sd, u32 freq) +{ + u32 N; + + switch (freq) { + case 32000: N = 4096; break; + case 44100: N = 6272; break; + case 48000: N = 6144; break; + case 88200: N = 12544; break; + case 96000: N = 12288; break; + case 176400: N = 25088; break; + case 192000: N = 24576; break; + default: + return -EINVAL; + } + + /* Set N (used with CTS to regenerate the audio clock) */ + ad9389b_wr(sd, 0x01, (N >> 16) & 0xf); + ad9389b_wr(sd, 0x02, (N >> 8) & 0xff); + ad9389b_wr(sd, 0x03, N & 0xff); + + return 0; +} + +static int ad9389b_s_i2s_clock_freq(struct v4l2_subdev *sd, u32 freq) +{ + u32 i2s_sf; + + switch (freq) { + case 32000: i2s_sf = 0x30; break; + case 44100: i2s_sf = 0x00; break; + case 48000: i2s_sf = 0x20; break; + case 88200: i2s_sf = 0x80; break; + case 96000: i2s_sf = 0xa0; break; + case 176400: i2s_sf = 0xc0; break; + case 192000: i2s_sf = 0xe0; break; + default: + return -EINVAL; + } + + /* Set sampling frequency for I2S audio to 48 kHz */ + ad9389b_wr_and_or(sd, 0x15, 0xf, i2s_sf); + + return 0; +} + +static int ad9389b_s_routing(struct v4l2_subdev *sd, u32 input, u32 output, u32 config) +{ + /* TODO based on input/output/config */ + /* TODO See datasheet "Programmers guide" p. 39-40 */ + + /* Only 2 channels in use for application */ + ad9389b_wr_and_or(sd, 0x50, 0x1f, 0x20); + /* Speaker mapping */ + ad9389b_wr(sd, 0x51, 0x00); + + /* TODO Where should this be placed? */ + /* 16 bit audio word length */ + ad9389b_wr_and_or(sd, 0x14, 0xf0, 0x02); + + return 0; +} + +static const struct v4l2_subdev_audio_ops ad9389b_audio_ops = { + .s_stream = ad9389b_s_audio_stream, + .s_clock_freq = ad9389b_s_clock_freq, + .s_i2s_clock_freq = ad9389b_s_i2s_clock_freq, + .s_routing = ad9389b_s_routing, +}; + +/* --------------------- SUBDEV OPS --------------------------------------- */ + +static const struct v4l2_subdev_ops ad9389b_ops = { + .core = &ad9389b_core_ops, + .video = &ad9389b_video_ops, + .audio = &ad9389b_audio_ops, + .pad = &ad9389b_pad_ops, +}; + +/* ----------------------------------------------------------------------- */ +static void ad9389b_dbg_dump_edid(int lvl, int debug, struct v4l2_subdev *sd, + int segment, u8 *buf) +{ + int i, j; + + if (debug < lvl) + return; + + v4l2_dbg(lvl, debug, sd, "edid segment %d\n", segment); + for (i = 0; i < 256; i += 16) { + u8 b[128]; + u8 *bp = b; + + if (i == 128) + v4l2_dbg(lvl, debug, sd, "\n"); + for (j = i; j < i + 16; j++) { + sprintf(bp, "0x%02x, ", buf[j]); + bp += 6; + } + bp[0] = '\0'; + v4l2_dbg(lvl, debug, sd, "%s\n", b); + } +} + +static void ad9389b_edid_handler(struct work_struct *work) +{ + struct delayed_work *dwork = to_delayed_work(work); + struct ad9389b_state *state = container_of(dwork, + struct ad9389b_state, edid_handler); + struct v4l2_subdev *sd = &state->sd; + struct ad9389b_edid_detect ed; + + v4l2_dbg(1, debug, sd, "%s:\n", __func__); + + if (ad9389b_check_edid_status(sd)) { + /* Return if we received the EDID. */ + return; + } + + if (ad9389b_have_hotplug(sd)) { + /* We must retry reading the EDID several times, it is possible + * that initially the EDID couldn't be read due to i2c errors + * (DVI connectors are particularly prone to this problem). */ + if (state->edid.read_retries) { + state->edid.read_retries--; + /* EDID read failed, trigger a retry */ + ad9389b_wr(sd, 0xc9, 0xf); + queue_delayed_work(state->work_queue, + &state->edid_handler, EDID_DELAY); + return; + } + } + + /* We failed to read the EDID, so send an event for this. */ + ed.present = false; + ed.segment = ad9389b_rd(sd, 0xc4); + v4l2_subdev_notify(sd, AD9389B_EDID_DETECT, (void *)&ed); + v4l2_dbg(1, debug, sd, "%s: no edid found\n", __func__); +} + +static void ad9389b_audio_setup(struct v4l2_subdev *sd) +{ + v4l2_dbg(1, debug, sd, "%s\n", __func__); + + ad9389b_s_i2s_clock_freq(sd, 48000); + ad9389b_s_clock_freq(sd, 48000); + ad9389b_s_routing(sd, 0, 0, 0); +} + +/* Initial setup of AD9389b */ + +/* Configure hdmi transmitter. */ +static void ad9389b_setup(struct v4l2_subdev *sd) +{ + struct ad9389b_state *state = get_ad9389b_state(sd); + + v4l2_dbg(1, debug, sd, "%s\n", __func__); + + /* Input format: RGB 4:4:4 */ + ad9389b_wr_and_or(sd, 0x15, 0xf1, 0x0); + /* Output format: RGB 4:4:4 */ + ad9389b_wr_and_or(sd, 0x16, 0x3f, 0x0); + /* CSC fixed point: +/-2, 1st order interpolation 4:2:2 -> 4:4:4 up + conversion, Aspect ratio: 16:9 */ + ad9389b_wr_and_or(sd, 0x17, 0xe1, 0x0e); + /* Disable pixel repetition and CSC */ + ad9389b_wr_and_or(sd, 0x3b, 0x9e, 0x0); + /* Output format: RGB 4:4:4, Active Format Information is valid. */ + ad9389b_wr_and_or(sd, 0x45, 0xc7, 0x08); + /* Underscanned */ + ad9389b_wr_and_or(sd, 0x46, 0x3f, 0x80); + /* Setup video format */ + ad9389b_wr(sd, 0x3c, 0x0); + /* Active format aspect ratio: same as picure. */ + ad9389b_wr(sd, 0x47, 0x80); + /* No encryption */ + ad9389b_wr_and_or(sd, 0xaf, 0xef, 0x0); + /* Positive clk edge capture for input video clock */ + ad9389b_wr_and_or(sd, 0xba, 0x1f, 0x60); + + ad9389b_audio_setup(sd); + + v4l2_ctrl_handler_setup(&state->hdl); + + ad9389b_set_IT_content_AVI_InfoFrame(sd); +} + +static void ad9389b_notify_monitor_detect(struct v4l2_subdev *sd) +{ + struct ad9389b_monitor_detect mdt; + struct ad9389b_state *state = get_ad9389b_state(sd); + + mdt.present = state->have_monitor; + v4l2_subdev_notify(sd, AD9389B_MONITOR_DETECT, (void *)&mdt); +} + +static void ad9389b_check_monitor_present_status(struct v4l2_subdev *sd) +{ + struct ad9389b_state *state = get_ad9389b_state(sd); + /* read hotplug and rx-sense state */ + u8 status = ad9389b_rd(sd, 0x42); + + v4l2_dbg(1, debug, sd, "%s: status: 0x%x%s%s\n", + __func__, + status, + status & MASK_AD9389B_HPD_DETECT ? ", hotplug" : "", + status & MASK_AD9389B_MSEN_DETECT ? ", rx-sense" : ""); + + if ((status & MASK_AD9389B_HPD_DETECT) && + ((status & MASK_AD9389B_MSEN_DETECT) || state->edid.segments)) { + v4l2_dbg(1, debug, sd, + "%s: hotplug and (rx-sense or edid)\n", __func__); + if (!state->have_monitor) { + v4l2_dbg(1, debug, sd, "%s: monitor detected\n", __func__); + state->have_monitor = true; + ad9389b_set_isr(sd, true); + if (!ad9389b_s_power(sd, true)) { + v4l2_dbg(1, debug, sd, + "%s: monitor detected, powerup failed\n", __func__); + return; + } + ad9389b_setup(sd); + ad9389b_notify_monitor_detect(sd); + state->edid.read_retries = EDID_MAX_RETRIES; + queue_delayed_work(state->work_queue, + &state->edid_handler, EDID_DELAY); + } + } else if (status & MASK_AD9389B_HPD_DETECT) { + v4l2_dbg(1, debug, sd, "%s: hotplug detected\n", __func__); + state->edid.read_retries = EDID_MAX_RETRIES; + queue_delayed_work(state->work_queue, + &state->edid_handler, EDID_DELAY); + } else if (!(status & MASK_AD9389B_HPD_DETECT)) { + v4l2_dbg(1, debug, sd, "%s: hotplug not detected\n", __func__); + if (state->have_monitor) { + v4l2_dbg(1, debug, sd, "%s: monitor not detected\n", __func__); + state->have_monitor = false; + ad9389b_notify_monitor_detect(sd); + } + ad9389b_s_power(sd, false); + memset(&state->edid, 0, sizeof(struct ad9389b_state_edid)); + } + + /* update read only ctrls */ + v4l2_ctrl_s_ctrl(state->hotplug_ctrl, ad9389b_have_hotplug(sd) ? 0x1 : 0x0); + v4l2_ctrl_s_ctrl(state->rx_sense_ctrl, ad9389b_have_rx_sense(sd) ? 0x1 : 0x0); + v4l2_ctrl_s_ctrl(state->have_edid0_ctrl, state->edid.segments ? 0x1 : 0x0); +} + +static bool edid_block_verify_crc(u8 *edid_block) +{ + int i; + u8 sum = 0; + + for (i = 0; i < 127; i++) + sum += *(edid_block + i); + return ((255 - sum + 1) == edid_block[127]); +} + +static bool edid_segment_verify_crc(struct v4l2_subdev *sd, u32 segment) +{ + struct ad9389b_state *state = get_ad9389b_state(sd); + u32 blocks = state->edid.blocks; + u8 *data = state->edid.data; + + if (edid_block_verify_crc(&data[segment * 256])) { + if ((segment + 1) * 2 <= blocks) + return edid_block_verify_crc(&data[segment * 256 + 128]); + return true; + } + return false; +} + +static bool ad9389b_check_edid_status(struct v4l2_subdev *sd) +{ + struct ad9389b_state *state = get_ad9389b_state(sd); + struct ad9389b_edid_detect ed; + int segment; + u8 edidRdy = ad9389b_rd(sd, 0xc5); + + v4l2_dbg(1, debug, sd, "%s: edid ready (retries: %d)\n", + __func__, EDID_MAX_RETRIES - state->edid.read_retries); + + if (!(edidRdy & MASK_AD9389B_EDID_RDY)) + return false; + + segment = ad9389b_rd(sd, 0xc4); + if (segment >= EDID_MAX_SEGM) { + v4l2_err(sd, "edid segment number too big\n"); + return false; + } + v4l2_dbg(1, debug, sd, "%s: got segment %d\n", __func__, segment); + ad9389b_edid_rd(sd, 256, &state->edid.data[segment * 256]); + ad9389b_dbg_dump_edid(2, debug, sd, segment, + &state->edid.data[segment * 256]); + if (segment == 0) { + state->edid.blocks = state->edid.data[0x7e] + 1; + v4l2_dbg(1, debug, sd, "%s: %d blocks in total\n", + __func__, state->edid.blocks); + } + if (!edid_segment_verify_crc(sd, segment)) { + /* edid crc error, force reread of edid segment */ + ad9389b_s_power(sd, false); + ad9389b_s_power(sd, true); + return false; + } + /* one more segment read ok */ + state->edid.segments = segment + 1; + if (((state->edid.data[0x7e] >> 1) + 1) > state->edid.segments) { + /* Request next EDID segment */ + v4l2_dbg(1, debug, sd, "%s: request segment %d\n", + __func__, state->edid.segments); + ad9389b_wr(sd, 0xc9, 0xf); + ad9389b_wr(sd, 0xc4, state->edid.segments); + state->edid.read_retries = EDID_MAX_RETRIES; + queue_delayed_work(state->work_queue, + &state->edid_handler, EDID_DELAY); + return false; + } + + /* report when we have all segments but report only for segment 0 */ + ed.present = true; + ed.segment = 0; + v4l2_subdev_notify(sd, AD9389B_EDID_DETECT, (void *)&ed); + state->edid_detect_counter++; + v4l2_ctrl_s_ctrl(state->have_edid0_ctrl, state->edid.segments ? 0x1 : 0x0); + return ed.present; +} + +/* ----------------------------------------------------------------------- */ + +static void ad9389b_init_setup(struct v4l2_subdev *sd) +{ + struct ad9389b_state *state = get_ad9389b_state(sd); + struct ad9389b_state_edid *edid = &state->edid; + + v4l2_dbg(1, debug, sd, "%s\n", __func__); + + /* clear all interrupts */ + ad9389b_wr(sd, 0x96, 0xff); + + memset(edid, 0, sizeof(struct ad9389b_state_edid)); + state->have_monitor = false; + ad9389b_set_isr(sd, false); +} + +static int ad9389b_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + const struct v4l2_dv_timings dv1080p60 = V4L2_DV_BT_CEA_1920X1080P60; + struct ad9389b_state *state; + struct ad9389b_platform_data *pdata = client->dev.platform_data; + struct v4l2_ctrl_handler *hdl; + struct v4l2_subdev *sd; + int err = -EIO; + + /* Check if the adapter supports the needed features */ + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) + return -EIO; + + v4l_dbg(1, debug, client, "detecting ad9389b client on address 0x%x\n", + client->addr << 1); + + state = kzalloc(sizeof(struct ad9389b_state), GFP_KERNEL); + if (!state) + return -ENOMEM; + + /* Platform data */ + if (pdata == NULL) { + v4l_err(client, "No platform data!\n"); + err = -ENODEV; + goto err_free; + } + memcpy(&state->pdata, pdata, sizeof(state->pdata)); + + sd = &state->sd; + v4l2_i2c_subdev_init(sd, client, &ad9389b_ops); + sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; + + hdl = &state->hdl; + v4l2_ctrl_handler_init(hdl, 5); + + /* private controls */ + + state->hdmi_mode_ctrl = v4l2_ctrl_new_std_menu(hdl, &ad9389b_ctrl_ops, + V4L2_CID_DV_TX_MODE, V4L2_DV_TX_MODE_HDMI, + 0, V4L2_DV_TX_MODE_DVI_D); + state->hdmi_mode_ctrl->is_private = true; + state->hotplug_ctrl = v4l2_ctrl_new_std(hdl, NULL, + V4L2_CID_DV_TX_HOTPLUG, 0, 1, 0, 0); + state->hotplug_ctrl->is_private = true; + state->rx_sense_ctrl = v4l2_ctrl_new_std(hdl, NULL, + V4L2_CID_DV_TX_RXSENSE, 0, 1, 0, 0); + state->rx_sense_ctrl->is_private = true; + state->have_edid0_ctrl = v4l2_ctrl_new_std(hdl, NULL, + V4L2_CID_DV_TX_EDID_PRESENT, 0, 1, 0, 0); + state->have_edid0_ctrl->is_private = true; + state->rgb_quantization_range_ctrl = + v4l2_ctrl_new_std_menu(hdl, &ad9389b_ctrl_ops, + V4L2_CID_DV_TX_RGB_RANGE, V4L2_DV_RGB_RANGE_FULL, + 0, V4L2_DV_RGB_RANGE_AUTO); + state->rgb_quantization_range_ctrl->is_private = true; + sd->ctrl_handler = hdl; + if (hdl->error) { + err = hdl->error; + + goto err_hdl; + } + + state->pad.flags = MEDIA_PAD_FL_SINK; + err = media_entity_init(&sd->entity, 1, &state->pad, 0); + if (err) + goto err_hdl; + + state->chip_revision = ad9389b_rd(sd, 0x0); + if (state->chip_revision != 2) { + v4l2_err(sd, "chip_revision %d != 2\n", state->chip_revision); + err = -EIO; + goto err_entity; + } + v4l2_dbg(1, debug, sd, "reg 0x41 0x%x, chip version (reg 0x00) 0x%x\n", + ad9389b_rd(sd, 0x41), state->chip_revision); + + state->edid_i2c_client = i2c_new_dummy(client->adapter, (0x7e>>1)); + if (state->edid_i2c_client == NULL) { + v4l2_err(sd, "failed to register edid i2c client\n"); + goto err_entity; + } + + state->work_queue = create_singlethread_workqueue(sd->name); + if (state->work_queue == NULL) { + v4l2_err(sd, "could not create workqueue\n"); + goto err_unreg; + } + + INIT_DELAYED_WORK(&state->edid_handler, ad9389b_edid_handler); + state->dv_timings = dv1080p60; + + ad9389b_init_setup(sd); + ad9389b_set_isr(sd, true); + + v4l2_info(sd, "%s found @ 0x%x (%s)\n", client->name, + client->addr << 1, client->adapter->name); + return 0; + +err_unreg: + i2c_unregister_device(state->edid_i2c_client); +err_entity: + media_entity_cleanup(&sd->entity); +err_hdl: + v4l2_ctrl_handler_free(&state->hdl); +err_free: + kfree(state); + return err; +} + +/* ----------------------------------------------------------------------- */ + +static int ad9389b_remove(struct i2c_client *client) +{ + struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct ad9389b_state *state = get_ad9389b_state(sd); + + state->chip_revision = -1; + + v4l2_dbg(1, debug, sd, "%s removed @ 0x%x (%s)\n", client->name, + client->addr << 1, client->adapter->name); + + ad9389b_s_stream(sd, false); + ad9389b_s_audio_stream(sd, false); + ad9389b_init_setup(sd); + cancel_delayed_work(&state->edid_handler); + i2c_unregister_device(state->edid_i2c_client); + destroy_workqueue(state->work_queue); + v4l2_device_unregister_subdev(sd); + media_entity_cleanup(&sd->entity); + v4l2_ctrl_handler_free(sd->ctrl_handler); + kfree(get_ad9389b_state(sd)); + return 0; +} + +/* ----------------------------------------------------------------------- */ + +static struct i2c_device_id ad9389b_id[] = { + { "ad9389b", V4L2_IDENT_AD9389B }, + { "ad9889b", V4L2_IDENT_AD9389B }, + { } +}; +MODULE_DEVICE_TABLE(i2c, ad9389b_id); + +static struct i2c_driver ad9389b_driver = { + .driver = { + .owner = THIS_MODULE, + .name = "ad9389b", + }, + .probe = ad9389b_probe, + .remove = ad9389b_remove, + .id_table = ad9389b_id, +}; + +module_i2c_driver(ad9389b_driver); diff --git a/drivers/media/video/adp1653.c b/drivers/media/i2c/adp1653.c index 57e87090388d..18a38b38fcb8 100644 --- a/drivers/media/video/adp1653.c +++ b/drivers/media/i2c/adp1653.c @@ -1,5 +1,5 @@ /* - * drivers/media/video/adp1653.c + * drivers/media/i2c/adp1653.c * * Copyright (C) 2008--2011 Nokia Corporation * diff --git a/drivers/media/video/adv7170.c b/drivers/media/i2c/adv7170.c index 6bc01fb98ff8..6bc01fb98ff8 100644 --- a/drivers/media/video/adv7170.c +++ b/drivers/media/i2c/adv7170.c diff --git a/drivers/media/video/adv7175.c b/drivers/media/i2c/adv7175.c index c7640fab5730..c7640fab5730 100644 --- a/drivers/media/video/adv7175.c +++ b/drivers/media/i2c/adv7175.c diff --git a/drivers/media/video/adv7180.c b/drivers/media/i2c/adv7180.c index 45ecf8db1eae..45ecf8db1eae 100644 --- a/drivers/media/video/adv7180.c +++ b/drivers/media/i2c/adv7180.c diff --git a/drivers/media/video/adv7183.c b/drivers/media/i2c/adv7183.c index e1d4c89d7140..e1d4c89d7140 100644 --- a/drivers/media/video/adv7183.c +++ b/drivers/media/i2c/adv7183.c diff --git a/drivers/media/video/adv7183_regs.h b/drivers/media/i2c/adv7183_regs.h index 4a5b7d211d2f..4a5b7d211d2f 100644 --- a/drivers/media/video/adv7183_regs.h +++ b/drivers/media/i2c/adv7183_regs.h diff --git a/drivers/media/video/adv7343.c b/drivers/media/i2c/adv7343.c index 2b5aa676a84e..2b5aa676a84e 100644 --- a/drivers/media/video/adv7343.c +++ b/drivers/media/i2c/adv7343.c diff --git a/drivers/media/video/adv7343_regs.h b/drivers/media/i2c/adv7343_regs.h index 446606764346..446606764346 100644 --- a/drivers/media/video/adv7343_regs.h +++ b/drivers/media/i2c/adv7343_regs.h diff --git a/drivers/media/video/adv7393.c b/drivers/media/i2c/adv7393.c index 3dc6098c7267..3dc6098c7267 100644 --- a/drivers/media/video/adv7393.c +++ b/drivers/media/i2c/adv7393.c diff --git a/drivers/media/video/adv7393_regs.h b/drivers/media/i2c/adv7393_regs.h index 78968330f0be..78968330f0be 100644 --- a/drivers/media/video/adv7393_regs.h +++ b/drivers/media/i2c/adv7393_regs.h diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c new file mode 100644 index 000000000000..109bc9b12e74 --- /dev/null +++ b/drivers/media/i2c/adv7604.c @@ -0,0 +1,1959 @@ +/* + * adv7604 - Analog Devices ADV7604 video decoder driver + * + * Copyright 2012 Cisco Systems, Inc. and/or its affiliates. All rights reserved. + * + * This program is free software; you may redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +/* + * References (c = chapter, p = page): + * REF_01 - Analog devices, ADV7604, Register Settings Recommendations, + * Revision 2.5, June 2010 + * REF_02 - Analog devices, Register map documentation, Documentation of + * the register maps, Software manual, Rev. F, June 2010 + * REF_03 - Analog devices, ADV7604, Hardware Manual, Rev. F, August 2010 + */ + + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/slab.h> +#include <linux/i2c.h> +#include <linux/delay.h> +#include <linux/videodev2.h> +#include <linux/workqueue.h> +#include <linux/v4l2-dv-timings.h> +#include <media/v4l2-device.h> +#include <media/v4l2-ctrls.h> +#include <media/v4l2-chip-ident.h> +#include <media/adv7604.h> + +static int debug; +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "debug level (0-2)"); + +MODULE_DESCRIPTION("Analog Devices ADV7604 video decoder driver"); +MODULE_AUTHOR("Hans Verkuil <hans.verkuil@cisco.com>"); +MODULE_AUTHOR("Mats Randgaard <mats.randgaard@cisco.com>"); +MODULE_LICENSE("GPL"); + +/* ADV7604 system clock frequency */ +#define ADV7604_fsc (28636360) + +#define DIGITAL_INPUT ((state->prim_mode == ADV7604_PRIM_MODE_HDMI_COMP) || \ + (state->prim_mode == ADV7604_PRIM_MODE_HDMI_GR)) + +/* + ********************************************************************** + * + * Arrays with configuration parameters for the ADV7604 + * + ********************************************************************** + */ +struct adv7604_state { + struct adv7604_platform_data pdata; + struct v4l2_subdev sd; + struct media_pad pad; + struct v4l2_ctrl_handler hdl; + enum adv7604_prim_mode prim_mode; + struct v4l2_dv_timings timings; + u8 edid[256]; + unsigned edid_blocks; + struct v4l2_fract aspect_ratio; + u32 rgb_quantization_range; + struct workqueue_struct *work_queues; + struct delayed_work delayed_work_enable_hotplug; + bool connector_hdmi; + + /* i2c clients */ + struct i2c_client *i2c_avlink; + struct i2c_client *i2c_cec; + struct i2c_client *i2c_infoframe; + struct i2c_client *i2c_esdp; + struct i2c_client *i2c_dpp; + struct i2c_client *i2c_afe; + struct i2c_client *i2c_repeater; + struct i2c_client *i2c_edid; + struct i2c_client *i2c_hdmi; + struct i2c_client *i2c_test; + struct i2c_client *i2c_cp; + struct i2c_client *i2c_vdp; + + /* controls */ + struct v4l2_ctrl *detect_tx_5v_ctrl; + struct v4l2_ctrl *analog_sampling_phase_ctrl; + struct v4l2_ctrl *free_run_color_manual_ctrl; + struct v4l2_ctrl *free_run_color_ctrl; + struct v4l2_ctrl *rgb_quantization_range_ctrl; +}; + +/* Supported CEA and DMT timings */ +static const struct v4l2_dv_timings adv7604_timings[] = { + V4L2_DV_BT_CEA_720X480P59_94, + V4L2_DV_BT_CEA_720X576P50, + V4L2_DV_BT_CEA_1280X720P24, + V4L2_DV_BT_CEA_1280X720P25, + V4L2_DV_BT_CEA_1280X720P30, + V4L2_DV_BT_CEA_1280X720P50, + V4L2_DV_BT_CEA_1280X720P60, + V4L2_DV_BT_CEA_1920X1080P24, + V4L2_DV_BT_CEA_1920X1080P25, + V4L2_DV_BT_CEA_1920X1080P30, + V4L2_DV_BT_CEA_1920X1080P50, + V4L2_DV_BT_CEA_1920X1080P60, + + V4L2_DV_BT_DMT_640X350P85, + V4L2_DV_BT_DMT_640X400P85, + V4L2_DV_BT_DMT_720X400P85, + V4L2_DV_BT_DMT_640X480P60, + V4L2_DV_BT_DMT_640X480P72, + V4L2_DV_BT_DMT_640X480P75, + V4L2_DV_BT_DMT_640X480P85, + V4L2_DV_BT_DMT_800X600P56, + V4L2_DV_BT_DMT_800X600P60, + V4L2_DV_BT_DMT_800X600P72, + V4L2_DV_BT_DMT_800X600P75, + V4L2_DV_BT_DMT_800X600P85, + V4L2_DV_BT_DMT_848X480P60, + V4L2_DV_BT_DMT_1024X768P60, + V4L2_DV_BT_DMT_1024X768P70, + V4L2_DV_BT_DMT_1024X768P75, + V4L2_DV_BT_DMT_1024X768P85, + V4L2_DV_BT_DMT_1152X864P75, + V4L2_DV_BT_DMT_1280X768P60_RB, + V4L2_DV_BT_DMT_1280X768P60, + V4L2_DV_BT_DMT_1280X768P75, + V4L2_DV_BT_DMT_1280X768P85, + V4L2_DV_BT_DMT_1280X800P60_RB, + V4L2_DV_BT_DMT_1280X800P60, + V4L2_DV_BT_DMT_1280X800P75, + V4L2_DV_BT_DMT_1280X800P85, + V4L2_DV_BT_DMT_1280X960P60, + V4L2_DV_BT_DMT_1280X960P85, + V4L2_DV_BT_DMT_1280X1024P60, + V4L2_DV_BT_DMT_1280X1024P75, + V4L2_DV_BT_DMT_1280X1024P85, + V4L2_DV_BT_DMT_1360X768P60, + V4L2_DV_BT_DMT_1400X1050P60_RB, + V4L2_DV_BT_DMT_1400X1050P60, + V4L2_DV_BT_DMT_1400X1050P75, + V4L2_DV_BT_DMT_1400X1050P85, + V4L2_DV_BT_DMT_1440X900P60_RB, + V4L2_DV_BT_DMT_1440X900P60, + V4L2_DV_BT_DMT_1600X1200P60, + V4L2_DV_BT_DMT_1680X1050P60_RB, + V4L2_DV_BT_DMT_1680X1050P60, + V4L2_DV_BT_DMT_1792X1344P60, + V4L2_DV_BT_DMT_1856X1392P60, + V4L2_DV_BT_DMT_1920X1200P60_RB, + V4L2_DV_BT_DMT_1366X768P60, + V4L2_DV_BT_DMT_1920X1080P60, + { }, +}; + +/* ----------------------------------------------------------------------- */ + +static inline struct adv7604_state *to_state(struct v4l2_subdev *sd) +{ + return container_of(sd, struct adv7604_state, sd); +} + +static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl) +{ + return &container_of(ctrl->handler, struct adv7604_state, hdl)->sd; +} + +static inline unsigned hblanking(const struct v4l2_bt_timings *t) +{ + return t->hfrontporch + t->hsync + t->hbackporch; +} + +static inline unsigned htotal(const struct v4l2_bt_timings *t) +{ + return t->width + t->hfrontporch + t->hsync + t->hbackporch; +} + +static inline unsigned vblanking(const struct v4l2_bt_timings *t) +{ + return t->vfrontporch + t->vsync + t->vbackporch; +} + +static inline unsigned vtotal(const struct v4l2_bt_timings *t) +{ + return t->height + t->vfrontporch + t->vsync + t->vbackporch; +} + +/* ----------------------------------------------------------------------- */ + +static s32 adv_smbus_read_byte_data_check(struct i2c_client *client, + u8 command, bool check) +{ + union i2c_smbus_data data; + + if (!i2c_smbus_xfer(client->adapter, client->addr, client->flags, + I2C_SMBUS_READ, command, + I2C_SMBUS_BYTE_DATA, &data)) + return data.byte; + if (check) + v4l_err(client, "error reading %02x, %02x\n", + client->addr, command); + return -EIO; +} + +static s32 adv_smbus_read_byte_data(struct i2c_client *client, u8 command) +{ + return adv_smbus_read_byte_data_check(client, command, true); +} + +static s32 adv_smbus_write_byte_data(struct i2c_client *client, + u8 command, u8 value) +{ + union i2c_smbus_data data; + int err; + int i; + + data.byte = value; + for (i = 0; i < 3; i++) { + err = i2c_smbus_xfer(client->adapter, client->addr, + client->flags, + I2C_SMBUS_WRITE, command, + I2C_SMBUS_BYTE_DATA, &data); + if (!err) + break; + } + if (err < 0) + v4l_err(client, "error writing %02x, %02x, %02x\n", + client->addr, command, value); + return err; +} + +static s32 adv_smbus_write_i2c_block_data(struct i2c_client *client, + u8 command, unsigned length, const u8 *values) +{ + union i2c_smbus_data data; + + if (length > I2C_SMBUS_BLOCK_MAX) + length = I2C_SMBUS_BLOCK_MAX; + data.block[0] = length; + memcpy(data.block + 1, values, length); + return i2c_smbus_xfer(client->adapter, client->addr, client->flags, + I2C_SMBUS_WRITE, command, + I2C_SMBUS_I2C_BLOCK_DATA, &data); +} + +/* ----------------------------------------------------------------------- */ + +static inline int io_read(struct v4l2_subdev *sd, u8 reg) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + + return adv_smbus_read_byte_data(client, reg); +} + +static inline int io_write(struct v4l2_subdev *sd, u8 reg, u8 val) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + + return adv_smbus_write_byte_data(client, reg, val); +} + +static inline int io_write_and_or(struct v4l2_subdev *sd, u8 reg, u8 mask, u8 val) +{ + return io_write(sd, reg, (io_read(sd, reg) & mask) | val); +} + +static inline int avlink_read(struct v4l2_subdev *sd, u8 reg) +{ + struct adv7604_state *state = to_state(sd); + + return adv_smbus_read_byte_data(state->i2c_avlink, reg); +} + +static inline int avlink_write(struct v4l2_subdev *sd, u8 reg, u8 val) +{ + struct adv7604_state *state = to_state(sd); + + return adv_smbus_write_byte_data(state->i2c_avlink, reg, val); +} + +static inline int cec_read(struct v4l2_subdev *sd, u8 reg) +{ + struct adv7604_state *state = to_state(sd); + + return adv_smbus_read_byte_data(state->i2c_cec, reg); +} + +static inline int cec_write(struct v4l2_subdev *sd, u8 reg, u8 val) +{ + struct adv7604_state *state = to_state(sd); + + return adv_smbus_write_byte_data(state->i2c_cec, reg, val); +} + +static inline int cec_write_and_or(struct v4l2_subdev *sd, u8 reg, u8 mask, u8 val) +{ + return cec_write(sd, reg, (cec_read(sd, reg) & mask) | val); +} + +static inline int infoframe_read(struct v4l2_subdev *sd, u8 reg) +{ + struct adv7604_state *state = to_state(sd); + + return adv_smbus_read_byte_data(state->i2c_infoframe, reg); +} + +static inline int infoframe_write(struct v4l2_subdev *sd, u8 reg, u8 val) +{ + struct adv7604_state *state = to_state(sd); + + return adv_smbus_write_byte_data(state->i2c_infoframe, reg, val); +} + +static inline int esdp_read(struct v4l2_subdev *sd, u8 reg) +{ + struct adv7604_state *state = to_state(sd); + + return adv_smbus_read_byte_data(state->i2c_esdp, reg); +} + +static inline int esdp_write(struct v4l2_subdev *sd, u8 reg, u8 val) +{ + struct adv7604_state *state = to_state(sd); + + return adv_smbus_write_byte_data(state->i2c_esdp, reg, val); +} + +static inline int dpp_read(struct v4l2_subdev *sd, u8 reg) +{ + struct adv7604_state *state = to_state(sd); + + return adv_smbus_read_byte_data(state->i2c_dpp, reg); +} + +static inline int dpp_write(struct v4l2_subdev *sd, u8 reg, u8 val) +{ + struct adv7604_state *state = to_state(sd); + + return adv_smbus_write_byte_data(state->i2c_dpp, reg, val); +} + +static inline int afe_read(struct v4l2_subdev *sd, u8 reg) +{ + struct adv7604_state *state = to_state(sd); + + return adv_smbus_read_byte_data(state->i2c_afe, reg); +} + +static inline int afe_write(struct v4l2_subdev *sd, u8 reg, u8 val) +{ + struct adv7604_state *state = to_state(sd); + + return adv_smbus_write_byte_data(state->i2c_afe, reg, val); +} + +static inline int rep_read(struct v4l2_subdev *sd, u8 reg) +{ + struct adv7604_state *state = to_state(sd); + + return adv_smbus_read_byte_data(state->i2c_repeater, reg); +} + +static inline int rep_write(struct v4l2_subdev *sd, u8 reg, u8 val) +{ + struct adv7604_state *state = to_state(sd); + + return adv_smbus_write_byte_data(state->i2c_repeater, reg, val); +} + +static inline int rep_write_and_or(struct v4l2_subdev *sd, u8 reg, u8 mask, u8 val) +{ + return rep_write(sd, reg, (rep_read(sd, reg) & mask) | val); +} + +static inline int edid_read(struct v4l2_subdev *sd, u8 reg) +{ + struct adv7604_state *state = to_state(sd); + + return adv_smbus_read_byte_data(state->i2c_edid, reg); +} + +static inline int edid_write(struct v4l2_subdev *sd, u8 reg, u8 val) +{ + struct adv7604_state *state = to_state(sd); + + return adv_smbus_write_byte_data(state->i2c_edid, reg, val); +} + +static inline int edid_read_block(struct v4l2_subdev *sd, unsigned len, u8 *val) +{ + struct adv7604_state *state = to_state(sd); + struct i2c_client *client = state->i2c_edid; + u8 msgbuf0[1] = { 0 }; + u8 msgbuf1[256]; + struct i2c_msg msg[2] = { { client->addr, 0, 1, msgbuf0 }, + { client->addr, 0 | I2C_M_RD, len, msgbuf1 } + }; + + if (i2c_transfer(client->adapter, msg, 2) < 0) + return -EIO; + memcpy(val, msgbuf1, len); + return 0; +} + +static void adv7604_delayed_work_enable_hotplug(struct work_struct *work) +{ + struct delayed_work *dwork = to_delayed_work(work); + struct adv7604_state *state = container_of(dwork, struct adv7604_state, + delayed_work_enable_hotplug); + struct v4l2_subdev *sd = &state->sd; + + v4l2_dbg(2, debug, sd, "%s: enable hotplug\n", __func__); + + v4l2_subdev_notify(sd, ADV7604_HOTPLUG, (void *)1); +} + +static inline int edid_write_block(struct v4l2_subdev *sd, + unsigned len, const u8 *val) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + struct adv7604_state *state = to_state(sd); + int err = 0; + int i; + + v4l2_dbg(2, debug, sd, "%s: write EDID block (%d byte)\n", __func__, len); + + v4l2_subdev_notify(sd, ADV7604_HOTPLUG, (void *)0); + + /* Disables I2C access to internal EDID ram from DDC port */ + rep_write_and_or(sd, 0x77, 0xf0, 0x0); + + for (i = 0; !err && i < len; i += I2C_SMBUS_BLOCK_MAX) + err = adv_smbus_write_i2c_block_data(state->i2c_edid, i, + I2C_SMBUS_BLOCK_MAX, val + i); + if (err) + return err; + + /* adv7604 calculates the checksums and enables I2C access to internal + EDID ram from DDC port. */ + rep_write_and_or(sd, 0x77, 0xf0, 0x1); + + for (i = 0; i < 1000; i++) { + if (rep_read(sd, 0x7d) & 1) + break; + mdelay(1); + } + if (i == 1000) { + v4l_err(client, "error enabling edid\n"); + return -EIO; + } + + /* enable hotplug after 100 ms */ + queue_delayed_work(state->work_queues, + &state->delayed_work_enable_hotplug, HZ / 10); + return 0; +} + +static inline int hdmi_read(struct v4l2_subdev *sd, u8 reg) +{ + struct adv7604_state *state = to_state(sd); + + return adv_smbus_read_byte_data(state->i2c_hdmi, reg); +} + +static inline int hdmi_write(struct v4l2_subdev *sd, u8 reg, u8 val) +{ + struct adv7604_state *state = to_state(sd); + + return adv_smbus_write_byte_data(state->i2c_hdmi, reg, val); +} + +static inline int test_read(struct v4l2_subdev *sd, u8 reg) +{ + struct adv7604_state *state = to_state(sd); + + return adv_smbus_read_byte_data(state->i2c_test, reg); +} + +static inline int test_write(struct v4l2_subdev *sd, u8 reg, u8 val) +{ + struct adv7604_state *state = to_state(sd); + + return adv_smbus_write_byte_data(state->i2c_test, reg, val); +} + +static inline int cp_read(struct v4l2_subdev *sd, u8 reg) +{ + struct adv7604_state *state = to_state(sd); + + return adv_smbus_read_byte_data(state->i2c_cp, reg); +} + +static inline int cp_write(struct v4l2_subdev *sd, u8 reg, u8 val) +{ + struct adv7604_state *state = to_state(sd); + + return adv_smbus_write_byte_data(state->i2c_cp, reg, val); +} + +static inline int cp_write_and_or(struct v4l2_subdev *sd, u8 reg, u8 mask, u8 val) +{ + return cp_write(sd, reg, (cp_read(sd, reg) & mask) | val); +} + +static inline int vdp_read(struct v4l2_subdev *sd, u8 reg) +{ + struct adv7604_state *state = to_state(sd); + + return adv_smbus_read_byte_data(state->i2c_vdp, reg); +} + +static inline int vdp_write(struct v4l2_subdev *sd, u8 reg, u8 val) +{ + struct adv7604_state *state = to_state(sd); + + return adv_smbus_write_byte_data(state->i2c_vdp, reg, val); +} + +/* ----------------------------------------------------------------------- */ + +#ifdef CONFIG_VIDEO_ADV_DEBUG +static void adv7604_inv_register(struct v4l2_subdev *sd) +{ + v4l2_info(sd, "0x000-0x0ff: IO Map\n"); + v4l2_info(sd, "0x100-0x1ff: AVLink Map\n"); + v4l2_info(sd, "0x200-0x2ff: CEC Map\n"); + v4l2_info(sd, "0x300-0x3ff: InfoFrame Map\n"); + v4l2_info(sd, "0x400-0x4ff: ESDP Map\n"); + v4l2_info(sd, "0x500-0x5ff: DPP Map\n"); + v4l2_info(sd, "0x600-0x6ff: AFE Map\n"); + v4l2_info(sd, "0x700-0x7ff: Repeater Map\n"); + v4l2_info(sd, "0x800-0x8ff: EDID Map\n"); + v4l2_info(sd, "0x900-0x9ff: HDMI Map\n"); + v4l2_info(sd, "0xa00-0xaff: Test Map\n"); + v4l2_info(sd, "0xb00-0xbff: CP Map\n"); + v4l2_info(sd, "0xc00-0xcff: VDP Map\n"); +} + +static int adv7604_g_register(struct v4l2_subdev *sd, + struct v4l2_dbg_register *reg) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + + if (!v4l2_chip_match_i2c_client(client, ®->match)) + return -EINVAL; + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + reg->size = 1; + switch (reg->reg >> 8) { + case 0: + reg->val = io_read(sd, reg->reg & 0xff); + break; + case 1: + reg->val = avlink_read(sd, reg->reg & 0xff); + break; + case 2: + reg->val = cec_read(sd, reg->reg & 0xff); + break; + case 3: + reg->val = infoframe_read(sd, reg->reg & 0xff); + break; + case 4: + reg->val = esdp_read(sd, reg->reg & 0xff); + break; + case 5: + reg->val = dpp_read(sd, reg->reg & 0xff); + break; + case 6: + reg->val = afe_read(sd, reg->reg & 0xff); + break; + case 7: + reg->val = rep_read(sd, reg->reg & 0xff); + break; + case 8: + reg->val = edid_read(sd, reg->reg & 0xff); + break; + case 9: + reg->val = hdmi_read(sd, reg->reg & 0xff); + break; + case 0xa: + reg->val = test_read(sd, reg->reg & 0xff); + break; + case 0xb: + reg->val = cp_read(sd, reg->reg & 0xff); + break; + case 0xc: + reg->val = vdp_read(sd, reg->reg & 0xff); + break; + default: + v4l2_info(sd, "Register %03llx not supported\n", reg->reg); + adv7604_inv_register(sd); + break; + } + return 0; +} + +static int adv7604_s_register(struct v4l2_subdev *sd, + struct v4l2_dbg_register *reg) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + + if (!v4l2_chip_match_i2c_client(client, ®->match)) + return -EINVAL; + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + switch (reg->reg >> 8) { + case 0: + io_write(sd, reg->reg & 0xff, reg->val & 0xff); + break; + case 1: + avlink_write(sd, reg->reg & 0xff, reg->val & 0xff); + break; + case 2: + cec_write(sd, reg->reg & 0xff, reg->val & 0xff); + break; + case 3: + infoframe_write(sd, reg->reg & 0xff, reg->val & 0xff); + break; + case 4: + esdp_write(sd, reg->reg & 0xff, reg->val & 0xff); + break; + case 5: + dpp_write(sd, reg->reg & 0xff, reg->val & 0xff); + break; + case 6: + afe_write(sd, reg->reg & 0xff, reg->val & 0xff); + break; + case 7: + rep_write(sd, reg->reg & 0xff, reg->val & 0xff); + break; + case 8: + edid_write(sd, reg->reg & 0xff, reg->val & 0xff); + break; + case 9: + hdmi_write(sd, reg->reg & 0xff, reg->val & 0xff); + break; + case 0xa: + test_write(sd, reg->reg & 0xff, reg->val & 0xff); + break; + case 0xb: + cp_write(sd, reg->reg & 0xff, reg->val & 0xff); + break; + case 0xc: + vdp_write(sd, reg->reg & 0xff, reg->val & 0xff); + break; + default: + v4l2_info(sd, "Register %03llx not supported\n", reg->reg); + adv7604_inv_register(sd); + break; + } + return 0; +} +#endif + +static int adv7604_s_detect_tx_5v_ctrl(struct v4l2_subdev *sd) +{ + struct adv7604_state *state = to_state(sd); + + /* port A only */ + return v4l2_ctrl_s_ctrl(state->detect_tx_5v_ctrl, + ((io_read(sd, 0x6f) & 0x10) >> 4)); +} + +static void configure_free_run(struct v4l2_subdev *sd, const struct v4l2_bt_timings *timings) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + u32 width = htotal(timings); + u32 height = vtotal(timings); + u16 ch1_fr_ll = (((u32)timings->pixelclock / 100) > 0) ? + ((width * (ADV7604_fsc / 100)) / ((u32)timings->pixelclock / 100)) : 0; + + v4l2_dbg(2, debug, sd, "%s\n", __func__); + + cp_write(sd, 0x8f, (ch1_fr_ll >> 8) & 0x7); /* CH1_FR_LL */ + cp_write(sd, 0x90, ch1_fr_ll & 0xff); /* CH1_FR_LL */ + cp_write(sd, 0xab, (height >> 4) & 0xff); /* CP_LCOUNT_MAX */ + cp_write(sd, 0xac, (height & 0x0f) << 4); /* CP_LCOUNT_MAX */ + /* TODO support interlaced */ + cp_write(sd, 0x91, 0x10); /* INTERLACED */ + + /* Should only be set in auto-graphics mode [REF_02 p. 91-92] */ + if ((io_read(sd, 0x00) == 0x07) && (io_read(sd, 0x01) == 0x02)) { + u16 cp_start_sav, cp_start_eav, cp_start_vbi, cp_end_vbi; + const u8 pll[2] = { + (0xc0 | ((width >> 8) & 0x1f)), + (width & 0xff) + }; + + /* setup PLL_DIV_MAN_EN and PLL_DIV_RATIO */ + /* IO-map reg. 0x16 and 0x17 should be written in sequence */ + if (adv_smbus_write_i2c_block_data(client, 0x16, 2, pll)) { + v4l2_err(sd, "writing to reg 0x16 and 0x17 failed\n"); + return; + } + + /* active video - horizontal timing */ + cp_start_sav = timings->hsync + timings->hbackporch - 4; + cp_start_eav = width - timings->hfrontporch; + cp_write(sd, 0xa2, (cp_start_sav >> 4) & 0xff); + cp_write(sd, 0xa3, ((cp_start_sav & 0x0f) << 4) | ((cp_start_eav >> 8) & 0x0f)); + cp_write(sd, 0xa4, cp_start_eav & 0xff); + + /* active video - vertical timing */ + cp_start_vbi = height - timings->vfrontporch; + cp_end_vbi = timings->vsync + timings->vbackporch; + cp_write(sd, 0xa5, (cp_start_vbi >> 4) & 0xff); + cp_write(sd, 0xa6, ((cp_start_vbi & 0xf) << 4) | ((cp_end_vbi >> 8) & 0xf)); + cp_write(sd, 0xa7, cp_end_vbi & 0xff); + } else { + /* reset to default values */ + io_write(sd, 0x16, 0x43); + io_write(sd, 0x17, 0x5a); + cp_write(sd, 0xa2, 0x00); + cp_write(sd, 0xa3, 0x00); + cp_write(sd, 0xa4, 0x00); + cp_write(sd, 0xa5, 0x00); + cp_write(sd, 0xa6, 0x00); + cp_write(sd, 0xa7, 0x00); + } +} + + +static void set_rgb_quantization_range(struct v4l2_subdev *sd) +{ + struct adv7604_state *state = to_state(sd); + + switch (state->rgb_quantization_range) { + case V4L2_DV_RGB_RANGE_AUTO: + /* automatic */ + if ((hdmi_read(sd, 0x05) & 0x80) || + (state->prim_mode == ADV7604_PRIM_MODE_COMP) || + (state->prim_mode == ADV7604_PRIM_MODE_RGB)) { + /* receiving HDMI or analog signal */ + io_write_and_or(sd, 0x02, 0x0f, 0xf0); + } else { + /* receiving DVI-D signal */ + + /* ADV7604 selects RGB limited range regardless of + input format (CE/IT) in automatic mode */ + if (state->timings.bt.standards & V4L2_DV_BT_STD_CEA861) { + /* RGB limited range (16-235) */ + io_write_and_or(sd, 0x02, 0x0f, 0x00); + + } else { + /* RGB full range (0-255) */ + io_write_and_or(sd, 0x02, 0x0f, 0x10); + } + } + break; + case V4L2_DV_RGB_RANGE_LIMITED: + /* RGB limited range (16-235) */ + io_write_and_or(sd, 0x02, 0x0f, 0x00); + break; + case V4L2_DV_RGB_RANGE_FULL: + /* RGB full range (0-255) */ + io_write_and_or(sd, 0x02, 0x0f, 0x10); + break; + } +} + + +static int adv7604_s_ctrl(struct v4l2_ctrl *ctrl) +{ + struct v4l2_subdev *sd = to_sd(ctrl); + struct adv7604_state *state = to_state(sd); + + switch (ctrl->id) { + case V4L2_CID_BRIGHTNESS: + cp_write(sd, 0x3c, ctrl->val); + return 0; + case V4L2_CID_CONTRAST: + cp_write(sd, 0x3a, ctrl->val); + return 0; + case V4L2_CID_SATURATION: + cp_write(sd, 0x3b, ctrl->val); + return 0; + case V4L2_CID_HUE: + cp_write(sd, 0x3d, ctrl->val); + return 0; + case V4L2_CID_DV_RX_RGB_RANGE: + state->rgb_quantization_range = ctrl->val; + set_rgb_quantization_range(sd); + return 0; + case V4L2_CID_ADV_RX_ANALOG_SAMPLING_PHASE: + /* Set the analog sampling phase. This is needed to find the + best sampling phase for analog video: an application or + driver has to try a number of phases and analyze the picture + quality before settling on the best performing phase. */ + afe_write(sd, 0xc8, ctrl->val); + return 0; + case V4L2_CID_ADV_RX_FREE_RUN_COLOR_MANUAL: + /* Use the default blue color for free running mode, + or supply your own. */ + cp_write_and_or(sd, 0xbf, ~0x04, (ctrl->val << 2)); + return 0; + case V4L2_CID_ADV_RX_FREE_RUN_COLOR: + cp_write(sd, 0xc0, (ctrl->val & 0xff0000) >> 16); + cp_write(sd, 0xc1, (ctrl->val & 0x00ff00) >> 8); + cp_write(sd, 0xc2, (u8)(ctrl->val & 0x0000ff)); + return 0; + } + return -EINVAL; +} + +static int adv7604_g_chip_ident(struct v4l2_subdev *sd, + struct v4l2_dbg_chip_ident *chip) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + + return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_ADV7604, 0); +} + +/* ----------------------------------------------------------------------- */ + +static inline bool no_power(struct v4l2_subdev *sd) +{ + /* Entire chip or CP powered off */ + return io_read(sd, 0x0c) & 0x24; +} + +static inline bool no_signal_tmds(struct v4l2_subdev *sd) +{ + /* TODO port B, C and D */ + return !(io_read(sd, 0x6a) & 0x10); +} + +static inline bool no_lock_tmds(struct v4l2_subdev *sd) +{ + return (io_read(sd, 0x6a) & 0xe0) != 0xe0; +} + +static inline bool no_lock_sspd(struct v4l2_subdev *sd) +{ + /* TODO channel 2 */ + return ((cp_read(sd, 0xb5) & 0xd0) != 0xd0); +} + +static inline bool no_lock_stdi(struct v4l2_subdev *sd) +{ + /* TODO channel 2 */ + return !(cp_read(sd, 0xb1) & 0x80); +} + +static inline bool no_signal(struct v4l2_subdev *sd) +{ + struct adv7604_state *state = to_state(sd); + bool ret; + + ret = no_power(sd); + + ret |= no_lock_stdi(sd); + ret |= no_lock_sspd(sd); + + if (DIGITAL_INPUT) { + ret |= no_lock_tmds(sd); + ret |= no_signal_tmds(sd); + } + + return ret; +} + +static inline bool no_lock_cp(struct v4l2_subdev *sd) +{ + /* CP has detected a non standard number of lines on the incoming + video compared to what it is configured to receive by s_dv_timings */ + return io_read(sd, 0x12) & 0x01; +} + +static int adv7604_g_input_status(struct v4l2_subdev *sd, u32 *status) +{ + struct adv7604_state *state = to_state(sd); + + *status = 0; + *status |= no_power(sd) ? V4L2_IN_ST_NO_POWER : 0; + *status |= no_signal(sd) ? V4L2_IN_ST_NO_SIGNAL : 0; + if (no_lock_cp(sd)) + *status |= DIGITAL_INPUT ? V4L2_IN_ST_NO_SYNC : V4L2_IN_ST_NO_H_LOCK; + + v4l2_dbg(1, debug, sd, "%s: status = 0x%x\n", __func__, *status); + + return 0; +} + +/* ----------------------------------------------------------------------- */ + +static void adv7604_print_timings(struct v4l2_subdev *sd, + struct v4l2_dv_timings *timings, const char *txt, bool detailed) +{ + struct v4l2_bt_timings *bt = &timings->bt; + u32 htot, vtot; + + if (timings->type != V4L2_DV_BT_656_1120) + return; + + htot = htotal(bt); + vtot = vtotal(bt); + + v4l2_info(sd, "%s %dx%d%s%d (%dx%d)", + txt, bt->width, bt->height, bt->interlaced ? "i" : "p", + (htot * vtot) > 0 ? ((u32)bt->pixelclock / + (htot * vtot)) : 0, + htot, vtot); + + if (detailed) { + v4l2_info(sd, " horizontal: fp = %d, %ssync = %d, bp = %d\n", + bt->hfrontporch, + (bt->polarities & V4L2_DV_HSYNC_POS_POL) ? "+" : "-", + bt->hsync, bt->hbackporch); + v4l2_info(sd, " vertical: fp = %d, %ssync = %d, bp = %d\n", + bt->vfrontporch, + (bt->polarities & V4L2_DV_VSYNC_POS_POL) ? "+" : "-", + bt->vsync, bt->vbackporch); + v4l2_info(sd, " pixelclock: %lld, flags: 0x%x, standards: 0x%x\n", + bt->pixelclock, bt->flags, bt->standards); + } +} + +struct stdi_readback { + u16 bl, lcf, lcvs; + u8 hs_pol, vs_pol; + bool interlaced; +}; + +static int stdi2dv_timings(struct v4l2_subdev *sd, + struct stdi_readback *stdi, + struct v4l2_dv_timings *timings) +{ + struct adv7604_state *state = to_state(sd); + u32 hfreq = (ADV7604_fsc * 8) / stdi->bl; + u32 pix_clk; + int i; + + for (i = 0; adv7604_timings[i].bt.height; i++) { + if (vtotal(&adv7604_timings[i].bt) != stdi->lcf + 1) + continue; + if (adv7604_timings[i].bt.vsync != stdi->lcvs) + continue; + + pix_clk = hfreq * htotal(&adv7604_timings[i].bt); + + if ((pix_clk < adv7604_timings[i].bt.pixelclock + 1000000) && + (pix_clk > adv7604_timings[i].bt.pixelclock - 1000000)) { + *timings = adv7604_timings[i]; + return 0; + } + } + + if (v4l2_detect_cvt(stdi->lcf + 1, hfreq, stdi->lcvs, + (stdi->hs_pol == '+' ? V4L2_DV_HSYNC_POS_POL : 0) | + (stdi->vs_pol == '+' ? V4L2_DV_VSYNC_POS_POL : 0), + timings)) + return 0; + if (v4l2_detect_gtf(stdi->lcf + 1, hfreq, stdi->lcvs, + (stdi->hs_pol == '+' ? V4L2_DV_HSYNC_POS_POL : 0) | + (stdi->vs_pol == '+' ? V4L2_DV_VSYNC_POS_POL : 0), + state->aspect_ratio, timings)) + return 0; + + v4l2_dbg(2, debug, sd, "%s: No format candidate found for lcf=%d, bl = %d\n", + __func__, stdi->lcf, stdi->bl); + return -1; +} + +static int read_stdi(struct v4l2_subdev *sd, struct stdi_readback *stdi) +{ + if (no_lock_stdi(sd) || no_lock_sspd(sd)) { + v4l2_dbg(2, debug, sd, "%s: STDI and/or SSPD not locked\n", __func__); + return -1; + } + + /* read STDI */ + stdi->bl = ((cp_read(sd, 0xb1) & 0x3f) << 8) | cp_read(sd, 0xb2); + stdi->lcf = ((cp_read(sd, 0xb3) & 0x7) << 8) | cp_read(sd, 0xb4); + stdi->lcvs = cp_read(sd, 0xb3) >> 3; + stdi->interlaced = io_read(sd, 0x12) & 0x10; + + /* read SSPD */ + if ((cp_read(sd, 0xb5) & 0x03) == 0x01) { + stdi->hs_pol = ((cp_read(sd, 0xb5) & 0x10) ? + ((cp_read(sd, 0xb5) & 0x08) ? '+' : '-') : 'x'); + stdi->vs_pol = ((cp_read(sd, 0xb5) & 0x40) ? + ((cp_read(sd, 0xb5) & 0x20) ? '+' : '-') : 'x'); + } else { + stdi->hs_pol = 'x'; + stdi->vs_pol = 'x'; + } + + if (no_lock_stdi(sd) || no_lock_sspd(sd)) { + v4l2_dbg(2, debug, sd, + "%s: signal lost during readout of STDI/SSPD\n", __func__); + return -1; + } + + if (stdi->lcf < 239 || stdi->bl < 8 || stdi->bl == 0x3fff) { + v4l2_dbg(2, debug, sd, "%s: invalid signal\n", __func__); + memset(stdi, 0, sizeof(struct stdi_readback)); + return -1; + } + + v4l2_dbg(2, debug, sd, + "%s: lcf (frame height - 1) = %d, bl = %d, lcvs (vsync) = %d, %chsync, %cvsync, %s\n", + __func__, stdi->lcf, stdi->bl, stdi->lcvs, + stdi->hs_pol, stdi->vs_pol, + stdi->interlaced ? "interlaced" : "progressive"); + + return 0; +} + +static int adv7604_enum_dv_timings(struct v4l2_subdev *sd, + struct v4l2_enum_dv_timings *timings) +{ + if (timings->index >= ARRAY_SIZE(adv7604_timings) - 1) + return -EINVAL; + memset(timings->reserved, 0, sizeof(timings->reserved)); + timings->timings = adv7604_timings[timings->index]; + return 0; +} + +static int adv7604_dv_timings_cap(struct v4l2_subdev *sd, + struct v4l2_dv_timings_cap *cap) +{ + struct adv7604_state *state = to_state(sd); + + cap->type = V4L2_DV_BT_656_1120; + cap->bt.max_width = 1920; + cap->bt.max_height = 1200; + cap->bt.min_pixelclock = 27000000; + if (DIGITAL_INPUT) + cap->bt.max_pixelclock = 225000000; + else + cap->bt.max_pixelclock = 170000000; + cap->bt.standards = V4L2_DV_BT_STD_CEA861 | V4L2_DV_BT_STD_DMT | + V4L2_DV_BT_STD_GTF | V4L2_DV_BT_STD_CVT; + cap->bt.capabilities = V4L2_DV_BT_CAP_PROGRESSIVE | + V4L2_DV_BT_CAP_REDUCED_BLANKING | V4L2_DV_BT_CAP_CUSTOM; + return 0; +} + +/* Fill the optional fields .standards and .flags in struct v4l2_dv_timings + if the format is listed in adv7604_timings[] */ +static void adv7604_fill_optional_dv_timings_fields(struct v4l2_subdev *sd, + struct v4l2_dv_timings *timings) +{ + struct adv7604_state *state = to_state(sd); + int i; + + for (i = 0; adv7604_timings[i].bt.width; i++) { + if (v4l_match_dv_timings(timings, &adv7604_timings[i], + DIGITAL_INPUT ? 250000 : 1000000)) { + *timings = adv7604_timings[i]; + break; + } + } +} + +static int adv7604_query_dv_timings(struct v4l2_subdev *sd, + struct v4l2_dv_timings *timings) +{ + struct adv7604_state *state = to_state(sd); + struct v4l2_bt_timings *bt = &timings->bt; + struct stdi_readback stdi; + + if (!timings) + return -EINVAL; + + memset(timings, 0, sizeof(struct v4l2_dv_timings)); + + if (no_signal(sd)) { + v4l2_dbg(1, debug, sd, "%s: no valid signal\n", __func__); + return -ENOLINK; + } + + /* read STDI */ + if (read_stdi(sd, &stdi)) { + v4l2_dbg(1, debug, sd, "%s: STDI/SSPD not locked\n", __func__); + return -ENOLINK; + } + bt->interlaced = stdi.interlaced ? + V4L2_DV_INTERLACED : V4L2_DV_PROGRESSIVE; + + if (DIGITAL_INPUT) { + timings->type = V4L2_DV_BT_656_1120; + + bt->width = (hdmi_read(sd, 0x07) & 0x0f) * 256 + hdmi_read(sd, 0x08); + bt->height = (hdmi_read(sd, 0x09) & 0x0f) * 256 + hdmi_read(sd, 0x0a); + bt->pixelclock = (hdmi_read(sd, 0x06) * 1000000) + + ((hdmi_read(sd, 0x3b) & 0x30) >> 4) * 250000; + bt->hfrontporch = (hdmi_read(sd, 0x20) & 0x03) * 256 + + hdmi_read(sd, 0x21); + bt->hsync = (hdmi_read(sd, 0x22) & 0x03) * 256 + + hdmi_read(sd, 0x23); + bt->hbackporch = (hdmi_read(sd, 0x24) & 0x03) * 256 + + hdmi_read(sd, 0x25); + bt->vfrontporch = ((hdmi_read(sd, 0x2a) & 0x1f) * 256 + + hdmi_read(sd, 0x2b)) / 2; + bt->vsync = ((hdmi_read(sd, 0x2e) & 0x1f) * 256 + + hdmi_read(sd, 0x2f)) / 2; + bt->vbackporch = ((hdmi_read(sd, 0x32) & 0x1f) * 256 + + hdmi_read(sd, 0x33)) / 2; + bt->polarities = ((hdmi_read(sd, 0x05) & 0x10) ? V4L2_DV_VSYNC_POS_POL : 0) | + ((hdmi_read(sd, 0x05) & 0x20) ? V4L2_DV_HSYNC_POS_POL : 0); + if (bt->interlaced == V4L2_DV_INTERLACED) { + bt->height += (hdmi_read(sd, 0x0b) & 0x0f) * 256 + + hdmi_read(sd, 0x0c); + bt->il_vfrontporch = ((hdmi_read(sd, 0x2c) & 0x1f) * 256 + + hdmi_read(sd, 0x2d)) / 2; + bt->il_vsync = ((hdmi_read(sd, 0x30) & 0x1f) * 256 + + hdmi_read(sd, 0x31)) / 2; + bt->vbackporch = ((hdmi_read(sd, 0x34) & 0x1f) * 256 + + hdmi_read(sd, 0x35)) / 2; + } + adv7604_fill_optional_dv_timings_fields(sd, timings); + } else { + /* find format + * Since LCVS values are inaccurate (REF_03, page 275-276), + * stdi2dv_timings() is called with lcvs +-1 if the first attempt fails. + */ + if (!stdi2dv_timings(sd, &stdi, timings)) + goto found; + stdi.lcvs += 1; + v4l2_dbg(1, debug, sd, "%s: lcvs + 1 = %d\n", __func__, stdi.lcvs); + if (!stdi2dv_timings(sd, &stdi, timings)) + goto found; + stdi.lcvs -= 2; + v4l2_dbg(1, debug, sd, "%s: lcvs - 1 = %d\n", __func__, stdi.lcvs); + if (stdi2dv_timings(sd, &stdi, timings)) { + v4l2_dbg(1, debug, sd, "%s: format not supported\n", __func__); + return -ERANGE; + } + } +found: + + if (no_signal(sd)) { + v4l2_dbg(1, debug, sd, "%s: signal lost during readout\n", __func__); + memset(timings, 0, sizeof(struct v4l2_dv_timings)); + return -ENOLINK; + } + + if ((!DIGITAL_INPUT && bt->pixelclock > 170000000) || + (DIGITAL_INPUT && bt->pixelclock > 225000000)) { + v4l2_dbg(1, debug, sd, "%s: pixelclock out of range %d\n", + __func__, (u32)bt->pixelclock); + return -ERANGE; + } + + if (debug > 1) + adv7604_print_timings(sd, timings, + "adv7604_query_dv_timings:", true); + + return 0; +} + +static int adv7604_s_dv_timings(struct v4l2_subdev *sd, + struct v4l2_dv_timings *timings) +{ + struct adv7604_state *state = to_state(sd); + struct v4l2_bt_timings *bt; + + if (!timings) + return -EINVAL; + + bt = &timings->bt; + + if ((!DIGITAL_INPUT && bt->pixelclock > 170000000) || + (DIGITAL_INPUT && bt->pixelclock > 225000000)) { + v4l2_dbg(1, debug, sd, "%s: pixelclock out of range %d\n", + __func__, (u32)bt->pixelclock); + return -ERANGE; + } + adv7604_fill_optional_dv_timings_fields(sd, timings); + + state->timings = *timings; + + /* freerun */ + configure_free_run(sd, bt); + + set_rgb_quantization_range(sd); + + + if (debug > 1) + adv7604_print_timings(sd, timings, + "adv7604_s_dv_timings:", true); + return 0; +} + +static int adv7604_g_dv_timings(struct v4l2_subdev *sd, + struct v4l2_dv_timings *timings) +{ + struct adv7604_state *state = to_state(sd); + + *timings = state->timings; + return 0; +} + +static void enable_input(struct v4l2_subdev *sd, enum adv7604_prim_mode prim_mode) +{ + switch (prim_mode) { + case ADV7604_PRIM_MODE_COMP: + case ADV7604_PRIM_MODE_RGB: + /* enable */ + io_write(sd, 0x15, 0xb0); /* Disable Tristate of Pins (no audio) */ + break; + case ADV7604_PRIM_MODE_HDMI_COMP: + case ADV7604_PRIM_MODE_HDMI_GR: + /* enable */ + hdmi_write(sd, 0x1a, 0x0a); /* Unmute audio */ + hdmi_write(sd, 0x01, 0x00); /* Enable HDMI clock terminators */ + io_write(sd, 0x15, 0xa0); /* Disable Tristate of Pins */ + break; + default: + v4l2_err(sd, "%s: reserved primary mode 0x%0x\n", + __func__, prim_mode); + break; + } +} + +static void disable_input(struct v4l2_subdev *sd) +{ + /* disable */ + io_write(sd, 0x15, 0xbe); /* Tristate all outputs from video core */ + hdmi_write(sd, 0x1a, 0x1a); /* Mute audio */ + hdmi_write(sd, 0x01, 0x78); /* Disable HDMI clock terminators */ +} + +static void select_input(struct v4l2_subdev *sd, enum adv7604_prim_mode prim_mode) +{ + switch (prim_mode) { + case ADV7604_PRIM_MODE_COMP: + case ADV7604_PRIM_MODE_RGB: + /* set mode and select free run resolution */ + io_write(sd, 0x00, 0x07); /* video std */ + io_write(sd, 0x01, 0x02); /* prim mode */ + /* enable embedded syncs for auto graphics mode */ + cp_write_and_or(sd, 0x81, 0xef, 0x10); + + /* reset ADI recommended settings for HDMI: */ + /* "ADV7604 Register Settings Recommendations (rev. 2.5, June 2010)" p. 4. */ + hdmi_write(sd, 0x0d, 0x04); /* HDMI filter optimization */ + hdmi_write(sd, 0x3d, 0x00); /* DDC bus active pull-up control */ + hdmi_write(sd, 0x3e, 0x74); /* TMDS PLL optimization */ + hdmi_write(sd, 0x4e, 0x3b); /* TMDS PLL optimization */ + hdmi_write(sd, 0x57, 0x74); /* TMDS PLL optimization */ + hdmi_write(sd, 0x58, 0x63); /* TMDS PLL optimization */ + hdmi_write(sd, 0x8d, 0x18); /* equaliser */ + hdmi_write(sd, 0x8e, 0x34); /* equaliser */ + hdmi_write(sd, 0x93, 0x88); /* equaliser */ + hdmi_write(sd, 0x94, 0x2e); /* equaliser */ + hdmi_write(sd, 0x96, 0x00); /* enable automatic EQ changing */ + + afe_write(sd, 0x00, 0x08); /* power up ADC */ + afe_write(sd, 0x01, 0x06); /* power up Analog Front End */ + afe_write(sd, 0xc8, 0x00); /* phase control */ + + /* set ADI recommended settings for digitizer */ + /* "ADV7604 Register Settings Recommendations (rev. 2.5, June 2010)" p. 17. */ + afe_write(sd, 0x12, 0x7b); /* ADC noise shaping filter controls */ + afe_write(sd, 0x0c, 0x1f); /* CP core gain controls */ + cp_write(sd, 0x3e, 0x04); /* CP core pre-gain control */ + cp_write(sd, 0xc3, 0x39); /* CP coast control. Graphics mode */ + cp_write(sd, 0x40, 0x5c); /* CP core pre-gain control. Graphics mode */ + break; + + case ADV7604_PRIM_MODE_HDMI_COMP: + case ADV7604_PRIM_MODE_HDMI_GR: + /* set mode and select free run resolution */ + /* video std */ + io_write(sd, 0x00, + (prim_mode == ADV7604_PRIM_MODE_HDMI_GR) ? 0x02 : 0x1e); + io_write(sd, 0x01, prim_mode); /* prim mode */ + /* disable embedded syncs for auto graphics mode */ + cp_write_and_or(sd, 0x81, 0xef, 0x00); + + /* set ADI recommended settings for HDMI: */ + /* "ADV7604 Register Settings Recommendations (rev. 2.5, June 2010)" p. 4. */ + hdmi_write(sd, 0x0d, 0x84); /* HDMI filter optimization */ + hdmi_write(sd, 0x3d, 0x10); /* DDC bus active pull-up control */ + hdmi_write(sd, 0x3e, 0x39); /* TMDS PLL optimization */ + hdmi_write(sd, 0x4e, 0x3b); /* TMDS PLL optimization */ + hdmi_write(sd, 0x57, 0xb6); /* TMDS PLL optimization */ + hdmi_write(sd, 0x58, 0x03); /* TMDS PLL optimization */ + hdmi_write(sd, 0x8d, 0x18); /* equaliser */ + hdmi_write(sd, 0x8e, 0x34); /* equaliser */ + hdmi_write(sd, 0x93, 0x8b); /* equaliser */ + hdmi_write(sd, 0x94, 0x2d); /* equaliser */ + hdmi_write(sd, 0x96, 0x01); /* enable automatic EQ changing */ + + afe_write(sd, 0x00, 0xff); /* power down ADC */ + afe_write(sd, 0x01, 0xfe); /* power down Analog Front End */ + afe_write(sd, 0xc8, 0x40); /* phase control */ + + /* reset ADI recommended settings for digitizer */ + /* "ADV7604 Register Settings Recommendations (rev. 2.5, June 2010)" p. 17. */ + afe_write(sd, 0x12, 0xfb); /* ADC noise shaping filter controls */ + afe_write(sd, 0x0c, 0x0d); /* CP core gain controls */ + cp_write(sd, 0x3e, 0x00); /* CP core pre-gain control */ + cp_write(sd, 0xc3, 0x39); /* CP coast control. Graphics mode */ + cp_write(sd, 0x40, 0x80); /* CP core pre-gain control. Graphics mode */ + + break; + default: + v4l2_err(sd, "%s: reserved primary mode 0x%0x\n", __func__, prim_mode); + break; + } +} + +static int adv7604_s_routing(struct v4l2_subdev *sd, + u32 input, u32 output, u32 config) +{ + struct adv7604_state *state = to_state(sd); + + v4l2_dbg(2, debug, sd, "%s: input %d", __func__, input); + + switch (input) { + case 0: + /* TODO select HDMI_COMP or HDMI_GR */ + state->prim_mode = ADV7604_PRIM_MODE_HDMI_COMP; + break; + case 1: + state->prim_mode = ADV7604_PRIM_MODE_RGB; + break; + case 2: + state->prim_mode = ADV7604_PRIM_MODE_COMP; + break; + default: + return -EINVAL; + } + + disable_input(sd); + + select_input(sd, state->prim_mode); + + enable_input(sd, state->prim_mode); + + return 0; +} + +static int adv7604_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned int index, + enum v4l2_mbus_pixelcode *code) +{ + if (index) + return -EINVAL; + /* Good enough for now */ + *code = V4L2_MBUS_FMT_FIXED; + return 0; +} + +static int adv7604_g_mbus_fmt(struct v4l2_subdev *sd, + struct v4l2_mbus_framefmt *fmt) +{ + struct adv7604_state *state = to_state(sd); + + fmt->width = state->timings.bt.width; + fmt->height = state->timings.bt.height; + fmt->code = V4L2_MBUS_FMT_FIXED; + fmt->field = V4L2_FIELD_NONE; + if (state->timings.bt.standards & V4L2_DV_BT_STD_CEA861) { + fmt->colorspace = (state->timings.bt.height <= 576) ? + V4L2_COLORSPACE_SMPTE170M : V4L2_COLORSPACE_REC709; + } + return 0; +} + +static int adv7604_isr(struct v4l2_subdev *sd, u32 status, bool *handled) +{ + struct adv7604_state *state = to_state(sd); + u8 fmt_change, fmt_change_digital, tx_5v; + + /* format change */ + fmt_change = io_read(sd, 0x43) & 0x98; + if (fmt_change) + io_write(sd, 0x44, fmt_change); + fmt_change_digital = DIGITAL_INPUT ? (io_read(sd, 0x6b) & 0xc0) : 0; + if (fmt_change_digital) + io_write(sd, 0x6c, fmt_change_digital); + if (fmt_change || fmt_change_digital) { + v4l2_dbg(1, debug, sd, + "%s: ADV7604_FMT_CHANGE, fmt_change = 0x%x, fmt_change_digital = 0x%x\n", + __func__, fmt_change, fmt_change_digital); + v4l2_subdev_notify(sd, ADV7604_FMT_CHANGE, NULL); + if (handled) + *handled = true; + } + /* tx 5v detect */ + tx_5v = io_read(sd, 0x70) & 0x10; + if (tx_5v) { + v4l2_dbg(1, debug, sd, "%s: tx_5v: 0x%x\n", __func__, tx_5v); + io_write(sd, 0x71, tx_5v); + adv7604_s_detect_tx_5v_ctrl(sd); + if (handled) + *handled = true; + } + return 0; +} + +static int adv7604_get_edid(struct v4l2_subdev *sd, struct v4l2_subdev_edid *edid) +{ + struct adv7604_state *state = to_state(sd); + + if (edid->pad != 0) + return -EINVAL; + if (edid->blocks == 0) + return -EINVAL; + if (edid->start_block >= state->edid_blocks) + return -EINVAL; + if (edid->start_block + edid->blocks > state->edid_blocks) + edid->blocks = state->edid_blocks - edid->start_block; + if (!edid->edid) + return -EINVAL; + memcpy(edid->edid + edid->start_block * 128, + state->edid + edid->start_block * 128, + edid->blocks * 128); + return 0; +} + +static int adv7604_set_edid(struct v4l2_subdev *sd, struct v4l2_subdev_edid *edid) +{ + struct adv7604_state *state = to_state(sd); + int err; + + if (edid->pad != 0) + return -EINVAL; + if (edid->start_block != 0) + return -EINVAL; + if (edid->blocks == 0) { + /* Pull down the hotplug pin */ + v4l2_subdev_notify(sd, ADV7604_HOTPLUG, (void *)0); + /* Disables I2C access to internal EDID ram from DDC port */ + rep_write_and_or(sd, 0x77, 0xf0, 0x0); + state->edid_blocks = 0; + /* Fall back to a 16:9 aspect ratio */ + state->aspect_ratio.numerator = 16; + state->aspect_ratio.denominator = 9; + return 0; + } + if (edid->blocks > 2) + return -E2BIG; + if (!edid->edid) + return -EINVAL; + memcpy(state->edid, edid->edid, 128 * edid->blocks); + state->edid_blocks = edid->blocks; + state->aspect_ratio = v4l2_calc_aspect_ratio(edid->edid[0x15], + edid->edid[0x16]); + err = edid_write_block(sd, 128 * edid->blocks, state->edid); + if (err < 0) + v4l2_err(sd, "error %d writing edid\n", err); + return err; +} + +/*********** avi info frame CEA-861-E **************/ + +static void print_avi_infoframe(struct v4l2_subdev *sd) +{ + int i; + u8 buf[14]; + u8 avi_len; + u8 avi_ver; + + if (!(hdmi_read(sd, 0x05) & 0x80)) { + v4l2_info(sd, "receive DVI-D signal (AVI infoframe not supported)\n"); + return; + } + if (!(io_read(sd, 0x60) & 0x01)) { + v4l2_info(sd, "AVI infoframe not received\n"); + return; + } + + if (io_read(sd, 0x83) & 0x01) { + v4l2_info(sd, "AVI infoframe checksum error has occurred earlier\n"); + io_write(sd, 0x85, 0x01); /* clear AVI_INF_CKS_ERR_RAW */ + if (io_read(sd, 0x83) & 0x01) { + v4l2_info(sd, "AVI infoframe checksum error still present\n"); + io_write(sd, 0x85, 0x01); /* clear AVI_INF_CKS_ERR_RAW */ + } + } + + avi_len = infoframe_read(sd, 0xe2); + avi_ver = infoframe_read(sd, 0xe1); + v4l2_info(sd, "AVI infoframe version %d (%d byte)\n", + avi_ver, avi_len); + + if (avi_ver != 0x02) + return; + + for (i = 0; i < 14; i++) + buf[i] = infoframe_read(sd, i); + + v4l2_info(sd, + "\t%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", + buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7], + buf[8], buf[9], buf[10], buf[11], buf[12], buf[13]); +} + +static int adv7604_log_status(struct v4l2_subdev *sd) +{ + struct adv7604_state *state = to_state(sd); + struct v4l2_dv_timings timings; + struct stdi_readback stdi; + u8 reg_io_0x02 = io_read(sd, 0x02); + + char *csc_coeff_sel_rb[16] = { + "bypassed", "YPbPr601 -> RGB", "reserved", "YPbPr709 -> RGB", + "reserved", "RGB -> YPbPr601", "reserved", "RGB -> YPbPr709", + "reserved", "YPbPr709 -> YPbPr601", "YPbPr601 -> YPbPr709", + "reserved", "reserved", "reserved", "reserved", "manual" + }; + char *input_color_space_txt[16] = { + "RGB limited range (16-235)", "RGB full range (0-255)", + "YCbCr Bt.601 (16-235)", "YCbCr Bt.709 (16-235)", + "XvYCC Bt.601", "XvYCC Bt.709", + "YCbCr Bt.601 (0-255)", "YCbCr Bt.709 (0-255)", + "invalid", "invalid", "invalid", "invalid", "invalid", + "invalid", "invalid", "automatic" + }; + char *rgb_quantization_range_txt[] = { + "Automatic", + "RGB limited range (16-235)", + "RGB full range (0-255)", + }; + + v4l2_info(sd, "-----Chip status-----\n"); + v4l2_info(sd, "Chip power: %s\n", no_power(sd) ? "off" : "on"); + v4l2_info(sd, "Connector type: %s\n", state->connector_hdmi ? + "HDMI" : (DIGITAL_INPUT ? "DVI-D" : "DVI-A")); + v4l2_info(sd, "EDID: %s\n", ((rep_read(sd, 0x7d) & 0x01) && + (rep_read(sd, 0x77) & 0x01)) ? "enabled" : "disabled "); + v4l2_info(sd, "CEC: %s\n", !!(cec_read(sd, 0x2a) & 0x01) ? + "enabled" : "disabled"); + + v4l2_info(sd, "-----Signal status-----\n"); + v4l2_info(sd, "Cable detected (+5V power): %s\n", + (io_read(sd, 0x6f) & 0x10) ? "true" : "false"); + v4l2_info(sd, "TMDS signal detected: %s\n", + no_signal_tmds(sd) ? "false" : "true"); + v4l2_info(sd, "TMDS signal locked: %s\n", + no_lock_tmds(sd) ? "false" : "true"); + v4l2_info(sd, "SSPD locked: %s\n", no_lock_sspd(sd) ? "false" : "true"); + v4l2_info(sd, "STDI locked: %s\n", no_lock_stdi(sd) ? "false" : "true"); + v4l2_info(sd, "CP locked: %s\n", no_lock_cp(sd) ? "false" : "true"); + v4l2_info(sd, "CP free run: %s\n", + (!!(cp_read(sd, 0xff) & 0x10) ? "on" : "off")); + v4l2_info(sd, "Prim-mode = 0x%x, video std = 0x%x\n", + io_read(sd, 0x01) & 0x0f, io_read(sd, 0x00) & 0x3f); + + v4l2_info(sd, "-----Video Timings-----\n"); + if (read_stdi(sd, &stdi)) + v4l2_info(sd, "STDI: not locked\n"); + else + v4l2_info(sd, "STDI: lcf (frame height - 1) = %d, bl = %d, lcvs (vsync) = %d, %s, %chsync, %cvsync\n", + stdi.lcf, stdi.bl, stdi.lcvs, + stdi.interlaced ? "interlaced" : "progressive", + stdi.hs_pol, stdi.vs_pol); + if (adv7604_query_dv_timings(sd, &timings)) + v4l2_info(sd, "No video detected\n"); + else + adv7604_print_timings(sd, &timings, "Detected format:", true); + adv7604_print_timings(sd, &state->timings, "Configured format:", true); + + v4l2_info(sd, "-----Color space-----\n"); + v4l2_info(sd, "RGB quantization range ctrl: %s\n", + rgb_quantization_range_txt[state->rgb_quantization_range]); + v4l2_info(sd, "Input color space: %s\n", + input_color_space_txt[reg_io_0x02 >> 4]); + v4l2_info(sd, "Output color space: %s %s, saturator %s\n", + (reg_io_0x02 & 0x02) ? "RGB" : "YCbCr", + (reg_io_0x02 & 0x04) ? "(16-235)" : "(0-255)", + ((reg_io_0x02 & 0x04) ^ (reg_io_0x02 & 0x01)) ? + "enabled" : "disabled"); + v4l2_info(sd, "Color space conversion: %s\n", + csc_coeff_sel_rb[cp_read(sd, 0xfc) >> 4]); + + /* Digital video */ + if (DIGITAL_INPUT) { + v4l2_info(sd, "-----HDMI status-----\n"); + v4l2_info(sd, "HDCP encrypted content: %s\n", + hdmi_read(sd, 0x05) & 0x40 ? "true" : "false"); + + print_avi_infoframe(sd); + } + + return 0; +} + +/* ----------------------------------------------------------------------- */ + +static const struct v4l2_ctrl_ops adv7604_ctrl_ops = { + .s_ctrl = adv7604_s_ctrl, +}; + +static const struct v4l2_subdev_core_ops adv7604_core_ops = { + .log_status = adv7604_log_status, + .g_ext_ctrls = v4l2_subdev_g_ext_ctrls, + .try_ext_ctrls = v4l2_subdev_try_ext_ctrls, + .s_ext_ctrls = v4l2_subdev_s_ext_ctrls, + .g_ctrl = v4l2_subdev_g_ctrl, + .s_ctrl = v4l2_subdev_s_ctrl, + .queryctrl = v4l2_subdev_queryctrl, + .querymenu = v4l2_subdev_querymenu, + .g_chip_ident = adv7604_g_chip_ident, + .interrupt_service_routine = adv7604_isr, +#ifdef CONFIG_VIDEO_ADV_DEBUG + .g_register = adv7604_g_register, + .s_register = adv7604_s_register, +#endif +}; + +static const struct v4l2_subdev_video_ops adv7604_video_ops = { + .s_routing = adv7604_s_routing, + .g_input_status = adv7604_g_input_status, + .s_dv_timings = adv7604_s_dv_timings, + .g_dv_timings = adv7604_g_dv_timings, + .query_dv_timings = adv7604_query_dv_timings, + .enum_dv_timings = adv7604_enum_dv_timings, + .dv_timings_cap = adv7604_dv_timings_cap, + .enum_mbus_fmt = adv7604_enum_mbus_fmt, + .g_mbus_fmt = adv7604_g_mbus_fmt, + .try_mbus_fmt = adv7604_g_mbus_fmt, + .s_mbus_fmt = adv7604_g_mbus_fmt, +}; + +static const struct v4l2_subdev_pad_ops adv7604_pad_ops = { + .get_edid = adv7604_get_edid, + .set_edid = adv7604_set_edid, +}; + +static const struct v4l2_subdev_ops adv7604_ops = { + .core = &adv7604_core_ops, + .video = &adv7604_video_ops, + .pad = &adv7604_pad_ops, +}; + +/* -------------------------- custom ctrls ---------------------------------- */ + +static const struct v4l2_ctrl_config adv7604_ctrl_analog_sampling_phase = { + .ops = &adv7604_ctrl_ops, + .id = V4L2_CID_ADV_RX_ANALOG_SAMPLING_PHASE, + .name = "Analog Sampling Phase", + .type = V4L2_CTRL_TYPE_INTEGER, + .min = 0, + .max = 0x1f, + .step = 1, + .def = 0, +}; + +static const struct v4l2_ctrl_config adv7604_ctrl_free_run_color_manual = { + .ops = &adv7604_ctrl_ops, + .id = V4L2_CID_ADV_RX_FREE_RUN_COLOR_MANUAL, + .name = "Free Running Color, Manual", + .type = V4L2_CTRL_TYPE_BOOLEAN, + .min = false, + .max = true, + .step = 1, + .def = false, +}; + +static const struct v4l2_ctrl_config adv7604_ctrl_free_run_color = { + .ops = &adv7604_ctrl_ops, + .id = V4L2_CID_ADV_RX_FREE_RUN_COLOR, + .name = "Free Running Color", + .type = V4L2_CTRL_TYPE_INTEGER, + .min = 0x0, + .max = 0xffffff, + .step = 0x1, + .def = 0x0, +}; + +/* ----------------------------------------------------------------------- */ + +static int adv7604_core_init(struct v4l2_subdev *sd) +{ + struct adv7604_state *state = to_state(sd); + struct adv7604_platform_data *pdata = &state->pdata; + + hdmi_write(sd, 0x48, + (pdata->disable_pwrdnb ? 0x80 : 0) | + (pdata->disable_cable_det_rst ? 0x40 : 0)); + + disable_input(sd); + + /* power */ + io_write(sd, 0x0c, 0x42); /* Power up part and power down VDP */ + io_write(sd, 0x0b, 0x44); /* Power down ESDP block */ + cp_write(sd, 0xcf, 0x01); /* Power down macrovision */ + + /* video format */ + io_write_and_or(sd, 0x02, 0xf0, + pdata->alt_gamma << 3 | + pdata->op_656_range << 2 | + pdata->rgb_out << 1 | + pdata->alt_data_sat << 0); + io_write(sd, 0x03, pdata->op_format_sel); + io_write_and_or(sd, 0x04, 0x1f, pdata->op_ch_sel << 5); + io_write_and_or(sd, 0x05, 0xf0, pdata->blank_data << 3 | + pdata->insert_av_codes << 2 | + pdata->replicate_av_codes << 1 | + pdata->invert_cbcr << 0); + + /* TODO from platform data */ + cp_write(sd, 0x69, 0x30); /* Enable CP CSC */ + io_write(sd, 0x06, 0xa6); /* positive VS and HS */ + io_write(sd, 0x14, 0x7f); /* Drive strength adjusted to max */ + cp_write(sd, 0xba, (pdata->hdmi_free_run_mode << 1) | 0x01); /* HDMI free run */ + cp_write(sd, 0xf3, 0xdc); /* Low threshold to enter/exit free run mode */ + cp_write(sd, 0xf9, 0x23); /* STDI ch. 1 - LCVS change threshold - + ADI recommended setting [REF_01 c. 2.3.3] */ + cp_write(sd, 0x45, 0x23); /* STDI ch. 2 - LCVS change threshold - + ADI recommended setting [REF_01 c. 2.3.3] */ + cp_write(sd, 0xc9, 0x2d); /* use prim_mode and vid_std as free run resolution + for digital formats */ + + /* TODO from platform data */ + afe_write(sd, 0xb5, 0x01); /* Setting MCLK to 256Fs */ + + afe_write(sd, 0x02, pdata->ain_sel); /* Select analog input muxing mode */ + io_write_and_or(sd, 0x30, ~(1 << 4), pdata->output_bus_lsb_to_msb << 4); + + state->prim_mode = pdata->prim_mode; + select_input(sd, pdata->prim_mode); + + enable_input(sd, pdata->prim_mode); + + /* interrupts */ + io_write(sd, 0x40, 0xc2); /* Configure INT1 */ + io_write(sd, 0x41, 0xd7); /* STDI irq for any change, disable INT2 */ + io_write(sd, 0x46, 0x98); /* Enable SSPD, STDI and CP unlocked interrupts */ + io_write(sd, 0x6e, 0xc0); /* Enable V_LOCKED and DE_REGEN_LCK interrupts */ + io_write(sd, 0x73, 0x10); /* Enable CABLE_DET_A_ST (+5v) interrupt */ + + return v4l2_ctrl_handler_setup(sd->ctrl_handler); +} + +static void adv7604_unregister_clients(struct adv7604_state *state) +{ + if (state->i2c_avlink) + i2c_unregister_device(state->i2c_avlink); + if (state->i2c_cec) + i2c_unregister_device(state->i2c_cec); + if (state->i2c_infoframe) + i2c_unregister_device(state->i2c_infoframe); + if (state->i2c_esdp) + i2c_unregister_device(state->i2c_esdp); + if (state->i2c_dpp) + i2c_unregister_device(state->i2c_dpp); + if (state->i2c_afe) + i2c_unregister_device(state->i2c_afe); + if (state->i2c_repeater) + i2c_unregister_device(state->i2c_repeater); + if (state->i2c_edid) + i2c_unregister_device(state->i2c_edid); + if (state->i2c_hdmi) + i2c_unregister_device(state->i2c_hdmi); + if (state->i2c_test) + i2c_unregister_device(state->i2c_test); + if (state->i2c_cp) + i2c_unregister_device(state->i2c_cp); + if (state->i2c_vdp) + i2c_unregister_device(state->i2c_vdp); +} + +static struct i2c_client *adv7604_dummy_client(struct v4l2_subdev *sd, + u8 addr, u8 io_reg) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + + if (addr) + io_write(sd, io_reg, addr << 1); + return i2c_new_dummy(client->adapter, io_read(sd, io_reg) >> 1); +} + +static int adv7604_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct adv7604_state *state; + struct adv7604_platform_data *pdata = client->dev.platform_data; + struct v4l2_ctrl_handler *hdl; + struct v4l2_subdev *sd; + int err; + + /* Check if the adapter supports the needed features */ + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) + return -EIO; + v4l_dbg(1, debug, client, "detecting adv7604 client on address 0x%x\n", + client->addr << 1); + + state = kzalloc(sizeof(struct adv7604_state), GFP_KERNEL); + if (!state) { + v4l_err(client, "Could not allocate adv7604_state memory!\n"); + return -ENOMEM; + } + + /* platform data */ + if (!pdata) { + v4l_err(client, "No platform data!\n"); + err = -ENODEV; + goto err_state; + } + memcpy(&state->pdata, pdata, sizeof(state->pdata)); + + sd = &state->sd; + v4l2_i2c_subdev_init(sd, client, &adv7604_ops); + sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; + state->connector_hdmi = pdata->connector_hdmi; + + /* i2c access to adv7604? */ + if (adv_smbus_read_byte_data_check(client, 0xfb, false) != 0x68) { + v4l2_info(sd, "not an adv7604 on address 0x%x\n", + client->addr << 1); + err = -ENODEV; + goto err_state; + } + + /* control handlers */ + hdl = &state->hdl; + v4l2_ctrl_handler_init(hdl, 9); + + v4l2_ctrl_new_std(hdl, &adv7604_ctrl_ops, + V4L2_CID_BRIGHTNESS, -128, 127, 1, 0); + v4l2_ctrl_new_std(hdl, &adv7604_ctrl_ops, + V4L2_CID_CONTRAST, 0, 255, 1, 128); + v4l2_ctrl_new_std(hdl, &adv7604_ctrl_ops, + V4L2_CID_SATURATION, 0, 255, 1, 128); + v4l2_ctrl_new_std(hdl, &adv7604_ctrl_ops, + V4L2_CID_HUE, 0, 128, 1, 0); + + /* private controls */ + state->detect_tx_5v_ctrl = v4l2_ctrl_new_std(hdl, NULL, + V4L2_CID_DV_RX_POWER_PRESENT, 0, 1, 0, 0); + state->detect_tx_5v_ctrl->is_private = true; + state->rgb_quantization_range_ctrl = + v4l2_ctrl_new_std_menu(hdl, &adv7604_ctrl_ops, + V4L2_CID_DV_RX_RGB_RANGE, V4L2_DV_RGB_RANGE_FULL, + 0, V4L2_DV_RGB_RANGE_AUTO); + state->rgb_quantization_range_ctrl->is_private = true; + + /* custom controls */ + state->analog_sampling_phase_ctrl = + v4l2_ctrl_new_custom(hdl, &adv7604_ctrl_analog_sampling_phase, NULL); + state->analog_sampling_phase_ctrl->is_private = true; + state->free_run_color_manual_ctrl = + v4l2_ctrl_new_custom(hdl, &adv7604_ctrl_free_run_color_manual, NULL); + state->free_run_color_manual_ctrl->is_private = true; + state->free_run_color_ctrl = + v4l2_ctrl_new_custom(hdl, &adv7604_ctrl_free_run_color, NULL); + state->free_run_color_ctrl->is_private = true; + + sd->ctrl_handler = hdl; + if (hdl->error) { + err = hdl->error; + goto err_hdl; + } + if (adv7604_s_detect_tx_5v_ctrl(sd)) { + err = -ENODEV; + goto err_hdl; + } + + state->i2c_avlink = adv7604_dummy_client(sd, pdata->i2c_avlink, 0xf3); + state->i2c_cec = adv7604_dummy_client(sd, pdata->i2c_cec, 0xf4); + state->i2c_infoframe = adv7604_dummy_client(sd, pdata->i2c_infoframe, 0xf5); + state->i2c_esdp = adv7604_dummy_client(sd, pdata->i2c_esdp, 0xf6); + state->i2c_dpp = adv7604_dummy_client(sd, pdata->i2c_dpp, 0xf7); + state->i2c_afe = adv7604_dummy_client(sd, pdata->i2c_afe, 0xf8); + state->i2c_repeater = adv7604_dummy_client(sd, pdata->i2c_repeater, 0xf9); + state->i2c_edid = adv7604_dummy_client(sd, pdata->i2c_edid, 0xfa); + state->i2c_hdmi = adv7604_dummy_client(sd, pdata->i2c_hdmi, 0xfb); + state->i2c_test = adv7604_dummy_client(sd, pdata->i2c_test, 0xfc); + state->i2c_cp = adv7604_dummy_client(sd, pdata->i2c_cp, 0xfd); + state->i2c_vdp = adv7604_dummy_client(sd, pdata->i2c_vdp, 0xfe); + if (!state->i2c_avlink || !state->i2c_cec || !state->i2c_infoframe || + !state->i2c_esdp || !state->i2c_dpp || !state->i2c_afe || + !state->i2c_repeater || !state->i2c_edid || !state->i2c_hdmi || + !state->i2c_test || !state->i2c_cp || !state->i2c_vdp) { + err = -ENOMEM; + v4l2_err(sd, "failed to create all i2c clients\n"); + goto err_i2c; + } + + /* work queues */ + state->work_queues = create_singlethread_workqueue(client->name); + if (!state->work_queues) { + v4l2_err(sd, "Could not create work queue\n"); + err = -ENOMEM; + goto err_i2c; + } + + INIT_DELAYED_WORK(&state->delayed_work_enable_hotplug, + adv7604_delayed_work_enable_hotplug); + + state->pad.flags = MEDIA_PAD_FL_SOURCE; + err = media_entity_init(&sd->entity, 1, &state->pad, 0); + if (err) + goto err_work_queues; + + err = adv7604_core_init(sd); + if (err) + goto err_entity; + v4l2_info(sd, "%s found @ 0x%x (%s)\n", client->name, + client->addr << 1, client->adapter->name); + return 0; + +err_entity: + media_entity_cleanup(&sd->entity); +err_work_queues: + cancel_delayed_work(&state->delayed_work_enable_hotplug); + destroy_workqueue(state->work_queues); +err_i2c: + adv7604_unregister_clients(state); +err_hdl: + v4l2_ctrl_handler_free(hdl); +err_state: + kfree(state); + return err; +} + +/* ----------------------------------------------------------------------- */ + +static int adv7604_remove(struct i2c_client *client) +{ + struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct adv7604_state *state = to_state(sd); + + cancel_delayed_work(&state->delayed_work_enable_hotplug); + destroy_workqueue(state->work_queues); + v4l2_device_unregister_subdev(sd); + media_entity_cleanup(&sd->entity); + adv7604_unregister_clients(to_state(sd)); + v4l2_ctrl_handler_free(sd->ctrl_handler); + kfree(to_state(sd)); + return 0; +} + +/* ----------------------------------------------------------------------- */ + +static struct i2c_device_id adv7604_id[] = { + { "adv7604", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, adv7604_id); + +static struct i2c_driver adv7604_driver = { + .driver = { + .owner = THIS_MODULE, + .name = "adv7604", + }, + .probe = adv7604_probe, + .remove = adv7604_remove, + .id_table = adv7604_id, +}; + +module_i2c_driver(adv7604_driver); diff --git a/drivers/media/video/ak881x.c b/drivers/media/i2c/ak881x.c index ba674656b10d..ba674656b10d 100644 --- a/drivers/media/video/ak881x.c +++ b/drivers/media/i2c/ak881x.c diff --git a/drivers/media/video/aptina-pll.c b/drivers/media/i2c/aptina-pll.c index 8153a449846b..8153a449846b 100644 --- a/drivers/media/video/aptina-pll.c +++ b/drivers/media/i2c/aptina-pll.c diff --git a/drivers/media/video/aptina-pll.h b/drivers/media/i2c/aptina-pll.h index b370e341e75d..b370e341e75d 100644 --- a/drivers/media/video/aptina-pll.h +++ b/drivers/media/i2c/aptina-pll.h diff --git a/drivers/media/video/as3645a.c b/drivers/media/i2c/as3645a.c index c4b03572dce8..3bfdbf9d9bf1 100644 --- a/drivers/media/video/as3645a.c +++ b/drivers/media/i2c/as3645a.c @@ -1,5 +1,5 @@ /* - * drivers/media/video/as3645a.c - AS3645A and LM3555 flash controllers driver + * drivers/media/i2c/as3645a.c - AS3645A and LM3555 flash controllers driver * * Copyright (C) 2008-2011 Nokia Corporation * Copyright (c) 2011, Intel Corporation. diff --git a/drivers/media/video/bt819.c b/drivers/media/i2c/bt819.c index 377bf05b1efd..377bf05b1efd 100644 --- a/drivers/media/video/bt819.c +++ b/drivers/media/i2c/bt819.c diff --git a/drivers/media/video/bt856.c b/drivers/media/i2c/bt856.c index 7e5bd365c239..7e5bd365c239 100644 --- a/drivers/media/video/bt856.c +++ b/drivers/media/i2c/bt856.c diff --git a/drivers/media/video/bt866.c b/drivers/media/i2c/bt866.c index 905320b67a1c..905320b67a1c 100644 --- a/drivers/media/video/bt866.c +++ b/drivers/media/i2c/bt866.c diff --git a/drivers/media/video/btcx-risc.c b/drivers/media/i2c/btcx-risc.c index ac1b2687a20d..ac1b2687a20d 100644 --- a/drivers/media/video/btcx-risc.c +++ b/drivers/media/i2c/btcx-risc.c diff --git a/drivers/media/video/btcx-risc.h b/drivers/media/i2c/btcx-risc.h index f8bc6e8e7b51..f8bc6e8e7b51 100644 --- a/drivers/media/video/btcx-risc.h +++ b/drivers/media/i2c/btcx-risc.h diff --git a/drivers/media/video/cs5345.c b/drivers/media/i2c/cs5345.c index c8581e26fa9c..c8581e26fa9c 100644 --- a/drivers/media/video/cs5345.c +++ b/drivers/media/i2c/cs5345.c diff --git a/drivers/media/video/cs53l32a.c b/drivers/media/i2c/cs53l32a.c index b293912206eb..b293912206eb 100644 --- a/drivers/media/video/cs53l32a.c +++ b/drivers/media/i2c/cs53l32a.c diff --git a/drivers/media/video/cx2341x.c b/drivers/media/i2c/cx2341x.c index 103ef6bad2e2..103ef6bad2e2 100644 --- a/drivers/media/video/cx2341x.c +++ b/drivers/media/i2c/cx2341x.c diff --git a/drivers/media/video/cx25840/Kconfig b/drivers/media/i2c/cx25840/Kconfig index 451133ad41ff..451133ad41ff 100644 --- a/drivers/media/video/cx25840/Kconfig +++ b/drivers/media/i2c/cx25840/Kconfig diff --git a/drivers/media/video/cx25840/Makefile b/drivers/media/i2c/cx25840/Makefile index dc40dde2e0c8..898eb13340ae 100644 --- a/drivers/media/video/cx25840/Makefile +++ b/drivers/media/i2c/cx25840/Makefile @@ -3,4 +3,4 @@ cx25840-objs := cx25840-core.o cx25840-audio.o cx25840-firmware.o \ obj-$(CONFIG_VIDEO_CX25840) += cx25840.o -ccflags-y += -Idrivers/media/video +ccflags-y += -Idrivers/media/i2c diff --git a/drivers/media/video/cx25840/cx25840-audio.c b/drivers/media/i2c/cx25840/cx25840-audio.c index 34b96c7cfd62..34b96c7cfd62 100644 --- a/drivers/media/video/cx25840/cx25840-audio.c +++ b/drivers/media/i2c/cx25840/cx25840-audio.c diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/i2c/cx25840/cx25840-core.c index d8eac3e30a7e..d8eac3e30a7e 100644 --- a/drivers/media/video/cx25840/cx25840-core.c +++ b/drivers/media/i2c/cx25840/cx25840-core.c diff --git a/drivers/media/video/cx25840/cx25840-core.h b/drivers/media/i2c/cx25840/cx25840-core.h index bd4ada28b490..bd4ada28b490 100644 --- a/drivers/media/video/cx25840/cx25840-core.h +++ b/drivers/media/i2c/cx25840/cx25840-core.h diff --git a/drivers/media/video/cx25840/cx25840-firmware.c b/drivers/media/i2c/cx25840/cx25840-firmware.c index 8150200511da..b3169f94ece8 100644 --- a/drivers/media/video/cx25840/cx25840-firmware.c +++ b/drivers/media/i2c/cx25840/cx25840-firmware.c @@ -61,6 +61,10 @@ static void end_fw_load(struct i2c_client *client) cx25840_write(client, 0x803, 0x03); } +#define CX2388x_FIRMWARE "v4l-cx23885-avcore-01.fw" +#define CX231xx_FIRMWARE "v4l-cx231xx-avcore-01.fw" +#define CX25840_FIRMWARE "v4l-cx25840.fw" + static const char *get_fw_name(struct i2c_client *client) { struct cx25840_state *state = to_state(i2c_get_clientdata(client)); @@ -68,10 +72,10 @@ static const char *get_fw_name(struct i2c_client *client) if (firmware[0]) return firmware; if (is_cx2388x(state)) - return "v4l-cx23885-avcore-01.fw"; + return CX2388x_FIRMWARE; if (is_cx231xx(state)) - return "v4l-cx231xx-avcore-01.fw"; - return "v4l-cx25840.fw"; + return CX231xx_FIRMWARE; + return CX25840_FIRMWARE; } static int check_fw_load(struct i2c_client *client, int size) @@ -164,3 +168,8 @@ int cx25840_loadfw(struct i2c_client *client) return check_fw_load(client, size); } + +MODULE_FIRMWARE(CX2388x_FIRMWARE); +MODULE_FIRMWARE(CX231xx_FIRMWARE); +MODULE_FIRMWARE(CX25840_FIRMWARE); + diff --git a/drivers/media/video/cx25840/cx25840-ir.c b/drivers/media/i2c/cx25840/cx25840-ir.c index 38ce76ed1924..38ce76ed1924 100644 --- a/drivers/media/video/cx25840/cx25840-ir.c +++ b/drivers/media/i2c/cx25840/cx25840-ir.c diff --git a/drivers/media/video/cx25840/cx25840-vbi.c b/drivers/media/i2c/cx25840/cx25840-vbi.c index 64a4004f8a97..c39e91dc1137 100644 --- a/drivers/media/video/cx25840/cx25840-vbi.c +++ b/drivers/media/i2c/cx25840/cx25840-vbi.c @@ -96,7 +96,8 @@ int cx25840_g_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format * int is_pal = !(state->std & V4L2_STD_525_60); int i; - memset(svbi, 0, sizeof(*svbi)); + memset(svbi->service_lines, 0, sizeof(svbi->service_lines)); + svbi->service_set = 0; /* we're done if raw VBI is active */ if ((cx25840_read(client, 0x404) & 0x10) == 0) return 0; diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/i2c/ir-kbd-i2c.c index 04f192a0398a..04f192a0398a 100644 --- a/drivers/media/video/ir-kbd-i2c.c +++ b/drivers/media/i2c/ir-kbd-i2c.c diff --git a/drivers/media/video/ks0127.c b/drivers/media/i2c/ks0127.c index ee7ca2dcca2f..04a6efa37cc3 100644 --- a/drivers/media/video/ks0127.c +++ b/drivers/media/i2c/ks0127.c @@ -319,8 +319,17 @@ static u8 ks0127_read(struct v4l2_subdev *sd, u8 reg) struct i2c_client *client = v4l2_get_subdevdata(sd); char val = 0; struct i2c_msg msgs[] = { - { client->addr, 0, sizeof(reg), ® }, - { client->addr, I2C_M_RD | I2C_M_NO_RD_ACK, sizeof(val), &val } + { + .addr = client->addr, + .len = sizeof(reg), + .buf = ® + }, + { + .addr = client->addr, + .flags = I2C_M_RD | I2C_M_NO_RD_ACK, + .len = sizeof(val), + .buf = &val + } }; int ret; diff --git a/drivers/media/video/ks0127.h b/drivers/media/i2c/ks0127.h index cb8abd5403b3..cb8abd5403b3 100644 --- a/drivers/media/video/ks0127.h +++ b/drivers/media/i2c/ks0127.h diff --git a/drivers/media/video/m52790.c b/drivers/media/i2c/m52790.c index 0991576f4c82..0991576f4c82 100644 --- a/drivers/media/video/m52790.c +++ b/drivers/media/i2c/m52790.c diff --git a/drivers/media/video/m5mols/Kconfig b/drivers/media/i2c/m5mols/Kconfig index dc8c2505907e..dc8c2505907e 100644 --- a/drivers/media/video/m5mols/Kconfig +++ b/drivers/media/i2c/m5mols/Kconfig diff --git a/drivers/media/video/m5mols/Makefile b/drivers/media/i2c/m5mols/Makefile index 0a44e028edc7..0a44e028edc7 100644 --- a/drivers/media/video/m5mols/Makefile +++ b/drivers/media/i2c/m5mols/Makefile diff --git a/drivers/media/video/m5mols/m5mols.h b/drivers/media/i2c/m5mols/m5mols.h index bb589917b65b..86c815be348c 100644 --- a/drivers/media/video/m5mols/m5mols.h +++ b/drivers/media/i2c/m5mols/m5mols.h @@ -155,8 +155,6 @@ struct m5mols_version { * @pdata: platform data * @sd: v4l-subdev instance * @pad: media pad - * @ffmt: current fmt according to resolution type - * @res_type: current resolution type * @irq_waitq: waitqueue for the capture * @irq_done: set to 1 in the interrupt handler * @handle: control handler @@ -174,6 +172,10 @@ struct m5mols_version { * @wdr: wide dynamic range control * @stabilization: image stabilization control * @jpeg_quality: JPEG compression quality control + * @set_power: optional power callback to the board code + * @lock: mutex protecting the structure fields below + * @ffmt: current fmt according to resolution type + * @res_type: current resolution type * @ver: information of the version * @cap: the capture mode attributes * @isp_ready: 1 when the ISP controller has completed booting @@ -181,14 +183,11 @@ struct m5mols_version { * @ctrl_sync: 1 when the control handler state is restored in H/W * @resolution: register value for current resolution * @mode: register value for current operation mode - * @set_power: optional power callback to the board code */ struct m5mols_info { const struct m5mols_platform_data *pdata; struct v4l2_subdev sd; struct media_pad pad; - struct v4l2_mbus_framefmt ffmt[M5MOLS_RESTYPE_MAX]; - int res_type; wait_queue_head_t irq_waitq; atomic_t irq_done; @@ -216,6 +215,13 @@ struct m5mols_info { struct v4l2_ctrl *stabilization; struct v4l2_ctrl *jpeg_quality; + int (*set_power)(struct device *dev, int on); + + struct mutex lock; + + struct v4l2_mbus_framefmt ffmt[M5MOLS_RESTYPE_MAX]; + int res_type; + struct m5mols_version ver; struct m5mols_capture cap; @@ -225,8 +231,6 @@ struct m5mols_info { u8 resolution; u8 mode; - - int (*set_power)(struct device *dev, int on); }; #define is_available_af(__info) (__info->ver.af) @@ -323,12 +327,12 @@ static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl) static inline void m5mols_set_ctrl_mode(struct v4l2_ctrl *ctrl, unsigned int mode) { - ctrl->priv = (void *)mode; + ctrl->priv = (void *)(uintptr_t)mode; } static inline unsigned int m5mols_get_ctrl_mode(struct v4l2_ctrl *ctrl) { - return (unsigned int)ctrl->priv; + return (unsigned int)(uintptr_t)ctrl->priv; } #endif /* M5MOLS_H */ diff --git a/drivers/media/video/m5mols/m5mols_capture.c b/drivers/media/i2c/m5mols/m5mols_capture.c index cb243bd278ce..cb243bd278ce 100644 --- a/drivers/media/video/m5mols/m5mols_capture.c +++ b/drivers/media/i2c/m5mols/m5mols_capture.c diff --git a/drivers/media/video/m5mols/m5mols_controls.c b/drivers/media/i2c/m5mols/m5mols_controls.c index fdbc205a2969..f34429e452ab 100644 --- a/drivers/media/video/m5mols/m5mols_controls.c +++ b/drivers/media/i2c/m5mols/m5mols_controls.c @@ -463,8 +463,8 @@ static int m5mols_s_ctrl(struct v4l2_ctrl *ctrl) return 0; } - v4l2_dbg(1, m5mols_debug, sd, "%s: %s, val: %d, priv: %#x\n", - __func__, ctrl->name, ctrl->val, (int)ctrl->priv); + v4l2_dbg(1, m5mols_debug, sd, "%s: %s, val: %d, priv: %p\n", + __func__, ctrl->name, ctrl->val, ctrl->priv); if (ctrl_mode && ctrl_mode != info->mode) { ret = m5mols_set_mode(info, ctrl_mode); diff --git a/drivers/media/video/m5mols/m5mols_core.c b/drivers/media/i2c/m5mols/m5mols_core.c index ac7d28b6ddf2..2f490ef26c38 100644 --- a/drivers/media/video/m5mols/m5mols_core.c +++ b/drivers/media/i2c/m5mols/m5mols_core.c @@ -551,13 +551,18 @@ static int m5mols_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, { struct m5mols_info *info = to_m5mols(sd); struct v4l2_mbus_framefmt *format; + int ret = 0; + + mutex_lock(&info->lock); format = __find_format(info, fh, fmt->which, info->res_type); if (!format) - return -EINVAL; + fmt->format = *format; + else + ret = -EINVAL; - fmt->format = *format; - return 0; + mutex_unlock(&info->lock); + return ret; } static int m5mols_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, @@ -578,6 +583,7 @@ static int m5mols_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, if (!sfmt) return 0; + mutex_lock(&info->lock); format->code = m5mols_default_ffmt[type].code; format->colorspace = V4L2_COLORSPACE_JPEG; @@ -589,7 +595,8 @@ static int m5mols_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, info->res_type = type; } - return 0; + mutex_unlock(&info->lock); + return ret; } static int m5mols_enum_mbus_code(struct v4l2_subdev *sd, @@ -661,20 +668,25 @@ static int m5mols_start_monitor(struct m5mols_info *info) static int m5mols_s_stream(struct v4l2_subdev *sd, int enable) { struct m5mols_info *info = to_m5mols(sd); - u32 code = info->ffmt[info->res_type].code; + u32 code; + int ret; - if (enable) { - int ret = -EINVAL; + mutex_lock(&info->lock); + code = info->ffmt[info->res_type].code; + if (enable) { if (is_code(code, M5MOLS_RESTYPE_MONITOR)) ret = m5mols_start_monitor(info); if (is_code(code, M5MOLS_RESTYPE_CAPTURE)) ret = m5mols_start_capture(info); - - return ret; + else + ret = -EINVAL; + } else { + ret = m5mols_set_mode(info, REG_PARAMETER); } - return m5mols_set_mode(info, REG_PARAMETER); + mutex_unlock(&info->lock); + return ret; } static const struct v4l2_subdev_video_ops m5mols_video_ops = { @@ -773,6 +785,20 @@ static int m5mols_fw_start(struct v4l2_subdev *sd) return ret; } +/* Execute the lens soft-landing algorithm */ +static int m5mols_auto_focus_stop(struct m5mols_info *info) +{ + int ret; + + ret = m5mols_write(&info->sd, AF_EXECUTE, REG_AF_STOP); + if (!ret) + ret = m5mols_write(&info->sd, AF_MODE, REG_AF_POWEROFF); + if (!ret) + ret = m5mols_busy_wait(&info->sd, SYSTEM_STATUS, REG_AF_IDLE, + 0xff, -1); + return ret; +} + /** * m5mols_s_power - Main sensor power control function * @@ -785,29 +811,26 @@ static int m5mols_s_power(struct v4l2_subdev *sd, int on) struct m5mols_info *info = to_m5mols(sd); int ret; + mutex_lock(&info->lock); + if (on) { ret = m5mols_sensor_power(info, true); if (!ret) ret = m5mols_fw_start(sd); - return ret; - } + } else { + if (is_manufacturer(info, REG_SAMSUNG_TECHWIN)) { + ret = m5mols_set_mode(info, REG_MONITOR); + if (!ret) + ret = m5mols_auto_focus_stop(info); + if (ret < 0) + v4l2_warn(sd, "Soft landing lens failed\n"); + } + ret = m5mols_sensor_power(info, false); - if (is_manufacturer(info, REG_SAMSUNG_TECHWIN)) { - ret = m5mols_set_mode(info, REG_MONITOR); - if (!ret) - ret = m5mols_write(sd, AF_EXECUTE, REG_AF_STOP); - if (!ret) - ret = m5mols_write(sd, AF_MODE, REG_AF_POWEROFF); - if (!ret) - ret = m5mols_busy_wait(sd, SYSTEM_STATUS, REG_AF_IDLE, - 0xff, -1); - if (ret < 0) - v4l2_warn(sd, "Soft landing lens failed\n"); + info->ctrl_sync = 0; } - ret = m5mols_sensor_power(info, false); - info->ctrl_sync = 0; - + mutex_unlock(&info->lock); return ret; } @@ -822,13 +845,6 @@ static int m5mols_log_status(struct v4l2_subdev *sd) static const struct v4l2_subdev_core_ops m5mols_core_ops = { .s_power = m5mols_s_power, - .g_ctrl = v4l2_subdev_g_ctrl, - .s_ctrl = v4l2_subdev_s_ctrl, - .queryctrl = v4l2_subdev_queryctrl, - .querymenu = v4l2_subdev_querymenu, - .g_ext_ctrls = v4l2_subdev_g_ext_ctrls, - .try_ext_ctrls = v4l2_subdev_try_ext_ctrls, - .s_ext_ctrls = v4l2_subdev_s_ext_ctrls, .log_status = m5mols_log_status, }; @@ -919,6 +935,8 @@ static int __devinit m5mols_probe(struct i2c_client *client, sd->entity.type = MEDIA_ENT_T_V4L2_SUBDEV_SENSOR; init_waitqueue_head(&info->irq_waitq); + mutex_init(&info->lock); + ret = request_irq(client->irq, m5mols_irq_handler, IRQF_TRIGGER_RISING, MODULE_NAME, sd); if (ret) { @@ -931,15 +949,17 @@ static int __devinit m5mols_probe(struct i2c_client *client, ret = m5mols_sensor_power(info, true); if (ret) - goto out_me; + goto out_irq; ret = m5mols_fw_start(sd); if (!ret) ret = m5mols_init_controls(sd); - m5mols_sensor_power(info, false); + ret = m5mols_sensor_power(info, false); if (!ret) return 0; +out_irq: + free_irq(client->irq, sd); out_me: media_entity_cleanup(&sd->entity); out_reg: diff --git a/drivers/media/video/m5mols/m5mols_reg.h b/drivers/media/i2c/m5mols/m5mols_reg.h index 14d4be72aeff..14d4be72aeff 100644 --- a/drivers/media/video/m5mols/m5mols_reg.h +++ b/drivers/media/i2c/m5mols/m5mols_reg.h diff --git a/drivers/media/video/msp3400-driver.c b/drivers/media/i2c/msp3400-driver.c index aeb22be7dcbd..766305f69a28 100644 --- a/drivers/media/video/msp3400-driver.c +++ b/drivers/media/i2c/msp3400-driver.c @@ -119,12 +119,31 @@ int msp_reset(struct i2c_client *client) static u8 write[3] = { I2C_MSP_DSP + 1, 0x00, 0x1e }; u8 read[2]; struct i2c_msg reset[2] = { - { client->addr, I2C_M_IGNORE_NAK, 3, reset_off }, - { client->addr, I2C_M_IGNORE_NAK, 3, reset_on }, + { + .addr = client->addr, + .flags = I2C_M_IGNORE_NAK, + .len = 3, + .buf = reset_off + }, + { + .addr = client->addr, + .flags = I2C_M_IGNORE_NAK, + .len = 3, + .buf = reset_on + }, }; struct i2c_msg test[2] = { - { client->addr, 0, 3, write }, - { client->addr, I2C_M_RD, 2, read }, + { + .addr = client->addr, + .len = 3, + .buf = write + }, + { + .addr = client->addr, + .flags = I2C_M_RD, + .len = 2, + .buf = read + }, }; v4l_dbg(3, msp_debug, client, "msp_reset\n"); @@ -143,8 +162,17 @@ static int msp_read(struct i2c_client *client, int dev, int addr) u8 write[3]; u8 read[2]; struct i2c_msg msgs[2] = { - { client->addr, 0, 3, write }, - { client->addr, I2C_M_RD, 2, read } + { + .addr = client->addr, + .len = 3, + .buf = write + }, + { + .addr = client->addr, + .flags = I2C_M_RD, + .len = 2, + .buf = read + } }; write[0] = dev + 1; diff --git a/drivers/media/video/msp3400-driver.h b/drivers/media/i2c/msp3400-driver.h index fbe5e0715f93..fbe5e0715f93 100644 --- a/drivers/media/video/msp3400-driver.h +++ b/drivers/media/i2c/msp3400-driver.h diff --git a/drivers/media/video/msp3400-kthreads.c b/drivers/media/i2c/msp3400-kthreads.c index f8b51714f2f9..f8b51714f2f9 100644 --- a/drivers/media/video/msp3400-kthreads.c +++ b/drivers/media/i2c/msp3400-kthreads.c diff --git a/drivers/media/video/mt9m032.c b/drivers/media/i2c/mt9m032.c index 445359c96113..f80c1d7ec884 100644 --- a/drivers/media/video/mt9m032.c +++ b/drivers/media/i2c/mt9m032.c @@ -781,7 +781,7 @@ static int mt9m032_probe(struct i2c_client *client, ret = mt9m032_write(client, MT9M032_RESET, 1); /* reset on */ if (ret < 0) goto error_entity; - mt9m032_write(client, MT9M032_RESET, 0); /* reset off */ + ret = mt9m032_write(client, MT9M032_RESET, 0); /* reset off */ if (ret < 0) goto error_entity; diff --git a/drivers/media/video/mt9p031.c b/drivers/media/i2c/mt9p031.c index 3be537ef22d2..2c0f4077c491 100644 --- a/drivers/media/video/mt9p031.c +++ b/drivers/media/i2c/mt9p031.c @@ -55,9 +55,9 @@ #define MT9P031_HORIZONTAL_BLANK_MIN 0 #define MT9P031_HORIZONTAL_BLANK_MAX 4095 #define MT9P031_VERTICAL_BLANK 0x06 -#define MT9P031_VERTICAL_BLANK_MIN 0 -#define MT9P031_VERTICAL_BLANK_MAX 4095 -#define MT9P031_VERTICAL_BLANK_DEF 25 +#define MT9P031_VERTICAL_BLANK_MIN 1 +#define MT9P031_VERTICAL_BLANK_MAX 4096 +#define MT9P031_VERTICAL_BLANK_DEF 26 #define MT9P031_OUTPUT_CONTROL 0x07 #define MT9P031_OUTPUT_CONTROL_CEN 2 #define MT9P031_OUTPUT_CONTROL_SYN 1 @@ -368,13 +368,13 @@ static int mt9p031_set_params(struct mt9p031 *mt9p031) /* Blanking - use minimum value for horizontal blanking and default * value for vertical blanking. */ - hblank = 346 * ybin + 64 + (80 >> max_t(unsigned int, xbin, 3)); + hblank = 346 * ybin + 64 + (80 >> min_t(unsigned int, xbin, 3)); vblank = MT9P031_VERTICAL_BLANK_DEF; - ret = mt9p031_write(client, MT9P031_HORIZONTAL_BLANK, hblank); + ret = mt9p031_write(client, MT9P031_HORIZONTAL_BLANK, hblank - 1); if (ret < 0) return ret; - ret = mt9p031_write(client, MT9P031_VERTICAL_BLANK, vblank); + ret = mt9p031_write(client, MT9P031_VERTICAL_BLANK, vblank - 1); if (ret < 0) return ret; diff --git a/drivers/media/video/mt9t001.c b/drivers/media/i2c/mt9t001.c index 6d343adf891d..6d343adf891d 100644 --- a/drivers/media/video/mt9t001.c +++ b/drivers/media/i2c/mt9t001.c diff --git a/drivers/media/video/mt9v011.c b/drivers/media/i2c/mt9v011.c index 6bf01ad62765..6bf01ad62765 100644 --- a/drivers/media/video/mt9v011.c +++ b/drivers/media/i2c/mt9v011.c diff --git a/drivers/media/video/mt9v032.c b/drivers/media/i2c/mt9v032.c index 4ba4884c016e..e2177405dad2 100644 --- a/drivers/media/video/mt9v032.c +++ b/drivers/media/i2c/mt9v032.c @@ -29,6 +29,8 @@ #define MT9V032_PIXEL_ARRAY_HEIGHT 492 #define MT9V032_PIXEL_ARRAY_WIDTH 782 +#define MT9V032_SYSCLK_FREQ_DEF 26600000 + #define MT9V032_CHIP_VERSION 0x00 #define MT9V032_CHIP_ID_REV1 0x1311 #define MT9V032_CHIP_ID_REV3 0x1313 @@ -50,9 +52,11 @@ #define MT9V032_WINDOW_WIDTH_MAX 752 #define MT9V032_HORIZONTAL_BLANKING 0x05 #define MT9V032_HORIZONTAL_BLANKING_MIN 43 +#define MT9V032_HORIZONTAL_BLANKING_DEF 94 #define MT9V032_HORIZONTAL_BLANKING_MAX 1023 #define MT9V032_VERTICAL_BLANKING 0x06 #define MT9V032_VERTICAL_BLANKING_MIN 4 +#define MT9V032_VERTICAL_BLANKING_DEF 45 #define MT9V032_VERTICAL_BLANKING_MAX 3000 #define MT9V032_CHIP_CONTROL 0x07 #define MT9V032_CHIP_CONTROL_MASTER_MODE (1 << 3) @@ -123,13 +127,20 @@ struct mt9v032 { struct v4l2_rect crop; struct v4l2_ctrl_handler ctrls; + struct { + struct v4l2_ctrl *link_freq; + struct v4l2_ctrl *pixel_rate; + }; struct mutex power_lock; int power_count; struct mt9v032_platform_data *pdata; + + u32 sysclk; u16 chip_control; u16 aec_agc; + u16 hblank; }; static struct mt9v032 *to_mt9v032(struct v4l2_subdev *sd) @@ -187,13 +198,25 @@ mt9v032_update_aec_agc(struct mt9v032 *mt9v032, u16 which, int enable) return 0; } +static int +mt9v032_update_hblank(struct mt9v032 *mt9v032) +{ + struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev); + struct v4l2_rect *crop = &mt9v032->crop; + + return mt9v032_write(client, MT9V032_HORIZONTAL_BLANKING, + max_t(s32, mt9v032->hblank, 660 - crop->width)); +} + +#define EXT_CLK 25000000 + static int mt9v032_power_on(struct mt9v032 *mt9v032) { struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev); int ret; if (mt9v032->pdata->set_clock) { - mt9v032->pdata->set_clock(&mt9v032->subdev, 25000000); + mt9v032->pdata->set_clock(&mt9v032->subdev, mt9v032->sysclk); udelay(1); } @@ -319,8 +342,7 @@ static int mt9v032_s_stream(struct v4l2_subdev *subdev, int enable) if (ret < 0) return ret; - ret = mt9v032_write(client, MT9V032_HORIZONTAL_BLANKING, - max(43, 660 - crop->width)); + ret = mt9v032_update_hblank(mt9v032); if (ret < 0) return ret; @@ -365,6 +387,18 @@ static int mt9v032_get_format(struct v4l2_subdev *subdev, return 0; } +static void mt9v032_configure_pixel_rate(struct mt9v032 *mt9v032, + unsigned int hratio) +{ + struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev); + int ret; + + ret = v4l2_ctrl_s_ctrl_int64(mt9v032->pixel_rate, + mt9v032->sysclk / hratio); + if (ret < 0) + dev_warn(&client->dev, "failed to set pixel rate (%d)\n", ret); +} + static int mt9v032_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh, struct v4l2_subdev_format *format) @@ -395,6 +429,8 @@ static int mt9v032_set_format(struct v4l2_subdev *subdev, format->which); __format->width = __crop->width / hratio; __format->height = __crop->height / vratio; + if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE) + mt9v032_configure_pixel_rate(mt9v032, hratio); format->format = *__format; @@ -450,6 +486,8 @@ static int mt9v032_set_crop(struct v4l2_subdev *subdev, crop->which); __format->width = rect.width; __format->height = rect.height; + if (crop->which == V4L2_SUBDEV_FORMAT_ACTIVE) + mt9v032_configure_pixel_rate(mt9v032, 1); } *__crop = rect; @@ -469,6 +507,7 @@ static int mt9v032_s_ctrl(struct v4l2_ctrl *ctrl) struct mt9v032 *mt9v032 = container_of(ctrl->handler, struct mt9v032, ctrls); struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev); + u32 freq; u16 data; switch (ctrl->id) { @@ -487,6 +526,24 @@ static int mt9v032_s_ctrl(struct v4l2_ctrl *ctrl) return mt9v032_write(client, MT9V032_TOTAL_SHUTTER_WIDTH, ctrl->val); + case V4L2_CID_HBLANK: + mt9v032->hblank = ctrl->val; + return mt9v032_update_hblank(mt9v032); + + case V4L2_CID_VBLANK: + return mt9v032_write(client, MT9V032_VERTICAL_BLANKING, + ctrl->val); + + case V4L2_CID_PIXEL_RATE: + case V4L2_CID_LINK_FREQ: + if (mt9v032->link_freq == NULL) + break; + + freq = mt9v032->pdata->link_freqs[mt9v032->link_freq->val]; + mt9v032->pixel_rate->val64 = freq; + mt9v032->sysclk = freq; + break; + case V4L2_CID_TEST_PATTERN: switch (ctrl->val) { case 0: @@ -598,6 +655,8 @@ static int mt9v032_registered(struct v4l2_subdev *subdev) dev_info(&client->dev, "MT9V032 detected at address 0x%02x\n", client->addr); + mt9v032_configure_pixel_rate(mt9v032, 1); + return ret; } @@ -663,6 +722,7 @@ static const struct v4l2_subdev_internal_ops mt9v032_subdev_internal_ops = { static int mt9v032_probe(struct i2c_client *client, const struct i2c_device_id *did) { + struct mt9v032_platform_data *pdata = client->dev.platform_data; struct mt9v032 *mt9v032; unsigned int i; int ret; @@ -679,9 +739,9 @@ static int mt9v032_probe(struct i2c_client *client, return -ENOMEM; mutex_init(&mt9v032->power_lock); - mt9v032->pdata = client->dev.platform_data; + mt9v032->pdata = pdata; - v4l2_ctrl_handler_init(&mt9v032->ctrls, ARRAY_SIZE(mt9v032_ctrls) + 4); + v4l2_ctrl_handler_init(&mt9v032->ctrls, ARRAY_SIZE(mt9v032_ctrls) + 8); v4l2_ctrl_new_std(&mt9v032->ctrls, &mt9v032_ctrl_ops, V4L2_CID_AUTOGAIN, 0, 1, 1, 1); @@ -695,6 +755,34 @@ static int mt9v032_probe(struct i2c_client *client, V4L2_CID_EXPOSURE, MT9V032_TOTAL_SHUTTER_WIDTH_MIN, MT9V032_TOTAL_SHUTTER_WIDTH_MAX, 1, MT9V032_TOTAL_SHUTTER_WIDTH_DEF); + v4l2_ctrl_new_std(&mt9v032->ctrls, &mt9v032_ctrl_ops, + V4L2_CID_HBLANK, MT9V032_HORIZONTAL_BLANKING_MIN, + MT9V032_HORIZONTAL_BLANKING_MAX, 1, + MT9V032_HORIZONTAL_BLANKING_DEF); + v4l2_ctrl_new_std(&mt9v032->ctrls, &mt9v032_ctrl_ops, + V4L2_CID_VBLANK, MT9V032_VERTICAL_BLANKING_MIN, + MT9V032_VERTICAL_BLANKING_MAX, 1, + MT9V032_VERTICAL_BLANKING_DEF); + + mt9v032->pixel_rate = + v4l2_ctrl_new_std(&mt9v032->ctrls, &mt9v032_ctrl_ops, + V4L2_CID_PIXEL_RATE, 0, 0, 1, 0); + + if (pdata && pdata->link_freqs) { + unsigned int def = 0; + + for (i = 0; pdata->link_freqs[i]; ++i) { + if (pdata->link_freqs[i] == pdata->link_def_freq) + def = i; + } + + mt9v032->link_freq = + v4l2_ctrl_new_int_menu(&mt9v032->ctrls, + &mt9v032_ctrl_ops, + V4L2_CID_LINK_FREQ, i - 1, def, + pdata->link_freqs); + v4l2_ctrl_cluster(2, &mt9v032->link_freq); + } for (i = 0; i < ARRAY_SIZE(mt9v032_ctrls); ++i) v4l2_ctrl_new_custom(&mt9v032->ctrls, &mt9v032_ctrls[i], NULL); @@ -717,6 +805,8 @@ static int mt9v032_probe(struct i2c_client *client, mt9v032->format.colorspace = V4L2_COLORSPACE_SRGB; mt9v032->aec_agc = MT9V032_AEC_ENABLE | MT9V032_AGC_ENABLE; + mt9v032->hblank = MT9V032_HORIZONTAL_BLANKING_DEF; + mt9v032->sysclk = MT9V032_SYSCLK_FREQ_DEF; v4l2_i2c_subdev_init(&mt9v032->subdev, client, &mt9v032_subdev_ops); mt9v032->subdev.internal_ops = &mt9v032_subdev_internal_ops; diff --git a/drivers/media/video/noon010pc30.c b/drivers/media/i2c/noon010pc30.c index 440c12962bae..440c12962bae 100644 --- a/drivers/media/video/noon010pc30.c +++ b/drivers/media/i2c/noon010pc30.c diff --git a/drivers/media/video/ov7670.c b/drivers/media/i2c/ov7670.c index e7c82b297514..e7c82b297514 100644 --- a/drivers/media/video/ov7670.c +++ b/drivers/media/i2c/ov7670.c diff --git a/drivers/media/i2c/s5k4ecgx.c b/drivers/media/i2c/s5k4ecgx.c new file mode 100644 index 000000000000..49c1b3abb425 --- /dev/null +++ b/drivers/media/i2c/s5k4ecgx.c @@ -0,0 +1,1036 @@ +/* + * Driver for Samsung S5K4ECGX 1/4" 5Mp CMOS Image Sensor SoC + * with an Embedded Image Signal Processor. + * + * Copyright (C) 2012, Linaro, Sangwook Lee <sangwook.lee@linaro.org> + * Copyright (C) 2012, Insignal Co,. Ltd, Homin Lee <suapapa@insignal.co.kr> + * + * Based on s5k6aa and noon010pc30 driver + * Copyright (C) 2011, Samsung Electronics Co., Ltd. + * + * 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 <linux/clk.h> +#include <linux/crc32.h> +#include <linux/ctype.h> +#include <linux/delay.h> +#include <linux/firmware.h> +#include <linux/gpio.h> +#include <linux/i2c.h> +#include <linux/module.h> +#include <linux/regulator/consumer.h> +#include <linux/slab.h> +#include <asm/unaligned.h> + +#include <media/media-entity.h> +#include <media/s5k4ecgx.h> +#include <media/v4l2-ctrls.h> +#include <media/v4l2-device.h> +#include <media/v4l2-mediabus.h> +#include <media/v4l2-subdev.h> + +static int debug; +module_param(debug, int, 0644); + +#define S5K4ECGX_DRIVER_NAME "s5k4ecgx" +#define S5K4ECGX_FIRMWARE "s5k4ecgx.bin" + +/* Firmware revision information */ +#define REG_FW_REVISION 0x700001a6 +#define REG_FW_VERSION 0x700001a4 +#define S5K4ECGX_REVISION_1_1 0x11 +#define S5K4ECGX_FW_VERSION 0x4ec0 + +/* General purpose parameters */ +#define REG_USER_BRIGHTNESS 0x7000022c +#define REG_USER_CONTRAST 0x7000022e +#define REG_USER_SATURATION 0x70000230 + +#define REG_G_ENABLE_PREV 0x7000023e +#define REG_G_ENABLE_PREV_CHG 0x70000240 +#define REG_G_NEW_CFG_SYNC 0x7000024a +#define REG_G_PREV_IN_WIDTH 0x70000250 +#define REG_G_PREV_IN_HEIGHT 0x70000252 +#define REG_G_PREV_IN_XOFFS 0x70000254 +#define REG_G_PREV_IN_YOFFS 0x70000256 +#define REG_G_CAP_IN_WIDTH 0x70000258 +#define REG_G_CAP_IN_HEIGHT 0x7000025a +#define REG_G_CAP_IN_XOFFS 0x7000025c +#define REG_G_CAP_IN_YOFFS 0x7000025e +#define REG_G_INPUTS_CHANGE_REQ 0x70000262 +#define REG_G_ACTIVE_PREV_CFG 0x70000266 +#define REG_G_PREV_CFG_CHG 0x70000268 +#define REG_G_PREV_OPEN_AFTER_CH 0x7000026a + +/* Preview context register sets. n = 0...4. */ +#define PREG(n, x) ((n) * 0x30 + (x)) +#define REG_P_OUT_WIDTH(n) PREG(n, 0x700002a6) +#define REG_P_OUT_HEIGHT(n) PREG(n, 0x700002a8) +#define REG_P_FMT(n) PREG(n, 0x700002aa) +#define REG_P_PVI_MASK(n) PREG(n, 0x700002b4) +#define REG_P_FR_TIME_TYPE(n) PREG(n, 0x700002be) +#define FR_TIME_DYNAMIC 0 +#define FR_TIME_FIXED 1 +#define FR_TIME_FIXED_ACCURATE 2 +#define REG_P_FR_TIME_Q_TYPE(n) PREG(n, 0x700002c0) +#define FR_TIME_Q_DYNAMIC 0 +#define FR_TIME_Q_BEST_FRRATE 1 +#define FR_TIME_Q_BEST_QUALITY 2 + +/* Frame period in 0.1 ms units */ +#define REG_P_MAX_FR_TIME(n) PREG(n, 0x700002c2) +#define REG_P_MIN_FR_TIME(n) PREG(n, 0x700002c4) +#define US_TO_FR_TIME(__t) ((__t) / 100) +#define REG_P_PREV_MIRROR(n) PREG(n, 0x700002d0) +#define REG_P_CAP_MIRROR(n) PREG(n, 0x700002d2) + +#define REG_G_PREVZOOM_IN_WIDTH 0x70000494 +#define REG_G_PREVZOOM_IN_HEIGHT 0x70000496 +#define REG_G_PREVZOOM_IN_XOFFS 0x70000498 +#define REG_G_PREVZOOM_IN_YOFFS 0x7000049a +#define REG_G_CAPZOOM_IN_WIDTH 0x7000049c +#define REG_G_CAPZOOM_IN_HEIGHT 0x7000049e +#define REG_G_CAPZOOM_IN_XOFFS 0x700004a0 +#define REG_G_CAPZOOM_IN_YOFFS 0x700004a2 + +/* n = 0...4 */ +#define REG_USER_SHARPNESS(n) (0x70000a28 + (n) * 0xb6) + +/* Reduce sharpness range for user space API */ +#define SHARPNESS_DIV 8208 +#define TOK_TERM 0xffffffff + +/* + * FIXME: This is copied from s5k6aa, because of no information + * in the S5K4ECGX datasheet. + * H/W register Interface (0xd0000000 - 0xd0000fff) + */ +#define AHB_MSB_ADDR_PTR 0xfcfc +#define GEN_REG_OFFSH 0xd000 +#define REG_CMDWR_ADDRH 0x0028 +#define REG_CMDWR_ADDRL 0x002a +#define REG_CMDRD_ADDRH 0x002c +#define REG_CMDRD_ADDRL 0x002e +#define REG_CMDBUF0_ADDR 0x0f12 + +struct s5k4ecgx_frmsize { + struct v4l2_frmsize_discrete size; + /* Fixed sensor matrix crop rectangle */ + struct v4l2_rect input_window; +}; + +struct regval_list { + u32 addr; + u16 val; +}; + +/* + * TODO: currently only preview is supported and snapshot (capture) + * is not implemented yet + */ +static const struct s5k4ecgx_frmsize s5k4ecgx_prev_sizes[] = { + { + .size = { 176, 144 }, + .input_window = { 0x00, 0x00, 0x928, 0x780 }, + }, { + .size = { 352, 288 }, + .input_window = { 0x00, 0x00, 0x928, 0x780 }, + }, { + .size = { 640, 480 }, + .input_window = { 0x00, 0x00, 0xa00, 0x780 }, + }, { + .size = { 720, 480 }, + .input_window = { 0x00, 0x00, 0xa00, 0x6a8 }, + } +}; + +#define S5K4ECGX_NUM_PREV ARRAY_SIZE(s5k4ecgx_prev_sizes) + +struct s5k4ecgx_pixfmt { + enum v4l2_mbus_pixelcode code; + u32 colorspace; + /* REG_TC_PCFG_Format register value */ + u16 reg_p_format; +}; + +/* By default value, output from sensor will be YUV422 0-255 */ +static const struct s5k4ecgx_pixfmt s5k4ecgx_formats[] = { + { V4L2_MBUS_FMT_YUYV8_2X8, V4L2_COLORSPACE_JPEG, 5 }, +}; + +static const char * const s5k4ecgx_supply_names[] = { + /* + * Usually 2.8V is used for analog power (vdda) + * and digital IO (vddio, vdddcore) + */ + "vdda", + "vddio", + "vddcore", + "vddreg", /* The internal s5k4ecgx regulator's supply (1.8V) */ +}; + +#define S5K4ECGX_NUM_SUPPLIES ARRAY_SIZE(s5k4ecgx_supply_names) + +enum s5k4ecgx_gpio_id { + STBY, + RST, + GPIO_NUM, +}; + +struct s5k4ecgx { + struct v4l2_subdev sd; + struct media_pad pad; + struct v4l2_ctrl_handler handler; + + struct s5k4ecgx_platform_data *pdata; + const struct s5k4ecgx_pixfmt *curr_pixfmt; + const struct s5k4ecgx_frmsize *curr_frmsize; + struct mutex lock; + u8 streaming; + u8 set_params; + + struct regulator_bulk_data supplies[S5K4ECGX_NUM_SUPPLIES]; + struct s5k4ecgx_gpio gpio[GPIO_NUM]; +}; + +static inline struct s5k4ecgx *to_s5k4ecgx(struct v4l2_subdev *sd) +{ + return container_of(sd, struct s5k4ecgx, sd); +} + +static int s5k4ecgx_i2c_read(struct i2c_client *client, u16 addr, u16 *val) +{ + u8 wbuf[2] = { addr >> 8, addr & 0xff }; + struct i2c_msg msg[2]; + u8 rbuf[2]; + int ret; + + msg[0].addr = client->addr; + msg[0].flags = 0; + msg[0].len = 2; + msg[0].buf = wbuf; + + msg[1].addr = client->addr; + msg[1].flags = I2C_M_RD; + msg[1].len = 2; + msg[1].buf = rbuf; + + ret = i2c_transfer(client->adapter, msg, 2); + *val = be16_to_cpu(*((u16 *)rbuf)); + + v4l2_dbg(4, debug, client, "i2c_read: 0x%04X : 0x%04x\n", addr, *val); + + return ret == 2 ? 0 : ret; +} + +static int s5k4ecgx_i2c_write(struct i2c_client *client, u16 addr, u16 val) +{ + u8 buf[4] = { addr >> 8, addr & 0xff, val >> 8, val & 0xff }; + + int ret = i2c_master_send(client, buf, 4); + v4l2_dbg(4, debug, client, "i2c_write: 0x%04x : 0x%04x\n", addr, val); + + return ret == 4 ? 0 : ret; +} + +static int s5k4ecgx_write(struct i2c_client *client, u32 addr, u16 val) +{ + u16 high = addr >> 16, low = addr & 0xffff; + int ret; + + v4l2_dbg(3, debug, client, "write: 0x%08x : 0x%04x\n", addr, val); + + ret = s5k4ecgx_i2c_write(client, REG_CMDWR_ADDRH, high); + if (!ret) + ret = s5k4ecgx_i2c_write(client, REG_CMDWR_ADDRL, low); + if (!ret) + ret = s5k4ecgx_i2c_write(client, REG_CMDBUF0_ADDR, val); + + return ret; +} + +static int s5k4ecgx_read(struct i2c_client *client, u32 addr, u16 *val) +{ + u16 high = addr >> 16, low = addr & 0xffff; + int ret; + + ret = s5k4ecgx_i2c_write(client, REG_CMDRD_ADDRH, high); + if (!ret) + ret = s5k4ecgx_i2c_write(client, REG_CMDRD_ADDRL, low); + if (!ret) + ret = s5k4ecgx_i2c_read(client, REG_CMDBUF0_ADDR, val); + if (!ret) + dev_err(&client->dev, "Failed to execute read command\n"); + + return ret; +} + +static int s5k4ecgx_read_fw_ver(struct v4l2_subdev *sd) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + u16 hw_rev, fw_ver = 0; + int ret; + + ret = s5k4ecgx_read(client, REG_FW_VERSION, &fw_ver); + if (ret < 0 || fw_ver != S5K4ECGX_FW_VERSION) { + v4l2_err(sd, "FW version check failed!\n"); + return -ENODEV; + } + + ret = s5k4ecgx_read(client, REG_FW_REVISION, &hw_rev); + if (ret < 0) + return ret; + + v4l2_info(sd, "chip found FW ver: 0x%x, HW rev: 0x%x\n", + fw_ver, hw_rev); + return 0; +} + +static int s5k4ecgx_set_ahb_address(struct v4l2_subdev *sd) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + int ret; + + /* Set APB peripherals start address */ + ret = s5k4ecgx_i2c_write(client, AHB_MSB_ADDR_PTR, GEN_REG_OFFSH); + if (ret < 0) + return ret; + /* + * FIXME: This is copied from s5k6aa, because of no information + * in s5k4ecgx's datasheet. + * sw_reset is activated to put device into idle status + */ + ret = s5k4ecgx_i2c_write(client, 0x0010, 0x0001); + if (ret < 0) + return ret; + + ret = s5k4ecgx_i2c_write(client, 0x1030, 0x0000); + if (ret < 0) + return ret; + /* Halt ARM CPU */ + return s5k4ecgx_i2c_write(client, 0x0014, 0x0001); +} + +#define FW_CRC_SIZE 4 +/* Register address, value are 4, 2 bytes */ +#define FW_RECORD_SIZE 6 +/* + * The firmware has following format: + * < total number of records (4 bytes + 2 bytes padding) N >, + * < record 0 >, ..., < record N - 1 >, < CRC32-CCITT (4-bytes) >, + * where "record" is a 4-byte register address followed by 2-byte + * register value (little endian). + * The firmware generator can be found in following git repository: + * git://git.linaro.org/people/sangwook/fimc-v4l2-app.git + */ +static int s5k4ecgx_load_firmware(struct v4l2_subdev *sd) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + const struct firmware *fw; + const u8 *ptr; + int err, i, regs_num; + u32 addr, crc, crc_file, addr_inc = 0; + u16 val; + + err = request_firmware(&fw, S5K4ECGX_FIRMWARE, sd->v4l2_dev->dev); + if (err) { + v4l2_err(sd, "Failed to read firmware %s\n", S5K4ECGX_FIRMWARE); + return err; + } + regs_num = le32_to_cpu(get_unaligned_le32(fw->data)); + + v4l2_dbg(3, debug, sd, "FW: %s size %d register sets %d\n", + S5K4ECGX_FIRMWARE, fw->size, regs_num); + + regs_num++; /* Add header */ + if (fw->size != regs_num * FW_RECORD_SIZE + FW_CRC_SIZE) { + err = -EINVAL; + goto fw_out; + } + crc_file = le32_to_cpu(get_unaligned_le32(fw->data + + regs_num * FW_RECORD_SIZE)); + crc = crc32_le(~0, fw->data, regs_num * FW_RECORD_SIZE); + if (crc != crc_file) { + v4l2_err(sd, "FW: invalid crc (%#x:%#x)\n", crc, crc_file); + err = -EINVAL; + goto fw_out; + } + ptr = fw->data + FW_RECORD_SIZE; + for (i = 1; i < regs_num; i++) { + addr = le32_to_cpu(get_unaligned_le32(ptr)); + ptr += sizeof(u32); + val = le16_to_cpu(get_unaligned_le16(ptr)); + ptr += sizeof(u16); + if (addr - addr_inc != 2) + err = s5k4ecgx_write(client, addr, val); + else + err = s5k4ecgx_i2c_write(client, REG_CMDBUF0_ADDR, val); + if (err) + break; + addr_inc = addr; + } +fw_out: + release_firmware(fw); + return err; +} + +/* Set preview and capture input window */ +static int s5k4ecgx_set_input_window(struct i2c_client *c, + const struct v4l2_rect *r) +{ + int ret; + + ret = s5k4ecgx_write(c, REG_G_PREV_IN_WIDTH, r->width); + if (!ret) + ret = s5k4ecgx_write(c, REG_G_PREV_IN_HEIGHT, r->height); + if (!ret) + ret = s5k4ecgx_write(c, REG_G_PREV_IN_XOFFS, r->left); + if (!ret) + ret = s5k4ecgx_write(c, REG_G_PREV_IN_YOFFS, r->top); + if (!ret) + ret = s5k4ecgx_write(c, REG_G_CAP_IN_WIDTH, r->width); + if (!ret) + ret = s5k4ecgx_write(c, REG_G_CAP_IN_HEIGHT, r->height); + if (!ret) + ret = s5k4ecgx_write(c, REG_G_CAP_IN_XOFFS, r->left); + if (!ret) + ret = s5k4ecgx_write(c, REG_G_CAP_IN_YOFFS, r->top); + + return ret; +} + +/* Set preview and capture zoom input window */ +static int s5k4ecgx_set_zoom_window(struct i2c_client *c, + const struct v4l2_rect *r) +{ + int ret; + + ret = s5k4ecgx_write(c, REG_G_PREVZOOM_IN_WIDTH, r->width); + if (!ret) + ret = s5k4ecgx_write(c, REG_G_PREVZOOM_IN_HEIGHT, r->height); + if (!ret) + ret = s5k4ecgx_write(c, REG_G_PREVZOOM_IN_XOFFS, r->left); + if (!ret) + ret = s5k4ecgx_write(c, REG_G_PREVZOOM_IN_YOFFS, r->top); + if (!ret) + ret = s5k4ecgx_write(c, REG_G_CAPZOOM_IN_WIDTH, r->width); + if (!ret) + ret = s5k4ecgx_write(c, REG_G_CAPZOOM_IN_HEIGHT, r->height); + if (!ret) + ret = s5k4ecgx_write(c, REG_G_CAPZOOM_IN_XOFFS, r->left); + if (!ret) + ret = s5k4ecgx_write(c, REG_G_CAPZOOM_IN_YOFFS, r->top); + + return ret; +} + +static int s5k4ecgx_set_output_framefmt(struct s5k4ecgx *priv) +{ + struct i2c_client *client = v4l2_get_subdevdata(&priv->sd); + int ret; + + ret = s5k4ecgx_write(client, REG_P_OUT_WIDTH(0), + priv->curr_frmsize->size.width); + if (!ret) + ret = s5k4ecgx_write(client, REG_P_OUT_HEIGHT(0), + priv->curr_frmsize->size.height); + if (!ret) + ret = s5k4ecgx_write(client, REG_P_FMT(0), + priv->curr_pixfmt->reg_p_format); + return ret; +} + +static int s5k4ecgx_init_sensor(struct v4l2_subdev *sd) +{ + int ret; + + ret = s5k4ecgx_set_ahb_address(sd); + + /* The delay is from manufacturer's settings */ + msleep(100); + + if (!ret) + ret = s5k4ecgx_load_firmware(sd); + if (ret) + v4l2_err(sd, "Failed to write initial settings\n"); + + return ret; +} + +static int s5k4ecgx_gpio_set_value(struct s5k4ecgx *priv, int id, u32 val) +{ + if (!gpio_is_valid(priv->gpio[id].gpio)) + return 0; + gpio_set_value(priv->gpio[id].gpio, val); + + return 1; +} + +static int __s5k4ecgx_power_on(struct s5k4ecgx *priv) +{ + int ret; + + ret = regulator_bulk_enable(S5K4ECGX_NUM_SUPPLIES, priv->supplies); + if (ret) + return ret; + usleep_range(30, 50); + + /* The polarity of STBY is controlled by TSP */ + if (s5k4ecgx_gpio_set_value(priv, STBY, priv->gpio[STBY].level)) + usleep_range(30, 50); + + if (s5k4ecgx_gpio_set_value(priv, RST, priv->gpio[RST].level)) + usleep_range(30, 50); + + return 0; +} + +static int __s5k4ecgx_power_off(struct s5k4ecgx *priv) +{ + if (s5k4ecgx_gpio_set_value(priv, RST, !priv->gpio[RST].level)) + usleep_range(30, 50); + + if (s5k4ecgx_gpio_set_value(priv, STBY, !priv->gpio[STBY].level)) + usleep_range(30, 50); + + priv->streaming = 0; + + return regulator_bulk_disable(S5K4ECGX_NUM_SUPPLIES, priv->supplies); +} + +/* Find nearest matching image pixel size. */ +static int s5k4ecgx_try_frame_size(struct v4l2_mbus_framefmt *mf, + const struct s5k4ecgx_frmsize **size) +{ + unsigned int min_err = ~0; + int i = ARRAY_SIZE(s5k4ecgx_prev_sizes); + const struct s5k4ecgx_frmsize *fsize = &s5k4ecgx_prev_sizes[0], + *match = NULL; + + while (i--) { + int err = abs(fsize->size.width - mf->width) + + abs(fsize->size.height - mf->height); + if (err < min_err) { + min_err = err; + match = fsize; + } + fsize++; + } + if (match) { + mf->width = match->size.width; + mf->height = match->size.height; + if (size) + *size = match; + return 0; + } + + return -EINVAL; +} + +static int s5k4ecgx_enum_mbus_code(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh, + struct v4l2_subdev_mbus_code_enum *code) +{ + if (code->index >= ARRAY_SIZE(s5k4ecgx_formats)) + return -EINVAL; + code->code = s5k4ecgx_formats[code->index].code; + + return 0; +} + +static int s5k4ecgx_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, + struct v4l2_subdev_format *fmt) +{ + struct s5k4ecgx *priv = to_s5k4ecgx(sd); + struct v4l2_mbus_framefmt *mf; + + if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { + if (fh) { + mf = v4l2_subdev_get_try_format(fh, 0); + fmt->format = *mf; + } + return 0; + } + + mf = &fmt->format; + + mutex_lock(&priv->lock); + mf->width = priv->curr_frmsize->size.width; + mf->height = priv->curr_frmsize->size.height; + mf->code = priv->curr_pixfmt->code; + mf->colorspace = priv->curr_pixfmt->colorspace; + mf->field = V4L2_FIELD_NONE; + mutex_unlock(&priv->lock); + + return 0; +} + +static const struct s5k4ecgx_pixfmt *s5k4ecgx_try_fmt(struct v4l2_subdev *sd, + struct v4l2_mbus_framefmt *mf) +{ + int i = ARRAY_SIZE(s5k4ecgx_formats); + + while (--i) + if (mf->code == s5k4ecgx_formats[i].code) + break; + mf->code = s5k4ecgx_formats[i].code; + + return &s5k4ecgx_formats[i]; +} + +static int s5k4ecgx_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, + struct v4l2_subdev_format *fmt) +{ + struct s5k4ecgx *priv = to_s5k4ecgx(sd); + const struct s5k4ecgx_frmsize *fsize = NULL; + const struct s5k4ecgx_pixfmt *pf; + struct v4l2_mbus_framefmt *mf; + int ret = 0; + + pf = s5k4ecgx_try_fmt(sd, &fmt->format); + s5k4ecgx_try_frame_size(&fmt->format, &fsize); + fmt->format.colorspace = V4L2_COLORSPACE_JPEG; + + if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { + if (fh) { + mf = v4l2_subdev_get_try_format(fh, 0); + *mf = fmt->format; + } + return 0; + } + + mutex_lock(&priv->lock); + if (!priv->streaming) { + priv->curr_frmsize = fsize; + priv->curr_pixfmt = pf; + priv->set_params = 1; + } else { + ret = -EBUSY; + } + mutex_unlock(&priv->lock); + + return ret; +} + +static const struct v4l2_subdev_pad_ops s5k4ecgx_pad_ops = { + .enum_mbus_code = s5k4ecgx_enum_mbus_code, + .get_fmt = s5k4ecgx_get_fmt, + .set_fmt = s5k4ecgx_set_fmt, +}; + +/* + * V4L2 subdev controls + */ +static int s5k4ecgx_s_ctrl(struct v4l2_ctrl *ctrl) +{ + struct v4l2_subdev *sd = &container_of(ctrl->handler, struct s5k4ecgx, + handler)->sd; + struct i2c_client *client = v4l2_get_subdevdata(sd); + struct s5k4ecgx *priv = to_s5k4ecgx(sd); + unsigned int i; + int err = 0; + + v4l2_dbg(1, debug, sd, "ctrl: 0x%x, value: %d\n", ctrl->id, ctrl->val); + + mutex_lock(&priv->lock); + switch (ctrl->id) { + case V4L2_CID_CONTRAST: + err = s5k4ecgx_write(client, REG_USER_CONTRAST, ctrl->val); + break; + + case V4L2_CID_SATURATION: + err = s5k4ecgx_write(client, REG_USER_SATURATION, ctrl->val); + break; + + case V4L2_CID_SHARPNESS: + /* TODO: Revisit, is this setting for all presets ? */ + for (i = 0; i < 4 && !err; i++) + err = s5k4ecgx_write(client, REG_USER_SHARPNESS(i), + ctrl->val * SHARPNESS_DIV); + break; + + case V4L2_CID_BRIGHTNESS: + err = s5k4ecgx_write(client, REG_USER_BRIGHTNESS, ctrl->val); + break; + } + mutex_unlock(&priv->lock); + if (err < 0) + v4l2_err(sd, "Failed to write s_ctrl err %d\n", err); + + return err; +} + +static const struct v4l2_ctrl_ops s5k4ecgx_ctrl_ops = { + .s_ctrl = s5k4ecgx_s_ctrl, +}; + +/* + * Reading s5k4ecgx version information + */ +static int s5k4ecgx_registered(struct v4l2_subdev *sd) +{ + int ret; + struct s5k4ecgx *priv = to_s5k4ecgx(sd); + + mutex_lock(&priv->lock); + ret = __s5k4ecgx_power_on(priv); + if (!ret) { + ret = s5k4ecgx_read_fw_ver(sd); + __s5k4ecgx_power_off(priv); + } + mutex_unlock(&priv->lock); + + return ret; +} + +/* + * V4L2 subdev internal operations + */ +static int s5k4ecgx_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) +{ + struct v4l2_mbus_framefmt *mf = v4l2_subdev_get_try_format(fh, 0); + + mf->width = s5k4ecgx_prev_sizes[0].size.width; + mf->height = s5k4ecgx_prev_sizes[0].size.height; + mf->code = s5k4ecgx_formats[0].code; + mf->colorspace = V4L2_COLORSPACE_JPEG; + mf->field = V4L2_FIELD_NONE; + + return 0; +} + +static const struct v4l2_subdev_internal_ops s5k4ecgx_subdev_internal_ops = { + .registered = s5k4ecgx_registered, + .open = s5k4ecgx_open, +}; + +static int s5k4ecgx_s_power(struct v4l2_subdev *sd, int on) +{ + struct s5k4ecgx *priv = to_s5k4ecgx(sd); + int ret; + + v4l2_dbg(1, debug, sd, "Switching %s\n", on ? "on" : "off"); + + if (on) { + ret = __s5k4ecgx_power_on(priv); + if (ret < 0) + return ret; + /* Time to stabilize sensor */ + msleep(100); + ret = s5k4ecgx_init_sensor(sd); + if (ret < 0) + __s5k4ecgx_power_off(priv); + else + priv->set_params = 1; + } else { + ret = __s5k4ecgx_power_off(priv); + } + + return ret; +} + +static int s5k4ecgx_log_status(struct v4l2_subdev *sd) +{ + v4l2_ctrl_handler_log_status(sd->ctrl_handler, sd->name); + + return 0; +} + +static const struct v4l2_subdev_core_ops s5k4ecgx_core_ops = { + .s_power = s5k4ecgx_s_power, + .log_status = s5k4ecgx_log_status, +}; + +static int __s5k4ecgx_s_params(struct s5k4ecgx *priv) +{ + struct i2c_client *client = v4l2_get_subdevdata(&priv->sd); + const struct v4l2_rect *crop_rect = &priv->curr_frmsize->input_window; + int ret; + + ret = s5k4ecgx_set_input_window(client, crop_rect); + if (!ret) + ret = s5k4ecgx_set_zoom_window(client, crop_rect); + if (!ret) + ret = s5k4ecgx_write(client, REG_G_INPUTS_CHANGE_REQ, 1); + if (!ret) + ret = s5k4ecgx_write(client, 0x70000a1e, 0x28); + if (!ret) + ret = s5k4ecgx_write(client, 0x70000ad4, 0x3c); + if (!ret) + ret = s5k4ecgx_set_output_framefmt(priv); + if (!ret) + ret = s5k4ecgx_write(client, REG_P_PVI_MASK(0), 0x52); + if (!ret) + ret = s5k4ecgx_write(client, REG_P_FR_TIME_TYPE(0), + FR_TIME_DYNAMIC); + if (!ret) + ret = s5k4ecgx_write(client, REG_P_FR_TIME_Q_TYPE(0), + FR_TIME_Q_BEST_FRRATE); + if (!ret) + ret = s5k4ecgx_write(client, REG_P_MIN_FR_TIME(0), + US_TO_FR_TIME(33300)); + if (!ret) + ret = s5k4ecgx_write(client, REG_P_MAX_FR_TIME(0), + US_TO_FR_TIME(66600)); + if (!ret) + ret = s5k4ecgx_write(client, REG_P_PREV_MIRROR(0), 0); + if (!ret) + ret = s5k4ecgx_write(client, REG_P_CAP_MIRROR(0), 0); + if (!ret) + ret = s5k4ecgx_write(client, REG_G_ACTIVE_PREV_CFG, 0); + if (!ret) + ret = s5k4ecgx_write(client, REG_G_PREV_OPEN_AFTER_CH, 1); + if (!ret) + ret = s5k4ecgx_write(client, REG_G_NEW_CFG_SYNC, 1); + if (!ret) + ret = s5k4ecgx_write(client, REG_G_PREV_CFG_CHG, 1); + + return ret; +} + +static int __s5k4ecgx_s_stream(struct s5k4ecgx *priv, int on) +{ + struct i2c_client *client = v4l2_get_subdevdata(&priv->sd); + int ret; + + if (on && priv->set_params) { + ret = __s5k4ecgx_s_params(priv); + if (ret < 0) + return ret; + priv->set_params = 0; + } + /* + * This enables/disables preview stream only. Capture requests + * are not supported yet. + */ + ret = s5k4ecgx_write(client, REG_G_ENABLE_PREV, on); + if (ret < 0) + return ret; + return s5k4ecgx_write(client, REG_G_ENABLE_PREV_CHG, 1); +} + +static int s5k4ecgx_s_stream(struct v4l2_subdev *sd, int on) +{ + struct s5k4ecgx *priv = to_s5k4ecgx(sd); + int ret = 0; + + v4l2_dbg(1, debug, sd, "Turn streaming %s\n", on ? "on" : "off"); + + mutex_lock(&priv->lock); + + if (priv->streaming == !on) { + ret = __s5k4ecgx_s_stream(priv, on); + if (!ret) + priv->streaming = on & 1; + } + + mutex_unlock(&priv->lock); + return ret; +} + +static const struct v4l2_subdev_video_ops s5k4ecgx_video_ops = { + .s_stream = s5k4ecgx_s_stream, +}; + +static const struct v4l2_subdev_ops s5k4ecgx_ops = { + .core = &s5k4ecgx_core_ops, + .pad = &s5k4ecgx_pad_ops, + .video = &s5k4ecgx_video_ops, +}; + +/* + * GPIO setup + */ +static int s5k4ecgx_config_gpio(int nr, int val, const char *name) +{ + unsigned long flags = val ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW; + int ret; + + if (!gpio_is_valid(nr)) + return 0; + ret = gpio_request_one(nr, flags, name); + if (!ret) + gpio_export(nr, 0); + + return ret; +} + +static void s5k4ecgx_free_gpios(struct s5k4ecgx *priv) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(priv->gpio); i++) { + if (!gpio_is_valid(priv->gpio[i].gpio)) + continue; + gpio_free(priv->gpio[i].gpio); + priv->gpio[i].gpio = -EINVAL; + } +} + +static int s5k4ecgx_config_gpios(struct s5k4ecgx *priv, + const struct s5k4ecgx_platform_data *pdata) +{ + const struct s5k4ecgx_gpio *gpio = &pdata->gpio_stby; + int ret; + + priv->gpio[STBY].gpio = -EINVAL; + priv->gpio[RST].gpio = -EINVAL; + + ret = s5k4ecgx_config_gpio(gpio->gpio, gpio->level, "S5K4ECGX_STBY"); + + if (ret) { + s5k4ecgx_free_gpios(priv); + return ret; + } + priv->gpio[STBY] = *gpio; + if (gpio_is_valid(gpio->gpio)) + gpio_set_value(gpio->gpio, 0); + + gpio = &pdata->gpio_reset; + + ret = s5k4ecgx_config_gpio(gpio->gpio, gpio->level, "S5K4ECGX_RST"); + if (ret) { + s5k4ecgx_free_gpios(priv); + return ret; + } + priv->gpio[RST] = *gpio; + if (gpio_is_valid(gpio->gpio)) + gpio_set_value(gpio->gpio, 0); + + return 0; +} + +static int s5k4ecgx_init_v4l2_ctrls(struct s5k4ecgx *priv) +{ + const struct v4l2_ctrl_ops *ops = &s5k4ecgx_ctrl_ops; + struct v4l2_ctrl_handler *hdl = &priv->handler; + int ret; + + ret = v4l2_ctrl_handler_init(hdl, 4); + if (ret) + return ret; + + v4l2_ctrl_new_std(hdl, ops, V4L2_CID_BRIGHTNESS, -208, 127, 1, 0); + v4l2_ctrl_new_std(hdl, ops, V4L2_CID_CONTRAST, -127, 127, 1, 0); + v4l2_ctrl_new_std(hdl, ops, V4L2_CID_SATURATION, -127, 127, 1, 0); + + /* Sharpness default is 24612, and then (24612/SHARPNESS_DIV) = 2 */ + v4l2_ctrl_new_std(hdl, ops, V4L2_CID_SHARPNESS, -32704/SHARPNESS_DIV, + 24612/SHARPNESS_DIV, 1, 2); + if (hdl->error) { + ret = hdl->error; + v4l2_ctrl_handler_free(hdl); + return ret; + } + priv->sd.ctrl_handler = hdl; + + return 0; +}; + +static int s5k4ecgx_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct s5k4ecgx_platform_data *pdata = client->dev.platform_data; + struct v4l2_subdev *sd; + struct s5k4ecgx *priv; + int ret, i; + + if (pdata == NULL) { + dev_err(&client->dev, "platform data is missing!\n"); + return -EINVAL; + } + + priv = devm_kzalloc(&client->dev, sizeof(struct s5k4ecgx), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + mutex_init(&priv->lock); + priv->streaming = 0; + + sd = &priv->sd; + /* Registering subdev */ + v4l2_i2c_subdev_init(sd, client, &s5k4ecgx_ops); + strlcpy(sd->name, S5K4ECGX_DRIVER_NAME, sizeof(sd->name)); + + sd->internal_ops = &s5k4ecgx_subdev_internal_ops; + /* Support v4l2 sub-device user space API */ + sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; + + priv->pad.flags = MEDIA_PAD_FL_SOURCE; + sd->entity.type = MEDIA_ENT_T_V4L2_SUBDEV_SENSOR; + ret = media_entity_init(&sd->entity, 1, &priv->pad, 0); + if (ret) + return ret; + + ret = s5k4ecgx_config_gpios(priv, pdata); + if (ret) { + dev_err(&client->dev, "Failed to set gpios\n"); + goto out_err1; + } + for (i = 0; i < S5K4ECGX_NUM_SUPPLIES; i++) + priv->supplies[i].supply = s5k4ecgx_supply_names[i]; + + ret = devm_regulator_bulk_get(&client->dev, S5K4ECGX_NUM_SUPPLIES, + priv->supplies); + if (ret) { + dev_err(&client->dev, "Failed to get regulators\n"); + goto out_err2; + } + ret = s5k4ecgx_init_v4l2_ctrls(priv); + if (ret) + goto out_err2; + + priv->curr_pixfmt = &s5k4ecgx_formats[0]; + priv->curr_frmsize = &s5k4ecgx_prev_sizes[0]; + + return 0; + +out_err2: + s5k4ecgx_free_gpios(priv); +out_err1: + media_entity_cleanup(&priv->sd.entity); + + return ret; +} + +static int s5k4ecgx_remove(struct i2c_client *client) +{ + struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct s5k4ecgx *priv = to_s5k4ecgx(sd); + + mutex_destroy(&priv->lock); + s5k4ecgx_free_gpios(priv); + v4l2_device_unregister_subdev(sd); + v4l2_ctrl_handler_free(&priv->handler); + media_entity_cleanup(&sd->entity); + + return 0; +} + +static const struct i2c_device_id s5k4ecgx_id[] = { + { S5K4ECGX_DRIVER_NAME, 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, s5k4ecgx_id); + +static struct i2c_driver v4l2_i2c_driver = { + .driver = { + .owner = THIS_MODULE, + .name = S5K4ECGX_DRIVER_NAME, + }, + .probe = s5k4ecgx_probe, + .remove = s5k4ecgx_remove, + .id_table = s5k4ecgx_id, +}; + +module_i2c_driver(v4l2_i2c_driver); + +MODULE_DESCRIPTION("Samsung S5K4ECGX 5MP SOC camera"); +MODULE_AUTHOR("Sangwook Lee <sangwook.lee@linaro.org>"); +MODULE_AUTHOR("Seok-Young Jang <quartz.jang@samsung.com>"); +MODULE_LICENSE("GPL"); +MODULE_FIRMWARE(S5K4ECGX_FIRMWARE); diff --git a/drivers/media/video/s5k6aa.c b/drivers/media/i2c/s5k6aa.c index 6625e46a4638..57cd4fa0193d 100644 --- a/drivers/media/video/s5k6aa.c +++ b/drivers/media/i2c/s5k6aa.c @@ -1061,10 +1061,9 @@ __s5k6aa_get_crop_rect(struct s5k6aa *s5k6aa, struct v4l2_subdev_fh *fh, { if (which == V4L2_SUBDEV_FORMAT_ACTIVE) return &s5k6aa->ccd_rect; - if (which == V4L2_SUBDEV_FORMAT_TRY) - return v4l2_subdev_get_try_crop(fh, 0); - return NULL; + WARN_ON(which != V4L2_SUBDEV_FORMAT_TRY); + return v4l2_subdev_get_try_crop(fh, 0); } static void s5k6aa_try_format(struct s5k6aa *s5k6aa, @@ -1169,12 +1168,10 @@ static int s5k6aa_get_crop(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, struct v4l2_rect *rect; memset(crop->reserved, 0, sizeof(crop->reserved)); - mutex_lock(&s5k6aa->lock); + mutex_lock(&s5k6aa->lock); rect = __s5k6aa_get_crop_rect(s5k6aa, fh, crop->which); - if (rect) - crop->rect = *rect; - + crop->rect = *rect; mutex_unlock(&s5k6aa->lock); v4l2_dbg(1, debug, sd, "Current crop rectangle: (%d,%d)/%dx%d\n", @@ -1436,7 +1433,7 @@ static int s5k6aa_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) return 0; } -int s5k6aa_check_fw_revision(struct s5k6aa *s5k6aa) +static int s5k6aa_check_fw_revision(struct s5k6aa *s5k6aa) { struct i2c_client *client = v4l2_get_subdevdata(&s5k6aa->sd); u16 api_ver = 0, fw_rev = 0; @@ -1568,7 +1565,7 @@ static int s5k6aa_probe(struct i2c_client *client, return -EINVAL; } - s5k6aa = kzalloc(sizeof(*s5k6aa), GFP_KERNEL); + s5k6aa = devm_kzalloc(&client->dev, sizeof(*s5k6aa), GFP_KERNEL); if (!s5k6aa) return -ENOMEM; @@ -1592,7 +1589,7 @@ static int s5k6aa_probe(struct i2c_client *client, sd->entity.type = MEDIA_ENT_T_V4L2_SUBDEV_SENSOR; ret = media_entity_init(&sd->entity, 1, &s5k6aa->pad, 0); if (ret) - goto out_err1; + return ret; ret = s5k6aa_configure_gpios(s5k6aa, pdata); if (ret) @@ -1627,8 +1624,6 @@ out_err3: s5k6aa_free_gpios(s5k6aa); out_err2: media_entity_cleanup(&s5k6aa->sd.entity); -out_err1: - kfree(s5k6aa); return ret; } @@ -1642,7 +1637,6 @@ static int s5k6aa_remove(struct i2c_client *client) media_entity_cleanup(&sd->entity); regulator_bulk_free(S5K6AA_NUM_SUPPLIES, s5k6aa->supplies); s5k6aa_free_gpios(s5k6aa); - kfree(s5k6aa); return 0; } diff --git a/drivers/media/video/saa6588.c b/drivers/media/i2c/saa6588.c index 0caac50d7cf4..0caac50d7cf4 100644 --- a/drivers/media/video/saa6588.c +++ b/drivers/media/i2c/saa6588.c diff --git a/drivers/media/video/saa7110.c b/drivers/media/i2c/saa7110.c index 51cd4c8f0520..51cd4c8f0520 100644 --- a/drivers/media/video/saa7110.c +++ b/drivers/media/i2c/saa7110.c diff --git a/drivers/media/video/saa7115.c b/drivers/media/i2c/saa7115.c index 2107336cd836..6b6788cd08f6 100644 --- a/drivers/media/video/saa7115.c +++ b/drivers/media/i2c/saa7115.c @@ -1066,7 +1066,8 @@ static int saa711x_g_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_f }; int i; - memset(sliced, 0, sizeof(*sliced)); + memset(sliced->service_lines, 0, sizeof(sliced->service_lines)); + sliced->service_set = 0; /* done if using raw VBI */ if (saa711x_read(sd, R_80_GLOBAL_CNTL_1) & 0x10) return 0; diff --git a/drivers/media/video/saa711x_regs.h b/drivers/media/i2c/saa711x_regs.h index 4e5f2eb0a2c1..4e5f2eb0a2c1 100644 --- a/drivers/media/video/saa711x_regs.h +++ b/drivers/media/i2c/saa711x_regs.h diff --git a/drivers/media/video/saa7127.c b/drivers/media/i2c/saa7127.c index 39c90b08eea8..b745f68fbc92 100644 --- a/drivers/media/video/saa7127.c +++ b/drivers/media/i2c/saa7127.c @@ -364,10 +364,7 @@ static int saa7127_set_vps(struct v4l2_subdev *sd, const struct v4l2_sliced_vbi_ state->vps_data[2] = data->data[9]; state->vps_data[3] = data->data[10]; state->vps_data[4] = data->data[11]; - v4l2_dbg(1, debug, sd, "Set VPS data %02x %02x %02x %02x %02x\n", - state->vps_data[0], state->vps_data[1], - state->vps_data[2], state->vps_data[3], - state->vps_data[4]); + v4l2_dbg(1, debug, sd, "Set VPS data %*ph\n", 5, state->vps_data); saa7127_write(sd, 0x55, state->vps_data[0]); saa7127_write(sd, 0x56, state->vps_data[1]); saa7127_write(sd, 0x57, state->vps_data[2]); @@ -628,7 +625,7 @@ static int saa7127_g_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_f { struct saa7127_state *state = to_state(sd); - memset(fmt, 0, sizeof(*fmt)); + memset(fmt->service_lines, 0, sizeof(fmt->service_lines)); if (state->vps_enable) fmt->service_lines[0][16] = V4L2_SLICED_VPS; if (state->wss_enable) diff --git a/drivers/media/video/saa717x.c b/drivers/media/i2c/saa717x.c index 1e84466515aa..1e84466515aa 100644 --- a/drivers/media/video/saa717x.c +++ b/drivers/media/i2c/saa717x.c diff --git a/drivers/media/video/saa7185.c b/drivers/media/i2c/saa7185.c index 2c6b65c76e2b..2c6b65c76e2b 100644 --- a/drivers/media/video/saa7185.c +++ b/drivers/media/i2c/saa7185.c diff --git a/drivers/media/video/saa7191.c b/drivers/media/i2c/saa7191.c index d7d1670e0ca3..d7d1670e0ca3 100644 --- a/drivers/media/video/saa7191.c +++ b/drivers/media/i2c/saa7191.c diff --git a/drivers/media/video/saa7191.h b/drivers/media/i2c/saa7191.h index 803c74d6066f..803c74d6066f 100644 --- a/drivers/media/video/saa7191.h +++ b/drivers/media/i2c/saa7191.h diff --git a/drivers/media/video/smiapp-pll.c b/drivers/media/i2c/smiapp-pll.c index a2e41a21dc65..a577614bd84f 100644 --- a/drivers/media/video/smiapp-pll.c +++ b/drivers/media/i2c/smiapp-pll.c @@ -1,5 +1,5 @@ /* - * drivers/media/video/smiapp-pll.c + * drivers/media/i2c/smiapp-pll.c * * Generic driver for SMIA/SMIA++ compliant camera modules * diff --git a/drivers/media/video/smiapp-pll.h b/drivers/media/i2c/smiapp-pll.h index 9eab63f23afb..cb2d2db5d02d 100644 --- a/drivers/media/video/smiapp-pll.h +++ b/drivers/media/i2c/smiapp-pll.h @@ -1,5 +1,5 @@ /* - * drivers/media/video/smiapp-pll.h + * drivers/media/i2c/smiapp-pll.h * * Generic driver for SMIA/SMIA++ compliant camera modules * diff --git a/drivers/media/video/smiapp/Kconfig b/drivers/media/i2c/smiapp/Kconfig index 3149cda1d0db..3149cda1d0db 100644 --- a/drivers/media/video/smiapp/Kconfig +++ b/drivers/media/i2c/smiapp/Kconfig diff --git a/drivers/media/video/smiapp/Makefile b/drivers/media/i2c/smiapp/Makefile index 36b0cfa2c541..f45a003cbe7e 100644 --- a/drivers/media/video/smiapp/Makefile +++ b/drivers/media/i2c/smiapp/Makefile @@ -2,4 +2,4 @@ smiapp-objs += smiapp-core.o smiapp-regs.o \ smiapp-quirk.o smiapp-limits.o obj-$(CONFIG_VIDEO_SMIAPP) += smiapp.o -ccflags-y += -Idrivers/media/video +ccflags-y += -Idrivers/media/i2c diff --git a/drivers/media/video/smiapp/smiapp-core.c b/drivers/media/i2c/smiapp/smiapp-core.c index bfd47c106134..e08e588ad24b 100644 --- a/drivers/media/video/smiapp/smiapp-core.c +++ b/drivers/media/i2c/smiapp/smiapp-core.c @@ -1,5 +1,5 @@ /* - * drivers/media/video/smiapp/smiapp-core.c + * drivers/media/i2c/smiapp/smiapp-core.c * * Generic driver for SMIA/SMIA++ compliant camera modules * @@ -777,7 +777,11 @@ static int smiapp_get_mbus_formats(struct smiapp_sensor *sensor) dev_dbg(&client->dev, "jolly good! %d\n", j); sensor->default_mbus_frame_fmts |= 1 << j; - if (!sensor->csi_format) { + if (!sensor->csi_format + || f->width > sensor->csi_format->width + || (f->width == sensor->csi_format->width + && f->compressed + > sensor->csi_format->compressed)) { sensor->csi_format = f; sensor->internal_csi_format = f; } @@ -2207,6 +2211,21 @@ smiapp_sysfs_nvm_read(struct device *dev, struct device_attribute *attr, } static DEVICE_ATTR(nvm, S_IRUGO, smiapp_sysfs_nvm_read, NULL); +static ssize_t +smiapp_sysfs_ident_read(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct v4l2_subdev *subdev = i2c_get_clientdata(to_i2c_client(dev)); + struct smiapp_sensor *sensor = to_smiapp_sensor(subdev); + struct smiapp_module_info *minfo = &sensor->minfo; + + return snprintf(buf, PAGE_SIZE, "%2.2x%4.4x%2.2x\n", + minfo->manufacturer_id, minfo->model_id, + minfo->revision_number_major) + 1; +} + +static DEVICE_ATTR(ident, S_IRUGO, smiapp_sysfs_ident_read, NULL); + /* ----------------------------------------------------------------------------- * V4L2 subdev core operations */ @@ -2355,20 +2374,19 @@ static int smiapp_registered(struct v4l2_subdev *subdev) unsigned int i; int rval; - sensor->vana = regulator_get(&client->dev, "VANA"); + sensor->vana = devm_regulator_get(&client->dev, "VANA"); if (IS_ERR(sensor->vana)) { dev_err(&client->dev, "could not get regulator for vana\n"); return -ENODEV; } if (!sensor->platform_data->set_xclk) { - sensor->ext_clk = clk_get(&client->dev, - sensor->platform_data->ext_clk_name); + sensor->ext_clk = devm_clk_get(&client->dev, + sensor->platform_data->ext_clk_name); if (IS_ERR(sensor->ext_clk)) { dev_err(&client->dev, "could not get clock %s\n", sensor->platform_data->ext_clk_name); - rval = -ENODEV; - goto out_clk_get; + return -ENODEV; } rval = clk_set_rate(sensor->ext_clk, @@ -2378,8 +2396,7 @@ static int smiapp_registered(struct v4l2_subdev *subdev) "unable to set clock %s freq to %u\n", sensor->platform_data->ext_clk_name, sensor->platform_data->ext_clk); - rval = -ENODEV; - goto out_clk_set_rate; + return -ENODEV; } } @@ -2389,8 +2406,7 @@ static int smiapp_registered(struct v4l2_subdev *subdev) dev_err(&client->dev, "unable to acquire reset gpio %d\n", sensor->platform_data->xshutdown); - rval = -ENODEV; - goto out_clk_set_rate; + return -ENODEV; } } @@ -2466,22 +2482,27 @@ static int smiapp_registered(struct v4l2_subdev *subdev) sensor->binning_horizontal = 1; sensor->binning_vertical = 1; + if (device_create_file(&client->dev, &dev_attr_ident) != 0) { + dev_err(&client->dev, "sysfs ident entry creation failed\n"); + rval = -ENOENT; + goto out_power_off; + } /* SMIA++ NVM initialization - it will be read from the sensor * when it is first requested by userspace. */ if (sensor->minfo.smiapp_version && sensor->platform_data->nvm_size) { - sensor->nvm = kzalloc(sensor->platform_data->nvm_size, - GFP_KERNEL); + sensor->nvm = devm_kzalloc(&client->dev, + sensor->platform_data->nvm_size, GFP_KERNEL); if (sensor->nvm == NULL) { dev_err(&client->dev, "nvm buf allocation failed\n"); rval = -ENOMEM; - goto out_power_off; + goto out_ident_release; } if (device_create_file(&client->dev, &dev_attr_nvm) != 0) { dev_err(&client->dev, "sysfs nvm entry failed\n"); rval = -EBUSY; - goto out_power_off; + goto out_ident_release; } } @@ -2636,22 +2657,16 @@ static int smiapp_registered(struct v4l2_subdev *subdev) out_nvm_release: device_remove_file(&client->dev, &dev_attr_nvm); +out_ident_release: + device_remove_file(&client->dev, &dev_attr_ident); + out_power_off: - kfree(sensor->nvm); - sensor->nvm = NULL; smiapp_power_off(sensor); out_smiapp_power_on: if (sensor->platform_data->xshutdown != SMIAPP_NO_XSHUTDOWN) gpio_free(sensor->platform_data->xshutdown); -out_clk_set_rate: - clk_put(sensor->ext_clk); - sensor->ext_clk = NULL; - -out_clk_get: - regulator_put(sensor->vana); - sensor->vana = NULL; return rval; } @@ -2801,12 +2816,11 @@ static int smiapp_probe(struct i2c_client *client, const struct i2c_device_id *devid) { struct smiapp_sensor *sensor; - int rval; if (client->dev.platform_data == NULL) return -ENODEV; - sensor = kzalloc(sizeof(*sensor), GFP_KERNEL); + sensor = devm_kzalloc(&client->dev, sizeof(*sensor), GFP_KERNEL); if (sensor == NULL) return -ENOMEM; @@ -2821,12 +2835,8 @@ static int smiapp_probe(struct i2c_client *client, sensor->src->sensor = sensor; sensor->src->pads[0].flags = MEDIA_PAD_FL_SOURCE; - rval = media_entity_init(&sensor->src->sd.entity, 2, + return media_entity_init(&sensor->src->sd.entity, 2, sensor->src->pads, 0); - if (rval < 0) - kfree(sensor); - - return rval; } static int __exit smiapp_remove(struct i2c_client *client) @@ -2845,10 +2855,9 @@ static int __exit smiapp_remove(struct i2c_client *client) sensor->power_count = 0; } - if (sensor->nvm) { + device_remove_file(&client->dev, &dev_attr_ident); + if (sensor->nvm) device_remove_file(&client->dev, &dev_attr_nvm); - kfree(sensor->nvm); - } for (i = 0; i < sensor->ssds_used; i++) { media_entity_cleanup(&sensor->ssds[i].sd.entity); @@ -2857,12 +2866,6 @@ static int __exit smiapp_remove(struct i2c_client *client) smiapp_free_controls(sensor); if (sensor->platform_data->xshutdown != SMIAPP_NO_XSHUTDOWN) gpio_free(sensor->platform_data->xshutdown); - if (sensor->ext_clk) - clk_put(sensor->ext_clk); - if (sensor->vana) - regulator_put(sensor->vana); - - kfree(sensor); return 0; } diff --git a/drivers/media/video/smiapp/smiapp-limits.c b/drivers/media/i2c/smiapp/smiapp-limits.c index 0800e095724e..fb2f81ad8c3b 100644 --- a/drivers/media/video/smiapp/smiapp-limits.c +++ b/drivers/media/i2c/smiapp/smiapp-limits.c @@ -1,5 +1,5 @@ /* - * drivers/media/video/smiapp/smiapp-limits.c + * drivers/media/i2c/smiapp/smiapp-limits.c * * Generic driver for SMIA/SMIA++ compliant camera modules * diff --git a/drivers/media/video/smiapp/smiapp-limits.h b/drivers/media/i2c/smiapp/smiapp-limits.h index 7f4836bb78db..9ae765e23ea5 100644 --- a/drivers/media/video/smiapp/smiapp-limits.h +++ b/drivers/media/i2c/smiapp/smiapp-limits.h @@ -1,5 +1,5 @@ /* - * drivers/media/video/smiapp/smiapp-limits.h + * drivers/media/i2c/smiapp/smiapp-limits.h * * Generic driver for SMIA/SMIA++ compliant camera modules * diff --git a/drivers/media/video/smiapp/smiapp-quirk.c b/drivers/media/i2c/smiapp/smiapp-quirk.c index 55e87950dcea..725cf62836c6 100644 --- a/drivers/media/video/smiapp/smiapp-quirk.c +++ b/drivers/media/i2c/smiapp/smiapp-quirk.c @@ -1,5 +1,5 @@ /* - * drivers/media/video/smiapp/smiapp-quirk.c + * drivers/media/i2c/smiapp/smiapp-quirk.c * * Generic driver for SMIA/SMIA++ compliant camera modules * @@ -61,26 +61,6 @@ void smiapp_replace_limit(struct smiapp_sensor *sensor, sensor->limits[limit] = val; } -int smiapp_replace_limit_at(struct smiapp_sensor *sensor, - u32 reg, u32 val) -{ - struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd); - int i; - - for (i = 0; smiapp_reg_limits[i].addr; i++) { - if ((smiapp_reg_limits[i].addr & 0xffff) != reg) - continue; - - smiapp_replace_limit(sensor, i, val); - - return 0; - } - - dev_dbg(&client->dev, "quirk: bad register 0x%4.4x\n", reg); - - return -EINVAL; -} - bool smiapp_quirk_reg(struct smiapp_sensor *sensor, u32 reg, u32 *val) { diff --git a/drivers/media/video/smiapp/smiapp-quirk.h b/drivers/media/i2c/smiapp/smiapp-quirk.h index f4dcaabaefe7..86fd3e8bfb0f 100644 --- a/drivers/media/video/smiapp/smiapp-quirk.h +++ b/drivers/media/i2c/smiapp/smiapp-quirk.h @@ -1,5 +1,5 @@ /* - * drivers/media/video/smiapp/smiapp-quirk.h + * drivers/media/i2c/smiapp/smiapp-quirk.h * * Generic driver for SMIA/SMIA++ compliant camera modules * diff --git a/drivers/media/video/smiapp/smiapp-reg-defs.h b/drivers/media/i2c/smiapp/smiapp-reg-defs.h index a089eb8161e1..defa7c5adebf 100644 --- a/drivers/media/video/smiapp/smiapp-reg-defs.h +++ b/drivers/media/i2c/smiapp/smiapp-reg-defs.h @@ -1,5 +1,5 @@ /* - * drivers/media/video/smiapp/smiapp-reg-defs.h + * drivers/media/i2c/smiapp/smiapp-reg-defs.h * * Generic driver for SMIA/SMIA++ compliant camera modules * diff --git a/drivers/media/video/smiapp/smiapp-reg.h b/drivers/media/i2c/smiapp/smiapp-reg.h index d0167aa17534..54568ca2fe6d 100644 --- a/drivers/media/video/smiapp/smiapp-reg.h +++ b/drivers/media/i2c/smiapp/smiapp-reg.h @@ -1,5 +1,5 @@ /* - * drivers/media/video/smiapp/smiapp-reg.h + * drivers/media/i2c/smiapp/smiapp-reg.h * * Generic driver for SMIA/SMIA++ compliant camera modules * diff --git a/drivers/media/video/smiapp/smiapp-regs.c b/drivers/media/i2c/smiapp/smiapp-regs.c index b1812b17a407..70e0d8db0130 100644 --- a/drivers/media/video/smiapp/smiapp-regs.c +++ b/drivers/media/i2c/smiapp/smiapp-regs.c @@ -1,5 +1,5 @@ /* - * drivers/media/video/smiapp/smiapp-regs.c + * drivers/media/i2c/smiapp/smiapp-regs.c * * Generic driver for SMIA/SMIA++ compliant camera modules * diff --git a/drivers/media/video/smiapp/smiapp-regs.h b/drivers/media/i2c/smiapp/smiapp-regs.h index 7f9013b47971..7f9013b47971 100644 --- a/drivers/media/video/smiapp/smiapp-regs.h +++ b/drivers/media/i2c/smiapp/smiapp-regs.h diff --git a/drivers/media/video/smiapp/smiapp.h b/drivers/media/i2c/smiapp/smiapp.h index 587f7f11238d..4182a695ab53 100644 --- a/drivers/media/video/smiapp/smiapp.h +++ b/drivers/media/i2c/smiapp/smiapp.h @@ -1,5 +1,5 @@ /* - * drivers/media/video/smiapp/smiapp.h + * drivers/media/i2c/smiapp/smiapp.h * * Generic driver for SMIA/SMIA++ compliant camera modules * diff --git a/drivers/media/i2c/soc_camera/Kconfig b/drivers/media/i2c/soc_camera/Kconfig new file mode 100644 index 000000000000..6dff2b7ad520 --- /dev/null +++ b/drivers/media/i2c/soc_camera/Kconfig @@ -0,0 +1,89 @@ +comment "soc_camera sensor drivers" + +config SOC_CAMERA_IMX074 + tristate "imx074 support" + depends on SOC_CAMERA && I2C + help + This driver supports IMX074 cameras from Sony + +config SOC_CAMERA_MT9M001 + tristate "mt9m001 support" + depends on SOC_CAMERA && I2C + select GPIO_PCA953X if MT9M001_PCA9536_SWITCH + help + This driver supports MT9M001 cameras from Micron, monochrome + and colour models. + +config SOC_CAMERA_MT9M111 + tristate "mt9m111, mt9m112 and mt9m131 support" + depends on SOC_CAMERA && I2C + help + This driver supports MT9M111, MT9M112 and MT9M131 cameras from + Micron/Aptina + +config SOC_CAMERA_MT9T031 + tristate "mt9t031 support" + depends on SOC_CAMERA && I2C + help + This driver supports MT9T031 cameras from Micron. + +config SOC_CAMERA_MT9T112 + tristate "mt9t112 support" + depends on SOC_CAMERA && I2C + help + This driver supports MT9T112 cameras from Aptina. + +config SOC_CAMERA_MT9V022 + tristate "mt9v022 and mt9v024 support" + depends on SOC_CAMERA && I2C + select GPIO_PCA953X if MT9V022_PCA9536_SWITCH + help + This driver supports MT9V022 cameras from Micron + +config SOC_CAMERA_OV2640 + tristate "ov2640 camera support" + depends on SOC_CAMERA && I2C + help + This is a ov2640 camera driver + +config SOC_CAMERA_OV5642 + tristate "ov5642 camera support" + depends on SOC_CAMERA && I2C + help + This is a V4L2 camera driver for the OmniVision OV5642 sensor + +config SOC_CAMERA_OV6650 + tristate "ov6650 sensor support" + depends on SOC_CAMERA && I2C + ---help--- + This is a V4L2 SoC camera driver for the OmniVision OV6650 sensor + +config SOC_CAMERA_OV772X + tristate "ov772x camera support" + depends on SOC_CAMERA && I2C + help + This is a ov772x camera driver + +config SOC_CAMERA_OV9640 + tristate "ov9640 camera support" + depends on SOC_CAMERA && I2C + help + This is a ov9640 camera driver + +config SOC_CAMERA_OV9740 + tristate "ov9740 camera support" + depends on SOC_CAMERA && I2C + help + This is a ov9740 camera driver + +config SOC_CAMERA_RJ54N1 + tristate "rj54n1cb0c support" + depends on SOC_CAMERA && I2C + help + This is a rj54n1cb0c video driver + +config SOC_CAMERA_TW9910 + tristate "tw9910 support" + depends on SOC_CAMERA && I2C + help + This is a tw9910 video driver diff --git a/drivers/media/i2c/soc_camera/Makefile b/drivers/media/i2c/soc_camera/Makefile new file mode 100644 index 000000000000..d0421feaa796 --- /dev/null +++ b/drivers/media/i2c/soc_camera/Makefile @@ -0,0 +1,14 @@ +obj-$(CONFIG_SOC_CAMERA_IMX074) += imx074.o +obj-$(CONFIG_SOC_CAMERA_MT9M001) += mt9m001.o +obj-$(CONFIG_SOC_CAMERA_MT9M111) += mt9m111.o +obj-$(CONFIG_SOC_CAMERA_MT9T031) += mt9t031.o +obj-$(CONFIG_SOC_CAMERA_MT9T112) += mt9t112.o +obj-$(CONFIG_SOC_CAMERA_MT9V022) += mt9v022.o +obj-$(CONFIG_SOC_CAMERA_OV2640) += ov2640.o +obj-$(CONFIG_SOC_CAMERA_OV5642) += ov5642.o +obj-$(CONFIG_SOC_CAMERA_OV6650) += ov6650.o +obj-$(CONFIG_SOC_CAMERA_OV772X) += ov772x.o +obj-$(CONFIG_SOC_CAMERA_OV9640) += ov9640.o +obj-$(CONFIG_SOC_CAMERA_OV9740) += ov9740.o +obj-$(CONFIG_SOC_CAMERA_RJ54N1) += rj54n1cb0c.o +obj-$(CONFIG_SOC_CAMERA_TW9910) += tw9910.o diff --git a/drivers/media/video/imx074.c b/drivers/media/i2c/soc_camera/imx074.c index 351e9bafe8fe..f8534eec9de9 100644 --- a/drivers/media/video/imx074.c +++ b/drivers/media/i2c/soc_camera/imx074.c @@ -268,6 +268,14 @@ static int imx074_g_chip_ident(struct v4l2_subdev *sd, return 0; } +static int imx074_s_power(struct v4l2_subdev *sd, int on) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + struct soc_camera_link *icl = soc_camera_i2c_to_link(client); + + return soc_camera_set_power(&client->dev, icl, on); +} + static int imx074_g_mbus_config(struct v4l2_subdev *sd, struct v4l2_mbus_config *cfg) { @@ -292,6 +300,7 @@ static struct v4l2_subdev_video_ops imx074_subdev_video_ops = { static struct v4l2_subdev_core_ops imx074_subdev_core_ops = { .g_chip_ident = imx074_g_chip_ident, + .s_power = imx074_s_power, }; static struct v4l2_subdev_ops imx074_subdev_ops = { @@ -301,26 +310,33 @@ static struct v4l2_subdev_ops imx074_subdev_ops = { static int imx074_video_probe(struct i2c_client *client) { + struct v4l2_subdev *subdev = i2c_get_clientdata(client); int ret; u16 id; + ret = imx074_s_power(subdev, 1); + if (ret < 0) + return ret; + /* Read sensor Model ID */ ret = reg_read(client, 0); if (ret < 0) - return ret; + goto done; id = ret << 8; ret = reg_read(client, 1); if (ret < 0) - return ret; + goto done; id |= ret; dev_info(&client->dev, "Chip ID 0x%04x detected\n", id); - if (id != 0x74) - return -ENODEV; + if (id != 0x74) { + ret = -ENODEV; + goto done; + } /* PLL Setting EXTCLK=24MHz, 22.5times */ reg_write(client, PLL_MULTIPLIER, 0x2D); @@ -402,7 +418,11 @@ static int imx074_video_probe(struct i2c_client *client) reg_write(client, GROUPED_PARAMETER_HOLD, 0x00); /* off */ - return 0; + ret = 0; + +done: + imx074_s_power(subdev, 0); + return ret; } static int imx074_probe(struct i2c_client *client, diff --git a/drivers/media/video/mt9m001.c b/drivers/media/i2c/soc_camera/mt9m001.c index 00583f5fd26b..19f8a07764f9 100644 --- a/drivers/media/video/mt9m001.c +++ b/drivers/media/i2c/soc_camera/mt9m001.c @@ -171,7 +171,7 @@ static int mt9m001_s_stream(struct v4l2_subdev *sd, int enable) return 0; } -static int mt9m001_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) +static int mt9m001_s_crop(struct v4l2_subdev *sd, const struct v4l2_crop *a) { struct i2c_client *client = v4l2_get_subdevdata(sd); struct mt9m001 *mt9m001 = to_mt9m001(client); @@ -377,6 +377,14 @@ static int mt9m001_s_register(struct v4l2_subdev *sd, } #endif +static int mt9m001_s_power(struct v4l2_subdev *sd, int on) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + struct soc_camera_link *icl = soc_camera_i2c_to_link(client); + + return soc_camera_set_power(&client->dev, icl, on); +} + static int mt9m001_g_volatile_ctrl(struct v4l2_ctrl *ctrl) { struct mt9m001 *mt9m001 = container_of(ctrl->handler, @@ -482,6 +490,10 @@ static int mt9m001_video_probe(struct soc_camera_link *icl, unsigned long flags; int ret; + ret = mt9m001_s_power(&mt9m001->subdev, 1); + if (ret < 0) + return ret; + /* Enable the chip */ data = reg_write(client, MT9M001_CHIP_ENABLE, 1); dev_dbg(&client->dev, "write: %d\n", data); @@ -503,7 +515,8 @@ static int mt9m001_video_probe(struct soc_camera_link *icl, default: dev_err(&client->dev, "No MT9M001 chip detected, register read %x\n", data); - return -ENODEV; + ret = -ENODEV; + goto done; } mt9m001->num_fmts = 0; @@ -532,11 +545,17 @@ static int mt9m001_video_probe(struct soc_camera_link *icl, data == 0x8431 ? "C12STM" : "C12ST"); ret = mt9m001_init(client); - if (ret < 0) + if (ret < 0) { dev_err(&client->dev, "Failed to initialise the camera\n"); + goto done; + } /* mt9m001_init() has reset the chip, returning registers to defaults */ - return v4l2_ctrl_handler_setup(&mt9m001->hdl); + ret = v4l2_ctrl_handler_setup(&mt9m001->hdl); + +done: + mt9m001_s_power(&mt9m001->subdev, 0); + return ret; } static void mt9m001_video_remove(struct soc_camera_link *icl) @@ -566,6 +585,7 @@ static struct v4l2_subdev_core_ops mt9m001_subdev_core_ops = { .g_register = mt9m001_g_register, .s_register = mt9m001_s_register, #endif + .s_power = mt9m001_s_power, }; static int mt9m001_enum_fmt(struct v4l2_subdev *sd, unsigned int index, diff --git a/drivers/media/video/mt9m111.c b/drivers/media/i2c/soc_camera/mt9m111.c index 863d722dda06..62fd94af599b 100644 --- a/drivers/media/video/mt9m111.c +++ b/drivers/media/i2c/soc_camera/mt9m111.c @@ -383,7 +383,7 @@ static int mt9m111_reset(struct mt9m111 *mt9m111) return ret; } -static int mt9m111_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) +static int mt9m111_s_crop(struct v4l2_subdev *sd, const struct v4l2_crop *a) { struct v4l2_rect rect = a->c; struct mt9m111 *mt9m111 = container_of(sd, struct mt9m111, subdev); @@ -796,45 +796,37 @@ static int mt9m111_init(struct mt9m111 *mt9m111) return ret; } -/* - * 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 mt9m111_video_probe(struct i2c_client *client) +static int mt9m111_power_on(struct mt9m111 *mt9m111) { - struct mt9m111 *mt9m111 = to_mt9m111(client); - s32 data; + struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev); + struct soc_camera_link *icl = soc_camera_i2c_to_link(client); int ret; - data = reg_read(CHIP_VERSION); + ret = soc_camera_power_on(&client->dev, icl); + if (ret < 0) + return ret; - switch (data) { - case 0x143a: /* MT9M111 or MT9M131 */ - mt9m111->model = V4L2_IDENT_MT9M111; - dev_info(&client->dev, - "Detected a MT9M111/MT9M131 chip ID %x\n", data); - break; - case 0x148c: /* MT9M112 */ - mt9m111->model = V4L2_IDENT_MT9M112; - dev_info(&client->dev, "Detected a MT9M112 chip ID %x\n", data); - break; - default: - dev_err(&client->dev, - "No MT9M111/MT9M112/MT9M131 chip detected register read %x\n", - data); - return -ENODEV; + ret = mt9m111_resume(mt9m111); + if (ret < 0) { + dev_err(&client->dev, "Failed to resume the sensor: %d\n", ret); + soc_camera_power_off(&client->dev, icl); } - ret = mt9m111_init(mt9m111); - if (ret) - return ret; - return v4l2_ctrl_handler_setup(&mt9m111->hdl); + return ret; +} + +static void mt9m111_power_off(struct mt9m111 *mt9m111) +{ + struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev); + struct soc_camera_link *icl = soc_camera_i2c_to_link(client); + + mt9m111_suspend(mt9m111); + soc_camera_power_off(&client->dev, icl); } static int mt9m111_s_power(struct v4l2_subdev *sd, int on) { struct mt9m111 *mt9m111 = container_of(sd, struct mt9m111, subdev); - struct i2c_client *client = v4l2_get_subdevdata(sd); int ret = 0; mutex_lock(&mt9m111->power_lock); @@ -844,23 +836,18 @@ static int mt9m111_s_power(struct v4l2_subdev *sd, int on) * update the power state. */ if (mt9m111->power_count == !on) { - if (on) { - ret = mt9m111_resume(mt9m111); - if (ret) { - dev_err(&client->dev, - "Failed to resume the sensor: %d\n", ret); - goto out; - } - } else { - mt9m111_suspend(mt9m111); - } + if (on) + ret = mt9m111_power_on(mt9m111); + else + mt9m111_power_off(mt9m111); } - /* Update the power count. */ - mt9m111->power_count += on ? 1 : -1; - WARN_ON(mt9m111->power_count < 0); + if (!ret) { + /* Update the power count. */ + mt9m111->power_count += on ? 1 : -1; + WARN_ON(mt9m111->power_count < 0); + } -out: mutex_unlock(&mt9m111->power_lock); return ret; } @@ -919,6 +906,51 @@ static struct v4l2_subdev_ops mt9m111_subdev_ops = { .video = &mt9m111_subdev_video_ops, }; +/* + * 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 mt9m111_video_probe(struct i2c_client *client) +{ + struct mt9m111 *mt9m111 = to_mt9m111(client); + s32 data; + int ret; + + ret = mt9m111_s_power(&mt9m111->subdev, 1); + if (ret < 0) + return ret; + + data = reg_read(CHIP_VERSION); + + switch (data) { + case 0x143a: /* MT9M111 or MT9M131 */ + mt9m111->model = V4L2_IDENT_MT9M111; + dev_info(&client->dev, + "Detected a MT9M111/MT9M131 chip ID %x\n", data); + break; + case 0x148c: /* MT9M112 */ + mt9m111->model = V4L2_IDENT_MT9M112; + dev_info(&client->dev, "Detected a MT9M112 chip ID %x\n", data); + break; + default: + dev_err(&client->dev, + "No MT9M111/MT9M112/MT9M131 chip detected register read %x\n", + data); + ret = -ENODEV; + goto done; + } + + ret = mt9m111_init(mt9m111); + if (ret) + goto done; + + ret = v4l2_ctrl_handler_setup(&mt9m111->hdl); + +done: + mt9m111_s_power(&mt9m111->subdev, 0); + return ret; +} + static int mt9m111_probe(struct i2c_client *client, const struct i2c_device_id *did) { diff --git a/drivers/media/video/mt9t031.c b/drivers/media/i2c/soc_camera/mt9t031.c index 1415074138a5..40800b10a080 100644 --- a/drivers/media/video/mt9t031.c +++ b/drivers/media/i2c/soc_camera/mt9t031.c @@ -161,14 +161,6 @@ static int mt9t031_idle(struct i2c_client *client) return ret >= 0 ? 0 : -EIO; } -static int mt9t031_disable(struct i2c_client *client) -{ - /* Disable the chip */ - reg_clear(client, MT9T031_OUTPUT_CONTROL, 2); - - return 0; -} - static int mt9t031_s_stream(struct v4l2_subdev *sd, int enable) { struct i2c_client *client = v4l2_get_subdevdata(sd); @@ -302,7 +294,7 @@ static int mt9t031_set_params(struct i2c_client *client, return ret < 0 ? ret : 0; } -static int mt9t031_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) +static int mt9t031_s_crop(struct v4l2_subdev *sd, const struct v4l2_crop *a) { struct v4l2_rect rect = a->c; struct i2c_client *client = v4l2_get_subdevdata(sd); @@ -616,12 +608,19 @@ static struct device_type mt9t031_dev_type = { static int mt9t031_s_power(struct v4l2_subdev *sd, int on) { struct i2c_client *client = v4l2_get_subdevdata(sd); + struct soc_camera_link *icl = soc_camera_i2c_to_link(client); struct video_device *vdev = soc_camera_i2c_to_vdev(client); + int ret; - if (on) + if (on) { + ret = soc_camera_power_on(&client->dev, icl); + if (ret < 0) + return ret; vdev->dev.type = &mt9t031_dev_type; - else + } else { vdev->dev.type = NULL; + soc_camera_power_off(&client->dev, icl); + } return 0; } @@ -636,9 +635,15 @@ static int mt9t031_video_probe(struct i2c_client *client) s32 data; int ret; - /* Enable the chip */ - data = reg_write(client, MT9T031_CHIP_ENABLE, 1); - dev_dbg(&client->dev, "write: %d\n", data); + ret = mt9t031_s_power(&mt9t031->subdev, 1); + if (ret < 0) + return ret; + + ret = mt9t031_idle(client); + if (ret < 0) { + dev_err(&client->dev, "Failed to initialise the camera\n"); + goto done; + } /* Read out the chip version register */ data = reg_read(client, MT9T031_CHIP_VERSION); @@ -650,16 +655,16 @@ static int mt9t031_video_probe(struct i2c_client *client) default: dev_err(&client->dev, "No MT9T031 chip detected, register read %x\n", data); - return -ENODEV; + ret = -ENODEV; + goto done; } dev_info(&client->dev, "Detected a MT9T031 chip ID %x\n", data); - ret = mt9t031_idle(client); - if (ret < 0) - dev_err(&client->dev, "Failed to initialise the camera\n"); - else - v4l2_ctrl_handler_setup(&mt9t031->hdl); + ret = v4l2_ctrl_handler_setup(&mt9t031->hdl); + +done: + mt9t031_s_power(&mt9t031->subdev, 0); return ret; } @@ -810,12 +815,7 @@ static int mt9t031_probe(struct i2c_client *client, mt9t031->xskip = 1; mt9t031->yskip = 1; - mt9t031_idle(client); - ret = mt9t031_video_probe(client); - - mt9t031_disable(client); - if (ret) { v4l2_ctrl_handler_free(&mt9t031->hdl); kfree(mt9t031); diff --git a/drivers/media/video/mt9t112.c b/drivers/media/i2c/soc_camera/mt9t112.c index e1ae46a7ee96..de7cd836b0a2 100644 --- a/drivers/media/video/mt9t112.c +++ b/drivers/media/i2c/soc_camera/mt9t112.c @@ -776,12 +776,21 @@ static int mt9t112_s_register(struct v4l2_subdev *sd, } #endif +static int mt9t112_s_power(struct v4l2_subdev *sd, int on) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + struct soc_camera_link *icl = soc_camera_i2c_to_link(client); + + return soc_camera_set_power(&client->dev, icl, on); +} + static struct v4l2_subdev_core_ops mt9t112_subdev_core_ops = { .g_chip_ident = mt9t112_g_chip_ident, #ifdef CONFIG_VIDEO_ADV_DEBUG .g_register = mt9t112_g_register, .s_register = mt9t112_s_register, #endif + .s_power = mt9t112_s_power, }; @@ -898,11 +907,11 @@ static int mt9t112_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) return 0; } -static int mt9t112_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) +static int mt9t112_s_crop(struct v4l2_subdev *sd, const struct v4l2_crop *a) { struct i2c_client *client = v4l2_get_subdevdata(sd); struct mt9t112_priv *priv = to_mt9t112(client); - struct v4l2_rect *rect = &a->c; + const struct v4l2_rect *rect = &a->c; return mt9t112_set_params(priv, rect, priv->format->code); } @@ -1032,6 +1041,11 @@ static int mt9t112_camera_probe(struct i2c_client *client) struct mt9t112_priv *priv = to_mt9t112(client); const char *devname; int chipid; + int ret; + + ret = mt9t112_s_power(&priv->subdev, 1); + if (ret < 0) + return ret; /* * check and show chip ID @@ -1049,12 +1063,15 @@ static int mt9t112_camera_probe(struct i2c_client *client) break; default: dev_err(&client->dev, "Product ID error %04x\n", chipid); - return -ENODEV; + ret = -ENODEV; + goto done; } dev_info(&client->dev, "%s chip ID %04x\n", devname, chipid); - return 0; +done: + mt9t112_s_power(&priv->subdev, 0); + return ret; } static int mt9t112_probe(struct i2c_client *client, diff --git a/drivers/media/video/mt9v022.c b/drivers/media/i2c/soc_camera/mt9v022.c index 72479247522a..13057b966ee9 100644 --- a/drivers/media/video/mt9v022.c +++ b/drivers/media/i2c/soc_camera/mt9v022.c @@ -57,6 +57,10 @@ MODULE_PARM_DESC(sensor_type, "Sensor type: \"colour\" or \"monochrome\""); #define MT9V022_AEC_AGC_ENABLE 0xAF #define MT9V022_MAX_TOTAL_SHUTTER_WIDTH 0xBD +/* mt9v024 partial list register addresses changes with respect to mt9v022 */ +#define MT9V024_PIXCLK_FV_LV 0x72 +#define MT9V024_MAX_TOTAL_SHUTTER_WIDTH 0xAD + /* Progressive scan, master, defaults */ #define MT9V022_CHIP_CONTROL_DEFAULT 0x188 @@ -67,6 +71,8 @@ MODULE_PARM_DESC(sensor_type, "Sensor type: \"colour\" or \"monochrome\""); #define MT9V022_COLUMN_SKIP 1 #define MT9V022_ROW_SKIP 4 +#define is_mt9v024(id) (id == 0x1324) + /* MT9V022 has only one fixed colorspace per pixelcode */ struct mt9v022_datafmt { enum v4l2_mbus_pixelcode code; @@ -101,6 +107,22 @@ static const struct mt9v022_datafmt mt9v022_monochrome_fmts[] = { {V4L2_MBUS_FMT_Y8_1X8, V4L2_COLORSPACE_JPEG}, }; +/* only registers with different addresses on different mt9v02x sensors */ +struct mt9v02x_register { + u8 max_total_shutter_width; + u8 pixclk_fv_lv; +}; + +static const struct mt9v02x_register mt9v022_register = { + .max_total_shutter_width = MT9V022_MAX_TOTAL_SHUTTER_WIDTH, + .pixclk_fv_lv = MT9V022_PIXCLK_FV_LV, +}; + +static const struct mt9v02x_register mt9v024_register = { + .max_total_shutter_width = MT9V024_MAX_TOTAL_SHUTTER_WIDTH, + .pixclk_fv_lv = MT9V024_PIXCLK_FV_LV, +}; + struct mt9v022 { struct v4l2_subdev subdev; struct v4l2_ctrl_handler hdl; @@ -117,6 +139,7 @@ struct mt9v022 { struct v4l2_rect rect; /* Sensor window */ const struct mt9v022_datafmt *fmt; const struct mt9v022_datafmt *fmts; + const struct mt9v02x_register *reg; int num_fmts; int model; /* V4L2_IDENT_MT9V022* codes from v4l2-chip-ident.h */ u16 chip_control; @@ -185,7 +208,7 @@ static int mt9v022_init(struct i2c_client *client) if (!ret) ret = reg_write(client, MT9V022_TOTAL_SHUTTER_WIDTH, 480); if (!ret) - ret = reg_write(client, MT9V022_MAX_TOTAL_SHUTTER_WIDTH, 480); + ret = reg_write(client, mt9v022->reg->max_total_shutter_width, 480); if (!ret) /* default - auto */ ret = reg_clear(client, MT9V022_BLACK_LEVEL_CALIB_CTRL, 1); @@ -214,7 +237,7 @@ static int mt9v022_s_stream(struct v4l2_subdev *sd, int enable) return 0; } -static int mt9v022_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) +static int mt9v022_s_crop(struct v4l2_subdev *sd, const struct v4l2_crop *a) { struct i2c_client *client = v4l2_get_subdevdata(sd); struct mt9v022 *mt9v022 = to_mt9v022(client); @@ -238,7 +261,7 @@ static int mt9v022_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) ret = reg_read(client, MT9V022_AEC_AGC_ENABLE); if (ret >= 0) { if (ret & 1) /* Autoexposure */ - ret = reg_write(client, MT9V022_MAX_TOTAL_SHUTTER_WIDTH, + ret = reg_write(client, mt9v022->reg->max_total_shutter_width, rect.height + mt9v022->y_skip_top + 43); else ret = reg_write(client, MT9V022_TOTAL_SHUTTER_WIDTH, @@ -445,6 +468,14 @@ static int mt9v022_s_register(struct v4l2_subdev *sd, } #endif +static int mt9v022_s_power(struct v4l2_subdev *sd, int on) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + struct soc_camera_link *icl = soc_camera_i2c_to_link(client); + + return soc_camera_set_power(&client->dev, icl, on); +} + static int mt9v022_g_volatile_ctrl(struct v4l2_ctrl *ctrl) { struct mt9v022 *mt9v022 = container_of(ctrl->handler, @@ -570,17 +601,24 @@ static int mt9v022_video_probe(struct i2c_client *client) int ret; unsigned long flags; + ret = mt9v022_s_power(&mt9v022->subdev, 1); + if (ret < 0) + return ret; + /* Read out the chip version register */ data = reg_read(client, MT9V022_CHIP_VERSION); - /* must be 0x1311 or 0x1313 */ - if (data != 0x1311 && data != 0x1313) { + /* must be 0x1311, 0x1313 or 0x1324 */ + if (data != 0x1311 && data != 0x1313 && data != 0x1324) { ret = -ENODEV; dev_info(&client->dev, "No MT9V022 found, ID register 0x%x\n", data); goto ei2c; } + mt9v022->reg = is_mt9v024(data) ? &mt9v024_register : + &mt9v022_register; + /* Soft reset */ ret = reg_write(client, MT9V022_RESET, 1); if (ret < 0) @@ -640,6 +678,7 @@ static int mt9v022_video_probe(struct i2c_client *client) dev_err(&client->dev, "Failed to initialise the camera\n"); ei2c: + mt9v022_s_power(&mt9v022->subdev, 0); return ret; } @@ -664,6 +703,7 @@ static struct v4l2_subdev_core_ops mt9v022_subdev_core_ops = { .g_register = mt9v022_g_register, .s_register = mt9v022_s_register, #endif + .s_power = mt9v022_s_power, }; static int mt9v022_enum_fmt(struct v4l2_subdev *sd, unsigned int index, @@ -728,7 +768,7 @@ static int mt9v022_s_mbus_config(struct v4l2_subdev *sd, if (!(flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH)) pixclk |= 0x2; - ret = reg_write(client, MT9V022_PIXCLK_FV_LV, pixclk); + ret = reg_write(client, mt9v022->reg->pixclk_fv_lv, pixclk); if (ret < 0) return ret; diff --git a/drivers/media/video/ov2640.c b/drivers/media/i2c/soc_camera/ov2640.c index 7c44d1fe3c87..78ac5744cb5d 100644 --- a/drivers/media/video/ov2640.c +++ b/drivers/media/i2c/soc_camera/ov2640.c @@ -742,6 +742,14 @@ static int ov2640_s_register(struct v4l2_subdev *sd, } #endif +static int ov2640_s_power(struct v4l2_subdev *sd, int on) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + struct soc_camera_link *icl = soc_camera_i2c_to_link(client); + + return soc_camera_set_power(&client->dev, icl, on); +} + /* Select the nearest higher resolution for capture */ static const struct ov2640_win_size *ov2640_select_win(u32 *width, u32 *height) { @@ -947,6 +955,10 @@ static int ov2640_video_probe(struct i2c_client *client) const char *devname; int ret; + ret = ov2640_s_power(&priv->subdev, 1); + if (ret < 0) + return ret; + /* * check and show product ID and manufacturer ID */ @@ -965,16 +977,17 @@ static int ov2640_video_probe(struct i2c_client *client) dev_err(&client->dev, "Product ID error %x:%x\n", pid, ver); ret = -ENODEV; - goto err; + goto done; } dev_info(&client->dev, "%s Product ID %0x:%0x Manufacturer ID %x:%x\n", devname, pid, ver, midh, midl); - return v4l2_ctrl_handler_setup(&priv->hdl); + ret = v4l2_ctrl_handler_setup(&priv->hdl); -err: +done: + ov2640_s_power(&priv->subdev, 0); return ret; } @@ -988,6 +1001,7 @@ static struct v4l2_subdev_core_ops ov2640_subdev_core_ops = { .g_register = ov2640_g_register, .s_register = ov2640_s_register, #endif + .s_power = ov2640_s_power, }; static int ov2640_g_mbus_config(struct v4l2_subdev *sd, diff --git a/drivers/media/video/ov5642.c b/drivers/media/i2c/soc_camera/ov5642.c index 0bc93313d37a..8577e0cfb7fe 100644 --- a/drivers/media/video/ov5642.c +++ b/drivers/media/i2c/soc_camera/ov5642.c @@ -865,24 +865,24 @@ static int ov5642_g_chip_ident(struct v4l2_subdev *sd, return 0; } -static int ov5642_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) +static int ov5642_s_crop(struct v4l2_subdev *sd, const struct v4l2_crop *a) { struct i2c_client *client = v4l2_get_subdevdata(sd); struct ov5642 *priv = to_ov5642(client); - struct v4l2_rect *rect = &a->c; + struct v4l2_rect rect = a->c; int ret; - v4l_bound_align_image(&rect->width, 48, OV5642_MAX_WIDTH, 1, - &rect->height, 32, OV5642_MAX_HEIGHT, 1, 0); + v4l_bound_align_image(&rect.width, 48, OV5642_MAX_WIDTH, 1, + &rect.height, 32, OV5642_MAX_HEIGHT, 1, 0); - priv->crop_rect.width = rect->width; - priv->crop_rect.height = rect->height; - priv->total_width = rect->width + BLANKING_EXTRA_WIDTH; - priv->total_height = max_t(int, rect->height + + priv->crop_rect.width = rect.width; + priv->crop_rect.height = rect.height; + priv->total_width = rect.width + BLANKING_EXTRA_WIDTH; + priv->total_height = max_t(int, rect.height + BLANKING_EXTRA_HEIGHT, BLANKING_MIN_HEIGHT); - priv->crop_rect.width = rect->width; - priv->crop_rect.height = rect->height; + priv->crop_rect.width = rect.width; + priv->crop_rect.height = rect.height; ret = ov5642_write_array(client, ov5642_default_regs_init); if (!ret) @@ -933,13 +933,17 @@ static int ov5642_g_mbus_config(struct v4l2_subdev *sd, static int ov5642_s_power(struct v4l2_subdev *sd, int on) { - struct i2c_client *client; + struct i2c_client *client = v4l2_get_subdevdata(sd); + struct soc_camera_link *icl = soc_camera_i2c_to_link(client); int ret; if (!on) - return 0; + return soc_camera_power_off(&client->dev, icl); + + ret = soc_camera_power_on(&client->dev, icl); + if (ret < 0) + return ret; - client = v4l2_get_subdevdata(sd); ret = ov5642_write_array(client, ov5642_default_regs_init); if (!ret) ret = ov5642_set_resolution(sd); @@ -976,29 +980,40 @@ static struct v4l2_subdev_ops ov5642_subdev_ops = { static int ov5642_video_probe(struct i2c_client *client) { + struct v4l2_subdev *subdev = i2c_get_clientdata(client); int ret; u8 id_high, id_low; u16 id; + ret = ov5642_s_power(subdev, 1); + if (ret < 0) + return ret; + /* Read sensor Model ID */ ret = reg_read(client, REG_CHIP_ID_HIGH, &id_high); if (ret < 0) - return ret; + goto done; id = id_high << 8; ret = reg_read(client, REG_CHIP_ID_LOW, &id_low); if (ret < 0) - return ret; + goto done; id |= id_low; dev_info(&client->dev, "Chip ID 0x%04x detected\n", id); - if (id != 0x5642) - return -ENODEV; + if (id != 0x5642) { + ret = -ENODEV; + goto done; + } - return 0; + ret = 0; + +done: + ov5642_s_power(subdev, 0); + return ret; } static int ov5642_probe(struct i2c_client *client, diff --git a/drivers/media/video/ov6650.c b/drivers/media/i2c/soc_camera/ov6650.c index 3e028b1970dd..e87feb0881e3 100644 --- a/drivers/media/video/ov6650.c +++ b/drivers/media/i2c/soc_camera/ov6650.c @@ -432,6 +432,14 @@ static int ov6650_set_register(struct v4l2_subdev *sd, } #endif +static int ov6650_s_power(struct v4l2_subdev *sd, int on) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + struct soc_camera_link *icl = soc_camera_i2c_to_link(client); + + return soc_camera_set_power(&client->dev, icl, on); +} + static int ov6650_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) { struct i2c_client *client = v4l2_get_subdevdata(sd); @@ -443,42 +451,42 @@ static int ov6650_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) return 0; } -static int ov6650_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) +static int ov6650_s_crop(struct v4l2_subdev *sd, const struct v4l2_crop *a) { struct i2c_client *client = v4l2_get_subdevdata(sd); struct ov6650 *priv = to_ov6650(client); - struct v4l2_rect *rect = &a->c; + struct v4l2_rect rect = a->c; int ret; if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; - rect->left = ALIGN(rect->left, 2); - rect->width = ALIGN(rect->width, 2); - rect->top = ALIGN(rect->top, 2); - rect->height = ALIGN(rect->height, 2); - soc_camera_limit_side(&rect->left, &rect->width, + rect.left = ALIGN(rect.left, 2); + rect.width = ALIGN(rect.width, 2); + rect.top = ALIGN(rect.top, 2); + rect.height = ALIGN(rect.height, 2); + soc_camera_limit_side(&rect.left, &rect.width, DEF_HSTRT << 1, 2, W_CIF); - soc_camera_limit_side(&rect->top, &rect->height, + soc_camera_limit_side(&rect.top, &rect.height, DEF_VSTRT << 1, 2, H_CIF); - ret = ov6650_reg_write(client, REG_HSTRT, rect->left >> 1); + ret = ov6650_reg_write(client, REG_HSTRT, rect.left >> 1); if (!ret) { - priv->rect.left = rect->left; + priv->rect.left = rect.left; ret = ov6650_reg_write(client, REG_HSTOP, - (rect->left + rect->width) >> 1); + (rect.left + rect.width) >> 1); } if (!ret) { - priv->rect.width = rect->width; - ret = ov6650_reg_write(client, REG_VSTRT, rect->top >> 1); + priv->rect.width = rect.width; + ret = ov6650_reg_write(client, REG_VSTRT, rect.top >> 1); } if (!ret) { - priv->rect.top = rect->top; + priv->rect.top = rect.top; ret = ov6650_reg_write(client, REG_VSTOP, - (rect->top + rect->height) >> 1); + (rect.top + rect.height) >> 1); } if (!ret) - priv->rect.height = rect->height; + priv->rect.height = rect.height; return ret; } @@ -821,8 +829,13 @@ static int ov6650_prog_dflt(struct i2c_client *client) static int ov6650_video_probe(struct i2c_client *client) { + struct ov6650 *priv = to_ov6650(client); u8 pidh, pidl, midh, midl; - int ret = 0; + int ret; + + ret = ov6650_s_power(&priv->subdev, 1); + if (ret < 0) + return ret; /* * check and show product ID and manufacturer ID @@ -836,12 +849,13 @@ static int ov6650_video_probe(struct i2c_client *client) ret = ov6650_reg_read(client, REG_MIDL, &midl); if (ret) - return ret; + goto done; if ((pidh != OV6650_PIDH) || (pidl != OV6650_PIDL)) { dev_err(&client->dev, "Product ID error 0x%02x:0x%02x\n", pidh, pidl); - return -ENODEV; + ret = -ENODEV; + goto done; } dev_info(&client->dev, @@ -851,7 +865,11 @@ static int ov6650_video_probe(struct i2c_client *client) ret = ov6650_reset(client); if (!ret) ret = ov6650_prog_dflt(client); + if (!ret) + ret = v4l2_ctrl_handler_setup(&priv->hdl); +done: + ov6650_s_power(&priv->subdev, 0); return ret; } @@ -866,6 +884,7 @@ static struct v4l2_subdev_core_ops ov6650_core_ops = { .g_register = ov6650_get_register, .s_register = ov6650_set_register, #endif + .s_power = ov6650_s_power, }; /* Request bus settings on camera side */ @@ -1010,9 +1029,6 @@ static int ov6650_probe(struct i2c_client *client, priv->colorspace = V4L2_COLORSPACE_JPEG; ret = ov6650_video_probe(client); - if (!ret) - ret = v4l2_ctrl_handler_setup(&priv->hdl); - if (ret) { v4l2_ctrl_handler_free(&priv->hdl); kfree(priv); diff --git a/drivers/media/video/ov772x.c b/drivers/media/i2c/soc_camera/ov772x.c index 6d79b89b8603..e4a10751894d 100644 --- a/drivers/media/video/ov772x.c +++ b/drivers/media/i2c/soc_camera/ov772x.c @@ -16,6 +16,7 @@ */ #include <linux/init.h> +#include <linux/kernel.h> #include <linux/module.h> #include <linux/i2c.h> #include <linux/slab.h> @@ -274,6 +275,7 @@ #define SLCT_VGA 0x00 /* 0 : VGA */ #define SLCT_QVGA 0x40 /* 1 : QVGA */ #define ITU656_ON_OFF 0x20 /* ITU656 protocol ON/OFF selection */ +#define SENSOR_RAW 0x10 /* Sensor RAW */ /* RGB output format control */ #define FMT_MASK 0x0c /* Mask of color format */ #define FMT_GBR422 0x00 /* 00 : GBR 4:2:2 */ @@ -316,8 +318,15 @@ #define SGLF_ON_OFF 0x02 /* Single frame ON/OFF selection */ #define SGLF_TRIG 0x01 /* Single frame transfer trigger */ +/* HREF */ +#define HREF_VSTART_SHIFT 6 /* VSTART LSB */ +#define HREF_HSTART_SHIFT 4 /* HSTART 2 LSBs */ +#define HREF_VSIZE_SHIFT 2 /* VSIZE LSB */ +#define HREF_HSIZE_SHIFT 0 /* HSIZE 2 LSBs */ + /* EXHCH */ -#define VSIZE_LSB 0x04 /* Vertical data output size LSB */ +#define EXHCH_VSIZE_SHIFT 2 /* VOUTSIZE LSB */ +#define EXHCH_HSIZE_SHIFT 0 /* HOUTSIZE 2 LSBs */ /* DSP_CTRL1 */ #define FIFO_ON 0x80 /* FIFO enable/disable selection */ @@ -337,29 +346,11 @@ #define CBAR_ON 0x20 /* ON */ #define CBAR_OFF 0x00 /* OFF */ -/* HSTART */ -#define HST_VGA 0x23 -#define HST_QVGA 0x3F - -/* HSIZE */ -#define HSZ_VGA 0xA0 -#define HSZ_QVGA 0x50 - -/* VSTART */ -#define VST_VGA 0x07 -#define VST_QVGA 0x03 - -/* VSIZE */ -#define VSZ_VGA 0xF0 -#define VSZ_QVGA 0x78 - -/* HOUTSIZE */ -#define HOSZ_VGA 0xA0 -#define HOSZ_QVGA 0x50 - -/* VOUTSIZE */ -#define VOSZ_VGA 0xF0 -#define VOSZ_QVGA 0x78 +/* DSP_CTRL4 */ +#define DSP_OFMT_YUV 0x00 +#define DSP_OFMT_RGB 0x00 +#define DSP_OFMT_RAW8 0x02 +#define DSP_OFMT_RAW10 0x03 /* DSPAUTO (DSP Auto Function ON/OFF Control) */ #define AWB_ACTRL 0x80 /* AWB auto threshold control */ @@ -369,6 +360,13 @@ #define SCAL0_ACTRL 0x08 /* Auto scaling factor control */ #define SCAL1_2_ACTRL 0x04 /* Auto scaling factor control */ +#define VGA_WIDTH 640 +#define VGA_HEIGHT 480 +#define QVGA_WIDTH 320 +#define QVGA_HEIGHT 240 +#define OV772X_MAX_WIDTH VGA_WIDTH +#define OV772X_MAX_HEIGHT VGA_HEIGHT + /* * ID */ @@ -379,25 +377,20 @@ /* * struct */ -struct regval_list { - unsigned char reg_num; - unsigned char value; -}; struct ov772x_color_format { enum v4l2_mbus_pixelcode code; enum v4l2_colorspace colorspace; u8 dsp3; + u8 dsp4; u8 com3; u8 com7; }; struct ov772x_win_size { char *name; - __u32 width; - __u32 height; unsigned char com7_bit; - const struct regval_list *regs; + struct v4l2_rect rect; }; struct ov772x_priv { @@ -413,31 +406,6 @@ struct ov772x_priv { unsigned short band_filter; }; -#define ENDMARKER { 0xff, 0xff } - -/* - * register setting for window size - */ -static const struct regval_list ov772x_qvga_regs[] = { - { HSTART, HST_QVGA }, - { HSIZE, HSZ_QVGA }, - { VSTART, VST_QVGA }, - { VSIZE, VSZ_QVGA }, - { HOUTSIZE, HOSZ_QVGA }, - { VOUTSIZE, VOSZ_QVGA }, - ENDMARKER, -}; - -static const struct regval_list ov772x_vga_regs[] = { - { HSTART, HST_VGA }, - { HSIZE, HSZ_VGA }, - { VSTART, VST_VGA }, - { VSIZE, VSZ_VGA }, - { HOUTSIZE, HOSZ_VGA }, - { VOUTSIZE, VOSZ_VGA }, - ENDMARKER, -}; - /* * supported color format list */ @@ -446,6 +414,7 @@ static const struct ov772x_color_format ov772x_cfmts[] = { .code = V4L2_MBUS_FMT_YUYV8_2X8, .colorspace = V4L2_COLORSPACE_JPEG, .dsp3 = 0x0, + .dsp4 = DSP_OFMT_YUV, .com3 = SWAP_YUV, .com7 = OFMT_YUV, }, @@ -453,6 +422,7 @@ static const struct ov772x_color_format ov772x_cfmts[] = { .code = V4L2_MBUS_FMT_YVYU8_2X8, .colorspace = V4L2_COLORSPACE_JPEG, .dsp3 = UV_ON, + .dsp4 = DSP_OFMT_YUV, .com3 = SWAP_YUV, .com7 = OFMT_YUV, }, @@ -460,6 +430,7 @@ static const struct ov772x_color_format ov772x_cfmts[] = { .code = V4L2_MBUS_FMT_UYVY8_2X8, .colorspace = V4L2_COLORSPACE_JPEG, .dsp3 = 0x0, + .dsp4 = DSP_OFMT_YUV, .com3 = 0x0, .com7 = OFMT_YUV, }, @@ -467,6 +438,7 @@ static const struct ov772x_color_format ov772x_cfmts[] = { .code = V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE, .colorspace = V4L2_COLORSPACE_SRGB, .dsp3 = 0x0, + .dsp4 = DSP_OFMT_YUV, .com3 = SWAP_RGB, .com7 = FMT_RGB555 | OFMT_RGB, }, @@ -474,6 +446,7 @@ static const struct ov772x_color_format ov772x_cfmts[] = { .code = V4L2_MBUS_FMT_RGB555_2X8_PADHI_BE, .colorspace = V4L2_COLORSPACE_SRGB, .dsp3 = 0x0, + .dsp4 = DSP_OFMT_YUV, .com3 = 0x0, .com7 = FMT_RGB555 | OFMT_RGB, }, @@ -481,6 +454,7 @@ static const struct ov772x_color_format ov772x_cfmts[] = { .code = V4L2_MBUS_FMT_RGB565_2X8_LE, .colorspace = V4L2_COLORSPACE_SRGB, .dsp3 = 0x0, + .dsp4 = DSP_OFMT_YUV, .com3 = SWAP_RGB, .com7 = FMT_RGB565 | OFMT_RGB, }, @@ -488,82 +462,94 @@ static const struct ov772x_color_format ov772x_cfmts[] = { .code = V4L2_MBUS_FMT_RGB565_2X8_BE, .colorspace = V4L2_COLORSPACE_SRGB, .dsp3 = 0x0, + .dsp4 = DSP_OFMT_YUV, .com3 = 0x0, .com7 = FMT_RGB565 | OFMT_RGB, }, + { + /* Setting DSP4 to DSP_OFMT_RAW8 still gives 10-bit output, + * regardless of the COM7 value. We can thus only support 10-bit + * Bayer until someone figures it out. + */ + .code = V4L2_MBUS_FMT_SBGGR10_1X10, + .colorspace = V4L2_COLORSPACE_SRGB, + .dsp3 = 0x0, + .dsp4 = DSP_OFMT_RAW10, + .com3 = 0x0, + .com7 = SENSOR_RAW | OFMT_BRAW, + }, }; /* * window size list */ -#define VGA_WIDTH 640 -#define VGA_HEIGHT 480 -#define QVGA_WIDTH 320 -#define QVGA_HEIGHT 240 -#define MAX_WIDTH VGA_WIDTH -#define MAX_HEIGHT VGA_HEIGHT - -static const struct ov772x_win_size ov772x_win_vga = { - .name = "VGA", - .width = VGA_WIDTH, - .height = VGA_HEIGHT, - .com7_bit = SLCT_VGA, - .regs = ov772x_vga_regs, -}; -static const struct ov772x_win_size ov772x_win_qvga = { - .name = "QVGA", - .width = QVGA_WIDTH, - .height = QVGA_HEIGHT, - .com7_bit = SLCT_QVGA, - .regs = ov772x_qvga_regs, +static const struct ov772x_win_size ov772x_win_sizes[] = { + { + .name = "VGA", + .com7_bit = SLCT_VGA, + .rect = { + .left = 140, + .top = 14, + .width = VGA_WIDTH, + .height = VGA_HEIGHT, + }, + }, { + .name = "QVGA", + .com7_bit = SLCT_QVGA, + .rect = { + .left = 252, + .top = 6, + .width = QVGA_WIDTH, + .height = QVGA_HEIGHT, + }, + }, }; /* * general function */ -static struct ov772x_priv *to_ov772x(const struct i2c_client *client) +static struct ov772x_priv *to_ov772x(struct v4l2_subdev *sd) { - return container_of(i2c_get_clientdata(client), struct ov772x_priv, - subdev); + return container_of(sd, struct ov772x_priv, subdev); } -static int ov772x_write_array(struct i2c_client *client, - const struct regval_list *vals) +static inline int ov772x_read(struct i2c_client *client, u8 addr) { - while (vals->reg_num != 0xff) { - int ret = i2c_smbus_write_byte_data(client, - vals->reg_num, - vals->value); - if (ret < 0) - return ret; - vals++; - } - return 0; + return i2c_smbus_read_byte_data(client, addr); +} + +static inline int ov772x_write(struct i2c_client *client, u8 addr, u8 value) +{ + return i2c_smbus_write_byte_data(client, addr, value); } -static int ov772x_mask_set(struct i2c_client *client, - u8 command, - u8 mask, - u8 set) +static int ov772x_mask_set(struct i2c_client *client, u8 command, u8 mask, + u8 set) { - s32 val = i2c_smbus_read_byte_data(client, command); + s32 val = ov772x_read(client, command); if (val < 0) return val; val &= ~mask; val |= set & mask; - return i2c_smbus_write_byte_data(client, command, val); + return ov772x_write(client, command, val); } static int ov772x_reset(struct i2c_client *client) { - int ret = i2c_smbus_write_byte_data(client, COM7, SCCB_RESET); + int ret; + + ret = ov772x_write(client, COM7, SCCB_RESET); + if (ret < 0) + return ret; + msleep(1); - return ret; + + return ov772x_mask_set(client, COM2, SOFT_SLEEP_MODE, SOFT_SLEEP_MODE); } /* @@ -573,18 +559,13 @@ static int ov772x_reset(struct i2c_client *client) static int ov772x_s_stream(struct v4l2_subdev *sd, int enable) { struct i2c_client *client = v4l2_get_subdevdata(sd); - struct ov772x_priv *priv = container_of(sd, struct ov772x_priv, subdev); + struct ov772x_priv *priv = to_ov772x(sd); if (!enable) { ov772x_mask_set(client, COM2, SOFT_SLEEP_MODE, SOFT_SLEEP_MODE); return 0; } - if (!priv->win || !priv->cfmt) { - dev_err(&client->dev, "norm or win select error\n"); - return -EPERM; - } - ov772x_mask_set(client, COM2, SOFT_SLEEP_MODE, 0); dev_dbg(&client->dev, "format %d, win %s\n", @@ -642,7 +623,7 @@ static int ov772x_s_ctrl(struct v4l2_ctrl *ctrl) static int ov772x_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *id) { - struct ov772x_priv *priv = container_of(sd, struct ov772x_priv, subdev); + struct ov772x_priv *priv = to_ov772x(sd); id->ident = priv->model; id->revision = 0; @@ -661,7 +642,7 @@ static int ov772x_g_register(struct v4l2_subdev *sd, if (reg->reg > 0xff) return -EINVAL; - ret = i2c_smbus_read_byte_data(client, reg->reg); + ret = ov772x_read(client, reg->reg); if (ret < 0) return ret; @@ -679,54 +660,63 @@ static int ov772x_s_register(struct v4l2_subdev *sd, reg->val > 0xff) return -EINVAL; - return i2c_smbus_write_byte_data(client, reg->reg, reg->val); + return ov772x_write(client, reg->reg, reg->val); } #endif -static const struct ov772x_win_size *ov772x_select_win(u32 width, u32 height) +static int ov772x_s_power(struct v4l2_subdev *sd, int on) { - __u32 diff; - const struct ov772x_win_size *win; + struct i2c_client *client = v4l2_get_subdevdata(sd); + struct soc_camera_link *icl = soc_camera_i2c_to_link(client); - /* default is QVGA */ - diff = abs(width - ov772x_win_qvga.width) + - abs(height - ov772x_win_qvga.height); - win = &ov772x_win_qvga; + return soc_camera_set_power(&client->dev, icl, on); +} - /* VGA */ - if (diff > - abs(width - ov772x_win_vga.width) + - abs(height - ov772x_win_vga.height)) - win = &ov772x_win_vga; +static const struct ov772x_win_size *ov772x_select_win(u32 width, u32 height) +{ + const struct ov772x_win_size *win = &ov772x_win_sizes[0]; + u32 best_diff = UINT_MAX; + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(ov772x_win_sizes); ++i) { + u32 diff = abs(width - ov772x_win_sizes[i].rect.width) + + abs(height - ov772x_win_sizes[i].rect.height); + if (diff < best_diff) { + best_diff = diff; + win = &ov772x_win_sizes[i]; + } + } return win; } -static int ov772x_set_params(struct i2c_client *client, u32 *width, u32 *height, - enum v4l2_mbus_pixelcode code) +static void ov772x_select_params(const struct v4l2_mbus_framefmt *mf, + const struct ov772x_color_format **cfmt, + const struct ov772x_win_size **win) { - struct ov772x_priv *priv = to_ov772x(client); - int ret = -EINVAL; - u8 val; - int i; + unsigned int i; + + /* Select a format. */ + *cfmt = &ov772x_cfmts[0]; - /* - * select format - */ - priv->cfmt = NULL; for (i = 0; i < ARRAY_SIZE(ov772x_cfmts); i++) { - if (code == ov772x_cfmts[i].code) { - priv->cfmt = ov772x_cfmts + i; + if (mf->code == ov772x_cfmts[i].code) { + *cfmt = &ov772x_cfmts[i]; break; } } - if (!priv->cfmt) - goto ov772x_set_fmt_error; - /* - * select win - */ - priv->win = ov772x_select_win(*width, *height); + /* Select a window size. */ + *win = ov772x_select_win(mf->width, mf->height); +} + +static int ov772x_set_params(struct ov772x_priv *priv, + const struct ov772x_color_format *cfmt, + const struct ov772x_win_size *win) +{ + struct i2c_client *client = v4l2_get_subdevdata(&priv->subdev); + int ret; + u8 val; /* * reset hardware @@ -780,17 +770,42 @@ static int ov772x_set_params(struct i2c_client *client, u32 *width, u32 *height, goto ov772x_set_fmt_error; } - /* - * set size format - */ - ret = ov772x_write_array(client, priv->win->regs); + /* Format and window size */ + ret = ov772x_write(client, HSTART, win->rect.left >> 2); + if (ret < 0) + goto ov772x_set_fmt_error; + ret = ov772x_write(client, HSIZE, win->rect.width >> 2); + if (ret < 0) + goto ov772x_set_fmt_error; + ret = ov772x_write(client, VSTART, win->rect.top >> 1); + if (ret < 0) + goto ov772x_set_fmt_error; + ret = ov772x_write(client, VSIZE, win->rect.height >> 1); + if (ret < 0) + goto ov772x_set_fmt_error; + ret = ov772x_write(client, HOUTSIZE, win->rect.width >> 2); + if (ret < 0) + goto ov772x_set_fmt_error; + ret = ov772x_write(client, VOUTSIZE, win->rect.height >> 1); + if (ret < 0) + goto ov772x_set_fmt_error; + ret = ov772x_write(client, HREF, + ((win->rect.top & 1) << HREF_VSTART_SHIFT) | + ((win->rect.left & 3) << HREF_HSTART_SHIFT) | + ((win->rect.height & 1) << HREF_VSIZE_SHIFT) | + ((win->rect.width & 3) << HREF_HSIZE_SHIFT)); + if (ret < 0) + goto ov772x_set_fmt_error; + ret = ov772x_write(client, EXHCH, + ((win->rect.height & 1) << EXHCH_VSIZE_SHIFT) | + ((win->rect.width & 3) << EXHCH_HSIZE_SHIFT)); if (ret < 0) goto ov772x_set_fmt_error; /* * set DSP_CTRL3 */ - val = priv->cfmt->dsp3; + val = cfmt->dsp3; if (val) { ret = ov772x_mask_set(client, DSP_CTRL3, UV_MASK, val); @@ -798,10 +813,17 @@ static int ov772x_set_params(struct i2c_client *client, u32 *width, u32 *height, goto ov772x_set_fmt_error; } + /* DSP_CTRL4: AEC reference point and DSP output format. */ + if (cfmt->dsp4) { + ret = ov772x_write(client, DSP_CTRL4, cfmt->dsp4); + if (ret < 0) + goto ov772x_set_fmt_error; + } + /* * set COM3 */ - val = priv->cfmt->com3; + val = cfmt->com3; if (priv->info->flags & OV772X_FLAG_VFLIP) val |= VFLIP_IMG; if (priv->info->flags & OV772X_FLAG_HFLIP) @@ -816,13 +838,8 @@ static int ov772x_set_params(struct i2c_client *client, u32 *width, u32 *height, if (ret < 0) goto ov772x_set_fmt_error; - /* - * set COM7 - */ - val = priv->win->com7_bit | priv->cfmt->com7; - ret = ov772x_mask_set(client, - COM7, SLCT_MASK | FMT_MASK | OFMT_MASK, - val); + /* COM7: Sensor resolution and output format control. */ + ret = ov772x_write(client, COM7, win->com7_bit | cfmt->com7); if (ret < 0) goto ov772x_set_fmt_error; @@ -838,16 +855,11 @@ static int ov772x_set_params(struct i2c_client *client, u32 *width, u32 *height, goto ov772x_set_fmt_error; } - *width = priv->win->width; - *height = priv->win->height; - return ret; ov772x_set_fmt_error: ov772x_reset(client); - priv->win = NULL; - priv->cfmt = NULL; return ret; } @@ -867,8 +879,8 @@ static int ov772x_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a) { a->bounds.left = 0; a->bounds.top = 0; - a->bounds.width = VGA_WIDTH; - a->bounds.height = VGA_HEIGHT; + a->bounds.width = OV772X_MAX_WIDTH; + a->bounds.height = OV772X_MAX_HEIGHT; a->defrect = a->bounds; a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; a->pixelaspect.numerator = 1; @@ -880,15 +892,10 @@ static int ov772x_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a) static int ov772x_g_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *mf) { - struct ov772x_priv *priv = container_of(sd, struct ov772x_priv, subdev); - - if (!priv->win || !priv->cfmt) { - priv->cfmt = &ov772x_cfmts[0]; - priv->win = ov772x_select_win(VGA_WIDTH, VGA_HEIGHT); - } + struct ov772x_priv *priv = to_ov772x(sd); - mf->width = priv->win->width; - mf->height = priv->win->height; + mf->width = priv->win->rect.width; + mf->height = priv->win->rect.height; mf->code = priv->cfmt->code; mf->colorspace = priv->cfmt->colorspace; mf->field = V4L2_FIELD_NONE; @@ -896,70 +903,64 @@ static int ov772x_g_fmt(struct v4l2_subdev *sd, return 0; } -static int ov772x_s_fmt(struct v4l2_subdev *sd, - struct v4l2_mbus_framefmt *mf) +static int ov772x_s_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *mf) { - struct i2c_client *client = v4l2_get_subdevdata(sd); - struct ov772x_priv *priv = container_of(sd, struct ov772x_priv, subdev); - int ret = ov772x_set_params(client, &mf->width, &mf->height, - mf->code); + struct ov772x_priv *priv = to_ov772x(sd); + const struct ov772x_color_format *cfmt; + const struct ov772x_win_size *win; + int ret; - if (!ret) - mf->colorspace = priv->cfmt->colorspace; + ov772x_select_params(mf, &cfmt, &win); - return ret; + ret = ov772x_set_params(priv, cfmt, win); + if (ret < 0) + return ret; + + priv->win = win; + priv->cfmt = cfmt; + + mf->code = cfmt->code; + mf->width = win->rect.width; + mf->height = win->rect.height; + mf->field = V4L2_FIELD_NONE; + mf->colorspace = cfmt->colorspace; + + return 0; } static int ov772x_try_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *mf) { - struct ov772x_priv *priv = container_of(sd, struct ov772x_priv, subdev); + const struct ov772x_color_format *cfmt; const struct ov772x_win_size *win; - int i; - /* - * select suitable win - */ - win = ov772x_select_win(mf->width, mf->height); + ov772x_select_params(mf, &cfmt, &win); - mf->width = win->width; - mf->height = win->height; - mf->field = V4L2_FIELD_NONE; - - for (i = 0; i < ARRAY_SIZE(ov772x_cfmts); i++) - if (mf->code == ov772x_cfmts[i].code) - break; - - if (i == ARRAY_SIZE(ov772x_cfmts)) { - /* Unsupported format requested. Propose either */ - if (priv->cfmt) { - /* the current one or */ - mf->colorspace = priv->cfmt->colorspace; - mf->code = priv->cfmt->code; - } else { - /* the default one */ - mf->colorspace = ov772x_cfmts[0].colorspace; - mf->code = ov772x_cfmts[0].code; - } - } else { - /* Also return the colorspace */ - mf->colorspace = ov772x_cfmts[i].colorspace; - } + mf->code = cfmt->code; + mf->width = win->rect.width; + mf->height = win->rect.height; + mf->field = V4L2_FIELD_NONE; + mf->colorspace = cfmt->colorspace; return 0; } -static int ov772x_video_probe(struct i2c_client *client) +static int ov772x_video_probe(struct ov772x_priv *priv) { - struct ov772x_priv *priv = to_ov772x(client); + struct i2c_client *client = v4l2_get_subdevdata(&priv->subdev); u8 pid, ver; const char *devname; + int ret; + + ret = ov772x_s_power(&priv->subdev, 1); + if (ret < 0) + return ret; /* * check and show product ID and manufacturer ID */ - pid = i2c_smbus_read_byte_data(client, PID); - ver = i2c_smbus_read_byte_data(client, VER); + pid = ov772x_read(client, PID); + ver = ov772x_read(client, VER); switch (VERSION(pid, ver)) { case OV7720: @@ -973,7 +974,8 @@ static int ov772x_video_probe(struct i2c_client *client) default: dev_err(&client->dev, "Product ID error %x:%x\n", pid, ver); - return -ENODEV; + ret = -ENODEV; + goto done; } dev_info(&client->dev, @@ -981,9 +983,13 @@ static int ov772x_video_probe(struct i2c_client *client) devname, pid, ver, - i2c_smbus_read_byte_data(client, MIDH), - i2c_smbus_read_byte_data(client, MIDL)); - return v4l2_ctrl_handler_setup(&priv->hdl); + ov772x_read(client, MIDH), + ov772x_read(client, MIDL)); + ret = v4l2_ctrl_handler_setup(&priv->hdl); + +done: + ov772x_s_power(&priv->subdev, 0); + return ret; } static const struct v4l2_ctrl_ops ov772x_ctrl_ops = { @@ -996,6 +1002,7 @@ static struct v4l2_subdev_core_ops ov772x_subdev_core_ops = { .g_register = ov772x_g_register, .s_register = ov772x_s_register, #endif + .s_power = ov772x_s_power, }; static int ov772x_enum_fmt(struct v4l2_subdev *sd, unsigned int index, @@ -1079,24 +1086,28 @@ static int ov772x_probe(struct i2c_client *client, V4L2_CID_BAND_STOP_FILTER, 0, 256, 1, 0); priv->subdev.ctrl_handler = &priv->hdl; if (priv->hdl.error) { - int err = priv->hdl.error; - - kfree(priv); - return err; + ret = priv->hdl.error; + goto done; } - ret = ov772x_video_probe(client); + ret = ov772x_video_probe(priv); + if (ret < 0) + goto done; + + priv->cfmt = &ov772x_cfmts[0]; + priv->win = &ov772x_win_sizes[0]; + +done: if (ret) { v4l2_ctrl_handler_free(&priv->hdl); kfree(priv); } - return ret; } static int ov772x_remove(struct i2c_client *client) { - struct ov772x_priv *priv = to_ov772x(client); + struct ov772x_priv *priv = to_ov772x(i2c_get_clientdata(client)); v4l2_device_unregister_subdev(&priv->subdev); v4l2_ctrl_handler_free(&priv->hdl); diff --git a/drivers/media/video/ov9640.c b/drivers/media/i2c/soc_camera/ov9640.c index 9ed4ba4236c4..b323684eaf77 100644 --- a/drivers/media/video/ov9640.c +++ b/drivers/media/i2c/soc_camera/ov9640.c @@ -333,6 +333,14 @@ static int ov9640_set_register(struct v4l2_subdev *sd, } #endif +static int ov9640_s_power(struct v4l2_subdev *sd, int on) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + struct soc_camera_link *icl = soc_camera_i2c_to_link(client); + + return soc_camera_set_power(&client->dev, icl, on); +} + /* select nearest higher resolution for capture */ static void ov9640_res_roundup(u32 *width, u32 *height) { @@ -584,7 +592,11 @@ static int ov9640_video_probe(struct i2c_client *client) struct ov9640_priv *priv = to_ov9640_sensor(sd); u8 pid, ver, midh, midl; const char *devname; - int ret = 0; + int ret; + + ret = ov9640_s_power(&priv->subdev, 1); + if (ret < 0) + return ret; /* * check and show product ID and manufacturer ID @@ -598,7 +610,7 @@ static int ov9640_video_probe(struct i2c_client *client) if (!ret) ret = ov9640_reg_read(client, OV9640_MIDL, &midl); if (ret) - return ret; + goto done; switch (VERSION(pid, ver)) { case OV9640_V2: @@ -613,13 +625,18 @@ static int ov9640_video_probe(struct i2c_client *client) break; default: dev_err(&client->dev, "Product ID error %x:%x\n", pid, ver); - return -ENODEV; + ret = -ENODEV; + goto done; } dev_info(&client->dev, "%s Product ID %0x:%0x Manufacturer ID %x:%x\n", devname, pid, ver, midh, midl); - return v4l2_ctrl_handler_setup(&priv->hdl); + ret = v4l2_ctrl_handler_setup(&priv->hdl); + +done: + ov9640_s_power(&priv->subdev, 0); + return ret; } static const struct v4l2_ctrl_ops ov9640_ctrl_ops = { @@ -632,7 +649,7 @@ static struct v4l2_subdev_core_ops ov9640_core_ops = { .g_register = ov9640_get_register, .s_register = ov9640_set_register, #endif - + .s_power = ov9640_s_power, }; /* Request bus settings on camera side */ diff --git a/drivers/media/video/ov9640.h b/drivers/media/i2c/soc_camera/ov9640.h index 6b33a972c83c..6b33a972c83c 100644 --- a/drivers/media/video/ov9640.h +++ b/drivers/media/i2c/soc_camera/ov9640.h diff --git a/drivers/media/video/ov9740.c b/drivers/media/i2c/soc_camera/ov9740.c index 3eb07c22516e..7a55889e397b 100644 --- a/drivers/media/video/ov9740.c +++ b/drivers/media/i2c/soc_camera/ov9740.c @@ -786,17 +786,27 @@ static int ov9740_g_chip_ident(struct v4l2_subdev *sd, static int ov9740_s_power(struct v4l2_subdev *sd, int on) { + struct i2c_client *client = v4l2_get_subdevdata(sd); + struct soc_camera_link *icl = soc_camera_i2c_to_link(client); struct ov9740_priv *priv = to_ov9740(sd); - - if (!priv->current_enable) - return 0; + int ret; if (on) { - ov9740_s_fmt(sd, &priv->current_mf); - ov9740_s_stream(sd, priv->current_enable); + ret = soc_camera_power_on(&client->dev, icl); + if (ret < 0) + return ret; + + if (priv->current_enable) { + ov9740_s_fmt(sd, &priv->current_mf); + ov9740_s_stream(sd, 1); + } } else { - ov9740_s_stream(sd, 0); - priv->current_enable = true; + if (priv->current_enable) { + ov9740_s_stream(sd, 0); + priv->current_enable = true; + } + + soc_camera_power_off(&client->dev, icl); } return 0; @@ -843,34 +853,38 @@ static int ov9740_video_probe(struct i2c_client *client) u8 modelhi, modello; int ret; + ret = ov9740_s_power(&priv->subdev, 1); + if (ret < 0) + return ret; + /* * check and show product ID and manufacturer ID */ ret = ov9740_reg_read(client, OV9740_MODEL_ID_HI, &modelhi); if (ret < 0) - goto err; + goto done; ret = ov9740_reg_read(client, OV9740_MODEL_ID_LO, &modello); if (ret < 0) - goto err; + goto done; priv->model = (modelhi << 8) | modello; ret = ov9740_reg_read(client, OV9740_REVISION_NUMBER, &priv->revision); if (ret < 0) - goto err; + goto done; ret = ov9740_reg_read(client, OV9740_MANUFACTURER_ID, &priv->manid); if (ret < 0) - goto err; + goto done; ret = ov9740_reg_read(client, OV9740_SMIA_VERSION, &priv->smiaver); if (ret < 0) - goto err; + goto done; if (priv->model != 0x9740) { ret = -ENODEV; - goto err; + goto done; } priv->ident = V4L2_IDENT_OV9740; @@ -879,7 +893,10 @@ static int ov9740_video_probe(struct i2c_client *client) "Manufacturer 0x%02x, SMIA Version 0x%02x\n", priv->model, priv->revision, priv->manid, priv->smiaver); -err: + ret = v4l2_ctrl_handler_setup(&priv->hdl); + +done: + ov9740_s_power(&priv->subdev, 0); return ret; } @@ -963,8 +980,6 @@ static int ov9740_probe(struct i2c_client *client, } ret = ov9740_video_probe(client); - if (!ret) - ret = v4l2_ctrl_handler_setup(&priv->hdl); if (ret < 0) { v4l2_ctrl_handler_free(&priv->hdl); kfree(priv); diff --git a/drivers/media/video/rj54n1cb0c.c b/drivers/media/i2c/soc_camera/rj54n1cb0c.c index f6419b22c258..02f0400051d9 100644 --- a/drivers/media/video/rj54n1cb0c.c +++ b/drivers/media/i2c/soc_camera/rj54n1cb0c.c @@ -536,11 +536,11 @@ static int rj54n1_commit(struct i2c_client *client) static int rj54n1_sensor_scale(struct v4l2_subdev *sd, s32 *in_w, s32 *in_h, s32 *out_w, s32 *out_h); -static int rj54n1_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) +static int rj54n1_s_crop(struct v4l2_subdev *sd, const struct v4l2_crop *a) { struct i2c_client *client = v4l2_get_subdevdata(sd); struct rj54n1 *rj54n1 = to_rj54n1(client); - struct v4l2_rect *rect = &a->c; + const struct v4l2_rect *rect = &a->c; int dummy = 0, output_w, output_h, input_w = rect->width, input_h = rect->height; int ret; @@ -1180,6 +1180,14 @@ static int rj54n1_s_register(struct v4l2_subdev *sd, } #endif +static int rj54n1_s_power(struct v4l2_subdev *sd, int on) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + struct soc_camera_link *icl = soc_camera_i2c_to_link(client); + + return soc_camera_set_power(&client->dev, icl, on); +} + static int rj54n1_s_ctrl(struct v4l2_ctrl *ctrl) { struct rj54n1 *rj54n1 = container_of(ctrl->handler, struct rj54n1, hdl); @@ -1230,6 +1238,7 @@ static struct v4l2_subdev_core_ops rj54n1_subdev_core_ops = { .g_register = rj54n1_g_register, .s_register = rj54n1_s_register, #endif + .s_power = rj54n1_s_power, }; static int rj54n1_g_mbus_config(struct v4l2_subdev *sd, @@ -1287,9 +1296,14 @@ static struct v4l2_subdev_ops rj54n1_subdev_ops = { static int rj54n1_video_probe(struct i2c_client *client, struct rj54n1_pdata *priv) { + struct rj54n1 *rj54n1 = to_rj54n1(client); int data1, data2; int ret; + ret = rj54n1_s_power(&rj54n1->subdev, 1); + if (ret < 0) + return ret; + /* Read out the chip version register */ data1 = reg_read(client, RJ54N1_DEV_CODE); data2 = reg_read(client, RJ54N1_DEV_CODE2); @@ -1298,18 +1312,21 @@ static int rj54n1_video_probe(struct i2c_client *client, ret = -ENODEV; dev_info(&client->dev, "No RJ54N1CB0C found, read 0x%x:0x%x\n", data1, data2); - goto ei2c; + goto done; } /* Configure IOCTL polarity from the platform data: 0 or 1 << 7. */ ret = reg_write(client, RJ54N1_IOC, priv->ioctl_high << 7); if (ret < 0) - goto ei2c; + goto done; dev_info(&client->dev, "Detected a RJ54N1CB0C chip ID 0x%x:0x%x\n", data1, data2); -ei2c: + ret = v4l2_ctrl_handler_setup(&rj54n1->hdl); + +done: + rj54n1_s_power(&rj54n1->subdev, 0); return ret; } @@ -1373,9 +1390,9 @@ static int rj54n1_probe(struct i2c_client *client, if (ret < 0) { v4l2_ctrl_handler_free(&rj54n1->hdl); kfree(rj54n1); - return ret; } - return v4l2_ctrl_handler_setup(&rj54n1->hdl); + + return ret; } static int rj54n1_remove(struct i2c_client *client) diff --git a/drivers/media/video/tw9910.c b/drivers/media/i2c/soc_camera/tw9910.c index 9f53eacb66e3..140716e71a15 100644 --- a/drivers/media/video/tw9910.c +++ b/drivers/media/i2c/soc_camera/tw9910.c @@ -566,6 +566,14 @@ static int tw9910_s_register(struct v4l2_subdev *sd, } #endif +static int tw9910_s_power(struct v4l2_subdev *sd, int on) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + struct soc_camera_link *icl = soc_camera_i2c_to_link(client); + + return soc_camera_set_power(&client->dev, icl, on); +} + static int tw9910_set_frame(struct v4l2_subdev *sd, u32 *width, u32 *height) { struct i2c_client *client = v4l2_get_subdevdata(sd); @@ -772,6 +780,7 @@ static int tw9910_video_probe(struct i2c_client *client) { struct tw9910_priv *priv = to_tw9910(client); s32 id; + int ret; /* * tw9910 only use 8 or 16 bit bus width @@ -782,6 +791,10 @@ static int tw9910_video_probe(struct i2c_client *client) return -ENODEV; } + ret = tw9910_s_power(&priv->subdev, 1); + if (ret < 0) + return ret; + /* * check and show Product ID * So far only revisions 0 and 1 have been seen @@ -795,7 +808,8 @@ static int tw9910_video_probe(struct i2c_client *client) dev_err(&client->dev, "Product ID error %x:%x\n", id, priv->revision); - return -ENODEV; + ret = -ENODEV; + goto done; } dev_info(&client->dev, @@ -803,7 +817,9 @@ static int tw9910_video_probe(struct i2c_client *client) priv->norm = V4L2_STD_NTSC; - return 0; +done: + tw9910_s_power(&priv->subdev, 0); + return ret; } static struct v4l2_subdev_core_ops tw9910_subdev_core_ops = { @@ -814,6 +830,7 @@ static struct v4l2_subdev_core_ops tw9910_subdev_core_ops = { .g_register = tw9910_g_register, .s_register = tw9910_s_register, #endif + .s_power = tw9910_s_power, }; static int tw9910_enum_fmt(struct v4l2_subdev *sd, unsigned int index, diff --git a/drivers/media/video/sr030pc30.c b/drivers/media/i2c/sr030pc30.c index e9d95bda2ab1..e9d95bda2ab1 100644 --- a/drivers/media/video/sr030pc30.c +++ b/drivers/media/i2c/sr030pc30.c diff --git a/drivers/media/video/tcm825x.c b/drivers/media/i2c/tcm825x.c index 462caa44ae00..9252529fc5dd 100644 --- a/drivers/media/video/tcm825x.c +++ b/drivers/media/i2c/tcm825x.c @@ -1,5 +1,5 @@ /* - * drivers/media/video/tcm825x.c + * drivers/media/i2c/tcm825x.c * * TCM825X camera sensor driver. * diff --git a/drivers/media/video/tcm825x.h b/drivers/media/i2c/tcm825x.h index 5b7e69682368..8ebab953963f 100644 --- a/drivers/media/video/tcm825x.h +++ b/drivers/media/i2c/tcm825x.h @@ -1,5 +1,5 @@ /* - * drivers/media/video/tcm825x.h + * drivers/media/i2c/tcm825x.h * * Register definitions for the TCM825X CameraChip. * diff --git a/drivers/media/video/tda7432.c b/drivers/media/i2c/tda7432.c index f7707e65761e..f7707e65761e 100644 --- a/drivers/media/video/tda7432.c +++ b/drivers/media/i2c/tda7432.c diff --git a/drivers/media/video/tda9840.c b/drivers/media/i2c/tda9840.c index 3d7ddd93282d..3d7ddd93282d 100644 --- a/drivers/media/video/tda9840.c +++ b/drivers/media/i2c/tda9840.c diff --git a/drivers/media/video/tea6415c.c b/drivers/media/i2c/tea6415c.c index d1d6ea1dd273..3d5b06a5c308 100644 --- a/drivers/media/video/tea6415c.c +++ b/drivers/media/i2c/tea6415c.c @@ -81,7 +81,7 @@ static int tea6415c_s_routing(struct v4l2_subdev *sd, case 13: byte = 0x28; break; - }; + } switch (i) { case 5: @@ -108,7 +108,7 @@ static int tea6415c_s_routing(struct v4l2_subdev *sd, case 11: byte |= 0x07; break; - }; + } ret = i2c_smbus_write_byte(client, byte); if (ret) { diff --git a/drivers/media/video/tea6415c.h b/drivers/media/i2c/tea6415c.h index 3a47d697536e..3a47d697536e 100644 --- a/drivers/media/video/tea6415c.h +++ b/drivers/media/i2c/tea6415c.h diff --git a/drivers/media/video/tea6420.c b/drivers/media/i2c/tea6420.c index 38757217a074..38757217a074 100644 --- a/drivers/media/video/tea6420.c +++ b/drivers/media/i2c/tea6420.c diff --git a/drivers/media/video/tea6420.h b/drivers/media/i2c/tea6420.h index 4aa3edb3e193..4aa3edb3e193 100644 --- a/drivers/media/video/tea6420.h +++ b/drivers/media/i2c/tea6420.h diff --git a/drivers/media/video/ths7303.c b/drivers/media/i2c/ths7303.c index e5c0eedebc58..e5c0eedebc58 100644 --- a/drivers/media/video/ths7303.c +++ b/drivers/media/i2c/ths7303.c diff --git a/drivers/media/video/tlv320aic23b.c b/drivers/media/i2c/tlv320aic23b.c index 809a75a558ee..809a75a558ee 100644 --- a/drivers/media/video/tlv320aic23b.c +++ b/drivers/media/i2c/tlv320aic23b.c diff --git a/drivers/media/video/tvaudio.c b/drivers/media/i2c/tvaudio.c index 321b3153df87..3b24d3fc1866 100644 --- a/drivers/media/video/tvaudio.c +++ b/drivers/media/i2c/tvaudio.c @@ -7,6 +7,10 @@ * Steve VanDeBogart (vandebo@uclink.berkeley.edu) * Greg Alexander (galexand@acm.org) * + * For the TDA9875 part: + * Copyright (c) 2000 Guillaume Delvit based on Gerd Knorr source + * and Eric Sandeen + * * Copyright(c) 2005-2008 Mauro Carvalho Chehab * - Some cleanups, code fixes, etc * - Convert it to V4L2 API @@ -217,8 +221,17 @@ static int chip_read2(struct CHIPSTATE *chip, int subaddr) unsigned char write[1]; unsigned char read[1]; struct i2c_msg msgs[2] = { - { c->addr, 0, 1, write }, - { c->addr, I2C_M_RD, 1, read } + { + .addr = c->addr, + .len = 1, + .buf = write + }, + { + .addr = c->addr, + .flags = I2C_M_RD, + .len = 1, + .buf = read + } }; write[0] = subaddr; diff --git a/drivers/media/video/tveeprom.c b/drivers/media/i2c/tveeprom.c index 3b6cf034976a..3b6cf034976a 100644 --- a/drivers/media/video/tveeprom.c +++ b/drivers/media/i2c/tveeprom.c diff --git a/drivers/media/video/tvp514x.c b/drivers/media/i2c/tvp514x.c index cd615c1d6011..1f3943bb87d5 100644 --- a/drivers/media/video/tvp514x.c +++ b/drivers/media/i2c/tvp514x.c @@ -1,5 +1,5 @@ /* - * drivers/media/video/tvp514x.c + * drivers/media/i2c/tvp514x.c * * TI TVP5146/47 decoder driver * diff --git a/drivers/media/video/tvp514x_regs.h b/drivers/media/i2c/tvp514x_regs.h index 18f29ad0dfe2..d23aa2fbb9b1 100644 --- a/drivers/media/video/tvp514x_regs.h +++ b/drivers/media/i2c/tvp514x_regs.h @@ -1,5 +1,5 @@ /* - * drivers/media/video/tvp514x_regs.h + * drivers/media/i2c/tvp514x_regs.h * * Copyright (C) 2008 Texas Instruments Inc * Author: Vaibhav Hiremath <hvaibhav@ti.com> diff --git a/drivers/media/video/tvp5150.c b/drivers/media/i2c/tvp5150.c index a751b6c146fd..31104a960652 100644 --- a/drivers/media/video/tvp5150.c +++ b/drivers/media/i2c/tvp5150.c @@ -865,7 +865,7 @@ static int tvp5150_mbus_fmt(struct v4l2_subdev *sd, return 0; } -static int tvp5150_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) +static int tvp5150_s_crop(struct v4l2_subdev *sd, const struct v4l2_crop *a) { struct v4l2_rect rect = a->c; struct tvp5150 *decoder = to_tvp5150(sd); @@ -1020,7 +1020,7 @@ static int tvp5150_g_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_f { int i, mask = 0; - memset(svbi, 0, sizeof(*svbi)); + memset(svbi->service_lines, 0, sizeof(svbi->service_lines)); for (i = 0; i <= 23; i++) { svbi->service_lines[0][i] = diff --git a/drivers/media/video/tvp5150_reg.h b/drivers/media/i2c/tvp5150_reg.h index 25a994944918..25a994944918 100644 --- a/drivers/media/video/tvp5150_reg.h +++ b/drivers/media/i2c/tvp5150_reg.h diff --git a/drivers/media/video/tvp7002.c b/drivers/media/i2c/tvp7002.c index fb6a5b57eb83..fb6a5b57eb83 100644 --- a/drivers/media/video/tvp7002.c +++ b/drivers/media/i2c/tvp7002.c diff --git a/drivers/media/video/tvp7002_reg.h b/drivers/media/i2c/tvp7002_reg.h index 0e34ca9bccf3..0e34ca9bccf3 100644 --- a/drivers/media/video/tvp7002_reg.h +++ b/drivers/media/i2c/tvp7002_reg.h diff --git a/drivers/media/video/upd64031a.c b/drivers/media/i2c/upd64031a.c index 1e7446542091..1e7446542091 100644 --- a/drivers/media/video/upd64031a.c +++ b/drivers/media/i2c/upd64031a.c diff --git a/drivers/media/video/upd64083.c b/drivers/media/i2c/upd64083.c index 75d6acc62018..75d6acc62018 100644 --- a/drivers/media/video/upd64083.c +++ b/drivers/media/i2c/upd64083.c diff --git a/drivers/media/video/vp27smpx.c b/drivers/media/i2c/vp27smpx.c index 7cfbc9d94a48..7cfbc9d94a48 100644 --- a/drivers/media/video/vp27smpx.c +++ b/drivers/media/i2c/vp27smpx.c diff --git a/drivers/media/video/vpx3220.c b/drivers/media/i2c/vpx3220.c index 2f67b4c5c823..2f67b4c5c823 100644 --- a/drivers/media/video/vpx3220.c +++ b/drivers/media/i2c/vpx3220.c diff --git a/drivers/media/video/vs6624.c b/drivers/media/i2c/vs6624.c index 42ae9dc9c574..42ae9dc9c574 100644 --- a/drivers/media/video/vs6624.c +++ b/drivers/media/i2c/vs6624.c diff --git a/drivers/media/video/vs6624_regs.h b/drivers/media/i2c/vs6624_regs.h index 6ba2ee25827e..6ba2ee25827e 100644 --- a/drivers/media/video/vs6624_regs.h +++ b/drivers/media/i2c/vs6624_regs.h diff --git a/drivers/media/video/wm8739.c b/drivers/media/i2c/wm8739.c index 3bb99e93febe..3bb99e93febe 100644 --- a/drivers/media/video/wm8739.c +++ b/drivers/media/i2c/wm8739.c diff --git a/drivers/media/video/wm8775.c b/drivers/media/i2c/wm8775.c index bee77ea9f49e..bee77ea9f49e 100644 --- a/drivers/media/video/wm8775.c +++ b/drivers/media/i2c/wm8775.c diff --git a/drivers/media/media-device.c b/drivers/media/media-device.c index 6f9eb94e85b3..d01fcb7e87c2 100644 --- a/drivers/media/media-device.c +++ b/drivers/media/media-device.c @@ -59,7 +59,9 @@ static int media_device_get_info(struct media_device *dev, info.hw_revision = dev->hw_revision; info.driver_version = dev->driver_version; - return copy_to_user(__info, &info, sizeof(*__info)); + if (copy_to_user(__info, &info, sizeof(*__info))) + return -EFAULT; + return 0; } static struct media_entity *find_entity(struct media_device *mdev, u32 id) diff --git a/drivers/media/media-devnode.c b/drivers/media/media-devnode.c index f6b52d549430..023b2a1cbb9b 100644 --- a/drivers/media/media-devnode.c +++ b/drivers/media/media-devnode.c @@ -30,6 +30,8 @@ * counting. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/errno.h> #include <linux/init.h> #include <linux/module.h> @@ -215,7 +217,7 @@ int __must_check media_devnode_register(struct media_devnode *mdev) minor = find_next_zero_bit(media_devnode_nums, MEDIA_NUM_DEVICES, 0); if (minor == MEDIA_NUM_DEVICES) { mutex_unlock(&media_devnode_lock); - printk(KERN_ERR "could not get a free minor\n"); + pr_err("could not get a free minor\n"); return -ENFILE; } @@ -230,7 +232,7 @@ int __must_check media_devnode_register(struct media_devnode *mdev) ret = cdev_add(&mdev->cdev, MKDEV(MAJOR(media_dev_t), mdev->minor), 1); if (ret < 0) { - printk(KERN_ERR "%s: cdev_add failed\n", __func__); + pr_err("%s: cdev_add failed\n", __func__); goto error; } @@ -243,7 +245,7 @@ int __must_check media_devnode_register(struct media_devnode *mdev) dev_set_name(&mdev->dev, "media%d", mdev->minor); ret = device_register(&mdev->dev); if (ret < 0) { - printk(KERN_ERR "%s: device_register failed\n", __func__); + pr_err("%s: device_register failed\n", __func__); goto error; } @@ -287,18 +289,18 @@ static int __init media_devnode_init(void) { int ret; - printk(KERN_INFO "Linux media interface: v0.10\n"); + pr_info("Linux media interface: v0.10\n"); ret = alloc_chrdev_region(&media_dev_t, 0, MEDIA_NUM_DEVICES, MEDIA_NAME); if (ret < 0) { - printk(KERN_WARNING "media: unable to allocate major\n"); + pr_warn("unable to allocate major\n"); return ret; } ret = bus_register(&media_bus_type); if (ret < 0) { unregister_chrdev_region(media_dev_t, MEDIA_NUM_DEVICES); - printk(KERN_WARNING "media: bus_register failed\n"); + pr_warn("bus_register failed\n"); return -EIO; } diff --git a/drivers/media/mmc/Kconfig b/drivers/media/mmc/Kconfig new file mode 100644 index 000000000000..8c30ada27c79 --- /dev/null +++ b/drivers/media/mmc/Kconfig @@ -0,0 +1,2 @@ +comment "Supported MMC/SDIO adapters" +source "drivers/media/mmc/siano/Kconfig" diff --git a/drivers/media/mmc/Makefile b/drivers/media/mmc/Makefile new file mode 100644 index 000000000000..31e297a202fb --- /dev/null +++ b/drivers/media/mmc/Makefile @@ -0,0 +1 @@ +obj-y += siano/ diff --git a/drivers/media/mmc/siano/Kconfig b/drivers/media/mmc/siano/Kconfig new file mode 100644 index 000000000000..fa62475be3bf --- /dev/null +++ b/drivers/media/mmc/siano/Kconfig @@ -0,0 +1,10 @@ +# +# Siano Mobile Silicon Digital TV device configuration +# + +config SMS_SDIO_DRV + tristate "Siano SMS1xxx based MDTV via SDIO interface" + depends on DVB_CORE && RC_CORE && HAS_DMA + depends on MMC + ---help--- + Choose if you would like to have Siano's support for SDIO interface diff --git a/drivers/media/mmc/siano/Makefile b/drivers/media/mmc/siano/Makefile new file mode 100644 index 000000000000..0e01f973db6b --- /dev/null +++ b/drivers/media/mmc/siano/Makefile @@ -0,0 +1,6 @@ +obj-$(CONFIG_SMS_SDIO_DRV) += smssdio.o + +ccflags-y += -Idrivers/media/dvb-core +ccflags-y += -Idrivers/media/common/siano +ccflags-y += $(extra-cflags-y) $(extra-cflags-m) + diff --git a/drivers/media/dvb/siano/smssdio.c b/drivers/media/mmc/siano/smssdio.c index d6f3f100699a..d6f3f100699a 100644 --- a/drivers/media/dvb/siano/smssdio.c +++ b/drivers/media/mmc/siano/smssdio.c diff --git a/drivers/media/parport/Kconfig b/drivers/media/parport/Kconfig new file mode 100644 index 000000000000..ece13dcff07d --- /dev/null +++ b/drivers/media/parport/Kconfig @@ -0,0 +1,52 @@ +menuconfig MEDIA_PARPORT_SUPPORT + bool "ISA and parallel port devices" + depends on (ISA || PARPORT) && MEDIA_CAMERA_SUPPORT + help + Enables drivers for ISA and parallel port bus. If you + need media drivers using those legacy buses, say Y. + +if MEDIA_PARPORT_SUPPORT +config VIDEO_BWQCAM + tristate "Quickcam BW Video For Linux" + depends on PARPORT && VIDEO_V4L2 + help + Say Y have if you the black and white version of the QuickCam + camera. See the next option for the color version. + + To compile this driver as a module, choose M here: the + module will be called bw-qcam. + +config VIDEO_CQCAM + tristate "QuickCam Colour Video For Linux" + depends on PARPORT && VIDEO_V4L2 + help + This is the video4linux driver for the colour version of the + Connectix QuickCam. If you have one of these cameras, say Y here, + otherwise say N. This driver does not work with the original + monochrome QuickCam, QuickCam VC or QuickClip. It is also available + as a module (c-qcam). + Read <file:Documentation/video4linux/CQcam.txt> for more information. + +config VIDEO_PMS + tristate "Mediavision Pro Movie Studio Video For Linux" + depends on ISA && VIDEO_V4L2 + help + Say Y if you have the ISA Mediavision Pro Movie Studio + capture card. + + To compile this driver as a module, choose M here: the + module will be called pms. + +config VIDEO_W9966 + tristate "W9966CF Webcam (FlyCam Supra and others) Video For Linux" + depends on PARPORT_1284 && PARPORT && VIDEO_V4L2 + help + Video4linux driver for Winbond's w9966 based Webcams. + Currently tested with the LifeView FlyCam Supra. + If you have one of these cameras, say Y here + otherwise say N. + This driver is also available as a module (w9966). + + Check out <file:Documentation/video4linux/w9966.txt> for more + information. +endif diff --git a/drivers/media/parport/Makefile b/drivers/media/parport/Makefile new file mode 100644 index 000000000000..4eea06d7af5b --- /dev/null +++ b/drivers/media/parport/Makefile @@ -0,0 +1,4 @@ +obj-$(CONFIG_VIDEO_CQCAM) += c-qcam.o +obj-$(CONFIG_VIDEO_BWQCAM) += bw-qcam.o +obj-$(CONFIG_VIDEO_W9966) += w9966.o +obj-$(CONFIG_VIDEO_PMS) += pms.o diff --git a/drivers/media/video/bw-qcam.c b/drivers/media/parport/bw-qcam.c index 5b75a64b199b..5b75a64b199b 100644 --- a/drivers/media/video/bw-qcam.c +++ b/drivers/media/parport/bw-qcam.c diff --git a/drivers/media/video/c-qcam.c b/drivers/media/parport/c-qcam.c index ec51e1f12e82..ec51e1f12e82 100644 --- a/drivers/media/video/c-qcam.c +++ b/drivers/media/parport/c-qcam.c diff --git a/drivers/media/video/pms.c b/drivers/media/parport/pms.c index 77f9c92186f4..77f9c92186f4 100644 --- a/drivers/media/video/pms.c +++ b/drivers/media/parport/pms.c diff --git a/drivers/media/video/w9966.c b/drivers/media/parport/w9966.c index db2a6003a1c3..db2a6003a1c3 100644 --- a/drivers/media/video/w9966.c +++ b/drivers/media/parport/w9966.c diff --git a/drivers/media/pci/Kconfig b/drivers/media/pci/Kconfig new file mode 100644 index 000000000000..d4e2ed3f27e5 --- /dev/null +++ b/drivers/media/pci/Kconfig @@ -0,0 +1,47 @@ +menuconfig MEDIA_PCI_SUPPORT + bool "Media PCI Adapters" + depends on PCI && MEDIA_SUPPORT + help + Enable media drivers for PCI/PCIe bus. + If you have such devices, say Y. + +if MEDIA_PCI_SUPPORT + +if MEDIA_CAMERA_SUPPORT + comment "Media capture support" +source "drivers/media/pci/meye/Kconfig" +source "drivers/media/pci/sta2x11/Kconfig" +endif + +if MEDIA_ANALOG_TV_SUPPORT + comment "Media capture/analog TV support" +source "drivers/media/pci/ivtv/Kconfig" +source "drivers/media/pci/zoran/Kconfig" +source "drivers/media/pci/saa7146/Kconfig" +endif + +if MEDIA_ANALOG_TV_SUPPORT || MEDIA_DIGITAL_TV_SUPPORT + comment "Media capture/analog/hybrid TV support" +source "drivers/media/pci/cx18/Kconfig" +source "drivers/media/pci/cx23885/Kconfig" +source "drivers/media/pci/cx25821/Kconfig" +source "drivers/media/pci/cx88/Kconfig" +source "drivers/media/pci/bt8xx/Kconfig" +source "drivers/media/pci/saa7134/Kconfig" +source "drivers/media/pci/saa7164/Kconfig" + +endif + +if MEDIA_DIGITAL_TV_SUPPORT + comment "Media digital TV PCI Adapters" +source "drivers/media/pci/ttpci/Kconfig" +source "drivers/media/pci/b2c2/Kconfig" +source "drivers/media/pci/pluto2/Kconfig" +source "drivers/media/pci/dm1105/Kconfig" +source "drivers/media/pci/pt1/Kconfig" +source "drivers/media/pci/mantis/Kconfig" +source "drivers/media/pci/ngene/Kconfig" +source "drivers/media/pci/ddbridge/Kconfig" +endif + +endif #MEDIA_PCI_SUPPORT diff --git a/drivers/media/pci/Makefile b/drivers/media/pci/Makefile new file mode 100644 index 000000000000..35cc57862c01 --- /dev/null +++ b/drivers/media/pci/Makefile @@ -0,0 +1,26 @@ +# +# Makefile for the kernel multimedia device drivers. +# + +obj-y += ttpci/ \ + b2c2/ \ + pluto2/ \ + dm1105/ \ + pt1/ \ + mantis/ \ + ngene/ \ + ddbridge/ \ + b2c2/ \ + saa7146/ + +obj-$(CONFIG_VIDEO_IVTV) += ivtv/ +obj-$(CONFIG_VIDEO_ZORAN) += zoran/ +obj-$(CONFIG_VIDEO_CX18) += cx18/ +obj-$(CONFIG_VIDEO_CX23885) += cx23885/ +obj-$(CONFIG_VIDEO_CX25821) += cx25821/ +obj-$(CONFIG_VIDEO_CX88) += cx88/ +obj-$(CONFIG_VIDEO_BT848) += bt8xx/ +obj-$(CONFIG_VIDEO_SAA7134) += saa7134/ +obj-$(CONFIG_VIDEO_SAA7164) += saa7164/ +obj-$(CONFIG_VIDEO_MEYE) += meye/ +obj-$(CONFIG_STA2X11_VIP) += sta2x11/ diff --git a/drivers/media/pci/b2c2/Kconfig b/drivers/media/pci/b2c2/Kconfig new file mode 100644 index 000000000000..58761a21caa0 --- /dev/null +++ b/drivers/media/pci/b2c2/Kconfig @@ -0,0 +1,15 @@ +config DVB_B2C2_FLEXCOP_PCI + tristate "Technisat/B2C2 Air/Sky/Cable2PC PCI" + depends on DVB_CORE && I2C + help + Support for the Air/Sky/CableStar2 PCI card (DVB/ATSC) by Technisat/B2C2. + + Say Y if you own such a device and want to use it. + +config DVB_B2C2_FLEXCOP_PCI_DEBUG + bool "Enable debug for the B2C2 FlexCop drivers" + depends on DVB_B2C2_FLEXCOP_PCI + select DVB_B2C2_FLEXCOP_DEBUG + help + Say Y if you want to enable the module option to control debug messages + of all B2C2 FlexCop drivers. diff --git a/drivers/media/pci/b2c2/Makefile b/drivers/media/pci/b2c2/Makefile new file mode 100644 index 000000000000..b894320a5f21 --- /dev/null +++ b/drivers/media/pci/b2c2/Makefile @@ -0,0 +1,9 @@ +ifneq ($(CONFIG_DVB_B2C2_FLEXCOP_PCI),) +b2c2-flexcop-pci-objs += flexcop-dma.o +endif + +b2c2-flexcop-pci-objs += flexcop-pci.o +obj-$(CONFIG_DVB_B2C2_FLEXCOP_PCI) += b2c2-flexcop-pci.o + +ccflags-y += -Idrivers/media/dvb-core/ +ccflags-y += -Idrivers/media/common/b2c2/ diff --git a/drivers/media/dvb/b2c2/flexcop-dma.c b/drivers/media/pci/b2c2/flexcop-dma.c index 2881e0d956ad..2881e0d956ad 100644 --- a/drivers/media/dvb/b2c2/flexcop-dma.c +++ b/drivers/media/pci/b2c2/flexcop-dma.c diff --git a/drivers/media/dvb/b2c2/flexcop-pci.c b/drivers/media/pci/b2c2/flexcop-pci.c index 44f8fb5f17ff..44f8fb5f17ff 100644 --- a/drivers/media/dvb/b2c2/flexcop-pci.c +++ b/drivers/media/pci/b2c2/flexcop-pci.c diff --git a/drivers/media/pci/bt8xx/Kconfig b/drivers/media/pci/bt8xx/Kconfig new file mode 100644 index 000000000000..61d09e010814 --- /dev/null +++ b/drivers/media/pci/bt8xx/Kconfig @@ -0,0 +1,43 @@ +config VIDEO_BT848 + tristate "BT848 Video For Linux" + depends on VIDEO_DEV && PCI && I2C && VIDEO_V4L2 + select I2C_ALGOBIT + select VIDEO_BTCX + select VIDEOBUF_DMA_SG + depends on RC_CORE + select VIDEO_TUNER + select VIDEO_TVEEPROM + select VIDEO_MSP3400 if MEDIA_SUBDRV_AUTOSELECT + select VIDEO_TVAUDIO if MEDIA_SUBDRV_AUTOSELECT + select VIDEO_TDA7432 if MEDIA_SUBDRV_AUTOSELECT + select VIDEO_SAA6588 if MEDIA_SUBDRV_AUTOSELECT + ---help--- + Support for BT848 based frame grabber/overlay boards. This includes + the Miro, Hauppauge and STB boards. Please read the material in + <file:Documentation/video4linux/bttv/> for more information. + + To compile this driver as a module, choose M here: the + module will be called bttv. + +config DVB_BT8XX + tristate "DVB/ATSC Support for bt878 based TV cards" + depends on DVB_CORE && PCI && I2C && VIDEO_BT848 + select DVB_MT352 if MEDIA_SUBDRV_AUTOSELECT + select DVB_SP887X if MEDIA_SUBDRV_AUTOSELECT + select DVB_NXT6000 if MEDIA_SUBDRV_AUTOSELECT + select DVB_CX24110 if MEDIA_SUBDRV_AUTOSELECT + select DVB_OR51211 if MEDIA_SUBDRV_AUTOSELECT + select DVB_LGDT330X if MEDIA_SUBDRV_AUTOSELECT + select DVB_ZL10353 if MEDIA_SUBDRV_AUTOSELECT + select MEDIA_TUNER_SIMPLE if MEDIA_SUBDRV_AUTOSELECT + help + Support for PCI cards based on the Bt8xx PCI bridge. Examples are + the Nebula cards, the Pinnacle PCTV cards, the Twinhan DST cards, + the pcHDTV HD2000 cards, the DViCO FusionHDTV Lite cards, and + some AVerMedia cards. + + Since these cards have no MPEG decoder onboard, they transmit + only compressed MPEG data over the PCI bus, so you need + an external software decoder to watch TV on your computer. + + Say Y if you own such a device and want to use it. diff --git a/drivers/media/pci/bt8xx/Makefile b/drivers/media/pci/bt8xx/Makefile new file mode 100644 index 000000000000..5f06597c6a6e --- /dev/null +++ b/drivers/media/pci/bt8xx/Makefile @@ -0,0 +1,11 @@ +bttv-objs := bttv-driver.o bttv-cards.o bttv-if.o \ + bttv-risc.o bttv-vbi.o bttv-i2c.o bttv-gpio.o \ + bttv-input.o bttv-audio-hook.o + +obj-$(CONFIG_VIDEO_BT848) += bttv.o +obj-$(CONFIG_DVB_BT8XX) += bt878.o dvb-bt8xx.o dst.o dst_ca.o + +ccflags-y += -Idrivers/media/dvb-core +ccflags-y += -Idrivers/media/dvb-frontends +ccflags-y += -Idrivers/media/i2c +ccflags-y += -Idrivers/media/tuners diff --git a/drivers/media/video/bt8xx/bt848.h b/drivers/media/pci/bt8xx/bt848.h index c37e6acffded..c37e6acffded 100644 --- a/drivers/media/video/bt8xx/bt848.h +++ b/drivers/media/pci/bt8xx/bt848.h diff --git a/drivers/media/dvb/bt8xx/bt878.c b/drivers/media/pci/bt8xx/bt878.c index b34fa95185e4..b34fa95185e4 100644 --- a/drivers/media/dvb/bt8xx/bt878.c +++ b/drivers/media/pci/bt8xx/bt878.c diff --git a/drivers/media/dvb/bt8xx/bt878.h b/drivers/media/pci/bt8xx/bt878.h index d19b59299d78..d19b59299d78 100644 --- a/drivers/media/dvb/bt8xx/bt878.h +++ b/drivers/media/pci/bt8xx/bt878.h diff --git a/drivers/media/video/bt8xx/bttv-audio-hook.c b/drivers/media/pci/bt8xx/bttv-audio-hook.c index 2364d16586b3..2364d16586b3 100644 --- a/drivers/media/video/bt8xx/bttv-audio-hook.c +++ b/drivers/media/pci/bt8xx/bttv-audio-hook.c diff --git a/drivers/media/video/bt8xx/bttv-audio-hook.h b/drivers/media/pci/bt8xx/bttv-audio-hook.h index 159d07adeff8..159d07adeff8 100644 --- a/drivers/media/video/bt8xx/bttv-audio-hook.h +++ b/drivers/media/pci/bt8xx/bttv-audio-hook.h diff --git a/drivers/media/video/bt8xx/bttv-cards.c b/drivers/media/pci/bt8xx/bttv-cards.c index 38952faaffda..38952faaffda 100644 --- a/drivers/media/video/bt8xx/bttv-cards.c +++ b/drivers/media/pci/bt8xx/bttv-cards.c diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/pci/bt8xx/bttv-driver.c index 2ce7179a3864..b68918c97f66 100644 --- a/drivers/media/video/bt8xx/bttv-driver.c +++ b/drivers/media/pci/bt8xx/bttv-driver.c @@ -2740,7 +2740,7 @@ static int bttv_overlay(struct file *file, void *f, unsigned int on) } static int bttv_s_fbuf(struct file *file, void *f, - struct v4l2_framebuffer *fb) + const struct v4l2_framebuffer *fb) { struct bttv_fh *fh = f; struct bttv *btv = fh->btv; @@ -2986,7 +2986,7 @@ static int bttv_g_crop(struct file *file, void *f, struct v4l2_crop *crop) return 0; } -static int bttv_s_crop(struct file *file, void *f, struct v4l2_crop *crop) +static int bttv_s_crop(struct file *file, void *f, const struct v4l2_crop *crop) { struct bttv_fh *fh = f; struct bttv *btv = fh->btv; @@ -3028,17 +3028,17 @@ static int bttv_s_crop(struct file *file, void *f, struct v4l2_crop *crop) } /* Min. scaled size 48 x 32. */ - c.rect.left = clamp(crop->c.left, b_left, b_right - 48); + c.rect.left = clamp_t(s32, crop->c.left, b_left, b_right - 48); c.rect.left = min(c.rect.left, (__s32) MAX_HDELAY); - c.rect.width = clamp(crop->c.width, + c.rect.width = clamp_t(s32, crop->c.width, 48, b_right - c.rect.left); - c.rect.top = clamp(crop->c.top, b_top, b_bottom - 32); + c.rect.top = clamp_t(s32, crop->c.top, b_top, b_bottom - 32); /* Top and height must be a multiple of two. */ c.rect.top = (c.rect.top + 1) & ~1; - c.rect.height = clamp(crop->c.height, + c.rect.height = clamp_t(s32, crop->c.height, 32, b_bottom - c.rect.top); c.rect.height = (c.rect.height + 1) & ~1; @@ -3076,7 +3076,7 @@ static int bttv_g_audio(struct file *file, void *priv, struct v4l2_audio *a) return 0; } -static int bttv_s_audio(struct file *file, void *priv, struct v4l2_audio *a) +static int bttv_s_audio(struct file *file, void *priv, const struct v4l2_audio *a) { if (unlikely(a->index)) return -EINVAL; @@ -3480,7 +3480,7 @@ static int radio_s_tuner(struct file *file, void *priv, } static int radio_s_audio(struct file *file, void *priv, - struct v4l2_audio *a) + const struct v4l2_audio *a) { if (unlikely(a->index)) return -EINVAL; diff --git a/drivers/media/video/bt8xx/bttv-gpio.c b/drivers/media/pci/bt8xx/bttv-gpio.c index 922e8233fd0b..922e8233fd0b 100644 --- a/drivers/media/video/bt8xx/bttv-gpio.c +++ b/drivers/media/pci/bt8xx/bttv-gpio.c diff --git a/drivers/media/video/bt8xx/bttv-i2c.c b/drivers/media/pci/bt8xx/bttv-i2c.c index 580c8e682392..580c8e682392 100644 --- a/drivers/media/video/bt8xx/bttv-i2c.c +++ b/drivers/media/pci/bt8xx/bttv-i2c.c diff --git a/drivers/media/video/bt8xx/bttv-if.c b/drivers/media/pci/bt8xx/bttv-if.c index a6a540dc9e4b..a6a540dc9e4b 100644 --- a/drivers/media/video/bt8xx/bttv-if.c +++ b/drivers/media/pci/bt8xx/bttv-if.c diff --git a/drivers/media/video/bt8xx/bttv-input.c b/drivers/media/pci/bt8xx/bttv-input.c index ef4c7cd41982..ef4c7cd41982 100644 --- a/drivers/media/video/bt8xx/bttv-input.c +++ b/drivers/media/pci/bt8xx/bttv-input.c diff --git a/drivers/media/video/bt8xx/bttv-risc.c b/drivers/media/pci/bt8xx/bttv-risc.c index 82cc47d2e3fa..82cc47d2e3fa 100644 --- a/drivers/media/video/bt8xx/bttv-risc.c +++ b/drivers/media/pci/bt8xx/bttv-risc.c diff --git a/drivers/media/video/bt8xx/bttv-vbi.c b/drivers/media/pci/bt8xx/bttv-vbi.c index b433267d9aa9..b433267d9aa9 100644 --- a/drivers/media/video/bt8xx/bttv-vbi.c +++ b/drivers/media/pci/bt8xx/bttv-vbi.c diff --git a/drivers/media/video/bt8xx/bttv.h b/drivers/media/pci/bt8xx/bttv.h index 79a11240a590..79a11240a590 100644 --- a/drivers/media/video/bt8xx/bttv.h +++ b/drivers/media/pci/bt8xx/bttv.h diff --git a/drivers/media/video/bt8xx/bttvp.h b/drivers/media/pci/bt8xx/bttvp.h index 70fd4f23f605..70fd4f23f605 100644 --- a/drivers/media/video/bt8xx/bttvp.h +++ b/drivers/media/pci/bt8xx/bttvp.h diff --git a/drivers/media/dvb/bt8xx/dst.c b/drivers/media/pci/bt8xx/dst.c index 430b3eb11815..430b3eb11815 100644 --- a/drivers/media/dvb/bt8xx/dst.c +++ b/drivers/media/pci/bt8xx/dst.c diff --git a/drivers/media/dvb/bt8xx/dst_ca.c b/drivers/media/pci/bt8xx/dst_ca.c index 66f52f116b60..ee3884fbc9ce 100644 --- a/drivers/media/dvb/bt8xx/dst_ca.c +++ b/drivers/media/pci/bt8xx/dst_ca.c @@ -321,7 +321,8 @@ static int ca_get_message(struct dst_state *state, struct ca_msg *p_ca_message, return -EFAULT; if (p_ca_message->msg) { - dprintk(verbose, DST_CA_NOTICE, 1, " Message = [%02x %02x %02x]", p_ca_message->msg[0], p_ca_message->msg[1], p_ca_message->msg[2]); + dprintk(verbose, DST_CA_NOTICE, 1, " Message = [%*ph]", + 3, p_ca_message->msg); for (i = 0; i < 3; i++) { command = command | p_ca_message->msg[i]; diff --git a/drivers/media/dvb/bt8xx/dst_ca.h b/drivers/media/pci/bt8xx/dst_ca.h index 59cd0ddd6d8e..59cd0ddd6d8e 100644 --- a/drivers/media/dvb/bt8xx/dst_ca.h +++ b/drivers/media/pci/bt8xx/dst_ca.h diff --git a/drivers/media/dvb/bt8xx/dst_common.h b/drivers/media/pci/bt8xx/dst_common.h index d70d98f1a571..d70d98f1a571 100644 --- a/drivers/media/dvb/bt8xx/dst_common.h +++ b/drivers/media/pci/bt8xx/dst_common.h diff --git a/drivers/media/dvb/bt8xx/dst_priv.h b/drivers/media/pci/bt8xx/dst_priv.h index 3974a4c6ebe7..3974a4c6ebe7 100644 --- a/drivers/media/dvb/bt8xx/dst_priv.h +++ b/drivers/media/pci/bt8xx/dst_priv.h diff --git a/drivers/media/dvb/bt8xx/dvb-bt8xx.c b/drivers/media/pci/bt8xx/dvb-bt8xx.c index 81fab9adc1ca..81fab9adc1ca 100644 --- a/drivers/media/dvb/bt8xx/dvb-bt8xx.c +++ b/drivers/media/pci/bt8xx/dvb-bt8xx.c diff --git a/drivers/media/dvb/bt8xx/dvb-bt8xx.h b/drivers/media/pci/bt8xx/dvb-bt8xx.h index 4499ed2ac0ed..4499ed2ac0ed 100644 --- a/drivers/media/dvb/bt8xx/dvb-bt8xx.h +++ b/drivers/media/pci/bt8xx/dvb-bt8xx.h diff --git a/drivers/media/video/cx18/Kconfig b/drivers/media/pci/cx18/Kconfig index 53b3c7702573..c675b83c43a9 100644 --- a/drivers/media/video/cx18/Kconfig +++ b/drivers/media/pci/cx18/Kconfig @@ -1,6 +1,6 @@ config VIDEO_CX18 tristate "Conexant cx23418 MPEG encoder support" - depends on VIDEO_V4L2 && DVB_CORE && PCI && I2C && EXPERIMENTAL + depends on VIDEO_V4L2 && DVB_CORE && PCI && I2C select I2C_ALGOBIT select VIDEOBUF_VMALLOC depends on RC_CORE @@ -8,11 +8,11 @@ config VIDEO_CX18 select VIDEO_TVEEPROM select VIDEO_CX2341X select VIDEO_CS5345 - select DVB_S5H1409 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMISE - select DVB_S5H1411 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_TDA18271 if !MEDIA_TUNER_CUSTOMISE - select MEDIA_TUNER_TDA8290 if !MEDIA_TUNER_CUSTOMISE + select DVB_S5H1409 if MEDIA_SUBDRV_AUTOSELECT + select MEDIA_TUNER_MXL5005S if MEDIA_SUBDRV_AUTOSELECT + select DVB_S5H1411 if MEDIA_SUBDRV_AUTOSELECT + select MEDIA_TUNER_TDA18271 if MEDIA_SUBDRV_AUTOSELECT + select MEDIA_TUNER_TDA8290 if MEDIA_SUBDRV_AUTOSELECT ---help--- This is a video4linux driver for Conexant cx23418 based PCI combo video recorder devices. @@ -25,7 +25,7 @@ config VIDEO_CX18 config VIDEO_CX18_ALSA tristate "Conexant 23418 DMA audio support" - depends on VIDEO_CX18 && SND && EXPERIMENTAL + depends on VIDEO_CX18 && SND select SND_PCM ---help--- This is a video4linux driver for direct (DMA) audio on diff --git a/drivers/media/video/cx18/Makefile b/drivers/media/pci/cx18/Makefile index a86bab5893ef..d3ff1545c2c5 100644 --- a/drivers/media/video/cx18/Makefile +++ b/drivers/media/pci/cx18/Makefile @@ -8,6 +8,6 @@ cx18-alsa-objs := cx18-alsa-main.o cx18-alsa-pcm.o obj-$(CONFIG_VIDEO_CX18) += cx18.o obj-$(CONFIG_VIDEO_CX18_ALSA) += cx18-alsa.o -ccflags-y += -Idrivers/media/dvb/dvb-core -ccflags-y += -Idrivers/media/dvb/frontends -ccflags-y += -Idrivers/media/common/tuners +ccflags-y += -Idrivers/media/dvb-core +ccflags-y += -Idrivers/media/dvb-frontends +ccflags-y += -Idrivers/media/tuners diff --git a/drivers/media/video/cx18/cx18-alsa-main.c b/drivers/media/pci/cx18/cx18-alsa-main.c index 6d2a98246b6d..6d2a98246b6d 100644 --- a/drivers/media/video/cx18/cx18-alsa-main.c +++ b/drivers/media/pci/cx18/cx18-alsa-main.c diff --git a/drivers/media/video/cx18/cx18-alsa-mixer.c b/drivers/media/pci/cx18/cx18-alsa-mixer.c index 341bddc00b77..341bddc00b77 100644 --- a/drivers/media/video/cx18/cx18-alsa-mixer.c +++ b/drivers/media/pci/cx18/cx18-alsa-mixer.c diff --git a/drivers/media/video/cx18/cx18-alsa-mixer.h b/drivers/media/pci/cx18/cx18-alsa-mixer.h index ec9238793f6f..ec9238793f6f 100644 --- a/drivers/media/video/cx18/cx18-alsa-mixer.h +++ b/drivers/media/pci/cx18/cx18-alsa-mixer.h diff --git a/drivers/media/video/cx18/cx18-alsa-pcm.c b/drivers/media/pci/cx18/cx18-alsa-pcm.c index 7a5b84a86bb3..7a5b84a86bb3 100644 --- a/drivers/media/video/cx18/cx18-alsa-pcm.c +++ b/drivers/media/pci/cx18/cx18-alsa-pcm.c diff --git a/drivers/media/video/cx18/cx18-alsa-pcm.h b/drivers/media/pci/cx18/cx18-alsa-pcm.h index d26e51f94577..d26e51f94577 100644 --- a/drivers/media/video/cx18/cx18-alsa-pcm.h +++ b/drivers/media/pci/cx18/cx18-alsa-pcm.h diff --git a/drivers/media/video/cx18/cx18-alsa.h b/drivers/media/pci/cx18/cx18-alsa.h index 447da374c9e8..447da374c9e8 100644 --- a/drivers/media/video/cx18/cx18-alsa.h +++ b/drivers/media/pci/cx18/cx18-alsa.h diff --git a/drivers/media/video/cx18/cx18-audio.c b/drivers/media/pci/cx18/cx18-audio.c index 35268923911c..35268923911c 100644 --- a/drivers/media/video/cx18/cx18-audio.c +++ b/drivers/media/pci/cx18/cx18-audio.c diff --git a/drivers/media/video/cx18/cx18-audio.h b/drivers/media/pci/cx18/cx18-audio.h index 2731d29b0ab9..2731d29b0ab9 100644 --- a/drivers/media/video/cx18/cx18-audio.h +++ b/drivers/media/pci/cx18/cx18-audio.h diff --git a/drivers/media/video/cx18/cx18-av-audio.c b/drivers/media/pci/cx18/cx18-av-audio.c index 4a24ffb17a7d..4a24ffb17a7d 100644 --- a/drivers/media/video/cx18/cx18-av-audio.c +++ b/drivers/media/pci/cx18/cx18-av-audio.c diff --git a/drivers/media/video/cx18/cx18-av-core.c b/drivers/media/pci/cx18/cx18-av-core.c index f164b7f610a5..f164b7f610a5 100644 --- a/drivers/media/video/cx18/cx18-av-core.c +++ b/drivers/media/pci/cx18/cx18-av-core.c diff --git a/drivers/media/video/cx18/cx18-av-core.h b/drivers/media/pci/cx18/cx18-av-core.h index e9c69d9c9e4a..e9c69d9c9e4a 100644 --- a/drivers/media/video/cx18/cx18-av-core.h +++ b/drivers/media/pci/cx18/cx18-av-core.h diff --git a/drivers/media/video/cx18/cx18-av-firmware.c b/drivers/media/pci/cx18/cx18-av-firmware.c index 280aa4d22488..a34fd082b76e 100644 --- a/drivers/media/video/cx18/cx18-av-firmware.c +++ b/drivers/media/pci/cx18/cx18-av-firmware.c @@ -221,3 +221,5 @@ int cx18_av_loadfw(struct cx18 *cx) release_firmware(fw); return 0; } + +MODULE_FIRMWARE(FWFILE); diff --git a/drivers/media/video/cx18/cx18-av-vbi.c b/drivers/media/pci/cx18/cx18-av-vbi.c index baa36fbcd4d4..246982841fec 100644 --- a/drivers/media/video/cx18/cx18-av-vbi.c +++ b/drivers/media/pci/cx18/cx18-av-vbi.c @@ -143,7 +143,9 @@ int cx18_av_g_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format * int is_pal = !(state->std & V4L2_STD_525_60); int i; - memset(svbi, 0, sizeof(*svbi)); + memset(svbi->service_lines, 0, sizeof(svbi->service_lines)); + svbi->service_set = 0; + /* we're done if raw VBI is active */ if ((cx18_av_read(cx, 0x404) & 0x10) == 0) return 0; diff --git a/drivers/media/video/cx18/cx18-cards.c b/drivers/media/pci/cx18/cx18-cards.c index c07c849b1aaf..c07c849b1aaf 100644 --- a/drivers/media/video/cx18/cx18-cards.c +++ b/drivers/media/pci/cx18/cx18-cards.c diff --git a/drivers/media/video/cx18/cx18-cards.h b/drivers/media/pci/cx18/cx18-cards.h index add7391ecaba..add7391ecaba 100644 --- a/drivers/media/video/cx18/cx18-cards.h +++ b/drivers/media/pci/cx18/cx18-cards.h diff --git a/drivers/media/video/cx18/cx18-controls.c b/drivers/media/pci/cx18/cx18-controls.c index 282a3d29fdaa..282a3d29fdaa 100644 --- a/drivers/media/video/cx18/cx18-controls.c +++ b/drivers/media/pci/cx18/cx18-controls.c diff --git a/drivers/media/video/cx18/cx18-controls.h b/drivers/media/pci/cx18/cx18-controls.h index cb5dfc7b2054..cb5dfc7b2054 100644 --- a/drivers/media/video/cx18/cx18-controls.h +++ b/drivers/media/pci/cx18/cx18-controls.h diff --git a/drivers/media/video/cx18/cx18-driver.c b/drivers/media/pci/cx18/cx18-driver.c index 75c890907920..039133d692e3 100644 --- a/drivers/media/video/cx18/cx18-driver.c +++ b/drivers/media/pci/cx18/cx18-driver.c @@ -1357,3 +1357,4 @@ static void __exit module_cleanup(void) module_init(module_start); module_exit(module_cleanup); +MODULE_FIRMWARE(XC2028_DEFAULT_FIRMWARE); diff --git a/drivers/media/video/cx18/cx18-driver.h b/drivers/media/pci/cx18/cx18-driver.h index 2767c64df0c8..2767c64df0c8 100644 --- a/drivers/media/video/cx18/cx18-driver.h +++ b/drivers/media/pci/cx18/cx18-driver.h diff --git a/drivers/media/video/cx18/cx18-dvb.c b/drivers/media/pci/cx18/cx18-dvb.c index f41922bd4020..3eac59c51231 100644 --- a/drivers/media/video/cx18/cx18-dvb.c +++ b/drivers/media/pci/cx18/cx18-dvb.c @@ -40,6 +40,8 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); +#define FWFILE "dvb-cx18-mpc718-mt352.fw" + #define CX18_REG_DMUX_NUM_PORT_0_CONTROL 0xd5a000 #define CX18_CLOCK_ENABLE2 0xc71024 #define CX18_DMUX_CLK_MASK 0x0080 @@ -135,7 +137,7 @@ static int yuan_mpc718_mt352_reqfw(struct cx18_stream *stream, const struct firmware **fw) { struct cx18 *cx = stream->cx; - const char *fn = "dvb-cx18-mpc718-mt352.fw"; + const char *fn = FWFILE; int ret; ret = request_firmware(fw, fn, &cx->pci_dev->dev); @@ -603,3 +605,5 @@ static int dvb_register(struct cx18_stream *stream) return ret; } + +MODULE_FIRMWARE(FWFILE); diff --git a/drivers/media/video/cx18/cx18-dvb.h b/drivers/media/pci/cx18/cx18-dvb.h index bf8d8f6f5455..bf8d8f6f5455 100644 --- a/drivers/media/video/cx18/cx18-dvb.h +++ b/drivers/media/pci/cx18/cx18-dvb.h diff --git a/drivers/media/video/cx18/cx18-fileops.c b/drivers/media/pci/cx18/cx18-fileops.c index 4bfd865a4106..4bfd865a4106 100644 --- a/drivers/media/video/cx18/cx18-fileops.c +++ b/drivers/media/pci/cx18/cx18-fileops.c diff --git a/drivers/media/video/cx18/cx18-fileops.h b/drivers/media/pci/cx18/cx18-fileops.h index b9e5110ad043..b9e5110ad043 100644 --- a/drivers/media/video/cx18/cx18-fileops.h +++ b/drivers/media/pci/cx18/cx18-fileops.h diff --git a/drivers/media/video/cx18/cx18-firmware.c b/drivers/media/pci/cx18/cx18-firmware.c index b85c292a849a..a1c1cec05f98 100644 --- a/drivers/media/video/cx18/cx18-firmware.c +++ b/drivers/media/pci/cx18/cx18-firmware.c @@ -376,6 +376,9 @@ void cx18_init_memory(struct cx18 *cx) cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT14); /* AVO */ } +#define CX18_CPU_FIRMWARE "v4l-cx23418-cpu.fw" +#define CX18_APU_FIRMWARE "v4l-cx23418-apu.fw" + int cx18_firmware_init(struct cx18 *cx) { u32 fw_entry_addr; @@ -400,7 +403,7 @@ int cx18_firmware_init(struct cx18 *cx) cx18_sw1_irq_enable(cx, IRQ_CPU_TO_EPU | IRQ_APU_TO_EPU); cx18_sw2_irq_enable(cx, IRQ_CPU_TO_EPU_ACK | IRQ_APU_TO_EPU_ACK); - sz = load_cpu_fw_direct("v4l-cx23418-cpu.fw", cx->enc_mem, cx); + sz = load_cpu_fw_direct(CX18_CPU_FIRMWARE, cx->enc_mem, cx); if (sz <= 0) return sz; @@ -408,7 +411,7 @@ int cx18_firmware_init(struct cx18 *cx) cx18_init_scb(cx); fw_entry_addr = 0; - sz = load_apu_fw_direct("v4l-cx23418-apu.fw", cx->enc_mem, cx, + sz = load_apu_fw_direct(CX18_APU_FIRMWARE, cx->enc_mem, cx, &fw_entry_addr); if (sz <= 0) return sz; @@ -451,3 +454,6 @@ int cx18_firmware_init(struct cx18 *cx) cx18_write_reg_expect(cx, 0x14001400, 0xc78110, 0x00001400, 0x14001400); return 0; } + +MODULE_FIRMWARE(CX18_CPU_FIRMWARE); +MODULE_FIRMWARE(CX18_APU_FIRMWARE); diff --git a/drivers/media/video/cx18/cx18-firmware.h b/drivers/media/pci/cx18/cx18-firmware.h index 38d4c05e8499..38d4c05e8499 100644 --- a/drivers/media/video/cx18/cx18-firmware.h +++ b/drivers/media/pci/cx18/cx18-firmware.h diff --git a/drivers/media/video/cx18/cx18-gpio.c b/drivers/media/pci/cx18/cx18-gpio.c index 5374aeb0cd22..5374aeb0cd22 100644 --- a/drivers/media/video/cx18/cx18-gpio.c +++ b/drivers/media/pci/cx18/cx18-gpio.c diff --git a/drivers/media/video/cx18/cx18-gpio.h b/drivers/media/pci/cx18/cx18-gpio.h index 4aea2ef88e8d..4aea2ef88e8d 100644 --- a/drivers/media/video/cx18/cx18-gpio.h +++ b/drivers/media/pci/cx18/cx18-gpio.h diff --git a/drivers/media/video/cx18/cx18-i2c.c b/drivers/media/pci/cx18/cx18-i2c.c index 51609d5c88ce..51609d5c88ce 100644 --- a/drivers/media/video/cx18/cx18-i2c.c +++ b/drivers/media/pci/cx18/cx18-i2c.c diff --git a/drivers/media/video/cx18/cx18-i2c.h b/drivers/media/pci/cx18/cx18-i2c.h index 1180fdc8d983..1180fdc8d983 100644 --- a/drivers/media/video/cx18/cx18-i2c.h +++ b/drivers/media/pci/cx18/cx18-i2c.h diff --git a/drivers/media/video/cx18/cx18-io.c b/drivers/media/pci/cx18/cx18-io.c index 49b9dbd06248..49b9dbd06248 100644 --- a/drivers/media/video/cx18/cx18-io.c +++ b/drivers/media/pci/cx18/cx18-io.c diff --git a/drivers/media/video/cx18/cx18-io.h b/drivers/media/pci/cx18/cx18-io.h index 18974d886cf7..18974d886cf7 100644 --- a/drivers/media/video/cx18/cx18-io.h +++ b/drivers/media/pci/cx18/cx18-io.h diff --git a/drivers/media/video/cx18/cx18-ioctl.c b/drivers/media/pci/cx18/cx18-ioctl.c index e9912db3b496..cd8d2c2b1624 100644 --- a/drivers/media/video/cx18/cx18-ioctl.c +++ b/drivers/media/pci/cx18/cx18-ioctl.c @@ -210,10 +210,6 @@ static int cx18_g_fmt_sliced_vbi_cap(struct file *file, void *fh, if (v4l2_subdev_call(cx->sd_av, vbi, g_sliced_fmt, &fmt->fmt.sliced)) return -EINVAL; - /* Ensure V4L2 spec compliant output */ - vbifmt->reserved[0] = 0; - vbifmt->reserved[1] = 0; - vbifmt->io_size = sizeof(struct v4l2_sliced_vbi_data) * 36; vbifmt->service_set = cx18_get_service_set(vbifmt); return 0; } @@ -492,7 +488,7 @@ static int cx18_g_audio(struct file *file, void *fh, struct v4l2_audio *vin) return cx18_get_audio_input(cx, vin->index, vin); } -static int cx18_s_audio(struct file *file, void *fh, struct v4l2_audio *vout) +static int cx18_s_audio(struct file *file, void *fh, const struct v4l2_audio *vout) { struct cx18 *cx = fh2id(fh)->cx; @@ -527,7 +523,7 @@ static int cx18_cropcap(struct file *file, void *fh, return 0; } -static int cx18_s_crop(struct file *file, void *fh, struct v4l2_crop *crop) +static int cx18_s_crop(struct file *file, void *fh, const struct v4l2_crop *crop) { struct cx18_open_id *id = fh2id(fh); struct cx18 *cx = id->cx; diff --git a/drivers/media/video/cx18/cx18-ioctl.h b/drivers/media/pci/cx18/cx18-ioctl.h index 2f9dd591ee0f..2f9dd591ee0f 100644 --- a/drivers/media/video/cx18/cx18-ioctl.h +++ b/drivers/media/pci/cx18/cx18-ioctl.h diff --git a/drivers/media/video/cx18/cx18-irq.c b/drivers/media/pci/cx18/cx18-irq.c index 80edfe93a3d8..80edfe93a3d8 100644 --- a/drivers/media/video/cx18/cx18-irq.c +++ b/drivers/media/pci/cx18/cx18-irq.c diff --git a/drivers/media/video/cx18/cx18-irq.h b/drivers/media/pci/cx18/cx18-irq.h index 30e7eaf8cb55..30e7eaf8cb55 100644 --- a/drivers/media/video/cx18/cx18-irq.h +++ b/drivers/media/pci/cx18/cx18-irq.h diff --git a/drivers/media/video/cx18/cx18-mailbox.c b/drivers/media/pci/cx18/cx18-mailbox.c index eabf00c6351b..eabf00c6351b 100644 --- a/drivers/media/video/cx18/cx18-mailbox.c +++ b/drivers/media/pci/cx18/cx18-mailbox.c diff --git a/drivers/media/video/cx18/cx18-mailbox.h b/drivers/media/pci/cx18/cx18-mailbox.h index b63fdfaac49e..b63fdfaac49e 100644 --- a/drivers/media/video/cx18/cx18-mailbox.h +++ b/drivers/media/pci/cx18/cx18-mailbox.h diff --git a/drivers/media/video/cx18/cx18-queue.c b/drivers/media/pci/cx18/cx18-queue.c index 8884537bd62f..8884537bd62f 100644 --- a/drivers/media/video/cx18/cx18-queue.c +++ b/drivers/media/pci/cx18/cx18-queue.c diff --git a/drivers/media/video/cx18/cx18-queue.h b/drivers/media/pci/cx18/cx18-queue.h index 4201ddc16091..4201ddc16091 100644 --- a/drivers/media/video/cx18/cx18-queue.h +++ b/drivers/media/pci/cx18/cx18-queue.h diff --git a/drivers/media/video/cx18/cx18-scb.c b/drivers/media/pci/cx18/cx18-scb.c index 85cc59637e54..85cc59637e54 100644 --- a/drivers/media/video/cx18/cx18-scb.c +++ b/drivers/media/pci/cx18/cx18-scb.c diff --git a/drivers/media/video/cx18/cx18-scb.h b/drivers/media/pci/cx18/cx18-scb.h index 08877652e321..08877652e321 100644 --- a/drivers/media/video/cx18/cx18-scb.h +++ b/drivers/media/pci/cx18/cx18-scb.h diff --git a/drivers/media/video/cx18/cx18-streams.c b/drivers/media/pci/cx18/cx18-streams.c index 9d598ab88615..72af9b5c2d7d 100644 --- a/drivers/media/video/cx18/cx18-streams.c +++ b/drivers/media/pci/cx18/cx18-streams.c @@ -58,42 +58,41 @@ static struct { int vfl_type; int num_offset; int dma; - enum v4l2_buf_type buf_type; } cx18_stream_info[] = { { /* CX18_ENC_STREAM_TYPE_MPG */ "encoder MPEG", VFL_TYPE_GRABBER, 0, - PCI_DMA_FROMDEVICE, V4L2_BUF_TYPE_VIDEO_CAPTURE, + PCI_DMA_FROMDEVICE, }, { /* CX18_ENC_STREAM_TYPE_TS */ "TS", VFL_TYPE_GRABBER, -1, - PCI_DMA_FROMDEVICE, V4L2_BUF_TYPE_VIDEO_CAPTURE, + PCI_DMA_FROMDEVICE, }, { /* CX18_ENC_STREAM_TYPE_YUV */ "encoder YUV", VFL_TYPE_GRABBER, CX18_V4L2_ENC_YUV_OFFSET, - PCI_DMA_FROMDEVICE, V4L2_BUF_TYPE_VIDEO_CAPTURE, + PCI_DMA_FROMDEVICE, }, { /* CX18_ENC_STREAM_TYPE_VBI */ "encoder VBI", VFL_TYPE_VBI, 0, - PCI_DMA_FROMDEVICE, V4L2_BUF_TYPE_VBI_CAPTURE, + PCI_DMA_FROMDEVICE, }, { /* CX18_ENC_STREAM_TYPE_PCM */ "encoder PCM audio", VFL_TYPE_GRABBER, CX18_V4L2_ENC_PCM_OFFSET, - PCI_DMA_FROMDEVICE, V4L2_BUF_TYPE_PRIVATE, + PCI_DMA_FROMDEVICE, }, { /* CX18_ENC_STREAM_TYPE_IDX */ "encoder IDX", VFL_TYPE_GRABBER, -1, - PCI_DMA_FROMDEVICE, V4L2_BUF_TYPE_VIDEO_CAPTURE, + PCI_DMA_FROMDEVICE, }, { /* CX18_ENC_STREAM_TYPE_RAD */ "encoder radio", VFL_TYPE_RADIO, 0, - PCI_DMA_NONE, V4L2_BUF_TYPE_PRIVATE, + PCI_DMA_NONE, }, }; diff --git a/drivers/media/video/cx18/cx18-streams.h b/drivers/media/pci/cx18/cx18-streams.h index 713b0e61536d..713b0e61536d 100644 --- a/drivers/media/video/cx18/cx18-streams.h +++ b/drivers/media/pci/cx18/cx18-streams.h diff --git a/drivers/media/video/cx18/cx18-vbi.c b/drivers/media/pci/cx18/cx18-vbi.c index 6d3121ff45a2..6d3121ff45a2 100644 --- a/drivers/media/video/cx18/cx18-vbi.c +++ b/drivers/media/pci/cx18/cx18-vbi.c diff --git a/drivers/media/video/cx18/cx18-vbi.h b/drivers/media/pci/cx18/cx18-vbi.h index b365cf4b4668..b365cf4b4668 100644 --- a/drivers/media/video/cx18/cx18-vbi.h +++ b/drivers/media/pci/cx18/cx18-vbi.h diff --git a/drivers/media/video/cx18/cx18-version.h b/drivers/media/pci/cx18/cx18-version.h index fed48b6bb67b..fed48b6bb67b 100644 --- a/drivers/media/video/cx18/cx18-version.h +++ b/drivers/media/pci/cx18/cx18-version.h diff --git a/drivers/media/video/cx18/cx18-video.c b/drivers/media/pci/cx18/cx18-video.c index 6dc84aac8f44..6dc84aac8f44 100644 --- a/drivers/media/video/cx18/cx18-video.c +++ b/drivers/media/pci/cx18/cx18-video.c diff --git a/drivers/media/video/cx18/cx18-video.h b/drivers/media/pci/cx18/cx18-video.h index 529006a06e5c..529006a06e5c 100644 --- a/drivers/media/video/cx18/cx18-video.h +++ b/drivers/media/pci/cx18/cx18-video.h diff --git a/drivers/media/video/cx18/cx23418.h b/drivers/media/pci/cx18/cx23418.h index 767a8d23e3f2..767a8d23e3f2 100644 --- a/drivers/media/video/cx18/cx23418.h +++ b/drivers/media/pci/cx18/cx23418.h diff --git a/drivers/media/pci/cx23885/Kconfig b/drivers/media/pci/cx23885/Kconfig new file mode 100644 index 000000000000..eafa1144b17d --- /dev/null +++ b/drivers/media/pci/cx23885/Kconfig @@ -0,0 +1,50 @@ +config VIDEO_CX23885 + tristate "Conexant cx23885 (2388x successor) support" + depends on DVB_CORE && VIDEO_DEV && PCI && I2C && INPUT && SND + select SND_PCM + select I2C_ALGOBIT + select VIDEO_BTCX + select VIDEO_TUNER + select VIDEO_TVEEPROM + depends on RC_CORE + select VIDEOBUF_DVB + select VIDEOBUF_DMA_SG + select VIDEO_CX25840 + select VIDEO_CX2341X + select DVB_DIB7000P if MEDIA_SUBDRV_AUTOSELECT + select DVB_DRXK if MEDIA_SUBDRV_AUTOSELECT + select DVB_S5H1409 if MEDIA_SUBDRV_AUTOSELECT + select DVB_S5H1411 if MEDIA_SUBDRV_AUTOSELECT + select DVB_LGDT330X if MEDIA_SUBDRV_AUTOSELECT + select DVB_ZL10353 if MEDIA_SUBDRV_AUTOSELECT + select DVB_TDA10048 if MEDIA_SUBDRV_AUTOSELECT + select DVB_LNBP21 if MEDIA_SUBDRV_AUTOSELECT + select DVB_STV090x if MEDIA_SUBDRV_AUTOSELECT + select DVB_STB6100 if MEDIA_SUBDRV_AUTOSELECT + select DVB_STV6110 if MEDIA_SUBDRV_AUTOSELECT + select DVB_CX24116 if MEDIA_SUBDRV_AUTOSELECT + select DVB_STV0900 if MEDIA_SUBDRV_AUTOSELECT + select DVB_DS3000 if MEDIA_SUBDRV_AUTOSELECT + select DVB_STV0367 if MEDIA_SUBDRV_AUTOSELECT + select MEDIA_TUNER_MT2063 if MEDIA_SUBDRV_AUTOSELECT + select MEDIA_TUNER_MT2131 if MEDIA_SUBDRV_AUTOSELECT + select MEDIA_TUNER_XC2028 if MEDIA_SUBDRV_AUTOSELECT + select MEDIA_TUNER_TDA8290 if MEDIA_SUBDRV_AUTOSELECT + select MEDIA_TUNER_TDA18271 if MEDIA_SUBDRV_AUTOSELECT + select MEDIA_TUNER_XC5000 if MEDIA_SUBDRV_AUTOSELECT + ---help--- + This is a video4linux driver for Conexant 23885 based + TV cards. + + To compile this driver as a module, choose M here: the + module will be called cx23885 + +config MEDIA_ALTERA_CI + tristate "Altera FPGA based CI module" + depends on VIDEO_CX23885 && DVB_CORE + select ALTERA_STAPL + ---help--- + An Altera FPGA CI module for NetUP Dual DVB-T/C RF CI card. + + To compile this driver as a module, choose M here: the + module will be called altera-ci diff --git a/drivers/media/video/cx23885/Makefile b/drivers/media/pci/cx23885/Makefile index f81f2796a0f9..a2cbdcf15a8c 100644 --- a/drivers/media/video/cx23885/Makefile +++ b/drivers/media/pci/cx23885/Makefile @@ -7,9 +7,9 @@ cx23885-objs := cx23885-cards.o cx23885-video.o cx23885-vbi.o \ obj-$(CONFIG_VIDEO_CX23885) += cx23885.o obj-$(CONFIG_MEDIA_ALTERA_CI) += altera-ci.o -ccflags-y += -Idrivers/media/video -ccflags-y += -Idrivers/media/common/tuners -ccflags-y += -Idrivers/media/dvb/dvb-core -ccflags-y += -Idrivers/media/dvb/frontends +ccflags-y += -Idrivers/media/i2c +ccflags-y += -Idrivers/media/tuners +ccflags-y += -Idrivers/media/dvb-core +ccflags-y += -Idrivers/media/dvb-frontends ccflags-y += $(extra-cflags-y) $(extra-cflags-m) diff --git a/drivers/media/video/cx23885/altera-ci.c b/drivers/media/pci/cx23885/altera-ci.c index 1fa8927f0d36..aee7f0dacff1 100644 --- a/drivers/media/video/cx23885/altera-ci.c +++ b/drivers/media/pci/cx23885/altera-ci.c @@ -724,6 +724,7 @@ int altera_ci_init(struct altera_ci_config *config, int ci_nr) if (temp_int != NULL) { inter = temp_int->internal; (inter->cis_used)++; + inter->fpga_rw = config->fpga_rw; ci_dbg_print("%s: Find Internal Structure!\n", __func__); } else { inter = kzalloc(sizeof(struct fpga_internal), GFP_KERNEL); @@ -743,7 +744,6 @@ int altera_ci_init(struct altera_ci_config *config, int ci_nr) ci_dbg_print("%s: setting state = %p for ci = %d\n", __func__, state, ci_nr - 1); - inter->state[ci_nr - 1] = state; state->internal = inter; state->nr = ci_nr - 1; @@ -765,6 +765,8 @@ int altera_ci_init(struct altera_ci_config *config, int ci_nr) if (0 != ret) goto err; + inter->state[ci_nr - 1] = state; + altera_hw_filt_init(config, ci_nr); if (inter->strt_wrk) { diff --git a/drivers/media/video/cx23885/altera-ci.h b/drivers/media/pci/cx23885/altera-ci.h index 70e4fd69ad9e..70e4fd69ad9e 100644 --- a/drivers/media/video/cx23885/altera-ci.h +++ b/drivers/media/pci/cx23885/altera-ci.h diff --git a/drivers/media/video/cx23885/cimax2.c b/drivers/media/pci/cx23885/cimax2.c index c9f15d6dec40..c9f15d6dec40 100644 --- a/drivers/media/video/cx23885/cimax2.c +++ b/drivers/media/pci/cx23885/cimax2.c diff --git a/drivers/media/video/cx23885/cimax2.h b/drivers/media/pci/cx23885/cimax2.h index 518744a4c8a5..518744a4c8a5 100644 --- a/drivers/media/video/cx23885/cimax2.h +++ b/drivers/media/pci/cx23885/cimax2.h diff --git a/drivers/media/video/cx23885/cx23885-417.c b/drivers/media/pci/cx23885/cx23885-417.c index f5c79e53e5a1..5d5052d0253f 100644 --- a/drivers/media/video/cx23885/cx23885-417.c +++ b/drivers/media/pci/cx23885/cx23885-417.c @@ -1786,3 +1786,5 @@ int cx23885_417_register(struct cx23885_dev *dev) return 0; } + +MODULE_FIRMWARE(CX23885_FIRM_IMAGE_NAME); diff --git a/drivers/media/video/cx23885/cx23885-alsa.c b/drivers/media/pci/cx23885/cx23885-alsa.c index 795169237e70..795169237e70 100644 --- a/drivers/media/video/cx23885/cx23885-alsa.c +++ b/drivers/media/pci/cx23885/cx23885-alsa.c diff --git a/drivers/media/video/cx23885/cx23885-av.c b/drivers/media/pci/cx23885/cx23885-av.c index 134ebddd860f..134ebddd860f 100644 --- a/drivers/media/video/cx23885/cx23885-av.c +++ b/drivers/media/pci/cx23885/cx23885-av.c diff --git a/drivers/media/video/cx23885/cx23885-av.h b/drivers/media/pci/cx23885/cx23885-av.h index d2915c3e53a2..d2915c3e53a2 100644 --- a/drivers/media/video/cx23885/cx23885-av.h +++ b/drivers/media/pci/cx23885/cx23885-av.h diff --git a/drivers/media/video/cx23885/cx23885-cards.c b/drivers/media/pci/cx23885/cx23885-cards.c index 080e11157e5f..39a4a4b9ed7e 100644 --- a/drivers/media/video/cx23885/cx23885-cards.c +++ b/drivers/media/pci/cx23885/cx23885-cards.c @@ -36,7 +36,7 @@ #include "xc5000.h" #include "cx23888-ir.h" -static unsigned int netup_card_rev = 1; +static unsigned int netup_card_rev = 4; module_param(netup_card_rev, int, 0644); MODULE_PARM_DESC(netup_card_rev, "NetUP Dual DVB-T/C CI card revision"); @@ -46,6 +46,7 @@ MODULE_PARM_DESC(enable_885_ir, "Enable integrated IR controller for supported\n" "\t\t CX2388[57] boards that are wired for it:\n" "\t\t\tHVR-1250 (reported safe)\n" + "\t\t\tTerraTec Cinergy T PCIe Dual (not well tested, appears to be safe)\n" "\t\t\tTeVii S470 (reported unsafe)\n" "\t\t This can cause an interrupt storm with some cards.\n" "\t\t Default: 0 [Disabled]"); @@ -564,6 +565,10 @@ struct cx23885_board cx23885_boards[] = { [CX23885_BOARD_TEVII_S471] = { .name = "TeVii S471", .portb = CX23885_MPEG_DVB, + }, + [CX23885_BOARD_PROF_8000] = { + .name = "Prof Revolution DVB-S2 8000", + .portb = CX23885_MPEG_DVB, } }; const unsigned int cx23885_bcount = ARRAY_SIZE(cx23885_boards); @@ -776,6 +781,10 @@ struct cx23885_subid cx23885_subids[] = { .subvendor = 0xd471, .subdevice = 0x9022, .card = CX23885_BOARD_TEVII_S471, + }, { + .subvendor = 0x8000, + .subdevice = 0x3034, + .card = CX23885_BOARD_PROF_8000, }, }; const unsigned int cx23885_idcount = ARRAY_SIZE(cx23885_subids); @@ -1155,6 +1164,7 @@ void cx23885_gpio_setup(struct cx23885_dev *dev) cx_set(GP0_IO, 0x00040004); break; case CX23885_BOARD_TBS_6920: + case CX23885_BOARD_PROF_8000: cx_write(MC417_CTL, 0x00000036); cx_write(MC417_OEN, 0x00001000); cx_set(MC417_RWD, 0x00000002); @@ -1363,6 +1373,7 @@ int cx23885_ir_init(struct cx23885_dev *dev) params.shutdown = true; v4l2_subdev_call(dev->sd_ir, ir, tx_s_parameters, ¶ms); break; + case CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL: case CX23885_BOARD_TEVII_S470: if (!enable_885_ir) break; @@ -1403,6 +1414,7 @@ void cx23885_ir_fini(struct cx23885_dev *dev) cx23888_ir_remove(dev); dev->sd_ir = NULL; break; + case CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL: case CX23885_BOARD_TEVII_S470: case CX23885_BOARD_HAUPPAUGE_HVR1250: cx23885_irq_remove(dev, PCI_MSK_AV_CORE); @@ -1446,6 +1458,7 @@ void cx23885_ir_pci_int_enable(struct cx23885_dev *dev) if (dev->sd_ir) cx23885_irq_add_enable(dev, PCI_MSK_IR); break; + case CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL: case CX23885_BOARD_TEVII_S470: case CX23885_BOARD_HAUPPAUGE_HVR1250: if (dev->sd_ir) @@ -1536,6 +1549,7 @@ void cx23885_card_setup(struct cx23885_dev *dev) case CX23885_BOARD_TEVII_S470: case CX23885_BOARD_TEVII_S471: case CX23885_BOARD_DVBWORLD_2005: + case CX23885_BOARD_PROF_8000: ts1->gen_ctrl_val = 0x5; /* Parallel */ ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */ ts1->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO; diff --git a/drivers/media/video/cx23885/cx23885-core.c b/drivers/media/pci/cx23885/cx23885-core.c index 697728f09430..697728f09430 100644 --- a/drivers/media/video/cx23885/cx23885-core.c +++ b/drivers/media/pci/cx23885/cx23885-core.c diff --git a/drivers/media/video/cx23885/cx23885-dvb.c b/drivers/media/pci/cx23885/cx23885-dvb.c index cd542684ba02..4379d8a6dad5 100644 --- a/drivers/media/video/cx23885/cx23885-dvb.c +++ b/drivers/media/pci/cx23885/cx23885-dvb.c @@ -63,6 +63,9 @@ #include "stv0367.h" #include "drxk.h" #include "mt2063.h" +#include "stv090x.h" +#include "stb6100.h" +#include "stb6100_cfg.h" static unsigned int debug; @@ -489,6 +492,42 @@ static struct xc5000_config mygica_x8506_xc5000_config = { .if_khz = 5380, }; +static struct stv090x_config prof_8000_stv090x_config = { + .device = STV0903, + .demod_mode = STV090x_SINGLE, + .clk_mode = STV090x_CLK_EXT, + .xtal = 27000000, + .address = 0x6A, + .ts1_mode = STV090x_TSMODE_PARALLEL_PUNCTURED, + .repeater_level = STV090x_RPTLEVEL_64, + .adc1_range = STV090x_ADC_2Vpp, + .diseqc_envelope_mode = false, + + .tuner_get_frequency = stb6100_get_frequency, + .tuner_set_frequency = stb6100_set_frequency, + .tuner_set_bandwidth = stb6100_set_bandwidth, + .tuner_get_bandwidth = stb6100_get_bandwidth, +}; + +static struct stb6100_config prof_8000_stb6100_config = { + .tuner_address = 0x60, + .refclock = 27000000, +}; + +static int p8000_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) +{ + struct cx23885_tsport *port = fe->dvb->priv; + struct cx23885_dev *dev = port->dev; + + if (voltage == SEC_VOLTAGE_18) + cx_write(MC417_RWD, 0x00001e00); + else if (voltage == SEC_VOLTAGE_13) + cx_write(MC417_RWD, 0x00001a00); + else + cx_write(MC417_RWD, 0x00001800); + return 0; +} + static int cx23885_dvb_set_frontend(struct dvb_frontend *fe) { struct dtv_frontend_properties *p = &fe->dtv_property_cache; @@ -1186,6 +1225,23 @@ static int dvb_register(struct cx23885_tsport *port) &tevii_ds3000_config, &i2c_bus->i2c_adap); break; + case CX23885_BOARD_PROF_8000: + i2c_bus = &dev->i2c_bus[0]; + + fe0->dvb.frontend = dvb_attach(stv090x_attach, + &prof_8000_stv090x_config, + &i2c_bus->i2c_adap, + STV090x_DEMODULATOR_0); + if (fe0->dvb.frontend != NULL) { + if (!dvb_attach(stb6100_attach, + fe0->dvb.frontend, + &prof_8000_stb6100_config, + &i2c_bus->i2c_adap)) + goto frontend_detach; + + fe0->dvb.frontend->ops.set_voltage = p8000_set_voltage; + } + break; default: printk(KERN_INFO "%s: The frontend of your DVB/ATSC card " " isn't supported yet\n", @@ -1218,8 +1274,7 @@ static int dvb_register(struct cx23885_tsport *port) /* register everything */ ret = videobuf_dvb_register_bus(&port->frontends, THIS_MODULE, port, - &dev->pci->dev, adapter_nr, mfe_shared, - NULL); + &dev->pci->dev, adapter_nr, mfe_shared); if (ret) goto frontend_detach; diff --git a/drivers/media/video/cx23885/cx23885-f300.c b/drivers/media/pci/cx23885/cx23885-f300.c index 93998f220986..93998f220986 100644 --- a/drivers/media/video/cx23885/cx23885-f300.c +++ b/drivers/media/pci/cx23885/cx23885-f300.c diff --git a/drivers/media/video/cx23885/cx23885-f300.h b/drivers/media/pci/cx23885/cx23885-f300.h index e73344c94963..e73344c94963 100644 --- a/drivers/media/video/cx23885/cx23885-f300.h +++ b/drivers/media/pci/cx23885/cx23885-f300.h diff --git a/drivers/media/video/cx23885/cx23885-i2c.c b/drivers/media/pci/cx23885/cx23885-i2c.c index 4887314339cb..4887314339cb 100644 --- a/drivers/media/video/cx23885/cx23885-i2c.c +++ b/drivers/media/pci/cx23885/cx23885-i2c.c diff --git a/drivers/media/video/cx23885/cx23885-input.c b/drivers/media/pci/cx23885/cx23885-input.c index bcbf7faf1bab..2c925f77cf2a 100644 --- a/drivers/media/video/cx23885/cx23885-input.c +++ b/drivers/media/pci/cx23885/cx23885-input.c @@ -85,6 +85,7 @@ void cx23885_input_rx_work_handler(struct cx23885_dev *dev, u32 events) case CX23885_BOARD_HAUPPAUGE_HVR1270: case CX23885_BOARD_HAUPPAUGE_HVR1850: case CX23885_BOARD_HAUPPAUGE_HVR1290: + case CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL: case CX23885_BOARD_TEVII_S470: case CX23885_BOARD_HAUPPAUGE_HVR1250: /* @@ -162,6 +163,7 @@ static int cx23885_input_ir_start(struct cx23885_dev *dev) */ params.invert_level = true; break; + case CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL: case CX23885_BOARD_TEVII_S470: /* * The IR controller on this board only returns pulse widths. @@ -272,6 +274,13 @@ int cx23885_input_init(struct cx23885_dev *dev) /* The grey Hauppauge RC-5 remote */ rc_map = RC_MAP_HAUPPAUGE; break; + case CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL: + /* Integrated CX23885 IR controller */ + driver_type = RC_DRIVER_IR_RAW; + allowed_protos = RC_TYPE_NEC; + /* The grey Terratec remote with orange buttons */ + rc_map = RC_MAP_NEC_TERRATEC_CINERGY_XS; + break; case CX23885_BOARD_TEVII_S470: /* Integrated CX23885 IR controller */ driver_type = RC_DRIVER_IR_RAW; diff --git a/drivers/media/video/cx23885/cx23885-input.h b/drivers/media/pci/cx23885/cx23885-input.h index 75ef15d3f523..75ef15d3f523 100644 --- a/drivers/media/video/cx23885/cx23885-input.h +++ b/drivers/media/pci/cx23885/cx23885-input.h diff --git a/drivers/media/video/cx23885/cx23885-ioctl.c b/drivers/media/pci/cx23885/cx23885-ioctl.c index 44812ca78899..44812ca78899 100644 --- a/drivers/media/video/cx23885/cx23885-ioctl.c +++ b/drivers/media/pci/cx23885/cx23885-ioctl.c diff --git a/drivers/media/video/cx23885/cx23885-ioctl.h b/drivers/media/pci/cx23885/cx23885-ioctl.h index 315be0ca5a04..315be0ca5a04 100644 --- a/drivers/media/video/cx23885/cx23885-ioctl.h +++ b/drivers/media/pci/cx23885/cx23885-ioctl.h diff --git a/drivers/media/video/cx23885/cx23885-ir.c b/drivers/media/pci/cx23885/cx23885-ir.c index 7125247dd255..7125247dd255 100644 --- a/drivers/media/video/cx23885/cx23885-ir.c +++ b/drivers/media/pci/cx23885/cx23885-ir.c diff --git a/drivers/media/video/cx23885/cx23885-ir.h b/drivers/media/pci/cx23885/cx23885-ir.h index 0c9d8bda9e28..0c9d8bda9e28 100644 --- a/drivers/media/video/cx23885/cx23885-ir.h +++ b/drivers/media/pci/cx23885/cx23885-ir.h diff --git a/drivers/media/video/cx23885/cx23885-reg.h b/drivers/media/pci/cx23885/cx23885-reg.h index a99936e0cbc2..a99936e0cbc2 100644 --- a/drivers/media/video/cx23885/cx23885-reg.h +++ b/drivers/media/pci/cx23885/cx23885-reg.h diff --git a/drivers/media/video/cx23885/cx23885-vbi.c b/drivers/media/pci/cx23885/cx23885-vbi.c index a1154f035bc1..a1154f035bc1 100644 --- a/drivers/media/video/cx23885/cx23885-vbi.c +++ b/drivers/media/pci/cx23885/cx23885-vbi.c diff --git a/drivers/media/video/cx23885/cx23885-video.c b/drivers/media/pci/cx23885/cx23885-video.c index 22f8e7fbd665..8c4a9a5f9a50 100644 --- a/drivers/media/video/cx23885/cx23885-video.c +++ b/drivers/media/pci/cx23885/cx23885-video.c @@ -1426,7 +1426,7 @@ static int vidioc_g_audinput(struct file *file, void *priv, } static int vidioc_s_audinput(struct file *file, void *priv, - struct v4l2_audio *i) + const struct v4l2_audio *i) { struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev; if (i->index >= 2) diff --git a/drivers/media/video/cx23885/cx23885.h b/drivers/media/pci/cx23885/cx23885.h index 5d560c747e09..67f40d31450b 100644 --- a/drivers/media/video/cx23885/cx23885.h +++ b/drivers/media/pci/cx23885/cx23885.h @@ -90,6 +90,7 @@ #define CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL 34 #define CX23885_BOARD_TEVII_S471 35 #define CX23885_BOARD_HAUPPAUGE_HVR1255_22111 36 +#define CX23885_BOARD_PROF_8000 37 #define GPIO_0 0x00000001 #define GPIO_1 0x00000002 diff --git a/drivers/media/video/cx23885/cx23888-ir.c b/drivers/media/pci/cx23885/cx23888-ir.c index c2bc39c58f82..c2bc39c58f82 100644 --- a/drivers/media/video/cx23885/cx23888-ir.c +++ b/drivers/media/pci/cx23885/cx23888-ir.c diff --git a/drivers/media/video/cx23885/cx23888-ir.h b/drivers/media/pci/cx23885/cx23888-ir.h index d2de41caaf1d..d2de41caaf1d 100644 --- a/drivers/media/video/cx23885/cx23888-ir.h +++ b/drivers/media/pci/cx23885/cx23888-ir.h diff --git a/drivers/media/video/cx23885/netup-eeprom.c b/drivers/media/pci/cx23885/netup-eeprom.c index 98a48f500684..98a48f500684 100644 --- a/drivers/media/video/cx23885/netup-eeprom.c +++ b/drivers/media/pci/cx23885/netup-eeprom.c diff --git a/drivers/media/video/cx23885/netup-eeprom.h b/drivers/media/pci/cx23885/netup-eeprom.h index 13926e18feba..13926e18feba 100644 --- a/drivers/media/video/cx23885/netup-eeprom.h +++ b/drivers/media/pci/cx23885/netup-eeprom.h diff --git a/drivers/media/video/cx23885/netup-init.c b/drivers/media/pci/cx23885/netup-init.c index f4893e69cd89..f4893e69cd89 100644 --- a/drivers/media/video/cx23885/netup-init.c +++ b/drivers/media/pci/cx23885/netup-init.c diff --git a/drivers/media/video/cx23885/netup-init.h b/drivers/media/pci/cx23885/netup-init.h index d26ae4b1590e..d26ae4b1590e 100644 --- a/drivers/media/video/cx23885/netup-init.h +++ b/drivers/media/pci/cx23885/netup-init.h diff --git a/drivers/media/video/cx25821/Kconfig b/drivers/media/pci/cx25821/Kconfig index 5f6b54213713..5f6b54213713 100644 --- a/drivers/media/video/cx25821/Kconfig +++ b/drivers/media/pci/cx25821/Kconfig diff --git a/drivers/media/video/cx25821/Makefile b/drivers/media/pci/cx25821/Makefile index aedde18c68f9..5bf3ea4c1556 100644 --- a/drivers/media/video/cx25821/Makefile +++ b/drivers/media/pci/cx25821/Makefile @@ -7,7 +7,7 @@ cx25821-y := cx25821-core.o cx25821-cards.o cx25821-i2c.o \ obj-$(CONFIG_VIDEO_CX25821) += cx25821.o obj-$(CONFIG_VIDEO_CX25821_ALSA) += cx25821-alsa.o -ccflags-y := -Idrivers/media/video -ccflags-y += -Idrivers/media/common/tuners -ccflags-y += -Idrivers/media/dvb/dvb-core -ccflags-y += -Idrivers/media/dvb/frontends +ccflags-y += -Idrivers/media/i2c +ccflags-y += -Idrivers/media/tuners +ccflags-y += -Idrivers/media/dvb-core +ccflags-y += -Idrivers/media/dvb-frontends diff --git a/drivers/media/video/cx25821/cx25821-alsa.c b/drivers/media/pci/cx25821/cx25821-alsa.c index 1858a45dd081..1858a45dd081 100644 --- a/drivers/media/video/cx25821/cx25821-alsa.c +++ b/drivers/media/pci/cx25821/cx25821-alsa.c diff --git a/drivers/media/video/cx25821/cx25821-audio-upstream.c b/drivers/media/pci/cx25821/cx25821-audio-upstream.c index 8b2a99975c23..8b2a99975c23 100644 --- a/drivers/media/video/cx25821/cx25821-audio-upstream.c +++ b/drivers/media/pci/cx25821/cx25821-audio-upstream.c diff --git a/drivers/media/video/cx25821/cx25821-audio-upstream.h b/drivers/media/pci/cx25821/cx25821-audio-upstream.h index af2ae7c5815a..af2ae7c5815a 100644 --- a/drivers/media/video/cx25821/cx25821-audio-upstream.h +++ b/drivers/media/pci/cx25821/cx25821-audio-upstream.h diff --git a/drivers/media/video/cx25821/cx25821-audio.h b/drivers/media/pci/cx25821/cx25821-audio.h index 1fc2d24f5110..1fc2d24f5110 100644 --- a/drivers/media/video/cx25821/cx25821-audio.h +++ b/drivers/media/pci/cx25821/cx25821-audio.h diff --git a/drivers/media/video/cx25821/cx25821-biffuncs.h b/drivers/media/pci/cx25821/cx25821-biffuncs.h index 9326a7c729ec..9326a7c729ec 100644 --- a/drivers/media/video/cx25821/cx25821-biffuncs.h +++ b/drivers/media/pci/cx25821/cx25821-biffuncs.h diff --git a/drivers/media/video/cx25821/cx25821-cards.c b/drivers/media/pci/cx25821/cx25821-cards.c index 99988c988095..99988c988095 100644 --- a/drivers/media/video/cx25821/cx25821-cards.c +++ b/drivers/media/pci/cx25821/cx25821-cards.c diff --git a/drivers/media/video/cx25821/cx25821-core.c b/drivers/media/pci/cx25821/cx25821-core.c index f11f6f07e915..f11f6f07e915 100644 --- a/drivers/media/video/cx25821/cx25821-core.c +++ b/drivers/media/pci/cx25821/cx25821-core.c diff --git a/drivers/media/video/cx25821/cx25821-gpio.c b/drivers/media/pci/cx25821/cx25821-gpio.c index 29e43b03c85e..29e43b03c85e 100644 --- a/drivers/media/video/cx25821/cx25821-gpio.c +++ b/drivers/media/pci/cx25821/cx25821-gpio.c diff --git a/drivers/media/video/cx25821/cx25821-i2c.c b/drivers/media/pci/cx25821/cx25821-i2c.c index 9844549764c9..9844549764c9 100644 --- a/drivers/media/video/cx25821/cx25821-i2c.c +++ b/drivers/media/pci/cx25821/cx25821-i2c.c diff --git a/drivers/media/video/cx25821/cx25821-medusa-defines.h b/drivers/media/pci/cx25821/cx25821-medusa-defines.h index 7a9e6470ba22..7a9e6470ba22 100644 --- a/drivers/media/video/cx25821/cx25821-medusa-defines.h +++ b/drivers/media/pci/cx25821/cx25821-medusa-defines.h diff --git a/drivers/media/video/cx25821/cx25821-medusa-reg.h b/drivers/media/pci/cx25821/cx25821-medusa-reg.h index c98ac946b277..c98ac946b277 100644 --- a/drivers/media/video/cx25821/cx25821-medusa-reg.h +++ b/drivers/media/pci/cx25821/cx25821-medusa-reg.h diff --git a/drivers/media/video/cx25821/cx25821-medusa-video.c b/drivers/media/pci/cx25821/cx25821-medusa-video.c index 6a92e5c70c2a..6a92e5c70c2a 100644 --- a/drivers/media/video/cx25821/cx25821-medusa-video.c +++ b/drivers/media/pci/cx25821/cx25821-medusa-video.c diff --git a/drivers/media/video/cx25821/cx25821-medusa-video.h b/drivers/media/pci/cx25821/cx25821-medusa-video.h index 6175e0961855..6175e0961855 100644 --- a/drivers/media/video/cx25821/cx25821-medusa-video.h +++ b/drivers/media/pci/cx25821/cx25821-medusa-video.h diff --git a/drivers/media/video/cx25821/cx25821-reg.h b/drivers/media/pci/cx25821/cx25821-reg.h index a3fc25a4dc0b..a3fc25a4dc0b 100644 --- a/drivers/media/video/cx25821/cx25821-reg.h +++ b/drivers/media/pci/cx25821/cx25821-reg.h diff --git a/drivers/media/video/cx25821/cx25821-sram.h b/drivers/media/pci/cx25821/cx25821-sram.h index 5f05d153bc4d..5f05d153bc4d 100644 --- a/drivers/media/video/cx25821/cx25821-sram.h +++ b/drivers/media/pci/cx25821/cx25821-sram.h diff --git a/drivers/media/video/cx25821/cx25821-video-upstream-ch2.c b/drivers/media/pci/cx25821/cx25821-video-upstream-ch2.c index c8c94fbf5d8d..c8c94fbf5d8d 100644 --- a/drivers/media/video/cx25821/cx25821-video-upstream-ch2.c +++ b/drivers/media/pci/cx25821/cx25821-video-upstream-ch2.c diff --git a/drivers/media/video/cx25821/cx25821-video-upstream-ch2.h b/drivers/media/pci/cx25821/cx25821-video-upstream-ch2.h index d42dab59b663..d42dab59b663 100644 --- a/drivers/media/video/cx25821/cx25821-video-upstream-ch2.h +++ b/drivers/media/pci/cx25821/cx25821-video-upstream-ch2.h diff --git a/drivers/media/video/cx25821/cx25821-video-upstream.c b/drivers/media/pci/cx25821/cx25821-video-upstream.c index 52c13e0b6492..52c13e0b6492 100644 --- a/drivers/media/video/cx25821/cx25821-video-upstream.c +++ b/drivers/media/pci/cx25821/cx25821-video-upstream.c diff --git a/drivers/media/video/cx25821/cx25821-video-upstream.h b/drivers/media/pci/cx25821/cx25821-video-upstream.h index 268ec8aa6a61..268ec8aa6a61 100644 --- a/drivers/media/video/cx25821/cx25821-video-upstream.h +++ b/drivers/media/pci/cx25821/cx25821-video-upstream.h diff --git a/drivers/media/video/cx25821/cx25821-video.c b/drivers/media/pci/cx25821/cx25821-video.c index b38d4379cc36..0a80245165d0 100644 --- a/drivers/media/video/cx25821/cx25821-video.c +++ b/drivers/media/pci/cx25821/cx25821-video.c @@ -1610,7 +1610,7 @@ int cx25821_vidioc_cropcap(struct file *file, void *priv, return 0; } -int cx25821_vidioc_s_crop(struct file *file, void *priv, struct v4l2_crop *crop) +int cx25821_vidioc_s_crop(struct file *file, void *priv, const struct v4l2_crop *crop) { struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; struct cx25821_fh *fh = priv; diff --git a/drivers/media/video/cx25821/cx25821-video.h b/drivers/media/pci/cx25821/cx25821-video.h index 9652a5e35ba2..c265e35b37c3 100644 --- a/drivers/media/video/cx25821/cx25821-video.h +++ b/drivers/media/pci/cx25821/cx25821-video.h @@ -177,7 +177,7 @@ extern int cx25821_set_control(struct cx25821_dev *dev, extern int cx25821_vidioc_cropcap(struct file *file, void *fh, struct v4l2_cropcap *cropcap); extern int cx25821_vidioc_s_crop(struct file *file, void *priv, - struct v4l2_crop *crop); + const struct v4l2_crop *crop); extern int cx25821_vidioc_g_crop(struct file *file, void *priv, struct v4l2_crop *crop); diff --git a/drivers/media/video/cx25821/cx25821.h b/drivers/media/pci/cx25821/cx25821.h index 8a9c0c869412..8a9c0c869412 100644 --- a/drivers/media/video/cx25821/cx25821.h +++ b/drivers/media/pci/cx25821/cx25821.h diff --git a/drivers/media/video/cx88/Kconfig b/drivers/media/pci/cx88/Kconfig index 3598dc087b08..d27fccbf03c4 100644 --- a/drivers/media/video/cx88/Kconfig +++ b/drivers/media/pci/cx88/Kconfig @@ -6,7 +6,7 @@ config VIDEO_CX88 select VIDEOBUF_DMA_SG select VIDEO_TUNER select VIDEO_TVEEPROM - select VIDEO_WM8775 if VIDEO_HELPER_CHIPS_AUTO + select VIDEO_WM8775 if MEDIA_SUBDRV_AUTOSELECT ---help--- This is a video4linux driver for Conexant 2388x based TV cards. @@ -46,23 +46,23 @@ config VIDEO_CX88_DVB tristate "DVB/ATSC Support for cx2388x based TV cards" depends on VIDEO_CX88 && DVB_CORE select VIDEOBUF_DVB - select DVB_PLL if !DVB_FE_CUSTOMISE - select DVB_MT352 if !DVB_FE_CUSTOMISE - select DVB_ZL10353 if !DVB_FE_CUSTOMISE - select DVB_OR51132 if !DVB_FE_CUSTOMISE - select DVB_CX22702 if !DVB_FE_CUSTOMISE - select DVB_LGDT330X if !DVB_FE_CUSTOMISE - select DVB_NXT200X if !DVB_FE_CUSTOMISE - select DVB_CX24123 if !DVB_FE_CUSTOMISE - select DVB_ISL6421 if !DVB_FE_CUSTOMISE - select DVB_S5H1411 if !DVB_FE_CUSTOMISE - select DVB_CX24116 if !DVB_FE_CUSTOMISE - select DVB_STV0299 if !DVB_FE_CUSTOMISE - select DVB_STV0288 if !DVB_FE_CUSTOMISE - select DVB_STB6000 if !DVB_FE_CUSTOMISE - select DVB_STV0900 if !DVB_FE_CUSTOMISE - select DVB_STB6100 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMISE + select DVB_PLL if MEDIA_SUBDRV_AUTOSELECT + select DVB_MT352 if MEDIA_SUBDRV_AUTOSELECT + select DVB_ZL10353 if MEDIA_SUBDRV_AUTOSELECT + select DVB_OR51132 if MEDIA_SUBDRV_AUTOSELECT + select DVB_CX22702 if MEDIA_SUBDRV_AUTOSELECT + select DVB_LGDT330X if MEDIA_SUBDRV_AUTOSELECT + select DVB_NXT200X if MEDIA_SUBDRV_AUTOSELECT + select DVB_CX24123 if MEDIA_SUBDRV_AUTOSELECT + select DVB_ISL6421 if MEDIA_SUBDRV_AUTOSELECT + select DVB_S5H1411 if MEDIA_SUBDRV_AUTOSELECT + select DVB_CX24116 if MEDIA_SUBDRV_AUTOSELECT + select DVB_STV0299 if MEDIA_SUBDRV_AUTOSELECT + select DVB_STV0288 if MEDIA_SUBDRV_AUTOSELECT + select DVB_STB6000 if MEDIA_SUBDRV_AUTOSELECT + select DVB_STV0900 if MEDIA_SUBDRV_AUTOSELECT + select DVB_STB6100 if MEDIA_SUBDRV_AUTOSELECT + select MEDIA_TUNER_SIMPLE if MEDIA_SUBDRV_AUTOSELECT ---help--- This adds support for DVB/ATSC cards based on the Conexant 2388x chip. diff --git a/drivers/media/video/cx88/Makefile b/drivers/media/pci/cx88/Makefile index c1a2785ba243..d3679c3ee248 100644 --- a/drivers/media/video/cx88/Makefile +++ b/drivers/media/pci/cx88/Makefile @@ -10,7 +10,7 @@ obj-$(CONFIG_VIDEO_CX88_BLACKBIRD) += cx88-blackbird.o obj-$(CONFIG_VIDEO_CX88_DVB) += cx88-dvb.o obj-$(CONFIG_VIDEO_CX88_VP3054) += cx88-vp3054-i2c.o -ccflags-y += -Idrivers/media/video -ccflags-y += -Idrivers/media/common/tuners -ccflags-y += -Idrivers/media/dvb/dvb-core -ccflags-y += -Idrivers/media/dvb/frontends +ccflags-y += -Idrivers/media/i2c +ccflags-y += -Idrivers/media/tuners +ccflags-y += -Idrivers/media/dvb-core +ccflags-y += -Idrivers/media/dvb-frontends diff --git a/drivers/media/video/cx88/cx88-alsa.c b/drivers/media/pci/cx88/cx88-alsa.c index dfac6e34859f..3aa6856ead3b 100644 --- a/drivers/media/video/cx88/cx88-alsa.c +++ b/drivers/media/pci/cx88/cx88-alsa.c @@ -749,7 +749,7 @@ static struct snd_kcontrol_new snd_cx88_alc_switch = { * Only boards with eeprom and byte 1 at eeprom=1 have it */ -static const struct pci_device_id const cx88_audio_pci_tbl[] __devinitdata = { +static const struct pci_device_id cx88_audio_pci_tbl[] __devinitdata = { {0x14f1,0x8801,PCI_ANY_ID,PCI_ANY_ID,0,0,0}, {0x14f1,0x8811,PCI_ANY_ID,PCI_ANY_ID,0,0,0}, {0, } diff --git a/drivers/media/video/cx88/cx88-blackbird.c b/drivers/media/pci/cx88/cx88-blackbird.c index 843ffd9e533b..def363fb71c0 100644 --- a/drivers/media/video/cx88/cx88-blackbird.c +++ b/drivers/media/pci/cx88/cx88-blackbird.c @@ -1236,7 +1236,7 @@ static int cx8802_blackbird_probe(struct cx8802_driver *drv) err = cx2341x_handler_init(&dev->cxhdl, 36); if (err) goto fail_core; - v4l2_ctrl_add_handler(&dev->cxhdl.hdl, &core->video_hdl); + v4l2_ctrl_add_handler(&dev->cxhdl.hdl, &core->video_hdl, NULL); /* blackbird stuff */ printk("%s/2: cx23416 based mpeg encoder (blackbird reference design)\n", diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/pci/cx88/cx88-cards.c index 4e9d4f722960..0c255248cbcd 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/pci/cx88/cx88-cards.c @@ -3028,9 +3028,9 @@ static int cx88_xc3028_winfast1800h_callback(struct cx88_core *core, cx_set(MO_GP1_IO, 0x1010); mdelay(50); cx_clear(MO_GP1_IO, 0x10); - mdelay(50); + mdelay(75); cx_set(MO_GP1_IO, 0x10); - mdelay(50); + mdelay(75); return 0; } return -EINVAL; diff --git a/drivers/media/video/cx88/cx88-core.c b/drivers/media/pci/cx88/cx88-core.c index e81c735f012a..c97b174be3ab 100644 --- a/drivers/media/video/cx88/cx88-core.c +++ b/drivers/media/pci/cx88/cx88-core.c @@ -253,7 +253,7 @@ cx88_free_buffer(struct videobuf_queue *q, struct cx88_buffer *buf) * 0x0c00 - FIFOs */ -const struct sram_channel const cx88_sram_channels[] = { +const struct sram_channel cx88_sram_channels[] = { [SRAM_CH21] = { .name = "video y / packed", .cmds_start = 0x180040, diff --git a/drivers/media/video/cx88/cx88-dsp.c b/drivers/media/pci/cx88/cx88-dsp.c index a9907265ff66..a9907265ff66 100644 --- a/drivers/media/video/cx88/cx88-dsp.c +++ b/drivers/media/pci/cx88/cx88-dsp.c diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/pci/cx88/cx88-dvb.c index 003937cd72f5..d803bba09525 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/pci/cx88/cx88-dvb.c @@ -1578,7 +1578,7 @@ static int dvb_register(struct cx8802_dev *dev) /* register everything */ res = videobuf_dvb_register_bus(&dev->frontends, THIS_MODULE, dev, - &dev->pci->dev, adapter_nr, mfe_shared, NULL); + &dev->pci->dev, adapter_nr, mfe_shared); if (res) goto frontend_detach; return res; diff --git a/drivers/media/video/cx88/cx88-i2c.c b/drivers/media/pci/cx88/cx88-i2c.c index de0f1af74e41..de0f1af74e41 100644 --- a/drivers/media/video/cx88/cx88-i2c.c +++ b/drivers/media/pci/cx88/cx88-i2c.c diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/pci/cx88/cx88-input.c index ebf448c48ca3..ebf448c48ca3 100644 --- a/drivers/media/video/cx88/cx88-input.c +++ b/drivers/media/pci/cx88/cx88-input.c diff --git a/drivers/media/video/cx88/cx88-mpeg.c b/drivers/media/pci/cx88/cx88-mpeg.c index c04fb618e10b..c04fb618e10b 100644 --- a/drivers/media/video/cx88/cx88-mpeg.c +++ b/drivers/media/pci/cx88/cx88-mpeg.c diff --git a/drivers/media/video/cx88/cx88-reg.h b/drivers/media/pci/cx88/cx88-reg.h index 2ec52d1cdea0..2ec52d1cdea0 100644 --- a/drivers/media/video/cx88/cx88-reg.h +++ b/drivers/media/pci/cx88/cx88-reg.h diff --git a/drivers/media/video/cx88/cx88-tvaudio.c b/drivers/media/pci/cx88/cx88-tvaudio.c index 770ec05b5e9b..770ec05b5e9b 100644 --- a/drivers/media/video/cx88/cx88-tvaudio.c +++ b/drivers/media/pci/cx88/cx88-tvaudio.c diff --git a/drivers/media/video/cx88/cx88-vbi.c b/drivers/media/pci/cx88/cx88-vbi.c index f8f8389c0362..f8f8389c0362 100644 --- a/drivers/media/video/cx88/cx88-vbi.c +++ b/drivers/media/pci/cx88/cx88-vbi.c diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/pci/cx88/cx88-video.c index f6fcc7e763ab..a146d50d7795 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/pci/cx88/cx88-video.c @@ -1795,7 +1795,7 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev, if (vc->id == V4L2_CID_CHROMA_AGC) core->chroma_agc = vc; } - v4l2_ctrl_add_handler(&core->video_hdl, &core->audio_hdl); + v4l2_ctrl_add_handler(&core->video_hdl, &core->audio_hdl, NULL); /* load and configure helper modules */ diff --git a/drivers/media/video/cx88/cx88-vp3054-i2c.c b/drivers/media/pci/cx88/cx88-vp3054-i2c.c index d77f8ecab9d7..d77f8ecab9d7 100644 --- a/drivers/media/video/cx88/cx88-vp3054-i2c.c +++ b/drivers/media/pci/cx88/cx88-vp3054-i2c.c diff --git a/drivers/media/video/cx88/cx88-vp3054-i2c.h b/drivers/media/pci/cx88/cx88-vp3054-i2c.h index be99c931dc3e..be99c931dc3e 100644 --- a/drivers/media/video/cx88/cx88-vp3054-i2c.h +++ b/drivers/media/pci/cx88/cx88-vp3054-i2c.h diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/pci/cx88/cx88.h index 0cae0fd9e164..44ffc8b3d45f 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/pci/cx88/cx88.h @@ -141,7 +141,7 @@ struct sram_channel { u32 cnt1_reg; u32 cnt2_reg; }; -extern const struct sram_channel const cx88_sram_channels[]; +extern const struct sram_channel cx88_sram_channels[]; /* ----------------------------------------------------------- */ /* card configuration */ diff --git a/drivers/media/dvb/ddbridge/Kconfig b/drivers/media/pci/ddbridge/Kconfig index d099e1a12c85..44e5dc15e60a 100644 --- a/drivers/media/dvb/ddbridge/Kconfig +++ b/drivers/media/pci/ddbridge/Kconfig @@ -1,11 +1,11 @@ config DVB_DDBRIDGE tristate "Digital Devices bridge support" depends on DVB_CORE && PCI && I2C - select DVB_LNBP21 if !DVB_FE_CUSTOMISE - select DVB_STV6110x if !DVB_FE_CUSTOMISE - select DVB_STV090x if !DVB_FE_CUSTOMISE - select DVB_DRXK if !DVB_FE_CUSTOMISE - select DVB_TDA18271C2DD if !DVB_FE_CUSTOMISE + select DVB_LNBP21 if MEDIA_SUBDRV_AUTOSELECT + select DVB_STV6110x if MEDIA_SUBDRV_AUTOSELECT + select DVB_STV090x if MEDIA_SUBDRV_AUTOSELECT + select DVB_DRXK if MEDIA_SUBDRV_AUTOSELECT + select DVB_TDA18271C2DD if MEDIA_SUBDRV_AUTOSELECT ---help--- Support for cards with the Digital Devices PCI express bridge: - Octopus PCIe Bridge diff --git a/drivers/media/dvb/ddbridge/Makefile b/drivers/media/pci/ddbridge/Makefile index 38019bafb862..7446c8b677b5 100644 --- a/drivers/media/dvb/ddbridge/Makefile +++ b/drivers/media/pci/ddbridge/Makefile @@ -6,9 +6,9 @@ ddbridge-objs := ddbridge-core.o obj-$(CONFIG_DVB_DDBRIDGE) += ddbridge.o -ccflags-y += -Idrivers/media/dvb/dvb-core/ -ccflags-y += -Idrivers/media/dvb/frontends/ -ccflags-y += -Idrivers/media/common/tuners/ +ccflags-y += -Idrivers/media/dvb-core/ +ccflags-y += -Idrivers/media/dvb-frontends/ +ccflags-y += -Idrivers/media/tuners/ # For the staging CI driver cxd2099 ccflags-y += -Idrivers/staging/media/cxd2099/ diff --git a/drivers/media/dvb/ddbridge/ddbridge-core.c b/drivers/media/pci/ddbridge/ddbridge-core.c index ebf3f05839d2..feff57ee5a08 100644 --- a/drivers/media/dvb/ddbridge/ddbridge-core.c +++ b/drivers/media/pci/ddbridge/ddbridge-core.c @@ -1497,7 +1497,7 @@ static int ddb_class_create(void) ddb_class = class_create(THIS_MODULE, DDB_NAME); if (IS_ERR(ddb_class)) { unregister_chrdev(ddb_major, DDB_NAME); - return -1; + return PTR_ERR(ddb_class); } ddb_class->devnode = ddb_devnode; return 0; @@ -1701,11 +1701,18 @@ static struct pci_driver ddb_pci_driver = { static __init int module_init_ddbridge(void) { + int ret; + printk(KERN_INFO "Digital Devices PCIE bridge driver, " "Copyright (C) 2010-11 Digital Devices GmbH\n"); - if (ddb_class_create()) - return -1; - return pci_register_driver(&ddb_pci_driver); + + ret = ddb_class_create(); + if (ret < 0) + return ret; + ret = pci_register_driver(&ddb_pci_driver); + if (ret < 0) + ddb_class_destroy(); + return ret; } static __exit void module_exit_ddbridge(void) diff --git a/drivers/media/dvb/ddbridge/ddbridge-regs.h b/drivers/media/pci/ddbridge/ddbridge-regs.h index a3ccb318b500..a3ccb318b500 100644 --- a/drivers/media/dvb/ddbridge/ddbridge-regs.h +++ b/drivers/media/pci/ddbridge/ddbridge-regs.h diff --git a/drivers/media/dvb/ddbridge/ddbridge.h b/drivers/media/pci/ddbridge/ddbridge.h index 8b1b41d2a52d..8b1b41d2a52d 100644 --- a/drivers/media/dvb/ddbridge/ddbridge.h +++ b/drivers/media/pci/ddbridge/ddbridge.h diff --git a/drivers/media/dvb/dm1105/Kconfig b/drivers/media/pci/dm1105/Kconfig index f3de0a4d63f2..013df4e015cd 100644 --- a/drivers/media/dvb/dm1105/Kconfig +++ b/drivers/media/pci/dm1105/Kconfig @@ -1,13 +1,13 @@ config DVB_DM1105 tristate "SDMC DM1105 based PCI cards" depends on DVB_CORE && PCI && I2C - select DVB_PLL if !DVB_FE_CUSTOMISE - select DVB_STV0299 if !DVB_FE_CUSTOMISE - select DVB_STV0288 if !DVB_FE_CUSTOMISE - select DVB_STB6000 if !DVB_FE_CUSTOMISE - select DVB_CX24116 if !DVB_FE_CUSTOMISE - select DVB_SI21XX if !DVB_FE_CUSTOMISE - select DVB_DS3000 if !DVB_FE_CUSTOMISE + select DVB_PLL if MEDIA_SUBDRV_AUTOSELECT + select DVB_STV0299 if MEDIA_SUBDRV_AUTOSELECT + select DVB_STV0288 if MEDIA_SUBDRV_AUTOSELECT + select DVB_STB6000 if MEDIA_SUBDRV_AUTOSELECT + select DVB_CX24116 if MEDIA_SUBDRV_AUTOSELECT + select DVB_SI21XX if MEDIA_SUBDRV_AUTOSELECT + select DVB_DS3000 if MEDIA_SUBDRV_AUTOSELECT depends on RC_CORE help Support for cards based on the SDMC DM1105 PCI chip like diff --git a/drivers/media/pci/dm1105/Makefile b/drivers/media/pci/dm1105/Makefile new file mode 100644 index 000000000000..327585143c83 --- /dev/null +++ b/drivers/media/pci/dm1105/Makefile @@ -0,0 +1,3 @@ +obj-$(CONFIG_DVB_DM1105) += dm1105.o + +ccflags-y += -Idrivers/media/dvb-core/ -Idrivers/media/dvb-frontends diff --git a/drivers/media/dvb/dm1105/dm1105.c b/drivers/media/pci/dm1105/dm1105.c index a609b3a9b146..a609b3a9b146 100644 --- a/drivers/media/dvb/dm1105/dm1105.c +++ b/drivers/media/pci/dm1105/dm1105.c diff --git a/drivers/media/video/ivtv/Kconfig b/drivers/media/pci/ivtv/Kconfig index 89f65914cc8e..dd6ee57e3a4c 100644 --- a/drivers/media/video/ivtv/Kconfig +++ b/drivers/media/pci/ivtv/Kconfig @@ -28,6 +28,22 @@ config VIDEO_IVTV To compile this driver as a module, choose M here: the module will be called ivtv. +config VIDEO_IVTV_ALSA + tristate "Conexant cx23415/cx23416 ALSA interface for PCM audio capture" + depends on VIDEO_IVTV && SND + select SND_PCM + ---help--- + This driver provides an ALSA interface as another method for user + applications to obtain PCM audio data from Conexant cx23415/cx23416 + based PCI TV cards supported by the ivtv driver. + + The ALSA interface has much wider use in user applications performing + PCM audio capture, than the V4L2 "/dev/video24" PCM audio interface + provided by the main ivtv driver. + + To compile this driver as a module, choose M here: the + module will be called ivtv-alsa. + config VIDEO_FB_IVTV tristate "Conexant cx23415 framebuffer support" depends on VIDEO_IVTV && FB diff --git a/drivers/media/video/ivtv/Makefile b/drivers/media/pci/ivtv/Makefile index 77de8a45b46f..0eaa88298b7e 100644 --- a/drivers/media/video/ivtv/Makefile +++ b/drivers/media/pci/ivtv/Makefile @@ -3,12 +3,14 @@ ivtv-objs := ivtv-routing.o ivtv-cards.o ivtv-controls.o \ ivtv-gpio.o ivtv-i2c.o ivtv-ioctl.o ivtv-irq.o \ ivtv-mailbox.o ivtv-queue.o ivtv-streams.o ivtv-udma.o \ ivtv-vbi.o ivtv-yuv.o +ivtv-alsa-objs := ivtv-alsa-main.o ivtv-alsa-pcm.o obj-$(CONFIG_VIDEO_IVTV) += ivtv.o +obj-$(CONFIG_VIDEO_IVTV_ALSA) += ivtv-alsa.o obj-$(CONFIG_VIDEO_FB_IVTV) += ivtvfb.o -ccflags-y += -I$(srctree)/drivers/media/video -ccflags-y += -I$(srctree)/drivers/media/common/tuners -ccflags-y += -I$(srctree)/drivers/media/dvb/dvb-core -ccflags-y += -I$(srctree)/drivers/media/dvb/frontends +ccflags-y += -I$(srctree)/drivers/media/i2c +ccflags-y += -I$(srctree)/drivers/media/tuners +ccflags-y += -I$(srctree)/drivers/media/dvb-core +ccflags-y += -I$(srctree)/drivers/media/dvb-frontends diff --git a/drivers/media/pci/ivtv/ivtv-alsa-main.c b/drivers/media/pci/ivtv/ivtv-alsa-main.c new file mode 100644 index 000000000000..8deab1629b3b --- /dev/null +++ b/drivers/media/pci/ivtv/ivtv-alsa-main.c @@ -0,0 +1,303 @@ +/* + * ALSA interface to ivtv PCM capture streams + * + * Copyright (C) 2009,2012 Andy Walls <awalls@md.metrocast.net> + * Copyright (C) 2009 Devin Heitmueller <dheitmueller@kernellabs.com> + * + * Portions of this work were sponsored by ONELAN Limited for the cx18 driver + * + * 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 + */ + +#include <linux/init.h> +#include <linux/slab.h> +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/device.h> +#include <linux/spinlock.h> + +#include <media/v4l2-device.h> + +#include <sound/core.h> +#include <sound/initval.h> + +#include "ivtv-driver.h" +#include "ivtv-version.h" +#include "ivtv-alsa.h" +#include "ivtv-alsa-mixer.h" +#include "ivtv-alsa-pcm.h" + +int ivtv_alsa_debug; + +#define IVTV_DEBUG_ALSA_INFO(fmt, arg...) \ + do { \ + if (ivtv_alsa_debug & 2) \ + pr_info("%s: " fmt, "ivtv-alsa", ## arg); \ + } while (0) + +module_param_named(debug, ivtv_alsa_debug, int, 0644); +MODULE_PARM_DESC(debug, + "Debug level (bitmask). Default: 0\n" + "\t\t\t 1/0x0001: warning\n" + "\t\t\t 2/0x0002: info\n"); + +MODULE_AUTHOR("Andy Walls"); +MODULE_DESCRIPTION("CX23415/CX23416 ALSA Interface"); +MODULE_SUPPORTED_DEVICE("CX23415/CX23416 MPEG2 encoder"); +MODULE_LICENSE("GPL"); + +MODULE_VERSION(IVTV_VERSION); + +static inline +struct snd_ivtv_card *to_snd_ivtv_card(struct v4l2_device *v4l2_dev) +{ + return to_ivtv(v4l2_dev)->alsa; +} + +static inline +struct snd_ivtv_card *p_to_snd_ivtv_card(struct v4l2_device **v4l2_dev) +{ + return container_of(v4l2_dev, struct snd_ivtv_card, v4l2_dev); +} + +static void snd_ivtv_card_free(struct snd_ivtv_card *itvsc) +{ + if (itvsc == NULL) + return; + + if (itvsc->v4l2_dev != NULL) + to_ivtv(itvsc->v4l2_dev)->alsa = NULL; + + /* FIXME - take any other stopping actions needed */ + + kfree(itvsc); +} + +static void snd_ivtv_card_private_free(struct snd_card *sc) +{ + if (sc == NULL) + return; + snd_ivtv_card_free(sc->private_data); + sc->private_data = NULL; + sc->private_free = NULL; +} + +static int snd_ivtv_card_create(struct v4l2_device *v4l2_dev, + struct snd_card *sc, + struct snd_ivtv_card **itvsc) +{ + *itvsc = kzalloc(sizeof(struct snd_ivtv_card), GFP_KERNEL); + if (*itvsc == NULL) + return -ENOMEM; + + (*itvsc)->v4l2_dev = v4l2_dev; + (*itvsc)->sc = sc; + + sc->private_data = *itvsc; + sc->private_free = snd_ivtv_card_private_free; + + return 0; +} + +static int snd_ivtv_card_set_names(struct snd_ivtv_card *itvsc) +{ + struct ivtv *itv = to_ivtv(itvsc->v4l2_dev); + struct snd_card *sc = itvsc->sc; + + /* sc->driver is used by alsa-lib's configurator: simple, unique */ + strlcpy(sc->driver, "CX2341[56]", sizeof(sc->driver)); + + /* sc->shortname is a symlink in /proc/asound: IVTV-M -> cardN */ + snprintf(sc->shortname, sizeof(sc->shortname), "IVTV-%d", + itv->instance); + + /* sc->longname is read from /proc/asound/cards */ + snprintf(sc->longname, sizeof(sc->longname), + "CX2341[56] #%d %s TV/FM Radio/Line-In Capture", + itv->instance, itv->card_name); + + return 0; +} + +static int snd_ivtv_init(struct v4l2_device *v4l2_dev) +{ + struct ivtv *itv = to_ivtv(v4l2_dev); + struct snd_card *sc = NULL; + struct snd_ivtv_card *itvsc; + int ret; + + /* Numbrs steps from "Writing an ALSA Driver" by Takashi Iwai */ + + /* (1) Check and increment the device index */ + /* This is a no-op for us. We'll use the itv->instance */ + + /* (2) Create a card instance */ + ret = snd_card_create(SNDRV_DEFAULT_IDX1, /* use first available id */ + SNDRV_DEFAULT_STR1, /* xid from end of shortname*/ + THIS_MODULE, 0, &sc); + if (ret) { + IVTV_ALSA_ERR("%s: snd_card_create() failed with err %d\n", + __func__, ret); + goto err_exit; + } + + /* (3) Create a main component */ + ret = snd_ivtv_card_create(v4l2_dev, sc, &itvsc); + if (ret) { + IVTV_ALSA_ERR("%s: snd_ivtv_card_create() failed with err %d\n", + __func__, ret); + goto err_exit_free; + } + + /* (4) Set the driver ID and name strings */ + snd_ivtv_card_set_names(itvsc); + + /* (5) Create other components: mixer, PCM, & proc files */ +#if 0 + ret = snd_ivtv_mixer_create(itvsc); + if (ret) { + IVTV_ALSA_WARN("%s: snd_ivtv_mixer_create() failed with err %d:" + " proceeding anyway\n", __func__, ret); + } +#endif + + ret = snd_ivtv_pcm_create(itvsc); + if (ret) { + IVTV_ALSA_ERR("%s: snd_ivtv_pcm_create() failed with err %d\n", + __func__, ret); + goto err_exit_free; + } + /* FIXME - proc files */ + + /* (7) Set the driver data and return 0 */ + /* We do this out of normal order for PCI drivers to avoid races */ + itv->alsa = itvsc; + + /* (6) Register the card instance */ + ret = snd_card_register(sc); + if (ret) { + itv->alsa = NULL; + IVTV_ALSA_ERR("%s: snd_card_register() failed with err %d\n", + __func__, ret); + goto err_exit_free; + } + + return 0; + +err_exit_free: + if (sc != NULL) + snd_card_free(sc); + kfree(itvsc); +err_exit: + return ret; +} + +int ivtv_alsa_load(struct ivtv *itv) +{ + struct v4l2_device *v4l2_dev = &itv->v4l2_dev; + struct ivtv_stream *s; + + if (v4l2_dev == NULL) { + pr_err("ivtv-alsa: %s: struct v4l2_device * is NULL\n", + __func__); + return 0; + } + + itv = to_ivtv(v4l2_dev); + if (itv == NULL) { + pr_err("ivtv-alsa itv is NULL\n"); + return 0; + } + + s = &itv->streams[IVTV_ENC_STREAM_TYPE_PCM]; + if (s->vdev == NULL) { + IVTV_DEBUG_ALSA_INFO("%s: PCM stream for card is disabled - " + "skipping\n", __func__); + return 0; + } + + if (itv->alsa != NULL) { + IVTV_ALSA_ERR("%s: struct snd_ivtv_card * already exists\n", + __func__); + return 0; + } + + if (snd_ivtv_init(v4l2_dev)) { + IVTV_ALSA_ERR("%s: failed to create struct snd_ivtv_card\n", + __func__); + } else { + IVTV_DEBUG_ALSA_INFO("%s: created ivtv ALSA interface instance " + "\n", __func__); + } + return 0; +} + +static int __init ivtv_alsa_init(void) +{ + pr_info("ivtv-alsa: module loading...\n"); + ivtv_ext_init = &ivtv_alsa_load; + return 0; +} + +static void __exit snd_ivtv_exit(struct snd_ivtv_card *itvsc) +{ + struct ivtv *itv = to_ivtv(itvsc->v4l2_dev); + + /* FIXME - pointer checks & shutdown itvsc */ + + snd_card_free(itvsc->sc); + itv->alsa = NULL; +} + +static int __exit ivtv_alsa_exit_callback(struct device *dev, void *data) +{ + struct v4l2_device *v4l2_dev = dev_get_drvdata(dev); + struct snd_ivtv_card *itvsc; + + if (v4l2_dev == NULL) { + pr_err("ivtv-alsa: %s: struct v4l2_device * is NULL\n", + __func__); + return 0; + } + + itvsc = to_snd_ivtv_card(v4l2_dev); + if (itvsc == NULL) { + IVTV_ALSA_WARN("%s: struct snd_ivtv_card * is NULL\n", + __func__); + return 0; + } + + snd_ivtv_exit(itvsc); + return 0; +} + +static void __exit ivtv_alsa_exit(void) +{ + struct device_driver *drv; + int ret; + + pr_info("ivtv-alsa: module unloading...\n"); + + drv = driver_find("ivtv", &pci_bus_type); + ret = driver_for_each_device(drv, NULL, NULL, ivtv_alsa_exit_callback); + (void)ret; /* suppress compiler warning */ + + ivtv_ext_init = NULL; + pr_info("ivtv-alsa: module unload complete\n"); +} + +module_init(ivtv_alsa_init); +module_exit(ivtv_alsa_exit); diff --git a/drivers/media/pci/ivtv/ivtv-alsa-mixer.c b/drivers/media/pci/ivtv/ivtv-alsa-mixer.c new file mode 100644 index 000000000000..33ec05b09af3 --- /dev/null +++ b/drivers/media/pci/ivtv/ivtv-alsa-mixer.c @@ -0,0 +1,175 @@ +/* + * ALSA mixer controls for the + * ALSA interface to ivtv PCM capture streams + * + * Copyright (C) 2009,2012 Andy Walls <awalls@md.metrocast.net> + * + * 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 + */ + +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/device.h> +#include <linux/spinlock.h> +#include <linux/videodev2.h> + +#include <media/v4l2-device.h> + +#include <sound/core.h> +#include <sound/control.h> +#include <sound/tlv.h> + +#include "ivtv-alsa.h" +#include "ivtv-driver.h" + +/* + * Note the cx25840-core volume scale is funny, due to the alignment of the + * scale with another chip's range: + * + * v4l2_control value /512 indicated dB actual dB reg 0x8d4 + * 0x0000 - 0x01ff 0 -119 -96 228 + * 0x0200 - 0x02ff 1 -118 -96 228 + * ... + * 0x2c00 - 0x2dff 22 -97 -96 228 + * 0x2e00 - 0x2fff 23 -96 -96 228 + * 0x3000 - 0x31ff 24 -95 -95 226 + * ... + * 0xee00 - 0xefff 119 0 0 36 + * ... + * 0xfe00 - 0xffff 127 +8 +8 20 + */ +static inline int dB_to_cx25840_vol(int dB) +{ + if (dB < -96) + dB = -96; + else if (dB > 8) + dB = 8; + return (dB + 119) << 9; +} + +static inline int cx25840_vol_to_dB(int v) +{ + if (v < (23 << 9)) + v = (23 << 9); + else if (v > (127 << 9)) + v = (127 << 9); + return (v >> 9) - 119; +} + +static int snd_ivtv_mixer_tv_vol_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = 1; + /* We're already translating values, just keep this control in dB */ + uinfo->value.integer.min = -96; + uinfo->value.integer.max = 8; + uinfo->value.integer.step = 1; + return 0; +} + +static int snd_ivtv_mixer_tv_vol_get(struct snd_kcontrol *kctl, + struct snd_ctl_elem_value *uctl) +{ + struct snd_ivtv_card *itvsc = snd_kcontrol_chip(kctl); + struct ivtv *itv = to_ivtv(itvsc->v4l2_dev); + struct v4l2_control vctrl; + int ret; + + vctrl.id = V4L2_CID_AUDIO_VOLUME; + vctrl.value = dB_to_cx25840_vol(uctl->value.integer.value[0]); + + snd_ivtv_lock(itvsc); + ret = v4l2_subdev_call(itv->sd_audio, core, g_ctrl, &vctrl); + snd_ivtv_unlock(itvsc); + + if (!ret) + uctl->value.integer.value[0] = cx25840_vol_to_dB(vctrl.value); + return ret; +} + +static int snd_ivtv_mixer_tv_vol_put(struct snd_kcontrol *kctl, + struct snd_ctl_elem_value *uctl) +{ + struct snd_ivtv_card *itvsc = snd_kcontrol_chip(kctl); + struct ivtv *itv = to_ivtv(itvsc->v4l2_dev); + struct v4l2_control vctrl; + int ret; + + vctrl.id = V4L2_CID_AUDIO_VOLUME; + vctrl.value = dB_to_cx25840_vol(uctl->value.integer.value[0]); + + snd_ivtv_lock(itvsc); + + /* Fetch current state */ + ret = v4l2_subdev_call(itv->sd_audio, core, g_ctrl, &vctrl); + + if (ret || + (cx25840_vol_to_dB(vctrl.value) != uctl->value.integer.value[0])) { + + /* Set, if needed */ + vctrl.value = dB_to_cx25840_vol(uctl->value.integer.value[0]); + ret = v4l2_subdev_call(itv->sd_audio, core, s_ctrl, &vctrl); + if (!ret) + ret = 1; /* Indicate control was changed w/o error */ + } + snd_ivtv_unlock(itvsc); + + return ret; +} + + +/* This is a bit of overkill, the slider is already in dB internally */ +static DECLARE_TLV_DB_SCALE(snd_ivtv_mixer_tv_vol_db_scale, -9600, 100, 0); + +static struct snd_kcontrol_new snd_ivtv_mixer_tv_vol __initdata = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Analog TV Capture Volume", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ, + .info = snd_ivtv_mixer_tv_volume_info, + .get = snd_ivtv_mixer_tv_volume_get, + .put = snd_ivtv_mixer_tv_volume_put, + .tlv.p = snd_ivtv_mixer_tv_vol_db_scale +}; + +/* FIXME - add mute switch and balance, bass, treble sliders: + V4L2_CID_AUDIO_MUTE + + V4L2_CID_AUDIO_BALANCE + + V4L2_CID_AUDIO_BASS + V4L2_CID_AUDIO_TREBLE +*/ + +/* FIXME - add stereo, lang1, lang2, mono menu */ +/* FIXME - add I2S volume */ + +int __init snd_ivtv_mixer_create(struct snd_ivtv_card *itvsc) +{ + struct v4l2_device *v4l2_dev = itvsc->v4l2_dev; + struct snd_card *sc = itvsc->sc; + int ret; + + strlcpy(sc->mixername, "CX2341[56] Mixer", sizeof(sc->mixername)); + + ret = snd_ctl_add(sc, snd_ctl_new1(snd_ivtv_mixer_tv_vol, itvsc)); + if (ret) { + IVTV_ALSA_WARN("%s: failed to add %s control, err %d\n", + __func__, snd_ivtv_mixer_tv_vol.name, ret); + } + return ret; +} diff --git a/drivers/media/pci/ivtv/ivtv-alsa-mixer.h b/drivers/media/pci/ivtv/ivtv-alsa-mixer.h new file mode 100644 index 000000000000..cdde36704d53 --- /dev/null +++ b/drivers/media/pci/ivtv/ivtv-alsa-mixer.h @@ -0,0 +1,23 @@ +/* + * ALSA mixer controls for the + * ALSA interface to ivtv PCM capture streams + * + * Copyright (C) 2009,2012 Andy Walls <awalls@md.metrocast.net> + * + * 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 + */ + +int __init snd_ivtv_mixer_create(struct snd_ivtv_card *itvsc); diff --git a/drivers/media/pci/ivtv/ivtv-alsa-pcm.c b/drivers/media/pci/ivtv/ivtv-alsa-pcm.c new file mode 100644 index 000000000000..f7022bd58ffd --- /dev/null +++ b/drivers/media/pci/ivtv/ivtv-alsa-pcm.c @@ -0,0 +1,356 @@ +/* + * ALSA PCM device for the + * ALSA interface to ivtv PCM capture streams + * + * Copyright (C) 2009,2012 Andy Walls <awalls@md.metrocast.net> + * Copyright (C) 2009 Devin Heitmueller <dheitmueller@kernellabs.com> + * + * Portions of this work were sponsored by ONELAN Limited for the cx18 driver + * + * 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 + */ + +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/vmalloc.h> + +#include <media/v4l2-device.h> + +#include <sound/core.h> +#include <sound/pcm.h> + +#include "ivtv-driver.h" +#include "ivtv-queue.h" +#include "ivtv-streams.h" +#include "ivtv-fileops.h" +#include "ivtv-alsa.h" + +static unsigned int pcm_debug; +module_param(pcm_debug, int, 0644); +MODULE_PARM_DESC(pcm_debug, "enable debug messages for pcm"); + +#define dprintk(fmt, arg...) \ + do { \ + if (pcm_debug) \ + pr_info("ivtv-alsa-pcm %s: " fmt, __func__, ##arg); \ + } while (0) + +static struct snd_pcm_hardware snd_ivtv_hw_capture = { + .info = SNDRV_PCM_INFO_BLOCK_TRANSFER | + SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_MMAP_VALID, + + .formats = SNDRV_PCM_FMTBIT_S16_LE, + + .rates = SNDRV_PCM_RATE_48000, + + .rate_min = 48000, + .rate_max = 48000, + .channels_min = 2, + .channels_max = 2, + .buffer_bytes_max = 62720 * 8, /* just about the value in usbaudio.c */ + .period_bytes_min = 64, /* 12544/2, */ + .period_bytes_max = 12544, + .periods_min = 2, + .periods_max = 98, /* 12544, */ +}; + +void ivtv_alsa_announce_pcm_data(struct snd_ivtv_card *itvsc, u8 *pcm_data, + size_t num_bytes) +{ + struct snd_pcm_substream *substream; + struct snd_pcm_runtime *runtime; + unsigned int oldptr; + unsigned int stride; + int period_elapsed = 0; + int length; + + dprintk("ivtv alsa announce ptr=%p data=%p num_bytes=%zd\n", itvsc, + pcm_data, num_bytes); + + substream = itvsc->capture_pcm_substream; + if (substream == NULL) { + dprintk("substream was NULL\n"); + return; + } + + runtime = substream->runtime; + if (runtime == NULL) { + dprintk("runtime was NULL\n"); + return; + } + + stride = runtime->frame_bits >> 3; + if (stride == 0) { + dprintk("stride is zero\n"); + return; + } + + length = num_bytes / stride; + if (length == 0) { + dprintk("%s: length was zero\n", __func__); + return; + } + + if (runtime->dma_area == NULL) { + dprintk("dma area was NULL - ignoring\n"); + return; + } + + oldptr = itvsc->hwptr_done_capture; + if (oldptr + length >= runtime->buffer_size) { + unsigned int cnt = + runtime->buffer_size - oldptr; + memcpy(runtime->dma_area + oldptr * stride, pcm_data, + cnt * stride); + memcpy(runtime->dma_area, pcm_data + cnt * stride, + length * stride - cnt * stride); + } else { + memcpy(runtime->dma_area + oldptr * stride, pcm_data, + length * stride); + } + snd_pcm_stream_lock(substream); + + itvsc->hwptr_done_capture += length; + if (itvsc->hwptr_done_capture >= + runtime->buffer_size) + itvsc->hwptr_done_capture -= + runtime->buffer_size; + + itvsc->capture_transfer_done += length; + if (itvsc->capture_transfer_done >= + runtime->period_size) { + itvsc->capture_transfer_done -= + runtime->period_size; + period_elapsed = 1; + } + + snd_pcm_stream_unlock(substream); + + if (period_elapsed) + snd_pcm_period_elapsed(substream); +} + +static int snd_ivtv_pcm_capture_open(struct snd_pcm_substream *substream) +{ + struct snd_ivtv_card *itvsc = snd_pcm_substream_chip(substream); + struct snd_pcm_runtime *runtime = substream->runtime; + struct v4l2_device *v4l2_dev = itvsc->v4l2_dev; + struct ivtv *itv = to_ivtv(v4l2_dev); + struct ivtv_stream *s; + struct ivtv_open_id item; + int ret; + + /* Instruct the CX2341[56] to start sending packets */ + snd_ivtv_lock(itvsc); + s = &itv->streams[IVTV_ENC_STREAM_TYPE_PCM]; + + v4l2_fh_init(&item.fh, s->vdev); + item.itv = itv; + item.type = s->type; + + /* See if the stream is available */ + if (ivtv_claim_stream(&item, item.type)) { + /* No, it's already in use */ + snd_ivtv_unlock(itvsc); + return -EBUSY; + } + + if (test_bit(IVTV_F_S_STREAMOFF, &s->s_flags) || + test_and_set_bit(IVTV_F_S_STREAMING, &s->s_flags)) { + /* We're already streaming. No additional action required */ + snd_ivtv_unlock(itvsc); + return 0; + } + + + runtime->hw = snd_ivtv_hw_capture; + snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); + itvsc->capture_pcm_substream = substream; + runtime->private_data = itv; + + itv->pcm_announce_callback = ivtv_alsa_announce_pcm_data; + + /* Not currently streaming, so start it up */ + set_bit(IVTV_F_S_STREAMING, &s->s_flags); + ret = ivtv_start_v4l2_encode_stream(s); + snd_ivtv_unlock(itvsc); + + return ret; +} + +static int snd_ivtv_pcm_capture_close(struct snd_pcm_substream *substream) +{ + struct snd_ivtv_card *itvsc = snd_pcm_substream_chip(substream); + struct v4l2_device *v4l2_dev = itvsc->v4l2_dev; + struct ivtv *itv = to_ivtv(v4l2_dev); + struct ivtv_stream *s; + + /* Instruct the ivtv to stop sending packets */ + snd_ivtv_lock(itvsc); + s = &itv->streams[IVTV_ENC_STREAM_TYPE_PCM]; + ivtv_stop_v4l2_encode_stream(s, 0); + clear_bit(IVTV_F_S_STREAMING, &s->s_flags); + + ivtv_release_stream(s); + + itv->pcm_announce_callback = NULL; + snd_ivtv_unlock(itvsc); + + return 0; +} + +static int snd_ivtv_pcm_ioctl(struct snd_pcm_substream *substream, + unsigned int cmd, void *arg) +{ + struct snd_ivtv_card *itvsc = snd_pcm_substream_chip(substream); + int ret; + + snd_ivtv_lock(itvsc); + ret = snd_pcm_lib_ioctl(substream, cmd, arg); + snd_ivtv_unlock(itvsc); + return ret; +} + + +static int snd_pcm_alloc_vmalloc_buffer(struct snd_pcm_substream *subs, + size_t size) +{ + struct snd_pcm_runtime *runtime = subs->runtime; + + dprintk("Allocating vbuffer\n"); + if (runtime->dma_area) { + if (runtime->dma_bytes > size) + return 0; + + vfree(runtime->dma_area); + } + runtime->dma_area = vmalloc(size); + if (!runtime->dma_area) + return -ENOMEM; + + runtime->dma_bytes = size; + + return 0; +} + +static int snd_ivtv_pcm_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + dprintk("%s called\n", __func__); + + return snd_pcm_alloc_vmalloc_buffer(substream, + params_buffer_bytes(params)); +} + +static int snd_ivtv_pcm_hw_free(struct snd_pcm_substream *substream) +{ + struct snd_ivtv_card *itvsc = snd_pcm_substream_chip(substream); + unsigned long flags; + + spin_lock_irqsave(&itvsc->slock, flags); + if (substream->runtime->dma_area) { + dprintk("freeing pcm capture region\n"); + vfree(substream->runtime->dma_area); + substream->runtime->dma_area = NULL; + } + spin_unlock_irqrestore(&itvsc->slock, flags); + + return 0; +} + +static int snd_ivtv_pcm_prepare(struct snd_pcm_substream *substream) +{ + struct snd_ivtv_card *itvsc = snd_pcm_substream_chip(substream); + + itvsc->hwptr_done_capture = 0; + itvsc->capture_transfer_done = 0; + + return 0; +} + +static int snd_ivtv_pcm_trigger(struct snd_pcm_substream *substream, int cmd) +{ + return 0; +} + +static +snd_pcm_uframes_t snd_ivtv_pcm_pointer(struct snd_pcm_substream *substream) +{ + unsigned long flags; + snd_pcm_uframes_t hwptr_done; + struct snd_ivtv_card *itvsc = snd_pcm_substream_chip(substream); + + spin_lock_irqsave(&itvsc->slock, flags); + hwptr_done = itvsc->hwptr_done_capture; + spin_unlock_irqrestore(&itvsc->slock, flags); + + return hwptr_done; +} + +static struct page *snd_pcm_get_vmalloc_page(struct snd_pcm_substream *subs, + unsigned long offset) +{ + void *pageptr = subs->runtime->dma_area + offset; + + return vmalloc_to_page(pageptr); +} + +static struct snd_pcm_ops snd_ivtv_pcm_capture_ops = { + .open = snd_ivtv_pcm_capture_open, + .close = snd_ivtv_pcm_capture_close, + .ioctl = snd_ivtv_pcm_ioctl, + .hw_params = snd_ivtv_pcm_hw_params, + .hw_free = snd_ivtv_pcm_hw_free, + .prepare = snd_ivtv_pcm_prepare, + .trigger = snd_ivtv_pcm_trigger, + .pointer = snd_ivtv_pcm_pointer, + .page = snd_pcm_get_vmalloc_page, +}; + +int snd_ivtv_pcm_create(struct snd_ivtv_card *itvsc) +{ + struct snd_pcm *sp; + struct snd_card *sc = itvsc->sc; + struct v4l2_device *v4l2_dev = itvsc->v4l2_dev; + struct ivtv *itv = to_ivtv(v4l2_dev); + int ret; + + ret = snd_pcm_new(sc, "CX2341[56] PCM", + 0, /* PCM device 0, the only one for this card */ + 0, /* 0 playback substreams */ + 1, /* 1 capture substream */ + &sp); + if (ret) { + IVTV_ALSA_ERR("%s: snd_ivtv_pcm_create() failed with err %d\n", + __func__, ret); + goto err_exit; + } + + spin_lock_init(&itvsc->slock); + + snd_pcm_set_ops(sp, SNDRV_PCM_STREAM_CAPTURE, + &snd_ivtv_pcm_capture_ops); + sp->info_flags = 0; + sp->private_data = itvsc; + strlcpy(sp->name, itv->card_name, sizeof(sp->name)); + + return 0; + +err_exit: + return ret; +} diff --git a/drivers/media/pci/ivtv/ivtv-alsa-pcm.h b/drivers/media/pci/ivtv/ivtv-alsa-pcm.h new file mode 100644 index 000000000000..5ab18319ea4d --- /dev/null +++ b/drivers/media/pci/ivtv/ivtv-alsa-pcm.h @@ -0,0 +1,27 @@ +/* + * ALSA PCM device for the + * ALSA interface to ivtv PCM capture streams + * + * Copyright (C) 2009,2012 Andy Walls <awalls@md.metrocast.net> + * + * 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 + */ + +int __init snd_ivtv_pcm_create(struct snd_ivtv_card *itvsc); + +/* Used by ivtv driver to announce the PCM data to the module */ +void ivtv_alsa_announce_pcm_data(struct snd_ivtv_card *card, u8 *pcm_data, + size_t num_bytes); diff --git a/drivers/media/pci/ivtv/ivtv-alsa.h b/drivers/media/pci/ivtv/ivtv-alsa.h new file mode 100644 index 000000000000..4a0d8f2c254d --- /dev/null +++ b/drivers/media/pci/ivtv/ivtv-alsa.h @@ -0,0 +1,75 @@ +/* + * ALSA interface to ivtv PCM capture streams + * + * Copyright (C) 2009,2012 Andy Walls <awalls@md.metrocast.net> + * Copyright (C) 2009 Devin Heitmueller <dheitmueller@kernellabs.com> + * + * 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 + */ + +struct snd_card; + +struct snd_ivtv_card { + struct v4l2_device *v4l2_dev; + struct snd_card *sc; + unsigned int capture_transfer_done; + unsigned int hwptr_done_capture; + struct snd_pcm_substream *capture_pcm_substream; + spinlock_t slock; +}; + +extern int ivtv_alsa_debug; + +/* + * File operations that manipulate the encoder or video or audio subdevices + * need to be serialized. Use the same lock we use for v4l2 file ops. + */ +static inline void snd_ivtv_lock(struct snd_ivtv_card *itvsc) +{ + struct ivtv *itv = to_ivtv(itvsc->v4l2_dev); + mutex_lock(&itv->serialize_lock); +} + +static inline void snd_ivtv_unlock(struct snd_ivtv_card *itvsc) +{ + struct ivtv *itv = to_ivtv(itvsc->v4l2_dev); + mutex_unlock(&itv->serialize_lock); +} + +#define IVTV_ALSA_DBGFLG_WARN (1 << 0) +#define IVTV_ALSA_DBGFLG_INFO (1 << 1) + +#define IVTV_ALSA_DEBUG(x, type, fmt, args...) \ + do { \ + if ((x) & ivtv_alsa_debug) \ + pr_info("%s-alsa: " type ": " fmt, \ + v4l2_dev->name , ## args); \ + } while (0) + +#define IVTV_ALSA_DEBUG_WARN(fmt, args...) \ + IVTV_ALSA_DEBUG(IVTV_ALSA_DBGFLG_WARN, "warning", fmt , ## args) + +#define IVTV_ALSA_DEBUG_INFO(fmt, args...) \ + IVTV_ALSA_DEBUG(IVTV_ALSA_DBGFLG_INFO, "info", fmt , ## args) + +#define IVTV_ALSA_ERR(fmt, args...) \ + pr_err("%s-alsa: " fmt, v4l2_dev->name , ## args) + +#define IVTV_ALSA_WARN(fmt, args...) \ + pr_warn("%s-alsa: " fmt, v4l2_dev->name , ## args) + +#define IVTV_ALSA_INFO(fmt, args...) \ + pr_info("%s-alsa: " fmt, v4l2_dev->name , ## args) diff --git a/drivers/media/video/ivtv/ivtv-cards.c b/drivers/media/pci/ivtv/ivtv-cards.c index 145e4749a69d..145e4749a69d 100644 --- a/drivers/media/video/ivtv/ivtv-cards.c +++ b/drivers/media/pci/ivtv/ivtv-cards.c diff --git a/drivers/media/video/ivtv/ivtv-cards.h b/drivers/media/pci/ivtv/ivtv-cards.h index e6f5c02981f1..e6f5c02981f1 100644 --- a/drivers/media/video/ivtv/ivtv-cards.h +++ b/drivers/media/pci/ivtv/ivtv-cards.h diff --git a/drivers/media/video/ivtv/ivtv-controls.c b/drivers/media/pci/ivtv/ivtv-controls.c index c60424601cb9..c60424601cb9 100644 --- a/drivers/media/video/ivtv/ivtv-controls.c +++ b/drivers/media/pci/ivtv/ivtv-controls.c diff --git a/drivers/media/video/ivtv/ivtv-controls.h b/drivers/media/pci/ivtv/ivtv-controls.h index 3999e6358312..3999e6358312 100644 --- a/drivers/media/video/ivtv/ivtv-controls.h +++ b/drivers/media/pci/ivtv/ivtv-controls.h diff --git a/drivers/media/video/ivtv/ivtv-driver.c b/drivers/media/pci/ivtv/ivtv-driver.c index 5462ce2f60ea..74e9a5032364 100644 --- a/drivers/media/video/ivtv/ivtv-driver.c +++ b/drivers/media/pci/ivtv/ivtv-driver.c @@ -68,6 +68,10 @@ setting this to 1 you ensure that radio0 is now also radio1. */ int ivtv_first_minor; +/* Callback for registering extensions */ +int (*ivtv_ext_init)(struct ivtv *); +EXPORT_SYMBOL(ivtv_ext_init); + /* add your revision and whatnot here */ static struct pci_device_id ivtv_pci_tbl[] __devinitdata = { {PCI_VENDOR_ID_ICOMP, PCI_DEVICE_ID_IVTV15, @@ -279,6 +283,34 @@ MODULE_LICENSE("GPL"); MODULE_VERSION(IVTV_VERSION); +#if defined(CONFIG_MODULES) && defined(MODULE) +static void request_module_async(struct work_struct *work) +{ + struct ivtv *dev = container_of(work, struct ivtv, request_module_wk); + + /* Make sure ivtv-alsa module is loaded */ + request_module("ivtv-alsa"); + + /* Initialize ivtv-alsa for this instance of the cx18 device */ + if (ivtv_ext_init != NULL) + ivtv_ext_init(dev); +} + +static void request_modules(struct ivtv *dev) +{ + INIT_WORK(&dev->request_module_wk, request_module_async); + schedule_work(&dev->request_module_wk); +} + +static void flush_request_modules(struct ivtv *dev) +{ + flush_work_sync(&dev->request_module_wk); +} +#else +#define request_modules(dev) +#define flush_request_modules(dev) +#endif /* CONFIG_MODULES */ + void ivtv_clear_irq_mask(struct ivtv *itv, u32 mask) { itv->irqmask &= ~mask; @@ -1253,6 +1285,9 @@ static int __devinit ivtv_probe(struct pci_dev *pdev, goto free_streams; } IVTV_INFO("Initialized card: %s\n", itv->card_name); + + /* Load ivtv submodules (ivtv-alsa) */ + request_modules(itv); return 0; free_streams: @@ -1290,6 +1325,7 @@ int ivtv_init_on_first_open(struct ivtv *itv) int video_input; fh.itv = itv; + fh.type = IVTV_ENC_STREAM_TYPE_MPG; if (test_bit(IVTV_F_I_FAILED, &itv->i_flags)) return -ENXIO; @@ -1380,6 +1416,8 @@ static void ivtv_remove(struct pci_dev *pdev) IVTV_DEBUG_INFO("Removing card\n"); + flush_request_modules(itv); + if (test_bit(IVTV_F_I_INITED, &itv->i_flags)) { /* Stop all captures */ IVTV_DEBUG_INFO("Stopping all streams\n"); diff --git a/drivers/media/video/ivtv/ivtv-driver.h b/drivers/media/pci/ivtv/ivtv-driver.h index a7e00f8938f8..bc309f42c8ed 100644 --- a/drivers/media/video/ivtv/ivtv-driver.h +++ b/drivers/media/pci/ivtv/ivtv-driver.h @@ -259,6 +259,7 @@ struct ivtv_mailbox_data { #define IVTV_F_I_DEC_PAUSED 20 /* the decoder is paused */ #define IVTV_F_I_INITED 21 /* set after first open */ #define IVTV_F_I_FAILED 22 /* set if first open failed */ +#define IVTV_F_I_WORK_HANDLER_PCM 23 /* there is work to be done for PCM */ /* Event notifications */ #define IVTV_F_I_EV_DEC_STOPPED 28 /* decoder stopped event */ @@ -669,6 +670,13 @@ struct ivtv { atomic_t capturing; /* count number of active capture streams */ atomic_t decoding; /* count number of active decoding streams */ + /* ALSA interface for PCM capture stream */ + struct snd_ivtv_card *alsa; + void (*pcm_announce_callback)(struct snd_ivtv_card *card, u8 *pcm_data, + size_t num_bytes); + + /* Used for ivtv-alsa module loading */ + struct work_struct request_module_wk; /* Interrupts & DMA */ u32 irqmask; /* active interrupts */ @@ -752,6 +760,9 @@ static inline struct ivtv *to_ivtv(struct v4l2_device *v4l2_dev) return container_of(v4l2_dev, struct ivtv, v4l2_dev); } +/* ivtv extensions to be loaded */ +extern int (*ivtv_ext_init)(struct ivtv *); + /* Globals */ extern int ivtv_first_minor; diff --git a/drivers/media/video/ivtv/ivtv-fileops.c b/drivers/media/pci/ivtv/ivtv-fileops.c index 9ff69b5a87e2..9caffd8aa995 100644 --- a/drivers/media/video/ivtv/ivtv-fileops.c +++ b/drivers/media/pci/ivtv/ivtv-fileops.c @@ -41,7 +41,7 @@ associated VBI streams are also automatically claimed. Possible error returns: -EBUSY if someone else has claimed the stream or 0 on success. */ -static int ivtv_claim_stream(struct ivtv_open_id *id, int type) +int ivtv_claim_stream(struct ivtv_open_id *id, int type) { struct ivtv *itv = id->itv; struct ivtv_stream *s = &itv->streams[type]; @@ -96,6 +96,7 @@ static int ivtv_claim_stream(struct ivtv_open_id *id, int type) set_bit(IVTV_F_S_INTERNAL_USE, &s_vbi->s_flags); return 0; } +EXPORT_SYMBOL(ivtv_claim_stream); /* This function releases a previously claimed stream. It will take into account associated VBI streams. */ @@ -146,6 +147,7 @@ void ivtv_release_stream(struct ivtv_stream *s) clear_bit(IVTV_F_S_CLAIMED, &s_vbi->s_flags); ivtv_flush_queues(s_vbi); } +EXPORT_SYMBOL(ivtv_release_stream); static void ivtv_dualwatch(struct ivtv *itv) { @@ -433,7 +435,7 @@ int ivtv_start_capture(struct ivtv_open_id *id) s->type == IVTV_DEC_STREAM_TYPE_YUV || s->type == IVTV_DEC_STREAM_TYPE_VOUT) { /* you cannot read from these stream types. */ - return -EPERM; + return -EINVAL; } /* Try to claim this stream. */ @@ -505,14 +507,17 @@ ssize_t ivtv_v4l2_read(struct file * filp, char __user *buf, size_t count, loff_ struct ivtv_open_id *id = fh2id(filp->private_data); struct ivtv *itv = id->itv; struct ivtv_stream *s = &itv->streams[id->type]; - int rc; + ssize_t rc; IVTV_DEBUG_HI_FILE("read %zd bytes from %s\n", count, s->name); + if (mutex_lock_interruptible(&itv->serialize_lock)) + return -ERESTARTSYS; rc = ivtv_start_capture(id); - if (rc) - return rc; - return ivtv_read_pos(s, buf, count, pos, filp->f_flags & O_NONBLOCK); + if (!rc) + rc = ivtv_read_pos(s, buf, count, pos, filp->f_flags & O_NONBLOCK); + mutex_unlock(&itv->serialize_lock); + return rc; } int ivtv_start_decoding(struct ivtv_open_id *id, int speed) @@ -540,7 +545,7 @@ int ivtv_start_decoding(struct ivtv_open_id *id, int speed) return 0; } -ssize_t ivtv_v4l2_write(struct file *filp, const char __user *user_buf, size_t count, loff_t *pos) +static ssize_t ivtv_write(struct file *filp, const char __user *user_buf, size_t count, loff_t *pos) { struct ivtv_open_id *id = fh2id(filp->private_data); struct ivtv *itv = id->itv; @@ -559,7 +564,7 @@ ssize_t ivtv_v4l2_write(struct file *filp, const char __user *user_buf, size_t c s->type != IVTV_DEC_STREAM_TYPE_YUV && s->type != IVTV_DEC_STREAM_TYPE_VOUT) /* not decoder streams */ - return -EPERM; + return -EINVAL; /* Try to claim this stream */ if (ivtv_claim_stream(id, s->type)) @@ -712,6 +717,19 @@ retry: return bytes_written; } +ssize_t ivtv_v4l2_write(struct file *filp, const char __user *user_buf, size_t count, loff_t *pos) +{ + struct ivtv_open_id *id = fh2id(filp->private_data); + struct ivtv *itv = id->itv; + ssize_t res; + + if (mutex_lock_interruptible(&itv->serialize_lock)) + return -ERESTARTSYS; + res = ivtv_write(filp, user_buf, count, pos); + mutex_unlock(&itv->serialize_lock); + return res; +} + unsigned int ivtv_v4l2_dec_poll(struct file *filp, poll_table *wait) { struct ivtv_open_id *id = fh2id(filp->private_data); @@ -757,10 +775,13 @@ unsigned int ivtv_v4l2_enc_poll(struct file *filp, poll_table *wait) /* Start a capture if there is none */ if (!eof && !test_bit(IVTV_F_S_STREAMING, &s->s_flags) && + s->type != IVTV_ENC_STREAM_TYPE_RAD && (req_events & (POLLIN | POLLRDNORM))) { int rc; + mutex_lock(&itv->serialize_lock); rc = ivtv_start_capture(id); + mutex_unlock(&itv->serialize_lock); if (rc) { IVTV_DEBUG_INFO("Could not start capture for %s (%d)\n", s->name, rc); @@ -863,6 +884,8 @@ int ivtv_v4l2_close(struct file *filp) IVTV_DEBUG_FILE("close %s\n", s->name); + mutex_lock(&itv->serialize_lock); + /* Stop radio */ if (id->type == IVTV_ENC_STREAM_TYPE_RAD && v4l2_fh_is_singular_file(filp)) { @@ -892,10 +915,8 @@ int ivtv_v4l2_close(struct file *filp) v4l2_fh_exit(fh); /* Easy case first: this stream was never claimed by us */ - if (s->fh != &id->fh) { - kfree(id); - return 0; - } + if (s->fh != &id->fh) + goto close_done; /* 'Unclaim' this stream */ @@ -913,11 +934,13 @@ int ivtv_v4l2_close(struct file *filp) } else { ivtv_stop_capture(id, 0); } +close_done: kfree(id); + mutex_unlock(&itv->serialize_lock); return 0; } -int ivtv_v4l2_open(struct file *filp) +static int ivtv_open(struct file *filp) { struct video_device *vdev = video_devdata(filp); struct ivtv_stream *s = video_get_drvdata(vdev); @@ -1020,6 +1043,18 @@ int ivtv_v4l2_open(struct file *filp) return 0; } +int ivtv_v4l2_open(struct file *filp) +{ + struct video_device *vdev = video_devdata(filp); + int res; + + if (mutex_lock_interruptible(vdev->lock)) + return -ERESTARTSYS; + res = ivtv_open(filp); + mutex_unlock(vdev->lock); + return res; +} + void ivtv_mute(struct ivtv *itv) { if (atomic_read(&itv->capturing)) diff --git a/drivers/media/video/ivtv/ivtv-fileops.h b/drivers/media/pci/ivtv/ivtv-fileops.h index 049a2923965d..5e08800772ca 100644 --- a/drivers/media/video/ivtv/ivtv-fileops.h +++ b/drivers/media/pci/ivtv/ivtv-fileops.h @@ -37,8 +37,8 @@ void ivtv_mute(struct ivtv *itv); void ivtv_unmute(struct ivtv *itv); /* Utilities */ - -/* Release a previously claimed stream. */ +/* Shared with ivtv-alsa module */ +int ivtv_claim_stream(struct ivtv_open_id *id, int type); void ivtv_release_stream(struct ivtv_stream *s); #endif diff --git a/drivers/media/video/ivtv/ivtv-firmware.c b/drivers/media/pci/ivtv/ivtv-firmware.c index 02c5adebf517..6ec7705af555 100644 --- a/drivers/media/video/ivtv/ivtv-firmware.c +++ b/drivers/media/pci/ivtv/ivtv-firmware.c @@ -396,3 +396,7 @@ int ivtv_firmware_check(struct ivtv *itv, char *where) return res; } + +MODULE_FIRMWARE(CX2341X_FIRM_ENC_FILENAME); +MODULE_FIRMWARE(CX2341X_FIRM_DEC_FILENAME); +MODULE_FIRMWARE(IVTV_DECODE_INIT_MPEG_FILENAME); diff --git a/drivers/media/video/ivtv/ivtv-firmware.h b/drivers/media/pci/ivtv/ivtv-firmware.h index 52bb4e5598fd..52bb4e5598fd 100644 --- a/drivers/media/video/ivtv/ivtv-firmware.h +++ b/drivers/media/pci/ivtv/ivtv-firmware.h diff --git a/drivers/media/video/ivtv/ivtv-gpio.c b/drivers/media/pci/ivtv/ivtv-gpio.c index 8f0d07789053..8f0d07789053 100644 --- a/drivers/media/video/ivtv/ivtv-gpio.c +++ b/drivers/media/pci/ivtv/ivtv-gpio.c diff --git a/drivers/media/video/ivtv/ivtv-gpio.h b/drivers/media/pci/ivtv/ivtv-gpio.h index 0b5d19c8ecb4..0b5d19c8ecb4 100644 --- a/drivers/media/video/ivtv/ivtv-gpio.h +++ b/drivers/media/pci/ivtv/ivtv-gpio.h diff --git a/drivers/media/video/ivtv/ivtv-i2c.c b/drivers/media/pci/ivtv/ivtv-i2c.c index d47f41a0ef66..d47f41a0ef66 100644 --- a/drivers/media/video/ivtv/ivtv-i2c.c +++ b/drivers/media/pci/ivtv/ivtv-i2c.c diff --git a/drivers/media/video/ivtv/ivtv-i2c.h b/drivers/media/pci/ivtv/ivtv-i2c.h index 7b9ec1cfeb80..7b9ec1cfeb80 100644 --- a/drivers/media/video/ivtv/ivtv-i2c.h +++ b/drivers/media/pci/ivtv/ivtv-i2c.h diff --git a/drivers/media/video/ivtv/ivtv-ioctl.c b/drivers/media/pci/ivtv/ivtv-ioctl.c index 32a591062d0b..949ae230e119 100644 --- a/drivers/media/video/ivtv/ivtv-ioctl.c +++ b/drivers/media/pci/ivtv/ivtv-ioctl.c @@ -289,6 +289,8 @@ static int ivtv_video_command(struct ivtv *itv, struct ivtv_open_id *id, case V4L2_DEC_CMD_PAUSE: dc->flags &= V4L2_DEC_CMD_PAUSE_TO_BLACK; if (try) break; + if (!atomic_read(&itv->decoding)) + return -EPERM; if (itv->output_mode != OUT_MPG) return -EBUSY; if (atomic_read(&itv->decoding) > 0) { @@ -301,6 +303,8 @@ static int ivtv_video_command(struct ivtv *itv, struct ivtv_open_id *id, case V4L2_DEC_CMD_RESUME: dc->flags = 0; if (try) break; + if (!atomic_read(&itv->decoding)) + return -EPERM; if (itv->output_mode != OUT_MPG) return -EBUSY; if (test_and_clear_bit(IVTV_F_I_DEC_PAUSED, &itv->i_flags)) { @@ -326,6 +330,7 @@ static int ivtv_g_fmt_sliced_vbi_out(struct file *file, void *fh, struct v4l2_fo if (!(itv->v4l2_cap & V4L2_CAP_SLICED_VBI_OUTPUT)) return -EINVAL; vbifmt->io_size = sizeof(struct v4l2_sliced_vbi_data) * 36; + memset(vbifmt->service_lines, 0, sizeof(vbifmt->service_lines)); if (itv->is_60hz) { vbifmt->service_lines[0][21] = V4L2_SLICED_CAPTION_525; vbifmt->service_lines[1][21] = V4L2_SLICED_CAPTION_525; @@ -393,6 +398,7 @@ static int ivtv_g_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_fo vbifmt->service_set = itv->is_50hz ? V4L2_SLICED_VBI_625 : V4L2_SLICED_VBI_525; ivtv_expand_service_set(vbifmt, itv->is_50hz); + vbifmt->service_set = ivtv_get_service_set(vbifmt); return 0; } @@ -784,7 +790,7 @@ static int ivtv_g_audio(struct file *file, void *fh, struct v4l2_audio *vin) return ivtv_get_audio_input(itv, vin->index, vin); } -static int ivtv_s_audio(struct file *file, void *fh, struct v4l2_audio *vout) +static int ivtv_s_audio(struct file *file, void *fh, const struct v4l2_audio *vout) { struct ivtv *itv = fh2id(fh)->itv; @@ -813,11 +819,13 @@ static int ivtv_g_audout(struct file *file, void *fh, struct v4l2_audioout *vin) return ivtv_get_audio_output(itv, vin->index, vin); } -static int ivtv_s_audout(struct file *file, void *fh, struct v4l2_audioout *vout) +static int ivtv_s_audout(struct file *file, void *fh, const struct v4l2_audioout *vout) { struct ivtv *itv = fh2id(fh)->itv; - return ivtv_get_audio_output(itv, vout->index, vout); + if (itv->card->video_outputs == NULL || vout->index != 0) + return -EINVAL; + return 0; } static int ivtv_enum_input(struct file *file, void *fh, struct v4l2_input *vin) @@ -872,7 +880,7 @@ static int ivtv_cropcap(struct file *file, void *fh, struct v4l2_cropcap *cropca return 0; } -static int ivtv_s_crop(struct file *file, void *fh, struct v4l2_crop *crop) +static int ivtv_s_crop(struct file *file, void *fh, const struct v4l2_crop *crop) { struct ivtv_open_id *id = fh2id(fh); struct ivtv *itv = id->itv; @@ -920,51 +928,53 @@ static int ivtv_g_crop(struct file *file, void *fh, struct v4l2_crop *crop) static int ivtv_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdesc *fmt) { - static struct v4l2_fmtdesc formats[] = { - { 0, 0, 0, - "HM12 (YUV 4:2:0)", V4L2_PIX_FMT_HM12, - { 0, 0, 0, 0 } - }, - { 1, 0, V4L2_FMT_FLAG_COMPRESSED, - "MPEG", V4L2_PIX_FMT_MPEG, - { 0, 0, 0, 0 } - } + static const struct v4l2_fmtdesc hm12 = { + 0, V4L2_BUF_TYPE_VIDEO_CAPTURE, 0, + "HM12 (YUV 4:2:0)", V4L2_PIX_FMT_HM12, + { 0, 0, 0, 0 } + }; + static const struct v4l2_fmtdesc mpeg = { + 0, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FMT_FLAG_COMPRESSED, + "MPEG", V4L2_PIX_FMT_MPEG, + { 0, 0, 0, 0 } }; - enum v4l2_buf_type type = fmt->type; + struct ivtv *itv = fh2id(fh)->itv; + struct ivtv_stream *s = &itv->streams[fh2id(fh)->type]; - if (fmt->index > 1) + if (fmt->index) + return -EINVAL; + if (s->type == IVTV_ENC_STREAM_TYPE_MPG) + *fmt = mpeg; + else if (s->type == IVTV_ENC_STREAM_TYPE_YUV) + *fmt = hm12; + else return -EINVAL; - - *fmt = formats[fmt->index]; - fmt->type = type; return 0; } static int ivtv_enum_fmt_vid_out(struct file *file, void *fh, struct v4l2_fmtdesc *fmt) { - struct ivtv *itv = fh2id(fh)->itv; - - static struct v4l2_fmtdesc formats[] = { - { 0, 0, 0, - "HM12 (YUV 4:2:0)", V4L2_PIX_FMT_HM12, - { 0, 0, 0, 0 } - }, - { 1, 0, V4L2_FMT_FLAG_COMPRESSED, - "MPEG", V4L2_PIX_FMT_MPEG, - { 0, 0, 0, 0 } - } + static const struct v4l2_fmtdesc hm12 = { + 0, V4L2_BUF_TYPE_VIDEO_OUTPUT, 0, + "HM12 (YUV 4:2:0)", V4L2_PIX_FMT_HM12, + { 0, 0, 0, 0 } + }; + static const struct v4l2_fmtdesc mpeg = { + 0, V4L2_BUF_TYPE_VIDEO_OUTPUT, V4L2_FMT_FLAG_COMPRESSED, + "MPEG", V4L2_PIX_FMT_MPEG, + { 0, 0, 0, 0 } }; - enum v4l2_buf_type type = fmt->type; + struct ivtv *itv = fh2id(fh)->itv; + struct ivtv_stream *s = &itv->streams[fh2id(fh)->type]; - if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) + if (fmt->index) return -EINVAL; - - if (fmt->index > 1) + if (s->type == IVTV_DEC_STREAM_TYPE_MPG) + *fmt = mpeg; + else if (s->type == IVTV_DEC_STREAM_TYPE_YUV) + *fmt = hm12; + else return -EINVAL; - - *fmt = formats[fmt->index]; - fmt->type = type; - return 0; } @@ -980,6 +990,8 @@ static int ivtv_g_input(struct file *file, void *fh, unsigned int *i) int ivtv_s_input(struct file *file, void *fh, unsigned int inp) { struct ivtv *itv = fh2id(fh)->itv; + v4l2_std_id std; + int i; if (inp < 0 || inp >= itv->nof_inputs) return -EINVAL; @@ -1001,6 +1013,13 @@ int ivtv_s_input(struct file *file, void *fh, unsigned int inp) input type. */ itv->audio_input = itv->card->video_inputs[inp].audio_index; + if (itv->card->video_inputs[inp].video_type == IVTV_CARD_INPUT_VID_TUNER) + std = itv->tuner_std; + else + std = V4L2_STD_ALL; + for (i = 0; i <= IVTV_ENC_STREAM_TYPE_VBI; i++) + itv->streams[i].vdev->tvnorms = std; + /* prevent others from messing with the streams until we're finished changing inputs. */ ivtv_mute(itv); @@ -1048,7 +1067,10 @@ static int ivtv_s_output(struct file *file, void *fh, unsigned int outp) static int ivtv_g_frequency(struct file *file, void *fh, struct v4l2_frequency *vf) { struct ivtv *itv = fh2id(fh)->itv; + struct ivtv_stream *s = &itv->streams[fh2id(fh)->type]; + if (s->vdev->vfl_dir) + return -ENOTTY; if (vf->tuner != 0) return -EINVAL; @@ -1059,7 +1081,10 @@ static int ivtv_g_frequency(struct file *file, void *fh, struct v4l2_frequency * int ivtv_s_frequency(struct file *file, void *fh, struct v4l2_frequency *vf) { struct ivtv *itv = fh2id(fh)->itv; + struct ivtv_stream *s = &itv->streams[fh2id(fh)->type]; + if (s->vdev->vfl_dir) + return -ENOTTY; if (vf->tuner != 0) return -EINVAL; @@ -1247,6 +1272,9 @@ static int ivtv_g_enc_index(struct file *file, void *fh, struct v4l2_enc_idx *id if (entries > V4L2_ENC_IDX_ENTRIES) entries = V4L2_ENC_IDX_ENTRIES; idx->entries = 0; + idx->entries_cap = IVTV_MAX_PGM_INDEX; + if (!atomic_read(&itv->capturing)) + return 0; for (i = 0; i < entries; i++) { *e = itv->pgm_info[(itv->pgm_info_read_idx + i) % IVTV_MAX_PGM_INDEX]; if ((e->flags & V4L2_ENC_IDX_FRAME_MASK) <= V4L2_ENC_IDX_FRAME_B) { @@ -1427,7 +1455,7 @@ static int ivtv_g_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *fb) return 0; } -static int ivtv_s_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *fb) +static int ivtv_s_fbuf(struct file *file, void *fh, const struct v4l2_framebuffer *fb) { struct ivtv_open_id *id = fh2id(fh); struct ivtv *itv = id->itv; @@ -1444,7 +1472,7 @@ static int ivtv_s_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *fb) 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; - return ivtv_g_fbuf(file, fh, fb); + return 0; } static int ivtv_overlay(struct file *file, void *fh, unsigned int on) @@ -1460,7 +1488,7 @@ static int ivtv_overlay(struct file *file, void *fh, unsigned int on) return 0; } -static int ivtv_subscribe_event(struct v4l2_fh *fh, struct v4l2_event_subscription *sub) +static int ivtv_subscribe_event(struct v4l2_fh *fh, const struct v4l2_event_subscription *sub) { switch (sub->type) { case V4L2_EVENT_VSYNC: diff --git a/drivers/media/video/ivtv/ivtv-ioctl.h b/drivers/media/pci/ivtv/ivtv-ioctl.h index 7c553d16579b..7c553d16579b 100644 --- a/drivers/media/video/ivtv/ivtv-ioctl.h +++ b/drivers/media/pci/ivtv/ivtv-ioctl.h diff --git a/drivers/media/video/ivtv/ivtv-irq.c b/drivers/media/pci/ivtv/ivtv-irq.c index 1b3b9578bf47..19a7c9b990a3 100644 --- a/drivers/media/video/ivtv/ivtv-irq.c +++ b/drivers/media/pci/ivtv/ivtv-irq.c @@ -38,6 +38,34 @@ static const int ivtv_stream_map[] = { IVTV_ENC_STREAM_TYPE_VBI, }; +static void ivtv_pcm_work_handler(struct ivtv *itv) +{ + struct ivtv_stream *s = &itv->streams[IVTV_ENC_STREAM_TYPE_PCM]; + struct ivtv_buffer *buf; + + /* Pass the PCM data to ivtv-alsa */ + + while (1) { + /* + * Users should not be using both the ALSA and V4L2 PCM audio + * capture interfaces at the same time. If the user is doing + * this, there maybe a buffer in q_io to grab, use, and put + * back in rotation. + */ + buf = ivtv_dequeue(s, &s->q_io); + if (buf == NULL) + buf = ivtv_dequeue(s, &s->q_full); + if (buf == NULL) + break; + + if (buf->readpos < buf->bytesused) + itv->pcm_announce_callback(itv->alsa, + (u8 *)(buf->buf + buf->readpos), + (size_t)(buf->bytesused - buf->readpos)); + + ivtv_enqueue(s, buf, &s->q_free); + } +} static void ivtv_pio_work_handler(struct ivtv *itv) { @@ -83,6 +111,9 @@ void ivtv_irq_work_handler(struct kthread_work *work) if (test_and_clear_bit(IVTV_F_I_WORK_HANDLER_YUV, &itv->i_flags)) ivtv_yuv_work_handler(itv); + + if (test_and_clear_bit(IVTV_F_I_WORK_HANDLER_PCM, &itv->i_flags)) + ivtv_pcm_work_handler(itv); } /* Determine the required DMA size, setup enough buffers in the predma queue and @@ -293,7 +324,26 @@ static void dma_post(struct ivtv_stream *s) return; } } + ivtv_queue_move(s, &s->q_dma, NULL, &s->q_full, s->q_dma.bytesused); + + if (s->type == IVTV_ENC_STREAM_TYPE_PCM && + itv->pcm_announce_callback != NULL) { + /* + * Set up the work handler to pass the data to ivtv-alsa. + * + * We just use q_full and let the work handler race with users + * making ivtv-fileops.c calls on the PCM device node. + * + * Users should not be using both the ALSA and V4L2 PCM audio + * capture interfaces at the same time. If the user does this, + * fragments of data will just go out each interface as they + * race for PCM data. + */ + set_bit(IVTV_F_I_WORK_HANDLER_PCM, &itv->i_flags); + set_bit(IVTV_F_I_HAVE_WORK, &itv->i_flags); + } + if (s->fh) wake_up(&s->waitq); } diff --git a/drivers/media/video/ivtv/ivtv-irq.h b/drivers/media/pci/ivtv/ivtv-irq.h index 1e84433737cc..1e84433737cc 100644 --- a/drivers/media/video/ivtv/ivtv-irq.h +++ b/drivers/media/pci/ivtv/ivtv-irq.h diff --git a/drivers/media/video/ivtv/ivtv-mailbox.c b/drivers/media/pci/ivtv/ivtv-mailbox.c index e3ce96763785..e3ce96763785 100644 --- a/drivers/media/video/ivtv/ivtv-mailbox.c +++ b/drivers/media/pci/ivtv/ivtv-mailbox.c diff --git a/drivers/media/video/ivtv/ivtv-mailbox.h b/drivers/media/pci/ivtv/ivtv-mailbox.h index 2c834d2cb56f..2c834d2cb56f 100644 --- a/drivers/media/video/ivtv/ivtv-mailbox.h +++ b/drivers/media/pci/ivtv/ivtv-mailbox.h diff --git a/drivers/media/video/ivtv/ivtv-queue.c b/drivers/media/pci/ivtv/ivtv-queue.c index 7fde36e6d227..7fde36e6d227 100644 --- a/drivers/media/video/ivtv/ivtv-queue.c +++ b/drivers/media/pci/ivtv/ivtv-queue.c diff --git a/drivers/media/video/ivtv/ivtv-queue.h b/drivers/media/pci/ivtv/ivtv-queue.h index 91233839a26c..91233839a26c 100644 --- a/drivers/media/video/ivtv/ivtv-queue.h +++ b/drivers/media/pci/ivtv/ivtv-queue.h diff --git a/drivers/media/video/ivtv/ivtv-routing.c b/drivers/media/pci/ivtv/ivtv-routing.c index 8898c569a1c9..8898c569a1c9 100644 --- a/drivers/media/video/ivtv/ivtv-routing.c +++ b/drivers/media/pci/ivtv/ivtv-routing.c diff --git a/drivers/media/video/ivtv/ivtv-routing.h b/drivers/media/pci/ivtv/ivtv-routing.h index c72a9731ca01..c72a9731ca01 100644 --- a/drivers/media/video/ivtv/ivtv-routing.h +++ b/drivers/media/pci/ivtv/ivtv-routing.h diff --git a/drivers/media/video/ivtv/ivtv-streams.c b/drivers/media/pci/ivtv/ivtv-streams.c index 87990c5f0910..70dad588a677 100644 --- a/drivers/media/video/ivtv/ivtv-streams.c +++ b/drivers/media/pci/ivtv/ivtv-streams.c @@ -65,6 +65,14 @@ static const struct v4l2_file_operations ivtv_v4l2_dec_fops = { .poll = ivtv_v4l2_dec_poll, }; +static const struct v4l2_file_operations ivtv_v4l2_radio_fops = { + .owner = THIS_MODULE, + .open = ivtv_v4l2_open, + .unlocked_ioctl = video_ioctl2, + .release = ivtv_v4l2_close, + .poll = ivtv_v4l2_enc_poll, +}; + #define IVTV_V4L2_DEC_MPG_OFFSET 16 /* offset from 0 to register decoder mpg v4l2 minors on */ #define IVTV_V4L2_ENC_PCM_OFFSET 24 /* offset from 0 to register pcm v4l2 minors on */ #define IVTV_V4L2_ENC_YUV_OFFSET 32 /* offset from 0 to register yuv v4l2 minors on */ @@ -77,14 +85,13 @@ static struct { int vfl_type; int num_offset; int dma, pio; - enum v4l2_buf_type buf_type; u32 v4l2_caps; const struct v4l2_file_operations *fops; } ivtv_stream_info[] = { { /* IVTV_ENC_STREAM_TYPE_MPG */ "encoder MPG", VFL_TYPE_GRABBER, 0, - PCI_DMA_FROMDEVICE, 0, V4L2_BUF_TYPE_VIDEO_CAPTURE, + PCI_DMA_FROMDEVICE, 0, V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_TUNER | V4L2_CAP_AUDIO | V4L2_CAP_READWRITE, &ivtv_v4l2_enc_fops @@ -92,7 +99,7 @@ static struct { { /* IVTV_ENC_STREAM_TYPE_YUV */ "encoder YUV", VFL_TYPE_GRABBER, IVTV_V4L2_ENC_YUV_OFFSET, - PCI_DMA_FROMDEVICE, 0, V4L2_BUF_TYPE_VIDEO_CAPTURE, + PCI_DMA_FROMDEVICE, 0, V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_TUNER | V4L2_CAP_AUDIO | V4L2_CAP_READWRITE, &ivtv_v4l2_enc_fops @@ -100,7 +107,7 @@ static struct { { /* IVTV_ENC_STREAM_TYPE_VBI */ "encoder VBI", VFL_TYPE_VBI, 0, - PCI_DMA_FROMDEVICE, 0, V4L2_BUF_TYPE_VBI_CAPTURE, + PCI_DMA_FROMDEVICE, 0, V4L2_CAP_VBI_CAPTURE | V4L2_CAP_SLICED_VBI_CAPTURE | V4L2_CAP_TUNER | V4L2_CAP_AUDIO | V4L2_CAP_READWRITE, &ivtv_v4l2_enc_fops @@ -108,42 +115,42 @@ static struct { { /* IVTV_ENC_STREAM_TYPE_PCM */ "encoder PCM", VFL_TYPE_GRABBER, IVTV_V4L2_ENC_PCM_OFFSET, - PCI_DMA_FROMDEVICE, 0, V4L2_BUF_TYPE_PRIVATE, + PCI_DMA_FROMDEVICE, 0, V4L2_CAP_TUNER | V4L2_CAP_AUDIO | V4L2_CAP_READWRITE, &ivtv_v4l2_enc_fops }, { /* IVTV_ENC_STREAM_TYPE_RAD */ "encoder radio", VFL_TYPE_RADIO, 0, - PCI_DMA_NONE, 1, V4L2_BUF_TYPE_PRIVATE, + PCI_DMA_NONE, 1, V4L2_CAP_RADIO | V4L2_CAP_TUNER, - &ivtv_v4l2_enc_fops + &ivtv_v4l2_radio_fops }, { /* IVTV_DEC_STREAM_TYPE_MPG */ "decoder MPG", VFL_TYPE_GRABBER, IVTV_V4L2_DEC_MPG_OFFSET, - PCI_DMA_TODEVICE, 0, V4L2_BUF_TYPE_VIDEO_OUTPUT, + PCI_DMA_TODEVICE, 0, V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_AUDIO | V4L2_CAP_READWRITE, &ivtv_v4l2_dec_fops }, { /* IVTV_DEC_STREAM_TYPE_VBI */ "decoder VBI", VFL_TYPE_VBI, IVTV_V4L2_DEC_VBI_OFFSET, - PCI_DMA_NONE, 1, V4L2_BUF_TYPE_VBI_CAPTURE, + PCI_DMA_NONE, 1, V4L2_CAP_SLICED_VBI_CAPTURE | V4L2_CAP_READWRITE, &ivtv_v4l2_enc_fops }, { /* IVTV_DEC_STREAM_TYPE_VOUT */ "decoder VOUT", VFL_TYPE_VBI, IVTV_V4L2_DEC_VOUT_OFFSET, - PCI_DMA_NONE, 1, V4L2_BUF_TYPE_VBI_OUTPUT, + PCI_DMA_NONE, 1, V4L2_CAP_SLICED_VBI_OUTPUT | V4L2_CAP_AUDIO | V4L2_CAP_READWRITE, &ivtv_v4l2_dec_fops }, { /* IVTV_DEC_STREAM_TYPE_YUV */ "decoder YUV", VFL_TYPE_GRABBER, IVTV_V4L2_DEC_YUV_OFFSET, - PCI_DMA_TODEVICE, 0, V4L2_BUF_TYPE_VIDEO_OUTPUT, + PCI_DMA_TODEVICE, 0, V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_AUDIO | V4L2_CAP_READWRITE, &ivtv_v4l2_dec_fops } @@ -223,15 +230,27 @@ static int ivtv_prep_dev(struct ivtv *itv, int type) s->vdev->num = num; s->vdev->v4l2_dev = &itv->v4l2_dev; + if (ivtv_stream_info[type].v4l2_caps & + (V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_SLICED_VBI_OUTPUT)) + s->vdev->vfl_dir = VFL_DIR_TX; s->vdev->fops = ivtv_stream_info[type].fops; s->vdev->ctrl_handler = itv->v4l2_dev.ctrl_handler; s->vdev->release = video_device_release; s->vdev->tvnorms = V4L2_STD_ALL; s->vdev->lock = &itv->serialize_lock; - /* Locking in file operations other than ioctl should be done - by the driver, not the V4L2 core. - This driver needs auditing so that this flag can be removed. */ - set_bit(V4L2_FL_LOCK_ALL_FOPS, &s->vdev->flags); + if (s->type == IVTV_DEC_STREAM_TYPE_VBI) { + v4l2_disable_ioctl(s->vdev, VIDIOC_S_AUDIO); + v4l2_disable_ioctl(s->vdev, VIDIOC_G_AUDIO); + v4l2_disable_ioctl(s->vdev, VIDIOC_ENUMAUDIO); + v4l2_disable_ioctl(s->vdev, VIDIOC_ENUMINPUT); + v4l2_disable_ioctl(s->vdev, VIDIOC_S_INPUT); + v4l2_disable_ioctl(s->vdev, VIDIOC_G_INPUT); + v4l2_disable_ioctl(s->vdev, VIDIOC_S_FREQUENCY); + v4l2_disable_ioctl(s->vdev, VIDIOC_G_FREQUENCY); + v4l2_disable_ioctl(s->vdev, VIDIOC_S_TUNER); + v4l2_disable_ioctl(s->vdev, VIDIOC_G_TUNER); + v4l2_disable_ioctl(s->vdev, VIDIOC_S_STD); + } set_bit(V4L2_FL_USE_FH_PRIO, &s->vdev->flags); ivtv_set_funcs(s->vdev); return 0; @@ -633,6 +652,7 @@ int ivtv_start_v4l2_encode_stream(struct ivtv_stream *s) atomic_inc(&itv->capturing); return 0; } +EXPORT_SYMBOL(ivtv_start_v4l2_encode_stream); static int ivtv_setup_v4l2_decode_stream(struct ivtv_stream *s) { @@ -889,6 +909,7 @@ int ivtv_stop_v4l2_encode_stream(struct ivtv_stream *s, int gop_end) return 0; } +EXPORT_SYMBOL(ivtv_stop_v4l2_encode_stream); int ivtv_stop_v4l2_decode_stream(struct ivtv_stream *s, int flags, u64 pts) { diff --git a/drivers/media/video/ivtv/ivtv-streams.h b/drivers/media/pci/ivtv/ivtv-streams.h index a653a5136417..a653a5136417 100644 --- a/drivers/media/video/ivtv/ivtv-streams.h +++ b/drivers/media/pci/ivtv/ivtv-streams.h diff --git a/drivers/media/video/ivtv/ivtv-udma.c b/drivers/media/pci/ivtv/ivtv-udma.c index 7338cb2d0a38..7338cb2d0a38 100644 --- a/drivers/media/video/ivtv/ivtv-udma.c +++ b/drivers/media/pci/ivtv/ivtv-udma.c diff --git a/drivers/media/video/ivtv/ivtv-udma.h b/drivers/media/pci/ivtv/ivtv-udma.h index ee3c9efb5b72..ee3c9efb5b72 100644 --- a/drivers/media/video/ivtv/ivtv-udma.h +++ b/drivers/media/pci/ivtv/ivtv-udma.h diff --git a/drivers/media/video/ivtv/ivtv-vbi.c b/drivers/media/pci/ivtv/ivtv-vbi.c index 293db806d936..293db806d936 100644 --- a/drivers/media/video/ivtv/ivtv-vbi.c +++ b/drivers/media/pci/ivtv/ivtv-vbi.c diff --git a/drivers/media/video/ivtv/ivtv-vbi.h b/drivers/media/pci/ivtv/ivtv-vbi.h index 166dd0b75d0f..166dd0b75d0f 100644 --- a/drivers/media/video/ivtv/ivtv-vbi.h +++ b/drivers/media/pci/ivtv/ivtv-vbi.h diff --git a/drivers/media/video/ivtv/ivtv-version.h b/drivers/media/pci/ivtv/ivtv-version.h index a20f346fcad8..a20f346fcad8 100644 --- a/drivers/media/video/ivtv/ivtv-version.h +++ b/drivers/media/pci/ivtv/ivtv-version.h diff --git a/drivers/media/video/ivtv/ivtv-yuv.c b/drivers/media/pci/ivtv/ivtv-yuv.c index 2ad65eb29832..2ad65eb29832 100644 --- a/drivers/media/video/ivtv/ivtv-yuv.c +++ b/drivers/media/pci/ivtv/ivtv-yuv.c diff --git a/drivers/media/video/ivtv/ivtv-yuv.h b/drivers/media/pci/ivtv/ivtv-yuv.h index ca5173fbf006..ca5173fbf006 100644 --- a/drivers/media/video/ivtv/ivtv-yuv.h +++ b/drivers/media/pci/ivtv/ivtv-yuv.h diff --git a/drivers/media/video/ivtv/ivtvfb.c b/drivers/media/pci/ivtv/ivtvfb.c index 05b94aa8ba32..05b94aa8ba32 100644 --- a/drivers/media/video/ivtv/ivtvfb.c +++ b/drivers/media/pci/ivtv/ivtvfb.c diff --git a/drivers/media/dvb/mantis/Kconfig b/drivers/media/pci/mantis/Kconfig index a13a50503134..d3cc21633b94 100644 --- a/drivers/media/dvb/mantis/Kconfig +++ b/drivers/media/pci/mantis/Kconfig @@ -10,15 +10,15 @@ config MANTIS_CORE config DVB_MANTIS tristate "MANTIS based cards" depends on MANTIS_CORE && DVB_CORE && PCI && I2C - select DVB_MB86A16 if !DVB_FE_CUSTOMISE - select DVB_ZL10353 if !DVB_FE_CUSTOMISE - select DVB_STV0299 if !DVB_FE_CUSTOMISE - select DVB_LNBP21 if !DVB_FE_CUSTOMISE - select DVB_STB0899 if !DVB_FE_CUSTOMISE - select DVB_STB6100 if !DVB_FE_CUSTOMISE - select DVB_TDA665x if !DVB_FE_CUSTOMISE - select DVB_TDA10021 if !DVB_FE_CUSTOMISE - select DVB_TDA10023 if !DVB_FE_CUSTOMISE + select DVB_MB86A16 if MEDIA_SUBDRV_AUTOSELECT + select DVB_ZL10353 if MEDIA_SUBDRV_AUTOSELECT + select DVB_STV0299 if MEDIA_SUBDRV_AUTOSELECT + select DVB_LNBP21 if MEDIA_SUBDRV_AUTOSELECT + select DVB_STB0899 if MEDIA_SUBDRV_AUTOSELECT + select DVB_STB6100 if MEDIA_SUBDRV_AUTOSELECT + select DVB_TDA665x if MEDIA_SUBDRV_AUTOSELECT + select DVB_TDA10021 if MEDIA_SUBDRV_AUTOSELECT + select DVB_TDA10023 if MEDIA_SUBDRV_AUTOSELECT select DVB_PLL help Support for PCI cards based on the Mantis PCI bridge. @@ -29,7 +29,7 @@ config DVB_MANTIS config DVB_HOPPER tristate "HOPPER based cards" depends on MANTIS_CORE && DVB_CORE && PCI && I2C - select DVB_ZL10353 if !DVB_FE_CUSTOMISE + select DVB_ZL10353 if MEDIA_SUBDRV_AUTOSELECT select DVB_PLL help Support for PCI cards based on the Hopper PCI bridge. diff --git a/drivers/media/dvb/mantis/Makefile b/drivers/media/pci/mantis/Makefile index ec8116dcb368..f715051e4453 100644 --- a/drivers/media/dvb/mantis/Makefile +++ b/drivers/media/pci/mantis/Makefile @@ -25,4 +25,4 @@ obj-$(CONFIG_MANTIS_CORE) += mantis_core.o obj-$(CONFIG_DVB_MANTIS) += mantis.o obj-$(CONFIG_DVB_HOPPER) += hopper.o -ccflags-y += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/ +ccflags-y += -Idrivers/media/dvb-core/ -Idrivers/media/dvb-frontends/ diff --git a/drivers/media/dvb/mantis/hopper_cards.c b/drivers/media/pci/mantis/hopper_cards.c index cc0251e01077..cc0251e01077 100644 --- a/drivers/media/dvb/mantis/hopper_cards.c +++ b/drivers/media/pci/mantis/hopper_cards.c diff --git a/drivers/media/dvb/mantis/hopper_vp3028.c b/drivers/media/pci/mantis/hopper_vp3028.c index 68a29f8bdf73..68a29f8bdf73 100644 --- a/drivers/media/dvb/mantis/hopper_vp3028.c +++ b/drivers/media/pci/mantis/hopper_vp3028.c diff --git a/drivers/media/dvb/mantis/hopper_vp3028.h b/drivers/media/pci/mantis/hopper_vp3028.h index 57239498bc87..57239498bc87 100644 --- a/drivers/media/dvb/mantis/hopper_vp3028.h +++ b/drivers/media/pci/mantis/hopper_vp3028.h diff --git a/drivers/media/dvb/mantis/mantis_ca.c b/drivers/media/pci/mantis/mantis_ca.c index 3d7046909009..3d7046909009 100644 --- a/drivers/media/dvb/mantis/mantis_ca.c +++ b/drivers/media/pci/mantis/mantis_ca.c diff --git a/drivers/media/dvb/mantis/mantis_ca.h b/drivers/media/pci/mantis/mantis_ca.h index dc63e55f7eca..dc63e55f7eca 100644 --- a/drivers/media/dvb/mantis/mantis_ca.h +++ b/drivers/media/pci/mantis/mantis_ca.h diff --git a/drivers/media/dvb/mantis/mantis_cards.c b/drivers/media/pci/mantis/mantis_cards.c index 095cf3a994e2..0207d1f064e0 100644 --- a/drivers/media/dvb/mantis/mantis_cards.c +++ b/drivers/media/pci/mantis/mantis_cards.c @@ -275,7 +275,7 @@ static struct pci_device_id mantis_pci_table[] = { MAKE_ENTRY(TWINHAN_TECHNOLOGIES, MANTIS_VP_2033_DVB_C, &vp2033_config), MAKE_ENTRY(TWINHAN_TECHNOLOGIES, MANTIS_VP_2040_DVB_C, &vp2040_config), MAKE_ENTRY(TECHNISAT, CABLESTAR_HD2, &vp2040_config), - MAKE_ENTRY(TERRATEC, CINERGY_C, &vp2033_config), + MAKE_ENTRY(TERRATEC, CINERGY_C, &vp2040_config), MAKE_ENTRY(TWINHAN_TECHNOLOGIES, MANTIS_VP_3030_DVB_T, &vp3030_config), { } }; diff --git a/drivers/media/dvb/mantis/mantis_common.h b/drivers/media/pci/mantis/mantis_common.h index f2410cf0a6bf..f2410cf0a6bf 100644 --- a/drivers/media/dvb/mantis/mantis_common.h +++ b/drivers/media/pci/mantis/mantis_common.h diff --git a/drivers/media/dvb/mantis/mantis_core.c b/drivers/media/pci/mantis/mantis_core.c index 22524a8e6f61..684d9061fe2a 100644 --- a/drivers/media/dvb/mantis/mantis_core.c +++ b/drivers/media/pci/mantis/mantis_core.c @@ -121,7 +121,7 @@ static void mantis_load_config(struct mantis_pci *mantis) mantis->hwconfig = &vp2033_mantis_config; break; case MANTIS_VP_2040_DVB_C: /* VP-2040 */ - case TERRATEC_CINERGY_C_PCI: /* VP-2040 clone */ + case CINERGY_C: /* VP-2040 clone */ case TECHNISAT_CABLESTAR_HD2: mantis->hwconfig = &vp2040_mantis_config; break; diff --git a/drivers/media/dvb/mantis/mantis_core.h b/drivers/media/pci/mantis/mantis_core.h index 833ee42e694e..833ee42e694e 100644 --- a/drivers/media/dvb/mantis/mantis_core.h +++ b/drivers/media/pci/mantis/mantis_core.h diff --git a/drivers/media/dvb/mantis/mantis_dma.c b/drivers/media/pci/mantis/mantis_dma.c index 566c407175a4..566c407175a4 100644 --- a/drivers/media/dvb/mantis/mantis_dma.c +++ b/drivers/media/pci/mantis/mantis_dma.c diff --git a/drivers/media/dvb/mantis/mantis_dma.h b/drivers/media/pci/mantis/mantis_dma.h index 6be00fa82094..6be00fa82094 100644 --- a/drivers/media/dvb/mantis/mantis_dma.h +++ b/drivers/media/pci/mantis/mantis_dma.h diff --git a/drivers/media/dvb/mantis/mantis_dvb.c b/drivers/media/pci/mantis/mantis_dvb.c index e5180e45d310..5d15c6b74d9b 100644 --- a/drivers/media/dvb/mantis/mantis_dvb.c +++ b/drivers/media/pci/mantis/mantis_dvb.c @@ -248,8 +248,10 @@ int __devinit mantis_dvb_init(struct mantis_pci *mantis) err5: tasklet_kill(&mantis->tasklet); dvb_net_release(&mantis->dvbnet); - dvb_unregister_frontend(mantis->fe); - dvb_frontend_detach(mantis->fe); + if (mantis->fe) { + dvb_unregister_frontend(mantis->fe); + dvb_frontend_detach(mantis->fe); + } err4: mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_mem); diff --git a/drivers/media/dvb/mantis/mantis_dvb.h b/drivers/media/pci/mantis/mantis_dvb.h index 464199db304e..464199db304e 100644 --- a/drivers/media/dvb/mantis/mantis_dvb.h +++ b/drivers/media/pci/mantis/mantis_dvb.h diff --git a/drivers/media/dvb/mantis/mantis_evm.c b/drivers/media/pci/mantis/mantis_evm.c index 909ff54868a3..909ff54868a3 100644 --- a/drivers/media/dvb/mantis/mantis_evm.c +++ b/drivers/media/pci/mantis/mantis_evm.c diff --git a/drivers/media/dvb/mantis/mantis_hif.c b/drivers/media/pci/mantis/mantis_hif.c index 10c68df7e16f..10c68df7e16f 100644 --- a/drivers/media/dvb/mantis/mantis_hif.c +++ b/drivers/media/pci/mantis/mantis_hif.c diff --git a/drivers/media/dvb/mantis/mantis_hif.h b/drivers/media/pci/mantis/mantis_hif.h index 9094f9ed2362..9094f9ed2362 100644 --- a/drivers/media/dvb/mantis/mantis_hif.h +++ b/drivers/media/pci/mantis/mantis_hif.h diff --git a/drivers/media/dvb/mantis/mantis_i2c.c b/drivers/media/pci/mantis/mantis_i2c.c index e7794517fe26..e7794517fe26 100644 --- a/drivers/media/dvb/mantis/mantis_i2c.c +++ b/drivers/media/pci/mantis/mantis_i2c.c diff --git a/drivers/media/dvb/mantis/mantis_i2c.h b/drivers/media/pci/mantis/mantis_i2c.h index 1342df2faed8..1342df2faed8 100644 --- a/drivers/media/dvb/mantis/mantis_i2c.h +++ b/drivers/media/pci/mantis/mantis_i2c.h diff --git a/drivers/media/dvb/mantis/mantis_input.c b/drivers/media/pci/mantis/mantis_input.c index db6d54d3fec0..db6d54d3fec0 100644 --- a/drivers/media/dvb/mantis/mantis_input.c +++ b/drivers/media/pci/mantis/mantis_input.c diff --git a/drivers/media/dvb/mantis/mantis_ioc.c b/drivers/media/pci/mantis/mantis_ioc.c index 24fcdc63d6d5..24fcdc63d6d5 100644 --- a/drivers/media/dvb/mantis/mantis_ioc.c +++ b/drivers/media/pci/mantis/mantis_ioc.c diff --git a/drivers/media/dvb/mantis/mantis_ioc.h b/drivers/media/pci/mantis/mantis_ioc.h index d56e002b2955..d56e002b2955 100644 --- a/drivers/media/dvb/mantis/mantis_ioc.h +++ b/drivers/media/pci/mantis/mantis_ioc.h diff --git a/drivers/media/dvb/mantis/mantis_link.h b/drivers/media/pci/mantis/mantis_link.h index 2a814774a001..2a814774a001 100644 --- a/drivers/media/dvb/mantis/mantis_link.h +++ b/drivers/media/pci/mantis/mantis_link.h diff --git a/drivers/media/dvb/mantis/mantis_pci.c b/drivers/media/pci/mantis/mantis_pci.c index 371558af2d96..371558af2d96 100644 --- a/drivers/media/dvb/mantis/mantis_pci.c +++ b/drivers/media/pci/mantis/mantis_pci.c diff --git a/drivers/media/dvb/mantis/mantis_pci.h b/drivers/media/pci/mantis/mantis_pci.h index 65f004519086..65f004519086 100644 --- a/drivers/media/dvb/mantis/mantis_pci.h +++ b/drivers/media/pci/mantis/mantis_pci.h diff --git a/drivers/media/dvb/mantis/mantis_pcmcia.c b/drivers/media/pci/mantis/mantis_pcmcia.c index 2f188c089666..2f188c089666 100644 --- a/drivers/media/dvb/mantis/mantis_pcmcia.c +++ b/drivers/media/pci/mantis/mantis_pcmcia.c diff --git a/drivers/media/dvb/mantis/mantis_reg.h b/drivers/media/pci/mantis/mantis_reg.h index 7761f9dc7fe0..7761f9dc7fe0 100644 --- a/drivers/media/dvb/mantis/mantis_reg.h +++ b/drivers/media/pci/mantis/mantis_reg.h diff --git a/drivers/media/dvb/mantis/mantis_uart.c b/drivers/media/pci/mantis/mantis_uart.c index 85e977861b4a..85e977861b4a 100644 --- a/drivers/media/dvb/mantis/mantis_uart.c +++ b/drivers/media/pci/mantis/mantis_uart.c diff --git a/drivers/media/dvb/mantis/mantis_uart.h b/drivers/media/pci/mantis/mantis_uart.h index ffb62a0a5a13..ffb62a0a5a13 100644 --- a/drivers/media/dvb/mantis/mantis_uart.h +++ b/drivers/media/pci/mantis/mantis_uart.h diff --git a/drivers/media/dvb/mantis/mantis_vp1033.c b/drivers/media/pci/mantis/mantis_vp1033.c index ad013e93ed11..ad013e93ed11 100644 --- a/drivers/media/dvb/mantis/mantis_vp1033.c +++ b/drivers/media/pci/mantis/mantis_vp1033.c diff --git a/drivers/media/dvb/mantis/mantis_vp1033.h b/drivers/media/pci/mantis/mantis_vp1033.h index 7daaa1bf127d..7daaa1bf127d 100644 --- a/drivers/media/dvb/mantis/mantis_vp1033.h +++ b/drivers/media/pci/mantis/mantis_vp1033.h diff --git a/drivers/media/dvb/mantis/mantis_vp1034.c b/drivers/media/pci/mantis/mantis_vp1034.c index 430ae84ce528..430ae84ce528 100644 --- a/drivers/media/dvb/mantis/mantis_vp1034.c +++ b/drivers/media/pci/mantis/mantis_vp1034.c diff --git a/drivers/media/dvb/mantis/mantis_vp1034.h b/drivers/media/pci/mantis/mantis_vp1034.h index 323f38ef8e3d..323f38ef8e3d 100644 --- a/drivers/media/dvb/mantis/mantis_vp1034.h +++ b/drivers/media/pci/mantis/mantis_vp1034.h diff --git a/drivers/media/dvb/mantis/mantis_vp1041.c b/drivers/media/pci/mantis/mantis_vp1041.c index 07aa887a4b4a..07aa887a4b4a 100644 --- a/drivers/media/dvb/mantis/mantis_vp1041.c +++ b/drivers/media/pci/mantis/mantis_vp1041.c diff --git a/drivers/media/dvb/mantis/mantis_vp1041.h b/drivers/media/pci/mantis/mantis_vp1041.h index 1ae5b3de8081..1ae5b3de8081 100644 --- a/drivers/media/dvb/mantis/mantis_vp1041.h +++ b/drivers/media/pci/mantis/mantis_vp1041.h diff --git a/drivers/media/dvb/mantis/mantis_vp2033.c b/drivers/media/pci/mantis/mantis_vp2033.c index 1ca6837fbe46..1ca6837fbe46 100644 --- a/drivers/media/dvb/mantis/mantis_vp2033.c +++ b/drivers/media/pci/mantis/mantis_vp2033.c diff --git a/drivers/media/dvb/mantis/mantis_vp2033.h b/drivers/media/pci/mantis/mantis_vp2033.h index c55242b79d54..c55242b79d54 100644 --- a/drivers/media/dvb/mantis/mantis_vp2033.h +++ b/drivers/media/pci/mantis/mantis_vp2033.h diff --git a/drivers/media/dvb/mantis/mantis_vp2040.c b/drivers/media/pci/mantis/mantis_vp2040.c index d480741afd78..d480741afd78 100644 --- a/drivers/media/dvb/mantis/mantis_vp2040.c +++ b/drivers/media/pci/mantis/mantis_vp2040.c diff --git a/drivers/media/dvb/mantis/mantis_vp2040.h b/drivers/media/pci/mantis/mantis_vp2040.h index d125e219b685..d125e219b685 100644 --- a/drivers/media/dvb/mantis/mantis_vp2040.h +++ b/drivers/media/pci/mantis/mantis_vp2040.h diff --git a/drivers/media/dvb/mantis/mantis_vp3028.c b/drivers/media/pci/mantis/mantis_vp3028.c index 4155c838a18a..4155c838a18a 100644 --- a/drivers/media/dvb/mantis/mantis_vp3028.c +++ b/drivers/media/pci/mantis/mantis_vp3028.c diff --git a/drivers/media/dvb/mantis/mantis_vp3028.h b/drivers/media/pci/mantis/mantis_vp3028.h index b07be6adc522..b07be6adc522 100644 --- a/drivers/media/dvb/mantis/mantis_vp3028.h +++ b/drivers/media/pci/mantis/mantis_vp3028.h diff --git a/drivers/media/dvb/mantis/mantis_vp3030.c b/drivers/media/pci/mantis/mantis_vp3030.c index c09308cd3ac6..c09308cd3ac6 100644 --- a/drivers/media/dvb/mantis/mantis_vp3030.c +++ b/drivers/media/pci/mantis/mantis_vp3030.c diff --git a/drivers/media/dvb/mantis/mantis_vp3030.h b/drivers/media/pci/mantis/mantis_vp3030.h index 5f12c4266277..5f12c4266277 100644 --- a/drivers/media/dvb/mantis/mantis_vp3030.h +++ b/drivers/media/pci/mantis/mantis_vp3030.h diff --git a/drivers/media/pci/meye/Kconfig b/drivers/media/pci/meye/Kconfig new file mode 100644 index 000000000000..b4bf848be5a0 --- /dev/null +++ b/drivers/media/pci/meye/Kconfig @@ -0,0 +1,13 @@ +config VIDEO_MEYE + tristate "Sony Vaio Picturebook Motion Eye Video For Linux" + depends on PCI && SONY_LAPTOP && VIDEO_V4L2 + ---help--- + This is the video4linux driver for the Motion Eye camera found + in the Vaio Picturebook laptops. Please read the material in + <file:Documentation/video4linux/meye.txt> for more information. + + If you say Y or M here, you need to say Y or M to "Sony Laptop + Extras" in the misc device section. + + To compile this driver as a module, choose M here: the + module will be called meye. diff --git a/drivers/media/pci/meye/Makefile b/drivers/media/pci/meye/Makefile new file mode 100644 index 000000000000..49388518cd01 --- /dev/null +++ b/drivers/media/pci/meye/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_VIDEO_MEYE) += meye.o diff --git a/drivers/media/video/meye.c b/drivers/media/pci/meye/meye.c index 7bc775219f97..7bc775219f97 100644 --- a/drivers/media/video/meye.c +++ b/drivers/media/pci/meye/meye.c diff --git a/drivers/media/video/meye.h b/drivers/media/pci/meye/meye.h index 4bdeb03f1644..4bdeb03f1644 100644 --- a/drivers/media/video/meye.h +++ b/drivers/media/pci/meye/meye.h diff --git a/drivers/media/pci/ngene/Kconfig b/drivers/media/pci/ngene/Kconfig new file mode 100644 index 000000000000..637d506b23c5 --- /dev/null +++ b/drivers/media/pci/ngene/Kconfig @@ -0,0 +1,13 @@ +config DVB_NGENE + tristate "Micronas nGene support" + depends on DVB_CORE && PCI && I2C + select DVB_LNBP21 if MEDIA_SUBDRV_AUTOSELECT + select DVB_STV6110x if MEDIA_SUBDRV_AUTOSELECT + select DVB_STV090x if MEDIA_SUBDRV_AUTOSELECT + select DVB_LGDT330X if MEDIA_SUBDRV_AUTOSELECT + select DVB_DRXK if MEDIA_SUBDRV_AUTOSELECT + select DVB_TDA18271C2DD if MEDIA_SUBDRV_AUTOSELECT + select MEDIA_TUNER_MT2131 if MEDIA_SUBDRV_AUTOSELECT + ---help--- + Support for Micronas PCI express cards with nGene bridge. + diff --git a/drivers/media/dvb/ngene/Makefile b/drivers/media/pci/ngene/Makefile index 13ebeffb705f..5c0b5d6b9d69 100644 --- a/drivers/media/dvb/ngene/Makefile +++ b/drivers/media/pci/ngene/Makefile @@ -6,9 +6,9 @@ ngene-objs := ngene-core.o ngene-i2c.o ngene-cards.o ngene-dvb.o obj-$(CONFIG_DVB_NGENE) += ngene.o -ccflags-y += -Idrivers/media/dvb/dvb-core/ -ccflags-y += -Idrivers/media/dvb/frontends/ -ccflags-y += -Idrivers/media/common/tuners/ +ccflags-y += -Idrivers/media/dvb-core/ +ccflags-y += -Idrivers/media/dvb-frontends/ +ccflags-y += -Idrivers/media/tuners/ # For the staging CI driver cxd2099 ccflags-y += -Idrivers/staging/media/cxd2099/ diff --git a/drivers/media/dvb/ngene/ngene-cards.c b/drivers/media/pci/ngene/ngene-cards.c index 0a497be97af8..96a13ed197d0 100644 --- a/drivers/media/dvb/ngene/ngene-cards.c +++ b/drivers/media/pci/ngene/ngene-cards.c @@ -42,6 +42,8 @@ #include "mt2131.h" #include "tda18271c2dd.h" #include "drxk.h" +#include "drxd.h" +#include "dvb-pll.h" /****************************************************************************/ @@ -313,6 +315,235 @@ static int demod_attach_lg330x(struct ngene_channel *chan) return (chan->fe) ? 0 : -ENODEV; } +static int demod_attach_drxd(struct ngene_channel *chan) +{ + struct drxd_config *feconf; + + feconf = chan->dev->card_info->fe_config[chan->number]; + + chan->fe = dvb_attach(drxd_attach, feconf, chan, + &chan->i2c_adapter, &chan->dev->pci_dev->dev); + if (!chan->fe) { + pr_err("No DRXD found!\n"); + return -ENODEV; + } + + if (!dvb_attach(dvb_pll_attach, chan->fe, feconf->pll_address, + &chan->i2c_adapter, + feconf->pll_type)) { + pr_err("No pll(%d) found!\n", feconf->pll_type); + return -ENODEV; + } + return 0; +} + +/****************************************************************************/ +/* EEPROM TAGS **************************************************************/ +/****************************************************************************/ + +#define MICNG_EE_START 0x0100 +#define MICNG_EE_END 0x0FF0 + +#define MICNG_EETAG_END0 0x0000 +#define MICNG_EETAG_END1 0xFFFF + +/* 0x0001 - 0x000F reserved for housekeeping */ +/* 0xFFFF - 0xFFFE reserved for housekeeping */ + +/* Micronas assigned tags + EEProm tags for hardware support */ + +#define MICNG_EETAG_DRXD1_OSCDEVIATION 0x1000 /* 2 Bytes data */ +#define MICNG_EETAG_DRXD2_OSCDEVIATION 0x1001 /* 2 Bytes data */ + +#define MICNG_EETAG_MT2060_1_1STIF 0x1100 /* 2 Bytes data */ +#define MICNG_EETAG_MT2060_2_1STIF 0x1101 /* 2 Bytes data */ + +/* Tag range for OEMs */ + +#define MICNG_EETAG_OEM_FIRST 0xC000 +#define MICNG_EETAG_OEM_LAST 0xFFEF + +static int i2c_write_eeprom(struct i2c_adapter *adapter, + u8 adr, u16 reg, u8 data) +{ + u8 m[3] = {(reg >> 8), (reg & 0xff), data}; + struct i2c_msg msg = {.addr = adr, .flags = 0, .buf = m, + .len = sizeof(m)}; + + if (i2c_transfer(adapter, &msg, 1) != 1) { + pr_err(DEVICE_NAME ": Error writing EEPROM!\n"); + return -EIO; + } + return 0; +} + +static int i2c_read_eeprom(struct i2c_adapter *adapter, + u8 adr, u16 reg, u8 *data, int len) +{ + u8 msg[2] = {(reg >> 8), (reg & 0xff)}; + struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0, + .buf = msg, .len = 2 }, + {.addr = adr, .flags = I2C_M_RD, + .buf = data, .len = len} }; + + if (i2c_transfer(adapter, msgs, 2) != 2) { + pr_err(DEVICE_NAME ": Error reading EEPROM\n"); + return -EIO; + } + return 0; +} + +static int ReadEEProm(struct i2c_adapter *adapter, + u16 Tag, u32 MaxLen, u8 *data, u32 *pLength) +{ + int status = 0; + u16 Addr = MICNG_EE_START, Length, tag = 0; + u8 EETag[3]; + + while (Addr + sizeof(u16) + 1 < MICNG_EE_END) { + if (i2c_read_eeprom(adapter, 0x50, Addr, EETag, sizeof(EETag))) + return -1; + tag = (EETag[0] << 8) | EETag[1]; + if (tag == MICNG_EETAG_END0 || tag == MICNG_EETAG_END1) + return -1; + if (tag == Tag) + break; + Addr += sizeof(u16) + 1 + EETag[2]; + } + if (Addr + sizeof(u16) + 1 + EETag[2] > MICNG_EE_END) { + pr_err(DEVICE_NAME + ": Reached EOEE @ Tag = %04x Length = %3d\n", + tag, EETag[2]); + return -1; + } + Length = EETag[2]; + if (Length > MaxLen) + Length = (u16) MaxLen; + if (Length > 0) { + Addr += sizeof(u16) + 1; + status = i2c_read_eeprom(adapter, 0x50, Addr, data, Length); + if (!status) { + *pLength = EETag[2]; + if (Length < EETag[2]) + ; /*status=STATUS_BUFFER_OVERFLOW; */ + } + } + return status; +} + +static int WriteEEProm(struct i2c_adapter *adapter, + u16 Tag, u32 Length, u8 *data) +{ + int status = 0; + u16 Addr = MICNG_EE_START; + u8 EETag[3]; + u16 tag = 0; + int retry, i; + + while (Addr + sizeof(u16) + 1 < MICNG_EE_END) { + if (i2c_read_eeprom(adapter, 0x50, Addr, EETag, sizeof(EETag))) + return -1; + tag = (EETag[0] << 8) | EETag[1]; + if (tag == MICNG_EETAG_END0 || tag == MICNG_EETAG_END1) + return -1; + if (tag == Tag) + break; + Addr += sizeof(u16) + 1 + EETag[2]; + } + if (Addr + sizeof(u16) + 1 + EETag[2] > MICNG_EE_END) { + pr_err(DEVICE_NAME + ": Reached EOEE @ Tag = %04x Length = %3d\n", + tag, EETag[2]); + return -1; + } + + if (Length > EETag[2]) + return -EINVAL; + /* Note: We write the data one byte at a time to avoid + issues with page sizes. (which are different for + each manufacture and eeprom size) + */ + Addr += sizeof(u16) + 1; + for (i = 0; i < Length; i++, Addr++) { + status = i2c_write_eeprom(adapter, 0x50, Addr, data[i]); + + if (status) + break; + + /* Poll for finishing write cycle */ + retry = 10; + while (retry) { + u8 Tmp; + + msleep(50); + status = i2c_read_eeprom(adapter, 0x50, Addr, &Tmp, 1); + if (status) + break; + if (Tmp != data[i]) + pr_err(DEVICE_NAME + "eeprom write error\n"); + retry -= 1; + } + if (status) { + pr_err(DEVICE_NAME + ": Timeout polling eeprom\n"); + break; + } + } + return status; +} + +static int eeprom_read_ushort(struct i2c_adapter *adapter, u16 tag, u16 *data) +{ + int stat; + u8 buf[2]; + u32 len = 0; + + stat = ReadEEProm(adapter, tag, 2, buf, &len); + if (stat) + return stat; + if (len != 2) + return -EINVAL; + + *data = (buf[0] << 8) | buf[1]; + return 0; +} + +static int eeprom_write_ushort(struct i2c_adapter *adapter, u16 tag, u16 data) +{ + int stat; + u8 buf[2]; + + buf[0] = data >> 8; + buf[1] = data & 0xff; + stat = WriteEEProm(adapter, tag, 2, buf); + if (stat) + return stat; + return 0; +} + +static s16 osc_deviation(void *priv, s16 deviation, int flag) +{ + struct ngene_channel *chan = priv; + struct i2c_adapter *adap = &chan->i2c_adapter; + u16 data = 0; + + if (flag) { + data = (u16) deviation; + pr_info(DEVICE_NAME ": write deviation %d\n", + deviation); + eeprom_write_ushort(adap, 0x1000 + chan->number, data); + } else { + if (eeprom_read_ushort(adap, 0x1000 + chan->number, &data)) + data = 0; + pr_info(DEVICE_NAME ": read deviation %d\n", + (s16) data); + } + + return (s16) data; +} + /****************************************************************************/ /* Switch control (I2C gates, etc.) *****************************************/ /****************************************************************************/ @@ -464,6 +695,37 @@ static struct ngene_info ngene_info_m780 = { .fw_version = 15, }; +static struct drxd_config fe_terratec_dvbt_0 = { + .index = 0, + .demod_address = 0x70, + .demod_revision = 0xa2, + .demoda_address = 0x00, + .pll_address = 0x60, + .pll_type = DVB_PLL_THOMSON_DTT7520X, + .clock = 20000, + .osc_deviation = osc_deviation, +}; + +static struct drxd_config fe_terratec_dvbt_1 = { + .index = 1, + .demod_address = 0x71, + .demod_revision = 0xa2, + .demoda_address = 0x00, + .pll_address = 0x60, + .pll_type = DVB_PLL_THOMSON_DTT7520X, + .clock = 20000, + .osc_deviation = osc_deviation, +}; + +static struct ngene_info ngene_info_terratec = { + .type = NGENE_TERRATEC, + .name = "Terratec Integra/Cinergy2400i Dual DVB-T", + .io_type = {NGENE_IO_TSIN, NGENE_IO_TSIN}, + .demod_attach = {demod_attach_drxd, demod_attach_drxd}, + .fe_config = {&fe_terratec_dvbt_0, &fe_terratec_dvbt_1}, + .i2c_access = 1, +}; + /****************************************************************************/ @@ -488,6 +750,7 @@ static const struct pci_device_id ngene_id_tbl[] __devinitdata = { NGENE_ID(0x18c3, 0xdd10, ngene_info_duoFlex), NGENE_ID(0x18c3, 0xdd20, ngene_info_duoFlex), NGENE_ID(0x1461, 0x062e, ngene_info_m780), + NGENE_ID(0x153b, 0x1167, ngene_info_terratec), {0} }; MODULE_DEVICE_TABLE(pci, ngene_id_tbl); diff --git a/drivers/media/dvb/ngene/ngene-core.c b/drivers/media/pci/ngene/ngene-core.c index 39857384af10..c8e0d5b99d4c 100644 --- a/drivers/media/dvb/ngene/ngene-core.c +++ b/drivers/media/pci/ngene/ngene-core.c @@ -258,22 +258,16 @@ static void dump_command_io(struct ngene *dev) u8 buf[8], *b; ngcpyfrom(buf, HOST_TO_NGENE, 8); - printk(KERN_ERR "host_to_ngene (%04x): %02x %02x %02x %02x %02x %02x %02x %02x\n", - HOST_TO_NGENE, buf[0], buf[1], buf[2], buf[3], - buf[4], buf[5], buf[6], buf[7]); + printk(KERN_ERR "host_to_ngene (%04x): %*ph\n", HOST_TO_NGENE, 8, buf); ngcpyfrom(buf, NGENE_TO_HOST, 8); - printk(KERN_ERR "ngene_to_host (%04x): %02x %02x %02x %02x %02x %02x %02x %02x\n", - NGENE_TO_HOST, buf[0], buf[1], buf[2], buf[3], - buf[4], buf[5], buf[6], buf[7]); + printk(KERN_ERR "ngene_to_host (%04x): %*ph\n", NGENE_TO_HOST, 8, buf); b = dev->hosttongene; - printk(KERN_ERR "dev->hosttongene (%p): %02x %02x %02x %02x %02x %02x %02x %02x\n", - b, b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7]); + printk(KERN_ERR "dev->hosttongene (%p): %*ph\n", b, 8, b); b = dev->ngenetohost; - printk(KERN_ERR "dev->ngenetohost (%p): %02x %02x %02x %02x %02x %02x %02x %02x\n", - b, b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7]); + printk(KERN_ERR "dev->ngenetohost (%p): %*ph\n", b, 8, b); } static int ngene_command_mutex(struct ngene *dev, struct ngene_command *com) diff --git a/drivers/media/dvb/ngene/ngene-dvb.c b/drivers/media/pci/ngene/ngene-dvb.c index fcb16a615aab..fcb16a615aab 100644 --- a/drivers/media/dvb/ngene/ngene-dvb.c +++ b/drivers/media/pci/ngene/ngene-dvb.c diff --git a/drivers/media/dvb/ngene/ngene-i2c.c b/drivers/media/pci/ngene/ngene-i2c.c index d28554f8ce99..d28554f8ce99 100644 --- a/drivers/media/dvb/ngene/ngene-i2c.c +++ b/drivers/media/pci/ngene/ngene-i2c.c diff --git a/drivers/media/dvb/ngene/ngene.h b/drivers/media/pci/ngene/ngene.h index 5443dc0caea5..5443dc0caea5 100644 --- a/drivers/media/dvb/ngene/ngene.h +++ b/drivers/media/pci/ngene/ngene.h diff --git a/drivers/media/dvb/pluto2/Kconfig b/drivers/media/pci/pluto2/Kconfig index 7d8e6e87bdbb..7d8e6e87bdbb 100644 --- a/drivers/media/dvb/pluto2/Kconfig +++ b/drivers/media/pci/pluto2/Kconfig diff --git a/drivers/media/pci/pluto2/Makefile b/drivers/media/pci/pluto2/Makefile new file mode 100644 index 000000000000..524bf841f42b --- /dev/null +++ b/drivers/media/pci/pluto2/Makefile @@ -0,0 +1,3 @@ +obj-$(CONFIG_DVB_PLUTO2) += pluto2.o + +ccflags-y += -Idrivers/media/dvb-core/ -Idrivers/media/dvb-frontends/ diff --git a/drivers/media/dvb/pluto2/pluto2.c b/drivers/media/pci/pluto2/pluto2.c index f148b19a206a..f148b19a206a 100644 --- a/drivers/media/dvb/pluto2/pluto2.c +++ b/drivers/media/pci/pluto2/pluto2.c diff --git a/drivers/media/dvb/pt1/Kconfig b/drivers/media/pci/pt1/Kconfig index 24501d5bf70d..24501d5bf70d 100644 --- a/drivers/media/dvb/pt1/Kconfig +++ b/drivers/media/pci/pt1/Kconfig diff --git a/drivers/media/dvb/pt1/Makefile b/drivers/media/pci/pt1/Makefile index d80d8e8e7c57..98e391295afe 100644 --- a/drivers/media/dvb/pt1/Makefile +++ b/drivers/media/pci/pt1/Makefile @@ -2,4 +2,4 @@ earth-pt1-objs := pt1.o va1j5jf8007s.o va1j5jf8007t.o obj-$(CONFIG_DVB_PT1) += earth-pt1.o -ccflags-y += -Idrivers/media/dvb/dvb-core -Idrivers/media/dvb/frontends +ccflags-y += -Idrivers/media/dvb-core -Idrivers/media/dvb-frontends diff --git a/drivers/media/dvb/pt1/pt1.c b/drivers/media/pci/pt1/pt1.c index 15b35c4725f1..15b35c4725f1 100644 --- a/drivers/media/dvb/pt1/pt1.c +++ b/drivers/media/pci/pt1/pt1.c diff --git a/drivers/media/dvb/pt1/va1j5jf8007s.c b/drivers/media/pci/pt1/va1j5jf8007s.c index d980dfb21e5e..1b637b74ef58 100644 --- a/drivers/media/dvb/pt1/va1j5jf8007s.c +++ b/drivers/media/pci/pt1/va1j5jf8007s.c @@ -329,8 +329,8 @@ va1j5jf8007s_set_ts_id(struct va1j5jf8007s_state *state) u8 buf[3]; struct i2c_msg msg; - ts_id = state->fe.dtv_property_cache.isdbs_ts_id; - if (!ts_id) + ts_id = state->fe.dtv_property_cache.stream_id; + if (!ts_id || ts_id == NO_STREAM_ID_FILTER) return 0; buf[0] = 0x8f; @@ -356,8 +356,8 @@ va1j5jf8007s_check_ts_id(struct va1j5jf8007s_state *state, int *lock) struct i2c_msg msgs[2]; u32 ts_id; - ts_id = state->fe.dtv_property_cache.isdbs_ts_id; - if (!ts_id) { + ts_id = state->fe.dtv_property_cache.stream_id; + if (!ts_id || ts_id == NO_STREAM_ID_FILTER) { *lock = 1; return 0; } @@ -587,7 +587,8 @@ static struct dvb_frontend_ops va1j5jf8007s_ops = { .frequency_stepsize = 1000, .caps = FE_CAN_INVERSION_AUTO | FE_CAN_FEC_AUTO | FE_CAN_QAM_AUTO | FE_CAN_TRANSMISSION_MODE_AUTO | - FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO, + FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO | + FE_CAN_MULTISTREAM, }, .read_snr = va1j5jf8007s_read_snr, diff --git a/drivers/media/dvb/pt1/va1j5jf8007s.h b/drivers/media/pci/pt1/va1j5jf8007s.h index b7d6f05a0e02..b7d6f05a0e02 100644 --- a/drivers/media/dvb/pt1/va1j5jf8007s.h +++ b/drivers/media/pci/pt1/va1j5jf8007s.h diff --git a/drivers/media/dvb/pt1/va1j5jf8007t.c b/drivers/media/pci/pt1/va1j5jf8007t.c index 2db15159d514..2db15159d514 100644 --- a/drivers/media/dvb/pt1/va1j5jf8007t.c +++ b/drivers/media/pci/pt1/va1j5jf8007t.c diff --git a/drivers/media/dvb/pt1/va1j5jf8007t.h b/drivers/media/pci/pt1/va1j5jf8007t.h index 2903be519ef5..2903be519ef5 100644 --- a/drivers/media/dvb/pt1/va1j5jf8007t.h +++ b/drivers/media/pci/pt1/va1j5jf8007t.h diff --git a/drivers/media/video/saa7134/Kconfig b/drivers/media/pci/saa7134/Kconfig index 39fc0187a747..15b90d6e9130 100644 --- a/drivers/media/video/saa7134/Kconfig +++ b/drivers/media/pci/saa7134/Kconfig @@ -5,7 +5,7 @@ config VIDEO_SAA7134 select VIDEO_TUNER select VIDEO_TVEEPROM select CRC32 - select VIDEO_SAA6588 if VIDEO_HELPER_CHIPS_AUTO + select VIDEO_SAA6588 if MEDIA_SUBDRV_AUTOSELECT ---help--- This is a video4linux driver for Philips SAA713x based TV cards. @@ -37,25 +37,25 @@ config VIDEO_SAA7134_DVB tristate "DVB/ATSC Support for saa7134 based TV cards" depends on VIDEO_SAA7134 && DVB_CORE select VIDEOBUF_DVB - select DVB_PLL if !DVB_FE_CUSTOMISE - select DVB_MT352 if !DVB_FE_CUSTOMISE - select DVB_TDA1004X if !DVB_FE_CUSTOMISE - select DVB_NXT200X if !DVB_FE_CUSTOMISE - select DVB_TDA10086 if !DVB_FE_CUSTOMISE - select DVB_TDA826X if !DVB_FE_CUSTOMISE - select DVB_ISL6421 if !DVB_FE_CUSTOMISE - select DVB_ISL6405 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_TDA827X if !MEDIA_TUNER_CUSTOMISE - select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMISE - select DVB_ZL10036 if !DVB_FE_CUSTOMISE - select DVB_MT312 if !DVB_FE_CUSTOMISE - select DVB_LNBP21 if !DVB_FE_CUSTOMISE - select DVB_ZL10353 if !DVB_FE_CUSTOMISE - select DVB_LGDT3305 if !DVB_FE_CUSTOMISE - select DVB_TDA10048 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_TDA18271 if !MEDIA_TUNER_CUSTOMISE - select MEDIA_TUNER_TDA8290 if !MEDIA_TUNER_CUSTOMISE - select DVB_ZL10039 if !DVB_FE_CUSTOMISE + select DVB_PLL if MEDIA_SUBDRV_AUTOSELECT + select DVB_MT352 if MEDIA_SUBDRV_AUTOSELECT + select DVB_TDA1004X if MEDIA_SUBDRV_AUTOSELECT + select DVB_NXT200X if MEDIA_SUBDRV_AUTOSELECT + select DVB_TDA10086 if MEDIA_SUBDRV_AUTOSELECT + select DVB_TDA826X if MEDIA_SUBDRV_AUTOSELECT + select DVB_ISL6421 if MEDIA_SUBDRV_AUTOSELECT + select DVB_ISL6405 if MEDIA_SUBDRV_AUTOSELECT + select MEDIA_TUNER_TDA827X if MEDIA_SUBDRV_AUTOSELECT + select MEDIA_TUNER_SIMPLE if MEDIA_SUBDRV_AUTOSELECT + select DVB_ZL10036 if MEDIA_SUBDRV_AUTOSELECT + select DVB_MT312 if MEDIA_SUBDRV_AUTOSELECT + select DVB_LNBP21 if MEDIA_SUBDRV_AUTOSELECT + select DVB_ZL10353 if MEDIA_SUBDRV_AUTOSELECT + select DVB_LGDT3305 if MEDIA_SUBDRV_AUTOSELECT + select DVB_TDA10048 if MEDIA_SUBDRV_AUTOSELECT + select MEDIA_TUNER_TDA18271 if MEDIA_SUBDRV_AUTOSELECT + select MEDIA_TUNER_TDA8290 if MEDIA_SUBDRV_AUTOSELECT + select DVB_ZL10039 if MEDIA_SUBDRV_AUTOSELECT ---help--- This adds support for DVB cards based on the Philips saa7134 chip. diff --git a/drivers/media/video/saa7134/Makefile b/drivers/media/pci/saa7134/Makefile index da3899329f52..35375480ed4d 100644 --- a/drivers/media/video/saa7134/Makefile +++ b/drivers/media/pci/saa7134/Makefile @@ -1,5 +1,5 @@ -saa7134-y := saa7134-cards.o saa7134-core.o saa7134-i2c.o +saa7134-y += saa7134-cards.o saa7134-core.o saa7134-i2c.o saa7134-y += saa7134-ts.o saa7134-tvaudio.o saa7134-vbi.o saa7134-y += saa7134-video.o saa7134-$(CONFIG_VIDEO_SAA7134_RC) += saa7134-input.o @@ -10,7 +10,7 @@ obj-$(CONFIG_VIDEO_SAA7134_ALSA) += saa7134-alsa.o obj-$(CONFIG_VIDEO_SAA7134_DVB) += saa7134-dvb.o -ccflags-y += -I$(srctree)/drivers/media/video -ccflags-y += -I$(srctree)/drivers/media/common/tuners -ccflags-y += -I$(srctree)/drivers/media/dvb/dvb-core -ccflags-y += -I$(srctree)/drivers/media/dvb/frontends +ccflags-y += -I$(srctree)/drivers/media/i2c +ccflags-y += -I$(srctree)/drivers/media/tuners +ccflags-y += -I$(srctree)/drivers/media/dvb-core +ccflags-y += -I$(srctree)/drivers/media/dvb-frontends diff --git a/drivers/media/video/saa7134/saa6752hs.c b/drivers/media/pci/saa7134/saa6752hs.c index f147b05bd860..f147b05bd860 100644 --- a/drivers/media/video/saa7134/saa6752hs.c +++ b/drivers/media/pci/saa7134/saa6752hs.c diff --git a/drivers/media/video/saa7134/saa7134-alsa.c b/drivers/media/pci/saa7134/saa7134-alsa.c index 10460fd3ce39..10460fd3ce39 100644 --- a/drivers/media/video/saa7134/saa7134-alsa.c +++ b/drivers/media/pci/saa7134/saa7134-alsa.c diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/pci/saa7134/saa7134-cards.c index bc08f1dbc293..bc08f1dbc293 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/pci/saa7134/saa7134-cards.c diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/pci/saa7134/saa7134-core.c index f2b37e05b964..f2b37e05b964 100644 --- a/drivers/media/video/saa7134/saa7134-core.c +++ b/drivers/media/pci/saa7134/saa7134-core.c diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/pci/saa7134/saa7134-dvb.c index cc7f3d6ee966..b209de40a4f8 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/pci/saa7134/saa7134-dvb.c @@ -1796,10 +1796,10 @@ static int dvb_init(struct saa7134_dev *dev) dvb_attach(tda829x_attach, fe0->dvb.frontend, &dev->i2c_adap, 0x4b, &tda829x_no_probe); + fe0->dvb.frontend->ops.i2c_gate_ctrl = kworld_sbtvd_gate_ctrl; dvb_attach(tda18271_attach, fe0->dvb.frontend, 0x60, &dev->i2c_adap, &kworld_tda18271_config); - fe0->dvb.frontend->ops.i2c_gate_ctrl = kworld_sbtvd_gate_ctrl; } /* mb86a20s need to use the I2C gateway */ @@ -1849,7 +1849,7 @@ static int dvb_init(struct saa7134_dev *dev) /* register everything else */ ret = videobuf_dvb_register_bus(&dev->frontends, THIS_MODULE, dev, - &dev->pci->dev, adapter_nr, 0, NULL); + &dev->pci->dev, adapter_nr, 0); /* this sequence is necessary to make the tda1004x load its firmware * and to enter analog mode of hybrid boards diff --git a/drivers/media/video/saa7134/saa7134-empress.c b/drivers/media/pci/saa7134/saa7134-empress.c index 4df79c656909..4df79c656909 100644 --- a/drivers/media/video/saa7134/saa7134-empress.c +++ b/drivers/media/pci/saa7134/saa7134-empress.c diff --git a/drivers/media/video/saa7134/saa7134-i2c.c b/drivers/media/pci/saa7134/saa7134-i2c.c index a176ec3285e0..a176ec3285e0 100644 --- a/drivers/media/video/saa7134/saa7134-i2c.c +++ b/drivers/media/pci/saa7134/saa7134-i2c.c diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/pci/saa7134/saa7134-input.c index 05c6e217d8a7..0f78f5e537e2 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/pci/saa7134/saa7134-input.c @@ -446,11 +446,8 @@ static void saa7134_input_timer(unsigned long data) static void ir_raw_decode_timer_end(unsigned long data) { struct saa7134_dev *dev = (struct saa7134_dev *)data; - struct saa7134_card_ir *ir = dev->remote; ir_raw_event_handle(dev->remote->dev); - - ir->active = false; } static int __saa7134_ir_start(void *priv) @@ -501,7 +498,6 @@ static int __saa7134_ir_start(void *priv) } ir->running = true; - ir->active = false; if (ir->polling) { setup_timer(&ir->timer, saa7134_input_timer, @@ -532,7 +528,6 @@ static void __saa7134_ir_stop(void *priv) if (ir->polling || ir->raw_decode) del_timer_sync(&ir->timer); - ir->active = false; ir->running = false; return; @@ -1035,10 +1030,11 @@ static int saa7134_raw_decode_irq(struct saa7134_dev *dev) * the event. This time is enough for NEC protocol. May need adjustments * to work with other protocols. */ - if (!ir->active) { + smp_mb(); + + if (!timer_pending(&ir->timer)) { timeout = jiffies + msecs_to_jiffies(15); mod_timer(&ir->timer, timeout); - ir->active = true; } return 1; diff --git a/drivers/media/video/saa7134/saa7134-reg.h b/drivers/media/pci/saa7134/saa7134-reg.h index e7e0af101fa7..e7e0af101fa7 100644 --- a/drivers/media/video/saa7134/saa7134-reg.h +++ b/drivers/media/pci/saa7134/saa7134-reg.h diff --git a/drivers/media/video/saa7134/saa7134-ts.c b/drivers/media/pci/saa7134/saa7134-ts.c index 2e3f4b412d8c..2e3f4b412d8c 100644 --- a/drivers/media/video/saa7134/saa7134-ts.c +++ b/drivers/media/pci/saa7134/saa7134-ts.c diff --git a/drivers/media/video/saa7134/saa7134-tvaudio.c b/drivers/media/pci/saa7134/saa7134-tvaudio.c index b7a99bee2f98..b7a99bee2f98 100644 --- a/drivers/media/video/saa7134/saa7134-tvaudio.c +++ b/drivers/media/pci/saa7134/saa7134-tvaudio.c diff --git a/drivers/media/video/saa7134/saa7134-vbi.c b/drivers/media/pci/saa7134/saa7134-vbi.c index e9aa94b807f1..e9aa94b807f1 100644 --- a/drivers/media/video/saa7134/saa7134-vbi.c +++ b/drivers/media/pci/saa7134/saa7134-vbi.c diff --git a/drivers/media/video/saa7134/saa7134-video.c b/drivers/media/pci/saa7134/saa7134-video.c index 6de10b1e7251..22f8758d047f 100644 --- a/drivers/media/video/saa7134/saa7134-video.c +++ b/drivers/media/pci/saa7134/saa7134-video.c @@ -1953,11 +1953,12 @@ static int saa7134_g_crop(struct file *file, void *f, struct v4l2_crop *crop) return 0; } -static int saa7134_s_crop(struct file *file, void *f, struct v4l2_crop *crop) +static int saa7134_s_crop(struct file *file, void *f, const struct v4l2_crop *crop) { struct saa7134_fh *fh = f; struct saa7134_dev *dev = fh->dev; struct v4l2_rect *b = &dev->crop_bounds; + struct v4l2_rect *c = &dev->crop_current; if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE && crop->type != V4L2_BUF_TYPE_VIDEO_OVERLAY) @@ -1972,21 +1973,20 @@ static int saa7134_s_crop(struct file *file, void *f, struct v4l2_crop *crop) if (res_locked(fh->dev, RESOURCE_VIDEO)) return -EBUSY; - if (crop->c.top < b->top) - crop->c.top = b->top; - if (crop->c.top > b->top + b->height) - crop->c.top = b->top + b->height; - if (crop->c.height > b->top - crop->c.top + b->height) - crop->c.height = b->top - crop->c.top + b->height; - - if (crop->c.left < b->left) - crop->c.left = b->left; - if (crop->c.left > b->left + b->width) - crop->c.left = b->left + b->width; - if (crop->c.width > b->left - crop->c.left + b->width) - crop->c.width = b->left - crop->c.left + b->width; - - dev->crop_current = crop->c; + *c = crop->c; + if (c->top < b->top) + c->top = b->top; + if (c->top > b->top + b->height) + c->top = b->top + b->height; + if (c->height > b->top - c->top + b->height) + c->height = b->top - c->top + b->height; + + if (c->left < b->left) + c->left = b->left; + if (c->left > b->left + b->width) + c->left = b->left + b->width; + if (c->width > b->left - c->left + b->width) + c->width = b->left - c->left + b->width; return 0; } @@ -2089,7 +2089,7 @@ static int saa7134_g_audio(struct file *file, void *priv, struct v4l2_audio *a) return 0; } -static int saa7134_s_audio(struct file *file, void *priv, struct v4l2_audio *a) +static int saa7134_s_audio(struct file *file, void *priv, const struct v4l2_audio *a) { return 0; } @@ -2158,7 +2158,7 @@ static int saa7134_g_fbuf(struct file *file, void *f, } static int saa7134_s_fbuf(struct file *file, void *f, - struct v4l2_framebuffer *fb) + const struct v4l2_framebuffer *fb) { struct saa7134_fh *fh = f; struct saa7134_dev *dev = fh->dev; @@ -2373,7 +2373,7 @@ static int radio_g_audio(struct file *file, void *priv, } static int radio_s_audio(struct file *file, void *priv, - struct v4l2_audio *a) + const struct v4l2_audio *a) { return 0; } diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/pci/saa7134/saa7134.h index 89c8333736a2..c24b6512bd8f 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/pci/saa7134/saa7134.h @@ -130,7 +130,6 @@ struct saa7134_card_ir { u32 mask_keycode, mask_keydown, mask_keyup; bool running; - bool active; struct timer_list timer; diff --git a/drivers/media/pci/saa7146/Kconfig b/drivers/media/pci/saa7146/Kconfig new file mode 100644 index 000000000000..da88b77a916c --- /dev/null +++ b/drivers/media/pci/saa7146/Kconfig @@ -0,0 +1,38 @@ +config VIDEO_HEXIUM_GEMINI + tristate "Hexium Gemini frame grabber" + depends on PCI && VIDEO_V4L2 && I2C + select VIDEO_SAA7146_VV + ---help--- + This is a video4linux driver for the Hexium Gemini frame + grabber card by Hexium. Please note that the Gemini Dual + card is *not* fully supported. + + To compile this driver as a module, choose M here: the + module will be called hexium_gemini. + +config VIDEO_HEXIUM_ORION + tristate "Hexium HV-PCI6 and Orion frame grabber" + depends on PCI && VIDEO_V4L2 && I2C + select VIDEO_SAA7146_VV + ---help--- + This is a video4linux driver for the Hexium HV-PCI6 and + Orion frame grabber cards by Hexium. + + To compile this driver as a module, choose M here: the + module will be called hexium_orion. + +config VIDEO_MXB + tristate "Siemens-Nixdorf 'Multimedia eXtension Board'" + depends on PCI && VIDEO_V4L2 && I2C + select VIDEO_SAA7146_VV + select VIDEO_TUNER + select VIDEO_SAA711X if MEDIA_SUBDRV_AUTOSELECT + select VIDEO_TDA9840 if MEDIA_SUBDRV_AUTOSELECT + select VIDEO_TEA6415C if MEDIA_SUBDRV_AUTOSELECT + select VIDEO_TEA6420 if MEDIA_SUBDRV_AUTOSELECT + ---help--- + This is a video4linux driver for the 'Multimedia eXtension Board' + TV card by Siemens-Nixdorf. + + To compile this driver as a module, choose M here: the + module will be called mxb. diff --git a/drivers/media/pci/saa7146/Makefile b/drivers/media/pci/saa7146/Makefile new file mode 100644 index 000000000000..f3566a95e4aa --- /dev/null +++ b/drivers/media/pci/saa7146/Makefile @@ -0,0 +1,5 @@ +obj-$(CONFIG_VIDEO_MXB) += mxb.o +obj-$(CONFIG_VIDEO_HEXIUM_ORION) += hexium_orion.o +obj-$(CONFIG_VIDEO_HEXIUM_GEMINI) += hexium_gemini.o + +ccflags-y += -I$(srctree)/drivers/media/i2c diff --git a/drivers/media/video/hexium_gemini.c b/drivers/media/pci/saa7146/hexium_gemini.c index 366434f5647e..366434f5647e 100644 --- a/drivers/media/video/hexium_gemini.c +++ b/drivers/media/pci/saa7146/hexium_gemini.c diff --git a/drivers/media/video/hexium_orion.c b/drivers/media/pci/saa7146/hexium_orion.c index a1eb26d11070..a1eb26d11070 100644 --- a/drivers/media/video/hexium_orion.c +++ b/drivers/media/pci/saa7146/hexium_orion.c diff --git a/drivers/media/video/mxb.c b/drivers/media/pci/saa7146/mxb.c index b520a45cb3f3..91369daad722 100644 --- a/drivers/media/video/mxb.c +++ b/drivers/media/pci/saa7146/mxb.c @@ -646,7 +646,7 @@ static int vidioc_g_audio(struct file *file, void *fh, struct v4l2_audio *a) return 0; } -static int vidioc_s_audio(struct file *file, void *fh, struct v4l2_audio *a) +static int vidioc_s_audio(struct file *file, void *fh, const struct v4l2_audio *a) { struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; struct mxb *mxb = (struct mxb *)dev->ext_priv; diff --git a/drivers/media/video/saa7164/Kconfig b/drivers/media/pci/saa7164/Kconfig index 353263725172..a53db7d1c96e 100644 --- a/drivers/media/video/saa7164/Kconfig +++ b/drivers/media/pci/saa7164/Kconfig @@ -1,14 +1,14 @@ config VIDEO_SAA7164 tristate "NXP SAA7164 support" - depends on DVB_CORE && PCI && I2C + depends on DVB_CORE && VIDEO_DEV && PCI && I2C select I2C_ALGOBIT select FW_LOADER select VIDEO_TUNER select VIDEO_TVEEPROM select VIDEOBUF_DVB - select DVB_TDA10048 if !DVB_FE_CUSTOMISE - select DVB_S5H1411 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_TDA18271 if !MEDIA_TUNER_CUSTOMISE + select DVB_TDA10048 if MEDIA_SUBDRV_AUTOSELECT + select DVB_S5H1411 if MEDIA_SUBDRV_AUTOSELECT + select MEDIA_TUNER_TDA18271 if MEDIA_SUBDRV_AUTOSELECT ---help--- This is a video4linux driver for NXP SAA7164 based TV cards. diff --git a/drivers/media/video/saa7164/Makefile b/drivers/media/pci/saa7164/Makefile index 068443af30c8..ba0e33a1ee24 100644 --- a/drivers/media/video/saa7164/Makefile +++ b/drivers/media/pci/saa7164/Makefile @@ -4,9 +4,9 @@ saa7164-objs := saa7164-cards.o saa7164-core.o saa7164-i2c.o saa7164-dvb.o \ obj-$(CONFIG_VIDEO_SAA7164) += saa7164.o -ccflags-y += -I$(srctree)/drivers/media/video -ccflags-y += -I$(srctree)/drivers/media/common/tuners -ccflags-y += -I$(srctree)/drivers/media/dvb/dvb-core -ccflags-y += -I$(srctree)/drivers/media/dvb/frontends +ccflags-y += -I$(srctree)/drivers/media/i2c +ccflags-y += -I$(srctree)/drivers/media/tuners +ccflags-y += -I$(srctree)/drivers/media/dvb-core +ccflags-y += -I$(srctree)/drivers/media/dvb-frontends ccflags-y += $(extra-cflags-y) $(extra-cflags-m) diff --git a/drivers/media/video/saa7164/saa7164-api.c b/drivers/media/pci/saa7164/saa7164-api.c index c8799fdaae67..eff7135cf0e8 100644 --- a/drivers/media/video/saa7164/saa7164-api.c +++ b/drivers/media/pci/saa7164/saa7164-api.c @@ -670,7 +670,8 @@ int saa7164_api_set_dif(struct saa7164_port *port, u8 reg, u8 val) if (ret != SAA_OK) printk(KERN_ERR "%s() error, ret(2) = 0x%x\n", __func__, ret); #if 0 - saa7164_dumphex16(dev, buf, 16); + print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 1, buf, 16, + false); #endif return ret == SAA_OK ? 0 : -EIO; } @@ -1352,7 +1353,8 @@ int saa7164_api_enum_subdevs(struct saa7164_dev *dev) } if (saa_debug & DBGLVL_API) - saa7164_dumphex16(dev, buf, (buflen/16)*16); + print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 1, buf, + buflen & ~15, false); saa7164_api_dump_subdevs(dev, buf, buflen); @@ -1403,7 +1405,8 @@ int saa7164_api_i2c_read(struct saa7164_i2c *bus, u8 addr, u32 reglen, u8 *reg, dprintk(DBGLVL_API, "%s() len = %d bytes\n", __func__, len); if (saa_debug & DBGLVL_I2C) - saa7164_dumphex16(dev, buf, 2 * 16); + print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 1, buf, + 32, false); ret = saa7164_cmd_send(bus->dev, unitid, GET_CUR, EXU_REGISTER_ACCESS_CONTROL, len, &buf); @@ -1411,7 +1414,8 @@ int saa7164_api_i2c_read(struct saa7164_i2c *bus, u8 addr, u32 reglen, u8 *reg, printk(KERN_ERR "%s() error, ret(2) = 0x%x\n", __func__, ret); else { if (saa_debug & DBGLVL_I2C) - saa7164_dumphex16(dev, buf, sizeof(buf)); + print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 1, + buf, sizeof(buf), false); memcpy(data, (buf + 2 * sizeof(u32) + reglen), datalen); } @@ -1471,7 +1475,8 @@ int saa7164_api_i2c_write(struct saa7164_i2c *bus, u8 addr, u32 datalen, memcpy((buf + 2 * sizeof(u32)), data, datalen); if (saa_debug & DBGLVL_I2C) - saa7164_dumphex16(dev, buf, sizeof(buf)); + print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 1, + buf, sizeof(buf), false); ret = saa7164_cmd_send(bus->dev, unitid, SET_CUR, EXU_REGISTER_ACCESS_CONTROL, len, &buf); diff --git a/drivers/media/video/saa7164/saa7164-buffer.c b/drivers/media/pci/saa7164/saa7164-buffer.c index 66696fa8341d..66696fa8341d 100644 --- a/drivers/media/video/saa7164/saa7164-buffer.c +++ b/drivers/media/pci/saa7164/saa7164-buffer.c diff --git a/drivers/media/video/saa7164/saa7164-bus.c b/drivers/media/pci/saa7164/saa7164-bus.c index a7f58a998752..a7f58a998752 100644 --- a/drivers/media/video/saa7164/saa7164-bus.c +++ b/drivers/media/pci/saa7164/saa7164-bus.c diff --git a/drivers/media/video/saa7164/saa7164-cards.c b/drivers/media/pci/saa7164/saa7164-cards.c index 5b72da5ce418..5b72da5ce418 100644 --- a/drivers/media/video/saa7164/saa7164-cards.c +++ b/drivers/media/pci/saa7164/saa7164-cards.c diff --git a/drivers/media/video/saa7164/saa7164-cmd.c b/drivers/media/pci/saa7164/saa7164-cmd.c index 62fac7f9d04e..62fac7f9d04e 100644 --- a/drivers/media/video/saa7164/saa7164-cmd.c +++ b/drivers/media/pci/saa7164/saa7164-cmd.c diff --git a/drivers/media/video/saa7164/saa7164-core.c b/drivers/media/pci/saa7164/saa7164-core.c index 3b7d7b4e3034..2c9ad878bef3 100644 --- a/drivers/media/video/saa7164/saa7164-core.c +++ b/drivers/media/pci/saa7164/saa7164-core.c @@ -92,28 +92,6 @@ LIST_HEAD(saa7164_devlist); #define INT_SIZE 16 -void saa7164_dumphex16FF(struct saa7164_dev *dev, u8 *buf, int len) -{ - int i; - u8 tmp[16]; - memset(&tmp[0], 0xff, sizeof(tmp)); - - printk(KERN_INFO "--------------------> " - "00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f\n"); - - for (i = 0; i < len; i += 16) { - if (memcmp(&tmp, buf + i, sizeof(tmp)) != 0) { - printk(KERN_INFO " [0x%08x] " - "%02x %02x %02x %02x %02x %02x %02x %02x " - "%02x %02x %02x %02x %02x %02x %02x %02x\n", i, - *(buf+i+0), *(buf+i+1), *(buf+i+2), *(buf+i+3), - *(buf+i+4), *(buf+i+5), *(buf+i+6), *(buf+i+7), - *(buf+i+8), *(buf+i+9), *(buf+i+10), *(buf+i+11), - *(buf+i+12), *(buf+i+13), *(buf+i+14), *(buf+i+15)); - } - } -} - static void saa7164_pack_verifier(struct saa7164_buffer *buf) { u8 *p = (u8 *)buf->cpu; @@ -125,7 +103,8 @@ static void saa7164_pack_verifier(struct saa7164_buffer *buf) (*(p + i + 2) != 0x01) || (*(p + i + 3) != 0xBA)) { printk(KERN_ERR "No pack at 0x%x\n", i); #if 0 - saa7164_dumphex16FF(buf->port->dev, (p + i), 32); + print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 1, + p + 1, 32, false); #endif } } @@ -316,7 +295,8 @@ static void saa7164_work_enchandler_helper(struct saa7164_port *port, int bufnr) printk(KERN_ERR "%s() buf %p guard buffer breach\n", __func__, buf); #if 0 - saa7164_dumphex16FF(dev, (p + buf->actual_size) - 32 , 64); + print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 1, + p + buf->actual_size - 32, 64, false); #endif } } @@ -777,24 +757,6 @@ u32 saa7164_getcurrentfirmwareversion(struct saa7164_dev *dev) } /* TODO: Debugging func, remove */ -void saa7164_dumphex16(struct saa7164_dev *dev, u8 *buf, int len) -{ - int i; - - printk(KERN_INFO "--------------------> " - "00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f\n"); - - for (i = 0; i < len; i += 16) - printk(KERN_INFO " [0x%08x] " - "%02x %02x %02x %02x %02x %02x %02x %02x " - "%02x %02x %02x %02x %02x %02x %02x %02x\n", i, - *(buf+i+0), *(buf+i+1), *(buf+i+2), *(buf+i+3), - *(buf+i+4), *(buf+i+5), *(buf+i+6), *(buf+i+7), - *(buf+i+8), *(buf+i+9), *(buf+i+10), *(buf+i+11), - *(buf+i+12), *(buf+i+13), *(buf+i+14), *(buf+i+15)); -} - -/* TODO: Debugging func, remove */ void saa7164_dumpregs(struct saa7164_dev *dev, u32 addr) { int i; diff --git a/drivers/media/video/saa7164/saa7164-dvb.c b/drivers/media/pci/saa7164/saa7164-dvb.c index 5c5cc3ebf9bd..5c5cc3ebf9bd 100644 --- a/drivers/media/video/saa7164/saa7164-dvb.c +++ b/drivers/media/pci/saa7164/saa7164-dvb.c diff --git a/drivers/media/video/saa7164/saa7164-encoder.c b/drivers/media/pci/saa7164/saa7164-encoder.c index a9ed686ad08a..a9ed686ad08a 100644 --- a/drivers/media/video/saa7164/saa7164-encoder.c +++ b/drivers/media/pci/saa7164/saa7164-encoder.c diff --git a/drivers/media/video/saa7164/saa7164-fw.c b/drivers/media/pci/saa7164/saa7164-fw.c index a266bf0169e6..a266bf0169e6 100644 --- a/drivers/media/video/saa7164/saa7164-fw.c +++ b/drivers/media/pci/saa7164/saa7164-fw.c diff --git a/drivers/media/video/saa7164/saa7164-i2c.c b/drivers/media/pci/saa7164/saa7164-i2c.c index 4f7e3b42263f..4f7e3b42263f 100644 --- a/drivers/media/video/saa7164/saa7164-i2c.c +++ b/drivers/media/pci/saa7164/saa7164-i2c.c diff --git a/drivers/media/video/saa7164/saa7164-reg.h b/drivers/media/pci/saa7164/saa7164-reg.h index 2bbf81583d33..2bbf81583d33 100644 --- a/drivers/media/video/saa7164/saa7164-reg.h +++ b/drivers/media/pci/saa7164/saa7164-reg.h diff --git a/drivers/media/video/saa7164/saa7164-types.h b/drivers/media/pci/saa7164/saa7164-types.h index 1d2140a3eb38..1d2140a3eb38 100644 --- a/drivers/media/video/saa7164/saa7164-types.h +++ b/drivers/media/pci/saa7164/saa7164-types.h diff --git a/drivers/media/video/saa7164/saa7164-vbi.c b/drivers/media/pci/saa7164/saa7164-vbi.c index d8e6c8f14079..d8e6c8f14079 100644 --- a/drivers/media/video/saa7164/saa7164-vbi.c +++ b/drivers/media/pci/saa7164/saa7164-vbi.c diff --git a/drivers/media/video/saa7164/saa7164.h b/drivers/media/pci/saa7164/saa7164.h index 35219b9b0fbc..437284e747c9 100644 --- a/drivers/media/video/saa7164/saa7164.h +++ b/drivers/media/pci/saa7164/saa7164.h @@ -484,7 +484,6 @@ extern unsigned int vbi_buffers; /* ----------------------------------------------------------- */ /* saa7164-core.c */ void saa7164_dumpregs(struct saa7164_dev *dev, u32 addr); -void saa7164_dumphex16(struct saa7164_dev *dev, u8 *buf, int len); void saa7164_getfirmwarestatus(struct saa7164_dev *dev); u32 saa7164_getcurrentfirmwareversion(struct saa7164_dev *dev); void saa7164_histogram_update(struct saa7164_histogram *hg, u32 val); diff --git a/drivers/media/pci/sta2x11/Kconfig b/drivers/media/pci/sta2x11/Kconfig new file mode 100644 index 000000000000..6749f67cab8a --- /dev/null +++ b/drivers/media/pci/sta2x11/Kconfig @@ -0,0 +1,12 @@ +config STA2X11_VIP + tristate "STA2X11 VIP Video For Linux" + depends on STA2X11 + select VIDEO_ADV7180 if MEDIA_SUBDRV_AUTOSELECT + select VIDEOBUF_DMA_CONTIG + depends on PCI && VIDEO_V4L2 && VIRT_TO_BUS + help + Say Y for support for STA2X11 VIP (Video Input Port) capture + device. + + To compile this driver as a module, choose M here: the + module will be called sta2x11_vip. diff --git a/drivers/media/pci/sta2x11/Makefile b/drivers/media/pci/sta2x11/Makefile new file mode 100644 index 000000000000..d6c471d1d1b4 --- /dev/null +++ b/drivers/media/pci/sta2x11/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_STA2X11_VIP) += sta2x11_vip.o diff --git a/drivers/media/video/sta2x11_vip.c b/drivers/media/pci/sta2x11/sta2x11_vip.c index 4c10205264d4..4c10205264d4 100644 --- a/drivers/media/video/sta2x11_vip.c +++ b/drivers/media/pci/sta2x11/sta2x11_vip.c diff --git a/drivers/media/video/sta2x11_vip.h b/drivers/media/pci/sta2x11/sta2x11_vip.h index 4f81a13666eb..4f81a13666eb 100644 --- a/drivers/media/video/sta2x11_vip.h +++ b/drivers/media/pci/sta2x11/sta2x11_vip.h diff --git a/drivers/media/dvb/ttpci/Kconfig b/drivers/media/pci/ttpci/Kconfig index 9d83ced69dd6..314e417addae 100644 --- a/drivers/media/dvb/ttpci/Kconfig +++ b/drivers/media/pci/ttpci/Kconfig @@ -9,14 +9,14 @@ config DVB_AV7110 select TTPCI_EEPROM select VIDEO_SAA7146_VV depends on VIDEO_DEV # dependencies of VIDEO_SAA7146_VV - select DVB_VES1820 if !DVB_FE_CUSTOMISE - select DVB_VES1X93 if !DVB_FE_CUSTOMISE - select DVB_STV0299 if !DVB_FE_CUSTOMISE - select DVB_TDA8083 if !DVB_FE_CUSTOMISE - select DVB_SP8870 if !DVB_FE_CUSTOMISE - select DVB_STV0297 if !DVB_FE_CUSTOMISE - select DVB_L64781 if !DVB_FE_CUSTOMISE - select DVB_LNBP21 if !DVB_FE_CUSTOMISE + select DVB_VES1820 if MEDIA_SUBDRV_AUTOSELECT + select DVB_VES1X93 if MEDIA_SUBDRV_AUTOSELECT + select DVB_STV0299 if MEDIA_SUBDRV_AUTOSELECT + select DVB_TDA8083 if MEDIA_SUBDRV_AUTOSELECT + select DVB_SP8870 if MEDIA_SUBDRV_AUTOSELECT + select DVB_STV0297 if MEDIA_SUBDRV_AUTOSELECT + select DVB_L64781 if MEDIA_SUBDRV_AUTOSELECT + select DVB_LNBP21 if MEDIA_SUBDRV_AUTOSELECT help Support for SAA7146 and AV7110 based DVB cards as produced by Fujitsu-Siemens, Technotrend, Hauppauge and others. @@ -63,19 +63,19 @@ config DVB_BUDGET_CORE config DVB_BUDGET tristate "Budget cards" depends on DVB_BUDGET_CORE && I2C - select DVB_STV0299 if !DVB_FE_CUSTOMISE - select DVB_VES1X93 if !DVB_FE_CUSTOMISE - select DVB_VES1820 if !DVB_FE_CUSTOMISE - select DVB_L64781 if !DVB_FE_CUSTOMISE - select DVB_TDA8083 if !DVB_FE_CUSTOMISE - select DVB_S5H1420 if !DVB_FE_CUSTOMISE - select DVB_TDA10086 if !DVB_FE_CUSTOMISE - select DVB_TDA826X if !DVB_FE_CUSTOMISE - select DVB_LNBP21 if !DVB_FE_CUSTOMISE - select DVB_TDA1004X if !DVB_FE_CUSTOMISE - select DVB_ISL6423 if !DVB_FE_CUSTOMISE - select DVB_STV090x if !DVB_FE_CUSTOMISE - select DVB_STV6110x if !DVB_FE_CUSTOMISE + select DVB_STV0299 if MEDIA_SUBDRV_AUTOSELECT + select DVB_VES1X93 if MEDIA_SUBDRV_AUTOSELECT + select DVB_VES1820 if MEDIA_SUBDRV_AUTOSELECT + select DVB_L64781 if MEDIA_SUBDRV_AUTOSELECT + select DVB_TDA8083 if MEDIA_SUBDRV_AUTOSELECT + select DVB_S5H1420 if MEDIA_SUBDRV_AUTOSELECT + select DVB_TDA10086 if MEDIA_SUBDRV_AUTOSELECT + select DVB_TDA826X if MEDIA_SUBDRV_AUTOSELECT + select DVB_LNBP21 if MEDIA_SUBDRV_AUTOSELECT + select DVB_TDA1004X if MEDIA_SUBDRV_AUTOSELECT + select DVB_ISL6423 if MEDIA_SUBDRV_AUTOSELECT + select DVB_STV090x if MEDIA_SUBDRV_AUTOSELECT + select DVB_STV6110x if MEDIA_SUBDRV_AUTOSELECT help Support for simple SAA7146 based DVB cards (so called Budget- or Nova-PCI cards) without onboard MPEG2 decoder, and without @@ -89,16 +89,16 @@ config DVB_BUDGET config DVB_BUDGET_CI tristate "Budget cards with onboard CI connector" depends on DVB_BUDGET_CORE && I2C - select DVB_STV0297 if !DVB_FE_CUSTOMISE - select DVB_STV0299 if !DVB_FE_CUSTOMISE - select DVB_TDA1004X if !DVB_FE_CUSTOMISE - select DVB_STB0899 if !DVB_FE_CUSTOMISE - select DVB_STB6100 if !DVB_FE_CUSTOMISE - select DVB_LNBP21 if !DVB_FE_CUSTOMISE - select DVB_STV0288 if !DVB_FE_CUSTOMISE - select DVB_STB6000 if !DVB_FE_CUSTOMISE - select DVB_TDA10023 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_TDA827X if !MEDIA_TUNER_CUSTOMISE + select DVB_STV0297 if MEDIA_SUBDRV_AUTOSELECT + select DVB_STV0299 if MEDIA_SUBDRV_AUTOSELECT + select DVB_TDA1004X if MEDIA_SUBDRV_AUTOSELECT + select DVB_STB0899 if MEDIA_SUBDRV_AUTOSELECT + select DVB_STB6100 if MEDIA_SUBDRV_AUTOSELECT + select DVB_LNBP21 if MEDIA_SUBDRV_AUTOSELECT + select DVB_STV0288 if MEDIA_SUBDRV_AUTOSELECT + select DVB_STB6000 if MEDIA_SUBDRV_AUTOSELECT + select DVB_TDA10023 if MEDIA_SUBDRV_AUTOSELECT + select MEDIA_TUNER_TDA827X if MEDIA_SUBDRV_AUTOSELECT depends on RC_CORE help Support for simple SAA7146 based DVB cards @@ -118,14 +118,14 @@ config DVB_BUDGET_AV depends on DVB_BUDGET_CORE && I2C select VIDEO_SAA7146_VV depends on VIDEO_DEV # dependencies of VIDEO_SAA7146_VV - select DVB_PLL if !DVB_FE_CUSTOMISE - select DVB_STV0299 if !DVB_FE_CUSTOMISE - select DVB_TDA1004X if !DVB_FE_CUSTOMISE - select DVB_TDA10021 if !DVB_FE_CUSTOMISE - select DVB_TDA10023 if !DVB_FE_CUSTOMISE - select DVB_STB0899 if !DVB_FE_CUSTOMISE - select DVB_TDA8261 if !DVB_FE_CUSTOMISE - select DVB_TUA6100 if !DVB_FE_CUSTOMISE + select DVB_PLL if MEDIA_SUBDRV_AUTOSELECT + select DVB_STV0299 if MEDIA_SUBDRV_AUTOSELECT + select DVB_TDA1004X if MEDIA_SUBDRV_AUTOSELECT + select DVB_TDA10021 if MEDIA_SUBDRV_AUTOSELECT + select DVB_TDA10023 if MEDIA_SUBDRV_AUTOSELECT + select DVB_STB0899 if MEDIA_SUBDRV_AUTOSELECT + select DVB_TDA8261 if MEDIA_SUBDRV_AUTOSELECT + select DVB_TUA6100 if MEDIA_SUBDRV_AUTOSELECT help Support for simple SAA7146 based DVB cards (so called Budget- or Nova-PCI cards) without onboard @@ -140,9 +140,9 @@ config DVB_BUDGET_PATCH tristate "AV7110 cards with Budget Patch" depends on DVB_BUDGET_CORE && I2C depends on DVB_AV7110 - select DVB_STV0299 if !DVB_FE_CUSTOMISE - select DVB_VES1X93 if !DVB_FE_CUSTOMISE - select DVB_TDA8083 if !DVB_FE_CUSTOMISE + select DVB_STV0299 if MEDIA_SUBDRV_AUTOSELECT + select DVB_VES1X93 if MEDIA_SUBDRV_AUTOSELECT + select DVB_TDA8083 if MEDIA_SUBDRV_AUTOSELECT help Support for Budget Patch (full TS) modification on SAA7146+AV7110 based cards (DVB-S cards). This diff --git a/drivers/media/dvb/ttpci/Makefile b/drivers/media/pci/ttpci/Makefile index f6e869372e30..98905963ff08 100644 --- a/drivers/media/dvb/ttpci/Makefile +++ b/drivers/media/pci/ttpci/Makefile @@ -17,5 +17,5 @@ obj-$(CONFIG_DVB_BUDGET_CI) += budget-ci.o obj-$(CONFIG_DVB_BUDGET_PATCH) += budget-patch.o obj-$(CONFIG_DVB_AV7110) += dvb-ttpci.o -ccflags-y += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/ -ccflags-y += -Idrivers/media/common/tuners +ccflags-y += -Idrivers/media/dvb-core/ -Idrivers/media/dvb-frontends/ +ccflags-y += -Idrivers/media/tuners diff --git a/drivers/media/dvb/ttpci/av7110.c b/drivers/media/pci/ttpci/av7110.c index 4bd8bd56befc..4bd8bd56befc 100644 --- a/drivers/media/dvb/ttpci/av7110.c +++ b/drivers/media/pci/ttpci/av7110.c diff --git a/drivers/media/dvb/ttpci/av7110.h b/drivers/media/pci/ttpci/av7110.h index 88b3b2d6cc0e..88b3b2d6cc0e 100644 --- a/drivers/media/dvb/ttpci/av7110.h +++ b/drivers/media/pci/ttpci/av7110.h diff --git a/drivers/media/dvb/ttpci/av7110_av.c b/drivers/media/pci/ttpci/av7110_av.c index 952b33dbac4f..952b33dbac4f 100644 --- a/drivers/media/dvb/ttpci/av7110_av.c +++ b/drivers/media/pci/ttpci/av7110_av.c diff --git a/drivers/media/dvb/ttpci/av7110_av.h b/drivers/media/pci/ttpci/av7110_av.h index 5f02ef85e47d..5f02ef85e47d 100644 --- a/drivers/media/dvb/ttpci/av7110_av.h +++ b/drivers/media/pci/ttpci/av7110_av.h diff --git a/drivers/media/dvb/ttpci/av7110_ca.c b/drivers/media/pci/ttpci/av7110_ca.c index 9fc1dd0ba4c3..9fc1dd0ba4c3 100644 --- a/drivers/media/dvb/ttpci/av7110_ca.c +++ b/drivers/media/pci/ttpci/av7110_ca.c diff --git a/drivers/media/dvb/ttpci/av7110_ca.h b/drivers/media/pci/ttpci/av7110_ca.h index 70ee855ece1b..70ee855ece1b 100644 --- a/drivers/media/dvb/ttpci/av7110_ca.h +++ b/drivers/media/pci/ttpci/av7110_ca.h diff --git a/drivers/media/dvb/ttpci/av7110_hw.c b/drivers/media/pci/ttpci/av7110_hw.c index f1cbfe526989..f1cbfe526989 100644 --- a/drivers/media/dvb/ttpci/av7110_hw.c +++ b/drivers/media/pci/ttpci/av7110_hw.c diff --git a/drivers/media/dvb/ttpci/av7110_hw.h b/drivers/media/pci/ttpci/av7110_hw.h index 1634aba5cb84..1634aba5cb84 100644 --- a/drivers/media/dvb/ttpci/av7110_hw.h +++ b/drivers/media/pci/ttpci/av7110_hw.h diff --git a/drivers/media/dvb/ttpci/av7110_ipack.c b/drivers/media/pci/ttpci/av7110_ipack.c index 699ef8b5b99a..699ef8b5b99a 100644 --- a/drivers/media/dvb/ttpci/av7110_ipack.c +++ b/drivers/media/pci/ttpci/av7110_ipack.c diff --git a/drivers/media/dvb/ttpci/av7110_ipack.h b/drivers/media/pci/ttpci/av7110_ipack.h index becf94d3fdfa..becf94d3fdfa 100644 --- a/drivers/media/dvb/ttpci/av7110_ipack.h +++ b/drivers/media/pci/ttpci/av7110_ipack.h diff --git a/drivers/media/dvb/ttpci/av7110_ir.c b/drivers/media/pci/ttpci/av7110_ir.c index 908f272fe26c..908f272fe26c 100644 --- a/drivers/media/dvb/ttpci/av7110_ir.c +++ b/drivers/media/pci/ttpci/av7110_ir.c diff --git a/drivers/media/dvb/ttpci/av7110_v4l.c b/drivers/media/pci/ttpci/av7110_v4l.c index 1b2d15140a1d..730e906ea912 100644 --- a/drivers/media/dvb/ttpci/av7110_v4l.c +++ b/drivers/media/pci/ttpci/av7110_v4l.c @@ -526,7 +526,7 @@ static int vidioc_g_audio(struct file *file, void *fh, struct v4l2_audio *a) return 0; } -static int vidioc_s_audio(struct file *file, void *fh, struct v4l2_audio *a) +static int vidioc_s_audio(struct file *file, void *fh, const struct v4l2_audio *a) { struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; struct av7110 *av7110 = (struct av7110 *)dev->ext_priv; diff --git a/drivers/media/dvb/ttpci/budget-av.c b/drivers/media/pci/ttpci/budget-av.c index 12ddb53c58dc..12ddb53c58dc 100644 --- a/drivers/media/dvb/ttpci/budget-av.c +++ b/drivers/media/pci/ttpci/budget-av.c diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/pci/ttpci/budget-ci.c index 98e524178765..98e524178765 100644 --- a/drivers/media/dvb/ttpci/budget-ci.c +++ b/drivers/media/pci/ttpci/budget-ci.c diff --git a/drivers/media/dvb/ttpci/budget-core.c b/drivers/media/pci/ttpci/budget-core.c index 37d02fe09137..37d02fe09137 100644 --- a/drivers/media/dvb/ttpci/budget-core.c +++ b/drivers/media/pci/ttpci/budget-core.c diff --git a/drivers/media/dvb/ttpci/budget-patch.c b/drivers/media/pci/ttpci/budget-patch.c index 2cb35c23d2ac..2cb35c23d2ac 100644 --- a/drivers/media/dvb/ttpci/budget-patch.c +++ b/drivers/media/pci/ttpci/budget-patch.c diff --git a/drivers/media/dvb/ttpci/budget.c b/drivers/media/pci/ttpci/budget.c index b21bcce66708..7e6e43ae5c51 100644 --- a/drivers/media/dvb/ttpci/budget.c +++ b/drivers/media/pci/ttpci/budget.c @@ -50,6 +50,8 @@ #include "stv6110x.h" #include "stv090x.h" #include "isl6423.h" +#include "lnbh24.h" + static int diseqc_method; module_param(diseqc_method, int, 0444); @@ -679,6 +681,62 @@ static void frontend_init(struct budget *budget) } } break; + + case 0x1020: { /* Omicom S2 */ + struct stv6110x_devctl *ctl; + saa7146_setgpio(budget->dev, 2, SAA7146_GPIO_OUTLO); + msleep(50); + saa7146_setgpio(budget->dev, 2, SAA7146_GPIO_OUTHI); + msleep(250); + + budget->dvb_frontend = dvb_attach(stv090x_attach, + &tt1600_stv090x_config, + &budget->i2c_adap, + STV090x_DEMODULATOR_0); + + if (budget->dvb_frontend) { + printk(KERN_INFO "budget: Omicom S2 detected\n"); + + ctl = dvb_attach(stv6110x_attach, + budget->dvb_frontend, + &tt1600_stv6110x_config, + &budget->i2c_adap); + + if (ctl) { + tt1600_stv090x_config.tuner_init = ctl->tuner_init; + tt1600_stv090x_config.tuner_sleep = ctl->tuner_sleep; + tt1600_stv090x_config.tuner_set_mode = ctl->tuner_set_mode; + tt1600_stv090x_config.tuner_set_frequency = ctl->tuner_set_frequency; + tt1600_stv090x_config.tuner_get_frequency = ctl->tuner_get_frequency; + tt1600_stv090x_config.tuner_set_bandwidth = ctl->tuner_set_bandwidth; + tt1600_stv090x_config.tuner_get_bandwidth = ctl->tuner_get_bandwidth; + tt1600_stv090x_config.tuner_set_bbgain = ctl->tuner_set_bbgain; + tt1600_stv090x_config.tuner_get_bbgain = ctl->tuner_get_bbgain; + tt1600_stv090x_config.tuner_set_refclk = ctl->tuner_set_refclk; + tt1600_stv090x_config.tuner_get_status = ctl->tuner_get_status; + + /* call the init function once to initialize + tuner's clock output divider and demod's + master clock */ + if (budget->dvb_frontend->ops.init) + budget->dvb_frontend->ops.init(budget->dvb_frontend); + + if (dvb_attach(lnbh24_attach, + budget->dvb_frontend, + &budget->i2c_adap, + LNBH24_PCL | LNBH24_TTX, + LNBH24_TEN, 0x14>>1) == NULL) { + printk(KERN_ERR + "No LNBH24 found!\n"); + goto error_out; + } + } else { + printk(KERN_ERR "%s: No STV6110(A) Silicon Tuner found!\n", __func__); + goto error_out; + } + } + } + break; } if (budget->dvb_frontend == NULL) { @@ -759,6 +817,7 @@ MAKE_BUDGET_INFO(fsacs0, "Fujitsu Siemens Activy Budget-S PCI (rev GR/grundig fr MAKE_BUDGET_INFO(fsacs1, "Fujitsu Siemens Activy Budget-S PCI (rev AL/alps frontend)", BUDGET_FS_ACTIVY); MAKE_BUDGET_INFO(fsact, "Fujitsu Siemens Activy Budget-T PCI (rev GR/Grundig frontend)", BUDGET_FS_ACTIVY); MAKE_BUDGET_INFO(fsact1, "Fujitsu Siemens Activy Budget-T PCI (rev AL/ALPS TDHD1-204A)", BUDGET_FS_ACTIVY); +MAKE_BUDGET_INFO(omicom, "Omicom S2 PCI", BUDGET_TT); static struct pci_device_id pci_tbl[] = { MAKE_EXTENSION_PCI(ttbs, 0x13c2, 0x1003), @@ -772,6 +831,7 @@ static struct pci_device_id pci_tbl[] = { MAKE_EXTENSION_PCI(fsacs0,0x1131, 0x4f61), MAKE_EXTENSION_PCI(fsact1, 0x1131, 0x5f60), MAKE_EXTENSION_PCI(fsact, 0x1131, 0x5f61), + MAKE_EXTENSION_PCI(omicom, 0x14c4, 0x1020), { .vendor = 0, } diff --git a/drivers/media/dvb/ttpci/budget.h b/drivers/media/pci/ttpci/budget.h index 3d8a806c20bb..3d8a806c20bb 100644 --- a/drivers/media/dvb/ttpci/budget.h +++ b/drivers/media/pci/ttpci/budget.h diff --git a/drivers/media/dvb/ttpci/ttpci-eeprom.c b/drivers/media/pci/ttpci/ttpci-eeprom.c index 32d43156c548..32d43156c548 100644 --- a/drivers/media/dvb/ttpci/ttpci-eeprom.c +++ b/drivers/media/pci/ttpci/ttpci-eeprom.c diff --git a/drivers/media/dvb/ttpci/ttpci-eeprom.h b/drivers/media/pci/ttpci/ttpci-eeprom.h index dcc33d5a5cb1..dcc33d5a5cb1 100644 --- a/drivers/media/dvb/ttpci/ttpci-eeprom.h +++ b/drivers/media/pci/ttpci/ttpci-eeprom.h diff --git a/drivers/media/video/zoran/Kconfig b/drivers/media/pci/zoran/Kconfig index fd4120e4c104..26ca8702e33f 100644 --- a/drivers/media/video/zoran/Kconfig +++ b/drivers/media/pci/zoran/Kconfig @@ -14,8 +14,8 @@ config VIDEO_ZORAN config VIDEO_ZORAN_DC30 tristate "Pinnacle/Miro DC30(+) support" depends on VIDEO_ZORAN - select VIDEO_ADV7175 if VIDEO_HELPER_CHIPS_AUTO - select VIDEO_VPX3220 if VIDEO_HELPER_CHIPS_AUTO + select VIDEO_ADV7175 if MEDIA_SUBDRV_AUTOSELECT + select VIDEO_VPX3220 if MEDIA_SUBDRV_AUTOSELECT help Support for the Pinnacle/Miro DC30(+) MJPEG capture/playback card. This also supports really old DC10 cards based on the @@ -32,16 +32,16 @@ config VIDEO_ZORAN_ZR36060 config VIDEO_ZORAN_BUZ tristate "Iomega Buz support" depends on VIDEO_ZORAN_ZR36060 - select VIDEO_SAA711X if VIDEO_HELPER_CHIPS_AUTO - select VIDEO_SAA7185 if VIDEO_HELPER_CHIPS_AUTO + select VIDEO_SAA711X if MEDIA_SUBDRV_AUTOSELECT + select VIDEO_SAA7185 if MEDIA_SUBDRV_AUTOSELECT help Support for the Iomega Buz MJPEG capture/playback card. config VIDEO_ZORAN_DC10 tristate "Pinnacle/Miro DC10(+) support" depends on VIDEO_ZORAN_ZR36060 - select VIDEO_SAA7110 if VIDEO_HELPER_CHIPS_AUTO - select VIDEO_ADV7175 if VIDEO_HELPER_CHIPS_AUTO + select VIDEO_SAA7110 if MEDIA_SUBDRV_AUTOSELECT + select VIDEO_ADV7175 if MEDIA_SUBDRV_AUTOSELECT help Support for the Pinnacle/Miro DC10(+) MJPEG capture/playback card. @@ -49,8 +49,8 @@ config VIDEO_ZORAN_DC10 config VIDEO_ZORAN_LML33 tristate "Linux Media Labs LML33 support" depends on VIDEO_ZORAN_ZR36060 - select VIDEO_BT819 if VIDEO_HELPER_CHIPS_AUTO - select VIDEO_BT856 if VIDEO_HELPER_CHIPS_AUTO + select VIDEO_BT819 if MEDIA_SUBDRV_AUTOSELECT + select VIDEO_BT856 if MEDIA_SUBDRV_AUTOSELECT help Support for the Linux Media Labs LML33 MJPEG capture/playback card. @@ -58,17 +58,17 @@ config VIDEO_ZORAN_LML33 config VIDEO_ZORAN_LML33R10 tristate "Linux Media Labs LML33R10 support" depends on VIDEO_ZORAN_ZR36060 - select VIDEO_SAA711X if VIDEO_HELPER_CHIPS_AUTO - select VIDEO_ADV7170 if VIDEO_HELPER_CHIPS_AUTO + select VIDEO_SAA711X if MEDIA_SUBDRV_AUTOSELECT + select VIDEO_ADV7170 if MEDIA_SUBDRV_AUTOSELECT help support for the Linux Media Labs LML33R10 MJPEG capture/playback card. config VIDEO_ZORAN_AVS6EYES - tristate "AverMedia 6 Eyes support (EXPERIMENTAL)" - depends on VIDEO_ZORAN_ZR36060 && EXPERIMENTAL - select VIDEO_BT856 if VIDEO_HELPER_CHIPS_AUTO - select VIDEO_BT866 if VIDEO_HELPER_CHIPS_AUTO - select VIDEO_KS0127 if VIDEO_HELPER_CHIPS_AUTO + tristate "AverMedia 6 Eyes support" + depends on VIDEO_ZORAN_ZR36060 + select VIDEO_BT856 if MEDIA_SUBDRV_AUTOSELECT + select VIDEO_BT866 if MEDIA_SUBDRV_AUTOSELECT + select VIDEO_KS0127 if MEDIA_SUBDRV_AUTOSELECT help Support for the AverMedia 6 Eyes video surveillance card. diff --git a/drivers/media/video/zoran/Makefile b/drivers/media/pci/zoran/Makefile index 44cc13352c88..44cc13352c88 100644 --- a/drivers/media/video/zoran/Makefile +++ b/drivers/media/pci/zoran/Makefile diff --git a/drivers/media/video/zoran/videocodec.c b/drivers/media/pci/zoran/videocodec.c index c01071635290..c01071635290 100644 --- a/drivers/media/video/zoran/videocodec.c +++ b/drivers/media/pci/zoran/videocodec.c diff --git a/drivers/media/video/zoran/videocodec.h b/drivers/media/pci/zoran/videocodec.h index def55585ad23..def55585ad23 100644 --- a/drivers/media/video/zoran/videocodec.h +++ b/drivers/media/pci/zoran/videocodec.h diff --git a/drivers/media/video/zoran/zoran.h b/drivers/media/pci/zoran/zoran.h index ca2754a3cd63..ca2754a3cd63 100644 --- a/drivers/media/video/zoran/zoran.h +++ b/drivers/media/pci/zoran/zoran.h diff --git a/drivers/media/video/zoran/zoran_card.c b/drivers/media/pci/zoran/zoran_card.c index c3602d6cd48e..fffc54b452c8 100644 --- a/drivers/media/video/zoran/zoran_card.c +++ b/drivers/media/pci/zoran/zoran_card.c @@ -1055,6 +1055,10 @@ zr36057_init (struct zoran *zr) memcpy(zr->video_dev, &zoran_template, sizeof(zoran_template)); zr->video_dev->parent = &zr->pci_dev->dev; strcpy(zr->video_dev->name, ZR_DEVNAME(zr)); + /* It's not a mem2mem device, but you can both capture and output from + one and the same device. This should really be split up into two + device nodes, but that's a job for another day. */ + zr->video_dev->vfl_dir = VFL_DIR_M2M; err = video_register_device(zr->video_dev, VFL_TYPE_GRABBER, video_nr[zr->id]); if (err < 0) goto exit_free; diff --git a/drivers/media/video/zoran/zoran_card.h b/drivers/media/pci/zoran/zoran_card.h index 4936fead73e8..4936fead73e8 100644 --- a/drivers/media/video/zoran/zoran_card.h +++ b/drivers/media/pci/zoran/zoran_card.h diff --git a/drivers/media/video/zoran/zoran_device.c b/drivers/media/pci/zoran/zoran_device.c index a4cd504b8eee..a4cd504b8eee 100644 --- a/drivers/media/video/zoran/zoran_device.c +++ b/drivers/media/pci/zoran/zoran_device.c diff --git a/drivers/media/video/zoran/zoran_device.h b/drivers/media/pci/zoran/zoran_device.h index 07f2c23ff740..07f2c23ff740 100644 --- a/drivers/media/video/zoran/zoran_device.h +++ b/drivers/media/pci/zoran/zoran_device.h diff --git a/drivers/media/video/zoran/zoran_driver.c b/drivers/media/pci/zoran/zoran_driver.c index c6ccdeb6d8d6..53f12c7466b0 100644 --- a/drivers/media/video/zoran/zoran_driver.c +++ b/drivers/media/pci/zoran/zoran_driver.c @@ -1978,7 +1978,7 @@ static int zoran_g_fbuf(struct file *file, void *__fh, } static int zoran_s_fbuf(struct file *file, void *__fh, - struct v4l2_framebuffer *fb) + const struct v4l2_framebuffer *fb) { struct zoran_fh *fh = __fh; struct zoran *zr = fh->zr; @@ -2598,7 +2598,7 @@ gcrop_unlock_and_return: return res; } -static int zoran_s_crop(struct file *file, void *__fh, struct v4l2_crop *crop) +static int zoran_s_crop(struct file *file, void *__fh, const struct v4l2_crop *crop) { struct zoran_fh *fh = __fh; struct zoran *zr = fh->zr; @@ -2674,7 +2674,7 @@ static int zoran_g_jpegcomp(struct file *file, void *__fh, } static int zoran_s_jpegcomp(struct file *file, void *__fh, - struct v4l2_jpegcompression *params) + const struct v4l2_jpegcompression *params) { struct zoran_fh *fh = __fh; struct zoran *zr = fh->zr; @@ -2701,7 +2701,7 @@ static int zoran_s_jpegcomp(struct file *file, void *__fh, if (!fh->buffers.allocated) fh->buffers.buffer_size = zoran_v4l2_calc_bufsize(&fh->jpg_settings); - fh->jpg_settings.jpg_comp = *params = settings.jpg_comp; + fh->jpg_settings.jpg_comp = settings.jpg_comp; sjpegc_unlock_and_return: mutex_unlock(&zr->resource_lock); diff --git a/drivers/media/video/zoran/zoran_procfs.c b/drivers/media/pci/zoran/zoran_procfs.c index f1423b777db1..f1423b777db1 100644 --- a/drivers/media/video/zoran/zoran_procfs.c +++ b/drivers/media/pci/zoran/zoran_procfs.c diff --git a/drivers/media/video/zoran/zoran_procfs.h b/drivers/media/pci/zoran/zoran_procfs.h index f2d5b1ba448f..f2d5b1ba448f 100644 --- a/drivers/media/video/zoran/zoran_procfs.h +++ b/drivers/media/pci/zoran/zoran_procfs.h diff --git a/drivers/media/video/zoran/zr36016.c b/drivers/media/pci/zoran/zr36016.c index b87ddba8608f..b87ddba8608f 100644 --- a/drivers/media/video/zoran/zr36016.c +++ b/drivers/media/pci/zoran/zr36016.c diff --git a/drivers/media/video/zoran/zr36016.h b/drivers/media/pci/zoran/zr36016.h index 8c79229f69d1..8c79229f69d1 100644 --- a/drivers/media/video/zoran/zr36016.h +++ b/drivers/media/pci/zoran/zr36016.h diff --git a/drivers/media/video/zoran/zr36050.c b/drivers/media/pci/zoran/zr36050.c index e1985609af4b..e1985609af4b 100644 --- a/drivers/media/video/zoran/zr36050.c +++ b/drivers/media/pci/zoran/zr36050.c diff --git a/drivers/media/video/zoran/zr36050.h b/drivers/media/pci/zoran/zr36050.h index 9f52f0cdde50..9f52f0cdde50 100644 --- a/drivers/media/video/zoran/zr36050.h +++ b/drivers/media/pci/zoran/zr36050.h diff --git a/drivers/media/video/zoran/zr36057.h b/drivers/media/pci/zoran/zr36057.h index 54c9362aa980..54c9362aa980 100644 --- a/drivers/media/video/zoran/zr36057.h +++ b/drivers/media/pci/zoran/zr36057.h diff --git a/drivers/media/video/zoran/zr36060.c b/drivers/media/pci/zoran/zr36060.c index f08546fe2234..f08546fe2234 100644 --- a/drivers/media/video/zoran/zr36060.c +++ b/drivers/media/pci/zoran/zr36060.c diff --git a/drivers/media/video/zoran/zr36060.h b/drivers/media/pci/zoran/zr36060.h index 914ffa4ad8d3..914ffa4ad8d3 100644 --- a/drivers/media/video/zoran/zr36060.h +++ b/drivers/media/pci/zoran/zr36060.h diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig new file mode 100644 index 000000000000..f588d6296c76 --- /dev/null +++ b/drivers/media/platform/Kconfig @@ -0,0 +1,223 @@ +# +# Platform drivers +# All drivers here are currently for webcam support + +menuconfig V4L_PLATFORM_DRIVERS + bool "V4L platform devices" + depends on MEDIA_CAMERA_SUPPORT + default n + ---help--- + Say Y here to enable support for platform-specific V4L drivers. + +if V4L_PLATFORM_DRIVERS + +source "drivers/media/platform/marvell-ccic/Kconfig" + +config VIDEO_VIA_CAMERA + tristate "VIAFB camera controller support" + depends on FB_VIA + select VIDEOBUF_DMA_SG + select VIDEO_OV7670 + help + Driver support for the integrated camera controller in VIA + Chrome9 chipsets. Currently only tested on OLPC xo-1.5 systems + with ov7670 sensors. + +# +# Platform multimedia device configuration +# + +source "drivers/media/platform/davinci/Kconfig" + +source "drivers/media/platform/omap/Kconfig" + +source "drivers/media/platform/blackfin/Kconfig" + +config VIDEO_SH_VOU + tristate "SuperH VOU video output driver" + depends on MEDIA_CAMERA_SUPPORT + depends on VIDEO_DEV && ARCH_SHMOBILE + select VIDEOBUF_DMA_CONTIG + help + Support for the Video Output Unit (VOU) on SuperH SoCs. + +config VIDEO_VIU + tristate "Freescale VIU Video Driver" + depends on VIDEO_V4L2 && PPC_MPC512x + select VIDEOBUF_DMA_CONTIG + default y + ---help--- + Support for Freescale VIU video driver. This device captures + video data, or overlays video on DIU frame buffer. + + Say Y here if you want to enable VIU device on MPC5121e Rev2+. + In doubt, say N. + +config VIDEO_TIMBERDALE + tristate "Support for timberdale Video In/LogiWIN" + depends on VIDEO_V4L2 && I2C && DMADEVICES + select DMA_ENGINE + select TIMB_DMA + select VIDEO_ADV7180 + select VIDEOBUF_DMA_CONTIG + ---help--- + Add support for the Video In peripherial of the timberdale FPGA. + +config VIDEO_VINO + tristate "SGI Vino Video For Linux" + depends on I2C && SGI_IP22 && VIDEO_V4L2 + select VIDEO_SAA7191 if MEDIA_SUBDRV_AUTOSELECT + help + Say Y here to build in support for the Vino video input system found + on SGI Indy machines. + +config VIDEO_M32R_AR + tristate "AR devices" + depends on M32R && VIDEO_V4L2 + ---help--- + This is a video4linux driver for the Renesas AR (Artificial Retina) + camera module. + +config VIDEO_M32R_AR_M64278 + tristate "AR device with color module M64278(VGA)" + depends on PLAT_M32700UT + select VIDEO_M32R_AR + ---help--- + This is a video4linux driver for the Renesas AR (Artificial + Retina) with M64278E-800 camera module. + This module supports VGA(640x480 pixels) resolutions. + + To compile this driver as a module, choose M here: the + module will be called arv. + +config VIDEO_OMAP2 + tristate "OMAP2 Camera Capture Interface driver" + depends on VIDEO_DEV && ARCH_OMAP2 + select VIDEOBUF_DMA_SG + ---help--- + This is a v4l2 driver for the TI OMAP2 camera capture interface + +config VIDEO_OMAP3 + tristate "OMAP 3 Camera support (EXPERIMENTAL)" + depends on OMAP_IOVMM && VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API && ARCH_OMAP3 && EXPERIMENTAL + ---help--- + Driver for an OMAP 3 camera controller. + +config VIDEO_OMAP3_DEBUG + bool "OMAP 3 Camera debug messages" + depends on VIDEO_OMAP3 + ---help--- + Enable debug messages on OMAP 3 camera controller driver. + +source "drivers/media/platform/soc_camera/Kconfig" +source "drivers/media/platform/s5p-fimc/Kconfig" +source "drivers/media/platform/s5p-tv/Kconfig" + +endif # V4L_PLATFORM_DRIVERS + +menuconfig V4L_MEM2MEM_DRIVERS + bool "Memory-to-memory multimedia devices" + depends on VIDEO_V4L2 + depends on MEDIA_CAMERA_SUPPORT + default n + ---help--- + Say Y here to enable selecting drivers for V4L devices that + use system memory for both source and destination buffers, as opposed + to capture and output drivers, which use memory buffers for just + one of those. + +if V4L_MEM2MEM_DRIVERS + +config VIDEO_CODA + tristate "Chips&Media Coda multi-standard codec IP" + depends on VIDEO_DEV && VIDEO_V4L2 && ARCH_MXC + select VIDEOBUF2_DMA_CONTIG + select V4L2_MEM2MEM_DEV + select IRAM_ALLOC if SOC_IMX53 + ---help--- + Coda is a range of video codec IPs that supports + H.264, MPEG-4, and other video formats. + +config VIDEO_MEM2MEM_DEINTERLACE + tristate "Deinterlace support" + depends on VIDEO_DEV && VIDEO_V4L2 && DMA_ENGINE + select VIDEOBUF2_DMA_CONTIG + select V4L2_MEM2MEM_DEV + help + Generic deinterlacing V4L2 driver. + +config VIDEO_SAMSUNG_S5P_G2D + tristate "Samsung S5P and EXYNOS4 G2D 2d graphics accelerator driver" + depends on VIDEO_DEV && VIDEO_V4L2 && PLAT_S5P + select VIDEOBUF2_DMA_CONTIG + select V4L2_MEM2MEM_DEV + default n + ---help--- + This is a v4l2 driver for Samsung S5P and EXYNOS4 G2D + 2d graphics accelerator. + +config VIDEO_SAMSUNG_S5P_JPEG + tristate "Samsung S5P/Exynos4 JPEG codec driver (EXPERIMENTAL)" + depends on VIDEO_DEV && VIDEO_V4L2 && PLAT_S5P && EXPERIMENTAL + select VIDEOBUF2_DMA_CONTIG + select V4L2_MEM2MEM_DEV + ---help--- + This is a v4l2 driver for Samsung S5P and EXYNOS4 JPEG codec + +config VIDEO_SAMSUNG_S5P_MFC + tristate "Samsung S5P MFC 5.1 Video Codec" + depends on VIDEO_DEV && VIDEO_V4L2 && PLAT_S5P + select VIDEOBUF2_DMA_CONTIG + default n + help + MFC 5.1 driver for V4L2. + +config VIDEO_MX2_EMMAPRP + tristate "MX2 eMMa-PrP support" + depends on VIDEO_DEV && VIDEO_V4L2 && SOC_IMX27 + select VIDEOBUF2_DMA_CONTIG + select V4L2_MEM2MEM_DEV + help + MX2X chips have a PrP that can be used to process buffers from + memory to memory. Operations include resizing and format + conversion. + +config VIDEO_SAMSUNG_EXYNOS_GSC + tristate "Samsung Exynos G-Scaler driver" + depends on VIDEO_DEV && VIDEO_V4L2 && ARCH_EXYNOS5 + select VIDEOBUF2_DMA_CONTIG + select V4L2_MEM2MEM_DEV + help + This is a v4l2 driver for Samsung EXYNOS5 SoC G-Scaler. + +endif # V4L_MEM2MEM_DRIVERS + +menuconfig V4L_TEST_DRIVERS + bool "Media test drivers" + depends on MEDIA_CAMERA_SUPPORT + +if V4L_TEST_DRIVERS +config VIDEO_VIVI + tristate "Virtual Video Driver" + depends on VIDEO_DEV && VIDEO_V4L2 && !SPARC32 && !SPARC64 + depends on FRAMEBUFFER_CONSOLE || STI_CONSOLE + select FONT_8x16 + select VIDEOBUF2_VMALLOC + default n + ---help--- + Enables a virtual video driver. This device shows a color bar + and a timestamp, as a real device would generate by using V4L2 + api. + Say Y here if you want to test video apps or debug V4L devices. + In doubt, say N. + +config VIDEO_MEM2MEM_TESTDEV + tristate "Virtual test device for mem2mem framework" + depends on VIDEO_DEV && VIDEO_V4L2 + select VIDEOBUF2_VMALLOC + select V4L2_MEM2MEM_DEV + default n + ---help--- + This is a virtual test device for the memory-to-memory driver + framework. +endif #V4L_TEST_DRIVERS diff --git a/drivers/media/platform/Makefile b/drivers/media/platform/Makefile new file mode 100644 index 000000000000..baaa55026c8e --- /dev/null +++ b/drivers/media/platform/Makefile @@ -0,0 +1,50 @@ +# +# Makefile for the video capture/playback device drivers. +# + +omap2cam-objs := omap24xxcam.o omap24xxcam-dma.o + +obj-$(CONFIG_VIDEO_VINO) += indycam.o +obj-$(CONFIG_VIDEO_VINO) += vino.o + +obj-$(CONFIG_VIDEO_TIMBERDALE) += timblogiw.o +obj-$(CONFIG_VIDEO_M32R_AR_M64278) += arv.o + +obj-$(CONFIG_VIDEO_VIA_CAMERA) += via-camera.o +obj-$(CONFIG_VIDEO_CAFE_CCIC) += marvell-ccic/ +obj-$(CONFIG_VIDEO_MMP_CAMERA) += marvell-ccic/ + +obj-$(CONFIG_VIDEO_OMAP2) += omap2cam.o +obj-$(CONFIG_VIDEO_OMAP3) += omap3isp/ + +obj-$(CONFIG_VIDEO_VIU) += fsl-viu.o +obj-$(CONFIG_VIDEO_VIVI) += vivi.o + +obj-$(CONFIG_VIDEO_MEM2MEM_TESTDEV) += mem2mem_testdev.o + +obj-$(CONFIG_VIDEO_MX2_EMMAPRP) += mx2_emmaprp.o +obj-$(CONFIG_VIDEO_CODA) += coda.o + +obj-$(CONFIG_VIDEO_MEM2MEM_DEINTERLACE) += m2m-deinterlace.o + +obj-$(CONFIG_VIDEO_SAMSUNG_S5P_FIMC) += s5p-fimc/ +obj-$(CONFIG_VIDEO_SAMSUNG_S5P_JPEG) += s5p-jpeg/ +obj-$(CONFIG_VIDEO_SAMSUNG_S5P_MFC) += s5p-mfc/ +obj-$(CONFIG_VIDEO_SAMSUNG_S5P_TV) += s5p-tv/ + +obj-$(CONFIG_VIDEO_SAMSUNG_S5P_G2D) += s5p-g2d/ +obj-$(CONFIG_VIDEO_SAMSUNG_EXYNOS_GSC) += exynos-gsc/ + +obj-$(CONFIG_BLACKFIN) += blackfin/ + +obj-$(CONFIG_ARCH_DAVINCI) += davinci/ + +obj-$(CONFIG_VIDEO_SH_VOU) += sh_vou.o + +obj-$(CONFIG_SOC_CAMERA) += soc_camera/ + +obj-y += davinci/ + +obj-$(CONFIG_ARCH_OMAP) += omap/ + +ccflags-y += -I$(srctree)/drivers/media/i2c diff --git a/drivers/media/video/arv.c b/drivers/media/platform/arv.c index e346d32d08ce..e346d32d08ce 100644 --- a/drivers/media/video/arv.c +++ b/drivers/media/platform/arv.c diff --git a/drivers/media/video/blackfin/Kconfig b/drivers/media/platform/blackfin/Kconfig index ecd5323768b7..ecd5323768b7 100644 --- a/drivers/media/video/blackfin/Kconfig +++ b/drivers/media/platform/blackfin/Kconfig diff --git a/drivers/media/video/blackfin/Makefile b/drivers/media/platform/blackfin/Makefile index aa3a0a216387..aa3a0a216387 100644 --- a/drivers/media/video/blackfin/Makefile +++ b/drivers/media/platform/blackfin/Makefile diff --git a/drivers/media/video/blackfin/bfin_capture.c b/drivers/media/platform/blackfin/bfin_capture.c index 0aba45e34f70..cb2eb26850b1 100644 --- a/drivers/media/video/blackfin/bfin_capture.c +++ b/drivers/media/platform/blackfin/bfin_capture.c @@ -235,8 +235,13 @@ static int bcap_release(struct file *file) static int bcap_mmap(struct file *file, struct vm_area_struct *vma) { struct bcap_device *bcap_dev = video_drvdata(file); + int ret; - return vb2_mmap(&bcap_dev->buffer_queue, vma); + if (mutex_lock_interruptible(&bcap_dev->mutex)) + return -ERESTARTSYS; + ret = vb2_mmap(&bcap_dev->buffer_queue, vma); + mutex_unlock(&bcap_dev->mutex); + return ret; } #ifndef CONFIG_MMU @@ -259,8 +264,12 @@ static unsigned long bcap_get_unmapped_area(struct file *file, static unsigned int bcap_poll(struct file *file, poll_table *wait) { struct bcap_device *bcap_dev = video_drvdata(file); + unsigned int res; - return vb2_poll(&bcap_dev->buffer_queue, file, wait); + mutex_lock(&bcap_dev->mutex); + res = vb2_poll(&bcap_dev->buffer_queue, file, wait); + mutex_unlock(&bcap_dev->mutex); + return res; } static int bcap_queue_setup(struct vb2_queue *vq, @@ -942,10 +951,6 @@ static int __devinit bcap_probe(struct platform_device *pdev) INIT_LIST_HEAD(&bcap_dev->dma_queue); vfd->lock = &bcap_dev->mutex; - /* Locking in file operations other than ioctl should be done - by the driver, not the V4L2 core. - This driver needs auditing so that this flag can be removed. */ - set_bit(V4L2_FL_LOCK_ALL_FOPS, &vfd->flags); /* register video device */ ret = video_register_device(bcap_dev->video_dev, VFL_TYPE_GRABBER, -1); @@ -963,6 +968,7 @@ static int __devinit bcap_probe(struct platform_device *pdev) if (!i2c_adap) { v4l2_err(&bcap_dev->v4l2_dev, "Unable to find i2c adapter\n"); + ret = -ENODEV; goto err_unreg_vdev; } diff --git a/drivers/media/video/blackfin/ppi.c b/drivers/media/platform/blackfin/ppi.c index d29592186b02..d29592186b02 100644 --- a/drivers/media/video/blackfin/ppi.c +++ b/drivers/media/platform/blackfin/ppi.c diff --git a/drivers/media/platform/coda.c b/drivers/media/platform/coda.c new file mode 100644 index 000000000000..cd04ae252c30 --- /dev/null +++ b/drivers/media/platform/coda.c @@ -0,0 +1,2049 @@ +/* + * Coda multi-standard codec IP + * + * Copyright (C) 2012 Vista Silicon S.L. + * Javier Martin, <javier.martin@vista-silicon.com> + * Xavier Duret + * + * 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 <linux/clk.h> +#include <linux/delay.h> +#include <linux/firmware.h> +#include <linux/interrupt.h> +#include <linux/io.h> +#include <linux/irq.h> +#include <linux/module.h> +#include <linux/of_device.h> +#include <linux/platform_device.h> +#include <linux/slab.h> +#include <linux/videodev2.h> +#include <linux/of.h> + +#include <mach/iram.h> +#include <media/v4l2-ctrls.h> +#include <media/v4l2-device.h> +#include <media/v4l2-ioctl.h> +#include <media/v4l2-mem2mem.h> +#include <media/videobuf2-core.h> +#include <media/videobuf2-dma-contig.h> + +#include "coda.h" + +#define CODA_NAME "coda" + +#define CODA_MAX_INSTANCES 4 + +#define CODA_FMO_BUF_SIZE 32 +#define CODADX6_WORK_BUF_SIZE (288 * 1024 + CODA_FMO_BUF_SIZE * 8 * 1024) +#define CODA7_WORK_BUF_SIZE (512 * 1024 + CODA_FMO_BUF_SIZE * 8 * 1024) +#define CODA_PARA_BUF_SIZE (10 * 1024) +#define CODA_ISRAM_SIZE (2048 * 2) +#define CODA7_IRAM_SIZE 0x14000 /* 81920 bytes */ + +#define CODA_MAX_FRAMEBUFFERS 2 + +#define MAX_W 720 +#define MAX_H 576 +#define CODA_MAX_FRAME_SIZE 0x90000 +#define FMO_SLICE_SAVE_BUF_SIZE (32) +#define CODA_DEFAULT_GAMMA 4096 + +#define MIN_W 176 +#define MIN_H 144 +#define MAX_W 720 +#define MAX_H 576 + +#define S_ALIGN 1 /* multiple of 2 */ +#define W_ALIGN 1 /* multiple of 2 */ +#define H_ALIGN 1 /* multiple of 2 */ + +#define fh_to_ctx(__fh) container_of(__fh, struct coda_ctx, fh) + +static int coda_debug; +module_param(coda_debug, int, 0); +MODULE_PARM_DESC(coda_debug, "Debug level (0-1)"); + +enum { + V4L2_M2M_SRC = 0, + V4L2_M2M_DST = 1, +}; + +enum coda_fmt_type { + CODA_FMT_ENC, + CODA_FMT_RAW, +}; + +enum coda_inst_type { + CODA_INST_ENCODER, + CODA_INST_DECODER, +}; + +enum coda_product { + CODA_DX6 = 0xf001, + CODA_7541 = 0xf012, +}; + +struct coda_fmt { + char *name; + u32 fourcc; + enum coda_fmt_type type; +}; + +struct coda_devtype { + char *firmware; + enum coda_product product; + struct coda_fmt *formats; + unsigned int num_formats; + size_t workbuf_size; +}; + +/* Per-queue, driver-specific private data */ +struct coda_q_data { + unsigned int width; + unsigned int height; + unsigned int sizeimage; + struct coda_fmt *fmt; +}; + +struct coda_aux_buf { + void *vaddr; + dma_addr_t paddr; + u32 size; +}; + +struct coda_dev { + struct v4l2_device v4l2_dev; + struct video_device vfd; + struct platform_device *plat_dev; + const struct coda_devtype *devtype; + + void __iomem *regs_base; + struct clk *clk_per; + struct clk *clk_ahb; + + struct coda_aux_buf codebuf; + struct coda_aux_buf workbuf; + long unsigned int iram_paddr; + + spinlock_t irqlock; + struct mutex dev_mutex; + struct v4l2_m2m_dev *m2m_dev; + struct vb2_alloc_ctx *alloc_ctx; + struct list_head instances; + unsigned long instance_mask; + struct delayed_work timeout; + struct completion done; +}; + +struct coda_params { + u8 rot_mode; + u8 h264_intra_qp; + u8 h264_inter_qp; + u8 mpeg4_intra_qp; + u8 mpeg4_inter_qp; + u8 gop_size; + int codec_mode; + enum v4l2_mpeg_video_multi_slice_mode slice_mode; + u32 framerate; + u16 bitrate; + u32 slice_max_bits; + u32 slice_max_mb; +}; + +struct coda_ctx { + struct coda_dev *dev; + struct list_head list; + int aborting; + int rawstreamon; + int compstreamon; + u32 isequence; + struct coda_q_data q_data[2]; + enum coda_inst_type inst_type; + enum v4l2_colorspace colorspace; + struct coda_params params; + struct v4l2_m2m_ctx *m2m_ctx; + struct v4l2_ctrl_handler ctrls; + struct v4l2_fh fh; + int gopcounter; + char vpu_header[3][64]; + int vpu_header_size[3]; + struct coda_aux_buf parabuf; + struct coda_aux_buf internal_frames[CODA_MAX_FRAMEBUFFERS]; + int num_internal_frames; + int idx; +}; + +static inline void coda_write(struct coda_dev *dev, u32 data, u32 reg) +{ + v4l2_dbg(1, coda_debug, &dev->v4l2_dev, + "%s: data=0x%x, reg=0x%x\n", __func__, data, reg); + writel(data, dev->regs_base + reg); +} + +static inline unsigned int coda_read(struct coda_dev *dev, u32 reg) +{ + u32 data; + data = readl(dev->regs_base + reg); + v4l2_dbg(1, coda_debug, &dev->v4l2_dev, + "%s: data=0x%x, reg=0x%x\n", __func__, data, reg); + return data; +} + +static inline unsigned long coda_isbusy(struct coda_dev *dev) +{ + return coda_read(dev, CODA_REG_BIT_BUSY); +} + +static inline int coda_is_initialized(struct coda_dev *dev) +{ + return (coda_read(dev, CODA_REG_BIT_CUR_PC) != 0); +} + +static int coda_wait_timeout(struct coda_dev *dev) +{ + unsigned long timeout = jiffies + msecs_to_jiffies(1000); + + while (coda_isbusy(dev)) { + if (time_after(jiffies, timeout)) + return -ETIMEDOUT; + } + return 0; +} + +static void coda_command_async(struct coda_ctx *ctx, int cmd) +{ + struct coda_dev *dev = ctx->dev; + coda_write(dev, CODA_REG_BIT_BUSY_FLAG, CODA_REG_BIT_BUSY); + + coda_write(dev, ctx->idx, CODA_REG_BIT_RUN_INDEX); + coda_write(dev, ctx->params.codec_mode, CODA_REG_BIT_RUN_COD_STD); + coda_write(dev, cmd, CODA_REG_BIT_RUN_COMMAND); +} + +static int coda_command_sync(struct coda_ctx *ctx, int cmd) +{ + struct coda_dev *dev = ctx->dev; + + coda_command_async(ctx, cmd); + return coda_wait_timeout(dev); +} + +static struct coda_q_data *get_q_data(struct coda_ctx *ctx, + enum v4l2_buf_type type) +{ + switch (type) { + case V4L2_BUF_TYPE_VIDEO_OUTPUT: + return &(ctx->q_data[V4L2_M2M_SRC]); + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + return &(ctx->q_data[V4L2_M2M_DST]); + default: + BUG(); + } + return NULL; +} + +/* + * Add one array of supported formats for each version of Coda: + * i.MX27 -> codadx6 + * i.MX51 -> coda7 + * i.MX6 -> coda960 + */ +static struct coda_fmt codadx6_formats[] = { + { + .name = "YUV 4:2:0 Planar", + .fourcc = V4L2_PIX_FMT_YUV420, + .type = CODA_FMT_RAW, + }, + { + .name = "H264 Encoded Stream", + .fourcc = V4L2_PIX_FMT_H264, + .type = CODA_FMT_ENC, + }, + { + .name = "MPEG4 Encoded Stream", + .fourcc = V4L2_PIX_FMT_MPEG4, + .type = CODA_FMT_ENC, + }, +}; + +static struct coda_fmt coda7_formats[] = { + { + .name = "YUV 4:2:0 Planar", + .fourcc = V4L2_PIX_FMT_YUV420, + .type = CODA_FMT_RAW, + }, + { + .name = "H264 Encoded Stream", + .fourcc = V4L2_PIX_FMT_H264, + .type = CODA_FMT_ENC, + }, + { + .name = "MPEG4 Encoded Stream", + .fourcc = V4L2_PIX_FMT_MPEG4, + .type = CODA_FMT_ENC, + }, +}; + +static struct coda_fmt *find_format(struct coda_dev *dev, struct v4l2_format *f) +{ + struct coda_fmt *formats = dev->devtype->formats; + int num_formats = dev->devtype->num_formats; + unsigned int k; + + for (k = 0; k < num_formats; k++) { + if (formats[k].fourcc == f->fmt.pix.pixelformat) + break; + } + + if (k == num_formats) + return NULL; + + return &formats[k]; +} + +/* + * V4L2 ioctl() operations. + */ +static int vidioc_querycap(struct file *file, void *priv, + struct v4l2_capability *cap) +{ + strlcpy(cap->driver, CODA_NAME, sizeof(cap->driver)); + strlcpy(cap->card, CODA_NAME, sizeof(cap->card)); + strlcpy(cap->bus_info, CODA_NAME, sizeof(cap->bus_info)); + /* + * This is only a mem-to-mem video device. The capture and output + * device capability flags are left only for backward compatibility + * and are scheduled for removal. + */ + cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT | + V4L2_CAP_VIDEO_M2M | V4L2_CAP_STREAMING; + cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; + + return 0; +} + +static int enum_fmt(void *priv, struct v4l2_fmtdesc *f, + enum coda_fmt_type type) +{ + struct coda_ctx *ctx = fh_to_ctx(priv); + struct coda_dev *dev = ctx->dev; + struct coda_fmt *formats = dev->devtype->formats; + struct coda_fmt *fmt; + int num_formats = dev->devtype->num_formats; + int i, num = 0; + + for (i = 0; i < num_formats; i++) { + if (formats[i].type == type) { + if (num == f->index) + break; + ++num; + } + } + + if (i < num_formats) { + fmt = &formats[i]; + strlcpy(f->description, fmt->name, sizeof(f->description)); + f->pixelformat = fmt->fourcc; + return 0; + } + + /* Format not found */ + return -EINVAL; +} + +static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_fmtdesc *f) +{ + return enum_fmt(priv, f, CODA_FMT_ENC); +} + +static int vidioc_enum_fmt_vid_out(struct file *file, void *priv, + struct v4l2_fmtdesc *f) +{ + return enum_fmt(priv, f, CODA_FMT_RAW); +} + +static int vidioc_g_fmt(struct file *file, void *priv, struct v4l2_format *f) +{ + struct vb2_queue *vq; + struct coda_q_data *q_data; + struct coda_ctx *ctx = fh_to_ctx(priv); + + vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type); + if (!vq) + return -EINVAL; + + q_data = get_q_data(ctx, f->type); + + f->fmt.pix.field = V4L2_FIELD_NONE; + f->fmt.pix.pixelformat = q_data->fmt->fourcc; + f->fmt.pix.width = q_data->width; + f->fmt.pix.height = q_data->height; + if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUV420) + f->fmt.pix.bytesperline = round_up(f->fmt.pix.width, 2); + else /* encoded formats h.264/mpeg4 */ + f->fmt.pix.bytesperline = 0; + + f->fmt.pix.sizeimage = q_data->sizeimage; + f->fmt.pix.colorspace = ctx->colorspace; + + return 0; +} + +static int vidioc_try_fmt(struct coda_dev *dev, struct v4l2_format *f) +{ + enum v4l2_field field; + + field = f->fmt.pix.field; + if (field == V4L2_FIELD_ANY) + field = V4L2_FIELD_NONE; + else if (V4L2_FIELD_NONE != field) + return -EINVAL; + + /* V4L2 specification suggests the driver corrects the format struct + * if any of the dimensions is unsupported */ + f->fmt.pix.field = field; + + if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUV420) { + v4l_bound_align_image(&f->fmt.pix.width, MIN_W, MAX_W, + W_ALIGN, &f->fmt.pix.height, + MIN_H, MAX_H, H_ALIGN, S_ALIGN); + f->fmt.pix.bytesperline = round_up(f->fmt.pix.width, 2); + f->fmt.pix.sizeimage = f->fmt.pix.width * + f->fmt.pix.height * 3 / 2; + } else { /*encoded formats h.264/mpeg4 */ + f->fmt.pix.bytesperline = 0; + f->fmt.pix.sizeimage = CODA_MAX_FRAME_SIZE; + } + + return 0; +} + +static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + int ret; + struct coda_fmt *fmt; + struct coda_ctx *ctx = fh_to_ctx(priv); + + fmt = find_format(ctx->dev, f); + /* + * Since decoding support is not implemented yet do not allow + * CODA_FMT_RAW formats in the capture interface. + */ + if (!fmt || !(fmt->type == CODA_FMT_ENC)) + f->fmt.pix.pixelformat = V4L2_PIX_FMT_H264; + + f->fmt.pix.colorspace = ctx->colorspace; + + ret = vidioc_try_fmt(ctx->dev, f); + if (ret < 0) + return ret; + + return 0; +} + +static int vidioc_try_fmt_vid_out(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct coda_ctx *ctx = fh_to_ctx(priv); + struct coda_fmt *fmt; + int ret; + + fmt = find_format(ctx->dev, f); + /* + * Since decoding support is not implemented yet do not allow + * CODA_FMT formats in the capture interface. + */ + if (!fmt || !(fmt->type == CODA_FMT_RAW)) + f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUV420; + + if (!f->fmt.pix.colorspace) + f->fmt.pix.colorspace = V4L2_COLORSPACE_REC709; + + ret = vidioc_try_fmt(ctx->dev, f); + if (ret < 0) + return ret; + + return 0; +} + +static int vidioc_s_fmt(struct coda_ctx *ctx, struct v4l2_format *f) +{ + struct coda_q_data *q_data; + struct vb2_queue *vq; + int ret; + + vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type); + if (!vq) + return -EINVAL; + + q_data = get_q_data(ctx, f->type); + if (!q_data) + return -EINVAL; + + if (vb2_is_busy(vq)) { + v4l2_err(&ctx->dev->v4l2_dev, "%s queue busy\n", __func__); + return -EBUSY; + } + + ret = vidioc_try_fmt(ctx->dev, f); + if (ret) + return ret; + + q_data->fmt = find_format(ctx->dev, f); + q_data->width = f->fmt.pix.width; + q_data->height = f->fmt.pix.height; + q_data->sizeimage = f->fmt.pix.sizeimage; + + v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev, + "Setting format for type %d, wxh: %dx%d, fmt: %d\n", + f->type, q_data->width, q_data->height, q_data->fmt->fourcc); + + return 0; +} + +static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + int ret; + + ret = vidioc_try_fmt_vid_cap(file, priv, f); + if (ret) + return ret; + + return vidioc_s_fmt(fh_to_ctx(priv), f); +} + +static int vidioc_s_fmt_vid_out(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct coda_ctx *ctx = fh_to_ctx(priv); + int ret; + + ret = vidioc_try_fmt_vid_out(file, priv, f); + if (ret) + return ret; + + ret = vidioc_s_fmt(ctx, f); + if (ret) + ctx->colorspace = f->fmt.pix.colorspace; + + return ret; +} + +static int vidioc_reqbufs(struct file *file, void *priv, + struct v4l2_requestbuffers *reqbufs) +{ + struct coda_ctx *ctx = fh_to_ctx(priv); + + return v4l2_m2m_reqbufs(file, ctx->m2m_ctx, reqbufs); +} + +static int vidioc_querybuf(struct file *file, void *priv, + struct v4l2_buffer *buf) +{ + struct coda_ctx *ctx = fh_to_ctx(priv); + + return v4l2_m2m_querybuf(file, ctx->m2m_ctx, buf); +} + +static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf) +{ + struct coda_ctx *ctx = fh_to_ctx(priv); + + return v4l2_m2m_qbuf(file, ctx->m2m_ctx, buf); +} + +static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf) +{ + struct coda_ctx *ctx = fh_to_ctx(priv); + + return v4l2_m2m_dqbuf(file, ctx->m2m_ctx, buf); +} + +static int vidioc_streamon(struct file *file, void *priv, + enum v4l2_buf_type type) +{ + struct coda_ctx *ctx = fh_to_ctx(priv); + + return v4l2_m2m_streamon(file, ctx->m2m_ctx, type); +} + +static int vidioc_streamoff(struct file *file, void *priv, + enum v4l2_buf_type type) +{ + struct coda_ctx *ctx = fh_to_ctx(priv); + + return v4l2_m2m_streamoff(file, ctx->m2m_ctx, type); +} + +static const struct v4l2_ioctl_ops coda_ioctl_ops = { + .vidioc_querycap = vidioc_querycap, + + .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, + .vidioc_g_fmt_vid_cap = vidioc_g_fmt, + .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, + .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, + + .vidioc_enum_fmt_vid_out = vidioc_enum_fmt_vid_out, + .vidioc_g_fmt_vid_out = vidioc_g_fmt, + .vidioc_try_fmt_vid_out = vidioc_try_fmt_vid_out, + .vidioc_s_fmt_vid_out = vidioc_s_fmt_vid_out, + + .vidioc_reqbufs = vidioc_reqbufs, + .vidioc_querybuf = vidioc_querybuf, + + .vidioc_qbuf = vidioc_qbuf, + .vidioc_dqbuf = vidioc_dqbuf, + + .vidioc_streamon = vidioc_streamon, + .vidioc_streamoff = vidioc_streamoff, +}; + +/* + * Mem-to-mem operations. + */ +static void coda_device_run(void *m2m_priv) +{ + struct coda_ctx *ctx = m2m_priv; + struct coda_q_data *q_data_src, *q_data_dst; + struct vb2_buffer *src_buf, *dst_buf; + struct coda_dev *dev = ctx->dev; + int force_ipicture; + int quant_param = 0; + u32 picture_y, picture_cb, picture_cr; + u32 pic_stream_buffer_addr, pic_stream_buffer_size; + u32 dst_fourcc; + + src_buf = v4l2_m2m_next_src_buf(ctx->m2m_ctx); + dst_buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx); + q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); + q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); + dst_fourcc = q_data_dst->fmt->fourcc; + + src_buf->v4l2_buf.sequence = ctx->isequence; + dst_buf->v4l2_buf.sequence = ctx->isequence; + ctx->isequence++; + + /* + * Workaround coda firmware BUG that only marks the first + * frame as IDR. This is a problem for some decoders that can't + * recover when a frame is lost. + */ + if (src_buf->v4l2_buf.sequence % ctx->params.gop_size) { + src_buf->v4l2_buf.flags |= V4L2_BUF_FLAG_PFRAME; + src_buf->v4l2_buf.flags &= ~V4L2_BUF_FLAG_KEYFRAME; + } else { + src_buf->v4l2_buf.flags |= V4L2_BUF_FLAG_KEYFRAME; + src_buf->v4l2_buf.flags &= ~V4L2_BUF_FLAG_PFRAME; + } + + /* + * Copy headers at the beginning of the first frame for H.264 only. + * In MPEG4 they are already copied by the coda. + */ + if (src_buf->v4l2_buf.sequence == 0) { + pic_stream_buffer_addr = + vb2_dma_contig_plane_dma_addr(dst_buf, 0) + + ctx->vpu_header_size[0] + + ctx->vpu_header_size[1] + + ctx->vpu_header_size[2]; + pic_stream_buffer_size = CODA_MAX_FRAME_SIZE - + ctx->vpu_header_size[0] - + ctx->vpu_header_size[1] - + ctx->vpu_header_size[2]; + memcpy(vb2_plane_vaddr(dst_buf, 0), + &ctx->vpu_header[0][0], ctx->vpu_header_size[0]); + memcpy(vb2_plane_vaddr(dst_buf, 0) + ctx->vpu_header_size[0], + &ctx->vpu_header[1][0], ctx->vpu_header_size[1]); + memcpy(vb2_plane_vaddr(dst_buf, 0) + ctx->vpu_header_size[0] + + ctx->vpu_header_size[1], &ctx->vpu_header[2][0], + ctx->vpu_header_size[2]); + } else { + pic_stream_buffer_addr = + vb2_dma_contig_plane_dma_addr(dst_buf, 0); + pic_stream_buffer_size = CODA_MAX_FRAME_SIZE; + } + + if (src_buf->v4l2_buf.flags & V4L2_BUF_FLAG_KEYFRAME) { + force_ipicture = 1; + switch (dst_fourcc) { + case V4L2_PIX_FMT_H264: + quant_param = ctx->params.h264_intra_qp; + break; + case V4L2_PIX_FMT_MPEG4: + quant_param = ctx->params.mpeg4_intra_qp; + break; + default: + v4l2_warn(&ctx->dev->v4l2_dev, + "cannot set intra qp, fmt not supported\n"); + break; + } + } else { + force_ipicture = 0; + switch (dst_fourcc) { + case V4L2_PIX_FMT_H264: + quant_param = ctx->params.h264_inter_qp; + break; + case V4L2_PIX_FMT_MPEG4: + quant_param = ctx->params.mpeg4_inter_qp; + break; + default: + v4l2_warn(&ctx->dev->v4l2_dev, + "cannot set inter qp, fmt not supported\n"); + break; + } + } + + /* submit */ + coda_write(dev, CODA_ROT_MIR_ENABLE | ctx->params.rot_mode, CODA_CMD_ENC_PIC_ROT_MODE); + coda_write(dev, quant_param, CODA_CMD_ENC_PIC_QS); + + + picture_y = vb2_dma_contig_plane_dma_addr(src_buf, 0); + picture_cb = picture_y + q_data_src->width * q_data_src->height; + picture_cr = picture_cb + q_data_src->width / 2 * + q_data_src->height / 2; + + coda_write(dev, picture_y, CODA_CMD_ENC_PIC_SRC_ADDR_Y); + coda_write(dev, picture_cb, CODA_CMD_ENC_PIC_SRC_ADDR_CB); + coda_write(dev, picture_cr, CODA_CMD_ENC_PIC_SRC_ADDR_CR); + coda_write(dev, force_ipicture << 1 & 0x2, + CODA_CMD_ENC_PIC_OPTION); + + coda_write(dev, pic_stream_buffer_addr, CODA_CMD_ENC_PIC_BB_START); + coda_write(dev, pic_stream_buffer_size / 1024, + CODA_CMD_ENC_PIC_BB_SIZE); + + if (dev->devtype->product == CODA_7541) { + coda_write(dev, CODA7_USE_BIT_ENABLE | CODA7_USE_HOST_BIT_ENABLE | + CODA7_USE_ME_ENABLE | CODA7_USE_HOST_ME_ENABLE, + CODA7_REG_BIT_AXI_SRAM_USE); + } + + /* 1 second timeout in case CODA locks up */ + schedule_delayed_work(&dev->timeout, HZ); + + INIT_COMPLETION(dev->done); + coda_command_async(ctx, CODA_COMMAND_PIC_RUN); +} + +static int coda_job_ready(void *m2m_priv) +{ + struct coda_ctx *ctx = m2m_priv; + + /* + * For both 'P' and 'key' frame cases 1 picture + * and 1 frame are needed. + */ + if (!v4l2_m2m_num_src_bufs_ready(ctx->m2m_ctx) || + !v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx)) { + v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev, + "not ready: not enough video buffers.\n"); + return 0; + } + + v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev, + "job ready\n"); + return 1; +} + +static void coda_job_abort(void *priv) +{ + struct coda_ctx *ctx = priv; + struct coda_dev *dev = ctx->dev; + + ctx->aborting = 1; + + v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev, + "Aborting task\n"); + + v4l2_m2m_job_finish(dev->m2m_dev, ctx->m2m_ctx); +} + +static void coda_lock(void *m2m_priv) +{ + struct coda_ctx *ctx = m2m_priv; + struct coda_dev *pcdev = ctx->dev; + mutex_lock(&pcdev->dev_mutex); +} + +static void coda_unlock(void *m2m_priv) +{ + struct coda_ctx *ctx = m2m_priv; + struct coda_dev *pcdev = ctx->dev; + mutex_unlock(&pcdev->dev_mutex); +} + +static struct v4l2_m2m_ops coda_m2m_ops = { + .device_run = coda_device_run, + .job_ready = coda_job_ready, + .job_abort = coda_job_abort, + .lock = coda_lock, + .unlock = coda_unlock, +}; + +static void set_default_params(struct coda_ctx *ctx) +{ + struct coda_dev *dev = ctx->dev; + + ctx->params.codec_mode = CODA_MODE_INVALID; + ctx->colorspace = V4L2_COLORSPACE_REC709; + ctx->params.framerate = 30; + ctx->aborting = 0; + + /* Default formats for output and input queues */ + ctx->q_data[V4L2_M2M_SRC].fmt = &dev->devtype->formats[0]; + ctx->q_data[V4L2_M2M_DST].fmt = &dev->devtype->formats[1]; + ctx->q_data[V4L2_M2M_SRC].width = MAX_W; + ctx->q_data[V4L2_M2M_SRC].height = MAX_H; + ctx->q_data[V4L2_M2M_SRC].sizeimage = (MAX_W * MAX_H * 3) / 2; + ctx->q_data[V4L2_M2M_DST].width = MAX_W; + ctx->q_data[V4L2_M2M_DST].height = MAX_H; + ctx->q_data[V4L2_M2M_DST].sizeimage = CODA_MAX_FRAME_SIZE; +} + +/* + * Queue operations + */ +static int coda_queue_setup(struct vb2_queue *vq, + const struct v4l2_format *fmt, + unsigned int *nbuffers, unsigned int *nplanes, + unsigned int sizes[], void *alloc_ctxs[]) +{ + struct coda_ctx *ctx = vb2_get_drv_priv(vq); + struct coda_q_data *q_data; + unsigned int size; + + q_data = get_q_data(ctx, vq->type); + size = q_data->sizeimage; + + *nplanes = 1; + sizes[0] = size; + + alloc_ctxs[0] = ctx->dev->alloc_ctx; + + v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev, + "get %d buffer(s) of size %d each.\n", *nbuffers, size); + + return 0; +} + +static int coda_buf_prepare(struct vb2_buffer *vb) +{ + struct coda_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); + struct coda_q_data *q_data; + + q_data = get_q_data(ctx, vb->vb2_queue->type); + + if (vb2_plane_size(vb, 0) < q_data->sizeimage) { + v4l2_warn(&ctx->dev->v4l2_dev, + "%s data will not fit into plane (%lu < %lu)\n", + __func__, vb2_plane_size(vb, 0), + (long)q_data->sizeimage); + return -EINVAL; + } + + vb2_set_plane_payload(vb, 0, q_data->sizeimage); + + return 0; +} + +static void coda_buf_queue(struct vb2_buffer *vb) +{ + struct coda_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); + v4l2_m2m_buf_queue(ctx->m2m_ctx, vb); +} + +static void coda_wait_prepare(struct vb2_queue *q) +{ + struct coda_ctx *ctx = vb2_get_drv_priv(q); + coda_unlock(ctx); +} + +static void coda_wait_finish(struct vb2_queue *q) +{ + struct coda_ctx *ctx = vb2_get_drv_priv(q); + coda_lock(ctx); +} + +static void coda_free_framebuffers(struct coda_ctx *ctx) +{ + int i; + + for (i = 0; i < CODA_MAX_FRAMEBUFFERS; i++) { + if (ctx->internal_frames[i].vaddr) { + dma_free_coherent(&ctx->dev->plat_dev->dev, + ctx->internal_frames[i].size, + ctx->internal_frames[i].vaddr, + ctx->internal_frames[i].paddr); + ctx->internal_frames[i].vaddr = NULL; + } + } +} + +static int coda_alloc_framebuffers(struct coda_ctx *ctx, struct coda_q_data *q_data, u32 fourcc) +{ + struct coda_dev *dev = ctx->dev; + + int height = q_data->height; + int width = q_data->width; + u32 *p; + int i; + + /* Allocate frame buffers */ + ctx->num_internal_frames = CODA_MAX_FRAMEBUFFERS; + for (i = 0; i < ctx->num_internal_frames; i++) { + ctx->internal_frames[i].size = q_data->sizeimage; + if (fourcc == V4L2_PIX_FMT_H264 && dev->devtype->product != CODA_DX6) + ctx->internal_frames[i].size += width / 2 * height / 2; + ctx->internal_frames[i].vaddr = dma_alloc_coherent( + &dev->plat_dev->dev, ctx->internal_frames[i].size, + &ctx->internal_frames[i].paddr, GFP_KERNEL); + if (!ctx->internal_frames[i].vaddr) { + coda_free_framebuffers(ctx); + return -ENOMEM; + } + } + + /* Register frame buffers in the parameter buffer */ + p = ctx->parabuf.vaddr; + + if (dev->devtype->product == CODA_DX6) { + for (i = 0; i < ctx->num_internal_frames; i++) { + p[i * 3] = ctx->internal_frames[i].paddr; /* Y */ + p[i * 3 + 1] = p[i * 3] + width * height; /* Cb */ + p[i * 3 + 2] = p[i * 3 + 1] + width / 2 * height / 2; /* Cr */ + } + } else { + for (i = 0; i < ctx->num_internal_frames; i += 2) { + p[i * 3 + 1] = ctx->internal_frames[i].paddr; /* Y */ + p[i * 3] = p[i * 3 + 1] + width * height; /* Cb */ + p[i * 3 + 3] = p[i * 3] + (width / 2) * (height / 2); /* Cr */ + + if (fourcc == V4L2_PIX_FMT_H264) + p[96 + i + 1] = p[i * 3 + 3] + (width / 2) * (height / 2); + + if (i + 1 < ctx->num_internal_frames) { + p[i * 3 + 2] = ctx->internal_frames[i+1].paddr; /* Y */ + p[i * 3 + 5] = p[i * 3 + 2] + width * height ; /* Cb */ + p[i * 3 + 4] = p[i * 3 + 5] + (width / 2) * (height / 2); /* Cr */ + + if (fourcc == V4L2_PIX_FMT_H264) + p[96 + i] = p[i * 3 + 4] + (width / 2) * (height / 2); + } + } + } + + return 0; +} + +static int coda_start_streaming(struct vb2_queue *q, unsigned int count) +{ + struct coda_ctx *ctx = vb2_get_drv_priv(q); + struct v4l2_device *v4l2_dev = &ctx->dev->v4l2_dev; + u32 bitstream_buf, bitstream_size; + struct coda_dev *dev = ctx->dev; + struct coda_q_data *q_data_src, *q_data_dst; + struct vb2_buffer *buf; + u32 dst_fourcc; + u32 value; + int ret; + + if (count < 1) + return -EINVAL; + + if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) + ctx->rawstreamon = 1; + else + ctx->compstreamon = 1; + + /* Don't start the coda unless both queues are on */ + if (!(ctx->rawstreamon & ctx->compstreamon)) + return 0; + + if (coda_isbusy(dev)) + if (wait_for_completion_interruptible_timeout(&dev->done, HZ) <= 0) + return -EBUSY; + + ctx->gopcounter = ctx->params.gop_size - 1; + + q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); + buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx); + bitstream_buf = vb2_dma_contig_plane_dma_addr(buf, 0); + q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); + bitstream_size = q_data_dst->sizeimage; + dst_fourcc = q_data_dst->fmt->fourcc; + + /* Find out whether coda must encode or decode */ + if (q_data_src->fmt->type == CODA_FMT_RAW && + q_data_dst->fmt->type == CODA_FMT_ENC) { + ctx->inst_type = CODA_INST_ENCODER; + } else if (q_data_src->fmt->type == CODA_FMT_ENC && + q_data_dst->fmt->type == CODA_FMT_RAW) { + ctx->inst_type = CODA_INST_DECODER; + v4l2_err(v4l2_dev, "decoding not supported.\n"); + return -EINVAL; + } else { + v4l2_err(v4l2_dev, "couldn't tell instance type.\n"); + return -EINVAL; + } + + if (!coda_is_initialized(dev)) { + v4l2_err(v4l2_dev, "coda is not initialized.\n"); + return -EFAULT; + } + coda_write(dev, ctx->parabuf.paddr, CODA_REG_BIT_PARA_BUF_ADDR); + coda_write(dev, bitstream_buf, CODA_REG_BIT_RD_PTR(ctx->idx)); + coda_write(dev, bitstream_buf, CODA_REG_BIT_WR_PTR(ctx->idx)); + switch (dev->devtype->product) { + case CODA_DX6: + coda_write(dev, CODADX6_STREAM_BUF_DYNALLOC_EN | + CODADX6_STREAM_BUF_PIC_RESET, CODA_REG_BIT_STREAM_CTRL); + break; + default: + coda_write(dev, CODA7_STREAM_BUF_DYNALLOC_EN | + CODA7_STREAM_BUF_PIC_RESET, CODA_REG_BIT_STREAM_CTRL); + } + + if (dev->devtype->product == CODA_DX6) { + /* Configure the coda */ + coda_write(dev, dev->iram_paddr, CODADX6_REG_BIT_SEARCH_RAM_BASE_ADDR); + } + + /* Could set rotation here if needed */ + switch (dev->devtype->product) { + case CODA_DX6: + value = (q_data_src->width & CODADX6_PICWIDTH_MASK) << CODADX6_PICWIDTH_OFFSET; + break; + default: + value = (q_data_src->width & CODA7_PICWIDTH_MASK) << CODA7_PICWIDTH_OFFSET; + } + value |= (q_data_src->height & CODA_PICHEIGHT_MASK) << CODA_PICHEIGHT_OFFSET; + coda_write(dev, value, CODA_CMD_ENC_SEQ_SRC_SIZE); + coda_write(dev, ctx->params.framerate, + CODA_CMD_ENC_SEQ_SRC_F_RATE); + + switch (dst_fourcc) { + case V4L2_PIX_FMT_MPEG4: + if (dev->devtype->product == CODA_DX6) + ctx->params.codec_mode = CODADX6_MODE_ENCODE_MP4; + else + ctx->params.codec_mode = CODA7_MODE_ENCODE_MP4; + + coda_write(dev, CODA_STD_MPEG4, CODA_CMD_ENC_SEQ_COD_STD); + coda_write(dev, 0, CODA_CMD_ENC_SEQ_MP4_PARA); + break; + case V4L2_PIX_FMT_H264: + if (dev->devtype->product == CODA_DX6) + ctx->params.codec_mode = CODADX6_MODE_ENCODE_H264; + else + ctx->params.codec_mode = CODA7_MODE_ENCODE_H264; + + coda_write(dev, CODA_STD_H264, CODA_CMD_ENC_SEQ_COD_STD); + coda_write(dev, 0, CODA_CMD_ENC_SEQ_264_PARA); + break; + default: + v4l2_err(v4l2_dev, + "dst format (0x%08x) invalid.\n", dst_fourcc); + return -EINVAL; + } + + switch (ctx->params.slice_mode) { + case V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE: + value = 0; + break; + case V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_MB: + value = (ctx->params.slice_max_mb & CODA_SLICING_SIZE_MASK) << CODA_SLICING_SIZE_OFFSET; + value |= (1 & CODA_SLICING_UNIT_MASK) << CODA_SLICING_UNIT_OFFSET; + value |= 1 & CODA_SLICING_MODE_MASK; + break; + case V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_BYTES: + value = (ctx->params.slice_max_bits & CODA_SLICING_SIZE_MASK) << CODA_SLICING_SIZE_OFFSET; + value |= (0 & CODA_SLICING_UNIT_MASK) << CODA_SLICING_UNIT_OFFSET; + value |= 1 & CODA_SLICING_MODE_MASK; + break; + } + coda_write(dev, value, CODA_CMD_ENC_SEQ_SLICE_MODE); + value = ctx->params.gop_size & CODA_GOP_SIZE_MASK; + coda_write(dev, value, CODA_CMD_ENC_SEQ_GOP_SIZE); + + if (ctx->params.bitrate) { + /* Rate control enabled */ + value = (ctx->params.bitrate & CODA_RATECONTROL_BITRATE_MASK) << CODA_RATECONTROL_BITRATE_OFFSET; + value |= 1 & CODA_RATECONTROL_ENABLE_MASK; + } else { + value = 0; + } + coda_write(dev, value, CODA_CMD_ENC_SEQ_RC_PARA); + + coda_write(dev, 0, CODA_CMD_ENC_SEQ_RC_BUF_SIZE); + coda_write(dev, 0, CODA_CMD_ENC_SEQ_INTRA_REFRESH); + + coda_write(dev, bitstream_buf, CODA_CMD_ENC_SEQ_BB_START); + coda_write(dev, bitstream_size / 1024, CODA_CMD_ENC_SEQ_BB_SIZE); + + /* set default gamma */ + value = (CODA_DEFAULT_GAMMA & CODA_GAMMA_MASK) << CODA_GAMMA_OFFSET; + coda_write(dev, value, CODA_CMD_ENC_SEQ_RC_GAMMA); + + value = (CODA_DEFAULT_GAMMA > 0) << CODA_OPTION_GAMMA_OFFSET; + value |= (0 & CODA_OPTION_SLICEREPORT_MASK) << CODA_OPTION_SLICEREPORT_OFFSET; + coda_write(dev, value, CODA_CMD_ENC_SEQ_OPTION); + + if (dst_fourcc == V4L2_PIX_FMT_H264) { + value = (FMO_SLICE_SAVE_BUF_SIZE << 7); + value |= (0 & CODA_FMOPARAM_TYPE_MASK) << CODA_FMOPARAM_TYPE_OFFSET; + value |= 0 & CODA_FMOPARAM_SLICENUM_MASK; + if (dev->devtype->product == CODA_DX6) { + coda_write(dev, value, CODADX6_CMD_ENC_SEQ_FMO); + } else { + coda_write(dev, dev->iram_paddr, CODA7_CMD_ENC_SEQ_SEARCH_BASE); + coda_write(dev, 48 * 1024, CODA7_CMD_ENC_SEQ_SEARCH_SIZE); + } + } + + if (coda_command_sync(ctx, CODA_COMMAND_SEQ_INIT)) { + v4l2_err(v4l2_dev, "CODA_COMMAND_SEQ_INIT timeout\n"); + return -ETIMEDOUT; + } + + if (coda_read(dev, CODA_RET_ENC_SEQ_SUCCESS) == 0) + return -EFAULT; + + ret = coda_alloc_framebuffers(ctx, q_data_src, dst_fourcc); + if (ret < 0) + return ret; + + coda_write(dev, ctx->num_internal_frames, CODA_CMD_SET_FRAME_BUF_NUM); + coda_write(dev, round_up(q_data_src->width, 8), CODA_CMD_SET_FRAME_BUF_STRIDE); + if (dev->devtype->product != CODA_DX6) { + coda_write(dev, round_up(q_data_src->width, 8), CODA7_CMD_SET_FRAME_SOURCE_BUF_STRIDE); + coda_write(dev, dev->iram_paddr + 48 * 1024, CODA7_CMD_SET_FRAME_AXI_DBKY_ADDR); + coda_write(dev, dev->iram_paddr + 53 * 1024, CODA7_CMD_SET_FRAME_AXI_DBKC_ADDR); + coda_write(dev, dev->iram_paddr + 58 * 1024, CODA7_CMD_SET_FRAME_AXI_BIT_ADDR); + coda_write(dev, dev->iram_paddr + 68 * 1024, CODA7_CMD_SET_FRAME_AXI_IPACDC_ADDR); + coda_write(dev, 0x0, CODA7_CMD_SET_FRAME_AXI_OVL_ADDR); + } + if (coda_command_sync(ctx, CODA_COMMAND_SET_FRAME_BUF)) { + v4l2_err(v4l2_dev, "CODA_COMMAND_SET_FRAME_BUF timeout\n"); + return -ETIMEDOUT; + } + + /* Save stream headers */ + buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx); + switch (dst_fourcc) { + case V4L2_PIX_FMT_H264: + /* + * Get SPS in the first frame and copy it to an + * intermediate buffer. + */ + coda_write(dev, vb2_dma_contig_plane_dma_addr(buf, 0), CODA_CMD_ENC_HEADER_BB_START); + coda_write(dev, bitstream_size, CODA_CMD_ENC_HEADER_BB_SIZE); + coda_write(dev, CODA_HEADER_H264_SPS, CODA_CMD_ENC_HEADER_CODE); + if (coda_command_sync(ctx, CODA_COMMAND_ENCODE_HEADER)) { + v4l2_err(v4l2_dev, "CODA_COMMAND_ENCODE_HEADER timeout\n"); + return -ETIMEDOUT; + } + ctx->vpu_header_size[0] = coda_read(dev, CODA_REG_BIT_WR_PTR(ctx->idx)) - + coda_read(dev, CODA_CMD_ENC_HEADER_BB_START); + memcpy(&ctx->vpu_header[0][0], vb2_plane_vaddr(buf, 0), + ctx->vpu_header_size[0]); + + /* + * Get PPS in the first frame and copy it to an + * intermediate buffer. + */ + coda_write(dev, vb2_dma_contig_plane_dma_addr(buf, 0), CODA_CMD_ENC_HEADER_BB_START); + coda_write(dev, bitstream_size, CODA_CMD_ENC_HEADER_BB_SIZE); + coda_write(dev, CODA_HEADER_H264_PPS, CODA_CMD_ENC_HEADER_CODE); + if (coda_command_sync(ctx, CODA_COMMAND_ENCODE_HEADER)) { + v4l2_err(v4l2_dev, "CODA_COMMAND_ENCODE_HEADER timeout\n"); + return -ETIMEDOUT; + } + ctx->vpu_header_size[1] = coda_read(dev, CODA_REG_BIT_WR_PTR(ctx->idx)) - + coda_read(dev, CODA_CMD_ENC_HEADER_BB_START); + memcpy(&ctx->vpu_header[1][0], vb2_plane_vaddr(buf, 0), + ctx->vpu_header_size[1]); + ctx->vpu_header_size[2] = 0; + break; + case V4L2_PIX_FMT_MPEG4: + /* + * Get VOS in the first frame and copy it to an + * intermediate buffer + */ + coda_write(dev, vb2_dma_contig_plane_dma_addr(buf, 0), CODA_CMD_ENC_HEADER_BB_START); + coda_write(dev, bitstream_size, CODA_CMD_ENC_HEADER_BB_SIZE); + coda_write(dev, CODA_HEADER_MP4V_VOS, CODA_CMD_ENC_HEADER_CODE); + if (coda_command_sync(ctx, CODA_COMMAND_ENCODE_HEADER)) { + v4l2_err(v4l2_dev, "CODA_COMMAND_ENCODE_HEADER timeout\n"); + return -ETIMEDOUT; + } + ctx->vpu_header_size[0] = coda_read(dev, CODA_REG_BIT_WR_PTR(ctx->idx)) - + coda_read(dev, CODA_CMD_ENC_HEADER_BB_START); + memcpy(&ctx->vpu_header[0][0], vb2_plane_vaddr(buf, 0), + ctx->vpu_header_size[0]); + + coda_write(dev, vb2_dma_contig_plane_dma_addr(buf, 0), CODA_CMD_ENC_HEADER_BB_START); + coda_write(dev, bitstream_size, CODA_CMD_ENC_HEADER_BB_SIZE); + coda_write(dev, CODA_HEADER_MP4V_VIS, CODA_CMD_ENC_HEADER_CODE); + if (coda_command_sync(ctx, CODA_COMMAND_ENCODE_HEADER)) { + v4l2_err(v4l2_dev, "CODA_COMMAND_ENCODE_HEADER failed\n"); + return -ETIMEDOUT; + } + ctx->vpu_header_size[1] = coda_read(dev, CODA_REG_BIT_WR_PTR(ctx->idx)) - + coda_read(dev, CODA_CMD_ENC_HEADER_BB_START); + memcpy(&ctx->vpu_header[1][0], vb2_plane_vaddr(buf, 0), + ctx->vpu_header_size[1]); + + coda_write(dev, vb2_dma_contig_plane_dma_addr(buf, 0), CODA_CMD_ENC_HEADER_BB_START); + coda_write(dev, bitstream_size, CODA_CMD_ENC_HEADER_BB_SIZE); + coda_write(dev, CODA_HEADER_MP4V_VOL, CODA_CMD_ENC_HEADER_CODE); + if (coda_command_sync(ctx, CODA_COMMAND_ENCODE_HEADER)) { + v4l2_err(v4l2_dev, "CODA_COMMAND_ENCODE_HEADER failed\n"); + return -ETIMEDOUT; + } + ctx->vpu_header_size[2] = coda_read(dev, CODA_REG_BIT_WR_PTR(ctx->idx)) - + coda_read(dev, CODA_CMD_ENC_HEADER_BB_START); + memcpy(&ctx->vpu_header[2][0], vb2_plane_vaddr(buf, 0), + ctx->vpu_header_size[2]); + break; + default: + /* No more formats need to save headers at the moment */ + break; + } + + return 0; +} + +static int coda_stop_streaming(struct vb2_queue *q) +{ + struct coda_ctx *ctx = vb2_get_drv_priv(q); + struct coda_dev *dev = ctx->dev; + + if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) { + v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev, + "%s: output\n", __func__); + ctx->rawstreamon = 0; + } else { + v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev, + "%s: capture\n", __func__); + ctx->compstreamon = 0; + } + + /* Don't stop the coda unless both queues are off */ + if (ctx->rawstreamon || ctx->compstreamon) + return 0; + + if (coda_isbusy(dev)) { + if (wait_for_completion_interruptible_timeout(&dev->done, HZ) <= 0) { + v4l2_warn(&dev->v4l2_dev, + "%s: timeout, sending SEQ_END anyway\n", __func__); + } + } + + cancel_delayed_work(&dev->timeout); + + v4l2_dbg(1, coda_debug, &dev->v4l2_dev, + "%s: sent command 'SEQ_END' to coda\n", __func__); + if (coda_command_sync(ctx, CODA_COMMAND_SEQ_END)) { + v4l2_err(&dev->v4l2_dev, + "CODA_COMMAND_SEQ_END failed\n"); + return -ETIMEDOUT; + } + + coda_free_framebuffers(ctx); + + return 0; +} + +static struct vb2_ops coda_qops = { + .queue_setup = coda_queue_setup, + .buf_prepare = coda_buf_prepare, + .buf_queue = coda_buf_queue, + .wait_prepare = coda_wait_prepare, + .wait_finish = coda_wait_finish, + .start_streaming = coda_start_streaming, + .stop_streaming = coda_stop_streaming, +}; + +static int coda_s_ctrl(struct v4l2_ctrl *ctrl) +{ + struct coda_ctx *ctx = + container_of(ctrl->handler, struct coda_ctx, ctrls); + + v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev, + "s_ctrl: id = %d, val = %d\n", ctrl->id, ctrl->val); + + switch (ctrl->id) { + case V4L2_CID_HFLIP: + if (ctrl->val) + ctx->params.rot_mode |= CODA_MIR_HOR; + else + ctx->params.rot_mode &= ~CODA_MIR_HOR; + break; + case V4L2_CID_VFLIP: + if (ctrl->val) + ctx->params.rot_mode |= CODA_MIR_VER; + else + ctx->params.rot_mode &= ~CODA_MIR_VER; + break; + case V4L2_CID_MPEG_VIDEO_BITRATE: + ctx->params.bitrate = ctrl->val / 1000; + break; + case V4L2_CID_MPEG_VIDEO_GOP_SIZE: + ctx->params.gop_size = ctrl->val; + break; + case V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP: + ctx->params.h264_intra_qp = ctrl->val; + break; + case V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP: + ctx->params.h264_inter_qp = ctrl->val; + break; + case V4L2_CID_MPEG_VIDEO_MPEG4_I_FRAME_QP: + ctx->params.mpeg4_intra_qp = ctrl->val; + break; + case V4L2_CID_MPEG_VIDEO_MPEG4_P_FRAME_QP: + ctx->params.mpeg4_inter_qp = ctrl->val; + break; + case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE: + ctx->params.slice_mode = ctrl->val; + break; + case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB: + ctx->params.slice_max_mb = ctrl->val; + break; + case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES: + ctx->params.slice_max_bits = ctrl->val * 8; + break; + case V4L2_CID_MPEG_VIDEO_HEADER_MODE: + break; + default: + v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev, + "Invalid control, id=%d, val=%d\n", + ctrl->id, ctrl->val); + return -EINVAL; + } + + return 0; +} + +static struct v4l2_ctrl_ops coda_ctrl_ops = { + .s_ctrl = coda_s_ctrl, +}; + +static int coda_ctrls_setup(struct coda_ctx *ctx) +{ + v4l2_ctrl_handler_init(&ctx->ctrls, 9); + + v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops, + V4L2_CID_HFLIP, 0, 1, 1, 0); + v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops, + V4L2_CID_VFLIP, 0, 1, 1, 0); + v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops, + V4L2_CID_MPEG_VIDEO_BITRATE, 0, 32767000, 1, 0); + v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops, + V4L2_CID_MPEG_VIDEO_GOP_SIZE, 1, 60, 1, 16); + v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops, + V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP, 1, 51, 1, 25); + v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops, + V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP, 1, 51, 1, 25); + v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops, + V4L2_CID_MPEG_VIDEO_MPEG4_I_FRAME_QP, 1, 31, 1, 2); + v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops, + V4L2_CID_MPEG_VIDEO_MPEG4_P_FRAME_QP, 1, 31, 1, 2); + v4l2_ctrl_new_std_menu(&ctx->ctrls, &coda_ctrl_ops, + V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE, + V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_BYTES, 0x0, + V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE); + v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops, + V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB, 1, 0x3fffffff, 1, 1); + v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops, + V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES, 1, 0x3fffffff, 1, 500); + v4l2_ctrl_new_std_menu(&ctx->ctrls, &coda_ctrl_ops, + V4L2_CID_MPEG_VIDEO_HEADER_MODE, + V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME, + (1 << V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE), + V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME); + + if (ctx->ctrls.error) { + v4l2_err(&ctx->dev->v4l2_dev, "control initialization error (%d)", + ctx->ctrls.error); + return -EINVAL; + } + + return v4l2_ctrl_handler_setup(&ctx->ctrls); +} + +static int coda_queue_init(void *priv, struct vb2_queue *src_vq, + struct vb2_queue *dst_vq) +{ + struct coda_ctx *ctx = priv; + int ret; + + src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; + src_vq->io_modes = VB2_MMAP | VB2_USERPTR; + src_vq->drv_priv = ctx; + src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); + src_vq->ops = &coda_qops; + src_vq->mem_ops = &vb2_dma_contig_memops; + + ret = vb2_queue_init(src_vq); + if (ret) + return ret; + + dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + dst_vq->io_modes = VB2_MMAP | VB2_USERPTR; + dst_vq->drv_priv = ctx; + dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); + dst_vq->ops = &coda_qops; + dst_vq->mem_ops = &vb2_dma_contig_memops; + + return vb2_queue_init(dst_vq); +} + +static int coda_next_free_instance(struct coda_dev *dev) +{ + return ffz(dev->instance_mask); +} + +static int coda_open(struct file *file) +{ + struct coda_dev *dev = video_drvdata(file); + struct coda_ctx *ctx = NULL; + int ret = 0; + int idx; + + idx = coda_next_free_instance(dev); + if (idx >= CODA_MAX_INSTANCES) + return -EBUSY; + set_bit(idx, &dev->instance_mask); + + ctx = kzalloc(sizeof *ctx, GFP_KERNEL); + if (!ctx) + return -ENOMEM; + + v4l2_fh_init(&ctx->fh, video_devdata(file)); + file->private_data = &ctx->fh; + v4l2_fh_add(&ctx->fh); + ctx->dev = dev; + ctx->idx = idx; + + set_default_params(ctx); + ctx->m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev, ctx, + &coda_queue_init); + if (IS_ERR(ctx->m2m_ctx)) { + int ret = PTR_ERR(ctx->m2m_ctx); + + v4l2_err(&dev->v4l2_dev, "%s return error (%d)\n", + __func__, ret); + goto err; + } + ret = coda_ctrls_setup(ctx); + if (ret) { + v4l2_err(&dev->v4l2_dev, "failed to setup coda controls\n"); + goto err; + } + + ctx->fh.ctrl_handler = &ctx->ctrls; + + ctx->parabuf.vaddr = dma_alloc_coherent(&dev->plat_dev->dev, + CODA_PARA_BUF_SIZE, &ctx->parabuf.paddr, GFP_KERNEL); + if (!ctx->parabuf.vaddr) { + v4l2_err(&dev->v4l2_dev, "failed to allocate parabuf"); + ret = -ENOMEM; + goto err; + } + + coda_lock(ctx); + list_add(&ctx->list, &dev->instances); + coda_unlock(ctx); + + clk_prepare_enable(dev->clk_per); + clk_prepare_enable(dev->clk_ahb); + + v4l2_dbg(1, coda_debug, &dev->v4l2_dev, "Created instance %d (%p)\n", + ctx->idx, ctx); + + return 0; + +err: + v4l2_fh_del(&ctx->fh); + v4l2_fh_exit(&ctx->fh); + kfree(ctx); + return ret; +} + +static int coda_release(struct file *file) +{ + struct coda_dev *dev = video_drvdata(file); + struct coda_ctx *ctx = fh_to_ctx(file->private_data); + + v4l2_dbg(1, coda_debug, &dev->v4l2_dev, "Releasing instance %p\n", + ctx); + + coda_lock(ctx); + list_del(&ctx->list); + coda_unlock(ctx); + + dma_free_coherent(&dev->plat_dev->dev, CODA_PARA_BUF_SIZE, + ctx->parabuf.vaddr, ctx->parabuf.paddr); + v4l2_m2m_ctx_release(ctx->m2m_ctx); + v4l2_ctrl_handler_free(&ctx->ctrls); + clk_disable_unprepare(dev->clk_per); + clk_disable_unprepare(dev->clk_ahb); + v4l2_fh_del(&ctx->fh); + v4l2_fh_exit(&ctx->fh); + clear_bit(ctx->idx, &dev->instance_mask); + kfree(ctx); + + return 0; +} + +static unsigned int coda_poll(struct file *file, + struct poll_table_struct *wait) +{ + struct coda_ctx *ctx = fh_to_ctx(file->private_data); + int ret; + + coda_lock(ctx); + ret = v4l2_m2m_poll(file, ctx->m2m_ctx, wait); + coda_unlock(ctx); + return ret; +} + +static int coda_mmap(struct file *file, struct vm_area_struct *vma) +{ + struct coda_ctx *ctx = fh_to_ctx(file->private_data); + + return v4l2_m2m_mmap(file, ctx->m2m_ctx, vma); +} + +static const struct v4l2_file_operations coda_fops = { + .owner = THIS_MODULE, + .open = coda_open, + .release = coda_release, + .poll = coda_poll, + .unlocked_ioctl = video_ioctl2, + .mmap = coda_mmap, +}; + +static irqreturn_t coda_irq_handler(int irq, void *data) +{ + struct vb2_buffer *src_buf, *dst_buf; + struct coda_dev *dev = data; + u32 wr_ptr, start_ptr; + struct coda_ctx *ctx; + + __cancel_delayed_work(&dev->timeout); + + /* read status register to attend the IRQ */ + coda_read(dev, CODA_REG_BIT_INT_STATUS); + coda_write(dev, CODA_REG_BIT_INT_CLEAR_SET, + CODA_REG_BIT_INT_CLEAR); + + ctx = v4l2_m2m_get_curr_priv(dev->m2m_dev); + if (ctx == NULL) { + v4l2_err(&dev->v4l2_dev, "Instance released before the end of transaction\n"); + return IRQ_HANDLED; + } + + if (ctx->aborting) { + v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev, + "task has been aborted\n"); + return IRQ_HANDLED; + } + + if (coda_isbusy(ctx->dev)) { + v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev, + "coda is still busy!!!!\n"); + return IRQ_NONE; + } + + complete(&dev->done); + + src_buf = v4l2_m2m_src_buf_remove(ctx->m2m_ctx); + dst_buf = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx); + + /* Get results from the coda */ + coda_read(dev, CODA_RET_ENC_PIC_TYPE); + start_ptr = coda_read(dev, CODA_CMD_ENC_PIC_BB_START); + wr_ptr = coda_read(dev, CODA_REG_BIT_WR_PTR(ctx->idx)); + /* Calculate bytesused field */ + if (dst_buf->v4l2_buf.sequence == 0) { + dst_buf->v4l2_planes[0].bytesused = (wr_ptr - start_ptr) + + ctx->vpu_header_size[0] + + ctx->vpu_header_size[1] + + ctx->vpu_header_size[2]; + } else { + dst_buf->v4l2_planes[0].bytesused = (wr_ptr - start_ptr); + } + + v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev, "frame size = %u\n", + wr_ptr - start_ptr); + + coda_read(dev, CODA_RET_ENC_PIC_SLICE_NUM); + coda_read(dev, CODA_RET_ENC_PIC_FLAG); + + if (src_buf->v4l2_buf.flags & V4L2_BUF_FLAG_KEYFRAME) { + dst_buf->v4l2_buf.flags |= V4L2_BUF_FLAG_KEYFRAME; + dst_buf->v4l2_buf.flags &= ~V4L2_BUF_FLAG_PFRAME; + } else { + dst_buf->v4l2_buf.flags |= V4L2_BUF_FLAG_PFRAME; + dst_buf->v4l2_buf.flags &= ~V4L2_BUF_FLAG_KEYFRAME; + } + + v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE); + v4l2_m2m_buf_done(dst_buf, VB2_BUF_STATE_DONE); + + ctx->gopcounter--; + if (ctx->gopcounter < 0) + ctx->gopcounter = ctx->params.gop_size - 1; + + v4l2_dbg(1, coda_debug, &dev->v4l2_dev, + "job finished: encoding frame (%d) (%s)\n", + dst_buf->v4l2_buf.sequence, + (dst_buf->v4l2_buf.flags & V4L2_BUF_FLAG_KEYFRAME) ? + "KEYFRAME" : "PFRAME"); + + v4l2_m2m_job_finish(ctx->dev->m2m_dev, ctx->m2m_ctx); + + return IRQ_HANDLED; +} + +static void coda_timeout(struct work_struct *work) +{ + struct coda_ctx *ctx; + struct coda_dev *dev = container_of(to_delayed_work(work), + struct coda_dev, timeout); + + if (completion_done(&dev->done)) + return; + + complete(&dev->done); + + v4l2_err(&dev->v4l2_dev, "CODA PIC_RUN timeout, stopping all streams\n"); + + mutex_lock(&dev->dev_mutex); + list_for_each_entry(ctx, &dev->instances, list) { + v4l2_m2m_streamoff(NULL, ctx->m2m_ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); + v4l2_m2m_streamoff(NULL, ctx->m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); + } + mutex_unlock(&dev->dev_mutex); +} + +static u32 coda_supported_firmwares[] = { + CODA_FIRMWARE_VERNUM(CODA_DX6, 2, 2, 5), + CODA_FIRMWARE_VERNUM(CODA_7541, 13, 4, 29), +}; + +static bool coda_firmware_supported(u32 vernum) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(coda_supported_firmwares); i++) + if (vernum == coda_supported_firmwares[i]) + return true; + return false; +} + +static char *coda_product_name(int product) +{ + static char buf[9]; + + switch (product) { + case CODA_DX6: + return "CodaDx6"; + case CODA_7541: + return "CODA7541"; + default: + snprintf(buf, sizeof(buf), "(0x%04x)", product); + return buf; + } +} + +static int coda_hw_init(struct coda_dev *dev) +{ + u16 product, major, minor, release; + u32 data; + u16 *p; + int i; + + clk_prepare_enable(dev->clk_per); + clk_prepare_enable(dev->clk_ahb); + + /* + * Copy the first CODA_ISRAM_SIZE in the internal SRAM. + * The 16-bit chars in the code buffer are in memory access + * order, re-sort them to CODA order for register download. + * Data in this SRAM survives a reboot. + */ + p = (u16 *)dev->codebuf.vaddr; + if (dev->devtype->product == CODA_DX6) { + for (i = 0; i < (CODA_ISRAM_SIZE / 2); i++) { + data = CODA_DOWN_ADDRESS_SET(i) | + CODA_DOWN_DATA_SET(p[i ^ 1]); + coda_write(dev, data, CODA_REG_BIT_CODE_DOWN); + } + } else { + for (i = 0; i < (CODA_ISRAM_SIZE / 2); i++) { + data = CODA_DOWN_ADDRESS_SET(i) | + CODA_DOWN_DATA_SET(p[round_down(i, 4) + + 3 - (i % 4)]); + coda_write(dev, data, CODA_REG_BIT_CODE_DOWN); + } + } + + /* Tell the BIT where to find everything it needs */ + coda_write(dev, dev->workbuf.paddr, + CODA_REG_BIT_WORK_BUF_ADDR); + coda_write(dev, dev->codebuf.paddr, + CODA_REG_BIT_CODE_BUF_ADDR); + coda_write(dev, 0, CODA_REG_BIT_CODE_RUN); + + /* Set default values */ + switch (dev->devtype->product) { + case CODA_DX6: + coda_write(dev, CODADX6_STREAM_BUF_PIC_FLUSH, CODA_REG_BIT_STREAM_CTRL); + break; + default: + coda_write(dev, CODA7_STREAM_BUF_PIC_FLUSH, CODA_REG_BIT_STREAM_CTRL); + } + coda_write(dev, 0, CODA_REG_BIT_FRAME_MEM_CTRL); + + if (dev->devtype->product != CODA_DX6) + coda_write(dev, 0, CODA7_REG_BIT_AXI_SRAM_USE); + + coda_write(dev, CODA_INT_INTERRUPT_ENABLE, + CODA_REG_BIT_INT_ENABLE); + + /* Reset VPU and start processor */ + data = coda_read(dev, CODA_REG_BIT_CODE_RESET); + data |= CODA_REG_RESET_ENABLE; + coda_write(dev, data, CODA_REG_BIT_CODE_RESET); + udelay(10); + data &= ~CODA_REG_RESET_ENABLE; + coda_write(dev, data, CODA_REG_BIT_CODE_RESET); + coda_write(dev, CODA_REG_RUN_ENABLE, CODA_REG_BIT_CODE_RUN); + + /* Load firmware */ + coda_write(dev, 0, CODA_CMD_FIRMWARE_VERNUM); + coda_write(dev, CODA_REG_BIT_BUSY_FLAG, CODA_REG_BIT_BUSY); + coda_write(dev, 0, CODA_REG_BIT_RUN_INDEX); + coda_write(dev, 0, CODA_REG_BIT_RUN_COD_STD); + coda_write(dev, CODA_COMMAND_FIRMWARE_GET, CODA_REG_BIT_RUN_COMMAND); + if (coda_wait_timeout(dev)) { + clk_disable_unprepare(dev->clk_per); + clk_disable_unprepare(dev->clk_ahb); + v4l2_err(&dev->v4l2_dev, "firmware get command error\n"); + return -EIO; + } + + /* Check we are compatible with the loaded firmware */ + data = coda_read(dev, CODA_CMD_FIRMWARE_VERNUM); + product = CODA_FIRMWARE_PRODUCT(data); + major = CODA_FIRMWARE_MAJOR(data); + minor = CODA_FIRMWARE_MINOR(data); + release = CODA_FIRMWARE_RELEASE(data); + + clk_disable_unprepare(dev->clk_per); + clk_disable_unprepare(dev->clk_ahb); + + if (product != dev->devtype->product) { + v4l2_err(&dev->v4l2_dev, "Wrong firmware. Hw: %s, Fw: %s," + " Version: %u.%u.%u\n", + coda_product_name(dev->devtype->product), + coda_product_name(product), major, minor, release); + return -EINVAL; + } + + v4l2_info(&dev->v4l2_dev, "Initialized %s.\n", + coda_product_name(product)); + + if (coda_firmware_supported(data)) { + v4l2_info(&dev->v4l2_dev, "Firmware version: %u.%u.%u\n", + major, minor, release); + } else { + v4l2_warn(&dev->v4l2_dev, "Unsupported firmware version: " + "%u.%u.%u\n", major, minor, release); + } + + return 0; +} + +static void coda_fw_callback(const struct firmware *fw, void *context) +{ + struct coda_dev *dev = context; + struct platform_device *pdev = dev->plat_dev; + int ret; + + if (!fw) { + v4l2_err(&dev->v4l2_dev, "firmware request failed\n"); + return; + } + + /* allocate auxiliary per-device code buffer for the BIT processor */ + dev->codebuf.size = fw->size; + dev->codebuf.vaddr = dma_alloc_coherent(&pdev->dev, fw->size, + &dev->codebuf.paddr, + GFP_KERNEL); + if (!dev->codebuf.vaddr) { + dev_err(&pdev->dev, "failed to allocate code buffer\n"); + return; + } + + /* Copy the whole firmware image to the code buffer */ + memcpy(dev->codebuf.vaddr, fw->data, fw->size); + release_firmware(fw); + + ret = coda_hw_init(dev); + if (ret) { + v4l2_err(&dev->v4l2_dev, "HW initialization failed\n"); + return; + } + + dev->vfd.fops = &coda_fops, + dev->vfd.ioctl_ops = &coda_ioctl_ops; + dev->vfd.release = video_device_release_empty, + dev->vfd.lock = &dev->dev_mutex; + dev->vfd.v4l2_dev = &dev->v4l2_dev; + dev->vfd.vfl_dir = VFL_DIR_M2M; + snprintf(dev->vfd.name, sizeof(dev->vfd.name), "%s", CODA_NAME); + video_set_drvdata(&dev->vfd, dev); + + dev->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev); + if (IS_ERR(dev->alloc_ctx)) { + v4l2_err(&dev->v4l2_dev, "Failed to alloc vb2 context\n"); + return; + } + + dev->m2m_dev = v4l2_m2m_init(&coda_m2m_ops); + if (IS_ERR(dev->m2m_dev)) { + v4l2_err(&dev->v4l2_dev, "Failed to init mem2mem device\n"); + goto rel_ctx; + } + + ret = video_register_device(&dev->vfd, VFL_TYPE_GRABBER, 0); + if (ret) { + v4l2_err(&dev->v4l2_dev, "Failed to register video device\n"); + goto rel_m2m; + } + v4l2_info(&dev->v4l2_dev, "codec registered as /dev/video%d\n", + dev->vfd.num); + + return; + +rel_m2m: + v4l2_m2m_release(dev->m2m_dev); +rel_ctx: + vb2_dma_contig_cleanup_ctx(dev->alloc_ctx); +} + +static int coda_firmware_request(struct coda_dev *dev) +{ + char *fw = dev->devtype->firmware; + + dev_dbg(&dev->plat_dev->dev, "requesting firmware '%s' for %s\n", fw, + coda_product_name(dev->devtype->product)); + + return request_firmware_nowait(THIS_MODULE, true, + fw, &dev->plat_dev->dev, GFP_KERNEL, dev, coda_fw_callback); +} + +enum coda_platform { + CODA_IMX27, + CODA_IMX53, +}; + +static const struct coda_devtype coda_devdata[] = { + [CODA_IMX27] = { + .firmware = "v4l-codadx6-imx27.bin", + .product = CODA_DX6, + .formats = codadx6_formats, + .num_formats = ARRAY_SIZE(codadx6_formats), + }, + [CODA_IMX53] = { + .firmware = "v4l-coda7541-imx53.bin", + .product = CODA_7541, + .formats = coda7_formats, + .num_formats = ARRAY_SIZE(coda7_formats), + }, +}; + +static struct platform_device_id coda_platform_ids[] = { + { .name = "coda-imx27", .driver_data = CODA_IMX27 }, + { .name = "coda-imx53", .driver_data = CODA_7541 }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(platform, coda_platform_ids); + +#ifdef CONFIG_OF +static const struct of_device_id coda_dt_ids[] = { + { .compatible = "fsl,imx27-vpu", .data = &coda_platform_ids[CODA_IMX27] }, + { .compatible = "fsl,imx53-vpu", .data = &coda_devdata[CODA_IMX53] }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, coda_dt_ids); +#endif + +static int __devinit coda_probe(struct platform_device *pdev) +{ + const struct of_device_id *of_id = + of_match_device(of_match_ptr(coda_dt_ids), &pdev->dev); + const struct platform_device_id *pdev_id; + struct coda_dev *dev; + struct resource *res; + int ret, irq; + + dev = devm_kzalloc(&pdev->dev, sizeof *dev, GFP_KERNEL); + if (!dev) { + dev_err(&pdev->dev, "Not enough memory for %s\n", + CODA_NAME); + return -ENOMEM; + } + + spin_lock_init(&dev->irqlock); + INIT_LIST_HEAD(&dev->instances); + INIT_DELAYED_WORK(&dev->timeout, coda_timeout); + init_completion(&dev->done); + complete(&dev->done); + + dev->plat_dev = pdev; + dev->clk_per = devm_clk_get(&pdev->dev, "per"); + if (IS_ERR(dev->clk_per)) { + dev_err(&pdev->dev, "Could not get per clock\n"); + return PTR_ERR(dev->clk_per); + } + + dev->clk_ahb = devm_clk_get(&pdev->dev, "ahb"); + if (IS_ERR(dev->clk_ahb)) { + dev_err(&pdev->dev, "Could not get ahb clock\n"); + return PTR_ERR(dev->clk_ahb); + } + + /* Get memory for physical registers */ + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (res == NULL) { + dev_err(&pdev->dev, "failed to get memory region resource\n"); + return -ENOENT; + } + + if (devm_request_mem_region(&pdev->dev, res->start, + resource_size(res), CODA_NAME) == NULL) { + dev_err(&pdev->dev, "failed to request memory region\n"); + return -ENOENT; + } + dev->regs_base = devm_ioremap(&pdev->dev, res->start, + resource_size(res)); + if (!dev->regs_base) { + dev_err(&pdev->dev, "failed to ioremap address region\n"); + return -ENOENT; + } + + /* IRQ */ + irq = platform_get_irq(pdev, 0); + if (irq < 0) { + dev_err(&pdev->dev, "failed to get irq resource\n"); + return -ENOENT; + } + + if (devm_request_irq(&pdev->dev, irq, coda_irq_handler, + 0, CODA_NAME, dev) < 0) { + dev_err(&pdev->dev, "failed to request irq\n"); + return -ENOENT; + } + + ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev); + if (ret) + return ret; + + mutex_init(&dev->dev_mutex); + + pdev_id = of_id ? of_id->data : platform_get_device_id(pdev); + + if (of_id) { + dev->devtype = of_id->data; + } else if (pdev_id) { + dev->devtype = &coda_devdata[pdev_id->driver_data]; + } else { + v4l2_device_unregister(&dev->v4l2_dev); + return -EINVAL; + } + + /* allocate auxiliary per-device buffers for the BIT processor */ + switch (dev->devtype->product) { + case CODA_DX6: + dev->workbuf.size = CODADX6_WORK_BUF_SIZE; + break; + default: + dev->workbuf.size = CODA7_WORK_BUF_SIZE; + } + dev->workbuf.vaddr = dma_alloc_coherent(&pdev->dev, dev->workbuf.size, + &dev->workbuf.paddr, + GFP_KERNEL); + if (!dev->workbuf.vaddr) { + dev_err(&pdev->dev, "failed to allocate work buffer\n"); + v4l2_device_unregister(&dev->v4l2_dev); + return -ENOMEM; + } + + if (dev->devtype->product == CODA_DX6) { + dev->iram_paddr = 0xffff4c00; + } else { + void __iomem *iram_vaddr; + + iram_vaddr = iram_alloc(CODA7_IRAM_SIZE, + &dev->iram_paddr); + if (!iram_vaddr) { + dev_err(&pdev->dev, "unable to alloc iram\n"); + return -ENOMEM; + } + } + + platform_set_drvdata(pdev, dev); + + return coda_firmware_request(dev); +} + +static int coda_remove(struct platform_device *pdev) +{ + struct coda_dev *dev = platform_get_drvdata(pdev); + + video_unregister_device(&dev->vfd); + if (dev->m2m_dev) + v4l2_m2m_release(dev->m2m_dev); + if (dev->alloc_ctx) + vb2_dma_contig_cleanup_ctx(dev->alloc_ctx); + v4l2_device_unregister(&dev->v4l2_dev); + if (dev->iram_paddr) + iram_free(dev->iram_paddr, CODA7_IRAM_SIZE); + if (dev->codebuf.vaddr) + dma_free_coherent(&pdev->dev, dev->codebuf.size, + &dev->codebuf.vaddr, dev->codebuf.paddr); + if (dev->workbuf.vaddr) + dma_free_coherent(&pdev->dev, dev->workbuf.size, &dev->workbuf.vaddr, + dev->workbuf.paddr); + return 0; +} + +static struct platform_driver coda_driver = { + .probe = coda_probe, + .remove = __devexit_p(coda_remove), + .driver = { + .name = CODA_NAME, + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(coda_dt_ids), + }, + .id_table = coda_platform_ids, +}; + +module_platform_driver(coda_driver); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Javier Martin <javier.martin@vista-silicon.com>"); +MODULE_DESCRIPTION("Coda multi-standard codec V4L2 driver"); diff --git a/drivers/media/platform/coda.h b/drivers/media/platform/coda.h new file mode 100644 index 000000000000..f3f5e43c1ac2 --- /dev/null +++ b/drivers/media/platform/coda.h @@ -0,0 +1,238 @@ +/* + * linux/drivers/media/platform/coda/coda_regs.h + * + * Copyright (C) 2012 Vista Silicon SL + * Javier Martin <javier.martin@vista-silicon.com> + * Xavier Duret + * + * 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. + */ + +#ifndef _REGS_CODA_H_ +#define _REGS_CODA_H_ + +/* HW registers */ +#define CODA_REG_BIT_CODE_RUN 0x000 +#define CODA_REG_RUN_ENABLE (1 << 0) +#define CODA_REG_BIT_CODE_DOWN 0x004 +#define CODA_DOWN_ADDRESS_SET(x) (((x) & 0xffff) << 16) +#define CODA_DOWN_DATA_SET(x) ((x) & 0xffff) +#define CODA_REG_BIT_HOST_IN_REQ 0x008 +#define CODA_REG_BIT_INT_CLEAR 0x00c +#define CODA_REG_BIT_INT_CLEAR_SET 0x1 +#define CODA_REG_BIT_INT_STATUS 0x010 +#define CODA_REG_BIT_CODE_RESET 0x014 +#define CODA_REG_RESET_ENABLE (1 << 0) +#define CODA_REG_BIT_CUR_PC 0x018 + +/* Static SW registers */ +#define CODA_REG_BIT_CODE_BUF_ADDR 0x100 +#define CODA_REG_BIT_WORK_BUF_ADDR 0x104 +#define CODA_REG_BIT_PARA_BUF_ADDR 0x108 +#define CODA_REG_BIT_STREAM_CTRL 0x10c +#define CODA7_STREAM_BUF_PIC_RESET (1 << 4) +#define CODADX6_STREAM_BUF_PIC_RESET (1 << 3) +#define CODA7_STREAM_BUF_PIC_FLUSH (1 << 3) +#define CODADX6_STREAM_BUF_PIC_FLUSH (1 << 2) +#define CODA7_STREAM_BUF_DYNALLOC_EN (1 << 5) +#define CODADX6_STREAM_BUF_DYNALLOC_EN (1 << 4) +#define CODA_STREAM_CHKDIS_OFFSET (1 << 1) +#define CODA_STREAM_ENDIAN_SELECT (1 << 0) +#define CODA_REG_BIT_FRAME_MEM_CTRL 0x110 +#define CODA_IMAGE_ENDIAN_SELECT (1 << 0) +#define CODA_REG_BIT_RD_PTR(x) (0x120 + 8 * (x)) +#define CODA_REG_BIT_WR_PTR(x) (0x124 + 8 * (x)) +#define CODADX6_REG_BIT_SEARCH_RAM_BASE_ADDR 0x140 +#define CODA7_REG_BIT_AXI_SRAM_USE 0x140 +#define CODA7_USE_BIT_ENABLE (1 << 0) +#define CODA7_USE_HOST_BIT_ENABLE (1 << 7) +#define CODA7_USE_ME_ENABLE (1 << 4) +#define CODA7_USE_HOST_ME_ENABLE (1 << 11) +#define CODA_REG_BIT_BUSY 0x160 +#define CODA_REG_BIT_BUSY_FLAG 1 +#define CODA_REG_BIT_RUN_COMMAND 0x164 +#define CODA_COMMAND_SEQ_INIT 1 +#define CODA_COMMAND_SEQ_END 2 +#define CODA_COMMAND_PIC_RUN 3 +#define CODA_COMMAND_SET_FRAME_BUF 4 +#define CODA_COMMAND_ENCODE_HEADER 5 +#define CODA_COMMAND_ENC_PARA_SET 6 +#define CODA_COMMAND_DEC_PARA_SET 7 +#define CODA_COMMAND_DEC_BUF_FLUSH 8 +#define CODA_COMMAND_RC_CHANGE_PARAMETER 9 +#define CODA_COMMAND_FIRMWARE_GET 0xf +#define CODA_REG_BIT_RUN_INDEX 0x168 +#define CODA_INDEX_SET(x) ((x) & 0x3) +#define CODA_REG_BIT_RUN_COD_STD 0x16c +#define CODADX6_MODE_DECODE_MP4 0 +#define CODADX6_MODE_ENCODE_MP4 1 +#define CODADX6_MODE_DECODE_H264 2 +#define CODADX6_MODE_ENCODE_H264 3 +#define CODA7_MODE_DECODE_H264 0 +#define CODA7_MODE_DECODE_VC1 1 +#define CODA7_MODE_DECODE_MP2 2 +#define CODA7_MODE_DECODE_MP4 3 +#define CODA7_MODE_DECODE_DV3 3 +#define CODA7_MODE_DECODE_RV 4 +#define CODA7_MODE_DECODE_MJPG 5 +#define CODA7_MODE_ENCODE_H264 8 +#define CODA7_MODE_ENCODE_MP4 11 +#define CODA7_MODE_ENCODE_MJPG 13 +#define CODA_MODE_INVALID 0xffff +#define CODA_REG_BIT_INT_ENABLE 0x170 +#define CODA_INT_INTERRUPT_ENABLE (1 << 3) + +/* + * Commands' mailbox: + * registers with offsets in the range 0x180-0x1d0 + * have different meaning depending on the command being + * issued. + */ + +/* Encoder Sequence Initialization */ +#define CODA_CMD_ENC_SEQ_BB_START 0x180 +#define CODA_CMD_ENC_SEQ_BB_SIZE 0x184 +#define CODA_CMD_ENC_SEQ_OPTION 0x188 +#define CODA_OPTION_GAMMA_OFFSET 7 +#define CODA_OPTION_GAMMA_MASK 0x01 +#define CODA_OPTION_LIMITQP_OFFSET 6 +#define CODA_OPTION_LIMITQP_MASK 0x01 +#define CODA_OPTION_RCINTRAQP_OFFSET 5 +#define CODA_OPTION_RCINTRAQP_MASK 0x01 +#define CODA_OPTION_FMO_OFFSET 4 +#define CODA_OPTION_FMO_MASK 0x01 +#define CODA_OPTION_SLICEREPORT_OFFSET 1 +#define CODA_OPTION_SLICEREPORT_MASK 0x01 +#define CODA_CMD_ENC_SEQ_COD_STD 0x18c +#define CODA_STD_MPEG4 0 +#define CODA_STD_H263 1 +#define CODA_STD_H264 2 +#define CODA_STD_MJPG 3 +#define CODA_CMD_ENC_SEQ_SRC_SIZE 0x190 +#define CODA7_PICWIDTH_OFFSET 16 +#define CODA7_PICWIDTH_MASK 0xffff +#define CODADX6_PICWIDTH_OFFSET 10 +#define CODADX6_PICWIDTH_MASK 0x3ff +#define CODA_PICHEIGHT_OFFSET 0 +#define CODA_PICHEIGHT_MASK 0x3ff +#define CODA_CMD_ENC_SEQ_SRC_F_RATE 0x194 +#define CODA_CMD_ENC_SEQ_MP4_PARA 0x198 +#define CODA_MP4PARAM_VERID_OFFSET 6 +#define CODA_MP4PARAM_VERID_MASK 0x01 +#define CODA_MP4PARAM_INTRADCVLCTHR_OFFSET 2 +#define CODA_MP4PARAM_INTRADCVLCTHR_MASK 0x07 +#define CODA_MP4PARAM_REVERSIBLEVLCENABLE_OFFSET 1 +#define CODA_MP4PARAM_REVERSIBLEVLCENABLE_MASK 0x01 +#define CODA_MP4PARAM_DATAPARTITIONENABLE_OFFSET 0 +#define CODA_MP4PARAM_DATAPARTITIONENABLE_MASK 0x01 +#define CODA_CMD_ENC_SEQ_263_PARA 0x19c +#define CODA_263PARAM_ANNEXJENABLE_OFFSET 2 +#define CODA_263PARAM_ANNEXJENABLE_MASK 0x01 +#define CODA_263PARAM_ANNEXKENABLE_OFFSET 1 +#define CODA_263PARAM_ANNEXKENABLE_MASK 0x01 +#define CODA_263PARAM_ANNEXTENABLE_OFFSET 0 +#define CODA_263PARAM_ANNEXTENABLE_MASK 0x01 +#define CODA_CMD_ENC_SEQ_264_PARA 0x1a0 +#define CODA_264PARAM_DEBLKFILTEROFFSETBETA_OFFSET 12 +#define CODA_264PARAM_DEBLKFILTEROFFSETBETA_MASK 0x0f +#define CODA_264PARAM_DEBLKFILTEROFFSETALPHA_OFFSET 8 +#define CODA_264PARAM_DEBLKFILTEROFFSETALPHA_MASK 0x0f +#define CODA_264PARAM_DISABLEDEBLK_OFFSET 6 +#define CODA_264PARAM_DISABLEDEBLK_MASK 0x01 +#define CODA_264PARAM_CONSTRAINEDINTRAPREDFLAG_OFFSET 5 +#define CODA_264PARAM_CONSTRAINEDINTRAPREDFLAG_MASK 0x01 +#define CODA_264PARAM_CHROMAQPOFFSET_OFFSET 0 +#define CODA_264PARAM_CHROMAQPOFFSET_MASK 0x1f +#define CODA_CMD_ENC_SEQ_SLICE_MODE 0x1a4 +#define CODA_SLICING_SIZE_OFFSET 2 +#define CODA_SLICING_SIZE_MASK 0x3fffffff +#define CODA_SLICING_UNIT_OFFSET 1 +#define CODA_SLICING_UNIT_MASK 0x01 +#define CODA_SLICING_MODE_OFFSET 0 +#define CODA_SLICING_MODE_MASK 0x01 +#define CODA_CMD_ENC_SEQ_GOP_SIZE 0x1a8 +#define CODA_GOP_SIZE_OFFSET 0 +#define CODA_GOP_SIZE_MASK 0x3f +#define CODA_CMD_ENC_SEQ_RC_PARA 0x1ac +#define CODA_RATECONTROL_AUTOSKIP_OFFSET 31 +#define CODA_RATECONTROL_AUTOSKIP_MASK 0x01 +#define CODA_RATECONTROL_INITIALDELAY_OFFSET 16 +#define CODA_RATECONTROL_INITIALDELAY_MASK 0x7f +#define CODA_RATECONTROL_BITRATE_OFFSET 1 +#define CODA_RATECONTROL_BITRATE_MASK 0x7f +#define CODA_RATECONTROL_ENABLE_OFFSET 0 +#define CODA_RATECONTROL_ENABLE_MASK 0x01 +#define CODA_CMD_ENC_SEQ_RC_BUF_SIZE 0x1b0 +#define CODA_CMD_ENC_SEQ_INTRA_REFRESH 0x1b4 +#define CODADX6_CMD_ENC_SEQ_FMO 0x1b8 +#define CODA_FMOPARAM_TYPE_OFFSET 4 +#define CODA_FMOPARAM_TYPE_MASK 1 +#define CODA_FMOPARAM_SLICENUM_OFFSET 0 +#define CODA_FMOPARAM_SLICENUM_MASK 0x0f +#define CODA7_CMD_ENC_SEQ_SEARCH_BASE 0x1b8 +#define CODA7_CMD_ENC_SEQ_SEARCH_SIZE 0x1bc +#define CODA_CMD_ENC_SEQ_RC_QP_MAX 0x1c8 +#define CODA_QPMAX_OFFSET 0 +#define CODA_QPMAX_MASK 0x3f +#define CODA_CMD_ENC_SEQ_RC_GAMMA 0x1cc +#define CODA_GAMMA_OFFSET 0 +#define CODA_GAMMA_MASK 0xffff +#define CODA_RET_ENC_SEQ_SUCCESS 0x1c0 + +/* Encoder Picture Run */ +#define CODA_CMD_ENC_PIC_SRC_ADDR_Y 0x180 +#define CODA_CMD_ENC_PIC_SRC_ADDR_CB 0x184 +#define CODA_CMD_ENC_PIC_SRC_ADDR_CR 0x188 +#define CODA_CMD_ENC_PIC_QS 0x18c +#define CODA_CMD_ENC_PIC_ROT_MODE 0x190 +#define CODA_ROT_MIR_ENABLE (1 << 4) +#define CODA_ROT_0 (0x0 << 0) +#define CODA_ROT_90 (0x1 << 0) +#define CODA_ROT_180 (0x2 << 0) +#define CODA_ROT_270 (0x3 << 0) +#define CODA_MIR_NONE (0x0 << 2) +#define CODA_MIR_VER (0x1 << 2) +#define CODA_MIR_HOR (0x2 << 2) +#define CODA_MIR_VER_HOR (0x3 << 2) +#define CODA_CMD_ENC_PIC_OPTION 0x194 +#define CODA_CMD_ENC_PIC_BB_START 0x198 +#define CODA_CMD_ENC_PIC_BB_SIZE 0x19c +#define CODA_RET_ENC_PIC_TYPE 0x1c4 +#define CODA_RET_ENC_PIC_SLICE_NUM 0x1cc +#define CODA_RET_ENC_PIC_FLAG 0x1d0 + +/* Set Frame Buffer */ +#define CODA_CMD_SET_FRAME_BUF_NUM 0x180 +#define CODA_CMD_SET_FRAME_BUF_STRIDE 0x184 +#define CODA7_CMD_SET_FRAME_AXI_BIT_ADDR 0x190 +#define CODA7_CMD_SET_FRAME_AXI_IPACDC_ADDR 0x194 +#define CODA7_CMD_SET_FRAME_AXI_DBKY_ADDR 0x198 +#define CODA7_CMD_SET_FRAME_AXI_DBKC_ADDR 0x19c +#define CODA7_CMD_SET_FRAME_AXI_OVL_ADDR 0x1a0 +#define CODA7_CMD_SET_FRAME_SOURCE_BUF_STRIDE 0x1a8 + +/* Encoder Header */ +#define CODA_CMD_ENC_HEADER_CODE 0x180 +#define CODA_GAMMA_OFFSET 0 +#define CODA_HEADER_H264_SPS 0 +#define CODA_HEADER_H264_PPS 1 +#define CODA_HEADER_MP4V_VOL 0 +#define CODA_HEADER_MP4V_VOS 1 +#define CODA_HEADER_MP4V_VIS 2 +#define CODA_CMD_ENC_HEADER_BB_START 0x184 +#define CODA_CMD_ENC_HEADER_BB_SIZE 0x188 + +/* Get Version */ +#define CODA_CMD_FIRMWARE_VERNUM 0x1c0 +#define CODA_FIRMWARE_PRODUCT(x) (((x) >> 16) & 0xffff) +#define CODA_FIRMWARE_MAJOR(x) (((x) >> 12) & 0x0f) +#define CODA_FIRMWARE_MINOR(x) (((x) >> 8) & 0x0f) +#define CODA_FIRMWARE_RELEASE(x) ((x) & 0xff) +#define CODA_FIRMWARE_VERNUM(product, major, minor, release) \ + ((product) << 16 | ((major) << 12) | \ + ((minor) << 8) | (release)) + +#endif diff --git a/drivers/media/video/davinci/Kconfig b/drivers/media/platform/davinci/Kconfig index 52c5ca68cb3d..78e26d24f637 100644 --- a/drivers/media/video/davinci/Kconfig +++ b/drivers/media/platform/davinci/Kconfig @@ -3,8 +3,8 @@ config VIDEO_DAVINCI_VPIF_DISPLAY depends on VIDEO_DEV && (MACH_DAVINCI_DM6467_EVM || MACH_DAVINCI_DA850_EVM) select VIDEOBUF2_DMA_CONTIG select VIDEO_DAVINCI_VPIF - select VIDEO_ADV7343 if VIDEO_HELPER_CHIPS_AUTO - select VIDEO_THS7303 if VIDEO_HELPER_CHIPS_AUTO + select VIDEO_ADV7343 if MEDIA_SUBDRV_AUTOSELECT + select VIDEO_THS7303 if MEDIA_SUBDRV_AUTOSELECT help Enables Davinci VPIF module used for display devices. This module is common for following DM6467/DA850/OMAPL138 diff --git a/drivers/media/video/davinci/Makefile b/drivers/media/platform/davinci/Makefile index 74ed92d09257..74ed92d09257 100644 --- a/drivers/media/video/davinci/Makefile +++ b/drivers/media/platform/davinci/Makefile diff --git a/drivers/media/video/davinci/ccdc_hw_device.h b/drivers/media/platform/davinci/ccdc_hw_device.h index 86b9b3518965..86b9b3518965 100644 --- a/drivers/media/video/davinci/ccdc_hw_device.h +++ b/drivers/media/platform/davinci/ccdc_hw_device.h diff --git a/drivers/media/video/davinci/dm355_ccdc.c b/drivers/media/platform/davinci/dm355_ccdc.c index 5b68847d4017..ce0e4131c067 100644 --- a/drivers/media/video/davinci/dm355_ccdc.c +++ b/drivers/media/platform/davinci/dm355_ccdc.c @@ -965,7 +965,7 @@ static struct ccdc_hw_device ccdc_hw_dev = { }, }; -static int __init dm355_ccdc_probe(struct platform_device *pdev) +static int __devinit dm355_ccdc_probe(struct platform_device *pdev) { void (*setup_pinmux)(void); struct resource *res; diff --git a/drivers/media/video/davinci/dm355_ccdc_regs.h b/drivers/media/platform/davinci/dm355_ccdc_regs.h index d6d2ef0533b5..d6d2ef0533b5 100644 --- a/drivers/media/video/davinci/dm355_ccdc_regs.h +++ b/drivers/media/platform/davinci/dm355_ccdc_regs.h diff --git a/drivers/media/video/davinci/dm644x_ccdc.c b/drivers/media/platform/davinci/dm644x_ccdc.c index 9303fe553b07..ee7942b1996e 100644 --- a/drivers/media/video/davinci/dm644x_ccdc.c +++ b/drivers/media/platform/davinci/dm644x_ccdc.c @@ -957,7 +957,7 @@ static struct ccdc_hw_device ccdc_hw_dev = { }, }; -static int __init dm644x_ccdc_probe(struct platform_device *pdev) +static int __devinit dm644x_ccdc_probe(struct platform_device *pdev) { struct resource *res; int status = 0; diff --git a/drivers/media/video/davinci/dm644x_ccdc_regs.h b/drivers/media/platform/davinci/dm644x_ccdc_regs.h index 90370e414e2c..90370e414e2c 100644 --- a/drivers/media/video/davinci/dm644x_ccdc_regs.h +++ b/drivers/media/platform/davinci/dm644x_ccdc_regs.h diff --git a/drivers/media/video/davinci/isif.c b/drivers/media/platform/davinci/isif.c index 5278fe7d6d0c..b99d5423e3a8 100644 --- a/drivers/media/video/davinci/isif.c +++ b/drivers/media/platform/davinci/isif.c @@ -1032,7 +1032,7 @@ static struct ccdc_hw_device isif_hw_dev = { }, }; -static int __init isif_probe(struct platform_device *pdev) +static int __devinit isif_probe(struct platform_device *pdev) { void (*setup_pinmux)(void); struct resource *res; diff --git a/drivers/media/video/davinci/isif_regs.h b/drivers/media/platform/davinci/isif_regs.h index aa69a463c122..aa69a463c122 100644 --- a/drivers/media/video/davinci/isif_regs.h +++ b/drivers/media/platform/davinci/isif_regs.h diff --git a/drivers/media/video/davinci/vpbe.c b/drivers/media/platform/davinci/vpbe.c index c4a82a1a8a97..c4a82a1a8a97 100644 --- a/drivers/media/video/davinci/vpbe.c +++ b/drivers/media/platform/davinci/vpbe.c diff --git a/drivers/media/video/davinci/vpbe_display.c b/drivers/media/platform/davinci/vpbe_display.c index 6fe7034bea7c..239f37bfa313 100644 --- a/drivers/media/video/davinci/vpbe_display.c +++ b/drivers/media/platform/davinci/vpbe_display.c @@ -629,7 +629,7 @@ static int vpbe_display_querycap(struct file *file, void *priv, } static int vpbe_display_s_crop(struct file *file, void *priv, - struct v4l2_crop *crop) + const struct v4l2_crop *crop) { struct vpbe_fh *fh = file->private_data; struct vpbe_layer *layer = fh->layer; @@ -1376,10 +1376,15 @@ static int vpbe_display_mmap(struct file *filep, struct vm_area_struct *vma) struct vpbe_fh *fh = filep->private_data; struct vpbe_layer *layer = fh->layer; struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev; + int ret; v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "vpbe_display_mmap\n"); - return videobuf_mmap_mapper(&layer->buffer_queue, vma); + if (mutex_lock_interruptible(&layer->opslock)) + return -ERESTARTSYS; + ret = videobuf_mmap_mapper(&layer->buffer_queue, vma); + mutex_unlock(&layer->opslock); + return ret; } /* vpbe_display_poll(): It is used for select/poll system call @@ -1392,8 +1397,11 @@ static unsigned int vpbe_display_poll(struct file *filep, poll_table *wait) unsigned int err = 0; v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "vpbe_display_poll\n"); - if (layer->started) + if (layer->started) { + mutex_lock(&layer->opslock); err = videobuf_poll_stream(filep, &layer->buffer_queue, wait); + mutex_unlock(&layer->opslock); + } return err; } @@ -1428,10 +1436,12 @@ static int vpbe_display_open(struct file *file) fh->disp_dev = disp_dev; if (!layer->usrs) { - + if (mutex_lock_interruptible(&layer->opslock)) + return -ERESTARTSYS; /* First claim the layer for this device */ err = osd_device->ops.request_layer(osd_device, layer->layer_info.id); + mutex_unlock(&layer->opslock); if (err < 0) { /* Couldn't get layer */ v4l2_err(&vpbe_dev->v4l2_dev, @@ -1469,6 +1479,7 @@ static int vpbe_display_release(struct file *file) v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "vpbe_display_release\n"); + mutex_lock(&layer->opslock); /* if this instance is doing IO */ if (fh->io_allowed) { /* Reset io_usrs member of layer object */ @@ -1503,6 +1514,7 @@ static int vpbe_display_release(struct file *file) /* Close the priority */ v4l2_prio_close(&layer->prio, fh->prio); file->private_data = NULL; + mutex_unlock(&layer->opslock); /* Free memory allocated to file handle object */ kfree(fh); @@ -1620,11 +1632,8 @@ static __devinit int init_vpbe_layer(int i, struct vpbe_display *disp_dev, vbd->ioctl_ops = &vpbe_ioctl_ops; vbd->minor = -1; vbd->v4l2_dev = &disp_dev->vpbe_dev->v4l2_dev; - /* Locking in file operations other than ioctl should be done - by the driver, not the V4L2 core. - This driver needs auditing so that this flag can be removed. */ - set_bit(V4L2_FL_LOCK_ALL_FOPS, &vbd->flags); vbd->lock = &vpbe_display_layer->opslock; + vbd->vfl_dir = VFL_DIR_TX; if (disp_dev->vpbe_dev->current_timings.timings_type & VPBE_ENC_STD) { diff --git a/drivers/media/video/davinci/vpbe_osd.c b/drivers/media/platform/davinci/vpbe_osd.c index bba299dbf396..bba299dbf396 100644 --- a/drivers/media/video/davinci/vpbe_osd.c +++ b/drivers/media/platform/davinci/vpbe_osd.c diff --git a/drivers/media/video/davinci/vpbe_osd_regs.h b/drivers/media/platform/davinci/vpbe_osd_regs.h index 584520f3af60..584520f3af60 100644 --- a/drivers/media/video/davinci/vpbe_osd_regs.h +++ b/drivers/media/platform/davinci/vpbe_osd_regs.h diff --git a/drivers/media/video/davinci/vpbe_venc.c b/drivers/media/platform/davinci/vpbe_venc.c index 0302669622d6..0302669622d6 100644 --- a/drivers/media/video/davinci/vpbe_venc.c +++ b/drivers/media/platform/davinci/vpbe_venc.c diff --git a/drivers/media/video/davinci/vpbe_venc_regs.h b/drivers/media/platform/davinci/vpbe_venc_regs.h index 947cb1510776..947cb1510776 100644 --- a/drivers/media/video/davinci/vpbe_venc_regs.h +++ b/drivers/media/platform/davinci/vpbe_venc_regs.h diff --git a/drivers/media/video/davinci/vpfe_capture.c b/drivers/media/platform/davinci/vpfe_capture.c index 49a845fb804a..48052cbffc2b 100644 --- a/drivers/media/video/davinci/vpfe_capture.c +++ b/drivers/media/platform/davinci/vpfe_capture.c @@ -1131,11 +1131,11 @@ static int vpfe_s_input(struct file *file, void *priv, unsigned int index) ret = -EBUSY; goto unlock_out; } - - if (vpfe_get_subdev_input_index(vpfe_dev, - &subdev_index, - &inp_index, - index) < 0) { + ret = vpfe_get_subdev_input_index(vpfe_dev, + &subdev_index, + &inp_index, + index); + if (ret < 0) { v4l2_err(&vpfe_dev->v4l2_dev, "invalid input index\n"); goto unlock_out; } @@ -1666,7 +1666,7 @@ static int vpfe_g_crop(struct file *file, void *priv, } static int vpfe_s_crop(struct file *file, void *priv, - struct v4l2_crop *crop) + const struct v4l2_crop *crop) { struct vpfe_device *vpfe_dev = video_drvdata(file); int ret = 0; @@ -1748,8 +1748,9 @@ static long vpfe_param_handler(struct file *file, void *priv, "Error setting parameters in CCDC\n"); goto unlock_out; } - if (vpfe_get_ccdc_image_format(vpfe_dev, - &vpfe_dev->fmt) < 0) { + ret = vpfe_get_ccdc_image_format(vpfe_dev, + &vpfe_dev->fmt); + if (ret < 0) { v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "Invalid image format at CCDC\n"); goto unlock_out; @@ -1829,7 +1830,7 @@ static struct vpfe_device *vpfe_initialize(void) * itself to the V4L2 driver and initializes fields of each * device objects */ -static __init int vpfe_probe(struct platform_device *pdev) +static __devinit int vpfe_probe(struct platform_device *pdev) { struct vpfe_subdev_info *sdinfo; struct vpfe_config *vpfe_cfg; diff --git a/drivers/media/video/davinci/vpif.c b/drivers/media/platform/davinci/vpif.c index b3637aff8fee..cff3c0ab501f 100644 --- a/drivers/media/video/davinci/vpif.c +++ b/drivers/media/platform/davinci/vpif.c @@ -25,6 +25,8 @@ #include <linux/io.h> #include <linux/clk.h> #include <linux/err.h> +#include <linux/v4l2-dv-timings.h> + #include <mach/hardware.h> #include "vpif.h" @@ -65,7 +67,7 @@ const struct vpif_channel_config_params ch_params[] = { .capture_format = 0, .vbi_supported = 0, .hd_sd = 1, - .dv_preset = V4L2_DV_480P59_94, + .dv_timings = V4L2_DV_BT_CEA_720X480P59_94, }, { .name = "576p50", @@ -82,7 +84,7 @@ const struct vpif_channel_config_params ch_params[] = { .capture_format = 0, .vbi_supported = 0, .hd_sd = 1, - .dv_preset = V4L2_DV_576P50, + .dv_timings = V4L2_DV_BT_CEA_720X576P50, }, { .name = "720p50", @@ -99,7 +101,7 @@ const struct vpif_channel_config_params ch_params[] = { .capture_format = 0, .vbi_supported = 0, .hd_sd = 1, - .dv_preset = V4L2_DV_720P50, + .dv_timings = V4L2_DV_BT_CEA_1280X720P50, }, { .name = "720p60", @@ -116,7 +118,7 @@ const struct vpif_channel_config_params ch_params[] = { .capture_format = 0, .vbi_supported = 0, .hd_sd = 1, - .dv_preset = V4L2_DV_720P60, + .dv_timings = V4L2_DV_BT_CEA_1280X720P60, }, { .name = "1080I50", @@ -136,7 +138,7 @@ const struct vpif_channel_config_params ch_params[] = { .capture_format = 0, .vbi_supported = 0, .hd_sd = 1, - .dv_preset = V4L2_DV_1080I50, + .dv_timings = V4L2_DV_BT_CEA_1920X1080I50, }, { .name = "1080I60", @@ -156,7 +158,7 @@ const struct vpif_channel_config_params ch_params[] = { .capture_format = 0, .vbi_supported = 0, .hd_sd = 1, - .dv_preset = V4L2_DV_1080I60, + .dv_timings = V4L2_DV_BT_CEA_1920X1080I60, }, { .name = "1080p60", @@ -173,7 +175,7 @@ const struct vpif_channel_config_params ch_params[] = { .capture_format = 0, .vbi_supported = 0, .hd_sd = 1, - .dv_preset = V4L2_DV_1080P60, + .dv_timings = V4L2_DV_BT_CEA_1920X1080P60, }, /* SDTV formats */ @@ -417,7 +419,7 @@ int vpif_channel_getfid(u8 channel_id) } EXPORT_SYMBOL(vpif_channel_getfid); -static int __init vpif_probe(struct platform_device *pdev) +static int __devinit vpif_probe(struct platform_device *pdev) { int status = 0; diff --git a/drivers/media/video/davinci/vpif.h b/drivers/media/platform/davinci/vpif.h index c2ce4d97c279..a1ab6a0f4e9e 100644 --- a/drivers/media/video/davinci/vpif.h +++ b/drivers/media/platform/davinci/vpif.h @@ -533,7 +533,7 @@ static inline void channel2_clipping_enable(int enable) } } -/* function to enable clipping (for both active and blanking regions) on ch 2 */ +/* function to enable clipping (for both active and blanking regions) on ch 3 */ static inline void channel3_clipping_enable(int enable) { if (enable) { @@ -634,7 +634,7 @@ struct vpif_channel_config_params { * supports capturing vbi or not */ u8 hd_sd; /* HDTV (1) or SDTV (0) format */ v4l2_std_id stdid; /* SDTV format */ - u32 dv_preset; /* HDTV format */ + struct v4l2_dv_timings dv_timings; /* HDTV format */ }; extern const unsigned int vpif_ch_params_count; diff --git a/drivers/media/video/davinci/vpif_capture.c b/drivers/media/platform/davinci/vpif_capture.c index 266025e5d81d..0bafecac4923 100644 --- a/drivers/media/video/davinci/vpif_capture.c +++ b/drivers/media/platform/davinci/vpif_capture.c @@ -339,6 +339,7 @@ static int vpif_start_streaming(struct vb2_queue *vq, unsigned int count) * Set interrupt for both the fields in VPIF Register enable channel in * VPIF register */ + channel_first_int[VPIF_VIDEO_INDEX][ch->channel_id] = 1; if ((VPIF_CHANNEL0_VIDEO == ch->channel_id)) { channel0_intr_assert(); channel0_intr_enable(1); @@ -350,7 +351,6 @@ static int vpif_start_streaming(struct vb2_queue *vq, unsigned int count) channel1_intr_enable(1); enable_channel1(1); } - channel_first_int[VPIF_VIDEO_INDEX][ch->channel_id] = 1; return 0; } @@ -551,7 +551,8 @@ static int vpif_update_std_info(struct channel_obj *ch) } } else { vpif_dbg(2, debug, "HD format\n"); - if (config->dv_preset == vid_ch->dv_preset) { + if (!memcmp(&config->dv_timings, &vid_ch->dv_timings, + sizeof(vid_ch->dv_timings))) { memcpy(std_info, config, sizeof(*config)); break; } @@ -820,10 +821,15 @@ static int vpif_mmap(struct file *filep, struct vm_area_struct *vma) struct vpif_fh *fh = filep->private_data; struct channel_obj *ch = fh->channel; struct common_obj *common = &(ch->common[VPIF_VIDEO_INDEX]); + int ret; vpif_dbg(2, debug, "vpif_mmap\n"); - return vb2_mmap(&common->buffer_queue, vma); + if (mutex_lock_interruptible(&common->lock)) + return -ERESTARTSYS; + ret = vb2_mmap(&common->buffer_queue, vma); + mutex_unlock(&common->lock); + return ret; } /** @@ -836,12 +842,16 @@ static unsigned int vpif_poll(struct file *filep, poll_table * wait) struct vpif_fh *fh = filep->private_data; struct channel_obj *channel = fh->channel; struct common_obj *common = &(channel->common[VPIF_VIDEO_INDEX]); + unsigned int res = 0; vpif_dbg(2, debug, "vpif_poll\n"); - if (common->started) - return vb2_poll(&common->buffer_queue, filep, wait); - return 0; + if (common->started) { + mutex_lock(&common->lock); + res = vb2_poll(&common->buffer_queue, filep, wait); + mutex_unlock(&common->lock); + } + return res; } /** @@ -895,6 +905,10 @@ static int vpif_open(struct file *filep) return -ENOMEM; } + if (mutex_lock_interruptible(&common->lock)) { + kfree(fh); + return -ERESTARTSYS; + } /* store pointer to fh in private_data member of filep */ filep->private_data = fh; fh->channel = ch; @@ -912,6 +926,7 @@ static int vpif_open(struct file *filep) /* Initialize priority of this instance to default priority */ fh->prio = V4L2_PRIORITY_UNSET; v4l2_prio_open(&ch->prio, &fh->prio); + mutex_unlock(&common->lock); return 0; } @@ -932,6 +947,7 @@ static int vpif_release(struct file *filep) common = &ch->common[VPIF_VIDEO_INDEX]; + mutex_lock(&common->lock); /* if this instance is doing IO */ if (fh->io_allowed[VPIF_VIDEO_INDEX]) { /* Reset io_usrs member of channel object */ @@ -961,6 +977,7 @@ static int vpif_release(struct file *filep) if (fh->initialized) ch->initialized = 0; + mutex_unlock(&common->lock); filep->private_data = NULL; kfree(fh); return 0; @@ -1368,8 +1385,7 @@ static int vpif_s_std(struct file *file, void *priv, v4l2_std_id *std_id) /* Call encoder subdevice function to set the standard */ ch->video.stdid = *std_id; - ch->video.dv_preset = V4L2_DV_INVALID; - memset(&ch->video.bt_timings, 0, sizeof(ch->video.bt_timings)); + memset(&ch->video.dv_timings, 0, sizeof(ch->video.dv_timings)); /* Get the information about the standard */ if (vpif_update_std_info(ch)) { @@ -1703,108 +1719,37 @@ static int vpif_cropcap(struct file *file, void *priv, } /** - * vpif_enum_dv_presets() - ENUM_DV_PRESETS handler + * vpif_enum_dv_timings() - ENUM_DV_TIMINGS handler * @file: file ptr * @priv: file handle - * @preset: input preset + * @timings: input timings */ -static int vpif_enum_dv_presets(struct file *file, void *priv, - struct v4l2_dv_enum_preset *preset) +static int +vpif_enum_dv_timings(struct file *file, void *priv, + struct v4l2_enum_dv_timings *timings) { struct vpif_fh *fh = priv; struct channel_obj *ch = fh->channel; return v4l2_subdev_call(vpif_obj.sd[ch->curr_sd_index], - video, enum_dv_presets, preset); + video, enum_dv_timings, timings); } /** - * vpif_query_dv_presets() - QUERY_DV_PRESET handler + * vpif_query_dv_timings() - QUERY_DV_TIMINGS handler * @file: file ptr * @priv: file handle - * @preset: input preset + * @timings: input timings */ -static int vpif_query_dv_preset(struct file *file, void *priv, - struct v4l2_dv_preset *preset) +static int +vpif_query_dv_timings(struct file *file, void *priv, + struct v4l2_dv_timings *timings) { struct vpif_fh *fh = priv; struct channel_obj *ch = fh->channel; return v4l2_subdev_call(vpif_obj.sd[ch->curr_sd_index], - video, query_dv_preset, preset); -} -/** - * vpif_s_dv_presets() - S_DV_PRESETS handler - * @file: file ptr - * @priv: file handle - * @preset: input preset - */ -static int vpif_s_dv_preset(struct file *file, void *priv, - struct v4l2_dv_preset *preset) -{ - struct vpif_fh *fh = priv; - struct channel_obj *ch = fh->channel; - struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; - int ret = 0; - - if (common->started) { - vpif_dbg(1, debug, "streaming in progress\n"); - return -EBUSY; - } - - if ((VPIF_CHANNEL0_VIDEO == ch->channel_id) || - (VPIF_CHANNEL1_VIDEO == ch->channel_id)) { - if (!fh->initialized) { - vpif_dbg(1, debug, "Channel Busy\n"); - return -EBUSY; - } - } - - ret = v4l2_prio_check(&ch->prio, fh->prio); - if (ret) - return ret; - - fh->initialized = 1; - - /* Call encoder subdevice function to set the standard */ - if (mutex_lock_interruptible(&common->lock)) - return -ERESTARTSYS; - - ch->video.dv_preset = preset->preset; - ch->video.stdid = V4L2_STD_UNKNOWN; - memset(&ch->video.bt_timings, 0, sizeof(ch->video.bt_timings)); - - /* Get the information about the standard */ - if (vpif_update_std_info(ch)) { - vpif_dbg(1, debug, "Error getting the standard info\n"); - ret = -EINVAL; - } else { - /* Configure the default format information */ - vpif_config_format(ch); - - ret = v4l2_subdev_call(vpif_obj.sd[ch->curr_sd_index], - video, s_dv_preset, preset); - } - - mutex_unlock(&common->lock); - - return ret; -} -/** - * vpif_g_dv_presets() - G_DV_PRESETS handler - * @file: file ptr - * @priv: file handle - * @preset: input preset - */ -static int vpif_g_dv_preset(struct file *file, void *priv, - struct v4l2_dv_preset *preset) -{ - struct vpif_fh *fh = priv; - struct channel_obj *ch = fh->channel; - - preset->preset = ch->video.dv_preset; - - return 0; + video, query_dv_timings, timings); } /** @@ -1821,7 +1766,7 @@ static int vpif_s_dv_timings(struct file *file, void *priv, struct vpif_params *vpifparams = &ch->vpifparams; struct vpif_channel_config_params *std_info = &vpifparams->std_info; struct video_obj *vid_ch = &ch->video; - struct v4l2_bt_timings *bt = &vid_ch->bt_timings; + struct v4l2_bt_timings *bt = &vid_ch->dv_timings.bt; int ret; if (timings->type != V4L2_DV_BT_656_1120) { @@ -1857,7 +1802,7 @@ static int vpif_s_dv_timings(struct file *file, void *priv, return -EINVAL; } - *bt = timings->bt; + vid_ch->dv_timings = *timings; /* Configure video port timings */ @@ -1900,10 +1845,8 @@ static int vpif_s_dv_timings(struct file *file, void *priv, std_info->vbi_supported = 0; std_info->hd_sd = 1; std_info->stdid = 0; - std_info->dv_preset = V4L2_DV_INVALID; vid_ch->stdid = 0; - vid_ch->dv_preset = V4L2_DV_INVALID; return 0; } @@ -1919,9 +1862,8 @@ static int vpif_g_dv_timings(struct file *file, void *priv, struct vpif_fh *fh = priv; struct channel_obj *ch = fh->channel; struct video_obj *vid_ch = &ch->video; - struct v4l2_bt_timings *bt = &vid_ch->bt_timings; - timings->bt = *bt; + *timings = vid_ch->dv_timings; return 0; } @@ -2024,10 +1966,8 @@ static const struct v4l2_ioctl_ops vpif_ioctl_ops = { .vidioc_streamon = vpif_streamon, .vidioc_streamoff = vpif_streamoff, .vidioc_cropcap = vpif_cropcap, - .vidioc_enum_dv_presets = vpif_enum_dv_presets, - .vidioc_s_dv_preset = vpif_s_dv_preset, - .vidioc_g_dv_preset = vpif_g_dv_preset, - .vidioc_query_dv_preset = vpif_query_dv_preset, + .vidioc_enum_dv_timings = vpif_enum_dv_timings, + .vidioc_query_dv_timings = vpif_query_dv_timings, .vidioc_s_dv_timings = vpif_s_dv_timings, .vidioc_g_dv_timings = vpif_g_dv_timings, .vidioc_g_chip_ident = vpif_g_chip_ident, @@ -2208,10 +2148,6 @@ static __init int vpif_probe(struct platform_device *pdev) common = &(ch->common[VPIF_VIDEO_INDEX]); spin_lock_init(&common->irqlock); mutex_init(&common->lock); - /* Locking in file operations other than ioctl should be done - by the driver, not the V4L2 core. - This driver needs auditing so that this flag can be removed. */ - set_bit(V4L2_FL_LOCK_ALL_FOPS, &ch->video_dev->flags); ch->video_dev->lock = &common->lock; /* Initialize prio member of channel object */ v4l2_prio_init(&ch->prio); diff --git a/drivers/media/video/davinci/vpif_capture.h b/drivers/media/platform/davinci/vpif_capture.h index 3511510f43ee..d24efc17e4c8 100644 --- a/drivers/media/video/davinci/vpif_capture.h +++ b/drivers/media/platform/davinci/vpif_capture.h @@ -25,7 +25,6 @@ #include <linux/videodev2.h> #include <media/v4l2-common.h> #include <media/v4l2-device.h> -#include <media/videobuf-core.h> #include <media/videobuf2-dma-contig.h> #include <media/davinci/vpif_types.h> @@ -54,8 +53,7 @@ struct video_obj { enum v4l2_field buf_field; /* Currently selected or default standard */ v4l2_std_id stdid; - u32 dv_preset; - struct v4l2_bt_timings bt_timings; + struct v4l2_dv_timings dv_timings; /* This is to track the last input that is passed to application */ u32 input_idx; }; diff --git a/drivers/media/video/davinci/vpif_display.c b/drivers/media/platform/davinci/vpif_display.c index e129c98921ad..a5b88689abad 100644 --- a/drivers/media/video/davinci/vpif_display.c +++ b/drivers/media/platform/davinci/vpif_display.c @@ -302,6 +302,7 @@ static int vpif_start_streaming(struct vb2_queue *vq, unsigned int count) /* Set interrupt for both the fields in VPIF Register enable channel in VPIF register */ + channel_first_int[VPIF_VIDEO_INDEX][ch->channel_id] = 1; if (VPIF_CHANNEL2_VIDEO == ch->channel_id) { channel2_intr_assert(); channel2_intr_enable(1); @@ -318,7 +319,6 @@ static int vpif_start_streaming(struct vb2_queue *vq, unsigned int count) if (vpif_config_data->ch3_clip_en) channel3_clipping_enable(1); } - channel_first_int[VPIF_VIDEO_INDEX][ch->channel_id] = 1; return 0; } @@ -499,12 +499,6 @@ static int vpif_update_std_info(struct channel_obj *ch) memcpy(std_info, config, sizeof(*config)); break; } - } else { - vpif_dbg(2, debug, "HD format\n"); - if (config->dv_preset == vid_ch->dv_preset) { - memcpy(std_info, config, sizeof(*config)); - break; - } } } @@ -523,10 +517,10 @@ static int vpif_update_resolution(struct channel_obj *ch) struct vpif_params *vpifparams = &ch->vpifparams; struct vpif_channel_config_params *std_info = &vpifparams->std_info; - if (!vid_ch->stdid && !vid_ch->dv_preset && !vid_ch->bt_timings.height) + if (!vid_ch->stdid && !vid_ch->dv_timings.bt.height) return -EINVAL; - if (vid_ch->stdid || vid_ch->dv_preset) { + if (vid_ch->stdid) { if (vpif_update_std_info(ch)) return -EINVAL; } @@ -695,10 +689,15 @@ static int vpif_mmap(struct file *filep, struct vm_area_struct *vma) struct vpif_fh *fh = filep->private_data; struct channel_obj *ch = fh->channel; struct common_obj *common = &(ch->common[VPIF_VIDEO_INDEX]); + int ret; vpif_dbg(2, debug, "vpif_mmap\n"); - return vb2_mmap(&common->buffer_queue, vma); + if (mutex_lock_interruptible(&common->lock)) + return -ERESTARTSYS; + ret = vb2_mmap(&common->buffer_queue, vma); + mutex_unlock(&common->lock); + return ret; } /* @@ -709,11 +708,15 @@ static unsigned int vpif_poll(struct file *filep, poll_table *wait) struct vpif_fh *fh = filep->private_data; struct channel_obj *ch = fh->channel; struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; + unsigned int res = 0; - if (common->started) - return vb2_poll(&common->buffer_queue, filep, wait); + if (common->started) { + mutex_lock(&common->lock); + res = vb2_poll(&common->buffer_queue, filep, wait); + mutex_unlock(&common->lock); + } - return 0; + return res; } /* @@ -723,10 +726,10 @@ static unsigned int vpif_poll(struct file *filep, poll_table *wait) static int vpif_open(struct file *filep) { struct video_device *vdev = video_devdata(filep); - struct channel_obj *ch = NULL; - struct vpif_fh *fh = NULL; + struct channel_obj *ch = video_get_drvdata(vdev); + struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; + struct vpif_fh *fh; - ch = video_get_drvdata(vdev); /* Allocate memory for the file handle object */ fh = kzalloc(sizeof(struct vpif_fh), GFP_KERNEL); if (fh == NULL) { @@ -734,6 +737,10 @@ static int vpif_open(struct file *filep) return -ENOMEM; } + if (mutex_lock_interruptible(&common->lock)) { + kfree(fh); + return -ERESTARTSYS; + } /* store pointer to fh in private_data member of filep */ filep->private_data = fh; fh->channel = ch; @@ -751,6 +758,7 @@ static int vpif_open(struct file *filep) /* Initialize priority of this instance to default priority */ fh->prio = V4L2_PRIORITY_UNSET; v4l2_prio_open(&ch->prio, &fh->prio); + mutex_unlock(&common->lock); return 0; } @@ -765,6 +773,7 @@ static int vpif_release(struct file *filep) struct channel_obj *ch = fh->channel; struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; + mutex_lock(&common->lock); /* if this instance is doing IO */ if (fh->io_allowed[VPIF_VIDEO_INDEX]) { /* Reset io_usrs member of channel object */ @@ -799,6 +808,7 @@ static int vpif_release(struct file *filep) v4l2_prio_close(&ch->prio, fh->prio); filep->private_data = NULL; fh->initialized = 0; + mutex_unlock(&common->lock); kfree(fh); return 0; @@ -1039,9 +1049,7 @@ static int vpif_s_std(struct file *file, void *priv, v4l2_std_id *std_id) /* Call encoder subdevice function to set the standard */ ch->video.stdid = *std_id; - ch->video.dv_preset = V4L2_DV_INVALID; - memset(&ch->video.bt_timings, 0, sizeof(ch->video.bt_timings)); - + memset(&ch->video.dv_timings, 0, sizeof(ch->video.dv_timings)); /* Get the information about the standard */ if (vpif_update_resolution(ch)) return -EINVAL; @@ -1271,88 +1279,24 @@ static int vpif_s_priority(struct file *file, void *priv, enum v4l2_priority p) } /** - * vpif_enum_dv_presets() - ENUM_DV_PRESETS handler + * vpif_enum_dv_timings() - ENUM_DV_TIMINGS handler * @file: file ptr * @priv: file handle - * @preset: input preset + * @timings: input timings */ -static int vpif_enum_dv_presets(struct file *file, void *priv, - struct v4l2_dv_enum_preset *preset) +static int +vpif_enum_dv_timings(struct file *file, void *priv, + struct v4l2_enum_dv_timings *timings) { struct vpif_fh *fh = priv; struct channel_obj *ch = fh->channel; struct video_obj *vid_ch = &ch->video; return v4l2_subdev_call(vpif_obj.sd[vid_ch->output_id], - video, enum_dv_presets, preset); + video, enum_dv_timings, timings); } /** - * vpif_s_dv_presets() - S_DV_PRESETS handler - * @file: file ptr - * @priv: file handle - * @preset: input preset - */ -static int vpif_s_dv_preset(struct file *file, void *priv, - struct v4l2_dv_preset *preset) -{ - struct vpif_fh *fh = priv; - struct channel_obj *ch = fh->channel; - struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; - struct video_obj *vid_ch = &ch->video; - int ret = 0; - - if (common->started) { - vpif_dbg(1, debug, "streaming in progress\n"); - return -EBUSY; - } - - ret = v4l2_prio_check(&ch->prio, fh->prio); - if (ret != 0) - return ret; - - fh->initialized = 1; - - /* Call encoder subdevice function to set the standard */ - if (mutex_lock_interruptible(&common->lock)) - return -ERESTARTSYS; - - ch->video.dv_preset = preset->preset; - ch->video.stdid = V4L2_STD_UNKNOWN; - memset(&ch->video.bt_timings, 0, sizeof(ch->video.bt_timings)); - - /* Get the information about the standard */ - if (vpif_update_resolution(ch)) { - ret = -EINVAL; - } else { - /* Configure the default format information */ - vpif_config_format(ch); - - ret = v4l2_subdev_call(vpif_obj.sd[vid_ch->output_id], - video, s_dv_preset, preset); - } - - mutex_unlock(&common->lock); - - return ret; -} -/** - * vpif_g_dv_presets() - G_DV_PRESETS handler - * @file: file ptr - * @priv: file handle - * @preset: input preset - */ -static int vpif_g_dv_preset(struct file *file, void *priv, - struct v4l2_dv_preset *preset) -{ - struct vpif_fh *fh = priv; - struct channel_obj *ch = fh->channel; - - preset->preset = ch->video.dv_preset; - - return 0; -} -/** * vpif_s_dv_timings() - S_DV_TIMINGS handler * @file: file ptr * @priv: file handle @@ -1366,7 +1310,7 @@ static int vpif_s_dv_timings(struct file *file, void *priv, struct vpif_params *vpifparams = &ch->vpifparams; struct vpif_channel_config_params *std_info = &vpifparams->std_info; struct video_obj *vid_ch = &ch->video; - struct v4l2_bt_timings *bt = &vid_ch->bt_timings; + struct v4l2_bt_timings *bt = &vid_ch->dv_timings.bt; int ret; if (timings->type != V4L2_DV_BT_656_1120) { @@ -1402,7 +1346,7 @@ static int vpif_s_dv_timings(struct file *file, void *priv, return -EINVAL; } - *bt = timings->bt; + vid_ch->dv_timings = *timings; /* Configure video port timings */ @@ -1446,10 +1390,7 @@ static int vpif_s_dv_timings(struct file *file, void *priv, std_info->vbi_supported = 0; std_info->hd_sd = 1; std_info->stdid = 0; - std_info->dv_preset = V4L2_DV_INVALID; - vid_ch->stdid = 0; - vid_ch->dv_preset = V4L2_DV_INVALID; return 0; } @@ -1466,9 +1407,8 @@ static int vpif_g_dv_timings(struct file *file, void *priv, struct vpif_fh *fh = priv; struct channel_obj *ch = fh->channel; struct video_obj *vid_ch = &ch->video; - struct v4l2_bt_timings *bt = &vid_ch->bt_timings; - timings->bt = *bt; + *timings = vid_ch->dv_timings; return 0; } @@ -1572,9 +1512,7 @@ static const struct v4l2_ioctl_ops vpif_ioctl_ops = { .vidioc_s_output = vpif_s_output, .vidioc_g_output = vpif_g_output, .vidioc_cropcap = vpif_cropcap, - .vidioc_enum_dv_presets = vpif_enum_dv_presets, - .vidioc_s_dv_preset = vpif_s_dv_preset, - .vidioc_g_dv_preset = vpif_g_dv_preset, + .vidioc_enum_dv_timings = vpif_enum_dv_timings, .vidioc_s_dv_timings = vpif_s_dv_timings, .vidioc_g_dv_timings = vpif_g_dv_timings, .vidioc_g_chip_ident = vpif_g_chip_ident, @@ -1729,6 +1667,7 @@ static __init int vpif_probe(struct platform_device *pdev) *vfd = vpif_video_template; vfd->v4l2_dev = &vpif_obj.v4l2_dev; vfd->release = video_device_release; + vfd->vfl_dir = VFL_DIR_TX; snprintf(vfd->name, sizeof(vfd->name), "VPIF_Display_DRIVER_V%s", VPIF_DISPLAY_VERSION); @@ -1789,10 +1728,6 @@ static __init int vpif_probe(struct platform_device *pdev) v4l2_prio_init(&ch->prio); ch->common[VPIF_VIDEO_INDEX].fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; - /* Locking in file operations other than ioctl should be done - by the driver, not the V4L2 core. - This driver needs auditing so that this flag can be removed. */ - set_bit(V4L2_FL_LOCK_ALL_FOPS, &ch->video_dev->flags); ch->video_dev->lock = &common->lock; /* register video device */ diff --git a/drivers/media/video/davinci/vpif_display.h b/drivers/media/platform/davinci/vpif_display.h index 8967ffb44058..f628ebcf3674 100644 --- a/drivers/media/video/davinci/vpif_display.h +++ b/drivers/media/platform/davinci/vpif_display.h @@ -20,7 +20,6 @@ #include <linux/videodev2.h> #include <media/v4l2-common.h> #include <media/v4l2-device.h> -#include <media/videobuf-core.h> #include <media/videobuf2-dma-contig.h> #include <media/davinci/vpif_types.h> @@ -62,8 +61,7 @@ struct video_obj { * most recent displayed frame only */ v4l2_std_id stdid; /* Currently selected or default * standard */ - u32 dv_preset; - struct v4l2_bt_timings bt_timings; + struct v4l2_dv_timings dv_timings; u32 output_id; /* Current output id */ }; diff --git a/drivers/media/video/davinci/vpss.c b/drivers/media/platform/davinci/vpss.c index 3e5cf27ec2b2..146e4b01ac17 100644 --- a/drivers/media/video/davinci/vpss.c +++ b/drivers/media/platform/davinci/vpss.c @@ -357,7 +357,7 @@ void dm365_vpss_set_pg_frame_size(struct vpss_pg_frame_size frame_size) } EXPORT_SYMBOL(dm365_vpss_set_pg_frame_size); -static int __init vpss_probe(struct platform_device *pdev) +static int __devinit vpss_probe(struct platform_device *pdev) { struct resource *r1, *r2; char *platform_name; diff --git a/drivers/media/platform/exynos-gsc/Makefile b/drivers/media/platform/exynos-gsc/Makefile new file mode 100644 index 000000000000..6d1411c6d49f --- /dev/null +++ b/drivers/media/platform/exynos-gsc/Makefile @@ -0,0 +1,3 @@ +exynos-gsc-objs := gsc-core.o gsc-m2m.o gsc-regs.o + +obj-$(CONFIG_VIDEO_SAMSUNG_EXYNOS_GSC) += exynos-gsc.o diff --git a/drivers/media/platform/exynos-gsc/gsc-core.c b/drivers/media/platform/exynos-gsc/gsc-core.c new file mode 100644 index 000000000000..bfec9e65aefb --- /dev/null +++ b/drivers/media/platform/exynos-gsc/gsc-core.c @@ -0,0 +1,1252 @@ +/* + * Copyright (c) 2011 - 2012 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * Samsung EXYNOS5 SoC series G-Scaler driver + * + * 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 <linux/module.h> +#include <linux/kernel.h> +#include <linux/types.h> +#include <linux/errno.h> +#include <linux/bug.h> +#include <linux/interrupt.h> +#include <linux/workqueue.h> +#include <linux/device.h> +#include <linux/platform_device.h> +#include <linux/list.h> +#include <linux/io.h> +#include <linux/slab.h> +#include <linux/clk.h> +#include <linux/of.h> +#include <media/v4l2-ioctl.h> + +#include "gsc-core.h" + +#define GSC_CLOCK_GATE_NAME "gscl" + +static const struct gsc_fmt gsc_formats[] = { + { + .name = "RGB565", + .pixelformat = V4L2_PIX_FMT_RGB565X, + .depth = { 16 }, + .color = GSC_RGB, + .num_planes = 1, + .num_comp = 1, + }, { + .name = "XRGB-8-8-8-8, 32 bpp", + .pixelformat = V4L2_PIX_FMT_RGB32, + .depth = { 32 }, + .color = GSC_RGB, + .num_planes = 1, + .num_comp = 1, + }, { + .name = "YUV 4:2:2 packed, YCbYCr", + .pixelformat = V4L2_PIX_FMT_YUYV, + .depth = { 16 }, + .color = GSC_YUV422, + .yorder = GSC_LSB_Y, + .corder = GSC_CBCR, + .num_planes = 1, + .num_comp = 1, + .mbus_code = V4L2_MBUS_FMT_YUYV8_2X8, + }, { + .name = "YUV 4:2:2 packed, CbYCrY", + .pixelformat = V4L2_PIX_FMT_UYVY, + .depth = { 16 }, + .color = GSC_YUV422, + .yorder = GSC_LSB_C, + .corder = GSC_CBCR, + .num_planes = 1, + .num_comp = 1, + .mbus_code = V4L2_MBUS_FMT_UYVY8_2X8, + }, { + .name = "YUV 4:2:2 packed, CrYCbY", + .pixelformat = V4L2_PIX_FMT_VYUY, + .depth = { 16 }, + .color = GSC_YUV422, + .yorder = GSC_LSB_C, + .corder = GSC_CRCB, + .num_planes = 1, + .num_comp = 1, + .mbus_code = V4L2_MBUS_FMT_VYUY8_2X8, + }, { + .name = "YUV 4:2:2 packed, YCrYCb", + .pixelformat = V4L2_PIX_FMT_YVYU, + .depth = { 16 }, + .color = GSC_YUV422, + .yorder = GSC_LSB_Y, + .corder = GSC_CRCB, + .num_planes = 1, + .num_comp = 1, + .mbus_code = V4L2_MBUS_FMT_YVYU8_2X8, + }, { + .name = "YUV 4:4:4 planar, YCbYCr", + .pixelformat = V4L2_PIX_FMT_YUV32, + .depth = { 32 }, + .color = GSC_YUV444, + .yorder = GSC_LSB_Y, + .corder = GSC_CBCR, + .num_planes = 1, + .num_comp = 1, + }, { + .name = "YUV 4:2:2 planar, Y/Cb/Cr", + .pixelformat = V4L2_PIX_FMT_YUV422P, + .depth = { 16 }, + .color = GSC_YUV422, + .yorder = GSC_LSB_Y, + .corder = GSC_CBCR, + .num_planes = 1, + .num_comp = 3, + }, { + .name = "YUV 4:2:2 planar, Y/CbCr", + .pixelformat = V4L2_PIX_FMT_NV16, + .depth = { 16 }, + .color = GSC_YUV422, + .yorder = GSC_LSB_Y, + .corder = GSC_CBCR, + .num_planes = 1, + .num_comp = 2, + }, { + .name = "YUV 4:2:2 planar, Y/CrCb", + .pixelformat = V4L2_PIX_FMT_NV61, + .depth = { 16 }, + .color = GSC_YUV422, + .yorder = GSC_LSB_Y, + .corder = GSC_CRCB, + .num_planes = 1, + .num_comp = 2, + }, { + .name = "YUV 4:2:0 planar, YCbCr", + .pixelformat = V4L2_PIX_FMT_YUV420, + .depth = { 12 }, + .color = GSC_YUV420, + .yorder = GSC_LSB_Y, + .corder = GSC_CBCR, + .num_planes = 1, + .num_comp = 3, + }, { + .name = "YUV 4:2:0 planar, YCrCb", + .pixelformat = V4L2_PIX_FMT_YVU420, + .depth = { 12 }, + .color = GSC_YUV420, + .yorder = GSC_LSB_Y, + .corder = GSC_CRCB, + .num_planes = 1, + .num_comp = 3, + + }, { + .name = "YUV 4:2:0 planar, Y/CbCr", + .pixelformat = V4L2_PIX_FMT_NV12, + .depth = { 12 }, + .color = GSC_YUV420, + .yorder = GSC_LSB_Y, + .corder = GSC_CBCR, + .num_planes = 1, + .num_comp = 2, + }, { + .name = "YUV 4:2:0 planar, Y/CrCb", + .pixelformat = V4L2_PIX_FMT_NV21, + .depth = { 12 }, + .color = GSC_YUV420, + .yorder = GSC_LSB_Y, + .corder = GSC_CRCB, + .num_planes = 1, + .num_comp = 2, + }, { + .name = "YUV 4:2:0 non-contig. 2p, Y/CbCr", + .pixelformat = V4L2_PIX_FMT_NV12M, + .depth = { 8, 4 }, + .color = GSC_YUV420, + .yorder = GSC_LSB_Y, + .corder = GSC_CBCR, + .num_planes = 2, + .num_comp = 2, + }, { + .name = "YUV 4:2:0 non-contig. 3p, Y/Cb/Cr", + .pixelformat = V4L2_PIX_FMT_YUV420M, + .depth = { 8, 2, 2 }, + .color = GSC_YUV420, + .yorder = GSC_LSB_Y, + .corder = GSC_CBCR, + .num_planes = 3, + .num_comp = 3, + }, { + .name = "YUV 4:2:0 non-contig. 3p, Y/Cr/Cb", + .pixelformat = V4L2_PIX_FMT_YVU420M, + .depth = { 8, 2, 2 }, + .color = GSC_YUV420, + .yorder = GSC_LSB_Y, + .corder = GSC_CRCB, + .num_planes = 3, + .num_comp = 3, + } +}; + +const struct gsc_fmt *get_format(int index) +{ + if (index >= ARRAY_SIZE(gsc_formats)) + return NULL; + + return (struct gsc_fmt *)&gsc_formats[index]; +} + +const struct gsc_fmt *find_fmt(u32 *pixelformat, u32 *mbus_code, u32 index) +{ + const struct gsc_fmt *fmt, *def_fmt = NULL; + unsigned int i; + + if (index >= ARRAY_SIZE(gsc_formats)) + return NULL; + + for (i = 0; i < ARRAY_SIZE(gsc_formats); ++i) { + fmt = get_format(i); + if (pixelformat && fmt->pixelformat == *pixelformat) + return fmt; + if (mbus_code && fmt->mbus_code == *mbus_code) + return fmt; + if (index == i) + def_fmt = fmt; + } + return def_fmt; + +} + +void gsc_set_frame_size(struct gsc_frame *frame, int width, int height) +{ + frame->f_width = width; + frame->f_height = height; + frame->crop.width = width; + frame->crop.height = height; + frame->crop.left = 0; + frame->crop.top = 0; +} + +int gsc_cal_prescaler_ratio(struct gsc_variant *var, u32 src, u32 dst, + u32 *ratio) +{ + if ((dst > src) || (dst >= src / var->poly_sc_down_max)) { + *ratio = 1; + return 0; + } + + if ((src / var->poly_sc_down_max / var->pre_sc_down_max) > dst) { + pr_err("Exceeded maximum downscaling ratio (1/16))"); + return -EINVAL; + } + + *ratio = (dst > (src / 8)) ? 2 : 4; + + return 0; +} + +void gsc_get_prescaler_shfactor(u32 hratio, u32 vratio, u32 *sh) +{ + if (hratio == 4 && vratio == 4) + *sh = 4; + else if ((hratio == 4 && vratio == 2) || + (hratio == 2 && vratio == 4)) + *sh = 3; + else if ((hratio == 4 && vratio == 1) || + (hratio == 1 && vratio == 4) || + (hratio == 2 && vratio == 2)) + *sh = 2; + else if (hratio == 1 && vratio == 1) + *sh = 0; + else + *sh = 1; +} + +void gsc_check_src_scale_info(struct gsc_variant *var, + struct gsc_frame *s_frame, u32 *wratio, + u32 tx, u32 ty, u32 *hratio) +{ + int remainder = 0, walign, halign; + + if (is_yuv420(s_frame->fmt->color)) { + walign = GSC_SC_ALIGN_4; + halign = GSC_SC_ALIGN_4; + } else if (is_yuv422(s_frame->fmt->color)) { + walign = GSC_SC_ALIGN_4; + halign = GSC_SC_ALIGN_2; + } else { + walign = GSC_SC_ALIGN_2; + halign = GSC_SC_ALIGN_2; + } + + remainder = s_frame->crop.width % (*wratio * walign); + if (remainder) { + s_frame->crop.width -= remainder; + gsc_cal_prescaler_ratio(var, s_frame->crop.width, tx, wratio); + pr_info("cropped src width size is recalculated from %d to %d", + s_frame->crop.width + remainder, s_frame->crop.width); + } + + remainder = s_frame->crop.height % (*hratio * halign); + if (remainder) { + s_frame->crop.height -= remainder; + gsc_cal_prescaler_ratio(var, s_frame->crop.height, ty, hratio); + pr_info("cropped src height size is recalculated from %d to %d", + s_frame->crop.height + remainder, s_frame->crop.height); + } +} + +int gsc_enum_fmt_mplane(struct v4l2_fmtdesc *f) +{ + const struct gsc_fmt *fmt; + + fmt = find_fmt(NULL, NULL, f->index); + if (!fmt) + return -EINVAL; + + strlcpy(f->description, fmt->name, sizeof(f->description)); + f->pixelformat = fmt->pixelformat; + + return 0; +} + +static u32 get_plane_info(struct gsc_frame *frm, u32 addr, u32 *index) +{ + if (frm->addr.y == addr) { + *index = 0; + return frm->addr.y; + } else if (frm->addr.cb == addr) { + *index = 1; + return frm->addr.cb; + } else if (frm->addr.cr == addr) { + *index = 2; + return frm->addr.cr; + } else { + pr_err("Plane address is wrong"); + return -EINVAL; + } +} + +void gsc_set_prefbuf(struct gsc_dev *gsc, struct gsc_frame *frm) +{ + u32 f_chk_addr, f_chk_len, s_chk_addr, s_chk_len; + f_chk_addr = f_chk_len = s_chk_addr = s_chk_len = 0; + + f_chk_addr = frm->addr.y; + f_chk_len = frm->payload[0]; + if (frm->fmt->num_planes == 2) { + s_chk_addr = frm->addr.cb; + s_chk_len = frm->payload[1]; + } else if (frm->fmt->num_planes == 3) { + u32 low_addr, low_plane, mid_addr, mid_plane; + u32 high_addr, high_plane; + u32 t_min, t_max; + + t_min = min3(frm->addr.y, frm->addr.cb, frm->addr.cr); + low_addr = get_plane_info(frm, t_min, &low_plane); + t_max = max3(frm->addr.y, frm->addr.cb, frm->addr.cr); + high_addr = get_plane_info(frm, t_max, &high_plane); + + mid_plane = 3 - (low_plane + high_plane); + if (mid_plane == 0) + mid_addr = frm->addr.y; + else if (mid_plane == 1) + mid_addr = frm->addr.cb; + else if (mid_plane == 2) + mid_addr = frm->addr.cr; + else + return; + + f_chk_addr = low_addr; + if (mid_addr + frm->payload[mid_plane] - low_addr > + high_addr + frm->payload[high_plane] - mid_addr) { + f_chk_len = frm->payload[low_plane]; + s_chk_addr = mid_addr; + s_chk_len = high_addr + + frm->payload[high_plane] - mid_addr; + } else { + f_chk_len = mid_addr + + frm->payload[mid_plane] - low_addr; + s_chk_addr = high_addr; + s_chk_len = frm->payload[high_plane]; + } + } + pr_debug("f_addr = 0x%08x, f_len = %d, s_addr = 0x%08x, s_len = %d\n", + f_chk_addr, f_chk_len, s_chk_addr, s_chk_len); +} + +int gsc_try_fmt_mplane(struct gsc_ctx *ctx, struct v4l2_format *f) +{ + struct gsc_dev *gsc = ctx->gsc_dev; + struct gsc_variant *variant = gsc->variant; + struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp; + const struct gsc_fmt *fmt; + u32 max_w, max_h, mod_x, mod_y; + u32 min_w, min_h, tmp_w, tmp_h; + int i; + + pr_debug("user put w: %d, h: %d", pix_mp->width, pix_mp->height); + + fmt = find_fmt(&pix_mp->pixelformat, NULL, 0); + if (!fmt) { + pr_err("pixelformat format (0x%X) invalid\n", + pix_mp->pixelformat); + return -EINVAL; + } + + if (pix_mp->field == V4L2_FIELD_ANY) + pix_mp->field = V4L2_FIELD_NONE; + else if (pix_mp->field != V4L2_FIELD_NONE) { + pr_err("Not supported field order(%d)\n", pix_mp->field); + return -EINVAL; + } + + max_w = variant->pix_max->target_rot_dis_w; + max_h = variant->pix_max->target_rot_dis_h; + + mod_x = ffs(variant->pix_align->org_w) - 1; + if (is_yuv420(fmt->color)) + mod_y = ffs(variant->pix_align->org_h) - 1; + else + mod_y = ffs(variant->pix_align->org_h) - 2; + + if (V4L2_TYPE_IS_OUTPUT(f->type)) { + min_w = variant->pix_min->org_w; + min_h = variant->pix_min->org_h; + } else { + min_w = variant->pix_min->target_rot_dis_w; + min_h = variant->pix_min->target_rot_dis_h; + } + + pr_debug("mod_x: %d, mod_y: %d, max_w: %d, max_h = %d", + mod_x, mod_y, max_w, max_h); + + /* To check if image size is modified to adjust parameter against + hardware abilities */ + tmp_w = pix_mp->width; + tmp_h = pix_mp->height; + + v4l_bound_align_image(&pix_mp->width, min_w, max_w, mod_x, + &pix_mp->height, min_h, max_h, mod_y, 0); + if (tmp_w != pix_mp->width || tmp_h != pix_mp->height) + pr_info("Image size has been modified from %dx%d to %dx%d", + tmp_w, tmp_h, pix_mp->width, pix_mp->height); + + pix_mp->num_planes = fmt->num_planes; + + if (pix_mp->width >= 1280) /* HD */ + pix_mp->colorspace = V4L2_COLORSPACE_REC709; + else /* SD */ + pix_mp->colorspace = V4L2_COLORSPACE_SMPTE170M; + + + for (i = 0; i < pix_mp->num_planes; ++i) { + int bpl = (pix_mp->width * fmt->depth[i]) >> 3; + pix_mp->plane_fmt[i].bytesperline = bpl; + pix_mp->plane_fmt[i].sizeimage = bpl * pix_mp->height; + + pr_debug("[%d]: bpl: %d, sizeimage: %d", + i, bpl, pix_mp->plane_fmt[i].sizeimage); + } + + return 0; +} + +int gsc_g_fmt_mplane(struct gsc_ctx *ctx, struct v4l2_format *f) +{ + struct gsc_frame *frame; + struct v4l2_pix_format_mplane *pix_mp; + int i; + + frame = ctx_get_frame(ctx, f->type); + if (IS_ERR(frame)) + return PTR_ERR(frame); + + pix_mp = &f->fmt.pix_mp; + + pix_mp->width = frame->f_width; + pix_mp->height = frame->f_height; + pix_mp->field = V4L2_FIELD_NONE; + pix_mp->pixelformat = frame->fmt->pixelformat; + pix_mp->colorspace = V4L2_COLORSPACE_REC709; + pix_mp->num_planes = frame->fmt->num_planes; + + for (i = 0; i < pix_mp->num_planes; ++i) { + pix_mp->plane_fmt[i].bytesperline = (frame->f_width * + frame->fmt->depth[i]) / 8; + pix_mp->plane_fmt[i].sizeimage = + pix_mp->plane_fmt[i].bytesperline * frame->f_height; + } + + return 0; +} + +void gsc_check_crop_change(u32 tmp_w, u32 tmp_h, u32 *w, u32 *h) +{ + if (tmp_w != *w || tmp_h != *h) { + pr_info("Cropped size has been modified from %dx%d to %dx%d", + *w, *h, tmp_w, tmp_h); + *w = tmp_w; + *h = tmp_h; + } +} + +int gsc_g_crop(struct gsc_ctx *ctx, struct v4l2_crop *cr) +{ + struct gsc_frame *frame; + + frame = ctx_get_frame(ctx, cr->type); + if (IS_ERR(frame)) + return PTR_ERR(frame); + + cr->c = frame->crop; + + return 0; +} + +int gsc_try_crop(struct gsc_ctx *ctx, struct v4l2_crop *cr) +{ + struct gsc_frame *f; + struct gsc_dev *gsc = ctx->gsc_dev; + struct gsc_variant *variant = gsc->variant; + u32 mod_x = 0, mod_y = 0, tmp_w, tmp_h; + u32 min_w, min_h, max_w, max_h; + + if (cr->c.top < 0 || cr->c.left < 0) { + pr_err("doesn't support negative values for top & left\n"); + return -EINVAL; + } + pr_debug("user put w: %d, h: %d", cr->c.width, cr->c.height); + + if (cr->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) + f = &ctx->d_frame; + else if (cr->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) + f = &ctx->s_frame; + else + return -EINVAL; + + max_w = f->f_width; + max_h = f->f_height; + tmp_w = cr->c.width; + tmp_h = cr->c.height; + + if (V4L2_TYPE_IS_OUTPUT(cr->type)) { + if ((is_yuv422(f->fmt->color) && f->fmt->num_comp == 1) || + is_rgb(f->fmt->color)) + min_w = 32; + else + min_w = 64; + if ((is_yuv422(f->fmt->color) && f->fmt->num_comp == 3) || + is_yuv420(f->fmt->color)) + min_h = 32; + else + min_h = 16; + } else { + if (is_yuv420(f->fmt->color) || is_yuv422(f->fmt->color)) + mod_x = ffs(variant->pix_align->target_w) - 1; + if (is_yuv420(f->fmt->color)) + mod_y = ffs(variant->pix_align->target_h) - 1; + if (ctx->gsc_ctrls.rotate->val == 90 || + ctx->gsc_ctrls.rotate->val == 270) { + max_w = f->f_height; + max_h = f->f_width; + min_w = variant->pix_min->target_rot_en_w; + min_h = variant->pix_min->target_rot_en_h; + tmp_w = cr->c.height; + tmp_h = cr->c.width; + } else { + min_w = variant->pix_min->target_rot_dis_w; + min_h = variant->pix_min->target_rot_dis_h; + } + } + pr_debug("mod_x: %d, mod_y: %d, min_w: %d, min_h = %d", + mod_x, mod_y, min_w, min_h); + pr_debug("tmp_w : %d, tmp_h : %d", tmp_w, tmp_h); + + v4l_bound_align_image(&tmp_w, min_w, max_w, mod_x, + &tmp_h, min_h, max_h, mod_y, 0); + + if (!V4L2_TYPE_IS_OUTPUT(cr->type) && + (ctx->gsc_ctrls.rotate->val == 90 || + ctx->gsc_ctrls.rotate->val == 270)) + gsc_check_crop_change(tmp_h, tmp_w, + &cr->c.width, &cr->c.height); + else + gsc_check_crop_change(tmp_w, tmp_h, + &cr->c.width, &cr->c.height); + + + /* adjust left/top if cropping rectangle is out of bounds */ + /* Need to add code to algin left value with 2's multiple */ + if (cr->c.left + tmp_w > max_w) + cr->c.left = max_w - tmp_w; + if (cr->c.top + tmp_h > max_h) + cr->c.top = max_h - tmp_h; + + if ((is_yuv420(f->fmt->color) || is_yuv422(f->fmt->color)) && + cr->c.left & 1) + cr->c.left -= 1; + + pr_debug("Aligned l:%d, t:%d, w:%d, h:%d, f_w: %d, f_h: %d", + cr->c.left, cr->c.top, cr->c.width, cr->c.height, max_w, max_h); + + return 0; +} + +int gsc_check_scaler_ratio(struct gsc_variant *var, int sw, int sh, int dw, + int dh, int rot, int out_path) +{ + int tmp_w, tmp_h, sc_down_max; + + if (out_path == GSC_DMA) + sc_down_max = var->sc_down_max; + else + sc_down_max = var->local_sc_down; + + if (rot == 90 || rot == 270) { + tmp_w = dh; + tmp_h = dw; + } else { + tmp_w = dw; + tmp_h = dh; + } + + if ((sw / tmp_w) > sc_down_max || + (sh / tmp_h) > sc_down_max || + (tmp_w / sw) > var->sc_up_max || + (tmp_h / sh) > var->sc_up_max) + return -EINVAL; + + return 0; +} + +int gsc_set_scaler_info(struct gsc_ctx *ctx) +{ + struct gsc_scaler *sc = &ctx->scaler; + struct gsc_frame *s_frame = &ctx->s_frame; + struct gsc_frame *d_frame = &ctx->d_frame; + struct gsc_variant *variant = ctx->gsc_dev->variant; + struct device *dev = &ctx->gsc_dev->pdev->dev; + int tx, ty; + int ret; + + ret = gsc_check_scaler_ratio(variant, s_frame->crop.width, + s_frame->crop.height, d_frame->crop.width, d_frame->crop.height, + ctx->gsc_ctrls.rotate->val, ctx->out_path); + if (ret) { + pr_err("out of scaler range"); + return ret; + } + + if (ctx->gsc_ctrls.rotate->val == 90 || + ctx->gsc_ctrls.rotate->val == 270) { + ty = d_frame->crop.width; + tx = d_frame->crop.height; + } else { + tx = d_frame->crop.width; + ty = d_frame->crop.height; + } + + if (tx <= 0 || ty <= 0) { + dev_err(dev, "Invalid target size: %dx%d", tx, ty); + return -EINVAL; + } + + ret = gsc_cal_prescaler_ratio(variant, s_frame->crop.width, + tx, &sc->pre_hratio); + if (ret) { + pr_err("Horizontal scale ratio is out of range"); + return ret; + } + + ret = gsc_cal_prescaler_ratio(variant, s_frame->crop.height, + ty, &sc->pre_vratio); + if (ret) { + pr_err("Vertical scale ratio is out of range"); + return ret; + } + + gsc_check_src_scale_info(variant, s_frame, &sc->pre_hratio, + tx, ty, &sc->pre_vratio); + + gsc_get_prescaler_shfactor(sc->pre_hratio, sc->pre_vratio, + &sc->pre_shfactor); + + sc->main_hratio = (s_frame->crop.width << 16) / tx; + sc->main_vratio = (s_frame->crop.height << 16) / ty; + + pr_debug("scaler input/output size : sx = %d, sy = %d, tx = %d, ty = %d", + s_frame->crop.width, s_frame->crop.height, tx, ty); + pr_debug("scaler ratio info : pre_shfactor : %d, pre_h : %d", + sc->pre_shfactor, sc->pre_hratio); + pr_debug("pre_v :%d, main_h : %d, main_v : %d", + sc->pre_vratio, sc->main_hratio, sc->main_vratio); + + return 0; +} + +static int __gsc_s_ctrl(struct gsc_ctx *ctx, struct v4l2_ctrl *ctrl) +{ + struct gsc_dev *gsc = ctx->gsc_dev; + struct gsc_variant *variant = gsc->variant; + unsigned int flags = GSC_DST_FMT | GSC_SRC_FMT; + int ret = 0; + + if (ctrl->flags & V4L2_CTRL_FLAG_INACTIVE) + return 0; + + switch (ctrl->id) { + case V4L2_CID_HFLIP: + ctx->hflip = ctrl->val; + break; + + case V4L2_CID_VFLIP: + ctx->vflip = ctrl->val; + break; + + case V4L2_CID_ROTATE: + if ((ctx->state & flags) == flags) { + ret = gsc_check_scaler_ratio(variant, + ctx->s_frame.crop.width, + ctx->s_frame.crop.height, + ctx->d_frame.crop.width, + ctx->d_frame.crop.height, + ctx->gsc_ctrls.rotate->val, + ctx->out_path); + + if (ret) + return -EINVAL; + } + + ctx->rotation = ctrl->val; + break; + + case V4L2_CID_ALPHA_COMPONENT: + ctx->d_frame.alpha = ctrl->val; + break; + } + + ctx->state |= GSC_PARAMS; + return 0; +} + +static int gsc_s_ctrl(struct v4l2_ctrl *ctrl) +{ + struct gsc_ctx *ctx = ctrl_to_ctx(ctrl); + unsigned long flags; + int ret; + + spin_lock_irqsave(&ctx->gsc_dev->slock, flags); + ret = __gsc_s_ctrl(ctx, ctrl); + spin_unlock_irqrestore(&ctx->gsc_dev->slock, flags); + + return ret; +} + +static const struct v4l2_ctrl_ops gsc_ctrl_ops = { + .s_ctrl = gsc_s_ctrl, +}; + +int gsc_ctrls_create(struct gsc_ctx *ctx) +{ + if (ctx->ctrls_rdy) { + pr_err("Control handler of this context was created already"); + return 0; + } + + v4l2_ctrl_handler_init(&ctx->ctrl_handler, GSC_MAX_CTRL_NUM); + + ctx->gsc_ctrls.rotate = v4l2_ctrl_new_std(&ctx->ctrl_handler, + &gsc_ctrl_ops, V4L2_CID_ROTATE, 0, 270, 90, 0); + ctx->gsc_ctrls.hflip = v4l2_ctrl_new_std(&ctx->ctrl_handler, + &gsc_ctrl_ops, V4L2_CID_HFLIP, 0, 1, 1, 0); + ctx->gsc_ctrls.vflip = v4l2_ctrl_new_std(&ctx->ctrl_handler, + &gsc_ctrl_ops, V4L2_CID_VFLIP, 0, 1, 1, 0); + ctx->gsc_ctrls.global_alpha = v4l2_ctrl_new_std(&ctx->ctrl_handler, + &gsc_ctrl_ops, V4L2_CID_ALPHA_COMPONENT, 0, 255, 1, 0); + + ctx->ctrls_rdy = ctx->ctrl_handler.error == 0; + + if (ctx->ctrl_handler.error) { + int err = ctx->ctrl_handler.error; + v4l2_ctrl_handler_free(&ctx->ctrl_handler); + pr_err("Failed to create G-Scaler control handlers"); + return err; + } + + return 0; +} + +void gsc_ctrls_delete(struct gsc_ctx *ctx) +{ + if (ctx->ctrls_rdy) { + v4l2_ctrl_handler_free(&ctx->ctrl_handler); + ctx->ctrls_rdy = false; + } +} + +/* The color format (num_comp, num_planes) must be already configured. */ +int gsc_prepare_addr(struct gsc_ctx *ctx, struct vb2_buffer *vb, + struct gsc_frame *frame, struct gsc_addr *addr) +{ + int ret = 0; + u32 pix_size; + + if ((vb == NULL) || (frame == NULL)) + return -EINVAL; + + pix_size = frame->f_width * frame->f_height; + + pr_debug("num_planes= %d, num_comp= %d, pix_size= %d", + frame->fmt->num_planes, frame->fmt->num_comp, pix_size); + + addr->y = vb2_dma_contig_plane_dma_addr(vb, 0); + + if (frame->fmt->num_planes == 1) { + switch (frame->fmt->num_comp) { + case 1: + addr->cb = 0; + addr->cr = 0; + break; + case 2: + /* decompose Y into Y/Cb */ + addr->cb = (dma_addr_t)(addr->y + pix_size); + addr->cr = 0; + break; + case 3: + /* decompose Y into Y/Cb/Cr */ + addr->cb = (dma_addr_t)(addr->y + pix_size); + if (GSC_YUV420 == frame->fmt->color) + addr->cr = (dma_addr_t)(addr->cb + + (pix_size >> 2)); + else /* 422 */ + addr->cr = (dma_addr_t)(addr->cb + + (pix_size >> 1)); + break; + default: + pr_err("Invalid the number of color planes"); + return -EINVAL; + } + } else { + if (frame->fmt->num_planes >= 2) + addr->cb = vb2_dma_contig_plane_dma_addr(vb, 1); + + if (frame->fmt->num_planes == 3) + addr->cr = vb2_dma_contig_plane_dma_addr(vb, 2); + } + + if ((frame->fmt->pixelformat == V4L2_PIX_FMT_VYUY) || + (frame->fmt->pixelformat == V4L2_PIX_FMT_YVYU) || + (frame->fmt->pixelformat == V4L2_PIX_FMT_NV61) || + (frame->fmt->pixelformat == V4L2_PIX_FMT_YVU420) || + (frame->fmt->pixelformat == V4L2_PIX_FMT_NV21) || + (frame->fmt->pixelformat == V4L2_PIX_FMT_YVU420M)) + swap(addr->cb, addr->cr); + + pr_debug("ADDR: y= 0x%X cb= 0x%X cr= 0x%X ret= %d", + addr->y, addr->cb, addr->cr, ret); + + return ret; +} + +static irqreturn_t gsc_irq_handler(int irq, void *priv) +{ + struct gsc_dev *gsc = priv; + struct gsc_ctx *ctx; + int gsc_irq; + + gsc_irq = gsc_hw_get_irq_status(gsc); + gsc_hw_clear_irq(gsc, gsc_irq); + + if (gsc_irq == GSC_IRQ_OVERRUN) { + pr_err("Local path input over-run interrupt has occurred!\n"); + return IRQ_HANDLED; + } + + spin_lock(&gsc->slock); + + if (test_and_clear_bit(ST_M2M_PEND, &gsc->state)) { + + gsc_hw_enable_control(gsc, false); + + if (test_and_clear_bit(ST_M2M_SUSPENDING, &gsc->state)) { + set_bit(ST_M2M_SUSPENDED, &gsc->state); + wake_up(&gsc->irq_queue); + goto isr_unlock; + } + ctx = v4l2_m2m_get_curr_priv(gsc->m2m.m2m_dev); + + if (!ctx || !ctx->m2m_ctx) + goto isr_unlock; + + spin_unlock(&gsc->slock); + gsc_m2m_job_finish(ctx, VB2_BUF_STATE_DONE); + + /* wake_up job_abort, stop_streaming */ + if (ctx->state & GSC_CTX_STOP_REQ) { + ctx->state &= ~GSC_CTX_STOP_REQ; + wake_up(&gsc->irq_queue); + } + return IRQ_HANDLED; + } + +isr_unlock: + spin_unlock(&gsc->slock); + return IRQ_HANDLED; +} + +static struct gsc_pix_max gsc_v_100_max = { + .org_scaler_bypass_w = 8192, + .org_scaler_bypass_h = 8192, + .org_scaler_input_w = 4800, + .org_scaler_input_h = 3344, + .real_rot_dis_w = 4800, + .real_rot_dis_h = 3344, + .real_rot_en_w = 2047, + .real_rot_en_h = 2047, + .target_rot_dis_w = 4800, + .target_rot_dis_h = 3344, + .target_rot_en_w = 2016, + .target_rot_en_h = 2016, +}; + +static struct gsc_pix_min gsc_v_100_min = { + .org_w = 64, + .org_h = 32, + .real_w = 64, + .real_h = 32, + .target_rot_dis_w = 64, + .target_rot_dis_h = 32, + .target_rot_en_w = 32, + .target_rot_en_h = 16, +}; + +static struct gsc_pix_align gsc_v_100_align = { + .org_h = 16, + .org_w = 16, /* yuv420 : 16, others : 8 */ + .offset_h = 2, /* yuv420/422 : 2, others : 1 */ + .real_w = 16, /* yuv420/422 : 4~16, others : 2~8 */ + .real_h = 16, /* yuv420 : 4~16, others : 1 */ + .target_w = 2, /* yuv420/422 : 2, others : 1 */ + .target_h = 2, /* yuv420 : 2, others : 1 */ +}; + +static struct gsc_variant gsc_v_100_variant = { + .pix_max = &gsc_v_100_max, + .pix_min = &gsc_v_100_min, + .pix_align = &gsc_v_100_align, + .in_buf_cnt = 8, + .out_buf_cnt = 16, + .sc_up_max = 8, + .sc_down_max = 16, + .poly_sc_down_max = 4, + .pre_sc_down_max = 4, + .local_sc_down = 2, +}; + +static struct gsc_driverdata gsc_v_100_drvdata = { + .variant = { + [0] = &gsc_v_100_variant, + [1] = &gsc_v_100_variant, + [2] = &gsc_v_100_variant, + [3] = &gsc_v_100_variant, + }, + .num_entities = 4, + .lclk_frequency = 266000000UL, +}; + +static struct platform_device_id gsc_driver_ids[] = { + { + .name = "exynos-gsc", + .driver_data = (unsigned long)&gsc_v_100_drvdata, + }, + {}, +}; +MODULE_DEVICE_TABLE(platform, gsc_driver_ids); + +static const struct of_device_id exynos_gsc_match[] = { + { .compatible = "samsung,exynos5250-gsc", + .data = &gsc_v_100_drvdata, }, + {}, +}; +MODULE_DEVICE_TABLE(of, exynos_gsc_match); + +static void *gsc_get_drv_data(struct platform_device *pdev) +{ + struct gsc_driverdata *driver_data = NULL; + + if (pdev->dev.of_node) { + const struct of_device_id *match; + match = of_match_node(of_match_ptr(exynos_gsc_match), + pdev->dev.of_node); + if (match) + driver_data = match->data; + } else { + driver_data = (struct gsc_driverdata *) + platform_get_device_id(pdev)->driver_data; + } + + return driver_data; +} + +static void gsc_clk_put(struct gsc_dev *gsc) +{ + if (IS_ERR_OR_NULL(gsc->clock)) + return; + + clk_unprepare(gsc->clock); + clk_put(gsc->clock); + gsc->clock = NULL; +} + +static int gsc_clk_get(struct gsc_dev *gsc) +{ + int ret; + + dev_dbg(&gsc->pdev->dev, "gsc_clk_get Called\n"); + + gsc->clock = clk_get(&gsc->pdev->dev, GSC_CLOCK_GATE_NAME); + if (IS_ERR(gsc->clock)) + goto err_print; + + ret = clk_prepare(gsc->clock); + if (ret < 0) { + clk_put(gsc->clock); + gsc->clock = NULL; + goto err; + } + + return 0; + +err: + dev_err(&gsc->pdev->dev, "clock prepare failed for clock: %s\n", + GSC_CLOCK_GATE_NAME); + gsc_clk_put(gsc); +err_print: + dev_err(&gsc->pdev->dev, "failed to get clock~~~: %s\n", + GSC_CLOCK_GATE_NAME); + return -ENXIO; +} + +static int gsc_m2m_suspend(struct gsc_dev *gsc) +{ + unsigned long flags; + int timeout; + + spin_lock_irqsave(&gsc->slock, flags); + if (!gsc_m2m_pending(gsc)) { + spin_unlock_irqrestore(&gsc->slock, flags); + return 0; + } + clear_bit(ST_M2M_SUSPENDED, &gsc->state); + set_bit(ST_M2M_SUSPENDING, &gsc->state); + spin_unlock_irqrestore(&gsc->slock, flags); + + timeout = wait_event_timeout(gsc->irq_queue, + test_bit(ST_M2M_SUSPENDED, &gsc->state), + GSC_SHUTDOWN_TIMEOUT); + + clear_bit(ST_M2M_SUSPENDING, &gsc->state); + return timeout == 0 ? -EAGAIN : 0; +} + +static int gsc_m2m_resume(struct gsc_dev *gsc) +{ + unsigned long flags; + + spin_lock_irqsave(&gsc->slock, flags); + /* Clear for full H/W setup in first run after resume */ + gsc->m2m.ctx = NULL; + spin_unlock_irqrestore(&gsc->slock, flags); + + if (test_and_clear_bit(ST_M2M_SUSPENDED, &gsc->state)) + gsc_m2m_job_finish(gsc->m2m.ctx, + VB2_BUF_STATE_ERROR); + return 0; +} + +static int gsc_probe(struct platform_device *pdev) +{ + struct gsc_dev *gsc; + struct resource *res; + struct gsc_driverdata *drv_data = gsc_get_drv_data(pdev); + struct device *dev = &pdev->dev; + int ret = 0; + + gsc = devm_kzalloc(dev, sizeof(struct gsc_dev), GFP_KERNEL); + if (!gsc) + return -ENOMEM; + + if (dev->of_node) + gsc->id = of_alias_get_id(pdev->dev.of_node, "gsc"); + else + gsc->id = pdev->id; + + if (gsc->id < 0 || gsc->id >= drv_data->num_entities) { + dev_err(dev, "Invalid platform device id: %d\n", gsc->id); + return -EINVAL; + } + + gsc->variant = drv_data->variant[gsc->id]; + gsc->pdev = pdev; + gsc->pdata = dev->platform_data; + + init_waitqueue_head(&gsc->irq_queue); + spin_lock_init(&gsc->slock); + mutex_init(&gsc->lock); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + gsc->regs = devm_request_and_ioremap(dev, res); + if (!gsc->regs) { + dev_err(dev, "failed to map registers\n"); + return -ENOENT; + } + + res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + if (!res) { + dev_err(dev, "failed to get IRQ resource\n"); + return -ENXIO; + } + + ret = gsc_clk_get(gsc); + if (ret) + return ret; + + ret = devm_request_irq(dev, res->start, gsc_irq_handler, + 0, pdev->name, gsc); + if (ret) { + dev_err(dev, "failed to install irq (%d)\n", ret); + goto err_clk; + } + + ret = gsc_register_m2m_device(gsc); + if (ret) + goto err_clk; + + platform_set_drvdata(pdev, gsc); + pm_runtime_enable(dev); + ret = pm_runtime_get_sync(&pdev->dev); + if (ret < 0) + goto err_m2m; + + /* Initialize continious memory allocator */ + gsc->alloc_ctx = vb2_dma_contig_init_ctx(dev); + if (IS_ERR(gsc->alloc_ctx)) { + ret = PTR_ERR(gsc->alloc_ctx); + goto err_pm; + } + + dev_dbg(dev, "gsc-%d registered successfully\n", gsc->id); + + pm_runtime_put(dev); + return 0; +err_pm: + pm_runtime_put(dev); +err_m2m: + gsc_unregister_m2m_device(gsc); +err_clk: + gsc_clk_put(gsc); + return ret; +} + +static int __devexit gsc_remove(struct platform_device *pdev) +{ + struct gsc_dev *gsc = platform_get_drvdata(pdev); + + gsc_unregister_m2m_device(gsc); + + vb2_dma_contig_cleanup_ctx(gsc->alloc_ctx); + pm_runtime_disable(&pdev->dev); + + dev_dbg(&pdev->dev, "%s driver unloaded\n", pdev->name); + return 0; +} + +static int gsc_runtime_resume(struct device *dev) +{ + struct gsc_dev *gsc = dev_get_drvdata(dev); + int ret = 0; + + pr_debug("gsc%d: state: 0x%lx", gsc->id, gsc->state); + + ret = clk_enable(gsc->clock); + if (ret) + return ret; + + gsc_hw_set_sw_reset(gsc); + gsc_wait_reset(gsc); + + return gsc_m2m_resume(gsc); +} + +static int gsc_runtime_suspend(struct device *dev) +{ + struct gsc_dev *gsc = dev_get_drvdata(dev); + int ret = 0; + + ret = gsc_m2m_suspend(gsc); + if (!ret) + clk_disable(gsc->clock); + + pr_debug("gsc%d: state: 0x%lx", gsc->id, gsc->state); + return ret; +} + +static int gsc_resume(struct device *dev) +{ + struct gsc_dev *gsc = dev_get_drvdata(dev); + unsigned long flags; + + pr_debug("gsc%d: state: 0x%lx", gsc->id, gsc->state); + + /* Do not resume if the device was idle before system suspend */ + spin_lock_irqsave(&gsc->slock, flags); + if (!test_and_clear_bit(ST_SUSPEND, &gsc->state) || + !gsc_m2m_active(gsc)) { + spin_unlock_irqrestore(&gsc->slock, flags); + return 0; + } + gsc_hw_set_sw_reset(gsc); + gsc_wait_reset(gsc); + + spin_unlock_irqrestore(&gsc->slock, flags); + + return gsc_m2m_resume(gsc); +} + +static int gsc_suspend(struct device *dev) +{ + struct gsc_dev *gsc = dev_get_drvdata(dev); + + pr_debug("gsc%d: state: 0x%lx", gsc->id, gsc->state); + + if (test_and_set_bit(ST_SUSPEND, &gsc->state)) + return 0; + + return gsc_m2m_suspend(gsc); +} + +static const struct dev_pm_ops gsc_pm_ops = { + .suspend = gsc_suspend, + .resume = gsc_resume, + .runtime_suspend = gsc_runtime_suspend, + .runtime_resume = gsc_runtime_resume, +}; + +static struct platform_driver gsc_driver = { + .probe = gsc_probe, + .remove = __devexit_p(gsc_remove), + .id_table = gsc_driver_ids, + .driver = { + .name = GSC_MODULE_NAME, + .owner = THIS_MODULE, + .pm = &gsc_pm_ops, + .of_match_table = exynos_gsc_match, + } +}; + +module_platform_driver(gsc_driver); + +MODULE_AUTHOR("Hyunwong Kim <khw0178.kim@samsung.com>"); +MODULE_DESCRIPTION("Samsung EXYNOS5 Soc series G-Scaler driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/platform/exynos-gsc/gsc-core.h b/drivers/media/platform/exynos-gsc/gsc-core.h new file mode 100644 index 000000000000..5f157efd24f0 --- /dev/null +++ b/drivers/media/platform/exynos-gsc/gsc-core.h @@ -0,0 +1,527 @@ +/* + * Copyright (c) 2011 - 2012 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * header file for Samsung EXYNOS5 SoC series G-Scaler driver + + * 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 GSC_CORE_H_ +#define GSC_CORE_H_ + +#include <linux/delay.h> +#include <linux/sched.h> +#include <linux/spinlock.h> +#include <linux/types.h> +#include <linux/videodev2.h> +#include <linux/io.h> +#include <linux/pm_runtime.h> +#include <media/videobuf2-core.h> +#include <media/v4l2-ctrls.h> +#include <media/v4l2-device.h> +#include <media/v4l2-mem2mem.h> +#include <media/v4l2-mediabus.h> +#include <media/videobuf2-dma-contig.h> + +#include "gsc-regs.h" + +#define CONFIG_VB2_GSC_DMA_CONTIG 1 +#define GSC_MODULE_NAME "exynos-gsc" + +#define GSC_SHUTDOWN_TIMEOUT ((100*HZ)/1000) +#define GSC_MAX_DEVS 4 +#define GSC_M2M_BUF_NUM 0 +#define GSC_MAX_CTRL_NUM 10 +#define GSC_SC_ALIGN_4 4 +#define GSC_SC_ALIGN_2 2 +#define DEFAULT_CSC_EQ 1 +#define DEFAULT_CSC_RANGE 1 + +#define GSC_PARAMS (1 << 0) +#define GSC_SRC_FMT (1 << 1) +#define GSC_DST_FMT (1 << 2) +#define GSC_CTX_M2M (1 << 3) +#define GSC_CTX_STOP_REQ (1 << 6) + +enum gsc_dev_flags { + /* for global */ + ST_SUSPEND, + + /* for m2m node */ + ST_M2M_OPEN, + ST_M2M_RUN, + ST_M2M_PEND, + ST_M2M_SUSPENDED, + ST_M2M_SUSPENDING, +}; + +enum gsc_irq { + GSC_IRQ_DONE, + GSC_IRQ_OVERRUN +}; + +/** + * enum gsc_datapath - the path of data used for G-Scaler + * @GSC_CAMERA: from camera + * @GSC_DMA: from/to DMA + * @GSC_LOCAL: to local path + * @GSC_WRITEBACK: from FIMD + */ +enum gsc_datapath { + GSC_CAMERA = 0x1, + GSC_DMA, + GSC_MIXER, + GSC_FIMD, + GSC_WRITEBACK, +}; + +enum gsc_color_fmt { + GSC_RGB = 0x1, + GSC_YUV420 = 0x2, + GSC_YUV422 = 0x4, + GSC_YUV444 = 0x8, +}; + +enum gsc_yuv_fmt { + GSC_LSB_Y = 0x10, + GSC_LSB_C, + GSC_CBCR = 0x20, + GSC_CRCB, +}; + +#define fh_to_ctx(__fh) container_of(__fh, struct gsc_ctx, fh) +#define is_rgb(x) (!!((x) & 0x1)) +#define is_yuv420(x) (!!((x) & 0x2)) +#define is_yuv422(x) (!!((x) & 0x4)) + +#define gsc_m2m_active(dev) test_bit(ST_M2M_RUN, &(dev)->state) +#define gsc_m2m_pending(dev) test_bit(ST_M2M_PEND, &(dev)->state) +#define gsc_m2m_opened(dev) test_bit(ST_M2M_OPEN, &(dev)->state) + +#define ctrl_to_ctx(__ctrl) \ + container_of((__ctrl)->handler, struct gsc_ctx, ctrl_handler) +/** + * struct gsc_fmt - the driver's internal color format data + * @mbus_code: Media Bus pixel code, -1 if not applicable + * @name: format description + * @pixelformat: the fourcc code for this format, 0 if not applicable + * @yorder: Y/C order + * @corder: Chrominance order control + * @num_planes: number of physically non-contiguous data planes + * @nr_comp: number of physically contiguous data planes + * @depth: per plane driver's private 'number of bits per pixel' + * @flags: flags indicating which operation mode format applies to + */ +struct gsc_fmt { + enum v4l2_mbus_pixelcode mbus_code; + char *name; + u32 pixelformat; + u32 color; + u32 yorder; + u32 corder; + u16 num_planes; + u16 num_comp; + u8 depth[VIDEO_MAX_PLANES]; + u32 flags; +}; + +/** + * struct gsc_input_buf - the driver's video buffer + * @vb: videobuf2 buffer + * @list : linked list structure for buffer queue + * @idx : index of G-Scaler input buffer + */ +struct gsc_input_buf { + struct vb2_buffer vb; + struct list_head list; + int idx; +}; + +/** + * struct gsc_addr - the G-Scaler physical address set + * @y: luminance plane address + * @cb: Cb plane address + * @cr: Cr plane address + */ +struct gsc_addr { + dma_addr_t y; + dma_addr_t cb; + dma_addr_t cr; +}; + +/* struct gsc_ctrls - the G-Scaler control set + * @rotate: rotation degree + * @hflip: horizontal flip + * @vflip: vertical flip + * @global_alpha: the alpha value of current frame + */ +struct gsc_ctrls { + struct v4l2_ctrl *rotate; + struct v4l2_ctrl *hflip; + struct v4l2_ctrl *vflip; + struct v4l2_ctrl *global_alpha; +}; + +/** + * struct gsc_scaler - the configuration data for G-Scaler inetrnal scaler + * @pre_shfactor: pre sclaer shift factor + * @pre_hratio: horizontal ratio of the prescaler + * @pre_vratio: vertical ratio of the prescaler + * @main_hratio: the main scaler's horizontal ratio + * @main_vratio: the main scaler's vertical ratio + */ +struct gsc_scaler { + u32 pre_shfactor; + u32 pre_hratio; + u32 pre_vratio; + u32 main_hratio; + u32 main_vratio; +}; + +struct gsc_dev; + +struct gsc_ctx; + +/** + * struct gsc_frame - source/target frame properties + * @f_width: SRC : SRCIMG_WIDTH, DST : OUTPUTDMA_WHOLE_IMG_WIDTH + * @f_height: SRC : SRCIMG_HEIGHT, DST : OUTPUTDMA_WHOLE_IMG_HEIGHT + * @crop: cropped(source)/scaled(destination) size + * @payload: image size in bytes (w x h x bpp) + * @addr: image frame buffer physical addresses + * @fmt: G-Scaler color format pointer + * @colorspace: value indicating v4l2_colorspace + * @alpha: frame's alpha value + */ +struct gsc_frame { + u32 f_width; + u32 f_height; + struct v4l2_rect crop; + unsigned long payload[VIDEO_MAX_PLANES]; + struct gsc_addr addr; + const struct gsc_fmt *fmt; + u32 colorspace; + u8 alpha; +}; + +/** + * struct gsc_m2m_device - v4l2 memory-to-memory device data + * @vfd: the video device node for v4l2 m2m mode + * @m2m_dev: v4l2 memory-to-memory device data + * @ctx: hardware context data + * @refcnt: the reference counter + */ +struct gsc_m2m_device { + struct video_device *vfd; + struct v4l2_m2m_dev *m2m_dev; + struct gsc_ctx *ctx; + int refcnt; +}; + +/** + * struct gsc_pix_max - image pixel size limits in various IP configurations + * + * @org_scaler_bypass_w: max pixel width when the scaler is disabled + * @org_scaler_bypass_h: max pixel height when the scaler is disabled + * @org_scaler_input_w: max pixel width when the scaler is enabled + * @org_scaler_input_h: max pixel height when the scaler is enabled + * @real_rot_dis_w: max pixel src cropped height with the rotator is off + * @real_rot_dis_h: max pixel src croppped width with the rotator is off + * @real_rot_en_w: max pixel src cropped width with the rotator is on + * @real_rot_en_h: max pixel src cropped height with the rotator is on + * @target_rot_dis_w: max pixel dst scaled width with the rotator is off + * @target_rot_dis_h: max pixel dst scaled height with the rotator is off + * @target_rot_en_w: max pixel dst scaled width with the rotator is on + * @target_rot_en_h: max pixel dst scaled height with the rotator is on + */ +struct gsc_pix_max { + u16 org_scaler_bypass_w; + u16 org_scaler_bypass_h; + u16 org_scaler_input_w; + u16 org_scaler_input_h; + u16 real_rot_dis_w; + u16 real_rot_dis_h; + u16 real_rot_en_w; + u16 real_rot_en_h; + u16 target_rot_dis_w; + u16 target_rot_dis_h; + u16 target_rot_en_w; + u16 target_rot_en_h; +}; + +/** + * struct gsc_pix_min - image pixel size limits in various IP configurations + * + * @org_w: minimum source pixel width + * @org_h: minimum source pixel height + * @real_w: minimum input crop pixel width + * @real_h: minimum input crop pixel height + * @target_rot_dis_w: minimum output scaled pixel height when rotator is off + * @target_rot_dis_h: minimum output scaled pixel height when rotator is off + * @target_rot_en_w: minimum output scaled pixel height when rotator is on + * @target_rot_en_h: minimum output scaled pixel height when rotator is on + */ +struct gsc_pix_min { + u16 org_w; + u16 org_h; + u16 real_w; + u16 real_h; + u16 target_rot_dis_w; + u16 target_rot_dis_h; + u16 target_rot_en_w; + u16 target_rot_en_h; +}; + +struct gsc_pix_align { + u16 org_h; + u16 org_w; + u16 offset_h; + u16 real_w; + u16 real_h; + u16 target_w; + u16 target_h; +}; + +/** + * struct gsc_variant - G-Scaler variant information + */ +struct gsc_variant { + struct gsc_pix_max *pix_max; + struct gsc_pix_min *pix_min; + struct gsc_pix_align *pix_align; + u16 in_buf_cnt; + u16 out_buf_cnt; + u16 sc_up_max; + u16 sc_down_max; + u16 poly_sc_down_max; + u16 pre_sc_down_max; + u16 local_sc_down; +}; + +/** + * struct gsc_driverdata - per device type driver data for init time. + * + * @variant: the variant information for this driver. + * @lclk_frequency: G-Scaler clock frequency + * @num_entities: the number of g-scalers + */ +struct gsc_driverdata { + struct gsc_variant *variant[GSC_MAX_DEVS]; + unsigned long lclk_frequency; + int num_entities; +}; + +/** + * struct gsc_dev - abstraction for G-Scaler entity + * @slock: the spinlock protecting this data structure + * @lock: the mutex protecting this data structure + * @pdev: pointer to the G-Scaler platform device + * @variant: the IP variant information + * @id: G-Scaler device index (0..GSC_MAX_DEVS) + * @clock: clocks required for G-Scaler operation + * @regs: the mapped hardware registers + * @irq_queue: interrupt handler waitqueue + * @m2m: memory-to-memory V4L2 device information + * @state: flags used to synchronize m2m and capture mode operation + * @alloc_ctx: videobuf2 memory allocator context + * @vdev: video device for G-Scaler instance + */ +struct gsc_dev { + spinlock_t slock; + struct mutex lock; + struct platform_device *pdev; + struct gsc_variant *variant; + u16 id; + struct clk *clock; + void __iomem *regs; + wait_queue_head_t irq_queue; + struct gsc_m2m_device m2m; + struct exynos_platform_gscaler *pdata; + unsigned long state; + struct vb2_alloc_ctx *alloc_ctx; + struct video_device vdev; +}; + +/** + * gsc_ctx - the device context data + * @s_frame: source frame properties + * @d_frame: destination frame properties + * @in_path: input mode (DMA or camera) + * @out_path: output mode (DMA or FIFO) + * @scaler: image scaler properties + * @flags: additional flags for image conversion + * @state: flags to keep track of user configuration + * @gsc_dev: the G-Scaler device this context applies to + * @m2m_ctx: memory-to-memory device context + * @fh: v4l2 file handle + * @ctrl_handler: v4l2 controls handler + * @gsc_ctrls G-Scaler control set + * @ctrls_rdy: true if the control handler is initialized + */ +struct gsc_ctx { + struct gsc_frame s_frame; + struct gsc_frame d_frame; + enum gsc_datapath in_path; + enum gsc_datapath out_path; + struct gsc_scaler scaler; + u32 flags; + u32 state; + int rotation; + unsigned int hflip:1; + unsigned int vflip:1; + struct gsc_dev *gsc_dev; + struct v4l2_m2m_ctx *m2m_ctx; + struct v4l2_fh fh; + struct v4l2_ctrl_handler ctrl_handler; + struct gsc_ctrls gsc_ctrls; + bool ctrls_rdy; +}; + +void gsc_set_prefbuf(struct gsc_dev *gsc, struct gsc_frame *frm); +int gsc_register_m2m_device(struct gsc_dev *gsc); +void gsc_unregister_m2m_device(struct gsc_dev *gsc); +void gsc_m2m_job_finish(struct gsc_ctx *ctx, int vb_state); + +u32 get_plane_size(struct gsc_frame *fr, unsigned int plane); +const struct gsc_fmt *get_format(int index); +const struct gsc_fmt *find_fmt(u32 *pixelformat, u32 *mbus_code, u32 index); +int gsc_enum_fmt_mplane(struct v4l2_fmtdesc *f); +int gsc_try_fmt_mplane(struct gsc_ctx *ctx, struct v4l2_format *f); +void gsc_set_frame_size(struct gsc_frame *frame, int width, int height); +int gsc_g_fmt_mplane(struct gsc_ctx *ctx, struct v4l2_format *f); +void gsc_check_crop_change(u32 tmp_w, u32 tmp_h, u32 *w, u32 *h); +int gsc_g_crop(struct gsc_ctx *ctx, struct v4l2_crop *cr); +int gsc_try_crop(struct gsc_ctx *ctx, struct v4l2_crop *cr); +int gsc_cal_prescaler_ratio(struct gsc_variant *var, u32 src, u32 dst, + u32 *ratio); +void gsc_get_prescaler_shfactor(u32 hratio, u32 vratio, u32 *sh); +void gsc_check_src_scale_info(struct gsc_variant *var, + struct gsc_frame *s_frame, + u32 *wratio, u32 tx, u32 ty, u32 *hratio); +int gsc_check_scaler_ratio(struct gsc_variant *var, int sw, int sh, int dw, + int dh, int rot, int out_path); +int gsc_set_scaler_info(struct gsc_ctx *ctx); +int gsc_ctrls_create(struct gsc_ctx *ctx); +void gsc_ctrls_delete(struct gsc_ctx *ctx); +int gsc_prepare_addr(struct gsc_ctx *ctx, struct vb2_buffer *vb, + struct gsc_frame *frame, struct gsc_addr *addr); + +static inline void gsc_ctx_state_lock_set(u32 state, struct gsc_ctx *ctx) +{ + unsigned long flags; + + spin_lock_irqsave(&ctx->gsc_dev->slock, flags); + ctx->state |= state; + spin_unlock_irqrestore(&ctx->gsc_dev->slock, flags); +} + +static inline void gsc_ctx_state_lock_clear(u32 state, struct gsc_ctx *ctx) +{ + unsigned long flags; + + spin_lock_irqsave(&ctx->gsc_dev->slock, flags); + ctx->state &= ~state; + spin_unlock_irqrestore(&ctx->gsc_dev->slock, flags); +} + +static inline void gsc_hw_enable_control(struct gsc_dev *dev, bool on) +{ + u32 cfg = readl(dev->regs + GSC_ENABLE); + + if (on) + cfg |= GSC_ENABLE_ON; + else + cfg &= ~GSC_ENABLE_ON; + + writel(cfg, dev->regs + GSC_ENABLE); +} + +static inline int gsc_hw_get_irq_status(struct gsc_dev *dev) +{ + u32 cfg = readl(dev->regs + GSC_IRQ); + if (cfg & GSC_IRQ_STATUS_OR_IRQ) + return GSC_IRQ_OVERRUN; + else + return GSC_IRQ_DONE; + +} + +static inline void gsc_hw_clear_irq(struct gsc_dev *dev, int irq) +{ + u32 cfg = readl(dev->regs + GSC_IRQ); + if (irq == GSC_IRQ_OVERRUN) + cfg |= GSC_IRQ_STATUS_OR_IRQ; + else if (irq == GSC_IRQ_DONE) + cfg |= GSC_IRQ_STATUS_FRM_DONE_IRQ; + writel(cfg, dev->regs + GSC_IRQ); +} + +static inline void gsc_lock(struct vb2_queue *vq) +{ + struct gsc_ctx *ctx = vb2_get_drv_priv(vq); + mutex_lock(&ctx->gsc_dev->lock); +} + +static inline void gsc_unlock(struct vb2_queue *vq) +{ + struct gsc_ctx *ctx = vb2_get_drv_priv(vq); + mutex_unlock(&ctx->gsc_dev->lock); +} + +static inline bool gsc_ctx_state_is_set(u32 mask, struct gsc_ctx *ctx) +{ + unsigned long flags; + bool ret; + + spin_lock_irqsave(&ctx->gsc_dev->slock, flags); + ret = (ctx->state & mask) == mask; + spin_unlock_irqrestore(&ctx->gsc_dev->slock, flags); + return ret; +} + +static inline struct gsc_frame *ctx_get_frame(struct gsc_ctx *ctx, + enum v4l2_buf_type type) +{ + struct gsc_frame *frame; + + if (V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE == type) { + frame = &ctx->s_frame; + } else if (V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE == type) { + frame = &ctx->d_frame; + } else { + pr_err("Wrong buffer/video queue type (%d)", type); + return ERR_PTR(-EINVAL); + } + + return frame; +} + +void gsc_hw_set_sw_reset(struct gsc_dev *dev); +int gsc_wait_reset(struct gsc_dev *dev); + +void gsc_hw_set_frm_done_irq_mask(struct gsc_dev *dev, bool mask); +void gsc_hw_set_gsc_irq_enable(struct gsc_dev *dev, bool mask); +void gsc_hw_set_input_buf_masking(struct gsc_dev *dev, u32 shift, bool enable); +void gsc_hw_set_output_buf_masking(struct gsc_dev *dev, u32 shift, bool enable); +void gsc_hw_set_input_addr(struct gsc_dev *dev, struct gsc_addr *addr, + int index); +void gsc_hw_set_output_addr(struct gsc_dev *dev, struct gsc_addr *addr, + int index); +void gsc_hw_set_input_path(struct gsc_ctx *ctx); +void gsc_hw_set_in_size(struct gsc_ctx *ctx); +void gsc_hw_set_in_image_rgb(struct gsc_ctx *ctx); +void gsc_hw_set_in_image_format(struct gsc_ctx *ctx); +void gsc_hw_set_output_path(struct gsc_ctx *ctx); +void gsc_hw_set_out_size(struct gsc_ctx *ctx); +void gsc_hw_set_out_image_rgb(struct gsc_ctx *ctx); +void gsc_hw_set_out_image_format(struct gsc_ctx *ctx); +void gsc_hw_set_prescaler(struct gsc_ctx *ctx); +void gsc_hw_set_mainscaler(struct gsc_ctx *ctx); +void gsc_hw_set_rotation(struct gsc_ctx *ctx); +void gsc_hw_set_global_alpha(struct gsc_ctx *ctx); +void gsc_hw_set_sfr_update(struct gsc_ctx *ctx); + +#endif /* GSC_CORE_H_ */ diff --git a/drivers/media/platform/exynos-gsc/gsc-m2m.c b/drivers/media/platform/exynos-gsc/gsc-m2m.c new file mode 100644 index 000000000000..3c7f00577bd9 --- /dev/null +++ b/drivers/media/platform/exynos-gsc/gsc-m2m.c @@ -0,0 +1,770 @@ +/* + * Copyright (c) 2011 - 2012 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * Samsung EXYNOS5 SoC series G-Scaler driver + * + * 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 <linux/module.h> +#include <linux/kernel.h> +#include <linux/types.h> +#include <linux/errno.h> +#include <linux/bug.h> +#include <linux/interrupt.h> +#include <linux/workqueue.h> +#include <linux/device.h> +#include <linux/platform_device.h> +#include <linux/list.h> +#include <linux/io.h> +#include <linux/slab.h> +#include <linux/clk.h> + +#include <media/v4l2-ioctl.h> + +#include "gsc-core.h" + +static int gsc_m2m_ctx_stop_req(struct gsc_ctx *ctx) +{ + struct gsc_ctx *curr_ctx; + struct gsc_dev *gsc = ctx->gsc_dev; + int ret; + + curr_ctx = v4l2_m2m_get_curr_priv(gsc->m2m.m2m_dev); + if (!gsc_m2m_pending(gsc) || (curr_ctx != ctx)) + return 0; + + gsc_ctx_state_lock_set(GSC_CTX_STOP_REQ, ctx); + ret = wait_event_timeout(gsc->irq_queue, + !gsc_ctx_state_is_set(GSC_CTX_STOP_REQ, ctx), + GSC_SHUTDOWN_TIMEOUT); + + return ret == 0 ? -ETIMEDOUT : ret; +} + +static int gsc_m2m_start_streaming(struct vb2_queue *q, unsigned int count) +{ + struct gsc_ctx *ctx = q->drv_priv; + int ret; + + ret = pm_runtime_get_sync(&ctx->gsc_dev->pdev->dev); + return ret > 0 ? 0 : ret; +} + +static int gsc_m2m_stop_streaming(struct vb2_queue *q) +{ + struct gsc_ctx *ctx = q->drv_priv; + int ret; + + ret = gsc_m2m_ctx_stop_req(ctx); + if (ret == -ETIMEDOUT) + gsc_m2m_job_finish(ctx, VB2_BUF_STATE_ERROR); + + pm_runtime_put(&ctx->gsc_dev->pdev->dev); + + return 0; +} + +void gsc_m2m_job_finish(struct gsc_ctx *ctx, int vb_state) +{ + struct vb2_buffer *src_vb, *dst_vb; + + if (!ctx || !ctx->m2m_ctx) + return; + + src_vb = v4l2_m2m_src_buf_remove(ctx->m2m_ctx); + dst_vb = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx); + + if (src_vb && dst_vb) { + v4l2_m2m_buf_done(src_vb, vb_state); + v4l2_m2m_buf_done(dst_vb, vb_state); + + v4l2_m2m_job_finish(ctx->gsc_dev->m2m.m2m_dev, + ctx->m2m_ctx); + } +} + + +static void gsc_m2m_job_abort(void *priv) +{ + struct gsc_ctx *ctx = priv; + int ret; + + ret = gsc_m2m_ctx_stop_req(ctx); + if (ret == -ETIMEDOUT) + gsc_m2m_job_finish(ctx, VB2_BUF_STATE_ERROR); +} + +static int gsc_fill_addr(struct gsc_ctx *ctx) +{ + struct gsc_frame *s_frame, *d_frame; + struct vb2_buffer *vb = NULL; + int ret; + + s_frame = &ctx->s_frame; + d_frame = &ctx->d_frame; + + vb = v4l2_m2m_next_src_buf(ctx->m2m_ctx); + ret = gsc_prepare_addr(ctx, vb, s_frame, &s_frame->addr); + if (ret) + return ret; + + vb = v4l2_m2m_next_dst_buf(ctx->m2m_ctx); + return gsc_prepare_addr(ctx, vb, d_frame, &d_frame->addr); +} + +static void gsc_m2m_device_run(void *priv) +{ + struct gsc_ctx *ctx = priv; + struct gsc_dev *gsc; + unsigned long flags; + u32 ret; + bool is_set = false; + + if (WARN(!ctx, "null hardware context\n")) + return; + + gsc = ctx->gsc_dev; + spin_lock_irqsave(&gsc->slock, flags); + + set_bit(ST_M2M_PEND, &gsc->state); + + /* Reconfigure hardware if the context has changed. */ + if (gsc->m2m.ctx != ctx) { + pr_debug("gsc->m2m.ctx = 0x%p, current_ctx = 0x%p", + gsc->m2m.ctx, ctx); + ctx->state |= GSC_PARAMS; + gsc->m2m.ctx = ctx; + } + + is_set = (ctx->state & GSC_CTX_STOP_REQ) ? 1 : 0; + ctx->state &= ~GSC_CTX_STOP_REQ; + if (is_set) { + wake_up(&gsc->irq_queue); + goto put_device; + } + + ret = gsc_fill_addr(ctx); + if (ret) { + pr_err("Wrong address"); + goto put_device; + } + + gsc_set_prefbuf(gsc, &ctx->s_frame); + gsc_hw_set_input_addr(gsc, &ctx->s_frame.addr, GSC_M2M_BUF_NUM); + gsc_hw_set_output_addr(gsc, &ctx->d_frame.addr, GSC_M2M_BUF_NUM); + + if (ctx->state & GSC_PARAMS) { + gsc_hw_set_input_buf_masking(gsc, GSC_M2M_BUF_NUM, false); + gsc_hw_set_output_buf_masking(gsc, GSC_M2M_BUF_NUM, false); + gsc_hw_set_frm_done_irq_mask(gsc, false); + gsc_hw_set_gsc_irq_enable(gsc, true); + + if (gsc_set_scaler_info(ctx)) { + pr_err("Scaler setup error"); + goto put_device; + } + + gsc_hw_set_input_path(ctx); + gsc_hw_set_in_size(ctx); + gsc_hw_set_in_image_format(ctx); + + gsc_hw_set_output_path(ctx); + gsc_hw_set_out_size(ctx); + gsc_hw_set_out_image_format(ctx); + + gsc_hw_set_prescaler(ctx); + gsc_hw_set_mainscaler(ctx); + gsc_hw_set_rotation(ctx); + gsc_hw_set_global_alpha(ctx); + } + + /* update shadow registers */ + gsc_hw_set_sfr_update(ctx); + + ctx->state &= ~GSC_PARAMS; + gsc_hw_enable_control(gsc, true); + + spin_unlock_irqrestore(&gsc->slock, flags); + return; + +put_device: + ctx->state &= ~GSC_PARAMS; + spin_unlock_irqrestore(&gsc->slock, flags); +} + +static int gsc_m2m_queue_setup(struct vb2_queue *vq, + const struct v4l2_format *fmt, + unsigned int *num_buffers, unsigned int *num_planes, + unsigned int sizes[], void *allocators[]) +{ + struct gsc_ctx *ctx = vb2_get_drv_priv(vq); + struct gsc_frame *frame; + int i; + + frame = ctx_get_frame(ctx, vq->type); + if (IS_ERR(frame)) + return PTR_ERR(frame); + + if (!frame->fmt) + return -EINVAL; + + *num_planes = frame->fmt->num_planes; + for (i = 0; i < frame->fmt->num_planes; i++) { + sizes[i] = frame->payload[i]; + allocators[i] = ctx->gsc_dev->alloc_ctx; + } + return 0; +} + +static int gsc_m2m_buf_prepare(struct vb2_buffer *vb) +{ + struct gsc_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); + struct gsc_frame *frame; + int i; + + frame = ctx_get_frame(ctx, vb->vb2_queue->type); + if (IS_ERR(frame)) + return PTR_ERR(frame); + + if (!V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type)) { + for (i = 0; i < frame->fmt->num_planes; i++) + vb2_set_plane_payload(vb, i, frame->payload[i]); + } + + return 0; +} + +static void gsc_m2m_buf_queue(struct vb2_buffer *vb) +{ + struct gsc_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); + + pr_debug("ctx: %p, ctx->state: 0x%x", ctx, ctx->state); + + if (ctx->m2m_ctx) + v4l2_m2m_buf_queue(ctx->m2m_ctx, vb); +} + +static struct vb2_ops gsc_m2m_qops = { + .queue_setup = gsc_m2m_queue_setup, + .buf_prepare = gsc_m2m_buf_prepare, + .buf_queue = gsc_m2m_buf_queue, + .wait_prepare = gsc_unlock, + .wait_finish = gsc_lock, + .stop_streaming = gsc_m2m_stop_streaming, + .start_streaming = gsc_m2m_start_streaming, +}; + +static int gsc_m2m_querycap(struct file *file, void *fh, + struct v4l2_capability *cap) +{ + struct gsc_ctx *ctx = fh_to_ctx(fh); + struct gsc_dev *gsc = ctx->gsc_dev; + + strlcpy(cap->driver, gsc->pdev->name, sizeof(cap->driver)); + strlcpy(cap->card, gsc->pdev->name, sizeof(cap->card)); + strlcpy(cap->bus_info, "platform", sizeof(cap->bus_info)); + cap->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_M2M_MPLANE | + V4L2_CAP_VIDEO_CAPTURE_MPLANE | V4L2_CAP_VIDEO_OUTPUT_MPLANE; + + cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; + return 0; +} + +static int gsc_m2m_enum_fmt_mplane(struct file *file, void *priv, + struct v4l2_fmtdesc *f) +{ + return gsc_enum_fmt_mplane(f); +} + +static int gsc_m2m_g_fmt_mplane(struct file *file, void *fh, + struct v4l2_format *f) +{ + struct gsc_ctx *ctx = fh_to_ctx(fh); + + return gsc_g_fmt_mplane(ctx, f); +} + +static int gsc_m2m_try_fmt_mplane(struct file *file, void *fh, + struct v4l2_format *f) +{ + struct gsc_ctx *ctx = fh_to_ctx(fh); + + return gsc_try_fmt_mplane(ctx, f); +} + +static int gsc_m2m_s_fmt_mplane(struct file *file, void *fh, + struct v4l2_format *f) +{ + struct gsc_ctx *ctx = fh_to_ctx(fh); + struct vb2_queue *vq; + struct gsc_frame *frame; + struct v4l2_pix_format_mplane *pix; + int i, ret = 0; + + ret = gsc_m2m_try_fmt_mplane(file, fh, f); + if (ret) + return ret; + + vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type); + + if (vb2_is_streaming(vq)) { + pr_err("queue (%d) busy", f->type); + return -EBUSY; + } + + if (V4L2_TYPE_IS_OUTPUT(f->type)) + frame = &ctx->s_frame; + else + frame = &ctx->d_frame; + + pix = &f->fmt.pix_mp; + frame->fmt = find_fmt(&pix->pixelformat, NULL, 0); + frame->colorspace = pix->colorspace; + if (!frame->fmt) + return -EINVAL; + + for (i = 0; i < frame->fmt->num_planes; i++) + frame->payload[i] = pix->plane_fmt[i].sizeimage; + + gsc_set_frame_size(frame, pix->width, pix->height); + + if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) + gsc_ctx_state_lock_set(GSC_PARAMS | GSC_DST_FMT, ctx); + else + gsc_ctx_state_lock_set(GSC_PARAMS | GSC_SRC_FMT, ctx); + + pr_debug("f_w: %d, f_h: %d", frame->f_width, frame->f_height); + + return 0; +} + +static int gsc_m2m_reqbufs(struct file *file, void *fh, + struct v4l2_requestbuffers *reqbufs) +{ + struct gsc_ctx *ctx = fh_to_ctx(fh); + struct gsc_dev *gsc = ctx->gsc_dev; + struct gsc_frame *frame; + u32 max_cnt; + + max_cnt = (reqbufs->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) ? + gsc->variant->in_buf_cnt : gsc->variant->out_buf_cnt; + if (reqbufs->count > max_cnt) { + return -EINVAL; + } else if (reqbufs->count == 0) { + if (reqbufs->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) + gsc_ctx_state_lock_clear(GSC_SRC_FMT, ctx); + else + gsc_ctx_state_lock_clear(GSC_DST_FMT, ctx); + } + + frame = ctx_get_frame(ctx, reqbufs->type); + + return v4l2_m2m_reqbufs(file, ctx->m2m_ctx, reqbufs); +} + +static int gsc_m2m_querybuf(struct file *file, void *fh, + struct v4l2_buffer *buf) +{ + struct gsc_ctx *ctx = fh_to_ctx(fh); + return v4l2_m2m_querybuf(file, ctx->m2m_ctx, buf); +} + +static int gsc_m2m_qbuf(struct file *file, void *fh, + struct v4l2_buffer *buf) +{ + struct gsc_ctx *ctx = fh_to_ctx(fh); + return v4l2_m2m_qbuf(file, ctx->m2m_ctx, buf); +} + +static int gsc_m2m_dqbuf(struct file *file, void *fh, + struct v4l2_buffer *buf) +{ + struct gsc_ctx *ctx = fh_to_ctx(fh); + return v4l2_m2m_dqbuf(file, ctx->m2m_ctx, buf); +} + +static int gsc_m2m_streamon(struct file *file, void *fh, + enum v4l2_buf_type type) +{ + struct gsc_ctx *ctx = fh_to_ctx(fh); + + /* The source and target color format need to be set */ + if (V4L2_TYPE_IS_OUTPUT(type)) { + if (!gsc_ctx_state_is_set(GSC_SRC_FMT, ctx)) + return -EINVAL; + } else if (!gsc_ctx_state_is_set(GSC_DST_FMT, ctx)) { + return -EINVAL; + } + + return v4l2_m2m_streamon(file, ctx->m2m_ctx, type); +} + +static int gsc_m2m_streamoff(struct file *file, void *fh, + enum v4l2_buf_type type) +{ + struct gsc_ctx *ctx = fh_to_ctx(fh); + return v4l2_m2m_streamoff(file, ctx->m2m_ctx, type); +} + +/* Return 1 if rectangle a is enclosed in rectangle b, or 0 otherwise. */ +static int is_rectangle_enclosed(struct v4l2_rect *a, struct v4l2_rect *b) +{ + if (a->left < b->left || a->top < b->top) + return 0; + + if (a->left + a->width > b->left + b->width) + return 0; + + if (a->top + a->height > b->top + b->height) + return 0; + + return 1; +} + +static int gsc_m2m_g_selection(struct file *file, void *fh, + struct v4l2_selection *s) +{ + struct gsc_frame *frame; + struct gsc_ctx *ctx = fh_to_ctx(fh); + + if ((s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) && + (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)) + return -EINVAL; + + frame = ctx_get_frame(ctx, s->type); + if (IS_ERR(frame)) + return PTR_ERR(frame); + + switch (s->target) { + case V4L2_SEL_TGT_COMPOSE_DEFAULT: + case V4L2_SEL_TGT_COMPOSE_BOUNDS: + case V4L2_SEL_TGT_CROP_BOUNDS: + case V4L2_SEL_TGT_CROP_DEFAULT: + s->r.left = 0; + s->r.top = 0; + s->r.width = frame->f_width; + s->r.height = frame->f_height; + return 0; + + case V4L2_SEL_TGT_COMPOSE: + case V4L2_SEL_TGT_CROP: + s->r.left = frame->crop.left; + s->r.top = frame->crop.top; + s->r.width = frame->crop.width; + s->r.height = frame->crop.height; + return 0; + } + + return -EINVAL; +} + +static int gsc_m2m_s_selection(struct file *file, void *fh, + struct v4l2_selection *s) +{ + struct gsc_frame *frame; + struct gsc_ctx *ctx = fh_to_ctx(fh); + struct v4l2_crop cr; + struct gsc_variant *variant = ctx->gsc_dev->variant; + int ret; + + cr.type = s->type; + cr.c = s->r; + + if ((s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) && + (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)) + return -EINVAL; + + ret = gsc_try_crop(ctx, &cr); + if (ret) + return ret; + + if (s->flags & V4L2_SEL_FLAG_LE && + !is_rectangle_enclosed(&cr.c, &s->r)) + return -ERANGE; + + if (s->flags & V4L2_SEL_FLAG_GE && + !is_rectangle_enclosed(&s->r, &cr.c)) + return -ERANGE; + + s->r = cr.c; + + switch (s->target) { + case V4L2_SEL_TGT_COMPOSE_BOUNDS: + case V4L2_SEL_TGT_COMPOSE_DEFAULT: + case V4L2_SEL_TGT_COMPOSE: + frame = &ctx->s_frame; + break; + + case V4L2_SEL_TGT_CROP_BOUNDS: + case V4L2_SEL_TGT_CROP: + case V4L2_SEL_TGT_CROP_DEFAULT: + frame = &ctx->d_frame; + break; + + default: + return -EINVAL; + } + + /* Check to see if scaling ratio is within supported range */ + if (gsc_ctx_state_is_set(GSC_DST_FMT | GSC_SRC_FMT, ctx)) { + if (s->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { + ret = gsc_check_scaler_ratio(variant, cr.c.width, + cr.c.height, ctx->d_frame.crop.width, + ctx->d_frame.crop.height, + ctx->gsc_ctrls.rotate->val, ctx->out_path); + } else { + ret = gsc_check_scaler_ratio(variant, + ctx->s_frame.crop.width, + ctx->s_frame.crop.height, cr.c.width, + cr.c.height, ctx->gsc_ctrls.rotate->val, + ctx->out_path); + } + + if (ret) { + pr_err("Out of scaler range"); + return -EINVAL; + } + } + + frame->crop = cr.c; + + gsc_ctx_state_lock_set(GSC_PARAMS, ctx); + return 0; +} + +static const struct v4l2_ioctl_ops gsc_m2m_ioctl_ops = { + .vidioc_querycap = gsc_m2m_querycap, + .vidioc_enum_fmt_vid_cap_mplane = gsc_m2m_enum_fmt_mplane, + .vidioc_enum_fmt_vid_out_mplane = gsc_m2m_enum_fmt_mplane, + .vidioc_g_fmt_vid_cap_mplane = gsc_m2m_g_fmt_mplane, + .vidioc_g_fmt_vid_out_mplane = gsc_m2m_g_fmt_mplane, + .vidioc_try_fmt_vid_cap_mplane = gsc_m2m_try_fmt_mplane, + .vidioc_try_fmt_vid_out_mplane = gsc_m2m_try_fmt_mplane, + .vidioc_s_fmt_vid_cap_mplane = gsc_m2m_s_fmt_mplane, + .vidioc_s_fmt_vid_out_mplane = gsc_m2m_s_fmt_mplane, + .vidioc_reqbufs = gsc_m2m_reqbufs, + .vidioc_querybuf = gsc_m2m_querybuf, + .vidioc_qbuf = gsc_m2m_qbuf, + .vidioc_dqbuf = gsc_m2m_dqbuf, + .vidioc_streamon = gsc_m2m_streamon, + .vidioc_streamoff = gsc_m2m_streamoff, + .vidioc_g_selection = gsc_m2m_g_selection, + .vidioc_s_selection = gsc_m2m_s_selection +}; + +static int queue_init(void *priv, struct vb2_queue *src_vq, + struct vb2_queue *dst_vq) +{ + struct gsc_ctx *ctx = priv; + int ret; + + memset(src_vq, 0, sizeof(*src_vq)); + src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; + src_vq->io_modes = VB2_MMAP | VB2_USERPTR; + src_vq->drv_priv = ctx; + src_vq->ops = &gsc_m2m_qops; + src_vq->mem_ops = &vb2_dma_contig_memops; + src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); + + ret = vb2_queue_init(src_vq); + if (ret) + return ret; + + memset(dst_vq, 0, sizeof(*dst_vq)); + dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + dst_vq->io_modes = VB2_MMAP | VB2_USERPTR; + dst_vq->drv_priv = ctx; + dst_vq->ops = &gsc_m2m_qops; + dst_vq->mem_ops = &vb2_dma_contig_memops; + dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); + + return vb2_queue_init(dst_vq); +} + +static int gsc_m2m_open(struct file *file) +{ + struct gsc_dev *gsc = video_drvdata(file); + struct gsc_ctx *ctx = NULL; + int ret; + + pr_debug("pid: %d, state: 0x%lx", task_pid_nr(current), gsc->state); + + if (mutex_lock_interruptible(&gsc->lock)) + return -ERESTARTSYS; + + ctx = kzalloc(sizeof (*ctx), GFP_KERNEL); + if (!ctx) { + ret = -ENOMEM; + goto unlock; + } + + v4l2_fh_init(&ctx->fh, gsc->m2m.vfd); + ret = gsc_ctrls_create(ctx); + if (ret) + goto error_fh; + + /* Use separate control handler per file handle */ + ctx->fh.ctrl_handler = &ctx->ctrl_handler; + file->private_data = &ctx->fh; + v4l2_fh_add(&ctx->fh); + + ctx->gsc_dev = gsc; + /* Default color format */ + ctx->s_frame.fmt = get_format(0); + ctx->d_frame.fmt = get_format(0); + /* Setup the device context for mem2mem mode. */ + ctx->state = GSC_CTX_M2M; + ctx->flags = 0; + ctx->in_path = GSC_DMA; + ctx->out_path = GSC_DMA; + + ctx->m2m_ctx = v4l2_m2m_ctx_init(gsc->m2m.m2m_dev, ctx, queue_init); + if (IS_ERR(ctx->m2m_ctx)) { + pr_err("Failed to initialize m2m context"); + ret = PTR_ERR(ctx->m2m_ctx); + goto error_ctrls; + } + + if (gsc->m2m.refcnt++ == 0) + set_bit(ST_M2M_OPEN, &gsc->state); + + pr_debug("gsc m2m driver is opened, ctx(0x%p)", ctx); + + mutex_unlock(&gsc->lock); + return 0; + +error_ctrls: + gsc_ctrls_delete(ctx); +error_fh: + v4l2_fh_del(&ctx->fh); + v4l2_fh_exit(&ctx->fh); + kfree(ctx); +unlock: + mutex_unlock(&gsc->lock); + return ret; +} + +static int gsc_m2m_release(struct file *file) +{ + struct gsc_ctx *ctx = fh_to_ctx(file->private_data); + struct gsc_dev *gsc = ctx->gsc_dev; + + pr_debug("pid: %d, state: 0x%lx, refcnt= %d", + task_pid_nr(current), gsc->state, gsc->m2m.refcnt); + + if (mutex_lock_interruptible(&gsc->lock)) + return -ERESTARTSYS; + + v4l2_m2m_ctx_release(ctx->m2m_ctx); + gsc_ctrls_delete(ctx); + v4l2_fh_del(&ctx->fh); + v4l2_fh_exit(&ctx->fh); + + if (--gsc->m2m.refcnt <= 0) + clear_bit(ST_M2M_OPEN, &gsc->state); + kfree(ctx); + + mutex_unlock(&gsc->lock); + return 0; +} + +static unsigned int gsc_m2m_poll(struct file *file, + struct poll_table_struct *wait) +{ + struct gsc_ctx *ctx = fh_to_ctx(file->private_data); + struct gsc_dev *gsc = ctx->gsc_dev; + int ret; + + if (mutex_lock_interruptible(&gsc->lock)) + return -ERESTARTSYS; + + ret = v4l2_m2m_poll(file, ctx->m2m_ctx, wait); + mutex_unlock(&gsc->lock); + + return ret; +} + +static int gsc_m2m_mmap(struct file *file, struct vm_area_struct *vma) +{ + struct gsc_ctx *ctx = fh_to_ctx(file->private_data); + struct gsc_dev *gsc = ctx->gsc_dev; + int ret; + + if (mutex_lock_interruptible(&gsc->lock)) + return -ERESTARTSYS; + + ret = v4l2_m2m_mmap(file, ctx->m2m_ctx, vma); + mutex_unlock(&gsc->lock); + + return ret; +} + +static const struct v4l2_file_operations gsc_m2m_fops = { + .owner = THIS_MODULE, + .open = gsc_m2m_open, + .release = gsc_m2m_release, + .poll = gsc_m2m_poll, + .unlocked_ioctl = video_ioctl2, + .mmap = gsc_m2m_mmap, +}; + +static struct v4l2_m2m_ops gsc_m2m_ops = { + .device_run = gsc_m2m_device_run, + .job_abort = gsc_m2m_job_abort, +}; + +int gsc_register_m2m_device(struct gsc_dev *gsc) +{ + struct platform_device *pdev; + int ret; + + if (!gsc) + return -ENODEV; + + pdev = gsc->pdev; + + gsc->vdev.fops = &gsc_m2m_fops; + gsc->vdev.ioctl_ops = &gsc_m2m_ioctl_ops; + gsc->vdev.release = video_device_release_empty; + gsc->vdev.lock = &gsc->lock; + snprintf(gsc->vdev.name, sizeof(gsc->vdev.name), "%s.%d:m2m", + GSC_MODULE_NAME, gsc->id); + + video_set_drvdata(&gsc->vdev, gsc); + + gsc->m2m.vfd = &gsc->vdev; + gsc->m2m.m2m_dev = v4l2_m2m_init(&gsc_m2m_ops); + if (IS_ERR(gsc->m2m.m2m_dev)) { + dev_err(&pdev->dev, "failed to initialize v4l2-m2m device\n"); + ret = PTR_ERR(gsc->m2m.m2m_dev); + goto err_m2m_r1; + } + + ret = video_register_device(&gsc->vdev, VFL_TYPE_GRABBER, -1); + if (ret) { + dev_err(&pdev->dev, + "%s(): failed to register video device\n", __func__); + goto err_m2m_r2; + } + + pr_debug("gsc m2m driver registered as /dev/video%d", gsc->vdev.num); + return 0; + +err_m2m_r2: + v4l2_m2m_release(gsc->m2m.m2m_dev); +err_m2m_r1: + video_device_release(gsc->m2m.vfd); + + return ret; +} + +void gsc_unregister_m2m_device(struct gsc_dev *gsc) +{ + if (gsc) + v4l2_m2m_release(gsc->m2m.m2m_dev); +} diff --git a/drivers/media/platform/exynos-gsc/gsc-regs.c b/drivers/media/platform/exynos-gsc/gsc-regs.c new file mode 100644 index 000000000000..0d8625f03a32 --- /dev/null +++ b/drivers/media/platform/exynos-gsc/gsc-regs.c @@ -0,0 +1,425 @@ +/* + * Copyright (c) 2011 - 2012 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * Samsung EXYNOS5 SoC series G-Scaler driver + * + * 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 <linux/io.h> +#include <linux/delay.h> +#include <mach/map.h> + +#include "gsc-core.h" + +void gsc_hw_set_sw_reset(struct gsc_dev *dev) +{ + writel(GSC_SW_RESET_SRESET, dev->regs + GSC_SW_RESET); +} + +int gsc_wait_reset(struct gsc_dev *dev) +{ + unsigned long end = jiffies + msecs_to_jiffies(50); + u32 cfg; + + while (time_before(jiffies, end)) { + cfg = readl(dev->regs + GSC_SW_RESET); + if (!cfg) + return 0; + usleep_range(10, 20); + } + + return -EBUSY; +} + +void gsc_hw_set_frm_done_irq_mask(struct gsc_dev *dev, bool mask) +{ + u32 cfg; + + cfg = readl(dev->regs + GSC_IRQ); + if (mask) + cfg |= GSC_IRQ_FRMDONE_MASK; + else + cfg &= ~GSC_IRQ_FRMDONE_MASK; + writel(cfg, dev->regs + GSC_IRQ); +} + +void gsc_hw_set_gsc_irq_enable(struct gsc_dev *dev, bool mask) +{ + u32 cfg; + + cfg = readl(dev->regs + GSC_IRQ); + if (mask) + cfg |= GSC_IRQ_ENABLE; + else + cfg &= ~GSC_IRQ_ENABLE; + writel(cfg, dev->regs + GSC_IRQ); +} + +void gsc_hw_set_input_buf_masking(struct gsc_dev *dev, u32 shift, + bool enable) +{ + u32 cfg = readl(dev->regs + GSC_IN_BASE_ADDR_Y_MASK); + u32 mask = 1 << shift; + + cfg &= ~mask; + cfg |= enable << shift; + + writel(cfg, dev->regs + GSC_IN_BASE_ADDR_Y_MASK); + writel(cfg, dev->regs + GSC_IN_BASE_ADDR_CB_MASK); + writel(cfg, dev->regs + GSC_IN_BASE_ADDR_CR_MASK); +} + +void gsc_hw_set_output_buf_masking(struct gsc_dev *dev, u32 shift, + bool enable) +{ + u32 cfg = readl(dev->regs + GSC_OUT_BASE_ADDR_Y_MASK); + u32 mask = 1 << shift; + + cfg &= ~mask; + cfg |= enable << shift; + + writel(cfg, dev->regs + GSC_OUT_BASE_ADDR_Y_MASK); + writel(cfg, dev->regs + GSC_OUT_BASE_ADDR_CB_MASK); + writel(cfg, dev->regs + GSC_OUT_BASE_ADDR_CR_MASK); +} + +void gsc_hw_set_input_addr(struct gsc_dev *dev, struct gsc_addr *addr, + int index) +{ + pr_debug("src_buf[%d]: 0x%X, cb: 0x%X, cr: 0x%X", index, + addr->y, addr->cb, addr->cr); + writel(addr->y, dev->regs + GSC_IN_BASE_ADDR_Y(index)); + writel(addr->cb, dev->regs + GSC_IN_BASE_ADDR_CB(index)); + writel(addr->cr, dev->regs + GSC_IN_BASE_ADDR_CR(index)); + +} + +void gsc_hw_set_output_addr(struct gsc_dev *dev, + struct gsc_addr *addr, int index) +{ + pr_debug("dst_buf[%d]: 0x%X, cb: 0x%X, cr: 0x%X", + index, addr->y, addr->cb, addr->cr); + writel(addr->y, dev->regs + GSC_OUT_BASE_ADDR_Y(index)); + writel(addr->cb, dev->regs + GSC_OUT_BASE_ADDR_CB(index)); + writel(addr->cr, dev->regs + GSC_OUT_BASE_ADDR_CR(index)); +} + +void gsc_hw_set_input_path(struct gsc_ctx *ctx) +{ + struct gsc_dev *dev = ctx->gsc_dev; + + u32 cfg = readl(dev->regs + GSC_IN_CON); + cfg &= ~(GSC_IN_PATH_MASK | GSC_IN_LOCAL_SEL_MASK); + + if (ctx->in_path == GSC_DMA) + cfg |= GSC_IN_PATH_MEMORY; + + writel(cfg, dev->regs + GSC_IN_CON); +} + +void gsc_hw_set_in_size(struct gsc_ctx *ctx) +{ + struct gsc_dev *dev = ctx->gsc_dev; + struct gsc_frame *frame = &ctx->s_frame; + u32 cfg; + + /* Set input pixel offset */ + cfg = GSC_SRCIMG_OFFSET_X(frame->crop.left); + cfg |= GSC_SRCIMG_OFFSET_Y(frame->crop.top); + writel(cfg, dev->regs + GSC_SRCIMG_OFFSET); + + /* Set input original size */ + cfg = GSC_SRCIMG_WIDTH(frame->f_width); + cfg |= GSC_SRCIMG_HEIGHT(frame->f_height); + writel(cfg, dev->regs + GSC_SRCIMG_SIZE); + + /* Set input cropped size */ + cfg = GSC_CROPPED_WIDTH(frame->crop.width); + cfg |= GSC_CROPPED_HEIGHT(frame->crop.height); + writel(cfg, dev->regs + GSC_CROPPED_SIZE); +} + +void gsc_hw_set_in_image_rgb(struct gsc_ctx *ctx) +{ + struct gsc_dev *dev = ctx->gsc_dev; + struct gsc_frame *frame = &ctx->s_frame; + u32 cfg; + + cfg = readl(dev->regs + GSC_IN_CON); + if (frame->colorspace == V4L2_COLORSPACE_REC709) + cfg |= GSC_IN_RGB_HD_WIDE; + else + cfg |= GSC_IN_RGB_SD_WIDE; + + if (frame->fmt->pixelformat == V4L2_PIX_FMT_RGB565X) + cfg |= GSC_IN_RGB565; + else if (frame->fmt->pixelformat == V4L2_PIX_FMT_RGB32) + cfg |= GSC_IN_XRGB8888; + + writel(cfg, dev->regs + GSC_IN_CON); +} + +void gsc_hw_set_in_image_format(struct gsc_ctx *ctx) +{ + struct gsc_dev *dev = ctx->gsc_dev; + struct gsc_frame *frame = &ctx->s_frame; + u32 i, depth = 0; + u32 cfg; + + cfg = readl(dev->regs + GSC_IN_CON); + cfg &= ~(GSC_IN_RGB_TYPE_MASK | GSC_IN_YUV422_1P_ORDER_MASK | + GSC_IN_CHROMA_ORDER_MASK | GSC_IN_FORMAT_MASK | + GSC_IN_TILE_TYPE_MASK | GSC_IN_TILE_MODE); + writel(cfg, dev->regs + GSC_IN_CON); + + if (is_rgb(frame->fmt->color)) { + gsc_hw_set_in_image_rgb(ctx); + return; + } + for (i = 0; i < frame->fmt->num_planes; i++) + depth += frame->fmt->depth[i]; + + switch (frame->fmt->num_comp) { + case 1: + cfg |= GSC_IN_YUV422_1P; + if (frame->fmt->yorder == GSC_LSB_Y) + cfg |= GSC_IN_YUV422_1P_ORDER_LSB_Y; + else + cfg |= GSC_IN_YUV422_1P_OEDER_LSB_C; + if (frame->fmt->corder == GSC_CBCR) + cfg |= GSC_IN_CHROMA_ORDER_CBCR; + else + cfg |= GSC_IN_CHROMA_ORDER_CRCB; + break; + case 2: + if (depth == 12) + cfg |= GSC_IN_YUV420_2P; + else + cfg |= GSC_IN_YUV422_2P; + if (frame->fmt->corder == GSC_CBCR) + cfg |= GSC_IN_CHROMA_ORDER_CBCR; + else + cfg |= GSC_IN_CHROMA_ORDER_CRCB; + break; + case 3: + if (depth == 12) + cfg |= GSC_IN_YUV420_3P; + else + cfg |= GSC_IN_YUV422_3P; + break; + }; + + writel(cfg, dev->regs + GSC_IN_CON); +} + +void gsc_hw_set_output_path(struct gsc_ctx *ctx) +{ + struct gsc_dev *dev = ctx->gsc_dev; + + u32 cfg = readl(dev->regs + GSC_OUT_CON); + cfg &= ~GSC_OUT_PATH_MASK; + + if (ctx->out_path == GSC_DMA) + cfg |= GSC_OUT_PATH_MEMORY; + else + cfg |= GSC_OUT_PATH_LOCAL; + + writel(cfg, dev->regs + GSC_OUT_CON); +} + +void gsc_hw_set_out_size(struct gsc_ctx *ctx) +{ + struct gsc_dev *dev = ctx->gsc_dev; + struct gsc_frame *frame = &ctx->d_frame; + u32 cfg; + + /* Set output original size */ + if (ctx->out_path == GSC_DMA) { + cfg = GSC_DSTIMG_OFFSET_X(frame->crop.left); + cfg |= GSC_DSTIMG_OFFSET_Y(frame->crop.top); + writel(cfg, dev->regs + GSC_DSTIMG_OFFSET); + + cfg = GSC_DSTIMG_WIDTH(frame->f_width); + cfg |= GSC_DSTIMG_HEIGHT(frame->f_height); + writel(cfg, dev->regs + GSC_DSTIMG_SIZE); + } + + /* Set output scaled size */ + if (ctx->gsc_ctrls.rotate->val == 90 || + ctx->gsc_ctrls.rotate->val == 270) { + cfg = GSC_SCALED_WIDTH(frame->crop.height); + cfg |= GSC_SCALED_HEIGHT(frame->crop.width); + } else { + cfg = GSC_SCALED_WIDTH(frame->crop.width); + cfg |= GSC_SCALED_HEIGHT(frame->crop.height); + } + writel(cfg, dev->regs + GSC_SCALED_SIZE); +} + +void gsc_hw_set_out_image_rgb(struct gsc_ctx *ctx) +{ + struct gsc_dev *dev = ctx->gsc_dev; + struct gsc_frame *frame = &ctx->d_frame; + u32 cfg; + + cfg = readl(dev->regs + GSC_OUT_CON); + if (frame->colorspace == V4L2_COLORSPACE_REC709) + cfg |= GSC_OUT_RGB_HD_WIDE; + else + cfg |= GSC_OUT_RGB_SD_WIDE; + + if (frame->fmt->pixelformat == V4L2_PIX_FMT_RGB565X) + cfg |= GSC_OUT_RGB565; + else if (frame->fmt->pixelformat == V4L2_PIX_FMT_RGB32) + cfg |= GSC_OUT_XRGB8888; + + writel(cfg, dev->regs + GSC_OUT_CON); +} + +void gsc_hw_set_out_image_format(struct gsc_ctx *ctx) +{ + struct gsc_dev *dev = ctx->gsc_dev; + struct gsc_frame *frame = &ctx->d_frame; + u32 i, depth = 0; + u32 cfg; + + cfg = readl(dev->regs + GSC_OUT_CON); + cfg &= ~(GSC_OUT_RGB_TYPE_MASK | GSC_OUT_YUV422_1P_ORDER_MASK | + GSC_OUT_CHROMA_ORDER_MASK | GSC_OUT_FORMAT_MASK | + GSC_OUT_TILE_TYPE_MASK | GSC_OUT_TILE_MODE); + writel(cfg, dev->regs + GSC_OUT_CON); + + if (is_rgb(frame->fmt->color)) { + gsc_hw_set_out_image_rgb(ctx); + return; + } + + if (ctx->out_path != GSC_DMA) { + cfg |= GSC_OUT_YUV444; + goto end_set; + } + + for (i = 0; i < frame->fmt->num_planes; i++) + depth += frame->fmt->depth[i]; + + switch (frame->fmt->num_comp) { + case 1: + cfg |= GSC_OUT_YUV422_1P; + if (frame->fmt->yorder == GSC_LSB_Y) + cfg |= GSC_OUT_YUV422_1P_ORDER_LSB_Y; + else + cfg |= GSC_OUT_YUV422_1P_OEDER_LSB_C; + if (frame->fmt->corder == GSC_CBCR) + cfg |= GSC_OUT_CHROMA_ORDER_CBCR; + else + cfg |= GSC_OUT_CHROMA_ORDER_CRCB; + break; + case 2: + if (depth == 12) + cfg |= GSC_OUT_YUV420_2P; + else + cfg |= GSC_OUT_YUV422_2P; + if (frame->fmt->corder == GSC_CBCR) + cfg |= GSC_OUT_CHROMA_ORDER_CBCR; + else + cfg |= GSC_OUT_CHROMA_ORDER_CRCB; + break; + case 3: + cfg |= GSC_OUT_YUV420_3P; + break; + }; + +end_set: + writel(cfg, dev->regs + GSC_OUT_CON); +} + +void gsc_hw_set_prescaler(struct gsc_ctx *ctx) +{ + struct gsc_dev *dev = ctx->gsc_dev; + struct gsc_scaler *sc = &ctx->scaler; + u32 cfg; + + cfg = GSC_PRESC_SHFACTOR(sc->pre_shfactor); + cfg |= GSC_PRESC_H_RATIO(sc->pre_hratio); + cfg |= GSC_PRESC_V_RATIO(sc->pre_vratio); + writel(cfg, dev->regs + GSC_PRE_SCALE_RATIO); +} + +void gsc_hw_set_mainscaler(struct gsc_ctx *ctx) +{ + struct gsc_dev *dev = ctx->gsc_dev; + struct gsc_scaler *sc = &ctx->scaler; + u32 cfg; + + cfg = GSC_MAIN_H_RATIO_VALUE(sc->main_hratio); + writel(cfg, dev->regs + GSC_MAIN_H_RATIO); + + cfg = GSC_MAIN_V_RATIO_VALUE(sc->main_vratio); + writel(cfg, dev->regs + GSC_MAIN_V_RATIO); +} + +void gsc_hw_set_rotation(struct gsc_ctx *ctx) +{ + struct gsc_dev *dev = ctx->gsc_dev; + u32 cfg; + + cfg = readl(dev->regs + GSC_IN_CON); + cfg &= ~GSC_IN_ROT_MASK; + + switch (ctx->gsc_ctrls.rotate->val) { + case 270: + cfg |= GSC_IN_ROT_270; + break; + case 180: + cfg |= GSC_IN_ROT_180; + break; + case 90: + if (ctx->gsc_ctrls.hflip->val) + cfg |= GSC_IN_ROT_90_XFLIP; + else if (ctx->gsc_ctrls.vflip->val) + cfg |= GSC_IN_ROT_90_YFLIP; + else + cfg |= GSC_IN_ROT_90; + break; + case 0: + if (ctx->gsc_ctrls.hflip->val) + cfg |= GSC_IN_ROT_XFLIP; + else if (ctx->gsc_ctrls.vflip->val) + cfg |= GSC_IN_ROT_YFLIP; + } + + writel(cfg, dev->regs + GSC_IN_CON); +} + +void gsc_hw_set_global_alpha(struct gsc_ctx *ctx) +{ + struct gsc_dev *dev = ctx->gsc_dev; + struct gsc_frame *frame = &ctx->d_frame; + u32 cfg; + + if (!is_rgb(frame->fmt->color)) { + pr_debug("Not a RGB format"); + return; + } + + cfg = readl(dev->regs + GSC_OUT_CON); + cfg &= ~GSC_OUT_GLOBAL_ALPHA_MASK; + + cfg |= GSC_OUT_GLOBAL_ALPHA(ctx->gsc_ctrls.global_alpha->val); + writel(cfg, dev->regs + GSC_OUT_CON); +} + +void gsc_hw_set_sfr_update(struct gsc_ctx *ctx) +{ + struct gsc_dev *dev = ctx->gsc_dev; + u32 cfg; + + cfg = readl(dev->regs + GSC_ENABLE); + cfg |= GSC_ENABLE_SFR_UPDATE; + writel(cfg, dev->regs + GSC_ENABLE); +} diff --git a/drivers/media/platform/exynos-gsc/gsc-regs.h b/drivers/media/platform/exynos-gsc/gsc-regs.h new file mode 100644 index 000000000000..533e9947a925 --- /dev/null +++ b/drivers/media/platform/exynos-gsc/gsc-regs.h @@ -0,0 +1,172 @@ +/* + * Copyright (c) 2011 - 2012 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * Register definition file for Samsung G-Scaler driver + * + * 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 REGS_GSC_H_ +#define REGS_GSC_H_ + +/* G-Scaler enable */ +#define GSC_ENABLE 0x00 +#define GSC_ENABLE_OP_STATUS (1 << 2) +#define GSC_ENABLE_SFR_UPDATE (1 << 1) +#define GSC_ENABLE_ON (1 << 0) + +/* G-Scaler S/W reset */ +#define GSC_SW_RESET 0x04 +#define GSC_SW_RESET_SRESET (1 << 0) + +/* G-Scaler IRQ */ +#define GSC_IRQ 0x08 +#define GSC_IRQ_STATUS_OR_IRQ (1 << 17) +#define GSC_IRQ_STATUS_FRM_DONE_IRQ (1 << 16) +#define GSC_IRQ_FRMDONE_MASK (1 << 1) +#define GSC_IRQ_ENABLE (1 << 0) + +/* G-Scaler input control */ +#define GSC_IN_CON 0x10 +#define GSC_IN_ROT_MASK (7 << 16) +#define GSC_IN_ROT_270 (7 << 16) +#define GSC_IN_ROT_90_YFLIP (6 << 16) +#define GSC_IN_ROT_90_XFLIP (5 << 16) +#define GSC_IN_ROT_90 (4 << 16) +#define GSC_IN_ROT_180 (3 << 16) +#define GSC_IN_ROT_YFLIP (2 << 16) +#define GSC_IN_ROT_XFLIP (1 << 16) +#define GSC_IN_RGB_TYPE_MASK (3 << 14) +#define GSC_IN_RGB_HD_WIDE (3 << 14) +#define GSC_IN_RGB_HD_NARROW (2 << 14) +#define GSC_IN_RGB_SD_WIDE (1 << 14) +#define GSC_IN_RGB_SD_NARROW (0 << 14) +#define GSC_IN_YUV422_1P_ORDER_MASK (1 << 13) +#define GSC_IN_YUV422_1P_ORDER_LSB_Y (0 << 13) +#define GSC_IN_YUV422_1P_OEDER_LSB_C (1 << 13) +#define GSC_IN_CHROMA_ORDER_MASK (1 << 12) +#define GSC_IN_CHROMA_ORDER_CBCR (0 << 12) +#define GSC_IN_CHROMA_ORDER_CRCB (1 << 12) +#define GSC_IN_FORMAT_MASK (7 << 8) +#define GSC_IN_XRGB8888 (0 << 8) +#define GSC_IN_RGB565 (1 << 8) +#define GSC_IN_YUV420_2P (2 << 8) +#define GSC_IN_YUV420_3P (3 << 8) +#define GSC_IN_YUV422_1P (4 << 8) +#define GSC_IN_YUV422_2P (5 << 8) +#define GSC_IN_YUV422_3P (6 << 8) +#define GSC_IN_TILE_TYPE_MASK (1 << 4) +#define GSC_IN_TILE_C_16x8 (0 << 4) +#define GSC_IN_TILE_MODE (1 << 3) +#define GSC_IN_LOCAL_SEL_MASK (3 << 1) +#define GSC_IN_PATH_MASK (1 << 0) +#define GSC_IN_PATH_MEMORY (0 << 0) + +/* G-Scaler source image size */ +#define GSC_SRCIMG_SIZE 0x14 +#define GSC_SRCIMG_HEIGHT(x) ((x) << 16) +#define GSC_SRCIMG_WIDTH(x) ((x) << 0) + +/* G-Scaler source image offset */ +#define GSC_SRCIMG_OFFSET 0x18 +#define GSC_SRCIMG_OFFSET_Y(x) ((x) << 16) +#define GSC_SRCIMG_OFFSET_X(x) ((x) << 0) + +/* G-Scaler cropped source image size */ +#define GSC_CROPPED_SIZE 0x1c +#define GSC_CROPPED_HEIGHT(x) ((x) << 16) +#define GSC_CROPPED_WIDTH(x) ((x) << 0) + +/* G-Scaler output control */ +#define GSC_OUT_CON 0x20 +#define GSC_OUT_GLOBAL_ALPHA_MASK (0xff << 24) +#define GSC_OUT_GLOBAL_ALPHA(x) ((x) << 24) +#define GSC_OUT_RGB_TYPE_MASK (3 << 10) +#define GSC_OUT_RGB_HD_NARROW (3 << 10) +#define GSC_OUT_RGB_HD_WIDE (2 << 10) +#define GSC_OUT_RGB_SD_NARROW (1 << 10) +#define GSC_OUT_RGB_SD_WIDE (0 << 10) +#define GSC_OUT_YUV422_1P_ORDER_MASK (1 << 9) +#define GSC_OUT_YUV422_1P_ORDER_LSB_Y (0 << 9) +#define GSC_OUT_YUV422_1P_OEDER_LSB_C (1 << 9) +#define GSC_OUT_CHROMA_ORDER_MASK (1 << 8) +#define GSC_OUT_CHROMA_ORDER_CBCR (0 << 8) +#define GSC_OUT_CHROMA_ORDER_CRCB (1 << 8) +#define GSC_OUT_FORMAT_MASK (7 << 4) +#define GSC_OUT_XRGB8888 (0 << 4) +#define GSC_OUT_RGB565 (1 << 4) +#define GSC_OUT_YUV420_2P (2 << 4) +#define GSC_OUT_YUV420_3P (3 << 4) +#define GSC_OUT_YUV422_1P (4 << 4) +#define GSC_OUT_YUV422_2P (5 << 4) +#define GSC_OUT_YUV444 (7 << 4) +#define GSC_OUT_TILE_TYPE_MASK (1 << 2) +#define GSC_OUT_TILE_C_16x8 (0 << 2) +#define GSC_OUT_TILE_MODE (1 << 1) +#define GSC_OUT_PATH_MASK (1 << 0) +#define GSC_OUT_PATH_LOCAL (1 << 0) +#define GSC_OUT_PATH_MEMORY (0 << 0) + +/* G-Scaler scaled destination image size */ +#define GSC_SCALED_SIZE 0x24 +#define GSC_SCALED_HEIGHT(x) ((x) << 16) +#define GSC_SCALED_WIDTH(x) ((x) << 0) + +/* G-Scaler pre scale ratio */ +#define GSC_PRE_SCALE_RATIO 0x28 +#define GSC_PRESC_SHFACTOR(x) ((x) << 28) +#define GSC_PRESC_V_RATIO(x) ((x) << 16) +#define GSC_PRESC_H_RATIO(x) ((x) << 0) + +/* G-Scaler main scale horizontal ratio */ +#define GSC_MAIN_H_RATIO 0x2c +#define GSC_MAIN_H_RATIO_VALUE(x) ((x) << 0) + +/* G-Scaler main scale vertical ratio */ +#define GSC_MAIN_V_RATIO 0x30 +#define GSC_MAIN_V_RATIO_VALUE(x) ((x) << 0) + +/* G-Scaler destination image size */ +#define GSC_DSTIMG_SIZE 0x40 +#define GSC_DSTIMG_HEIGHT(x) ((x) << 16) +#define GSC_DSTIMG_WIDTH(x) ((x) << 0) + +/* G-Scaler destination image offset */ +#define GSC_DSTIMG_OFFSET 0x44 +#define GSC_DSTIMG_OFFSET_Y(x) ((x) << 16) +#define GSC_DSTIMG_OFFSET_X(x) ((x) << 0) + +/* G-Scaler input y address mask */ +#define GSC_IN_BASE_ADDR_Y_MASK 0x4c +/* G-Scaler input y base address */ +#define GSC_IN_BASE_ADDR_Y(n) (0x50 + (n) * 0x4) + +/* G-Scaler input cb address mask */ +#define GSC_IN_BASE_ADDR_CB_MASK 0x7c +/* G-Scaler input cb base address */ +#define GSC_IN_BASE_ADDR_CB(n) (0x80 + (n) * 0x4) + +/* G-Scaler input cr address mask */ +#define GSC_IN_BASE_ADDR_CR_MASK 0xac +/* G-Scaler input cr base address */ +#define GSC_IN_BASE_ADDR_CR(n) (0xb0 + (n) * 0x4) + +/* G-Scaler output y address mask */ +#define GSC_OUT_BASE_ADDR_Y_MASK 0x10c +/* G-Scaler output y base address */ +#define GSC_OUT_BASE_ADDR_Y(n) (0x110 + (n) * 0x4) + +/* G-Scaler output cb address mask */ +#define GSC_OUT_BASE_ADDR_CB_MASK 0x15c +/* G-Scaler output cb base address */ +#define GSC_OUT_BASE_ADDR_CB(n) (0x160 + (n) * 0x4) + +/* G-Scaler output cr address mask */ +#define GSC_OUT_BASE_ADDR_CR_MASK 0x1ac +/* G-Scaler output cr base address */ +#define GSC_OUT_BASE_ADDR_CR(n) (0x1b0 + (n) * 0x4) + +#endif /* REGS_GSC_H_ */ diff --git a/drivers/media/video/fsl-viu.c b/drivers/media/platform/fsl-viu.c index 777486f7cadb..897250b88647 100644 --- a/drivers/media/video/fsl-viu.c +++ b/drivers/media/platform/fsl-viu.c @@ -860,7 +860,7 @@ int vidioc_g_fbuf(struct file *file, void *priv, struct v4l2_framebuffer *arg) return 0; } -int vidioc_s_fbuf(struct file *file, void *priv, struct v4l2_framebuffer *arg) +int vidioc_s_fbuf(struct file *file, void *priv, const struct v4l2_framebuffer *arg) { struct viu_fh *fh = priv; struct viu_dev *dev = fh->dev; @@ -1279,10 +1279,16 @@ static int viu_open(struct file *file) dprintk(1, "open minor=%d type=%s users=%d\n", minor, v4l2_type_names[V4L2_BUF_TYPE_VIDEO_CAPTURE], dev->users); + if (mutex_lock_interruptible(&dev->lock)) { + dev->users--; + return -ERESTARTSYS; + } + /* allocate and initialize per filehandle data */ fh = kzalloc(sizeof(*fh), GFP_KERNEL); if (!fh) { dev->users--; + mutex_unlock(&dev->lock); return -ENOMEM; } @@ -1325,6 +1331,7 @@ static int viu_open(struct file *file) fh->type, V4L2_FIELD_INTERLACED, sizeof(struct viu_buf), fh, &fh->dev->lock); + mutex_unlock(&dev->lock); return 0; } @@ -1340,9 +1347,12 @@ static ssize_t viu_read(struct file *file, char __user *data, size_t count, dev->ovenable = 0; if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { + if (mutex_lock_interruptible(&dev->lock)) + return -ERESTARTSYS; viu_start_dma(dev); ret = videobuf_read_stream(&fh->vb_vidq, data, count, ppos, 0, file->f_flags & O_NONBLOCK); + mutex_unlock(&dev->lock); return ret; } return 0; @@ -1352,11 +1362,16 @@ static unsigned int viu_poll(struct file *file, struct poll_table_struct *wait) { struct viu_fh *fh = file->private_data; struct videobuf_queue *q = &fh->vb_vidq; + struct viu_dev *dev = fh->dev; + unsigned int res; if (V4L2_BUF_TYPE_VIDEO_CAPTURE != fh->type) return POLLERR; - return videobuf_poll_stream(file, q, wait); + mutex_lock(&dev->lock); + res = videobuf_poll_stream(file, q, wait); + mutex_unlock(&dev->lock); + return res; } static int viu_release(struct file *file) @@ -1365,9 +1380,11 @@ static int viu_release(struct file *file) struct viu_dev *dev = fh->dev; int minor = video_devdata(file)->minor; + mutex_lock(&dev->lock); viu_stop_dma(dev); videobuf_stop(&fh->vb_vidq); videobuf_mmap_free(&fh->vb_vidq); + mutex_unlock(&dev->lock); kfree(fh); @@ -1394,11 +1411,15 @@ void viu_reset(struct viu_reg *reg) static int viu_mmap(struct file *file, struct vm_area_struct *vma) { struct viu_fh *fh = file->private_data; + struct viu_dev *dev = fh->dev; int ret; dprintk(1, "mmap called, vma=0x%08lx\n", (unsigned long)vma); + if (mutex_lock_interruptible(&dev->lock)) + return -ERESTARTSYS; ret = videobuf_mmap_mapper(&fh->vb_vidq, vma); + mutex_unlock(&dev->lock); dprintk(1, "vma start=0x%08lx, size=%ld, ret=%d\n", (unsigned long)vma->vm_start, @@ -1544,10 +1565,6 @@ static int __devinit viu_of_probe(struct platform_device *op) /* initialize locks */ mutex_init(&viu_dev->lock); - /* Locking in file operations other than ioctl should be done - by the driver, not the V4L2 core. - This driver needs auditing so that this flag can be removed. */ - set_bit(V4L2_FL_LOCK_ALL_FOPS, &viu_dev->vdev->flags); viu_dev->vdev->lock = &viu_dev->lock; spin_lock_init(&viu_dev->slock); diff --git a/drivers/media/video/indycam.c b/drivers/media/platform/indycam.c index 548236333cce..548236333cce 100644 --- a/drivers/media/video/indycam.c +++ b/drivers/media/platform/indycam.c diff --git a/drivers/media/video/indycam.h b/drivers/media/platform/indycam.h index 881f21c474c4..881f21c474c4 100644 --- a/drivers/media/video/indycam.h +++ b/drivers/media/platform/indycam.h diff --git a/drivers/media/platform/m2m-deinterlace.c b/drivers/media/platform/m2m-deinterlace.c new file mode 100644 index 000000000000..45164c4f8452 --- /dev/null +++ b/drivers/media/platform/m2m-deinterlace.c @@ -0,0 +1,1124 @@ +/* + * V4L2 deinterlacing support. + * + * Copyright (c) 2012 Vista Silicon S.L. + * Javier Martin <javier.martin@vista-silicon.com> + * + * 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 <linux/module.h> +#include <linux/slab.h> +#include <linux/interrupt.h> +#include <linux/dmaengine.h> +#include <linux/platform_device.h> + +#include <media/v4l2-mem2mem.h> +#include <media/v4l2-device.h> +#include <media/v4l2-ioctl.h> +#include <media/videobuf2-dma-contig.h> + +#define MEM2MEM_TEST_MODULE_NAME "mem2mem-deinterlace" + +MODULE_DESCRIPTION("mem2mem device which supports deinterlacing using dmaengine"); +MODULE_AUTHOR("Javier Martin <javier.martin@vista-silicon.com"); +MODULE_LICENSE("GPL"); +MODULE_VERSION("0.0.1"); + +static bool debug = true; +module_param(debug, bool, 0644); + +/* Flags that indicate a format can be used for capture/output */ +#define MEM2MEM_CAPTURE (1 << 0) +#define MEM2MEM_OUTPUT (1 << 1) + +#define MEM2MEM_NAME "m2m-deinterlace" + +#define dprintk(dev, fmt, arg...) \ + v4l2_dbg(1, debug, &dev->v4l2_dev, "%s: " fmt, __func__, ## arg) + +struct deinterlace_fmt { + char *name; + u32 fourcc; + /* Types the format can be used for */ + u32 types; +}; + +static struct deinterlace_fmt formats[] = { + { + .name = "YUV 4:2:0 Planar", + .fourcc = V4L2_PIX_FMT_YUV420, + .types = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT, + }, + { + .name = "YUYV 4:2:2", + .fourcc = V4L2_PIX_FMT_YUYV, + .types = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT, + }, +}; + +#define NUM_FORMATS ARRAY_SIZE(formats) + +/* Per-queue, driver-specific private data */ +struct deinterlace_q_data { + unsigned int width; + unsigned int height; + unsigned int sizeimage; + struct deinterlace_fmt *fmt; + enum v4l2_field field; +}; + +enum { + V4L2_M2M_SRC = 0, + V4L2_M2M_DST = 1, +}; + +enum { + YUV420_DMA_Y_ODD, + YUV420_DMA_Y_EVEN, + YUV420_DMA_U_ODD, + YUV420_DMA_U_EVEN, + YUV420_DMA_V_ODD, + YUV420_DMA_V_EVEN, + YUV420_DMA_Y_ODD_DOUBLING, + YUV420_DMA_U_ODD_DOUBLING, + YUV420_DMA_V_ODD_DOUBLING, + YUYV_DMA_ODD, + YUYV_DMA_EVEN, + YUYV_DMA_EVEN_DOUBLING, +}; + +/* Source and destination queue data */ +static struct deinterlace_q_data q_data[2]; + +static struct deinterlace_q_data *get_q_data(enum v4l2_buf_type type) +{ + switch (type) { + case V4L2_BUF_TYPE_VIDEO_OUTPUT: + return &q_data[V4L2_M2M_SRC]; + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + return &q_data[V4L2_M2M_DST]; + default: + BUG(); + } + return NULL; +} + +static struct deinterlace_fmt *find_format(struct v4l2_format *f) +{ + struct deinterlace_fmt *fmt; + unsigned int k; + + for (k = 0; k < NUM_FORMATS; k++) { + fmt = &formats[k]; + if ((fmt->types & f->type) && + (fmt->fourcc == f->fmt.pix.pixelformat)) + break; + } + + if (k == NUM_FORMATS) + return NULL; + + return &formats[k]; +} + +struct deinterlace_dev { + struct v4l2_device v4l2_dev; + struct video_device *vfd; + + atomic_t busy; + struct mutex dev_mutex; + spinlock_t irqlock; + + struct dma_chan *dma_chan; + + struct v4l2_m2m_dev *m2m_dev; + struct vb2_alloc_ctx *alloc_ctx; +}; + +struct deinterlace_ctx { + struct deinterlace_dev *dev; + + /* Abort requested by m2m */ + int aborting; + enum v4l2_colorspace colorspace; + dma_cookie_t cookie; + struct v4l2_m2m_ctx *m2m_ctx; + struct dma_interleaved_template *xt; +}; + +/* + * mem2mem callbacks + */ +static int deinterlace_job_ready(void *priv) +{ + struct deinterlace_ctx *ctx = priv; + struct deinterlace_dev *pcdev = ctx->dev; + + if ((v4l2_m2m_num_src_bufs_ready(ctx->m2m_ctx) > 0) + && (v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx) > 0) + && (atomic_read(&ctx->dev->busy) == 0)) { + dprintk(pcdev, "Task ready\n"); + return 1; + } + + dprintk(pcdev, "Task not ready to run\n"); + + return 0; +} + +static void deinterlace_job_abort(void *priv) +{ + struct deinterlace_ctx *ctx = priv; + struct deinterlace_dev *pcdev = ctx->dev; + + ctx->aborting = 1; + + dprintk(pcdev, "Aborting task\n"); + + v4l2_m2m_job_finish(pcdev->m2m_dev, ctx->m2m_ctx); +} + +static void deinterlace_lock(void *priv) +{ + struct deinterlace_ctx *ctx = priv; + struct deinterlace_dev *pcdev = ctx->dev; + mutex_lock(&pcdev->dev_mutex); +} + +static void deinterlace_unlock(void *priv) +{ + struct deinterlace_ctx *ctx = priv; + struct deinterlace_dev *pcdev = ctx->dev; + mutex_unlock(&pcdev->dev_mutex); +} + +static void dma_callback(void *data) +{ + struct deinterlace_ctx *curr_ctx = data; + struct deinterlace_dev *pcdev = curr_ctx->dev; + struct vb2_buffer *src_vb, *dst_vb; + + atomic_set(&pcdev->busy, 0); + + src_vb = v4l2_m2m_src_buf_remove(curr_ctx->m2m_ctx); + dst_vb = v4l2_m2m_dst_buf_remove(curr_ctx->m2m_ctx); + + v4l2_m2m_buf_done(src_vb, VB2_BUF_STATE_DONE); + v4l2_m2m_buf_done(dst_vb, VB2_BUF_STATE_DONE); + + v4l2_m2m_job_finish(pcdev->m2m_dev, curr_ctx->m2m_ctx); + + dprintk(pcdev, "dma transfers completed.\n"); +} + +static void deinterlace_issue_dma(struct deinterlace_ctx *ctx, int op, + int do_callback) +{ + struct deinterlace_q_data *s_q_data, *d_q_data; + struct vb2_buffer *src_buf, *dst_buf; + struct deinterlace_dev *pcdev = ctx->dev; + struct dma_chan *chan = pcdev->dma_chan; + struct dma_device *dmadev = chan->device; + struct dma_async_tx_descriptor *tx; + unsigned int s_width, s_height; + unsigned int d_width, d_height; + unsigned int d_size, s_size; + dma_addr_t p_in, p_out; + enum dma_ctrl_flags flags; + + src_buf = v4l2_m2m_next_src_buf(ctx->m2m_ctx); + dst_buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx); + + s_q_data = get_q_data(V4L2_BUF_TYPE_VIDEO_OUTPUT); + s_width = s_q_data->width; + s_height = s_q_data->height; + s_size = s_width * s_height; + + d_q_data = get_q_data(V4L2_BUF_TYPE_VIDEO_CAPTURE); + d_width = d_q_data->width; + d_height = d_q_data->height; + d_size = d_width * d_height; + + p_in = (dma_addr_t)vb2_dma_contig_plane_dma_addr(src_buf, 0); + p_out = (dma_addr_t)vb2_dma_contig_plane_dma_addr(dst_buf, 0); + if (!p_in || !p_out) { + v4l2_err(&pcdev->v4l2_dev, + "Acquiring kernel pointers to buffers failed\n"); + return; + } + + switch (op) { + case YUV420_DMA_Y_ODD: + ctx->xt->numf = s_height / 2; + ctx->xt->sgl[0].size = s_width; + ctx->xt->sgl[0].icg = s_width; + ctx->xt->src_start = p_in; + ctx->xt->dst_start = p_out; + break; + case YUV420_DMA_Y_EVEN: + ctx->xt->numf = s_height / 2; + ctx->xt->sgl[0].size = s_width; + ctx->xt->sgl[0].icg = s_width; + ctx->xt->src_start = p_in + s_size / 2; + ctx->xt->dst_start = p_out + s_width; + break; + case YUV420_DMA_U_ODD: + ctx->xt->numf = s_height / 4; + ctx->xt->sgl[0].size = s_width / 2; + ctx->xt->sgl[0].icg = s_width / 2; + ctx->xt->src_start = p_in + s_size; + ctx->xt->dst_start = p_out + s_size; + break; + case YUV420_DMA_U_EVEN: + ctx->xt->numf = s_height / 4; + ctx->xt->sgl[0].size = s_width / 2; + ctx->xt->sgl[0].icg = s_width / 2; + ctx->xt->src_start = p_in + (9 * s_size) / 8; + ctx->xt->dst_start = p_out + s_size + s_width / 2; + break; + case YUV420_DMA_V_ODD: + ctx->xt->numf = s_height / 4; + ctx->xt->sgl[0].size = s_width / 2; + ctx->xt->sgl[0].icg = s_width / 2; + ctx->xt->src_start = p_in + (5 * s_size) / 4; + ctx->xt->dst_start = p_out + (5 * s_size) / 4; + break; + case YUV420_DMA_V_EVEN: + ctx->xt->numf = s_height / 4; + ctx->xt->sgl[0].size = s_width / 2; + ctx->xt->sgl[0].icg = s_width / 2; + ctx->xt->src_start = p_in + (11 * s_size) / 8; + ctx->xt->dst_start = p_out + (5 * s_size) / 4 + s_width / 2; + break; + case YUV420_DMA_Y_ODD_DOUBLING: + ctx->xt->numf = s_height / 2; + ctx->xt->sgl[0].size = s_width; + ctx->xt->sgl[0].icg = s_width; + ctx->xt->src_start = p_in; + ctx->xt->dst_start = p_out + s_width; + break; + case YUV420_DMA_U_ODD_DOUBLING: + ctx->xt->numf = s_height / 4; + ctx->xt->sgl[0].size = s_width / 2; + ctx->xt->sgl[0].icg = s_width / 2; + ctx->xt->src_start = p_in + s_size; + ctx->xt->dst_start = p_out + s_size + s_width / 2; + break; + case YUV420_DMA_V_ODD_DOUBLING: + ctx->xt->numf = s_height / 4; + ctx->xt->sgl[0].size = s_width / 2; + ctx->xt->sgl[0].icg = s_width / 2; + ctx->xt->src_start = p_in + (5 * s_size) / 4; + ctx->xt->dst_start = p_out + (5 * s_size) / 4 + s_width / 2; + break; + case YUYV_DMA_ODD: + ctx->xt->numf = s_height / 2; + ctx->xt->sgl[0].size = s_width * 2; + ctx->xt->sgl[0].icg = s_width * 2; + ctx->xt->src_start = p_in; + ctx->xt->dst_start = p_out; + break; + case YUYV_DMA_EVEN: + ctx->xt->numf = s_height / 2; + ctx->xt->sgl[0].size = s_width * 2; + ctx->xt->sgl[0].icg = s_width * 2; + ctx->xt->src_start = p_in + s_size; + ctx->xt->dst_start = p_out + s_width * 2; + break; + case YUYV_DMA_EVEN_DOUBLING: + default: + ctx->xt->numf = s_height / 2; + ctx->xt->sgl[0].size = s_width * 2; + ctx->xt->sgl[0].icg = s_width * 2; + ctx->xt->src_start = p_in; + ctx->xt->dst_start = p_out + s_width * 2; + break; + } + + /* Common parameters for al transfers */ + ctx->xt->frame_size = 1; + ctx->xt->dir = DMA_MEM_TO_MEM; + ctx->xt->src_sgl = false; + ctx->xt->dst_sgl = true; + flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT | + DMA_COMPL_SKIP_DEST_UNMAP | DMA_COMPL_SKIP_SRC_UNMAP; + + tx = dmadev->device_prep_interleaved_dma(chan, ctx->xt, flags); + if (tx == NULL) { + v4l2_warn(&pcdev->v4l2_dev, "DMA interleaved prep error\n"); + return; + } + + if (do_callback) { + tx->callback = dma_callback; + tx->callback_param = ctx; + } + + ctx->cookie = dmaengine_submit(tx); + if (dma_submit_error(ctx->cookie)) { + v4l2_warn(&pcdev->v4l2_dev, + "DMA submit error %d with src=0x%x dst=0x%x len=0x%x\n", + ctx->cookie, (unsigned)p_in, (unsigned)p_out, + s_size * 3/2); + return; + } + + dma_async_issue_pending(chan); +} + +static void deinterlace_device_run(void *priv) +{ + struct deinterlace_ctx *ctx = priv; + struct deinterlace_q_data *dst_q_data; + + atomic_set(&ctx->dev->busy, 1); + + dprintk(ctx->dev, "%s: DMA try issue.\n", __func__); + + dst_q_data = get_q_data(V4L2_BUF_TYPE_VIDEO_CAPTURE); + + /* + * 4 possible field conversions are possible at the moment: + * V4L2_FIELD_SEQ_TB --> V4L2_FIELD_INTERLACED_TB: + * two separate fields in the same input buffer are interlaced + * in the output buffer using weaving. Top field comes first. + * V4L2_FIELD_SEQ_TB --> V4L2_FIELD_NONE: + * top field from the input buffer is copied to the output buffer + * using line doubling. Bottom field from the input buffer is discarded. + * V4L2_FIELD_SEQ_BT --> V4L2_FIELD_INTERLACED_BT: + * two separate fields in the same input buffer are interlaced + * in the output buffer using weaving. Bottom field comes first. + * V4L2_FIELD_SEQ_BT --> V4L2_FIELD_NONE: + * bottom field from the input buffer is copied to the output buffer + * using line doubling. Top field from the input buffer is discarded. + */ + switch (dst_q_data->fmt->fourcc) { + case V4L2_PIX_FMT_YUV420: + switch (dst_q_data->field) { + case V4L2_FIELD_INTERLACED_TB: + case V4L2_FIELD_INTERLACED_BT: + dprintk(ctx->dev, "%s: yuv420 interlaced tb.\n", + __func__); + deinterlace_issue_dma(ctx, YUV420_DMA_Y_ODD, 0); + deinterlace_issue_dma(ctx, YUV420_DMA_Y_EVEN, 0); + deinterlace_issue_dma(ctx, YUV420_DMA_U_ODD, 0); + deinterlace_issue_dma(ctx, YUV420_DMA_U_EVEN, 0); + deinterlace_issue_dma(ctx, YUV420_DMA_V_ODD, 0); + deinterlace_issue_dma(ctx, YUV420_DMA_V_EVEN, 1); + break; + case V4L2_FIELD_NONE: + default: + dprintk(ctx->dev, "%s: yuv420 interlaced line doubling.\n", + __func__); + deinterlace_issue_dma(ctx, YUV420_DMA_Y_ODD, 0); + deinterlace_issue_dma(ctx, YUV420_DMA_Y_ODD_DOUBLING, 0); + deinterlace_issue_dma(ctx, YUV420_DMA_U_ODD, 0); + deinterlace_issue_dma(ctx, YUV420_DMA_U_ODD_DOUBLING, 0); + deinterlace_issue_dma(ctx, YUV420_DMA_V_ODD, 0); + deinterlace_issue_dma(ctx, YUV420_DMA_V_ODD_DOUBLING, 1); + break; + } + break; + case V4L2_PIX_FMT_YUYV: + default: + switch (dst_q_data->field) { + case V4L2_FIELD_INTERLACED_TB: + case V4L2_FIELD_INTERLACED_BT: + dprintk(ctx->dev, "%s: yuyv interlaced_tb.\n", + __func__); + deinterlace_issue_dma(ctx, YUYV_DMA_ODD, 0); + deinterlace_issue_dma(ctx, YUYV_DMA_EVEN, 1); + break; + case V4L2_FIELD_NONE: + default: + dprintk(ctx->dev, "%s: yuyv interlaced line doubling.\n", + __func__); + deinterlace_issue_dma(ctx, YUYV_DMA_ODD, 0); + deinterlace_issue_dma(ctx, YUYV_DMA_EVEN_DOUBLING, 1); + break; + } + break; + } + + dprintk(ctx->dev, "%s: DMA issue done.\n", __func__); +} + +/* + * video ioctls + */ +static int vidioc_querycap(struct file *file, void *priv, + struct v4l2_capability *cap) +{ + strlcpy(cap->driver, MEM2MEM_NAME, sizeof(cap->driver)); + strlcpy(cap->card, MEM2MEM_NAME, sizeof(cap->card)); + strlcpy(cap->bus_info, MEM2MEM_NAME, sizeof(cap->card)); + /* + * This is only a mem-to-mem video device. The capture and output + * device capability flags are left only for backward compatibility + * and are scheduled for removal. + */ + cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT | + V4L2_CAP_VIDEO_M2M | V4L2_CAP_STREAMING; + cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; + + return 0; +} + +static int enum_fmt(struct v4l2_fmtdesc *f, u32 type) +{ + int i, num; + struct deinterlace_fmt *fmt; + + num = 0; + + for (i = 0; i < NUM_FORMATS; ++i) { + if (formats[i].types & type) { + /* index-th format of type type found ? */ + if (num == f->index) + break; + /* Correct type but haven't reached our index yet, + * just increment per-type index */ + ++num; + } + } + + if (i < NUM_FORMATS) { + /* Format found */ + fmt = &formats[i]; + strlcpy(f->description, fmt->name, sizeof(f->description)); + f->pixelformat = fmt->fourcc; + return 0; + } + + /* Format not found */ + return -EINVAL; +} + +static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_fmtdesc *f) +{ + return enum_fmt(f, MEM2MEM_CAPTURE); +} + +static int vidioc_enum_fmt_vid_out(struct file *file, void *priv, + struct v4l2_fmtdesc *f) +{ + return enum_fmt(f, MEM2MEM_OUTPUT); +} + +static int vidioc_g_fmt(struct deinterlace_ctx *ctx, struct v4l2_format *f) +{ + struct vb2_queue *vq; + struct deinterlace_q_data *q_data; + + vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type); + if (!vq) + return -EINVAL; + + q_data = get_q_data(f->type); + + f->fmt.pix.width = q_data->width; + f->fmt.pix.height = q_data->height; + f->fmt.pix.field = q_data->field; + f->fmt.pix.pixelformat = q_data->fmt->fourcc; + + switch (q_data->fmt->fourcc) { + case V4L2_PIX_FMT_YUV420: + f->fmt.pix.bytesperline = q_data->width * 3 / 2; + break; + case V4L2_PIX_FMT_YUYV: + default: + f->fmt.pix.bytesperline = q_data->width * 2; + } + + f->fmt.pix.sizeimage = q_data->sizeimage; + f->fmt.pix.colorspace = ctx->colorspace; + + return 0; +} + +static int vidioc_g_fmt_vid_out(struct file *file, void *priv, + struct v4l2_format *f) +{ + return vidioc_g_fmt(priv, f); +} + +static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + return vidioc_g_fmt(priv, f); +} + +static int vidioc_try_fmt(struct v4l2_format *f, struct deinterlace_fmt *fmt) +{ + switch (f->fmt.pix.pixelformat) { + case V4L2_PIX_FMT_YUV420: + f->fmt.pix.bytesperline = f->fmt.pix.width * 3 / 2; + break; + case V4L2_PIX_FMT_YUYV: + default: + f->fmt.pix.bytesperline = f->fmt.pix.width * 2; + } + f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; + + return 0; +} + +static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct deinterlace_fmt *fmt; + struct deinterlace_ctx *ctx = priv; + + fmt = find_format(f); + if (!fmt || !(fmt->types & MEM2MEM_CAPTURE)) + f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUV420; + + f->fmt.pix.colorspace = ctx->colorspace; + + if (f->fmt.pix.field != V4L2_FIELD_INTERLACED_TB && + f->fmt.pix.field != V4L2_FIELD_INTERLACED_BT && + f->fmt.pix.field != V4L2_FIELD_NONE) + f->fmt.pix.field = V4L2_FIELD_INTERLACED_TB; + + return vidioc_try_fmt(f, fmt); +} + +static int vidioc_try_fmt_vid_out(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct deinterlace_fmt *fmt; + + fmt = find_format(f); + if (!fmt || !(fmt->types & MEM2MEM_OUTPUT)) + f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUV420; + + if (!f->fmt.pix.colorspace) + f->fmt.pix.colorspace = V4L2_COLORSPACE_REC709; + + if (f->fmt.pix.field != V4L2_FIELD_SEQ_TB && + f->fmt.pix.field != V4L2_FIELD_SEQ_BT) + f->fmt.pix.field = V4L2_FIELD_SEQ_TB; + + return vidioc_try_fmt(f, fmt); +} + +static int vidioc_s_fmt(struct deinterlace_ctx *ctx, struct v4l2_format *f) +{ + struct deinterlace_q_data *q_data; + struct vb2_queue *vq; + + vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type); + if (!vq) + return -EINVAL; + + q_data = get_q_data(f->type); + if (!q_data) + return -EINVAL; + + if (vb2_is_busy(vq)) { + v4l2_err(&ctx->dev->v4l2_dev, "%s queue busy\n", __func__); + return -EBUSY; + } + + q_data->fmt = find_format(f); + if (!q_data->fmt) { + v4l2_err(&ctx->dev->v4l2_dev, + "Couldn't set format type %d, wxh: %dx%d. fmt: %d, field: %d\n", + f->type, f->fmt.pix.width, f->fmt.pix.height, + f->fmt.pix.pixelformat, f->fmt.pix.field); + return -EINVAL; + } + + q_data->width = f->fmt.pix.width; + q_data->height = f->fmt.pix.height; + q_data->field = f->fmt.pix.field; + + switch (f->fmt.pix.pixelformat) { + case V4L2_PIX_FMT_YUV420: + f->fmt.pix.bytesperline = f->fmt.pix.width * 3 / 2; + q_data->sizeimage = (q_data->width * q_data->height * 3) / 2; + break; + case V4L2_PIX_FMT_YUYV: + default: + f->fmt.pix.bytesperline = f->fmt.pix.width * 2; + q_data->sizeimage = q_data->width * q_data->height * 2; + } + + dprintk(ctx->dev, + "Setting format for type %d, wxh: %dx%d, fmt: %d, field: %d\n", + f->type, q_data->width, q_data->height, q_data->fmt->fourcc, + q_data->field); + + return 0; +} + +static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + int ret; + + ret = vidioc_try_fmt_vid_cap(file, priv, f); + if (ret) + return ret; + return vidioc_s_fmt(priv, f); +} + +static int vidioc_s_fmt_vid_out(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct deinterlace_ctx *ctx = priv; + int ret; + + ret = vidioc_try_fmt_vid_out(file, priv, f); + if (ret) + return ret; + + ret = vidioc_s_fmt(priv, f); + if (!ret) + ctx->colorspace = f->fmt.pix.colorspace; + + return ret; +} + +static int vidioc_reqbufs(struct file *file, void *priv, + struct v4l2_requestbuffers *reqbufs) +{ + struct deinterlace_ctx *ctx = priv; + + return v4l2_m2m_reqbufs(file, ctx->m2m_ctx, reqbufs); +} + +static int vidioc_querybuf(struct file *file, void *priv, + struct v4l2_buffer *buf) +{ + struct deinterlace_ctx *ctx = priv; + + return v4l2_m2m_querybuf(file, ctx->m2m_ctx, buf); +} + +static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf) +{ + struct deinterlace_ctx *ctx = priv; + + return v4l2_m2m_qbuf(file, ctx->m2m_ctx, buf); +} + +static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf) +{ + struct deinterlace_ctx *ctx = priv; + + return v4l2_m2m_dqbuf(file, ctx->m2m_ctx, buf); +} + +static int vidioc_streamon(struct file *file, void *priv, + enum v4l2_buf_type type) +{ + struct deinterlace_q_data *s_q_data, *d_q_data; + struct deinterlace_ctx *ctx = priv; + + s_q_data = get_q_data(V4L2_BUF_TYPE_VIDEO_OUTPUT); + d_q_data = get_q_data(V4L2_BUF_TYPE_VIDEO_CAPTURE); + + /* Check that src and dst queues have the same pix format */ + if (s_q_data->fmt->fourcc != d_q_data->fmt->fourcc) { + v4l2_err(&ctx->dev->v4l2_dev, + "src and dst formats don't match.\n"); + return -EINVAL; + } + + /* Check that input and output deinterlacing types are compatible */ + switch (s_q_data->field) { + case V4L2_FIELD_SEQ_BT: + if (d_q_data->field != V4L2_FIELD_NONE && + d_q_data->field != V4L2_FIELD_INTERLACED_BT) { + v4l2_err(&ctx->dev->v4l2_dev, + "src and dst field conversion [(%d)->(%d)] not supported.\n", + s_q_data->field, d_q_data->field); + return -EINVAL; + } + break; + case V4L2_FIELD_SEQ_TB: + if (d_q_data->field != V4L2_FIELD_NONE && + d_q_data->field != V4L2_FIELD_INTERLACED_TB) { + v4l2_err(&ctx->dev->v4l2_dev, + "src and dst field conversion [(%d)->(%d)] not supported.\n", + s_q_data->field, d_q_data->field); + return -EINVAL; + } + break; + default: + return -EINVAL; + } + + return v4l2_m2m_streamon(file, ctx->m2m_ctx, type); +} + +static int vidioc_streamoff(struct file *file, void *priv, + enum v4l2_buf_type type) +{ + struct deinterlace_ctx *ctx = priv; + + return v4l2_m2m_streamoff(file, ctx->m2m_ctx, type); +} + +static const struct v4l2_ioctl_ops deinterlace_ioctl_ops = { + .vidioc_querycap = vidioc_querycap, + + .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, + .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, + .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, + .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, + + .vidioc_enum_fmt_vid_out = vidioc_enum_fmt_vid_out, + .vidioc_g_fmt_vid_out = vidioc_g_fmt_vid_out, + .vidioc_try_fmt_vid_out = vidioc_try_fmt_vid_out, + .vidioc_s_fmt_vid_out = vidioc_s_fmt_vid_out, + + .vidioc_reqbufs = vidioc_reqbufs, + .vidioc_querybuf = vidioc_querybuf, + + .vidioc_qbuf = vidioc_qbuf, + .vidioc_dqbuf = vidioc_dqbuf, + + .vidioc_streamon = vidioc_streamon, + .vidioc_streamoff = vidioc_streamoff, +}; + + +/* + * Queue operations + */ +struct vb2_dc_conf { + struct device *dev; +}; + +static int deinterlace_queue_setup(struct vb2_queue *vq, + const struct v4l2_format *fmt, + unsigned int *nbuffers, unsigned int *nplanes, + unsigned int sizes[], void *alloc_ctxs[]) +{ + struct deinterlace_ctx *ctx = vb2_get_drv_priv(vq); + struct deinterlace_q_data *q_data; + unsigned int size, count = *nbuffers; + + q_data = get_q_data(vq->type); + + switch (q_data->fmt->fourcc) { + case V4L2_PIX_FMT_YUV420: + size = q_data->width * q_data->height * 3 / 2; + break; + case V4L2_PIX_FMT_YUYV: + default: + size = q_data->width * q_data->height * 2; + } + + *nplanes = 1; + *nbuffers = count; + sizes[0] = size; + + alloc_ctxs[0] = ctx->dev->alloc_ctx; + + dprintk(ctx->dev, "get %d buffer(s) of size %d each.\n", count, size); + + return 0; +} + +static int deinterlace_buf_prepare(struct vb2_buffer *vb) +{ + struct deinterlace_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); + struct deinterlace_q_data *q_data; + + dprintk(ctx->dev, "type: %d\n", vb->vb2_queue->type); + + q_data = get_q_data(vb->vb2_queue->type); + + if (vb2_plane_size(vb, 0) < q_data->sizeimage) { + dprintk(ctx->dev, "%s data will not fit into plane (%lu < %lu)\n", + __func__, vb2_plane_size(vb, 0), (long)q_data->sizeimage); + return -EINVAL; + } + + vb2_set_plane_payload(vb, 0, q_data->sizeimage); + + return 0; +} + +static void deinterlace_buf_queue(struct vb2_buffer *vb) +{ + struct deinterlace_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); + v4l2_m2m_buf_queue(ctx->m2m_ctx, vb); +} + +static struct vb2_ops deinterlace_qops = { + .queue_setup = deinterlace_queue_setup, + .buf_prepare = deinterlace_buf_prepare, + .buf_queue = deinterlace_buf_queue, +}; + +static int queue_init(void *priv, struct vb2_queue *src_vq, + struct vb2_queue *dst_vq) +{ + struct deinterlace_ctx *ctx = priv; + int ret; + + src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; + src_vq->io_modes = VB2_MMAP | VB2_USERPTR; + src_vq->drv_priv = ctx; + src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); + src_vq->ops = &deinterlace_qops; + src_vq->mem_ops = &vb2_dma_contig_memops; + q_data[V4L2_M2M_SRC].fmt = &formats[0]; + q_data[V4L2_M2M_SRC].width = 640; + q_data[V4L2_M2M_SRC].height = 480; + q_data[V4L2_M2M_SRC].sizeimage = (640 * 480 * 3) / 2; + q_data[V4L2_M2M_SRC].field = V4L2_FIELD_SEQ_TB; + + ret = vb2_queue_init(src_vq); + if (ret) + return ret; + + dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + dst_vq->io_modes = VB2_MMAP | VB2_USERPTR; + dst_vq->drv_priv = ctx; + dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); + dst_vq->ops = &deinterlace_qops; + dst_vq->mem_ops = &vb2_dma_contig_memops; + q_data[V4L2_M2M_DST].fmt = &formats[0]; + q_data[V4L2_M2M_DST].width = 640; + q_data[V4L2_M2M_DST].height = 480; + q_data[V4L2_M2M_DST].sizeimage = (640 * 480 * 3) / 2; + q_data[V4L2_M2M_SRC].field = V4L2_FIELD_INTERLACED_TB; + + return vb2_queue_init(dst_vq); +} + +/* + * File operations + */ +static int deinterlace_open(struct file *file) +{ + struct deinterlace_dev *pcdev = video_drvdata(file); + struct deinterlace_ctx *ctx = NULL; + + ctx = kzalloc(sizeof *ctx, GFP_KERNEL); + if (!ctx) + return -ENOMEM; + + file->private_data = ctx; + ctx->dev = pcdev; + + ctx->m2m_ctx = v4l2_m2m_ctx_init(pcdev->m2m_dev, ctx, &queue_init); + if (IS_ERR(ctx->m2m_ctx)) { + int ret = PTR_ERR(ctx->m2m_ctx); + + kfree(ctx); + return ret; + } + + ctx->xt = kzalloc(sizeof(struct dma_async_tx_descriptor) + + sizeof(struct data_chunk), GFP_KERNEL); + if (!ctx->xt) { + int ret = PTR_ERR(ctx->xt); + + kfree(ctx); + return ret; + } + + ctx->colorspace = V4L2_COLORSPACE_REC709; + + dprintk(pcdev, "Created instance %p, m2m_ctx: %p\n", ctx, ctx->m2m_ctx); + + return 0; +} + +static int deinterlace_release(struct file *file) +{ + struct deinterlace_dev *pcdev = video_drvdata(file); + struct deinterlace_ctx *ctx = file->private_data; + + dprintk(pcdev, "Releasing instance %p\n", ctx); + + v4l2_m2m_ctx_release(ctx->m2m_ctx); + kfree(ctx->xt); + kfree(ctx); + + return 0; +} + +static unsigned int deinterlace_poll(struct file *file, + struct poll_table_struct *wait) +{ + struct deinterlace_ctx *ctx = file->private_data; + int ret; + + deinterlace_lock(ctx); + ret = v4l2_m2m_poll(file, ctx->m2m_ctx, wait); + deinterlace_unlock(ctx); + + return ret; +} + +static int deinterlace_mmap(struct file *file, struct vm_area_struct *vma) +{ + struct deinterlace_ctx *ctx = file->private_data; + + return v4l2_m2m_mmap(file, ctx->m2m_ctx, vma); +} + +static const struct v4l2_file_operations deinterlace_fops = { + .owner = THIS_MODULE, + .open = deinterlace_open, + .release = deinterlace_release, + .poll = deinterlace_poll, + .unlocked_ioctl = video_ioctl2, + .mmap = deinterlace_mmap, +}; + +static struct video_device deinterlace_videodev = { + .name = MEM2MEM_NAME, + .fops = &deinterlace_fops, + .ioctl_ops = &deinterlace_ioctl_ops, + .minor = -1, + .release = video_device_release, + .vfl_dir = VFL_DIR_M2M, +}; + +static struct v4l2_m2m_ops m2m_ops = { + .device_run = deinterlace_device_run, + .job_ready = deinterlace_job_ready, + .job_abort = deinterlace_job_abort, + .lock = deinterlace_lock, + .unlock = deinterlace_unlock, +}; + +static int deinterlace_probe(struct platform_device *pdev) +{ + struct deinterlace_dev *pcdev; + struct video_device *vfd; + dma_cap_mask_t mask; + int ret = 0; + + pcdev = kzalloc(sizeof *pcdev, GFP_KERNEL); + if (!pcdev) + return -ENOMEM; + + spin_lock_init(&pcdev->irqlock); + + dma_cap_zero(mask); + dma_cap_set(DMA_INTERLEAVE, mask); + pcdev->dma_chan = dma_request_channel(mask, NULL, pcdev); + if (!pcdev->dma_chan) + goto free_dev; + + if (!dma_has_cap(DMA_INTERLEAVE, pcdev->dma_chan->device->cap_mask)) { + v4l2_err(&pcdev->v4l2_dev, "DMA does not support INTERLEAVE\n"); + goto rel_dma; + } + + ret = v4l2_device_register(&pdev->dev, &pcdev->v4l2_dev); + if (ret) + goto rel_dma; + + atomic_set(&pcdev->busy, 0); + mutex_init(&pcdev->dev_mutex); + + vfd = video_device_alloc(); + if (!vfd) { + v4l2_err(&pcdev->v4l2_dev, "Failed to allocate video device\n"); + ret = -ENOMEM; + goto unreg_dev; + } + + *vfd = deinterlace_videodev; + vfd->lock = &pcdev->dev_mutex; + + ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0); + if (ret) { + v4l2_err(&pcdev->v4l2_dev, "Failed to register video device\n"); + goto rel_vdev; + } + + video_set_drvdata(vfd, pcdev); + snprintf(vfd->name, sizeof(vfd->name), "%s", deinterlace_videodev.name); + pcdev->vfd = vfd; + v4l2_info(&pcdev->v4l2_dev, MEM2MEM_TEST_MODULE_NAME + " Device registered as /dev/video%d\n", vfd->num); + + platform_set_drvdata(pdev, pcdev); + + pcdev->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev); + if (IS_ERR(pcdev->alloc_ctx)) { + v4l2_err(&pcdev->v4l2_dev, "Failed to alloc vb2 context\n"); + ret = PTR_ERR(pcdev->alloc_ctx); + goto err_ctx; + } + + pcdev->m2m_dev = v4l2_m2m_init(&m2m_ops); + if (IS_ERR(pcdev->m2m_dev)) { + v4l2_err(&pcdev->v4l2_dev, "Failed to init mem2mem device\n"); + ret = PTR_ERR(pcdev->m2m_dev); + goto err_m2m; + } + + return 0; + + v4l2_m2m_release(pcdev->m2m_dev); +err_m2m: + video_unregister_device(pcdev->vfd); +err_ctx: + vb2_dma_contig_cleanup_ctx(pcdev->alloc_ctx); +rel_vdev: + video_device_release(vfd); +unreg_dev: + v4l2_device_unregister(&pcdev->v4l2_dev); +rel_dma: + dma_release_channel(pcdev->dma_chan); +free_dev: + kfree(pcdev); + + return ret; +} + +static int deinterlace_remove(struct platform_device *pdev) +{ + struct deinterlace_dev *pcdev = + (struct deinterlace_dev *)platform_get_drvdata(pdev); + + v4l2_info(&pcdev->v4l2_dev, "Removing " MEM2MEM_TEST_MODULE_NAME); + v4l2_m2m_release(pcdev->m2m_dev); + video_unregister_device(pcdev->vfd); + v4l2_device_unregister(&pcdev->v4l2_dev); + vb2_dma_contig_cleanup_ctx(pcdev->alloc_ctx); + dma_release_channel(pcdev->dma_chan); + kfree(pcdev); + + return 0; +} + +static struct platform_driver deinterlace_pdrv = { + .probe = deinterlace_probe, + .remove = deinterlace_remove, + .driver = { + .name = MEM2MEM_NAME, + .owner = THIS_MODULE, + }, +}; + +static void __exit deinterlace_exit(void) +{ + platform_driver_unregister(&deinterlace_pdrv); +} + +static int __init deinterlace_init(void) +{ + return platform_driver_register(&deinterlace_pdrv); +} + +module_init(deinterlace_init); +module_exit(deinterlace_exit); + diff --git a/drivers/media/video/marvell-ccic/Kconfig b/drivers/media/platform/marvell-ccic/Kconfig index bf739e3b3398..bf739e3b3398 100644 --- a/drivers/media/video/marvell-ccic/Kconfig +++ b/drivers/media/platform/marvell-ccic/Kconfig diff --git a/drivers/media/video/marvell-ccic/Makefile b/drivers/media/platform/marvell-ccic/Makefile index 05a792c579a2..05a792c579a2 100644 --- a/drivers/media/video/marvell-ccic/Makefile +++ b/drivers/media/platform/marvell-ccic/Makefile diff --git a/drivers/media/video/marvell-ccic/cafe-driver.c b/drivers/media/platform/marvell-ccic/cafe-driver.c index d030f9beae88..d030f9beae88 100644 --- a/drivers/media/video/marvell-ccic/cafe-driver.c +++ b/drivers/media/platform/marvell-ccic/cafe-driver.c diff --git a/drivers/media/video/marvell-ccic/mcam-core.c b/drivers/media/platform/marvell-ccic/mcam-core.c index ce2b7b4788d6..ce2b7b4788d6 100644 --- a/drivers/media/video/marvell-ccic/mcam-core.c +++ b/drivers/media/platform/marvell-ccic/mcam-core.c diff --git a/drivers/media/video/marvell-ccic/mcam-core.h b/drivers/media/platform/marvell-ccic/mcam-core.h index bd6acba9fb37..bd6acba9fb37 100644 --- a/drivers/media/video/marvell-ccic/mcam-core.h +++ b/drivers/media/platform/marvell-ccic/mcam-core.h diff --git a/drivers/media/video/marvell-ccic/mmp-driver.c b/drivers/media/platform/marvell-ccic/mmp-driver.c index c4c17fe76c0d..c4c17fe76c0d 100644 --- a/drivers/media/video/marvell-ccic/mmp-driver.c +++ b/drivers/media/platform/marvell-ccic/mmp-driver.c diff --git a/drivers/media/video/mem2mem_testdev.c b/drivers/media/platform/mem2mem_testdev.c index 0b91a5cd38eb..d03637537118 100644 --- a/drivers/media/video/mem2mem_testdev.c +++ b/drivers/media/platform/mem2mem_testdev.c @@ -70,7 +70,7 @@ MODULE_VERSION("0.1.1"); v4l2_dbg(1, 1, &dev->v4l2_dev, "%s: " fmt, __func__, ## arg) -void m2mtest_dev_release(struct device *dev) +static void m2mtest_dev_release(struct device *dev) {} static struct platform_device m2mtest_pdev = { @@ -430,7 +430,8 @@ static int vidioc_querycap(struct file *file, void *priv, { strncpy(cap->driver, MEM2MEM_NAME, sizeof(cap->driver) - 1); strncpy(cap->card, MEM2MEM_NAME, sizeof(cap->card) - 1); - strlcpy(cap->bus_info, MEM2MEM_NAME, sizeof(cap->bus_info)); + snprintf(cap->bus_info, sizeof(cap->bus_info), + "platform:%s", MEM2MEM_NAME); cap->device_caps = V4L2_CAP_VIDEO_M2M | V4L2_CAP_STREAMING; cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; return 0; @@ -838,7 +839,6 @@ static int queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *ds struct m2mtest_ctx *ctx = priv; int ret; - memset(src_vq, 0, sizeof(*src_vq)); src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; src_vq->io_modes = VB2_MMAP; src_vq->drv_priv = ctx; @@ -850,7 +850,6 @@ static int queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *ds if (ret) return ret; - memset(dst_vq, 0, sizeof(*dst_vq)); dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; dst_vq->io_modes = VB2_MMAP; dst_vq->drv_priv = ctx; @@ -891,10 +890,15 @@ static int m2mtest_open(struct file *file) struct m2mtest_dev *dev = video_drvdata(file); struct m2mtest_ctx *ctx = NULL; struct v4l2_ctrl_handler *hdl; + int rc = 0; + if (mutex_lock_interruptible(&dev->dev_mutex)) + return -ERESTARTSYS; ctx = kzalloc(sizeof *ctx, GFP_KERNEL); - if (!ctx) - return -ENOMEM; + if (!ctx) { + rc = -ENOMEM; + goto open_unlock; + } v4l2_fh_init(&ctx->fh, video_devdata(file)); file->private_data = &ctx->fh; @@ -906,10 +910,9 @@ static int m2mtest_open(struct file *file) v4l2_ctrl_new_custom(hdl, &m2mtest_ctrl_trans_time_msec, NULL); v4l2_ctrl_new_custom(hdl, &m2mtest_ctrl_trans_num_bufs, NULL); if (hdl->error) { - int err = hdl->error; - + rc = hdl->error; v4l2_ctrl_handler_free(hdl); - return err; + goto open_unlock; } ctx->fh.ctrl_handler = hdl; v4l2_ctrl_handler_setup(hdl); @@ -927,11 +930,11 @@ static int m2mtest_open(struct file *file) ctx->m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev, ctx, &queue_init); if (IS_ERR(ctx->m2m_ctx)) { - int ret = PTR_ERR(ctx->m2m_ctx); + rc = PTR_ERR(ctx->m2m_ctx); v4l2_ctrl_handler_free(hdl); kfree(ctx); - return ret; + goto open_unlock; } v4l2_fh_add(&ctx->fh); @@ -939,7 +942,9 @@ static int m2mtest_open(struct file *file) dprintk(dev, "Created instance %p, m2m_ctx: %p\n", ctx, ctx->m2m_ctx); - return 0; +open_unlock: + mutex_unlock(&dev->dev_mutex); + return rc; } static int m2mtest_release(struct file *file) @@ -952,7 +957,9 @@ static int m2mtest_release(struct file *file) v4l2_fh_del(&ctx->fh); v4l2_fh_exit(&ctx->fh); v4l2_ctrl_handler_free(&ctx->hdl); + mutex_lock(&dev->dev_mutex); v4l2_m2m_ctx_release(ctx->m2m_ctx); + mutex_unlock(&dev->dev_mutex); kfree(ctx); atomic_dec(&dev->num_inst); @@ -970,9 +977,15 @@ static unsigned int m2mtest_poll(struct file *file, static int m2mtest_mmap(struct file *file, struct vm_area_struct *vma) { + struct m2mtest_dev *dev = video_drvdata(file); struct m2mtest_ctx *ctx = file2ctx(file); + int res; - return v4l2_m2m_mmap(file, ctx->m2m_ctx, vma); + if (mutex_lock_interruptible(&dev->dev_mutex)) + return -ERESTARTSYS; + res = v4l2_m2m_mmap(file, ctx->m2m_ctx, vma); + mutex_unlock(&dev->dev_mutex); + return res; } static const struct v4l2_file_operations m2mtest_fops = { @@ -986,6 +999,7 @@ static const struct v4l2_file_operations m2mtest_fops = { static struct video_device m2mtest_videodev = { .name = MEM2MEM_NAME, + .vfl_dir = VFL_DIR_M2M, .fops = &m2mtest_fops, .ioctl_ops = &m2mtest_ioctl_ops, .minor = -1, @@ -1027,10 +1041,6 @@ static int m2mtest_probe(struct platform_device *pdev) } *vfd = m2mtest_videodev; - /* Locking in file operations other than ioctl should be done - by the driver, not the V4L2 core. - This driver needs auditing so that this flag can be removed. */ - set_bit(V4L2_FL_LOCK_ALL_FOPS, &vfd->flags); vfd->lock = &dev->dev_mutex; ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0); diff --git a/drivers/media/video/mx2_emmaprp.c b/drivers/media/platform/mx2_emmaprp.c index 5f8a6f5b98f9..8f22ce543cf7 100644 --- a/drivers/media/video/mx2_emmaprp.c +++ b/drivers/media/platform/mx2_emmaprp.c @@ -209,7 +209,7 @@ struct emmaprp_dev { int irq_emma; void __iomem *base_emma; - struct clk *clk_emma; + struct clk *clk_emma_ahb, *clk_emma_ipg; struct resource *res_emma; struct v4l2_m2m_dev *m2m_dev; @@ -757,7 +757,6 @@ static int queue_init(void *priv, struct vb2_queue *src_vq, struct emmaprp_ctx *ctx = priv; int ret; - memset(src_vq, 0, sizeof(*src_vq)); src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; src_vq->io_modes = VB2_MMAP | VB2_USERPTR; src_vq->drv_priv = ctx; @@ -769,7 +768,6 @@ static int queue_init(void *priv, struct vb2_queue *src_vq, if (ret) return ret; - memset(dst_vq, 0, sizeof(*dst_vq)); dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; dst_vq->io_modes = VB2_MMAP | VB2_USERPTR; dst_vq->drv_priv = ctx; @@ -795,18 +793,26 @@ static int emmaprp_open(struct file *file) file->private_data = ctx; ctx->dev = pcdev; + if (mutex_lock_interruptible(&pcdev->dev_mutex)) { + kfree(ctx); + return -ERESTARTSYS; + } + ctx->m2m_ctx = v4l2_m2m_ctx_init(pcdev->m2m_dev, ctx, &queue_init); if (IS_ERR(ctx->m2m_ctx)) { int ret = PTR_ERR(ctx->m2m_ctx); + mutex_unlock(&pcdev->dev_mutex); kfree(ctx); return ret; } - clk_enable(pcdev->clk_emma); + clk_prepare_enable(pcdev->clk_emma_ipg); + clk_prepare_enable(pcdev->clk_emma_ahb); ctx->q_data[V4L2_M2M_SRC].fmt = &formats[1]; ctx->q_data[V4L2_M2M_DST].fmt = &formats[0]; + mutex_unlock(&pcdev->dev_mutex); dprintk(pcdev, "Created instance %p, m2m_ctx: %p\n", ctx, ctx->m2m_ctx); @@ -820,8 +826,11 @@ static int emmaprp_release(struct file *file) dprintk(pcdev, "Releasing instance %p\n", ctx); - clk_disable(pcdev->clk_emma); + mutex_lock(&pcdev->dev_mutex); + clk_disable_unprepare(pcdev->clk_emma_ahb); + clk_disable_unprepare(pcdev->clk_emma_ipg); v4l2_m2m_ctx_release(ctx->m2m_ctx); + mutex_unlock(&pcdev->dev_mutex); kfree(ctx); return 0; @@ -830,16 +839,27 @@ static int emmaprp_release(struct file *file) static unsigned int emmaprp_poll(struct file *file, struct poll_table_struct *wait) { + struct emmaprp_dev *pcdev = video_drvdata(file); struct emmaprp_ctx *ctx = file->private_data; + unsigned int res; - return v4l2_m2m_poll(file, ctx->m2m_ctx, wait); + mutex_lock(&pcdev->dev_mutex); + res = v4l2_m2m_poll(file, ctx->m2m_ctx, wait); + mutex_unlock(&pcdev->dev_mutex); + return res; } static int emmaprp_mmap(struct file *file, struct vm_area_struct *vma) { + struct emmaprp_dev *pcdev = video_drvdata(file); struct emmaprp_ctx *ctx = file->private_data; + int ret; - return v4l2_m2m_mmap(file, ctx->m2m_ctx, vma); + if (mutex_lock_interruptible(&pcdev->dev_mutex)) + return -ERESTARTSYS; + ret = v4l2_m2m_mmap(file, ctx->m2m_ctx, vma); + mutex_unlock(&pcdev->dev_mutex); + return ret; } static const struct v4l2_file_operations emmaprp_fops = { @@ -857,6 +877,7 @@ static struct video_device emmaprp_videodev = { .ioctl_ops = &emmaprp_ioctl_ops, .minor = -1, .release = video_device_release, + .vfl_dir = VFL_DIR_M2M, }; static struct v4l2_m2m_ops m2m_ops = { @@ -874,29 +895,31 @@ static int emmaprp_probe(struct platform_device *pdev) int irq_emma; int ret; - pcdev = kzalloc(sizeof *pcdev, GFP_KERNEL); + pcdev = devm_kzalloc(&pdev->dev, sizeof(*pcdev), GFP_KERNEL); if (!pcdev) return -ENOMEM; spin_lock_init(&pcdev->irqlock); - pcdev->clk_emma = clk_get(&pdev->dev, NULL); - if (IS_ERR(pcdev->clk_emma)) { - ret = PTR_ERR(pcdev->clk_emma); - goto free_dev; + pcdev->clk_emma_ipg = devm_clk_get(&pdev->dev, "ipg"); + if (IS_ERR(pcdev->clk_emma_ipg)) { + return PTR_ERR(pcdev->clk_emma_ipg); } + pcdev->clk_emma_ahb = devm_clk_get(&pdev->dev, "ahb"); + if (IS_ERR(pcdev->clk_emma_ahb)) + return PTR_ERR(pcdev->clk_emma_ahb); + irq_emma = platform_get_irq(pdev, 0); res_emma = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (irq_emma < 0 || res_emma == NULL) { dev_err(&pdev->dev, "Missing platform resources data\n"); - ret = -ENODEV; - goto free_clk; + return -ENODEV; } ret = v4l2_device_register(&pdev->dev, &pcdev->v4l2_dev); if (ret) - goto free_clk; + return ret; mutex_init(&pcdev->dev_mutex); @@ -908,10 +931,6 @@ static int emmaprp_probe(struct platform_device *pdev) } *vfd = emmaprp_videodev; - /* Locking in file operations other than ioctl should be done - by the driver, not the V4L2 core. - This driver needs auditing so that this flag can be removed. */ - set_bit(V4L2_FL_LOCK_ALL_FOPS, &vfd->flags); vfd->lock = &pcdev->dev_mutex; video_set_drvdata(vfd, pcdev); @@ -922,21 +941,20 @@ static int emmaprp_probe(struct platform_device *pdev) platform_set_drvdata(pdev, pcdev); - if (devm_request_mem_region(&pdev->dev, res_emma->start, - resource_size(res_emma), MEM2MEM_NAME) == NULL) - goto rel_vdev; - - pcdev->base_emma = devm_ioremap(&pdev->dev, res_emma->start, - resource_size(res_emma)); - if (!pcdev->base_emma) + pcdev->base_emma = devm_request_and_ioremap(&pdev->dev, res_emma); + if (!pcdev->base_emma) { + ret = -ENXIO; goto rel_vdev; + } pcdev->irq_emma = irq_emma; pcdev->res_emma = res_emma; if (devm_request_irq(&pdev->dev, pcdev->irq_emma, emmaprp_irq, - 0, MEM2MEM_NAME, pcdev) < 0) + 0, MEM2MEM_NAME, pcdev) < 0) { + ret = -ENODEV; goto rel_vdev; + } pcdev->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev); if (IS_ERR(pcdev->alloc_ctx)) { @@ -969,10 +987,6 @@ rel_vdev: video_device_release(vfd); unreg_dev: v4l2_device_unregister(&pcdev->v4l2_dev); -free_clk: - clk_put(pcdev->clk_emma); -free_dev: - kfree(pcdev); return ret; } @@ -987,8 +1001,6 @@ static int emmaprp_remove(struct platform_device *pdev) v4l2_m2m_release(pcdev->m2m_dev); vb2_dma_contig_cleanup_ctx(pcdev->alloc_ctx); v4l2_device_unregister(&pcdev->v4l2_dev); - clk_put(pcdev->clk_emma); - kfree(pcdev); return 0; } diff --git a/drivers/media/video/omap/Kconfig b/drivers/media/platform/omap/Kconfig index 390ab094f9f2..390ab094f9f2 100644 --- a/drivers/media/video/omap/Kconfig +++ b/drivers/media/platform/omap/Kconfig diff --git a/drivers/media/video/omap/Makefile b/drivers/media/platform/omap/Makefile index fc410b438f7d..d80df41fde28 100644 --- a/drivers/media/video/omap/Makefile +++ b/drivers/media/platform/omap/Makefile @@ -3,6 +3,6 @@ # # OMAP2/3 Display driver -omap-vout-y := omap_vout.o omap_voutlib.o +omap-vout-y += omap_vout.o omap_voutlib.o omap-vout-$(CONFIG_VIDEO_OMAP2_VOUT_VRFB) += omap_vout_vrfb.o obj-$(CONFIG_VIDEO_OMAP2_VOUT) += omap-vout.o diff --git a/drivers/media/video/omap/omap_vout.c b/drivers/media/platform/omap/omap_vout.c index 409da0f8e5cf..66ac21d466af 100644 --- a/drivers/media/video/omap/omap_vout.c +++ b/drivers/media/platform/omap/omap_vout.c @@ -1292,7 +1292,7 @@ static int vidioc_g_crop(struct file *file, void *fh, struct v4l2_crop *crop) return 0; } -static int vidioc_s_crop(struct file *file, void *fh, struct v4l2_crop *crop) +static int vidioc_s_crop(struct file *file, void *fh, const struct v4l2_crop *crop) { int ret = -EINVAL; struct omap_vout_device *vout = fh; @@ -1745,7 +1745,7 @@ static int vidioc_streamoff(struct file *file, void *fh, enum v4l2_buf_type i) } static int vidioc_s_fbuf(struct file *file, void *fh, - struct v4l2_framebuffer *a) + const struct v4l2_framebuffer *a) { int enable = 0; struct omap_overlay *ovl; @@ -1952,6 +1952,7 @@ static int __init omap_vout_setup_video_data(struct omap_vout_device *vout) vfd->fops = &omap_vout_fops; vfd->v4l2_dev = &vout->vid_dev->v4l2_dev; + vfd->vfl_dir = VFL_DIR_TX; mutex_init(&vout->lock); vfd->minor = -1; diff --git a/drivers/media/video/omap/omap_vout_vrfb.c b/drivers/media/platform/omap/omap_vout_vrfb.c index 4be26abf6cea..4be26abf6cea 100644 --- a/drivers/media/video/omap/omap_vout_vrfb.c +++ b/drivers/media/platform/omap/omap_vout_vrfb.c diff --git a/drivers/media/video/omap/omap_vout_vrfb.h b/drivers/media/platform/omap/omap_vout_vrfb.h index ffde741e0590..ffde741e0590 100644 --- a/drivers/media/video/omap/omap_vout_vrfb.h +++ b/drivers/media/platform/omap/omap_vout_vrfb.h diff --git a/drivers/media/video/omap/omap_voutdef.h b/drivers/media/platform/omap/omap_voutdef.h index 27a95d23b913..27a95d23b913 100644 --- a/drivers/media/video/omap/omap_voutdef.h +++ b/drivers/media/platform/omap/omap_voutdef.h diff --git a/drivers/media/video/omap/omap_voutlib.c b/drivers/media/platform/omap/omap_voutlib.c index 115408b9274f..115408b9274f 100644 --- a/drivers/media/video/omap/omap_voutlib.c +++ b/drivers/media/platform/omap/omap_voutlib.c diff --git a/drivers/media/video/omap/omap_voutlib.h b/drivers/media/platform/omap/omap_voutlib.h index e51750a597e3..e51750a597e3 100644 --- a/drivers/media/video/omap/omap_voutlib.h +++ b/drivers/media/platform/omap/omap_voutlib.h diff --git a/drivers/media/video/omap24xxcam-dma.c b/drivers/media/platform/omap24xxcam-dma.c index b5ae170de4a5..9c00776d6583 100644 --- a/drivers/media/video/omap24xxcam-dma.c +++ b/drivers/media/platform/omap24xxcam-dma.c @@ -1,5 +1,5 @@ /* - * drivers/media/video/omap24xxcam-dma.c + * drivers/media/platform/omap24xxcam-dma.c * * Copyright (C) 2004 MontaVista Software, Inc. * Copyright (C) 2004 Texas Instruments. diff --git a/drivers/media/video/omap24xxcam.c b/drivers/media/platform/omap24xxcam.c index 8d7283bbd431..70f45c381318 100644 --- a/drivers/media/video/omap24xxcam.c +++ b/drivers/media/platform/omap24xxcam.c @@ -1,5 +1,5 @@ /* - * drivers/media/video/omap24xxcam.c + * drivers/media/platform/omap24xxcam.c * * OMAP 2 camera block driver. * diff --git a/drivers/media/video/omap24xxcam.h b/drivers/media/platform/omap24xxcam.h index d59727afe894..c4395956a493 100644 --- a/drivers/media/video/omap24xxcam.h +++ b/drivers/media/platform/omap24xxcam.h @@ -1,5 +1,5 @@ /* - * drivers/media/video/omap24xxcam.h + * drivers/media/platform/omap24xxcam.h * * Copyright (C) 2004 MontaVista Software, Inc. * Copyright (C) 2004 Texas Instruments. diff --git a/drivers/media/video/omap3isp/Makefile b/drivers/media/platform/omap3isp/Makefile index e8847e79e31a..e8847e79e31a 100644 --- a/drivers/media/video/omap3isp/Makefile +++ b/drivers/media/platform/omap3isp/Makefile diff --git a/drivers/media/video/omap3isp/cfa_coef_table.h b/drivers/media/platform/omap3isp/cfa_coef_table.h index c60df0ed075a..c84df0706f3e 100644 --- a/drivers/media/video/omap3isp/cfa_coef_table.h +++ b/drivers/media/platform/omap3isp/cfa_coef_table.h @@ -23,7 +23,7 @@ * 02110-1301 USA */ -244, 0, 247, 0, 12, 27, 36, 247, 250, 0, 27, 0, 4, 250, 12, 244, +{ 244, 0, 247, 0, 12, 27, 36, 247, 250, 0, 27, 0, 4, 250, 12, 244, 248, 0, 0, 0, 0, 40, 0, 0, 244, 12, 250, 4, 0, 27, 0, 250, 247, 36, 27, 12, 0, 247, 0, 244, 0, 0, 40, 0, 0, 0, 0, 248, 244, 0, 247, 0, 12, 27, 36, 247, 250, 0, 27, 0, 4, 250, 12, 244, @@ -31,8 +31,8 @@ 247, 36, 27, 12, 0, 247, 0, 244, 0, 0, 40, 0, 0, 0, 0, 248, 244, 0, 247, 0, 12, 27, 36, 247, 250, 0, 27, 0, 4, 250, 12, 244, 248, 0, 0, 0, 0, 40, 0, 0, 244, 12, 250, 4, 0, 27, 0, 250, -247, 36, 27, 12, 0, 247, 0, 244, 0, 0, 40, 0, 0, 0, 0, 248, - 0, 247, 0, 244, 247, 36, 27, 12, 0, 27, 0, 250, 244, 12, 250, 4, +247, 36, 27, 12, 0, 247, 0, 244, 0, 0, 40, 0, 0, 0, 0, 248 }, +{ 0, 247, 0, 244, 247, 36, 27, 12, 0, 27, 0, 250, 244, 12, 250, 4, 0, 0, 0, 248, 0, 0, 40, 0, 4, 250, 12, 244, 250, 0, 27, 0, 12, 27, 36, 247, 244, 0, 247, 0, 0, 40, 0, 0, 248, 0, 0, 0, 0, 247, 0, 244, 247, 36, 27, 12, 0, 27, 0, 250, 244, 12, 250, 4, @@ -40,8 +40,8 @@ 12, 27, 36, 247, 244, 0, 247, 0, 0, 40, 0, 0, 248, 0, 0, 0, 0, 247, 0, 244, 247, 36, 27, 12, 0, 27, 0, 250, 244, 12, 250, 4, 0, 0, 0, 248, 0, 0, 40, 0, 4, 250, 12, 244, 250, 0, 27, 0, - 12, 27, 36, 247, 244, 0, 247, 0, 0, 40, 0, 0, 248, 0, 0, 0, - 4, 250, 12, 244, 250, 0, 27, 0, 12, 27, 36, 247, 244, 0, 247, 0, + 12, 27, 36, 247, 244, 0, 247, 0, 0, 40, 0, 0, 248, 0, 0, 0 }, +{ 4, 250, 12, 244, 250, 0, 27, 0, 12, 27, 36, 247, 244, 0, 247, 0, 0, 0, 0, 248, 0, 0, 40, 0, 0, 247, 0, 244, 247, 36, 27, 12, 0, 27, 0, 250, 244, 12, 250, 4, 0, 40, 0, 0, 248, 0, 0, 0, 4, 250, 12, 244, 250, 0, 27, 0, 12, 27, 36, 247, 244, 0, 247, 0, @@ -49,8 +49,8 @@ 0, 27, 0, 250, 244, 12, 250, 4, 0, 40, 0, 0, 248, 0, 0, 0, 4, 250, 12, 244, 250, 0, 27, 0, 12, 27, 36, 247, 244, 0, 247, 0, 0, 0, 0, 248, 0, 0, 40, 0, 0, 247, 0, 244, 247, 36, 27, 12, - 0, 27, 0, 250, 244, 12, 250, 4, 0, 40, 0, 0, 248, 0, 0, 0, -244, 12, 250, 4, 0, 27, 0, 250, 247, 36, 27, 12, 0, 247, 0, 244, + 0, 27, 0, 250, 244, 12, 250, 4, 0, 40, 0, 0, 248, 0, 0, 0 }, +{ 244,12, 250, 4, 0, 27, 0, 250, 247, 36, 27, 12, 0, 247, 0, 244, 248, 0, 0, 0, 0, 40, 0, 0, 244, 0, 247, 0, 12, 27, 36, 247, 250, 0, 27, 0, 4, 250, 12, 244, 0, 0, 40, 0, 0, 0, 0, 248, 244, 12, 250, 4, 0, 27, 0, 250, 247, 36, 27, 12, 0, 247, 0, 244, @@ -58,4 +58,4 @@ 250, 0, 27, 0, 4, 250, 12, 244, 0, 0, 40, 0, 0, 0, 0, 248, 244, 12, 250, 4, 0, 27, 0, 250, 247, 36, 27, 12, 0, 247, 0, 244, 248, 0, 0, 0, 0, 40, 0, 0, 244, 0, 247, 0, 12, 27, 36, 247, -250, 0, 27, 0, 4, 250, 12, 244, 0, 0, 40, 0, 0, 0, 0, 248 +250, 0, 27, 0, 4, 250, 12, 244, 0, 0, 40, 0, 0, 0, 0, 248 }, diff --git a/drivers/media/video/omap3isp/gamma_table.h b/drivers/media/platform/omap3isp/gamma_table.h index 78deebf7d965..78deebf7d965 100644 --- a/drivers/media/video/omap3isp/gamma_table.h +++ b/drivers/media/platform/omap3isp/gamma_table.h diff --git a/drivers/media/video/omap3isp/isp.c b/drivers/media/platform/omap3isp/isp.c index 43e61fe5df50..99640d8c1db0 100644 --- a/drivers/media/video/omap3isp/isp.c +++ b/drivers/media/platform/omap3isp/isp.c @@ -254,13 +254,18 @@ static u32 isp_set_xclk(struct isp_device *isp, u32 xclk, u8 xclksel) } /* - * isp_power_settings - Sysconfig settings, for Power Management. + * isp_core_init - ISP core settings * @isp: OMAP3 ISP device * @idle: Consider idle state. * - * Sets the power settings for the ISP, and SBL bus. + * Set the power settings for the ISP and SBL bus and cConfigure the HS/VS + * interrupt source. + * + * We need to configure the HS/VS interrupt source before interrupts get + * enabled, as the sensor might be free-running and the ISP default setting + * (HS edge) would put an unnecessary burden on the CPU. */ -static void isp_power_settings(struct isp_device *isp, int idle) +static void isp_core_init(struct isp_device *isp, int idle) { isp_reg_writel(isp, ((idle ? ISP_SYSCONFIG_MIDLEMODE_SMARTSTANDBY : @@ -270,9 +275,10 @@ static void isp_power_settings(struct isp_device *isp, int idle) ISP_SYSCONFIG_AUTOIDLE : 0), OMAP3_ISP_IOMEM_MAIN, ISP_SYSCONFIG); - if (isp->autoidle) - isp_reg_writel(isp, ISPCTRL_SBL_AUTOIDLE, OMAP3_ISP_IOMEM_MAIN, - ISP_CTRL); + isp_reg_writel(isp, + (isp->autoidle ? ISPCTRL_SBL_AUTOIDLE : 0) | + ISPCTRL_SYNC_DETECT_VSRISE, + OMAP3_ISP_IOMEM_MAIN, ISP_CTRL); } /* @@ -289,7 +295,7 @@ static void isp_power_settings(struct isp_device *isp, int idle) void omap3isp_configure_bridge(struct isp_device *isp, enum ccdc_input_entity input, const struct isp_parallel_platform_data *pdata, - unsigned int shift) + unsigned int shift, unsigned int bridge) { u32 ispctrl_val; @@ -298,12 +304,12 @@ void omap3isp_configure_bridge(struct isp_device *isp, ispctrl_val &= ~ISPCTRL_PAR_CLK_POL_INV; ispctrl_val &= ~ISPCTRL_PAR_SER_CLK_SEL_MASK; ispctrl_val &= ~ISPCTRL_PAR_BRIDGE_MASK; + ispctrl_val |= bridge; switch (input) { case CCDC_INPUT_PARALLEL: ispctrl_val |= ISPCTRL_PAR_SER_CLK_SEL_PARALLEL; ispctrl_val |= pdata->clk_pol << ISPCTRL_PAR_CLK_POL_SHIFT; - ispctrl_val |= pdata->bridge << ISPCTRL_PAR_BRIDGE_SHIFT; shift += pdata->data_lane_shift * 2; break; @@ -325,9 +331,6 @@ void omap3isp_configure_bridge(struct isp_device *isp, ispctrl_val |= ((shift/2) << ISPCTRL_SHIFT_SHIFT) & ISPCTRL_SHIFT_MASK; - ispctrl_val &= ~ISPCTRL_SYNC_DETECT_MASK; - ispctrl_val |= ISPCTRL_SYNC_DETECT_VSRISE; - isp_reg_writel(isp, ispctrl_val, OMAP3_ISP_IOMEM_MAIN, ISP_CTRL); } @@ -1283,7 +1286,9 @@ static void __isp_subclk_update(struct isp_device *isp) { u32 clk = 0; - if (isp->subclk_resources & OMAP3_ISP_SUBCLK_H3A) + /* AEWB and AF share the same clock. */ + if (isp->subclk_resources & + (OMAP3_ISP_SUBCLK_AEWB | OMAP3_ISP_SUBCLK_AF)) clk |= ISPCTRL_H3A_CLK_EN; if (isp->subclk_resources & OMAP3_ISP_SUBCLK_HIST) @@ -1443,7 +1448,7 @@ static int isp_get_clocks(struct isp_device *isp) * * Return a pointer to the ISP device structure, or NULL if an error occurred. */ -struct isp_device *omap3isp_get(struct isp_device *isp) +static struct isp_device *__omap3isp_get(struct isp_device *isp, bool irq) { struct isp_device *__isp = isp; @@ -1462,10 +1467,9 @@ struct isp_device *omap3isp_get(struct isp_device *isp) /* We don't want to restore context before saving it! */ if (isp->has_context) isp_restore_ctx(isp); - else - isp->has_context = 1; - isp_enable_interrupts(isp); + if (irq) + isp_enable_interrupts(isp); out: if (__isp != NULL) @@ -1475,6 +1479,11 @@ out: return __isp; } +struct isp_device *omap3isp_get(struct isp_device *isp) +{ + return __omap3isp_get(isp, true); +} + /* * omap3isp_put - Release the ISP * @@ -1490,8 +1499,10 @@ void omap3isp_put(struct isp_device *isp) BUG_ON(isp->ref_count == 0); if (--isp->ref_count == 0) { isp_disable_interrupts(isp); - if (isp->domain) + if (isp->domain) { isp_save_ctx(isp); + isp->has_context = 1; + } /* Reset the ISP if an entity has failed to stop. This is the * only way to recover from such conditions. */ @@ -1975,7 +1986,7 @@ static int __devexit isp_remove(struct platform_device *pdev) isp_unregister_entities(isp); isp_cleanup_modules(isp); - omap3isp_get(isp); + __omap3isp_get(isp, false); iommu_detach_device(isp->domain, &pdev->dev); iommu_domain_free(isp->domain); isp->domain = NULL; @@ -2093,8 +2104,10 @@ static int __devinit isp_probe(struct platform_device *pdev) if (ret < 0) goto error; - if (omap3isp_get(isp) == NULL) + if (__omap3isp_get(isp, false) == NULL) { + ret = -ENODEV; goto error; + } ret = isp_reset(isp); if (ret < 0) @@ -2160,7 +2173,7 @@ static int __devinit isp_probe(struct platform_device *pdev) if (ret < 0) goto error_modules; - isp_power_settings(isp, 1); + isp_core_init(isp, 1); omap3isp_put(isp); return 0; diff --git a/drivers/media/video/omap3isp/isp.h b/drivers/media/platform/omap3isp/isp.h index fc7af3e32efd..8be7487c326f 100644 --- a/drivers/media/video/omap3isp/isp.h +++ b/drivers/media/platform/omap3isp/isp.h @@ -90,10 +90,11 @@ enum isp_sbl_resource { enum isp_subclk_resource { OMAP3_ISP_SUBCLK_CCDC = (1 << 0), - OMAP3_ISP_SUBCLK_H3A = (1 << 1), - OMAP3_ISP_SUBCLK_HIST = (1 << 2), - OMAP3_ISP_SUBCLK_PREVIEW = (1 << 3), - OMAP3_ISP_SUBCLK_RESIZER = (1 << 4), + OMAP3_ISP_SUBCLK_AEWB = (1 << 1), + OMAP3_ISP_SUBCLK_AF = (1 << 2), + OMAP3_ISP_SUBCLK_HIST = (1 << 3), + OMAP3_ISP_SUBCLK_PREVIEW = (1 << 4), + OMAP3_ISP_SUBCLK_RESIZER = (1 << 5), }; /* ISP: OMAP 34xx ES 1.0 */ @@ -235,7 +236,7 @@ int omap3isp_pipeline_set_stream(struct isp_pipeline *pipe, void omap3isp_configure_bridge(struct isp_device *isp, enum ccdc_input_entity input, const struct isp_parallel_platform_data *pdata, - unsigned int shift); + unsigned int shift, unsigned int bridge); struct isp_device *omap3isp_get(struct isp_device *isp); void omap3isp_put(struct isp_device *isp); diff --git a/drivers/media/video/omap3isp/ispccdc.c b/drivers/media/platform/omap3isp/ispccdc.c index f1220d3d4970..60181ab96063 100644 --- a/drivers/media/video/omap3isp/ispccdc.c +++ b/drivers/media/platform/omap3isp/ispccdc.c @@ -61,6 +61,8 @@ static const unsigned int ccdc_fmts[] = { V4L2_MBUS_FMT_SRGGB12_1X12, V4L2_MBUS_FMT_SBGGR12_1X12, V4L2_MBUS_FMT_SGBRG12_1X12, + V4L2_MBUS_FMT_YUYV8_2X8, + V4L2_MBUS_FMT_UYVY8_2X8, }; /* @@ -627,9 +629,12 @@ static void ccdc_configure_lpf(struct isp_ccdc_device *ccdc) static void ccdc_configure_alaw(struct isp_ccdc_device *ccdc) { struct isp_device *isp = to_isp_device(ccdc); + const struct isp_format_info *info; u32 alaw = 0; - switch (ccdc->syncif.datsz) { + info = omap3isp_video_format_info(ccdc->formats[CCDC_PAD_SINK].code); + + switch (info->width) { case 8: return; @@ -813,6 +818,7 @@ static void ccdc_config_vp(struct isp_ccdc_device *ccdc) { struct isp_pipeline *pipe = to_isp_pipeline(&ccdc->subdev.entity); struct isp_device *isp = to_isp_device(ccdc); + const struct isp_format_info *info; unsigned long l3_ick = pipe->l3_ick; unsigned int max_div = isp->revision == ISP_REVISION_15_0 ? 64 : 8; unsigned int div = 0; @@ -821,7 +827,9 @@ static void ccdc_config_vp(struct isp_ccdc_device *ccdc) fmtcfg_vp = isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMTCFG) & ~(ISPCCDC_FMTCFG_VPIN_MASK | ISPCCDC_FMTCFG_VPIF_FRQ_MASK); - switch (ccdc->syncif.datsz) { + info = omap3isp_video_format_info(ccdc->formats[CCDC_PAD_SINK].code); + + switch (info->width) { case 8: case 10: fmtcfg_vp |= ISPCCDC_FMTCFG_VPIN_9_0; @@ -835,7 +843,7 @@ static void ccdc_config_vp(struct isp_ccdc_device *ccdc) case 13: fmtcfg_vp |= ISPCCDC_FMTCFG_VPIN_12_3; break; - }; + } if (pipe->input) div = DIV_ROUND_UP(l3_ick, pipe->max_rate); @@ -959,26 +967,28 @@ void omap3isp_ccdc_max_rate(struct isp_ccdc_device *ccdc, /* * ccdc_config_sync_if - Set CCDC sync interface configuration * @ccdc: Pointer to ISP CCDC device. - * @syncif: Structure containing the sync parameters like field state, CCDC in - * master/slave mode, raw/yuv data, polarity of data, field, hs, vs - * signals. + * @pdata: Parallel interface platform data (may be NULL) + * @data_size: Data size */ static void ccdc_config_sync_if(struct isp_ccdc_device *ccdc, - struct ispccdc_syncif *syncif) + struct isp_parallel_platform_data *pdata, + unsigned int data_size) { struct isp_device *isp = to_isp_device(ccdc); - u32 syn_mode = isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCDC, - ISPCCDC_SYN_MODE); + const struct v4l2_mbus_framefmt *format; + u32 syn_mode = ISPCCDC_SYN_MODE_VDHDEN; - syn_mode |= ISPCCDC_SYN_MODE_VDHDEN; + format = &ccdc->formats[CCDC_PAD_SINK]; - if (syncif->fldstat) - syn_mode |= ISPCCDC_SYN_MODE_FLDSTAT; - else - syn_mode &= ~ISPCCDC_SYN_MODE_FLDSTAT; + if (format->code == V4L2_MBUS_FMT_YUYV8_2X8 || + format->code == V4L2_MBUS_FMT_UYVY8_2X8) { + /* The bridge is enabled for YUV8 formats. Configure the input + * mode accordingly. + */ + syn_mode |= ISPCCDC_SYN_MODE_INPMOD_YCBCR16; + } - syn_mode &= ~ISPCCDC_SYN_MODE_DATSIZ_MASK; - switch (syncif->datsz) { + switch (data_size) { case 8: syn_mode |= ISPCCDC_SYN_MODE_DATSIZ_8; break; @@ -991,55 +1001,31 @@ static void ccdc_config_sync_if(struct isp_ccdc_device *ccdc, case 12: syn_mode |= ISPCCDC_SYN_MODE_DATSIZ_12; break; - }; - - if (syncif->fldmode) - syn_mode |= ISPCCDC_SYN_MODE_FLDMODE; - else - syn_mode &= ~ISPCCDC_SYN_MODE_FLDMODE; + } - if (syncif->datapol) + if (pdata && pdata->data_pol) syn_mode |= ISPCCDC_SYN_MODE_DATAPOL; - else - syn_mode &= ~ISPCCDC_SYN_MODE_DATAPOL; - - if (syncif->fldpol) - syn_mode |= ISPCCDC_SYN_MODE_FLDPOL; - else - syn_mode &= ~ISPCCDC_SYN_MODE_FLDPOL; - if (syncif->hdpol) + if (pdata && pdata->hs_pol) syn_mode |= ISPCCDC_SYN_MODE_HDPOL; - else - syn_mode &= ~ISPCCDC_SYN_MODE_HDPOL; - if (syncif->vdpol) + if (pdata && pdata->vs_pol) syn_mode |= ISPCCDC_SYN_MODE_VDPOL; - else - syn_mode &= ~ISPCCDC_SYN_MODE_VDPOL; - - if (syncif->ccdc_mastermode) { - syn_mode |= ISPCCDC_SYN_MODE_FLDOUT | ISPCCDC_SYN_MODE_VDHDOUT; - isp_reg_writel(isp, - syncif->hs_width << ISPCCDC_HD_VD_WID_HDW_SHIFT - | syncif->vs_width << ISPCCDC_HD_VD_WID_VDW_SHIFT, - OMAP3_ISP_IOMEM_CCDC, - ISPCCDC_HD_VD_WID); - - isp_reg_writel(isp, - syncif->ppln << ISPCCDC_PIX_LINES_PPLN_SHIFT - | syncif->hlprf << ISPCCDC_PIX_LINES_HLPRF_SHIFT, - OMAP3_ISP_IOMEM_CCDC, - ISPCCDC_PIX_LINES); - } else - syn_mode &= ~(ISPCCDC_SYN_MODE_FLDOUT | - ISPCCDC_SYN_MODE_VDHDOUT); isp_reg_writel(isp, syn_mode, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SYN_MODE); - if (!syncif->bt_r656_en) - isp_reg_clr(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_REC656IF, - ISPCCDC_REC656IF_R656ON); + /* The CCDC_CFG.Y8POS bit is used in YCbCr8 input mode only. The + * hardware seems to ignore it in all other input modes. + */ + if (format->code == V4L2_MBUS_FMT_UYVY8_2X8) + isp_reg_set(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CFG, + ISPCCDC_CFG_Y8POS); + else + isp_reg_clr(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CFG, + ISPCCDC_CFG_Y8POS); + + isp_reg_clr(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_REC656IF, + ISPCCDC_REC656IF_R656ON); } /* CCDC formats descriptions */ @@ -1128,6 +1114,7 @@ static void ccdc_configure(struct isp_ccdc_device *ccdc) unsigned int depth_in = 0; struct media_pad *pad; unsigned long flags; + unsigned int bridge; unsigned int shift; u32 syn_mode; u32 ccdc_pattern; @@ -1138,28 +1125,31 @@ static void ccdc_configure(struct isp_ccdc_device *ccdc) pdata = &((struct isp_v4l2_subdevs_group *)sensor->host_priv) ->bus.parallel; - /* Compute shift value for lane shifter to configure the bridge. */ + /* Compute the lane shifter shift value and enable the bridge when the + * input format is YUV. + */ fmt_src.pad = pad->index; fmt_src.which = V4L2_SUBDEV_FORMAT_ACTIVE; if (!v4l2_subdev_call(sensor, pad, get_fmt, NULL, &fmt_src)) { fmt_info = omap3isp_video_format_info(fmt_src.format.code); - depth_in = fmt_info->bpp; + depth_in = fmt_info->width; } fmt_info = omap3isp_video_format_info (isp->isp_ccdc.formats[CCDC_PAD_SINK].code); - depth_out = fmt_info->bpp; - + depth_out = fmt_info->width; shift = depth_in - depth_out; - omap3isp_configure_bridge(isp, ccdc->input, pdata, shift); - ccdc->syncif.datsz = depth_out; - ccdc->syncif.hdpol = pdata ? pdata->hs_pol : 0; - ccdc->syncif.vdpol = pdata ? pdata->vs_pol : 0; - ccdc_config_sync_if(ccdc, &ccdc->syncif); + if (fmt_info->code == V4L2_MBUS_FMT_YUYV8_2X8) + bridge = ISPCTRL_PAR_BRIDGE_LENDIAN; + else if (fmt_info->code == V4L2_MBUS_FMT_UYVY8_2X8) + bridge = ISPCTRL_PAR_BRIDGE_BENDIAN; + else + bridge = ISPCTRL_PAR_BRIDGE_DISABLE; + + omap3isp_configure_bridge(isp, ccdc->input, pdata, shift, bridge); - /* CCDC_PAD_SINK */ - format = &ccdc->formats[CCDC_PAD_SINK]; + ccdc_config_sync_if(ccdc, pdata, depth_out); syn_mode = isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SYN_MODE); @@ -1178,13 +1168,8 @@ static void ccdc_configure(struct isp_ccdc_device *ccdc) else syn_mode &= ~ISPCCDC_SYN_MODE_SDR2RSZ; - /* Use PACK8 mode for 1byte per pixel formats. */ - if (omap3isp_video_format_info(format->code)->bpp <= 8) - syn_mode |= ISPCCDC_SYN_MODE_PACK8; - else - syn_mode &= ~ISPCCDC_SYN_MODE_PACK8; - - isp_reg_writel(isp, syn_mode, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SYN_MODE); + /* CCDC_PAD_SINK */ + format = &ccdc->formats[CCDC_PAD_SINK]; /* Mosaic filter */ switch (format->code) { @@ -1215,6 +1200,7 @@ static void ccdc_configure(struct isp_ccdc_device *ccdc) OMAP3_ISP_IOMEM_CCDC, ISPCCDC_VDINT); /* CCDC_PAD_SOURCE_OF */ + format = &ccdc->formats[CCDC_PAD_SOURCE_OF]; crop = &ccdc->crop; isp_reg_writel(isp, (crop->left << ISPCCDC_HORZ_INFO_SPH_SHIFT) | @@ -1228,6 +1214,24 @@ static void ccdc_configure(struct isp_ccdc_device *ccdc) ccdc_config_outlineoffset(ccdc, ccdc->video_out.bpl_value, 0, 0); + /* The CCDC outputs data in UYVY order by default. Swap bytes to get + * YUYV. + */ + if (format->code == V4L2_MBUS_FMT_YUYV8_1X16) + isp_reg_set(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CFG, + ISPCCDC_CFG_BSWD); + else + isp_reg_clr(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CFG, + ISPCCDC_CFG_BSWD); + + /* Use PACK8 mode for 1byte per pixel formats. */ + if (omap3isp_video_format_info(format->code)->width <= 8) + syn_mode |= ISPCCDC_SYN_MODE_PACK8; + else + syn_mode &= ~ISPCCDC_SYN_MODE_PACK8; + + isp_reg_writel(isp, syn_mode, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SYN_MODE); + /* CCDC_PAD_SOURCE_VP */ format = &ccdc->formats[CCDC_PAD_SOURCE_VP]; @@ -1242,6 +1246,7 @@ static void ccdc_configure(struct isp_ccdc_device *ccdc) (format->height << ISPCCDC_VP_OUT_VERT_NUM_SHIFT), OMAP3_ISP_IOMEM_CCDC, ISPCCDC_VP_OUT); + /* Lens shading correction. */ spin_lock_irqsave(&ccdc->lsc.req_lock, flags); if (ccdc->lsc.request == NULL) goto unlock; @@ -1701,7 +1706,7 @@ static long ccdc_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) } static int ccdc_subscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh, - struct v4l2_event_subscription *sub) + const struct v4l2_event_subscription *sub) { if (sub->type != V4L2_EVENT_FRAME_SYNC) return -EINVAL; @@ -1714,7 +1719,7 @@ static int ccdc_subscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh, } static int ccdc_unsubscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh, - struct v4l2_event_subscription *sub) + const struct v4l2_event_subscription *sub) { return v4l2_event_unsubscribe(fh, sub); } @@ -1819,8 +1824,8 @@ ccdc_try_format(struct isp_ccdc_device *ccdc, struct v4l2_subdev_fh *fh, unsigned int pad, struct v4l2_mbus_framefmt *fmt, enum v4l2_subdev_format_whence which) { - struct v4l2_mbus_framefmt *format; const struct isp_format_info *info; + enum v4l2_mbus_pixelcode pixelcode; unsigned int width = fmt->width; unsigned int height = fmt->height; struct v4l2_rect *crop; @@ -1828,9 +1833,6 @@ ccdc_try_format(struct isp_ccdc_device *ccdc, struct v4l2_subdev_fh *fh, switch (pad) { case CCDC_PAD_SINK: - /* TODO: If the CCDC output formatter pad is connected directly - * to the resizer, only YUV formats can be used. - */ for (i = 0; i < ARRAY_SIZE(ccdc_fmts); i++) { if (fmt->code == ccdc_fmts[i]) break; @@ -1846,8 +1848,26 @@ ccdc_try_format(struct isp_ccdc_device *ccdc, struct v4l2_subdev_fh *fh, break; case CCDC_PAD_SOURCE_OF: - format = __ccdc_get_format(ccdc, fh, CCDC_PAD_SINK, which); - memcpy(fmt, format, sizeof(*fmt)); + pixelcode = fmt->code; + *fmt = *__ccdc_get_format(ccdc, fh, CCDC_PAD_SINK, which); + + /* YUV formats are converted from 2X8 to 1X16 by the bridge and + * can be byte-swapped. + */ + if (fmt->code == V4L2_MBUS_FMT_YUYV8_2X8 || + fmt->code == V4L2_MBUS_FMT_UYVY8_2X8) { + /* Use the user requested format if YUV. */ + if (pixelcode == V4L2_MBUS_FMT_YUYV8_2X8 || + pixelcode == V4L2_MBUS_FMT_UYVY8_2X8 || + pixelcode == V4L2_MBUS_FMT_YUYV8_1X16 || + pixelcode == V4L2_MBUS_FMT_UYVY8_1X16) + fmt->code = pixelcode; + + if (fmt->code == V4L2_MBUS_FMT_YUYV8_2X8) + fmt->code = V4L2_MBUS_FMT_YUYV8_1X16; + else if (fmt->code == V4L2_MBUS_FMT_UYVY8_2X8) + fmt->code = V4L2_MBUS_FMT_UYVY8_1X16; + } /* Hardcode the output size to the crop rectangle size. */ crop = __ccdc_get_crop(ccdc, fh, which); @@ -1856,13 +1876,17 @@ ccdc_try_format(struct isp_ccdc_device *ccdc, struct v4l2_subdev_fh *fh, break; case CCDC_PAD_SOURCE_VP: - format = __ccdc_get_format(ccdc, fh, CCDC_PAD_SINK, which); - memcpy(fmt, format, sizeof(*fmt)); + *fmt = *__ccdc_get_format(ccdc, fh, CCDC_PAD_SINK, which); /* The video port interface truncates the data to 10 bits. */ info = omap3isp_video_format_info(fmt->code); fmt->code = info->truncated; + /* YUV formats are not supported by the video port. */ + if (fmt->code == V4L2_MBUS_FMT_YUYV8_2X8 || + fmt->code == V4L2_MBUS_FMT_UYVY8_2X8) + fmt->code = 0; + /* The number of lines that can be clocked out from the video * port output must be at least one line less than the number * of input lines. @@ -1945,14 +1969,46 @@ static int ccdc_enum_mbus_code(struct v4l2_subdev *sd, break; case CCDC_PAD_SOURCE_OF: + format = __ccdc_get_format(ccdc, fh, code->pad, + V4L2_SUBDEV_FORMAT_TRY); + + if (format->code == V4L2_MBUS_FMT_YUYV8_2X8 || + format->code == V4L2_MBUS_FMT_UYVY8_2X8) { + /* In YUV mode the CCDC can swap bytes. */ + if (code->index == 0) + code->code = V4L2_MBUS_FMT_YUYV8_1X16; + else if (code->index == 1) + code->code = V4L2_MBUS_FMT_UYVY8_1X16; + else + return -EINVAL; + } else { + /* In raw mode, no configurable format confversion is + * available. + */ + if (code->index == 0) + code->code = format->code; + else + return -EINVAL; + } + break; + case CCDC_PAD_SOURCE_VP: - /* No format conversion inside CCDC */ + /* The CCDC supports no configurable format conversion + * compatible with the video port. Enumerate a single output + * format code. + */ if (code->index != 0) return -EINVAL; - format = __ccdc_get_format(ccdc, fh, CCDC_PAD_SINK, + format = __ccdc_get_format(ccdc, fh, code->pad, V4L2_SUBDEV_FORMAT_TRY); + /* A pixel code equal to 0 means that the video port doesn't + * support the input format. Don't enumerate any pixel code. + */ + if (format->code == 0) + return -EINVAL; + code->code = format->code; break; @@ -2182,7 +2238,7 @@ static bool ccdc_is_shiftable(enum v4l2_mbus_pixelcode in, if (in_info->flavor != out_info->flavor) return false; - return in_info->bpp - out_info->bpp + additional_shift <= 6; + return in_info->width - out_info->width + additional_shift <= 6; } static int ccdc_link_validate(struct v4l2_subdev *sd, @@ -2487,14 +2543,6 @@ int omap3isp_ccdc_init(struct isp_device *isp) INIT_LIST_HEAD(&ccdc->lsc.free_queue); spin_lock_init(&ccdc->lsc.req_lock); - ccdc->syncif.ccdc_mastermode = 0; - ccdc->syncif.datapol = 0; - ccdc->syncif.datsz = 0; - ccdc->syncif.fldmode = 0; - ccdc->syncif.fldout = 0; - ccdc->syncif.fldpol = 0; - ccdc->syncif.fldstat = 0; - ccdc->clamp.oblen = 0; ccdc->clamp.dcsubval = 0; diff --git a/drivers/media/video/omap3isp/ispccdc.h b/drivers/media/platform/omap3isp/ispccdc.h index 890f6b3a68fd..a5da9e19edbf 100644 --- a/drivers/media/video/omap3isp/ispccdc.h +++ b/drivers/media/platform/omap3isp/ispccdc.h @@ -46,40 +46,6 @@ enum ccdc_input_entity { #define OMAP3ISP_CCDC_NEVENTS 16 -/* - * struct ispccdc_syncif - Structure for Sync Interface between sensor and CCDC - * @ccdc_mastermode: Master mode. 1 - Master, 0 - Slave. - * @fldstat: Field state. 0 - Odd Field, 1 - Even Field. - * @datsz: Data size. - * @fldmode: 0 - Progressive, 1 - Interlaced. - * @datapol: 0 - Positive, 1 - Negative. - * @fldpol: 0 - Positive, 1 - Negative. - * @hdpol: 0 - Positive, 1 - Negative. - * @vdpol: 0 - Positive, 1 - Negative. - * @fldout: 0 - Input, 1 - Output. - * @hs_width: Width of the Horizontal Sync pulse, used for HS/VS Output. - * @vs_width: Width of the Vertical Sync pulse, used for HS/VS Output. - * @ppln: Number of pixels per line, used for HS/VS Output. - * @hlprf: Number of half lines per frame, used for HS/VS Output. - * @bt_r656_en: 1 - Enable ITU-R BT656 mode, 0 - Sync mode. - */ -struct ispccdc_syncif { - u8 ccdc_mastermode; - u8 fldstat; - u8 datsz; - u8 fldmode; - u8 datapol; - u8 fldpol; - u8 hdpol; - u8 vdpol; - u8 fldout; - u8 hs_width; - u8 vs_width; - u8 ppln; - u8 hlprf; - u8 bt_r656_en; -}; - enum ispccdc_lsc_state { LSC_STATE_STOPPED = 0, LSC_STATE_STOPPING = 1, @@ -153,7 +119,6 @@ struct ispccdc_lsc { * @lsc: Lens shading compensation configuration * @update: Bitmask of controls to update during the next interrupt * @shadow_update: Controls update in progress by userspace - * @syncif: Interface synchronization configuration * @underrun: A buffer underrun occurred and a new buffer has been queued * @state: Streaming state * @lock: Serializes shadow_update with interrupt handler @@ -182,8 +147,6 @@ struct isp_ccdc_device { unsigned int update; unsigned int shadow_update; - struct ispccdc_syncif syncif; - unsigned int underrun:1; enum isp_pipeline_stream_state state; spinlock_t lock; diff --git a/drivers/media/video/omap3isp/ispccp2.c b/drivers/media/platform/omap3isp/ispccp2.c index 85f0de85f37c..85f0de85f37c 100644 --- a/drivers/media/video/omap3isp/ispccp2.c +++ b/drivers/media/platform/omap3isp/ispccp2.c diff --git a/drivers/media/video/omap3isp/ispccp2.h b/drivers/media/platform/omap3isp/ispccp2.h index 76d65f4576ef..76d65f4576ef 100644 --- a/drivers/media/video/omap3isp/ispccp2.h +++ b/drivers/media/platform/omap3isp/ispccp2.h diff --git a/drivers/media/video/omap3isp/ispcsi2.c b/drivers/media/platform/omap3isp/ispcsi2.c index a1724362b6d5..6a3ff792af7d 100644 --- a/drivers/media/video/omap3isp/ispcsi2.c +++ b/drivers/media/platform/omap3isp/ispcsi2.c @@ -96,11 +96,12 @@ static const unsigned int csi2_input_fmts[] = { V4L2_MBUS_FMT_SBGGR10_DPCM8_1X8, V4L2_MBUS_FMT_SGBRG10_1X10, V4L2_MBUS_FMT_SGBRG10_DPCM8_1X8, + V4L2_MBUS_FMT_YUYV8_2X8, }; /* To set the format on the CSI2 requires a mapping function that takes * the following inputs: - * - 2 different formats (at this time) + * - 3 different formats (at this time) * - 2 destinations (mem, vp+mem) (vp only handled separately) * - 2 decompression options (on, off) * - 2 isp revisions (certain format must be handled differently on OMAP3630) @@ -108,7 +109,7 @@ static const unsigned int csi2_input_fmts[] = { * Array indices as follows: [format][dest][decompr][is_3630] * Not all combinations are valid. 0 means invalid. */ -static const u16 __csi2_fmt_map[2][2][2][2] = { +static const u16 __csi2_fmt_map[3][2][2][2] = { /* RAW10 formats */ { /* Output to memory */ @@ -147,6 +148,25 @@ static const u16 __csi2_fmt_map[2][2][2][2] = { CSI2_USERDEF_8BIT_DATA1_DPCM10_VP }, }, }, + /* YUYV8 2X8 formats */ + { + /* Output to memory */ + { + /* No DPCM decompression */ + { CSI2_PIX_FMT_YUV422_8BIT, + CSI2_PIX_FMT_YUV422_8BIT }, + /* DPCM decompression */ + { 0, 0 }, + }, + /* Output to both */ + { + /* No DPCM decompression */ + { CSI2_PIX_FMT_YUV422_8BIT_VP, + CSI2_PIX_FMT_YUV422_8BIT_VP }, + /* DPCM decompression */ + { 0, 0 }, + }, + }, }; /* @@ -173,6 +193,9 @@ static u16 csi2_ctx_map_format(struct isp_csi2_device *csi2) case V4L2_MBUS_FMT_SGBRG10_DPCM8_1X8: fmtidx = 1; break; + case V4L2_MBUS_FMT_YUYV8_2X8: + fmtidx = 2; + break; default: WARN(1, KERN_ERR "CSI2: pixel format %08x unsupported!\n", fmt->code); diff --git a/drivers/media/video/omap3isp/ispcsi2.h b/drivers/media/platform/omap3isp/ispcsi2.h index c57729b7e86e..c57729b7e86e 100644 --- a/drivers/media/video/omap3isp/ispcsi2.h +++ b/drivers/media/platform/omap3isp/ispcsi2.h diff --git a/drivers/media/video/omap3isp/ispcsiphy.c b/drivers/media/platform/omap3isp/ispcsiphy.c index 348f67ebbbc9..348f67ebbbc9 100644 --- a/drivers/media/video/omap3isp/ispcsiphy.c +++ b/drivers/media/platform/omap3isp/ispcsiphy.c diff --git a/drivers/media/video/omap3isp/ispcsiphy.h b/drivers/media/platform/omap3isp/ispcsiphy.h index e93a661e65d9..e93a661e65d9 100644 --- a/drivers/media/video/omap3isp/ispcsiphy.h +++ b/drivers/media/platform/omap3isp/ispcsiphy.h diff --git a/drivers/media/video/omap3isp/isph3a.h b/drivers/media/platform/omap3isp/isph3a.h index fb09fd4ca755..fb09fd4ca755 100644 --- a/drivers/media/video/omap3isp/isph3a.h +++ b/drivers/media/platform/omap3isp/isph3a.h diff --git a/drivers/media/video/omap3isp/isph3a_aewb.c b/drivers/media/platform/omap3isp/isph3a_aewb.c index a3c76bf18175..036e9961d027 100644 --- a/drivers/media/video/omap3isp/isph3a_aewb.c +++ b/drivers/media/platform/omap3isp/isph3a_aewb.c @@ -93,17 +93,11 @@ static void h3a_aewb_enable(struct ispstat *aewb, int enable) if (enable) { isp_reg_set(aewb->isp, OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR, ISPH3A_PCR_AEW_EN); - /* This bit is already set if AF is enabled */ - if (aewb->isp->isp_af.state != ISPSTAT_ENABLED) - isp_reg_set(aewb->isp, OMAP3_ISP_IOMEM_MAIN, ISP_CTRL, - ISPCTRL_H3A_CLK_EN); + omap3isp_subclk_enable(aewb->isp, OMAP3_ISP_SUBCLK_AEWB); } else { isp_reg_clr(aewb->isp, OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR, ISPH3A_PCR_AEW_EN); - /* This bit can't be cleared if AF is enabled */ - if (aewb->isp->isp_af.state != ISPSTAT_ENABLED) - isp_reg_clr(aewb->isp, OMAP3_ISP_IOMEM_MAIN, ISP_CTRL, - ISPCTRL_H3A_CLK_EN); + omap3isp_subclk_disable(aewb->isp, OMAP3_ISP_SUBCLK_AEWB); } } diff --git a/drivers/media/video/omap3isp/isph3a_af.c b/drivers/media/platform/omap3isp/isph3a_af.c index 58e0bc414899..42ccce318d5d 100644 --- a/drivers/media/video/omap3isp/isph3a_af.c +++ b/drivers/media/platform/omap3isp/isph3a_af.c @@ -143,17 +143,11 @@ static void h3a_af_enable(struct ispstat *af, int enable) if (enable) { isp_reg_set(af->isp, OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR, ISPH3A_PCR_AF_EN); - /* This bit is already set if AEWB is enabled */ - if (af->isp->isp_aewb.state != ISPSTAT_ENABLED) - isp_reg_set(af->isp, OMAP3_ISP_IOMEM_MAIN, ISP_CTRL, - ISPCTRL_H3A_CLK_EN); + omap3isp_subclk_enable(af->isp, OMAP3_ISP_SUBCLK_AF); } else { isp_reg_clr(af->isp, OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR, ISPH3A_PCR_AF_EN); - /* This bit can't be cleared if AEWB is enabled */ - if (af->isp->isp_aewb.state != ISPSTAT_ENABLED) - isp_reg_clr(af->isp, OMAP3_ISP_IOMEM_MAIN, ISP_CTRL, - ISPCTRL_H3A_CLK_EN); + omap3isp_subclk_disable(af->isp, OMAP3_ISP_SUBCLK_AF); } } diff --git a/drivers/media/video/omap3isp/isphist.c b/drivers/media/platform/omap3isp/isphist.c index 1163907bcddc..d1a8dee5e1ca 100644 --- a/drivers/media/video/omap3isp/isphist.c +++ b/drivers/media/platform/omap3isp/isphist.c @@ -167,13 +167,11 @@ static void hist_enable(struct ispstat *hist, int enable) if (enable) { isp_reg_set(hist->isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_PCR, ISPHIST_PCR_ENABLE); - isp_reg_set(hist->isp, OMAP3_ISP_IOMEM_MAIN, ISP_CTRL, - ISPCTRL_HIST_CLK_EN); + omap3isp_subclk_enable(hist->isp, OMAP3_ISP_SUBCLK_HIST); } else { isp_reg_clr(hist->isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_PCR, ISPHIST_PCR_ENABLE); - isp_reg_clr(hist->isp, OMAP3_ISP_IOMEM_MAIN, ISP_CTRL, - ISPCTRL_HIST_CLK_EN); + omap3isp_subclk_disable(hist->isp, OMAP3_ISP_SUBCLK_HIST); } } diff --git a/drivers/media/video/omap3isp/isphist.h b/drivers/media/platform/omap3isp/isphist.h index 0b2a38ec94c4..0b2a38ec94c4 100644 --- a/drivers/media/video/omap3isp/isphist.h +++ b/drivers/media/platform/omap3isp/isphist.h diff --git a/drivers/media/video/omap3isp/isppreview.c b/drivers/media/platform/omap3isp/isppreview.c index 53f5a703e31a..1ae1c0909ed1 100644 --- a/drivers/media/video/omap3isp/isppreview.c +++ b/drivers/media/platform/omap3isp/isppreview.c @@ -131,7 +131,7 @@ static struct omap3isp_prev_csc flr_prev_csc = { * CFA Filter Coefficient Table * */ -static u32 cfa_coef_table[] = { +static u32 cfa_coef_table[4][OMAP3ISP_PREV_CFA_BLK_SIZE] = { #include "cfa_coef_table.h" }; @@ -157,85 +157,74 @@ static u32 luma_enhance_table[] = { }; /* - * preview_enable_invalaw - Enable/Disable Inverse A-Law module in Preview. - * @enable: 1 - Reverse the A-Law done in CCDC. + * preview_config_luma_enhancement - Configure the Luminance Enhancement table */ static void -preview_enable_invalaw(struct isp_prev_device *prev, u8 enable) +preview_config_luma_enhancement(struct isp_prev_device *prev, + const struct prev_params *params) { struct isp_device *isp = to_isp_device(prev); + const struct omap3isp_prev_luma *yt = ¶ms->luma; + unsigned int i; - if (enable) - isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, - ISPPRV_PCR_WIDTH | ISPPRV_PCR_INVALAW); - else - isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, - ISPPRV_PCR_WIDTH | ISPPRV_PCR_INVALAW); + isp_reg_writel(isp, ISPPRV_YENH_TABLE_ADDR, + OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR); + for (i = 0; i < OMAP3ISP_PREV_YENH_TBL_SIZE; i++) { + isp_reg_writel(isp, yt->table[i], + OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_DATA); + } } /* - * preview_enable_drkframe_capture - Enable/Disable of the darkframe capture. - * @prev - - * @enable: 1 - Enable, 0 - Disable - * - * NOTE: PRV_WSDR_ADDR and PRV_WADD_OFFSET must be set also - * The process is applied for each captured frame. + * preview_enable_luma_enhancement - Enable/disable Luminance Enhancement */ static void -preview_enable_drkframe_capture(struct isp_prev_device *prev, u8 enable) +preview_enable_luma_enhancement(struct isp_prev_device *prev, bool enable) { struct isp_device *isp = to_isp_device(prev); if (enable) isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, - ISPPRV_PCR_DRKFCAP); + ISPPRV_PCR_YNENHEN); else isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, - ISPPRV_PCR_DRKFCAP); + ISPPRV_PCR_YNENHEN); } /* - * preview_enable_drkframe - Enable/Disable of the darkframe subtract. - * @enable: 1 - Acquires memory bandwidth since the pixels in each frame is - * subtracted with the pixels in the current frame. - * - * The process is applied for each captured frame. + * preview_enable_invalaw - Enable/disable Inverse A-Law decompression */ -static void -preview_enable_drkframe(struct isp_prev_device *prev, u8 enable) +static void preview_enable_invalaw(struct isp_prev_device *prev, bool enable) { struct isp_device *isp = to_isp_device(prev); if (enable) isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, - ISPPRV_PCR_DRKFEN); + ISPPRV_PCR_WIDTH | ISPPRV_PCR_INVALAW); else isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, - ISPPRV_PCR_DRKFEN); + ISPPRV_PCR_WIDTH | ISPPRV_PCR_INVALAW); } /* - * preview_config_drkf_shadcomp - Configures shift value in shading comp. - * @scomp_shtval: 3bit value of shift used in shading compensation. + * preview_config_hmed - Configure the Horizontal Median Filter */ -static void -preview_config_drkf_shadcomp(struct isp_prev_device *prev, - const void *scomp_shtval) +static void preview_config_hmed(struct isp_prev_device *prev, + const struct prev_params *params) { struct isp_device *isp = to_isp_device(prev); - const u32 *shtval = scomp_shtval; + const struct omap3isp_prev_hmed *hmed = ¶ms->hmed; - isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, - ISPPRV_PCR_SCOMP_SFT_MASK, - *shtval << ISPPRV_PCR_SCOMP_SFT_SHIFT); + isp_reg_writel(isp, (hmed->odddist == 1 ? 0 : ISPPRV_HMED_ODDDIST) | + (hmed->evendist == 1 ? 0 : ISPPRV_HMED_EVENDIST) | + (hmed->thres << ISPPRV_HMED_THRESHOLD_SHIFT), + OMAP3_ISP_IOMEM_PREV, ISPPRV_HMED); } /* - * preview_enable_hmed - Enables/Disables of the Horizontal Median Filter. - * @enable: 1 - Enables Horizontal Median Filter. + * preview_enable_hmed - Enable/disable the Horizontal Median Filter */ -static void -preview_enable_hmed(struct isp_prev_device *prev, u8 enable) +static void preview_enable_hmed(struct isp_prev_device *prev, bool enable) { struct isp_device *isp = to_isp_device(prev); @@ -248,81 +237,27 @@ preview_enable_hmed(struct isp_prev_device *prev, u8 enable) } /* - * preview_config_hmed - Configures the Horizontal Median Filter. - * @prev_hmed: Structure containing the odd and even distance between the - * pixels in the image along with the filter threshold. - */ -static void -preview_config_hmed(struct isp_prev_device *prev, const void *prev_hmed) -{ - struct isp_device *isp = to_isp_device(prev); - const struct omap3isp_prev_hmed *hmed = prev_hmed; - - isp_reg_writel(isp, (hmed->odddist == 1 ? 0 : ISPPRV_HMED_ODDDIST) | - (hmed->evendist == 1 ? 0 : ISPPRV_HMED_EVENDIST) | - (hmed->thres << ISPPRV_HMED_THRESHOLD_SHIFT), - OMAP3_ISP_IOMEM_PREV, ISPPRV_HMED); -} - -/* - * preview_config_noisefilter - Configures the Noise Filter. - * @prev_nf: Structure containing the noisefilter table, strength to be used - * for the noise filter and the defect correction enable flag. - */ -static void -preview_config_noisefilter(struct isp_prev_device *prev, const void *prev_nf) -{ - struct isp_device *isp = to_isp_device(prev); - const struct omap3isp_prev_nf *nf = prev_nf; - unsigned int i; - - isp_reg_writel(isp, nf->spread, OMAP3_ISP_IOMEM_PREV, ISPPRV_NF); - isp_reg_writel(isp, ISPPRV_NF_TABLE_ADDR, - OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR); - for (i = 0; i < OMAP3ISP_PREV_NF_TBL_SIZE; i++) { - isp_reg_writel(isp, nf->table[i], - OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_DATA); - } -} - -/* - * preview_config_dcor - Configures the defect correction - * @prev_dcor: Structure containing the defect correct thresholds - */ -static void -preview_config_dcor(struct isp_prev_device *prev, const void *prev_dcor) -{ - struct isp_device *isp = to_isp_device(prev); - const struct omap3isp_prev_dcor *dcor = prev_dcor; - - isp_reg_writel(isp, dcor->detect_correct[0], - OMAP3_ISP_IOMEM_PREV, ISPPRV_CDC_THR0); - isp_reg_writel(isp, dcor->detect_correct[1], - OMAP3_ISP_IOMEM_PREV, ISPPRV_CDC_THR1); - isp_reg_writel(isp, dcor->detect_correct[2], - OMAP3_ISP_IOMEM_PREV, ISPPRV_CDC_THR2); - isp_reg_writel(isp, dcor->detect_correct[3], - OMAP3_ISP_IOMEM_PREV, ISPPRV_CDC_THR3); - isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, - ISPPRV_PCR_DCCOUP, - dcor->couplet_mode_en ? ISPPRV_PCR_DCCOUP : 0); -} - -/* - * preview_config_cfa - Configures the CFA Interpolation parameters. - * @prev_cfa: Structure containing the CFA interpolation table, CFA format - * in the image, vertical and horizontal gradient threshold. - */ -static void -preview_config_cfa(struct isp_prev_device *prev, const void *prev_cfa) -{ + * preview_config_cfa - Configure CFA Interpolation for Bayer formats + * + * The CFA table is organised in four blocks, one per Bayer component. The + * hardware expects blocks to follow the Bayer order of the input data, while + * the driver stores the table in GRBG order in memory. The blocks need to be + * reordered to support non-GRBG Bayer patterns. + */ +static void preview_config_cfa(struct isp_prev_device *prev, + const struct prev_params *params) +{ + static const unsigned int cfa_coef_order[4][4] = { + { 0, 1, 2, 3 }, /* GRBG */ + { 1, 0, 3, 2 }, /* RGGB */ + { 2, 3, 0, 1 }, /* BGGR */ + { 3, 2, 1, 0 }, /* GBRG */ + }; + const unsigned int *order = cfa_coef_order[prev->params.cfa_order]; + const struct omap3isp_prev_cfa *cfa = ¶ms->cfa; struct isp_device *isp = to_isp_device(prev); - const struct omap3isp_prev_cfa *cfa = prev_cfa; unsigned int i; - - isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, - ISPPRV_PCR_CFAFMT_MASK, - cfa->format << ISPPRV_PCR_CFAFMT_SHIFT); + unsigned int j; isp_reg_writel(isp, (cfa->gradthrs_vert << ISPPRV_CFA_GRADTH_VER_SHIFT) | @@ -332,73 +267,24 @@ preview_config_cfa(struct isp_prev_device *prev, const void *prev_cfa) isp_reg_writel(isp, ISPPRV_CFA_TABLE_ADDR, OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR); - for (i = 0; i < OMAP3ISP_PREV_CFA_TBL_SIZE; i++) { - isp_reg_writel(isp, cfa->table[i], - OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_DATA); - } -} - -/* - * preview_config_gammacorrn - Configures the Gamma Correction table values - * @gtable: Structure containing the table for red, blue, green gamma table. - */ -static void -preview_config_gammacorrn(struct isp_prev_device *prev, const void *gtable) -{ - struct isp_device *isp = to_isp_device(prev); - const struct omap3isp_prev_gtables *gt = gtable; - unsigned int i; - - isp_reg_writel(isp, ISPPRV_REDGAMMA_TABLE_ADDR, - OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR); - for (i = 0; i < OMAP3ISP_PREV_GAMMA_TBL_SIZE; i++) - isp_reg_writel(isp, gt->red[i], OMAP3_ISP_IOMEM_PREV, - ISPPRV_SET_TBL_DATA); - - isp_reg_writel(isp, ISPPRV_GREENGAMMA_TABLE_ADDR, - OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR); - for (i = 0; i < OMAP3ISP_PREV_GAMMA_TBL_SIZE; i++) - isp_reg_writel(isp, gt->green[i], OMAP3_ISP_IOMEM_PREV, - ISPPRV_SET_TBL_DATA); - - isp_reg_writel(isp, ISPPRV_BLUEGAMMA_TABLE_ADDR, - OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR); - for (i = 0; i < OMAP3ISP_PREV_GAMMA_TBL_SIZE; i++) - isp_reg_writel(isp, gt->blue[i], OMAP3_ISP_IOMEM_PREV, - ISPPRV_SET_TBL_DATA); -} - -/* - * preview_config_luma_enhancement - Sets the Luminance Enhancement table. - * @ytable: Structure containing the table for Luminance Enhancement table. - */ -static void -preview_config_luma_enhancement(struct isp_prev_device *prev, - const void *ytable) -{ - struct isp_device *isp = to_isp_device(prev); - const struct omap3isp_prev_luma *yt = ytable; - unsigned int i; + for (i = 0; i < 4; ++i) { + const __u32 *block = cfa->table[order[i]]; - isp_reg_writel(isp, ISPPRV_YENH_TABLE_ADDR, - OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR); - for (i = 0; i < OMAP3ISP_PREV_YENH_TBL_SIZE; i++) { - isp_reg_writel(isp, yt->table[i], - OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_DATA); + for (j = 0; j < OMAP3ISP_PREV_CFA_BLK_SIZE; ++j) + isp_reg_writel(isp, block[j], OMAP3_ISP_IOMEM_PREV, + ISPPRV_SET_TBL_DATA); } } /* - * preview_config_chroma_suppression - Configures the Chroma Suppression. - * @csup: Structure containing the threshold value for suppression - * and the hypass filter enable flag. + * preview_config_chroma_suppression - Configure Chroma Suppression */ static void preview_config_chroma_suppression(struct isp_prev_device *prev, - const void *csup) + const struct prev_params *params) { struct isp_device *isp = to_isp_device(prev); - const struct omap3isp_prev_csup *cs = csup; + const struct omap3isp_prev_csup *cs = ¶ms->csup; isp_reg_writel(isp, cs->gain | (cs->thres << ISPPRV_CSUP_THRES_SHIFT) | @@ -407,80 +293,10 @@ preview_config_chroma_suppression(struct isp_prev_device *prev, } /* - * preview_enable_noisefilter - Enables/Disables the Noise Filter. - * @enable: 1 - Enables the Noise Filter. - */ -static void -preview_enable_noisefilter(struct isp_prev_device *prev, u8 enable) -{ - struct isp_device *isp = to_isp_device(prev); - - if (enable) - isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, - ISPPRV_PCR_NFEN); - else - isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, - ISPPRV_PCR_NFEN); -} - -/* - * preview_enable_dcor - Enables/Disables the defect correction. - * @enable: 1 - Enables the defect correction. - */ -static void -preview_enable_dcor(struct isp_prev_device *prev, u8 enable) -{ - struct isp_device *isp = to_isp_device(prev); - - if (enable) - isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, - ISPPRV_PCR_DCOREN); - else - isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, - ISPPRV_PCR_DCOREN); -} - -/* - * preview_enable_gammabypass - Enables/Disables the GammaByPass - * @enable: 1 - Bypasses Gamma - 10bit input is cropped to 8MSB. - * 0 - Goes through Gamma Correction. input and output is 10bit. + * preview_enable_chroma_suppression - Enable/disable Chrominance Suppression */ static void -preview_enable_gammabypass(struct isp_prev_device *prev, u8 enable) -{ - struct isp_device *isp = to_isp_device(prev); - - if (enable) - isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, - ISPPRV_PCR_GAMMA_BYPASS); - else - isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, - ISPPRV_PCR_GAMMA_BYPASS); -} - -/* - * preview_enable_luma_enhancement - Enables/Disables Luminance Enhancement - * @enable: 1 - Enable the Luminance Enhancement. - */ -static void -preview_enable_luma_enhancement(struct isp_prev_device *prev, u8 enable) -{ - struct isp_device *isp = to_isp_device(prev); - - if (enable) - isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, - ISPPRV_PCR_YNENHEN); - else - isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, - ISPPRV_PCR_YNENHEN); -} - -/* - * preview_enable_chroma_suppression - Enables/Disables Chrominance Suppr. - * @enable: 1 - Enable the Chrominance Suppression. - */ -static void -preview_enable_chroma_suppression(struct isp_prev_device *prev, u8 enable) +preview_enable_chroma_suppression(struct isp_prev_device *prev, bool enable) { struct isp_device *isp = to_isp_device(prev); @@ -493,17 +309,16 @@ preview_enable_chroma_suppression(struct isp_prev_device *prev, u8 enable) } /* - * preview_config_whitebalance - Configures the White Balance parameters. - * @prev_wbal: Structure containing the digital gain and white balance - * coefficient. + * preview_config_whitebalance - Configure White Balance parameters * * Coefficient matrix always with default values. */ static void -preview_config_whitebalance(struct isp_prev_device *prev, const void *prev_wbal) +preview_config_whitebalance(struct isp_prev_device *prev, + const struct prev_params *params) { struct isp_device *isp = to_isp_device(prev); - const struct omap3isp_prev_wbal *wbal = prev_wbal; + const struct omap3isp_prev_wbal *wbal = ¶ms->wbal; u32 val; isp_reg_writel(isp, wbal->dgain, OMAP3_ISP_IOMEM_PREV, ISPPRV_WB_DGAIN); @@ -535,15 +350,14 @@ preview_config_whitebalance(struct isp_prev_device *prev, const void *prev_wbal) } /* - * preview_config_blkadj - Configures the Black Adjustment parameters. - * @prev_blkadj: Structure containing the black adjustment towards red, green, - * blue. + * preview_config_blkadj - Configure Black Adjustment */ static void -preview_config_blkadj(struct isp_prev_device *prev, const void *prev_blkadj) +preview_config_blkadj(struct isp_prev_device *prev, + const struct prev_params *params) { struct isp_device *isp = to_isp_device(prev); - const struct omap3isp_prev_blkadj *blkadj = prev_blkadj; + const struct omap3isp_prev_blkadj *blkadj = ¶ms->blkadj; isp_reg_writel(isp, (blkadj->blue << ISPPRV_BLKADJOFF_B_SHIFT) | (blkadj->green << ISPPRV_BLKADJOFF_G_SHIFT) | @@ -552,15 +366,14 @@ preview_config_blkadj(struct isp_prev_device *prev, const void *prev_blkadj) } /* - * preview_config_rgb_blending - Configures the RGB-RGB Blending matrix. - * @rgb2rgb: Structure containing the rgb to rgb blending matrix and the rgb - * offset. + * preview_config_rgb_blending - Configure RGB-RGB Blending */ static void -preview_config_rgb_blending(struct isp_prev_device *prev, const void *rgb2rgb) +preview_config_rgb_blending(struct isp_prev_device *prev, + const struct prev_params *params) { struct isp_device *isp = to_isp_device(prev); - const struct omap3isp_prev_rgbtorgb *rgbrgb = rgb2rgb; + const struct omap3isp_prev_rgbtorgb *rgbrgb = ¶ms->rgb2rgb; u32 val; val = (rgbrgb->matrix[0][0] & 0xfff) << ISPPRV_RGB_MAT1_MTX_RR_SHIFT; @@ -591,15 +404,14 @@ preview_config_rgb_blending(struct isp_prev_device *prev, const void *rgb2rgb) } /* - * Configures the color space conversion (RGB toYCbYCr) matrix - * @prev_csc: Structure containing the RGB to YCbYCr matrix and the - * YCbCr offset. + * preview_config_csc - Configure Color Space Conversion (RGB to YCbYCr) */ static void -preview_config_csc(struct isp_prev_device *prev, const void *prev_csc) +preview_config_csc(struct isp_prev_device *prev, + const struct prev_params *params) { struct isp_device *isp = to_isp_device(prev); - const struct omap3isp_prev_csc *csc = prev_csc; + const struct omap3isp_prev_csc *csc = ¶ms->csc; u32 val; val = (csc->matrix[0][0] & 0x3ff) << ISPPRV_CSC0_RY_SHIFT; @@ -624,6 +436,208 @@ preview_config_csc(struct isp_prev_device *prev, const void *prev_csc) } /* + * preview_config_yc_range - Configure the max and min Y and C values + */ +static void +preview_config_yc_range(struct isp_prev_device *prev, + const struct prev_params *params) +{ + struct isp_device *isp = to_isp_device(prev); + const struct omap3isp_prev_yclimit *yc = ¶ms->yclimit; + + isp_reg_writel(isp, + yc->maxC << ISPPRV_SETUP_YC_MAXC_SHIFT | + yc->maxY << ISPPRV_SETUP_YC_MAXY_SHIFT | + yc->minC << ISPPRV_SETUP_YC_MINC_SHIFT | + yc->minY << ISPPRV_SETUP_YC_MINY_SHIFT, + OMAP3_ISP_IOMEM_PREV, ISPPRV_SETUP_YC); +} + +/* + * preview_config_dcor - Configure Couplet Defect Correction + */ +static void +preview_config_dcor(struct isp_prev_device *prev, + const struct prev_params *params) +{ + struct isp_device *isp = to_isp_device(prev); + const struct omap3isp_prev_dcor *dcor = ¶ms->dcor; + + isp_reg_writel(isp, dcor->detect_correct[0], + OMAP3_ISP_IOMEM_PREV, ISPPRV_CDC_THR0); + isp_reg_writel(isp, dcor->detect_correct[1], + OMAP3_ISP_IOMEM_PREV, ISPPRV_CDC_THR1); + isp_reg_writel(isp, dcor->detect_correct[2], + OMAP3_ISP_IOMEM_PREV, ISPPRV_CDC_THR2); + isp_reg_writel(isp, dcor->detect_correct[3], + OMAP3_ISP_IOMEM_PREV, ISPPRV_CDC_THR3); + isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, + ISPPRV_PCR_DCCOUP, + dcor->couplet_mode_en ? ISPPRV_PCR_DCCOUP : 0); +} + +/* + * preview_enable_dcor - Enable/disable Couplet Defect Correction + */ +static void preview_enable_dcor(struct isp_prev_device *prev, bool enable) +{ + struct isp_device *isp = to_isp_device(prev); + + if (enable) + isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, + ISPPRV_PCR_DCOREN); + else + isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, + ISPPRV_PCR_DCOREN); +} + +/* + * preview_enable_drkframe_capture - Enable/disable Dark Frame Capture + */ +static void +preview_enable_drkframe_capture(struct isp_prev_device *prev, bool enable) +{ + struct isp_device *isp = to_isp_device(prev); + + if (enable) + isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, + ISPPRV_PCR_DRKFCAP); + else + isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, + ISPPRV_PCR_DRKFCAP); +} + +/* + * preview_enable_drkframe - Enable/disable Dark Frame Subtraction + */ +static void preview_enable_drkframe(struct isp_prev_device *prev, bool enable) +{ + struct isp_device *isp = to_isp_device(prev); + + if (enable) + isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, + ISPPRV_PCR_DRKFEN); + else + isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, + ISPPRV_PCR_DRKFEN); +} + +/* + * preview_config_noisefilter - Configure the Noise Filter + */ +static void +preview_config_noisefilter(struct isp_prev_device *prev, + const struct prev_params *params) +{ + struct isp_device *isp = to_isp_device(prev); + const struct omap3isp_prev_nf *nf = ¶ms->nf; + unsigned int i; + + isp_reg_writel(isp, nf->spread, OMAP3_ISP_IOMEM_PREV, ISPPRV_NF); + isp_reg_writel(isp, ISPPRV_NF_TABLE_ADDR, + OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR); + for (i = 0; i < OMAP3ISP_PREV_NF_TBL_SIZE; i++) { + isp_reg_writel(isp, nf->table[i], + OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_DATA); + } +} + +/* + * preview_enable_noisefilter - Enable/disable the Noise Filter + */ +static void +preview_enable_noisefilter(struct isp_prev_device *prev, bool enable) +{ + struct isp_device *isp = to_isp_device(prev); + + if (enable) + isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, + ISPPRV_PCR_NFEN); + else + isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, + ISPPRV_PCR_NFEN); +} + +/* + * preview_config_gammacorrn - Configure the Gamma Correction tables + */ +static void +preview_config_gammacorrn(struct isp_prev_device *prev, + const struct prev_params *params) +{ + struct isp_device *isp = to_isp_device(prev); + const struct omap3isp_prev_gtables *gt = ¶ms->gamma; + unsigned int i; + + isp_reg_writel(isp, ISPPRV_REDGAMMA_TABLE_ADDR, + OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR); + for (i = 0; i < OMAP3ISP_PREV_GAMMA_TBL_SIZE; i++) + isp_reg_writel(isp, gt->red[i], OMAP3_ISP_IOMEM_PREV, + ISPPRV_SET_TBL_DATA); + + isp_reg_writel(isp, ISPPRV_GREENGAMMA_TABLE_ADDR, + OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR); + for (i = 0; i < OMAP3ISP_PREV_GAMMA_TBL_SIZE; i++) + isp_reg_writel(isp, gt->green[i], OMAP3_ISP_IOMEM_PREV, + ISPPRV_SET_TBL_DATA); + + isp_reg_writel(isp, ISPPRV_BLUEGAMMA_TABLE_ADDR, + OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR); + for (i = 0; i < OMAP3ISP_PREV_GAMMA_TBL_SIZE; i++) + isp_reg_writel(isp, gt->blue[i], OMAP3_ISP_IOMEM_PREV, + ISPPRV_SET_TBL_DATA); +} + +/* + * preview_enable_gammacorrn - Enable/disable Gamma Correction + * + * When gamma correction is disabled, the module is bypassed and its output is + * the 8 MSB of the 10-bit input . + */ +static void +preview_enable_gammacorrn(struct isp_prev_device *prev, bool enable) +{ + struct isp_device *isp = to_isp_device(prev); + + if (enable) + isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, + ISPPRV_PCR_GAMMA_BYPASS); + else + isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, + ISPPRV_PCR_GAMMA_BYPASS); +} + +/* + * preview_config_contrast - Configure the Contrast + * + * Value should be programmed before enabling the module. + */ +static void +preview_config_contrast(struct isp_prev_device *prev, + const struct prev_params *params) +{ + struct isp_device *isp = to_isp_device(prev); + + isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_CNT_BRT, + 0xff << ISPPRV_CNT_BRT_CNT_SHIFT, + params->contrast << ISPPRV_CNT_BRT_CNT_SHIFT); +} + +/* + * preview_config_brightness - Configure the Brightness + */ +static void +preview_config_brightness(struct isp_prev_device *prev, + const struct prev_params *params) +{ + struct isp_device *isp = to_isp_device(prev); + + isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_CNT_BRT, + 0xff << ISPPRV_CNT_BRT_BRT_SHIFT, + params->brightness << ISPPRV_CNT_BRT_BRT_SHIFT); +} + +/* * preview_update_contrast - Updates the contrast. * @contrast: Pointer to hold the current programmed contrast value. * @@ -647,22 +661,6 @@ preview_update_contrast(struct isp_prev_device *prev, u8 contrast) } /* - * preview_config_contrast - Configures the Contrast. - * @params: Contrast value (u8 pointer, U8Q0 format). - * - * Value should be programmed before enabling the module. - */ -static void -preview_config_contrast(struct isp_prev_device *prev, const void *params) -{ - struct isp_device *isp = to_isp_device(prev); - - isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_CNT_BRT, - 0xff << ISPPRV_CNT_BRT_CNT_SHIFT, - *(u8 *)params << ISPPRV_CNT_BRT_CNT_SHIFT); -} - -/* * preview_update_brightness - Updates the brightness in preview module. * @brightness: Pointer to hold the current programmed brightness value. * @@ -684,38 +682,6 @@ preview_update_brightness(struct isp_prev_device *prev, u8 brightness) spin_unlock_irqrestore(&prev->params.lock, flags); } -/* - * preview_config_brightness - Configures the brightness. - * @params: Brightness value (u8 pointer, U8Q0 format). - */ -static void -preview_config_brightness(struct isp_prev_device *prev, const void *params) -{ - struct isp_device *isp = to_isp_device(prev); - - isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_CNT_BRT, - 0xff << ISPPRV_CNT_BRT_BRT_SHIFT, - *(u8 *)params << ISPPRV_CNT_BRT_BRT_SHIFT); -} - -/* - * preview_config_yc_range - Configures the max and min Y and C values. - * @yclimit: Structure containing the range of Y and C values. - */ -static void -preview_config_yc_range(struct isp_prev_device *prev, const void *yclimit) -{ - struct isp_device *isp = to_isp_device(prev); - const struct omap3isp_prev_yclimit *yc = yclimit; - - isp_reg_writel(isp, - yc->maxC << ISPPRV_SETUP_YC_MAXC_SHIFT | - yc->maxY << ISPPRV_SETUP_YC_MAXY_SHIFT | - yc->minC << ISPPRV_SETUP_YC_MINC_SHIFT | - yc->minY << ISPPRV_SETUP_YC_MINY_SHIFT, - OMAP3_ISP_IOMEM_PREV, ISPPRV_SETUP_YC); -} - static u32 preview_params_lock(struct isp_prev_device *prev, u32 update, bool shadow) { @@ -787,8 +753,8 @@ static void preview_params_switch(struct isp_prev_device *prev) /* preview parameters update structure */ struct preview_update { - void (*config)(struct isp_prev_device *, const void *); - void (*enable)(struct isp_prev_device *, u8); + void (*config)(struct isp_prev_device *, const struct prev_params *); + void (*enable)(struct isp_prev_device *, bool); unsigned int param_offset; unsigned int param_size; unsigned int config_offset; @@ -860,9 +826,9 @@ static const struct preview_update update_attrs[] = { offsetof(struct prev_params, dcor), FIELD_SIZEOF(struct prev_params, dcor), offsetof(struct omap3isp_prev_update_config, dcor), - }, /* OMAP3ISP_PREV_GAMMABYPASS */ { + }, /* Previously OMAP3ISP_PREV_GAMMABYPASS, not used anymore */ { + NULL, NULL, - preview_enable_gammabypass, }, /* OMAP3ISP_PREV_DRK_FRM_CAPTURE */ { NULL, preview_enable_drkframe_capture, @@ -870,7 +836,7 @@ static const struct preview_update update_attrs[] = { NULL, preview_enable_drkframe, }, /* OMAP3ISP_PREV_LENS_SHADING */ { - preview_config_drkf_shadcomp, + NULL, preview_enable_drkframe, }, /* OMAP3ISP_PREV_NF */ { preview_config_noisefilter, @@ -880,20 +846,18 @@ static const struct preview_update update_attrs[] = { offsetof(struct omap3isp_prev_update_config, nf), }, /* OMAP3ISP_PREV_GAMMA */ { preview_config_gammacorrn, - NULL, + preview_enable_gammacorrn, offsetof(struct prev_params, gamma), FIELD_SIZEOF(struct prev_params, gamma), offsetof(struct omap3isp_prev_update_config, gamma), }, /* OMAP3ISP_PREV_CONTRAST */ { preview_config_contrast, NULL, - offsetof(struct prev_params, contrast), - 0, 0, true, + 0, 0, 0, true, }, /* OMAP3ISP_PREV_BRIGHTNESS */ { preview_config_brightness, NULL, - offsetof(struct prev_params, brightness), - 0, 0, true, + 0, 0, 0, true, }, }; @@ -988,7 +952,6 @@ static void preview_setup_hw(struct isp_prev_device *prev, u32 update, const struct preview_update *attr = &update_attrs[i]; struct prev_params *params; unsigned int bit = 1 << i; - void *param_ptr; if (!(update & bit)) continue; @@ -996,15 +959,13 @@ static void preview_setup_hw(struct isp_prev_device *prev, u32 update, params = &prev->params.params[!(active & bit)]; if (params->features & bit) { - if (attr->config) { - param_ptr = (void *)params + attr->param_offset; - attr->config(prev, param_ptr); - } + if (attr->config) + attr->config(prev, params); if (attr->enable) - attr->enable(prev, 1); + attr->enable(prev, true); } else { if (attr->enable) - attr->enable(prev, 0); + attr->enable(prev, false); } } } @@ -1043,42 +1004,60 @@ preview_config_ycpos(struct isp_prev_device *prev, static void preview_config_averager(struct isp_prev_device *prev, u8 average) { struct isp_device *isp = to_isp_device(prev); - struct prev_params *params; - int reg = 0; - - params = (prev->params.active & OMAP3ISP_PREV_CFA) - ? &prev->params.params[0] : &prev->params.params[1]; - if (params->cfa.format == OMAP3ISP_CFAFMT_BAYER) - reg = ISPPRV_AVE_EVENDIST_2 << ISPPRV_AVE_EVENDIST_SHIFT | - ISPPRV_AVE_ODDDIST_2 << ISPPRV_AVE_ODDDIST_SHIFT | - average; - else if (params->cfa.format == OMAP3ISP_CFAFMT_RGBFOVEON) - reg = ISPPRV_AVE_EVENDIST_3 << ISPPRV_AVE_EVENDIST_SHIFT | - ISPPRV_AVE_ODDDIST_3 << ISPPRV_AVE_ODDDIST_SHIFT | - average; - isp_reg_writel(isp, reg, OMAP3_ISP_IOMEM_PREV, ISPPRV_AVE); + isp_reg_writel(isp, ISPPRV_AVE_EVENDIST_2 << ISPPRV_AVE_EVENDIST_SHIFT | + ISPPRV_AVE_ODDDIST_2 << ISPPRV_AVE_ODDDIST_SHIFT | + average, OMAP3_ISP_IOMEM_PREV, ISPPRV_AVE); } + /* * preview_config_input_format - Configure the input format * @prev: The preview engine * @format: Format on the preview engine sink pad * - * Enable CFA interpolation for Bayer formats and disable it for greyscale - * formats. + * Enable and configure CFA interpolation for Bayer formats and disable it for + * greyscale formats. + * + * The CFA table is organised in four blocks, one per Bayer component. The + * hardware expects blocks to follow the Bayer order of the input data, while + * the driver stores the table in GRBG order in memory. The blocks need to be + * reordered to support non-GRBG Bayer patterns. */ static void preview_config_input_format(struct isp_prev_device *prev, const struct v4l2_mbus_framefmt *format) { struct isp_device *isp = to_isp_device(prev); + struct prev_params *params; - if (format->code != V4L2_MBUS_FMT_Y10_1X10) - isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, - ISPPRV_PCR_CFAEN); - else + switch (format->code) { + case V4L2_MBUS_FMT_SGRBG10_1X10: + prev->params.cfa_order = 0; + break; + case V4L2_MBUS_FMT_SRGGB10_1X10: + prev->params.cfa_order = 1; + break; + case V4L2_MBUS_FMT_SBGGR10_1X10: + prev->params.cfa_order = 2; + break; + case V4L2_MBUS_FMT_SGBRG10_1X10: + prev->params.cfa_order = 3; + break; + default: + /* Disable CFA for non-Bayer formats. */ isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, ISPPRV_PCR_CFAEN); + return; + } + + isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, ISPPRV_PCR_CFAEN); + isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, + ISPPRV_PCR_CFAFMT_MASK, ISPPRV_PCR_CFAFMT_BAYER); + + params = (prev->params.active & OMAP3ISP_PREV_CFA) + ? &prev->params.params[0] : &prev->params.params[1]; + + preview_config_cfa(prev, params); } /* @@ -1421,22 +1400,6 @@ static void preview_configure(struct isp_prev_device *prev) active = prev->params.active; spin_unlock_irqrestore(&prev->params.lock, flags); - preview_setup_hw(prev, update, active); - - if (prev->output & PREVIEW_OUTPUT_MEMORY) - isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, - ISPPRV_PCR_SDRPORT); - else - isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, - ISPPRV_PCR_SDRPORT); - - if (prev->output & PREVIEW_OUTPUT_RESIZER) - isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, - ISPPRV_PCR_RSZPORT); - else - isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, - ISPPRV_PCR_RSZPORT); - /* PREV_PAD_SINK */ format = &prev->formats[PREV_PAD_SINK]; @@ -1451,10 +1414,26 @@ static void preview_configure(struct isp_prev_device *prev) preview_config_inlineoffset(prev, ALIGN(format->width, 0x20) * 2); + preview_setup_hw(prev, update, active); + /* PREV_PAD_SOURCE */ format = &prev->formats[PREV_PAD_SOURCE]; if (prev->output & PREVIEW_OUTPUT_MEMORY) + isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, + ISPPRV_PCR_SDRPORT); + else + isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, + ISPPRV_PCR_SDRPORT); + + if (prev->output & PREVIEW_OUTPUT_RESIZER) + isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, + ISPPRV_PCR_RSZPORT); + else + isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, + ISPPRV_PCR_RSZPORT); + + if (prev->output & PREVIEW_OUTPUT_MEMORY) preview_config_outlineoffset(prev, ALIGN(format->width, 0x10) * 2); diff --git a/drivers/media/video/omap3isp/isppreview.h b/drivers/media/platform/omap3isp/isppreview.h index 6663ab64e4b1..f66923407f8c 100644 --- a/drivers/media/video/omap3isp/isppreview.h +++ b/drivers/media/platform/omap3isp/isppreview.h @@ -144,6 +144,7 @@ struct isp_prev_device { struct isp_video video_out; struct { + unsigned int cfa_order; struct prev_params params[2]; u32 active; spinlock_t lock; diff --git a/drivers/media/video/omap3isp/ispqueue.c b/drivers/media/platform/omap3isp/ispqueue.c index 9bebb1e57aab..15bf3eab2224 100644 --- a/drivers/media/video/omap3isp/ispqueue.c +++ b/drivers/media/platform/omap3isp/ispqueue.c @@ -647,7 +647,7 @@ static int isp_video_queue_alloc(struct isp_video_queue *queue, if (ret < 0) return ret; - /* Bail out of no buffers should be allocated. */ + /* Bail out if no buffers should be allocated. */ if (nbuffers == 0) return 0; @@ -908,13 +908,14 @@ done: * * This function is intended to be used as a VIDIOC_DQBUF ioctl handler. * - * The v4l2_buffer structure passed from userspace is first sanity tested. If - * sane, the buffer is then processed and added to the main queue and, if the - * queue is streaming, to the IRQ queue. + * Wait until a buffer is ready to be dequeued, remove it from the queue and + * copy its information to the v4l2_buffer structure. * - * Before being enqueued, USERPTR buffers are checked for address changes. If - * the buffer has a different userspace address, the old memory area is unlocked - * and the new memory area is locked. + * If the nonblocking argument is not zero and no buffer is ready, return + * -EAGAIN immediately instead of waiting. + * + * If no buffer has been enqueued, or if the requested buffer type doesn't match + * the queue type, return -EINVAL. */ int omap3isp_video_queue_dqbuf(struct isp_video_queue *queue, struct v4l2_buffer *vbuf, int nonblocking) diff --git a/drivers/media/video/omap3isp/ispqueue.h b/drivers/media/platform/omap3isp/ispqueue.h index 908dfd712e8e..908dfd712e8e 100644 --- a/drivers/media/video/omap3isp/ispqueue.h +++ b/drivers/media/platform/omap3isp/ispqueue.h diff --git a/drivers/media/video/omap3isp/ispreg.h b/drivers/media/platform/omap3isp/ispreg.h index 084ea77d65a7..084ea77d65a7 100644 --- a/drivers/media/video/omap3isp/ispreg.h +++ b/drivers/media/platform/omap3isp/ispreg.h diff --git a/drivers/media/video/omap3isp/ispresizer.c b/drivers/media/platform/omap3isp/ispresizer.c index ae17d917f77b..d11fb261d530 100644 --- a/drivers/media/video/omap3isp/ispresizer.c +++ b/drivers/media/platform/omap3isp/ispresizer.c @@ -690,7 +690,7 @@ static void resizer_print_status(struct isp_res_device *res) } /* - * resizer_calc_ratios - Helper function for calculate resizer ratios + * resizer_calc_ratios - Helper function for calculating resizer ratios * @res: pointer to resizer private data structure * @input: input frame size * @output: output frame size @@ -734,7 +734,7 @@ static void resizer_print_status(struct isp_res_device *res) * value will still satisfy the original inequality, as b will disappear when * the expression will be shifted right by 8. * - * The reverted the equations thus become + * The reverted equations thus become * * - 8-phase, 4-tap mode * hrsz = ((iw - 7) * 256 + 255 - 16 - 32 * sph) / (ow - 1) @@ -759,7 +759,7 @@ static void resizer_print_status(struct isp_res_device *res) * loop', the smallest of the ratio values will be used, never exceeding the * requested input size. * - * We first clamp the output size according to the hardware capabilitie to avoid + * We first clamp the output size according to the hardware capability to avoid * auto-cropping the input more than required to satisfy the TRM equations. The * minimum output size is achieved with a scaling factor of 1024. It is thus * computed using the 7-tap equations. @@ -1730,6 +1730,8 @@ static int resizer_init_entities(struct isp_res_device *res) if (ret < 0) goto error_video_out; + res->video_out.video.entity.flags |= MEDIA_ENT_FL_DEFAULT; + /* Connect the video nodes to the resizer subdev. */ ret = media_entity_create_link(&res->video_in.video.entity, 0, &res->subdev.entity, RESZ_PAD_SINK, 0); diff --git a/drivers/media/video/omap3isp/ispresizer.h b/drivers/media/platform/omap3isp/ispresizer.h index 70c1c0e1bbdf..70c1c0e1bbdf 100644 --- a/drivers/media/video/omap3isp/ispresizer.h +++ b/drivers/media/platform/omap3isp/ispresizer.h diff --git a/drivers/media/video/omap3isp/ispstat.c b/drivers/media/platform/omap3isp/ispstat.c index b8640be692f1..d7ac76b5c2ae 100644 --- a/drivers/media/video/omap3isp/ispstat.c +++ b/drivers/media/platform/omap3isp/ispstat.c @@ -1025,7 +1025,7 @@ void omap3isp_stat_dma_isr(struct ispstat *stat) int omap3isp_stat_subscribe_event(struct v4l2_subdev *subdev, struct v4l2_fh *fh, - struct v4l2_event_subscription *sub) + const struct v4l2_event_subscription *sub) { struct ispstat *stat = v4l2_get_subdevdata(subdev); @@ -1037,7 +1037,7 @@ int omap3isp_stat_subscribe_event(struct v4l2_subdev *subdev, int omap3isp_stat_unsubscribe_event(struct v4l2_subdev *subdev, struct v4l2_fh *fh, - struct v4l2_event_subscription *sub) + const struct v4l2_event_subscription *sub) { return v4l2_event_unsubscribe(fh, sub); } diff --git a/drivers/media/video/omap3isp/ispstat.h b/drivers/media/platform/omap3isp/ispstat.h index 9b7c8654dc8a..a6fe653eb237 100644 --- a/drivers/media/video/omap3isp/ispstat.h +++ b/drivers/media/platform/omap3isp/ispstat.h @@ -147,10 +147,10 @@ int omap3isp_stat_init(struct ispstat *stat, const char *name, void omap3isp_stat_cleanup(struct ispstat *stat); int omap3isp_stat_subscribe_event(struct v4l2_subdev *subdev, struct v4l2_fh *fh, - struct v4l2_event_subscription *sub); + const struct v4l2_event_subscription *sub); int omap3isp_stat_unsubscribe_event(struct v4l2_subdev *subdev, struct v4l2_fh *fh, - struct v4l2_event_subscription *sub); + const struct v4l2_event_subscription *sub); int omap3isp_stat_s_stream(struct v4l2_subdev *subdev, int enable); int omap3isp_stat_busy(struct ispstat *stat); diff --git a/drivers/media/video/omap3isp/ispvideo.c b/drivers/media/platform/omap3isp/ispvideo.c index b37379d39cdd..a0b737fecf13 100644 --- a/drivers/media/video/omap3isp/ispvideo.c +++ b/drivers/media/platform/omap3isp/ispvideo.c @@ -53,67 +53,77 @@ static struct isp_format_info formats[] = { { V4L2_MBUS_FMT_Y8_1X8, V4L2_MBUS_FMT_Y8_1X8, V4L2_MBUS_FMT_Y8_1X8, V4L2_MBUS_FMT_Y8_1X8, - V4L2_PIX_FMT_GREY, 8, }, + V4L2_PIX_FMT_GREY, 8, 1, }, { V4L2_MBUS_FMT_Y10_1X10, V4L2_MBUS_FMT_Y10_1X10, V4L2_MBUS_FMT_Y10_1X10, V4L2_MBUS_FMT_Y8_1X8, - V4L2_PIX_FMT_Y10, 10, }, + V4L2_PIX_FMT_Y10, 10, 2, }, { V4L2_MBUS_FMT_Y12_1X12, V4L2_MBUS_FMT_Y10_1X10, V4L2_MBUS_FMT_Y12_1X12, V4L2_MBUS_FMT_Y8_1X8, - V4L2_PIX_FMT_Y12, 12, }, + V4L2_PIX_FMT_Y12, 12, 2, }, { V4L2_MBUS_FMT_SBGGR8_1X8, V4L2_MBUS_FMT_SBGGR8_1X8, V4L2_MBUS_FMT_SBGGR8_1X8, V4L2_MBUS_FMT_SBGGR8_1X8, - V4L2_PIX_FMT_SBGGR8, 8, }, + V4L2_PIX_FMT_SBGGR8, 8, 1, }, { V4L2_MBUS_FMT_SGBRG8_1X8, V4L2_MBUS_FMT_SGBRG8_1X8, V4L2_MBUS_FMT_SGBRG8_1X8, V4L2_MBUS_FMT_SGBRG8_1X8, - V4L2_PIX_FMT_SGBRG8, 8, }, + V4L2_PIX_FMT_SGBRG8, 8, 1, }, { V4L2_MBUS_FMT_SGRBG8_1X8, V4L2_MBUS_FMT_SGRBG8_1X8, V4L2_MBUS_FMT_SGRBG8_1X8, V4L2_MBUS_FMT_SGRBG8_1X8, - V4L2_PIX_FMT_SGRBG8, 8, }, + V4L2_PIX_FMT_SGRBG8, 8, 1, }, { V4L2_MBUS_FMT_SRGGB8_1X8, V4L2_MBUS_FMT_SRGGB8_1X8, V4L2_MBUS_FMT_SRGGB8_1X8, V4L2_MBUS_FMT_SRGGB8_1X8, - V4L2_PIX_FMT_SRGGB8, 8, }, + V4L2_PIX_FMT_SRGGB8, 8, 1, }, { V4L2_MBUS_FMT_SBGGR10_DPCM8_1X8, V4L2_MBUS_FMT_SBGGR10_DPCM8_1X8, V4L2_MBUS_FMT_SBGGR10_1X10, 0, - V4L2_PIX_FMT_SBGGR10DPCM8, 8, }, + V4L2_PIX_FMT_SBGGR10DPCM8, 8, 1, }, { V4L2_MBUS_FMT_SGBRG10_DPCM8_1X8, V4L2_MBUS_FMT_SGBRG10_DPCM8_1X8, V4L2_MBUS_FMT_SGBRG10_1X10, 0, - V4L2_PIX_FMT_SGBRG10DPCM8, 8, }, + V4L2_PIX_FMT_SGBRG10DPCM8, 8, 1, }, { V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8, V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8, V4L2_MBUS_FMT_SGRBG10_1X10, 0, - V4L2_PIX_FMT_SGRBG10DPCM8, 8, }, + V4L2_PIX_FMT_SGRBG10DPCM8, 8, 1, }, { V4L2_MBUS_FMT_SRGGB10_DPCM8_1X8, V4L2_MBUS_FMT_SRGGB10_DPCM8_1X8, V4L2_MBUS_FMT_SRGGB10_1X10, 0, - V4L2_PIX_FMT_SRGGB10DPCM8, 8, }, + V4L2_PIX_FMT_SRGGB10DPCM8, 8, 1, }, { V4L2_MBUS_FMT_SBGGR10_1X10, V4L2_MBUS_FMT_SBGGR10_1X10, V4L2_MBUS_FMT_SBGGR10_1X10, V4L2_MBUS_FMT_SBGGR8_1X8, - V4L2_PIX_FMT_SBGGR10, 10, }, + V4L2_PIX_FMT_SBGGR10, 10, 2, }, { V4L2_MBUS_FMT_SGBRG10_1X10, V4L2_MBUS_FMT_SGBRG10_1X10, V4L2_MBUS_FMT_SGBRG10_1X10, V4L2_MBUS_FMT_SGBRG8_1X8, - V4L2_PIX_FMT_SGBRG10, 10, }, + V4L2_PIX_FMT_SGBRG10, 10, 2, }, { V4L2_MBUS_FMT_SGRBG10_1X10, V4L2_MBUS_FMT_SGRBG10_1X10, V4L2_MBUS_FMT_SGRBG10_1X10, V4L2_MBUS_FMT_SGRBG8_1X8, - V4L2_PIX_FMT_SGRBG10, 10, }, + V4L2_PIX_FMT_SGRBG10, 10, 2, }, { V4L2_MBUS_FMT_SRGGB10_1X10, V4L2_MBUS_FMT_SRGGB10_1X10, V4L2_MBUS_FMT_SRGGB10_1X10, V4L2_MBUS_FMT_SRGGB8_1X8, - V4L2_PIX_FMT_SRGGB10, 10, }, + V4L2_PIX_FMT_SRGGB10, 10, 2, }, { V4L2_MBUS_FMT_SBGGR12_1X12, V4L2_MBUS_FMT_SBGGR10_1X10, V4L2_MBUS_FMT_SBGGR12_1X12, V4L2_MBUS_FMT_SBGGR8_1X8, - V4L2_PIX_FMT_SBGGR12, 12, }, + V4L2_PIX_FMT_SBGGR12, 12, 2, }, { V4L2_MBUS_FMT_SGBRG12_1X12, V4L2_MBUS_FMT_SGBRG10_1X10, V4L2_MBUS_FMT_SGBRG12_1X12, V4L2_MBUS_FMT_SGBRG8_1X8, - V4L2_PIX_FMT_SGBRG12, 12, }, + V4L2_PIX_FMT_SGBRG12, 12, 2, }, { V4L2_MBUS_FMT_SGRBG12_1X12, V4L2_MBUS_FMT_SGRBG10_1X10, V4L2_MBUS_FMT_SGRBG12_1X12, V4L2_MBUS_FMT_SGRBG8_1X8, - V4L2_PIX_FMT_SGRBG12, 12, }, + V4L2_PIX_FMT_SGRBG12, 12, 2, }, { V4L2_MBUS_FMT_SRGGB12_1X12, V4L2_MBUS_FMT_SRGGB10_1X10, V4L2_MBUS_FMT_SRGGB12_1X12, V4L2_MBUS_FMT_SRGGB8_1X8, - V4L2_PIX_FMT_SRGGB12, 12, }, + V4L2_PIX_FMT_SRGGB12, 12, 2, }, { V4L2_MBUS_FMT_UYVY8_1X16, V4L2_MBUS_FMT_UYVY8_1X16, V4L2_MBUS_FMT_UYVY8_1X16, 0, - V4L2_PIX_FMT_UYVY, 16, }, + V4L2_PIX_FMT_UYVY, 16, 2, }, { V4L2_MBUS_FMT_YUYV8_1X16, V4L2_MBUS_FMT_YUYV8_1X16, V4L2_MBUS_FMT_YUYV8_1X16, 0, - V4L2_PIX_FMT_YUYV, 16, }, + V4L2_PIX_FMT_YUYV, 16, 2, }, + { V4L2_MBUS_FMT_UYVY8_2X8, V4L2_MBUS_FMT_UYVY8_2X8, + V4L2_MBUS_FMT_UYVY8_2X8, 0, + V4L2_PIX_FMT_UYVY, 8, 2, }, + { V4L2_MBUS_FMT_YUYV8_2X8, V4L2_MBUS_FMT_YUYV8_2X8, + V4L2_MBUS_FMT_YUYV8_2X8, 0, + V4L2_PIX_FMT_YUYV, 8, 2, }, + /* Empty entry to catch the unsupported pixel code (0) used by the CCDC + * module and avoid NULL pointer dereferences. + */ + { 0, } }; const struct isp_format_info * @@ -161,7 +171,7 @@ static unsigned int isp_video_mbus_to_pix(const struct isp_video *video, if (WARN_ON(i == ARRAY_SIZE(formats))) return 0; - min_bpl = pix->width * ALIGN(formats[i].bpp, 8) / 8; + min_bpl = pix->width * formats[i].bpp; /* Clamp the requested bytes per line value. If the maximum bytes per * line value is zero, the module doesn't support user configurable line @@ -723,7 +733,7 @@ isp_video_try_format(struct file *file, void *fh, struct v4l2_format *format) fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE; ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &fmt); if (ret) - return ret == -ENOIOCTLCMD ? -EINVAL : ret; + return ret == -ENOIOCTLCMD ? -ENOTTY : ret; isp_video_mbus_to_pix(video, &fmt.format, &format->fmt.pix); return 0; @@ -744,7 +754,7 @@ isp_video_cropcap(struct file *file, void *fh, struct v4l2_cropcap *cropcap) ret = v4l2_subdev_call(subdev, video, cropcap, cropcap); mutex_unlock(&video->mutex); - return ret == -ENOIOCTLCMD ? -EINVAL : ret; + return ret == -ENOIOCTLCMD ? -ENOTTY : ret; } static int @@ -771,7 +781,7 @@ isp_video_get_crop(struct file *file, void *fh, struct v4l2_crop *crop) format.which = V4L2_SUBDEV_FORMAT_ACTIVE; ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &format); if (ret < 0) - return ret == -ENOIOCTLCMD ? -EINVAL : ret; + return ret == -ENOIOCTLCMD ? -ENOTTY : ret; crop->c.left = 0; crop->c.top = 0; @@ -796,7 +806,7 @@ isp_video_set_crop(struct file *file, void *fh, struct v4l2_crop *crop) ret = v4l2_subdev_call(subdev, video, s_crop, crop); mutex_unlock(&video->mutex); - return ret == -ENOIOCTLCMD ? -EINVAL : ret; + return ret == -ENOIOCTLCMD ? -ENOTTY : ret; } static int @@ -921,7 +931,8 @@ static int isp_video_check_external_subdevs(struct isp_video *video, return ret; } - pipe->external_bpp = omap3isp_video_format_info(fmt.format.code)->bpp; + pipe->external_width = + omap3isp_video_format_info(fmt.format.code)->width; memset(&ctrls, 0, sizeof(ctrls)); memset(&ctrl, 0, sizeof(ctrl)); @@ -1331,6 +1342,7 @@ int omap3isp_video_init(struct isp_video *video, const char *name) case V4L2_BUF_TYPE_VIDEO_OUTPUT: direction = "input"; video->pad.flags = MEDIA_PAD_FL_SOURCE; + video->video.vfl_dir = VFL_DIR_TX; break; default: diff --git a/drivers/media/video/omap3isp/ispvideo.h b/drivers/media/platform/omap3isp/ispvideo.h index 5acc909500ec..1ad470ec2b9d 100644 --- a/drivers/media/video/omap3isp/ispvideo.h +++ b/drivers/media/platform/omap3isp/ispvideo.h @@ -51,7 +51,8 @@ struct v4l2_pix_format; * @flavor: V4L2 media bus format code for the same pixel layout but * shifted to be 8 bits per pixel. =0 if format is not shiftable. * @pixelformat: V4L2 pixel format FCC identifier - * @bpp: Bits per pixel + * @width: Bits per pixel (when transferred over a bus) + * @bpp: Bytes per pixel (when stored in memory) */ struct isp_format_info { enum v4l2_mbus_pixelcode code; @@ -59,6 +60,7 @@ struct isp_format_info { enum v4l2_mbus_pixelcode uncompressed; enum v4l2_mbus_pixelcode flavor; u32 pixelformat; + unsigned int width; unsigned int bpp; }; @@ -106,7 +108,7 @@ struct isp_pipeline { struct v4l2_fract max_timeperframe; struct v4l2_subdev *external; unsigned int external_rate; - unsigned int external_bpp; + unsigned int external_width; }; #define to_isp_pipeline(__e) \ diff --git a/drivers/media/video/omap3isp/luma_enhance_table.h b/drivers/media/platform/omap3isp/luma_enhance_table.h index 098b45e2280f..098b45e2280f 100644 --- a/drivers/media/video/omap3isp/luma_enhance_table.h +++ b/drivers/media/platform/omap3isp/luma_enhance_table.h diff --git a/drivers/media/video/omap3isp/noise_filter_table.h b/drivers/media/platform/omap3isp/noise_filter_table.h index d50451a4a242..d50451a4a242 100644 --- a/drivers/media/video/omap3isp/noise_filter_table.h +++ b/drivers/media/platform/omap3isp/noise_filter_table.h diff --git a/drivers/media/video/s5p-fimc/Kconfig b/drivers/media/platform/s5p-fimc/Kconfig index a564f7eeb064..8f090a8f270e 100644 --- a/drivers/media/video/s5p-fimc/Kconfig +++ b/drivers/media/platform/s5p-fimc/Kconfig @@ -31,7 +31,7 @@ config VIDEO_S5P_MIPI_CSIS To compile this driver as a module, choose M here: the module will be called s5p-csis. -if ARCH_EXYNOS +if SOC_EXYNOS4212 || SOC_EXYNOS4412 || SOC_EXYNOS5250 config VIDEO_EXYNOS_FIMC_LITE tristate "EXYNOS FIMC-LITE camera interface driver" diff --git a/drivers/media/video/s5p-fimc/Makefile b/drivers/media/platform/s5p-fimc/Makefile index 46485143e1ca..46485143e1ca 100644 --- a/drivers/media/video/s5p-fimc/Makefile +++ b/drivers/media/platform/s5p-fimc/Makefile diff --git a/drivers/media/video/s5p-fimc/fimc-capture.c b/drivers/media/platform/s5p-fimc/fimc-capture.c index 8e413dd3c0b0..dded98815220 100644 --- a/drivers/media/video/s5p-fimc/fimc-capture.c +++ b/drivers/media/platform/s5p-fimc/fimc-capture.c @@ -50,9 +50,9 @@ static int fimc_capture_hw_init(struct fimc_dev *fimc) fimc_prepare_dma_offset(ctx, &ctx->d_frame); fimc_set_yuv_order(ctx); - fimc_hw_set_camera_polarity(fimc, sensor->pdata); - fimc_hw_set_camera_type(fimc, sensor->pdata); - fimc_hw_set_camera_source(fimc, sensor->pdata); + fimc_hw_set_camera_polarity(fimc, &sensor->pdata); + fimc_hw_set_camera_type(fimc, &sensor->pdata); + fimc_hw_set_camera_source(fimc, &sensor->pdata); fimc_hw_set_camera_offset(fimc, &ctx->s_frame); ret = fimc_set_scaler_info(ctx); @@ -118,7 +118,8 @@ static int fimc_capture_state_cleanup(struct fimc_dev *fimc, bool suspend) spin_unlock_irqrestore(&fimc->slock, flags); if (streaming) - return fimc_pipeline_s_stream(&fimc->pipeline, 0); + return fimc_pipeline_call(fimc, set_stream, + &fimc->pipeline, 0); else return 0; } @@ -264,7 +265,8 @@ static int start_streaming(struct vb2_queue *q, unsigned int count) fimc_activate_capture(ctx); if (!test_and_set_bit(ST_CAPT_ISP_STREAM, &fimc->state)) - fimc_pipeline_s_stream(&fimc->pipeline, 1); + fimc_pipeline_call(fimc, set_stream, + &fimc->pipeline, 1); } return 0; @@ -288,7 +290,7 @@ int fimc_capture_suspend(struct fimc_dev *fimc) int ret = fimc_stop_capture(fimc, suspend); if (ret) return ret; - return fimc_pipeline_shutdown(&fimc->pipeline); + return fimc_pipeline_call(fimc, close, &fimc->pipeline); } static void buffer_queue(struct vb2_buffer *vb); @@ -304,8 +306,8 @@ int fimc_capture_resume(struct fimc_dev *fimc) INIT_LIST_HEAD(&fimc->vid_cap.active_buf_q); vid_cap->buf_index = 0; - fimc_pipeline_initialize(&fimc->pipeline, &vid_cap->vfd->entity, - false); + fimc_pipeline_call(fimc, open, &fimc->pipeline, + &vid_cap->vfd.entity, false); fimc_capture_hw_init(fimc); clear_bit(ST_CAPT_SUSPENDED, &fimc->state); @@ -371,7 +373,7 @@ static int buffer_prepare(struct vb2_buffer *vb) unsigned long size = ctx->d_frame.payload[i]; if (vb2_plane_size(vb, i) < size) { - v4l2_err(ctx->fimc_dev->vid_cap.vfd, + v4l2_err(&ctx->fimc_dev->vid_cap.vfd, "User buffer too small (%ld < %ld)\n", vb2_plane_size(vb, i), size); return -EINVAL; @@ -422,7 +424,8 @@ static void buffer_queue(struct vb2_buffer *vb) spin_unlock_irqrestore(&fimc->slock, flags); if (!test_and_set_bit(ST_CAPT_ISP_STREAM, &fimc->state)) - fimc_pipeline_s_stream(&fimc->pipeline, 1); + fimc_pipeline_call(fimc, set_stream, + &fimc->pipeline, 1); return; } spin_unlock_irqrestore(&fimc->slock, flags); @@ -472,7 +475,7 @@ int fimc_capture_ctrls_create(struct fimc_dev *fimc) return ret; return v4l2_ctrl_add_handler(&vid_cap->ctx->ctrls.handler, - fimc->pipeline.subdevs[IDX_SENSOR]->ctrl_handler); + fimc->pipeline.subdevs[IDX_SENSOR]->ctrl_handler, NULL); } static int fimc_capture_set_default_format(struct fimc_dev *fimc); @@ -502,8 +505,8 @@ static int fimc_capture_open(struct file *file) } if (++fimc->vid_cap.refcnt == 1) { - ret = fimc_pipeline_initialize(&fimc->pipeline, - &fimc->vid_cap.vfd->entity, true); + ret = fimc_pipeline_call(fimc, open, &fimc->pipeline, + &fimc->vid_cap.vfd.entity, true); if (!ret && !fimc->vid_cap.user_subdev_api) ret = fimc_capture_set_default_format(fimc); @@ -536,7 +539,7 @@ static int fimc_capture_close(struct file *file) if (--fimc->vid_cap.refcnt == 0) { clear_bit(ST_CAPT_BUSY, &fimc->state); fimc_stop_capture(fimc, false); - fimc_pipeline_shutdown(&fimc->pipeline); + fimc_pipeline_call(fimc, close, &fimc->pipeline); clear_bit(ST_CAPT_SUSPENDED, &fimc->state); } @@ -1587,13 +1590,13 @@ static int fimc_capture_set_default_format(struct fimc_dev *fimc) static int fimc_register_capture_device(struct fimc_dev *fimc, struct v4l2_device *v4l2_dev) { - struct video_device *vfd; + struct video_device *vfd = &fimc->vid_cap.vfd; struct fimc_vid_cap *vid_cap; struct fimc_ctx *ctx; struct vb2_queue *q; int ret = -ENOMEM; - ctx = kzalloc(sizeof *ctx, GFP_KERNEL); + ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); if (!ctx) return -ENOMEM; @@ -1604,25 +1607,19 @@ static int fimc_register_capture_device(struct fimc_dev *fimc, ctx->s_frame.fmt = fimc_find_format(NULL, NULL, FMT_FLAGS_CAM, 0); ctx->d_frame.fmt = ctx->s_frame.fmt; - vfd = video_device_alloc(); - if (!vfd) { - v4l2_err(v4l2_dev, "Failed to allocate video device\n"); - goto err_vd_alloc; - } - + memset(vfd, 0, sizeof(*vfd)); snprintf(vfd->name, sizeof(vfd->name), "fimc.%d.capture", fimc->id); vfd->fops = &fimc_capture_fops; vfd->ioctl_ops = &fimc_capture_ioctl_ops; vfd->v4l2_dev = v4l2_dev; vfd->minor = -1; - vfd->release = video_device_release; + vfd->release = video_device_release_empty; vfd->lock = &fimc->lock; video_set_drvdata(vfd, fimc); vid_cap = &fimc->vid_cap; - vid_cap->vfd = vfd; vid_cap->active_buf_cnt = 0; vid_cap->reqbufs_count = 0; vid_cap->refcnt = 0; @@ -1660,8 +1657,6 @@ static int fimc_register_capture_device(struct fimc_dev *fimc, err_vd: media_entity_cleanup(&vfd->entity); err_ent: - video_device_release(vfd); -err_vd_alloc: kfree(ctx); return ret; } @@ -1671,6 +1666,9 @@ static int fimc_capture_subdev_registered(struct v4l2_subdev *sd) struct fimc_dev *fimc = v4l2_get_subdevdata(sd); int ret; + if (fimc == NULL) + return -ENXIO; + ret = fimc_register_m2m_device(fimc, sd->v4l2_dev); if (ret) return ret; @@ -1691,12 +1689,10 @@ static void fimc_capture_subdev_unregistered(struct v4l2_subdev *sd) fimc_unregister_m2m_device(fimc); - if (fimc->vid_cap.vfd) { - media_entity_cleanup(&fimc->vid_cap.vfd->entity); - video_unregister_device(fimc->vid_cap.vfd); - fimc->vid_cap.vfd = NULL; + if (video_is_registered(&fimc->vid_cap.vfd)) { + video_unregister_device(&fimc->vid_cap.vfd); + media_entity_cleanup(&fimc->vid_cap.vfd.entity); } - kfree(fimc->vid_cap.ctx); fimc->vid_cap.ctx = NULL; } diff --git a/drivers/media/video/s5p-fimc/fimc-core.c b/drivers/media/platform/s5p-fimc/fimc-core.c index 1a445404e73d..1a445404e73d 100644 --- a/drivers/media/video/s5p-fimc/fimc-core.c +++ b/drivers/media/platform/s5p-fimc/fimc-core.c diff --git a/drivers/media/video/s5p-fimc/fimc-core.h b/drivers/media/platform/s5p-fimc/fimc-core.h index 808ccc621846..cd716ba6015f 100644 --- a/drivers/media/video/s5p-fimc/fimc-core.h +++ b/drivers/media/platform/s5p-fimc/fimc-core.h @@ -17,7 +17,7 @@ #include <linux/types.h> #include <linux/videodev2.h> #include <linux/io.h> -#include <asm/sizes.h> +#include <linux/sizes.h> #include <media/media-entity.h> #include <media/videobuf2-core.h> @@ -287,7 +287,7 @@ struct fimc_frame { * @refcnt: the reference counter */ struct fimc_m2m_device { - struct video_device *vfd; + struct video_device vfd; struct v4l2_m2m_dev *m2m_dev; struct fimc_ctx *ctx; int refcnt; @@ -320,7 +320,7 @@ struct fimc_m2m_device { struct fimc_vid_cap { struct fimc_ctx *ctx; struct vb2_alloc_ctx *alloc_ctx; - struct video_device *vfd; + struct video_device vfd; struct v4l2_subdev subdev; struct media_pad vd_pad; struct v4l2_mbus_framefmt mf; @@ -440,6 +440,7 @@ struct fimc_dev { unsigned long state; struct vb2_alloc_ctx *alloc_ctx; struct fimc_pipeline pipeline; + const struct fimc_pipeline_ops *pipeline_ops; }; /** diff --git a/drivers/media/video/s5p-fimc/fimc-lite-reg.c b/drivers/media/platform/s5p-fimc/fimc-lite-reg.c index f996e94873f6..a22d7eb05c82 100644 --- a/drivers/media/video/s5p-fimc/fimc-lite-reg.c +++ b/drivers/media/platform/s5p-fimc/fimc-lite-reg.c @@ -118,9 +118,9 @@ static const u32 src_pixfmt_map[8][3] = { FLITE_REG_CIGCTRL_YUV422_1P }, { V4L2_MBUS_FMT_VYUY8_2X8, FLITE_REG_CISRCSIZE_ORDER422_IN_CRYCBY, FLITE_REG_CIGCTRL_YUV422_1P }, - { V4L2_PIX_FMT_SGRBG8, 0, FLITE_REG_CIGCTRL_RAW8 }, - { V4L2_PIX_FMT_SGRBG10, 0, FLITE_REG_CIGCTRL_RAW10 }, - { V4L2_PIX_FMT_SGRBG12, 0, FLITE_REG_CIGCTRL_RAW12 }, + { V4L2_MBUS_FMT_SGRBG8_1X8, 0, FLITE_REG_CIGCTRL_RAW8 }, + { V4L2_MBUS_FMT_SGRBG10_1X10, 0, FLITE_REG_CIGCTRL_RAW10 }, + { V4L2_MBUS_FMT_SGRBG12_1X12, 0, FLITE_REG_CIGCTRL_RAW12 }, { V4L2_MBUS_FMT_JPEG_1X8, 0, FLITE_REG_CIGCTRL_USER(1) }, }; @@ -137,7 +137,7 @@ void flite_hw_set_source_format(struct fimc_lite *dev, struct flite_frame *f) } if (i == 0 && src_pixfmt_map[i][0] != pixelcode) { - v4l2_err(dev->vfd, + v4l2_err(&dev->vfd, "Unsupported pixel code, falling back to %#08x\n", src_pixfmt_map[i][0]); } diff --git a/drivers/media/video/s5p-fimc/fimc-lite-reg.h b/drivers/media/platform/s5p-fimc/fimc-lite-reg.h index adb9e9e6f3c2..adb9e9e6f3c2 100644 --- a/drivers/media/video/s5p-fimc/fimc-lite-reg.h +++ b/drivers/media/platform/s5p-fimc/fimc-lite-reg.h diff --git a/drivers/media/video/s5p-fimc/fimc-lite.c b/drivers/media/platform/s5p-fimc/fimc-lite.c index c5b57e805b68..70bcf39de879 100644 --- a/drivers/media/video/s5p-fimc/fimc-lite.c +++ b/drivers/media/platform/s5p-fimc/fimc-lite.c @@ -28,9 +28,11 @@ #include <media/v4l2-mem2mem.h> #include <media/videobuf2-core.h> #include <media/videobuf2-dma-contig.h> +#include <media/s5p_fimc.h> #include "fimc-mdevice.h" #include "fimc-core.h" +#include "fimc-lite.h" #include "fimc-lite-reg.h" static int debug; @@ -133,7 +135,7 @@ static int fimc_lite_hw_init(struct fimc_lite *fimc) sensor = v4l2_get_subdev_hostdata(pipeline->subdevs[IDX_SENSOR]); spin_lock_irqsave(&fimc->slock, flags); - flite_hw_set_camera_bus(fimc, sensor->pdata); + flite_hw_set_camera_bus(fimc, &sensor->pdata); flite_hw_set_source_format(fimc, &fimc->inp_frame); flite_hw_set_window_offset(fimc, &fimc->inp_frame); flite_hw_set_output_dma(fimc, &fimc->out_frame, true); @@ -193,7 +195,7 @@ static int fimc_lite_reinit(struct fimc_lite *fimc, bool suspend) if (!streaming) return 0; - return fimc_pipeline_s_stream(&fimc->pipeline, 0); + return fimc_pipeline_call(fimc, set_stream, &fimc->pipeline, 0); } static int fimc_lite_stop_capture(struct fimc_lite *fimc, bool suspend) @@ -307,7 +309,8 @@ static int start_streaming(struct vb2_queue *q, unsigned int count) flite_hw_capture_start(fimc); if (!test_and_set_bit(ST_SENSOR_STREAM, &fimc->state)) - fimc_pipeline_s_stream(&fimc->pipeline, 1); + fimc_pipeline_call(fimc, set_stream, + &fimc->pipeline, 1); } if (debug > 0) flite_hw_dump_regs(fimc, __func__); @@ -374,7 +377,7 @@ static int buffer_prepare(struct vb2_buffer *vb) unsigned long size = fimc->payload[i]; if (vb2_plane_size(vb, i) < size) { - v4l2_err(fimc->vfd, + v4l2_err(&fimc->vfd, "User buffer too small (%ld < %ld)\n", vb2_plane_size(vb, i), size); return -EINVAL; @@ -411,7 +414,8 @@ static void buffer_queue(struct vb2_buffer *vb) spin_unlock_irqrestore(&fimc->slock, flags); if (!test_and_set_bit(ST_SENSOR_STREAM, &fimc->state)) - fimc_pipeline_s_stream(&fimc->pipeline, 1); + fimc_pipeline_call(fimc, set_stream, + &fimc->pipeline, 1); return; } spin_unlock_irqrestore(&fimc->slock, flags); @@ -466,8 +470,8 @@ static int fimc_lite_open(struct file *file) goto done; if (++fimc->ref_count == 1 && fimc->out_path == FIMC_IO_DMA) { - ret = fimc_pipeline_initialize(&fimc->pipeline, - &fimc->vfd->entity, true); + ret = fimc_pipeline_call(fimc, open, &fimc->pipeline, + &fimc->vfd.entity, true); if (ret < 0) { pm_runtime_put_sync(&fimc->pdev->dev); fimc->ref_count--; @@ -493,7 +497,7 @@ static int fimc_lite_close(struct file *file) if (--fimc->ref_count == 0 && fimc->out_path == FIMC_IO_DMA) { clear_bit(ST_FLITE_IN_USE, &fimc->state); fimc_lite_stop_capture(fimc, false); - fimc_pipeline_shutdown(&fimc->pipeline); + fimc_pipeline_call(fimc, close, &fimc->pipeline); clear_bit(ST_FLITE_SUSPENDED, &fimc->state); } @@ -825,7 +829,7 @@ static int fimc_lite_reqbufs(struct file *file, void *priv, reqbufs->count = max_t(u32, FLITE_REQ_BUFS_MIN, reqbufs->count); ret = vb2_reqbufs(&fimc->vb_queue, reqbufs); - if (!ret < 0) + if (!ret) fimc->reqbufs_count = reqbufs->count; return ret; @@ -1064,6 +1068,7 @@ static int fimc_lite_subdev_set_fmt(struct v4l2_subdev *sd, struct fimc_lite *fimc = v4l2_get_subdevdata(sd); struct v4l2_mbus_framefmt *mf = &fmt->format; struct flite_frame *sink = &fimc->inp_frame; + struct flite_frame *source = &fimc->out_frame; const struct fimc_fmt *ffmt; v4l2_dbg(1, debug, sd, "pad%d: code: 0x%x, %dx%d", @@ -1097,8 +1102,10 @@ static int fimc_lite_subdev_set_fmt(struct v4l2_subdev *sd, sink->rect.height = mf->height; sink->rect.left = 0; sink->rect.top = 0; - /* Reset source crop rectangle */ - fimc->out_frame.rect = sink->rect; + /* Reset source format and crop rectangle */ + source->rect = sink->rect; + source->f_width = mf->width; + source->f_height = mf->height; } else { /* Allow changing format only on sink pad */ mf->code = fimc->fmt->mbus_code; @@ -1215,18 +1222,14 @@ static int fimc_lite_subdev_registered(struct v4l2_subdev *sd) { struct fimc_lite *fimc = v4l2_get_subdevdata(sd); struct vb2_queue *q = &fimc->vb_queue; - struct video_device *vfd; + struct video_device *vfd = &fimc->vfd; int ret; + memset(vfd, 0, sizeof(*vfd)); + fimc->fmt = &fimc_lite_formats[0]; fimc->out_path = FIMC_IO_DMA; - vfd = video_device_alloc(); - if (!vfd) { - v4l2_err(sd->v4l2_dev, "Failed to allocate video device\n"); - return -ENOMEM; - } - snprintf(vfd->name, sizeof(vfd->name), "fimc-lite.%d.capture", fimc->index); @@ -1234,9 +1237,8 @@ static int fimc_lite_subdev_registered(struct v4l2_subdev *sd) vfd->ioctl_ops = &fimc_lite_ioctl_ops; vfd->v4l2_dev = sd->v4l2_dev; vfd->minor = -1; - vfd->release = video_device_release; + vfd->release = video_device_release_empty; vfd->lock = &fimc->lock; - fimc->vfd = vfd; fimc->ref_count = 0; fimc->reqbufs_count = 0; @@ -1255,24 +1257,20 @@ static int fimc_lite_subdev_registered(struct v4l2_subdev *sd) fimc->vd_pad.flags = MEDIA_PAD_FL_SINK; ret = media_entity_init(&vfd->entity, 1, &fimc->vd_pad, 0); - if (ret) - goto err; + if (ret < 0) + return ret; video_set_drvdata(vfd, fimc); ret = video_register_device(vfd, VFL_TYPE_GRABBER, -1); - if (ret) - goto err_vd; + if (ret < 0) { + media_entity_cleanup(&vfd->entity); + return ret; + } v4l2_info(sd->v4l2_dev, "Registered %s as /dev/%s\n", vfd->name, video_device_node_name(vfd)); return 0; - - err_vd: - media_entity_cleanup(&vfd->entity); - err: - video_device_release(vfd); - return ret; } static void fimc_lite_subdev_unregistered(struct v4l2_subdev *sd) @@ -1282,10 +1280,9 @@ static void fimc_lite_subdev_unregistered(struct v4l2_subdev *sd) if (fimc == NULL) return; - if (fimc->vfd) { - video_unregister_device(fimc->vfd); - media_entity_cleanup(&fimc->vfd->entity); - fimc->vfd = NULL; + if (video_is_registered(&fimc->vfd)) { + video_unregister_device(&fimc->vfd); + media_entity_cleanup(&fimc->vfd.entity); } } @@ -1515,7 +1512,8 @@ static int fimc_lite_resume(struct device *dev) return 0; INIT_LIST_HEAD(&fimc->active_buf_q); - fimc_pipeline_initialize(&fimc->pipeline, &fimc->vfd->entity, false); + fimc_pipeline_call(fimc, open, &fimc->pipeline, + &fimc->vfd.entity, false); fimc_lite_hw_init(fimc); clear_bit(ST_FLITE_SUSPENDED, &fimc->state); @@ -1541,7 +1539,7 @@ static int fimc_lite_suspend(struct device *dev) if (ret < 0 || !fimc_lite_active(fimc)) return ret; - return fimc_pipeline_shutdown(&fimc->pipeline); + return fimc_pipeline_call(fimc, close, &fimc->pipeline); } #endif /* CONFIG_PM_SLEEP */ diff --git a/drivers/media/video/s5p-fimc/fimc-lite.h b/drivers/media/platform/s5p-fimc/fimc-lite.h index 44424eee81d8..3081db35c5b0 100644 --- a/drivers/media/video/s5p-fimc/fimc-lite.h +++ b/drivers/media/platform/s5p-fimc/fimc-lite.h @@ -9,7 +9,7 @@ #ifndef FIMC_LITE_H_ #define FIMC_LITE_H_ -#include <asm/sizes.h> +#include <linux/sizes.h> #include <linux/io.h> #include <linux/irqreturn.h> #include <linux/platform_device.h> @@ -108,6 +108,7 @@ struct flite_buffer { * @test_pattern: test pattern controls * @index: FIMC-LITE platform device index * @pipeline: video capture pipeline data structure + * @pipeline_ops: media pipeline ops for the video node driver * @slock: spinlock protecting this data structure and the hw registers * @lock: mutex serializing video device and the subdev operations * @clock: FIMC-LITE gate clock @@ -132,7 +133,7 @@ struct fimc_lite { struct platform_device *pdev; struct flite_variant *variant; struct v4l2_device *v4l2_dev; - struct video_device *vfd; + struct video_device vfd; struct v4l2_fh fh; struct vb2_alloc_ctx *alloc_ctx; struct v4l2_subdev subdev; @@ -142,6 +143,7 @@ struct fimc_lite { struct v4l2_ctrl *test_pattern; u32 index; struct fimc_pipeline pipeline; + const struct fimc_pipeline_ops *pipeline_ops; struct mutex lock; spinlock_t slock; diff --git a/drivers/media/video/s5p-fimc/fimc-m2m.c b/drivers/media/platform/s5p-fimc/fimc-m2m.c index c587011d80ef..6b71d953fd15 100644 --- a/drivers/media/video/s5p-fimc/fimc-m2m.c +++ b/drivers/media/platform/s5p-fimc/fimc-m2m.c @@ -370,7 +370,7 @@ static int fimc_m2m_s_fmt_mplane(struct file *file, void *fh, vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type); if (vb2_is_busy(vq)) { - v4l2_err(fimc->m2m.vfd, "queue (%d) busy\n", f->type); + v4l2_err(&fimc->m2m.vfd, "queue (%d) busy\n", f->type); return -EBUSY; } @@ -507,7 +507,7 @@ static int fimc_m2m_try_crop(struct fimc_ctx *ctx, struct v4l2_crop *cr) int i; if (cr->c.top < 0 || cr->c.left < 0) { - v4l2_err(fimc->m2m.vfd, + v4l2_err(&fimc->m2m.vfd, "doesn't support negative values for top & left\n"); return -EINVAL; } @@ -551,7 +551,7 @@ static int fimc_m2m_try_crop(struct fimc_ctx *ctx, struct v4l2_crop *cr) return 0; } -static int fimc_m2m_s_crop(struct file *file, void *fh, struct v4l2_crop *cr) +static int fimc_m2m_s_crop(struct file *file, void *fh, const struct v4l2_crop *cr) { struct fimc_ctx *ctx = fh_to_ctx(fh); struct fimc_dev *fimc = ctx->fimc_dev; @@ -577,7 +577,7 @@ static int fimc_m2m_s_crop(struct file *file, void *fh, struct v4l2_crop *cr) cr->c.height, ctx->rotation); } if (ret) { - v4l2_err(fimc->m2m.vfd, "Out of scaler range\n"); + v4l2_err(&fimc->m2m.vfd, "Out of scaler range\n"); return -EINVAL; } } @@ -620,7 +620,6 @@ static int queue_init(void *priv, struct vb2_queue *src_vq, struct fimc_ctx *ctx = priv; int ret; - memset(src_vq, 0, sizeof(*src_vq)); src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; src_vq->io_modes = VB2_MMAP | VB2_USERPTR; src_vq->drv_priv = ctx; @@ -632,7 +631,6 @@ static int queue_init(void *priv, struct vb2_queue *src_vq, if (ret) return ret; - memset(dst_vq, 0, sizeof(*dst_vq)); dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; dst_vq->io_modes = VB2_MMAP | VB2_USERPTR; dst_vq->drv_priv = ctx; @@ -661,12 +659,12 @@ static int fimc_m2m_open(struct file *file) if (fimc->vid_cap.refcnt > 0) goto unlock; - ctx = kzalloc(sizeof *ctx, GFP_KERNEL); + ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); if (!ctx) { ret = -ENOMEM; goto unlock; } - v4l2_fh_init(&ctx->fh, fimc->m2m.vfd); + v4l2_fh_init(&ctx->fh, &fimc->m2m.vfd); ctx->fimc_dev = fimc; /* Default color format */ @@ -784,38 +782,27 @@ static struct v4l2_m2m_ops m2m_ops = { int fimc_register_m2m_device(struct fimc_dev *fimc, struct v4l2_device *v4l2_dev) { - struct video_device *vfd; - struct platform_device *pdev; - int ret = 0; - - if (!fimc) - return -ENODEV; + struct video_device *vfd = &fimc->m2m.vfd; + int ret; - pdev = fimc->pdev; fimc->v4l2_dev = v4l2_dev; - vfd = video_device_alloc(); - if (!vfd) { - v4l2_err(v4l2_dev, "Failed to allocate video device\n"); - return -ENOMEM; - } - + memset(vfd, 0, sizeof(*vfd)); vfd->fops = &fimc_m2m_fops; vfd->ioctl_ops = &fimc_m2m_ioctl_ops; vfd->v4l2_dev = v4l2_dev; vfd->minor = -1; - vfd->release = video_device_release; + vfd->release = video_device_release_empty; vfd->lock = &fimc->lock; + vfd->vfl_dir = VFL_DIR_M2M; snprintf(vfd->name, sizeof(vfd->name), "fimc.%d.m2m", fimc->id); video_set_drvdata(vfd, fimc); - fimc->m2m.vfd = vfd; fimc->m2m.m2m_dev = v4l2_m2m_init(&m2m_ops); if (IS_ERR(fimc->m2m.m2m_dev)) { v4l2_err(v4l2_dev, "failed to initialize v4l2-m2m device\n"); - ret = PTR_ERR(fimc->m2m.m2m_dev); - goto err_init; + return PTR_ERR(fimc->m2m.m2m_dev); } ret = media_entity_init(&vfd->entity, 0, NULL, 0); @@ -834,8 +821,6 @@ err_vd: media_entity_cleanup(&vfd->entity); err_me: v4l2_m2m_release(fimc->m2m.m2m_dev); -err_init: - video_device_release(fimc->m2m.vfd); return ret; } @@ -846,9 +831,9 @@ void fimc_unregister_m2m_device(struct fimc_dev *fimc) if (fimc->m2m.m2m_dev) v4l2_m2m_release(fimc->m2m.m2m_dev); - if (fimc->m2m.vfd) { - media_entity_cleanup(&fimc->m2m.vfd->entity); - /* Can also be called if video device wasn't registered */ - video_unregister_device(fimc->m2m.vfd); + + if (video_is_registered(&fimc->m2m.vfd)) { + video_unregister_device(&fimc->m2m.vfd); + media_entity_cleanup(&fimc->m2m.vfd.entity); } } diff --git a/drivers/media/video/s5p-fimc/fimc-mdevice.c b/drivers/media/platform/s5p-fimc/fimc-mdevice.c index e65bb283fd8a..80ada5882f62 100644 --- a/drivers/media/video/s5p-fimc/fimc-mdevice.c +++ b/drivers/media/platform/s5p-fimc/fimc-mdevice.c @@ -23,6 +23,7 @@ #include <linux/slab.h> #include <media/v4l2-ctrls.h> #include <media/media-device.h> +#include <media/s5p_fimc.h> #include "fimc-core.h" #include "fimc-lite.h" @@ -38,7 +39,8 @@ static int __fimc_md_set_camclk(struct fimc_md *fmd, * * Caller holds the graph mutex. */ -void fimc_pipeline_prepare(struct fimc_pipeline *p, struct media_entity *me) +static void fimc_pipeline_prepare(struct fimc_pipeline *p, + struct media_entity *me) { struct media_pad *pad = &me->pads[0]; struct v4l2_subdev *sd; @@ -114,7 +116,7 @@ static int __subdev_set_power(struct v4l2_subdev *sd, int on) * * Needs to be called with the graph mutex held. */ -int fimc_pipeline_s_power(struct fimc_pipeline *p, bool state) +static int fimc_pipeline_s_power(struct fimc_pipeline *p, bool state) { unsigned int i; int ret; @@ -134,15 +136,15 @@ int fimc_pipeline_s_power(struct fimc_pipeline *p, bool state) } /** - * __fimc_pipeline_initialize - update the pipeline information, enable power - * of all pipeline subdevs and the sensor clock + * __fimc_pipeline_open - update the pipeline information, enable power + * of all pipeline subdevs and the sensor clock * @me: media entity to start graph walk with * @prep: true to acquire sensor (and csis) subdevs * * This function must be called with the graph mutex held. */ -static int __fimc_pipeline_initialize(struct fimc_pipeline *p, - struct media_entity *me, bool prep) +static int __fimc_pipeline_open(struct fimc_pipeline *p, + struct media_entity *me, bool prep) { int ret; @@ -159,28 +161,27 @@ static int __fimc_pipeline_initialize(struct fimc_pipeline *p, return fimc_pipeline_s_power(p, 1); } -int fimc_pipeline_initialize(struct fimc_pipeline *p, struct media_entity *me, - bool prep) +static int fimc_pipeline_open(struct fimc_pipeline *p, + struct media_entity *me, bool prep) { int ret; mutex_lock(&me->parent->graph_mutex); - ret = __fimc_pipeline_initialize(p, me, prep); + ret = __fimc_pipeline_open(p, me, prep); mutex_unlock(&me->parent->graph_mutex); return ret; } -EXPORT_SYMBOL_GPL(fimc_pipeline_initialize); /** - * __fimc_pipeline_shutdown - disable the sensor clock and pipeline power + * __fimc_pipeline_close - disable the sensor clock and pipeline power * @fimc: fimc device terminating the pipeline * * Disable power of all subdevs in the pipeline and turn off the external * sensor clock. * Called with the graph mutex held. */ -static int __fimc_pipeline_shutdown(struct fimc_pipeline *p) +static int __fimc_pipeline_close(struct fimc_pipeline *p) { int ret = 0; @@ -191,7 +192,7 @@ static int __fimc_pipeline_shutdown(struct fimc_pipeline *p) return ret == -ENXIO ? 0 : ret; } -int fimc_pipeline_shutdown(struct fimc_pipeline *p) +static int fimc_pipeline_close(struct fimc_pipeline *p) { struct media_entity *me; int ret; @@ -201,12 +202,11 @@ int fimc_pipeline_shutdown(struct fimc_pipeline *p) me = &p->subdevs[IDX_SENSOR]->entity; mutex_lock(&me->parent->graph_mutex); - ret = __fimc_pipeline_shutdown(p); + ret = __fimc_pipeline_close(p); mutex_unlock(&me->parent->graph_mutex); return ret; } -EXPORT_SYMBOL_GPL(fimc_pipeline_shutdown); /** * fimc_pipeline_s_stream - invoke s_stream on pipeline subdevs @@ -232,7 +232,13 @@ int fimc_pipeline_s_stream(struct fimc_pipeline *p, bool on) return 0; } -EXPORT_SYMBOL_GPL(fimc_pipeline_s_stream); + +/* Media pipeline operations for the FIMC/FIMC-LITE video device driver */ +static const struct fimc_pipeline_ops fimc_pipeline_ops = { + .open = fimc_pipeline_open, + .close = fimc_pipeline_close, + .set_stream = fimc_pipeline_s_stream, +}; /* * Sensor subdevice helper functions @@ -246,27 +252,27 @@ static struct v4l2_subdev *fimc_md_register_sensor(struct fimc_md *fmd, if (!s_info || !fmd) return NULL; - adapter = i2c_get_adapter(s_info->pdata->i2c_bus_num); + adapter = i2c_get_adapter(s_info->pdata.i2c_bus_num); if (!adapter) { v4l2_warn(&fmd->v4l2_dev, "Failed to get I2C adapter %d, deferring probe\n", - s_info->pdata->i2c_bus_num); + s_info->pdata.i2c_bus_num); return ERR_PTR(-EPROBE_DEFER); } sd = v4l2_i2c_new_subdev_board(&fmd->v4l2_dev, adapter, - s_info->pdata->board_info, NULL); + s_info->pdata.board_info, NULL); if (IS_ERR_OR_NULL(sd)) { i2c_put_adapter(adapter); v4l2_warn(&fmd->v4l2_dev, "Failed to acquire subdev %s, deferring probe\n", - s_info->pdata->board_info->type); + s_info->pdata.board_info->type); return ERR_PTR(-EPROBE_DEFER); } v4l2_set_subdev_hostdata(sd, s_info); sd->grp_id = SENSOR_GROUP_ID; v4l2_info(&fmd->v4l2_dev, "Registered sensor subdevice %s\n", - s_info->pdata->board_info->type); + s_info->pdata.board_info->type); return sd; } @@ -310,7 +316,7 @@ static int fimc_md_register_sensor_entities(struct fimc_md *fmd) for (i = 0; i < num_clients; i++) { struct v4l2_subdev *sd; - fmd->sensor[i].pdata = &pdata->isp_info[i]; + fmd->sensor[i].pdata = pdata->isp_info[i]; ret = __fimc_md_set_camclk(fmd, &fmd->sensor[i], true); if (ret) break; @@ -347,6 +353,7 @@ static int fimc_register_callback(struct device *dev, void *p) if (fimc->pdev->id < 0 || fimc->pdev->id >= FIMC_MAX_DEVS) return 0; + fimc->pipeline_ops = &fimc_pipeline_ops; fmd->fimc[fimc->pdev->id] = fimc; sd->grp_id = FIMC_GROUP_ID; @@ -372,6 +379,7 @@ static int fimc_lite_register_callback(struct device *dev, void *p) if (fimc->index >= FIMC_LITE_MAX_DEVS) return 0; + fimc->pipeline_ops = &fimc_pipeline_ops; fmd->fimc_lite[fimc->index] = fimc; sd->grp_id = FLITE_GROUP_ID; @@ -473,12 +481,14 @@ static void fimc_md_unregister_entities(struct fimc_md *fmd) if (fmd->fimc[i] == NULL) continue; v4l2_device_unregister_subdev(&fmd->fimc[i]->vid_cap.subdev); + fmd->fimc[i]->pipeline_ops = NULL; fmd->fimc[i] = NULL; } for (i = 0; i < FIMC_LITE_MAX_DEVS; i++) { if (fmd->fimc_lite[i] == NULL) continue; v4l2_device_unregister_subdev(&fmd->fimc_lite[i]->subdev); + fmd->fimc[i]->pipeline_ops = NULL; fmd->fimc_lite[i] = NULL; } for (i = 0; i < CSIS_MAX_ENTITIES; i++) { @@ -591,7 +601,7 @@ static int __fimc_md_create_flite_source_links(struct fimc_md *fmd) if (fimc == NULL) continue; source = &fimc->subdev.entity; - sink = &fimc->vfd->entity; + sink = &fimc->vfd.entity; /* FIMC-LITE's subdev and video node */ ret = media_entity_create_link(source, FIMC_SD_PAD_SOURCE, sink, 0, flags); @@ -617,6 +627,7 @@ static int __fimc_md_create_flite_source_links(struct fimc_md *fmd) */ static int fimc_md_create_links(struct fimc_md *fmd) { + struct v4l2_subdev *csi_sensors[2] = { NULL }; struct v4l2_subdev *sensor, *csis; struct s5p_fimc_isp_info *pdata; struct fimc_sensor_info *s_info; @@ -630,11 +641,11 @@ static int fimc_md_create_links(struct fimc_md *fmd) sensor = fmd->sensor[i].subdev; s_info = v4l2_get_subdev_hostdata(sensor); - if (!s_info || !s_info->pdata) + if (!s_info) continue; source = NULL; - pdata = s_info->pdata; + pdata = &s_info->pdata; switch (pdata->bus_type) { case FIMC_MIPI_CSI2: @@ -659,6 +670,7 @@ static int fimc_md_create_links(struct fimc_md *fmd) sensor->entity.name, csis->entity.name); source = NULL; + csi_sensors[pdata->mux_id] = sensor; break; case FIMC_ITU_601...FIMC_ITU_656: @@ -684,9 +696,10 @@ static int fimc_md_create_links(struct fimc_md *fmd) continue; source = &fmd->csis[i].sd->entity; pad = CSIS_PAD_SOURCE; + sensor = csi_sensors[i]; link_mask = 1 << fimc_id++; - ret = __fimc_md_create_fimc_sink_links(fmd, source, NULL, + ret = __fimc_md_create_fimc_sink_links(fmd, source, sensor, pad, link_mask); } @@ -696,7 +709,7 @@ static int fimc_md_create_links(struct fimc_md *fmd) if (!fmd->fimc[i]) continue; source = &fmd->fimc[i]->vid_cap.subdev.entity; - sink = &fmd->fimc[i]->vid_cap.vfd->entity; + sink = &fmd->fimc[i]->vid_cap.vfd.entity; ret = media_entity_create_link(source, FIMC_SD_PAD_SOURCE, sink, 0, flags); if (ret) @@ -744,7 +757,7 @@ static int __fimc_md_set_camclk(struct fimc_md *fmd, struct fimc_sensor_info *s_info, bool on) { - struct s5p_fimc_isp_info *pdata = s_info->pdata; + struct s5p_fimc_isp_info *pdata = &s_info->pdata; struct fimc_camclk_info *camclk; int ret = 0; @@ -829,7 +842,7 @@ static int fimc_md_link_notify(struct media_pad *source, } if (!(flags & MEDIA_LNK_FL_ENABLED)) { - ret = __fimc_pipeline_shutdown(pipeline); + ret = __fimc_pipeline_close(pipeline); pipeline->subdevs[IDX_SENSOR] = NULL; pipeline->subdevs[IDX_CSIS] = NULL; @@ -848,8 +861,8 @@ static int fimc_md_link_notify(struct media_pad *source, if (fimc) { mutex_lock(&fimc->lock); if (fimc->vid_cap.refcnt > 0) { - ret = __fimc_pipeline_initialize(pipeline, - source->entity, true); + ret = __fimc_pipeline_open(pipeline, + source->entity, true); if (!ret) ret = fimc_capture_ctrls_create(fimc); } @@ -857,8 +870,8 @@ static int fimc_md_link_notify(struct media_pad *source, } else { mutex_lock(&fimc_lite->lock); if (fimc_lite->ref_count > 0) { - ret = __fimc_pipeline_initialize(pipeline, - source->entity, true); + ret = __fimc_pipeline_open(pipeline, + source->entity, true); } mutex_unlock(&fimc_lite->lock); } diff --git a/drivers/media/video/s5p-fimc/fimc-mdevice.h b/drivers/media/platform/s5p-fimc/fimc-mdevice.h index 1f5dbaff5442..2d8d41d82620 100644 --- a/drivers/media/video/s5p-fimc/fimc-mdevice.h +++ b/drivers/media/platform/s5p-fimc/fimc-mdevice.h @@ -51,7 +51,7 @@ struct fimc_camclk_info { * This data structure applies to image sensor and the writeback subdevs. */ struct fimc_sensor_info { - struct s5p_fimc_isp_info *pdata; + struct s5p_fimc_isp_info pdata; struct v4l2_subdev *subdev; struct fimc_dev *host; }; @@ -99,22 +99,14 @@ static inline struct fimc_md *entity_to_fimc_mdev(struct media_entity *me) static inline void fimc_md_graph_lock(struct fimc_dev *fimc) { - BUG_ON(fimc->vid_cap.vfd == NULL); - mutex_lock(&fimc->vid_cap.vfd->entity.parent->graph_mutex); + mutex_lock(&fimc->vid_cap.vfd.entity.parent->graph_mutex); } static inline void fimc_md_graph_unlock(struct fimc_dev *fimc) { - BUG_ON(fimc->vid_cap.vfd == NULL); - mutex_unlock(&fimc->vid_cap.vfd->entity.parent->graph_mutex); + mutex_unlock(&fimc->vid_cap.vfd.entity.parent->graph_mutex); } int fimc_md_set_camclk(struct v4l2_subdev *sd, bool on); -void fimc_pipeline_prepare(struct fimc_pipeline *p, struct media_entity *me); -int fimc_pipeline_initialize(struct fimc_pipeline *p, struct media_entity *me, - bool resume); -int fimc_pipeline_shutdown(struct fimc_pipeline *p); -int fimc_pipeline_s_power(struct fimc_pipeline *p, bool state); -int fimc_pipeline_s_stream(struct fimc_pipeline *p, bool state); #endif diff --git a/drivers/media/video/s5p-fimc/fimc-reg.c b/drivers/media/platform/s5p-fimc/fimc-reg.c index 0e3eb9ce4f98..783408fd7d56 100644 --- a/drivers/media/video/s5p-fimc/fimc-reg.c +++ b/drivers/media/platform/s5p-fimc/fimc-reg.c @@ -612,7 +612,7 @@ int fimc_hw_set_camera_source(struct fimc_dev *fimc, } if (i == ARRAY_SIZE(pix_desc)) { - v4l2_err(fimc->vid_cap.vfd, + v4l2_err(&fimc->vid_cap.vfd, "Camera color format not supported: %d\n", fimc->vid_cap.mf.code); return -EINVAL; @@ -684,7 +684,7 @@ int fimc_hw_set_camera_type(struct fimc_dev *fimc, cfg |= FIMC_REG_CIGCTRL_CAM_JPEG; break; default: - v4l2_err(vid_cap->vfd, + v4l2_err(&vid_cap->vfd, "Not supported camera pixel format: %#x\n", vid_cap->mf.code); return -EINVAL; @@ -701,7 +701,7 @@ int fimc_hw_set_camera_type(struct fimc_dev *fimc, cfg |= FIMC_REG_CIGCTRL_CAMIF_SELWB; break; default: - v4l2_err(vid_cap->vfd, "Invalid camera bus type selected\n"); + v4l2_err(&vid_cap->vfd, "Invalid camera bus type selected\n"); return -EINVAL; } writel(cfg, fimc->regs + FIMC_REG_CIGCTRL); diff --git a/drivers/media/video/s5p-fimc/fimc-reg.h b/drivers/media/platform/s5p-fimc/fimc-reg.h index 579ac8ac03de..579ac8ac03de 100644 --- a/drivers/media/video/s5p-fimc/fimc-reg.h +++ b/drivers/media/platform/s5p-fimc/fimc-reg.h diff --git a/drivers/media/video/s5p-fimc/mipi-csis.c b/drivers/media/platform/s5p-fimc/mipi-csis.c index 5e898432883a..e92236ac5cfe 100644 --- a/drivers/media/video/s5p-fimc/mipi-csis.c +++ b/drivers/media/platform/s5p-fimc/mipi-csis.c @@ -31,7 +31,7 @@ static int debug; module_param(debug, int, 0644); -MODULE_PARM_DESC(debug, "Debug level (0-1)"); +MODULE_PARM_DESC(debug, "Debug level (0-2)"); /* Register map definition */ @@ -60,10 +60,38 @@ MODULE_PARM_DESC(debug, "Debug level (0-1)"); #define S5PCSIS_CFG_FMT_MASK (0x3f << 2) #define S5PCSIS_CFG_NR_LANE_MASK 3 -/* Interrupt mask. */ +/* Interrupt mask */ #define S5PCSIS_INTMSK 0x10 -#define S5PCSIS_INTMSK_EN_ALL 0xf000003f +#define S5PCSIS_INTMSK_EN_ALL 0xf000103f +#define S5PCSIS_INTMSK_EVEN_BEFORE (1 << 31) +#define S5PCSIS_INTMSK_EVEN_AFTER (1 << 30) +#define S5PCSIS_INTMSK_ODD_BEFORE (1 << 29) +#define S5PCSIS_INTMSK_ODD_AFTER (1 << 28) +#define S5PCSIS_INTMSK_ERR_SOT_HS (1 << 12) +#define S5PCSIS_INTMSK_ERR_LOST_FS (1 << 5) +#define S5PCSIS_INTMSK_ERR_LOST_FE (1 << 4) +#define S5PCSIS_INTMSK_ERR_OVER (1 << 3) +#define S5PCSIS_INTMSK_ERR_ECC (1 << 2) +#define S5PCSIS_INTMSK_ERR_CRC (1 << 1) +#define S5PCSIS_INTMSK_ERR_UNKNOWN (1 << 0) + +/* Interrupt source */ #define S5PCSIS_INTSRC 0x14 +#define S5PCSIS_INTSRC_EVEN_BEFORE (1 << 31) +#define S5PCSIS_INTSRC_EVEN_AFTER (1 << 30) +#define S5PCSIS_INTSRC_EVEN (0x3 << 30) +#define S5PCSIS_INTSRC_ODD_BEFORE (1 << 29) +#define S5PCSIS_INTSRC_ODD_AFTER (1 << 28) +#define S5PCSIS_INTSRC_ODD (0x3 << 28) +#define S5PCSIS_INTSRC_NON_IMAGE_DATA (0xff << 28) +#define S5PCSIS_INTSRC_ERR_SOT_HS (0xf << 12) +#define S5PCSIS_INTSRC_ERR_LOST_FS (1 << 5) +#define S5PCSIS_INTSRC_ERR_LOST_FE (1 << 4) +#define S5PCSIS_INTSRC_ERR_OVER (1 << 3) +#define S5PCSIS_INTSRC_ERR_ECC (1 << 2) +#define S5PCSIS_INTSRC_ERR_CRC (1 << 1) +#define S5PCSIS_INTSRC_ERR_UNKNOWN (1 << 0) +#define S5PCSIS_INTSRC_ERRORS 0xf03f /* Pixel resolution */ #define S5PCSIS_RESOL 0x2c @@ -93,6 +121,29 @@ enum { ST_SUSPENDED = 4, }; +struct s5pcsis_event { + u32 mask; + const char * const name; + unsigned int counter; +}; + +static const struct s5pcsis_event s5pcsis_events[] = { + /* Errors */ + { S5PCSIS_INTSRC_ERR_SOT_HS, "SOT Error" }, + { S5PCSIS_INTSRC_ERR_LOST_FS, "Lost Frame Start Error" }, + { S5PCSIS_INTSRC_ERR_LOST_FE, "Lost Frame End Error" }, + { S5PCSIS_INTSRC_ERR_OVER, "FIFO Overflow Error" }, + { S5PCSIS_INTSRC_ERR_ECC, "ECC Error" }, + { S5PCSIS_INTSRC_ERR_CRC, "CRC Error" }, + { S5PCSIS_INTSRC_ERR_UNKNOWN, "Unknown Error" }, + /* Non-image data receive events */ + { S5PCSIS_INTSRC_EVEN_BEFORE, "Non-image data before even frame" }, + { S5PCSIS_INTSRC_EVEN_AFTER, "Non-image data after even frame" }, + { S5PCSIS_INTSRC_ODD_BEFORE, "Non-image data before odd frame" }, + { S5PCSIS_INTSRC_ODD_AFTER, "Non-image data after odd frame" }, +}; +#define S5PCSIS_NUM_EVENTS ARRAY_SIZE(s5pcsis_events) + /** * struct csis_state - the driver's internal state data structure * @lock: mutex serializing the subdev and power management operations, @@ -101,11 +152,14 @@ enum { * @sd: v4l2_subdev associated with CSIS device instance * @pdev: CSIS platform device * @regs: mmaped I/O registers memory + * @supplies: CSIS regulator supplies * @clock: CSIS clocks * @irq: requested s5p-mipi-csis irq number * @flags: the state variable for power and streaming control * @csis_fmt: current CSIS pixel format * @format: common media bus format for the source and sink pad + * @slock: spinlock protecting structure members below + * @events: MIPI-CSIS event (error) counters */ struct csis_state { struct mutex lock; @@ -119,6 +173,9 @@ struct csis_state { u32 flags; const struct csis_pix_format *csis_fmt; struct v4l2_mbus_framefmt format; + + struct spinlock slock; + struct s5pcsis_event events[S5PCSIS_NUM_EVENTS]; }; /** @@ -292,17 +349,6 @@ err: return -ENXIO; } -static int s5pcsis_s_power(struct v4l2_subdev *sd, int on) -{ - struct csis_state *state = sd_to_csis_state(sd); - struct device *dev = &state->pdev->dev; - - if (on) - return pm_runtime_get_sync(dev); - - return pm_runtime_put_sync(dev); -} - static void s5pcsis_start_stream(struct csis_state *state) { s5pcsis_reset(state); @@ -317,7 +363,47 @@ static void s5pcsis_stop_stream(struct csis_state *state) s5pcsis_system_enable(state, false); } -/* v4l2_subdev operations */ +static void s5pcsis_clear_counters(struct csis_state *state) +{ + unsigned long flags; + int i; + + spin_lock_irqsave(&state->slock, flags); + for (i = 0; i < S5PCSIS_NUM_EVENTS; i++) + state->events[i].counter = 0; + spin_unlock_irqrestore(&state->slock, flags); +} + +static void s5pcsis_log_counters(struct csis_state *state, bool non_errors) +{ + int i = non_errors ? S5PCSIS_NUM_EVENTS : S5PCSIS_NUM_EVENTS - 4; + unsigned long flags; + + spin_lock_irqsave(&state->slock, flags); + + for (i--; i >= 0; i--) + if (state->events[i].counter >= 0) + v4l2_info(&state->sd, "%s events: %d\n", + state->events[i].name, + state->events[i].counter); + + spin_unlock_irqrestore(&state->slock, flags); +} + +/* + * V4L2 subdev operations + */ +static int s5pcsis_s_power(struct v4l2_subdev *sd, int on) +{ + struct csis_state *state = sd_to_csis_state(sd); + struct device *dev = &state->pdev->dev; + + if (on) + return pm_runtime_get_sync(dev); + + return pm_runtime_put_sync(dev); +} + static int s5pcsis_s_stream(struct v4l2_subdev *sd, int enable) { struct csis_state *state = sd_to_csis_state(sd); @@ -327,10 +413,12 @@ static int s5pcsis_s_stream(struct v4l2_subdev *sd, int enable) __func__, enable, state->flags); if (enable) { + s5pcsis_clear_counters(state); ret = pm_runtime_get_sync(&state->pdev->dev); if (ret && ret != 1) return ret; } + mutex_lock(&state->lock); if (enable) { if (state->flags & ST_SUSPENDED) { @@ -342,6 +430,8 @@ static int s5pcsis_s_stream(struct v4l2_subdev *sd, int enable) } else { s5pcsis_stop_stream(state); state->flags &= ~ST_STREAMING; + if (debug > 0) + s5pcsis_log_counters(state, true); } unlock: mutex_unlock(&state->lock); @@ -439,6 +529,14 @@ static int s5pcsis_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, return 0; } +static int s5pcsis_log_status(struct v4l2_subdev *sd) +{ + struct csis_state *state = sd_to_csis_state(sd); + + s5pcsis_log_counters(state, true); + return 0; +} + static int s5pcsis_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) { struct v4l2_mbus_framefmt *format = v4l2_subdev_get_try_format(fh, 0); @@ -458,6 +556,7 @@ static const struct v4l2_subdev_internal_ops s5pcsis_sd_internal_ops = { static struct v4l2_subdev_core_ops s5pcsis_core_ops = { .s_power = s5pcsis_s_power, + .log_status = s5pcsis_log_status, }; static struct v4l2_subdev_pad_ops s5pcsis_pad_ops = { @@ -479,12 +578,29 @@ static struct v4l2_subdev_ops s5pcsis_subdev_ops = { static irqreturn_t s5pcsis_irq_handler(int irq, void *dev_id) { struct csis_state *state = dev_id; - u32 val; - - /* Just clear the interrupt pending bits. */ - val = s5pcsis_read(state, S5PCSIS_INTSRC); - s5pcsis_write(state, S5PCSIS_INTSRC, val); + unsigned long flags; + u32 status; + + status = s5pcsis_read(state, S5PCSIS_INTSRC); + + spin_lock_irqsave(&state->slock, flags); + + /* Update the event/error counters */ + if ((status & S5PCSIS_INTSRC_ERRORS) || debug) { + int i; + for (i = 0; i < S5PCSIS_NUM_EVENTS; i++) { + if (!(status & state->events[i].mask)) + continue; + state->events[i].counter++; + v4l2_dbg(2, debug, &state->sd, "%s: %d\n", + state->events[i].name, + state->events[i].counter); + } + v4l2_dbg(2, debug, &state->sd, "status: %08x\n", status); + } + spin_unlock_irqrestore(&state->slock, flags); + s5pcsis_write(state, S5PCSIS_INTSRC, status); return IRQ_HANDLED; } @@ -501,6 +617,8 @@ static int __devinit s5pcsis_probe(struct platform_device *pdev) return -ENOMEM; mutex_init(&state->lock); + spin_lock_init(&state->slock); + state->pdev = pdev; pdata = pdev->dev.platform_data; @@ -577,6 +695,8 @@ static int __devinit s5pcsis_probe(struct platform_device *pdev) /* .. and a pointer to the subdev. */ platform_set_drvdata(pdev, &state->sd); + memcpy(state->events, s5pcsis_events, sizeof(state->events)); + pm_runtime_enable(&pdev->dev); return 0; diff --git a/drivers/media/video/s5p-fimc/mipi-csis.h b/drivers/media/platform/s5p-fimc/mipi-csis.h index 2709286396e1..2709286396e1 100644 --- a/drivers/media/video/s5p-fimc/mipi-csis.h +++ b/drivers/media/platform/s5p-fimc/mipi-csis.h diff --git a/drivers/media/video/s5p-g2d/Makefile b/drivers/media/platform/s5p-g2d/Makefile index 2c48c416a804..2c48c416a804 100644 --- a/drivers/media/video/s5p-g2d/Makefile +++ b/drivers/media/platform/s5p-g2d/Makefile diff --git a/drivers/media/video/s5p-g2d/g2d-hw.c b/drivers/media/platform/s5p-g2d/g2d-hw.c index 5b86cbe408e2..5b86cbe408e2 100644 --- a/drivers/media/video/s5p-g2d/g2d-hw.c +++ b/drivers/media/platform/s5p-g2d/g2d-hw.c diff --git a/drivers/media/video/s5p-g2d/g2d-regs.h b/drivers/media/platform/s5p-g2d/g2d-regs.h index 02e1cf50da4e..02e1cf50da4e 100644 --- a/drivers/media/video/s5p-g2d/g2d-regs.h +++ b/drivers/media/platform/s5p-g2d/g2d-regs.h diff --git a/drivers/media/video/s5p-g2d/g2d.c b/drivers/media/platform/s5p-g2d/g2d.c index 7c2200435206..1e3b9dd014c0 100644 --- a/drivers/media/video/s5p-g2d/g2d.c +++ b/drivers/media/platform/s5p-g2d/g2d.c @@ -151,7 +151,6 @@ static int queue_init(void *priv, struct vb2_queue *src_vq, struct g2d_ctx *ctx = priv; int ret; - memset(src_vq, 0, sizeof(*src_vq)); src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; src_vq->io_modes = VB2_MMAP | VB2_USERPTR; src_vq->drv_priv = ctx; @@ -163,7 +162,6 @@ static int queue_init(void *priv, struct vb2_queue *src_vq, if (ret) return ret; - memset(dst_vq, 0, sizeof(*dst_vq)); dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; dst_vq->io_modes = VB2_MMAP | VB2_USERPTR; dst_vq->drv_priv = ctx; @@ -248,9 +246,14 @@ static int g2d_open(struct file *file) ctx->in = def_frame; ctx->out = def_frame; + if (mutex_lock_interruptible(&dev->mutex)) { + kfree(ctx); + return -ERESTARTSYS; + } ctx->m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev, ctx, &queue_init); if (IS_ERR(ctx->m2m_ctx)) { ret = PTR_ERR(ctx->m2m_ctx); + mutex_unlock(&dev->mutex); kfree(ctx); return ret; } @@ -264,6 +267,7 @@ static int g2d_open(struct file *file) v4l2_ctrl_handler_setup(&ctx->ctrl_handler); ctx->fh.ctrl_handler = &ctx->ctrl_handler; + mutex_unlock(&dev->mutex); v4l2_info(&dev->v4l2_dev, "instance opened\n"); return 0; @@ -406,13 +410,26 @@ static int vidioc_s_fmt(struct file *file, void *prv, struct v4l2_format *f) static unsigned int g2d_poll(struct file *file, struct poll_table_struct *wait) { struct g2d_ctx *ctx = fh2ctx(file->private_data); - return v4l2_m2m_poll(file, ctx->m2m_ctx, wait); + struct g2d_dev *dev = ctx->dev; + unsigned int res; + + mutex_lock(&dev->mutex); + res = v4l2_m2m_poll(file, ctx->m2m_ctx, wait); + mutex_unlock(&dev->mutex); + return res; } static int g2d_mmap(struct file *file, struct vm_area_struct *vma) { struct g2d_ctx *ctx = fh2ctx(file->private_data); - return v4l2_m2m_mmap(file, ctx->m2m_ctx, vma); + struct g2d_dev *dev = ctx->dev; + int ret; + + if (mutex_lock_interruptible(&dev->mutex)) + return -ERESTARTSYS; + ret = v4l2_m2m_mmap(file, ctx->m2m_ctx, vma); + mutex_unlock(&dev->mutex); + return ret; } static int vidioc_reqbufs(struct file *file, void *priv, @@ -509,7 +526,7 @@ static int vidioc_try_crop(struct file *file, void *prv, struct v4l2_crop *cr) return 0; } -static int vidioc_s_crop(struct file *file, void *prv, struct v4l2_crop *cr) +static int vidioc_s_crop(struct file *file, void *prv, const struct v4l2_crop *cr) { struct g2d_ctx *ctx = prv; struct g2d_frame *f; @@ -663,6 +680,7 @@ static struct video_device g2d_videodev = { .ioctl_ops = &g2d_ioctl_ops, .minor = -1, .release = video_device_release, + .vfl_dir = VFL_DIR_M2M, }; static struct v4l2_m2m_ops g2d_m2m_ops = { @@ -753,10 +771,6 @@ static int g2d_probe(struct platform_device *pdev) goto unreg_v4l2_dev; } *vfd = g2d_videodev; - /* Locking in file operations other than ioctl should be done - by the driver, not the V4L2 core. - This driver needs auditing so that this flag can be removed. */ - set_bit(V4L2_FL_LOCK_ALL_FOPS, &vfd->flags); vfd->lock = &dev->mutex; ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0); if (ret) { diff --git a/drivers/media/video/s5p-g2d/g2d.h b/drivers/media/platform/s5p-g2d/g2d.h index 6b765b0216c5..6b765b0216c5 100644 --- a/drivers/media/video/s5p-g2d/g2d.h +++ b/drivers/media/platform/s5p-g2d/g2d.h diff --git a/drivers/media/video/s5p-jpeg/Makefile b/drivers/media/platform/s5p-jpeg/Makefile index ddc2900d88a2..ddc2900d88a2 100644 --- a/drivers/media/video/s5p-jpeg/Makefile +++ b/drivers/media/platform/s5p-jpeg/Makefile diff --git a/drivers/media/video/s5p-jpeg/jpeg-core.c b/drivers/media/platform/s5p-jpeg/jpeg-core.c index 813b801238d1..394775ae5774 100644 --- a/drivers/media/video/s5p-jpeg/jpeg-core.c +++ b/drivers/media/platform/s5p-jpeg/jpeg-core.c @@ -1,4 +1,4 @@ -/* linux/drivers/media/video/s5p-jpeg/jpeg-core.c +/* linux/drivers/media/platform/s5p-jpeg/jpeg-core.c * * Copyright (c) 2011 Samsung Electronics Co., Ltd. * http://www.samsung.com @@ -288,10 +288,15 @@ static int s5p_jpeg_open(struct file *file) struct s5p_jpeg_fmt *out_fmt; int ret = 0; - ctx = kzalloc(sizeof *ctx, GFP_KERNEL); + ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); if (!ctx) return -ENOMEM; + if (mutex_lock_interruptible(&jpeg->lock)) { + ret = -ERESTARTSYS; + goto free; + } + v4l2_fh_init(&ctx->fh, vfd); /* Use separate control handler per file handle */ ctx->fh.ctrl_handler = &ctx->ctrl_handler; @@ -319,20 +324,26 @@ static int s5p_jpeg_open(struct file *file) ctx->out_q.fmt = out_fmt; ctx->cap_q.fmt = s5p_jpeg_find_format(ctx->mode, V4L2_PIX_FMT_YUYV); + mutex_unlock(&jpeg->lock); return 0; error: v4l2_fh_del(&ctx->fh); v4l2_fh_exit(&ctx->fh); + mutex_unlock(&jpeg->lock); +free: kfree(ctx); return ret; } static int s5p_jpeg_release(struct file *file) { + struct s5p_jpeg *jpeg = video_drvdata(file); struct s5p_jpeg_ctx *ctx = fh_to_ctx(file->private_data); + mutex_lock(&jpeg->lock); v4l2_m2m_ctx_release(ctx->m2m_ctx); + mutex_unlock(&jpeg->lock); v4l2_ctrl_handler_free(&ctx->ctrl_handler); v4l2_fh_del(&ctx->fh); v4l2_fh_exit(&ctx->fh); @@ -344,16 +355,27 @@ static int s5p_jpeg_release(struct file *file) static unsigned int s5p_jpeg_poll(struct file *file, struct poll_table_struct *wait) { + struct s5p_jpeg *jpeg = video_drvdata(file); struct s5p_jpeg_ctx *ctx = fh_to_ctx(file->private_data); + unsigned int res; - return v4l2_m2m_poll(file, ctx->m2m_ctx, wait); + mutex_lock(&jpeg->lock); + res = v4l2_m2m_poll(file, ctx->m2m_ctx, wait); + mutex_unlock(&jpeg->lock); + return res; } static int s5p_jpeg_mmap(struct file *file, struct vm_area_struct *vma) { + struct s5p_jpeg *jpeg = video_drvdata(file); struct s5p_jpeg_ctx *ctx = fh_to_ctx(file->private_data); + int ret; - return v4l2_m2m_mmap(file, ctx->m2m_ctx, vma); + if (mutex_lock_interruptible(&jpeg->lock)) + return -ERESTARTSYS; + ret = v4l2_m2m_mmap(file, ctx->m2m_ctx, vma); + mutex_unlock(&jpeg->lock); + return ret; } static const struct v4l2_file_operations s5p_jpeg_fops = { @@ -1201,7 +1223,6 @@ static int queue_init(void *priv, struct vb2_queue *src_vq, struct s5p_jpeg_ctx *ctx = priv; int ret; - memset(src_vq, 0, sizeof(*src_vq)); src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; src_vq->io_modes = VB2_MMAP | VB2_USERPTR; src_vq->drv_priv = ctx; @@ -1213,7 +1234,6 @@ static int queue_init(void *priv, struct vb2_queue *src_vq, if (ret) return ret; - memset(dst_vq, 0, sizeof(*dst_vq)); dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; dst_vq->io_modes = VB2_MMAP | VB2_USERPTR; dst_vq->drv_priv = ctx; @@ -1372,10 +1392,7 @@ static int s5p_jpeg_probe(struct platform_device *pdev) jpeg->vfd_encoder->release = video_device_release; jpeg->vfd_encoder->lock = &jpeg->lock; jpeg->vfd_encoder->v4l2_dev = &jpeg->v4l2_dev; - /* Locking in file operations other than ioctl should be done - by the driver, not the V4L2 core. - This driver needs auditing so that this flag can be removed. */ - set_bit(V4L2_FL_LOCK_ALL_FOPS, &jpeg->vfd_encoder->flags); + jpeg->vfd_encoder->vfl_dir = VFL_DIR_M2M; ret = video_register_device(jpeg->vfd_encoder, VFL_TYPE_GRABBER, -1); if (ret) { @@ -1403,10 +1420,6 @@ static int s5p_jpeg_probe(struct platform_device *pdev) jpeg->vfd_decoder->release = video_device_release; jpeg->vfd_decoder->lock = &jpeg->lock; jpeg->vfd_decoder->v4l2_dev = &jpeg->v4l2_dev; - /* Locking in file operations other than ioctl should be done by the driver, - not the V4L2 core. - This driver needs auditing so that this flag can be removed. */ - set_bit(V4L2_FL_LOCK_ALL_FOPS, &jpeg->vfd_decoder->flags); ret = video_register_device(jpeg->vfd_decoder, VFL_TYPE_GRABBER, -1); if (ret) { diff --git a/drivers/media/video/s5p-jpeg/jpeg-core.h b/drivers/media/platform/s5p-jpeg/jpeg-core.h index 9d0cd2b76f61..022b9b9baff9 100644 --- a/drivers/media/video/s5p-jpeg/jpeg-core.h +++ b/drivers/media/platform/s5p-jpeg/jpeg-core.h @@ -1,4 +1,4 @@ -/* linux/drivers/media/video/s5p-jpeg/jpeg-core.h +/* linux/drivers/media/platform/s5p-jpeg/jpeg-core.h * * Copyright (c) 2011 Samsung Electronics Co., Ltd. * http://www.samsung.com diff --git a/drivers/media/video/s5p-jpeg/jpeg-hw.h b/drivers/media/platform/s5p-jpeg/jpeg-hw.h index f12f0fdbde7c..b47e887b6138 100644 --- a/drivers/media/video/s5p-jpeg/jpeg-hw.h +++ b/drivers/media/platform/s5p-jpeg/jpeg-hw.h @@ -1,4 +1,4 @@ -/* linux/drivers/media/video/s5p-jpeg/jpeg-hw.h +/* linux/drivers/media/platform/s5p-jpeg/jpeg-hw.h * * Copyright (c) 2011 Samsung Electronics Co., Ltd. * http://www.samsung.com diff --git a/drivers/media/video/s5p-jpeg/jpeg-regs.h b/drivers/media/platform/s5p-jpeg/jpeg-regs.h index 91f4dd5f86dd..38e50815668c 100644 --- a/drivers/media/video/s5p-jpeg/jpeg-regs.h +++ b/drivers/media/platform/s5p-jpeg/jpeg-regs.h @@ -1,4 +1,4 @@ -/* linux/drivers/media/video/s5p-jpeg/jpeg-regs.h +/* linux/drivers/media/platform/s5p-jpeg/jpeg-regs.h * * Register definition file for Samsung JPEG codec driver * diff --git a/drivers/media/video/s5p-mfc/Makefile b/drivers/media/platform/s5p-mfc/Makefile index d0663409af00..d0663409af00 100644 --- a/drivers/media/video/s5p-mfc/Makefile +++ b/drivers/media/platform/s5p-mfc/Makefile diff --git a/drivers/media/video/s5p-mfc/regs-mfc.h b/drivers/media/platform/s5p-mfc/regs-mfc.h index a19bece41ba9..a19bece41ba9 100644 --- a/drivers/media/video/s5p-mfc/regs-mfc.h +++ b/drivers/media/platform/s5p-mfc/regs-mfc.h diff --git a/drivers/media/video/s5p-mfc/s5p_mfc.c b/drivers/media/platform/s5p-mfc/s5p_mfc.c index 9bb68e7b5ae8..5587ef15ca4f 100644 --- a/drivers/media/video/s5p-mfc/s5p_mfc.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c @@ -19,6 +19,7 @@ #include <linux/sched.h> #include <linux/slab.h> #include <linux/videodev2.h> +#include <media/v4l2-event.h> #include <linux/workqueue.h> #include <media/videobuf2-core.h> #include "regs-mfc.h" @@ -40,16 +41,49 @@ module_param(debug, int, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(debug, "Debug level - higher value produces more verbose messages"); /* Helper functions for interrupt processing */ + /* Remove from hw execution round robin */ -static void clear_work_bit(struct s5p_mfc_ctx *ctx) +void clear_work_bit(struct s5p_mfc_ctx *ctx) +{ + struct s5p_mfc_dev *dev = ctx->dev; + + spin_lock(&dev->condlock); + __clear_bit(ctx->num, &dev->ctx_work_bits); + spin_unlock(&dev->condlock); +} + +/* Add to hw execution round robin */ +void set_work_bit(struct s5p_mfc_ctx *ctx) { struct s5p_mfc_dev *dev = ctx->dev; spin_lock(&dev->condlock); - clear_bit(ctx->num, &dev->ctx_work_bits); + __set_bit(ctx->num, &dev->ctx_work_bits); spin_unlock(&dev->condlock); } +/* Remove from hw execution round robin */ +void clear_work_bit_irqsave(struct s5p_mfc_ctx *ctx) +{ + struct s5p_mfc_dev *dev = ctx->dev; + unsigned long flags; + + spin_lock_irqsave(&dev->condlock, flags); + __clear_bit(ctx->num, &dev->ctx_work_bits); + spin_unlock_irqrestore(&dev->condlock, flags); +} + +/* Add to hw execution round robin */ +void set_work_bit_irqsave(struct s5p_mfc_ctx *ctx) +{ + struct s5p_mfc_dev *dev = ctx->dev; + unsigned long flags; + + spin_lock_irqsave(&dev->condlock, flags); + __set_bit(ctx->num, &dev->ctx_work_bits); + spin_unlock_irqrestore(&dev->condlock, flags); +} + /* Wake up context wait_queue */ static void wake_up_ctx(struct s5p_mfc_ctx *ctx, unsigned int reason, unsigned int err) @@ -503,9 +537,7 @@ static void s5p_mfc_handle_init_buffers(struct s5p_mfc_ctx *ctx, ctx->int_type = reason; ctx->int_err = err; ctx->int_cond = 1; - spin_lock(&dev->condlock); - clear_bit(ctx->num, &dev->ctx_work_bits); - spin_unlock(&dev->condlock); + clear_work_bit(ctx); if (err == 0) { ctx->state = MFCINST_RUNNING; if (!ctx->dpb_flush_flag) { @@ -539,6 +571,40 @@ static void s5p_mfc_handle_init_buffers(struct s5p_mfc_ctx *ctx, } } +static void s5p_mfc_handle_stream_complete(struct s5p_mfc_ctx *ctx, + unsigned int reason, unsigned int err) +{ + struct s5p_mfc_dev *dev = ctx->dev; + struct s5p_mfc_buf *mb_entry; + + mfc_debug(2, "Stream completed"); + + s5p_mfc_clear_int_flags(dev); + ctx->int_type = reason; + ctx->int_err = err; + ctx->state = MFCINST_FINISHED; + + spin_lock(&dev->irqlock); + if (!list_empty(&ctx->dst_queue)) { + mb_entry = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, + list); + list_del(&mb_entry->list); + ctx->dst_queue_cnt--; + vb2_set_plane_payload(mb_entry->b, 0, 0); + vb2_buffer_done(mb_entry->b, VB2_BUF_STATE_DONE); + } + spin_unlock(&dev->irqlock); + + clear_work_bit(ctx); + + if (test_and_clear_bit(0, &dev->hw_lock) == 0) + WARN_ON(1); + + s5p_mfc_clock_off(); + wake_up(&ctx->queue); + s5p_mfc_try_run(dev); +} + /* Interrupt processing */ static irqreturn_t s5p_mfc_irq(int irq, void *priv) { @@ -614,6 +680,11 @@ static irqreturn_t s5p_mfc_irq(int irq, void *priv) case S5P_FIMV_R2H_CMD_INIT_BUFFERS_RET: s5p_mfc_handle_init_buffers(ctx, reason, err); break; + + case S5P_FIMV_R2H_CMD_ENC_COMPLETE_RET: + s5p_mfc_handle_stream_complete(ctx, reason, err); + break; + default: mfc_debug(2, "Unknown int reason\n"); s5p_mfc_clear_int_flags(dev); @@ -641,13 +712,14 @@ static int s5p_mfc_open(struct file *file) struct s5p_mfc_dev *dev = video_drvdata(file); struct s5p_mfc_ctx *ctx = NULL; struct vb2_queue *q; - unsigned long flags; int ret = 0; mfc_debug_enter(); + if (mutex_lock_interruptible(&dev->mfc_mutex)) + return -ERESTARTSYS; dev->num_inst++; /* It is guarded by mfc_mutex in vfd */ /* Allocate memory for context */ - ctx = kzalloc(sizeof *ctx, GFP_KERNEL); + ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); if (!ctx) { mfc_err("Not enough memory\n"); ret = -ENOMEM; @@ -672,9 +744,7 @@ static int s5p_mfc_open(struct file *file) } } /* Mark context as idle */ - spin_lock_irqsave(&dev->condlock, flags); - clear_bit(ctx->num, &dev->ctx_work_bits); - spin_unlock_irqrestore(&dev->condlock, flags); + clear_work_bit_irqsave(ctx); dev->ctx[ctx->num] = ctx; if (s5p_mfc_get_node_type(file) == MFCNODE_DECODER) { ctx->type = MFCINST_DECODER; @@ -765,6 +835,7 @@ static int s5p_mfc_open(struct file *file) goto err_queue_init; } init_waitqueue_head(&ctx->queue); + mutex_unlock(&dev->mfc_mutex); mfc_debug_leave(); return ret; /* Deinit when failure occured */ @@ -790,6 +861,7 @@ err_no_ctx: kfree(ctx); err_alloc: dev->num_inst--; + mutex_unlock(&dev->mfc_mutex); mfc_debug_leave(); return ret; } @@ -799,24 +871,20 @@ static int s5p_mfc_release(struct file *file) { struct s5p_mfc_ctx *ctx = fh_to_ctx(file->private_data); struct s5p_mfc_dev *dev = ctx->dev; - unsigned long flags; mfc_debug_enter(); + mutex_lock(&dev->mfc_mutex); s5p_mfc_clock_on(); vb2_queue_release(&ctx->vq_src); vb2_queue_release(&ctx->vq_dst); /* Mark context as idle */ - spin_lock_irqsave(&dev->condlock, flags); - clear_bit(ctx->num, &dev->ctx_work_bits); - spin_unlock_irqrestore(&dev->condlock, flags); + clear_work_bit_irqsave(ctx); /* If instance was initialised then * return instance and free reosurces */ if (ctx->inst_no != MFC_NO_INSTANCE_SET) { mfc_debug(2, "Has to free instance\n"); ctx->state = MFCINST_RETURN_INST; - spin_lock_irqsave(&dev->condlock, flags); - set_bit(ctx->num, &dev->ctx_work_bits); - spin_unlock_irqrestore(&dev->condlock, flags); + set_work_bit_irqsave(ctx); s5p_mfc_clean_ctx_int_flags(ctx); s5p_mfc_try_run(dev); /* Wait until instance is returned or timeout occured */ @@ -855,6 +923,7 @@ static int s5p_mfc_release(struct file *file) v4l2_fh_exit(&ctx->fh); kfree(ctx); mfc_debug_leave(); + mutex_unlock(&dev->mfc_mutex); return 0; } @@ -869,6 +938,7 @@ static unsigned int s5p_mfc_poll(struct file *file, unsigned int rc = 0; unsigned long flags; + mutex_lock(&dev->mfc_mutex); src_q = &ctx->vq_src; dst_q = &ctx->vq_dst; /* @@ -882,9 +952,12 @@ static unsigned int s5p_mfc_poll(struct file *file, goto end; } mutex_unlock(&dev->mfc_mutex); + poll_wait(file, &ctx->fh.wait, wait); poll_wait(file, &src_q->done_wq, wait); poll_wait(file, &dst_q->done_wq, wait); mutex_lock(&dev->mfc_mutex); + if (v4l2_event_pending(&ctx->fh)) + rc |= POLLPRI; spin_lock_irqsave(&src_q->done_lock, flags); if (!list_empty(&src_q->done_list)) src_vb = list_first_entry(&src_q->done_list, struct vb2_buffer, @@ -902,6 +975,7 @@ static unsigned int s5p_mfc_poll(struct file *file, rc |= POLLIN | POLLRDNORM; spin_unlock_irqrestore(&dst_q->done_lock, flags); end: + mutex_unlock(&dev->mfc_mutex); return rc; } @@ -909,8 +983,12 @@ end: static int s5p_mfc_mmap(struct file *file, struct vm_area_struct *vma) { struct s5p_mfc_ctx *ctx = fh_to_ctx(file->private_data); + struct s5p_mfc_dev *dev = ctx->dev; unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; int ret; + + if (mutex_lock_interruptible(&dev->mfc_mutex)) + return -ERESTARTSYS; if (offset < DST_QUEUE_OFF_BASE) { mfc_debug(2, "mmaping source\n"); ret = vb2_mmap(&ctx->vq_src, vma); @@ -919,6 +997,7 @@ static int s5p_mfc_mmap(struct file *file, struct vm_area_struct *vma) vma->vm_pgoff -= (DST_QUEUE_OFF_BASE >> PAGE_SHIFT); ret = vb2_mmap(&ctx->vq_dst, vma); } + mutex_unlock(&dev->mfc_mutex); return ret; } @@ -948,7 +1027,7 @@ static int s5p_mfc_probe(struct platform_device *pdev) int ret; pr_debug("%s++\n", __func__); - dev = devm_kzalloc(&pdev->dev, sizeof *dev, GFP_KERNEL); + dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL); if (!dev) { dev_err(&pdev->dev, "Not enough memory for MFC device\n"); return -ENOMEM; @@ -1034,11 +1113,8 @@ static int s5p_mfc_probe(struct platform_device *pdev) vfd->ioctl_ops = get_dec_v4l2_ioctl_ops(); vfd->release = video_device_release, vfd->lock = &dev->mfc_mutex; - /* Locking in file operations other than ioctl should be done - by the driver, not the V4L2 core. - This driver needs auditing so that this flag can be removed. */ - set_bit(V4L2_FL_LOCK_ALL_FOPS, &vfd->flags); vfd->v4l2_dev = &dev->v4l2_dev; + vfd->vfl_dir = VFL_DIR_M2M; snprintf(vfd->name, sizeof(vfd->name), "%s", S5P_MFC_DEC_NAME); dev->vfd_dec = vfd; ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0); @@ -1062,8 +1138,6 @@ static int s5p_mfc_probe(struct platform_device *pdev) vfd->ioctl_ops = get_enc_v4l2_ioctl_ops(); vfd->release = video_device_release, vfd->lock = &dev->mfc_mutex; - /* This should not be necessary */ - set_bit(V4L2_FL_LOCK_ALL_FOPS, &vfd->flags); vfd->v4l2_dev = &dev->v4l2_dev; snprintf(vfd->name, sizeof(vfd->name), "%s", S5P_MFC_ENC_NAME); dev->vfd_enc = vfd; @@ -1141,7 +1215,7 @@ static int s5p_mfc_suspend(struct device *dev) if (m_dev->num_inst == 0) return 0; - return s5p_mfc_sleep(m_dev); + if (test_and_set_bit(0, &m_dev->enter_suspend) != 0) { mfc_err("Error: going to suspend for a second time\n"); return -EIO; @@ -1160,7 +1234,8 @@ static int s5p_mfc_suspend(struct device *dev) return -EIO; } } - return 0; + + return s5p_mfc_sleep(m_dev); } static int s5p_mfc_resume(struct device *dev) diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_cmd.c b/drivers/media/platform/s5p-mfc/s5p_mfc_cmd.c index f0665ed1a529..91a415573bd2 100644 --- a/drivers/media/video/s5p-mfc/s5p_mfc_cmd.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_cmd.c @@ -1,5 +1,5 @@ /* - * linux/drivers/media/video/s5p-mfc/s5p_mfc_cmd.c + * linux/drivers/media/platform/s5p-mfc/s5p_mfc_cmd.c * * Copyright (C) 2011 Samsung Electronics Co., Ltd. * http://www.samsung.com/ diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_cmd.h b/drivers/media/platform/s5p-mfc/s5p_mfc_cmd.h index 5ceebfe6131a..8b090d3723e7 100644 --- a/drivers/media/video/s5p-mfc/s5p_mfc_cmd.h +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_cmd.h @@ -1,5 +1,5 @@ /* - * linux/drivers/media/video/s5p-mfc/s5p_mfc_cmd.h + * linux/drivers/media/platform/s5p-mfc/s5p_mfc_cmd.h * * Copyright (C) 2011 Samsung Electronics Co., Ltd. * http://www.samsung.com/ diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_common.h b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h index bd5706a6bad1..519b0d66d8d1 100644 --- a/drivers/media/video/s5p-mfc/s5p_mfc_common.h +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h @@ -146,6 +146,9 @@ enum s5p_mfc_decode_arg { MFC_DEC_RES_CHANGE, }; +#define MFC_BUF_FLAG_USED (1 << 0) +#define MFC_BUF_FLAG_EOS (1 << 1) + struct s5p_mfc_ctx; /** @@ -161,7 +164,7 @@ struct s5p_mfc_buf { } raw; size_t stream; } cookie; - int used; + int flags; }; /** @@ -567,4 +570,9 @@ struct mfc_control { #define ctrl_to_ctx(__ctrl) \ container_of((__ctrl)->handler, struct s5p_mfc_ctx, ctrl_handler) +void clear_work_bit(struct s5p_mfc_ctx *ctx); +void set_work_bit(struct s5p_mfc_ctx *ctx); +void clear_work_bit_irqsave(struct s5p_mfc_ctx *ctx); +void set_work_bit_irqsave(struct s5p_mfc_ctx *ctx); + #endif /* S5P_MFC_COMMON_H_ */ diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_ctrl.c b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c index 08a5cfeaa59e..0deba6bc687c 100644 --- a/drivers/media/video/s5p-mfc/s5p_mfc_ctrl.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c @@ -1,5 +1,5 @@ /* - * linux/drivers/media/video/s5p-mfc/s5p_mfc_ctrl.c + * linux/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c * * Copyright (c) 2010 Samsung Electronics Co., Ltd. * http://www.samsung.com/ @@ -78,7 +78,7 @@ int s5p_mfc_alloc_and_load_firmware(struct s5p_mfc_dev *dev) } dev->bank1 = s5p_mfc_bitproc_phys; b_base = vb2_dma_contig_memops.alloc( - dev->alloc_ctx[MFC_BANK2_ALLOC_CTX], 1 << MFC_BANK2_ALIGN_ORDER); + dev->alloc_ctx[MFC_BANK2_ALLOC_CTX], 1 << MFC_BASE_ALIGN_ORDER); if (IS_ERR(b_base)) { vb2_dma_contig_memops.put(s5p_mfc_bitproc_buf); s5p_mfc_bitproc_phys = 0; @@ -98,7 +98,11 @@ int s5p_mfc_alloc_and_load_firmware(struct s5p_mfc_dev *dev) release_firmware(fw_blob); return -EIO; } - dev->bank2 = bank2_base_phys; + /* Valid buffers passed to MFC encoder with LAST_FRAME command + * should not have address of bank2 - MFC will treat it as a null frame. + * To avoid such situation we set bank2 address below the pool address. + */ + dev->bank2 = bank2_base_phys - (1 << MFC_BASE_ALIGN_ORDER); memcpy(s5p_mfc_bitproc_virt, fw_blob->data, fw_blob->size); wmb(); release_firmware(fw_blob); diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_ctrl.h b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.h index 61dc23b7ee5a..e1e0c544b6a2 100644 --- a/drivers/media/video/s5p-mfc/s5p_mfc_ctrl.h +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.h @@ -1,5 +1,5 @@ /* - * linux/drivers/media/video/s5p-mfc/s5p_mfc_ctrl.h + * linux/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.h * * Copyright (c) 2010 Samsung Electronics Co., Ltd. * http://www.samsung.com/ diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_debug.h b/drivers/media/platform/s5p-mfc/s5p_mfc_debug.h index ecb8616a492a..bd5cd4ae993c 100644 --- a/drivers/media/video/s5p-mfc/s5p_mfc_debug.h +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_debug.h @@ -1,5 +1,5 @@ /* - * drivers/media/video/samsung/mfc5/s5p_mfc_debug.h + * drivers/media/platform/samsung/mfc5/s5p_mfc_debug.h * * Header file for Samsung MFC (Multi Function Codec - FIMV) driver * This file contains debug macros diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_dec.c b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c index c5d567f87d77..6ee21bb71398 100644 --- a/drivers/media/video/s5p-mfc/s5p_mfc_dec.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c @@ -1,5 +1,5 @@ /* - * linux/drivers/media/video/s5p-mfc/s5p_mfc_dec.c + * linux/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c * * Copyright (C) 2011 Samsung Electronics Co., Ltd. * http://www.samsung.com/ @@ -415,7 +415,6 @@ static int vidioc_reqbufs(struct file *file, void *priv, struct s5p_mfc_dev *dev = video_drvdata(file); struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); int ret = 0; - unsigned long flags; if (reqbufs->memory != V4L2_MEMORY_MMAP) { mfc_err("Only V4L2_MEMORY_MAP is supported\n"); @@ -497,11 +496,8 @@ static int vidioc_reqbufs(struct file *file, void *priv, s5p_mfc_clock_off(); return -ENOMEM; } - if (s5p_mfc_ctx_ready(ctx)) { - spin_lock_irqsave(&dev->condlock, flags); - set_bit(ctx->num, &dev->ctx_work_bits); - spin_unlock_irqrestore(&dev->condlock, flags); - } + if (s5p_mfc_ctx_ready(ctx)) + set_work_bit_irqsave(ctx); s5p_mfc_try_run(dev); s5p_mfc_wait_for_done_ctx(ctx, S5P_FIMV_R2H_CMD_INIT_BUFFERS_RET, 0); @@ -576,7 +572,6 @@ static int vidioc_streamon(struct file *file, void *priv, { struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); struct s5p_mfc_dev *dev = ctx->dev; - unsigned long flags; int ret = -EINVAL; mfc_debug_enter(); @@ -589,9 +584,7 @@ static int vidioc_streamon(struct file *file, void *priv, ctx->output_state = QUEUE_FREE; s5p_mfc_alloc_instance_buffer(ctx); s5p_mfc_alloc_dec_temp_buffers(ctx); - spin_lock_irqsave(&dev->condlock, flags); - set_bit(ctx->num, &dev->ctx_work_bits); - spin_unlock_irqrestore(&dev->condlock, flags); + set_work_bit_irqsave(ctx); s5p_mfc_clean_ctx_int_flags(ctx); s5p_mfc_try_run(dev); @@ -875,18 +868,14 @@ static int s5p_mfc_start_streaming(struct vb2_queue *q, unsigned int count) { struct s5p_mfc_ctx *ctx = fh_to_ctx(q->drv_priv); struct s5p_mfc_dev *dev = ctx->dev; - unsigned long flags; v4l2_ctrl_handler_setup(&ctx->ctrl_handler); if (ctx->state == MFCINST_FINISHING || ctx->state == MFCINST_FINISHED) ctx->state = MFCINST_RUNNING; /* If context is ready then dev = work->data;schedule it to run */ - if (s5p_mfc_ctx_ready(ctx)) { - spin_lock_irqsave(&dev->condlock, flags); - set_bit(ctx->num, &dev->ctx_work_bits); - spin_unlock_irqrestore(&dev->condlock, flags); - } + if (s5p_mfc_ctx_ready(ctx)) + set_work_bit_irqsave(ctx); s5p_mfc_try_run(dev); return 0; } @@ -936,14 +925,14 @@ static void s5p_mfc_buf_queue(struct vb2_buffer *vb) if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { mfc_buf = &ctx->src_bufs[vb->v4l2_buf.index]; - mfc_buf->used = 0; + mfc_buf->flags &= ~MFC_BUF_FLAG_USED; spin_lock_irqsave(&dev->irqlock, flags); list_add_tail(&mfc_buf->list, &ctx->src_queue); ctx->src_queue_cnt++; spin_unlock_irqrestore(&dev->irqlock, flags); } else if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { mfc_buf = &ctx->dst_bufs[vb->v4l2_buf.index]; - mfc_buf->used = 0; + mfc_buf->flags &= ~MFC_BUF_FLAG_USED; /* Mark destination as available for use by MFC */ spin_lock_irqsave(&dev->irqlock, flags); set_bit(vb->v4l2_buf.index, &ctx->dec_dst_flag); @@ -953,11 +942,8 @@ static void s5p_mfc_buf_queue(struct vb2_buffer *vb) } else { mfc_err("Unsupported buffer type (%d)\n", vq->type); } - if (s5p_mfc_ctx_ready(ctx)) { - spin_lock_irqsave(&dev->condlock, flags); - set_bit(ctx->num, &dev->ctx_work_bits); - spin_unlock_irqrestore(&dev->condlock, flags); - } + if (s5p_mfc_ctx_ready(ctx)) + set_work_bit_irqsave(ctx); s5p_mfc_try_run(dev); } diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_dec.h b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.h index fb8b215db0e7..fdf1d99a9d15 100644 --- a/drivers/media/video/s5p-mfc/s5p_mfc_dec.h +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.h @@ -1,5 +1,5 @@ /* - * linux/drivers/media/video/s5p-mfc/s5p_mfc_dec.h + * linux/drivers/media/platform/s5p-mfc/s5p_mfc_dec.h * * Copyright (C) 2011 Samsung Electronics Co., Ltd. * http://www.samsung.com/ diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_enc.c b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c index aa1c244cf66e..179e4db60b15 100644 --- a/drivers/media/video/s5p-mfc/s5p_mfc_enc.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c @@ -1,5 +1,5 @@ /* - * linux/drivers/media/video/s5p-mfc/s5p_mfc_enc.c + * linux/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c * * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd. * http://www.samsung.com/ @@ -21,6 +21,7 @@ #include <linux/sched.h> #include <linux/version.h> #include <linux/videodev2.h> +#include <media/v4l2-event.h> #include <linux/workqueue.h> #include <media/v4l2-ctrls.h> #include <media/videobuf2-core.h> @@ -576,9 +577,9 @@ static int s5p_mfc_ctx_ready(struct s5p_mfc_ctx *ctx) if (ctx->state == MFCINST_RUNNING && ctx->src_queue_cnt >= 1 && ctx->dst_queue_cnt >= 1) return 1; - /* context is ready to encode remain frames */ + /* context is ready to encode remaining frames */ if (ctx->state == MFCINST_FINISHING && - ctx->src_queue_cnt >= 1 && ctx->dst_queue_cnt >= 1) + ctx->dst_queue_cnt >= 1) return 1; mfc_debug(2, "ctx is not ready\n"); return 0; @@ -642,11 +643,8 @@ static int enc_post_seq_start(struct s5p_mfc_ctx *ctx) spin_unlock_irqrestore(&dev->irqlock, flags); } ctx->state = MFCINST_RUNNING; - if (s5p_mfc_ctx_ready(ctx)) { - spin_lock_irqsave(&dev->condlock, flags); - set_bit(ctx->num, &dev->ctx_work_bits); - spin_unlock_irqrestore(&dev->condlock, flags); - } + if (s5p_mfc_ctx_ready(ctx)) + set_work_bit_irqsave(ctx); s5p_mfc_try_run(dev); return 0; } @@ -724,7 +722,7 @@ static int enc_post_frame_start(struct s5p_mfc_ctx *ctx) if ((ctx->src_queue_cnt > 0) && (ctx->state == MFCINST_RUNNING)) { mb_entry = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list); - if (mb_entry->used) { + if (mb_entry->flags & MFC_BUF_FLAG_USED) { list_del(&mb_entry->list); ctx->src_queue_cnt--; list_add_tail(&mb_entry->list, &ctx->ref_queue); @@ -754,11 +752,8 @@ static int enc_post_frame_start(struct s5p_mfc_ctx *ctx) vb2_buffer_done(mb_entry->b, VB2_BUF_STATE_DONE); } spin_unlock_irqrestore(&dev->irqlock, flags); - if ((ctx->src_queue_cnt == 0) || (ctx->dst_queue_cnt == 0)) { - spin_lock(&dev->condlock); - clear_bit(ctx->num, &dev->ctx_work_bits); - spin_unlock(&dev->condlock); - } + if ((ctx->src_queue_cnt == 0) || (ctx->dst_queue_cnt == 0)) + clear_work_bit(ctx); return 0; } @@ -921,7 +916,6 @@ static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f) struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); struct s5p_mfc_fmt *fmt; struct v4l2_pix_format_mplane *pix_fmt_mp = &f->fmt.pix_mp; - unsigned long flags; int ret = 0; ret = vidioc_try_fmt(file, priv, f); @@ -946,9 +940,7 @@ static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f) ctx->dst_bufs_cnt = 0; ctx->capture_state = QUEUE_FREE; s5p_mfc_alloc_instance_buffer(ctx); - spin_lock_irqsave(&dev->condlock, flags); - set_bit(ctx->num, &dev->ctx_work_bits); - spin_unlock_irqrestore(&dev->condlock, flags); + set_work_bit_irqsave(ctx); s5p_mfc_clean_ctx_int_flags(ctx); s5p_mfc_try_run(dev); if (s5p_mfc_wait_for_done_ctx(ctx, \ @@ -1119,27 +1111,43 @@ static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf) mfc_err("Call on QBUF after unrecoverable error\n"); return -EIO; } - if (buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) + if (buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { + if (ctx->state == MFCINST_FINISHING) { + mfc_err("Call on QBUF after EOS command\n"); + return -EIO; + } return vb2_qbuf(&ctx->vq_src, buf); - else if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) + } else if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { return vb2_qbuf(&ctx->vq_dst, buf); + } return -EINVAL; } /* Dequeue a buffer */ static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf) { + const struct v4l2_event ev = { + .type = V4L2_EVENT_EOS + }; struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); + int ret; if (ctx->state == MFCINST_ERROR) { mfc_err("Call on DQBUF after unrecoverable error\n"); return -EIO; } - if (buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) - return vb2_dqbuf(&ctx->vq_src, buf, file->f_flags & O_NONBLOCK); - else if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) - return vb2_dqbuf(&ctx->vq_dst, buf, file->f_flags & O_NONBLOCK); - return -EINVAL; + if (buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { + ret = vb2_dqbuf(&ctx->vq_src, buf, file->f_flags & O_NONBLOCK); + } else if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { + ret = vb2_dqbuf(&ctx->vq_dst, buf, file->f_flags & O_NONBLOCK); + if (ret == 0 && ctx->state == MFCINST_FINISHED + && list_empty(&ctx->vq_dst.done_list)) + v4l2_event_queue_fh(&ctx->fh, &ev); + } else { + ret = -EINVAL; + } + + return ret; } /* Stream on */ @@ -1471,6 +1479,57 @@ static int vidioc_g_parm(struct file *file, void *priv, return 0; } +int vidioc_encoder_cmd(struct file *file, void *priv, + struct v4l2_encoder_cmd *cmd) +{ + struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); + struct s5p_mfc_dev *dev = ctx->dev; + struct s5p_mfc_buf *buf; + unsigned long flags; + + switch (cmd->cmd) { + case V4L2_ENC_CMD_STOP: + if (cmd->flags != 0) + return -EINVAL; + + if (!ctx->vq_src.streaming) + return -EINVAL; + + spin_lock_irqsave(&dev->irqlock, flags); + if (list_empty(&ctx->src_queue)) { + mfc_debug(2, "EOS: empty src queue, entering finishing state"); + ctx->state = MFCINST_FINISHING; + spin_unlock_irqrestore(&dev->irqlock, flags); + s5p_mfc_try_run(dev); + } else { + mfc_debug(2, "EOS: marking last buffer of stream"); + buf = list_entry(ctx->src_queue.prev, + struct s5p_mfc_buf, list); + if (buf->flags & MFC_BUF_FLAG_USED) + ctx->state = MFCINST_FINISHING; + else + buf->flags |= MFC_BUF_FLAG_EOS; + spin_unlock_irqrestore(&dev->irqlock, flags); + } + break; + default: + return -EINVAL; + + } + return 0; +} + +static int vidioc_subscribe_event(struct v4l2_fh *fh, + struct v4l2_event_subscription *sub) +{ + switch (sub->type) { + case V4L2_EVENT_EOS: + return v4l2_event_subscribe(fh, sub, 2, NULL); + default: + return -EINVAL; + } +} + static const struct v4l2_ioctl_ops s5p_mfc_enc_ioctl_ops = { .vidioc_querycap = vidioc_querycap, .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, @@ -1491,6 +1550,9 @@ static const struct v4l2_ioctl_ops s5p_mfc_enc_ioctl_ops = { .vidioc_streamoff = vidioc_streamoff, .vidioc_s_parm = vidioc_s_parm, .vidioc_g_parm = vidioc_g_parm, + .vidioc_encoder_cmd = vidioc_encoder_cmd, + .vidioc_subscribe_event = vidioc_subscribe_event, + .vidioc_unsubscribe_event = v4l2_event_unsubscribe, }; static int check_vb_with_fmt(struct s5p_mfc_fmt *fmt, struct vb2_buffer *vb) @@ -1648,15 +1710,11 @@ static int s5p_mfc_start_streaming(struct vb2_queue *q, unsigned int count) { struct s5p_mfc_ctx *ctx = fh_to_ctx(q->drv_priv); struct s5p_mfc_dev *dev = ctx->dev; - unsigned long flags; v4l2_ctrl_handler_setup(&ctx->ctrl_handler); /* If context is ready then dev = work->data;schedule it to run */ - if (s5p_mfc_ctx_ready(ctx)) { - spin_lock_irqsave(&dev->condlock, flags); - set_bit(ctx->num, &dev->ctx_work_bits); - spin_unlock_irqrestore(&dev->condlock, flags); - } + if (s5p_mfc_ctx_ready(ctx)) + set_work_bit_irqsave(ctx); s5p_mfc_try_run(dev); return 0; } @@ -1706,7 +1764,7 @@ static void s5p_mfc_buf_queue(struct vb2_buffer *vb) } if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { mfc_buf = &ctx->dst_bufs[vb->v4l2_buf.index]; - mfc_buf->used = 0; + mfc_buf->flags &= ~MFC_BUF_FLAG_USED; /* Mark destination as available for use by MFC */ spin_lock_irqsave(&dev->irqlock, flags); list_add_tail(&mfc_buf->list, &ctx->dst_queue); @@ -1714,26 +1772,16 @@ static void s5p_mfc_buf_queue(struct vb2_buffer *vb) spin_unlock_irqrestore(&dev->irqlock, flags); } else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { mfc_buf = &ctx->src_bufs[vb->v4l2_buf.index]; - mfc_buf->used = 0; + mfc_buf->flags &= ~MFC_BUF_FLAG_USED; spin_lock_irqsave(&dev->irqlock, flags); - if (vb->v4l2_planes[0].bytesused == 0) { - mfc_debug(1, "change state to FINISHING\n"); - ctx->state = MFCINST_FINISHING; - vb2_buffer_done(vb, VB2_BUF_STATE_DONE); - cleanup_ref_queue(ctx); - } else { - list_add_tail(&mfc_buf->list, &ctx->src_queue); - ctx->src_queue_cnt++; - } + list_add_tail(&mfc_buf->list, &ctx->src_queue); + ctx->src_queue_cnt++; spin_unlock_irqrestore(&dev->irqlock, flags); } else { mfc_err("unsupported buffer type (%d)\n", vq->type); } - if (s5p_mfc_ctx_ready(ctx)) { - spin_lock_irqsave(&dev->condlock, flags); - set_bit(ctx->num, &dev->ctx_work_bits); - spin_unlock_irqrestore(&dev->condlock, flags); - } + if (s5p_mfc_ctx_ready(ctx)) + set_work_bit_irqsave(ctx); s5p_mfc_try_run(dev); } diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_enc.h b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.h index 405bdd3ee083..ca9fd66bd310 100644 --- a/drivers/media/video/s5p-mfc/s5p_mfc_enc.h +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.h @@ -1,5 +1,5 @@ /* - * linux/drivers/media/video/s5p-mfc/s5p_mfc_enc.h + * linux/drivers/media/platform/s5p-mfc/s5p_mfc_enc.h * * Copyright (C) 2011 Samsung Electronics Co., Ltd. * http://www.samsung.com/ diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_intr.c b/drivers/media/platform/s5p-mfc/s5p_mfc_intr.c index 8f2f8bf4da7f..37860e299021 100644 --- a/drivers/media/video/s5p-mfc/s5p_mfc_intr.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_intr.c @@ -1,5 +1,5 @@ /* - * drivers/media/video/samsung/mfc5/s5p_mfc_intr.c + * drivers/media/platform/samsung/mfc5/s5p_mfc_intr.c * * C file for Samsung MFC (Multi Function Codec - FIMV) driver * This file contains functions used to wait for command completion. diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_intr.h b/drivers/media/platform/s5p-mfc/s5p_mfc_intr.h index 122d7732f745..18341a88514e 100644 --- a/drivers/media/video/s5p-mfc/s5p_mfc_intr.h +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_intr.h @@ -1,5 +1,5 @@ /* - * drivers/media/video/samsung/mfc5/s5p_mfc_intr.h + * drivers/media/platform/samsung/mfc5/s5p_mfc_intr.h * * Header file for Samsung MFC (Multi Function Codec - FIMV) driver * It contains waiting functions declarations. diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_opr.c b/drivers/media/platform/s5p-mfc/s5p_mfc_opr.c index e6217cbfa4a3..767a51271dc2 100644 --- a/drivers/media/video/s5p-mfc/s5p_mfc_opr.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr.c @@ -1,5 +1,5 @@ /* - * drivers/media/video/samsung/mfc5/s5p_mfc_opr.c + * drivers/media/platform/samsung/mfc5/s5p_mfc_opr.c * * Samsung MFC (Multi Function Codec - FIMV) driver * This file contains hw related functions. @@ -1075,14 +1075,21 @@ int s5p_mfc_init_encode(struct s5p_mfc_ctx *ctx) int s5p_mfc_encode_one_frame(struct s5p_mfc_ctx *ctx) { struct s5p_mfc_dev *dev = ctx->dev; + int cmd; /* memory structure cur. frame */ if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12M) mfc_write(dev, 0, S5P_FIMV_ENC_MAP_FOR_CUR); else if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12MT) mfc_write(dev, 3, S5P_FIMV_ENC_MAP_FOR_CUR); s5p_mfc_set_shared_buffer(ctx); - mfc_write(dev, (S5P_FIMV_CH_FRAME_START << 16 & 0x70000) | - (ctx->inst_no), S5P_FIMV_SI_CH0_INST_ID); + + if (ctx->state == MFCINST_FINISHING) + cmd = S5P_FIMV_CH_LAST_FRAME; + else + cmd = S5P_FIMV_CH_FRAME_START; + mfc_write(dev, ((cmd & S5P_FIMV_CH_MASK) << S5P_FIMV_CH_SHIFT) + | (ctx->inst_no), S5P_FIMV_SI_CH0_INST_ID); + return 0; } @@ -1133,7 +1140,7 @@ static int s5p_mfc_run_dec_frame(struct s5p_mfc_ctx *ctx, int last_frame) } /* Get the next source buffer */ temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list); - temp_vb->used = 1; + temp_vb->flags |= MFC_BUF_FLAG_USED; s5p_mfc_set_dec_stream_buffer(ctx, vb2_dma_contig_plane_dma_addr(temp_vb->b, 0), ctx->consumed_stream, temp_vb->b->v4l2_planes[0].bytesused); @@ -1160,7 +1167,7 @@ static int s5p_mfc_run_enc_frame(struct s5p_mfc_ctx *ctx) unsigned int dst_size; spin_lock_irqsave(&dev->irqlock, flags); - if (list_empty(&ctx->src_queue)) { + if (list_empty(&ctx->src_queue) && ctx->state != MFCINST_FINISHING) { mfc_debug(2, "no src buffers\n"); spin_unlock_irqrestore(&dev->irqlock, flags); return -EAGAIN; @@ -1170,19 +1177,40 @@ static int s5p_mfc_run_enc_frame(struct s5p_mfc_ctx *ctx) spin_unlock_irqrestore(&dev->irqlock, flags); return -EAGAIN; } - src_mb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list); - src_mb->used = 1; - src_y_addr = vb2_dma_contig_plane_dma_addr(src_mb->b, 0); - src_c_addr = vb2_dma_contig_plane_dma_addr(src_mb->b, 1); - s5p_mfc_set_enc_frame_buffer(ctx, src_y_addr, src_c_addr); + if (list_empty(&ctx->src_queue)) { + /* send null frame */ + s5p_mfc_set_enc_frame_buffer(ctx, dev->bank2, dev->bank2); + src_mb = NULL; + } else { + src_mb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, + list); + src_mb->flags |= MFC_BUF_FLAG_USED; + if (src_mb->b->v4l2_planes[0].bytesused == 0) { + /* send null frame */ + s5p_mfc_set_enc_frame_buffer(ctx, dev->bank2, + dev->bank2); + ctx->state = MFCINST_FINISHING; + } else { + src_y_addr = vb2_dma_contig_plane_dma_addr(src_mb->b, + 0); + src_c_addr = vb2_dma_contig_plane_dma_addr(src_mb->b, + 1); + s5p_mfc_set_enc_frame_buffer(ctx, src_y_addr, + src_c_addr); + if (src_mb->flags & MFC_BUF_FLAG_EOS) + ctx->state = MFCINST_FINISHING; + } + } dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list); - dst_mb->used = 1; + dst_mb->flags |= MFC_BUF_FLAG_USED; dst_addr = vb2_dma_contig_plane_dma_addr(dst_mb->b, 0); dst_size = vb2_plane_size(dst_mb->b, 0); s5p_mfc_set_enc_stream_buffer(ctx, dst_addr, dst_size); spin_unlock_irqrestore(&dev->irqlock, flags); dev->curr_ctx = ctx->num; s5p_mfc_clean_ctx_int_flags(ctx); + mfc_debug(2, "encoding buffer with index=%d state=%d", + src_mb ? src_mb->b->v4l2_buf.index : -1, ctx->state); s5p_mfc_encode_one_frame(ctx); return 0; } diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_opr.h b/drivers/media/platform/s5p-mfc/s5p_mfc_opr.h index 5932d1c782c5..2ad3def052f8 100644 --- a/drivers/media/video/s5p-mfc/s5p_mfc_opr.h +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr.h @@ -1,5 +1,5 @@ /* - * drivers/media/video/samsung/mfc5/s5p_mfc_opr.h + * drivers/media/platform/samsung/mfc5/s5p_mfc_opr.h * * Header file for Samsung MFC (Multi Function Codec - FIMV) driver * Contains declarations of hw related functions. diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_pm.c b/drivers/media/platform/s5p-mfc/s5p_mfc_pm.c index 738a607be43c..0503d14ac94e 100644 --- a/drivers/media/video/s5p-mfc/s5p_mfc_pm.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_pm.c @@ -1,5 +1,5 @@ /* - * linux/drivers/media/video/s5p-mfc/s5p_mfc_pm.c + * linux/drivers/media/platform/s5p-mfc/s5p_mfc_pm.c * * Copyright (c) 2010 Samsung Electronics Co., Ltd. * http://www.samsung.com/ diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_pm.h b/drivers/media/platform/s5p-mfc/s5p_mfc_pm.h index 5107914f27e4..875c5346bc85 100644 --- a/drivers/media/video/s5p-mfc/s5p_mfc_pm.h +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_pm.h @@ -1,5 +1,5 @@ /* - * linux/drivers/media/video/s5p-mfc/s5p_mfc_pm.h + * linux/drivers/media/platform/s5p-mfc/s5p_mfc_pm.h * * Copyright (C) 2011 Samsung Electronics Co., Ltd. * http://www.samsung.com/ diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_shm.c b/drivers/media/platform/s5p-mfc/s5p_mfc_shm.c index 91fdbac8c37a..b5933d233a4b 100644 --- a/drivers/media/video/s5p-mfc/s5p_mfc_shm.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_shm.c @@ -1,5 +1,5 @@ /* - * linux/drivers/media/video/s5p-mfc/s5p_mfc_shm.c + * linux/drivers/media/platform/s5p-mfc/s5p_mfc_shm.c * * Copyright (c) 2010 Samsung Electronics Co., Ltd. * http://www.samsung.com/ diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_shm.h b/drivers/media/platform/s5p-mfc/s5p_mfc_shm.h index cf962a466276..416ebd7ba35a 100644 --- a/drivers/media/video/s5p-mfc/s5p_mfc_shm.h +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_shm.h @@ -1,5 +1,5 @@ /* - * linux/drivers/media/video/s5p-mfc/s5p_mfc_shm.h + * linux/drivers/media/platform/s5p-mfc/s5p_mfc_shm.h * * Copyright (c) 2011 Samsung Electronics Co., Ltd. * http://www.samsung.com/ diff --git a/drivers/media/video/s5p-tv/Kconfig b/drivers/media/platform/s5p-tv/Kconfig index f248b2856720..ea11a513033f 100644 --- a/drivers/media/video/s5p-tv/Kconfig +++ b/drivers/media/platform/s5p-tv/Kconfig @@ -1,4 +1,4 @@ -# drivers/media/video/s5p-tv/Kconfig +# drivers/media/platform/s5p-tv/Kconfig # # Copyright (c) 2010-2011 Samsung Electronics Co., Ltd. # http://www.samsung.com/ diff --git a/drivers/media/video/s5p-tv/Makefile b/drivers/media/platform/s5p-tv/Makefile index f49e756a2fde..7cd47902e269 100644 --- a/drivers/media/video/s5p-tv/Makefile +++ b/drivers/media/platform/s5p-tv/Makefile @@ -1,4 +1,4 @@ -# drivers/media/video/samsung/tvout/Makefile +# drivers/media/platform/samsung/tvout/Makefile # # Copyright (c) 2010-2011 Samsung Electronics Co., Ltd. # http://www.samsung.com/ diff --git a/drivers/media/video/s5p-tv/hdmi_drv.c b/drivers/media/platform/s5p-tv/hdmi_drv.c index 20cb6eef2979..8a9cf43018f6 100644 --- a/drivers/media/video/s5p-tv/hdmi_drv.c +++ b/drivers/media/platform/s5p-tv/hdmi_drv.c @@ -11,6 +11,8 @@ * or (at your option) any later version */ +#define pr_fmt(fmt) "s5p-tv (hdmi_drv): " fmt + #ifdef CONFIG_VIDEO_SAMSUNG_S5P_HDMI_DEBUG #define DEBUG #endif @@ -161,12 +163,12 @@ static irqreturn_t hdmi_irq_handler(int irq, void *dev_data) intc_flag = hdmi_read(hdev, HDMI_INTC_FLAG); /* clearing flags for HPD plug/unplug */ if (intc_flag & HDMI_INTC_FLAG_HPD_UNPLUG) { - printk(KERN_INFO "unplugged\n"); + pr_info("unplugged\n"); hdmi_write_mask(hdev, HDMI_INTC_FLAG, ~0, HDMI_INTC_FLAG_HPD_UNPLUG); } if (intc_flag & HDMI_INTC_FLAG_HPD_PLUG) { - printk(KERN_INFO "plugged\n"); + pr_info("plugged\n"); hdmi_write_mask(hdev, HDMI_INTC_FLAG, ~0, HDMI_INTC_FLAG_HPD_PLUG); } diff --git a/drivers/media/video/s5p-tv/hdmiphy_drv.c b/drivers/media/platform/s5p-tv/hdmiphy_drv.c index f67b38631801..f67b38631801 100644 --- a/drivers/media/video/s5p-tv/hdmiphy_drv.c +++ b/drivers/media/platform/s5p-tv/hdmiphy_drv.c diff --git a/drivers/media/video/s5p-tv/mixer.h b/drivers/media/platform/s5p-tv/mixer.h index ddb422e23550..ddb422e23550 100644 --- a/drivers/media/video/s5p-tv/mixer.h +++ b/drivers/media/platform/s5p-tv/mixer.h diff --git a/drivers/media/video/s5p-tv/mixer_drv.c b/drivers/media/platform/s5p-tv/mixer_drv.c index edca06592883..ca0f29717448 100644 --- a/drivers/media/video/s5p-tv/mixer_drv.c +++ b/drivers/media/platform/s5p-tv/mixer_drv.c @@ -384,7 +384,7 @@ static int __devinit mxr_probe(struct platform_device *pdev) mdev = kzalloc(sizeof *mdev, GFP_KERNEL); if (!mdev) { - mxr_err(mdev, "not enough memory.\n"); + dev_err(dev, "not enough memory.\n"); ret = -ENOMEM; goto fail; } @@ -461,10 +461,10 @@ static struct platform_driver mxr_driver __refdata = { static int __init mxr_init(void) { int i, ret; - static const char banner[] __initconst = KERN_INFO + static const char banner[] __initconst = "Samsung TV Mixer driver, " "(c) 2010-2011 Samsung Electronics Co., Ltd.\n"; - printk(banner); + pr_info("%s\n", banner); /* Loading auxiliary modules */ for (i = 0; i < ARRAY_SIZE(mxr_output_conf); ++i) @@ -472,7 +472,7 @@ static int __init mxr_init(void) ret = platform_driver_register(&mxr_driver); if (ret != 0) { - printk(KERN_ERR "registration of MIXER driver failed\n"); + pr_err("s5p-tv: registration of MIXER driver failed\n"); return -ENXIO; } diff --git a/drivers/media/video/s5p-tv/mixer_grp_layer.c b/drivers/media/platform/s5p-tv/mixer_grp_layer.c index b93a21f5aa13..b93a21f5aa13 100644 --- a/drivers/media/video/s5p-tv/mixer_grp_layer.c +++ b/drivers/media/platform/s5p-tv/mixer_grp_layer.c diff --git a/drivers/media/video/s5p-tv/mixer_reg.c b/drivers/media/platform/s5p-tv/mixer_reg.c index 3b1670a045f4..3b1670a045f4 100644 --- a/drivers/media/video/s5p-tv/mixer_reg.c +++ b/drivers/media/platform/s5p-tv/mixer_reg.c diff --git a/drivers/media/video/s5p-tv/mixer_video.c b/drivers/media/platform/s5p-tv/mixer_video.c index 6c74b05d1f95..0c1cd895ff66 100644 --- a/drivers/media/video/s5p-tv/mixer_video.c +++ b/drivers/media/platform/s5p-tv/mixer_video.c @@ -11,6 +11,8 @@ * or (at your option) any later version */ +#define pr_fmt(fmt) "s5p-tv (mixer): " fmt + #include "mixer.h" #include <media/v4l2-ioctl.h> @@ -162,9 +164,8 @@ static int mxr_querycap(struct file *file, void *priv, strlcpy(cap->driver, MXR_DRIVER_NAME, sizeof cap->driver); strlcpy(cap->card, layer->vfd.name, sizeof cap->card); sprintf(cap->bus_info, "%d", layer->idx); - cap->version = KERNEL_VERSION(0, 1, 0); - cap->capabilities = V4L2_CAP_STREAMING | - V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_VIDEO_OUTPUT_MPLANE; + cap->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_OUTPUT_MPLANE; + cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; return 0; } @@ -716,7 +717,7 @@ static int mxr_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) static const struct v4l2_ioctl_ops mxr_ioctl_ops = { .vidioc_querycap = mxr_querycap, /* format handling */ - .vidioc_enum_fmt_vid_out = mxr_enum_fmt, + .vidioc_enum_fmt_vid_out_mplane = mxr_enum_fmt, .vidioc_s_fmt_vid_out_mplane = mxr_s_fmt, .vidioc_g_fmt_vid_out_mplane = mxr_g_fmt, /* buffer control */ @@ -750,18 +751,20 @@ static int mxr_video_open(struct file *file) int ret = 0; mxr_dbg(mdev, "%s:%d\n", __func__, __LINE__); + if (mutex_lock_interruptible(&layer->mutex)) + return -ERESTARTSYS; /* assure device probe is finished */ wait_for_device_probe(); /* creating context for file descriptor */ ret = v4l2_fh_open(file); if (ret) { mxr_err(mdev, "v4l2_fh_open failed\n"); - return ret; + goto unlock; } /* leaving if layer is already initialized */ if (!v4l2_fh_is_singular_file(file)) - return 0; + goto unlock; /* FIXME: should power be enabled on open? */ ret = mxr_power_get(mdev); @@ -779,6 +782,7 @@ static int mxr_video_open(struct file *file) layer->fmt = layer->fmt_array[0]; /* setup default geometry */ mxr_layer_default_geo(layer); + mutex_unlock(&layer->mutex); return 0; @@ -788,6 +792,9 @@ fail_power: fail_fh_open: v4l2_fh_release(file); +unlock: + mutex_unlock(&layer->mutex); + return ret; } @@ -795,19 +802,28 @@ static unsigned int mxr_video_poll(struct file *file, struct poll_table_struct *wait) { struct mxr_layer *layer = video_drvdata(file); + unsigned int res; mxr_dbg(layer->mdev, "%s:%d\n", __func__, __LINE__); - return vb2_poll(&layer->vb_queue, file, wait); + mutex_lock(&layer->mutex); + res = vb2_poll(&layer->vb_queue, file, wait); + mutex_unlock(&layer->mutex); + return res; } static int mxr_video_mmap(struct file *file, struct vm_area_struct *vma) { struct mxr_layer *layer = video_drvdata(file); + int ret; mxr_dbg(layer->mdev, "%s:%d\n", __func__, __LINE__); - return vb2_mmap(&layer->vb_queue, vma); + if (mutex_lock_interruptible(&layer->mutex)) + return -ERESTARTSYS; + ret = vb2_mmap(&layer->vb_queue, vma); + mutex_unlock(&layer->mutex); + return ret; } static int mxr_video_release(struct file *file) @@ -815,11 +831,13 @@ static int mxr_video_release(struct file *file) struct mxr_layer *layer = video_drvdata(file); mxr_dbg(layer->mdev, "%s:%d\n", __func__, __LINE__); + mutex_lock(&layer->mutex); if (v4l2_fh_is_singular_file(file)) { vb2_queue_release(&layer->vb_queue); mxr_power_put(layer->mdev); } v4l2_fh_release(file); + mutex_unlock(&layer->mutex); return 0; } @@ -1036,7 +1054,7 @@ void mxr_base_layer_release(struct mxr_layer *layer) static void mxr_vfd_release(struct video_device *vdev) { - printk(KERN_INFO "video device release\n"); + pr_info("video device release\n"); } struct mxr_layer *mxr_base_layer_create(struct mxr_device *mdev, @@ -1062,6 +1080,7 @@ struct mxr_layer *mxr_base_layer_create(struct mxr_device *mdev, .minor = -1, .release = mxr_vfd_release, .fops = &mxr_fops, + .vfl_dir = VFL_DIR_TX, .ioctl_ops = &mxr_ioctl_ops, }; strlcpy(layer->vfd.name, name, sizeof(layer->vfd.name)); @@ -1069,10 +1088,6 @@ struct mxr_layer *mxr_base_layer_create(struct mxr_device *mdev, set_bit(V4L2_FL_USE_FH_PRIO, &layer->vfd.flags); video_set_drvdata(&layer->vfd, layer); - /* Locking in file operations other than ioctl should be done - by the driver, not the V4L2 core. - This driver needs auditing so that this flag can be removed. */ - set_bit(V4L2_FL_LOCK_ALL_FOPS, &layer->vfd.flags); layer->vfd.lock = &layer->mutex; layer->vfd.v4l2_dev = &mdev->v4l2_dev; diff --git a/drivers/media/video/s5p-tv/mixer_vp_layer.c b/drivers/media/platform/s5p-tv/mixer_vp_layer.c index 3d13a636877b..3d13a636877b 100644 --- a/drivers/media/video/s5p-tv/mixer_vp_layer.c +++ b/drivers/media/platform/s5p-tv/mixer_vp_layer.c diff --git a/drivers/media/video/s5p-tv/regs-hdmi.h b/drivers/media/platform/s5p-tv/regs-hdmi.h index a889d1f57f28..a889d1f57f28 100644 --- a/drivers/media/video/s5p-tv/regs-hdmi.h +++ b/drivers/media/platform/s5p-tv/regs-hdmi.h diff --git a/drivers/media/video/s5p-tv/regs-mixer.h b/drivers/media/platform/s5p-tv/regs-mixer.h index 158abb43d0a4..158abb43d0a4 100644 --- a/drivers/media/video/s5p-tv/regs-mixer.h +++ b/drivers/media/platform/s5p-tv/regs-mixer.h diff --git a/drivers/media/video/s5p-tv/regs-sdo.h b/drivers/media/platform/s5p-tv/regs-sdo.h index 7f7c2b8ac140..6f22fbfe2f6c 100644 --- a/drivers/media/video/s5p-tv/regs-sdo.h +++ b/drivers/media/platform/s5p-tv/regs-sdo.h @@ -1,4 +1,4 @@ -/* drivers/media/video/s5p-tv/regs-sdo.h +/* drivers/media/platform/s5p-tv/regs-sdo.h * * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd. * http://www.samsung.com/ diff --git a/drivers/media/video/s5p-tv/regs-vp.h b/drivers/media/platform/s5p-tv/regs-vp.h index 6c63984e11e8..6c63984e11e8 100644 --- a/drivers/media/video/s5p-tv/regs-vp.h +++ b/drivers/media/platform/s5p-tv/regs-vp.h diff --git a/drivers/media/video/s5p-tv/sdo_drv.c b/drivers/media/platform/s5p-tv/sdo_drv.c index f6bca2c20e89..ad68bbed014e 100644 --- a/drivers/media/video/s5p-tv/sdo_drv.c +++ b/drivers/media/platform/s5p-tv/sdo_drv.c @@ -374,15 +374,15 @@ static int __devinit sdo_probe(struct platform_device *pdev) dev_info(dev, "fout_vpll.rate = %lu\n", clk_get_rate(sclk_vpll)); /* acquire regulator */ - sdev->vdac = regulator_get(dev, "vdd33a_dac"); + sdev->vdac = devm_regulator_get(dev, "vdd33a_dac"); if (IS_ERR_OR_NULL(sdev->vdac)) { dev_err(dev, "failed to get regulator 'vdac'\n"); goto fail_fout_vpll; } - sdev->vdet = regulator_get(dev, "vdet"); + sdev->vdet = devm_regulator_get(dev, "vdet"); if (IS_ERR_OR_NULL(sdev->vdet)) { dev_err(dev, "failed to get regulator 'vdet'\n"); - goto fail_vdac; + goto fail_fout_vpll; } /* enable gate for dac clock, because mixer uses it */ @@ -406,8 +406,6 @@ static int __devinit sdo_probe(struct platform_device *pdev) dev_info(dev, "probe succeeded\n"); return 0; -fail_vdac: - regulator_put(sdev->vdac); fail_fout_vpll: clk_put(sdev->fout_vpll); fail_dacphy: @@ -428,8 +426,6 @@ static int __devexit sdo_remove(struct platform_device *pdev) pm_runtime_disable(&pdev->dev); clk_disable(sdev->dac); - regulator_put(sdev->vdet); - regulator_put(sdev->vdac); clk_put(sdev->fout_vpll); clk_put(sdev->dacphy); clk_put(sdev->dac); diff --git a/drivers/media/video/s5p-tv/sii9234_drv.c b/drivers/media/platform/s5p-tv/sii9234_drv.c index 6d348f90237a..716d4846f8bd 100644 --- a/drivers/media/video/s5p-tv/sii9234_drv.c +++ b/drivers/media/platform/s5p-tv/sii9234_drv.c @@ -323,7 +323,7 @@ static int __devinit sii9234_probe(struct i2c_client *client, struct sii9234_context *ctx; int ret; - ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); + ctx = devm_kzalloc(&client->dev, sizeof(*ctx), GFP_KERNEL); if (!ctx) { dev_err(dev, "out of memory\n"); ret = -ENOMEM; @@ -331,18 +331,17 @@ static int __devinit sii9234_probe(struct i2c_client *client, } ctx->client = client; - ctx->power = regulator_get(dev, "hdmi-en"); + ctx->power = devm_regulator_get(dev, "hdmi-en"); if (IS_ERR(ctx->power)) { dev_err(dev, "failed to acquire regulator hdmi-en\n"); - ret = PTR_ERR(ctx->power); - goto fail_ctx; + return PTR_ERR(ctx->power); } ctx->gpio_n_reset = pdata->gpio_n_reset; ret = gpio_request(ctx->gpio_n_reset, "MHL_RST"); if (ret) { dev_err(dev, "failed to acquire MHL_RST gpio\n"); - goto fail_power; + return ret; } v4l2_i2c_subdev_init(&ctx->sd, client, &sii9234_ops); @@ -373,12 +372,6 @@ fail_pm: pm_runtime_disable(dev); gpio_free(ctx->gpio_n_reset); -fail_power: - regulator_put(ctx->power); - -fail_ctx: - kfree(ctx); - fail: dev_err(dev, "probe failed\n"); @@ -393,8 +386,6 @@ static int __devexit sii9234_remove(struct i2c_client *client) pm_runtime_disable(dev); gpio_free(ctx->gpio_n_reset); - regulator_put(ctx->power); - kfree(ctx); dev_info(dev, "remove successful\n"); diff --git a/drivers/media/video/sh_vou.c b/drivers/media/platform/sh_vou.c index 8fd1874382c6..85fd312f0a82 100644 --- a/drivers/media/video/sh_vou.c +++ b/drivers/media/platform/sh_vou.c @@ -933,7 +933,7 @@ static int sh_vou_g_crop(struct file *file, void *fh, struct v4l2_crop *a) } /* Assume a dull encoder, do all the work ourselves. */ -static int sh_vou_s_crop(struct file *file, void *fh, struct v4l2_crop *a) +static int sh_vou_s_crop(struct file *file, void *fh, const struct v4l2_crop *a) { struct video_device *vdev = video_devdata(file); struct sh_vou_device *vou_dev = video_get_drvdata(vdev); @@ -1171,6 +1171,8 @@ static int sh_vou_open(struct file *file) file->private_data = vou_file; + if (mutex_lock_interruptible(&vou_dev->fop_lock)) + return -ERESTARTSYS; if (atomic_inc_return(&vou_dev->use_count) == 1) { int ret; /* First open */ @@ -1181,6 +1183,7 @@ static int sh_vou_open(struct file *file) atomic_dec(&vou_dev->use_count); pm_runtime_put(vdev->v4l2_dev->dev); vou_dev->status = SH_VOU_IDLE; + mutex_unlock(&vou_dev->fop_lock); return ret; } } @@ -1191,6 +1194,7 @@ static int sh_vou_open(struct file *file) V4L2_FIELD_NONE, sizeof(struct videobuf_buffer), vdev, &vou_dev->fop_lock); + mutex_unlock(&vou_dev->fop_lock); return 0; } @@ -1204,10 +1208,12 @@ static int sh_vou_release(struct file *file) dev_dbg(vou_file->vbq.dev, "%s()\n", __func__); if (!atomic_dec_return(&vou_dev->use_count)) { + mutex_lock(&vou_dev->fop_lock); /* Last close */ vou_dev->status = SH_VOU_IDLE; sh_vou_reg_a_set(vou_dev, VOUER, 0, 0x101); pm_runtime_put(vdev->v4l2_dev->dev); + mutex_unlock(&vou_dev->fop_lock); } file->private_data = NULL; @@ -1218,20 +1224,33 @@ static int sh_vou_release(struct file *file) static int sh_vou_mmap(struct file *file, struct vm_area_struct *vma) { + struct video_device *vdev = video_devdata(file); + struct sh_vou_device *vou_dev = video_get_drvdata(vdev); struct sh_vou_file *vou_file = file->private_data; + int ret; dev_dbg(vou_file->vbq.dev, "%s()\n", __func__); - return videobuf_mmap_mapper(&vou_file->vbq, vma); + if (mutex_lock_interruptible(&vou_dev->fop_lock)) + return -ERESTARTSYS; + ret = videobuf_mmap_mapper(&vou_file->vbq, vma); + mutex_unlock(&vou_dev->fop_lock); + return ret; } static unsigned int sh_vou_poll(struct file *file, poll_table *wait) { + struct video_device *vdev = video_devdata(file); + struct sh_vou_device *vou_dev = video_get_drvdata(vdev); struct sh_vou_file *vou_file = file->private_data; + unsigned int res; dev_dbg(vou_file->vbq.dev, "%s()\n", __func__); - return videobuf_poll_stream(file, &vou_file->vbq, wait); + mutex_lock(&vou_dev->fop_lock); + res = videobuf_poll_stream(file, &vou_file->vbq, wait); + mutex_unlock(&vou_dev->fop_lock); + return res; } static int sh_vou_g_chip_ident(struct file *file, void *fh, @@ -1303,6 +1322,7 @@ static const struct video_device sh_vou_video_template = { .ioctl_ops = &sh_vou_ioctl_ops, .tvnorms = V4L2_STD_525_60, /* PAL only supported in 8-bit non-bt656 mode */ .current_norm = V4L2_STD_NTSC_M, + .vfl_dir = VFL_DIR_TX, }; static int __devinit sh_vou_probe(struct platform_device *pdev) @@ -1390,10 +1410,6 @@ static int __devinit sh_vou_probe(struct platform_device *pdev) vdev->v4l2_dev = &vou_dev->v4l2_dev; vdev->release = video_device_release; vdev->lock = &vou_dev->fop_lock; - /* Locking in file operations other than ioctl should be done - by the driver, not the V4L2 core. - This driver needs auditing so that this flag can be removed. */ - set_bit(V4L2_FL_LOCK_ALL_FOPS, &vdev->flags); vou_dev->vdev = vdev; video_set_drvdata(vdev, vou_dev); diff --git a/drivers/media/platform/soc_camera/Kconfig b/drivers/media/platform/soc_camera/Kconfig new file mode 100644 index 000000000000..9afe1e7bde74 --- /dev/null +++ b/drivers/media/platform/soc_camera/Kconfig @@ -0,0 +1,87 @@ +config SOC_CAMERA + tristate "SoC camera support" + depends on VIDEO_V4L2 && HAS_DMA && I2C + select VIDEOBUF_GEN + select VIDEOBUF2_CORE + 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_PLATFORM + tristate "platform camera support" + depends on SOC_CAMERA + help + This is a generic SoC camera platform driver, useful for testing + +config MX1_VIDEO + bool + +config VIDEO_MX1 + tristate "i.MX1/i.MXL CMOS Sensor Interface driver" + depends on VIDEO_DEV && ARCH_MX1 && SOC_CAMERA + select FIQ + select VIDEOBUF_DMA_CONTIG + select MX1_VIDEO + ---help--- + This is a v4l2 driver for the i.MX1/i.MXL CMOS Sensor Interface + +config MX3_VIDEO + bool + +config VIDEO_MX3 + tristate "i.MX3x Camera Sensor Interface driver" + depends on VIDEO_DEV && MX3_IPU && SOC_CAMERA + select VIDEOBUF2_DMA_CONTIG + select MX3_VIDEO + ---help--- + This is a v4l2 driver for the i.MX3x Camera Sensor Interface + +config VIDEO_PXA27x + tristate "PXA27x Quick Capture Interface driver" + depends on VIDEO_DEV && PXA27x && SOC_CAMERA + select VIDEOBUF_DMA_SG + ---help--- + This is a v4l2 driver for the PXA27x Quick Capture Interface + +config VIDEO_SH_MOBILE_CSI2 + tristate "SuperH Mobile MIPI CSI-2 Interface driver" + depends on VIDEO_DEV && SOC_CAMERA && HAVE_CLK + ---help--- + This is a v4l2 driver for the SuperH MIPI CSI-2 Interface + +config VIDEO_SH_MOBILE_CEU + tristate "SuperH Mobile CEU Interface driver" + depends on VIDEO_DEV && SOC_CAMERA && HAS_DMA && HAVE_CLK + select VIDEOBUF2_DMA_CONTIG + ---help--- + This is a v4l2 driver for the SuperH Mobile CEU Interface + +config VIDEO_OMAP1 + tristate "OMAP1 Camera Interface driver" + depends on VIDEO_DEV && ARCH_OMAP1 && SOC_CAMERA + select VIDEOBUF_DMA_CONTIG + select VIDEOBUF_DMA_SG + ---help--- + This is a v4l2 driver for the TI OMAP1 camera interface + +config VIDEO_MX2_HOSTSUPPORT + bool + +config VIDEO_MX2 + tristate "i.MX27/i.MX25 Camera Sensor Interface driver" + depends on VIDEO_DEV && SOC_CAMERA && (MACH_MX27 || (ARCH_MX25 && BROKEN)) + select VIDEOBUF2_DMA_CONTIG + select VIDEO_MX2_HOSTSUPPORT + ---help--- + This is a v4l2 driver for the i.MX27 and the i.MX25 Camera Sensor + Interface + +config VIDEO_ATMEL_ISI + tristate "ATMEL Image Sensor Interface (ISI) support" + depends on VIDEO_DEV && SOC_CAMERA && ARCH_AT91 + select VIDEOBUF2_DMA_CONTIG + ---help--- + This module makes the ATMEL Image Sensor Interface available + as a v4l2 device. + diff --git a/drivers/media/platform/soc_camera/Makefile b/drivers/media/platform/soc_camera/Makefile new file mode 100644 index 000000000000..136b7f8ff10d --- /dev/null +++ b/drivers/media/platform/soc_camera/Makefile @@ -0,0 +1,14 @@ +obj-$(CONFIG_SOC_CAMERA) += soc_camera.o soc_mediabus.o +obj-$(CONFIG_SOC_CAMERA_PLATFORM) += soc_camera_platform.o + +# soc-camera host drivers have to be linked after camera drivers +obj-$(CONFIG_VIDEO_ATMEL_ISI) += atmel-isi.o +obj-$(CONFIG_VIDEO_MX1) += mx1_camera.o +obj-$(CONFIG_VIDEO_MX2) += mx2_camera.o +obj-$(CONFIG_VIDEO_MX3) += mx3_camera.o +obj-$(CONFIG_VIDEO_OMAP1) += omap1_camera.o +obj-$(CONFIG_VIDEO_PXA27x) += pxa_camera.o +obj-$(CONFIG_VIDEO_SH_MOBILE_CEU) += sh_mobile_ceu_camera.o +obj-$(CONFIG_VIDEO_SH_MOBILE_CSI2) += sh_mobile_csi2.o + +ccflags-y += -I$(srctree)/drivers/media/i2c/soc_camera diff --git a/drivers/media/video/atmel-isi.c b/drivers/media/platform/soc_camera/atmel-isi.c index 6274a91c25c7..6274a91c25c7 100644 --- a/drivers/media/video/atmel-isi.c +++ b/drivers/media/platform/soc_camera/atmel-isi.c diff --git a/drivers/media/video/mx1_camera.c b/drivers/media/platform/soc_camera/mx1_camera.c index bbe70991d30b..bbe70991d30b 100644 --- a/drivers/media/video/mx1_camera.c +++ b/drivers/media/platform/soc_camera/mx1_camera.c diff --git a/drivers/media/video/mx2_camera.c b/drivers/media/platform/soc_camera/mx2_camera.c index 965427f279a5..403d7f17bfab 100644 --- a/drivers/media/video/mx2_camera.c +++ b/drivers/media/platform/soc_camera/mx2_camera.c @@ -274,12 +274,9 @@ struct mx2_camera_dev { struct soc_camera_device *icd; struct clk *clk_csi, *clk_emma_ahb, *clk_emma_ipg; - unsigned int irq_csi, irq_emma; void __iomem *base_csi, *base_emma; - unsigned long base_dma; struct mx2_camera_platform_data *pdata; - struct resource *res_csi, *res_emma; unsigned long platform_flags; struct list_head capture; @@ -336,6 +333,34 @@ static struct mx2_fmt_cfg mx27_emma_prp_table[] = { } }, { + .in_fmt = V4L2_MBUS_FMT_UYVY8_2X8, + .out_fmt = V4L2_PIX_FMT_YUYV, + .cfg = { + .channel = 1, + .in_fmt = PRP_CNTL_DATA_IN_YUV422, + .out_fmt = PRP_CNTL_CH1_OUT_YUV422, + .src_pixel = 0x22000888, /* YUV422 (YUYV) */ + .ch1_pixel = 0x62000888, /* YUV422 (YUYV) */ + .irq_flags = PRP_INTR_RDERR | PRP_INTR_CH1WERR | + PRP_INTR_CH1FC | PRP_INTR_LBOVF, + .csicr1 = CSICR1_SWAP16_EN, + } + }, + { + .in_fmt = V4L2_MBUS_FMT_YUYV8_2X8, + .out_fmt = V4L2_PIX_FMT_YUYV, + .cfg = { + .channel = 1, + .in_fmt = PRP_CNTL_DATA_IN_YUV422, + .out_fmt = PRP_CNTL_CH1_OUT_YUV422, + .src_pixel = 0x22000888, /* YUV422 (YUYV) */ + .ch1_pixel = 0x62000888, /* YUV422 (YUYV) */ + .irq_flags = PRP_INTR_RDERR | PRP_INTR_CH1WERR | + PRP_INTR_CH1FC | PRP_INTR_LBOVF, + .csicr1 = CSICR1_PACK_DIR, + } + }, + { .in_fmt = V4L2_MBUS_FMT_YUYV8_2X8, .out_fmt = V4L2_PIX_FMT_YUV420, .cfg = { @@ -441,11 +466,9 @@ static int mx2_camera_add_device(struct soc_camera_device *icd) csicr1 = CSICR1_MCLKEN; - if (cpu_is_mx27()) { + if (cpu_is_mx27()) csicr1 |= CSICR1_PRP_IF_EN | CSICR1_FCC | CSICR1_RXFF_LEVEL(0); - } else if (cpu_is_mx27()) - csicr1 |= CSICR1_SOF_INTEN | CSICR1_RXFF_LEVEL(2); pcdev->csicr1 = csicr1; writel(pcdev->csicr1, pcdev->base_csi + CSICR1); @@ -1142,6 +1165,18 @@ static int mx2_camera_get_formats(struct soc_camera_device *icd, } } + if (code == V4L2_MBUS_FMT_UYVY8_2X8) { + formats++; + if (xlate) { + xlate->host_fmt = + soc_mbus_get_fmtdesc(V4L2_MBUS_FMT_YUYV8_2X8); + xlate->code = code; + dev_dbg(dev, "Providing host format %s for sensor code %d\n", + xlate->host_fmt->name, code); + xlate++; + } + } + /* Generic pass-trough */ formats++; if (xlate) { @@ -1609,64 +1644,59 @@ static irqreturn_t mx27_camera_emma_irq(int irq_emma, void *data) return IRQ_HANDLED; } -static int __devinit mx27_camera_emma_init(struct mx2_camera_dev *pcdev) +static int __devinit mx27_camera_emma_init(struct platform_device *pdev) { - struct resource *res_emma = pcdev->res_emma; + struct mx2_camera_dev *pcdev = platform_get_drvdata(pdev); + struct resource *res_emma; + int irq_emma; int err = 0; - if (!request_mem_region(res_emma->start, resource_size(res_emma), - MX2_CAM_DRV_NAME)) { - err = -EBUSY; + res_emma = platform_get_resource(pdev, IORESOURCE_MEM, 1); + irq_emma = platform_get_irq(pdev, 1); + if (!res_emma || !irq_emma) { + dev_err(pcdev->dev, "no EMMA resources\n"); goto out; } - pcdev->base_emma = ioremap(res_emma->start, resource_size(res_emma)); + pcdev->base_emma = devm_request_and_ioremap(pcdev->dev, res_emma); if (!pcdev->base_emma) { - err = -ENOMEM; - goto exit_release; + err = -EADDRNOTAVAIL; + goto out; } - err = request_irq(pcdev->irq_emma, mx27_camera_emma_irq, 0, - MX2_CAM_DRV_NAME, pcdev); + err = devm_request_irq(pcdev->dev, irq_emma, mx27_camera_emma_irq, 0, + MX2_CAM_DRV_NAME, pcdev); if (err) { dev_err(pcdev->dev, "Camera EMMA interrupt register failed \n"); - goto exit_iounmap; + goto out; } - pcdev->clk_emma_ipg = clk_get(pcdev->dev, "emma-ipg"); + pcdev->clk_emma_ipg = devm_clk_get(pcdev->dev, "emma-ipg"); if (IS_ERR(pcdev->clk_emma_ipg)) { err = PTR_ERR(pcdev->clk_emma_ipg); - goto exit_free_irq; + goto out; } clk_prepare_enable(pcdev->clk_emma_ipg); - pcdev->clk_emma_ahb = clk_get(pcdev->dev, "emma-ahb"); + pcdev->clk_emma_ahb = devm_clk_get(pcdev->dev, "emma-ahb"); if (IS_ERR(pcdev->clk_emma_ahb)) { err = PTR_ERR(pcdev->clk_emma_ahb); - goto exit_clk_emma_ipg_put; + goto exit_clk_emma_ipg; } clk_prepare_enable(pcdev->clk_emma_ahb); err = mx27_camera_emma_prp_reset(pcdev); if (err) - goto exit_clk_emma_ahb_put; + goto exit_clk_emma_ahb; return err; -exit_clk_emma_ahb_put: +exit_clk_emma_ahb: clk_disable_unprepare(pcdev->clk_emma_ahb); - clk_put(pcdev->clk_emma_ahb); -exit_clk_emma_ipg_put: +exit_clk_emma_ipg: clk_disable_unprepare(pcdev->clk_emma_ipg); - clk_put(pcdev->clk_emma_ipg); -exit_free_irq: - free_irq(pcdev->irq_emma, pcdev); -exit_iounmap: - iounmap(pcdev->base_emma); -exit_release: - release_mem_region(res_emma->start, resource_size(res_emma)); out: return err; } @@ -1674,9 +1704,8 @@ out: static int __devinit mx2_camera_probe(struct platform_device *pdev) { struct mx2_camera_dev *pcdev; - struct resource *res_csi, *res_emma; - void __iomem *base_csi; - int irq_csi, irq_emma; + struct resource *res_csi; + int irq_csi; int err = 0; dev_dbg(&pdev->dev, "initialising\n"); @@ -1689,21 +1718,20 @@ static int __devinit mx2_camera_probe(struct platform_device *pdev) goto exit; } - pcdev = kzalloc(sizeof(*pcdev), GFP_KERNEL); + pcdev = devm_kzalloc(&pdev->dev, sizeof(*pcdev), GFP_KERNEL); if (!pcdev) { dev_err(&pdev->dev, "Could not allocate pcdev\n"); err = -ENOMEM; goto exit; } - pcdev->clk_csi = clk_get(&pdev->dev, "ahb"); + pcdev->clk_csi = devm_clk_get(&pdev->dev, "ahb"); if (IS_ERR(pcdev->clk_csi)) { dev_err(&pdev->dev, "Could not get csi clock\n"); err = PTR_ERR(pcdev->clk_csi); - goto exit_kfree; + goto exit; } - pcdev->res_csi = res_csi; pcdev->pdata = pdev->dev.platform_data; if (pcdev->pdata) { long rate; @@ -1713,11 +1741,11 @@ static int __devinit mx2_camera_probe(struct platform_device *pdev) rate = clk_round_rate(pcdev->clk_csi, pcdev->pdata->clk * 2); if (rate <= 0) { err = -ENODEV; - goto exit_dma_free; + goto exit; } err = clk_set_rate(pcdev->clk_csi, rate); if (err < 0) - goto exit_dma_free; + goto exit; } INIT_LIST_HEAD(&pcdev->capture); @@ -1725,50 +1753,36 @@ static int __devinit mx2_camera_probe(struct platform_device *pdev) INIT_LIST_HEAD(&pcdev->discard); spin_lock_init(&pcdev->lock); - /* - * Request the regions. - */ - if (!request_mem_region(res_csi->start, resource_size(res_csi), - MX2_CAM_DRV_NAME)) { - err = -EBUSY; - goto exit_dma_free; + pcdev->base_csi = devm_request_and_ioremap(&pdev->dev, res_csi); + if (!pcdev->base_csi) { + err = -EADDRNOTAVAIL; + goto exit; } - base_csi = ioremap(res_csi->start, resource_size(res_csi)); - if (!base_csi) { - err = -ENOMEM; - goto exit_release; - } - pcdev->irq_csi = irq_csi; - pcdev->base_csi = base_csi; - pcdev->base_dma = res_csi->start; pcdev->dev = &pdev->dev; + platform_set_drvdata(pdev, pcdev); if (cpu_is_mx25()) { - err = request_irq(pcdev->irq_csi, mx25_camera_irq, 0, - MX2_CAM_DRV_NAME, pcdev); + err = devm_request_irq(&pdev->dev, irq_csi, mx25_camera_irq, 0, + MX2_CAM_DRV_NAME, pcdev); if (err) { dev_err(pcdev->dev, "Camera interrupt register failed \n"); - goto exit_iounmap; + goto exit; } } if (cpu_is_mx27()) { - /* EMMA support */ - res_emma = platform_get_resource(pdev, IORESOURCE_MEM, 1); - irq_emma = platform_get_irq(pdev, 1); - - if (!res_emma || !irq_emma) { - dev_err(&pdev->dev, "no EMMA resources\n"); - goto exit_free_irq; - } - - pcdev->res_emma = res_emma; - pcdev->irq_emma = irq_emma; - if (mx27_camera_emma_init(pcdev)) - goto exit_free_irq; + err = mx27_camera_emma_init(pdev); + if (err) + goto exit; } + /* + * We're done with drvdata here. Clear the pointer so that + * v4l2 core can start using drvdata on its purpose. + */ + platform_set_drvdata(pdev, NULL); + pcdev->soc_host.drv_name = MX2_CAM_DRV_NAME, pcdev->soc_host.ops = &mx2_soc_camera_host_ops, pcdev->soc_host.priv = pcdev; @@ -1795,25 +1809,9 @@ exit_free_emma: vb2_dma_contig_cleanup_ctx(pcdev->alloc_ctx); eallocctx: if (cpu_is_mx27()) { - free_irq(pcdev->irq_emma, pcdev); clk_disable_unprepare(pcdev->clk_emma_ipg); - clk_put(pcdev->clk_emma_ipg); clk_disable_unprepare(pcdev->clk_emma_ahb); - clk_put(pcdev->clk_emma_ahb); - iounmap(pcdev->base_emma); - release_mem_region(pcdev->res_emma->start, resource_size(pcdev->res_emma)); } -exit_free_irq: - if (cpu_is_mx25()) - free_irq(pcdev->irq_csi, pcdev); -exit_iounmap: - iounmap(base_csi); -exit_release: - release_mem_region(res_csi->start, resource_size(res_csi)); -exit_dma_free: - clk_put(pcdev->clk_csi); -exit_kfree: - kfree(pcdev); exit: return err; } @@ -1823,35 +1821,16 @@ static int __devexit mx2_camera_remove(struct platform_device *pdev) struct soc_camera_host *soc_host = to_soc_camera_host(&pdev->dev); struct mx2_camera_dev *pcdev = container_of(soc_host, struct mx2_camera_dev, soc_host); - struct resource *res; - - clk_put(pcdev->clk_csi); - if (cpu_is_mx25()) - free_irq(pcdev->irq_csi, pcdev); - if (cpu_is_mx27()) - free_irq(pcdev->irq_emma, pcdev); soc_camera_host_unregister(&pcdev->soc_host); vb2_dma_contig_cleanup_ctx(pcdev->alloc_ctx); - iounmap(pcdev->base_csi); - if (cpu_is_mx27()) { clk_disable_unprepare(pcdev->clk_emma_ipg); - clk_put(pcdev->clk_emma_ipg); clk_disable_unprepare(pcdev->clk_emma_ahb); - clk_put(pcdev->clk_emma_ahb); - iounmap(pcdev->base_emma); - res = pcdev->res_emma; - release_mem_region(res->start, resource_size(res)); } - res = pcdev->res_csi; - release_mem_region(res->start, resource_size(res)); - - kfree(pcdev); - dev_info(&pdev->dev, "MX2 Camera driver unloaded\n"); return 0; diff --git a/drivers/media/video/mx3_camera.c b/drivers/media/platform/soc_camera/mx3_camera.c index 1481b0d419da..3557ac97e430 100644 --- a/drivers/media/video/mx3_camera.c +++ b/drivers/media/platform/soc_camera/mx3_camera.c @@ -1171,9 +1171,7 @@ static int __devinit mx3_camera_probe(struct platform_device *pdev) mx3_cam->pdata = pdev->dev.platform_data; mx3_cam->platform_flags = mx3_cam->pdata->flags; - if (!(mx3_cam->platform_flags & (MX3_CAMERA_DATAWIDTH_4 | - MX3_CAMERA_DATAWIDTH_8 | MX3_CAMERA_DATAWIDTH_10 | - MX3_CAMERA_DATAWIDTH_15))) { + if (!(mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_MASK)) { /* * Platform hasn't set available data widths. This is bad. * Warn and use a default. diff --git a/drivers/media/video/omap1_camera.c b/drivers/media/platform/soc_camera/omap1_camera.c index c7e41145041f..fa08c7695ccb 100644 --- a/drivers/media/video/omap1_camera.c +++ b/drivers/media/platform/soc_camera/omap1_camera.c @@ -12,7 +12,7 @@ * Copyright (C) 2008, Guennadi Liakhovetski <kernel@pengutronix.de> * * Hardware specific bits initialy based on former work by Matt Callow - * drivers/media/video/omap/omap1510cam.c + * drivers/media/platform/omap/omap1510cam.c * Copyright (C) 2006 Matt Callow * * This program is free software; you can redistribute it and/or modify diff --git a/drivers/media/video/pxa_camera.c b/drivers/media/platform/soc_camera/pxa_camera.c index 1e3776d08dac..1e3776d08dac 100644 --- a/drivers/media/video/pxa_camera.c +++ b/drivers/media/platform/soc_camera/pxa_camera.c diff --git a/drivers/media/video/sh_mobile_ceu_camera.c b/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c index 0baaf94db7e0..0a24253dcda2 100644 --- a/drivers/media/video/sh_mobile_ceu_camera.c +++ b/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c @@ -1263,7 +1263,7 @@ static void update_subrect(struct sh_mobile_ceu_cam *cam) * 3. if (2) failed, try to request the maximum image */ static int client_s_crop(struct soc_camera_device *icd, struct v4l2_crop *crop, - struct v4l2_crop *cam_crop) + const struct v4l2_crop *cam_crop) { struct v4l2_subdev *sd = soc_camera_to_subdev(icd); struct v4l2_rect *rect = &crop->c, *cam_rect = &cam_crop->c; @@ -1517,7 +1517,7 @@ static int client_scale(struct soc_camera_device *icd, * scaling and cropping algorithms and for the meaning of referenced here steps. */ static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd, - struct v4l2_crop *a) + const struct v4l2_crop *a) { struct v4l2_rect *rect = &a->c; struct device *dev = icd->parent; diff --git a/drivers/media/video/sh_mobile_csi2.c b/drivers/media/platform/soc_camera/sh_mobile_csi2.c index 05286500b4d4..05286500b4d4 100644 --- a/drivers/media/video/sh_mobile_csi2.c +++ b/drivers/media/platform/soc_camera/sh_mobile_csi2.c diff --git a/drivers/media/video/soc_camera.c b/drivers/media/platform/soc_camera/soc_camera.c index 1bde255e45df..3be92944f8e7 100644 --- a/drivers/media/video/soc_camera.c +++ b/drivers/media/platform/soc_camera/soc_camera.c @@ -50,66 +50,77 @@ static LIST_HEAD(hosts); static LIST_HEAD(devices); static DEFINE_MUTEX(list_lock); /* Protects the list of hosts */ -static int soc_camera_power_on(struct soc_camera_device *icd, - struct soc_camera_link *icl) +int soc_camera_power_on(struct device *dev, struct soc_camera_link *icl) { - struct v4l2_subdev *sd = soc_camera_to_subdev(icd); int ret = regulator_bulk_enable(icl->num_regulators, icl->regulators); if (ret < 0) { - dev_err(icd->pdev, "Cannot enable regulators\n"); + dev_err(dev, "Cannot enable regulators\n"); return ret; } if (icl->power) { - ret = icl->power(icd->control, 1); + ret = icl->power(dev, 1); if (ret < 0) { - dev_err(icd->pdev, + dev_err(dev, "Platform failed to power-on the camera.\n"); - goto elinkpwr; + regulator_bulk_disable(icl->num_regulators, + icl->regulators); } } - ret = v4l2_subdev_call(sd, core, s_power, 1); - if (ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV) - goto esdpwr; - - return 0; - -esdpwr: - if (icl->power) - icl->power(icd->control, 0); -elinkpwr: - regulator_bulk_disable(icl->num_regulators, - icl->regulators); return ret; } +EXPORT_SYMBOL(soc_camera_power_on); -static int soc_camera_power_off(struct soc_camera_device *icd, - struct soc_camera_link *icl) +int soc_camera_power_off(struct device *dev, struct soc_camera_link *icl) { - struct v4l2_subdev *sd = soc_camera_to_subdev(icd); - int ret = v4l2_subdev_call(sd, core, s_power, 0); - - if (ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV) - return ret; + int ret = 0; + int err; if (icl->power) { - ret = icl->power(icd->control, 0); - if (ret < 0) { - dev_err(icd->pdev, + err = icl->power(dev, 0); + if (err < 0) { + dev_err(dev, "Platform failed to power-off the camera.\n"); - return ret; + ret = err; } } - ret = regulator_bulk_disable(icl->num_regulators, + err = regulator_bulk_disable(icl->num_regulators, icl->regulators); - if (ret < 0) - dev_err(icd->pdev, "Cannot disable regulators\n"); + if (err < 0) { + dev_err(dev, "Cannot disable regulators\n"); + ret = ret ? : err; + } return ret; } +EXPORT_SYMBOL(soc_camera_power_off); + +static int __soc_camera_power_on(struct soc_camera_device *icd) +{ + struct v4l2_subdev *sd = soc_camera_to_subdev(icd); + int ret; + + ret = v4l2_subdev_call(sd, core, s_power, 1); + if (ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV) + return ret; + + return 0; +} + +static int __soc_camera_power_off(struct soc_camera_device *icd) +{ + struct v4l2_subdev *sd = soc_camera_to_subdev(icd); + int ret; + + ret = v4l2_subdev_call(sd, core, s_power, 0); + if (ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV) + return ret; + + return 0; +} const struct soc_camera_format_xlate *soc_camera_xlate_by_fourcc( struct soc_camera_device *icd, unsigned int fourcc) @@ -508,9 +519,12 @@ static int soc_camera_open(struct file *file) ici = to_soc_camera_host(icd->parent); + if (mutex_lock_interruptible(&icd->video_lock)) + return -ERESTARTSYS; if (!try_module_get(ici->ops->owner)) { dev_err(icd->pdev, "Couldn't lock capture bus driver.\n"); - return -EINVAL; + ret = -EINVAL; + goto emodule; } icd->use_count++; @@ -543,7 +557,7 @@ static int soc_camera_open(struct file *file) goto eiciadd; } - ret = soc_camera_power_on(icd, icl); + ret = __soc_camera_power_on(icd); if (ret < 0) goto epower; @@ -571,6 +585,7 @@ static int soc_camera_open(struct file *file) } v4l2_ctrl_handler_setup(&icd->ctrl_handler); } + mutex_unlock(&icd->video_lock); file->private_data = icd; dev_dbg(icd->pdev, "camera device open\n"); @@ -585,12 +600,14 @@ einitvb: esfmt: pm_runtime_disable(&icd->vdev->dev); eresume: - soc_camera_power_off(icd, icl); + __soc_camera_power_off(icd); epower: ici->ops->remove(icd); eiciadd: icd->use_count--; module_put(ici->ops->owner); +emodule: + mutex_unlock(&icd->video_lock); return ret; } @@ -600,10 +617,9 @@ static int soc_camera_close(struct file *file) struct soc_camera_device *icd = file->private_data; struct soc_camera_host *ici = to_soc_camera_host(icd->parent); + mutex_lock(&icd->video_lock); icd->use_count--; if (!icd->use_count) { - struct soc_camera_link *icl = to_soc_camera_link(icd); - pm_runtime_suspend(&icd->vdev->dev); pm_runtime_disable(&icd->vdev->dev); @@ -611,11 +627,12 @@ static int soc_camera_close(struct file *file) vb2_queue_release(&icd->vb2_vidq); ici->ops->remove(icd); - soc_camera_power_off(icd, icl); + __soc_camera_power_off(icd); } if (icd->streamer == file) icd->streamer = NULL; + mutex_unlock(&icd->video_lock); module_put(ici->ops->owner); @@ -646,10 +663,13 @@ static int soc_camera_mmap(struct file *file, struct vm_area_struct *vma) if (icd->streamer != file) return -EBUSY; + if (mutex_lock_interruptible(&icd->video_lock)) + return -ERESTARTSYS; if (ici->ops->init_videobuf) err = videobuf_mmap_mapper(&icd->vb_vidq, vma); else err = vb2_mmap(&icd->vb2_vidq, vma); + mutex_unlock(&icd->video_lock); dev_dbg(icd->pdev, "vma start=0x%08lx, size=%ld, ret=%d\n", (unsigned long)vma->vm_start, @@ -663,16 +683,18 @@ static unsigned int soc_camera_poll(struct file *file, poll_table *pt) { struct soc_camera_device *icd = file->private_data; struct soc_camera_host *ici = to_soc_camera_host(icd->parent); + unsigned res = POLLERR; if (icd->streamer != file) - return -EBUSY; - - if (ici->ops->init_videobuf && list_empty(&icd->vb_vidq.stream)) { - dev_err(icd->pdev, "Trying to poll with no queued buffers!\n"); return POLLERR; - } - return ici->ops->poll(file, pt); + mutex_lock(&icd->video_lock); + if (ici->ops->init_videobuf && list_empty(&icd->vb_vidq.stream)) + dev_err(icd->pdev, "Trying to poll with no queued buffers!\n"); + else + res = ici->ops->poll(file, pt); + mutex_unlock(&icd->video_lock); + return res; } void soc_camera_lock(struct vb2_queue *vq) @@ -866,11 +888,11 @@ static int soc_camera_g_crop(struct file *file, void *fh, * retrieve it. */ static int soc_camera_s_crop(struct file *file, void *fh, - struct v4l2_crop *a) + const struct v4l2_crop *a) { struct soc_camera_device *icd = file->private_data; struct soc_camera_host *ici = to_soc_camera_host(icd->parent); - struct v4l2_rect *rect = &a->c; + const struct v4l2_rect *rect = &a->c; struct v4l2_crop current_crop; int ret; @@ -903,6 +925,65 @@ static int soc_camera_s_crop(struct file *file, void *fh, return ret; } +static int soc_camera_g_selection(struct file *file, void *fh, + struct v4l2_selection *s) +{ + struct soc_camera_device *icd = file->private_data; + struct soc_camera_host *ici = to_soc_camera_host(icd->parent); + + /* With a wrong type no need to try to fall back to cropping */ + if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + if (!ici->ops->get_selection) + return -ENOTTY; + + return ici->ops->get_selection(icd, s); +} + +static int soc_camera_s_selection(struct file *file, void *fh, + struct v4l2_selection *s) +{ + struct soc_camera_device *icd = file->private_data; + struct soc_camera_host *ici = to_soc_camera_host(icd->parent); + int ret; + + /* In all these cases cropping emulation will not help */ + if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE || + (s->target != V4L2_SEL_TGT_COMPOSE_ACTIVE && + s->target != V4L2_SEL_TGT_CROP_ACTIVE)) + return -EINVAL; + + if (s->target == V4L2_SEL_TGT_COMPOSE_ACTIVE) { + /* No output size change during a running capture! */ + if (is_streaming(ici, icd) && + (icd->user_width != s->r.width || + icd->user_height != s->r.height)) + return -EBUSY; + + /* + * Only one user is allowed to change the output format, touch + * buffers, start / stop streaming, poll for data + */ + if (icd->streamer && icd->streamer != file) + return -EBUSY; + } + + if (!ici->ops->set_selection) + return -ENOTTY; + + ret = ici->ops->set_selection(icd, s); + if (!ret && + s->target == V4L2_SEL_TGT_COMPOSE_ACTIVE) { + icd->user_width = s->r.width; + icd->user_height = s->r.height; + if (!icd->streamer) + icd->streamer = file; + } + + return ret; +} + static int soc_camera_g_parm(struct file *file, void *fh, struct v4l2_streamparm *a) { @@ -1065,16 +1146,6 @@ static int soc_camera_probe(struct soc_camera_device *icd) if (ret < 0) goto eadd; - /* - * This will not yet call v4l2_subdev_core_ops::s_power(1), because the - * subdevice has not been initialised yet. We'll have to call it once - * again after initialisation, even though it shouldn't be needed, we - * don't do any IO here. - */ - ret = soc_camera_power_on(icd, icl); - if (ret < 0) - goto epower; - /* Must have icd->vdev before registering the device */ ret = video_dev_create(icd); if (ret < 0) @@ -1113,7 +1184,7 @@ static int soc_camera_probe(struct soc_camera_device *icd) sd->grp_id = soc_camera_grp_id(icd); v4l2_set_subdev_hostdata(sd, icd); - if (v4l2_ctrl_add_handler(&icd->ctrl_handler, sd->ctrl_handler)) + if (v4l2_ctrl_add_handler(&icd->ctrl_handler, sd->ctrl_handler, NULL)) goto ectrl; /* At this point client .probe() should have run already */ @@ -1134,10 +1205,6 @@ static int soc_camera_probe(struct soc_camera_device *icd) if (ret < 0) goto evidstart; - ret = v4l2_subdev_call(sd, core, s_power, 1); - if (ret < 0 && ret != -ENOIOCTLCMD) - goto esdpwr; - /* Try to improve our guess of a reasonable window format */ if (!v4l2_subdev_call(sd, video, g_mbus_fmt, &mf)) { icd->user_width = mf.width; @@ -1148,14 +1215,10 @@ static int soc_camera_probe(struct soc_camera_device *icd) ici->ops->remove(icd); - soc_camera_power_off(icd, icl); - mutex_unlock(&icd->video_lock); return 0; -esdpwr: - video_unregister_device(icd->vdev); evidstart: mutex_unlock(&icd->video_lock); soc_camera_free_user_formats(icd); @@ -1172,8 +1235,6 @@ eadddev: video_device_release(icd->vdev); icd->vdev = NULL; evdc: - soc_camera_power_off(icd, icl); -epower: ici->ops->remove(icd); eadd: regulator_bulk_free(icl->num_regulators, icl->regulators); @@ -1228,7 +1289,7 @@ static int default_g_crop(struct soc_camera_device *icd, struct v4l2_crop *a) return v4l2_subdev_call(sd, video, g_crop, a); } -static int default_s_crop(struct soc_camera_device *icd, struct v4l2_crop *a) +static int default_s_crop(struct soc_camera_device *icd, const struct v4l2_crop *a) { struct v4l2_subdev *sd = soc_camera_to_subdev(icd); return v4l2_subdev_call(sd, video, s_crop, a); @@ -1406,6 +1467,8 @@ static const struct v4l2_ioctl_ops soc_camera_ioctl_ops = { .vidioc_cropcap = soc_camera_cropcap, .vidioc_g_crop = soc_camera_g_crop, .vidioc_s_crop = soc_camera_s_crop, + .vidioc_g_selection = soc_camera_g_selection, + .vidioc_s_selection = soc_camera_s_selection, .vidioc_g_parm = soc_camera_g_parm, .vidioc_s_parm = soc_camera_s_parm, .vidioc_g_chip_ident = soc_camera_g_chip_ident, @@ -1433,10 +1496,6 @@ static int video_dev_create(struct soc_camera_device *icd) vdev->tvnorms = V4L2_STD_UNKNOWN; vdev->ctrl_handler = &icd->ctrl_handler; vdev->lock = &icd->video_lock; - /* Locking in file operations other than ioctl should be done - by the driver, not the V4L2 core. - This driver needs auditing so that this flag can be removed. */ - set_bit(V4L2_FL_LOCK_ALL_FOPS, &vdev->flags); icd->vdev = vdev; diff --git a/drivers/media/video/soc_camera_platform.c b/drivers/media/platform/soc_camera/soc_camera_platform.c index f59ccade07c8..7cf7fd16481f 100644 --- a/drivers/media/video/soc_camera_platform.c +++ b/drivers/media/platform/soc_camera/soc_camera_platform.c @@ -50,7 +50,16 @@ static int soc_camera_platform_fill_fmt(struct v4l2_subdev *sd, return 0; } -static struct v4l2_subdev_core_ops platform_subdev_core_ops; +static int soc_camera_platform_s_power(struct v4l2_subdev *sd, int on) +{ + struct soc_camera_platform_info *p = v4l2_get_subdevdata(sd); + + return soc_camera_set_power(p->icd->control, p->icd->link, on); +} + +static struct v4l2_subdev_core_ops platform_subdev_core_ops = { + .s_power = soc_camera_platform_s_power, +}; static int soc_camera_platform_enum_fmt(struct v4l2_subdev *sd, unsigned int index, enum v4l2_mbus_pixelcode *code) diff --git a/drivers/media/video/soc_mediabus.c b/drivers/media/platform/soc_camera/soc_mediabus.c index a397812635d6..a397812635d6 100644 --- a/drivers/media/video/soc_mediabus.c +++ b/drivers/media/platform/soc_camera/soc_mediabus.c diff --git a/drivers/media/video/timblogiw.c b/drivers/media/platform/timblogiw.c index 02194c056b00..02194c056b00 100644 --- a/drivers/media/video/timblogiw.c +++ b/drivers/media/platform/timblogiw.c diff --git a/drivers/media/video/via-camera.c b/drivers/media/platform/via-camera.c index eb404c2ce270..eb404c2ce270 100644 --- a/drivers/media/video/via-camera.c +++ b/drivers/media/platform/via-camera.c diff --git a/drivers/media/video/via-camera.h b/drivers/media/platform/via-camera.h index b12a4b3d616f..b12a4b3d616f 100644 --- a/drivers/media/video/via-camera.h +++ b/drivers/media/platform/via-camera.h diff --git a/drivers/media/video/vino.c b/drivers/media/platform/vino.c index aae1720b2f2d..790d96cffeea 100644 --- a/drivers/media/video/vino.c +++ b/drivers/media/platform/vino.c @@ -3284,7 +3284,7 @@ static int vino_g_crop(struct file *file, void *__fh, } static int vino_s_crop(struct file *file, void *__fh, - struct v4l2_crop *c) + const struct v4l2_crop *c) { struct vino_channel_settings *vcs = video_drvdata(file); unsigned long flags; diff --git a/drivers/media/video/vino.h b/drivers/media/platform/vino.h index de2d615ae7c9..de2d615ae7c9 100644 --- a/drivers/media/video/vino.h +++ b/drivers/media/platform/vino.h diff --git a/drivers/media/video/vivi.c b/drivers/media/platform/vivi.c index a05494b71b20..b366b050a3dd 100644 --- a/drivers/media/video/vivi.c +++ b/drivers/media/platform/vivi.c @@ -80,7 +80,8 @@ static const u8 *font8x16; struct vivi_fmt { char *name; u32 fourcc; /* v4l2 format id */ - int depth; + u8 depth; + bool is_yuv; }; static struct vivi_fmt formats[] = { @@ -88,21 +89,25 @@ static struct vivi_fmt formats[] = { .name = "4:2:2, packed, YUYV", .fourcc = V4L2_PIX_FMT_YUYV, .depth = 16, + .is_yuv = true, }, { .name = "4:2:2, packed, UYVY", .fourcc = V4L2_PIX_FMT_UYVY, .depth = 16, + .is_yuv = true, }, { .name = "4:2:2, packed, YVYU", .fourcc = V4L2_PIX_FMT_YVYU, .depth = 16, + .is_yuv = true, }, { .name = "4:2:2, packed, VYUY", .fourcc = V4L2_PIX_FMT_VYUY, .depth = 16, + .is_yuv = true, }, { .name = "RGB565 (LE)", @@ -309,15 +314,9 @@ static void precalculate_bars(struct vivi_dev *dev) r = bars[dev->input].bar[k][0]; g = bars[dev->input].bar[k][1]; b = bars[dev->input].bar[k][2]; - is_yuv = 0; + is_yuv = dev->fmt->is_yuv; switch (dev->fmt->fourcc) { - case V4L2_PIX_FMT_YUYV: - case V4L2_PIX_FMT_UYVY: - case V4L2_PIX_FMT_YVYU: - case V4L2_PIX_FMT_VYUY: - is_yuv = 1; - break; case V4L2_PIX_FMT_RGB565: case V4L2_PIX_FMT_RGB565X: r >>= 3; @@ -330,6 +329,10 @@ static void precalculate_bars(struct vivi_dev *dev) g >>= 3; b >>= 3; break; + case V4L2_PIX_FMT_YUYV: + case V4L2_PIX_FMT_UYVY: + case V4L2_PIX_FMT_YVYU: + case V4L2_PIX_FMT_VYUY: case V4L2_PIX_FMT_RGB24: case V4L2_PIX_FMT_BGR24: case V4L2_PIX_FMT_RGB32: @@ -895,7 +898,8 @@ static int vidioc_querycap(struct file *file, void *priv, strcpy(cap->driver, "vivi"); strcpy(cap->card, "vivi"); - strlcpy(cap->bus_info, dev->v4l2_dev.name, sizeof(cap->bus_info)); + snprintf(cap->bus_info, sizeof(cap->bus_info), + "platform:%s", dev->v4l2_dev.name); cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING | V4L2_CAP_READWRITE; cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; @@ -930,8 +934,7 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, (f->fmt.pix.width * dev->fmt->depth) >> 3; f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; - if (dev->fmt->fourcc == V4L2_PIX_FMT_YUYV || - dev->fmt->fourcc == V4L2_PIX_FMT_UYVY) + if (dev->fmt->is_yuv) f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; else f->fmt.pix.colorspace = V4L2_COLORSPACE_SRGB; @@ -959,11 +962,11 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, (f->fmt.pix.width * fmt->depth) >> 3; f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; - if (fmt->fourcc == V4L2_PIX_FMT_YUYV || - fmt->fourcc == V4L2_PIX_FMT_UYVY) + if (fmt->is_yuv) f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; else f->fmt.pix.colorspace = V4L2_COLORSPACE_SRGB; + f->fmt.pix.priv = 0; return 0; } @@ -990,6 +993,27 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, return 0; } +static int vidioc_enum_framesizes(struct file *file, void *fh, + struct v4l2_frmsizeenum *fsize) +{ + static const struct v4l2_frmsize_stepwise sizes = { + 48, MAX_WIDTH, 4, + 32, MAX_HEIGHT, 1 + }; + int i; + + if (fsize->index) + return -EINVAL; + for (i = 0; i < ARRAY_SIZE(formats); i++) + if (formats[i].fourcc == fsize->pixel_format) + break; + if (i == ARRAY_SIZE(formats)) + return -EINVAL; + fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE; + fsize->stepwise = sizes; + return 0; +} + /* only one input in this sample driver */ static int vidioc_enum_input(struct file *file, void *priv, struct v4l2_input *inp) @@ -1174,6 +1198,7 @@ static const struct v4l2_ioctl_ops vivi_ioctl_ops = { .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, + .vidioc_enum_framesizes = vidioc_enum_framesizes, .vidioc_reqbufs = vb2_ioctl_reqbufs, .vidioc_create_bufs = vb2_ioctl_create_bufs, .vidioc_prepare_buf = vb2_ioctl_prepare_buf, @@ -1282,7 +1307,6 @@ static int __init vivi_create_instance(int inst) /* initialize queue */ q = &dev->vb_vidq; - memset(q, 0, sizeof(dev->vb_vidq)); q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ; q->drv_priv = dev; @@ -1290,7 +1314,9 @@ static int __init vivi_create_instance(int inst) q->ops = &vivi_video_qops; q->mem_ops = &vb2_vmalloc_memops; - vb2_queue_init(q); + ret = vb2_queue_init(q); + if (ret) + goto unreg_dev; mutex_init(&dev->mutex); diff --git a/drivers/media/radio/radio-keene.c b/drivers/media/radio/radio-keene.c index 79adf3e654e5..e10e525f33e5 100644 --- a/drivers/media/radio/radio-keene.c +++ b/drivers/media/radio/radio-keene.c @@ -203,7 +203,7 @@ static int vidioc_g_modulator(struct file *file, void *priv, } static int vidioc_s_modulator(struct file *file, void *priv, - struct v4l2_modulator *v) + const struct v4l2_modulator *v) { struct keene_device *radio = video_drvdata(file); diff --git a/drivers/media/radio/radio-miropcm20.c b/drivers/media/radio/radio-miropcm20.c index 87c1ee13b058..11f76ed4c6fb 100644 --- a/drivers/media/radio/radio-miropcm20.c +++ b/drivers/media/radio/radio-miropcm20.c @@ -197,7 +197,7 @@ static int vidioc_g_audio(struct file *file, void *priv, } static int vidioc_s_audio(struct file *file, void *priv, - struct v4l2_audio *a) + const struct v4l2_audio *a) { return a->index ? -EINVAL : 0; } diff --git a/drivers/media/radio/radio-mr800.c b/drivers/media/radio/radio-mr800.c index 3182b26d6efa..9c5a267b60b4 100644 --- a/drivers/media/radio/radio-mr800.c +++ b/drivers/media/radio/radio-mr800.c @@ -348,7 +348,7 @@ static int vidioc_g_frequency(struct file *file, void *priv, } static int vidioc_s_hw_freq_seek(struct file *file, void *priv, - struct v4l2_hw_freq_seek *seek) + const struct v4l2_hw_freq_seek *seek) { static u8 buf[8] = { 0x3d, 0x32, 0x0f, 0x08, 0x3d, 0x32, 0x0f, 0x08 @@ -360,6 +360,9 @@ static int vidioc_s_hw_freq_seek(struct file *file, void *priv, if (seek->tuner != 0 || !seek->wrap_around) return -EINVAL; + if (file->f_flags & O_NONBLOCK) + return -EWOULDBLOCK; + retval = amradio_send_cmd(radio, AMRADIO_SET_SEARCH_LVL, 0, buf, 8, false); if (retval) diff --git a/drivers/media/radio/radio-sf16fmi.c b/drivers/media/radio/radio-sf16fmi.c index 8185d5fbfa89..227dcdb54df3 100644 --- a/drivers/media/radio/radio-sf16fmi.c +++ b/drivers/media/radio/radio-sf16fmi.c @@ -239,7 +239,7 @@ static int vidioc_g_audio(struct file *file, void *priv, } static int vidioc_s_audio(struct file *file, void *priv, - struct v4l2_audio *a) + const struct v4l2_audio *a) { return a->index ? -EINVAL : 0; } diff --git a/drivers/media/radio/radio-shark.c b/drivers/media/radio/radio-shark.c index 72ded29728bb..8c309c7134d7 100644 --- a/drivers/media/radio/radio-shark.c +++ b/drivers/media/radio/radio-shark.c @@ -59,7 +59,8 @@ MODULE_LICENSE("GPL"); #define v4l2_dev_to_shark(d) container_of(d, struct shark_device, v4l2_dev) -enum { BLUE_LED, BLUE_PULSE_LED, RED_LED, NO_LEDS }; +/* Note BLUE_IS_PULSE comes after NO_LEDS as it is a status bit, not a LED */ +enum { BLUE_LED, BLUE_PULSE_LED, RED_LED, NO_LEDS, BLUE_IS_PULSE }; struct shark_device { struct usb_device *usbdev; @@ -190,6 +191,7 @@ static void shark_led_set_blue(struct led_classdev *led_cdev, atomic_set(&shark->brightness[BLUE_LED], value); set_bit(BLUE_LED, &shark->brightness_new); + clear_bit(BLUE_IS_PULSE, &shark->brightness_new); schedule_work(&shark->led_work); } @@ -201,6 +203,7 @@ static void shark_led_set_blue_pulse(struct led_classdev *led_cdev, atomic_set(&shark->brightness[BLUE_PULSE_LED], 256 - value); set_bit(BLUE_PULSE_LED, &shark->brightness_new); + set_bit(BLUE_IS_PULSE, &shark->brightness_new); schedule_work(&shark->led_work); } @@ -240,6 +243,7 @@ static int shark_register_leds(struct shark_device *shark, struct device *dev) { int i, retval; + atomic_set(&shark->brightness[BLUE_LED], 127); INIT_WORK(&shark->led_work, shark_led_work); for (i = 0; i < NO_LEDS; i++) { shark->leds[i] = shark_led_templates[i]; @@ -266,6 +270,16 @@ static void shark_unregister_leds(struct shark_device *shark) cancel_work_sync(&shark->led_work); } + +static void shark_resume_leds(struct shark_device *shark) +{ + if (test_bit(BLUE_IS_PULSE, &shark->brightness_new)) + set_bit(BLUE_PULSE_LED, &shark->brightness_new); + else + set_bit(BLUE_LED, &shark->brightness_new); + set_bit(RED_LED, &shark->brightness_new); + schedule_work(&shark->led_work); +} #else static int shark_register_leds(struct shark_device *shark, struct device *dev) { @@ -274,6 +288,7 @@ static int shark_register_leds(struct shark_device *shark, struct device *dev) return 0; } static inline void shark_unregister_leds(struct shark_device *shark) { } +static inline void shark_resume_leds(struct shark_device *shark) { } #endif static void usb_shark_disconnect(struct usb_interface *intf) @@ -333,6 +348,7 @@ static int usb_shark_probe(struct usb_interface *intf, shark->tea.radio_nr = -1; shark->tea.ops = &shark_tea_ops; shark->tea.cannot_mute = true; + shark->tea.has_am = true; strlcpy(shark->tea.card, "Griffin radioSHARK", sizeof(shark->tea.card)); usb_make_path(shark->usbdev, shark->tea.bus_info, @@ -358,6 +374,27 @@ err_alloc_buffer: return retval; } +#ifdef CONFIG_PM +static int usb_shark_suspend(struct usb_interface *intf, pm_message_t message) +{ + return 0; +} + +static int usb_shark_resume(struct usb_interface *intf) +{ + struct v4l2_device *v4l2_dev = usb_get_intfdata(intf); + struct shark_device *shark = v4l2_dev_to_shark(v4l2_dev); + + mutex_lock(&shark->tea.mutex); + snd_tea575x_set_freq(&shark->tea); + mutex_unlock(&shark->tea.mutex); + + shark_resume_leds(shark); + + return 0; +} +#endif + /* Specify the bcdDevice value, as the radioSHARK and radioSHARK2 share ids */ static struct usb_device_id usb_shark_device_table[] = { { .match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION | @@ -377,5 +414,10 @@ static struct usb_driver usb_shark_driver = { .probe = usb_shark_probe, .disconnect = usb_shark_disconnect, .id_table = usb_shark_device_table, +#ifdef CONFIG_PM + .suspend = usb_shark_suspend, + .resume = usb_shark_resume, + .reset_resume = usb_shark_resume, +#endif }; module_usb_driver(usb_shark_driver); diff --git a/drivers/media/radio/radio-shark2.c b/drivers/media/radio/radio-shark2.c index 7b4efdfaae28..ef65ebbd5364 100644 --- a/drivers/media/radio/radio-shark2.c +++ b/drivers/media/radio/radio-shark2.c @@ -86,12 +86,8 @@ static int shark_write_reg(struct radio_tea5777 *tea, u64 reg) for (i = 0; i < 6; i++) shark->transfer_buffer[i + 1] = (reg >> (40 - i * 8)) & 0xff; - v4l2_dbg(1, debug, tea->v4l2_dev, - "shark2-write: %02x %02x %02x %02x %02x %02x %02x\n", - shark->transfer_buffer[0], shark->transfer_buffer[1], - shark->transfer_buffer[2], shark->transfer_buffer[3], - shark->transfer_buffer[4], shark->transfer_buffer[5], - shark->transfer_buffer[6]); + v4l2_dbg(1, debug, tea->v4l2_dev, "shark2-write: %*ph\n", + 7, shark->transfer_buffer); res = usb_interrupt_msg(shark->usbdev, usb_sndintpipe(shark->usbdev, SHARK_OUT_EP), @@ -134,9 +130,8 @@ static int shark_read_reg(struct radio_tea5777 *tea, u32 *reg_ret) for (i = 0; i < 3; i++) reg |= shark->transfer_buffer[i] << (16 - i * 8); - v4l2_dbg(1, debug, tea->v4l2_dev, "shark2-read: %02x %02x %02x\n", - shark->transfer_buffer[0], shark->transfer_buffer[1], - shark->transfer_buffer[2]); + v4l2_dbg(1, debug, tea->v4l2_dev, "shark2-read: %*ph\n", + 3, shark->transfer_buffer); *reg_ret = reg; return 0; @@ -214,6 +209,7 @@ static int shark_register_leds(struct shark_device *shark, struct device *dev) { int i, retval; + atomic_set(&shark->brightness[BLUE_LED], 127); INIT_WORK(&shark->led_work, shark_led_work); for (i = 0; i < NO_LEDS; i++) { shark->leds[i] = shark_led_templates[i]; @@ -240,6 +236,16 @@ static void shark_unregister_leds(struct shark_device *shark) cancel_work_sync(&shark->led_work); } + +static void shark_resume_leds(struct shark_device *shark) +{ + int i; + + for (i = 0; i < NO_LEDS; i++) + set_bit(i, &shark->brightness_new); + + schedule_work(&shark->led_work); +} #else static int shark_register_leds(struct shark_device *shark, struct device *dev) { @@ -248,6 +254,7 @@ static int shark_register_leds(struct shark_device *shark, struct device *dev) return 0; } static inline void shark_unregister_leds(struct shark_device *shark) { } +static inline void shark_resume_leds(struct shark_device *shark) { } #endif static void usb_shark_disconnect(struct usb_interface *intf) @@ -332,6 +339,28 @@ err_alloc_buffer: return retval; } +#ifdef CONFIG_PM +static int usb_shark_suspend(struct usb_interface *intf, pm_message_t message) +{ + return 0; +} + +static int usb_shark_resume(struct usb_interface *intf) +{ + struct v4l2_device *v4l2_dev = usb_get_intfdata(intf); + struct shark_device *shark = v4l2_dev_to_shark(v4l2_dev); + int ret; + + mutex_lock(&shark->tea.mutex); + ret = radio_tea5777_set_freq(&shark->tea); + mutex_unlock(&shark->tea.mutex); + + shark_resume_leds(shark); + + return ret; +} +#endif + /* Specify the bcdDevice value, as the radioSHARK and radioSHARK2 share ids */ static struct usb_device_id usb_shark_device_table[] = { { .match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION | @@ -351,5 +380,10 @@ static struct usb_driver usb_shark_driver = { .probe = usb_shark_probe, .disconnect = usb_shark_disconnect, .id_table = usb_shark_device_table, +#ifdef CONFIG_PM + .suspend = usb_shark_suspend, + .resume = usb_shark_resume, + .reset_resume = usb_shark_resume, +#endif }; module_usb_driver(usb_shark_driver); diff --git a/drivers/media/radio/radio-si4713.c b/drivers/media/radio/radio-si4713.c index c54210c7fef9..a082e400ed0f 100644 --- a/drivers/media/radio/radio-si4713.c +++ b/drivers/media/radio/radio-si4713.c @@ -83,7 +83,7 @@ static int radio_si4713_g_audout(struct file *file, void *priv, } static int radio_si4713_s_audout(struct file *file, void *priv, - struct v4l2_audioout *vao) + const struct v4l2_audioout *vao) { return vao->index ? -EINVAL : 0; } @@ -200,7 +200,7 @@ static int radio_si4713_g_modulator(struct file *file, void *p, } static int radio_si4713_s_modulator(struct file *file, void *p, - struct v4l2_modulator *vm) + const struct v4l2_modulator *vm) { return v4l2_device_call_until_err(get_v4l2_dev(file), 0, tuner, s_modulator, vm); @@ -268,7 +268,7 @@ static int radio_si4713_pdriver_probe(struct platform_device *pdev) goto exit; } - rsdev = kzalloc(sizeof *rsdev, GFP_KERNEL); + rsdev = devm_kzalloc(&pdev->dev, sizeof(*rsdev), GFP_KERNEL); if (!rsdev) { dev_err(&pdev->dev, "Failed to alloc video device.\n"); rval = -ENOMEM; @@ -278,7 +278,7 @@ static int radio_si4713_pdriver_probe(struct platform_device *pdev) rval = v4l2_device_register(&pdev->dev, &rsdev->v4l2_dev); if (rval) { dev_err(&pdev->dev, "Failed to register v4l2 device.\n"); - goto free_rsdev; + goto exit; } adapter = i2c_get_adapter(pdata->i2c_bus); @@ -322,8 +322,6 @@ put_adapter: i2c_put_adapter(adapter); unregister_v4l2_dev: v4l2_device_unregister(&rsdev->v4l2_dev); -free_rsdev: - kfree(rsdev); exit: return rval; } @@ -342,7 +340,6 @@ static int __exit radio_si4713_pdriver_remove(struct platform_device *pdev) video_unregister_device(rsdev->radio_dev); i2c_put_adapter(client->adapter); v4l2_device_unregister(&rsdev->v4l2_dev); - kfree(rsdev); return 0; } diff --git a/drivers/media/radio/radio-tea5764.c b/drivers/media/radio/radio-tea5764.c index 6b1fae32b483..d0c905310071 100644 --- a/drivers/media/radio/radio-tea5764.c +++ b/drivers/media/radio/radio-tea5764.c @@ -151,8 +151,11 @@ int tea5764_i2c_read(struct tea5764_device *radio) u16 *p = (u16 *) &radio->regs; struct i2c_msg msgs[1] = { - { radio->i2c_client->addr, I2C_M_RD, sizeof(radio->regs), - (void *)&radio->regs }, + { .addr = radio->i2c_client->addr, + .flags = I2C_M_RD, + .len = sizeof(radio->regs), + .buf = (void *)&radio->regs + }, }; if (i2c_transfer(radio->i2c_client->adapter, msgs, 1) != 1) return -EIO; @@ -167,7 +170,11 @@ int tea5764_i2c_write(struct tea5764_device *radio) struct tea5764_write_regs wr; struct tea5764_regs *r = &radio->regs; struct i2c_msg msgs[1] = { - { radio->i2c_client->addr, 0, sizeof(wr), (void *) &wr }, + { + .addr = radio->i2c_client->addr, + .len = sizeof(wr), + .buf = (void *)&wr + }, }; wr.intreg = r->intreg & 0xff; wr.frqset = __cpu_to_be16(r->frqset); @@ -448,7 +455,7 @@ static int vidioc_g_audio(struct file *file, void *priv, } static int vidioc_s_audio(struct file *file, void *priv, - struct v4l2_audio *a) + const struct v4l2_audio *a) { if (a->index != 0) return -EINVAL; diff --git a/drivers/media/radio/radio-tea5777.c b/drivers/media/radio/radio-tea5777.c index 5bc9fa62720b..4b5190d4fea5 100644 --- a/drivers/media/radio/radio-tea5777.c +++ b/drivers/media/radio/radio-tea5777.c @@ -33,20 +33,17 @@ #include <media/v4l2-fh.h> #include <media/v4l2-ioctl.h> #include <media/v4l2-event.h> -#include <asm/div64.h> #include "radio-tea5777.h" MODULE_AUTHOR("Hans de Goede <perex@perex.cz>"); MODULE_DESCRIPTION("Routines for control of TEA5777 Philips AM/FM radio tuner chips"); MODULE_LICENSE("GPL"); -/* Fixed FM only band for now, will implement multi-band support when the - VIDIOC_ENUM_FREQ_BANDS API is upstream */ -#define TEA5777_FM_RANGELOW (76000 * 16) -#define TEA5777_FM_RANGEHIGH (108000 * 16) - #define TEA5777_FM_IF 150 /* kHz */ -#define TEA5777_FM_FREQ_STEP 50 /* kHz */ +#define TEA5777_FM_FREQ_STEP 50 /* kHz */ + +#define TEA5777_AM_IF 21 /* kHz */ +#define TEA5777_AM_FREQ_STEP 1 /* kHz */ /* Write reg, common bits */ #define TEA5777_W_MUTE_MASK (1LL << 47) @@ -95,7 +92,7 @@ MODULE_LICENSE("GPL"); #define TEA5777_W_FM_PLL_SHIFT 32 #define TEA5777_W_FM_FREF_MASK (0x03LL << 30) #define TEA5777_W_FM_FREF_SHIFT 30 -#define TEA5777_W_FM_FREF_VALUE 0 /* 50 kHz tune steps, 150 kHz IF */ +#define TEA5777_W_FM_FREF_VALUE 0LL /* 50k steps, 150k IF */ #define TEA5777_W_FM_FORCEMONO_MASK (1LL << 15) #define TEA5777_W_FM_FORCEMONO_SHIFT 15 @@ -116,6 +113,8 @@ MODULE_LICENSE("GPL"); #define TEA5777_W_AM_AGCIF_SHIFT 32 #define TEA5777_W_AM_MWLW_MASK (1LL << 31) #define TEA5777_W_AM_MWLW_SHIFT 31 +#define TEA5777_W_AM_LW 0LL +#define TEA5777_W_AM_MW 1LL #define TEA5777_W_AM_LNA_MASK (1LL << 30) #define TEA5777_W_AM_LNA_SHIFT 30 @@ -148,26 +147,82 @@ MODULE_LICENSE("GPL"); #define TEA5777_R_FM_PLL_MASK 0x1fff #define TEA5777_R_FM_PLL_SHIFT 0 +enum { BAND_FM, BAND_AM }; + +static const struct v4l2_frequency_band bands[] = { + { + .type = V4L2_TUNER_RADIO, + .index = 0, + .capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO | + V4L2_TUNER_CAP_FREQ_BANDS | + V4L2_TUNER_CAP_HWSEEK_BOUNDED | + V4L2_TUNER_CAP_HWSEEK_PROG_LIM, + .rangelow = 76000 * 16, + .rangehigh = 108000 * 16, + .modulation = V4L2_BAND_MODULATION_FM, + }, + { + .type = V4L2_TUNER_RADIO, + .index = 1, + .capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_FREQ_BANDS | + V4L2_TUNER_CAP_HWSEEK_BOUNDED | + V4L2_TUNER_CAP_HWSEEK_PROG_LIM, + .rangelow = 530 * 16, + .rangehigh = 1710 * 16, + .modulation = V4L2_BAND_MODULATION_AM, + }, +}; + static u32 tea5777_freq_to_v4l2_freq(struct radio_tea5777 *tea, u32 freq) { - return (freq * TEA5777_FM_FREQ_STEP + TEA5777_FM_IF) * 16; + switch (tea->band) { + case BAND_FM: + return (freq * TEA5777_FM_FREQ_STEP + TEA5777_FM_IF) * 16; + case BAND_AM: + return (freq * TEA5777_AM_FREQ_STEP + TEA5777_AM_IF) * 16; + } + return 0; /* Never reached */ } -static int radio_tea5777_set_freq(struct radio_tea5777 *tea) +int radio_tea5777_set_freq(struct radio_tea5777 *tea) { - u64 freq; + u32 freq; int res; - freq = clamp_t(u32, tea->freq, - TEA5777_FM_RANGELOW, TEA5777_FM_RANGEHIGH) + 8; - do_div(freq, 16); /* to kHz */ - - freq -= TEA5777_FM_IF; - do_div(freq, TEA5777_FM_FREQ_STEP); - - tea->write_reg &= ~(TEA5777_W_FM_PLL_MASK | TEA5777_W_FM_FREF_MASK); - tea->write_reg |= freq << TEA5777_W_FM_PLL_SHIFT; - tea->write_reg |= TEA5777_W_FM_FREF_VALUE << TEA5777_W_FM_FREF_SHIFT; + freq = clamp(tea->freq, bands[tea->band].rangelow, + bands[tea->band].rangehigh); + freq = (freq + 8) / 16; /* to kHz */ + + switch (tea->band) { + case BAND_FM: + tea->write_reg &= ~TEA5777_W_AM_FM_MASK; + freq = (freq - TEA5777_FM_IF) / TEA5777_FM_FREQ_STEP; + tea->write_reg &= ~TEA5777_W_FM_PLL_MASK; + tea->write_reg |= (u64)freq << TEA5777_W_FM_PLL_SHIFT; + tea->write_reg &= ~TEA5777_W_FM_FREF_MASK; + tea->write_reg |= TEA5777_W_FM_FREF_VALUE << + TEA5777_W_FM_FREF_SHIFT; + tea->write_reg &= ~TEA5777_W_FM_FORCEMONO_MASK; + if (tea->audmode == V4L2_TUNER_MODE_MONO) + tea->write_reg |= 1LL << TEA5777_W_FM_FORCEMONO_SHIFT; + break; + case BAND_AM: + tea->write_reg &= ~TEA5777_W_AM_FM_MASK; + tea->write_reg |= (1LL << TEA5777_W_AM_FM_SHIFT); + freq = (freq - TEA5777_AM_IF) / TEA5777_AM_FREQ_STEP; + tea->write_reg &= ~TEA5777_W_AM_PLL_MASK; + tea->write_reg |= (u64)freq << TEA5777_W_AM_PLL_SHIFT; + tea->write_reg &= ~TEA5777_W_AM_AGCRF_MASK; + tea->write_reg &= ~TEA5777_W_AM_AGCRF_MASK; + tea->write_reg &= ~TEA5777_W_AM_MWLW_MASK; + tea->write_reg |= TEA5777_W_AM_MW << TEA5777_W_AM_MWLW_SHIFT; + tea->write_reg &= ~TEA5777_W_AM_LNA_MASK; + tea->write_reg |= 1LL << TEA5777_W_AM_LNA_SHIFT; + tea->write_reg &= ~TEA5777_W_AM_PEAK_MASK; + tea->write_reg |= 1LL << TEA5777_W_AM_PEAK_SHIFT; + tea->write_reg &= ~TEA5777_W_AM_CALLIGN_MASK; + break; + } res = tea->ops->write_reg(tea, tea->write_reg); if (res) @@ -225,6 +280,19 @@ static int vidioc_querycap(struct file *file, void *priv, return 0; } +static int vidioc_enum_freq_bands(struct file *file, void *priv, + struct v4l2_frequency_band *band) +{ + struct radio_tea5777 *tea = video_drvdata(file); + + if (band->tuner != 0 || band->index >= ARRAY_SIZE(bands) || + (!tea->has_am && band->index == BAND_AM)) + return -EINVAL; + + *band = bands[band->index]; + return 0; +} + static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { @@ -245,13 +313,18 @@ static int vidioc_g_tuner(struct file *file, void *priv, strlcpy(v->name, "FM", sizeof(v->name)); v->type = V4L2_TUNER_RADIO; v->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO | - V4L2_TUNER_CAP_HWSEEK_BOUNDED; - v->rangelow = TEA5777_FM_RANGELOW; - v->rangehigh = TEA5777_FM_RANGEHIGH; - v->rxsubchans = (tea->read_reg & TEA5777_R_FM_STEREO_MASK) ? - V4L2_TUNER_SUB_STEREO : V4L2_TUNER_SUB_MONO; - v->audmode = (tea->write_reg & TEA5777_W_FM_FORCEMONO_MASK) ? - V4L2_TUNER_MODE_MONO : V4L2_TUNER_MODE_STEREO; + V4L2_TUNER_CAP_FREQ_BANDS | + V4L2_TUNER_CAP_HWSEEK_BOUNDED | + V4L2_TUNER_CAP_HWSEEK_PROG_LIM; + v->rangelow = tea->has_am ? bands[BAND_AM].rangelow : + bands[BAND_FM].rangelow; + v->rangehigh = bands[BAND_FM].rangehigh; + if (tea->band == BAND_FM && + (tea->read_reg & TEA5777_R_FM_STEREO_MASK)) + v->rxsubchans = V4L2_TUNER_SUB_STEREO; + else + v->rxsubchans = V4L2_TUNER_SUB_MONO; + v->audmode = tea->audmode; /* shift - 12 to convert 4-bits (0-15) scale to 16-bits (0-65535) */ v->signal = (tea->read_reg & TEA5777_R_LEVEL_MASK) >> (TEA5777_R_LEVEL_SHIFT - 12); @@ -266,16 +339,20 @@ static int vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { struct radio_tea5777 *tea = video_drvdata(file); + u32 orig_audmode = tea->audmode; if (v->index) return -EINVAL; - if (v->audmode == V4L2_TUNER_MODE_MONO) - tea->write_reg |= TEA5777_W_FM_FORCEMONO_MASK; - else - tea->write_reg &= ~TEA5777_W_FM_FORCEMONO_MASK; + if (v->audmode > V4L2_TUNER_MODE_STEREO) + v->audmode = V4L2_TUNER_MODE_STEREO; - return radio_tea5777_set_freq(tea); + tea->audmode = v->audmode; + + if (tea->audmode != orig_audmode && tea->band == BAND_FM) + return radio_tea5777_set_freq(tea); + + return 0; } static int vidioc_g_frequency(struct file *file, void *priv, @@ -298,40 +375,74 @@ static int vidioc_s_frequency(struct file *file, void *priv, if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO) return -EINVAL; + if (tea->has_am && f->frequency < (20000 * 16)) + tea->band = BAND_AM; + else + tea->band = BAND_FM; + tea->freq = f->frequency; return radio_tea5777_set_freq(tea); } static int vidioc_s_hw_freq_seek(struct file *file, void *fh, - struct v4l2_hw_freq_seek *a) + const struct v4l2_hw_freq_seek *a) { struct radio_tea5777 *tea = video_drvdata(file); - u32 orig_freq = tea->freq; unsigned long timeout; - int res, spacing = 200 * 16; /* 200 kHz */ - /* These are fixed *for now* */ - const u32 seek_rangelow = TEA5777_FM_RANGELOW; - const u32 seek_rangehigh = TEA5777_FM_RANGEHIGH; + u32 rangelow = a->rangelow; + u32 rangehigh = a->rangehigh; + int i, res, spacing; + u32 orig_freq; if (a->tuner || a->wrap_around) return -EINVAL; + if (file->f_flags & O_NONBLOCK) + return -EWOULDBLOCK; + + if (rangelow || rangehigh) { + for (i = 0; i < ARRAY_SIZE(bands); i++) { + if (i == BAND_AM && !tea->has_am) + continue; + if (bands[i].rangelow >= rangelow && + bands[i].rangehigh <= rangehigh) + break; + } + if (i == ARRAY_SIZE(bands)) + return -EINVAL; /* No matching band found */ + + tea->band = i; + if (tea->freq < rangelow || tea->freq > rangehigh) { + tea->freq = clamp(tea->freq, rangelow, + rangehigh); + res = radio_tea5777_set_freq(tea); + if (res) + return res; + } + } else { + rangelow = bands[tea->band].rangelow; + rangehigh = bands[tea->band].rangehigh; + } + + spacing = (tea->band == BAND_AM) ? (5 * 16) : (200 * 16); /* kHz */ + orig_freq = tea->freq; + tea->write_reg |= TEA5777_W_PROGBLIM_MASK; - if (seek_rangelow != tea->seek_rangelow) { + if (tea->seek_rangelow != rangelow) { tea->write_reg &= ~TEA5777_W_UPDWN_MASK; - tea->freq = seek_rangelow; + tea->freq = rangelow; res = radio_tea5777_set_freq(tea); if (res) goto leave; - tea->seek_rangelow = tea->freq; + tea->seek_rangelow = rangelow; } - if (seek_rangehigh != tea->seek_rangehigh) { + if (tea->seek_rangehigh != rangehigh) { tea->write_reg |= TEA5777_W_UPDWN_MASK; - tea->freq = seek_rangehigh; + tea->freq = rangehigh; res = radio_tea5777_set_freq(tea); if (res) goto leave; - tea->seek_rangehigh = tea->freq; + tea->seek_rangehigh = rangehigh; } tea->write_reg &= ~TEA5777_W_PROGBLIM_MASK; @@ -419,6 +530,7 @@ static const struct v4l2_ioctl_ops tea575x_ioctl_ops = { .vidioc_g_frequency = vidioc_g_frequency, .vidioc_s_frequency = vidioc_s_frequency, .vidioc_s_hw_freq_seek = vidioc_s_hw_freq_seek, + .vidioc_enum_freq_bands = vidioc_enum_freq_bands, .vidioc_log_status = v4l2_ctrl_log_status, .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, .vidioc_unsubscribe_event = v4l2_event_unsubscribe, @@ -441,8 +553,9 @@ int radio_tea5777_init(struct radio_tea5777 *tea, struct module *owner) (1LL << TEA5777_W_IFW_SHIFT) | (1LL << TEA5777_W_INTEXT_SHIFT) | (1LL << TEA5777_W_CHP0_SHIFT) | - (2LL << TEA5777_W_SLEV_SHIFT); + (1LL << TEA5777_W_SLEV_SHIFT); tea->freq = 90500 * 16; /* 90.5Mhz default */ + tea->audmode = V4L2_TUNER_MODE_STEREO; res = radio_tea5777_set_freq(tea); if (res) { v4l2_err(tea->v4l2_dev, "can't set initial freq (%d)\n", res); diff --git a/drivers/media/radio/radio-tea5777.h b/drivers/media/radio/radio-tea5777.h index 55cbd78df5ed..4ea43a90a151 100644 --- a/drivers/media/radio/radio-tea5777.h +++ b/drivers/media/radio/radio-tea5777.h @@ -68,7 +68,9 @@ struct radio_tea5777 { bool has_am; /* Device can tune to AM freqs */ bool write_before_read; /* must write before read quirk */ bool needs_write; /* for write before read quirk */ + u32 band; /* current band */ u32 freq; /* current frequency */ + u32 audmode; /* last set audmode */ u32 seek_rangelow; /* current hwseek limits */ u32 seek_rangehigh; u32 read_reg; @@ -83,5 +85,6 @@ struct radio_tea5777 { int radio_tea5777_init(struct radio_tea5777 *tea, struct module *owner); void radio_tea5777_exit(struct radio_tea5777 *tea); +int radio_tea5777_set_freq(struct radio_tea5777 *tea); #endif /* __RADIO_TEA5777_H */ diff --git a/drivers/media/radio/radio-timb.c b/drivers/media/radio/radio-timb.c index 7052adc0c0b0..5cf07779f4bb 100644 --- a/drivers/media/radio/radio-timb.c +++ b/drivers/media/radio/radio-timb.c @@ -85,7 +85,7 @@ static int timbradio_vidioc_g_audio(struct file *file, void *priv, } static int timbradio_vidioc_s_audio(struct file *file, void *priv, - struct v4l2_audio *a) + const struct v4l2_audio *a) { return a->index ? -EINVAL : 0; } @@ -157,7 +157,7 @@ static int __devinit timbradio_probe(struct platform_device *pdev) goto err; } - tr = kzalloc(sizeof(*tr), GFP_KERNEL); + tr = devm_kzalloc(&pdev->dev, sizeof(*tr), GFP_KERNEL); if (!tr) { err = -ENOMEM; goto err; @@ -177,7 +177,7 @@ static int __devinit timbradio_probe(struct platform_device *pdev) strlcpy(tr->v4l2_dev.name, DRIVER_NAME, sizeof(tr->v4l2_dev.name)); err = v4l2_device_register(NULL, &tr->v4l2_dev); if (err) - goto err_v4l2_dev; + goto err; tr->video_dev.v4l2_dev = &tr->v4l2_dev; @@ -195,8 +195,6 @@ static int __devinit timbradio_probe(struct platform_device *pdev) err_video_req: video_device_release_empty(&tr->video_dev); v4l2_device_unregister(&tr->v4l2_dev); -err_v4l2_dev: - kfree(tr); err: dev_err(&pdev->dev, "Failed to register: %d\n", err); @@ -212,8 +210,6 @@ static int __devexit timbradio_remove(struct platform_device *pdev) v4l2_device_unregister(&tr->v4l2_dev); - kfree(tr); - return 0; } diff --git a/drivers/media/radio/radio-wl1273.c b/drivers/media/radio/radio-wl1273.c index e8428f573ccd..9b0c9fa0beb8 100644 --- a/drivers/media/radio/radio-wl1273.c +++ b/drivers/media/radio/radio-wl1273.c @@ -1479,7 +1479,7 @@ static int wl1273_fm_vidioc_g_audio(struct file *file, void *priv, } static int wl1273_fm_vidioc_s_audio(struct file *file, void *priv, - struct v4l2_audio *audio) + const struct v4l2_audio *audio) { struct wl1273_device *radio = video_get_drvdata(video_devdata(file)); @@ -1682,7 +1682,7 @@ static int wl1273_fm_vidioc_s_frequency(struct file *file, void *priv, #define WL1273_DEFAULT_SEEK_LEVEL 7 static int wl1273_fm_vidioc_s_hw_freq_seek(struct file *file, void *priv, - struct v4l2_hw_freq_seek *seek) + const struct v4l2_hw_freq_seek *seek) { struct wl1273_device *radio = video_get_drvdata(video_devdata(file)); struct wl1273_core *core = radio->core; @@ -1693,6 +1693,9 @@ static int wl1273_fm_vidioc_s_hw_freq_seek(struct file *file, void *priv, if (seek->tuner != 0 || seek->type != V4L2_TUNER_RADIO) return -EINVAL; + if (file->f_flags & O_NONBLOCK) + return -EWOULDBLOCK; + if (mutex_lock_interruptible(&core->lock)) return -EINTR; @@ -1715,7 +1718,7 @@ out: } static int wl1273_fm_vidioc_s_modulator(struct file *file, void *priv, - struct v4l2_modulator *modulator) + const struct v4l2_modulator *modulator) { struct wl1273_device *radio = video_get_drvdata(video_devdata(file)); struct wl1273_core *core = radio->core; @@ -1983,9 +1986,6 @@ static int wl1273_fm_radio_remove(struct platform_device *pdev) v4l2_ctrl_handler_free(&radio->ctrl_handler); video_unregister_device(&radio->videodev); v4l2_device_unregister(&radio->v4l2dev); - kfree(radio->buffer); - kfree(radio->write_buf); - kfree(radio); return 0; } @@ -2005,7 +2005,7 @@ static int __devinit wl1273_fm_radio_probe(struct platform_device *pdev) goto pdata_err; } - radio = kzalloc(sizeof(*radio), GFP_KERNEL); + radio = devm_kzalloc(&pdev->dev, sizeof(*radio), GFP_KERNEL); if (!radio) { r = -ENOMEM; goto pdata_err; @@ -2013,11 +2013,11 @@ static int __devinit wl1273_fm_radio_probe(struct platform_device *pdev) /* RDS buffer allocation */ radio->buf_size = rds_buf * RDS_BLOCK_SIZE; - radio->buffer = kmalloc(radio->buf_size, GFP_KERNEL); + radio->buffer = devm_kzalloc(&pdev->dev, radio->buf_size, GFP_KERNEL); if (!radio->buffer) { pr_err("Cannot allocate memory for RDS buffer.\n"); r = -ENOMEM; - goto err_kmalloc; + goto pdata_err; } radio->core = *core; @@ -2043,7 +2043,7 @@ static int __devinit wl1273_fm_radio_probe(struct platform_device *pdev) if (r) { dev_err(radio->dev, WL1273_FM_DRIVER_NAME ": Cannot get platform data\n"); - goto err_resources; + goto pdata_err; } dev_dbg(radio->dev, "irq: %d\n", radio->core->client->irq); @@ -2061,13 +2061,13 @@ static int __devinit wl1273_fm_radio_probe(struct platform_device *pdev) dev_err(radio->dev, WL1273_FM_DRIVER_NAME ": Core WL1273 IRQ" " not configured"); r = -EINVAL; - goto err_resources; + goto pdata_err; } init_completion(&radio->busy); init_waitqueue_head(&radio->read_queue); - radio->write_buf = kmalloc(256, GFP_KERNEL); + radio->write_buf = devm_kzalloc(&pdev->dev, 256, GFP_KERNEL); if (!radio->write_buf) { r = -ENOMEM; goto write_buf_err; @@ -2080,7 +2080,7 @@ static int __devinit wl1273_fm_radio_probe(struct platform_device *pdev) r = v4l2_device_register(&pdev->dev, &radio->v4l2dev); if (r) { dev_err(&pdev->dev, "Cannot register v4l2_device.\n"); - goto device_register_err; + goto write_buf_err; } /* V4L2 configuration */ @@ -2135,16 +2135,10 @@ static int __devinit wl1273_fm_radio_probe(struct platform_device *pdev) handler_init_err: v4l2_ctrl_handler_free(&radio->ctrl_handler); v4l2_device_unregister(&radio->v4l2dev); -device_register_err: - kfree(radio->write_buf); write_buf_err: free_irq(radio->core->client->irq, radio); err_request_irq: radio->core->pdata->free_resources(); -err_resources: - kfree(radio->buffer); -err_kmalloc: - kfree(radio); pdata_err: return r; } diff --git a/drivers/media/radio/saa7706h.c b/drivers/media/radio/saa7706h.c index bb953ef75f61..54db36ccb9ee 100644 --- a/drivers/media/radio/saa7706h.c +++ b/drivers/media/radio/saa7706h.c @@ -199,8 +199,19 @@ static int saa7706h_get_reg16(struct v4l2_subdev *sd, u16 reg) u8 buf[2]; int err; u8 regaddr[] = {reg >> 8, reg}; - struct i2c_msg msg[] = { {client->addr, 0, sizeof(regaddr), regaddr}, - {client->addr, I2C_M_RD, sizeof(buf), buf} }; + struct i2c_msg msg[] = { + { + .addr = client->addr, + .len = sizeof(regaddr), + .buf = regaddr + }, + { + .addr = client->addr, + .flags = I2C_M_RD, + .len = sizeof(buf), + .buf = buf + } + }; err = saa7706h_i2c_transfer(client, msg, ARRAY_SIZE(msg)); if (err) diff --git a/drivers/media/radio/si470x/radio-si470x-common.c b/drivers/media/radio/si470x/radio-si470x-common.c index 9bb65e170d99..18989388ddc1 100644 --- a/drivers/media/radio/si470x/radio-si470x-common.c +++ b/drivers/media/radio/si470x/radio-si470x-common.c @@ -296,7 +296,7 @@ int si470x_set_freq(struct si470x_device *radio, unsigned int freq) * si470x_set_seek - set seek */ static int si470x_set_seek(struct si470x_device *radio, - struct v4l2_hw_freq_seek *seek) + const struct v4l2_hw_freq_seek *seek) { int band, retval; unsigned int freq; @@ -701,13 +701,16 @@ static int si470x_vidioc_s_frequency(struct file *file, void *priv, * si470x_vidioc_s_hw_freq_seek - set hardware frequency seek */ static int si470x_vidioc_s_hw_freq_seek(struct file *file, void *priv, - struct v4l2_hw_freq_seek *seek) + const struct v4l2_hw_freq_seek *seek) { struct si470x_device *radio = video_drvdata(file); if (seek->tuner != 0) return -EINVAL; + if (file->f_flags & O_NONBLOCK) + return -EWOULDBLOCK; + return si470x_set_seek(radio, seek); } diff --git a/drivers/media/radio/si470x/radio-si470x-i2c.c b/drivers/media/radio/si470x/radio-si470x-i2c.c index f867f04cccc9..e5024cfd27a7 100644 --- a/drivers/media/radio/si470x/radio-si470x-i2c.c +++ b/drivers/media/radio/si470x/radio-si470x-i2c.c @@ -98,8 +98,12 @@ int si470x_get_register(struct si470x_device *radio, int regnr) { u16 buf[READ_REG_NUM]; struct i2c_msg msgs[1] = { - { radio->client->addr, I2C_M_RD, sizeof(u16) * READ_REG_NUM, - (void *)buf }, + { + .addr = radio->client->addr, + .flags = I2C_M_RD, + .len = sizeof(u16) * READ_REG_NUM, + .buf = (void *)buf + }, }; if (i2c_transfer(radio->client->adapter, msgs, 1) != 1) @@ -119,8 +123,11 @@ int si470x_set_register(struct si470x_device *radio, int regnr) int i; u16 buf[WRITE_REG_NUM]; struct i2c_msg msgs[1] = { - { radio->client->addr, 0, sizeof(u16) * WRITE_REG_NUM, - (void *)buf }, + { + .addr = radio->client->addr, + .len = sizeof(u16) * WRITE_REG_NUM, + .buf = (void *)buf + }, }; for (i = 0; i < WRITE_REG_NUM; i++) @@ -146,8 +153,12 @@ static int si470x_get_all_registers(struct si470x_device *radio) int i; u16 buf[READ_REG_NUM]; struct i2c_msg msgs[1] = { - { radio->client->addr, I2C_M_RD, sizeof(u16) * READ_REG_NUM, - (void *)buf }, + { + .addr = radio->client->addr, + .flags = I2C_M_RD, + .len = sizeof(u16) * READ_REG_NUM, + .buf = (void *)buf + }, }; if (i2c_transfer(radio->client->adapter, msgs, 1) != 1) diff --git a/drivers/media/radio/si4713-i2c.c b/drivers/media/radio/si4713-i2c.c index b898c8925ab7..a9e6d17015ef 100644 --- a/drivers/media/radio/si4713-i2c.c +++ b/drivers/media/radio/si4713-i2c.c @@ -1213,7 +1213,7 @@ exit: } static int si4713_s_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *f); -static int si4713_s_modulator(struct v4l2_subdev *sd, struct v4l2_modulator *); +static int si4713_s_modulator(struct v4l2_subdev *sd, const struct v4l2_modulator *); /* * si4713_setup - Sets the device up with current configuration. * @sdev: si4713_device structure for the device we are communicating @@ -1873,7 +1873,7 @@ exit: } /* si4713_s_modulator - set modulator attributes */ -static int si4713_s_modulator(struct v4l2_subdev *sd, struct v4l2_modulator *vm) +static int si4713_s_modulator(struct v4l2_subdev *sd, const struct v4l2_modulator *vm) { struct si4713_device *sdev = to_si4713_device(sd); int rval = 0; diff --git a/drivers/media/radio/wl128x/fmdrv_v4l2.c b/drivers/media/radio/wl128x/fmdrv_v4l2.c index 49a11ec1f449..048de4536036 100644 --- a/drivers/media/radio/wl128x/fmdrv_v4l2.c +++ b/drivers/media/radio/wl128x/fmdrv_v4l2.c @@ -56,23 +56,29 @@ static ssize_t fm_v4l2_fops_read(struct file *file, char __user * buf, return -EIO; } - /* Turn on RDS mode , if it is disabled */ + if (mutex_lock_interruptible(&fmdev->mutex)) + return -ERESTARTSYS; + + /* Turn on RDS mode if it is disabled */ ret = fm_rx_get_rds_mode(fmdev, &rds_mode); if (ret < 0) { fmerr("Unable to read current rds mode\n"); - return ret; + goto read_unlock; } if (rds_mode == FM_RDS_DISABLE) { ret = fmc_set_rds_mode(fmdev, FM_RDS_ENABLE); if (ret < 0) { fmerr("Failed to enable rds mode\n"); - return ret; + goto read_unlock; } } /* Copy RDS data from internal buffer to user buffer */ - return fmc_transfer_rds_from_internal_buff(fmdev, file, buf, count); + ret = fmc_transfer_rds_from_internal_buff(fmdev, file, buf, count); +read_unlock: + mutex_unlock(&fmdev->mutex); + return ret; } /* Write TX RDS data */ @@ -91,8 +97,11 @@ static ssize_t fm_v4l2_fops_write(struct file *file, const char __user * buf, return -EFAULT; fmdev = video_drvdata(file); + if (mutex_lock_interruptible(&fmdev->mutex)) + return -ERESTARTSYS; fm_tx_set_radio_text(fmdev, rds.text, rds.text_type); fm_tx_set_af(fmdev, rds.af_freq); + mutex_unlock(&fmdev->mutex); return sizeof(rds); } @@ -103,7 +112,9 @@ static u32 fm_v4l2_fops_poll(struct file *file, struct poll_table_struct *pts) struct fmdev *fmdev; fmdev = video_drvdata(file); + mutex_lock(&fmdev->mutex); ret = fmc_is_rds_data_available(fmdev, file, pts); + mutex_unlock(&fmdev->mutex); if (ret < 0) return POLLIN | POLLRDNORM; @@ -127,10 +138,12 @@ static int fm_v4l2_fops_open(struct file *file) fmdev = video_drvdata(file); + if (mutex_lock_interruptible(&fmdev->mutex)) + return -ERESTARTSYS; ret = fmc_prepare(fmdev); if (ret < 0) { fmerr("Unable to prepare FM CORE\n"); - return ret; + goto open_unlock; } fmdbg("Load FM RX firmware..\n"); @@ -138,10 +151,12 @@ static int fm_v4l2_fops_open(struct file *file) ret = fmc_set_mode(fmdev, FM_MODE_RX); if (ret < 0) { fmerr("Unable to load FM RX firmware\n"); - return ret; + goto open_unlock; } radio_disconnected = 1; +open_unlock: + mutex_unlock(&fmdev->mutex); return ret; } @@ -156,19 +171,22 @@ static int fm_v4l2_fops_release(struct file *file) return 0; } + mutex_lock(&fmdev->mutex); ret = fmc_set_mode(fmdev, FM_MODE_OFF); if (ret < 0) { fmerr("Unable to turn off the chip\n"); - return ret; + goto release_unlock; } ret = fmc_release(fmdev); if (ret < 0) { fmerr("FM CORE release failed\n"); - return ret; + goto release_unlock; } radio_disconnected = 0; +release_unlock: + mutex_unlock(&fmdev->mutex); return ret; } @@ -240,7 +258,7 @@ static int fm_v4l2_vidioc_g_audio(struct file *file, void *priv, } static int fm_v4l2_vidioc_s_audio(struct file *file, void *priv, - struct v4l2_audio *audio) + const struct v4l2_audio *audio) { if (audio->index != 0) return -EINVAL; @@ -385,11 +403,14 @@ static int fm_v4l2_vidioc_s_freq(struct file *file, void *priv, /* Set hardware frequency seek. If current mode is NOT RX, set it RX. */ static int fm_v4l2_vidioc_s_hw_freq_seek(struct file *file, void *priv, - struct v4l2_hw_freq_seek *seek) + const struct v4l2_hw_freq_seek *seek) { struct fmdev *fmdev = video_drvdata(file); int ret; + if (file->f_flags & O_NONBLOCK) + return -EWOULDBLOCK; + if (fmdev->curr_fmmode != FM_MODE_RX) { ret = fmc_set_mode(fmdev, FM_MODE_RX); if (ret != 0) { @@ -430,7 +451,7 @@ static int fm_v4l2_vidioc_g_modulator(struct file *file, void *priv, /* Set modulator attributes. If mode is not TX, set to TX. */ static int fm_v4l2_vidioc_s_modulator(struct file *file, void *priv, - struct v4l2_modulator *mod) + const struct v4l2_modulator *mod) { struct fmdev *fmdev = video_drvdata(file); u8 rds_mode; @@ -520,10 +541,6 @@ int fm_v4l2_init_video_device(struct fmdev *fmdev, int radio_nr) video_set_drvdata(gradio_dev, fmdev); gradio_dev->lock = &fmdev->mutex; - /* Locking in file operations other than ioctl should be done - by the driver, not the V4L2 core. - This driver needs auditing so that this flag can be removed. */ - set_bit(V4L2_FL_LOCK_ALL_FOPS, &gradio_dev->flags); /* Register with V4L2 subsystem as RADIO device */ if (video_register_device(gradio_dev, VFL_TYPE_RADIO, radio_nr)) { diff --git a/drivers/media/rc/Kconfig b/drivers/media/rc/Kconfig index 8be57634ba60..79ba242fe263 100644 --- a/drivers/media/rc/Kconfig +++ b/drivers/media/rc/Kconfig @@ -265,12 +265,40 @@ config IR_IGUANA depends on RC_CORE select USB ---help--- - Say Y here if you want to use the IgaunaWorks USB IR Transceiver. - Both infrared receive and send are supported. + Say Y here if you want to use the IguanaWorks USB IR Transceiver. + Both infrared receive and send are supported. If you want to + change the ID or the pin config, use the user space driver from + IguanaWorks. + + Only firmware 0x0205 and later is supported. To compile this driver as a module, choose M here: the module will be called iguanair. +config IR_TTUSBIR + tristate "TechnoTrend USB IR Receiver" + depends on USB_ARCH_HAS_HCD + depends on RC_CORE + select USB + select NEW_LEDS + select LEDS_CLASS + ---help--- + Say Y here if you want to use the TechnoTrend USB IR Receiver. The + driver can control the led. + + To compile this driver as a module, choose M here: the module will + be called ttusbir. + +config IR_RX51 + tristate "Nokia N900 IR transmitter diode" + depends on OMAP_DM_TIMER && LIRC + ---help--- + Say Y or M here if you want to enable support for the IR + transmitter diode built in the Nokia N900 (RX51) device. + + The driver uses omap DM timers for generating the carrier + wave and pulses. + config RC_LOOPBACK tristate "Remote Control Loopback Driver" depends on RC_CORE diff --git a/drivers/media/rc/Makefile b/drivers/media/rc/Makefile index f871d1986c21..56bacf07b361 100644 --- a/drivers/media/rc/Makefile +++ b/drivers/media/rc/Makefile @@ -23,8 +23,10 @@ obj-$(CONFIG_IR_FINTEK) += fintek-cir.o obj-$(CONFIG_IR_NUVOTON) += nuvoton-cir.o obj-$(CONFIG_IR_ENE) += ene_ir.o obj-$(CONFIG_IR_REDRAT3) += redrat3.o +obj-$(CONFIG_IR_RX51) += ir-rx51.o obj-$(CONFIG_IR_STREAMZAP) += streamzap.o obj-$(CONFIG_IR_WINBOND_CIR) += winbond-cir.o obj-$(CONFIG_RC_LOOPBACK) += rc-loopback.o obj-$(CONFIG_IR_GPIO_CIR) += gpio-ir-recv.o obj-$(CONFIG_IR_IGUANA) += iguanair.o +obj-$(CONFIG_IR_TTUSBIR) += ttusbir.o diff --git a/drivers/media/rc/ati_remote.c b/drivers/media/rc/ati_remote.c index 8fa72e2dacb1..49bb356ed14c 100644 --- a/drivers/media/rc/ati_remote.c +++ b/drivers/media/rc/ati_remote.c @@ -331,13 +331,9 @@ static void ati_remote_dump(struct device *dev, unsigned char *data, if (data[0] != (unsigned char)0xff && data[0] != 0x00) dev_warn(dev, "Weird byte 0x%02x\n", data[0]); } else if (len == 4) - dev_warn(dev, "Weird key %02x %02x %02x %02x\n", - data[0], data[1], data[2], data[3]); + dev_warn(dev, "Weird key %*ph\n", 4, data); else - dev_warn(dev, - "Weird data, len=%d %02x %02x %02x %02x %02x %02x ...\n", - len, data[0], data[1], data[2], data[3], data[4], - data[5]); + dev_warn(dev, "Weird data, len=%d %*ph ...\n", len, 6, data); } /* @@ -519,8 +515,7 @@ static void ati_remote_input_report(struct urb *urb) if (data[1] != ((data[2] + data[3] + 0xd5) & 0xff)) { dbginfo(&ati_remote->interface->dev, - "wrong checksum in input: %02x %02x %02x %02x\n", - data[0], data[1], data[2], data[3]); + "wrong checksum in input: %*ph\n", 4, data); return; } @@ -942,8 +937,10 @@ static int ati_remote_probe(struct usb_interface *interface, /* Set up and register mouse input device */ if (mouse) { input_dev = input_allocate_device(); - if (!input_dev) + if (!input_dev) { + err = -ENOMEM; goto fail4; + } ati_remote->idev = input_dev; ati_remote_input_init(ati_remote); diff --git a/drivers/media/rc/fintek-cir.c b/drivers/media/rc/fintek-cir.c index ab30c64f8124..52fd7696b1ba 100644 --- a/drivers/media/rc/fintek-cir.c +++ b/drivers/media/rc/fintek-cir.c @@ -295,6 +295,7 @@ static void fintek_process_rx_ir_data(struct fintek_dev *fintek) { DEFINE_IR_RAW_EVENT(rawir); u8 sample; + bool event = false; int i; for (i = 0; i < fintek->pkts; i++) { @@ -332,7 +333,9 @@ static void fintek_process_rx_ir_data(struct fintek_dev *fintek) fit_dbg("Storing %s with duration %d", rawir.pulse ? "pulse" : "space", rawir.duration); - ir_raw_event_store_with_filter(fintek->rdev, &rawir); + if (ir_raw_event_store_with_filter(fintek->rdev, + &rawir)) + event = true; break; } @@ -342,8 +345,10 @@ static void fintek_process_rx_ir_data(struct fintek_dev *fintek) fintek->pkts = 0; - fit_dbg("Calling ir_raw_event_handle"); - ir_raw_event_handle(fintek->rdev); + if (event) { + fit_dbg("Calling ir_raw_event_handle"); + ir_raw_event_handle(fintek->rdev); + } } /* copy data from hardware rx register into driver buffer */ diff --git a/drivers/media/rc/iguanair.c b/drivers/media/rc/iguanair.c index 5e2eaf8ba73e..1e4c68a5cecf 100644 --- a/drivers/media/rc/iguanair.c +++ b/drivers/media/rc/iguanair.c @@ -35,9 +35,9 @@ struct iguanair { struct device *dev; struct usb_device *udev; - int pipe_in, pipe_out; + int pipe_out; + uint16_t version; uint8_t bufsize; - uint8_t version[2]; struct mutex lock; @@ -75,6 +75,7 @@ struct iguanair { #define MAX_PACKET_SIZE 8u #define TIMEOUT 1000 +#define RX_RESOLUTION 21333 struct packet { uint16_t start; @@ -82,11 +83,6 @@ struct packet { uint8_t cmd; }; -struct response_packet { - struct packet header; - uint8_t data[4]; -}; - struct send_packet { struct packet header; uint8_t length; @@ -100,6 +96,25 @@ static void process_ir_data(struct iguanair *ir, unsigned len) { if (len >= 4 && ir->buf_in[0] == 0 && ir->buf_in[1] == 0) { switch (ir->buf_in[3]) { + case CMD_GET_VERSION: + if (len == 6) { + ir->version = (ir->buf_in[5] << 8) | + ir->buf_in[4]; + complete(&ir->completion); + } + break; + case CMD_GET_BUFSIZE: + if (len >= 5) { + ir->bufsize = ir->buf_in[4]; + complete(&ir->completion); + } + break; + case CMD_GET_FEATURES: + if (len > 5) { + ir->cycle_overhead = ir->buf_in[5]; + complete(&ir->completion); + } + break; case CMD_TX_OVERFLOW: ir->tx_overflow = true; case CMD_RECEIVER_OFF: @@ -109,6 +124,7 @@ static void process_ir_data(struct iguanair *ir, unsigned len) break; case CMD_RX_OVERFLOW: dev_warn(ir->dev, "receive overflow\n"); + ir_raw_event_reset(ir->rc); break; default: dev_warn(ir->dev, "control code %02x received\n", @@ -118,6 +134,7 @@ static void process_ir_data(struct iguanair *ir, unsigned len) } else if (len >= 7) { DEFINE_IR_RAW_EVENT(rawir); unsigned i; + bool event = false; init_ir_raw_event(&rawir); @@ -128,19 +145,22 @@ static void process_ir_data(struct iguanair *ir, unsigned len) } else { rawir.pulse = (ir->buf_in[i] & 0x80) == 0; rawir.duration = ((ir->buf_in[i] & 0x7f) + 1) * - 21330; + RX_RESOLUTION; } - ir_raw_event_store_with_filter(ir->rc, &rawir); + if (ir_raw_event_store_with_filter(ir->rc, &rawir)) + event = true; } - ir_raw_event_handle(ir->rc); + if (event) + ir_raw_event_handle(ir->rc); } } static void iguanair_rx(struct urb *urb) { struct iguanair *ir; + int rc; if (!urb) return; @@ -166,34 +186,27 @@ static void iguanair_rx(struct urb *urb) break; } - usb_submit_urb(urb, GFP_ATOMIC); + rc = usb_submit_urb(urb, GFP_ATOMIC); + if (rc && rc != -ENODEV) + dev_warn(ir->dev, "failed to resubmit urb: %d\n", rc); } -static int iguanair_send(struct iguanair *ir, void *data, unsigned size, - struct response_packet *response, unsigned *res_len) +static int iguanair_send(struct iguanair *ir, void *data, unsigned size) { - unsigned offset, len; int rc, transferred; - for (offset = 0; offset < size; offset += MAX_PACKET_SIZE) { - len = min(size - offset, MAX_PACKET_SIZE); - - if (ir->tx_overflow) - return -EOVERFLOW; + INIT_COMPLETION(ir->completion); - rc = usb_interrupt_msg(ir->udev, ir->pipe_out, data + offset, - len, &transferred, TIMEOUT); - if (rc) - return rc; + rc = usb_interrupt_msg(ir->udev, ir->pipe_out, data, size, + &transferred, TIMEOUT); + if (rc) + return rc; - if (transferred != len) - return -EIO; - } + if (transferred != size) + return -EIO; - if (response) { - rc = usb_interrupt_msg(ir->udev, ir->pipe_in, response, - sizeof(*response), res_len, TIMEOUT); - } + if (wait_for_completion_timeout(&ir->completion, TIMEOUT) == 0) + return -ETIMEDOUT; return rc; } @@ -201,66 +214,43 @@ static int iguanair_send(struct iguanair *ir, void *data, unsigned size, static int iguanair_get_features(struct iguanair *ir) { struct packet packet; - struct response_packet response; - int rc, len; + int rc; packet.start = 0; packet.direction = DIR_OUT; packet.cmd = CMD_GET_VERSION; - rc = iguanair_send(ir, &packet, sizeof(packet), &response, &len); + rc = iguanair_send(ir, &packet, sizeof(packet)); if (rc) { dev_info(ir->dev, "failed to get version\n"); goto out; } - if (len != 6) { - dev_info(ir->dev, "failed to get version\n"); - rc = -EIO; + if (ir->version < 0x205) { + dev_err(ir->dev, "firmware 0x%04x is too old\n", ir->version); + rc = -ENODEV; goto out; } - ir->version[0] = response.data[0]; - ir->version[1] = response.data[1]; ir->bufsize = 150; ir->cycle_overhead = 65; packet.cmd = CMD_GET_BUFSIZE; - rc = iguanair_send(ir, &packet, sizeof(packet), &response, &len); + rc = iguanair_send(ir, &packet, sizeof(packet)); if (rc) { dev_info(ir->dev, "failed to get buffer size\n"); goto out; } - if (len != 5) { - dev_info(ir->dev, "failed to get buffer size\n"); - rc = -EIO; - goto out; - } - - ir->bufsize = response.data[0]; - - if (ir->version[0] == 0 || ir->version[1] == 0) - goto out; - packet.cmd = CMD_GET_FEATURES; - rc = iguanair_send(ir, &packet, sizeof(packet), &response, &len); + rc = iguanair_send(ir, &packet, sizeof(packet)); if (rc) { dev_info(ir->dev, "failed to get features\n"); goto out; } - if (len < 5) { - dev_info(ir->dev, "failed to get features\n"); - rc = -EIO; - goto out; - } - - if (len > 5 && ir->version[0] >= 4) - ir->cycle_overhead = response.data[1]; - out: return rc; } @@ -269,17 +259,11 @@ static int iguanair_receiver(struct iguanair *ir, bool enable) { struct packet packet = { 0, DIR_OUT, enable ? CMD_RECEIVER_ON : CMD_RECEIVER_OFF }; - int rc; - - INIT_COMPLETION(ir->completion); - rc = iguanair_send(ir, &packet, sizeof(packet), NULL, NULL); - if (rc) - return rc; - - wait_for_completion_timeout(&ir->completion, TIMEOUT); + if (enable) + ir_raw_event_reset(ir->rc); - return 0; + return iguanair_send(ir, &packet, sizeof(packet)); } /* @@ -350,26 +334,38 @@ static int iguanair_set_tx_mask(struct rc_dev *dev, uint32_t mask) static int iguanair_tx(struct rc_dev *dev, unsigned *txbuf, unsigned count) { struct iguanair *ir = dev->priv; - uint8_t space, *payload; - unsigned i, size, rc; + uint8_t space; + unsigned i, size, periods, bytes; + int rc; struct send_packet *packet; mutex_lock(&ir->lock); - /* convert from us to carrier periods */ - for (i = size = 0; i < count; i++) { - txbuf[i] = DIV_ROUND_CLOSEST(txbuf[i] * ir->carrier, 1000000); - size += (txbuf[i] + 126) / 127; - } - - packet = kmalloc(sizeof(*packet) + size, GFP_KERNEL); + packet = kmalloc(sizeof(*packet) + ir->bufsize, GFP_KERNEL); if (!packet) { rc = -ENOMEM; goto out; } - if (size > ir->bufsize) { - rc = -E2BIG; + /* convert from us to carrier periods */ + for (i = space = size = 0; i < count; i++) { + periods = DIV_ROUND_CLOSEST(txbuf[i] * ir->carrier, 1000000); + bytes = DIV_ROUND_UP(periods, 127); + if (size + bytes > ir->bufsize) { + count = i; + break; + } + while (periods > 127) { + packet->payload[size++] = 127 | space; + periods -= 127; + } + + packet->payload[size++] = periods | space; + space ^= 0x80; + } + + if (count == 0) { + rc = -EINVAL; goto out; } @@ -381,21 +377,6 @@ static int iguanair_tx(struct rc_dev *dev, unsigned *txbuf, unsigned count) packet->busy7 = ir->busy7; packet->busy4 = ir->busy4; - space = 0; - payload = packet->payload; - - for (i = 0; i < count; i++) { - unsigned periods = txbuf[i]; - - while (periods > 127) { - *payload++ = 127 | space; - periods -= 127; - } - - *payload++ = periods | space; - space ^= 0x80; - } - if (ir->receiver_on) { rc = iguanair_receiver(ir, false); if (rc) { @@ -406,17 +387,10 @@ static int iguanair_tx(struct rc_dev *dev, unsigned *txbuf, unsigned count) ir->tx_overflow = false; - INIT_COMPLETION(ir->completion); + rc = iguanair_send(ir, packet, size + 8); - rc = iguanair_send(ir, packet, size + 8, NULL, NULL); - - if (rc == 0) { - wait_for_completion_timeout(&ir->completion, TIMEOUT); - if (ir->tx_overflow) - rc = -EOVERFLOW; - } - - ir->tx_overflow = false; + if (rc == 0 && ir->tx_overflow) + rc = -EOVERFLOW; if (ir->receiver_on) { if (iguanair_receiver(ir, true)) @@ -424,10 +398,10 @@ static int iguanair_tx(struct rc_dev *dev, unsigned *txbuf, unsigned count) } out: - mutex_unlock(&ir->lock); kfree(packet); + mutex_unlock(&ir->lock); - return rc; + return rc ? rc : count; } static int iguanair_open(struct rc_dev *rdev) @@ -437,8 +411,6 @@ static int iguanair_open(struct rc_dev *rdev) mutex_lock(&ir->lock); - usb_submit_urb(ir->urb_in, GFP_KERNEL); - BUG_ON(ir->receiver_on); rc = iguanair_receiver(ir, true); @@ -459,11 +431,9 @@ static void iguanair_close(struct rc_dev *rdev) rc = iguanair_receiver(ir, false); ir->receiver_on = false; - if (rc) + if (rc && rc != -ENODEV) dev_warn(ir->dev, "failed to disable receiver: %d\n", rc); - usb_kill_urb(ir->urb_in); - mutex_unlock(&ir->lock); } @@ -473,22 +443,22 @@ static int __devinit iguanair_probe(struct usb_interface *intf, struct usb_device *udev = interface_to_usbdev(intf); struct iguanair *ir; struct rc_dev *rc; - int ret; + int ret, pipein; struct usb_host_interface *idesc; ir = kzalloc(sizeof(*ir), GFP_KERNEL); rc = rc_allocate_device(); if (!ir || !rc) { - ret = ENOMEM; + ret = -ENOMEM; goto out; } - ir->buf_in = usb_alloc_coherent(udev, MAX_PACKET_SIZE, GFP_ATOMIC, + ir->buf_in = usb_alloc_coherent(udev, MAX_PACKET_SIZE, GFP_KERNEL, &ir->dma_in); ir->urb_in = usb_alloc_urb(0, GFP_KERNEL); if (!ir->buf_in || !ir->urb_in) { - ret = ENOMEM; + ret = -ENOMEM; goto out; } @@ -502,28 +472,29 @@ static int __devinit iguanair_probe(struct usb_interface *intf, ir->rc = rc; ir->dev = &intf->dev; ir->udev = udev; - ir->pipe_in = usb_rcvintpipe(udev, - idesc->endpoint[0].desc.bEndpointAddress); ir->pipe_out = usb_sndintpipe(udev, idesc->endpoint[1].desc.bEndpointAddress); mutex_init(&ir->lock); init_completion(&ir->completion); - ret = iguanair_get_features(ir); + pipein = usb_rcvintpipe(udev, idesc->endpoint[0].desc.bEndpointAddress); + usb_fill_int_urb(ir->urb_in, udev, pipein, ir->buf_in, MAX_PACKET_SIZE, + iguanair_rx, ir, 1); + ir->urb_in->transfer_dma = ir->dma_in; + ir->urb_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; + + ret = usb_submit_urb(ir->urb_in, GFP_KERNEL); if (ret) { - dev_warn(&intf->dev, "failed to get device features"); + dev_warn(&intf->dev, "failed to submit urb: %d\n", ret); goto out; } - usb_fill_int_urb(ir->urb_in, ir->udev, ir->pipe_in, ir->buf_in, - MAX_PACKET_SIZE, iguanair_rx, ir, - idesc->endpoint[0].desc.bInterval); - ir->urb_in->transfer_dma = ir->dma_in; - ir->urb_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; + ret = iguanair_get_features(ir); + if (ret) + goto out2; snprintf(ir->name, sizeof(ir->name), - "IguanaWorks USB IR Transceiver version %d.%d", - ir->version[0], ir->version[1]); + "IguanaWorks USB IR Transceiver version 0x%04x", ir->version); usb_make_path(ir->udev, ir->phys, sizeof(ir->phys)); @@ -540,21 +511,23 @@ static int __devinit iguanair_probe(struct usb_interface *intf, rc->s_tx_carrier = iguanair_set_tx_carrier; rc->tx_ir = iguanair_tx; rc->driver_name = DRIVER_NAME; - rc->map_name = RC_MAP_EMPTY; + rc->map_name = RC_MAP_RC6_MCE; + rc->timeout = MS_TO_NS(100); + rc->rx_resolution = RX_RESOLUTION; iguanair_set_tx_carrier(rc, 38000); ret = rc_register_device(rc); if (ret < 0) { dev_err(&intf->dev, "failed to register rc device %d", ret); - goto out; + goto out2; } usb_set_intfdata(intf, ir); - dev_info(&intf->dev, "Registered %s", ir->name); - return 0; +out2: + usb_kill_urb(ir->urb_in); out: if (ir) { usb_free_urb(ir->urb_in); @@ -570,12 +543,11 @@ static void __devexit iguanair_disconnect(struct usb_interface *intf) { struct iguanair *ir = usb_get_intfdata(intf); + rc_unregister_device(ir->rc); usb_set_intfdata(intf, NULL); - usb_kill_urb(ir->urb_in); usb_free_urb(ir->urb_in); usb_free_coherent(ir->udev, MAX_PACKET_SIZE, ir->buf_in, ir->dma_in); - rc_unregister_device(ir->rc); kfree(ir); } @@ -592,6 +564,8 @@ static int iguanair_suspend(struct usb_interface *intf, pm_message_t message) dev_warn(ir->dev, "failed to disable receiver for suspend\n"); } + usb_kill_urb(ir->urb_in); + mutex_unlock(&ir->lock); return rc; @@ -604,6 +578,10 @@ static int iguanair_resume(struct usb_interface *intf) mutex_lock(&ir->lock); + rc = usb_submit_urb(ir->urb_in, GFP_KERNEL); + if (rc) + dev_warn(&intf->dev, "failed to submit urb: %d\n", rc); + if (ir->receiver_on) { rc = iguanair_receiver(ir, true); if (rc) @@ -627,7 +605,8 @@ static struct usb_driver iguanair_driver = { .suspend = iguanair_suspend, .resume = iguanair_resume, .reset_resume = iguanair_resume, - .id_table = iguanair_table + .id_table = iguanair_table, + .soft_unbind = 1 /* we want to disable receiver on unbind */ }; module_usb_driver(iguanair_driver); diff --git a/drivers/media/rc/ir-lirc-codec.c b/drivers/media/rc/ir-lirc-codec.c index 5faba2a2fdd3..569124b03de3 100644 --- a/drivers/media/rc/ir-lirc-codec.c +++ b/drivers/media/rc/ir-lirc-codec.c @@ -105,8 +105,14 @@ static ssize_t ir_lirc_transmit_ir(struct file *file, const char __user *buf, struct lirc_codec *lirc; struct rc_dev *dev; unsigned int *txbuf; /* buffer with values to transmit */ - ssize_t ret = 0; + ssize_t ret = -EINVAL; size_t count; + ktime_t start; + s64 towait; + unsigned int duration = 0; /* signal duration in us */ + int i; + + start = ktime_get(); lirc = lirc_get_pdata(file); if (!lirc) @@ -129,11 +135,30 @@ static ssize_t ir_lirc_transmit_ir(struct file *file, const char __user *buf, goto out; } - if (dev->tx_ir) - ret = dev->tx_ir(dev, txbuf, count); + if (!dev->tx_ir) { + ret = -ENOSYS; + goto out; + } + + ret = dev->tx_ir(dev, txbuf, count); + if (ret < 0) + goto out; + + for (i = 0; i < ret; i++) + duration += txbuf[i]; - if (ret > 0) - ret *= sizeof(unsigned); + ret *= sizeof(unsigned int); + + /* + * The lircd gap calculation expects the write function to + * wait for the actual IR signal to be transmitted before + * returning. + */ + towait = ktime_us_delta(ktime_add_us(start, duration), ktime_get()); + if (towait > 0) { + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(usecs_to_jiffies(towait)); + } out: kfree(txbuf); diff --git a/drivers/media/rc/ir-nec-decoder.c b/drivers/media/rc/ir-nec-decoder.c index 3c9431a9f62d..2ca509e6e16b 100644 --- a/drivers/media/rc/ir-nec-decoder.c +++ b/drivers/media/rc/ir-nec-decoder.c @@ -70,7 +70,7 @@ static int ir_nec_decode(struct rc_dev *dev, struct ir_raw_event ev) if (!ev.pulse) break; - if (eq_margin(ev.duration, NEC_HEADER_PULSE, NEC_UNIT / 2)) { + if (eq_margin(ev.duration, NEC_HEADER_PULSE, NEC_UNIT * 2)) { data->is_nec_x = false; data->necx_repeat = false; } else if (eq_margin(ev.duration, NECX_HEADER_PULSE, NEC_UNIT / 2)) @@ -86,7 +86,7 @@ static int ir_nec_decode(struct rc_dev *dev, struct ir_raw_event ev) if (ev.pulse) break; - if (eq_margin(ev.duration, NEC_HEADER_SPACE, NEC_UNIT / 2)) { + if (eq_margin(ev.duration, NEC_HEADER_SPACE, NEC_UNIT)) { data->state = STATE_BIT_PULSE; return 0; } else if (eq_margin(ev.duration, NEC_REPEAT_SPACE, NEC_UNIT / 2)) { diff --git a/drivers/media/rc/ir-raw.c b/drivers/media/rc/ir-raw.c index a82025121345..97dc8d13b06b 100644 --- a/drivers/media/rc/ir-raw.c +++ b/drivers/media/rc/ir-raw.c @@ -157,7 +157,9 @@ EXPORT_SYMBOL_GPL(ir_raw_event_store_edge); * This routine (which may be called from an interrupt context) works * in similar manner to ir_raw_event_store_edge. * This routine is intended for devices with limited internal buffer - * It automerges samples of same type, and handles timeouts + * It automerges samples of same type, and handles timeouts. Returns non-zero + * if the event was added, and zero if the event was ignored due to idle + * processing. */ int ir_raw_event_store_with_filter(struct rc_dev *dev, struct ir_raw_event *ev) { @@ -184,7 +186,7 @@ int ir_raw_event_store_with_filter(struct rc_dev *dev, struct ir_raw_event *ev) dev->raw->this_ev.duration >= dev->timeout) ir_raw_event_set_idle(dev, true); - return 0; + return 1; } EXPORT_SYMBOL_GPL(ir_raw_event_store_with_filter); diff --git a/drivers/media/rc/ir-rx51.c b/drivers/media/rc/ir-rx51.c new file mode 100644 index 000000000000..546199e9ccc7 --- /dev/null +++ b/drivers/media/rc/ir-rx51.c @@ -0,0 +1,498 @@ +/* + * Copyright (C) 2008 Nokia Corporation + * + * Based on lirc_serial.c + * + * 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 + * + */ + +#include <linux/module.h> +#include <linux/interrupt.h> +#include <linux/uaccess.h> +#include <linux/platform_device.h> +#include <linux/sched.h> +#include <linux/wait.h> + +#include <plat/dmtimer.h> +#include <plat/clock.h> +#include <plat/omap-pm.h> + +#include <media/lirc.h> +#include <media/lirc_dev.h> +#include <media/ir-rx51.h> + +#define LIRC_RX51_DRIVER_FEATURES (LIRC_CAN_SET_SEND_DUTY_CYCLE | \ + LIRC_CAN_SET_SEND_CARRIER | \ + LIRC_CAN_SEND_PULSE) + +#define DRIVER_NAME "lirc_rx51" + +#define WBUF_LEN 256 + +#define TIMER_MAX_VALUE 0xffffffff + +struct lirc_rx51 { + struct omap_dm_timer *pwm_timer; + struct omap_dm_timer *pulse_timer; + struct device *dev; + struct lirc_rx51_platform_data *pdata; + wait_queue_head_t wqueue; + + unsigned long fclk_khz; + unsigned int freq; /* carrier frequency */ + unsigned int duty_cycle; /* carrier duty cycle */ + unsigned int irq_num; + unsigned int match; + int wbuf[WBUF_LEN]; + int wbuf_index; + unsigned long device_is_open; + int pwm_timer_num; +}; + +static void lirc_rx51_on(struct lirc_rx51 *lirc_rx51) +{ + omap_dm_timer_set_pwm(lirc_rx51->pwm_timer, 0, 1, + OMAP_TIMER_TRIGGER_OVERFLOW_AND_COMPARE); +} + +static void lirc_rx51_off(struct lirc_rx51 *lirc_rx51) +{ + omap_dm_timer_set_pwm(lirc_rx51->pwm_timer, 0, 1, + OMAP_TIMER_TRIGGER_NONE); +} + +static int init_timing_params(struct lirc_rx51 *lirc_rx51) +{ + u32 load, match; + + load = -(lirc_rx51->fclk_khz * 1000 / lirc_rx51->freq); + match = -(lirc_rx51->duty_cycle * -load / 100); + omap_dm_timer_set_load(lirc_rx51->pwm_timer, 1, load); + omap_dm_timer_set_match(lirc_rx51->pwm_timer, 1, match); + omap_dm_timer_write_counter(lirc_rx51->pwm_timer, TIMER_MAX_VALUE - 2); + omap_dm_timer_start(lirc_rx51->pwm_timer); + omap_dm_timer_set_int_enable(lirc_rx51->pulse_timer, 0); + omap_dm_timer_start(lirc_rx51->pulse_timer); + + lirc_rx51->match = 0; + + return 0; +} + +#define tics_after(a, b) ((long)(b) - (long)(a) < 0) + +static int pulse_timer_set_timeout(struct lirc_rx51 *lirc_rx51, int usec) +{ + int counter; + + BUG_ON(usec < 0); + + if (lirc_rx51->match == 0) + counter = omap_dm_timer_read_counter(lirc_rx51->pulse_timer); + else + counter = lirc_rx51->match; + + counter += (u32)(lirc_rx51->fclk_khz * usec / (1000)); + omap_dm_timer_set_match(lirc_rx51->pulse_timer, 1, counter); + omap_dm_timer_set_int_enable(lirc_rx51->pulse_timer, + OMAP_TIMER_INT_MATCH); + if (tics_after(omap_dm_timer_read_counter(lirc_rx51->pulse_timer), + counter)) { + return 1; + } + return 0; +} + +static irqreturn_t lirc_rx51_interrupt_handler(int irq, void *ptr) +{ + unsigned int retval; + struct lirc_rx51 *lirc_rx51 = ptr; + + retval = omap_dm_timer_read_status(lirc_rx51->pulse_timer); + if (!retval) + return IRQ_NONE; + + if (retval & ~OMAP_TIMER_INT_MATCH) + dev_err_ratelimited(lirc_rx51->dev, + ": Unexpected interrupt source: %x\n", retval); + + omap_dm_timer_write_status(lirc_rx51->pulse_timer, + OMAP_TIMER_INT_MATCH | + OMAP_TIMER_INT_OVERFLOW | + OMAP_TIMER_INT_CAPTURE); + if (lirc_rx51->wbuf_index < 0) { + dev_err_ratelimited(lirc_rx51->dev, + ": BUG wbuf_index has value of %i\n", + lirc_rx51->wbuf_index); + goto end; + } + + /* + * If we happen to hit an odd latency spike, loop through the + * pulses until we catch up. + */ + do { + if (lirc_rx51->wbuf_index >= WBUF_LEN) + goto end; + if (lirc_rx51->wbuf[lirc_rx51->wbuf_index] == -1) + goto end; + + if (lirc_rx51->wbuf_index % 2) + lirc_rx51_off(lirc_rx51); + else + lirc_rx51_on(lirc_rx51); + + retval = pulse_timer_set_timeout(lirc_rx51, + lirc_rx51->wbuf[lirc_rx51->wbuf_index]); + lirc_rx51->wbuf_index++; + + } while (retval); + + return IRQ_HANDLED; +end: + /* Stop TX here */ + lirc_rx51_off(lirc_rx51); + lirc_rx51->wbuf_index = -1; + omap_dm_timer_stop(lirc_rx51->pwm_timer); + omap_dm_timer_stop(lirc_rx51->pulse_timer); + omap_dm_timer_set_int_enable(lirc_rx51->pulse_timer, 0); + wake_up_interruptible(&lirc_rx51->wqueue); + + return IRQ_HANDLED; +} + +static int lirc_rx51_init_port(struct lirc_rx51 *lirc_rx51) +{ + struct clk *clk_fclk; + int retval, pwm_timer = lirc_rx51->pwm_timer_num; + + lirc_rx51->pwm_timer = omap_dm_timer_request_specific(pwm_timer); + if (lirc_rx51->pwm_timer == NULL) { + dev_err(lirc_rx51->dev, ": Error requesting GPT%d timer\n", + pwm_timer); + return -EBUSY; + } + + lirc_rx51->pulse_timer = omap_dm_timer_request(); + if (lirc_rx51->pulse_timer == NULL) { + dev_err(lirc_rx51->dev, ": Error requesting pulse timer\n"); + retval = -EBUSY; + goto err1; + } + + omap_dm_timer_set_source(lirc_rx51->pwm_timer, OMAP_TIMER_SRC_SYS_CLK); + omap_dm_timer_set_source(lirc_rx51->pulse_timer, + OMAP_TIMER_SRC_SYS_CLK); + + omap_dm_timer_enable(lirc_rx51->pwm_timer); + omap_dm_timer_enable(lirc_rx51->pulse_timer); + + lirc_rx51->irq_num = omap_dm_timer_get_irq(lirc_rx51->pulse_timer); + retval = request_irq(lirc_rx51->irq_num, lirc_rx51_interrupt_handler, + IRQF_DISABLED | IRQF_SHARED, + "lirc_pulse_timer", lirc_rx51); + if (retval) { + dev_err(lirc_rx51->dev, ": Failed to request interrupt line\n"); + goto err2; + } + + clk_fclk = omap_dm_timer_get_fclk(lirc_rx51->pwm_timer); + lirc_rx51->fclk_khz = clk_fclk->rate / 1000; + + return 0; + +err2: + omap_dm_timer_free(lirc_rx51->pulse_timer); +err1: + omap_dm_timer_free(lirc_rx51->pwm_timer); + + return retval; +} + +static int lirc_rx51_free_port(struct lirc_rx51 *lirc_rx51) +{ + omap_dm_timer_set_int_enable(lirc_rx51->pulse_timer, 0); + free_irq(lirc_rx51->irq_num, lirc_rx51); + lirc_rx51_off(lirc_rx51); + omap_dm_timer_disable(lirc_rx51->pwm_timer); + omap_dm_timer_disable(lirc_rx51->pulse_timer); + omap_dm_timer_free(lirc_rx51->pwm_timer); + omap_dm_timer_free(lirc_rx51->pulse_timer); + lirc_rx51->wbuf_index = -1; + + return 0; +} + +static ssize_t lirc_rx51_write(struct file *file, const char *buf, + size_t n, loff_t *ppos) +{ + int count, i; + struct lirc_rx51 *lirc_rx51 = file->private_data; + + if (n % sizeof(int)) + return -EINVAL; + + count = n / sizeof(int); + if ((count > WBUF_LEN) || (count % 2 == 0)) + return -EINVAL; + + /* Wait any pending transfers to finish */ + wait_event_interruptible(lirc_rx51->wqueue, lirc_rx51->wbuf_index < 0); + + if (copy_from_user(lirc_rx51->wbuf, buf, n)) + return -EFAULT; + + /* Sanity check the input pulses */ + for (i = 0; i < count; i++) + if (lirc_rx51->wbuf[i] < 0) + return -EINVAL; + + init_timing_params(lirc_rx51); + if (count < WBUF_LEN) + lirc_rx51->wbuf[count] = -1; /* Insert termination mark */ + + /* + * Adjust latency requirements so the device doesn't go in too + * deep sleep states + */ + lirc_rx51->pdata->set_max_mpu_wakeup_lat(lirc_rx51->dev, 50); + + lirc_rx51_on(lirc_rx51); + lirc_rx51->wbuf_index = 1; + pulse_timer_set_timeout(lirc_rx51, lirc_rx51->wbuf[0]); + + /* + * Don't return back to the userspace until the transfer has + * finished + */ + wait_event_interruptible(lirc_rx51->wqueue, lirc_rx51->wbuf_index < 0); + + /* We can sleep again */ + lirc_rx51->pdata->set_max_mpu_wakeup_lat(lirc_rx51->dev, -1); + + return n; +} + +static long lirc_rx51_ioctl(struct file *filep, + unsigned int cmd, unsigned long arg) +{ + int result; + unsigned long value; + unsigned int ivalue; + struct lirc_rx51 *lirc_rx51 = filep->private_data; + + switch (cmd) { + case LIRC_GET_SEND_MODE: + result = put_user(LIRC_MODE_PULSE, (unsigned long *)arg); + if (result) + return result; + break; + + case LIRC_SET_SEND_MODE: + result = get_user(value, (unsigned long *)arg); + if (result) + return result; + + /* only LIRC_MODE_PULSE supported */ + if (value != LIRC_MODE_PULSE) + return -ENOSYS; + break; + + case LIRC_GET_REC_MODE: + result = put_user(0, (unsigned long *) arg); + if (result) + return result; + break; + + case LIRC_GET_LENGTH: + return -ENOSYS; + break; + + case LIRC_SET_SEND_DUTY_CYCLE: + result = get_user(ivalue, (unsigned int *) arg); + if (result) + return result; + + if (ivalue <= 0 || ivalue > 100) { + dev_err(lirc_rx51->dev, ": invalid duty cycle %d\n", + ivalue); + return -EINVAL; + } + + lirc_rx51->duty_cycle = ivalue; + break; + + case LIRC_SET_SEND_CARRIER: + result = get_user(ivalue, (unsigned int *) arg); + if (result) + return result; + + if (ivalue > 500000 || ivalue < 20000) { + dev_err(lirc_rx51->dev, ": invalid carrier freq %d\n", + ivalue); + return -EINVAL; + } + + lirc_rx51->freq = ivalue; + break; + + case LIRC_GET_FEATURES: + result = put_user(LIRC_RX51_DRIVER_FEATURES, + (unsigned long *) arg); + if (result) + return result; + break; + + default: + return -ENOIOCTLCMD; + } + + return 0; +} + +static int lirc_rx51_open(struct inode *inode, struct file *file) +{ + struct lirc_rx51 *lirc_rx51 = lirc_get_pdata(file); + BUG_ON(!lirc_rx51); + + file->private_data = lirc_rx51; + + if (test_and_set_bit(1, &lirc_rx51->device_is_open)) + return -EBUSY; + + return lirc_rx51_init_port(lirc_rx51); +} + +static int lirc_rx51_release(struct inode *inode, struct file *file) +{ + struct lirc_rx51 *lirc_rx51 = file->private_data; + + lirc_rx51_free_port(lirc_rx51); + + clear_bit(1, &lirc_rx51->device_is_open); + + return 0; +} + +static struct lirc_rx51 lirc_rx51 = { + .freq = 38000, + .duty_cycle = 50, + .wbuf_index = -1, +}; + +static const struct file_operations lirc_fops = { + .owner = THIS_MODULE, + .write = lirc_rx51_write, + .unlocked_ioctl = lirc_rx51_ioctl, + .read = lirc_dev_fop_read, + .poll = lirc_dev_fop_poll, + .open = lirc_rx51_open, + .release = lirc_rx51_release, +}; + +static struct lirc_driver lirc_rx51_driver = { + .name = DRIVER_NAME, + .minor = -1, + .code_length = 1, + .data = &lirc_rx51, + .fops = &lirc_fops, + .owner = THIS_MODULE, +}; + +#ifdef CONFIG_PM + +static int lirc_rx51_suspend(struct platform_device *dev, pm_message_t state) +{ + /* + * In case the device is still open, do not suspend. Normally + * this should not be a problem as lircd only keeps the device + * open only for short periods of time. We also don't want to + * get involved with race conditions that might happen if we + * were in a middle of a transmit. Thus, we defer any suspend + * actions until transmit has completed. + */ + if (test_and_set_bit(1, &lirc_rx51.device_is_open)) + return -EAGAIN; + + clear_bit(1, &lirc_rx51.device_is_open); + + return 0; +} + +static int lirc_rx51_resume(struct platform_device *dev) +{ + return 0; +} + +#else + +#define lirc_rx51_suspend NULL +#define lirc_rx51_resume NULL + +#endif /* CONFIG_PM */ + +static int __devinit lirc_rx51_probe(struct platform_device *dev) +{ + lirc_rx51_driver.features = LIRC_RX51_DRIVER_FEATURES; + lirc_rx51.pdata = dev->dev.platform_data; + lirc_rx51.pwm_timer_num = lirc_rx51.pdata->pwm_timer; + lirc_rx51.dev = &dev->dev; + lirc_rx51_driver.dev = &dev->dev; + lirc_rx51_driver.minor = lirc_register_driver(&lirc_rx51_driver); + init_waitqueue_head(&lirc_rx51.wqueue); + + if (lirc_rx51_driver.minor < 0) { + dev_err(lirc_rx51.dev, ": lirc_register_driver failed: %d\n", + lirc_rx51_driver.minor); + return lirc_rx51_driver.minor; + } + dev_info(lirc_rx51.dev, "registration ok, minor: %d, pwm: %d\n", + lirc_rx51_driver.minor, lirc_rx51.pwm_timer_num); + + return 0; +} + +static int __exit lirc_rx51_remove(struct platform_device *dev) +{ + return lirc_unregister_driver(lirc_rx51_driver.minor); +} + +struct platform_driver lirc_rx51_platform_driver = { + .probe = lirc_rx51_probe, + .remove = __exit_p(lirc_rx51_remove), + .suspend = lirc_rx51_suspend, + .resume = lirc_rx51_resume, + .driver = { + .name = DRIVER_NAME, + .owner = THIS_MODULE, + }, +}; + +static int __init lirc_rx51_init(void) +{ + return platform_driver_register(&lirc_rx51_platform_driver); +} +module_init(lirc_rx51_init); + +static void __exit lirc_rx51_exit(void) +{ + platform_driver_unregister(&lirc_rx51_platform_driver); +} +module_exit(lirc_rx51_exit); + +MODULE_DESCRIPTION("LIRC TX driver for Nokia RX51"); +MODULE_AUTHOR("Nokia Corporation"); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/rc/ite-cir.c b/drivers/media/rc/ite-cir.c index 36fe5a349b95..24c77a42fc36 100644 --- a/drivers/media/rc/ite-cir.c +++ b/drivers/media/rc/ite-cir.c @@ -1473,6 +1473,7 @@ static int ite_probe(struct pnp_dev *pdev, const struct pnp_device_id rdev = rc_allocate_device(); if (!rdev) goto failure; + itdev->rdev = rdev; ret = -ENODEV; @@ -1604,7 +1605,6 @@ static int ite_probe(struct pnp_dev *pdev, const struct pnp_device_id if (ret) goto failure3; - itdev->rdev = rdev; ite_pr(KERN_NOTICE, "driver has been successfully loaded\n"); return 0; diff --git a/drivers/media/rc/keymaps/rc-tt-1500.c b/drivers/media/rc/keymaps/rc-tt-1500.c index caeff85603e3..80217ffc91db 100644 --- a/drivers/media/rc/keymaps/rc-tt-1500.c +++ b/drivers/media/rc/keymaps/rc-tt-1500.c @@ -61,7 +61,7 @@ static struct rc_map_list tt_1500_map = { .map = { .scan = tt_1500, .size = ARRAY_SIZE(tt_1500), - .rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */ + .rc_type = RC_TYPE_RC5, .name = RC_MAP_TT_1500, } }; diff --git a/drivers/media/rc/mceusb.c b/drivers/media/rc/mceusb.c index f38d9a8c6880..850547fe711c 100644 --- a/drivers/media/rc/mceusb.c +++ b/drivers/media/rc/mceusb.c @@ -627,7 +627,7 @@ static void mceusb_dev_printdata(struct mceusb_dev *ir, char *buf, break; case MCE_RSP_EQIRCFS: period = DIV_ROUND_CLOSEST( - (1 << data1 * 2) * (data2 + 1), 10); + (1U << data1 * 2) * (data2 + 1), 10); if (!period) break; carrier = (1000 * 1000) / period; @@ -791,10 +791,6 @@ static int mceusb_tx_ir(struct rc_dev *dev, unsigned *txbuf, unsigned count) int i, ret = 0; int cmdcount = 0; unsigned char *cmdbuf; /* MCE command buffer */ - long signal_duration = 0; /* Singnal length in us */ - struct timeval start_time, end_time; - - do_gettimeofday(&start_time); cmdbuf = kzalloc(sizeof(unsigned) * MCE_CMDBUF_SIZE, GFP_KERNEL); if (!cmdbuf) @@ -807,7 +803,6 @@ static int mceusb_tx_ir(struct rc_dev *dev, unsigned *txbuf, unsigned count) /* Generate mce packet data */ for (i = 0; (i < count) && (cmdcount < MCE_CMDBUF_SIZE); i++) { - signal_duration += txbuf[i]; txbuf[i] = txbuf[i] / MCE_TIME_UNIT; do { /* loop to support long pulses/spaces > 127*50us=6.35ms */ @@ -850,19 +845,6 @@ static int mceusb_tx_ir(struct rc_dev *dev, unsigned *txbuf, unsigned count) /* Transmit the command to the mce device */ mce_async_out(ir, cmdbuf, cmdcount); - /* - * The lircd gap calculation expects the write function to - * wait the time it takes for the ircommand to be sent before - * it returns. - */ - do_gettimeofday(&end_time); - signal_duration -= (end_time.tv_usec - start_time.tv_usec) + - (end_time.tv_sec - start_time.tv_sec) * 1000000; - - /* delay with the closest number of ticks */ - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(usecs_to_jiffies(signal_duration)); - out: kfree(cmdbuf); return ret ? ret : count; @@ -974,6 +956,7 @@ static void mceusb_handle_command(struct mceusb_dev *ir, int index) static void mceusb_process_ir_data(struct mceusb_dev *ir, int buf_len) { DEFINE_IR_RAW_EVENT(rawir); + bool event = false; int i = 0; /* skip meaningless 0xb1 0x60 header bytes on orig receiver */ @@ -1004,7 +987,8 @@ static void mceusb_process_ir_data(struct mceusb_dev *ir, int buf_len) rawir.pulse ? "pulse" : "space", rawir.duration); - ir_raw_event_store_with_filter(ir->rc, &rawir); + if (ir_raw_event_store_with_filter(ir->rc, &rawir)) + event = true; break; case CMD_DATA: ir->rem--; @@ -1032,8 +1016,10 @@ static void mceusb_process_ir_data(struct mceusb_dev *ir, int buf_len) if (ir->parser_state != CMD_HEADER && !ir->rem) ir->parser_state = CMD_HEADER; } - mce_dbg(ir->dev, "processed IR data, calling ir_raw_event_handle\n"); - ir_raw_event_handle(ir->rc); + if (event) { + mce_dbg(ir->dev, "processed IR data, calling ir_raw_event_handle\n"); + ir_raw_event_handle(ir->rc); + } } static void mceusb_dev_recv(struct urb *urb) diff --git a/drivers/media/rc/rc-loopback.c b/drivers/media/rc/rc-loopback.c index fae1615e0ff2..f9be68132c67 100644 --- a/drivers/media/rc/rc-loopback.c +++ b/drivers/media/rc/rc-loopback.c @@ -105,18 +105,9 @@ static int loop_tx_ir(struct rc_dev *dev, unsigned *txbuf, unsigned count) { struct loopback_dev *lodev = dev->priv; u32 rxmask; - unsigned total_duration = 0; unsigned i; DEFINE_IR_RAW_EVENT(rawir); - for (i = 0; i < count; i++) - total_duration += abs(txbuf[i]); - - if (total_duration == 0) { - dprintk("invalid tx data, total duration zero\n"); - return -EINVAL; - } - if (lodev->txcarrier < lodev->rxcarriermin || lodev->txcarrier > lodev->rxcarriermax) { dprintk("ignoring tx, carrier out of range\n"); @@ -148,9 +139,6 @@ static int loop_tx_ir(struct rc_dev *dev, unsigned *txbuf, unsigned count) ir_raw_event_handle(dev); out: - /* Lirc expects this function to take as long as the total duration */ - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(usecs_to_jiffies(total_duration)); return count; } diff --git a/drivers/media/rc/redrat3.c b/drivers/media/rc/redrat3.c index 2878b0ed9741..49731b1a9c57 100644 --- a/drivers/media/rc/redrat3.c +++ b/drivers/media/rc/redrat3.c @@ -1217,9 +1217,10 @@ static int __devinit redrat3_dev_probe(struct usb_interface *intf, rr3->carrier = 38000; rr3->rc = redrat3_init_rc_dev(rr3); - if (!rr3->rc) + if (!rr3->rc) { + retval = -ENOMEM; goto error; - + } setup_timer(&rr3->rx_timeout, redrat3_rx_timeout, (unsigned long)rr3); /* we can register the device now, as it is ready */ diff --git a/drivers/media/rc/ttusbir.c b/drivers/media/rc/ttusbir.c new file mode 100644 index 000000000000..fef05235234a --- /dev/null +++ b/drivers/media/rc/ttusbir.c @@ -0,0 +1,447 @@ +/* + * TechnoTrend USB IR Receiver + * + * Copyright (C) 2012 Sean Young <sean@mess.org> + * + * 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 + */ + +#include <linux/module.h> +#include <linux/usb.h> +#include <linux/usb/input.h> +#include <linux/slab.h> +#include <linux/leds.h> +#include <media/rc-core.h> + +#define DRIVER_NAME "ttusbir" +#define DRIVER_DESC "TechnoTrend USB IR Receiver" +/* + * The Windows driver uses 8 URBS, the original lirc drivers has a + * configurable amount (2 default, 4 max). This device generates about 125 + * messages per second (!), whether IR is idle or not. + */ +#define NUM_URBS 4 +#define NS_PER_BYTE 62500 +#define NS_PER_BIT (NS_PER_BYTE/8) + +struct ttusbir { + struct rc_dev *rc; + struct device *dev; + struct usb_device *udev; + + struct urb *urb[NUM_URBS]; + + struct led_classdev led; + struct urb *bulk_urb; + uint8_t bulk_buffer[5]; + int bulk_out_endp, iso_in_endp; + bool led_on, is_led_on; + atomic_t led_complete; + + char phys[64]; +}; + +static enum led_brightness ttusbir_brightness_get(struct led_classdev *led_dev) +{ + struct ttusbir *tt = container_of(led_dev, struct ttusbir, led); + + return tt->led_on ? LED_FULL : LED_OFF; +} + +static void ttusbir_set_led(struct ttusbir *tt) +{ + int ret; + + smp_mb(); + + if (tt->led_on != tt->is_led_on && tt->udev && + atomic_add_unless(&tt->led_complete, 1, 1)) { + tt->bulk_buffer[4] = tt->is_led_on = tt->led_on; + ret = usb_submit_urb(tt->bulk_urb, GFP_ATOMIC); + if (ret) { + dev_warn(tt->dev, "failed to submit bulk urb: %d\n", + ret); + atomic_dec(&tt->led_complete); + } + } +} + +static void ttusbir_brightness_set(struct led_classdev *led_dev, enum + led_brightness brightness) +{ + struct ttusbir *tt = container_of(led_dev, struct ttusbir, led); + + tt->led_on = brightness != LED_OFF; + + ttusbir_set_led(tt); +} + +/* + * The urb cannot be reused until the urb completes + */ +static void ttusbir_bulk_complete(struct urb *urb) +{ + struct ttusbir *tt = urb->context; + + atomic_dec(&tt->led_complete); + + switch (urb->status) { + case 0: + break; + case -ECONNRESET: + case -ENOENT: + case -ESHUTDOWN: + usb_unlink_urb(urb); + return; + case -EPIPE: + default: + dev_dbg(tt->dev, "Error: urb status = %d\n", urb->status); + break; + } + + ttusbir_set_led(tt); +} + +/* + * The data is one bit per sample, a set bit signifying silence and samples + * being MSB first. Bit 0 can contain garbage so take it to be whatever + * bit 1 is, so we don't have unexpected edges. + */ +static void ttusbir_process_ir_data(struct ttusbir *tt, uint8_t *buf) +{ + struct ir_raw_event rawir; + unsigned i, v, b; + bool event = false; + + init_ir_raw_event(&rawir); + + for (i = 0; i < 128; i++) { + v = buf[i] & 0xfe; + switch (v) { + case 0xfe: + rawir.pulse = false; + rawir.duration = NS_PER_BYTE; + if (ir_raw_event_store_with_filter(tt->rc, &rawir)) + event = true; + break; + case 0: + rawir.pulse = true; + rawir.duration = NS_PER_BYTE; + if (ir_raw_event_store_with_filter(tt->rc, &rawir)) + event = true; + break; + default: + /* one edge per byte */ + if (v & 2) { + b = ffz(v | 1); + rawir.pulse = true; + } else { + b = ffs(v) - 1; + rawir.pulse = false; + } + + rawir.duration = NS_PER_BIT * (8 - b); + if (ir_raw_event_store_with_filter(tt->rc, &rawir)) + event = true; + + rawir.pulse = !rawir.pulse; + rawir.duration = NS_PER_BIT * b; + if (ir_raw_event_store_with_filter(tt->rc, &rawir)) + event = true; + break; + } + } + + /* don't wakeup when there's nothing to do */ + if (event) + ir_raw_event_handle(tt->rc); +} + +static void ttusbir_urb_complete(struct urb *urb) +{ + struct ttusbir *tt = urb->context; + int rc; + + switch (urb->status) { + case 0: + ttusbir_process_ir_data(tt, urb->transfer_buffer); + break; + case -ECONNRESET: + case -ENOENT: + case -ESHUTDOWN: + usb_unlink_urb(urb); + return; + case -EPIPE: + default: + dev_dbg(tt->dev, "Error: urb status = %d\n", urb->status); + break; + } + + rc = usb_submit_urb(urb, GFP_ATOMIC); + if (rc && rc != -ENODEV) + dev_warn(tt->dev, "failed to resubmit urb: %d\n", rc); +} + +static int __devinit ttusbir_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + struct ttusbir *tt; + struct usb_interface_descriptor *idesc; + struct usb_endpoint_descriptor *desc; + struct rc_dev *rc; + int i, j, ret; + int altsetting = -1; + + tt = kzalloc(sizeof(*tt), GFP_KERNEL); + rc = rc_allocate_device(); + if (!tt || !rc) { + ret = -ENOMEM; + goto out; + } + + /* find the correct alt setting */ + for (i = 0; i < intf->num_altsetting && altsetting == -1; i++) { + int bulk_out_endp = -1, iso_in_endp = -1; + + idesc = &intf->altsetting[i].desc; + + for (j = 0; j < idesc->bNumEndpoints; j++) { + desc = &intf->altsetting[i].endpoint[j].desc; + if (usb_endpoint_dir_in(desc) && + usb_endpoint_xfer_isoc(desc) && + desc->wMaxPacketSize == 0x10) + iso_in_endp = j; + else if (usb_endpoint_dir_out(desc) && + usb_endpoint_xfer_bulk(desc) && + desc->wMaxPacketSize == 0x20) + bulk_out_endp = j; + + if (bulk_out_endp != -1 && iso_in_endp != -1) { + tt->bulk_out_endp = bulk_out_endp; + tt->iso_in_endp = iso_in_endp; + altsetting = i; + break; + } + } + } + + if (altsetting == -1) { + dev_err(&intf->dev, "cannot find expected altsetting\n"); + ret = -ENODEV; + goto out; + } + + tt->dev = &intf->dev; + tt->udev = interface_to_usbdev(intf); + tt->rc = rc; + + ret = usb_set_interface(tt->udev, 0, altsetting); + if (ret) + goto out; + + for (i = 0; i < NUM_URBS; i++) { + struct urb *urb = usb_alloc_urb(8, GFP_KERNEL); + void *buffer; + + if (!urb) { + ret = -ENOMEM; + goto out; + } + + urb->dev = tt->udev; + urb->context = tt; + urb->pipe = usb_rcvisocpipe(tt->udev, tt->iso_in_endp); + urb->interval = 1; + buffer = usb_alloc_coherent(tt->udev, 128, GFP_KERNEL, + &urb->transfer_dma); + if (!buffer) { + usb_free_urb(urb); + ret = -ENOMEM; + goto out; + } + urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP | URB_ISO_ASAP; + urb->transfer_buffer = buffer; + urb->complete = ttusbir_urb_complete; + urb->number_of_packets = 8; + urb->transfer_buffer_length = 128; + + for (j = 0; j < 8; j++) { + urb->iso_frame_desc[j].offset = j * 16; + urb->iso_frame_desc[j].length = 16; + } + + tt->urb[i] = urb; + } + + tt->bulk_urb = usb_alloc_urb(0, GFP_KERNEL); + if (!tt->bulk_urb) { + ret = -ENOMEM; + goto out; + } + + tt->bulk_buffer[0] = 0xaa; + tt->bulk_buffer[1] = 0x01; + tt->bulk_buffer[2] = 0x05; + tt->bulk_buffer[3] = 0x01; + + usb_fill_bulk_urb(tt->bulk_urb, tt->udev, usb_sndbulkpipe(tt->udev, + tt->bulk_out_endp), tt->bulk_buffer, sizeof(tt->bulk_buffer), + ttusbir_bulk_complete, tt); + + tt->led.name = "ttusbir:green:power"; + tt->led.brightness_set = ttusbir_brightness_set; + tt->led.brightness_get = ttusbir_brightness_get; + tt->is_led_on = tt->led_on = true; + atomic_set(&tt->led_complete, 0); + ret = led_classdev_register(&intf->dev, &tt->led); + if (ret) + goto out; + + usb_make_path(tt->udev, tt->phys, sizeof(tt->phys)); + + rc->input_name = DRIVER_DESC; + rc->input_phys = tt->phys; + usb_to_input_id(tt->udev, &rc->input_id); + rc->dev.parent = &intf->dev; + rc->driver_type = RC_DRIVER_IR_RAW; + rc->allowed_protos = RC_TYPE_ALL; + rc->priv = tt; + rc->driver_name = DRIVER_NAME; + rc->map_name = RC_MAP_TT_1500; + rc->timeout = MS_TO_NS(100); + /* + * The precision is NS_PER_BIT, but since every 8th bit can be + * overwritten with garbage the accuracy is at best 2 * NS_PER_BIT. + */ + rc->rx_resolution = NS_PER_BIT; + + ret = rc_register_device(rc); + if (ret) { + dev_err(&intf->dev, "failed to register rc device %d\n", ret); + goto out2; + } + + usb_set_intfdata(intf, tt); + + for (i = 0; i < NUM_URBS; i++) { + ret = usb_submit_urb(tt->urb[i], GFP_KERNEL); + if (ret) { + dev_err(tt->dev, "failed to submit urb %d\n", ret); + goto out3; + } + } + + return 0; +out3: + rc_unregister_device(rc); +out2: + led_classdev_unregister(&tt->led); +out: + if (tt) { + for (i = 0; i < NUM_URBS && tt->urb[i]; i++) { + struct urb *urb = tt->urb[i]; + + usb_kill_urb(urb); + usb_free_coherent(tt->udev, 128, urb->transfer_buffer, + urb->transfer_dma); + usb_free_urb(urb); + } + usb_kill_urb(tt->bulk_urb); + usb_free_urb(tt->bulk_urb); + kfree(tt); + } + rc_free_device(rc); + + return ret; +} + +static void __devexit ttusbir_disconnect(struct usb_interface *intf) +{ + struct ttusbir *tt = usb_get_intfdata(intf); + struct usb_device *udev = tt->udev; + int i; + + tt->udev = NULL; + + rc_unregister_device(tt->rc); + led_classdev_unregister(&tt->led); + for (i = 0; i < NUM_URBS; i++) { + usb_kill_urb(tt->urb[i]); + usb_free_coherent(udev, 128, tt->urb[i]->transfer_buffer, + tt->urb[i]->transfer_dma); + usb_free_urb(tt->urb[i]); + } + usb_kill_urb(tt->bulk_urb); + usb_free_urb(tt->bulk_urb); + usb_set_intfdata(intf, NULL); + kfree(tt); +} + +static int ttusbir_suspend(struct usb_interface *intf, pm_message_t message) +{ + struct ttusbir *tt = usb_get_intfdata(intf); + int i; + + for (i = 0; i < NUM_URBS; i++) + usb_kill_urb(tt->urb[i]); + + led_classdev_suspend(&tt->led); + usb_kill_urb(tt->bulk_urb); + + return 0; +} + +static int ttusbir_resume(struct usb_interface *intf) +{ + struct ttusbir *tt = usb_get_intfdata(intf); + int i, rc; + + led_classdev_resume(&tt->led); + tt->is_led_on = true; + ttusbir_set_led(tt); + + for (i = 0; i < NUM_URBS; i++) { + rc = usb_submit_urb(tt->urb[i], GFP_KERNEL); + if (rc) { + dev_warn(tt->dev, "failed to submit urb: %d\n", rc); + break; + } + } + + return rc; +} + +static const struct usb_device_id ttusbir_table[] = { + { USB_DEVICE(0x0b48, 0x2003) }, + { } +}; + +static struct usb_driver ttusbir_driver = { + .name = DRIVER_NAME, + .id_table = ttusbir_table, + .probe = ttusbir_probe, + .suspend = ttusbir_suspend, + .resume = ttusbir_resume, + .reset_resume = ttusbir_resume, + .disconnect = __devexit_p(ttusbir_disconnect) +}; + +module_usb_driver(ttusbir_driver); + +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_AUTHOR("Sean Young <sean@mess.org>"); +MODULE_LICENSE("GPL"); +MODULE_DEVICE_TABLE(usb, ttusbir_table); + diff --git a/drivers/media/rc/winbond-cir.c b/drivers/media/rc/winbond-cir.c index 54ee34872d14..30ae1f24abc3 100644 --- a/drivers/media/rc/winbond-cir.c +++ b/drivers/media/rc/winbond-cir.c @@ -180,7 +180,6 @@ enum wbcir_rxstate { enum wbcir_txstate { WBCIR_TXSTATE_INACTIVE = 0, WBCIR_TXSTATE_ACTIVE, - WBCIR_TXSTATE_DONE, WBCIR_TXSTATE_ERROR }; @@ -216,7 +215,6 @@ struct wbcir_data { u32 txlen; u32 txoff; u32 *txbuf; - wait_queue_head_t txwaitq; u8 txmask; u32 txcarrier; }; @@ -358,7 +356,7 @@ wbcir_irq_rx(struct wbcir_data *data, struct pnp_dev *device) if (data->rxstate == WBCIR_RXSTATE_ERROR) continue; rawir.pulse = irdata & 0x80 ? false : true; - rawir.duration = US_TO_NS((irdata & 0x7F) * 10); + rawir.duration = US_TO_NS(((irdata & 0x7F) + 1) * 10); ir_raw_event_store_with_filter(data->dev, &rawir); } @@ -424,11 +422,11 @@ wbcir_irq_tx(struct wbcir_data *data) if (data->txstate == WBCIR_TXSTATE_ERROR) /* Clear TX underrun bit */ outb(WBCIR_TX_UNDERRUN, data->sbase + WBCIR_REG_SP3_ASCR); - else - data->txstate = WBCIR_TXSTATE_DONE; wbcir_set_irqmask(data, WBCIR_IRQ_RX | WBCIR_IRQ_ERR); led_trigger_event(data->txtrigger, LED_OFF); - wake_up(&data->txwaitq); + kfree(data->txbuf); + data->txbuf = NULL; + data->txstate = WBCIR_TXSTATE_INACTIVE; } else if (data->txoff == data->txlen) { /* At the end of transmission, tell the hw before last byte */ outsb(data->sbase + WBCIR_REG_SP3_TXDATA, bytes, used - 1); @@ -579,43 +577,37 @@ wbcir_txmask(struct rc_dev *dev, u32 mask) } static int -wbcir_tx(struct rc_dev *dev, unsigned *buf, unsigned count) +wbcir_tx(struct rc_dev *dev, unsigned *b, unsigned count) { struct wbcir_data *data = dev->priv; + unsigned *buf; unsigned i; unsigned long flags; + buf = kmalloc(count * sizeof(*b), GFP_KERNEL); + if (!buf) + return -ENOMEM; + + /* Convert values to multiples of 10us */ + for (i = 0; i < count; i++) + buf[i] = DIV_ROUND_CLOSEST(b[i], 10); + /* Not sure if this is possible, but better safe than sorry */ spin_lock_irqsave(&data->spinlock, flags); if (data->txstate != WBCIR_TXSTATE_INACTIVE) { spin_unlock_irqrestore(&data->spinlock, flags); + kfree(buf); return -EBUSY; } - /* Convert values to multiples of 10us */ - for (i = 0; i < count; i++) - buf[i] = DIV_ROUND_CLOSEST(buf[i], 10); - /* Fill the TX fifo once, the irq handler will do the rest */ data->txbuf = buf; data->txlen = count; data->txoff = 0; wbcir_irq_tx(data); - /* Wait for the TX to complete */ - while (data->txstate == WBCIR_TXSTATE_ACTIVE) { - spin_unlock_irqrestore(&data->spinlock, flags); - wait_event(data->txwaitq, data->txstate != WBCIR_TXSTATE_ACTIVE); - spin_lock_irqsave(&data->spinlock, flags); - } - /* We're done */ - if (data->txstate == WBCIR_TXSTATE_ERROR) - count = -EAGAIN; - data->txstate = WBCIR_TXSTATE_INACTIVE; - data->txbuf = NULL; spin_unlock_irqrestore(&data->spinlock, flags); - return count; } @@ -927,13 +919,11 @@ wbcir_init_hw(struct wbcir_data *data) ir_raw_event_reset(data->dev); ir_raw_event_handle(data->dev); - /* - * Check TX state, if we did a suspend/resume cycle while TX was - * active, we will have a process waiting in txwaitq. - */ + /* Clear TX state */ if (data->txstate == WBCIR_TXSTATE_ACTIVE) { - data->txstate = WBCIR_TXSTATE_ERROR; - wake_up(&data->txwaitq); + kfree(data->txbuf); + data->txbuf = NULL; + data->txstate = WBCIR_TXSTATE_INACTIVE; } /* Enable interrupts */ @@ -974,7 +964,6 @@ wbcir_probe(struct pnp_dev *device, const struct pnp_device_id *dev_id) pnp_set_drvdata(device, data); spin_lock_init(&data->spinlock); - init_waitqueue_head(&data->txwaitq); data->ebase = pnp_port_start(device, 0); data->wbase = pnp_port_start(device, 1); data->sbase = pnp_port_start(device, 2); diff --git a/drivers/media/common/tuners/Kconfig b/drivers/media/tuners/Kconfig index 94c6ff7a5da3..e8fdf713fce8 100644 --- a/drivers/media/common/tuners/Kconfig +++ b/drivers/media/tuners/Kconfig @@ -18,43 +18,31 @@ config MEDIA_ATTACH If unsure say Y. +# Analog TV tuners, auto-loaded via tuner.ko config MEDIA_TUNER tristate depends on (MEDIA_ANALOG_TV_SUPPORT || MEDIA_RADIO_SUPPORT) && I2C default y - select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMISE - select MEDIA_TUNER_XC5000 if !MEDIA_TUNER_CUSTOMISE - select MEDIA_TUNER_XC4000 if !MEDIA_TUNER_CUSTOMISE - select MEDIA_TUNER_MT20XX if !MEDIA_TUNER_CUSTOMISE - select MEDIA_TUNER_TDA8290 if !MEDIA_TUNER_CUSTOMISE - select MEDIA_TUNER_TEA5761 if !MEDIA_TUNER_CUSTOMISE && MEDIA_RADIO_SUPPORT && EXPERIMENTAL - select MEDIA_TUNER_TEA5767 if !MEDIA_TUNER_CUSTOMISE && MEDIA_RADIO_SUPPORT - select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMISE - select MEDIA_TUNER_TDA9887 if !MEDIA_TUNER_CUSTOMISE - select MEDIA_TUNER_MC44S803 if !MEDIA_TUNER_CUSTOMISE - -config MEDIA_TUNER_CUSTOMISE - bool "Customize analog and hybrid tuner modules to build" - depends on MEDIA_TUNER - default y if EXPERT - help - This allows the user to deselect tuner drivers unnecessary - for their hardware from the build. Use this option with care - as deselecting tuner drivers which are in fact necessary will - result in V4L/DVB devices which cannot be tuned due to lack of - driver support - - If unsure say N. + select MEDIA_TUNER_XC2028 if MEDIA_SUBDRV_AUTOSELECT + select MEDIA_TUNER_XC5000 if MEDIA_SUBDRV_AUTOSELECT + select MEDIA_TUNER_XC4000 if MEDIA_SUBDRV_AUTOSELECT + select MEDIA_TUNER_MT20XX if MEDIA_SUBDRV_AUTOSELECT + select MEDIA_TUNER_TDA8290 if MEDIA_SUBDRV_AUTOSELECT + select MEDIA_TUNER_TEA5761 if MEDIA_SUBDRV_AUTOSELECT && MEDIA_RADIO_SUPPORT + select MEDIA_TUNER_TEA5767 if MEDIA_SUBDRV_AUTOSELECT && MEDIA_RADIO_SUPPORT + select MEDIA_TUNER_SIMPLE if MEDIA_SUBDRV_AUTOSELECT + select MEDIA_TUNER_TDA9887 if MEDIA_SUBDRV_AUTOSELECT + select MEDIA_TUNER_MC44S803 if MEDIA_SUBDRV_AUTOSELECT menu "Customize TV tuners" - visible if MEDIA_TUNER_CUSTOMISE + visible if !MEDIA_SUBDRV_AUTOSELECT depends on MEDIA_ANALOG_TV_SUPPORT || MEDIA_DIGITAL_TV_SUPPORT || MEDIA_RADIO_SUPPORT config MEDIA_TUNER_SIMPLE tristate "Simple tuner support" depends on MEDIA_SUPPORT && I2C select MEDIA_TUNER_TDA9887 - default m if MEDIA_TUNER_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help Say Y here to include support for various simple tuners. @@ -63,100 +51,99 @@ config MEDIA_TUNER_TDA8290 depends on MEDIA_SUPPORT && I2C select MEDIA_TUNER_TDA827X select MEDIA_TUNER_TDA18271 - default m if MEDIA_TUNER_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help Say Y here to include support for Philips TDA8290+8275(a) tuner. config MEDIA_TUNER_TDA827X tristate "Philips TDA827X silicon tuner" depends on MEDIA_SUPPORT && I2C - default m if MEDIA_TUNER_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help A DVB-T silicon tuner module. Say Y when you want to support this tuner. config MEDIA_TUNER_TDA18271 tristate "NXP TDA18271 silicon tuner" depends on MEDIA_SUPPORT && I2C - default m if MEDIA_TUNER_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help A silicon tuner module. Say Y when you want to support this tuner. config MEDIA_TUNER_TDA9887 tristate "TDA 9885/6/7 analog IF demodulator" depends on MEDIA_SUPPORT && I2C - default m if MEDIA_TUNER_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help Say Y here to include support for Philips TDA9885/6/7 analog IF demodulator. config MEDIA_TUNER_TEA5761 - tristate "TEA 5761 radio tuner (EXPERIMENTAL)" + tristate "TEA 5761 radio tuner" depends on MEDIA_SUPPORT && I2C - depends on EXPERIMENTAL - default m if MEDIA_TUNER_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help Say Y here to include support for the Philips TEA5761 radio tuner. config MEDIA_TUNER_TEA5767 tristate "TEA 5767 radio tuner" depends on MEDIA_SUPPORT && I2C - default m if MEDIA_TUNER_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help Say Y here to include support for the Philips TEA5767 radio tuner. config MEDIA_TUNER_MT20XX tristate "Microtune 2032 / 2050 tuners" depends on MEDIA_SUPPORT && I2C - default m if MEDIA_TUNER_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help Say Y here to include support for the MT2032 / MT2050 tuner. config MEDIA_TUNER_MT2060 tristate "Microtune MT2060 silicon IF tuner" depends on MEDIA_SUPPORT && I2C - default m if MEDIA_TUNER_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help A driver for the silicon IF tuner MT2060 from Microtune. config MEDIA_TUNER_MT2063 tristate "Microtune MT2063 silicon IF tuner" depends on MEDIA_SUPPORT && I2C - default m if MEDIA_TUNER_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help A driver for the silicon IF tuner MT2063 from Microtune. config MEDIA_TUNER_MT2266 tristate "Microtune MT2266 silicon tuner" depends on MEDIA_SUPPORT && I2C - default m if MEDIA_TUNER_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help A driver for the silicon baseband tuner MT2266 from Microtune. config MEDIA_TUNER_MT2131 tristate "Microtune MT2131 silicon tuner" depends on MEDIA_SUPPORT && I2C - default m if MEDIA_TUNER_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help A driver for the silicon baseband tuner MT2131 from Microtune. config MEDIA_TUNER_QT1010 tristate "Quantek QT1010 silicon tuner" depends on MEDIA_SUPPORT && I2C - default m if MEDIA_TUNER_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help A driver for the silicon tuner QT1010 from Quantek. config MEDIA_TUNER_XC2028 tristate "XCeive xc2028/xc3028 tuners" depends on MEDIA_SUPPORT && I2C - default m if MEDIA_TUNER_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help Say Y here to include support for the xc2028/xc3028 tuners. config MEDIA_TUNER_XC5000 tristate "Xceive XC5000 silicon tuner" depends on MEDIA_SUPPORT && I2C - default m if MEDIA_TUNER_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help A driver for the silicon tuner XC5000 from Xceive. This device is only used inside a SiP called together with a @@ -165,7 +152,7 @@ config MEDIA_TUNER_XC5000 config MEDIA_TUNER_XC4000 tristate "Xceive XC4000 silicon tuner" depends on MEDIA_SUPPORT && I2C - default m if MEDIA_TUNER_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help A driver for the silicon tuner XC4000 from Xceive. This device is only used inside a SiP called together with a @@ -174,70 +161,84 @@ config MEDIA_TUNER_XC4000 config MEDIA_TUNER_MXL5005S tristate "MaxLinear MSL5005S silicon tuner" depends on MEDIA_SUPPORT && I2C - default m if MEDIA_TUNER_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help A driver for the silicon tuner MXL5005S from MaxLinear. config MEDIA_TUNER_MXL5007T tristate "MaxLinear MxL5007T silicon tuner" depends on MEDIA_SUPPORT && I2C - default m if MEDIA_TUNER_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help A driver for the silicon tuner MxL5007T from MaxLinear. config MEDIA_TUNER_MC44S803 tristate "Freescale MC44S803 Low Power CMOS Broadband tuners" depends on MEDIA_SUPPORT && I2C - default m if MEDIA_TUNER_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help Say Y here to support the Freescale MC44S803 based tuners config MEDIA_TUNER_MAX2165 tristate "Maxim MAX2165 silicon tuner" depends on MEDIA_SUPPORT && I2C - default m if MEDIA_TUNER_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help A driver for the silicon tuner MAX2165 from Maxim. config MEDIA_TUNER_TDA18218 tristate "NXP TDA18218 silicon tuner" depends on MEDIA_SUPPORT && I2C - default m if MEDIA_TUNER_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help NXP TDA18218 silicon tuner driver. config MEDIA_TUNER_FC0011 tristate "Fitipower FC0011 silicon tuner" depends on MEDIA_SUPPORT && I2C - default m if MEDIA_TUNER_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help Fitipower FC0011 silicon tuner driver. config MEDIA_TUNER_FC0012 tristate "Fitipower FC0012 silicon tuner" depends on MEDIA_SUPPORT && I2C - default m if MEDIA_TUNER_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help Fitipower FC0012 silicon tuner driver. config MEDIA_TUNER_FC0013 tristate "Fitipower FC0013 silicon tuner" depends on MEDIA_SUPPORT && I2C - default m if MEDIA_TUNER_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help Fitipower FC0013 silicon tuner driver. config MEDIA_TUNER_TDA18212 tristate "NXP TDA18212 silicon tuner" depends on MEDIA_SUPPORT && I2C - default m if MEDIA_TUNER_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help NXP TDA18212 silicon tuner driver. +config MEDIA_TUNER_E4000 + tristate "Elonics E4000 silicon tuner" + depends on MEDIA_SUPPORT && I2C + default m if !MEDIA_SUBDRV_AUTOSELECT + help + Elonics E4000 silicon tuner driver. + +config MEDIA_TUNER_FC2580 + tristate "FCI FC2580 silicon tuner" + depends on MEDIA_SUPPORT && I2C + default m if !MEDIA_SUBDRV_AUTOSELECT + help + FCI FC2580 silicon tuner driver. + config MEDIA_TUNER_TUA9001 tristate "Infineon TUA 9001 silicon tuner" depends on MEDIA_SUPPORT && I2C - default m if MEDIA_TUNER_CUSTOMISE + default m if !MEDIA_SUBDRV_AUTOSELECT help Infineon TUA 9001 silicon tuner driver. endmenu diff --git a/drivers/media/common/tuners/Makefile b/drivers/media/tuners/Makefile index 891b80e60808..5e569b1083cf 100644 --- a/drivers/media/common/tuners/Makefile +++ b/drivers/media/tuners/Makefile @@ -28,10 +28,12 @@ obj-$(CONFIG_MEDIA_TUNER_MC44S803) += mc44s803.o obj-$(CONFIG_MEDIA_TUNER_MAX2165) += max2165.o obj-$(CONFIG_MEDIA_TUNER_TDA18218) += tda18218.o obj-$(CONFIG_MEDIA_TUNER_TDA18212) += tda18212.o +obj-$(CONFIG_MEDIA_TUNER_E4000) += e4000.o +obj-$(CONFIG_MEDIA_TUNER_FC2580) += fc2580.o obj-$(CONFIG_MEDIA_TUNER_TUA9001) += tua9001.o obj-$(CONFIG_MEDIA_TUNER_FC0011) += fc0011.o obj-$(CONFIG_MEDIA_TUNER_FC0012) += fc0012.o obj-$(CONFIG_MEDIA_TUNER_FC0013) += fc0013.o -ccflags-y += -I$(srctree)/drivers/media/dvb/dvb-core -ccflags-y += -I$(srctree)/drivers/media/dvb/frontends +ccflags-y += -I$(srctree)/drivers/media/dvb-core +ccflags-y += -I$(srctree)/drivers/media/dvb-frontends diff --git a/drivers/media/tuners/e4000.c b/drivers/media/tuners/e4000.c new file mode 100644 index 000000000000..1b33ed368abe --- /dev/null +++ b/drivers/media/tuners/e4000.c @@ -0,0 +1,409 @@ +/* + * Elonics E4000 silicon tuner driver + * + * Copyright (C) 2012 Antti Palosaari <crope@iki.fi> + * + * 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "e4000_priv.h" + +/* write multiple registers */ +static int e4000_wr_regs(struct e4000_priv *priv, u8 reg, u8 *val, int len) +{ + int ret; + u8 buf[1 + len]; + struct i2c_msg msg[1] = { + { + .addr = priv->cfg->i2c_addr, + .flags = 0, + .len = sizeof(buf), + .buf = buf, + } + }; + + buf[0] = reg; + memcpy(&buf[1], val, len); + + ret = i2c_transfer(priv->i2c, msg, 1); + if (ret == 1) { + ret = 0; + } else { + dev_warn(&priv->i2c->dev, "%s: i2c wr failed=%d reg=%02x " \ + "len=%d\n", KBUILD_MODNAME, ret, reg, len); + ret = -EREMOTEIO; + } + return ret; +} + +/* read multiple registers */ +static int e4000_rd_regs(struct e4000_priv *priv, u8 reg, u8 *val, int len) +{ + int ret; + u8 buf[len]; + struct i2c_msg msg[2] = { + { + .addr = priv->cfg->i2c_addr, + .flags = 0, + .len = 1, + .buf = ®, + }, { + .addr = priv->cfg->i2c_addr, + .flags = I2C_M_RD, + .len = sizeof(buf), + .buf = buf, + } + }; + + ret = i2c_transfer(priv->i2c, msg, 2); + if (ret == 2) { + memcpy(val, buf, len); + ret = 0; + } else { + dev_warn(&priv->i2c->dev, "%s: i2c rd failed=%d reg=%02x " \ + "len=%d\n", KBUILD_MODNAME, ret, reg, len); + ret = -EREMOTEIO; + } + + return ret; +} + +/* write single register */ +static int e4000_wr_reg(struct e4000_priv *priv, u8 reg, u8 val) +{ + return e4000_wr_regs(priv, reg, &val, 1); +} + +/* read single register */ +static int e4000_rd_reg(struct e4000_priv *priv, u8 reg, u8 *val) +{ + return e4000_rd_regs(priv, reg, val, 1); +} + +static int e4000_init(struct dvb_frontend *fe) +{ + struct e4000_priv *priv = fe->tuner_priv; + int ret; + + dev_dbg(&priv->i2c->dev, "%s:\n", __func__); + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + + /* dummy I2C to ensure I2C wakes up */ + ret = e4000_wr_reg(priv, 0x02, 0x40); + + /* reset */ + ret = e4000_wr_reg(priv, 0x00, 0x01); + if (ret < 0) + goto err; + + /* disable output clock */ + ret = e4000_wr_reg(priv, 0x06, 0x00); + if (ret < 0) + goto err; + + ret = e4000_wr_reg(priv, 0x7a, 0x96); + if (ret < 0) + goto err; + + /* configure gains */ + ret = e4000_wr_regs(priv, 0x7e, "\x01\xfe", 2); + if (ret < 0) + goto err; + + ret = e4000_wr_reg(priv, 0x82, 0x00); + if (ret < 0) + goto err; + + ret = e4000_wr_reg(priv, 0x24, 0x05); + if (ret < 0) + goto err; + + ret = e4000_wr_regs(priv, 0x87, "\x20\x01", 2); + if (ret < 0) + goto err; + + ret = e4000_wr_regs(priv, 0x9f, "\x7f\x07", 2); + if (ret < 0) + goto err; + + /* + * TODO: Implement DC offset control correctly. + * DC offsets has quite much effect for received signal quality in case + * of direct conversion tuners (Zero-IF). Surely we will now lose few + * decimals or even decibels from SNR... + */ + /* DC offset control */ + ret = e4000_wr_reg(priv, 0x2d, 0x0c); + if (ret < 0) + goto err; + + /* gain control */ + ret = e4000_wr_reg(priv, 0x1a, 0x17); + if (ret < 0) + goto err; + + ret = e4000_wr_reg(priv, 0x1f, 0x1a); + if (ret < 0) + goto err; + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); + + return 0; +err: + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); + + dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); + return ret; +} + +static int e4000_sleep(struct dvb_frontend *fe) +{ + struct e4000_priv *priv = fe->tuner_priv; + int ret; + + dev_dbg(&priv->i2c->dev, "%s:\n", __func__); + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + + ret = e4000_wr_reg(priv, 0x00, 0x00); + if (ret < 0) + goto err; + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); + + return 0; +err: + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); + + dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); + return ret; +} + +static int e4000_set_params(struct dvb_frontend *fe) +{ + struct e4000_priv *priv = fe->tuner_priv; + struct dtv_frontend_properties *c = &fe->dtv_property_cache; + int ret, i, sigma_delta; + unsigned int f_VCO; + u8 buf[5]; + + dev_dbg(&priv->i2c->dev, "%s: delivery_system=%d frequency=%d " \ + "bandwidth_hz=%d\n", __func__, + c->delivery_system, c->frequency, c->bandwidth_hz); + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + + /* gain control manual */ + ret = e4000_wr_reg(priv, 0x1a, 0x00); + if (ret < 0) + goto err; + + /* PLL */ + for (i = 0; i < ARRAY_SIZE(e4000_pll_lut); i++) { + if (c->frequency <= e4000_pll_lut[i].freq) + break; + } + + if (i == ARRAY_SIZE(e4000_pll_lut)) + goto err; + + /* + * Note: Currently f_VCO overflows when c->frequency is 1 073 741 824 Hz + * or more. + */ + f_VCO = c->frequency * e4000_pll_lut[i].mul; + sigma_delta = 0x10000UL * (f_VCO % priv->cfg->clock) / priv->cfg->clock; + buf[0] = f_VCO / priv->cfg->clock; + buf[1] = (sigma_delta >> 0) & 0xff; + buf[2] = (sigma_delta >> 8) & 0xff; + buf[3] = 0x00; + buf[4] = e4000_pll_lut[i].div; + + dev_dbg(&priv->i2c->dev, "%s: f_VCO=%u pll div=%d sigma_delta=%04x\n", + __func__, f_VCO, buf[0], sigma_delta); + + ret = e4000_wr_regs(priv, 0x09, buf, 5); + if (ret < 0) + goto err; + + /* LNA filter (RF filter) */ + for (i = 0; i < ARRAY_SIZE(e400_lna_filter_lut); i++) { + if (c->frequency <= e400_lna_filter_lut[i].freq) + break; + } + + if (i == ARRAY_SIZE(e400_lna_filter_lut)) + goto err; + + ret = e4000_wr_reg(priv, 0x10, e400_lna_filter_lut[i].val); + if (ret < 0) + goto err; + + /* IF filters */ + for (i = 0; i < ARRAY_SIZE(e4000_if_filter_lut); i++) { + if (c->bandwidth_hz <= e4000_if_filter_lut[i].freq) + break; + } + + if (i == ARRAY_SIZE(e4000_if_filter_lut)) + goto err; + + buf[0] = e4000_if_filter_lut[i].reg11_val; + buf[1] = e4000_if_filter_lut[i].reg12_val; + + ret = e4000_wr_regs(priv, 0x11, buf, 2); + if (ret < 0) + goto err; + + /* frequency band */ + for (i = 0; i < ARRAY_SIZE(e4000_band_lut); i++) { + if (c->frequency <= e4000_band_lut[i].freq) + break; + } + + if (i == ARRAY_SIZE(e4000_band_lut)) + goto err; + + ret = e4000_wr_reg(priv, 0x07, e4000_band_lut[i].reg07_val); + if (ret < 0) + goto err; + + ret = e4000_wr_reg(priv, 0x78, e4000_band_lut[i].reg78_val); + if (ret < 0) + goto err; + + /* gain control auto */ + ret = e4000_wr_reg(priv, 0x1a, 0x17); + if (ret < 0) + goto err; + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); + + return 0; +err: + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); + + dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); + return ret; +} + +static int e4000_get_if_frequency(struct dvb_frontend *fe, u32 *frequency) +{ + struct e4000_priv *priv = fe->tuner_priv; + + dev_dbg(&priv->i2c->dev, "%s:\n", __func__); + + *frequency = 0; /* Zero-IF */ + + return 0; +} + +static int e4000_release(struct dvb_frontend *fe) +{ + struct e4000_priv *priv = fe->tuner_priv; + + dev_dbg(&priv->i2c->dev, "%s:\n", __func__); + + kfree(fe->tuner_priv); + + return 0; +} + +static const struct dvb_tuner_ops e4000_tuner_ops = { + .info = { + .name = "Elonics E4000", + .frequency_min = 174000000, + .frequency_max = 862000000, + }, + + .release = e4000_release, + + .init = e4000_init, + .sleep = e4000_sleep, + .set_params = e4000_set_params, + + .get_if_frequency = e4000_get_if_frequency, +}; + +struct dvb_frontend *e4000_attach(struct dvb_frontend *fe, + struct i2c_adapter *i2c, const struct e4000_config *cfg) +{ + struct e4000_priv *priv; + int ret; + u8 chip_id; + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + + priv = kzalloc(sizeof(struct e4000_priv), GFP_KERNEL); + if (!priv) { + ret = -ENOMEM; + dev_err(&i2c->dev, "%s: kzalloc() failed\n", KBUILD_MODNAME); + goto err; + } + + priv->cfg = cfg; + priv->i2c = i2c; + + /* check if the tuner is there */ + ret = e4000_rd_reg(priv, 0x02, &chip_id); + if (ret < 0) + goto err; + + dev_dbg(&priv->i2c->dev, "%s: chip_id=%02x\n", __func__, chip_id); + + if (chip_id != 0x40) + goto err; + + /* put sleep as chip seems to be in normal mode by default */ + ret = e4000_wr_reg(priv, 0x00, 0x00); + if (ret < 0) + goto err; + + dev_info(&priv->i2c->dev, + "%s: Elonics E4000 successfully identified\n", + KBUILD_MODNAME); + + fe->tuner_priv = priv; + memcpy(&fe->ops.tuner_ops, &e4000_tuner_ops, + sizeof(struct dvb_tuner_ops)); + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); + + return fe; +err: + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); + + dev_dbg(&i2c->dev, "%s: failed=%d\n", __func__, ret); + kfree(priv); + return NULL; +} +EXPORT_SYMBOL(e4000_attach); + +MODULE_DESCRIPTION("Elonics E4000 silicon tuner driver"); +MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>"); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/tuners/e4000.h b/drivers/media/tuners/e4000.h new file mode 100644 index 000000000000..71b1935eb3d2 --- /dev/null +++ b/drivers/media/tuners/e4000.h @@ -0,0 +1,52 @@ +/* + * Elonics E4000 silicon tuner driver + * + * Copyright (C) 2012 Antti Palosaari <crope@iki.fi> + * + * 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef E4000_H +#define E4000_H + +#include "dvb_frontend.h" + +struct e4000_config { + /* + * I2C address + * 0x64, 0x65, 0x66, 0x67 + */ + u8 i2c_addr; + + /* + * clock + */ + u32 clock; +}; + +#if defined(CONFIG_MEDIA_TUNER_E4000) || \ + (defined(CONFIG_MEDIA_TUNER_E4000_MODULE) && defined(MODULE)) +extern struct dvb_frontend *e4000_attach(struct dvb_frontend *fe, + struct i2c_adapter *i2c, const struct e4000_config *cfg); +#else +static inline struct dvb_frontend *e4000_attach(struct dvb_frontend *fe, + struct i2c_adapter *i2c, const struct e4000_config *cfg) +{ + pr_warn("%s: driver disabled by Kconfig\n", __func__); + return NULL; +} +#endif + +#endif diff --git a/drivers/media/tuners/e4000_priv.h b/drivers/media/tuners/e4000_priv.h new file mode 100644 index 000000000000..a3855053e78f --- /dev/null +++ b/drivers/media/tuners/e4000_priv.h @@ -0,0 +1,147 @@ +/* + * Elonics E4000 silicon tuner driver + * + * Copyright (C) 2012 Antti Palosaari <crope@iki.fi> + * + * 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef E4000_PRIV_H +#define E4000_PRIV_H + +#include "e4000.h" + +struct e4000_priv { + const struct e4000_config *cfg; + struct i2c_adapter *i2c; +}; + +struct e4000_pll { + u32 freq; + u8 div; + u8 mul; +}; + +static const struct e4000_pll e4000_pll_lut[] = { +/* VCO min VCO max */ + { 72400000, 0x0f, 48 }, /* .......... 3475200000 */ + { 81200000, 0x0e, 40 }, /* 2896000000 3248000000 */ + { 108300000, 0x0d, 32 }, /* 2598400000 3465600000 */ + { 162500000, 0x0c, 24 }, /* 2599200000 3900000000 */ + { 216600000, 0x0b, 16 }, /* 2600000000 3465600000 */ + { 325000000, 0x0a, 12 }, /* 2599200000 3900000000 */ + { 350000000, 0x09, 8 }, /* 2600000000 2800000000 */ + { 432000000, 0x03, 8 }, /* 2800000000 3456000000 */ + { 667000000, 0x02, 6 }, /* 2592000000 4002000000 */ + { 1200000000, 0x01, 4 }, /* 2668000000 4800000000 */ + { 0xffffffff, 0x00, 2 }, /* 2400000000 .......... */ +}; + +struct e4000_lna_filter { + u32 freq; + u8 val; +}; + +static const struct e4000_lna_filter e400_lna_filter_lut[] = { + { 370000000, 0 }, + { 392500000, 1 }, + { 415000000, 2 }, + { 437500000, 3 }, + { 462500000, 4 }, + { 490000000, 5 }, + { 522500000, 6 }, + { 557500000, 7 }, + { 595000000, 8 }, + { 642500000, 9 }, + { 695000000, 10 }, + { 740000000, 11 }, + { 800000000, 12 }, + { 865000000, 13 }, + { 930000000, 14 }, + { 1000000000, 15 }, + { 1310000000, 0 }, + { 1340000000, 1 }, + { 1385000000, 2 }, + { 1427500000, 3 }, + { 1452500000, 4 }, + { 1475000000, 5 }, + { 1510000000, 6 }, + { 1545000000, 7 }, + { 1575000000, 8 }, + { 1615000000, 9 }, + { 1650000000, 10 }, + { 1670000000, 11 }, + { 1690000000, 12 }, + { 1710000000, 13 }, + { 1735000000, 14 }, + { 0xffffffff, 15 }, +}; + +struct e4000_band { + u32 freq; + u8 reg07_val; + u8 reg78_val; +}; + +static const struct e4000_band e4000_band_lut[] = { + { 140000000, 0x01, 0x03 }, + { 350000000, 0x03, 0x03 }, + { 1000000000, 0x05, 0x03 }, + { 0xffffffff, 0x07, 0x00 }, +}; + +struct e4000_if_filter { + u32 freq; + u8 reg11_val; + u8 reg12_val; +}; + +static const struct e4000_if_filter e4000_if_filter_lut[] = { + { 4300000, 0xfd, 0x1f }, + { 4400000, 0xfd, 0x1e }, + { 4480000, 0xfc, 0x1d }, + { 4560000, 0xfc, 0x1c }, + { 4600000, 0xfc, 0x1b }, + { 4800000, 0xfc, 0x1a }, + { 4900000, 0xfc, 0x19 }, + { 5000000, 0xfc, 0x18 }, + { 5100000, 0xfc, 0x17 }, + { 5200000, 0xfc, 0x16 }, + { 5400000, 0xfc, 0x15 }, + { 5500000, 0xfc, 0x14 }, + { 5600000, 0xfc, 0x13 }, + { 5800000, 0xfb, 0x12 }, + { 5900000, 0xfb, 0x11 }, + { 6000000, 0xfb, 0x10 }, + { 6200000, 0xfb, 0x0f }, + { 6400000, 0xfa, 0x0e }, + { 6600000, 0xfa, 0x0d }, + { 6800000, 0xf9, 0x0c }, + { 7200000, 0xf9, 0x0b }, + { 7400000, 0xf9, 0x0a }, + { 7600000, 0xf8, 0x09 }, + { 7800000, 0xf8, 0x08 }, + { 8200000, 0xf8, 0x07 }, + { 8600000, 0xf7, 0x06 }, + { 8800000, 0xf7, 0x05 }, + { 9200000, 0xf7, 0x04 }, + { 9600000, 0xf6, 0x03 }, + { 10000000, 0xf6, 0x02 }, + { 10600000, 0xf5, 0x01 }, + { 11000000, 0xf5, 0x00 }, + { 0xffffffff, 0x00, 0x20 }, +}; + +#endif diff --git a/drivers/media/common/tuners/fc0011.c b/drivers/media/tuners/fc0011.c index e4882546c283..e4882546c283 100644 --- a/drivers/media/common/tuners/fc0011.c +++ b/drivers/media/tuners/fc0011.c diff --git a/drivers/media/common/tuners/fc0011.h b/drivers/media/tuners/fc0011.h index 0ee581f122d2..0ee581f122d2 100644 --- a/drivers/media/common/tuners/fc0011.h +++ b/drivers/media/tuners/fc0011.h diff --git a/drivers/media/common/tuners/fc0012-priv.h b/drivers/media/tuners/fc0012-priv.h index 4577c917e616..4577c917e616 100644 --- a/drivers/media/common/tuners/fc0012-priv.h +++ b/drivers/media/tuners/fc0012-priv.h diff --git a/drivers/media/common/tuners/fc0012.c b/drivers/media/tuners/fc0012.c index 308135abd54c..308135abd54c 100644 --- a/drivers/media/common/tuners/fc0012.c +++ b/drivers/media/tuners/fc0012.c diff --git a/drivers/media/common/tuners/fc0012.h b/drivers/media/tuners/fc0012.h index 4dbd5efe8845..4dbd5efe8845 100644 --- a/drivers/media/common/tuners/fc0012.h +++ b/drivers/media/tuners/fc0012.h diff --git a/drivers/media/common/tuners/fc0013-priv.h b/drivers/media/tuners/fc0013-priv.h index bfd49dedea22..bfd49dedea22 100644 --- a/drivers/media/common/tuners/fc0013-priv.h +++ b/drivers/media/tuners/fc0013-priv.h diff --git a/drivers/media/common/tuners/fc0013.c b/drivers/media/tuners/fc0013.c index bd8f0f1e8f3b..bd8f0f1e8f3b 100644 --- a/drivers/media/common/tuners/fc0013.c +++ b/drivers/media/tuners/fc0013.c diff --git a/drivers/media/common/tuners/fc0013.h b/drivers/media/tuners/fc0013.h index 594efd64aeec..594efd64aeec 100644 --- a/drivers/media/common/tuners/fc0013.h +++ b/drivers/media/tuners/fc0013.h diff --git a/drivers/media/common/tuners/fc001x-common.h b/drivers/media/tuners/fc001x-common.h index 718818156934..718818156934 100644 --- a/drivers/media/common/tuners/fc001x-common.h +++ b/drivers/media/tuners/fc001x-common.h diff --git a/drivers/media/tuners/fc2580.c b/drivers/media/tuners/fc2580.c new file mode 100644 index 000000000000..aff39ae457a0 --- /dev/null +++ b/drivers/media/tuners/fc2580.c @@ -0,0 +1,529 @@ +/* + * FCI FC2580 silicon tuner driver + * + * Copyright (C) 2012 Antti Palosaari <crope@iki.fi> + * + * 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "fc2580_priv.h" + +/* + * TODO: + * I2C write and read works only for one single register. Multiple registers + * could not be accessed using normal register address auto-increment. + * There could be (very likely) register to change that behavior.... + * + * Due to that limitation functions: + * fc2580_wr_regs() + * fc2580_rd_regs() + * could not be used for accessing more than one register at once. + * + * TODO: + * Currently it blind writes bunch of static registers from the + * fc2580_freq_regs_lut[] when fc2580_set_params() is called. Add some + * logic to reduce unneeded register writes. + * There is also don't-care registers, initialized with value 0xff, and those + * are also written to the chip currently (yes, not wise). + */ + +/* write multiple registers */ +static int fc2580_wr_regs(struct fc2580_priv *priv, u8 reg, u8 *val, int len) +{ + int ret; + u8 buf[1 + len]; + struct i2c_msg msg[1] = { + { + .addr = priv->cfg->i2c_addr, + .flags = 0, + .len = sizeof(buf), + .buf = buf, + } + }; + + buf[0] = reg; + memcpy(&buf[1], val, len); + + ret = i2c_transfer(priv->i2c, msg, 1); + if (ret == 1) { + ret = 0; + } else { + dev_warn(&priv->i2c->dev, "%s: i2c wr failed=%d reg=%02x " \ + "len=%d\n", KBUILD_MODNAME, ret, reg, len); + ret = -EREMOTEIO; + } + return ret; +} + +/* read multiple registers */ +static int fc2580_rd_regs(struct fc2580_priv *priv, u8 reg, u8 *val, int len) +{ + int ret; + u8 buf[len]; + struct i2c_msg msg[2] = { + { + .addr = priv->cfg->i2c_addr, + .flags = 0, + .len = 1, + .buf = ®, + }, { + .addr = priv->cfg->i2c_addr, + .flags = I2C_M_RD, + .len = sizeof(buf), + .buf = buf, + } + }; + + ret = i2c_transfer(priv->i2c, msg, 2); + if (ret == 2) { + memcpy(val, buf, len); + ret = 0; + } else { + dev_warn(&priv->i2c->dev, "%s: i2c rd failed=%d reg=%02x " \ + "len=%d\n", KBUILD_MODNAME, ret, reg, len); + ret = -EREMOTEIO; + } + + return ret; +} + +/* write single register */ +static int fc2580_wr_reg(struct fc2580_priv *priv, u8 reg, u8 val) +{ + return fc2580_wr_regs(priv, reg, &val, 1); +} + +/* read single register */ +static int fc2580_rd_reg(struct fc2580_priv *priv, u8 reg, u8 *val) +{ + return fc2580_rd_regs(priv, reg, val, 1); +} + +static int fc2580_set_params(struct dvb_frontend *fe) +{ + struct fc2580_priv *priv = fe->tuner_priv; + struct dtv_frontend_properties *c = &fe->dtv_property_cache; + int ret = 0, i; + unsigned int r_val, n_val, k_val, k_val_reg, f_ref; + u8 tmp_val, r18_val; + u64 f_vco; + + /* + * Fractional-N synthesizer/PLL. + * Most likely all those PLL calculations are not correct. I am not + * sure, but it looks like it is divider based Fractional-N synthesizer. + * There is divider for reference clock too? + * Anyhow, synthesizer calculation results seems to be quite correct. + */ + + dev_dbg(&priv->i2c->dev, "%s: delivery_system=%d frequency=%d " \ + "bandwidth_hz=%d\n", __func__, + c->delivery_system, c->frequency, c->bandwidth_hz); + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + + /* PLL */ + for (i = 0; i < ARRAY_SIZE(fc2580_pll_lut); i++) { + if (c->frequency <= fc2580_pll_lut[i].freq) + break; + } + + if (i == ARRAY_SIZE(fc2580_pll_lut)) + goto err; + + f_vco = c->frequency; + f_vco *= fc2580_pll_lut[i].div; + + if (f_vco >= 2600000000UL) + tmp_val = 0x0e | fc2580_pll_lut[i].band; + else + tmp_val = 0x06 | fc2580_pll_lut[i].band; + + ret = fc2580_wr_reg(priv, 0x02, tmp_val); + if (ret < 0) + goto err; + + if (f_vco >= 2UL * 76 * priv->cfg->clock) { + r_val = 1; + r18_val = 0x00; + } else if (f_vco >= 1UL * 76 * priv->cfg->clock) { + r_val = 2; + r18_val = 0x10; + } else { + r_val = 4; + r18_val = 0x20; + } + + f_ref = 2UL * priv->cfg->clock / r_val; + n_val = div_u64_rem(f_vco, f_ref, &k_val); + k_val_reg = 1UL * k_val * (1 << 20) / f_ref; + + ret = fc2580_wr_reg(priv, 0x18, r18_val | ((k_val_reg >> 16) & 0xff)); + if (ret < 0) + goto err; + + ret = fc2580_wr_reg(priv, 0x1a, (k_val_reg >> 8) & 0xff); + if (ret < 0) + goto err; + + ret = fc2580_wr_reg(priv, 0x1b, (k_val_reg >> 0) & 0xff); + if (ret < 0) + goto err; + + ret = fc2580_wr_reg(priv, 0x1c, n_val); + if (ret < 0) + goto err; + + if (priv->cfg->clock >= 28000000) { + ret = fc2580_wr_reg(priv, 0x4b, 0x22); + if (ret < 0) + goto err; + } + + if (fc2580_pll_lut[i].band == 0x00) { + if (c->frequency <= 794000000) + tmp_val = 0x9f; + else + tmp_val = 0x8f; + + ret = fc2580_wr_reg(priv, 0x2d, tmp_val); + if (ret < 0) + goto err; + } + + /* registers */ + for (i = 0; i < ARRAY_SIZE(fc2580_freq_regs_lut); i++) { + if (c->frequency <= fc2580_freq_regs_lut[i].freq) + break; + } + + if (i == ARRAY_SIZE(fc2580_freq_regs_lut)) + goto err; + + ret = fc2580_wr_reg(priv, 0x25, fc2580_freq_regs_lut[i].r25_val); + if (ret < 0) + goto err; + + ret = fc2580_wr_reg(priv, 0x27, fc2580_freq_regs_lut[i].r27_val); + if (ret < 0) + goto err; + + ret = fc2580_wr_reg(priv, 0x28, fc2580_freq_regs_lut[i].r28_val); + if (ret < 0) + goto err; + + ret = fc2580_wr_reg(priv, 0x29, fc2580_freq_regs_lut[i].r29_val); + if (ret < 0) + goto err; + + ret = fc2580_wr_reg(priv, 0x2b, fc2580_freq_regs_lut[i].r2b_val); + if (ret < 0) + goto err; + + ret = fc2580_wr_reg(priv, 0x2c, fc2580_freq_regs_lut[i].r2c_val); + if (ret < 0) + goto err; + + ret = fc2580_wr_reg(priv, 0x2d, fc2580_freq_regs_lut[i].r2d_val); + if (ret < 0) + goto err; + + ret = fc2580_wr_reg(priv, 0x30, fc2580_freq_regs_lut[i].r30_val); + if (ret < 0) + goto err; + + ret = fc2580_wr_reg(priv, 0x44, fc2580_freq_regs_lut[i].r44_val); + if (ret < 0) + goto err; + + ret = fc2580_wr_reg(priv, 0x50, fc2580_freq_regs_lut[i].r50_val); + if (ret < 0) + goto err; + + ret = fc2580_wr_reg(priv, 0x53, fc2580_freq_regs_lut[i].r53_val); + if (ret < 0) + goto err; + + ret = fc2580_wr_reg(priv, 0x5f, fc2580_freq_regs_lut[i].r5f_val); + if (ret < 0) + goto err; + + ret = fc2580_wr_reg(priv, 0x61, fc2580_freq_regs_lut[i].r61_val); + if (ret < 0) + goto err; + + ret = fc2580_wr_reg(priv, 0x62, fc2580_freq_regs_lut[i].r62_val); + if (ret < 0) + goto err; + + ret = fc2580_wr_reg(priv, 0x63, fc2580_freq_regs_lut[i].r63_val); + if (ret < 0) + goto err; + + ret = fc2580_wr_reg(priv, 0x67, fc2580_freq_regs_lut[i].r67_val); + if (ret < 0) + goto err; + + ret = fc2580_wr_reg(priv, 0x68, fc2580_freq_regs_lut[i].r68_val); + if (ret < 0) + goto err; + + ret = fc2580_wr_reg(priv, 0x69, fc2580_freq_regs_lut[i].r69_val); + if (ret < 0) + goto err; + + ret = fc2580_wr_reg(priv, 0x6a, fc2580_freq_regs_lut[i].r6a_val); + if (ret < 0) + goto err; + + ret = fc2580_wr_reg(priv, 0x6b, fc2580_freq_regs_lut[i].r6b_val); + if (ret < 0) + goto err; + + ret = fc2580_wr_reg(priv, 0x6c, fc2580_freq_regs_lut[i].r6c_val); + if (ret < 0) + goto err; + + ret = fc2580_wr_reg(priv, 0x6d, fc2580_freq_regs_lut[i].r6d_val); + if (ret < 0) + goto err; + + ret = fc2580_wr_reg(priv, 0x6e, fc2580_freq_regs_lut[i].r6e_val); + if (ret < 0) + goto err; + + ret = fc2580_wr_reg(priv, 0x6f, fc2580_freq_regs_lut[i].r6f_val); + if (ret < 0) + goto err; + + /* IF filters */ + for (i = 0; i < ARRAY_SIZE(fc2580_if_filter_lut); i++) { + if (c->bandwidth_hz <= fc2580_if_filter_lut[i].freq) + break; + } + + if (i == ARRAY_SIZE(fc2580_if_filter_lut)) + goto err; + + ret = fc2580_wr_reg(priv, 0x36, fc2580_if_filter_lut[i].r36_val); + if (ret < 0) + goto err; + + ret = fc2580_wr_reg(priv, 0x37, 1UL * priv->cfg->clock * \ + fc2580_if_filter_lut[i].mul / 1000000000); + if (ret < 0) + goto err; + + ret = fc2580_wr_reg(priv, 0x39, fc2580_if_filter_lut[i].r39_val); + if (ret < 0) + goto err; + + /* calibration? */ + ret = fc2580_wr_reg(priv, 0x2e, 0x09); + if (ret < 0) + goto err; + + for (i = 0; i < 5; i++) { + ret = fc2580_rd_reg(priv, 0x2f, &tmp_val); + if (ret < 0) + goto err; + + /* done when [7:6] are set */ + if ((tmp_val & 0xc0) == 0xc0) + break; + + ret = fc2580_wr_reg(priv, 0x2e, 0x01); + if (ret < 0) + goto err; + + ret = fc2580_wr_reg(priv, 0x2e, 0x09); + if (ret < 0) + goto err; + + usleep_range(5000, 25000); + } + + dev_dbg(&priv->i2c->dev, "%s: loop=%i\n", __func__, i); + + ret = fc2580_wr_reg(priv, 0x2e, 0x01); + if (ret < 0) + goto err; + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); + + return 0; +err: + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); + + dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); + return ret; +} + +static int fc2580_init(struct dvb_frontend *fe) +{ + struct fc2580_priv *priv = fe->tuner_priv; + int ret, i; + + dev_dbg(&priv->i2c->dev, "%s:\n", __func__); + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + + for (i = 0; i < ARRAY_SIZE(fc2580_init_reg_vals); i++) { + ret = fc2580_wr_reg(priv, fc2580_init_reg_vals[i].reg, + fc2580_init_reg_vals[i].val); + if (ret < 0) + goto err; + } + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); + + return 0; +err: + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); + + dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); + return ret; +} + +static int fc2580_sleep(struct dvb_frontend *fe) +{ + struct fc2580_priv *priv = fe->tuner_priv; + int ret; + + dev_dbg(&priv->i2c->dev, "%s:\n", __func__); + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + + ret = fc2580_wr_reg(priv, 0x02, 0x0a); + if (ret < 0) + goto err; + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); + + return 0; +err: + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); + + dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); + return ret; +} + +static int fc2580_get_if_frequency(struct dvb_frontend *fe, u32 *frequency) +{ + struct fc2580_priv *priv = fe->tuner_priv; + + dev_dbg(&priv->i2c->dev, "%s:\n", __func__); + + *frequency = 0; /* Zero-IF */ + + return 0; +} + +static int fc2580_release(struct dvb_frontend *fe) +{ + struct fc2580_priv *priv = fe->tuner_priv; + + dev_dbg(&priv->i2c->dev, "%s:\n", __func__); + + kfree(fe->tuner_priv); + + return 0; +} + +static const struct dvb_tuner_ops fc2580_tuner_ops = { + .info = { + .name = "FCI FC2580", + .frequency_min = 174000000, + .frequency_max = 862000000, + }, + + .release = fc2580_release, + + .init = fc2580_init, + .sleep = fc2580_sleep, + .set_params = fc2580_set_params, + + .get_if_frequency = fc2580_get_if_frequency, +}; + +struct dvb_frontend *fc2580_attach(struct dvb_frontend *fe, + struct i2c_adapter *i2c, const struct fc2580_config *cfg) +{ + struct fc2580_priv *priv; + int ret; + u8 chip_id; + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + + priv = kzalloc(sizeof(struct fc2580_priv), GFP_KERNEL); + if (!priv) { + ret = -ENOMEM; + dev_err(&i2c->dev, "%s: kzalloc() failed\n", KBUILD_MODNAME); + goto err; + } + + priv->cfg = cfg; + priv->i2c = i2c; + + /* check if the tuner is there */ + ret = fc2580_rd_reg(priv, 0x01, &chip_id); + if (ret < 0) + goto err; + + dev_dbg(&priv->i2c->dev, "%s: chip_id=%02x\n", __func__, chip_id); + + switch (chip_id) { + case 0x56: + case 0x5a: + break; + default: + goto err; + } + + dev_info(&priv->i2c->dev, + "%s: FCI FC2580 successfully identified\n", + KBUILD_MODNAME); + + fe->tuner_priv = priv; + memcpy(&fe->ops.tuner_ops, &fc2580_tuner_ops, + sizeof(struct dvb_tuner_ops)); + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); + + return fe; +err: + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); + + dev_dbg(&i2c->dev, "%s: failed=%d\n", __func__, ret); + kfree(priv); + return NULL; +} +EXPORT_SYMBOL(fc2580_attach); + +MODULE_DESCRIPTION("FCI FC2580 silicon tuner driver"); +MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>"); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/tuners/fc2580.h b/drivers/media/tuners/fc2580.h new file mode 100644 index 000000000000..222601e5d23b --- /dev/null +++ b/drivers/media/tuners/fc2580.h @@ -0,0 +1,52 @@ +/* + * FCI FC2580 silicon tuner driver + * + * Copyright (C) 2012 Antti Palosaari <crope@iki.fi> + * + * 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef FC2580_H +#define FC2580_H + +#include "dvb_frontend.h" + +struct fc2580_config { + /* + * I2C address + * 0x56, ... + */ + u8 i2c_addr; + + /* + * clock + */ + u32 clock; +}; + +#if defined(CONFIG_MEDIA_TUNER_FC2580) || \ + (defined(CONFIG_MEDIA_TUNER_FC2580_MODULE) && defined(MODULE)) +extern struct dvb_frontend *fc2580_attach(struct dvb_frontend *fe, + struct i2c_adapter *i2c, const struct fc2580_config *cfg); +#else +static inline struct dvb_frontend *fc2580_attach(struct dvb_frontend *fe, + struct i2c_adapter *i2c, const struct fc2580_config *cfg) +{ + pr_warn("%s: driver disabled by Kconfig\n", __func__); + return NULL; +} +#endif + +#endif diff --git a/drivers/media/tuners/fc2580_priv.h b/drivers/media/tuners/fc2580_priv.h new file mode 100644 index 000000000000..be38a9e637e0 --- /dev/null +++ b/drivers/media/tuners/fc2580_priv.h @@ -0,0 +1,134 @@ +/* + * FCI FC2580 silicon tuner driver + * + * Copyright (C) 2012 Antti Palosaari <crope@iki.fi> + * + * 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef FC2580_PRIV_H +#define FC2580_PRIV_H + +#include "fc2580.h" + +struct fc2580_reg_val { + u8 reg; + u8 val; +}; + +static const struct fc2580_reg_val fc2580_init_reg_vals[] = { + {0x00, 0x00}, + {0x12, 0x86}, + {0x14, 0x5c}, + {0x16, 0x3c}, + {0x1f, 0xd2}, + {0x09, 0xd7}, + {0x0b, 0xd5}, + {0x0c, 0x32}, + {0x0e, 0x43}, + {0x21, 0x0a}, + {0x22, 0x82}, + {0x45, 0x10}, + {0x4c, 0x00}, + {0x3f, 0x88}, + {0x02, 0x0e}, + {0x58, 0x14}, +}; + +struct fc2580_pll { + u32 freq; + u8 div; + u8 band; +}; + +static const struct fc2580_pll fc2580_pll_lut[] = { + /* VCO min VCO max */ + { 400000000, 12, 0x80}, /* .......... 4800000000 */ + {1000000000, 4, 0x00}, /* 1600000000 4000000000 */ + {0xffffffff, 2, 0x40}, /* 2000000000 .......... */ +}; + +struct fc2580_if_filter { + u32 freq; + u16 mul; + u8 r36_val; + u8 r39_val; +}; + +static const struct fc2580_if_filter fc2580_if_filter_lut[] = { + { 6000000, 4400, 0x18, 0x00}, + { 7000000, 3910, 0x18, 0x80}, + { 8000000, 3300, 0x18, 0x80}, + {0xffffffff, 3300, 0x18, 0x80}, +}; + +struct fc2580_freq_regs { + u32 freq; + u8 r25_val; + u8 r27_val; + u8 r28_val; + u8 r29_val; + u8 r2b_val; + u8 r2c_val; + u8 r2d_val; + u8 r30_val; + u8 r44_val; + u8 r50_val; + u8 r53_val; + u8 r5f_val; + u8 r61_val; + u8 r62_val; + u8 r63_val; + u8 r67_val; + u8 r68_val; + u8 r69_val; + u8 r6a_val; + u8 r6b_val; + u8 r6c_val; + u8 r6d_val; + u8 r6e_val; + u8 r6f_val; +}; + +/* XXX: 0xff is used for don't-care! */ +static const struct fc2580_freq_regs fc2580_freq_regs_lut[] = { + { 400000000, + 0xff, 0x77, 0x33, 0x40, 0xff, 0xff, 0xff, 0x09, 0xff, 0x8c, + 0x50, 0x0f, 0x07, 0x00, 0x15, 0x03, 0x05, 0x10, 0x12, 0x08, + 0x0a, 0x78, 0x32, 0x54}, + { 538000000, + 0xf0, 0x77, 0x53, 0x60, 0xff, 0xff, 0xff, 0x09, 0xff, 0x8c, + 0x50, 0x13, 0x07, 0x06, 0x15, 0x06, 0x08, 0x10, 0x12, 0x0b, + 0x0c, 0x78, 0x32, 0x14}, + { 794000000, + 0xf0, 0x77, 0x53, 0x60, 0xff, 0xff, 0xff, 0x09, 0xff, 0x8c, + 0x50, 0x15, 0x03, 0x03, 0x15, 0x03, 0x05, 0x0c, 0x0e, 0x0b, + 0x0c, 0x78, 0x32, 0x14}, + {1000000000, + 0xf0, 0x77, 0x53, 0x60, 0xff, 0xff, 0xff, 0x09, 0xff, 0x8c, + 0x50, 0x15, 0x07, 0x06, 0x15, 0x07, 0x09, 0x10, 0x12, 0x0b, + 0x0c, 0x78, 0x32, 0x14}, + {0xffffffff, + 0xff, 0xff, 0xff, 0xff, 0x70, 0x37, 0xe7, 0x09, 0x20, 0x8c, + 0x50, 0x0f, 0x0f, 0x00, 0x13, 0x00, 0x02, 0x0c, 0x0e, 0x08, + 0x0a, 0xa0, 0x50, 0x14}, +}; + +struct fc2580_priv { + const struct fc2580_config *cfg; + struct i2c_adapter *i2c; +}; + +#endif diff --git a/drivers/media/common/tuners/max2165.c b/drivers/media/tuners/max2165.c index ba84936aafd6..ba84936aafd6 100644 --- a/drivers/media/common/tuners/max2165.c +++ b/drivers/media/tuners/max2165.c diff --git a/drivers/media/common/tuners/max2165.h b/drivers/media/tuners/max2165.h index c063c36a93d3..c063c36a93d3 100644 --- a/drivers/media/common/tuners/max2165.h +++ b/drivers/media/tuners/max2165.h diff --git a/drivers/media/common/tuners/max2165_priv.h b/drivers/media/tuners/max2165_priv.h index 91bbe021a08d..91bbe021a08d 100644 --- a/drivers/media/common/tuners/max2165_priv.h +++ b/drivers/media/tuners/max2165_priv.h diff --git a/drivers/media/common/tuners/mc44s803.c b/drivers/media/tuners/mc44s803.c index 5ddce7e326f7..f1b764074661 100644 --- a/drivers/media/common/tuners/mc44s803.c +++ b/drivers/media/tuners/mc44s803.c @@ -298,6 +298,12 @@ static int mc44s803_get_frequency(struct dvb_frontend *fe, u32 *frequency) return 0; } +static int mc44s803_get_if_frequency(struct dvb_frontend *fe, u32 *frequency) +{ + *frequency = MC44S803_IF2; /* 36.125 MHz */ + return 0; +} + static const struct dvb_tuner_ops mc44s803_tuner_ops = { .info = { .name = "Freescale MC44S803", @@ -309,7 +315,8 @@ static const struct dvb_tuner_ops mc44s803_tuner_ops = { .release = mc44s803_release, .init = mc44s803_init, .set_params = mc44s803_set_params, - .get_frequency = mc44s803_get_frequency + .get_frequency = mc44s803_get_frequency, + .get_if_frequency = mc44s803_get_if_frequency, }; /* This functions tries to identify a MC44S803 tuner by reading the ID diff --git a/drivers/media/common/tuners/mc44s803.h b/drivers/media/tuners/mc44s803.h index 34f3892d3f6d..34f3892d3f6d 100644 --- a/drivers/media/common/tuners/mc44s803.h +++ b/drivers/media/tuners/mc44s803.h diff --git a/drivers/media/common/tuners/mc44s803_priv.h b/drivers/media/tuners/mc44s803_priv.h index 14a92780906d..14a92780906d 100644 --- a/drivers/media/common/tuners/mc44s803_priv.h +++ b/drivers/media/tuners/mc44s803_priv.h diff --git a/drivers/media/common/tuners/mt2060.c b/drivers/media/tuners/mt2060.c index 13381de58a84..13381de58a84 100644 --- a/drivers/media/common/tuners/mt2060.c +++ b/drivers/media/tuners/mt2060.c diff --git a/drivers/media/common/tuners/mt2060.h b/drivers/media/tuners/mt2060.h index cb60caffb6b6..cb60caffb6b6 100644 --- a/drivers/media/common/tuners/mt2060.h +++ b/drivers/media/tuners/mt2060.h diff --git a/drivers/media/common/tuners/mt2060_priv.h b/drivers/media/tuners/mt2060_priv.h index 2b60de6c707d..2b60de6c707d 100644 --- a/drivers/media/common/tuners/mt2060_priv.h +++ b/drivers/media/tuners/mt2060_priv.h diff --git a/drivers/media/common/tuners/mt2063.c b/drivers/media/tuners/mt2063.c index 0ed9091ff48e..0ed9091ff48e 100644 --- a/drivers/media/common/tuners/mt2063.c +++ b/drivers/media/tuners/mt2063.c diff --git a/drivers/media/common/tuners/mt2063.h b/drivers/media/tuners/mt2063.h index 3f5cfd93713f..3f5cfd93713f 100644 --- a/drivers/media/common/tuners/mt2063.h +++ b/drivers/media/tuners/mt2063.h diff --git a/drivers/media/common/tuners/mt20xx.c b/drivers/media/tuners/mt20xx.c index 0e74e97e0d1a..0e74e97e0d1a 100644 --- a/drivers/media/common/tuners/mt20xx.c +++ b/drivers/media/tuners/mt20xx.c diff --git a/drivers/media/common/tuners/mt20xx.h b/drivers/media/tuners/mt20xx.h index 259553a24903..259553a24903 100644 --- a/drivers/media/common/tuners/mt20xx.h +++ b/drivers/media/tuners/mt20xx.h diff --git a/drivers/media/common/tuners/mt2131.c b/drivers/media/tuners/mt2131.c index f83b0c1ea6c8..f83b0c1ea6c8 100644 --- a/drivers/media/common/tuners/mt2131.c +++ b/drivers/media/tuners/mt2131.c diff --git a/drivers/media/common/tuners/mt2131.h b/drivers/media/tuners/mt2131.h index 6632de640df0..6632de640df0 100644 --- a/drivers/media/common/tuners/mt2131.h +++ b/drivers/media/tuners/mt2131.h diff --git a/drivers/media/common/tuners/mt2131_priv.h b/drivers/media/tuners/mt2131_priv.h index 62aeedf5c550..62aeedf5c550 100644 --- a/drivers/media/common/tuners/mt2131_priv.h +++ b/drivers/media/tuners/mt2131_priv.h diff --git a/drivers/media/common/tuners/mt2266.c b/drivers/media/tuners/mt2266.c index bca4d75e42d4..bca4d75e42d4 100644 --- a/drivers/media/common/tuners/mt2266.c +++ b/drivers/media/tuners/mt2266.c diff --git a/drivers/media/common/tuners/mt2266.h b/drivers/media/tuners/mt2266.h index 4d083882d044..4d083882d044 100644 --- a/drivers/media/common/tuners/mt2266.h +++ b/drivers/media/tuners/mt2266.h diff --git a/drivers/media/common/tuners/mxl5005s.c b/drivers/media/tuners/mxl5005s.c index 6133315fb0e3..b473b76cb278 100644 --- a/drivers/media/common/tuners/mxl5005s.c +++ b/drivers/media/tuners/mxl5005s.c @@ -4054,6 +4054,16 @@ static int mxl5005s_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth) return 0; } +static int mxl5005s_get_if_frequency(struct dvb_frontend *fe, u32 *frequency) +{ + struct mxl5005s_state *state = fe->tuner_priv; + dprintk(1, "%s()\n", __func__); + + *frequency = state->IF_OUT; + + return 0; +} + static int mxl5005s_release(struct dvb_frontend *fe) { dprintk(1, "%s()\n", __func__); @@ -4076,6 +4086,7 @@ static const struct dvb_tuner_ops mxl5005s_tuner_ops = { .set_params = mxl5005s_set_params, .get_frequency = mxl5005s_get_frequency, .get_bandwidth = mxl5005s_get_bandwidth, + .get_if_frequency = mxl5005s_get_if_frequency, }; struct dvb_frontend *mxl5005s_attach(struct dvb_frontend *fe, diff --git a/drivers/media/common/tuners/mxl5005s.h b/drivers/media/tuners/mxl5005s.h index fc8a1ffc53b4..fc8a1ffc53b4 100644 --- a/drivers/media/common/tuners/mxl5005s.h +++ b/drivers/media/tuners/mxl5005s.h diff --git a/drivers/media/common/tuners/mxl5007t.c b/drivers/media/tuners/mxl5007t.c index 69e453ef0a1a..69e453ef0a1a 100644 --- a/drivers/media/common/tuners/mxl5007t.c +++ b/drivers/media/tuners/mxl5007t.c diff --git a/drivers/media/common/tuners/mxl5007t.h b/drivers/media/tuners/mxl5007t.h index aa3eea0b5262..aa3eea0b5262 100644 --- a/drivers/media/common/tuners/mxl5007t.h +++ b/drivers/media/tuners/mxl5007t.h diff --git a/drivers/media/common/tuners/qt1010.c b/drivers/media/tuners/qt1010.c index 2d79b1f5d5eb..bc419f8a9671 100644 --- a/drivers/media/common/tuners/qt1010.c +++ b/drivers/media/tuners/qt1010.c @@ -21,15 +21,6 @@ #include "qt1010.h" #include "qt1010_priv.h" -static int debug; -module_param(debug, int, 0644); -MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off)."); - -#define dprintk(args...) \ - do { \ - if (debug) printk(KERN_DEBUG "QT1010: " args); \ - } while (0) - /* read single register */ static int qt1010_readreg(struct qt1010_priv *priv, u8 reg, u8 *val) { @@ -41,7 +32,8 @@ static int qt1010_readreg(struct qt1010_priv *priv, u8 reg, u8 *val) }; if (i2c_transfer(priv->i2c, msg, 2) != 2) { - printk(KERN_WARNING "qt1010 I2C read failed\n"); + dev_warn(&priv->i2c->dev, "%s: i2c rd failed reg=%02x\n", + KBUILD_MODNAME, reg); return -EREMOTEIO; } return 0; @@ -55,33 +47,13 @@ static int qt1010_writereg(struct qt1010_priv *priv, u8 reg, u8 val) .flags = 0, .buf = buf, .len = 2 }; if (i2c_transfer(priv->i2c, &msg, 1) != 1) { - printk(KERN_WARNING "qt1010 I2C write failed\n"); + dev_warn(&priv->i2c->dev, "%s: i2c wr failed reg=%02x\n", + KBUILD_MODNAME, reg); return -EREMOTEIO; } return 0; } -/* dump all registers */ -static void qt1010_dump_regs(struct qt1010_priv *priv) -{ - u8 reg, val; - - for (reg = 0; ; reg++) { - if (reg % 16 == 0) { - if (reg) - printk(KERN_CONT "\n"); - printk(KERN_DEBUG "%02x:", reg); - } - if (qt1010_readreg(priv, reg, &val) == 0) - printk(KERN_CONT " %02x", val); - else - printk(KERN_CONT " --"); - if (reg == 0x2f) - break; - } - printk(KERN_CONT "\n"); -} - static int qt1010_set_params(struct dvb_frontend *fe) { struct dtv_frontend_properties *c = &fe->dtv_property_cache; @@ -229,12 +201,14 @@ static int qt1010_set_params(struct dvb_frontend *fe) /* 00 */ rd[45].val = 0x92; /* TODO: correct value calculation */ - dprintk("freq:%u 05:%02x 07:%02x 09:%02x 0a:%02x 0b:%02x " \ - "1a:%02x 11:%02x 12:%02x 22:%02x 05:%02x 1f:%02x " \ - "20:%02x 25:%02x 00:%02x", \ - freq, rd[2].val, rd[4].val, rd[6].val, rd[7].val, rd[8].val, \ - rd[10].val, rd[13].val, rd[14].val, rd[15].val, rd[35].val, \ - rd[40].val, rd[41].val, rd[43].val, rd[45].val); + dev_dbg(&priv->i2c->dev, + "%s: freq:%u 05:%02x 07:%02x 09:%02x 0a:%02x 0b:%02x " \ + "1a:%02x 11:%02x 12:%02x 22:%02x 05:%02x 1f:%02x " \ + "20:%02x 25:%02x 00:%02x\n", __func__, \ + freq, rd[2].val, rd[4].val, rd[6].val, rd[7].val, \ + rd[8].val, rd[10].val, rd[13].val, rd[14].val, \ + rd[15].val, rd[35].val, rd[40].val, rd[41].val, \ + rd[43].val, rd[45].val); for (i = 0; i < ARRAY_SIZE(rd); i++) { if (rd[i].oper == QT1010_WR) { @@ -245,9 +219,6 @@ static int qt1010_set_params(struct dvb_frontend *fe) if (err) return err; } - if (debug) - qt1010_dump_regs(priv); - if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0); /* close i2c_gate */ @@ -281,14 +252,15 @@ static int qt1010_init_meas1(struct qt1010_priv *priv, val1 = val2; err = qt1010_readreg(priv, reg, &val2); if (err) return err; - dprintk("compare reg:%02x %02x %02x", reg, val1, val2); + dev_dbg(&priv->i2c->dev, "%s: compare reg:%02x %02x %02x\n", + __func__, reg, val1, val2); } while (val1 != val2); *retval = val1; return qt1010_writereg(priv, 0x1e, 0x00); } -static u8 qt1010_init_meas2(struct qt1010_priv *priv, +static int qt1010_init_meas2(struct qt1010_priv *priv, u8 reg_init_val, u8 *retval) { u8 i, val; @@ -395,7 +367,8 @@ static int qt1010_init(struct dvb_frontend *fe) if ((err = qt1010_init_meas2(priv, i, &tmpval))) return err; - c->frequency = 545000000; /* Sigmatek DVB-110 545000000 */ + if (!c->frequency) + c->frequency = 545000000; /* Sigmatek DVB-110 545000000 */ /* MSI Megasky 580 GL861 533000000 */ return qt1010_set_params(fe); } @@ -464,7 +437,10 @@ struct dvb_frontend * qt1010_attach(struct dvb_frontend *fe, if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0); /* close i2c_gate */ - printk(KERN_INFO "Quantek QT1010 successfully identified.\n"); + dev_info(&priv->i2c->dev, + "%s: Quantek QT1010 successfully identified\n", + KBUILD_MODNAME); + memcpy(&fe->ops.tuner_ops, &qt1010_tuner_ops, sizeof(struct dvb_tuner_ops)); diff --git a/drivers/media/common/tuners/qt1010.h b/drivers/media/tuners/qt1010.h index 807fb7b6146b..807fb7b6146b 100644 --- a/drivers/media/common/tuners/qt1010.h +++ b/drivers/media/tuners/qt1010.h diff --git a/drivers/media/common/tuners/qt1010_priv.h b/drivers/media/tuners/qt1010_priv.h index 2c42d3f01636..2c42d3f01636 100644 --- a/drivers/media/common/tuners/qt1010_priv.h +++ b/drivers/media/tuners/qt1010_priv.h diff --git a/drivers/media/common/tuners/tda18212.c b/drivers/media/tuners/tda18212.c index 602c2e392b17..5d9f02842501 100644 --- a/drivers/media/common/tuners/tda18212.c +++ b/drivers/media/tuners/tda18212.c @@ -18,8 +18,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - #include "tda18212.h" struct tda18212_priv { @@ -29,16 +27,6 @@ struct tda18212_priv { u32 if_frequency; }; -#define dbg(fmt, arg...) \ -do { \ - if (debug) \ - pr_info("%s: " fmt, __func__, ##arg); \ -} while (0) - -static int debug; -module_param(debug, int, 0644); -MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off)."); - /* write multiple registers */ static int tda18212_wr_regs(struct tda18212_priv *priv, u8 reg, u8 *val, int len) @@ -61,8 +49,8 @@ static int tda18212_wr_regs(struct tda18212_priv *priv, u8 reg, u8 *val, if (ret == 1) { ret = 0; } else { - pr_warn("i2c wr failed ret:%d reg:%02x len:%d\n", - ret, reg, len); + dev_warn(&priv->i2c->dev, "%s: i2c wr failed=%d reg=%02x " \ + "len=%d\n", KBUILD_MODNAME, ret, reg, len); ret = -EREMOTEIO; } return ret; @@ -93,8 +81,8 @@ static int tda18212_rd_regs(struct tda18212_priv *priv, u8 reg, u8 *val, memcpy(val, buf, len); ret = 0; } else { - pr_warn("i2c rd failed ret:%d reg:%02x len:%d\n", - ret, reg, len); + dev_warn(&priv->i2c->dev, "%s: i2c rd failed=%d reg=%02x " \ + "len=%d\n", KBUILD_MODNAME, ret, reg, len); ret = -EREMOTEIO; } @@ -157,8 +145,10 @@ static int tda18212_set_params(struct dvb_frontend *fe) [DVBC_8] = { 0x92, 0x53, 0x03 }, }; - dbg("delsys=%d RF=%d BW=%d\n", - c->delivery_system, c->frequency, c->bandwidth_hz); + dev_dbg(&priv->i2c->dev, + "%s: delivery_system=%d frequency=%d bandwidth_hz=%d\n", + __func__, c->delivery_system, c->frequency, + c->bandwidth_hz); if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */ @@ -247,7 +237,7 @@ exit: return ret; error: - dbg("failed:%d\n", ret); + dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); goto exit; } @@ -287,7 +277,7 @@ struct dvb_frontend *tda18212_attach(struct dvb_frontend *fe, { struct tda18212_priv *priv = NULL; int ret; - u8 val; + u8 uninitialized_var(val); priv = kzalloc(sizeof(struct tda18212_priv), GFP_KERNEL); if (priv == NULL) @@ -306,13 +296,16 @@ struct dvb_frontend *tda18212_attach(struct dvb_frontend *fe, if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */ - dbg("ret:%d chip ID:%02x\n", ret, val); + dev_dbg(&priv->i2c->dev, "%s: ret=%d chip id=%02x\n", __func__, ret, + val); if (ret || val != 0xc7) { kfree(priv); return NULL; } - pr_info("NXP TDA18212HN successfully identified\n"); + dev_info(&priv->i2c->dev, + "%s: NXP TDA18212HN successfully identified\n", + KBUILD_MODNAME); memcpy(&fe->ops.tuner_ops, &tda18212_tuner_ops, sizeof(struct dvb_tuner_ops)); diff --git a/drivers/media/common/tuners/tda18212.h b/drivers/media/tuners/tda18212.h index 9bd5da4aabb7..9bd5da4aabb7 100644 --- a/drivers/media/common/tuners/tda18212.h +++ b/drivers/media/tuners/tda18212.h diff --git a/drivers/media/common/tuners/tda18218.c b/drivers/media/tuners/tda18218.c index dfb3a831df45..18198537be9f 100644 --- a/drivers/media/common/tuners/tda18218.c +++ b/drivers/media/tuners/tda18218.c @@ -18,18 +18,13 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include "tda18218.h" #include "tda18218_priv.h" -static int debug; -module_param(debug, int, 0644); -MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off)."); - /* write multiple registers */ static int tda18218_wr_regs(struct tda18218_priv *priv, u8 reg, u8 *val, u8 len) { - int ret = 0; - u8 buf[1+len], quotient, remainder, i, msg_len, msg_len_max; + int ret = 0, len2, remaining; + u8 buf[1 + len]; struct i2c_msg msg[1] = { { .addr = priv->cfg->i2c_address, @@ -38,17 +33,15 @@ static int tda18218_wr_regs(struct tda18218_priv *priv, u8 reg, u8 *val, u8 len) } }; - msg_len_max = priv->cfg->i2c_wr_max - 1; - quotient = len / msg_len_max; - remainder = len % msg_len_max; - msg_len = msg_len_max; - for (i = 0; (i <= quotient && remainder); i++) { - if (i == quotient) /* set len of the last msg */ - msg_len = remainder; + for (remaining = len; remaining > 0; + remaining -= (priv->cfg->i2c_wr_max - 1)) { + len2 = remaining; + if (len2 > (priv->cfg->i2c_wr_max - 1)) + len2 = (priv->cfg->i2c_wr_max - 1); - msg[0].len = msg_len + 1; - buf[0] = reg + i * msg_len_max; - memcpy(&buf[1], &val[i * msg_len_max], msg_len); + msg[0].len = 1 + len2; + buf[0] = reg + len - remaining; + memcpy(&buf[1], &val[len - remaining], len2); ret = i2c_transfer(priv->i2c, msg, 1); if (ret != 1) @@ -58,7 +51,8 @@ static int tda18218_wr_regs(struct tda18218_priv *priv, u8 reg, u8 *val, u8 len) if (ret == 1) { ret = 0; } else { - warn("i2c wr failed ret:%d reg:%02x len:%d", ret, reg, len); + dev_warn(&priv->i2c->dev, "%s: i2c wr failed=%d reg=%02x " \ + "len=%d\n", KBUILD_MODNAME, ret, reg, len); ret = -EREMOTEIO; } @@ -89,7 +83,8 @@ static int tda18218_rd_regs(struct tda18218_priv *priv, u8 reg, u8 *val, u8 len) memcpy(val, &buf[reg], len); ret = 0; } else { - warn("i2c rd failed ret:%d reg:%02x len:%d", ret, reg, len); + dev_warn(&priv->i2c->dev, "%s: i2c rd failed=%d reg=%02x " \ + "len=%d\n", KBUILD_MODNAME, ret, reg, len); ret = -EREMOTEIO; } @@ -199,7 +194,7 @@ error: fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */ if (ret) - dbg("%s: failed ret:%d", __func__, ret); + dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); return ret; } @@ -208,7 +203,7 @@ static int tda18218_get_if_frequency(struct dvb_frontend *fe, u32 *frequency) { struct tda18218_priv *priv = fe->tuner_priv; *frequency = priv->if_frequency; - dbg("%s: if=%d", __func__, *frequency); + dev_dbg(&priv->i2c->dev, "%s: if_frequency=%d\n", __func__, *frequency); return 0; } @@ -227,7 +222,7 @@ static int tda18218_sleep(struct dvb_frontend *fe) fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */ if (ret) - dbg("%s: failed ret:%d", __func__, ret); + dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); return ret; } @@ -248,7 +243,7 @@ static int tda18218_init(struct dvb_frontend *fe) fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */ if (ret) - dbg("%s: failed ret:%d", __func__, ret); + dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); return ret; } @@ -282,7 +277,7 @@ struct dvb_frontend *tda18218_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct tda18218_config *cfg) { struct tda18218_priv *priv = NULL; - u8 val; + u8 uninitialized_var(val); int ret; /* chip default registers values */ static u8 def_regs[] = { @@ -307,13 +302,16 @@ struct dvb_frontend *tda18218_attach(struct dvb_frontend *fe, /* check if the tuner is there */ ret = tda18218_rd_reg(priv, R00_ID, &val); - dbg("%s: ret:%d chip ID:%02x", __func__, ret, val); + dev_dbg(&priv->i2c->dev, "%s: ret=%d chip id=%02x\n", __func__, ret, + val); if (ret || val != def_regs[R00_ID]) { kfree(priv); return NULL; } - info("NXP TDA18218HN successfully identified."); + dev_info(&priv->i2c->dev, + "%s: NXP TDA18218HN successfully identified\n", + KBUILD_MODNAME); memcpy(&fe->ops.tuner_ops, &tda18218_tuner_ops, sizeof(struct dvb_tuner_ops)); @@ -328,7 +326,7 @@ struct dvb_frontend *tda18218_attach(struct dvb_frontend *fe, /* standby */ ret = tda18218_wr_reg(priv, R17_PD1, priv->regs[R17_PD1] | (1 << 0)); if (ret) - dbg("%s: failed ret:%d", __func__, ret); + dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */ diff --git a/drivers/media/common/tuners/tda18218.h b/drivers/media/tuners/tda18218.h index b4180d180029..b4180d180029 100644 --- a/drivers/media/common/tuners/tda18218.h +++ b/drivers/media/tuners/tda18218.h diff --git a/drivers/media/common/tuners/tda18218_priv.h b/drivers/media/tuners/tda18218_priv.h index dc52b72e1407..285b77366c8d 100644 --- a/drivers/media/common/tuners/tda18218_priv.h +++ b/drivers/media/tuners/tda18218_priv.h @@ -21,18 +21,7 @@ #ifndef TDA18218_PRIV_H #define TDA18218_PRIV_H -#define LOG_PREFIX "tda18218" - -#undef dbg -#define dbg(f, arg...) \ - if (debug) \ - printk(KERN_DEBUG LOG_PREFIX": " f "\n" , ## arg) -#undef err -#define err(f, arg...) printk(KERN_ERR LOG_PREFIX": " f "\n" , ## arg) -#undef info -#define info(f, arg...) printk(KERN_INFO LOG_PREFIX": " f "\n" , ## arg) -#undef warn -#define warn(f, arg...) printk(KERN_WARNING LOG_PREFIX": " f "\n" , ## arg) +#include "tda18218.h" #define R00_ID 0x00 /* ID byte */ #define R01_R1 0x01 /* Read byte 1 */ diff --git a/drivers/media/common/tuners/tda18271-common.c b/drivers/media/tuners/tda18271-common.c index 39c645787b62..221171eeb0c3 100644 --- a/drivers/media/common/tuners/tda18271-common.c +++ b/drivers/media/tuners/tda18271-common.c @@ -275,7 +275,7 @@ int tda18271_init_regs(struct dvb_frontend *fe) case TDA18271HDC2: regs[R_ID] = 0x84; break; - }; + } regs[R_TM] = 0x08; regs[R_PL] = 0x80; @@ -300,7 +300,7 @@ int tda18271_init_regs(struct dvb_frontend *fe) case TDA18271HDC2: regs[R_EB1] = 0xfc; break; - }; + } regs[R_EB2] = 0x01; regs[R_EB3] = 0x84; @@ -320,7 +320,7 @@ int tda18271_init_regs(struct dvb_frontend *fe) case TDA18271HDC2: regs[R_EB12] = 0x33; break; - }; + } regs[R_EB13] = 0xc1; regs[R_EB14] = 0x00; @@ -335,7 +335,7 @@ int tda18271_init_regs(struct dvb_frontend *fe) case TDA18271HDC2: regs[R_EB18] = 0x8c; break; - }; + } regs[R_EB19] = 0x00; regs[R_EB20] = 0x20; @@ -347,7 +347,7 @@ int tda18271_init_regs(struct dvb_frontend *fe) case TDA18271HDC2: regs[R_EB21] = 0xb3; break; - }; + } regs[R_EB22] = 0x48; regs[R_EB23] = 0xb0; diff --git a/drivers/media/common/tuners/tda18271-fe.c b/drivers/media/tuners/tda18271-fe.c index 2e67f4459904..72c26fd77922 100644 --- a/drivers/media/common/tuners/tda18271-fe.c +++ b/drivers/media/tuners/tda18271-fe.c @@ -1159,11 +1159,19 @@ static int tda18271_get_id(struct dvb_frontend *fe) struct tda18271_priv *priv = fe->tuner_priv; unsigned char *regs = priv->tda18271_regs; char *name; + int ret; mutex_lock(&priv->lock); - tda18271_read_regs(fe); + ret = tda18271_read_regs(fe); mutex_unlock(&priv->lock); + if (ret) { + tda_info("Error reading device ID @ %d-%04x, bailing out.\n", + i2c_adapter_id(priv->i2c_props.adap), + priv->i2c_props.addr); + return -EIO; + } + switch (regs[R_ID] & 0x7f) { case 3: name = "TDA18271HD/C1"; @@ -1278,6 +1286,11 @@ struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr, if (tda_fail(ret)) goto fail; + /* if delay_cal is set, delay IR & RF calibration until init() + * module option 'cal' overrides this delay */ + if ((cfg->delay_cal) && (!tda18271_need_cal_on_startup(cfg))) + break; + mutex_lock(&priv->lock); tda18271_init_regs(fe); @@ -1285,6 +1298,10 @@ struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr, (priv->id == TDA18271HDC2)) tda18271c2_rf_cal_init(fe); + /* enter standby mode, with required output features enabled */ + ret = tda18271_toggle_output(fe, 1); + tda_fail(ret); + mutex_unlock(&priv->lock); break; default: diff --git a/drivers/media/common/tuners/tda18271-maps.c b/drivers/media/tuners/tda18271-maps.c index fb881c667c94..fb881c667c94 100644 --- a/drivers/media/common/tuners/tda18271-maps.c +++ b/drivers/media/tuners/tda18271-maps.c diff --git a/drivers/media/common/tuners/tda18271-priv.h b/drivers/media/tuners/tda18271-priv.h index 454c152ccaa0..454c152ccaa0 100644 --- a/drivers/media/common/tuners/tda18271-priv.h +++ b/drivers/media/tuners/tda18271-priv.h diff --git a/drivers/media/common/tuners/tda18271.h b/drivers/media/tuners/tda18271.h index 640bae4e6a5a..89b6c6d93fec 100644 --- a/drivers/media/common/tuners/tda18271.h +++ b/drivers/media/tuners/tda18271.h @@ -105,6 +105,11 @@ struct tda18271_config { /* force rf tracking filter calibration on startup */ unsigned int rf_cal_on_startup:1; + /* prevent any register access during attach(), + * delaying both IR & RF calibration until init() + * module option 'cal' overrides this delay */ + unsigned int delay_cal:1; + /* interface to saa713x / tda829x */ unsigned int config; }; diff --git a/drivers/media/common/tuners/tda827x.c b/drivers/media/tuners/tda827x.c index a0d176267470..a0d176267470 100644 --- a/drivers/media/common/tuners/tda827x.c +++ b/drivers/media/tuners/tda827x.c diff --git a/drivers/media/common/tuners/tda827x.h b/drivers/media/tuners/tda827x.h index 7d72ce0a0c2d..7d72ce0a0c2d 100644 --- a/drivers/media/common/tuners/tda827x.h +++ b/drivers/media/tuners/tda827x.h diff --git a/drivers/media/common/tuners/tda8290.c b/drivers/media/tuners/tda8290.c index 8c4852114eeb..8c4852114eeb 100644 --- a/drivers/media/common/tuners/tda8290.c +++ b/drivers/media/tuners/tda8290.c diff --git a/drivers/media/common/tuners/tda8290.h b/drivers/media/tuners/tda8290.h index 7e288b26fcc3..7e288b26fcc3 100644 --- a/drivers/media/common/tuners/tda8290.h +++ b/drivers/media/tuners/tda8290.h diff --git a/drivers/media/common/tuners/tda9887.c b/drivers/media/tuners/tda9887.c index cdb645d57438..cdb645d57438 100644 --- a/drivers/media/common/tuners/tda9887.c +++ b/drivers/media/tuners/tda9887.c diff --git a/drivers/media/common/tuners/tda9887.h b/drivers/media/tuners/tda9887.h index acc419e8c4fc..acc419e8c4fc 100644 --- a/drivers/media/common/tuners/tda9887.h +++ b/drivers/media/tuners/tda9887.h diff --git a/drivers/media/common/tuners/tea5761.c b/drivers/media/tuners/tea5761.c index bf78cb9fc52c..bf78cb9fc52c 100644 --- a/drivers/media/common/tuners/tea5761.c +++ b/drivers/media/tuners/tea5761.c diff --git a/drivers/media/common/tuners/tea5761.h b/drivers/media/tuners/tea5761.h index 2e2ff82c95a4..2e2ff82c95a4 100644 --- a/drivers/media/common/tuners/tea5761.h +++ b/drivers/media/tuners/tea5761.h diff --git a/drivers/media/common/tuners/tea5767.c b/drivers/media/tuners/tea5767.c index 36e85d81acb2..36e85d81acb2 100644 --- a/drivers/media/common/tuners/tea5767.c +++ b/drivers/media/tuners/tea5767.c diff --git a/drivers/media/common/tuners/tea5767.h b/drivers/media/tuners/tea5767.h index d30ab1b483de..d30ab1b483de 100644 --- a/drivers/media/common/tuners/tea5767.h +++ b/drivers/media/tuners/tea5767.h diff --git a/drivers/media/common/tuners/tua9001.c b/drivers/media/tuners/tua9001.c index de2607084672..389668474070 100644 --- a/drivers/media/common/tuners/tua9001.c +++ b/drivers/media/tuners/tua9001.c @@ -39,8 +39,8 @@ static int tua9001_wr_reg(struct tua9001_priv *priv, u8 reg, u16 val) if (ret == 1) { ret = 0; } else { - printk(KERN_WARNING "%s: I2C wr failed=%d reg=%02x\n", - __func__, ret, reg); + dev_warn(&priv->i2c->dev, "%s: i2c wr failed=%d reg=%02x\n", + KBUILD_MODNAME, ret, reg); ret = -EREMOTEIO; } @@ -49,10 +49,19 @@ static int tua9001_wr_reg(struct tua9001_priv *priv, u8 reg, u16 val) static int tua9001_release(struct dvb_frontend *fe) { + struct tua9001_priv *priv = fe->tuner_priv; + int ret = 0; + + dev_dbg(&priv->i2c->dev, "%s:\n", __func__); + + if (fe->callback) + ret = fe->callback(priv->i2c, DVB_FRONTEND_COMPONENT_TUNER, + TUA9001_CMD_CEN, 0); + kfree(fe->tuner_priv); fe->tuner_priv = NULL; - return 0; + return ret; } static int tua9001_init(struct dvb_frontend *fe) @@ -78,20 +87,47 @@ static int tua9001_init(struct dvb_frontend *fe) { 0x34, 0x0a40 }, }; + dev_dbg(&priv->i2c->dev, "%s:\n", __func__); + + if (fe->callback) { + ret = fe->callback(priv->i2c, DVB_FRONTEND_COMPONENT_TUNER, + TUA9001_CMD_RESETN, 0); + if (ret < 0) + goto err; + } + if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 1); /* open i2c-gate */ for (i = 0; i < ARRAY_SIZE(data); i++) { ret = tua9001_wr_reg(priv, data[i].reg, data[i].val); - if (ret) - break; + if (ret < 0) + goto err_i2c_gate_ctrl; } +err_i2c_gate_ctrl: if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0); /* close i2c-gate */ +err: + if (ret < 0) + dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); + + return ret; +} + +static int tua9001_sleep(struct dvb_frontend *fe) +{ + struct tua9001_priv *priv = fe->tuner_priv; + int ret = 0; + + dev_dbg(&priv->i2c->dev, "%s:\n", __func__); + + if (fe->callback) + ret = fe->callback(priv->i2c, DVB_FRONTEND_COMPONENT_TUNER, + TUA9001_CMD_RESETN, 1); if (ret < 0) - pr_debug("%s: failed=%d\n", __func__, ret); + dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); return ret; } @@ -105,9 +141,9 @@ static int tua9001_set_params(struct dvb_frontend *fe) u32 frequency; struct reg_val data[2]; - pr_debug("%s: delivery_system=%d frequency=%d bandwidth_hz=%d\n", - __func__, c->delivery_system, c->frequency, - c->bandwidth_hz); + dev_dbg(&priv->i2c->dev, "%s: delivery_system=%d frequency=%d " \ + "bandwidth_hz=%d\n", __func__, + c->delivery_system, c->frequency, c->bandwidth_hz); switch (c->delivery_system) { case SYS_DVBT: @@ -148,24 +184,42 @@ static int tua9001_set_params(struct dvb_frontend *fe) if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 1); /* open i2c-gate */ + if (fe->callback) { + ret = fe->callback(priv->i2c, DVB_FRONTEND_COMPONENT_TUNER, + TUA9001_CMD_RXEN, 0); + if (ret < 0) + goto err_i2c_gate_ctrl; + } + for (i = 0; i < ARRAY_SIZE(data); i++) { ret = tua9001_wr_reg(priv, data[i].reg, data[i].val); if (ret < 0) - break; + goto err_i2c_gate_ctrl; + } + + if (fe->callback) { + ret = fe->callback(priv->i2c, DVB_FRONTEND_COMPONENT_TUNER, + TUA9001_CMD_RXEN, 1); + if (ret < 0) + goto err_i2c_gate_ctrl; } +err_i2c_gate_ctrl: if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0); /* close i2c-gate */ - err: if (ret < 0) - pr_debug("%s: failed=%d\n", __func__, ret); + dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); return ret; } static int tua9001_get_if_frequency(struct dvb_frontend *fe, u32 *frequency) { + struct tua9001_priv *priv = fe->tuner_priv; + + dev_dbg(&priv->i2c->dev, "%s:\n", __func__); + *frequency = 0; /* Zero-IF */ return 0; @@ -183,6 +237,7 @@ static const struct dvb_tuner_ops tua9001_tuner_ops = { .release = tua9001_release, .init = tua9001_init, + .sleep = tua9001_sleep, .set_params = tua9001_set_params, .get_if_frequency = tua9001_get_if_frequency, @@ -192,6 +247,7 @@ struct dvb_frontend *tua9001_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct tua9001_config *cfg) { struct tua9001_priv *priv = NULL; + int ret; priv = kzalloc(sizeof(struct tua9001_priv), GFP_KERNEL); if (priv == NULL) @@ -200,13 +256,36 @@ struct dvb_frontend *tua9001_attach(struct dvb_frontend *fe, priv->cfg = cfg; priv->i2c = i2c; - printk(KERN_INFO "Infineon TUA 9001 successfully attached."); + if (fe->callback) { + ret = fe->callback(priv->i2c, DVB_FRONTEND_COMPONENT_TUNER, + TUA9001_CMD_CEN, 1); + if (ret < 0) + goto err; + + ret = fe->callback(priv->i2c, DVB_FRONTEND_COMPONENT_TUNER, + TUA9001_CMD_RXEN, 0); + if (ret < 0) + goto err; + + ret = fe->callback(priv->i2c, DVB_FRONTEND_COMPONENT_TUNER, + TUA9001_CMD_RESETN, 1); + if (ret < 0) + goto err; + } + + dev_info(&priv->i2c->dev, + "%s: Infineon TUA 9001 successfully attached\n", + KBUILD_MODNAME); memcpy(&fe->ops.tuner_ops, &tua9001_tuner_ops, sizeof(struct dvb_tuner_ops)); fe->tuner_priv = priv; return fe; +err: + dev_dbg(&i2c->dev, "%s: failed=%d\n", __func__, ret); + kfree(priv); + return NULL; } EXPORT_SYMBOL(tua9001_attach); diff --git a/drivers/media/common/tuners/tua9001.h b/drivers/media/tuners/tua9001.h index 38d6ae76b1d6..cf5b815feff9 100644 --- a/drivers/media/common/tuners/tua9001.h +++ b/drivers/media/tuners/tua9001.h @@ -30,6 +30,26 @@ struct tua9001_config { u8 i2c_addr; }; +/* + * TUA9001 I/O PINs: + * + * CEN - chip enable + * 0 = chip disabled (chip off) + * 1 = chip enabled (chip on) + * + * RESETN - chip reset + * 0 = reset disabled (chip reset off) + * 1 = reset enabled (chip reset on) + * + * RXEN - RX enable + * 0 = RX disabled (chip idle) + * 1 = RX enabled (chip tuned) + */ + +#define TUA9001_CMD_CEN 0 +#define TUA9001_CMD_RESETN 1 +#define TUA9001_CMD_RXEN 2 + #if defined(CONFIG_MEDIA_TUNER_TUA9001) || \ (defined(CONFIG_MEDIA_TUNER_TUA9001_MODULE) && defined(MODULE)) extern struct dvb_frontend *tua9001_attach(struct dvb_frontend *fe, diff --git a/drivers/media/common/tuners/tua9001_priv.h b/drivers/media/tuners/tua9001_priv.h index 73cc1ce0575c..73cc1ce0575c 100644 --- a/drivers/media/common/tuners/tua9001_priv.h +++ b/drivers/media/tuners/tua9001_priv.h diff --git a/drivers/media/common/tuners/tuner-i2c.h b/drivers/media/tuners/tuner-i2c.h index 18f005634c67..18f005634c67 100644 --- a/drivers/media/common/tuners/tuner-i2c.h +++ b/drivers/media/tuners/tuner-i2c.h diff --git a/drivers/media/common/tuners/tuner-simple.c b/drivers/media/tuners/tuner-simple.c index 39e7e583c8c0..39e7e583c8c0 100644 --- a/drivers/media/common/tuners/tuner-simple.c +++ b/drivers/media/tuners/tuner-simple.c diff --git a/drivers/media/common/tuners/tuner-simple.h b/drivers/media/tuners/tuner-simple.h index 381fa5d35a9b..381fa5d35a9b 100644 --- a/drivers/media/common/tuners/tuner-simple.h +++ b/drivers/media/tuners/tuner-simple.h diff --git a/drivers/media/common/tuners/tuner-types.c b/drivers/media/tuners/tuner-types.c index 2da4440c16ee..2da4440c16ee 100644 --- a/drivers/media/common/tuners/tuner-types.c +++ b/drivers/media/tuners/tuner-types.c diff --git a/drivers/media/common/tuners/tuner-xc2028-types.h b/drivers/media/tuners/tuner-xc2028-types.h index 74dc46a71f64..74dc46a71f64 100644 --- a/drivers/media/common/tuners/tuner-xc2028-types.h +++ b/drivers/media/tuners/tuner-xc2028-types.h diff --git a/drivers/media/common/tuners/tuner-xc2028.c b/drivers/media/tuners/tuner-xc2028.c index ea0550eafe7d..7bcb6b0ff1df 100644 --- a/drivers/media/common/tuners/tuner-xc2028.c +++ b/drivers/media/tuners/tuner-xc2028.c @@ -1126,8 +1126,7 @@ static int generic_set_freq(struct dvb_frontend *fe, u32 freq /* in HZ */, priv->frequency = freq; - tuner_dbg("divisor= %02x %02x %02x %02x (freq=%d.%03d)\n", - buf[0], buf[1], buf[2], buf[3], + tuner_dbg("divisor= %*ph (freq=%d.%03d)\n", 4, buf, freq / 1000000, (freq % 1000000) / 1000); rc = 0; @@ -1414,8 +1413,8 @@ static int xc2028_set_config(struct dvb_frontend *fe, void *priv_cfg) tuner_err("Failed to request firmware %s\n", priv->fname); priv->state = XC2028_NODEV; - } - priv->state = XC2028_WAITING_FIRMWARE; + } else + priv->state = XC2028_WAITING_FIRMWARE; } mutex_unlock(&priv->lock); diff --git a/drivers/media/common/tuners/tuner-xc2028.h b/drivers/media/tuners/tuner-xc2028.h index 9ebfb2d0ff14..9ebfb2d0ff14 100644 --- a/drivers/media/common/tuners/tuner-xc2028.h +++ b/drivers/media/tuners/tuner-xc2028.h diff --git a/drivers/media/common/tuners/xc4000.c b/drivers/media/tuners/xc4000.c index 68397110b7d9..4937712278f6 100644 --- a/drivers/media/common/tuners/xc4000.c +++ b/drivers/media/tuners/xc4000.c @@ -263,8 +263,7 @@ static int xc_send_i2c_data(struct xc4000_priv *priv, u8 *buf, int len) printk(KERN_ERR "xc4000: I2C write failed (len=%i)\n", len); if (len == 4) { - printk(KERN_ERR "bytes %02x %02x %02x %02x\n", buf[0], - buf[1], buf[2], buf[3]); + printk(KERN_ERR "bytes %*ph\n", 4, buf); } return -EREMOTEIO; } diff --git a/drivers/media/common/tuners/xc4000.h b/drivers/media/tuners/xc4000.h index e6a44d151cbd..e6a44d151cbd 100644 --- a/drivers/media/common/tuners/xc4000.h +++ b/drivers/media/tuners/xc4000.h diff --git a/drivers/media/common/tuners/xc5000.c b/drivers/media/tuners/xc5000.c index 362a8d7c9738..dc93cf338f36 100644 --- a/drivers/media/common/tuners/xc5000.c +++ b/drivers/media/tuners/xc5000.c @@ -62,6 +62,9 @@ struct xc5000_priv { u8 radio_input; int chip_id; + u16 pll_register_no; + u8 init_status_supported; + u8 fw_checksum_supported; }; /* Misc Defines */ @@ -111,6 +114,9 @@ struct xc5000_priv { #define XREG_PRODUCT_ID 0x08 #define XREG_BUSY 0x09 #define XREG_BUILD 0x0D +#define XREG_TOTALGAIN 0x0F +#define XREG_FW_CHECKSUM 0x12 +#define XREG_INIT_STATUS 0x13 /* Basic firmware description. This will remain with @@ -208,18 +214,25 @@ static struct XC_TV_STANDARD XC5000_Standard[MAX_TV_STANDARD] = { struct xc5000_fw_cfg { char *name; u16 size; + u16 pll_reg; + u8 init_status_supported; + u8 fw_checksum_supported; }; #define XC5000A_FIRMWARE "dvb-fe-xc5000-1.6.114.fw" static const struct xc5000_fw_cfg xc5000a_1_6_114 = { .name = XC5000A_FIRMWARE, .size = 12401, + .pll_reg = 0x806c, }; -#define XC5000C_FIRMWARE "dvb-fe-xc5000c-41.024.5.fw" +#define XC5000C_FIRMWARE "dvb-fe-xc5000c-4.1.30.7.fw" static const struct xc5000_fw_cfg xc5000c_41_024_5 = { .name = XC5000C_FIRMWARE, .size = 16497, + .pll_reg = 0x13, + .init_status_supported = 1, + .fw_checksum_supported = 1, }; static inline const struct xc5000_fw_cfg *xc5000_assign_firmware(int chip_id) @@ -233,7 +246,7 @@ static inline const struct xc5000_fw_cfg *xc5000_assign_firmware(int chip_id) } } -static int xc_load_fw_and_init_tuner(struct dvb_frontend *fe); +static int xc_load_fw_and_init_tuner(struct dvb_frontend *fe, int force); static int xc5000_is_firmware_loaded(struct dvb_frontend *fe); static int xc5000_readreg(struct xc5000_priv *priv, u16 reg, u16 *val); static int xc5000_TunerReset(struct dvb_frontend *fe); @@ -342,7 +355,7 @@ static int xc_write_reg(struct xc5000_priv *priv, u16 regAddr, u16 i2cData) } } } - if (WatchDogTimer < 0) + if (WatchDogTimer <= 0) result = XC_RESULT_I2C_WRITE_FAILURE; return result; @@ -541,6 +554,16 @@ static int xc_get_quality(struct xc5000_priv *priv, u16 *quality) return xc5000_readreg(priv, XREG_QUALITY, quality); } +static int xc_get_analogsnr(struct xc5000_priv *priv, u16 *snr) +{ + return xc5000_readreg(priv, XREG_SNR, snr); +} + +static int xc_get_totalgain(struct xc5000_priv *priv, u16 *totalgain) +{ + return xc5000_readreg(priv, XREG_TOTALGAIN, totalgain); +} + static u16 WaitForLock(struct xc5000_priv *priv) { u16 lockState = 0; @@ -608,6 +631,9 @@ static int xc5000_fwupload(struct dvb_frontend *fe) int ret; const struct xc5000_fw_cfg *desired_fw = xc5000_assign_firmware(priv->chip_id); + priv->pll_register_no = desired_fw->pll_reg; + priv->init_status_supported = desired_fw->init_status_supported; + priv->fw_checksum_supported = desired_fw->fw_checksum_supported; /* request the firmware, this will block and timeout */ printk(KERN_INFO "xc5000: waiting for firmware upload (%s)...\n", @@ -652,9 +678,12 @@ static void xc_debug_dump(struct xc5000_priv *priv) u32 hsync_freq_hz = 0; u16 frame_lines; u16 quality; + u16 snr; + u16 totalgain; u8 hw_majorversion = 0, hw_minorversion = 0; u8 fw_majorversion = 0, fw_minorversion = 0; u16 fw_buildversion = 0; + u16 regval; /* Wait for stats to stabilize. * Frame Lines needs two frame times after initial lock @@ -675,7 +704,7 @@ static void xc_debug_dump(struct xc5000_priv *priv) xc_get_version(priv, &hw_majorversion, &hw_minorversion, &fw_majorversion, &fw_minorversion); xc_get_buildversion(priv, &fw_buildversion); - dprintk(1, "*** HW: V%02x.%02x, FW: V%02x.%02x.%04x\n", + dprintk(1, "*** HW: V%d.%d, FW: V %d.%d.%d\n", hw_majorversion, hw_minorversion, fw_majorversion, fw_minorversion, fw_buildversion); @@ -686,7 +715,19 @@ static void xc_debug_dump(struct xc5000_priv *priv) dprintk(1, "*** Frame lines = %d\n", frame_lines); xc_get_quality(priv, &quality); - dprintk(1, "*** Quality (0:<8dB, 7:>56dB) = %d\n", quality); + dprintk(1, "*** Quality (0:<8dB, 7:>56dB) = %d\n", quality & 0x07); + + xc_get_analogsnr(priv, &snr); + dprintk(1, "*** Unweighted analog SNR = %d dB\n", snr & 0x3f); + + xc_get_totalgain(priv, &totalgain); + dprintk(1, "*** Total gain = %d.%d dB\n", totalgain / 256, + (totalgain % 256) * 100 / 256); + + if (priv->pll_register_no) { + xc5000_readreg(priv, priv->pll_register_no, ®val); + dprintk(1, "*** PLL lock status = 0x%04x\n", regval); + } } static int xc5000_set_params(struct dvb_frontend *fe) @@ -697,11 +738,9 @@ static int xc5000_set_params(struct dvb_frontend *fe) u32 freq = fe->dtv_property_cache.frequency; u32 delsys = fe->dtv_property_cache.delivery_system; - if (xc5000_is_firmware_loaded(fe) != XC_RESULT_SUCCESS) { - if (xc_load_fw_and_init_tuner(fe) != XC_RESULT_SUCCESS) { - dprintk(1, "Unable to load firmware and init tuner\n"); - return -EINVAL; - } + if (xc_load_fw_and_init_tuner(fe, 0) != XC_RESULT_SUCCESS) { + dprintk(1, "Unable to load firmware and init tuner\n"); + return -EINVAL; } dprintk(1, "%s() frequency=%d (Hz)\n", __func__, freq); @@ -832,6 +871,7 @@ static int xc5000_set_tv_freq(struct dvb_frontend *fe, struct analog_parameters *params) { struct xc5000_priv *priv = fe->tuner_priv; + u16 pll_lock_status; int ret; dprintk(1, "%s() frequency=%d (in units of 62.5khz)\n", @@ -912,6 +952,21 @@ tune_channel: if (debug) xc_debug_dump(priv); + if (priv->pll_register_no != 0) { + msleep(20); + xc5000_readreg(priv, priv->pll_register_no, &pll_lock_status); + if (pll_lock_status > 63) { + /* PLL is unlocked, force reload of the firmware */ + dprintk(1, "xc5000: PLL not locked (0x%x). Reloading...\n", + pll_lock_status); + if (xc_load_fw_and_init_tuner(fe, 1) != XC_RESULT_SUCCESS) { + printk(KERN_ERR "xc5000: Unable to reload fw\n"); + return -EREMOTEIO; + } + goto tune_channel; + } + } + return 0; } @@ -982,11 +1037,9 @@ static int xc5000_set_analog_params(struct dvb_frontend *fe, if (priv->i2c_props.adap == NULL) return -EINVAL; - if (xc5000_is_firmware_loaded(fe) != XC_RESULT_SUCCESS) { - if (xc_load_fw_and_init_tuner(fe) != XC_RESULT_SUCCESS) { - dprintk(1, "Unable to load firmware and init tuner\n"); - return -EINVAL; - } + if (xc_load_fw_and_init_tuner(fe, 0) != XC_RESULT_SUCCESS) { + dprintk(1, "Unable to load firmware and init tuner\n"); + return -EINVAL; } switch (params->mode) { @@ -1042,29 +1095,77 @@ static int xc5000_get_status(struct dvb_frontend *fe, u32 *status) return 0; } -static int xc_load_fw_and_init_tuner(struct dvb_frontend *fe) +static int xc_load_fw_and_init_tuner(struct dvb_frontend *fe, int force) { struct xc5000_priv *priv = fe->tuner_priv; - int ret = 0; + int ret = XC_RESULT_SUCCESS; + u16 pll_lock_status; + u16 fw_ck; + + if (force || xc5000_is_firmware_loaded(fe) != XC_RESULT_SUCCESS) { + +fw_retry: - if (xc5000_is_firmware_loaded(fe) != XC_RESULT_SUCCESS) { ret = xc5000_fwupload(fe); if (ret != XC_RESULT_SUCCESS) return ret; - } - /* Start the tuner self-calibration process */ - ret |= xc_initialize(priv); + msleep(20); - /* Wait for calibration to complete. - * We could continue but XC5000 will clock stretch subsequent - * I2C transactions until calibration is complete. This way we - * don't have to rely on clock stretching working. - */ - xc_wait(100); + if (priv->fw_checksum_supported) { + if (xc5000_readreg(priv, XREG_FW_CHECKSUM, &fw_ck) + != XC_RESULT_SUCCESS) { + dprintk(1, "%s() FW checksum reading failed.\n", + __func__); + goto fw_retry; + } + + if (fw_ck == 0) { + dprintk(1, "%s() FW checksum failed = 0x%04x\n", + __func__, fw_ck); + goto fw_retry; + } + } + + /* Start the tuner self-calibration process */ + ret |= xc_initialize(priv); - /* Default to "CABLE" mode */ - ret |= xc_write_reg(priv, XREG_SIGNALSOURCE, XC_RF_MODE_CABLE); + if (ret != XC_RESULT_SUCCESS) + goto fw_retry; + + /* Wait for calibration to complete. + * We could continue but XC5000 will clock stretch subsequent + * I2C transactions until calibration is complete. This way we + * don't have to rely on clock stretching working. + */ + xc_wait(100); + + if (priv->init_status_supported) { + if (xc5000_readreg(priv, XREG_INIT_STATUS, &fw_ck) != XC_RESULT_SUCCESS) { + dprintk(1, "%s() FW failed reading init status.\n", + __func__); + goto fw_retry; + } + + if (fw_ck == 0) { + dprintk(1, "%s() FW init status failed = 0x%04x\n", __func__, fw_ck); + goto fw_retry; + } + } + + if (priv->pll_register_no) { + xc5000_readreg(priv, priv->pll_register_no, + &pll_lock_status); + if (pll_lock_status > 63) { + /* PLL is unlocked, force reload of the firmware */ + printk(KERN_ERR "xc5000: PLL not running after fwload.\n"); + goto fw_retry; + } + } + + /* Default to "CABLE" mode */ + ret |= xc_write_reg(priv, XREG_SIGNALSOURCE, XC_RF_MODE_CABLE); + } return ret; } @@ -1097,7 +1198,7 @@ static int xc5000_init(struct dvb_frontend *fe) struct xc5000_priv *priv = fe->tuner_priv; dprintk(1, "%s()\n", __func__); - if (xc_load_fw_and_init_tuner(fe) != XC_RESULT_SUCCESS) { + if (xc_load_fw_and_init_tuner(fe, 0) != XC_RESULT_SUCCESS) { printk(KERN_ERR "xc5000: Unable to initialise tuner\n"); return -EREMOTEIO; } diff --git a/drivers/media/common/tuners/xc5000.h b/drivers/media/tuners/xc5000.h index b1a547494625..b1a547494625 100644 --- a/drivers/media/common/tuners/xc5000.h +++ b/drivers/media/tuners/xc5000.h diff --git a/drivers/media/usb/Kconfig b/drivers/media/usb/Kconfig new file mode 100644 index 000000000000..6746994d03fe --- /dev/null +++ b/drivers/media/usb/Kconfig @@ -0,0 +1,54 @@ +menuconfig MEDIA_USB_SUPPORT + bool "Media USB Adapters" + depends on USB && MEDIA_SUPPORT + help + Enable media drivers for USB bus. + If you have such devices, say Y. + +if MEDIA_USB_SUPPORT + +if MEDIA_CAMERA_SUPPORT + comment "Webcam devices" +source "drivers/media/usb/uvc/Kconfig" +source "drivers/media/usb/gspca/Kconfig" +source "drivers/media/usb/pwc/Kconfig" +source "drivers/media/usb/cpia2/Kconfig" +source "drivers/media/usb/zr364xx/Kconfig" +source "drivers/media/usb/stkwebcam/Kconfig" +source "drivers/media/usb/s2255/Kconfig" +source "drivers/media/usb/sn9c102/Kconfig" +endif + +if MEDIA_ANALOG_TV_SUPPORT + comment "Analog TV USB devices" +source "drivers/media/usb/au0828/Kconfig" +source "drivers/media/usb/pvrusb2/Kconfig" +source "drivers/media/usb/hdpvr/Kconfig" +source "drivers/media/usb/tlg2300/Kconfig" +source "drivers/media/usb/usbvision/Kconfig" +source "drivers/media/usb/stk1160/Kconfig" +endif + +if (MEDIA_ANALOG_TV_SUPPORT || MEDIA_DIGITAL_TV_SUPPORT) + comment "Analog/digital TV USB devices" +source "drivers/media/usb/cx231xx/Kconfig" +source "drivers/media/usb/tm6000/Kconfig" +endif + + +if I2C && MEDIA_DIGITAL_TV_SUPPORT + comment "Digital TV USB devices" +source "drivers/media/usb/dvb-usb/Kconfig" +source "drivers/media/usb/dvb-usb-v2/Kconfig" +source "drivers/media/usb/ttusb-budget/Kconfig" +source "drivers/media/usb/ttusb-dec/Kconfig" +source "drivers/media/usb/siano/Kconfig" +source "drivers/media/usb/b2c2/Kconfig" +endif + +if (MEDIA_CAMERA_SUPPORT || MEDIA_ANALOG_TV_SUPPORT || MEDIA_DIGITAL_TV_SUPPORT) + comment "Webcam, TV (analog/digital) USB devices" +source "drivers/media/usb/em28xx/Kconfig" +endif + +endif #MEDIA_USB_SUPPORT diff --git a/drivers/media/usb/Makefile b/drivers/media/usb/Makefile new file mode 100644 index 000000000000..7f51d7e5f739 --- /dev/null +++ b/drivers/media/usb/Makefile @@ -0,0 +1,22 @@ +# +# Makefile for the USB media device drivers +# + +# DVB USB-only drivers +obj-y += ttusb-dec/ ttusb-budget/ dvb-usb/ dvb-usb-v2/ siano/ b2c2/ +obj-y += zr364xx/ stkwebcam/ s2255/ + +obj-$(CONFIG_USB_VIDEO_CLASS) += uvc/ +obj-$(CONFIG_USB_GSPCA) += gspca/ +obj-$(CONFIG_USB_PWC) += pwc/ +obj-$(CONFIG_VIDEO_CPIA2) += cpia2/ +obj-$(CONFIG_USB_SN9C102) += sn9c102/ +obj-$(CONFIG_VIDEO_AU0828) += au0828/ +obj-$(CONFIG_VIDEO_HDPVR) += hdpvr/ +obj-$(CONFIG_VIDEO_PVRUSB2) += pvrusb2/ +obj-$(CONFIG_VIDEO_TLG2300) += tlg2300/ +obj-$(CONFIG_VIDEO_USBVISION) += usbvision/ +obj-$(CONFIG_VIDEO_STK1160) += stk1160/ +obj-$(CONFIG_VIDEO_CX231XX) += cx231xx/ +obj-$(CONFIG_VIDEO_TM6000) += tm6000/ +obj-$(CONFIG_VIDEO_EM28XX) += em28xx/ diff --git a/drivers/media/video/au0828/Kconfig b/drivers/media/usb/au0828/Kconfig index 23f7fd22f0eb..1766c0ce93be 100644 --- a/drivers/media/video/au0828/Kconfig +++ b/drivers/media/usb/au0828/Kconfig @@ -2,15 +2,14 @@ config VIDEO_AU0828 tristate "Auvitek AU0828 support" depends on I2C && INPUT && DVB_CORE && USB && VIDEO_V4L2 - depends on DVB_CAPTURE_DRIVERS select I2C_ALGOBIT select VIDEO_TVEEPROM select VIDEOBUF_VMALLOC - select DVB_AU8522_DTV if !DVB_FE_CUSTOMISE - select DVB_AU8522_V4L if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_XC5000 if !MEDIA_TUNER_CUSTOMISE - select MEDIA_TUNER_MXL5007T if !MEDIA_TUNER_CUSTOMISE - select MEDIA_TUNER_TDA18271 if !MEDIA_TUNER_CUSTOMISE + select DVB_AU8522_DTV if MEDIA_SUBDRV_AUTOSELECT + select DVB_AU8522_V4L if MEDIA_SUBDRV_AUTOSELECT + select MEDIA_TUNER_XC5000 if MEDIA_SUBDRV_AUTOSELECT + select MEDIA_TUNER_MXL5007T if MEDIA_SUBDRV_AUTOSELECT + select MEDIA_TUNER_TDA18271 if MEDIA_SUBDRV_AUTOSELECT ---help--- This is a video4linux driver for Auvitek's USB device. diff --git a/drivers/media/video/au0828/Makefile b/drivers/media/usb/au0828/Makefile index bd22223f8d9f..98cc20cc0ffb 100644 --- a/drivers/media/video/au0828/Makefile +++ b/drivers/media/usb/au0828/Makefile @@ -2,8 +2,8 @@ au0828-objs := au0828-core.o au0828-i2c.o au0828-cards.o au0828-dvb.o au0828-vid obj-$(CONFIG_VIDEO_AU0828) += au0828.o -ccflags-y += -Idrivers/media/common/tuners -ccflags-y += -Idrivers/media/dvb/dvb-core -ccflags-y += -Idrivers/media/dvb/frontends +ccflags-y += -Idrivers/media/tuners +ccflags-y += -Idrivers/media/dvb-core +ccflags-y += -Idrivers/media/dvb-frontends ccflags-y += $(extra-cflags-y) $(extra-cflags-m) diff --git a/drivers/media/video/au0828/au0828-cards.c b/drivers/media/usb/au0828/au0828-cards.c index e3fe9a6637f6..448361c6a13e 100644 --- a/drivers/media/video/au0828/au0828-cards.c +++ b/drivers/media/usb/au0828/au0828-cards.c @@ -46,7 +46,7 @@ struct au0828_board au0828_boards[] = { .name = "Hauppauge HVR850", .tuner_type = TUNER_XC5000, .tuner_addr = 0x61, - .i2c_clk_divider = AU0828_I2C_CLK_30KHZ, + .i2c_clk_divider = AU0828_I2C_CLK_20KHZ, .input = { { .type = AU0828_VMUX_TELEVISION, @@ -77,7 +77,7 @@ struct au0828_board au0828_boards[] = { stretch fits inside of a normal clock cycle, or else the au0828 fails to set the STOP bit. A 30 KHz clock puts the clock pulse width at 18us */ - .i2c_clk_divider = AU0828_I2C_CLK_30KHZ, + .i2c_clk_divider = AU0828_I2C_CLK_20KHZ, .input = { { .type = AU0828_VMUX_TELEVISION, diff --git a/drivers/media/video/au0828/au0828-cards.h b/drivers/media/usb/au0828/au0828-cards.h index 48a1882c2b6b..48a1882c2b6b 100644 --- a/drivers/media/video/au0828/au0828-cards.h +++ b/drivers/media/usb/au0828/au0828-cards.h diff --git a/drivers/media/video/au0828/au0828-core.c b/drivers/media/usb/au0828/au0828-core.c index 1e4ce5068ec2..745a80a798c8 100644 --- a/drivers/media/video/au0828/au0828-core.c +++ b/drivers/media/usb/au0828/au0828-core.c @@ -46,7 +46,7 @@ MODULE_PARM_DESC(disable_usb_speed_check, #define _BULKPIPESIZE 0xffff static int send_control_msg(struct au0828_dev *dev, u16 request, u32 value, - u16 index, unsigned char *cp, u16 size); + u16 index); static int recv_control_msg(struct au0828_dev *dev, u16 request, u32 value, u16 index, unsigned char *cp, u16 size); @@ -56,41 +56,25 @@ static int recv_control_msg(struct au0828_dev *dev, u16 request, u32 value, u32 au0828_readreg(struct au0828_dev *dev, u16 reg) { - recv_control_msg(dev, CMD_REQUEST_IN, 0, reg, dev->ctrlmsg, 1); - dprintk(8, "%s(0x%04x) = 0x%02x\n", __func__, reg, dev->ctrlmsg[0]); - return dev->ctrlmsg[0]; + u8 result = 0; + + recv_control_msg(dev, CMD_REQUEST_IN, 0, reg, &result, 1); + dprintk(8, "%s(0x%04x) = 0x%02x\n", __func__, reg, result); + + return result; } u32 au0828_writereg(struct au0828_dev *dev, u16 reg, u32 val) { dprintk(8, "%s(0x%04x, 0x%02x)\n", __func__, reg, val); - return send_control_msg(dev, CMD_REQUEST_OUT, val, reg, - dev->ctrlmsg, 0); -} - -static void cmd_msg_dump(struct au0828_dev *dev) -{ - int i; - - for (i = 0; i < sizeof(dev->ctrlmsg); i += 16) - dprintk(2, "%s() %02x %02x %02x %02x %02x %02x %02x %02x " - "%02x %02x %02x %02x %02x %02x %02x %02x\n", - __func__, - dev->ctrlmsg[i+0], dev->ctrlmsg[i+1], - dev->ctrlmsg[i+2], dev->ctrlmsg[i+3], - dev->ctrlmsg[i+4], dev->ctrlmsg[i+5], - dev->ctrlmsg[i+6], dev->ctrlmsg[i+7], - dev->ctrlmsg[i+8], dev->ctrlmsg[i+9], - dev->ctrlmsg[i+10], dev->ctrlmsg[i+11], - dev->ctrlmsg[i+12], dev->ctrlmsg[i+13], - dev->ctrlmsg[i+14], dev->ctrlmsg[i+15]); + return send_control_msg(dev, CMD_REQUEST_OUT, val, reg); } static int send_control_msg(struct au0828_dev *dev, u16 request, u32 value, - u16 index, unsigned char *cp, u16 size) + u16 index) { int status = -ENODEV; - mutex_lock(&dev->mutex); + if (dev->usbdev) { /* cp must be memory that has been allocated by kmalloc */ @@ -99,8 +83,7 @@ static int send_control_msg(struct au0828_dev *dev, u16 request, u32 value, request, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - value, index, - cp, size, 1000); + value, index, NULL, 0, 1000); status = min(status, 0); @@ -110,7 +93,7 @@ static int send_control_msg(struct au0828_dev *dev, u16 request, u32 value, } } - mutex_unlock(&dev->mutex); + return status; } @@ -120,24 +103,23 @@ static int recv_control_msg(struct au0828_dev *dev, u16 request, u32 value, int status = -ENODEV; mutex_lock(&dev->mutex); if (dev->usbdev) { - - memset(dev->ctrlmsg, 0, sizeof(dev->ctrlmsg)); - - /* cp must be memory that has been allocated by kmalloc */ status = usb_control_msg(dev->usbdev, usb_rcvctrlpipe(dev->usbdev, 0), request, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, value, index, - cp, size, 1000); + dev->ctrlmsg, size, 1000); status = min(status, 0); if (status < 0) { printk(KERN_ERR "%s() Failed receiving control message, error %d.\n", __func__, status); - } else - cmd_msg_dump(dev); + } + + /* the host controller requires heap allocated memory, which + is why we didn't just pass "cp" into usb_control_msg */ + memcpy(cp, dev->ctrlmsg, size); } mutex_unlock(&dev->mutex); return status; @@ -205,6 +187,8 @@ static int au0828_usb_probe(struct usb_interface *interface, return -ENOMEM; } + mutex_init(&dev->lock); + mutex_lock(&dev->lock); mutex_init(&dev->mutex); mutex_init(&dev->dvb.lock); dev->usbdev = usbdev; @@ -215,6 +199,7 @@ static int au0828_usb_probe(struct usb_interface *interface, if (retval) { printk(KERN_ERR "%s() v4l2_device_register failed\n", __func__); + mutex_unlock(&dev->lock); kfree(dev); return -EIO; } @@ -245,6 +230,8 @@ static int au0828_usb_probe(struct usb_interface *interface, printk(KERN_INFO "Registered device AU0828 [%s]\n", dev->board.name == NULL ? "Unset" : dev->board.name); + mutex_unlock(&dev->lock); + return 0; } diff --git a/drivers/media/video/au0828/au0828-dvb.c b/drivers/media/usb/au0828/au0828-dvb.c index 39ece8e24985..b328f6550d0b 100644 --- a/drivers/media/video/au0828/au0828-dvb.c +++ b/drivers/media/usb/au0828/au0828-dvb.c @@ -101,11 +101,14 @@ static struct tda18271_config hauppauge_woodbury_tunerconfig = { .gate = TDA18271_GATE_DIGITAL, }; +static void au0828_restart_dvb_streaming(struct work_struct *work); + /*-------------------------------------------------------------------*/ static void urb_completion(struct urb *purb) { struct au0828_dev *dev = purb->context; int ptype = usb_pipetype(purb->pipe); + unsigned char *ptr; dprintk(2, "%s()\n", __func__); @@ -121,6 +124,16 @@ static void urb_completion(struct urb *purb) return; } + /* See if the stream is corrupted (to work around a hardware + bug where the stream gets misaligned */ + ptr = purb->transfer_buffer; + if (purb->actual_length > 0 && ptr[0] != 0x47) { + dprintk(1, "Need to restart streaming %02x len=%d!\n", + ptr[0], purb->actual_length); + schedule_work(&dev->restart_streaming); + return; + } + /* Feed the transport payload into the kernel demux */ dvb_dmx_swfilter_packets(&dev->dvb.demux, purb->transfer_buffer, purb->actual_length / 188); @@ -138,14 +151,13 @@ static int stop_urb_transfer(struct au0828_dev *dev) dprintk(2, "%s()\n", __func__); + dev->urb_streaming = 0; for (i = 0; i < URB_COUNT; i++) { usb_kill_urb(dev->urbs[i]); kfree(dev->urbs[i]->transfer_buffer); usb_free_urb(dev->urbs[i]); } - dev->urb_streaming = 0; - return 0; } @@ -246,11 +258,8 @@ static int au0828_dvb_stop_feed(struct dvb_demux_feed *feed) mutex_lock(&dvb->lock); if (--dvb->feeding == 0) { /* Stop transport */ - au0828_write(dev, 0x608, 0x00); - au0828_write(dev, 0x609, 0x00); - au0828_write(dev, 0x60a, 0x00); - au0828_write(dev, 0x60b, 0x00); ret = stop_urb_transfer(dev); + au0828_write(dev, 0x60b, 0x00); } mutex_unlock(&dvb->lock); } @@ -258,6 +267,37 @@ static int au0828_dvb_stop_feed(struct dvb_demux_feed *feed) return ret; } +static void au0828_restart_dvb_streaming(struct work_struct *work) +{ + struct au0828_dev *dev = container_of(work, struct au0828_dev, + restart_streaming); + struct au0828_dvb *dvb = &dev->dvb; + int ret; + + if (dev->urb_streaming == 0) + return; + + dprintk(1, "Restarting streaming...!\n"); + + mutex_lock(&dvb->lock); + + /* Stop transport */ + ret = stop_urb_transfer(dev); + au0828_write(dev, 0x608, 0x00); + au0828_write(dev, 0x609, 0x00); + au0828_write(dev, 0x60a, 0x00); + au0828_write(dev, 0x60b, 0x00); + + /* Start transport */ + au0828_write(dev, 0x608, 0x90); + au0828_write(dev, 0x609, 0x72); + au0828_write(dev, 0x60a, 0x71); + au0828_write(dev, 0x60b, 0x01); + ret = start_urb_transfer(dev); + + mutex_unlock(&dvb->lock); +} + static int dvb_register(struct au0828_dev *dev) { struct au0828_dvb *dvb = &dev->dvb; @@ -265,6 +305,8 @@ static int dvb_register(struct au0828_dev *dev) dprintk(1, "%s()\n", __func__); + INIT_WORK(&dev->restart_streaming, au0828_restart_dvb_streaming); + /* register adapter */ result = dvb_register_adapter(&dvb->adapter, DRIVER_NAME, THIS_MODULE, &dev->usbdev->dev, adapter_nr); diff --git a/drivers/media/video/au0828/au0828-i2c.c b/drivers/media/usb/au0828/au0828-i2c.c index 05c299fa5d79..4ded17fe1957 100644 --- a/drivers/media/video/au0828/au0828-i2c.c +++ b/drivers/media/usb/au0828/au0828-i2c.c @@ -26,15 +26,15 @@ #include <linux/io.h> #include "au0828.h" - +#include "media/tuner.h" #include <media/v4l2-common.h> static int i2c_scan; module_param(i2c_scan, int, 0444); MODULE_PARM_DESC(i2c_scan, "scan i2c bus at insmod time"); -#define I2C_WAIT_DELAY 512 -#define I2C_WAIT_RETRY 64 +#define I2C_WAIT_DELAY 25 +#define I2C_WAIT_RETRY 1000 static inline int i2c_slave_did_write_ack(struct i2c_adapter *i2c_adap) { @@ -147,8 +147,19 @@ static int i2c_sendbytes(struct i2c_adapter *i2c_adap, au0828_write(dev, AU0828_I2C_MULTIBYTE_MODE_2FF, 0x01); /* Set the I2C clock */ - au0828_write(dev, AU0828_I2C_CLK_DIVIDER_202, - dev->board.i2c_clk_divider); + if (((dev->board.tuner_type == TUNER_XC5000) || + (dev->board.tuner_type == TUNER_XC5000C)) && + (dev->board.tuner_addr == msg->addr) && + (msg->len == 64)) { + /* Hack to speed up firmware load. The xc5000 lets us do up + to 400 KHz when in firmware download mode */ + au0828_write(dev, AU0828_I2C_CLK_DIVIDER_202, + AU0828_I2C_CLK_250KHZ); + } else { + /* Use the i2c clock speed in the board configuration */ + au0828_write(dev, AU0828_I2C_CLK_DIVIDER_202, + dev->board.i2c_clk_divider); + } /* Hardware needs 8 bit addresses */ au0828_write(dev, AU0828_I2C_DEST_ADDR_203, msg->addr << 1); diff --git a/drivers/media/video/au0828/au0828-reg.h b/drivers/media/usb/au0828/au0828-reg.h index c39f3d2b721e..2140f4cfb645 100644 --- a/drivers/media/video/au0828/au0828-reg.h +++ b/drivers/media/usb/au0828/au0828-reg.h @@ -63,3 +63,4 @@ #define AU0828_I2C_CLK_250KHZ 0x07 #define AU0828_I2C_CLK_100KHZ 0x14 #define AU0828_I2C_CLK_30KHZ 0x40 +#define AU0828_I2C_CLK_20KHZ 0x60 diff --git a/drivers/media/video/au0828/au0828-vbi.c b/drivers/media/usb/au0828/au0828-vbi.c index 63f593070ee8..63f593070ee8 100644 --- a/drivers/media/video/au0828/au0828-vbi.c +++ b/drivers/media/usb/au0828/au0828-vbi.c diff --git a/drivers/media/video/au0828/au0828-video.c b/drivers/media/usb/au0828/au0828-video.c index ac3dd733ab81..870585570571 100644 --- a/drivers/media/video/au0828/au0828-video.c +++ b/drivers/media/usb/au0828/au0828-video.c @@ -864,17 +864,15 @@ static int res_get(struct au0828_fh *fh, unsigned int bit) return 1; /* is it free? */ - mutex_lock(&dev->lock); if (dev->resources & bit) { /* no, someone else uses it */ - mutex_unlock(&dev->lock); return 0; } /* it's free, grab it */ fh->resources |= bit; dev->resources |= bit; dprintk(1, "res: get %d\n", bit); - mutex_unlock(&dev->lock); + return 1; } @@ -894,11 +892,9 @@ static void res_free(struct au0828_fh *fh, unsigned int bits) BUG_ON((fh->resources & bits) != bits); - mutex_lock(&dev->lock); fh->resources &= ~bits; dev->resources &= ~bits; dprintk(1, "res: put %d\n", bits); - mutex_unlock(&dev->lock); } static int get_ressource(struct au0828_fh *fh) @@ -1023,7 +1019,8 @@ static int au0828_v4l2_open(struct file *filp) NULL, &dev->slock, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_INTERLACED, - sizeof(struct au0828_buffer), fh, NULL); + sizeof(struct au0828_buffer), fh, + &dev->lock); /* VBI Setup */ dev->vbi_width = 720; @@ -1032,8 +1029,8 @@ static int au0828_v4l2_open(struct file *filp) NULL, &dev->slock, V4L2_BUF_TYPE_VBI_CAPTURE, V4L2_FIELD_SEQ_TB, - sizeof(struct au0828_buffer), fh, NULL); - + sizeof(struct au0828_buffer), fh, + &dev->lock); return ret; } @@ -1312,8 +1309,6 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, if (rc < 0) return rc; - mutex_lock(&dev->lock); - if (videobuf_queue_is_busy(&fh->vb_vidq)) { printk(KERN_INFO "%s queue busy\n", __func__); rc = -EBUSY; @@ -1322,7 +1317,6 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, rc = au0828_set_format(dev, VIDIOC_S_FMT, f); out: - mutex_unlock(&dev->lock); return rc; } @@ -1331,11 +1325,19 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id * norm) struct au0828_fh *fh = priv; struct au0828_dev *dev = fh->dev; + if (dev->dvb.frontend && dev->dvb.frontend->ops.analog_ops.i2c_gate_ctrl) + dev->dvb.frontend->ops.analog_ops.i2c_gate_ctrl(dev->dvb.frontend, 1); + /* FIXME: when we support something other than NTSC, we are going to have to make the au0828 bridge adjust the size of its capture buffer, which is currently hardcoded at 720x480 */ v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_std, *norm); + dev->std_set_in_tuner_core = 1; + + if (dev->dvb.frontend && dev->dvb.frontend->ops.analog_ops.i2c_gate_ctrl) + dev->dvb.frontend->ops.analog_ops.i2c_gate_ctrl(dev->dvb.frontend, 0); + return 0; } @@ -1463,7 +1465,7 @@ static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a) return 0; } -static int vidioc_s_audio(struct file *file, void *priv, struct v4l2_audio *a) +static int vidioc_s_audio(struct file *file, void *priv, const struct v4l2_audio *a) { struct au0828_fh *fh = priv; struct au0828_dev *dev = fh->dev; @@ -1515,9 +1517,18 @@ static int vidioc_s_tuner(struct file *file, void *priv, return -EINVAL; t->type = V4L2_TUNER_ANALOG_TV; + + if (dev->dvb.frontend && dev->dvb.frontend->ops.analog_ops.i2c_gate_ctrl) + dev->dvb.frontend->ops.analog_ops.i2c_gate_ctrl(dev->dvb.frontend, 1); + v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_tuner, t); + + if (dev->dvb.frontend && dev->dvb.frontend->ops.analog_ops.i2c_gate_ctrl) + dev->dvb.frontend->ops.analog_ops.i2c_gate_ctrl(dev->dvb.frontend, 0); + dprintk(1, "VIDIOC_S_TUNER: signal = %x, afc = %x\n", t->signal, t->afc); + return 0; } @@ -1546,8 +1557,23 @@ static int vidioc_s_frequency(struct file *file, void *priv, dev->ctrl_freq = freq->frequency; + if (dev->dvb.frontend && dev->dvb.frontend->ops.analog_ops.i2c_gate_ctrl) + dev->dvb.frontend->ops.analog_ops.i2c_gate_ctrl(dev->dvb.frontend, 1); + + if (dev->std_set_in_tuner_core == 0) { + /* If we've never sent the standard in tuner core, do so now. We + don't do this at device probe because we don't want to incur + the cost of a firmware load */ + v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_std, + dev->vdev->tvnorms); + dev->std_set_in_tuner_core = 1; + } + v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_frequency, freq); + if (dev->dvb.frontend && dev->dvb.frontend->ops.analog_ops.i2c_gate_ctrl) + dev->dvb.frontend->ops.analog_ops.i2c_gate_ctrl(dev->dvb.frontend, 0); + au0828_analog_stream_reset(dev); return 0; @@ -1692,14 +1718,18 @@ static int vidioc_streamoff(struct file *file, void *priv, (AUVI_INPUT(i).audio_setup)(dev, 0); } - videobuf_streamoff(&fh->vb_vidq); - res_free(fh, AU0828_RESOURCE_VIDEO); + if (res_check(fh, AU0828_RESOURCE_VIDEO)) { + videobuf_streamoff(&fh->vb_vidq); + res_free(fh, AU0828_RESOURCE_VIDEO); + } } else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) { dev->vbi_timeout_running = 0; del_timer_sync(&dev->vbi_timeout); - videobuf_streamoff(&fh->vb_vbiq); - res_free(fh, AU0828_RESOURCE_VBI); + if (res_check(fh, AU0828_RESOURCE_VBI)) { + videobuf_streamoff(&fh->vb_vbiq); + res_free(fh, AU0828_RESOURCE_VBI); + } } return 0; @@ -1717,8 +1747,12 @@ static int vidioc_g_register(struct file *file, void *priv, v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_register, reg); return 0; default: - return -EINVAL; + if (!v4l2_chip_match_host(®->match)) + return -EINVAL; } + + reg->val = au0828_read(dev, reg->reg); + return 0; } static int vidioc_s_register(struct file *file, void *priv, @@ -1732,9 +1766,10 @@ static int vidioc_s_register(struct file *file, void *priv, v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_register, reg); return 0; default: - return -EINVAL; + if (!v4l2_chip_match_host(®->match)) + return -EINVAL; } - return 0; + return au0828_writereg(dev, reg->reg, reg->val); } #endif @@ -1827,7 +1862,7 @@ static struct v4l2_file_operations au0828_v4l_fops = { .read = au0828_v4l2_read, .poll = au0828_v4l2_poll, .mmap = au0828_v4l2_mmap, - .ioctl = video_ioctl2, + .unlocked_ioctl = video_ioctl2, }; static const struct v4l2_ioctl_ops video_ioctl_ops = { @@ -1917,7 +1952,6 @@ int au0828_analog_register(struct au0828_dev *dev, init_waitqueue_head(&dev->open); spin_lock_init(&dev->slock); - mutex_init(&dev->lock); /* init video dma queues */ INIT_LIST_HEAD(&dev->vidq.active); @@ -1958,11 +1992,13 @@ int au0828_analog_register(struct au0828_dev *dev, /* Fill the video capture device struct */ *dev->vdev = au0828_video_template; dev->vdev->parent = &dev->usbdev->dev; + dev->vdev->lock = &dev->lock; strcpy(dev->vdev->name, "au0828a video"); /* Setup the VBI device */ *dev->vbi_dev = au0828_video_template; dev->vbi_dev->parent = &dev->usbdev->dev; + dev->vbi_dev->lock = &dev->lock; strcpy(dev->vbi_dev->name, "au0828a vbi"); /* Register the v4l2 device */ diff --git a/drivers/media/video/au0828/au0828.h b/drivers/media/usb/au0828/au0828.h index 9cde35321824..66a56ef7bbe4 100644 --- a/drivers/media/video/au0828/au0828.h +++ b/drivers/media/usb/au0828/au0828.h @@ -197,6 +197,7 @@ struct au0828_dev { /* Digital */ struct au0828_dvb dvb; + struct work_struct restart_streaming; /* Analog */ struct v4l2_device v4l2_dev; @@ -224,6 +225,7 @@ struct au0828_dev { unsigned int frame_count; int ctrl_freq; int input_type; + int std_set_in_tuner_core; unsigned int ctrl_input; enum au0828_dev_state dev_state; enum au0828_stream_state stream_state; diff --git a/drivers/media/usb/b2c2/Kconfig b/drivers/media/usb/b2c2/Kconfig new file mode 100644 index 000000000000..17d35833980c --- /dev/null +++ b/drivers/media/usb/b2c2/Kconfig @@ -0,0 +1,15 @@ +config DVB_B2C2_FLEXCOP_USB + tristate "Technisat/B2C2 Air/Sky/Cable2PC USB" + depends on DVB_CORE && I2C + help + Support for the Air/Sky/Cable2PC USB1.1 box (DVB/ATSC) by Technisat/B2C2, + + Say Y if you own such a device and want to use it. + +config DVB_B2C2_FLEXCOP_USB_DEBUG + bool "Enable debug for the B2C2 FlexCop drivers" + depends on DVB_B2C2_FLEXCOP_USB + select DVB_B2C2_FLEXCOP_DEBUG + help + Say Y if you want to enable the module option to control debug messages + of all B2C2 FlexCop drivers. diff --git a/drivers/media/usb/b2c2/Makefile b/drivers/media/usb/b2c2/Makefile new file mode 100644 index 000000000000..2778c19a45eb --- /dev/null +++ b/drivers/media/usb/b2c2/Makefile @@ -0,0 +1,5 @@ +b2c2-flexcop-usb-objs := flexcop-usb.o +obj-$(CONFIG_DVB_B2C2_FLEXCOP_USB) += b2c2-flexcop-usb.o + +ccflags-y += -Idrivers/media/dvb-core/ +ccflags-y += -Idrivers/media/common/b2c2/ diff --git a/drivers/media/dvb/b2c2/flexcop-usb.c b/drivers/media/usb/b2c2/flexcop-usb.c index 26c666dd3514..8b6275f85908 100644 --- a/drivers/media/dvb/b2c2/flexcop-usb.c +++ b/drivers/media/usb/b2c2/flexcop-usb.c @@ -324,10 +324,7 @@ static void flexcop_usb_process_frame(struct flexcop_usb *fc_usb, flexcop_pass_dmx_packets( fc_usb->fc_dev, b+2, 1); else - deb_ts( - "not ts packet %02x %02x %02x %02x \n", - *(b+2), *(b+3), - *(b+4), *(b+5)); + deb_ts("not ts packet %*ph\n", 4, b+2); b += 190; l -= 190; break; diff --git a/drivers/media/dvb/b2c2/flexcop-usb.h b/drivers/media/usb/b2c2/flexcop-usb.h index 92529a9c4475..92529a9c4475 100644 --- a/drivers/media/dvb/b2c2/flexcop-usb.h +++ b/drivers/media/usb/b2c2/flexcop-usb.h diff --git a/drivers/media/video/cpia2/Kconfig b/drivers/media/usb/cpia2/Kconfig index 66e9283f5993..66e9283f5993 100644 --- a/drivers/media/video/cpia2/Kconfig +++ b/drivers/media/usb/cpia2/Kconfig diff --git a/drivers/media/video/cpia2/Makefile b/drivers/media/usb/cpia2/Makefile index 828cf1b1df86..828cf1b1df86 100644 --- a/drivers/media/video/cpia2/Makefile +++ b/drivers/media/usb/cpia2/Makefile diff --git a/drivers/media/video/cpia2/cpia2.h b/drivers/media/usb/cpia2/cpia2.h index cdef677d57ec..cdef677d57ec 100644 --- a/drivers/media/video/cpia2/cpia2.h +++ b/drivers/media/usb/cpia2/cpia2.h diff --git a/drivers/media/video/cpia2/cpia2_core.c b/drivers/media/usb/cpia2/cpia2_core.c index 17188e234770..187012ce444b 100644 --- a/drivers/media/video/cpia2/cpia2_core.c +++ b/drivers/media/usb/cpia2/cpia2_core.c @@ -31,11 +31,15 @@ #include "cpia2.h" +#include <linux/module.h> #include <linux/slab.h> #include <linux/mm.h> #include <linux/vmalloc.h> #include <linux/firmware.h> +#define FIRMWARE "cpia2/stv0672_vp4.bin" +MODULE_FIRMWARE(FIRMWARE); + /* #define _CPIA2_DEBUG_ */ #ifdef _CPIA2_DEBUG_ @@ -898,7 +902,7 @@ static int cpia2_send_onebyte_command(struct camera_data *cam, static int apply_vp_patch(struct camera_data *cam) { const struct firmware *fw; - const char fw_name[] = "cpia2/stv0672_vp4.bin"; + const char fw_name[] = FIRMWARE; int i, ret; struct cpia2_command cmd; diff --git a/drivers/media/video/cpia2/cpia2_registers.h b/drivers/media/usb/cpia2/cpia2_registers.h index 3bbec514a967..3bbec514a967 100644 --- a/drivers/media/video/cpia2/cpia2_registers.h +++ b/drivers/media/usb/cpia2/cpia2_registers.h diff --git a/drivers/media/video/cpia2/cpia2_usb.c b/drivers/media/usb/cpia2/cpia2_usb.c index 95b5d6e7cdc4..95b5d6e7cdc4 100644 --- a/drivers/media/video/cpia2/cpia2_usb.c +++ b/drivers/media/usb/cpia2/cpia2_usb.c diff --git a/drivers/media/video/cpia2/cpia2_v4l.c b/drivers/media/usb/cpia2/cpia2_v4l.c index a62a7b739991..aeb9d2275725 100644 --- a/drivers/media/video/cpia2/cpia2_v4l.c +++ b/drivers/media/usb/cpia2/cpia2_v4l.c @@ -84,21 +84,26 @@ MODULE_VERSION(CPIA_VERSION); static int cpia2_open(struct file *file) { struct camera_data *cam = video_drvdata(file); - int retval = v4l2_fh_open(file); + int retval; + if (mutex_lock_interruptible(&cam->v4l2_lock)) + return -ERESTARTSYS; + retval = v4l2_fh_open(file); if (retval) - return retval; + goto open_unlock; if (v4l2_fh_is_singular_file(file)) { if (cpia2_allocate_buffers(cam)) { v4l2_fh_release(file); - return -ENOMEM; + retval = -ENOMEM; + goto open_unlock; } /* reset the camera */ if (cpia2_reset_camera(cam) < 0) { v4l2_fh_release(file); - return -EIO; + retval = -EIO; + goto open_unlock; } cam->APP_len = 0; @@ -106,7 +111,9 @@ static int cpia2_open(struct file *file) } cpia2_dbg_dump_registers(cam); - return 0; +open_unlock: + mutex_unlock(&cam->v4l2_lock); + return retval; } /****************************************************************************** @@ -119,6 +126,7 @@ static int cpia2_close(struct file *file) struct video_device *dev = video_devdata(file); struct camera_data *cam = video_get_drvdata(dev); + mutex_lock(&cam->v4l2_lock); if (video_is_registered(&cam->vdev) && v4l2_fh_is_singular_file(file)) { cpia2_usb_stream_stop(cam); @@ -133,6 +141,7 @@ static int cpia2_close(struct file *file) cam->stream_fh = NULL; cam->mmapped = 0; } + mutex_unlock(&cam->v4l2_lock); return v4l2_fh_release(file); } @@ -146,11 +155,16 @@ static ssize_t cpia2_v4l_read(struct file *file, char __user *buf, size_t count, { struct camera_data *cam = video_drvdata(file); int noblock = file->f_flags&O_NONBLOCK; + ssize_t ret; if(!cam) return -EINVAL; - return cpia2_read(cam, buf, count, noblock); + if (mutex_lock_interruptible(&cam->v4l2_lock)) + return -ERESTARTSYS; + ret = cpia2_read(cam, buf, count, noblock); + mutex_unlock(&cam->v4l2_lock); + return ret; } @@ -162,8 +176,12 @@ static ssize_t cpia2_v4l_read(struct file *file, char __user *buf, size_t count, static unsigned int cpia2_v4l_poll(struct file *filp, struct poll_table_struct *wait) { struct camera_data *cam = video_drvdata(filp); + unsigned int res; - return cpia2_poll(cam, filp, wait); + mutex_lock(&cam->v4l2_lock); + res = cpia2_poll(cam, filp, wait); + mutex_unlock(&cam->v4l2_lock); + return res; } @@ -716,7 +734,8 @@ static int cpia2_g_jpegcomp(struct file *file, void *fh, struct v4l2_jpegcompres * *****************************************************************************/ -static int cpia2_s_jpegcomp(struct file *file, void *fh, struct v4l2_jpegcompression *parms) +static int cpia2_s_jpegcomp(struct file *file, void *fh, + const struct v4l2_jpegcompression *parms) { struct camera_data *cam = video_drvdata(file); @@ -725,8 +744,6 @@ static int cpia2_s_jpegcomp(struct file *file, void *fh, struct v4l2_jpegcompres cam->params.compression.inhibit_htables = !(parms->jpeg_markers & V4L2_JPEG_MARKER_DHT); - parms->jpeg_markers &= V4L2_JPEG_MARKER_DQT | V4L2_JPEG_MARKER_DRI | - V4L2_JPEG_MARKER_DHT; if(parms->APP_len != 0) { if(parms->APP_len > 0 && @@ -987,10 +1004,13 @@ static int cpia2_mmap(struct file *file, struct vm_area_struct *area) struct camera_data *cam = video_drvdata(file); int retval; + if (mutex_lock_interruptible(&cam->v4l2_lock)) + return -ERESTARTSYS; retval = cpia2_remap_buffer(cam, area); if(!retval) cam->stream_fh = file->private_data; + mutex_unlock(&cam->v4l2_lock); return retval; } @@ -1147,10 +1167,6 @@ int cpia2_register_camera(struct camera_data *cam) cam->vdev.ctrl_handler = hdl; cam->vdev.v4l2_dev = &cam->v4l2_dev; set_bit(V4L2_FL_USE_FH_PRIO, &cam->vdev.flags); - /* Locking in file operations other than ioctl should be done - by the driver, not the V4L2 core. - This driver needs auditing so that this flag can be removed. */ - set_bit(V4L2_FL_LOCK_ALL_FOPS, &cam->vdev.flags); reset_camera_struct_v4l(cam); diff --git a/drivers/media/video/cx231xx/Kconfig b/drivers/media/usb/cx231xx/Kconfig index 446f692aabb7..86feeeaf61c2 100644 --- a/drivers/media/video/cx231xx/Kconfig +++ b/drivers/media/usb/cx231xx/Kconfig @@ -40,11 +40,11 @@ config VIDEO_CX231XX_ALSA config VIDEO_CX231XX_DVB tristate "DVB/ATSC Support for Cx231xx based TV cards" - depends on VIDEO_CX231XX && DVB_CORE && DVB_CAPTURE_DRIVERS + depends on VIDEO_CX231XX && DVB_CORE select VIDEOBUF_DVB - select MEDIA_TUNER_XC5000 if !MEDIA_TUNER_CUSTOMISE - select MEDIA_TUNER_TDA18271 if !MEDIA_TUNER_CUSTOMISE - select DVB_MB86A20S if !DVB_FE_CUSTOMISE + select MEDIA_TUNER_XC5000 if MEDIA_SUBDRV_AUTOSELECT + select MEDIA_TUNER_TDA18271 if MEDIA_SUBDRV_AUTOSELECT + select DVB_MB86A20S if MEDIA_SUBDRV_AUTOSELECT ---help--- This adds support for DVB cards based on the diff --git a/drivers/media/video/cx231xx/Makefile b/drivers/media/usb/cx231xx/Makefile index b3348975c7c2..52cf76935e69 100644 --- a/drivers/media/video/cx231xx/Makefile +++ b/drivers/media/usb/cx231xx/Makefile @@ -8,9 +8,8 @@ obj-$(CONFIG_VIDEO_CX231XX) += cx231xx.o obj-$(CONFIG_VIDEO_CX231XX_ALSA) += cx231xx-alsa.o obj-$(CONFIG_VIDEO_CX231XX_DVB) += cx231xx-dvb.o -ccflags-y += -Idrivers/media/video -ccflags-y += -Idrivers/media/common/tuners -ccflags-y += -Idrivers/media/dvb/dvb-core -ccflags-y += -Idrivers/media/dvb/frontends -ccflags-y += -Idrivers/media/dvb/dvb-usb - +ccflags-y += -Idrivers/media/i2c +ccflags-y += -Idrivers/media/tuners +ccflags-y += -Idrivers/media/dvb-core +ccflags-y += -Idrivers/media/dvb-frontends +ccflags-y += -Idrivers/media/usb/dvb-usb diff --git a/drivers/media/video/cx231xx/cx231xx-417.c b/drivers/media/usb/cx231xx/cx231xx-417.c index ce2f62238a19..b024e5197a75 100644 --- a/drivers/media/video/cx231xx/cx231xx-417.c +++ b/drivers/media/usb/cx231xx/cx231xx-417.c @@ -2193,3 +2193,5 @@ int cx231xx_417_register(struct cx231xx *dev) return 0; } + +MODULE_FIRMWARE(CX231xx_FIRM_IMAGE_NAME); diff --git a/drivers/media/video/cx231xx/cx231xx-audio.c b/drivers/media/usb/cx231xx/cx231xx-audio.c index b4c99c7270cf..b4c99c7270cf 100644 --- a/drivers/media/video/cx231xx/cx231xx-audio.c +++ b/drivers/media/usb/cx231xx/cx231xx-audio.c diff --git a/drivers/media/video/cx231xx/cx231xx-avcore.c b/drivers/media/usb/cx231xx/cx231xx-avcore.c index 447148eff958..447148eff958 100644 --- a/drivers/media/video/cx231xx/cx231xx-avcore.c +++ b/drivers/media/usb/cx231xx/cx231xx-avcore.c diff --git a/drivers/media/video/cx231xx/cx231xx-cards.c b/drivers/media/usb/cx231xx/cx231xx-cards.c index b84ebc54d91b..b84ebc54d91b 100644 --- a/drivers/media/video/cx231xx/cx231xx-cards.c +++ b/drivers/media/usb/cx231xx/cx231xx-cards.c diff --git a/drivers/media/video/cx231xx/cx231xx-conf-reg.h b/drivers/media/usb/cx231xx/cx231xx-conf-reg.h index 25593f212abf..25593f212abf 100644 --- a/drivers/media/video/cx231xx/cx231xx-conf-reg.h +++ b/drivers/media/usb/cx231xx/cx231xx-conf-reg.h diff --git a/drivers/media/video/cx231xx/cx231xx-core.c b/drivers/media/usb/cx231xx/cx231xx-core.c index 05358d486135..05358d486135 100644 --- a/drivers/media/video/cx231xx/cx231xx-core.c +++ b/drivers/media/usb/cx231xx/cx231xx-core.c diff --git a/drivers/media/video/cx231xx/cx231xx-dif.h b/drivers/media/usb/cx231xx/cx231xx-dif.h index 2b63c2f6d3b0..2b63c2f6d3b0 100644 --- a/drivers/media/video/cx231xx/cx231xx-dif.h +++ b/drivers/media/usb/cx231xx/cx231xx-dif.h diff --git a/drivers/media/video/cx231xx/cx231xx-dvb.c b/drivers/media/usb/cx231xx/cx231xx-dvb.c index 7c4e360ba9bc..7c4e360ba9bc 100644 --- a/drivers/media/video/cx231xx/cx231xx-dvb.c +++ b/drivers/media/usb/cx231xx/cx231xx-dvb.c diff --git a/drivers/media/video/cx231xx/cx231xx-i2c.c b/drivers/media/usb/cx231xx/cx231xx-i2c.c index 781feed406f7..781feed406f7 100644 --- a/drivers/media/video/cx231xx/cx231xx-i2c.c +++ b/drivers/media/usb/cx231xx/cx231xx-i2c.c diff --git a/drivers/media/video/cx231xx/cx231xx-input.c b/drivers/media/usb/cx231xx/cx231xx-input.c index 96176e9db5a2..96176e9db5a2 100644 --- a/drivers/media/video/cx231xx/cx231xx-input.c +++ b/drivers/media/usb/cx231xx/cx231xx-input.c diff --git a/drivers/media/video/cx231xx/cx231xx-pcb-cfg.c b/drivers/media/usb/cx231xx/cx231xx-pcb-cfg.c index 7473c33e823e..7473c33e823e 100644 --- a/drivers/media/video/cx231xx/cx231xx-pcb-cfg.c +++ b/drivers/media/usb/cx231xx/cx231xx-pcb-cfg.c diff --git a/drivers/media/video/cx231xx/cx231xx-pcb-cfg.h b/drivers/media/usb/cx231xx/cx231xx-pcb-cfg.h index f5e46e89f3ab..f5e46e89f3ab 100644 --- a/drivers/media/video/cx231xx/cx231xx-pcb-cfg.h +++ b/drivers/media/usb/cx231xx/cx231xx-pcb-cfg.h diff --git a/drivers/media/video/cx231xx/cx231xx-reg.h b/drivers/media/usb/cx231xx/cx231xx-reg.h index 750c5d37d569..750c5d37d569 100644 --- a/drivers/media/video/cx231xx/cx231xx-reg.h +++ b/drivers/media/usb/cx231xx/cx231xx-reg.h diff --git a/drivers/media/video/cx231xx/cx231xx-vbi.c b/drivers/media/usb/cx231xx/cx231xx-vbi.c index ac7db52f404f..ac7db52f404f 100644 --- a/drivers/media/video/cx231xx/cx231xx-vbi.c +++ b/drivers/media/usb/cx231xx/cx231xx-vbi.c diff --git a/drivers/media/video/cx231xx/cx231xx-vbi.h b/drivers/media/usb/cx231xx/cx231xx-vbi.h index 16c7d20a22a4..16c7d20a22a4 100644 --- a/drivers/media/video/cx231xx/cx231xx-vbi.h +++ b/drivers/media/usb/cx231xx/cx231xx-vbi.h diff --git a/drivers/media/video/cx231xx/cx231xx-video.c b/drivers/media/usb/cx231xx/cx231xx-video.c index 523aa49d6b86..fedf7852a355 100644 --- a/drivers/media/video/cx231xx/cx231xx-video.c +++ b/drivers/media/usb/cx231xx/cx231xx-video.c @@ -1253,7 +1253,7 @@ static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a) return 0; } -static int vidioc_s_audio(struct file *file, void *priv, struct v4l2_audio *a) +static int vidioc_s_audio(struct file *file, void *priv, const struct v4l2_audio *a) { struct cx231xx_fh *fh = priv; struct cx231xx *dev = fh->dev; @@ -2096,7 +2096,7 @@ static int radio_s_tuner(struct file *file, void *priv, struct v4l2_tuner *t) return 0; } -static int radio_s_audio(struct file *file, void *fh, struct v4l2_audio *a) +static int radio_s_audio(struct file *file, void *fh, const struct v4l2_audio *a) { return 0; } @@ -2168,6 +2168,10 @@ static int cx231xx_v4l2_open(struct file *filp) cx231xx_errdev("cx231xx-video.c: Out of memory?!\n"); return -ENOMEM; } + if (mutex_lock_interruptible(&dev->lock)) { + kfree(fh); + return -ERESTARTSYS; + } fh->dev = dev; fh->radio = radio; fh->type = fh_type; @@ -2226,6 +2230,7 @@ static int cx231xx_v4l2_open(struct file *filp) sizeof(struct cx231xx_buffer), fh, &dev->lock); } + mutex_unlock(&dev->lock); return errCode; } @@ -2272,11 +2277,11 @@ void cx231xx_release_analog_resources(struct cx231xx *dev) } /* - * cx231xx_v4l2_close() + * cx231xx_close() * stops streaming and deallocates all resources allocated by the v4l2 * calls and ioctls */ -static int cx231xx_v4l2_close(struct file *filp) +static int cx231xx_close(struct file *filp) { struct cx231xx_fh *fh = filp->private_data; struct cx231xx *dev = fh->dev; @@ -2355,6 +2360,18 @@ static int cx231xx_v4l2_close(struct file *filp) return 0; } +static int cx231xx_v4l2_close(struct file *filp) +{ + struct cx231xx_fh *fh = filp->private_data; + struct cx231xx *dev = fh->dev; + int rc; + + mutex_lock(&dev->lock); + rc = cx231xx_close(filp); + mutex_unlock(&dev->lock); + return rc; +} + /* * cx231xx_v4l2_read() * will allocate buffers when called for the first time @@ -2378,8 +2395,12 @@ cx231xx_v4l2_read(struct file *filp, char __user *buf, size_t count, if (unlikely(rc < 0)) return rc; - return videobuf_read_stream(&fh->vb_vidq, buf, count, pos, 0, + if (mutex_lock_interruptible(&dev->lock)) + return -ERESTARTSYS; + rc = videobuf_read_stream(&fh->vb_vidq, buf, count, pos, 0, filp->f_flags & O_NONBLOCK); + mutex_unlock(&dev->lock); + return rc; } return 0; } @@ -2404,10 +2425,15 @@ static unsigned int cx231xx_v4l2_poll(struct file *filp, poll_table *wait) return POLLERR; if ((V4L2_BUF_TYPE_VIDEO_CAPTURE == fh->type) || - (V4L2_BUF_TYPE_VBI_CAPTURE == fh->type)) - return videobuf_poll_stream(filp, &fh->vb_vidq, wait); - else - return POLLERR; + (V4L2_BUF_TYPE_VBI_CAPTURE == fh->type)) { + unsigned int res; + + mutex_lock(&dev->lock); + res = videobuf_poll_stream(filp, &fh->vb_vidq, wait); + mutex_unlock(&dev->lock); + return res; + } + return POLLERR; } /* @@ -2428,7 +2454,10 @@ static int cx231xx_v4l2_mmap(struct file *filp, struct vm_area_struct *vma) if (unlikely(rc < 0)) return rc; + if (mutex_lock_interruptible(&dev->lock)) + return -ERESTARTSYS; rc = videobuf_mmap_mapper(&fh->vb_vidq, vma); + mutex_unlock(&dev->lock); cx231xx_videodbg("vma start=0x%08lx, size=%ld, ret=%d\n", (unsigned long)vma->vm_start, @@ -2545,10 +2574,6 @@ static struct video_device *cx231xx_vdev_init(struct cx231xx *dev, vfd->release = video_device_release; vfd->debug = video_debug; vfd->lock = &dev->lock; - /* Locking in file operations other than ioctl should be done - by the driver, not the V4L2 core. - This driver needs auditing so that this flag can be removed. */ - set_bit(V4L2_FL_LOCK_ALL_FOPS, &vfd->flags); snprintf(vfd->name, sizeof(vfd->name), "%s %s", dev->name, type_name); diff --git a/drivers/media/video/cx231xx/cx231xx.h b/drivers/media/usb/cx231xx/cx231xx.h index a89d020de948..a89d020de948 100644 --- a/drivers/media/video/cx231xx/cx231xx.h +++ b/drivers/media/usb/cx231xx/cx231xx.h diff --git a/drivers/media/usb/dvb-usb-v2/Kconfig b/drivers/media/usb/dvb-usb-v2/Kconfig new file mode 100644 index 000000000000..834bfecbed73 --- /dev/null +++ b/drivers/media/usb/dvb-usb-v2/Kconfig @@ -0,0 +1,149 @@ +config DVB_USB_V2 + tristate "Support for various USB DVB devices v2" + depends on DVB_CORE && USB && I2C && RC_CORE + help + By enabling this you will be able to choose the various supported + USB1.1 and USB2.0 DVB devices. + + Almost every USB device needs a firmware, please look into + <file:Documentation/dvb/README.dvb-usb>. + + For a complete list of supported USB devices see the LinuxTV DVB Wiki: + <http://www.linuxtv.org/wiki/index.php/DVB_USB> + + Say Y if you own a USB DVB device. + +config DVB_USB_CYPRESS_FIRMWARE + tristate "Cypress firmware helper routines" + depends on DVB_USB_V2 + +config DVB_USB_AF9015 + tristate "Afatech AF9015 DVB-T USB2.0 support" + depends on DVB_USB_V2 + select DVB_AF9013 + select DVB_PLL if MEDIA_SUBDRV_AUTOSELECT + select MEDIA_TUNER_MT2060 if MEDIA_SUBDRV_AUTOSELECT + select MEDIA_TUNER_QT1010 if MEDIA_SUBDRV_AUTOSELECT + select MEDIA_TUNER_TDA18271 if MEDIA_SUBDRV_AUTOSELECT + select MEDIA_TUNER_MXL5005S if MEDIA_SUBDRV_AUTOSELECT + select MEDIA_TUNER_MC44S803 if MEDIA_SUBDRV_AUTOSELECT + select MEDIA_TUNER_TDA18218 if MEDIA_SUBDRV_AUTOSELECT + select MEDIA_TUNER_MXL5007T if MEDIA_SUBDRV_AUTOSELECT + help + Say Y here to support the Afatech AF9015 based DVB-T USB2.0 receiver + +config DVB_USB_AF9035 + tristate "Afatech AF9035 DVB-T USB2.0 support" + depends on DVB_USB_V2 + select DVB_AF9033 + select MEDIA_TUNER_TUA9001 if MEDIA_SUBDRV_AUTOSELECT + select MEDIA_TUNER_FC0011 if MEDIA_SUBDRV_AUTOSELECT + select MEDIA_TUNER_MXL5007T if MEDIA_SUBDRV_AUTOSELECT + select MEDIA_TUNER_TDA18218 if MEDIA_SUBDRV_AUTOSELECT + select MEDIA_TUNER_FC2580 if MEDIA_SUBDRV_AUTOSELECT + help + Say Y here to support the Afatech AF9035 based DVB USB receiver. + +config DVB_USB_ANYSEE + tristate "Anysee DVB-T/C USB2.0 support" + depends on DVB_USB_V2 + select DVB_PLL if MEDIA_SUBDRV_AUTOSELECT + select DVB_MT352 if MEDIA_SUBDRV_AUTOSELECT + select DVB_ZL10353 if MEDIA_SUBDRV_AUTOSELECT + select DVB_TDA10023 if MEDIA_SUBDRV_AUTOSELECT + select MEDIA_TUNER_TDA18212 if MEDIA_SUBDRV_AUTOSELECT + select DVB_CX24116 if MEDIA_SUBDRV_AUTOSELECT + select DVB_STV0900 if MEDIA_SUBDRV_AUTOSELECT + select DVB_STV6110 if MEDIA_SUBDRV_AUTOSELECT + select DVB_ISL6423 if MEDIA_SUBDRV_AUTOSELECT + select DVB_CXD2820R if MEDIA_SUBDRV_AUTOSELECT + help + Say Y here to support the Anysee E30, Anysee E30 Plus or + Anysee E30 C Plus DVB USB2.0 receiver. + +config DVB_USB_AU6610 + tristate "Alcor Micro AU6610 USB2.0 support" + depends on DVB_USB_V2 + select DVB_ZL10353 if MEDIA_SUBDRV_AUTOSELECT + select MEDIA_TUNER_QT1010 if MEDIA_SUBDRV_AUTOSELECT + help + Say Y here to support the Sigmatek DVB-110 DVB-T USB2.0 receiver. + +config DVB_USB_AZ6007 + tristate "AzureWave 6007 and clones DVB-T/C USB2.0 support" + depends on DVB_USB_V2 + select DVB_USB_CYPRESS_FIRMWARE + select DVB_DRXK if MEDIA_SUBDRV_AUTOSELECT + select MEDIA_TUNER_MT2063 if MEDIA_SUBDRV_AUTOSELECT + help + Say Y here to support the AZ6007 receivers like Terratec H7. + +config DVB_USB_CE6230 + tristate "Intel CE6230 DVB-T USB2.0 support" + depends on DVB_USB_V2 + select DVB_ZL10353 + select MEDIA_TUNER_MXL5005S if MEDIA_SUBDRV_AUTOSELECT + help + Say Y here to support the Intel CE6230 DVB-T USB2.0 receiver + +config DVB_USB_EC168 + tristate "E3C EC168 DVB-T USB2.0 support" + depends on DVB_USB_V2 + select DVB_EC100 + select MEDIA_TUNER_MXL5005S if MEDIA_SUBDRV_AUTOSELECT + help + Say Y here to support the E3C EC168 DVB-T USB2.0 receiver. + +config DVB_USB_GL861 + tristate "Genesys Logic GL861 USB2.0 support" + depends on DVB_USB_V2 + select DVB_ZL10353 if MEDIA_SUBDRV_AUTOSELECT + select MEDIA_TUNER_QT1010 if MEDIA_SUBDRV_AUTOSELECT + help + Say Y here to support the MSI Megasky 580 (55801) DVB-T USB2.0 + receiver with USB ID 0db0:5581. + +config DVB_USB_IT913X + tristate "ITE IT913X DVB-T USB2.0 support" + depends on DVB_USB_V2 + select DVB_IT913X_FE + help + Say Y here to support the ITE IT913X DVB-T USB2.0 + +config DVB_USB_LME2510 + tristate "LME DM04/QQBOX DVB-S USB2.0 support" + depends on DVB_USB_V2 + select DVB_TDA10086 if MEDIA_SUBDRV_AUTOSELECT + select DVB_TDA826X if MEDIA_SUBDRV_AUTOSELECT + select DVB_STV0288 if MEDIA_SUBDRV_AUTOSELECT + select DVB_IX2505V if MEDIA_SUBDRV_AUTOSELECT + select DVB_STV0299 if MEDIA_SUBDRV_AUTOSELECT + select DVB_PLL if MEDIA_SUBDRV_AUTOSELECT + select DVB_M88RS2000 if MEDIA_SUBDRV_AUTOSELECT + help + Say Y here to support the LME DM04/QQBOX DVB-S USB2.0 + +config DVB_USB_MXL111SF + tristate "MxL111SF DTV USB2.0 support" + depends on DVB_USB_V2 + select DVB_LGDT3305 if MEDIA_SUBDRV_AUTOSELECT + select DVB_LG2160 if MEDIA_SUBDRV_AUTOSELECT + select VIDEO_TVEEPROM + help + Say Y here to support the MxL111SF USB2.0 DTV receiver. + +config DVB_USB_RTL28XXU + tristate "Realtek RTL28xxU DVB USB support" + depends on DVB_USB_V2 && EXPERIMENTAL + select DVB_RTL2830 + select DVB_RTL2832 + select MEDIA_TUNER_QT1010 if MEDIA_SUBDRV_AUTOSELECT + select MEDIA_TUNER_MT2060 if MEDIA_SUBDRV_AUTOSELECT + select MEDIA_TUNER_MXL5005S if MEDIA_SUBDRV_AUTOSELECT + select MEDIA_TUNER_FC0012 if MEDIA_SUBDRV_AUTOSELECT + select MEDIA_TUNER_FC0013 if MEDIA_SUBDRV_AUTOSELECT + select MEDIA_TUNER_E4000 if MEDIA_SUBDRV_AUTOSELECT + select MEDIA_TUNER_FC2580 if MEDIA_SUBDRV_AUTOSELECT + help + Say Y here to support the Realtek RTL28xxU DVB USB receiver. + diff --git a/drivers/media/usb/dvb-usb-v2/Makefile b/drivers/media/usb/dvb-usb-v2/Makefile new file mode 100644 index 000000000000..b76f58e6c64f --- /dev/null +++ b/drivers/media/usb/dvb-usb-v2/Makefile @@ -0,0 +1,49 @@ +dvb_usb_v2-objs := dvb_usb_core.o dvb_usb_urb.o usb_urb.o +obj-$(CONFIG_DVB_USB_V2) += dvb_usb_v2.o + +dvb_usb_cypress_firmware-objs := cypress_firmware.o +obj-$(CONFIG_DVB_USB_CYPRESS_FIRMWARE) += dvb_usb_cypress_firmware.o + +dvb-usb-af9015-objs := af9015.o +obj-$(CONFIG_DVB_USB_AF9015) += dvb-usb-af9015.o + +dvb-usb-af9035-objs := af9035.o +obj-$(CONFIG_DVB_USB_AF9035) += dvb-usb-af9035.o + +dvb-usb-anysee-objs := anysee.o +obj-$(CONFIG_DVB_USB_ANYSEE) += dvb-usb-anysee.o + +dvb-usb-au6610-objs := au6610.o +obj-$(CONFIG_DVB_USB_AU6610) += dvb-usb-au6610.o + +dvb-usb-az6007-objs := az6007.o +obj-$(CONFIG_DVB_USB_AZ6007) += dvb-usb-az6007.o + +dvb-usb-ce6230-objs := ce6230.o +obj-$(CONFIG_DVB_USB_CE6230) += dvb-usb-ce6230.o + +dvb-usb-ec168-objs := ec168.o +obj-$(CONFIG_DVB_USB_EC168) += dvb-usb-ec168.o + +dvb-usb-it913x-objs := it913x.o +obj-$(CONFIG_DVB_USB_IT913X) += dvb-usb-it913x.o + +dvb-usb-lmedm04-objs := lmedm04.o +obj-$(CONFIG_DVB_USB_LME2510) += dvb-usb-lmedm04.o + +dvb-usb-gl861-objs := gl861.o +obj-$(CONFIG_DVB_USB_GL861) += dvb-usb-gl861.o + +dvb-usb-mxl111sf-objs += mxl111sf.o mxl111sf-phy.o mxl111sf-i2c.o +dvb-usb-mxl111sf-objs += mxl111sf-gpio.o +obj-$(CONFIG_DVB_USB_MXL111SF) += dvb-usb-mxl111sf.o +obj-$(CONFIG_DVB_USB_MXL111SF) += mxl111sf-demod.o +obj-$(CONFIG_DVB_USB_MXL111SF) += mxl111sf-tuner.o + +dvb-usb-rtl28xxu-objs := rtl28xxu.o +obj-$(CONFIG_DVB_USB_RTL28XXU) += dvb-usb-rtl28xxu.o + +ccflags-y += -I$(srctree)/drivers/media/dvb-core +ccflags-y += -I$(srctree)/drivers/media/dvb-frontends +ccflags-y += -I$(srctree)/drivers/media/tuners + diff --git a/drivers/media/usb/dvb-usb-v2/af9015.c b/drivers/media/usb/dvb-usb-v2/af9015.c new file mode 100644 index 000000000000..824f1911ee21 --- /dev/null +++ b/drivers/media/usb/dvb-usb-v2/af9015.c @@ -0,0 +1,1454 @@ +/* + * DVB USB Linux driver for Afatech AF9015 DVB-T USB2.0 receiver + * + * Copyright (C) 2007 Antti Palosaari <crope@iki.fi> + * + * Thanks to Afatech who kindly provided information. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include "af9015.h" + +static int dvb_usb_af9015_remote; +module_param_named(remote, dvb_usb_af9015_remote, int, 0644); +MODULE_PARM_DESC(remote, "select remote"); +DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); + +static int af9015_ctrl_msg(struct dvb_usb_device *d, struct req_t *req) +{ +#define BUF_LEN 63 +#define REQ_HDR_LEN 8 /* send header size */ +#define ACK_HDR_LEN 2 /* rece header size */ + struct af9015_state *state = d_to_priv(d); + int ret, wlen, rlen; + u8 buf[BUF_LEN]; + u8 write = 1; + + buf[0] = req->cmd; + buf[1] = state->seq++; + buf[2] = req->i2c_addr; + buf[3] = req->addr >> 8; + buf[4] = req->addr & 0xff; + buf[5] = req->mbox; + buf[6] = req->addr_len; + buf[7] = req->data_len; + + switch (req->cmd) { + case GET_CONFIG: + case READ_MEMORY: + case RECONNECT_USB: + write = 0; + break; + case READ_I2C: + write = 0; + buf[2] |= 0x01; /* set I2C direction */ + case WRITE_I2C: + buf[0] = READ_WRITE_I2C; + break; + case WRITE_MEMORY: + if (((req->addr & 0xff00) == 0xff00) || + ((req->addr & 0xff00) == 0xae00)) + buf[0] = WRITE_VIRTUAL_MEMORY; + case WRITE_VIRTUAL_MEMORY: + case COPY_FIRMWARE: + case DOWNLOAD_FIRMWARE: + case BOOT: + break; + default: + dev_err(&d->udev->dev, "%s: unknown command=%d\n", + KBUILD_MODNAME, req->cmd); + ret = -EIO; + goto error; + } + + /* buffer overflow check */ + if ((write && (req->data_len > BUF_LEN - REQ_HDR_LEN)) || + (!write && (req->data_len > BUF_LEN - ACK_HDR_LEN))) { + dev_err(&d->udev->dev, "%s: too much data; cmd=%d len=%d\n", + KBUILD_MODNAME, req->cmd, req->data_len); + ret = -EINVAL; + goto error; + } + + /* write receives seq + status = 2 bytes + read receives seq + status + data = 2 + N bytes */ + wlen = REQ_HDR_LEN; + rlen = ACK_HDR_LEN; + if (write) { + wlen += req->data_len; + memcpy(&buf[REQ_HDR_LEN], req->data, req->data_len); + } else { + rlen += req->data_len; + } + + /* no ack for these packets */ + if (req->cmd == DOWNLOAD_FIRMWARE || req->cmd == RECONNECT_USB) + rlen = 0; + + ret = dvb_usbv2_generic_rw(d, buf, wlen, buf, rlen); + if (ret) + goto error; + + /* check status */ + if (rlen && buf[1]) { + dev_err(&d->udev->dev, "%s: command failed=%d\n", + KBUILD_MODNAME, buf[1]); + ret = -EIO; + goto error; + } + + /* read request, copy returned data to return buf */ + if (!write) + memcpy(req->data, &buf[ACK_HDR_LEN], req->data_len); +error: + return ret; +} + +static int af9015_write_regs(struct dvb_usb_device *d, u16 addr, u8 *val, + u8 len) +{ + struct req_t req = {WRITE_MEMORY, AF9015_I2C_DEMOD, addr, 0, 0, len, + val}; + return af9015_ctrl_msg(d, &req); +} + +static int af9015_read_regs(struct dvb_usb_device *d, u16 addr, u8 *val, u8 len) +{ + struct req_t req = {READ_MEMORY, AF9015_I2C_DEMOD, addr, 0, 0, len, + val}; + return af9015_ctrl_msg(d, &req); +} + +static int af9015_write_reg(struct dvb_usb_device *d, u16 addr, u8 val) +{ + return af9015_write_regs(d, addr, &val, 1); +} + +static int af9015_read_reg(struct dvb_usb_device *d, u16 addr, u8 *val) +{ + return af9015_read_regs(d, addr, val, 1); +} + +static int af9015_write_reg_i2c(struct dvb_usb_device *d, u8 addr, u16 reg, + u8 val) +{ + struct af9015_state *state = d_to_priv(d); + struct req_t req = {WRITE_I2C, addr, reg, 1, 1, 1, &val}; + + if (addr == state->af9013_config[0].i2c_addr || + addr == state->af9013_config[1].i2c_addr) + req.addr_len = 3; + + return af9015_ctrl_msg(d, &req); +} + +static int af9015_read_reg_i2c(struct dvb_usb_device *d, u8 addr, u16 reg, + u8 *val) +{ + struct af9015_state *state = d_to_priv(d); + struct req_t req = {READ_I2C, addr, reg, 0, 1, 1, val}; + + if (addr == state->af9013_config[0].i2c_addr || + addr == state->af9013_config[1].i2c_addr) + req.addr_len = 3; + + return af9015_ctrl_msg(d, &req); +} + +static int af9015_do_reg_bit(struct dvb_usb_device *d, u16 addr, u8 bit, u8 op) +{ + int ret; + u8 val, mask = 0x01; + + ret = af9015_read_reg(d, addr, &val); + if (ret) + return ret; + + mask <<= bit; + if (op) { + /* set bit */ + val |= mask; + } else { + /* clear bit */ + mask ^= 0xff; + val &= mask; + } + + return af9015_write_reg(d, addr, val); +} + +static int af9015_set_reg_bit(struct dvb_usb_device *d, u16 addr, u8 bit) +{ + return af9015_do_reg_bit(d, addr, bit, 1); +} + +static int af9015_clear_reg_bit(struct dvb_usb_device *d, u16 addr, u8 bit) +{ + return af9015_do_reg_bit(d, addr, bit, 0); +} + +static int af9015_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], + int num) +{ + struct dvb_usb_device *d = i2c_get_adapdata(adap); + struct af9015_state *state = d_to_priv(d); + int ret = 0, i = 0; + u16 addr; + u8 uninitialized_var(mbox), addr_len; + struct req_t req; + +/* +The bus lock is needed because there is two tuners both using same I2C-address. +Due to that the only way to select correct tuner is use demodulator I2C-gate. + +................................................ +. AF9015 includes integrated AF9013 demodulator. +. ____________ ____________ . ____________ +.| uC | | demod | . | tuner | +.|------------| |------------| . |------------| +.| AF9015 | | AF9013/5 | . | MXL5003 | +.| |--+----I2C-------|-----/ -----|-.-----I2C-------| | +.| | | | addr 0x38 | . | addr 0xc6 | +.|____________| | |____________| . |____________| +.................|.............................. + | ____________ ____________ + | | demod | | tuner | + | |------------| |------------| + | | AF9013 | | MXL5003 | + +----I2C-------|-----/ -----|-------I2C-------| | + | addr 0x3a | | addr 0xc6 | + |____________| |____________| +*/ + if (mutex_lock_interruptible(&d->i2c_mutex) < 0) + return -EAGAIN; + + while (i < num) { + if (msg[i].addr == state->af9013_config[0].i2c_addr || + msg[i].addr == state->af9013_config[1].i2c_addr) { + addr = msg[i].buf[0] << 8; + addr += msg[i].buf[1]; + mbox = msg[i].buf[2]; + addr_len = 3; + } else { + addr = msg[i].buf[0]; + addr_len = 1; + /* mbox is don't care in that case */ + } + + if (num > i + 1 && (msg[i+1].flags & I2C_M_RD)) { + if (msg[i].len > 3 || msg[i+1].len > 61) { + ret = -EOPNOTSUPP; + goto error; + } + if (msg[i].addr == state->af9013_config[0].i2c_addr) + req.cmd = READ_MEMORY; + else + req.cmd = READ_I2C; + req.i2c_addr = msg[i].addr; + req.addr = addr; + req.mbox = mbox; + req.addr_len = addr_len; + req.data_len = msg[i+1].len; + req.data = &msg[i+1].buf[0]; + ret = af9015_ctrl_msg(d, &req); + i += 2; + } else if (msg[i].flags & I2C_M_RD) { + if (msg[i].len > 61) { + ret = -EOPNOTSUPP; + goto error; + } + if (msg[i].addr == state->af9013_config[0].i2c_addr) { + ret = -EINVAL; + goto error; + } + req.cmd = READ_I2C; + req.i2c_addr = msg[i].addr; + req.addr = addr; + req.mbox = mbox; + req.addr_len = addr_len; + req.data_len = msg[i].len; + req.data = &msg[i].buf[0]; + ret = af9015_ctrl_msg(d, &req); + i += 1; + } else { + if (msg[i].len > 21) { + ret = -EOPNOTSUPP; + goto error; + } + if (msg[i].addr == state->af9013_config[0].i2c_addr) + req.cmd = WRITE_MEMORY; + else + req.cmd = WRITE_I2C; + req.i2c_addr = msg[i].addr; + req.addr = addr; + req.mbox = mbox; + req.addr_len = addr_len; + req.data_len = msg[i].len-addr_len; + req.data = &msg[i].buf[addr_len]; + ret = af9015_ctrl_msg(d, &req); + i += 1; + } + if (ret) + goto error; + + } + ret = i; + +error: + mutex_unlock(&d->i2c_mutex); + + return ret; +} + +static u32 af9015_i2c_func(struct i2c_adapter *adapter) +{ + return I2C_FUNC_I2C; +} + +static struct i2c_algorithm af9015_i2c_algo = { + .master_xfer = af9015_i2c_xfer, + .functionality = af9015_i2c_func, +}; + +static int af9015_identify_state(struct dvb_usb_device *d, const char **name) +{ + int ret; + u8 reply; + struct req_t req = {GET_CONFIG, 0, 0, 0, 0, 1, &reply}; + + ret = af9015_ctrl_msg(d, &req); + if (ret) + return ret; + + dev_dbg(&d->udev->dev, "%s: reply=%02x\n", __func__, reply); + + if (reply == 0x02) + ret = WARM; + else + ret = COLD; + + return ret; +} + +static int af9015_download_firmware(struct dvb_usb_device *d, + const struct firmware *fw) +{ + struct af9015_state *state = d_to_priv(d); + int i, len, remaining, ret; + struct req_t req = {DOWNLOAD_FIRMWARE, 0, 0, 0, 0, 0, NULL}; + u16 checksum = 0; + dev_dbg(&d->udev->dev, "%s:\n", __func__); + + /* calc checksum */ + for (i = 0; i < fw->size; i++) + checksum += fw->data[i]; + + state->firmware_size = fw->size; + state->firmware_checksum = checksum; + + #define FW_ADDR 0x5100 /* firmware start address */ + #define LEN_MAX 55 /* max packet size */ + for (remaining = fw->size; remaining > 0; remaining -= LEN_MAX) { + len = remaining; + if (len > LEN_MAX) + len = LEN_MAX; + + req.data_len = len; + req.data = (u8 *) &fw->data[fw->size - remaining]; + req.addr = FW_ADDR + fw->size - remaining; + + ret = af9015_ctrl_msg(d, &req); + if (ret) { + dev_err(&d->udev->dev, + "%s: firmware download failed=%d\n", + KBUILD_MODNAME, ret); + goto error; + } + } + + /* firmware loaded, request boot */ + req.cmd = BOOT; + req.data_len = 0; + ret = af9015_ctrl_msg(d, &req); + if (ret) { + dev_err(&d->udev->dev, "%s: firmware boot failed=%d\n", + KBUILD_MODNAME, ret); + goto error; + } + +error: + return ret; +} + +/* hash (and dump) eeprom */ +static int af9015_eeprom_hash(struct dvb_usb_device *d) +{ + struct af9015_state *state = d_to_priv(d); + int ret, i; + static const unsigned int AF9015_EEPROM_SIZE = 256; + u8 buf[AF9015_EEPROM_SIZE]; + struct req_t req = {READ_I2C, AF9015_I2C_EEPROM, 0, 0, 1, 1, NULL}; + + /* read eeprom */ + for (i = 0; i < AF9015_EEPROM_SIZE; i++) { + req.addr = i; + req.data = &buf[i]; + ret = af9015_ctrl_msg(d, &req); + if (ret < 0) + goto err; + } + + /* calculate checksum */ + for (i = 0; i < AF9015_EEPROM_SIZE / sizeof(u32); i++) { + state->eeprom_sum *= GOLDEN_RATIO_PRIME_32; + state->eeprom_sum += le32_to_cpu(((u32 *)buf)[i]); + } + + for (i = 0; i < AF9015_EEPROM_SIZE; i += 16) + dev_dbg(&d->udev->dev, "%s: %*ph\n", __func__, 16, buf + i); + + dev_dbg(&d->udev->dev, "%s: eeprom sum=%.8x\n", + __func__, state->eeprom_sum); + return 0; +err: + dev_err(&d->udev->dev, "%s: eeprom failed=%d\n", KBUILD_MODNAME, ret); + return ret; +} + +static int af9015_read_config(struct dvb_usb_device *d) +{ + struct af9015_state *state = d_to_priv(d); + int ret; + u8 val, i, offset = 0; + struct req_t req = {READ_I2C, AF9015_I2C_EEPROM, 0, 0, 1, 1, &val}; + + dev_dbg(&d->udev->dev, "%s:\n", __func__); + + /* IR remote controller */ + req.addr = AF9015_EEPROM_IR_MODE; + /* first message will timeout often due to possible hw bug */ + for (i = 0; i < 4; i++) { + ret = af9015_ctrl_msg(d, &req); + if (!ret) + break; + } + if (ret) + goto error; + + ret = af9015_eeprom_hash(d); + if (ret) + goto error; + + state->ir_mode = val; + dev_dbg(&d->udev->dev, "%s: IR mode=%d\n", __func__, val); + + /* TS mode - one or two receivers */ + req.addr = AF9015_EEPROM_TS_MODE; + ret = af9015_ctrl_msg(d, &req); + if (ret) + goto error; + + state->dual_mode = val; + dev_dbg(&d->udev->dev, "%s: TS mode=%d\n", __func__, state->dual_mode); + + /* disable 2nd adapter because we don't have PID-filters */ + if (d->udev->speed == USB_SPEED_FULL) + state->dual_mode = 0; + + if (state->dual_mode) { + /* read 2nd demodulator I2C address */ + req.addr = AF9015_EEPROM_DEMOD2_I2C; + ret = af9015_ctrl_msg(d, &req); + if (ret) + goto error; + + state->af9013_config[1].i2c_addr = val; + } + + for (i = 0; i < state->dual_mode + 1; i++) { + if (i == 1) + offset = AF9015_EEPROM_OFFSET; + /* xtal */ + req.addr = AF9015_EEPROM_XTAL_TYPE1 + offset; + ret = af9015_ctrl_msg(d, &req); + if (ret) + goto error; + switch (val) { + case 0: + state->af9013_config[i].clock = 28800000; + break; + case 1: + state->af9013_config[i].clock = 20480000; + break; + case 2: + state->af9013_config[i].clock = 28000000; + break; + case 3: + state->af9013_config[i].clock = 25000000; + break; + }; + dev_dbg(&d->udev->dev, "%s: [%d] xtal=%d set clock=%d\n", + __func__, i, val, + state->af9013_config[i].clock); + + /* IF frequency */ + req.addr = AF9015_EEPROM_IF1H + offset; + ret = af9015_ctrl_msg(d, &req); + if (ret) + goto error; + + state->af9013_config[i].if_frequency = val << 8; + + req.addr = AF9015_EEPROM_IF1L + offset; + ret = af9015_ctrl_msg(d, &req); + if (ret) + goto error; + + state->af9013_config[i].if_frequency += val; + state->af9013_config[i].if_frequency *= 1000; + dev_dbg(&d->udev->dev, "%s: [%d] IF frequency=%d\n", __func__, + i, state->af9013_config[i].if_frequency); + + /* MT2060 IF1 */ + req.addr = AF9015_EEPROM_MT2060_IF1H + offset; + ret = af9015_ctrl_msg(d, &req); + if (ret) + goto error; + state->mt2060_if1[i] = val << 8; + req.addr = AF9015_EEPROM_MT2060_IF1L + offset; + ret = af9015_ctrl_msg(d, &req); + if (ret) + goto error; + state->mt2060_if1[i] += val; + dev_dbg(&d->udev->dev, "%s: [%d] MT2060 IF1=%d\n", __func__, i, + state->mt2060_if1[i]); + + /* tuner */ + req.addr = AF9015_EEPROM_TUNER_ID1 + offset; + ret = af9015_ctrl_msg(d, &req); + if (ret) + goto error; + switch (val) { + case AF9013_TUNER_ENV77H11D5: + case AF9013_TUNER_MT2060: + case AF9013_TUNER_QT1010: + case AF9013_TUNER_UNKNOWN: + case AF9013_TUNER_MT2060_2: + case AF9013_TUNER_TDA18271: + case AF9013_TUNER_QT1010A: + case AF9013_TUNER_TDA18218: + state->af9013_config[i].spec_inv = 1; + break; + case AF9013_TUNER_MXL5003D: + case AF9013_TUNER_MXL5005D: + case AF9013_TUNER_MXL5005R: + case AF9013_TUNER_MXL5007T: + state->af9013_config[i].spec_inv = 0; + break; + case AF9013_TUNER_MC44S803: + state->af9013_config[i].gpio[1] = AF9013_GPIO_LO; + state->af9013_config[i].spec_inv = 1; + break; + default: + dev_err(&d->udev->dev, "%s: tuner id=%d not " \ + "supported, please report!\n", + KBUILD_MODNAME, val); + return -ENODEV; + }; + + state->af9013_config[i].tuner = val; + dev_dbg(&d->udev->dev, "%s: [%d] tuner id=%d\n", + __func__, i, val); + } + +error: + if (ret) + dev_err(&d->udev->dev, "%s: eeprom read failed=%d\n", + KBUILD_MODNAME, ret); + + /* AverMedia AVerTV Volar Black HD (A850) device have bad EEPROM + content :-( Override some wrong values here. Ditto for the + AVerTV Red HD+ (A850T) device. */ + if (le16_to_cpu(d->udev->descriptor.idVendor) == USB_VID_AVERMEDIA && + ((le16_to_cpu(d->udev->descriptor.idProduct) == + USB_PID_AVERMEDIA_A850) || + (le16_to_cpu(d->udev->descriptor.idProduct) == + USB_PID_AVERMEDIA_A850T))) { + dev_dbg(&d->udev->dev, + "%s: AverMedia A850: overriding config\n", + __func__); + /* disable dual mode */ + state->dual_mode = 0; + + /* set correct IF */ + state->af9013_config[0].if_frequency = 4570000; + } + + return ret; +} + +static int af9015_get_stream_config(struct dvb_frontend *fe, u8 *ts_type, + struct usb_data_stream_properties *stream) +{ + struct dvb_usb_device *d = fe_to_d(fe); + dev_dbg(&d->udev->dev, "%s: adap=%d\n", __func__, fe_to_adap(fe)->id); + + if (d->udev->speed == USB_SPEED_FULL) + stream->u.bulk.buffersize = TS_USB11_FRAME_SIZE; + + return 0; +} + +static int af9015_get_adapter_count(struct dvb_usb_device *d) +{ + struct af9015_state *state = d_to_priv(d); + return state->dual_mode + 1; +} + +/* override demod callbacks for resource locking */ +static int af9015_af9013_set_frontend(struct dvb_frontend *fe) +{ + int ret; + struct af9015_state *state = fe_to_priv(fe); + + if (mutex_lock_interruptible(&state->fe_mutex)) + return -EAGAIN; + + ret = state->set_frontend[fe_to_adap(fe)->id](fe); + + mutex_unlock(&state->fe_mutex); + + return ret; +} + +/* override demod callbacks for resource locking */ +static int af9015_af9013_read_status(struct dvb_frontend *fe, + fe_status_t *status) +{ + int ret; + struct af9015_state *state = fe_to_priv(fe); + + if (mutex_lock_interruptible(&state->fe_mutex)) + return -EAGAIN; + + ret = state->read_status[fe_to_adap(fe)->id](fe, status); + + mutex_unlock(&state->fe_mutex); + + return ret; +} + +/* override demod callbacks for resource locking */ +static int af9015_af9013_init(struct dvb_frontend *fe) +{ + int ret; + struct af9015_state *state = fe_to_priv(fe); + + if (mutex_lock_interruptible(&state->fe_mutex)) + return -EAGAIN; + + ret = state->init[fe_to_adap(fe)->id](fe); + + mutex_unlock(&state->fe_mutex); + + return ret; +} + +/* override demod callbacks for resource locking */ +static int af9015_af9013_sleep(struct dvb_frontend *fe) +{ + int ret; + struct af9015_state *state = fe_to_priv(fe); + + if (mutex_lock_interruptible(&state->fe_mutex)) + return -EAGAIN; + + ret = state->sleep[fe_to_adap(fe)->id](fe); + + mutex_unlock(&state->fe_mutex); + + return ret; +} + +/* override tuner callbacks for resource locking */ +static int af9015_tuner_init(struct dvb_frontend *fe) +{ + int ret; + struct af9015_state *state = fe_to_priv(fe); + + if (mutex_lock_interruptible(&state->fe_mutex)) + return -EAGAIN; + + ret = state->tuner_init[fe_to_adap(fe)->id](fe); + + mutex_unlock(&state->fe_mutex); + + return ret; +} + +/* override tuner callbacks for resource locking */ +static int af9015_tuner_sleep(struct dvb_frontend *fe) +{ + int ret; + struct af9015_state *state = fe_to_priv(fe); + + if (mutex_lock_interruptible(&state->fe_mutex)) + return -EAGAIN; + + ret = state->tuner_sleep[fe_to_adap(fe)->id](fe); + + mutex_unlock(&state->fe_mutex); + + return ret; +} + +static int af9015_copy_firmware(struct dvb_usb_device *d) +{ + struct af9015_state *state = d_to_priv(d); + int ret; + u8 fw_params[4]; + u8 val, i; + struct req_t req = {COPY_FIRMWARE, 0, 0x5100, 0, 0, sizeof(fw_params), + fw_params }; + dev_dbg(&d->udev->dev, "%s:\n", __func__); + + fw_params[0] = state->firmware_size >> 8; + fw_params[1] = state->firmware_size & 0xff; + fw_params[2] = state->firmware_checksum >> 8; + fw_params[3] = state->firmware_checksum & 0xff; + + /* wait 2nd demodulator ready */ + msleep(100); + + ret = af9015_read_reg_i2c(d, state->af9013_config[1].i2c_addr, + 0x98be, &val); + if (ret) + goto error; + else + dev_dbg(&d->udev->dev, "%s: firmware status=%02x\n", + __func__, val); + + if (val == 0x0c) /* fw is running, no need for download */ + goto exit; + + /* set I2C master clock to fast (to speed up firmware copy) */ + ret = af9015_write_reg(d, 0xd416, 0x04); /* 0x04 * 400ns */ + if (ret) + goto error; + + msleep(50); + + /* copy firmware */ + ret = af9015_ctrl_msg(d, &req); + if (ret) + dev_err(&d->udev->dev, "%s: firmware copy cmd failed=%d\n", + KBUILD_MODNAME, ret); + + dev_dbg(&d->udev->dev, "%s: firmware copy done\n", __func__); + + /* set I2C master clock back to normal */ + ret = af9015_write_reg(d, 0xd416, 0x14); /* 0x14 * 400ns */ + if (ret) + goto error; + + /* request boot firmware */ + ret = af9015_write_reg_i2c(d, state->af9013_config[1].i2c_addr, + 0xe205, 1); + dev_dbg(&d->udev->dev, "%s: firmware boot cmd status=%d\n", + __func__, ret); + if (ret) + goto error; + + for (i = 0; i < 15; i++) { + msleep(100); + + /* check firmware status */ + ret = af9015_read_reg_i2c(d, state->af9013_config[1].i2c_addr, + 0x98be, &val); + dev_dbg(&d->udev->dev, "%s: firmware status cmd status=%d " \ + "firmware status=%02x\n", __func__, ret, val); + if (ret) + goto error; + + if (val == 0x0c || val == 0x04) /* success or fail */ + break; + } + + if (val == 0x04) { + dev_err(&d->udev->dev, "%s: firmware did not run\n", + KBUILD_MODNAME); + ret = -ETIMEDOUT; + } else if (val != 0x0c) { + dev_err(&d->udev->dev, "%s: firmware boot timeout\n", + KBUILD_MODNAME); + ret = -ETIMEDOUT; + } + +error: +exit: + return ret; +} + +static int af9015_af9013_frontend_attach(struct dvb_usb_adapter *adap) +{ + int ret; + struct af9015_state *state = adap_to_priv(adap); + + if (adap->id == 0) { + state->af9013_config[0].ts_mode = AF9013_TS_USB; + memcpy(state->af9013_config[0].api_version, "\x0\x1\x9\x0", 4); + state->af9013_config[0].gpio[0] = AF9013_GPIO_HI; + state->af9013_config[0].gpio[3] = AF9013_GPIO_TUNER_ON; + } else if (adap->id == 1) { + state->af9013_config[1].ts_mode = AF9013_TS_SERIAL; + memcpy(state->af9013_config[1].api_version, "\x0\x1\x9\x0", 4); + state->af9013_config[1].gpio[0] = AF9013_GPIO_TUNER_ON; + state->af9013_config[1].gpio[1] = AF9013_GPIO_LO; + + /* copy firmware to 2nd demodulator */ + if (state->dual_mode) { + ret = af9015_copy_firmware(adap_to_d(adap)); + if (ret) { + dev_err(&adap_to_d(adap)->udev->dev, + "%s: firmware copy to 2nd " \ + "frontend failed, will " \ + "disable it\n", KBUILD_MODNAME); + state->dual_mode = 0; + return -ENODEV; + } + } else { + return -ENODEV; + } + } + + /* attach demodulator */ + adap->fe[0] = dvb_attach(af9013_attach, + &state->af9013_config[adap->id], &adap_to_d(adap)->i2c_adap); + + /* + * AF9015 firmware does not like if it gets interrupted by I2C adapter + * request on some critical phases. During normal operation I2C adapter + * is used only 2nd demodulator and tuner on dual tuner devices. + * Override demodulator callbacks and use mutex for limit access to + * those "critical" paths to keep AF9015 happy. + */ + if (adap->fe[0]) { + state->set_frontend[adap->id] = + adap->fe[0]->ops.set_frontend; + adap->fe[0]->ops.set_frontend = + af9015_af9013_set_frontend; + + state->read_status[adap->id] = + adap->fe[0]->ops.read_status; + adap->fe[0]->ops.read_status = + af9015_af9013_read_status; + + state->init[adap->id] = adap->fe[0]->ops.init; + adap->fe[0]->ops.init = af9015_af9013_init; + + state->sleep[adap->id] = adap->fe[0]->ops.sleep; + adap->fe[0]->ops.sleep = af9015_af9013_sleep; + } + + return adap->fe[0] == NULL ? -ENODEV : 0; +} + +static struct mt2060_config af9015_mt2060_config = { + .i2c_address = 0xc0, + .clock_out = 0, +}; + +static struct qt1010_config af9015_qt1010_config = { + .i2c_address = 0xc4, +}; + +static struct tda18271_config af9015_tda18271_config = { + .gate = TDA18271_GATE_DIGITAL, + .small_i2c = TDA18271_16_BYTE_CHUNK_INIT, +}; + +static struct mxl5005s_config af9015_mxl5003_config = { + .i2c_address = 0xc6, + .if_freq = IF_FREQ_4570000HZ, + .xtal_freq = CRYSTAL_FREQ_16000000HZ, + .agc_mode = MXL_SINGLE_AGC, + .tracking_filter = MXL_TF_DEFAULT, + .rssi_enable = MXL_RSSI_ENABLE, + .cap_select = MXL_CAP_SEL_ENABLE, + .div_out = MXL_DIV_OUT_4, + .clock_out = MXL_CLOCK_OUT_DISABLE, + .output_load = MXL5005S_IF_OUTPUT_LOAD_200_OHM, + .top = MXL5005S_TOP_25P2, + .mod_mode = MXL_DIGITAL_MODE, + .if_mode = MXL_ZERO_IF, + .AgcMasterByte = 0x00, +}; + +static struct mxl5005s_config af9015_mxl5005_config = { + .i2c_address = 0xc6, + .if_freq = IF_FREQ_4570000HZ, + .xtal_freq = CRYSTAL_FREQ_16000000HZ, + .agc_mode = MXL_SINGLE_AGC, + .tracking_filter = MXL_TF_OFF, + .rssi_enable = MXL_RSSI_ENABLE, + .cap_select = MXL_CAP_SEL_ENABLE, + .div_out = MXL_DIV_OUT_4, + .clock_out = MXL_CLOCK_OUT_DISABLE, + .output_load = MXL5005S_IF_OUTPUT_LOAD_200_OHM, + .top = MXL5005S_TOP_25P2, + .mod_mode = MXL_DIGITAL_MODE, + .if_mode = MXL_ZERO_IF, + .AgcMasterByte = 0x00, +}; + +static struct mc44s803_config af9015_mc44s803_config = { + .i2c_address = 0xc0, + .dig_out = 1, +}; + +static struct tda18218_config af9015_tda18218_config = { + .i2c_address = 0xc0, + .i2c_wr_max = 21, /* max wr bytes AF9015 I2C adap can handle at once */ +}; + +static struct mxl5007t_config af9015_mxl5007t_config = { + .xtal_freq_hz = MxL_XTAL_24_MHZ, + .if_freq_hz = MxL_IF_4_57_MHZ, +}; + +static int af9015_tuner_attach(struct dvb_usb_adapter *adap) +{ + struct dvb_usb_device *d = adap_to_d(adap); + struct af9015_state *state = d_to_priv(d); + int ret; + dev_dbg(&d->udev->dev, "%s:\n", __func__); + + switch (state->af9013_config[adap->id].tuner) { + case AF9013_TUNER_MT2060: + case AF9013_TUNER_MT2060_2: + ret = dvb_attach(mt2060_attach, adap->fe[0], + &adap_to_d(adap)->i2c_adap, &af9015_mt2060_config, + state->mt2060_if1[adap->id]) + == NULL ? -ENODEV : 0; + break; + case AF9013_TUNER_QT1010: + case AF9013_TUNER_QT1010A: + ret = dvb_attach(qt1010_attach, adap->fe[0], + &adap_to_d(adap)->i2c_adap, + &af9015_qt1010_config) == NULL ? -ENODEV : 0; + break; + case AF9013_TUNER_TDA18271: + ret = dvb_attach(tda18271_attach, adap->fe[0], 0xc0, + &adap_to_d(adap)->i2c_adap, + &af9015_tda18271_config) == NULL ? -ENODEV : 0; + break; + case AF9013_TUNER_TDA18218: + ret = dvb_attach(tda18218_attach, adap->fe[0], + &adap_to_d(adap)->i2c_adap, + &af9015_tda18218_config) == NULL ? -ENODEV : 0; + break; + case AF9013_TUNER_MXL5003D: + ret = dvb_attach(mxl5005s_attach, adap->fe[0], + &adap_to_d(adap)->i2c_adap, + &af9015_mxl5003_config) == NULL ? -ENODEV : 0; + break; + case AF9013_TUNER_MXL5005D: + case AF9013_TUNER_MXL5005R: + ret = dvb_attach(mxl5005s_attach, adap->fe[0], + &adap_to_d(adap)->i2c_adap, + &af9015_mxl5005_config) == NULL ? -ENODEV : 0; + break; + case AF9013_TUNER_ENV77H11D5: + ret = dvb_attach(dvb_pll_attach, adap->fe[0], 0xc0, + &adap_to_d(adap)->i2c_adap, + DVB_PLL_TDA665X) == NULL ? -ENODEV : 0; + break; + case AF9013_TUNER_MC44S803: + ret = dvb_attach(mc44s803_attach, adap->fe[0], + &adap_to_d(adap)->i2c_adap, + &af9015_mc44s803_config) == NULL ? -ENODEV : 0; + break; + case AF9013_TUNER_MXL5007T: + ret = dvb_attach(mxl5007t_attach, adap->fe[0], + &adap_to_d(adap)->i2c_adap, + 0xc0, &af9015_mxl5007t_config) == NULL ? -ENODEV : 0; + break; + case AF9013_TUNER_UNKNOWN: + default: + dev_err(&d->udev->dev, "%s: unknown tuner id=%d\n", + KBUILD_MODNAME, + state->af9013_config[adap->id].tuner); + ret = -ENODEV; + } + + if (adap->fe[0]->ops.tuner_ops.init) { + state->tuner_init[adap->id] = + adap->fe[0]->ops.tuner_ops.init; + adap->fe[0]->ops.tuner_ops.init = af9015_tuner_init; + } + + if (adap->fe[0]->ops.tuner_ops.sleep) { + state->tuner_sleep[adap->id] = + adap->fe[0]->ops.tuner_ops.sleep; + adap->fe[0]->ops.tuner_ops.sleep = af9015_tuner_sleep; + } + + return ret; +} + +static int af9015_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff) +{ + struct dvb_usb_device *d = adap_to_d(adap); + int ret; + dev_dbg(&d->udev->dev, "%s: onoff=%d\n", __func__, onoff); + + if (onoff) + ret = af9015_set_reg_bit(d, 0xd503, 0); + else + ret = af9015_clear_reg_bit(d, 0xd503, 0); + + return ret; +} + +static int af9015_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid, + int onoff) +{ + struct dvb_usb_device *d = adap_to_d(adap); + int ret; + u8 idx; + dev_dbg(&d->udev->dev, "%s: index=%d pid=%04x onoff=%d\n", + __func__, index, pid, onoff); + + ret = af9015_write_reg(d, 0xd505, (pid & 0xff)); + if (ret) + goto error; + + ret = af9015_write_reg(d, 0xd506, (pid >> 8)); + if (ret) + goto error; + + idx = ((index & 0x1f) | (1 << 5)); + ret = af9015_write_reg(d, 0xd504, idx); + +error: + return ret; +} + +static int af9015_init_endpoint(struct dvb_usb_device *d) +{ + struct af9015_state *state = d_to_priv(d); + int ret; + u16 frame_size; + u8 packet_size; + dev_dbg(&d->udev->dev, "%s: USB speed=%d\n", __func__, d->udev->speed); + + if (d->udev->speed == USB_SPEED_FULL) { + frame_size = TS_USB11_FRAME_SIZE/4; + packet_size = TS_USB11_MAX_PACKET_SIZE/4; + } else { + frame_size = TS_USB20_FRAME_SIZE/4; + packet_size = TS_USB20_MAX_PACKET_SIZE/4; + } + + ret = af9015_set_reg_bit(d, 0xd507, 2); /* assert EP4 reset */ + if (ret) + goto error; + ret = af9015_set_reg_bit(d, 0xd50b, 1); /* assert EP5 reset */ + if (ret) + goto error; + ret = af9015_clear_reg_bit(d, 0xdd11, 5); /* disable EP4 */ + if (ret) + goto error; + ret = af9015_clear_reg_bit(d, 0xdd11, 6); /* disable EP5 */ + if (ret) + goto error; + ret = af9015_set_reg_bit(d, 0xdd11, 5); /* enable EP4 */ + if (ret) + goto error; + if (state->dual_mode) { + ret = af9015_set_reg_bit(d, 0xdd11, 6); /* enable EP5 */ + if (ret) + goto error; + } + ret = af9015_clear_reg_bit(d, 0xdd13, 5); /* disable EP4 NAK */ + if (ret) + goto error; + if (state->dual_mode) { + ret = af9015_clear_reg_bit(d, 0xdd13, 6); /* disable EP5 NAK */ + if (ret) + goto error; + } + /* EP4 xfer length */ + ret = af9015_write_reg(d, 0xdd88, frame_size & 0xff); + if (ret) + goto error; + ret = af9015_write_reg(d, 0xdd89, frame_size >> 8); + if (ret) + goto error; + /* EP5 xfer length */ + ret = af9015_write_reg(d, 0xdd8a, frame_size & 0xff); + if (ret) + goto error; + ret = af9015_write_reg(d, 0xdd8b, frame_size >> 8); + if (ret) + goto error; + ret = af9015_write_reg(d, 0xdd0c, packet_size); /* EP4 packet size */ + if (ret) + goto error; + ret = af9015_write_reg(d, 0xdd0d, packet_size); /* EP5 packet size */ + if (ret) + goto error; + ret = af9015_clear_reg_bit(d, 0xd507, 2); /* negate EP4 reset */ + if (ret) + goto error; + if (state->dual_mode) { + ret = af9015_clear_reg_bit(d, 0xd50b, 1); /* negate EP5 reset */ + if (ret) + goto error; + } + + /* enable / disable mp2if2 */ + if (state->dual_mode) + ret = af9015_set_reg_bit(d, 0xd50b, 0); + else + ret = af9015_clear_reg_bit(d, 0xd50b, 0); + +error: + if (ret) + dev_err(&d->udev->dev, "%s: endpoint init failed=%d\n", + KBUILD_MODNAME, ret); + + return ret; +} + +static int af9015_init(struct dvb_usb_device *d) +{ + struct af9015_state *state = d_to_priv(d); + int ret; + dev_dbg(&d->udev->dev, "%s:\n", __func__); + + mutex_init(&state->fe_mutex); + + /* init RC canary */ + ret = af9015_write_reg(d, 0x98e9, 0xff); + if (ret) + goto error; + + ret = af9015_init_endpoint(d); + if (ret) + goto error; + +error: + return ret; +} + +struct af9015_rc_setup { + unsigned int id; + char *rc_codes; +}; + +static char *af9015_rc_setup_match(unsigned int id, + const struct af9015_rc_setup *table) +{ + for (; table->rc_codes; table++) + if (table->id == id) + return table->rc_codes; + return NULL; +} + +static const struct af9015_rc_setup af9015_rc_setup_modparam[] = { + { AF9015_REMOTE_A_LINK_DTU_M, RC_MAP_ALINK_DTU_M }, + { AF9015_REMOTE_MSI_DIGIVOX_MINI_II_V3, RC_MAP_MSI_DIGIVOX_II }, + { AF9015_REMOTE_MYGICTV_U718, RC_MAP_TOTAL_MEDIA_IN_HAND }, + { AF9015_REMOTE_DIGITTRADE_DVB_T, RC_MAP_DIGITTRADE }, + { AF9015_REMOTE_AVERMEDIA_KS, RC_MAP_AVERMEDIA_RM_KS }, + { } +}; + +static const struct af9015_rc_setup af9015_rc_setup_hashes[] = { + { 0xb8feb708, RC_MAP_MSI_DIGIVOX_II }, + { 0xa3703d00, RC_MAP_ALINK_DTU_M }, + { 0x9b7dc64e, RC_MAP_TOTAL_MEDIA_IN_HAND }, /* MYGICTV U718 */ + { 0x5d49e3db, RC_MAP_DIGITTRADE }, /* LC-Power LC-USB-DVBT */ + { } +}; + +static int af9015_rc_query(struct dvb_usb_device *d) +{ + struct af9015_state *state = d_to_priv(d); + int ret; + u8 buf[17]; + + /* read registers needed to detect remote controller code */ + ret = af9015_read_regs(d, 0x98d9, buf, sizeof(buf)); + if (ret) + goto error; + + /* If any of these are non-zero, assume invalid data */ + if (buf[1] || buf[2] || buf[3]) { + dev_dbg(&d->udev->dev, "%s: invalid data\n", __func__); + return ret; + } + + /* Check for repeat of previous code */ + if ((state->rc_repeat != buf[6] || buf[0]) && + !memcmp(&buf[12], state->rc_last, 4)) { + dev_dbg(&d->udev->dev, "%s: key repeated\n", __func__); + rc_keydown(d->rc_dev, state->rc_keycode, 0); + state->rc_repeat = buf[6]; + return ret; + } + + /* Only process key if canary killed */ + if (buf[16] != 0xff && buf[0] != 0x01) { + dev_dbg(&d->udev->dev, "%s: key pressed %*ph\n", + __func__, 4, buf + 12); + + /* Reset the canary */ + ret = af9015_write_reg(d, 0x98e9, 0xff); + if (ret) + goto error; + + /* Remember this key */ + memcpy(state->rc_last, &buf[12], 4); + if (buf[14] == (u8) ~buf[15]) { + if (buf[12] == (u8) ~buf[13]) { + /* NEC */ + state->rc_keycode = buf[12] << 8 | buf[14]; + } else { + /* NEC extended*/ + state->rc_keycode = buf[12] << 16 | + buf[13] << 8 | buf[14]; + } + } else { + /* 32 bit NEC */ + state->rc_keycode = buf[12] << 24 | buf[13] << 16 | + buf[14] << 8 | buf[15]; + } + rc_keydown(d->rc_dev, state->rc_keycode, 0); + } else { + dev_dbg(&d->udev->dev, "%s: no key press\n", __func__); + /* Invalidate last keypress */ + /* Not really needed, but helps with debug */ + state->rc_last[2] = state->rc_last[3]; + } + + state->rc_repeat = buf[6]; + state->rc_failed = false; + +error: + if (ret) { + dev_warn(&d->udev->dev, "%s: rc query failed=%d\n", + KBUILD_MODNAME, ret); + + /* allow random errors as dvb-usb will stop polling on error */ + if (!state->rc_failed) + ret = 0; + + state->rc_failed = true; + } + + return ret; +} + +static int af9015_get_rc_config(struct dvb_usb_device *d, struct dvb_usb_rc *rc) +{ + struct af9015_state *state = d_to_priv(d); + u16 vid = le16_to_cpu(d->udev->descriptor.idVendor); + + if (state->ir_mode == AF9015_IR_MODE_DISABLED) + return 0; + + /* try to load remote based module param */ + if (!rc->map_name) + rc->map_name = af9015_rc_setup_match(dvb_usb_af9015_remote, + af9015_rc_setup_modparam); + + /* try to load remote based eeprom hash */ + if (!rc->map_name) + rc->map_name = af9015_rc_setup_match(state->eeprom_sum, + af9015_rc_setup_hashes); + + /* try to load remote based USB iManufacturer string */ + if (!rc->map_name && vid == USB_VID_AFATECH) { + /* Check USB manufacturer and product strings and try + to determine correct remote in case of chip vendor + reference IDs are used. + DO NOT ADD ANYTHING NEW HERE. Use hashes instead. */ + char manufacturer[10]; + memset(manufacturer, 0, sizeof(manufacturer)); + usb_string(d->udev, d->udev->descriptor.iManufacturer, + manufacturer, sizeof(manufacturer)); + if (!strcmp("MSI", manufacturer)) { + /* iManufacturer 1 MSI + iProduct 2 MSI K-VOX */ + rc->map_name = af9015_rc_setup_match( + AF9015_REMOTE_MSI_DIGIVOX_MINI_II_V3, + af9015_rc_setup_modparam); + } + } + + /* load empty to enable rc */ + if (!rc->map_name) + rc->map_name = RC_MAP_EMPTY; + + rc->allowed_protos = RC_TYPE_NEC; + rc->query = af9015_rc_query; + rc->interval = 500; + + return 0; +} + +/* interface 0 is used by DVB-T receiver and + interface 1 is for remote controller (HID) */ +static struct dvb_usb_device_properties af9015_props = { + .driver_name = KBUILD_MODNAME, + .owner = THIS_MODULE, + .adapter_nr = adapter_nr, + .size_of_priv = sizeof(struct af9015_state), + + .generic_bulk_ctrl_endpoint = 0x02, + .generic_bulk_ctrl_endpoint_response = 0x81, + + .identify_state = af9015_identify_state, + .firmware = AF9015_FIRMWARE, + .download_firmware = af9015_download_firmware, + + .i2c_algo = &af9015_i2c_algo, + .read_config = af9015_read_config, + .frontend_attach = af9015_af9013_frontend_attach, + .tuner_attach = af9015_tuner_attach, + .init = af9015_init, + .get_rc_config = af9015_get_rc_config, + .get_stream_config = af9015_get_stream_config, + + .get_adapter_count = af9015_get_adapter_count, + .adapter = { + { + .caps = DVB_USB_ADAP_HAS_PID_FILTER | + DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, + .pid_filter_count = 32, + .pid_filter = af9015_pid_filter, + .pid_filter_ctrl = af9015_pid_filter_ctrl, + + .stream = DVB_USB_STREAM_BULK(0x84, 8, TS_USB20_FRAME_SIZE), + }, { + .stream = DVB_USB_STREAM_BULK(0x85, 8, TS_USB20_FRAME_SIZE), + }, + }, +}; + +static const struct usb_device_id af9015_id_table[] = { + { DVB_USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9015_9015, + &af9015_props, "Afatech AF9015 reference design", NULL) }, + { DVB_USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9015_9016, + &af9015_props, "Afatech AF9015 reference design", NULL) }, + { DVB_USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV_DONGLE_GOLD, + &af9015_props, "Leadtek WinFast DTV Dongle Gold", RC_MAP_LEADTEK_Y04G0051) }, + { DVB_USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV71E, + &af9015_props, "Pinnacle PCTV 71e", NULL) }, + { DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_399U, + &af9015_props, "KWorld PlusTV Dual DVB-T Stick (DVB-T 399U)", NULL) }, + { DVB_USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_TINYTWIN, + &af9015_props, "DigitalNow TinyTwin", RC_MAP_AZUREWAVE_AD_TU700) }, + { DVB_USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_AZUREWAVE_AD_TU700, + &af9015_props, "TwinHan AzureWave AD-TU700(704J)", RC_MAP_AZUREWAVE_AD_TU700) }, + { DVB_USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_USB_XE_REV2, + &af9015_props, "TerraTec Cinergy T USB XE", NULL) }, + { DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_PC160_2T, + &af9015_props, "KWorld PlusTV Dual DVB-T PCI (DVB-T PC160-2T)", NULL) }, + { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR_X, + &af9015_props, "AVerMedia AVerTV DVB-T Volar X", RC_MAP_AVERMEDIA_M135A) }, + { DVB_USB_DEVICE(USB_VID_XTENSIONS, USB_PID_XTENSIONS_XD_380, + &af9015_props, "Xtensions XD-380", NULL) }, + { DVB_USB_DEVICE(USB_VID_MSI_2, USB_PID_MSI_DIGIVOX_DUO, + &af9015_props, "MSI DIGIVOX Duo", RC_MAP_MSI_DIGIVOX_III) }, + { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR_X_2, + &af9015_props, "Fujitsu-Siemens Slim Mobile USB DVB-T", NULL) }, + { DVB_USB_DEVICE(USB_VID_TELESTAR, USB_PID_TELESTAR_STARSTICK_2, + &af9015_props, "Telestar Starstick 2", NULL) }, + { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A309, + &af9015_props, "AVerMedia A309", NULL) }, + { DVB_USB_DEVICE(USB_VID_MSI_2, USB_PID_MSI_DIGI_VOX_MINI_III, + &af9015_props, "MSI Digi VOX mini III", RC_MAP_MSI_DIGIVOX_III) }, + { DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_395U, + &af9015_props, "KWorld USB DVB-T TV Stick II (VS-DVB-T 395U)", NULL) }, + { DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_395U_2, + &af9015_props, "KWorld USB DVB-T TV Stick II (VS-DVB-T 395U)", NULL) }, + { DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_395U_3, + &af9015_props, "KWorld USB DVB-T TV Stick II (VS-DVB-T 395U)", NULL) }, + { DVB_USB_DEVICE(USB_VID_AFATECH, USB_PID_TREKSTOR_DVBT, + &af9015_props, "TrekStor DVB-T USB Stick", RC_MAP_TREKSTOR) }, + { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A850, + &af9015_props, "AverMedia AVerTV Volar Black HD (A850)", NULL) }, + { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A805, + &af9015_props, "AverMedia AVerTV Volar GPS 805 (A805)", NULL) }, + { DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_CONCEPTRONIC_CTVDIGRCU, + &af9015_props, "Conceptronic USB2.0 DVB-T CTVDIGRCU V3.0", NULL) }, + { DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_MC810, + &af9015_props, "KWorld Digial MC-810", NULL) }, + { DVB_USB_DEVICE(USB_VID_KYE, USB_PID_GENIUS_TVGO_DVB_T03, + &af9015_props, "Genius TVGo DVB-T03", NULL) }, + { DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_399U_2, + &af9015_props, "KWorld PlusTV Dual DVB-T Stick (DVB-T 399U)", NULL) }, + { DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_PC160_T, + &af9015_props, "KWorld PlusTV DVB-T PCI Pro Card (DVB-T PC160-T)", NULL) }, + { DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_SVEON_STV20, + &af9015_props, "Sveon STV20 Tuner USB DVB-T HDTV", NULL) }, + { DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_TINYTWIN_2, + &af9015_props, "DigitalNow TinyTwin v2", RC_MAP_DIGITALNOW_TINYTWIN) }, + { DVB_USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV2000DS, + &af9015_props, "Leadtek WinFast DTV2000DS", RC_MAP_LEADTEK_Y04G0051) }, + { DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_UB383_T, + &af9015_props, "KWorld USB DVB-T Stick Mobile (UB383-T)", NULL) }, + { DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_395U_4, + &af9015_props, "KWorld USB DVB-T TV Stick II (VS-DVB-T 395U)", NULL) }, + { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A815M, + &af9015_props, "AverMedia AVerTV Volar M (A815Mac)", NULL) }, + { DVB_USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_STICK_RC, + &af9015_props, "TerraTec Cinergy T Stick RC", RC_MAP_TERRATEC_SLIM_2) }, + { DVB_USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_STICK_DUAL_RC, + &af9015_props, "TerraTec Cinergy T Stick Dual RC", RC_MAP_TERRATEC_SLIM) }, + { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A850T, + &af9015_props, "AverMedia AVerTV Red HD+ (A850T)", NULL) }, + { DVB_USB_DEVICE(USB_VID_GTEK, USB_PID_TINYTWIN_3, + &af9015_props, "DigitalNow TinyTwin v3", RC_MAP_DIGITALNOW_TINYTWIN) }, + { DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_SVEON_STV22, + &af9015_props, "Sveon STV22 Dual USB DVB-T Tuner HDTV", RC_MAP_MSI_DIGIVOX_III) }, + { } +}; +MODULE_DEVICE_TABLE(usb, af9015_id_table); + +/* usb specific object needed to register this driver with the usb subsystem */ +static struct usb_driver af9015_usb_driver = { + .name = KBUILD_MODNAME, + .id_table = af9015_id_table, + .probe = dvb_usbv2_probe, + .disconnect = dvb_usbv2_disconnect, + .suspend = dvb_usbv2_suspend, + .resume = dvb_usbv2_resume, + .reset_resume = dvb_usbv2_reset_resume, + .no_dynamic_id = 1, + .soft_unbind = 1, +}; + +module_usb_driver(af9015_usb_driver); + +MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>"); +MODULE_DESCRIPTION("Afatech AF9015 driver"); +MODULE_LICENSE("GPL"); +MODULE_FIRMWARE(AF9015_FIRMWARE); diff --git a/drivers/media/dvb/dvb-usb/af9015.h b/drivers/media/usb/dvb-usb-v2/af9015.h index 2f68419e899b..533637dedd23 100644 --- a/drivers/media/dvb/dvb-usb/af9015.h +++ b/drivers/media/usb/dvb-usb-v2/af9015.h @@ -21,18 +21,35 @@ * */ -#ifndef _DVB_USB_AF9015_H_ -#define _DVB_USB_AF9015_H_ +#ifndef AF9015_H +#define AF9015_H -#define DVB_USB_LOG_PREFIX "af9015" -#include "dvb-usb.h" +#include <linux/hash.h> +#include "dvb_usb.h" +#include "af9013.h" +#include "dvb-pll.h" +#include "mt2060.h" +#include "qt1010.h" +#include "tda18271.h" +#include "mxl5005s.h" +#include "mc44s803.h" +#include "tda18218.h" +#include "mxl5007t.h" -#define deb_info(args...) dprintk(dvb_usb_af9015_debug, 0x01, args) -#define deb_rc(args...) dprintk(dvb_usb_af9015_debug, 0x02, args) -#define deb_xfer(args...) dprintk(dvb_usb_af9015_debug, 0x04, args) -#define deb_reg(args...) dprintk(dvb_usb_af9015_debug, 0x08, args) -#define deb_i2c(args...) dprintk(dvb_usb_af9015_debug, 0x10, args) -#define deb_fw(args...) dprintk(dvb_usb_af9015_debug, 0x20, args) +#define AF9015_FIRMWARE "dvb-usb-af9015.fw" + +/* Windows driver uses packet count 21 for USB1.1 and 348 for USB2.0. + We use smaller - about 1/4 from the original, 5 and 87. */ +#define TS_PACKET_SIZE 188 + +#define TS_USB20_PACKET_COUNT 87 +#define TS_USB20_FRAME_SIZE (TS_PACKET_SIZE*TS_USB20_PACKET_COUNT) + +#define TS_USB11_PACKET_COUNT 5 +#define TS_USB11_FRAME_SIZE (TS_PACKET_SIZE*TS_USB11_PACKET_COUNT) + +#define TS_USB20_MAX_PACKET_SIZE 512 +#define TS_USB11_MAX_PACKET_SIZE 64 #define AF9015_I2C_EEPROM 0xa0 #define AF9015_I2C_DEMOD 0x38 @@ -99,9 +116,18 @@ enum af9015_ir_mode { }; struct af9015_state { + u8 ir_mode; u8 rc_repeat; u32 rc_keycode; u8 rc_last[4]; + bool rc_failed; + u8 dual_mode; + u8 seq; /* packet sequence number */ + u16 mt2060_if1[2]; + u16 firmware_size; + u16 firmware_checksum; + u32 eeprom_sum; + struct af9013_config af9013_config[2]; /* for demod callback override */ int (*set_frontend[2]) (struct dvb_frontend *fe); @@ -110,14 +136,7 @@ struct af9015_state { int (*sleep[2]) (struct dvb_frontend *fe); int (*tuner_init[2]) (struct dvb_frontend *fe); int (*tuner_sleep[2]) (struct dvb_frontend *fe); -}; - -struct af9015_config { - u8 dual_mode:1; - u16 mt2060_if1[2]; - u16 firmware_size; - u16 firmware_checksum; - u32 eeprom_sum; + struct mutex fe_mutex; }; enum af9015_remote { diff --git a/drivers/media/dvb/dvb-usb/af9035.c b/drivers/media/usb/dvb-usb-v2/af9035.c index e83b39d3993c..aabd3fc03ea7 100644 --- a/drivers/media/dvb/dvb-usb/af9035.c +++ b/drivers/media/usb/dvb-usb-v2/af9035.c @@ -22,9 +22,6 @@ #include "af9035.h" DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); -static DEFINE_MUTEX(af9035_usb_mutex); -static struct dvb_usb_device_properties af9035_properties[2]; -static int af9035_properties_count = ARRAY_SIZE(af9035_properties); static u16 af9035_checksum(const u8 *buf, size_t len) { @@ -42,100 +39,80 @@ static u16 af9035_checksum(const u8 *buf, size_t len) return checksum; } -static int af9035_ctrl_msg(struct usb_device *udev, struct usb_req *req) +static int af9035_ctrl_msg(struct dvb_usb_device *d, struct usb_req *req) { #define BUF_LEN 64 #define REQ_HDR_LEN 4 /* send header size */ #define ACK_HDR_LEN 3 /* rece header size */ #define CHECKSUM_LEN 2 #define USB_TIMEOUT 2000 - - int ret, msg_len, act_len; + struct state *state = d_to_priv(d); + int ret, wlen, rlen; u8 buf[BUF_LEN]; - static u8 seq; /* packet sequence number */ u16 checksum, tmp_checksum; /* buffer overflow check */ if (req->wlen > (BUF_LEN - REQ_HDR_LEN - CHECKSUM_LEN) || - req->rlen > (BUF_LEN - ACK_HDR_LEN - CHECKSUM_LEN)) { - pr_debug("%s: too much data wlen=%d rlen=%d\n", __func__, - req->wlen, req->rlen); + req->rlen > (BUF_LEN - ACK_HDR_LEN - CHECKSUM_LEN)) { + dev_err(&d->udev->dev, "%s: too much data wlen=%d rlen=%d\n", + __func__, req->wlen, req->rlen); return -EINVAL; } - if (mutex_lock_interruptible(&af9035_usb_mutex) < 0) - return -EAGAIN; - buf[0] = REQ_HDR_LEN + req->wlen + CHECKSUM_LEN - 1; buf[1] = req->mbox; buf[2] = req->cmd; - buf[3] = seq++; - if (req->wlen) - memcpy(&buf[4], req->wbuf, req->wlen); + buf[3] = state->seq++; + memcpy(&buf[REQ_HDR_LEN], req->wbuf, req->wlen); + + wlen = REQ_HDR_LEN + req->wlen + CHECKSUM_LEN; + rlen = ACK_HDR_LEN + req->rlen + CHECKSUM_LEN; /* calc and add checksum */ checksum = af9035_checksum(buf, buf[0] - 1); buf[buf[0] - 1] = (checksum >> 8); buf[buf[0] - 0] = (checksum & 0xff); - msg_len = REQ_HDR_LEN + req->wlen + CHECKSUM_LEN ; + /* no ack for these packets */ + if (req->cmd == CMD_FW_DL) + rlen = 0; - /* send req */ - ret = usb_bulk_msg(udev, usb_sndbulkpipe(udev, 0x02), buf, msg_len, - &act_len, USB_TIMEOUT); - if (ret < 0) - err("bulk message failed=%d (%d/%d)", ret, msg_len, act_len); - else - if (act_len != msg_len) - ret = -EIO; /* all data is not send */ - if (ret < 0) - goto err_mutex_unlock; + ret = dvb_usbv2_generic_rw(d, buf, wlen, buf, rlen); + if (ret) + goto err; /* no ack for those packets */ if (req->cmd == CMD_FW_DL) - goto exit_mutex_unlock; - - /* receive ack and data if read req */ - msg_len = ACK_HDR_LEN + req->rlen + CHECKSUM_LEN; - ret = usb_bulk_msg(udev, usb_rcvbulkpipe(udev, 0x81), buf, msg_len, - &act_len, USB_TIMEOUT); - if (ret < 0) { - err("recv bulk message failed=%d", ret); - ret = -EIO; - goto err_mutex_unlock; - } - - if (act_len != msg_len) { - err("recv bulk message truncated (%d != %d)", act_len, msg_len); - ret = -EIO; - goto err_mutex_unlock; - } + goto exit; /* verify checksum */ - checksum = af9035_checksum(buf, act_len - 2); - tmp_checksum = (buf[act_len - 2] << 8) | buf[act_len - 1]; + checksum = af9035_checksum(buf, rlen - 2); + tmp_checksum = (buf[rlen - 2] << 8) | buf[rlen - 1]; if (tmp_checksum != checksum) { - err("%s: command=%02x checksum mismatch (%04x != %04x)", - __func__, req->cmd, tmp_checksum, checksum); + dev_err(&d->udev->dev, "%s: command=%02x checksum mismatch " \ + "(%04x != %04x)\n", KBUILD_MODNAME, req->cmd, + tmp_checksum, checksum); ret = -EIO; - goto err_mutex_unlock; + goto err; } /* check status */ if (buf[2]) { - pr_debug("%s: command=%02x failed fw error=%d\n", __func__, - req->cmd, buf[2]); + dev_dbg(&d->udev->dev, "%s: command=%02x failed fw error=%d\n", + __func__, req->cmd, buf[2]); ret = -EIO; - goto err_mutex_unlock; + goto err; } /* read request, copy returned data to return buf */ if (req->rlen) memcpy(req->rbuf, &buf[ACK_HDR_LEN], req->rlen); -err_mutex_unlock: -exit_mutex_unlock: - mutex_unlock(&af9035_usb_mutex); +exit: + return 0; + +err: + dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); return ret; } @@ -155,7 +132,7 @@ static int af9035_wr_regs(struct dvb_usb_device *d, u32 reg, u8 *val, int len) wbuf[5] = (reg >> 0) & 0xff; memcpy(&wbuf[6], val, len); - return af9035_ctrl_msg(d->udev, &req); + return af9035_ctrl_msg(d, &req); } /* read multiple registers */ @@ -165,7 +142,7 @@ static int af9035_rd_regs(struct dvb_usb_device *d, u32 reg, u8 *val, int len) u8 mbox = (reg >> 16) & 0xff; struct usb_req req = { CMD_MEM_RD, mbox, sizeof(wbuf), wbuf, len, val }; - return af9035_ctrl_msg(d->udev, &req); + return af9035_ctrl_msg(d, &req); } /* write single register */ @@ -205,7 +182,7 @@ static int af9035_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], int num) { struct dvb_usb_device *d = i2c_get_adapdata(adap); - struct state *state = d->priv; + struct state *state = d_to_priv(d); int ret; if (mutex_lock_interruptible(&d->i2c_mutex) < 0) @@ -249,7 +226,7 @@ static int af9035_i2c_master_xfer(struct i2c_adapter *adap, buf[3] = 0x00; /* reg addr MSB */ buf[4] = 0x00; /* reg addr LSB */ memcpy(&buf[5], msg[0].buf, msg[0].len); - ret = af9035_ctrl_msg(d->udev, &req); + ret = af9035_ctrl_msg(d, &req); } } else if (num == 1 && !(msg[0].flags & I2C_M_RD)) { if (msg[0].len > 40) { @@ -272,7 +249,7 @@ static int af9035_i2c_master_xfer(struct i2c_adapter *adap, buf[3] = 0x00; /* reg addr MSB */ buf[4] = 0x00; /* reg addr LSB */ memcpy(&buf[5], msg[0].buf, msg[0].len); - ret = af9035_ctrl_msg(d->udev, &req); + ret = af9035_ctrl_msg(d, &req); } } else { /* @@ -301,87 +278,7 @@ static struct i2c_algorithm af9035_i2c_algo = { .functionality = af9035_i2c_functionality, }; -#define AF9035_POLL 250 -static int af9035_rc_query(struct dvb_usb_device *d) -{ - unsigned int key; - unsigned char b[4]; - int ret; - struct usb_req req = { CMD_IR_GET, 0, 0, NULL, 4, b }; - - ret = af9035_ctrl_msg(d->udev, &req); - if (ret < 0) - goto err; - - if ((b[2] + b[3]) == 0xff) { - if ((b[0] + b[1]) == 0xff) { - /* NEC */ - key = b[0] << 8 | b[2]; - } else { - /* ext. NEC */ - key = b[0] << 16 | b[1] << 8 | b[2]; - } - } else { - key = b[0] << 24 | b[1] << 16 | b[2] << 8 | b[3]; - } - - rc_keydown(d->rc_dev, key, 0); - -err: - /* ignore errors */ - return 0; -} - -static int af9035_init(struct dvb_usb_device *d) -{ - struct state *state = d->priv; - int ret, i; - u16 frame_size = 87 * 188 / 4; - u8 packet_size = 512 / 4; - struct reg_val_mask tab[] = { - { 0x80f99d, 0x01, 0x01 }, - { 0x80f9a4, 0x01, 0x01 }, - { 0x00dd11, 0x00, 0x20 }, - { 0x00dd11, 0x00, 0x40 }, - { 0x00dd13, 0x00, 0x20 }, - { 0x00dd13, 0x00, 0x40 }, - { 0x00dd11, 0x20, 0x20 }, - { 0x00dd88, (frame_size >> 0) & 0xff, 0xff}, - { 0x00dd89, (frame_size >> 8) & 0xff, 0xff}, - { 0x00dd0c, packet_size, 0xff}, - { 0x00dd11, state->dual_mode << 6, 0x40 }, - { 0x00dd8a, (frame_size >> 0) & 0xff, 0xff}, - { 0x00dd8b, (frame_size >> 8) & 0xff, 0xff}, - { 0x00dd0d, packet_size, 0xff }, - { 0x80f9a3, 0x00, 0x01 }, - { 0x80f9cd, 0x00, 0x01 }, - { 0x80f99d, 0x00, 0x01 }, - { 0x80f9a4, 0x00, 0x01 }, - }; - - pr_debug("%s: USB speed=%d frame_size=%04x packet_size=%02x\n", - __func__, d->udev->speed, frame_size, packet_size); - - /* init endpoints */ - for (i = 0; i < ARRAY_SIZE(tab); i++) { - ret = af9035_wr_reg_mask(d, tab[i].reg, tab[i].val, - tab[i].mask); - if (ret < 0) - goto err; - } - - return 0; - -err: - pr_debug("%s: failed=%d\n", __func__, ret); - - return ret; -} - -static int af9035_identify_state(struct usb_device *udev, - struct dvb_usb_device_properties *props, - struct dvb_usb_device_description **desc, - int *cold) +static int af9035_identify_state(struct dvb_usb_device *d, const char **name) { int ret; u8 wbuf[1] = { 1 }; @@ -389,26 +286,25 @@ static int af9035_identify_state(struct usb_device *udev, struct usb_req req = { CMD_FW_QUERYINFO, 0, sizeof(wbuf), wbuf, sizeof(rbuf), rbuf }; - ret = af9035_ctrl_msg(udev, &req); + ret = af9035_ctrl_msg(d, &req); if (ret < 0) goto err; - pr_debug("%s: reply=%02x %02x %02x %02x\n", __func__, - rbuf[0], rbuf[1], rbuf[2], rbuf[3]); + dev_dbg(&d->udev->dev, "%s: reply=%*ph\n", __func__, 4, rbuf); if (rbuf[0] || rbuf[1] || rbuf[2] || rbuf[3]) - *cold = 0; + ret = WARM; else - *cold = 1; + ret = COLD; - return 0; + return ret; err: - pr_debug("%s: failed=%d\n", __func__, ret); + dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); return ret; } -static int af9035_download_firmware(struct usb_device *udev, +static int af9035_download_firmware(struct dvb_usb_device *d, const struct firmware *fw) { int ret, i, j, len; @@ -443,19 +339,19 @@ static int af9035_download_firmware(struct usb_device *udev, hdr_checksum = fw->data[fw->size - i + 5] << 8; hdr_checksum |= fw->data[fw->size - i + 6] << 0; - pr_debug("%s: core=%d addr=%04x data_len=%d checksum=%04x\n", - __func__, hdr_core, hdr_addr, hdr_data_len, - hdr_checksum); + dev_dbg(&d->udev->dev, "%s: core=%d addr=%04x data_len=%d " \ + "checksum=%04x\n", __func__, hdr_core, hdr_addr, + hdr_data_len, hdr_checksum); if (((hdr_core != 1) && (hdr_core != 2)) || (hdr_data_len > i)) { - pr_debug("%s: bad firmware\n", __func__); + dev_dbg(&d->udev->dev, "%s: bad firmware\n", __func__); break; } /* download begin packet */ req.cmd = CMD_FW_DL_BEGIN; - ret = af9035_ctrl_msg(udev, &req); + ret = af9035_ctrl_msg(d, &req); if (ret < 0) goto err; @@ -467,52 +363,54 @@ static int af9035_download_firmware(struct usb_device *udev, req_fw_dl.wlen = len; req_fw_dl.wbuf = (u8 *) &fw->data[fw->size - i + HDR_SIZE + hdr_data_len - j]; - ret = af9035_ctrl_msg(udev, &req_fw_dl); + ret = af9035_ctrl_msg(d, &req_fw_dl); if (ret < 0) goto err; } /* download end packet */ req.cmd = CMD_FW_DL_END; - ret = af9035_ctrl_msg(udev, &req); + ret = af9035_ctrl_msg(d, &req); if (ret < 0) goto err; i -= hdr_data_len + HDR_SIZE; - pr_debug("%s: data uploaded=%zu\n", __func__, fw->size - i); + dev_dbg(&d->udev->dev, "%s: data uploaded=%zu\n", + __func__, fw->size - i); } /* firmware loaded, request boot */ req.cmd = CMD_FW_BOOT; - ret = af9035_ctrl_msg(udev, &req); + ret = af9035_ctrl_msg(d, &req); if (ret < 0) goto err; /* ensure firmware starts */ wbuf[0] = 1; - ret = af9035_ctrl_msg(udev, &req_fw_ver); + ret = af9035_ctrl_msg(d, &req_fw_ver); if (ret < 0) goto err; if (!(rbuf[0] || rbuf[1] || rbuf[2] || rbuf[3])) { - info("firmware did not run"); + dev_err(&d->udev->dev, "%s: firmware did not run\n", + KBUILD_MODNAME); ret = -ENODEV; goto err; } - info("firmware version=%d.%d.%d.%d", rbuf[0], rbuf[1], rbuf[2], - rbuf[3]); + dev_info(&d->udev->dev, "%s: firmware version=%d.%d.%d.%d", + KBUILD_MODNAME, rbuf[0], rbuf[1], rbuf[2], rbuf[3]); return 0; err: - pr_debug("%s: failed=%d\n", __func__, ret); + dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); return ret; } -static int af9035_download_firmware_it9135(struct usb_device *udev, +static int af9035_download_firmware_it9135(struct dvb_usb_device *d, const struct firmware *fw) { int ret, i, i_prev; @@ -545,47 +443,48 @@ static int af9035_download_firmware_it9135(struct usb_device *udev, req_fw_dl.wlen = i - i_prev; req_fw_dl.wbuf = (u8 *) &fw->data[i_prev]; i_prev = i; - ret = af9035_ctrl_msg(udev, &req_fw_dl); + ret = af9035_ctrl_msg(d, &req_fw_dl); if (ret < 0) goto err; - pr_debug("%s: data uploaded=%d\n", __func__, i); + dev_dbg(&d->udev->dev, "%s: data uploaded=%d\n", + __func__, i); } } /* firmware loaded, request boot */ req.cmd = CMD_FW_BOOT; - ret = af9035_ctrl_msg(udev, &req); + ret = af9035_ctrl_msg(d, &req); if (ret < 0) goto err; /* ensure firmware starts */ wbuf[0] = 1; - ret = af9035_ctrl_msg(udev, &req_fw_ver); + ret = af9035_ctrl_msg(d, &req_fw_ver); if (ret < 0) goto err; if (!(rbuf[0] || rbuf[1] || rbuf[2] || rbuf[3])) { - info("firmware did not run"); + dev_err(&d->udev->dev, "%s: firmware did not run\n", + KBUILD_MODNAME); ret = -ENODEV; goto err; } - info("firmware version=%d.%d.%d.%d", rbuf[0], rbuf[1], rbuf[2], - rbuf[3]); + dev_info(&d->udev->dev, "%s: firmware version=%d.%d.%d.%d", + KBUILD_MODNAME, rbuf[0], rbuf[1], rbuf[2], rbuf[3]); return 0; err: - pr_debug("%s: failed=%d\n", __func__, ret); + dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); return ret; } -/* abuse that callback as there is no better one for reading eeprom */ -static int af9035_read_mac_address(struct dvb_usb_device *d, u8 mac[6]) +static int af9035_read_config(struct dvb_usb_device *d) { - struct state *state = d->priv; + struct state *state = d_to_priv(d); int ret, i, eeprom_shift = 0; u8 tmp; u16 tmp16; @@ -596,27 +495,31 @@ static int af9035_read_mac_address(struct dvb_usb_device *d, u8 mac[6]) goto err; state->dual_mode = tmp; - pr_debug("%s: dual mode=%d\n", __func__, state->dual_mode); + dev_dbg(&d->udev->dev, "%s: dual mode=%d\n", + __func__, state->dual_mode); - for (i = 0; i < af9035_properties[0].num_adapters; i++) { + for (i = 0; i < state->dual_mode + 1; i++) { /* tuner */ ret = af9035_rd_reg(d, EEPROM_1_TUNER_ID + eeprom_shift, &tmp); if (ret < 0) goto err; state->af9033_config[i].tuner = tmp; - pr_debug("%s: [%d]tuner=%02x\n", __func__, i, tmp); + dev_dbg(&d->udev->dev, "%s: [%d]tuner=%02x\n", + __func__, i, tmp); switch (tmp) { case AF9033_TUNER_TUA9001: case AF9033_TUNER_FC0011: case AF9033_TUNER_MXL5007T: case AF9033_TUNER_TDA18218: + case AF9033_TUNER_FC2580: state->af9033_config[i].spec_inv = 1; break; default: - warn("tuner ID=%02x not supported, please report!", - tmp); + dev_warn(&d->udev->dev, "%s: tuner id=%02x not " \ + "supported, please report!", + KBUILD_MODNAME, tmp); }; /* tuner IF frequency */ @@ -632,7 +535,7 @@ static int af9035_read_mac_address(struct dvb_usb_device *d, u8 mac[6]) tmp16 |= tmp << 8; - pr_debug("%s: [%d]IF=%d\n", __func__, i, tmp16); + dev_dbg(&d->udev->dev, "%s: [%d]IF=%d\n", __func__, i, tmp16); eeprom_shift = 0x10; /* shift for the 2nd tuner params */ } @@ -644,47 +547,20 @@ static int af9035_read_mac_address(struct dvb_usb_device *d, u8 mac[6]) tmp = (tmp >> 0) & 0x0f; - for (i = 0; i < af9035_properties[0].num_adapters; i++) + for (i = 0; i < ARRAY_SIZE(state->af9033_config); i++) state->af9033_config[i].clock = clock_lut[tmp]; - ret = af9035_rd_reg(d, EEPROM_IR_MODE, &tmp); - if (ret < 0) - goto err; - pr_debug("%s: ir_mode=%02x\n", __func__, tmp); - - /* don't activate rc if in HID mode or if not available */ - if (tmp == 5) { - ret = af9035_rd_reg(d, EEPROM_IR_TYPE, &tmp); - if (ret < 0) - goto err; - pr_debug("%s: ir_type=%02x\n", __func__, tmp); - - switch (tmp) { - case 0: /* NEC */ - default: - d->props.rc.core.protocol = RC_TYPE_NEC; - d->props.rc.core.allowed_protos = RC_TYPE_NEC; - break; - case 1: /* RC6 */ - d->props.rc.core.protocol = RC_TYPE_RC6; - d->props.rc.core.allowed_protos = RC_TYPE_RC6; - break; - } - d->props.rc.core.rc_query = af9035_rc_query; - } - return 0; err: - pr_debug("%s: failed=%d\n", __func__, ret); + dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); return ret; } -/* abuse that callback as there is no better one for reading eeprom */ -static int af9035_read_mac_address_it9135(struct dvb_usb_device *d, u8 mac[6]) +static int af9035_read_config_it9135(struct dvb_usb_device *d) { - struct state *state = d->priv; + struct state *state = d_to_priv(d); int ret, i; u8 tmp; @@ -697,17 +573,63 @@ static int af9035_read_mac_address_it9135(struct dvb_usb_device *d, u8 mac[6]) tmp = (tmp >> 0) & 0x0f; - for (i = 0; i < af9035_properties[0].num_adapters; i++) + for (i = 0; i < ARRAY_SIZE(state->af9033_config); i++) state->af9033_config[i].clock = clock_lut_it9135[tmp]; return 0; err: - pr_debug("%s: failed=%d\n", __func__, ret); + dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); + + return ret; +} + +static int af9035_tua9001_tuner_callback(struct dvb_usb_device *d, + int cmd, int arg) +{ + int ret; + u8 val; + + dev_dbg(&d->udev->dev, "%s: cmd=%d arg=%d\n", __func__, cmd, arg); + + /* + * CEN always enabled by hardware wiring + * RESETN GPIOT3 + * RXEN GPIOT2 + */ + + switch (cmd) { + case TUA9001_CMD_RESETN: + if (arg) + val = 0x00; + else + val = 0x01; + + ret = af9035_wr_reg_mask(d, 0x00d8e7, val, 0x01); + if (ret < 0) + goto err; + break; + case TUA9001_CMD_RXEN: + if (arg) + val = 0x01; + else + val = 0x00; + + ret = af9035_wr_reg_mask(d, 0x00d8eb, val, 0x01); + if (ret < 0) + goto err; + break; + } + + return 0; + +err: + dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); return ret; } + static int af9035_fc0011_tuner_callback(struct dvb_usb_device *d, int cmd, int arg) { @@ -768,23 +690,25 @@ static int af9035_fc0011_tuner_callback(struct dvb_usb_device *d, return 0; err: - pr_debug("%s: failed=%d\n", __func__, ret); + dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); return ret; } static int af9035_tuner_callback(struct dvb_usb_device *d, int cmd, int arg) { - struct state *state = d->priv; + struct state *state = d_to_priv(d); switch (state->af9033_config[0].tuner) { case AF9033_TUNER_FC0011: return af9035_fc0011_tuner_callback(d, cmd, arg); + case AF9033_TUNER_TUA9001: + return af9035_tua9001_tuner_callback(d, cmd, arg); default: break; } - return -ENODEV; + return 0; } static int af9035_frontend_callback(void *adapter_priv, int component, @@ -793,6 +717,9 @@ static int af9035_frontend_callback(void *adapter_priv, int component, struct i2c_adapter *adap = adapter_priv; struct dvb_usb_device *d = i2c_get_adapdata(adap); + dev_dbg(&d->udev->dev, "%s: component=%d cmd=%d arg=%d\n", + __func__, component, cmd, arg); + switch (component) { case DVB_FRONTEND_COMPONENT_TUNER: return af9035_tuner_callback(d, cmd, arg); @@ -800,12 +727,13 @@ static int af9035_frontend_callback(void *adapter_priv, int component, break; } - return -EINVAL; + return 0; } static int af9035_frontend_attach(struct dvb_usb_adapter *adap) { - struct state *state = adap->dev->priv; + struct state *state = adap_to_priv(adap); + struct dvb_usb_device *d = adap_to_d(adap); int ret; if (!state->af9033_config[adap->id].tuner) { @@ -818,33 +746,33 @@ static int af9035_frontend_attach(struct dvb_usb_adapter *adap) state->af9033_config[0].ts_mode = AF9033_TS_MODE_USB; state->af9033_config[1].ts_mode = AF9033_TS_MODE_SERIAL; - ret = af9035_wr_reg(adap->dev, 0x00417f, + ret = af9035_wr_reg(d, 0x00417f, state->af9033_config[1].i2c_addr); if (ret < 0) goto err; - ret = af9035_wr_reg(adap->dev, 0x00d81a, + ret = af9035_wr_reg(d, 0x00d81a, state->dual_mode); if (ret < 0) goto err; } /* attach demodulator */ - adap->fe_adap[0].fe = dvb_attach(af9033_attach, - &state->af9033_config[adap->id], &adap->dev->i2c_adap); - if (adap->fe_adap[0].fe == NULL) { + adap->fe[0] = dvb_attach(af9033_attach, + &state->af9033_config[adap->id], &d->i2c_adap); + if (adap->fe[0] == NULL) { ret = -ENODEV; goto err; } /* disable I2C-gate */ - adap->fe_adap[0].fe->ops.i2c_gate_ctrl = NULL; - adap->fe_adap[0].fe->callback = af9035_frontend_callback; + adap->fe[0]->ops.i2c_gate_ctrl = NULL; + adap->fe[0]->callback = af9035_frontend_callback; return 0; err: - pr_debug("%s: failed=%d\n", __func__, ret); + dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); return ret; } @@ -871,9 +799,15 @@ static struct tda18218_config af9035_tda18218_config = { .i2c_wr_max = 21, }; +static const struct fc2580_config af9035_fc2580_config = { + .i2c_addr = 0x56, + .clock = 16384000, +}; + static int af9035_tuner_attach(struct dvb_usb_adapter *adap) { - struct state *state = adap->dev->priv; + struct state *state = adap_to_priv(adap); + struct dvb_usb_device *d = adap_to_d(adap); int ret; struct dvb_frontend *fe; @@ -883,93 +817,95 @@ static int af9035_tuner_attach(struct dvb_usb_adapter *adap) AF9035 gpiot2 = TUA9001 RXEN */ /* configure gpiot2 and gpiot2 as output */ - ret = af9035_wr_reg_mask(adap->dev, 0x00d8ec, 0x01, 0x01); + ret = af9035_wr_reg_mask(d, 0x00d8ec, 0x01, 0x01); if (ret < 0) goto err; - ret = af9035_wr_reg_mask(adap->dev, 0x00d8ed, 0x01, 0x01); + ret = af9035_wr_reg_mask(d, 0x00d8ed, 0x01, 0x01); if (ret < 0) goto err; - ret = af9035_wr_reg_mask(adap->dev, 0x00d8e8, 0x01, 0x01); + ret = af9035_wr_reg_mask(d, 0x00d8e8, 0x01, 0x01); if (ret < 0) goto err; - ret = af9035_wr_reg_mask(adap->dev, 0x00d8e9, 0x01, 0x01); - if (ret < 0) - goto err; - - /* reset tuner */ - ret = af9035_wr_reg_mask(adap->dev, 0x00d8e7, 0x00, 0x01); - if (ret < 0) - goto err; - - usleep_range(2000, 20000); - - ret = af9035_wr_reg_mask(adap->dev, 0x00d8e7, 0x01, 0x01); - if (ret < 0) - goto err; - - /* activate tuner RX */ - /* TODO: use callback for TUA9001 RXEN */ - ret = af9035_wr_reg_mask(adap->dev, 0x00d8eb, 0x01, 0x01); + ret = af9035_wr_reg_mask(d, 0x00d8e9, 0x01, 0x01); if (ret < 0) goto err; /* attach tuner */ - fe = dvb_attach(tua9001_attach, adap->fe_adap[0].fe, - &adap->dev->i2c_adap, &af9035_tua9001_config); + fe = dvb_attach(tua9001_attach, adap->fe[0], + &d->i2c_adap, &af9035_tua9001_config); break; case AF9033_TUNER_FC0011: - fe = dvb_attach(fc0011_attach, adap->fe_adap[0].fe, - &adap->dev->i2c_adap, &af9035_fc0011_config); + fe = dvb_attach(fc0011_attach, adap->fe[0], + &d->i2c_adap, &af9035_fc0011_config); break; case AF9033_TUNER_MXL5007T: - ret = af9035_wr_reg(adap->dev, 0x00d8e0, 1); + ret = af9035_wr_reg(d, 0x00d8e0, 1); if (ret < 0) goto err; - ret = af9035_wr_reg(adap->dev, 0x00d8e1, 1); + ret = af9035_wr_reg(d, 0x00d8e1, 1); if (ret < 0) goto err; - ret = af9035_wr_reg(adap->dev, 0x00d8df, 0); + ret = af9035_wr_reg(d, 0x00d8df, 0); if (ret < 0) goto err; msleep(30); - ret = af9035_wr_reg(adap->dev, 0x00d8df, 1); + ret = af9035_wr_reg(d, 0x00d8df, 1); if (ret < 0) goto err; msleep(300); - ret = af9035_wr_reg(adap->dev, 0x00d8c0, 1); + ret = af9035_wr_reg(d, 0x00d8c0, 1); if (ret < 0) goto err; - ret = af9035_wr_reg(adap->dev, 0x00d8c1, 1); + ret = af9035_wr_reg(d, 0x00d8c1, 1); if (ret < 0) goto err; - ret = af9035_wr_reg(adap->dev, 0x00d8bf, 0); + ret = af9035_wr_reg(d, 0x00d8bf, 0); if (ret < 0) goto err; - ret = af9035_wr_reg(adap->dev, 0x00d8b4, 1); + ret = af9035_wr_reg(d, 0x00d8b4, 1); if (ret < 0) goto err; - ret = af9035_wr_reg(adap->dev, 0x00d8b5, 1); + ret = af9035_wr_reg(d, 0x00d8b5, 1); if (ret < 0) goto err; - ret = af9035_wr_reg(adap->dev, 0x00d8b3, 1); + ret = af9035_wr_reg(d, 0x00d8b3, 1); if (ret < 0) goto err; /* attach tuner */ - fe = dvb_attach(mxl5007t_attach, adap->fe_adap[0].fe, - &adap->dev->i2c_adap, 0x60, &af9035_mxl5007t_config); + fe = dvb_attach(mxl5007t_attach, adap->fe[0], + &d->i2c_adap, 0x60, &af9035_mxl5007t_config); break; case AF9033_TUNER_TDA18218: /* attach tuner */ - fe = dvb_attach(tda18218_attach, adap->fe_adap[0].fe, - &adap->dev->i2c_adap, &af9035_tda18218_config); + fe = dvb_attach(tda18218_attach, adap->fe[0], + &d->i2c_adap, &af9035_tda18218_config); + break; + case AF9033_TUNER_FC2580: + /* Tuner enable using gpiot2_o, gpiot2_en and gpiot2_on */ + ret = af9035_wr_reg_mask(d, 0xd8eb, 0x01, 0x01); + if (ret < 0) + goto err; + + ret = af9035_wr_reg_mask(d, 0xd8ec, 0x01, 0x01); + if (ret < 0) + goto err; + + ret = af9035_wr_reg_mask(d, 0xd8ed, 0x01, 0x01); + if (ret < 0) + goto err; + + usleep_range(10000, 50000); + /* attach tuner */ + fe = dvb_attach(fc2580_attach, adap->fe[0], + &d->i2c_adap, &af9035_fc2580_config); break; default: fe = NULL; @@ -983,256 +919,234 @@ static int af9035_tuner_attach(struct dvb_usb_adapter *adap) return 0; err: - pr_debug("%s: failed=%d\n", __func__, ret); + dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); return ret; } -enum af9035_id_entry { - AF9035_15A4_9035, - AF9035_15A4_1000, - AF9035_15A4_1001, - AF9035_15A4_1002, - AF9035_15A4_1003, - AF9035_0CCD_0093, - AF9035_07CA_A835, - AF9035_07CA_B835, - AF9035_07CA_1867, - AF9035_07CA_A867, - AF9035_07CA_0825, -}; - -static struct usb_device_id af9035_id[] = { - [AF9035_15A4_9035] = { - USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9035_9035)}, - [AF9035_15A4_1000] = { - USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9035_1000)}, - [AF9035_15A4_1001] = { - USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9035_1001)}, - [AF9035_15A4_1002] = { - USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9035_1002)}, - [AF9035_15A4_1003] = { - USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9035_1003)}, - [AF9035_0CCD_0093] = { - USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_STICK)}, - [AF9035_07CA_A835] = { - USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A835)}, - [AF9035_07CA_B835] = { - USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_B835)}, - [AF9035_07CA_1867] = { - USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_1867)}, - [AF9035_07CA_A867] = { - USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A867)}, - [AF9035_07CA_0825] = { - USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_TWINSTAR)}, - {}, -}; +static int af9035_init(struct dvb_usb_device *d) +{ + struct state *state = d_to_priv(d); + int ret, i; + u16 frame_size = 87 * 188 / 4; + u8 packet_size = 512 / 4; + struct reg_val_mask tab[] = { + { 0x80f99d, 0x01, 0x01 }, + { 0x80f9a4, 0x01, 0x01 }, + { 0x00dd11, 0x00, 0x20 }, + { 0x00dd11, 0x00, 0x40 }, + { 0x00dd13, 0x00, 0x20 }, + { 0x00dd13, 0x00, 0x40 }, + { 0x00dd11, 0x20, 0x20 }, + { 0x00dd88, (frame_size >> 0) & 0xff, 0xff}, + { 0x00dd89, (frame_size >> 8) & 0xff, 0xff}, + { 0x00dd0c, packet_size, 0xff}, + { 0x00dd11, state->dual_mode << 6, 0x40 }, + { 0x00dd8a, (frame_size >> 0) & 0xff, 0xff}, + { 0x00dd8b, (frame_size >> 8) & 0xff, 0xff}, + { 0x00dd0d, packet_size, 0xff }, + { 0x80f9a3, 0x00, 0x01 }, + { 0x80f9cd, 0x00, 0x01 }, + { 0x80f99d, 0x00, 0x01 }, + { 0x80f9a4, 0x00, 0x01 }, + }; -MODULE_DEVICE_TABLE(usb, af9035_id); - -static struct dvb_usb_device_properties af9035_properties[] = { - { - .caps = DVB_USB_IS_AN_I2C_ADAPTER, - - .usb_ctrl = DEVICE_SPECIFIC, - .download_firmware = af9035_download_firmware, - .firmware = "dvb-usb-af9035-02.fw", - .no_reconnect = 1, - - .size_of_priv = sizeof(struct state), - - .num_adapters = 1, - .adapter = { - { - .num_frontends = 1, - .fe = { - { - .frontend_attach = af9035_frontend_attach, - .tuner_attach = af9035_tuner_attach, - .stream = { - .type = USB_BULK, - .count = 6, - .endpoint = 0x84, - .u = { - .bulk = { - .buffersize = (87 * 188), - } - } - } - } - } - } - }, + dev_dbg(&d->udev->dev, "%s: USB speed=%d frame_size=%04x " \ + "packet_size=%02x\n", __func__, + d->udev->speed, frame_size, packet_size); - .identify_state = af9035_identify_state, - .read_mac_address = af9035_read_mac_address, + /* init endpoints */ + for (i = 0; i < ARRAY_SIZE(tab); i++) { + ret = af9035_wr_reg_mask(d, tab[i].reg, tab[i].val, + tab[i].mask); + if (ret < 0) + goto err; + } - .i2c_algo = &af9035_i2c_algo, + return 0; - .rc.core = { - .protocol = RC_TYPE_UNKNOWN, - .module_name = "af9035", - .rc_query = NULL, - .rc_interval = AF9035_POLL, - .allowed_protos = RC_TYPE_UNKNOWN, - .rc_codes = RC_MAP_EMPTY, - }, - .num_device_descs = 5, - .devices = { - { - .name = "Afatech AF9035 reference design", - .cold_ids = { - &af9035_id[AF9035_15A4_9035], - &af9035_id[AF9035_15A4_1000], - &af9035_id[AF9035_15A4_1001], - &af9035_id[AF9035_15A4_1002], - &af9035_id[AF9035_15A4_1003], - }, - }, { - .name = "TerraTec Cinergy T Stick", - .cold_ids = { - &af9035_id[AF9035_0CCD_0093], - }, - }, { - .name = "AVerMedia AVerTV Volar HD/PRO (A835)", - .cold_ids = { - &af9035_id[AF9035_07CA_A835], - &af9035_id[AF9035_07CA_B835], - }, - }, { - .name = "AVerMedia HD Volar (A867)", - .cold_ids = { - &af9035_id[AF9035_07CA_1867], - &af9035_id[AF9035_07CA_A867], - }, - }, { - .name = "AVerMedia Twinstar (A825)", - .cold_ids = { - &af9035_id[AF9035_07CA_0825], - }, - }, - } - }, - { - .caps = DVB_USB_IS_AN_I2C_ADAPTER, - - .usb_ctrl = DEVICE_SPECIFIC, - .download_firmware = af9035_download_firmware_it9135, - .firmware = "dvb-usb-it9135-01.fw", - .no_reconnect = 1, - - .size_of_priv = sizeof(struct state), - - .num_adapters = 1, - .adapter = { - { - .num_frontends = 1, - .fe = { - { - .frontend_attach = af9035_frontend_attach, - .tuner_attach = af9035_tuner_attach, - .stream = { - .type = USB_BULK, - .count = 6, - .endpoint = 0x84, - .u = { - .bulk = { - .buffersize = (87 * 188), - } - } - } - } - } - } - }, +err: + dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); - .identify_state = af9035_identify_state, - .read_mac_address = af9035_read_mac_address_it9135, + return ret; +} - .i2c_algo = &af9035_i2c_algo, +static int af9035_rc_query(struct dvb_usb_device *d) +{ + unsigned int key; + unsigned char b[4]; + int ret; + struct usb_req req = { CMD_IR_GET, 0, 0, NULL, 4, b }; - .num_device_descs = 0, /* disabled as no support for IT9135 */ - .devices = { - { - .name = "ITE Tech. IT9135 reference design", - }, - } - }, -}; + ret = af9035_ctrl_msg(d, &req); + if (ret < 0) + goto err; -static int af9035_usb_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - int ret, i; - struct dvb_usb_device *d = NULL; - struct usb_device *udev; - bool found; - - pr_debug("%s: interface=%d\n", __func__, - intf->cur_altsetting->desc.bInterfaceNumber); - - /* interface 0 is used by DVB-T receiver and - interface 1 is for remote controller (HID) */ - if (intf->cur_altsetting->desc.bInterfaceNumber != 0) - return 0; - - /* Dynamic USB ID support. Replaces first device ID with current one. */ - udev = interface_to_usbdev(intf); - - for (i = 0, found = false; i < ARRAY_SIZE(af9035_id) - 1; i++) { - if (af9035_id[i].idVendor == - le16_to_cpu(udev->descriptor.idVendor) && - af9035_id[i].idProduct == - le16_to_cpu(udev->descriptor.idProduct)) { - found = true; - break; + if ((b[2] + b[3]) == 0xff) { + if ((b[0] + b[1]) == 0xff) { + /* NEC */ + key = b[0] << 8 | b[2]; + } else { + /* ext. NEC */ + key = b[0] << 16 | b[1] << 8 | b[2]; } + } else { + key = b[0] << 24 | b[1] << 16 | b[2] << 8 | b[3]; } - if (!found) { - pr_debug("%s: using dynamic ID %04x:%04x\n", __func__, - le16_to_cpu(udev->descriptor.idVendor), - le16_to_cpu(udev->descriptor.idProduct)); - af9035_properties[0].devices[0].cold_ids[0]->idVendor = - le16_to_cpu(udev->descriptor.idVendor); - af9035_properties[0].devices[0].cold_ids[0]->idProduct = - le16_to_cpu(udev->descriptor.idProduct); - } - + rc_keydown(d->rc_dev, key, 0); - for (i = 0; i < af9035_properties_count; i++) { - ret = dvb_usb_device_init(intf, &af9035_properties[i], - THIS_MODULE, &d, adapter_nr); +err: + /* ignore errors */ + return 0; +} - if (ret == -ENODEV) - continue; - else - break; - } +static int af9035_get_rc_config(struct dvb_usb_device *d, struct dvb_usb_rc *rc) +{ + int ret; + u8 tmp; + ret = af9035_rd_reg(d, EEPROM_IR_MODE, &tmp); if (ret < 0) goto err; - if (d) { - ret = af9035_init(d); + dev_dbg(&d->udev->dev, "%s: ir_mode=%02x\n", __func__, tmp); + + /* don't activate rc if in HID mode or if not available */ + if (tmp == 5) { + ret = af9035_rd_reg(d, EEPROM_IR_TYPE, &tmp); if (ret < 0) goto err; + + dev_dbg(&d->udev->dev, "%s: ir_type=%02x\n", __func__, tmp); + + switch (tmp) { + case 0: /* NEC */ + default: + rc->allowed_protos = RC_TYPE_NEC; + break; + case 1: /* RC6 */ + rc->allowed_protos = RC_TYPE_RC6; + break; + } + + rc->query = af9035_rc_query; + rc->interval = 500; + + /* load empty to enable rc */ + if (!rc->map_name) + rc->map_name = RC_MAP_EMPTY; } return 0; err: - pr_debug("%s: failed=%d\n", __func__, ret); + dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); return ret; } -/* usb specific object needed to register this driver with the usb subsystem */ +/* interface 0 is used by DVB-T receiver and + interface 1 is for remote controller (HID) */ +static const struct dvb_usb_device_properties af9035_props = { + .driver_name = KBUILD_MODNAME, + .owner = THIS_MODULE, + .adapter_nr = adapter_nr, + .size_of_priv = sizeof(struct state), + + .generic_bulk_ctrl_endpoint = 0x02, + .generic_bulk_ctrl_endpoint_response = 0x81, + + .identify_state = af9035_identify_state, + .firmware = AF9035_FIRMWARE_AF9035, + .download_firmware = af9035_download_firmware, + + .i2c_algo = &af9035_i2c_algo, + .read_config = af9035_read_config, + .frontend_attach = af9035_frontend_attach, + .tuner_attach = af9035_tuner_attach, + .init = af9035_init, + .get_rc_config = af9035_get_rc_config, + + .num_adapters = 1, + .adapter = { + { + .stream = DVB_USB_STREAM_BULK(0x84, 6, 87 * 188), + }, { + .stream = DVB_USB_STREAM_BULK(0x85, 6, 87 * 188), + }, + }, +}; + +static const struct dvb_usb_device_properties it9135_props = { + .driver_name = KBUILD_MODNAME, + .owner = THIS_MODULE, + .adapter_nr = adapter_nr, + .size_of_priv = sizeof(struct state), + + .generic_bulk_ctrl_endpoint = 0x02, + .generic_bulk_ctrl_endpoint_response = 0x81, + + .identify_state = af9035_identify_state, + .firmware = AF9035_FIRMWARE_IT9135, + .download_firmware = af9035_download_firmware_it9135, + + .i2c_algo = &af9035_i2c_algo, + .read_config = af9035_read_config_it9135, + .frontend_attach = af9035_frontend_attach, + .tuner_attach = af9035_tuner_attach, + .init = af9035_init, + .get_rc_config = af9035_get_rc_config, + + .num_adapters = 1, + .adapter = { + { + .stream = DVB_USB_STREAM_BULK(0x84, 6, 87 * 188), + }, { + .stream = DVB_USB_STREAM_BULK(0x85, 6, 87 * 188), + }, + }, +}; + +static const struct usb_device_id af9035_id_table[] = { + { DVB_USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9035_9035, + &af9035_props, "Afatech AF9035 reference design", NULL) }, + { DVB_USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9035_1000, + &af9035_props, "Afatech AF9035 reference design", NULL) }, + { DVB_USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9035_1001, + &af9035_props, "Afatech AF9035 reference design", NULL) }, + { DVB_USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9035_1002, + &af9035_props, "Afatech AF9035 reference design", NULL) }, + { DVB_USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9035_1003, + &af9035_props, "Afatech AF9035 reference design", NULL) }, + { DVB_USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_STICK, + &af9035_props, "TerraTec Cinergy T Stick", NULL) }, + { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A835, + &af9035_props, "AVerMedia AVerTV Volar HD/PRO (A835)", NULL) }, + { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_B835, + &af9035_props, "AVerMedia AVerTV Volar HD/PRO (A835)", NULL) }, + { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_1867, + &af9035_props, "AVerMedia HD Volar (A867)", NULL) }, + { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A867, + &af9035_props, "AVerMedia HD Volar (A867)", NULL) }, + { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_TWINSTAR, + &af9035_props, "AVerMedia Twinstar (A825)", NULL) }, + { DVB_USB_DEVICE(USB_VID_ASUS, USB_PID_ASUS_U3100MINI_PLUS, + &af9035_props, "Asus U3100Mini Plus", NULL) }, + { } +}; +MODULE_DEVICE_TABLE(usb, af9035_id_table); + static struct usb_driver af9035_usb_driver = { - .name = "dvb_usb_af9035", - .probe = af9035_usb_probe, - .disconnect = dvb_usb_device_exit, - .id_table = af9035_id, + .name = KBUILD_MODNAME, + .id_table = af9035_id_table, + .probe = dvb_usbv2_probe, + .disconnect = dvb_usbv2_disconnect, + .suspend = dvb_usbv2_suspend, + .resume = dvb_usbv2_resume, + .reset_resume = dvb_usbv2_reset_resume, + .no_dynamic_id = 1, + .soft_unbind = 1, }; module_usb_driver(af9035_usb_driver); @@ -1240,3 +1154,5 @@ module_usb_driver(af9035_usb_driver); MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>"); MODULE_DESCRIPTION("Afatech AF9035 driver"); MODULE_LICENSE("GPL"); +MODULE_FIRMWARE(AF9035_FIRMWARE_AF9035); +MODULE_FIRMWARE(AF9035_FIRMWARE_IT9135); diff --git a/drivers/media/dvb/dvb-usb/af9035.h b/drivers/media/usb/dvb-usb-v2/af9035.h index 481a1a43dd2a..75ef1ec13fbf 100644 --- a/drivers/media/dvb/dvb-usb/af9035.h +++ b/drivers/media/usb/dvb-usb-v2/af9035.h @@ -22,15 +22,13 @@ #ifndef AF9035_H #define AF9035_H -/* prefix for dvb-usb log writings */ -#define DVB_USB_LOG_PREFIX "af9035" - -#include "dvb-usb.h" +#include "dvb_usb.h" #include "af9033.h" #include "tua9001.h" #include "fc0011.h" #include "mxl5007t.h" #include "tda18218.h" +#include "fc2580.h" struct reg_val { u32 reg; @@ -53,6 +51,7 @@ struct usb_req { }; struct state { + u8 seq; /* packet sequence number */ bool dual_mode; struct af9033_config af9033_config[2]; @@ -86,6 +85,9 @@ u32 clock_lut_it9135[] = { 22000000, /* 22.00 MHz */ }; +#define AF9035_FIRMWARE_AF9035 "dvb-usb-af9035-02.fw" +#define AF9035_FIRMWARE_IT9135 "dvb-usb-it9135-01.fw" + /* EEPROM locations */ #define EEPROM_IR_MODE 0x430d #define EEPROM_DUAL_MODE 0x4326 diff --git a/drivers/media/dvb/dvb-usb/anysee.c b/drivers/media/usb/dvb-usb-v2/anysee.c index 03c28655af1b..ec540140c810 100644 --- a/drivers/media/dvb/dvb-usb/anysee.c +++ b/drivers/media/usb/dvb-usb-v2/anysee.c @@ -32,6 +32,7 @@ */ #include "anysee.h" +#include "dvb-pll.h" #include "tda1002x.h" #include "mt352.h" #include "mt352_priv.h" @@ -43,36 +44,26 @@ #include "isl6423.h" #include "cxd2820r.h" -/* debug */ -static int dvb_usb_anysee_debug; -module_param_named(debug, dvb_usb_anysee_debug, int, 0644); -MODULE_PARM_DESC(debug, "set debugging level" DVB_USB_DEBUG_STATUS); -static int dvb_usb_anysee_delsys; -module_param_named(delsys, dvb_usb_anysee_delsys, int, 0644); -MODULE_PARM_DESC(delsys, "select delivery mode (0=DVB-C, 1=DVB-T)"); DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); - static DEFINE_MUTEX(anysee_usb_mutex); static int anysee_ctrl_msg(struct dvb_usb_device *d, u8 *sbuf, u8 slen, u8 *rbuf, u8 rlen) { - struct anysee_state *state = d->priv; + struct anysee_state *state = d_to_priv(d); int act_len, ret, i; u8 buf[64]; memcpy(&buf[0], sbuf, slen); buf[60] = state->seq++; - if (mutex_lock_interruptible(&anysee_usb_mutex) < 0) - return -EAGAIN; + mutex_lock(&anysee_usb_mutex); - deb_xfer(">>> "); - debug_dump(buf, slen, deb_xfer); + dev_dbg(&d->udev->dev, "%s: >>> %*ph\n", __func__, slen, buf); /* We need receive one message more after dvb_usb_generic_rw due to weird transaction flow, which is 1 x send + 2 x receive. */ - ret = dvb_usb_generic_rw(d, buf, sizeof(buf), buf, sizeof(buf), 0); + ret = dvb_usbv2_generic_rw(d, buf, sizeof(buf), buf, sizeof(buf)); if (ret) goto error_unlock; @@ -91,18 +82,19 @@ static int anysee_ctrl_msg(struct dvb_usb_device *d, u8 *sbuf, u8 slen, for (i = 0; i < 3; i++) { /* receive 2nd answer */ ret = usb_bulk_msg(d->udev, usb_rcvbulkpipe(d->udev, - d->props.generic_bulk_ctrl_endpoint), buf, sizeof(buf), + d->props->generic_bulk_ctrl_endpoint), buf, sizeof(buf), &act_len, 2000); if (ret) { - deb_info("%s: recv bulk message failed: %d", - __func__, ret); + dev_dbg(&d->udev->dev, "%s: recv bulk message " \ + "failed=%d\n", __func__, ret); } else { - deb_xfer("<<< "); - debug_dump(buf, rlen, deb_xfer); + dev_dbg(&d->udev->dev, "%s: <<< %*ph\n", __func__, + rlen, buf); if (buf[63] != 0x4f) - deb_info("%s: cmd failed\n", __func__); + dev_dbg(&d->udev->dev, "%s: cmd failed\n", + __func__); break; } @@ -110,7 +102,8 @@ static int anysee_ctrl_msg(struct dvb_usb_device *d, u8 *sbuf, u8 slen, if (ret) { /* all retries failed, it is fatal */ - err("%s: recv bulk message failed: %d", __func__, ret); + dev_err(&d->udev->dev, "%s: recv bulk message failed=%d\n", + KBUILD_MODNAME, ret); goto error_unlock; } @@ -129,14 +122,14 @@ static int anysee_read_reg(struct dvb_usb_device *d, u16 reg, u8 *val) u8 buf[] = {CMD_REG_READ, reg >> 8, reg & 0xff, 0x01}; int ret; ret = anysee_ctrl_msg(d, buf, sizeof(buf), val, 1); - deb_info("%s: reg:%04x val:%02x\n", __func__, reg, *val); + dev_dbg(&d->udev->dev, "%s: reg=%04x val=%02x\n", __func__, reg, *val); return ret; } static int anysee_write_reg(struct dvb_usb_device *d, u16 reg, u8 val) { u8 buf[] = {CMD_REG_WRITE, reg >> 8, reg & 0xff, 0x01, val}; - deb_info("%s: reg:%04x val:%02x\n", __func__, reg, val); + dev_dbg(&d->udev->dev, "%s: reg=%04x val=%02x\n", __func__, reg, val); return anysee_ctrl_msg(d, buf, sizeof(buf), NULL, 0); } @@ -190,24 +183,25 @@ static int anysee_get_hw_info(struct dvb_usb_device *d, u8 *id) return anysee_ctrl_msg(d, buf, sizeof(buf), id, 3); } -static int anysee_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) +static int anysee_streaming_ctrl(struct dvb_frontend *fe, int onoff) { u8 buf[] = {CMD_STREAMING_CTRL, (u8)onoff, 0x00}; - deb_info("%s: onoff:%02x\n", __func__, onoff); - return anysee_ctrl_msg(adap->dev, buf, sizeof(buf), NULL, 0); + dev_dbg(&fe_to_d(fe)->udev->dev, "%s: onoff=%d\n", __func__, onoff); + return anysee_ctrl_msg(fe_to_d(fe), buf, sizeof(buf), NULL, 0); } static int anysee_led_ctrl(struct dvb_usb_device *d, u8 mode, u8 interval) { u8 buf[] = {CMD_LED_AND_IR_CTRL, 0x01, mode, interval}; - deb_info("%s: state:%02x interval:%02x\n", __func__, mode, interval); + dev_dbg(&d->udev->dev, "%s: state=%d interval=%d\n", __func__, + mode, interval); return anysee_ctrl_msg(d, buf, sizeof(buf), NULL, 0); } static int anysee_ir_ctrl(struct dvb_usb_device *d, u8 onoff) { u8 buf[] = {CMD_LED_AND_IR_CTRL, 0x02, onoff}; - deb_info("%s: onoff:%02x\n", __func__, onoff); + dev_dbg(&d->udev->dev, "%s: onoff=%d\n", __func__, onoff); return anysee_ctrl_msg(d, buf, sizeof(buf), NULL, 0); } @@ -509,23 +503,48 @@ static struct cxd2820r_config anysee_cxd2820r_config = { * IOE[5] STV0903 1=enabled */ +static int anysee_read_config(struct dvb_usb_device *d) +{ + struct anysee_state *state = d_to_priv(d); + int ret; + u8 hw_info[3]; + + /* + * Check which hardware we have. + * We must do this call two times to get reliable values (hw/fw bug). + */ + ret = anysee_get_hw_info(d, hw_info); + if (ret) + goto error; + + ret = anysee_get_hw_info(d, hw_info); + if (ret) + goto error; + + /* + * Meaning of these info bytes are guessed. + */ + dev_info(&d->udev->dev, "%s: firmware version %d.%d hardware id %d\n", + KBUILD_MODNAME, hw_info[1], hw_info[2], hw_info[0]); + + state->hw = hw_info[0]; +error: + return ret; +} /* external I2C gate used for DNOD44CDH086A(TDA18212) tuner module */ static int anysee_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) { - struct dvb_usb_adapter *adap = fe->dvb->priv; - /* enable / disable tuner access on IOE[4] */ - return anysee_wr_reg_mask(adap->dev, REG_IOE, (enable << 4), 0x10); + return anysee_wr_reg_mask(fe_to_d(fe), REG_IOE, (enable << 4), 0x10); } static int anysee_frontend_ctrl(struct dvb_frontend *fe, int onoff) { - struct dvb_usb_adapter *adap = fe->dvb->priv; - struct anysee_state *state = adap->dev->priv; + struct anysee_state *state = fe_to_priv(fe); + struct dvb_usb_device *d = fe_to_d(fe); int ret; - - deb_info("%s: fe=%d onoff=%d\n", __func__, fe->id, onoff); + dev_dbg(&d->udev->dev, "%s: fe=%d onoff=%d\n", __func__, fe->id, onoff); /* no frontend sleep control */ if (onoff == 0) @@ -536,40 +555,34 @@ static int anysee_frontend_ctrl(struct dvb_frontend *fe, int onoff) /* E30 Combo Plus */ /* E30 C Plus */ - if ((fe->id ^ dvb_usb_anysee_delsys) == 0) { + if (fe->id == 0) { /* disable DVB-T demod on IOD[0] */ - ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 0), - 0x01); + ret = anysee_wr_reg_mask(d, REG_IOD, (0 << 0), 0x01); if (ret) goto error; /* enable DVB-C demod on IOD[5] */ - ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 5), - 0x20); + ret = anysee_wr_reg_mask(d, REG_IOD, (1 << 5), 0x20); if (ret) goto error; /* enable DVB-C tuner on IOE[0] */ - ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (1 << 0), - 0x01); + ret = anysee_wr_reg_mask(d, REG_IOE, (1 << 0), 0x01); if (ret) goto error; } else { /* disable DVB-C demod on IOD[5] */ - ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 5), - 0x20); + ret = anysee_wr_reg_mask(d, REG_IOD, (0 << 5), 0x20); if (ret) goto error; /* enable DVB-T demod on IOD[0] */ - ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 0), - 0x01); + ret = anysee_wr_reg_mask(d, REG_IOD, (1 << 0), 0x01); if (ret) goto error; /* enable DVB-T tuner on IOE[0] */ - ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (0 << 0), - 0x01); + ret = anysee_wr_reg_mask(d, REG_IOE, (0 << 0), 0x01); if (ret) goto error; } @@ -580,40 +593,34 @@ static int anysee_frontend_ctrl(struct dvb_frontend *fe, int onoff) /* E7 TC */ /* E7 PTC */ - if ((fe->id ^ dvb_usb_anysee_delsys) == 0) { + if (fe->id == 0) { /* disable DVB-T demod on IOD[6] */ - ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 6), - 0x40); + ret = anysee_wr_reg_mask(d, REG_IOD, (0 << 6), 0x40); if (ret) goto error; /* enable DVB-C demod on IOD[5] */ - ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 5), - 0x20); + ret = anysee_wr_reg_mask(d, REG_IOD, (1 << 5), 0x20); if (ret) goto error; /* enable IF route on IOE[0] */ - ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (1 << 0), - 0x01); + ret = anysee_wr_reg_mask(d, REG_IOE, (1 << 0), 0x01); if (ret) goto error; } else { /* disable DVB-C demod on IOD[5] */ - ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 5), - 0x20); + ret = anysee_wr_reg_mask(d, REG_IOD, (0 << 5), 0x20); if (ret) goto error; /* enable DVB-T demod on IOD[6] */ - ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 6), - 0x40); + ret = anysee_wr_reg_mask(d, REG_IOD, (1 << 6), 0x40); if (ret) goto error; /* enable IF route on IOE[0] */ - ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (0 << 0), - 0x01); + ret = anysee_wr_reg_mask(d, REG_IOE, (0 << 0), 0x01); if (ret) goto error; } @@ -629,9 +636,9 @@ error: static int anysee_frontend_attach(struct dvb_usb_adapter *adap) { + struct anysee_state *state = adap_to_priv(adap); + struct dvb_usb_device *d = adap_to_d(adap); int ret; - struct anysee_state *state = adap->dev->priv; - u8 hw_info[3]; u8 tmp; struct i2c_msg msg[2] = { { @@ -647,100 +654,63 @@ static int anysee_frontend_attach(struct dvb_usb_adapter *adap) } }; - /* detect hardware only once */ - if (adap->fe_adap[0].fe == NULL) { - /* Check which hardware we have. - * We must do this call two times to get reliable values - * (hw/fw bug). - */ - ret = anysee_get_hw_info(adap->dev, hw_info); - if (ret) - goto error; - - ret = anysee_get_hw_info(adap->dev, hw_info); - if (ret) - goto error; - - /* Meaning of these info bytes are guessed. */ - info("firmware version:%d.%d hardware id:%d", - hw_info[1], hw_info[2], hw_info[0]); - - state->hw = hw_info[0]; - } - - /* set current frondend ID for devices having two frondends */ - if (adap->fe_adap[0].fe) - state->fe_id++; - switch (state->hw) { case ANYSEE_HW_507T: /* 2 */ /* E30 */ - if (state->fe_id) - break; - /* attach demod */ - adap->fe_adap[0].fe = dvb_attach(mt352_attach, - &anysee_mt352_config, &adap->dev->i2c_adap); - if (adap->fe_adap[0].fe) + adap->fe[0] = dvb_attach(mt352_attach, &anysee_mt352_config, + &d->i2c_adap); + if (adap->fe[0]) break; /* attach demod */ - adap->fe_adap[0].fe = dvb_attach(zl10353_attach, - &anysee_zl10353_config, &adap->dev->i2c_adap); + adap->fe[0] = dvb_attach(zl10353_attach, &anysee_zl10353_config, + &d->i2c_adap); break; case ANYSEE_HW_507CD: /* 6 */ /* E30 Plus */ - if (state->fe_id) - break; - /* enable DVB-T demod on IOD[0] */ - ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 0), 0x01); + ret = anysee_wr_reg_mask(d, REG_IOD, (1 << 0), 0x01); if (ret) goto error; /* enable transport stream on IOA[7] */ - ret = anysee_wr_reg_mask(adap->dev, REG_IOA, (0 << 7), 0x80); + ret = anysee_wr_reg_mask(d, REG_IOA, (0 << 7), 0x80); if (ret) goto error; /* attach demod */ - adap->fe_adap[0].fe = dvb_attach(zl10353_attach, - &anysee_zl10353_config, &adap->dev->i2c_adap); + adap->fe[0] = dvb_attach(zl10353_attach, &anysee_zl10353_config, + &d->i2c_adap); break; case ANYSEE_HW_507DC: /* 10 */ /* E30 C Plus */ - if (state->fe_id) - break; - /* enable DVB-C demod on IOD[0] */ - ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 0), 0x01); + ret = anysee_wr_reg_mask(d, REG_IOD, (1 << 0), 0x01); if (ret) goto error; /* attach demod */ - adap->fe_adap[0].fe = dvb_attach(tda10023_attach, - &anysee_tda10023_config, &adap->dev->i2c_adap, 0x48); + adap->fe[0] = dvb_attach(tda10023_attach, + &anysee_tda10023_config, &d->i2c_adap, 0x48); break; case ANYSEE_HW_507SI: /* 11 */ /* E30 S2 Plus */ - if (state->fe_id) - break; - /* enable DVB-S/S2 demod on IOD[0] */ - ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 0), 0x01); + ret = anysee_wr_reg_mask(d, REG_IOD, (1 << 0), 0x01); if (ret) goto error; /* attach demod */ - adap->fe_adap[0].fe = dvb_attach(cx24116_attach, - &anysee_cx24116_config, &adap->dev->i2c_adap); + adap->fe[0] = dvb_attach(cx24116_attach, &anysee_cx24116_config, + &d->i2c_adap); break; case ANYSEE_HW_507FA: /* 15 */ @@ -748,84 +718,82 @@ static int anysee_frontend_attach(struct dvb_usb_adapter *adap) /* E30 C Plus */ /* enable tuner on IOE[4] */ - ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (1 << 4), 0x10); + ret = anysee_wr_reg_mask(d, REG_IOE, (1 << 4), 0x10); if (ret) goto error; /* probe TDA18212 */ tmp = 0; - ret = i2c_transfer(&adap->dev->i2c_adap, msg, 2); + ret = i2c_transfer(&d->i2c_adap, msg, 2); if (ret == 2 && tmp == 0xc7) - deb_info("%s: TDA18212 found\n", __func__); + dev_dbg(&d->udev->dev, "%s: TDA18212 found\n", + __func__); else tmp = 0; /* disable tuner on IOE[4] */ - ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (0 << 4), 0x10); + ret = anysee_wr_reg_mask(d, REG_IOE, (0 << 4), 0x10); if (ret) goto error; - if ((state->fe_id ^ dvb_usb_anysee_delsys) == 0) { - /* disable DVB-T demod on IOD[0] */ - ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 0), - 0x01); - if (ret) - goto error; + /* disable DVB-T demod on IOD[0] */ + ret = anysee_wr_reg_mask(d, REG_IOD, (0 << 0), 0x01); + if (ret) + goto error; - /* enable DVB-C demod on IOD[5] */ - ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 5), - 0x20); - if (ret) - goto error; + /* enable DVB-C demod on IOD[5] */ + ret = anysee_wr_reg_mask(d, REG_IOD, (1 << 5), 0x20); + if (ret) + goto error; - /* attach demod */ - if (tmp == 0xc7) { - /* TDA18212 config */ - adap->fe_adap[state->fe_id].fe = dvb_attach( - tda10023_attach, + /* attach demod */ + if (tmp == 0xc7) { + /* TDA18212 config */ + adap->fe[0] = dvb_attach(tda10023_attach, &anysee_tda10023_tda18212_config, - &adap->dev->i2c_adap, 0x48); - } else { - /* PLL config */ - adap->fe_adap[state->fe_id].fe = dvb_attach( - tda10023_attach, - &anysee_tda10023_config, - &adap->dev->i2c_adap, 0x48); - } + &d->i2c_adap, 0x48); + + /* I2C gate for DNOD44CDH086A(TDA18212) tuner module */ + if (adap->fe[0]) + adap->fe[0]->ops.i2c_gate_ctrl = + anysee_i2c_gate_ctrl; } else { - /* disable DVB-C demod on IOD[5] */ - ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 5), - 0x20); - if (ret) - goto error; + /* PLL config */ + adap->fe[0] = dvb_attach(tda10023_attach, + &anysee_tda10023_config, + &d->i2c_adap, 0x48); + } - /* enable DVB-T demod on IOD[0] */ - ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 0), - 0x01); - if (ret) - goto error; + /* break out if first frontend attaching fails */ + if (!adap->fe[0]) + break; - /* attach demod */ - if (tmp == 0xc7) { - /* TDA18212 config */ - adap->fe_adap[state->fe_id].fe = dvb_attach( - zl10353_attach, - &anysee_zl10353_tda18212_config2, - &adap->dev->i2c_adap); - } else { - /* PLL config */ - adap->fe_adap[state->fe_id].fe = dvb_attach( - zl10353_attach, - &anysee_zl10353_config, - &adap->dev->i2c_adap); - } - } + /* disable DVB-C demod on IOD[5] */ + ret = anysee_wr_reg_mask(d, REG_IOD, (0 << 5), 0x20); + if (ret) + goto error; - /* I2C gate for DNOD44CDH086A(TDA18212) tuner module */ + /* enable DVB-T demod on IOD[0] */ + ret = anysee_wr_reg_mask(d, REG_IOD, (1 << 0), 0x01); + if (ret) + goto error; + + /* attach demod */ if (tmp == 0xc7) { - if (adap->fe_adap[state->fe_id].fe) - adap->fe_adap[state->fe_id].fe->ops.i2c_gate_ctrl = - anysee_i2c_gate_ctrl; + /* TDA18212 config */ + adap->fe[1] = dvb_attach(zl10353_attach, + &anysee_zl10353_tda18212_config2, + &d->i2c_adap); + + /* I2C gate for DNOD44CDH086A(TDA18212) tuner module */ + if (adap->fe[1]) + adap->fe[1]->ops.i2c_gate_ctrl = + anysee_i2c_gate_ctrl; + } else { + /* PLL config */ + adap->fe[1] = dvb_attach(zl10353_attach, + &anysee_zl10353_config, + &d->i2c_adap); } break; @@ -834,48 +802,47 @@ static int anysee_frontend_attach(struct dvb_usb_adapter *adap) /* E7 TC */ /* E7 PTC */ - if ((state->fe_id ^ dvb_usb_anysee_delsys) == 0) { - /* disable DVB-T demod on IOD[6] */ - ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 6), - 0x40); - if (ret) - goto error; + /* disable DVB-T demod on IOD[6] */ + ret = anysee_wr_reg_mask(d, REG_IOD, (0 << 6), 0x40); + if (ret) + goto error; - /* enable DVB-C demod on IOD[5] */ - ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 5), - 0x20); - if (ret) - goto error; + /* enable DVB-C demod on IOD[5] */ + ret = anysee_wr_reg_mask(d, REG_IOD, (1 << 5), 0x20); + if (ret) + goto error; - /* attach demod */ - adap->fe_adap[state->fe_id].fe = - dvb_attach(tda10023_attach, + /* attach demod */ + adap->fe[0] = dvb_attach(tda10023_attach, &anysee_tda10023_tda18212_config, - &adap->dev->i2c_adap, 0x48); - } else { - /* disable DVB-C demod on IOD[5] */ - ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 5), - 0x20); - if (ret) - goto error; + &d->i2c_adap, 0x48); - /* enable DVB-T demod on IOD[6] */ - ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 6), - 0x40); - if (ret) - goto error; + /* I2C gate for DNOD44CDH086A(TDA18212) tuner module */ + if (adap->fe[0]) + adap->fe[0]->ops.i2c_gate_ctrl = anysee_i2c_gate_ctrl; + + /* break out if first frontend attaching fails */ + if (!adap->fe[0]) + break; + + /* disable DVB-C demod on IOD[5] */ + ret = anysee_wr_reg_mask(d, REG_IOD, (0 << 5), 0x20); + if (ret) + goto error; - /* attach demod */ - adap->fe_adap[state->fe_id].fe = - dvb_attach(zl10353_attach, + /* enable DVB-T demod on IOD[6] */ + ret = anysee_wr_reg_mask(d, REG_IOD, (1 << 6), 0x40); + if (ret) + goto error; + + /* attach demod */ + adap->fe[1] = dvb_attach(zl10353_attach, &anysee_zl10353_tda18212_config, - &adap->dev->i2c_adap); - } + &d->i2c_adap); /* I2C gate for DNOD44CDH086A(TDA18212) tuner module */ - if (adap->fe_adap[state->fe_id].fe) - adap->fe_adap[state->fe_id].fe->ops.i2c_gate_ctrl = - anysee_i2c_gate_ctrl; + if (adap->fe[1]) + adap->fe[1]->ops.i2c_gate_ctrl = anysee_i2c_gate_ctrl; state->has_ci = true; @@ -885,17 +852,14 @@ static int anysee_frontend_attach(struct dvb_usb_adapter *adap) /* E7 S2 */ /* E7 PS2 */ - if (state->fe_id) - break; - /* enable DVB-S/S2 demod on IOE[5] */ - ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (1 << 5), 0x20); + ret = anysee_wr_reg_mask(d, REG_IOE, (1 << 5), 0x20); if (ret) goto error; /* attach demod */ - adap->fe_adap[0].fe = dvb_attach(stv0900_attach, - &anysee_stv0900_config, &adap->dev->i2c_adap, 0); + adap->fe[0] = dvb_attach(stv0900_attach, + &anysee_stv0900_config, &d->i2c_adap, 0); state->has_ci = true; @@ -903,28 +867,27 @@ static int anysee_frontend_attach(struct dvb_usb_adapter *adap) case ANYSEE_HW_508T2C: /* 20 */ /* E7 T2C */ - if (state->fe_id) - break; - /* enable DVB-T/T2/C demod on IOE[5] */ - ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (1 << 5), 0x20); + ret = anysee_wr_reg_mask(d, REG_IOE, (1 << 5), 0x20); if (ret) goto error; /* attach demod */ - adap->fe_adap[state->fe_id].fe = dvb_attach(cxd2820r_attach, - &anysee_cxd2820r_config, &adap->dev->i2c_adap); + adap->fe[0] = dvb_attach(cxd2820r_attach, + &anysee_cxd2820r_config, &d->i2c_adap, NULL); state->has_ci = true; break; } - if (!adap->fe_adap[0].fe) { + if (!adap->fe[0]) { /* we have no frontend :-( */ ret = -ENODEV; - err("Unsupported Anysee version. " \ - "Please report the <linux-media@vger.kernel.org>."); + dev_err(&d->udev->dev, "%s: Unsupported Anysee version. " \ + "Please report the " \ + "<linux-media@vger.kernel.org>.\n", + KBUILD_MODNAME); } error: return ret; @@ -932,44 +895,43 @@ error: static int anysee_tuner_attach(struct dvb_usb_adapter *adap) { - struct anysee_state *state = adap->dev->priv; + struct anysee_state *state = adap_to_priv(adap); + struct dvb_usb_device *d = adap_to_d(adap); struct dvb_frontend *fe; int ret; - deb_info("%s: fe=%d\n", __func__, state->fe_id); + dev_dbg(&d->udev->dev, "%s:\n", __func__); switch (state->hw) { case ANYSEE_HW_507T: /* 2 */ /* E30 */ /* attach tuner */ - fe = dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, - (0xc2 >> 1), NULL, DVB_PLL_THOMSON_DTT7579); + fe = dvb_attach(dvb_pll_attach, adap->fe[0], (0xc2 >> 1), NULL, + DVB_PLL_THOMSON_DTT7579); break; case ANYSEE_HW_507CD: /* 6 */ /* E30 Plus */ /* attach tuner */ - fe = dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, - (0xc2 >> 1), &adap->dev->i2c_adap, - DVB_PLL_THOMSON_DTT7579); + fe = dvb_attach(dvb_pll_attach, adap->fe[0], (0xc2 >> 1), + &d->i2c_adap, DVB_PLL_THOMSON_DTT7579); break; case ANYSEE_HW_507DC: /* 10 */ /* E30 C Plus */ /* attach tuner */ - fe = dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, - (0xc0 >> 1), &adap->dev->i2c_adap, - DVB_PLL_SAMSUNG_DTOS403IH102A); + fe = dvb_attach(dvb_pll_attach, adap->fe[0], (0xc0 >> 1), + &d->i2c_adap, DVB_PLL_SAMSUNG_DTOS403IH102A); break; case ANYSEE_HW_507SI: /* 11 */ /* E30 S2 Plus */ /* attach LNB controller */ - fe = dvb_attach(isl6423_attach, adap->fe_adap[0].fe, - &adap->dev->i2c_adap, &anysee_isl6423_config); + fe = dvb_attach(isl6423_attach, adap->fe[0], &d->i2c_adap, + &anysee_isl6423_config); break; case ANYSEE_HW_507FA: /* 15 */ @@ -980,15 +942,28 @@ static int anysee_tuner_attach(struct dvb_usb_adapter *adap) * fails attach old simple PLL. */ /* attach tuner */ - fe = dvb_attach(tda18212_attach, adap->fe_adap[state->fe_id].fe, - &adap->dev->i2c_adap, &anysee_tda18212_config); - if (fe) + fe = dvb_attach(tda18212_attach, adap->fe[0], &d->i2c_adap, + &anysee_tda18212_config); + + if (fe && adap->fe[1]) { + /* attach tuner for 2nd FE */ + fe = dvb_attach(tda18212_attach, adap->fe[1], + &d->i2c_adap, &anysee_tda18212_config); + break; + } else if (fe) { break; + } /* attach tuner */ - fe = dvb_attach(dvb_pll_attach, adap->fe_adap[state->fe_id].fe, - (0xc0 >> 1), &adap->dev->i2c_adap, - DVB_PLL_SAMSUNG_DTOS403IH102A); + fe = dvb_attach(dvb_pll_attach, adap->fe[0], (0xc0 >> 1), + &d->i2c_adap, DVB_PLL_SAMSUNG_DTOS403IH102A); + + if (fe && adap->fe[1]) { + /* attach tuner for 2nd FE */ + fe = dvb_attach(dvb_pll_attach, adap->fe[0], + (0xc0 >> 1), &d->i2c_adap, + DVB_PLL_SAMSUNG_DTOS403IH102A); + } break; case ANYSEE_HW_508TC: /* 18 */ @@ -997,8 +972,14 @@ static int anysee_tuner_attach(struct dvb_usb_adapter *adap) /* E7 PTC */ /* attach tuner */ - fe = dvb_attach(tda18212_attach, adap->fe_adap[state->fe_id].fe, - &adap->dev->i2c_adap, &anysee_tda18212_config); + fe = dvb_attach(tda18212_attach, adap->fe[0], &d->i2c_adap, + &anysee_tda18212_config); + + if (fe) { + /* attach tuner for 2nd FE */ + fe = dvb_attach(tda18212_attach, adap->fe[1], + &d->i2c_adap, &anysee_tda18212_config); + } break; case ANYSEE_HW_508S2: /* 19 */ @@ -1007,13 +988,13 @@ static int anysee_tuner_attach(struct dvb_usb_adapter *adap) /* E7 PS2 */ /* attach tuner */ - fe = dvb_attach(stv6110_attach, adap->fe_adap[0].fe, - &anysee_stv6110_config, &adap->dev->i2c_adap); + fe = dvb_attach(stv6110_attach, adap->fe[0], + &anysee_stv6110_config, &d->i2c_adap); if (fe) { /* attach LNB controller */ - fe = dvb_attach(isl6423_attach, adap->fe_adap[0].fe, - &adap->dev->i2c_adap, &anysee_isl6423_config); + fe = dvb_attach(isl6423_attach, adap->fe[0], + &d->i2c_adap, &anysee_isl6423_config); } break; @@ -1022,8 +1003,8 @@ static int anysee_tuner_attach(struct dvb_usb_adapter *adap) /* E7 T2C */ /* attach tuner */ - fe = dvb_attach(tda18212_attach, adap->fe_adap[state->fe_id].fe, - &adap->dev->i2c_adap, &anysee_tda18212_config2); + fe = dvb_attach(tda18212_attach, adap->fe[0], &d->i2c_adap, + &anysee_tda18212_config2); break; default: @@ -1057,13 +1038,23 @@ static int anysee_rc_query(struct dvb_usb_device *d) return ret; if (ircode[0]) { - deb_rc("%s: key pressed %02x\n", __func__, ircode[1]); + dev_dbg(&d->udev->dev, "%s: key pressed %02x\n", __func__, + ircode[1]); rc_keydown(d->rc_dev, 0x08 << 8 | ircode[1], 0); } return 0; } +static int anysee_get_rc_config(struct dvb_usb_device *d, struct dvb_usb_rc *rc) +{ + rc->allowed_protos = RC_TYPE_NEC; + rc->query = anysee_rc_query; + rc->interval = 250; /* windows driver uses 500ms */ + + return 0; +} + static int anysee_ci_read_attribute_mem(struct dvb_ca_en50221 *ci, int slot, int addr) { @@ -1126,7 +1117,7 @@ static int anysee_ci_slot_reset(struct dvb_ca_en50221 *ci, int slot) { struct dvb_usb_device *d = ci->data; int ret; - struct anysee_state *state = d->priv; + struct anysee_state *state = d_to_priv(d); state->ci_cam_ready = jiffies + msecs_to_jiffies(1000); @@ -1177,7 +1168,7 @@ static int anysee_ci_poll_slot_status(struct dvb_ca_en50221 *ci, int slot, int open) { struct dvb_usb_device *d = ci->data; - struct anysee_state *state = d->priv; + struct anysee_state *state = d_to_priv(d); int ret; u8 tmp; @@ -1196,7 +1187,7 @@ static int anysee_ci_poll_slot_status(struct dvb_ca_en50221 *ci, int slot, static int anysee_ci_init(struct dvb_usb_device *d) { - struct anysee_state *state = d->priv; + struct anysee_state *state = d_to_priv(d); int ret; state->ci.owner = THIS_MODULE; @@ -1226,15 +1217,17 @@ static int anysee_ci_init(struct dvb_usb_device *d) if (ret) return ret; + state->ci_attached = true; + return 0; } static void anysee_ci_release(struct dvb_usb_device *d) { - struct anysee_state *state = d->priv; + struct anysee_state *state = d_to_priv(d); /* detach CI */ - if (state->has_ci) + if (state->ci_attached) dvb_ca_en50221_release(&state->ci); return; @@ -1242,9 +1235,17 @@ static void anysee_ci_release(struct dvb_usb_device *d) static int anysee_init(struct dvb_usb_device *d) { - struct anysee_state *state = d->priv; + struct anysee_state *state = d_to_priv(d); int ret; + /* There is one interface with two alternate settings. + Alternate setting 0 is for bulk transfer. + Alternate setting 1 is for isochronous transfer. + We use bulk transfer (alternate setting 0). */ + ret = usb_set_interface(d->udev, 0, 0); + if (ret) + return ret; + /* LED light */ ret = anysee_led_ctrl(d, 0x01, 0x03); if (ret) @@ -1258,148 +1259,68 @@ static int anysee_init(struct dvb_usb_device *d) /* attach CI */ if (state->has_ci) { ret = anysee_ci_init(d); - if (ret) { - state->has_ci = false; + if (ret) return ret; - } } return 0; } -/* DVB USB Driver stuff */ -static struct dvb_usb_device_properties anysee_properties; - -static int anysee_probe(struct usb_interface *intf, - const struct usb_device_id *id) +static void anysee_exit(struct dvb_usb_device *d) { - struct dvb_usb_device *d; - struct usb_host_interface *alt; - int ret; - - /* There is one interface with two alternate settings. - Alternate setting 0 is for bulk transfer. - Alternate setting 1 is for isochronous transfer. - We use bulk transfer (alternate setting 0). */ - if (intf->num_altsetting < 1) - return -ENODEV; - - /* - * Anysee is always warm (its USB-bridge, Cypress FX2, uploads - * firmware from eeprom). If dvb_usb_device_init() succeeds that - * means d is a valid pointer. - */ - ret = dvb_usb_device_init(intf, &anysee_properties, THIS_MODULE, &d, - adapter_nr); - if (ret) - return ret; - - alt = usb_altnum_to_altsetting(intf, 0); - if (alt == NULL) { - deb_info("%s: no alt found!\n", __func__); - return -ENODEV; - } - - ret = usb_set_interface(d->udev, alt->desc.bInterfaceNumber, - alt->desc.bAlternateSetting); - if (ret) - return ret; - - return anysee_init(d); + return anysee_ci_release(d); } -static void anysee_disconnect(struct usb_interface *intf) -{ - struct dvb_usb_device *d = usb_get_intfdata(intf); - - anysee_ci_release(d); - dvb_usb_device_exit(intf); - - return; -} - -static struct usb_device_id anysee_table[] = { - { USB_DEVICE(USB_VID_CYPRESS, USB_PID_ANYSEE) }, - { USB_DEVICE(USB_VID_AMT, USB_PID_ANYSEE) }, - { } /* Terminating entry */ -}; -MODULE_DEVICE_TABLE(usb, anysee_table); - -static struct dvb_usb_device_properties anysee_properties = { - .caps = DVB_USB_IS_AN_I2C_ADAPTER, +/* DVB USB Driver stuff */ +static struct dvb_usb_device_properties anysee_props = { + .driver_name = KBUILD_MODNAME, + .owner = THIS_MODULE, + .adapter_nr = adapter_nr, + .size_of_priv = sizeof(struct anysee_state), - .usb_ctrl = DEVICE_SPECIFIC, + .generic_bulk_ctrl_endpoint = 0x01, + .generic_bulk_ctrl_endpoint_response = 0x81, - .size_of_priv = sizeof(struct anysee_state), + .i2c_algo = &anysee_i2c_algo, + .read_config = anysee_read_config, + .frontend_attach = anysee_frontend_attach, + .tuner_attach = anysee_tuner_attach, + .init = anysee_init, + .get_rc_config = anysee_get_rc_config, + .frontend_ctrl = anysee_frontend_ctrl, + .streaming_ctrl = anysee_streaming_ctrl, + .exit = anysee_exit, .num_adapters = 1, .adapter = { { - .num_frontends = 2, - .frontend_ctrl = anysee_frontend_ctrl, - .fe = { { - .streaming_ctrl = anysee_streaming_ctrl, - .frontend_attach = anysee_frontend_attach, - .tuner_attach = anysee_tuner_attach, - .stream = { - .type = USB_BULK, - .count = 8, - .endpoint = 0x82, - .u = { - .bulk = { - .buffersize = (16*512), - } - } - }, - }, { - .streaming_ctrl = anysee_streaming_ctrl, - .frontend_attach = anysee_frontend_attach, - .tuner_attach = anysee_tuner_attach, - .stream = { - .type = USB_BULK, - .count = 8, - .endpoint = 0x82, - .u = { - .bulk = { - .buffersize = (16*512), - } - } - }, - } }, + .stream = DVB_USB_STREAM_BULK(0x82, 8, 16 * 512), } - }, - - .rc.core = { - .rc_codes = RC_MAP_ANYSEE, - .protocol = RC_TYPE_OTHER, - .module_name = "anysee", - .rc_query = anysee_rc_query, - .rc_interval = 250, /* windows driver uses 500ms */ - }, - - .i2c_algo = &anysee_i2c_algo, - - .generic_bulk_ctrl_endpoint = 1, - - .num_device_descs = 1, - .devices = { - { - .name = "Anysee DVB USB2.0", - .cold_ids = {NULL}, - .warm_ids = {&anysee_table[0], - &anysee_table[1], NULL}, - }, } }; -static struct usb_driver anysee_driver = { - .name = "dvb_usb_anysee", - .probe = anysee_probe, - .disconnect = anysee_disconnect, - .id_table = anysee_table, +static const struct usb_device_id anysee_id_table[] = { + { DVB_USB_DEVICE(USB_VID_CYPRESS, USB_PID_ANYSEE, + &anysee_props, "Anysee", RC_MAP_ANYSEE) }, + { DVB_USB_DEVICE(USB_VID_AMT, USB_PID_ANYSEE, + &anysee_props, "Anysee", RC_MAP_ANYSEE) }, + { } +}; +MODULE_DEVICE_TABLE(usb, anysee_id_table); + +static struct usb_driver anysee_usb_driver = { + .name = KBUILD_MODNAME, + .id_table = anysee_id_table, + .probe = dvb_usbv2_probe, + .disconnect = dvb_usbv2_disconnect, + .suspend = dvb_usbv2_suspend, + .resume = dvb_usbv2_resume, + .reset_resume = dvb_usbv2_reset_resume, + .no_dynamic_id = 1, + .soft_unbind = 1, }; -module_usb_driver(anysee_driver); +module_usb_driver(anysee_usb_driver); MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>"); MODULE_DESCRIPTION("Driver Anysee E30 DVB-C & DVB-T USB2.0"); diff --git a/drivers/media/dvb/dvb-usb/anysee.h b/drivers/media/usb/dvb-usb-v2/anysee.h index 8ac879431540..c1a4273f14ff 100644 --- a/drivers/media/dvb/dvb-usb/anysee.h +++ b/drivers/media/usb/dvb-usb-v2/anysee.h @@ -35,16 +35,9 @@ #define _DVB_USB_ANYSEE_H_ #define DVB_USB_LOG_PREFIX "anysee" -#include "dvb-usb.h" +#include "dvb_usb.h" #include "dvb_ca_en50221.h" -#define deb_info(args...) dprintk(dvb_usb_anysee_debug, 0x01, args) -#define deb_xfer(args...) dprintk(dvb_usb_anysee_debug, 0x02, args) -#define deb_rc(args...) dprintk(dvb_usb_anysee_debug, 0x04, args) -#define deb_reg(args...) dprintk(dvb_usb_anysee_debug, 0x08, args) -#define deb_i2c(args...) dprintk(dvb_usb_anysee_debug, 0x10, args) -#define deb_fw(args...) dprintk(dvb_usb_anysee_debug, 0x20, args) - enum cmd { CMD_I2C_READ = 0x33, CMD_I2C_WRITE = 0x31, @@ -63,6 +56,7 @@ struct anysee_state { u8 seq; u8 fe_id:1; /* frondend ID */ u8 has_ci:1; + u8 ci_attached:1; struct dvb_ca_en50221 ci; unsigned long ci_cam_ready; /* jiffies */ }; diff --git a/drivers/media/dvb/dvb-usb/au6610.c b/drivers/media/usb/dvb-usb-v2/au6610.c index 16210c060302..ae6a671b7fd5 100644 --- a/drivers/media/dvb/dvb-usb/au6610.c +++ b/drivers/media/usb/dvb-usb-v2/au6610.c @@ -22,10 +22,6 @@ #include "zl10353.h" #include "qt1010.h" -/* debug */ -static int dvb_usb_au6610_debug; -module_param_named(debug, dvb_usb_au6610_debug, int, 0644); -MODULE_PARM_DESC(debug, "set debugging level" DVB_USB_DEBUG_STATUS); DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); static int au6610_usb_msg(struct dvb_usb_device *d, u8 operation, u8 addr, @@ -52,7 +48,8 @@ static int au6610_usb_msg(struct dvb_usb_device *d, u8 operation, u8 addr, index += wbuf[1]; break; default: - warn("wlen = %x, aborting.", wlen); + dev_err(&d->udev->dev, "%s: wlen=%d, aborting\n", + KBUILD_MODNAME, wlen); ret = -EINVAL; goto error; } @@ -60,6 +57,11 @@ static int au6610_usb_msg(struct dvb_usb_device *d, u8 operation, u8 addr, ret = usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0), operation, USB_TYPE_VENDOR|USB_DIR_IN, addr << 1, index, usb_buf, 6, AU6610_USB_TIMEOUT); + + dvb_usb_dbg_usb_control_msg(d->udev, operation, + (USB_TYPE_VENDOR|USB_DIR_IN), addr << 1, index, + usb_buf, 6); + if (ret < 0) goto error; @@ -140,9 +142,9 @@ static struct zl10353_config au6610_zl10353_config = { static int au6610_zl10353_frontend_attach(struct dvb_usb_adapter *adap) { - adap->fe_adap[0].fe = dvb_attach(zl10353_attach, &au6610_zl10353_config, - &adap->dev->i2c_adap); - if (adap->fe_adap[0].fe == NULL) + adap->fe[0] = dvb_attach(zl10353_attach, &au6610_zl10353_config, + &adap_to_d(adap)->i2c_adap); + if (adap->fe[0] == NULL) return -ENODEV; return 0; @@ -154,94 +156,53 @@ static struct qt1010_config au6610_qt1010_config = { static int au6610_qt1010_tuner_attach(struct dvb_usb_adapter *adap) { - return dvb_attach(qt1010_attach, - adap->fe_adap[0].fe, &adap->dev->i2c_adap, - &au6610_qt1010_config) == NULL ? -ENODEV : 0; + return dvb_attach(qt1010_attach, adap->fe[0], + &adap_to_d(adap)->i2c_adap, + &au6610_qt1010_config) == NULL ? -ENODEV : 0; } -/* DVB USB Driver stuff */ -static struct dvb_usb_device_properties au6610_properties; - -static int au6610_probe(struct usb_interface *intf, - const struct usb_device_id *id) +static int au6610_init(struct dvb_usb_device *d) { - struct dvb_usb_device *d; - struct usb_host_interface *alt; - int ret; - - if (intf->num_altsetting < AU6610_ALTSETTING_COUNT) - return -ENODEV; - - ret = dvb_usb_device_init(intf, &au6610_properties, THIS_MODULE, &d, - adapter_nr); - if (ret == 0) { - alt = usb_altnum_to_altsetting(intf, AU6610_ALTSETTING); - - if (alt == NULL) { - deb_info("%s: no alt found!\n", __func__); - return -ENODEV; - } - ret = usb_set_interface(d->udev, alt->desc.bInterfaceNumber, - alt->desc.bAlternateSetting); - } - - return ret; + /* TODO: this functionality belongs likely to the streaming control */ + /* bInterfaceNumber 0, bAlternateSetting 5 */ + return usb_set_interface(d->udev, 0, 5); } -static struct usb_device_id au6610_table [] = { - { USB_DEVICE(USB_VID_ALCOR_MICRO, USB_PID_SIGMATEK_DVB_110) }, - { } /* Terminating entry */ -}; -MODULE_DEVICE_TABLE(usb, au6610_table); +static struct dvb_usb_device_properties au6610_props = { + .driver_name = KBUILD_MODNAME, + .owner = THIS_MODULE, + .adapter_nr = adapter_nr, -static struct dvb_usb_device_properties au6610_properties = { - .caps = DVB_USB_IS_AN_I2C_ADAPTER, - - .usb_ctrl = DEVICE_SPECIFIC, - - .size_of_priv = 0, + .i2c_algo = &au6610_i2c_algo, + .frontend_attach = au6610_zl10353_frontend_attach, + .tuner_attach = au6610_qt1010_tuner_attach, + .init = au6610_init, .num_adapters = 1, .adapter = { { - .num_frontends = 1, - .fe = {{ - .frontend_attach = au6610_zl10353_frontend_attach, - .tuner_attach = au6610_qt1010_tuner_attach, - - .stream = { - .type = USB_ISOC, - .count = 5, - .endpoint = 0x82, - .u = { - .isoc = { - .framesperurb = 40, - .framesize = 942, - .interval = 1, - } - } - }, - }}, - } + .stream = DVB_USB_STREAM_ISOC(0x82, 5, 40, 942, 1), + }, }, +}; - .i2c_algo = &au6610_i2c_algo, - - .num_device_descs = 1, - .devices = { - { - .name = "Sigmatek DVB-110 DVB-T USB2.0", - .cold_ids = {NULL}, - .warm_ids = {&au6610_table[0], NULL}, - }, - } +static const struct usb_device_id au6610_id_table[] = { + { DVB_USB_DEVICE(USB_VID_ALCOR_MICRO, USB_PID_SIGMATEK_DVB_110, + &au6610_props, "Sigmatek DVB-110", NULL) }, + { } }; +MODULE_DEVICE_TABLE(usb, au6610_id_table); static struct usb_driver au6610_driver = { - .name = "dvb_usb_au6610", - .probe = au6610_probe, - .disconnect = dvb_usb_device_exit, - .id_table = au6610_table, + .name = KBUILD_MODNAME, + .id_table = au6610_id_table, + .probe = dvb_usbv2_probe, + .disconnect = dvb_usbv2_disconnect, + .suspend = dvb_usbv2_suspend, + .resume = dvb_usbv2_resume, + .reset_resume = dvb_usbv2_reset_resume, + .no_dynamic_id = 1, + .soft_unbind = 1, }; module_usb_driver(au6610_driver); diff --git a/drivers/media/dvb/dvb-usb/au6610.h b/drivers/media/usb/dvb-usb-v2/au6610.h index 7849abe2c614..ea337bfc00b1 100644 --- a/drivers/media/dvb/dvb-usb/au6610.h +++ b/drivers/media/usb/dvb-usb-v2/au6610.h @@ -18,13 +18,9 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#ifndef _DVB_USB_AU6610_H_ -#define _DVB_USB_AU6610_H_ - -#define DVB_USB_LOG_PREFIX "au6610" -#include "dvb-usb.h" - -#define deb_info(args...) dprintk(dvb_usb_au6610_debug, 0x01, args) +#ifndef AU6610_H +#define AU6610_H +#include "dvb_usb.h" #define AU6610_REQ_I2C_WRITE 0x14 #define AU6610_REQ_I2C_READ 0x13 @@ -33,7 +29,4 @@ #define AU6610_USB_TIMEOUT 1000 -#define AU6610_ALTSETTING_COUNT 6 -#define AU6610_ALTSETTING 5 - #endif diff --git a/drivers/media/dvb/dvb-usb/az6007.c b/drivers/media/usb/dvb-usb-v2/az6007.c index 86861e6f86d2..54f1221d930d 100644 --- a/drivers/media/dvb/dvb-usb/az6007.c +++ b/drivers/media/usb/dvb-usb-v2/az6007.c @@ -7,9 +7,9 @@ * http://linux.terratec.de/files/TERRATEC_H7/20110323_TERRATEC_H7_Linux.tar.gz * The original driver's license is GPL, as declared with MODULE_LICENSE() * - * Copyright (c) 2010-2011 Mauro Carvalho Chehab <mchehab@redhat.com> + * Copyright (c) 2010-2012 Mauro Carvalho Chehab <mchehab@redhat.com> * Driver modified by in order to work with upstream drxk driver, and - * tons of bugs got fixed. + * tons of bugs got fixed, and converted to use dvb-usb-v2. * * 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 @@ -24,20 +24,14 @@ #include "drxk.h" #include "mt2063.h" #include "dvb_ca_en50221.h" +#include "dvb_usb.h" +#include "cypress_firmware.h" -#define DVB_USB_LOG_PREFIX "az6007" -#include "dvb-usb.h" +#define AZ6007_FIRMWARE "dvb-usb-terratec-h7-az6007.fw" -/* debug */ -int dvb_usb_az6007_debug; -module_param_named(debug, dvb_usb_az6007_debug, int, 0644); -MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,rc=4 (or-able))." - DVB_USB_DEBUG_STATUS); - -#define deb_info(args...) dprintk(dvb_usb_az6007_debug, 0x01, args) -#define deb_xfer(args...) dprintk(dvb_usb_az6007_debug, 0x02, args) -#define deb_rc(args...) dprintk(dvb_usb_az6007_debug, 0x04, args) -#define deb_fe(args...) dprintk(dvb_usb_az6007_debug, 0x08, args) +static int az6007_xfer_debug; +module_param_named(xfer_debug, az6007_xfer_debug, int, 0644); +MODULE_PARM_DESC(xfer_debug, "Enable xfer debug"); DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); @@ -70,23 +64,19 @@ static struct drxk_config terratec_h7_drxk = { .no_i2c_bridge = false, .chunk_size = 64, .mpeg_out_clk_strength = 0x02, + .qam_demod_parameter_count = 2, .microcode_name = "dvb-usb-terratec-h7-drxk.fw", }; static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable) { + struct az6007_device_state *st = fe_to_priv(fe); struct dvb_usb_adapter *adap = fe->sec_priv; - struct az6007_device_state *st; int status = 0; - deb_info("%s: %s\n", __func__, enable ? "enable" : "disable"); - - if (!adap) - return -EINVAL; - - st = adap->dev->priv; + pr_debug("%s: %s\n", __func__, enable ? "enable" : "disable"); - if (!st) + if (!adap || !st) return -EINVAL; if (enable) @@ -113,13 +103,16 @@ static int __az6007_read(struct usb_device *udev, u8 req, u16 value, USB_TYPE_VENDOR | USB_DIR_IN, value, index, b, blen, 5000); if (ret < 0) { - warn("usb read operation failed. (%d)", ret); + pr_warn("usb read operation failed. (%d)\n", ret); return -EIO; } - deb_xfer("in: req. %02x, val: %04x, ind: %04x, buffer: ", req, value, - index); - debug_dump(b, blen, deb_xfer); + if (az6007_xfer_debug) { + printk(KERN_DEBUG "az6007: IN req: %02x, value: %04x, index: %04x\n", + req, value, index); + print_hex_dump_bytes("az6007: payload: ", + DUMP_PREFIX_NONE, b, blen); + } return ret; } @@ -145,13 +138,16 @@ static int __az6007_write(struct usb_device *udev, u8 req, u16 value, { int ret; - deb_xfer("out: req. %02x, val: %04x, ind: %04x, buffer: ", req, value, - index); - debug_dump(b, blen, deb_xfer); + if (az6007_xfer_debug) { + printk(KERN_DEBUG "az6007: OUT req: %02x, value: %04x, index: %04x\n", + req, value, index); + print_hex_dump_bytes("az6007: payload: ", + DUMP_PREFIX_NONE, b, blen); + } if (blen > 64) { - err("az6007: tried to write %d bytes, but I2C max size is 64 bytes\n", - blen); + pr_err("az6007: tried to write %d bytes, but I2C max size is 64 bytes\n", + blen); return -EOPNOTSUPP; } @@ -161,7 +157,7 @@ static int __az6007_write(struct usb_device *udev, u8 req, u16 value, USB_TYPE_VENDOR | USB_DIR_OUT, value, index, b, blen, 5000); if (ret != blen) { - err("usb write operation failed. (%d)", ret); + pr_err("usb write operation failed. (%d)\n", ret); return -EIO; } @@ -184,11 +180,11 @@ static int az6007_write(struct dvb_usb_device *d, u8 req, u16 value, return ret; } -static int az6007_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) +static int az6007_streaming_ctrl(struct dvb_frontend *fe, int onoff) { - struct dvb_usb_device *d = adap->dev; + struct dvb_usb_device *d = fe_to_d(fe); - deb_info("%s: %s", __func__, onoff ? "enable" : "disable"); + pr_debug("%s: %s\n", __func__, onoff ? "enable" : "disable"); return az6007_write(d, 0xbc, onoff, 0, NULL, 0); } @@ -196,7 +192,7 @@ static int az6007_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) /* remote control stuff (does not work with my box) */ static int az6007_rc_query(struct dvb_usb_device *d) { - struct az6007_device_state *st = d->priv; + struct az6007_device_state *st = d_to_priv(d); unsigned code = 0; az6007_read(d, AZ6007_READ_IR, 0, 0, st->data, 10); @@ -224,7 +220,7 @@ static int az6007_ci_read_attribute_mem(struct dvb_ca_en50221 *ca, int address) { struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; - struct az6007_device_state *state = (struct az6007_device_state *)d->priv; + struct az6007_device_state *state = d_to_priv(d); int ret; u8 req; @@ -249,7 +245,7 @@ static int az6007_ci_read_attribute_mem(struct dvb_ca_en50221 *ca, ret = az6007_read(d, req, value, index, b, blen); if (ret < 0) { - warn("usb in operation failed. (%d)", ret); + pr_warn("usb in operation failed. (%d)\n", ret); ret = -EINVAL; } else { ret = b[0]; @@ -266,7 +262,7 @@ static int az6007_ci_write_attribute_mem(struct dvb_ca_en50221 *ca, u8 value) { struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; - struct az6007_device_state *state = (struct az6007_device_state *)d->priv; + struct az6007_device_state *state = d_to_priv(d); int ret; u8 req; @@ -274,7 +270,7 @@ static int az6007_ci_write_attribute_mem(struct dvb_ca_en50221 *ca, u16 index; int blen; - deb_info("%s %d", __func__, slot); + pr_debug("%s(), slot %d\n", __func__, slot); if (slot != 0) return -EINVAL; @@ -286,7 +282,7 @@ static int az6007_ci_write_attribute_mem(struct dvb_ca_en50221 *ca, ret = az6007_write(d, req, value1, index, NULL, blen); if (ret != 0) - warn("usb out operation failed. (%d)", ret); + pr_warn("usb out operation failed. (%d)\n", ret); mutex_unlock(&state->ca_mutex); return ret; @@ -297,7 +293,7 @@ static int az6007_ci_read_cam_control(struct dvb_ca_en50221 *ca, u8 address) { struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; - struct az6007_device_state *state = (struct az6007_device_state *)d->priv; + struct az6007_device_state *state = d_to_priv(d); int ret; u8 req; @@ -322,14 +318,14 @@ static int az6007_ci_read_cam_control(struct dvb_ca_en50221 *ca, ret = az6007_read(d, req, value, index, b, blen); if (ret < 0) { - warn("usb in operation failed. (%d)", ret); + pr_warn("usb in operation failed. (%d)\n", ret); ret = -EINVAL; } else { if (b[0] == 0) - warn("Read CI IO error"); + pr_warn("Read CI IO error\n"); ret = b[1]; - deb_info("read cam data = %x from 0x%x", b[1], value); + pr_debug("read cam data = %x from 0x%x\n", b[1], value); } mutex_unlock(&state->ca_mutex); @@ -343,7 +339,7 @@ static int az6007_ci_write_cam_control(struct dvb_ca_en50221 *ca, u8 value) { struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; - struct az6007_device_state *state = (struct az6007_device_state *)d->priv; + struct az6007_device_state *state = d_to_priv(d); int ret; u8 req; @@ -362,7 +358,7 @@ static int az6007_ci_write_cam_control(struct dvb_ca_en50221 *ca, ret = az6007_write(d, req, value1, index, NULL, blen); if (ret != 0) { - warn("usb out operation failed. (%d)", ret); + pr_warn("usb out operation failed. (%d)\n", ret); goto failed; } @@ -393,7 +389,7 @@ static int CI_CamReady(struct dvb_ca_en50221 *ca, int slot) ret = az6007_read(d, req, value, index, b, blen); if (ret < 0) { - warn("usb in operation failed. (%d)", ret); + pr_warn("usb in operation failed. (%d)\n", ret); ret = -EIO; } else{ ret = b[0]; @@ -405,7 +401,7 @@ static int CI_CamReady(struct dvb_ca_en50221 *ca, int slot) static int az6007_ci_slot_reset(struct dvb_ca_en50221 *ca, int slot) { struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; - struct az6007_device_state *state = (struct az6007_device_state *)d->priv; + struct az6007_device_state *state = d_to_priv(d); int ret, i; u8 req; @@ -422,7 +418,7 @@ static int az6007_ci_slot_reset(struct dvb_ca_en50221 *ca, int slot) ret = az6007_write(d, req, value, index, NULL, blen); if (ret != 0) { - warn("usb out operation failed. (%d)", ret); + pr_warn("usb out operation failed. (%d)\n", ret); goto failed; } @@ -434,7 +430,7 @@ static int az6007_ci_slot_reset(struct dvb_ca_en50221 *ca, int slot) ret = az6007_write(d, req, value, index, NULL, blen); if (ret != 0) { - warn("usb out operation failed. (%d)", ret); + pr_warn("usb out operation failed. (%d)\n", ret); goto failed; } @@ -442,7 +438,7 @@ static int az6007_ci_slot_reset(struct dvb_ca_en50221 *ca, int slot) msleep(100); if (CI_CamReady(ca, slot)) { - deb_info("CAM Ready"); + pr_debug("CAM Ready\n"); break; } } @@ -461,7 +457,7 @@ static int az6007_ci_slot_shutdown(struct dvb_ca_en50221 *ca, int slot) static int az6007_ci_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot) { struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; - struct az6007_device_state *state = (struct az6007_device_state *)d->priv; + struct az6007_device_state *state = d_to_priv(d); int ret; u8 req; @@ -469,7 +465,7 @@ static int az6007_ci_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot) u16 index; int blen; - deb_info("%s", __func__); + pr_debug("%s()\n", __func__); mutex_lock(&state->ca_mutex); req = 0xC7; value = 1; @@ -478,7 +474,7 @@ static int az6007_ci_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot) ret = az6007_write(d, req, value, index, NULL, blen); if (ret != 0) { - warn("usb out operation failed. (%d)", ret); + pr_warn("usb out operation failed. (%d)\n", ret); goto failed; } @@ -490,7 +486,7 @@ failed: static int az6007_ci_poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open) { struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; - struct az6007_device_state *state = (struct az6007_device_state *)d->priv; + struct az6007_device_state *state = d_to_priv(d); int ret; u8 req; u16 value; @@ -510,7 +506,7 @@ static int az6007_ci_poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int o ret = az6007_read(d, req, value, index, b, blen); if (ret < 0) { - warn("usb in operation failed. (%d)", ret); + pr_warn("usb in operation failed. (%d)\n", ret); ret = -EIO; } else ret = 0; @@ -530,12 +526,12 @@ static void az6007_ci_uninit(struct dvb_usb_device *d) { struct az6007_device_state *state; - deb_info("%s", __func__); + pr_debug("%s()\n", __func__); if (NULL == d) return; - state = (struct az6007_device_state *)d->priv; + state = d_to_priv(d); if (NULL == state) return; @@ -548,16 +544,15 @@ static void az6007_ci_uninit(struct dvb_usb_device *d) } -static int az6007_ci_init(struct dvb_usb_adapter *a) +static int az6007_ci_init(struct dvb_usb_adapter *adap) { - struct dvb_usb_device *d = a->dev; - struct az6007_device_state *state = (struct az6007_device_state *)d->priv; + struct dvb_usb_device *d = adap_to_d(adap); + struct az6007_device_state *state = adap_to_priv(adap); int ret; - deb_info("%s", __func__); + pr_debug("%s()\n", __func__); mutex_init(&state->ca_mutex); - state->ca.owner = THIS_MODULE; state->ca.read_attribute_mem = az6007_ci_read_attribute_mem; state->ca.write_attribute_mem = az6007_ci_write_attribute_mem; @@ -569,49 +564,51 @@ static int az6007_ci_init(struct dvb_usb_adapter *a) state->ca.poll_slot_status = az6007_ci_poll_slot_status; state->ca.data = d; - ret = dvb_ca_en50221_init(&a->dvb_adap, + ret = dvb_ca_en50221_init(&adap->dvb_adap, &state->ca, 0, /* flags */ 1);/* n_slots */ if (ret != 0) { - err("Cannot initialize CI: Error %d.", ret); + pr_err("Cannot initialize CI: Error %d.\n", ret); memset(&state->ca, 0, sizeof(state->ca)); return ret; } - deb_info("CI initialized."); + pr_debug("CI initialized.\n"); return 0; } -static int az6007_read_mac_addr(struct dvb_usb_device *d, u8 mac[6]) +static int az6007_read_mac_addr(struct dvb_usb_adapter *adap, u8 mac[6]) { - struct az6007_device_state *st = d->priv; + struct dvb_usb_device *d = adap_to_d(adap); + struct az6007_device_state *st = adap_to_priv(adap); int ret; ret = az6007_read(d, AZ6007_READ_DATA, 6, 0, st->data, 6); memcpy(mac, st->data, 6); if (ret > 0) - deb_info("%s: mac is %pM\n", __func__, mac); + pr_debug("%s: mac is %pM\n", __func__, mac); return ret; } static int az6007_frontend_attach(struct dvb_usb_adapter *adap) { - struct az6007_device_state *st = adap->dev->priv; + struct az6007_device_state *st = adap_to_priv(adap); + struct dvb_usb_device *d = adap_to_d(adap); - deb_info("attaching demod drxk"); + pr_debug("attaching demod drxk\n"); - adap->fe_adap[0].fe = dvb_attach(drxk_attach, &terratec_h7_drxk, - &adap->dev->i2c_adap); - if (!adap->fe_adap[0].fe) + adap->fe[0] = dvb_attach(drxk_attach, &terratec_h7_drxk, + &d->i2c_adap); + if (!adap->fe[0]) return -EINVAL; - adap->fe_adap[0].fe->sec_priv = adap; - st->gate_ctrl = adap->fe_adap[0].fe->ops.i2c_gate_ctrl; - adap->fe_adap[0].fe->ops.i2c_gate_ctrl = drxk_gate_ctrl; + adap->fe[0]->sec_priv = adap; + st->gate_ctrl = adap->fe[0]->ops.i2c_gate_ctrl; + adap->fe[0]->ops.i2c_gate_ctrl = drxk_gate_ctrl; az6007_ci_init(adap); @@ -620,31 +617,33 @@ static int az6007_frontend_attach(struct dvb_usb_adapter *adap) static int az6007_tuner_attach(struct dvb_usb_adapter *adap) { - deb_info("attaching tuner mt2063"); + struct dvb_usb_device *d = adap_to_d(adap); + + pr_debug("attaching tuner mt2063\n"); /* Attach mt2063 to DVB-C frontend */ - if (adap->fe_adap[0].fe->ops.i2c_gate_ctrl) - adap->fe_adap[0].fe->ops.i2c_gate_ctrl(adap->fe_adap[0].fe, 1); - if (!dvb_attach(mt2063_attach, adap->fe_adap[0].fe, + if (adap->fe[0]->ops.i2c_gate_ctrl) + adap->fe[0]->ops.i2c_gate_ctrl(adap->fe[0], 1); + if (!dvb_attach(mt2063_attach, adap->fe[0], &az6007_mt2063_config, - &adap->dev->i2c_adap)) + &d->i2c_adap)) return -EINVAL; - if (adap->fe_adap[0].fe->ops.i2c_gate_ctrl) - adap->fe_adap[0].fe->ops.i2c_gate_ctrl(adap->fe_adap[0].fe, 0); + if (adap->fe[0]->ops.i2c_gate_ctrl) + adap->fe[0]->ops.i2c_gate_ctrl(adap->fe[0], 0); return 0; } -int az6007_power_ctrl(struct dvb_usb_device *d, int onoff) +static int az6007_power_ctrl(struct dvb_usb_device *d, int onoff) { - struct az6007_device_state *st = d->priv; + struct az6007_device_state *state = d_to_priv(d); int ret; - deb_info("%s()\n", __func__); + pr_debug("%s()\n", __func__); - if (!st->warm) { - mutex_init(&st->mutex); + if (!state->warm) { + mutex_init(&state->mutex); ret = az6007_write(d, AZ6007_POWER, 0, 2, NULL, 0); if (ret < 0) @@ -675,7 +674,7 @@ int az6007_power_ctrl(struct dvb_usb_device *d, int onoff) if (ret < 0) return ret; - st->warm = true; + state->warm = true; return 0; } @@ -694,7 +693,7 @@ static int az6007_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) { struct dvb_usb_device *d = i2c_get_adapdata(adap); - struct az6007_device_state *st = d->priv; + struct az6007_device_state *st = d_to_priv(d); int i, j, len; int ret = 0; u16 index; @@ -709,7 +708,7 @@ static int az6007_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], addr = msgs[i].addr << 1; if (((i + 1) < num) && (msgs[i].len == 1) - && (!msgs[i].flags & I2C_M_RD) + && ((msgs[i].flags & I2C_M_RD) != I2C_M_RD) && (msgs[i + 1].flags & I2C_M_RD) && (msgs[i].addr == msgs[i + 1].addr)) { /* @@ -717,9 +716,8 @@ static int az6007_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], * the first xfer has just 1 byte length. * Need to join both into one operation */ - if (dvb_usb_az6007_debug & 2) - printk(KERN_DEBUG - "az6007 I2C xfer write+read addr=0x%x len=%d/%d: ", + if (az6007_xfer_debug) + printk(KERN_DEBUG "az6007: I2C W/R addr=0x%x len=%d/%d\n", addr, msgs[i].len, msgs[i + 1].len); req = AZ6007_I2C_RD; index = msgs[i].buf[0]; @@ -729,42 +727,29 @@ static int az6007_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], ret = __az6007_read(d->udev, req, value, index, st->data, length); if (ret >= len) { - for (j = 0; j < len; j++) { + for (j = 0; j < len; j++) msgs[i + 1].buf[j] = st->data[j + 5]; - if (dvb_usb_az6007_debug & 2) - printk(KERN_CONT - "0x%02x ", - msgs[i + 1].buf[j]); - } } else ret = -EIO; i++; } else if (!(msgs[i].flags & I2C_M_RD)) { /* write bytes */ - if (dvb_usb_az6007_debug & 2) - printk(KERN_DEBUG - "az6007 I2C xfer write addr=0x%x len=%d: ", + if (az6007_xfer_debug) + printk(KERN_DEBUG "az6007: I2C W addr=0x%x len=%d\n", addr, msgs[i].len); req = AZ6007_I2C_WR; index = msgs[i].buf[0]; value = addr | (1 << 8); length = msgs[i].len - 1; len = msgs[i].len - 1; - if (dvb_usb_az6007_debug & 2) - printk(KERN_CONT "(0x%02x) ", msgs[i].buf[0]); - for (j = 0; j < len; j++) { + for (j = 0; j < len; j++) st->data[j] = msgs[i].buf[j + 1]; - if (dvb_usb_az6007_debug & 2) - printk(KERN_CONT "0x%02x ", - st->data[j]); - } ret = __az6007_write(d->udev, req, value, index, st->data, length); } else { /* read bytes */ - if (dvb_usb_az6007_debug & 2) - printk(KERN_DEBUG - "az6007 I2C xfer read addr=0x%x len=%d: ", + if (az6007_xfer_debug) + printk(KERN_DEBUG "az6007: I2C R addr=0x%x len=%d\n", addr, msgs[i].len); req = AZ6007_I2C_RD; index = msgs[i].buf[0]; @@ -773,15 +758,9 @@ static int az6007_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], len = msgs[i].len; ret = __az6007_read(d->udev, req, value, index, st->data, length); - for (j = 0; j < len; j++) { + for (j = 0; j < len; j++) msgs[i].buf[j] = st->data[j + 5]; - if (dvb_usb_az6007_debug & 2) - printk(KERN_CONT - "0x%02x ", st->data[j + 5]); - } } - if (dvb_usb_az6007_debug & 2) - printk(KERN_CONT "\n"); if (ret < 0) goto err; } @@ -789,7 +768,7 @@ err: mutex_unlock(&st->mutex); if (ret < 0) { - info("%s ERROR: %i", __func__, ret); + pr_info("%s ERROR: %i\n", __func__, ret); return ret; } return num; @@ -805,151 +784,136 @@ static struct i2c_algorithm az6007_i2c_algo = { .functionality = az6007_i2c_func, }; -int az6007_identify_state(struct usb_device *udev, - struct dvb_usb_device_properties *props, - struct dvb_usb_device_description **desc, int *cold) +static int az6007_identify_state(struct dvb_usb_device *d, const char **name) { int ret; u8 *mac; + pr_debug("Identifying az6007 state\n"); + mac = kmalloc(6, GFP_ATOMIC); if (!mac) return -ENOMEM; /* Try to read the mac address */ - ret = __az6007_read(udev, AZ6007_READ_DATA, 6, 0, mac, 6); + ret = __az6007_read(d->udev, AZ6007_READ_DATA, 6, 0, mac, 6); if (ret == 6) - *cold = 0; + ret = WARM; else - *cold = 1; + ret = COLD; kfree(mac); - if (*cold) { - __az6007_write(udev, 0x09, 1, 0, NULL, 0); - __az6007_write(udev, 0x00, 0, 0, NULL, 0); - __az6007_write(udev, 0x00, 0, 0, NULL, 0); + if (ret == COLD) { + __az6007_write(d->udev, 0x09, 1, 0, NULL, 0); + __az6007_write(d->udev, 0x00, 0, 0, NULL, 0); + __az6007_write(d->udev, 0x00, 0, 0, NULL, 0); } - deb_info("Device is on %s state\n", *cold ? "warm" : "cold"); - return 0; + pr_debug("Device is on %s state\n", + ret == WARM ? "warm" : "cold"); + return ret; } -static struct dvb_usb_device_properties az6007_properties; - static void az6007_usb_disconnect(struct usb_interface *intf) { struct dvb_usb_device *d = usb_get_intfdata(intf); az6007_ci_uninit(d); - dvb_usb_device_exit(intf); + dvb_usbv2_disconnect(intf); } -static int az6007_usb_probe(struct usb_interface *intf, - const struct usb_device_id *id) +static int az6007_get_rc_config(struct dvb_usb_device *d, struct dvb_usb_rc *rc) { - return dvb_usb_device_init(intf, &az6007_properties, - THIS_MODULE, NULL, adapter_nr); + pr_debug("Getting az6007 Remote Control properties\n"); + + rc->allowed_protos = RC_TYPE_NEC; + rc->query = az6007_rc_query; + rc->interval = 400; + + return 0; } -static struct usb_device_id az6007_usb_table[] = { - {USB_DEVICE(USB_VID_AZUREWAVE, USB_PID_AZUREWAVE_6007)}, - {USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_H7)}, - {USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_H7_2)}, - {0}, -}; +static int az6007_download_firmware(struct dvb_usb_device *d, + const struct firmware *fw) +{ + pr_debug("Loading az6007 firmware\n"); -MODULE_DEVICE_TABLE(usb, az6007_usb_table); + return usbv2_cypress_load_firmware(d->udev, fw, CYPRESS_FX2); +} + +/* DVB USB Driver stuff */ +static struct dvb_usb_device_properties az6007_props = { + .driver_name = KBUILD_MODNAME, + .owner = THIS_MODULE, + .firmware = AZ6007_FIRMWARE, -static struct dvb_usb_device_properties az6007_properties = { - .caps = DVB_USB_IS_AN_I2C_ADAPTER, - .usb_ctrl = CYPRESS_FX2, - .firmware = "dvb-usb-terratec-h7-az6007.fw", - .no_reconnect = 1, + .adapter_nr = adapter_nr, .size_of_priv = sizeof(struct az6007_device_state), + .i2c_algo = &az6007_i2c_algo, + .tuner_attach = az6007_tuner_attach, + .frontend_attach = az6007_frontend_attach, + .streaming_ctrl = az6007_streaming_ctrl, + .get_rc_config = az6007_get_rc_config, + .read_mac_address = az6007_read_mac_addr, + .download_firmware = az6007_download_firmware, .identify_state = az6007_identify_state, - .num_adapters = 1, - .adapter = { - { - .num_frontends = 1, - .fe = {{ - .streaming_ctrl = az6007_streaming_ctrl, - .tuner_attach = az6007_tuner_attach, - .frontend_attach = az6007_frontend_attach, - - /* parameter for the MPEG2-data transfer */ - .stream = { - .type = USB_BULK, - .count = 10, - .endpoint = 0x02, - .u = { - .bulk = { - .buffersize = 4096, - } - } - }, - } } - } }, - .power_ctrl = az6007_power_ctrl, - .read_mac_address = az6007_read_mac_addr, - - .rc.core = { - .rc_interval = 400, - .rc_codes = RC_MAP_NEC_TERRATEC_CINERGY_XS, - .module_name = "az6007", - .rc_query = az6007_rc_query, - .allowed_protos = RC_TYPE_NEC, - }, - .i2c_algo = &az6007_i2c_algo, - - .num_device_descs = 2, - .devices = { - { .name = "AzureWave DTV StarBox DVB-T/C USB2.0 (az6007)", - .cold_ids = { &az6007_usb_table[0], NULL }, - .warm_ids = { NULL }, - }, - { .name = "TerraTec DTV StarBox DVB-T/C USB2.0 (az6007)", - .cold_ids = { &az6007_usb_table[1], &az6007_usb_table[2], NULL }, - .warm_ids = { NULL }, - }, - { NULL }, + .power_ctrl = az6007_power_ctrl, + .num_adapters = 1, + .adapter = { + { .stream = DVB_USB_STREAM_BULK(0x02, 10, 4096), } } }; -/* usb specific object needed to register this driver with the usb subsystem */ -static struct usb_driver az6007_usb_driver = { - .name = "dvb_usb_az6007", - .probe = az6007_usb_probe, - .disconnect = az6007_usb_disconnect, - .id_table = az6007_usb_table, +static struct usb_device_id az6007_usb_table[] = { + {DVB_USB_DEVICE(USB_VID_AZUREWAVE, USB_PID_AZUREWAVE_6007, + &az6007_props, "Azurewave 6007", RC_MAP_EMPTY)}, + {DVB_USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_H7, + &az6007_props, "Terratec H7", RC_MAP_NEC_TERRATEC_CINERGY_XS)}, + {DVB_USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_H7_2, + &az6007_props, "Terratec H7", RC_MAP_NEC_TERRATEC_CINERGY_XS)}, + {0}, }; -/* module stuff */ -static int __init az6007_usb_module_init(void) -{ - int result; - deb_info("az6007 usb module init\n"); +MODULE_DEVICE_TABLE(usb, az6007_usb_table); - result = usb_register(&az6007_usb_driver); - if (result) { - err("usb_register failed. (%d)", result); - return result; - } +static int az6007_suspend(struct usb_interface *intf, pm_message_t msg) +{ + struct dvb_usb_device *d = usb_get_intfdata(intf); - return 0; + az6007_ci_uninit(d); + return dvb_usbv2_suspend(intf, msg); } -static void __exit az6007_usb_module_exit(void) +static int az6007_resume(struct usb_interface *intf) { - /* deregister this driver from the USB subsystem */ - deb_info("az6007 usb module exit\n"); - usb_deregister(&az6007_usb_driver); + struct dvb_usb_device *d = usb_get_intfdata(intf); + struct dvb_usb_adapter *adap = &d->adapter[0]; + + az6007_ci_init(adap); + return dvb_usbv2_resume(intf); } -module_init(az6007_usb_module_init); -module_exit(az6007_usb_module_exit); +/* usb specific object needed to register this driver with the usb subsystem */ +static struct usb_driver az6007_usb_driver = { + .name = KBUILD_MODNAME, + .id_table = az6007_usb_table, + .probe = dvb_usbv2_probe, + .disconnect = az6007_usb_disconnect, + .no_dynamic_id = 1, + .soft_unbind = 1, + /* + * FIXME: need to implement reset_resume, likely with + * dvb-usb-v2 core support + */ + .suspend = az6007_suspend, + .resume = az6007_resume, +}; + +module_usb_driver(az6007_usb_driver); MODULE_AUTHOR("Henry Wang <Henry.wang@AzureWave.com>"); MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); MODULE_DESCRIPTION("Driver for AzureWave 6007 DVB-C/T USB2.0 and clones"); -MODULE_VERSION("1.1"); +MODULE_VERSION("2.0"); MODULE_LICENSE("GPL"); +MODULE_FIRMWARE(AZ6007_FIRMWARE); diff --git a/drivers/media/dvb/dvb-usb/ce6230.c b/drivers/media/usb/dvb-usb-v2/ce6230.c index fa637255729c..f67b14bc32e3 100644 --- a/drivers/media/dvb/dvb-usb/ce6230.c +++ b/drivers/media/usb/dvb-usb-v2/ce6230.c @@ -1,5 +1,5 @@ /* - * DVB USB Linux driver for Intel CE6230 DVB-T USB2.0 receiver + * Intel CE6230 DVB USB driver * * Copyright (C) 2009 Antti Palosaari <crope@iki.fi> * @@ -20,18 +20,10 @@ */ #include "ce6230.h" -#include "zl10353.h" -#include "mxl5005s.h" -/* debug */ -static int dvb_usb_ce6230_debug; -module_param_named(debug, dvb_usb_ce6230_debug, int, 0644); -MODULE_PARM_DESC(debug, "set debugging level" DVB_USB_DEBUG_STATUS); DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); -static struct zl10353_config ce6230_zl10353_config; - -static int ce6230_rw_udev(struct usb_device *udev, struct req_t *req) +static int ce6230_ctrl_msg(struct dvb_usb_device *d, struct usb_req *req) { int ret; unsigned int pipe; @@ -57,8 +49,9 @@ static int ce6230_rw_udev(struct usb_device *udev, struct req_t *req) requesttype = (USB_TYPE_VENDOR | USB_DIR_OUT); break; default: - err("unknown command:%02x", req->cmd); - ret = -EPERM; + dev_err(&d->udev->dev, "%s: unknown command=%02x\n", + KBUILD_MODNAME, req->cmd); + ret = -EINVAL; goto error; } @@ -71,22 +64,23 @@ static int ce6230_rw_udev(struct usb_device *udev, struct req_t *req) if (requesttype == (USB_TYPE_VENDOR | USB_DIR_OUT)) { /* write */ memcpy(buf, req->data, req->data_len); - pipe = usb_sndctrlpipe(udev, 0); + pipe = usb_sndctrlpipe(d->udev, 0); } else { /* read */ - pipe = usb_rcvctrlpipe(udev, 0); + pipe = usb_rcvctrlpipe(d->udev, 0); } msleep(1); /* avoid I2C errors */ - ret = usb_control_msg(udev, pipe, request, requesttype, value, index, - buf, req->data_len, CE6230_USB_TIMEOUT); + ret = usb_control_msg(d->udev, pipe, request, requesttype, value, index, + buf, req->data_len, CE6230_USB_TIMEOUT); - ce6230_debug_dump(request, requesttype, value, index, buf, - req->data_len, deb_xfer); + dvb_usb_dbg_usb_control_msg(d->udev, request, requesttype, value, index, + buf, req->data_len); if (ret < 0) - deb_info("%s: usb_control_msg failed:%d\n", __func__, ret); + dev_err(&d->udev->dev, "%s: usb_control_msg() failed=%d\n", + KBUILD_MODNAME, ret); else ret = 0; @@ -99,23 +93,20 @@ error: return ret; } -static int ce6230_ctrl_msg(struct dvb_usb_device *d, struct req_t *req) -{ - return ce6230_rw_udev(d->udev, req); -} - /* I2C */ -static int ce6230_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], - int num) +static struct zl10353_config ce6230_zl10353_config; + +static int ce6230_i2c_master_xfer(struct i2c_adapter *adap, + struct i2c_msg msg[], int num) { struct dvb_usb_device *d = i2c_get_adapdata(adap); - int i = 0; - struct req_t req; - int ret = 0; - memset(&req, 0, sizeof(req)); + int ret = 0, i = 0; + struct usb_req req; if (num > 2) - return -EINVAL; + return -EOPNOTSUPP; + + memset(&req, 0, sizeof(req)); if (mutex_lock_interruptible(&d->i2c_mutex) < 0) return -EAGAIN; @@ -131,8 +122,10 @@ static int ce6230_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], req.data = &msg[i+1].buf[0]; ret = ce6230_ctrl_msg(d, &req); } else { - err("i2c read not implemented"); - ret = -EPERM; + dev_err(&d->udev->dev, "%s: I2C read not " \ + "implemented\n", + KBUILD_MODNAME); + ret = -EOPNOTSUPP; } i += 2; } else { @@ -162,14 +155,14 @@ static int ce6230_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], return ret ? ret : i; } -static u32 ce6230_i2c_func(struct i2c_adapter *adapter) +static u32 ce6230_i2c_functionality(struct i2c_adapter *adapter) { return I2C_FUNC_I2C; } -static struct i2c_algorithm ce6230_i2c_algo = { - .master_xfer = ce6230_i2c_xfer, - .functionality = ce6230_i2c_func, +static struct i2c_algorithm ce6230_i2c_algorithm = { + .master_xfer = ce6230_i2c_master_xfer, + .functionality = ce6230_i2c_functionality, }; /* Callbacks for DVB USB */ @@ -185,11 +178,15 @@ static struct zl10353_config ce6230_zl10353_config = { static int ce6230_zl10353_frontend_attach(struct dvb_usb_adapter *adap) { - deb_info("%s:\n", __func__); - adap->fe_adap[0].fe = dvb_attach(zl10353_attach, &ce6230_zl10353_config, - &adap->dev->i2c_adap); - if (adap->fe_adap[0].fe == NULL) + struct dvb_usb_device *d = adap_to_d(adap); + + dev_dbg(&d->udev->dev, "%s:\n", __func__); + + adap->fe[0] = dvb_attach(zl10353_attach, &ce6230_zl10353_config, + &d->i2c_adap); + if (adap->fe[0] == NULL) return -ENODEV; + return 0; } @@ -212,9 +209,12 @@ static struct mxl5005s_config ce6230_mxl5003s_config = { static int ce6230_mxl5003s_tuner_attach(struct dvb_usb_adapter *adap) { + struct dvb_usb_device *d = adap_to_d(adap); int ret; - deb_info("%s:\n", __func__); - ret = dvb_attach(mxl5005s_attach, adap->fe_adap[0].fe, &adap->dev->i2c_adap, + + dev_dbg(&d->udev->dev, "%s:\n", __func__); + + ret = dvb_attach(mxl5005s_attach, adap->fe[0], &d->i2c_adap, &ce6230_mxl5003s_config) == NULL ? -ENODEV : 0; return ret; } @@ -222,103 +222,71 @@ static int ce6230_mxl5003s_tuner_attach(struct dvb_usb_adapter *adap) static int ce6230_power_ctrl(struct dvb_usb_device *d, int onoff) { int ret; - deb_info("%s: onoff:%d\n", __func__, onoff); + + dev_dbg(&d->udev->dev, "%s: onoff=%d\n", __func__, onoff); /* InterfaceNumber 1 / AlternateSetting 0 idle InterfaceNumber 1 / AlternateSetting 1 streaming */ ret = usb_set_interface(d->udev, 1, onoff); if (ret) - err("usb_set_interface failed with error:%d", ret); + dev_err(&d->udev->dev, "%s: usb_set_interface() failed=%d\n", + KBUILD_MODNAME, ret); return ret; } /* DVB USB Driver stuff */ -static struct dvb_usb_device_properties ce6230_properties; - -static int ce6230_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - int ret = 0; - struct dvb_usb_device *d = NULL; - - deb_info("%s: interface:%d\n", __func__, - intf->cur_altsetting->desc.bInterfaceNumber); +static struct dvb_usb_device_properties ce6230_props = { + .driver_name = KBUILD_MODNAME, + .owner = THIS_MODULE, + .adapter_nr = adapter_nr, + .bInterfaceNumber = 1, - if (intf->cur_altsetting->desc.bInterfaceNumber == 1) { - ret = dvb_usb_device_init(intf, &ce6230_properties, THIS_MODULE, - &d, adapter_nr); - if (ret) - err("init failed with error:%d\n", ret); - } - - return ret; -} - -static struct usb_device_id ce6230_table[] = { - { USB_DEVICE(USB_VID_INTEL, USB_PID_INTEL_CE9500) }, - { USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A310) }, - { } /* Terminating entry */ -}; -MODULE_DEVICE_TABLE(usb, ce6230_table); - -static struct dvb_usb_device_properties ce6230_properties = { - .caps = DVB_USB_IS_AN_I2C_ADAPTER, - - .usb_ctrl = DEVICE_SPECIFIC, - .no_reconnect = 1, - - .size_of_priv = 0, + .i2c_algo = &ce6230_i2c_algorithm, + .power_ctrl = ce6230_power_ctrl, + .frontend_attach = ce6230_zl10353_frontend_attach, + .tuner_attach = ce6230_mxl5003s_tuner_attach, .num_adapters = 1, .adapter = { { - .num_frontends = 1, - .fe = {{ - .frontend_attach = ce6230_zl10353_frontend_attach, - .tuner_attach = ce6230_mxl5003s_tuner_attach, .stream = { .type = USB_BULK, .count = 6, .endpoint = 0x82, .u = { .bulk = { - .buffersize = (16*512), + .buffersize = (16 * 512), } } }, - }}, } }, - - .power_ctrl = ce6230_power_ctrl, - - .i2c_algo = &ce6230_i2c_algo, - - .num_device_descs = 2, - .devices = { - { - .name = "Intel CE9500 reference design", - .cold_ids = {NULL}, - .warm_ids = {&ce6230_table[0], NULL}, - }, - { - .name = "AVerMedia A310 USB 2.0 DVB-T tuner", - .cold_ids = {NULL}, - .warm_ids = {&ce6230_table[1], NULL}, - }, - } }; -static struct usb_driver ce6230_driver = { - .name = "dvb_usb_ce6230", - .probe = ce6230_probe, - .disconnect = dvb_usb_device_exit, - .id_table = ce6230_table, +static const struct usb_device_id ce6230_id_table[] = { + { DVB_USB_DEVICE(USB_VID_INTEL, USB_PID_INTEL_CE9500, + &ce6230_props, "Intel CE9500 reference design", NULL) }, + { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A310, + &ce6230_props, "AVerMedia A310 USB 2.0 DVB-T tuner", NULL) }, + { } +}; +MODULE_DEVICE_TABLE(usb, ce6230_id_table); + +static struct usb_driver ce6230_usb_driver = { + .name = KBUILD_MODNAME, + .id_table = ce6230_id_table, + .probe = dvb_usbv2_probe, + .disconnect = dvb_usbv2_disconnect, + .suspend = dvb_usbv2_suspend, + .resume = dvb_usbv2_resume, + .reset_resume = dvb_usbv2_reset_resume, + .no_dynamic_id = 1, + .soft_unbind = 1, }; -module_usb_driver(ce6230_driver); +module_usb_driver(ce6230_usb_driver); MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>"); -MODULE_DESCRIPTION("Driver for Intel CE6230 DVB-T USB2.0"); +MODULE_DESCRIPTION("Intel CE6230 driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/dvb/dvb-usb/ce6230.h b/drivers/media/usb/dvb-usb-v2/ce6230.h index 97c42482ccb3..299e57e3390b 100644 --- a/drivers/media/dvb/dvb-usb/ce6230.h +++ b/drivers/media/usb/dvb-usb-v2/ce6230.h @@ -1,5 +1,5 @@ /* - * DVB USB Linux driver for Intel CE6230 DVB-T USB2.0 receiver + * Intel CE6230 DVB USB driver * * Copyright (C) 2009 Antti Palosaari <crope@iki.fi> * @@ -19,35 +19,16 @@ * */ -#ifndef _DVB_USB_CE6230_H_ -#define _DVB_USB_CE6230_H_ +#ifndef CE6230_H +#define CE6230_H -#define DVB_USB_LOG_PREFIX "ce6230" -#include "dvb-usb.h" - -#define deb_info(args...) dprintk(dvb_usb_ce6230_debug, 0x01, args) -#define deb_rc(args...) dprintk(dvb_usb_ce6230_debug, 0x02, args) -#define deb_xfer(args...) dprintk(dvb_usb_ce6230_debug, 0x04, args) -#define deb_reg(args...) dprintk(dvb_usb_ce6230_debug, 0x08, args) -#define deb_i2c(args...) dprintk(dvb_usb_ce6230_debug, 0x10, args) -#define deb_fw(args...) dprintk(dvb_usb_ce6230_debug, 0x20, args) - -#define ce6230_debug_dump(r, t, v, i, b, l, func) { \ - int loop_; \ - func("%02x %02x %02x %02x %02x %02x %02x %02x", \ - t, r, v & 0xff, v >> 8, i & 0xff, i >> 8, l & 0xff, l >> 8); \ - if (t == (USB_TYPE_VENDOR | USB_DIR_OUT)) \ - func(" >>> "); \ - else \ - func(" <<< "); \ - for (loop_ = 0; loop_ < l; loop_++) \ - func("%02x ", b[loop_]); \ - func("\n");\ -} +#include "dvb_usb.h" +#include "zl10353.h" +#include "mxl5005s.h" #define CE6230_USB_TIMEOUT 1000 -struct req_t { +struct usb_req { u8 cmd; /* [1] */ u16 value; /* [2|3] */ u16 index; /* [4|5] */ diff --git a/drivers/media/usb/dvb-usb-v2/cypress_firmware.c b/drivers/media/usb/dvb-usb-v2/cypress_firmware.c new file mode 100644 index 000000000000..211df549f26a --- /dev/null +++ b/drivers/media/usb/dvb-usb-v2/cypress_firmware.c @@ -0,0 +1,134 @@ +/* cypress_firmware.c is part of the DVB USB library. + * + * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@desy.de) + * see dvb-usb-init.c for copyright information. + * + * This file contains functions for downloading the firmware to Cypress FX 1 + * and 2 based devices. + * + */ + +#include "dvb_usb.h" +#include "cypress_firmware.h" + +struct usb_cypress_controller { + u8 id; + const char *name; /* name of the usb controller */ + u16 cs_reg; /* needs to be restarted, + * when the firmware has been downloaded */ +}; + +static const struct usb_cypress_controller cypress[] = { + { .id = CYPRESS_AN2135, .name = "Cypress AN2135", .cs_reg = 0x7f92 }, + { .id = CYPRESS_AN2235, .name = "Cypress AN2235", .cs_reg = 0x7f92 }, + { .id = CYPRESS_FX2, .name = "Cypress FX2", .cs_reg = 0xe600 }, +}; + +/* + * load a firmware packet to the device + */ +static int usb_cypress_writemem(struct usb_device *udev, u16 addr, u8 *data, + u8 len) +{ + dvb_usb_dbg_usb_control_msg(udev, + 0xa0, USB_TYPE_VENDOR, addr, 0x00, data, len); + + return usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + 0xa0, USB_TYPE_VENDOR, addr, 0x00, data, len, 5000); +} + +int usbv2_cypress_load_firmware(struct usb_device *udev, + const struct firmware *fw, int type) +{ + struct hexline *hx; + int ret, pos = 0; + + hx = kmalloc(sizeof(struct hexline), GFP_KERNEL); + if (!hx) { + dev_err(&udev->dev, "%s: kmalloc() failed\n", KBUILD_MODNAME); + return -ENOMEM; + } + + /* stop the CPU */ + hx->data[0] = 1; + ret = usb_cypress_writemem(udev, cypress[type].cs_reg, hx->data, 1); + if (ret != 1) { + dev_err(&udev->dev, "%s: CPU stop failed=%d\n", + KBUILD_MODNAME, ret); + ret = -EIO; + goto err_kfree; + } + + /* write firmware to memory */ + for (;;) { + ret = dvb_usbv2_get_hexline(fw, hx, &pos); + if (ret < 0) + goto err_kfree; + else if (ret == 0) + break; + + ret = usb_cypress_writemem(udev, hx->addr, hx->data, hx->len); + if (ret < 0) { + goto err_kfree; + } else if (ret != hx->len) { + dev_err(&udev->dev, "%s: error while transferring " \ + "firmware (transferred size=%d, " \ + "block size=%d)\n", + KBUILD_MODNAME, ret, hx->len); + ret = -EIO; + goto err_kfree; + } + } + + /* start the CPU */ + hx->data[0] = 0; + ret = usb_cypress_writemem(udev, cypress[type].cs_reg, hx->data, 1); + if (ret != 1) { + dev_err(&udev->dev, "%s: CPU start failed=%d\n", + KBUILD_MODNAME, ret); + ret = -EIO; + goto err_kfree; + } + + ret = 0; +err_kfree: + kfree(hx); + return ret; +} +EXPORT_SYMBOL(usbv2_cypress_load_firmware); + +int dvb_usbv2_get_hexline(const struct firmware *fw, struct hexline *hx, + int *pos) +{ + u8 *b = (u8 *) &fw->data[*pos]; + int data_offs = 4; + + if (*pos >= fw->size) + return 0; + + memset(hx, 0, sizeof(struct hexline)); + hx->len = b[0]; + + if ((*pos + hx->len + 4) >= fw->size) + return -EINVAL; + + hx->addr = b[1] | (b[2] << 8); + hx->type = b[3]; + + if (hx->type == 0x04) { + /* b[4] and b[5] are the Extended linear address record data + * field */ + hx->addr |= (b[4] << 24) | (b[5] << 16); + } + + memcpy(hx->data, &b[data_offs], hx->len); + hx->chk = b[hx->len + data_offs]; + *pos += hx->len + 5; + + return *pos; +} +EXPORT_SYMBOL(dvb_usbv2_get_hexline); + +MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>"); +MODULE_DESCRIPTION("Cypress firmware download"); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/usb/dvb-usb-v2/cypress_firmware.h b/drivers/media/usb/dvb-usb-v2/cypress_firmware.h new file mode 100644 index 000000000000..80085fd4132c --- /dev/null +++ b/drivers/media/usb/dvb-usb-v2/cypress_firmware.h @@ -0,0 +1,31 @@ +/* cypress_firmware.h is part of the DVB USB library. + * + * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@desy.de) + * see dvb-usb-init.c for copyright information. + * + * This file contains functions for downloading the firmware to Cypress FX 1 + * and 2 based devices. + * + */ + +#ifndef CYPRESS_FIRMWARE_H +#define CYPRESS_FIRMWARE_H + +#define CYPRESS_AN2135 0 +#define CYPRESS_AN2235 1 +#define CYPRESS_FX2 2 + +/* commonly used firmware download types and function */ +struct hexline { + u8 len; + u32 addr; + u8 type; + u8 data[255]; + u8 chk; +}; +extern int usbv2_cypress_load_firmware(struct usb_device *, + const struct firmware *, int); +extern int dvb_usbv2_get_hexline(const struct firmware *, + struct hexline *, int *); + +#endif diff --git a/drivers/media/usb/dvb-usb-v2/dvb_usb.h b/drivers/media/usb/dvb-usb-v2/dvb_usb.h new file mode 100644 index 000000000000..bae16a1189d6 --- /dev/null +++ b/drivers/media/usb/dvb-usb-v2/dvb_usb.h @@ -0,0 +1,403 @@ +/* + * DVB USB framework + * + * Copyright (C) 2004-6 Patrick Boettcher <patrick.boettcher@desy.de> + * Copyright (C) 2012 Antti Palosaari <crope@iki.fi> + * + * 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef DVB_USB_H +#define DVB_USB_H + +#include <linux/usb/input.h> +#include <linux/firmware.h> +#include <media/rc-core.h> + +#include "dvb_frontend.h" +#include "dvb_demux.h" +#include "dvb_net.h" +#include "dmxdev.h" +#include "dvb-usb-ids.h" + +/* + * device file: /dev/dvb/adapter[0-1]/frontend[0-2] + * + * |-- device + * | |-- adapter0 + * | | |-- frontend0 + * | | |-- frontend1 + * | | `-- frontend2 + * | `-- adapter1 + * | |-- frontend0 + * | |-- frontend1 + * | `-- frontend2 + * + * + * Commonly used variable names: + * d = pointer to device (struct dvb_usb_device *) + * adap = pointer to adapter (struct dvb_usb_adapter *) + * fe = pointer to frontend (struct dvb_frontend *) + * + * Use macros defined in that file to resolve needed pointers. + */ + +/* helper macros for every DVB USB driver use */ +#define adap_to_d(adap) (container_of(adap, struct dvb_usb_device, \ + adapter[adap->id])) +#define adap_to_priv(adap) (adap_to_d(adap)->priv) +#define fe_to_adap(fe) ((struct dvb_usb_adapter *) ((fe)->dvb->priv)) +#define fe_to_d(fe) (adap_to_d(fe_to_adap(fe))) +#define fe_to_priv(fe) (fe_to_d(fe)->priv) +#define d_to_priv(d) (d->priv) + +#define dvb_usb_dbg_usb_control_msg(udev, r, t, v, i, b, l) { \ + char *direction; \ + if (t == (USB_TYPE_VENDOR | USB_DIR_OUT)) \ + direction = ">>>"; \ + else \ + direction = "<<<"; \ + dev_dbg(&udev->dev, "%s: %02x %02x %02x %02x %02x %02x %02x %02x " \ + "%s %*ph\n", __func__, t, r, v & 0xff, v >> 8, \ + i & 0xff, i >> 8, l & 0xff, l >> 8, direction, l, b); \ +} + +#define DVB_USB_STREAM_BULK(endpoint_, count_, size_) { \ + .type = USB_BULK, \ + .count = count_, \ + .endpoint = endpoint_, \ + .u = { \ + .bulk = { \ + .buffersize = size_, \ + } \ + } \ +} + +#define DVB_USB_STREAM_ISOC(endpoint_, count_, frames_, size_, interval_) { \ + .type = USB_ISOC, \ + .count = count_, \ + .endpoint = endpoint_, \ + .u = { \ + .isoc = { \ + .framesperurb = frames_, \ + .framesize = size_,\ + .interval = interval_, \ + } \ + } \ +} + +#define DVB_USB_DEVICE(vend, prod, props_, name_, rc) \ + .match_flags = USB_DEVICE_ID_MATCH_DEVICE, \ + .idVendor = (vend), \ + .idProduct = (prod), \ + .driver_info = (kernel_ulong_t) &((const struct dvb_usb_driver_info) { \ + .props = (props_), \ + .name = (name_), \ + .rc_map = (rc), \ + }) + +struct dvb_usb_device; +struct dvb_usb_adapter; + +/** + * structure for carrying all needed data from the device driver to the general + * dvb usb routines + * @name: device name + * @rc_map: name of rc codes table + * @props: structure containing all device properties + */ +struct dvb_usb_driver_info { + const char *name; + const char *rc_map; + const struct dvb_usb_device_properties *props; +}; + +/** + * structure for remote controller configuration + * @map_name: name of rc codes table + * @allowed_protos: protocol(s) supported by the driver + * @change_protocol: callback to change protocol + * @query: called to query an event from the device + * @interval: time in ms between two queries + * @driver_type: used to point if a device supports raw mode + * @bulk_mode: device supports bulk mode for rc (disable polling mode) + */ +struct dvb_usb_rc { + const char *map_name; + u64 allowed_protos; + int (*change_protocol)(struct rc_dev *dev, u64 rc_type); + int (*query) (struct dvb_usb_device *d); + unsigned int interval; + const enum rc_driver_type driver_type; + bool bulk_mode; +}; + +/** + * usb streaming configration for adapter + * @type: urb type + * @count: count of used urbs + * @endpoint: stream usb endpoint number + */ +struct usb_data_stream_properties { +#define USB_BULK 1 +#define USB_ISOC 2 + u8 type; + u8 count; + u8 endpoint; + + union { + struct { + unsigned int buffersize; /* per URB */ + } bulk; + struct { + int framesperurb; + int framesize; + int interval; + } isoc; + } u; +}; + +/** + * properties of dvb usb device adapter + * @caps: adapter capabilities + * @pid_filter_count: pid count of adapter pid-filter + * @pid_filter_ctrl: called to enable/disable pid-filter + * @pid_filter: called to set/unset pid for filtering + * @stream: adapter usb stream configuration + */ +#define MAX_NO_OF_FE_PER_ADAP 3 +struct dvb_usb_adapter_properties { +#define DVB_USB_ADAP_HAS_PID_FILTER 0x01 +#define DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF 0x02 +#define DVB_USB_ADAP_NEED_PID_FILTERING 0x04 + u8 caps; + + u8 pid_filter_count; + int (*pid_filter_ctrl) (struct dvb_usb_adapter *, int); + int (*pid_filter) (struct dvb_usb_adapter *, int, u16, int); + + struct usb_data_stream_properties stream; +}; + +/** + * struct dvb_usb_device_properties - properties of a dvb-usb-device + * @driver_name: name of the owning driver module + * @owner: owner of the dvb_adapter + * @adapter_nr: values from the DVB_DEFINE_MOD_OPT_ADAPTER_NR() macro + * @bInterfaceNumber: usb interface number driver binds + * @size_of_priv: bytes allocated for the driver private data + * @generic_bulk_ctrl_endpoint: bulk control endpoint number for sent + * @generic_bulk_ctrl_endpoint_response: bulk control endpoint number for + * receive + * @generic_bulk_ctrl_delay: delay between bulk control sent and receive message + * @identify_state: called to determine the firmware state (cold or warm) and + * return possible firmware file name to be loaded + * @firmware: name of the firmware file to be loaded + * @download_firmware: called to download the firmware + * @i2c_algo: i2c_algorithm if the device has i2c-adapter + * @num_adapters: dvb usb device adapter count + * @get_adapter_count: called to resolve adapter count + * @adapter: array of all adapter properties of device + * @power_ctrl: called to enable/disable power of the device + * @read_config: called to resolve device configuration + * @read_mac_address: called to resolve adapter mac-address + * @frontend_attach: called to attach the possible frontends + * @tuner_attach: called to attach the possible tuners + * @frontend_ctrl: called to power on/off active frontend + * @streaming_ctrl: called to start/stop the usb streaming of adapter + * @init: called after adapters are created in order to finalize device + * configuration + * @exit: called when driver is unloaded + * @get_rc_config: called to resolve used remote controller configuration + * @get_stream_config: called to resolve input and output stream configuration + * of the adapter just before streaming is started. input stream is transport + * stream from the demodulator and output stream is usb stream to host. + */ +#define MAX_NO_OF_ADAPTER_PER_DEVICE 2 +struct dvb_usb_device_properties { + const char *driver_name; + struct module *owner; + short *adapter_nr; + + u8 bInterfaceNumber; + unsigned int size_of_priv; + u8 generic_bulk_ctrl_endpoint; + u8 generic_bulk_ctrl_endpoint_response; + unsigned int generic_bulk_ctrl_delay; + +#define WARM 0 +#define COLD 1 + int (*identify_state) (struct dvb_usb_device *, const char **); + const char *firmware; +#define RECONNECTS_USB 1 + int (*download_firmware) (struct dvb_usb_device *, + const struct firmware *); + + struct i2c_algorithm *i2c_algo; + + unsigned int num_adapters; + int (*get_adapter_count) (struct dvb_usb_device *); + struct dvb_usb_adapter_properties adapter[MAX_NO_OF_ADAPTER_PER_DEVICE]; + int (*power_ctrl) (struct dvb_usb_device *, int); + int (*read_config) (struct dvb_usb_device *d); + int (*read_mac_address) (struct dvb_usb_adapter *, u8 []); + int (*frontend_attach) (struct dvb_usb_adapter *); + int (*tuner_attach) (struct dvb_usb_adapter *); + int (*frontend_ctrl) (struct dvb_frontend *, int); + int (*streaming_ctrl) (struct dvb_frontend *, int); + int (*init) (struct dvb_usb_device *); + void (*exit) (struct dvb_usb_device *); + int (*get_rc_config) (struct dvb_usb_device *, struct dvb_usb_rc *); +#define DVB_USB_FE_TS_TYPE_188 0 +#define DVB_USB_FE_TS_TYPE_204 1 +#define DVB_USB_FE_TS_TYPE_RAW 2 + int (*get_stream_config) (struct dvb_frontend *, u8 *, + struct usb_data_stream_properties *); +}; + +/** + * generic object of an usb stream + * @buf_num: number of buffer allocated + * @buf_size: size of each buffer in buf_list + * @buf_list: array containing all allocate buffers for streaming + * @dma_addr: list of dma_addr_t for each buffer in buf_list + * + * @urbs_initialized: number of URBs initialized + * @urbs_submitted: number of URBs submitted + */ +#define MAX_NO_URBS_FOR_DATA_STREAM 10 +struct usb_data_stream { + struct usb_device *udev; + struct usb_data_stream_properties props; + +#define USB_STATE_INIT 0x00 +#define USB_STATE_URB_BUF 0x01 + u8 state; + + void (*complete) (struct usb_data_stream *, u8 *, size_t); + + struct urb *urb_list[MAX_NO_URBS_FOR_DATA_STREAM]; + int buf_num; + unsigned long buf_size; + u8 *buf_list[MAX_NO_URBS_FOR_DATA_STREAM]; + dma_addr_t dma_addr[MAX_NO_URBS_FOR_DATA_STREAM]; + + int urbs_initialized; + int urbs_submitted; + + void *user_priv; +}; + +/** + * dvb adapter object on dvb usb device + * @props: pointer to adapter properties + * @stream: adapter the usb data stream + * @id: index of this adapter (starting with 0) + * @ts_type: transport stream, input stream, type + * @suspend_resume_active: set when there is ongoing suspend / resume + * @pid_filtering: is hardware pid_filtering used or not + * @feed_count: current feed count + * @max_feed_count: maimum feed count device can handle + * @dvb_adap: adapter dvb_adapter + * @dmxdev: adapter dmxdev + * @demux: adapter software demuxer + * @dvb_net: adapter dvb_net interfaces + * @sync_mutex: mutex used to sync control and streaming of the adapter + * @fe: adapter frontends + * @fe_init: rerouted frontend-init function + * @fe_sleep: rerouted frontend-sleep function + */ +struct dvb_usb_adapter { + const struct dvb_usb_adapter_properties *props; + struct usb_data_stream stream; + u8 id; + u8 ts_type; + bool suspend_resume_active; + bool pid_filtering; + u8 feed_count; + u8 max_feed_count; + s8 active_fe; + + /* dvb */ + struct dvb_adapter dvb_adap; + struct dmxdev dmxdev; + struct dvb_demux demux; + struct dvb_net dvb_net; + struct mutex sync_mutex; + + struct dvb_frontend *fe[MAX_NO_OF_FE_PER_ADAP]; + int (*fe_init[MAX_NO_OF_FE_PER_ADAP]) (struct dvb_frontend *); + int (*fe_sleep[MAX_NO_OF_FE_PER_ADAP]) (struct dvb_frontend *); +}; + +/** + * dvb usb device object + * @props: device properties + * @name: device name + * @rc_map: name of rc codes table + * @udev: pointer to the device's struct usb_device + * @intf: pointer to the device's usb interface + * @rc: remote controller configuration + * @probe_work: work to defer .probe() + * @powered: indicated whether the device is power or not + * @usb_mutex: mutex for usb control messages + * @i2c_mutex: mutex for i2c-transfers + * @i2c_adap: device's i2c-adapter + * @rc_dev: rc device for the remote control + * @rc_query_work: work for polling remote + * @priv: private data of the actual driver (allocate by dvb usb, size defined + * in size_of_priv of dvb_usb_properties). + */ +struct dvb_usb_device { + const struct dvb_usb_device_properties *props; + const char *name; + const char *rc_map; + + struct usb_device *udev; + struct usb_interface *intf; + struct dvb_usb_rc rc; + struct work_struct probe_work; + pid_t work_pid; + int powered; + + /* locking */ + struct mutex usb_mutex; + + /* i2c */ + struct mutex i2c_mutex; + struct i2c_adapter i2c_adap; + + struct dvb_usb_adapter adapter[MAX_NO_OF_ADAPTER_PER_DEVICE]; + + /* remote control */ + struct rc_dev *rc_dev; + char rc_phys[64]; + struct delayed_work rc_query_work; + + void *priv; +}; + +extern int dvb_usbv2_probe(struct usb_interface *, + const struct usb_device_id *); +extern void dvb_usbv2_disconnect(struct usb_interface *); +extern int dvb_usbv2_suspend(struct usb_interface *, pm_message_t); +extern int dvb_usbv2_resume(struct usb_interface *); +extern int dvb_usbv2_reset_resume(struct usb_interface *); + +/* the generic read/write method for device control */ +extern int dvb_usbv2_generic_rw(struct dvb_usb_device *, u8 *, u16, u8 *, u16); +extern int dvb_usbv2_generic_write(struct dvb_usb_device *, u8 *, u16); + +#endif diff --git a/drivers/media/usb/dvb-usb-v2/dvb_usb_common.h b/drivers/media/usb/dvb-usb-v2/dvb_usb_common.h new file mode 100644 index 000000000000..45f07090d431 --- /dev/null +++ b/drivers/media/usb/dvb-usb-v2/dvb_usb_common.h @@ -0,0 +1,35 @@ +/* + * DVB USB framework + * + * Copyright (C) 2004-6 Patrick Boettcher <patrick.boettcher@desy.de> + * Copyright (C) 2012 Antti Palosaari <crope@iki.fi> + * + * 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef DVB_USB_COMMON_H +#define DVB_USB_COMMON_H + +#include "dvb_usb.h" + +/* commonly used methods */ +extern int usb_urb_initv2(struct usb_data_stream *stream, + const struct usb_data_stream_properties *props); +extern int usb_urb_exitv2(struct usb_data_stream *stream); +extern int usb_urb_submitv2(struct usb_data_stream *stream, + struct usb_data_stream_properties *props); +extern int usb_urb_killv2(struct usb_data_stream *stream); + +#endif diff --git a/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c b/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c new file mode 100644 index 000000000000..9859d2a2449b --- /dev/null +++ b/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c @@ -0,0 +1,1049 @@ +/* + * DVB USB framework + * + * Copyright (C) 2004-6 Patrick Boettcher <patrick.boettcher@desy.de> + * Copyright (C) 2012 Antti Palosaari <crope@iki.fi> + * + * 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "dvb_usb_common.h" + +int dvb_usbv2_disable_rc_polling; +module_param_named(disable_rc_polling, dvb_usbv2_disable_rc_polling, int, 0644); +MODULE_PARM_DESC(disable_rc_polling, + "disable remote control polling (default: 0)"); +static int dvb_usb_force_pid_filter_usage; +module_param_named(force_pid_filter_usage, dvb_usb_force_pid_filter_usage, + int, 0444); +MODULE_PARM_DESC(force_pid_filter_usage, "force all DVB USB devices to use a " \ + "PID filter, if any (default: 0)"); + +static int dvb_usbv2_download_firmware(struct dvb_usb_device *d, const char *name) +{ + int ret; + const struct firmware *fw; + dev_dbg(&d->udev->dev, "%s:\n", __func__); + + if (!d->props->download_firmware) { + ret = -EINVAL; + goto err; + } + + ret = request_firmware(&fw, name, &d->udev->dev); + if (ret < 0) { + dev_err(&d->udev->dev, "%s: Did not find the firmware file "\ + "'%s'. Please see linux/Documentation/dvb/ " \ + "for more details on firmware-problems. " \ + "Status %d\n", KBUILD_MODNAME, name, ret); + goto err; + } + + dev_info(&d->udev->dev, "%s: downloading firmware from file '%s'\n", + KBUILD_MODNAME, name); + + ret = d->props->download_firmware(d, fw); + release_firmware(fw); + if (ret < 0) + goto err; + + return ret; +err: + dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); + return ret; +} + +static int dvb_usbv2_i2c_init(struct dvb_usb_device *d) +{ + int ret; + dev_dbg(&d->udev->dev, "%s:\n", __func__); + + if (!d->props->i2c_algo) + return 0; + + strlcpy(d->i2c_adap.name, d->name, sizeof(d->i2c_adap.name)); + d->i2c_adap.algo = d->props->i2c_algo; + d->i2c_adap.dev.parent = &d->udev->dev; + i2c_set_adapdata(&d->i2c_adap, d); + + ret = i2c_add_adapter(&d->i2c_adap); + if (ret < 0) { + d->i2c_adap.algo = NULL; + dev_err(&d->udev->dev, "%s: i2c_add_adapter() failed=%d\n", + KBUILD_MODNAME, ret); + goto err; + } + + return 0; +err: + dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); + return ret; +} + +static int dvb_usbv2_i2c_exit(struct dvb_usb_device *d) +{ + dev_dbg(&d->udev->dev, "%s:\n", __func__); + + if (d->i2c_adap.algo) + i2c_del_adapter(&d->i2c_adap); + + return 0; +} + +static void dvb_usb_read_remote_control(struct work_struct *work) +{ + struct dvb_usb_device *d = container_of(work, + struct dvb_usb_device, rc_query_work.work); + int ret; + + /* + * When the parameter has been set to 1 via sysfs while the + * driver was running, or when bulk mode is enabled after IR init. + */ + if (dvb_usbv2_disable_rc_polling || d->rc.bulk_mode) + return; + + ret = d->rc.query(d); + if (ret < 0) { + dev_err(&d->udev->dev, "%s: rc.query() failed=%d\n", + KBUILD_MODNAME, ret); + return; /* stop polling */ + } + + schedule_delayed_work(&d->rc_query_work, + msecs_to_jiffies(d->rc.interval)); +} + +static int dvb_usbv2_remote_init(struct dvb_usb_device *d) +{ + int ret; + struct rc_dev *dev; + dev_dbg(&d->udev->dev, "%s:\n", __func__); + + if (dvb_usbv2_disable_rc_polling || !d->props->get_rc_config) + return 0; + + d->rc.map_name = d->rc_map; + ret = d->props->get_rc_config(d, &d->rc); + if (ret < 0) + goto err; + + /* disable rc when there is no keymap defined */ + if (!d->rc.map_name) + return 0; + + dev = rc_allocate_device(); + if (!dev) { + ret = -ENOMEM; + goto err; + } + + dev->dev.parent = &d->udev->dev; + dev->input_name = d->name; + usb_make_path(d->udev, d->rc_phys, sizeof(d->rc_phys)); + strlcat(d->rc_phys, "/ir0", sizeof(d->rc_phys)); + dev->input_phys = d->rc_phys; + usb_to_input_id(d->udev, &dev->input_id); + /* TODO: likely RC-core should took const char * */ + dev->driver_name = (char *) d->props->driver_name; + dev->map_name = d->rc.map_name; + dev->driver_type = d->rc.driver_type; + dev->allowed_protos = d->rc.allowed_protos; + dev->change_protocol = d->rc.change_protocol; + dev->priv = d; + + ret = rc_register_device(dev); + if (ret < 0) { + rc_free_device(dev); + goto err; + } + + d->rc_dev = dev; + + /* start polling if needed */ + if (d->rc.query && !d->rc.bulk_mode) { + /* initialize a work queue for handling polling */ + INIT_DELAYED_WORK(&d->rc_query_work, + dvb_usb_read_remote_control); + dev_info(&d->udev->dev, "%s: schedule remote query interval " \ + "to %d msecs\n", KBUILD_MODNAME, + d->rc.interval); + schedule_delayed_work(&d->rc_query_work, + msecs_to_jiffies(d->rc.interval)); + } + + return 0; +err: + dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); + return ret; +} + +static int dvb_usbv2_remote_exit(struct dvb_usb_device *d) +{ + dev_dbg(&d->udev->dev, "%s:\n", __func__); + + if (d->rc_dev) { + cancel_delayed_work_sync(&d->rc_query_work); + rc_unregister_device(d->rc_dev); + d->rc_dev = NULL; + } + + return 0; +} + +static void dvb_usb_data_complete(struct usb_data_stream *stream, u8 *buf, + size_t len) +{ + struct dvb_usb_adapter *adap = stream->user_priv; + dvb_dmx_swfilter(&adap->demux, buf, len); +} + +static void dvb_usb_data_complete_204(struct usb_data_stream *stream, u8 *buf, + size_t len) +{ + struct dvb_usb_adapter *adap = stream->user_priv; + dvb_dmx_swfilter_204(&adap->demux, buf, len); +} + +static void dvb_usb_data_complete_raw(struct usb_data_stream *stream, u8 *buf, + size_t len) +{ + struct dvb_usb_adapter *adap = stream->user_priv; + dvb_dmx_swfilter_raw(&adap->demux, buf, len); +} + +int dvb_usbv2_adapter_stream_init(struct dvb_usb_adapter *adap) +{ + dev_dbg(&adap_to_d(adap)->udev->dev, "%s: adap=%d\n", __func__, + adap->id); + + adap->stream.udev = adap_to_d(adap)->udev; + adap->stream.user_priv = adap; + adap->stream.complete = dvb_usb_data_complete; + + return usb_urb_initv2(&adap->stream, &adap->props->stream); +} + +int dvb_usbv2_adapter_stream_exit(struct dvb_usb_adapter *adap) +{ + dev_dbg(&adap_to_d(adap)->udev->dev, "%s: adap=%d\n", __func__, + adap->id); + + return usb_urb_exitv2(&adap->stream); +} + +static inline int dvb_usb_ctrl_feed(struct dvb_demux_feed *dvbdmxfeed, + int count) +{ + struct dvb_usb_adapter *adap = dvbdmxfeed->demux->priv; + struct dvb_usb_device *d = adap_to_d(adap); + int ret; + dev_dbg(&d->udev->dev, "%s: adap=%d active_fe=%d feed_type=%d " \ + "setting pid [%s]: %04x (%04d) at index %d '%s'\n", + __func__, adap->id, adap->active_fe, dvbdmxfeed->type, + adap->pid_filtering ? "yes" : "no", dvbdmxfeed->pid, + dvbdmxfeed->pid, dvbdmxfeed->index, + (count == 1) ? "on" : "off"); + + if (adap->active_fe == -1) + return -EINVAL; + + adap->feed_count += count; + + /* stop feeding if it is last pid */ + if (adap->feed_count == 0) { + dev_dbg(&d->udev->dev, "%s: stop feeding\n", __func__); + + if (d->props->streaming_ctrl) { + ret = d->props->streaming_ctrl( + adap->fe[adap->active_fe], 0); + if (ret < 0) { + dev_err(&d->udev->dev, "%s: streaming_ctrl() " \ + "failed=%d\n", KBUILD_MODNAME, + ret); + usb_urb_killv2(&adap->stream); + goto err_mutex_unlock; + } + } + usb_urb_killv2(&adap->stream); + mutex_unlock(&adap->sync_mutex); + } + + /* activate the pid on the device pid filter */ + if (adap->props->caps & DVB_USB_ADAP_HAS_PID_FILTER && + adap->pid_filtering && + adap->props->pid_filter) + ret = adap->props->pid_filter(adap, dvbdmxfeed->index, + dvbdmxfeed->pid, (count == 1) ? 1 : 0); + if (ret < 0) + dev_err(&d->udev->dev, "%s: pid_filter() " \ + "failed=%d\n", KBUILD_MODNAME, + ret); + + /* start feeding if it is first pid */ + if (adap->feed_count == 1 && count == 1) { + struct usb_data_stream_properties stream_props; + mutex_lock(&adap->sync_mutex); + dev_dbg(&d->udev->dev, "%s: start feeding\n", __func__); + + /* resolve input and output streaming paramters */ + if (d->props->get_stream_config) { + memcpy(&stream_props, &adap->props->stream, + sizeof(struct usb_data_stream_properties)); + ret = d->props->get_stream_config( + adap->fe[adap->active_fe], + &adap->ts_type, &stream_props); + if (ret < 0) + goto err_mutex_unlock; + } else { + stream_props = adap->props->stream; + } + + switch (adap->ts_type) { + case DVB_USB_FE_TS_TYPE_204: + adap->stream.complete = dvb_usb_data_complete_204; + break; + case DVB_USB_FE_TS_TYPE_RAW: + adap->stream.complete = dvb_usb_data_complete_raw; + break; + case DVB_USB_FE_TS_TYPE_188: + default: + adap->stream.complete = dvb_usb_data_complete; + break; + } + + usb_urb_submitv2(&adap->stream, &stream_props); + + if (adap->props->caps & DVB_USB_ADAP_HAS_PID_FILTER && + adap->props->caps & + DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF && + adap->props->pid_filter_ctrl) { + ret = adap->props->pid_filter_ctrl(adap, + adap->pid_filtering); + if (ret < 0) { + dev_err(&d->udev->dev, "%s: " \ + "pid_filter_ctrl() failed=%d\n", + KBUILD_MODNAME, ret); + goto err_mutex_unlock; + } + } + + if (d->props->streaming_ctrl) { + ret = d->props->streaming_ctrl( + adap->fe[adap->active_fe], 1); + if (ret < 0) { + dev_err(&d->udev->dev, "%s: streaming_ctrl() " \ + "failed=%d\n", KBUILD_MODNAME, + ret); + goto err_mutex_unlock; + } + } + } + + return 0; +err_mutex_unlock: + mutex_unlock(&adap->sync_mutex); + dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); + return ret; +} + +static int dvb_usb_start_feed(struct dvb_demux_feed *dvbdmxfeed) +{ + return dvb_usb_ctrl_feed(dvbdmxfeed, 1); +} + +static int dvb_usb_stop_feed(struct dvb_demux_feed *dvbdmxfeed) +{ + return dvb_usb_ctrl_feed(dvbdmxfeed, -1); +} + +int dvb_usbv2_adapter_dvb_init(struct dvb_usb_adapter *adap) +{ + int ret; + struct dvb_usb_device *d = adap_to_d(adap); + dev_dbg(&d->udev->dev, "%s: adap=%d\n", __func__, adap->id); + + ret = dvb_register_adapter(&adap->dvb_adap, d->name, d->props->owner, + &d->udev->dev, d->props->adapter_nr); + if (ret < 0) { + dev_dbg(&d->udev->dev, "%s: dvb_register_adapter() failed=%d\n", + __func__, ret); + goto err_dvb_register_adapter; + } + + adap->dvb_adap.priv = adap; + + if (d->props->read_mac_address) { + ret = d->props->read_mac_address(adap, + adap->dvb_adap.proposed_mac); + if (ret < 0) + goto err_dvb_dmx_init; + + dev_info(&d->udev->dev, "%s: MAC address: %pM\n", + KBUILD_MODNAME, adap->dvb_adap.proposed_mac); + } + + adap->demux.dmx.capabilities = DMX_TS_FILTERING | DMX_SECTION_FILTERING; + adap->demux.priv = adap; + adap->demux.filternum = 0; + adap->demux.filternum = adap->max_feed_count; + adap->demux.feednum = adap->demux.filternum; + adap->demux.start_feed = dvb_usb_start_feed; + adap->demux.stop_feed = dvb_usb_stop_feed; + adap->demux.write_to_decoder = NULL; + ret = dvb_dmx_init(&adap->demux); + if (ret < 0) { + dev_err(&d->udev->dev, "%s: dvb_dmx_init() failed=%d\n", + KBUILD_MODNAME, ret); + goto err_dvb_dmx_init; + } + + adap->dmxdev.filternum = adap->demux.filternum; + adap->dmxdev.demux = &adap->demux.dmx; + adap->dmxdev.capabilities = 0; + ret = dvb_dmxdev_init(&adap->dmxdev, &adap->dvb_adap); + if (ret < 0) { + dev_err(&d->udev->dev, "%s: dvb_dmxdev_init() failed=%d\n", + KBUILD_MODNAME, ret); + goto err_dvb_dmxdev_init; + } + + ret = dvb_net_init(&adap->dvb_adap, &adap->dvb_net, &adap->demux.dmx); + if (ret < 0) { + dev_err(&d->udev->dev, "%s: dvb_net_init() failed=%d\n", + KBUILD_MODNAME, ret); + goto err_dvb_net_init; + } + + mutex_init(&adap->sync_mutex); + + return 0; +err_dvb_net_init: + dvb_dmxdev_release(&adap->dmxdev); +err_dvb_dmxdev_init: + dvb_dmx_release(&adap->demux); +err_dvb_dmx_init: + dvb_unregister_adapter(&adap->dvb_adap); +err_dvb_register_adapter: + adap->dvb_adap.priv = NULL; + return ret; +} + +int dvb_usbv2_adapter_dvb_exit(struct dvb_usb_adapter *adap) +{ + dev_dbg(&adap_to_d(adap)->udev->dev, "%s: adap=%d\n", __func__, + adap->id); + + if (adap->dvb_adap.priv) { + dvb_net_release(&adap->dvb_net); + adap->demux.dmx.close(&adap->demux.dmx); + dvb_dmxdev_release(&adap->dmxdev); + dvb_dmx_release(&adap->demux); + dvb_unregister_adapter(&adap->dvb_adap); + } + + return 0; +} + +int dvb_usbv2_device_power_ctrl(struct dvb_usb_device *d, int onoff) +{ + int ret; + + if (onoff) + d->powered++; + else + d->powered--; + + if (d->powered == 0 || (onoff && d->powered == 1)) { + /* when switching from 1 to 0 or from 0 to 1 */ + dev_dbg(&d->udev->dev, "%s: power=%d\n", __func__, onoff); + if (d->props->power_ctrl) { + ret = d->props->power_ctrl(d, onoff); + if (ret < 0) + goto err; + } + } + + return 0; +err: + dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); + return ret; +} + +static int dvb_usb_fe_init(struct dvb_frontend *fe) +{ + int ret; + struct dvb_usb_adapter *adap = fe->dvb->priv; + struct dvb_usb_device *d = adap_to_d(adap); + dev_dbg(&d->udev->dev, "%s: adap=%d fe=%d\n", __func__, adap->id, + fe->id); + + if (!adap->suspend_resume_active) { + adap->active_fe = fe->id; + mutex_lock(&adap->sync_mutex); + } + + ret = dvb_usbv2_device_power_ctrl(d, 1); + if (ret < 0) + goto err; + + if (d->props->frontend_ctrl) { + ret = d->props->frontend_ctrl(fe, 1); + if (ret < 0) + goto err; + } + + if (adap->fe_init[fe->id]) { + ret = adap->fe_init[fe->id](fe); + if (ret < 0) + goto err; + } +err: + if (!adap->suspend_resume_active) + mutex_unlock(&adap->sync_mutex); + + dev_dbg(&d->udev->dev, "%s: ret=%d\n", __func__, ret); + return ret; +} + +static int dvb_usb_fe_sleep(struct dvb_frontend *fe) +{ + int ret; + struct dvb_usb_adapter *adap = fe->dvb->priv; + struct dvb_usb_device *d = adap_to_d(adap); + dev_dbg(&d->udev->dev, "%s: adap=%d fe=%d\n", __func__, adap->id, + fe->id); + + if (!adap->suspend_resume_active) + mutex_lock(&adap->sync_mutex); + + if (adap->fe_sleep[fe->id]) { + ret = adap->fe_sleep[fe->id](fe); + if (ret < 0) + goto err; + } + + if (d->props->frontend_ctrl) { + ret = d->props->frontend_ctrl(fe, 0); + if (ret < 0) + goto err; + } + + ret = dvb_usbv2_device_power_ctrl(d, 0); + if (ret < 0) + goto err; +err: + if (!adap->suspend_resume_active) { + adap->active_fe = -1; + mutex_unlock(&adap->sync_mutex); + } + + dev_dbg(&d->udev->dev, "%s: ret=%d\n", __func__, ret); + return ret; +} + +int dvb_usbv2_adapter_frontend_init(struct dvb_usb_adapter *adap) +{ + int ret, i, count_registered = 0; + struct dvb_usb_device *d = adap_to_d(adap); + dev_dbg(&d->udev->dev, "%s: adap=%d\n", __func__, adap->id); + + memset(adap->fe, 0, sizeof(adap->fe)); + adap->active_fe = -1; + + if (d->props->frontend_attach) { + ret = d->props->frontend_attach(adap); + if (ret < 0) { + dev_dbg(&d->udev->dev, "%s: frontend_attach() " \ + "failed=%d\n", __func__, ret); + goto err_dvb_frontend_detach; + } + } else { + dev_dbg(&d->udev->dev, "%s: frontend_attach() do not exists\n", + __func__); + ret = 0; + goto err; + } + + for (i = 0; i < MAX_NO_OF_FE_PER_ADAP && adap->fe[i]; i++) { + adap->fe[i]->id = i; + /* re-assign sleep and wakeup functions */ + adap->fe_init[i] = adap->fe[i]->ops.init; + adap->fe[i]->ops.init = dvb_usb_fe_init; + adap->fe_sleep[i] = adap->fe[i]->ops.sleep; + adap->fe[i]->ops.sleep = dvb_usb_fe_sleep; + + ret = dvb_register_frontend(&adap->dvb_adap, adap->fe[i]); + if (ret < 0) { + dev_err(&d->udev->dev, "%s: frontend%d registration " \ + "failed\n", KBUILD_MODNAME, i); + goto err_dvb_unregister_frontend; + } + + count_registered++; + } + + if (d->props->tuner_attach) { + ret = d->props->tuner_attach(adap); + if (ret < 0) { + dev_dbg(&d->udev->dev, "%s: tuner_attach() failed=%d\n", + __func__, ret); + goto err_dvb_unregister_frontend; + } + } + + return 0; + +err_dvb_unregister_frontend: + for (i = count_registered - 1; i >= 0; i--) + dvb_unregister_frontend(adap->fe[i]); + +err_dvb_frontend_detach: + for (i = MAX_NO_OF_FE_PER_ADAP - 1; i >= 0; i--) { + if (adap->fe[i]) { + dvb_frontend_detach(adap->fe[i]); + adap->fe[i] = NULL; + } + } + +err: + dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); + return ret; +} + +int dvb_usbv2_adapter_frontend_exit(struct dvb_usb_adapter *adap) +{ + int i; + dev_dbg(&adap_to_d(adap)->udev->dev, "%s: adap=%d\n", __func__, + adap->id); + + for (i = MAX_NO_OF_FE_PER_ADAP - 1; i >= 0; i--) { + if (adap->fe[i]) { + dvb_unregister_frontend(adap->fe[i]); + dvb_frontend_detach(adap->fe[i]); + } + } + + return 0; +} + +static int dvb_usbv2_adapter_init(struct dvb_usb_device *d) +{ + struct dvb_usb_adapter *adap; + int ret, i, adapter_count; + + /* resolve adapter count */ + adapter_count = d->props->num_adapters; + if (d->props->get_adapter_count) { + ret = d->props->get_adapter_count(d); + if (ret < 0) + goto err; + + adapter_count = ret; + } + + for (i = 0; i < adapter_count; i++) { + adap = &d->adapter[i]; + adap->id = i; + adap->props = &d->props->adapter[i]; + + /* speed - when running at FULL speed we need a HW PID filter */ + if (d->udev->speed == USB_SPEED_FULL && + !(adap->props->caps & DVB_USB_ADAP_HAS_PID_FILTER)) { + dev_err(&d->udev->dev, "%s: this USB2.0 device " \ + "cannot be run on a USB1.1 port (it " \ + "lacks a hardware PID filter)\n", + KBUILD_MODNAME); + ret = -ENODEV; + goto err; + } else if ((d->udev->speed == USB_SPEED_FULL && + adap->props->caps & DVB_USB_ADAP_HAS_PID_FILTER) || + (adap->props->caps & DVB_USB_ADAP_NEED_PID_FILTERING)) { + dev_info(&d->udev->dev, "%s: will use the device's " \ + "hardware PID filter " \ + "(table count: %d)\n", KBUILD_MODNAME, + adap->props->pid_filter_count); + adap->pid_filtering = 1; + adap->max_feed_count = adap->props->pid_filter_count; + } else { + dev_info(&d->udev->dev, "%s: will pass the complete " \ + "MPEG2 transport stream to the " \ + "software demuxer\n", KBUILD_MODNAME); + adap->pid_filtering = 0; + adap->max_feed_count = 255; + } + + if (!adap->pid_filtering && dvb_usb_force_pid_filter_usage && + adap->props->caps & DVB_USB_ADAP_HAS_PID_FILTER) { + dev_info(&d->udev->dev, "%s: PID filter enabled by " \ + "module option\n", KBUILD_MODNAME); + adap->pid_filtering = 1; + adap->max_feed_count = adap->props->pid_filter_count; + } + + ret = dvb_usbv2_adapter_stream_init(adap); + if (ret) + goto err; + + ret = dvb_usbv2_adapter_dvb_init(adap); + if (ret) + goto err; + + ret = dvb_usbv2_adapter_frontend_init(adap); + if (ret) + goto err; + + /* use exclusive FE lock if there is multiple shared FEs */ + if (adap->fe[1]) + adap->dvb_adap.mfe_shared = 1; + } + + return 0; +err: + dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); + return ret; +} + +static int dvb_usbv2_adapter_exit(struct dvb_usb_device *d) +{ + int i; + dev_dbg(&d->udev->dev, "%s:\n", __func__); + + for (i = MAX_NO_OF_ADAPTER_PER_DEVICE - 1; i >= 0; i--) { + if (d->adapter[i].props) { + dvb_usbv2_adapter_frontend_exit(&d->adapter[i]); + dvb_usbv2_adapter_dvb_exit(&d->adapter[i]); + dvb_usbv2_adapter_stream_exit(&d->adapter[i]); + } + } + + return 0; +} + +/* general initialization functions */ +static int dvb_usbv2_exit(struct dvb_usb_device *d) +{ + dev_dbg(&d->udev->dev, "%s:\n", __func__); + + dvb_usbv2_remote_exit(d); + dvb_usbv2_adapter_exit(d); + dvb_usbv2_i2c_exit(d); + kfree(d->priv); + kfree(d); + + return 0; +} + +static int dvb_usbv2_init(struct dvb_usb_device *d) +{ + int ret; + dev_dbg(&d->udev->dev, "%s:\n", __func__); + + dvb_usbv2_device_power_ctrl(d, 1); + + if (d->props->read_config) { + ret = d->props->read_config(d); + if (ret < 0) + goto err; + } + + ret = dvb_usbv2_i2c_init(d); + if (ret < 0) + goto err; + + ret = dvb_usbv2_adapter_init(d); + if (ret < 0) + goto err; + + if (d->props->init) { + ret = d->props->init(d); + if (ret < 0) + goto err; + } + + ret = dvb_usbv2_remote_init(d); + if (ret < 0) + goto err; + + dvb_usbv2_device_power_ctrl(d, 0); + + return 0; +err: + dvb_usbv2_device_power_ctrl(d, 0); + dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); + return ret; +} + +/* + * udev, which is used for the firmware downloading, requires we cannot + * block during module_init(). module_init() calls USB probe() which + * is this routine. Due to that we delay actual operation using workqueue + * and return always success here. + */ +static void dvb_usbv2_init_work(struct work_struct *work) +{ + int ret; + struct dvb_usb_device *d = + container_of(work, struct dvb_usb_device, probe_work); + + d->work_pid = current->pid; + dev_dbg(&d->udev->dev, "%s: work_pid=%d\n", __func__, d->work_pid); + + if (d->props->size_of_priv) { + d->priv = kzalloc(d->props->size_of_priv, GFP_KERNEL); + if (!d->priv) { + dev_err(&d->udev->dev, "%s: kzalloc() failed\n", + KBUILD_MODNAME); + ret = -ENOMEM; + goto err_usb_driver_release_interface; + } + } + + if (d->props->identify_state) { + const char *name = NULL; + ret = d->props->identify_state(d, &name); + if (ret == 0) { + ; + } else if (ret == COLD) { + dev_info(&d->udev->dev, "%s: found a '%s' in cold " \ + "state\n", KBUILD_MODNAME, d->name); + + if (!name) + name = d->props->firmware; + + ret = dvb_usbv2_download_firmware(d, name); + if (ret == 0) { + /* device is warm, continue initialization */ + ; + } else if (ret == RECONNECTS_USB) { + /* + * USB core will call disconnect() and then + * probe() as device reconnects itself from the + * USB bus. disconnect() will release all driver + * resources and probe() is called for 'new' + * device. As 'new' device is warm we should + * never go here again. + */ + return; + } else { + /* + * Unexpected error. We must unregister driver + * manually from the device, because device is + * already register by returning from probe() + * with success. usb_driver_release_interface() + * finally calls disconnect() in order to free + * resources. + */ + goto err_usb_driver_release_interface; + } + } else { + goto err_usb_driver_release_interface; + } + } + + dev_info(&d->udev->dev, "%s: found a '%s' in warm state\n", + KBUILD_MODNAME, d->name); + + ret = dvb_usbv2_init(d); + if (ret < 0) + goto err_usb_driver_release_interface; + + dev_info(&d->udev->dev, "%s: '%s' successfully initialized and " \ + "connected\n", KBUILD_MODNAME, d->name); + + return; +err_usb_driver_release_interface: + dev_info(&d->udev->dev, "%s: '%s' error while loading driver (%d)\n", + KBUILD_MODNAME, d->name, ret); + usb_driver_release_interface(to_usb_driver(d->intf->dev.driver), + d->intf); + dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); + return; +} + +int dvb_usbv2_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + int ret; + struct dvb_usb_device *d; + struct usb_device *udev = interface_to_usbdev(intf); + struct dvb_usb_driver_info *driver_info = + (struct dvb_usb_driver_info *) id->driver_info; + + dev_dbg(&udev->dev, "%s: bInterfaceNumber=%d\n", __func__, + intf->cur_altsetting->desc.bInterfaceNumber); + + if (!id->driver_info) { + dev_err(&udev->dev, "%s: driver_info failed\n", KBUILD_MODNAME); + ret = -ENODEV; + goto err; + } + + d = kzalloc(sizeof(struct dvb_usb_device), GFP_KERNEL); + if (!d) { + dev_err(&udev->dev, "%s: kzalloc() failed\n", KBUILD_MODNAME); + ret = -ENOMEM; + goto err; + } + + d->name = driver_info->name; + d->rc_map = driver_info->rc_map; + d->udev = udev; + d->intf = intf; + d->props = driver_info->props; + + if (d->intf->cur_altsetting->desc.bInterfaceNumber != + d->props->bInterfaceNumber) { + ret = -ENODEV; + goto err_kfree; + } + + mutex_init(&d->usb_mutex); + mutex_init(&d->i2c_mutex); + INIT_WORK(&d->probe_work, dvb_usbv2_init_work); + usb_set_intfdata(intf, d); + ret = schedule_work(&d->probe_work); + if (ret < 0) { + dev_err(&d->udev->dev, "%s: schedule_work() failed\n", + KBUILD_MODNAME); + goto err_kfree; + } + + return 0; +err_kfree: + kfree(d); +err: + dev_dbg(&udev->dev, "%s: failed=%d\n", __func__, ret); + return ret; +} +EXPORT_SYMBOL(dvb_usbv2_probe); + +void dvb_usbv2_disconnect(struct usb_interface *intf) +{ + struct dvb_usb_device *d = usb_get_intfdata(intf); + const char *name = d->name; + struct device dev = d->udev->dev; + dev_dbg(&d->udev->dev, "%s: pid=%d work_pid=%d\n", __func__, + current->pid, d->work_pid); + + /* ensure initialization work is finished until release resources */ + if (d->work_pid != current->pid) + cancel_work_sync(&d->probe_work); + + if (d->props->exit) + d->props->exit(d); + + dvb_usbv2_exit(d); + + dev_info(&dev, "%s: '%s' successfully deinitialized and disconnected\n", + KBUILD_MODNAME, name); +} +EXPORT_SYMBOL(dvb_usbv2_disconnect); + +int dvb_usbv2_suspend(struct usb_interface *intf, pm_message_t msg) +{ + struct dvb_usb_device *d = usb_get_intfdata(intf); + int ret = 0, i, active_fe; + struct dvb_frontend *fe; + dev_dbg(&d->udev->dev, "%s:\n", __func__); + + /* stop remote controller poll */ + if (d->rc.query && !d->rc.bulk_mode) + cancel_delayed_work_sync(&d->rc_query_work); + + for (i = MAX_NO_OF_ADAPTER_PER_DEVICE - 1; i >= 0; i--) { + active_fe = d->adapter[i].active_fe; + if (d->adapter[i].dvb_adap.priv && active_fe != -1) { + fe = d->adapter[i].fe[active_fe]; + d->adapter[i].suspend_resume_active = true; + + if (d->props->streaming_ctrl) + d->props->streaming_ctrl(fe, 0); + + /* stop usb streaming */ + usb_urb_killv2(&d->adapter[i].stream); + + ret = dvb_frontend_suspend(fe); + } + } + + return ret; +} +EXPORT_SYMBOL(dvb_usbv2_suspend); + +static int dvb_usbv2_resume_common(struct dvb_usb_device *d) +{ + int ret = 0, i, active_fe; + struct dvb_frontend *fe; + dev_dbg(&d->udev->dev, "%s:\n", __func__); + + for (i = 0; i < MAX_NO_OF_ADAPTER_PER_DEVICE; i++) { + active_fe = d->adapter[i].active_fe; + if (d->adapter[i].dvb_adap.priv && active_fe != -1) { + fe = d->adapter[i].fe[active_fe]; + + ret = dvb_frontend_resume(fe); + + /* resume usb streaming */ + usb_urb_submitv2(&d->adapter[i].stream, NULL); + + if (d->props->streaming_ctrl) + d->props->streaming_ctrl(fe, 1); + + d->adapter[i].suspend_resume_active = false; + } + } + + /* start remote controller poll */ + if (d->rc.query && !d->rc.bulk_mode) + schedule_delayed_work(&d->rc_query_work, + msecs_to_jiffies(d->rc.interval)); + + return ret; +} + +int dvb_usbv2_resume(struct usb_interface *intf) +{ + struct dvb_usb_device *d = usb_get_intfdata(intf); + dev_dbg(&d->udev->dev, "%s:\n", __func__); + + return dvb_usbv2_resume_common(d); +} +EXPORT_SYMBOL(dvb_usbv2_resume); + +int dvb_usbv2_reset_resume(struct usb_interface *intf) +{ + struct dvb_usb_device *d = usb_get_intfdata(intf); + int ret; + dev_dbg(&d->udev->dev, "%s:\n", __func__); + + dvb_usbv2_device_power_ctrl(d, 1); + + if (d->props->init) + d->props->init(d); + + ret = dvb_usbv2_resume_common(d); + + dvb_usbv2_device_power_ctrl(d, 0); + + return ret; +} +EXPORT_SYMBOL(dvb_usbv2_reset_resume); + +MODULE_VERSION("2.0"); +MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>"); +MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>"); +MODULE_DESCRIPTION("DVB USB common"); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/usb/dvb-usb-v2/dvb_usb_urb.c b/drivers/media/usb/dvb-usb-v2/dvb_usb_urb.c new file mode 100644 index 000000000000..0431beed0ef4 --- /dev/null +++ b/drivers/media/usb/dvb-usb-v2/dvb_usb_urb.c @@ -0,0 +1,77 @@ +/* + * DVB USB framework + * + * Copyright (C) 2004-6 Patrick Boettcher <patrick.boettcher@desy.de> + * Copyright (C) 2012 Antti Palosaari <crope@iki.fi> + * + * 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "dvb_usb_common.h" + +int dvb_usbv2_generic_rw(struct dvb_usb_device *d, u8 *wbuf, u16 wlen, u8 *rbuf, + u16 rlen) +{ + int ret, actual_length; + + if (!d || !wbuf || !wlen || !d->props->generic_bulk_ctrl_endpoint || + !d->props->generic_bulk_ctrl_endpoint_response) { + dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, -EINVAL); + return -EINVAL; + } + + ret = mutex_lock_interruptible(&d->usb_mutex); + if (ret < 0) + return ret; + + dev_dbg(&d->udev->dev, "%s: >>> %*ph\n", __func__, wlen, wbuf); + + ret = usb_bulk_msg(d->udev, usb_sndbulkpipe(d->udev, + d->props->generic_bulk_ctrl_endpoint), wbuf, wlen, + &actual_length, 2000); + if (ret < 0) + dev_err(&d->udev->dev, "%s: usb_bulk_msg() failed=%d\n", + KBUILD_MODNAME, ret); + else + ret = actual_length != wlen ? -EIO : 0; + + /* an answer is expected, and no error before */ + if (!ret && rbuf && rlen) { + if (d->props->generic_bulk_ctrl_delay) + usleep_range(d->props->generic_bulk_ctrl_delay, + d->props->generic_bulk_ctrl_delay + + 20000); + + ret = usb_bulk_msg(d->udev, usb_rcvbulkpipe(d->udev, + d->props->generic_bulk_ctrl_endpoint_response), + rbuf, rlen, &actual_length, 2000); + if (ret) + dev_err(&d->udev->dev, "%s: 2nd usb_bulk_msg() " \ + "failed=%d\n", KBUILD_MODNAME, ret); + + dev_dbg(&d->udev->dev, "%s: <<< %*ph\n", __func__, + actual_length, rbuf); + } + + mutex_unlock(&d->usb_mutex); + return ret; +} +EXPORT_SYMBOL(dvb_usbv2_generic_rw); + +int dvb_usbv2_generic_write(struct dvb_usb_device *d, u8 *buf, u16 len) +{ + return dvb_usbv2_generic_rw(d, buf, len, NULL, 0); +} +EXPORT_SYMBOL(dvb_usbv2_generic_write); diff --git a/drivers/media/dvb/dvb-usb/ec168.c b/drivers/media/usb/dvb-usb-v2/ec168.c index b4989ba8897d..5c68f3918bc8 100644 --- a/drivers/media/dvb/dvb-usb/ec168.c +++ b/drivers/media/usb/dvb-usb-v2/ec168.c @@ -23,23 +23,15 @@ #include "ec100.h" #include "mxl5005s.h" -/* debug */ -static int dvb_usb_ec168_debug; -module_param_named(debug, dvb_usb_ec168_debug, int, 0644); -MODULE_PARM_DESC(debug, "set debugging level" DVB_USB_DEBUG_STATUS); DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); -static struct ec100_config ec168_ec100_config; - -static int ec168_rw_udev(struct usb_device *udev, struct ec168_req *req) +static int ec168_ctrl_msg(struct dvb_usb_device *d, struct ec168_req *req) { int ret; unsigned int pipe; u8 request, requesttype; u8 *buf; - - switch (req->cmd) { case DOWNLOAD_FIRMWARE: case GPIO: @@ -69,8 +61,9 @@ static int ec168_rw_udev(struct usb_device *udev, struct ec168_req *req) request = DEMOD_RW; break; default: - err("unknown command:%02x", req->cmd); - ret = -EPERM; + dev_err(&d->udev->dev, "%s: unknown command=%02x\n", + KBUILD_MODNAME, req->cmd); + ret = -EINVAL; goto error; } @@ -83,19 +76,19 @@ static int ec168_rw_udev(struct usb_device *udev, struct ec168_req *req) if (requesttype == (USB_TYPE_VENDOR | USB_DIR_OUT)) { /* write */ memcpy(buf, req->data, req->size); - pipe = usb_sndctrlpipe(udev, 0); + pipe = usb_sndctrlpipe(d->udev, 0); } else { /* read */ - pipe = usb_rcvctrlpipe(udev, 0); + pipe = usb_rcvctrlpipe(d->udev, 0); } msleep(1); /* avoid I2C errors */ - ret = usb_control_msg(udev, pipe, request, requesttype, req->value, + ret = usb_control_msg(d->udev, pipe, request, requesttype, req->value, req->index, buf, req->size, EC168_USB_TIMEOUT); - ec168_debug_dump(request, requesttype, req->value, req->index, buf, - req->size, deb_xfer); + dvb_usb_dbg_usb_control_msg(d->udev, request, requesttype, req->value, + req->index, buf, req->size); if (ret < 0) goto err_dealloc; @@ -112,16 +105,13 @@ static int ec168_rw_udev(struct usb_device *udev, struct ec168_req *req) err_dealloc: kfree(buf); error: - deb_info("%s: failed:%d\n", __func__, ret); + dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); return ret; } -static int ec168_ctrl_msg(struct dvb_usb_device *d, struct ec168_req *req) -{ - return ec168_rw_udev(d->udev, req); -} - /* I2C */ +static struct ec100_config ec168_ec100_config; + static int ec168_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], int num) { @@ -147,8 +137,10 @@ static int ec168_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], ret = ec168_ctrl_msg(d, &req); i += 2; } else { - err("I2C read not implemented"); - ret = -ENOSYS; + dev_err(&d->udev->dev, "%s: I2C read not " \ + "implemented\n", + KBUILD_MODNAME); + ret = -EOPNOTSUPP; i += 2; } } else { @@ -181,7 +173,6 @@ error: return i; } - static u32 ec168_i2c_func(struct i2c_adapter *adapter) { return I2C_FUNC_I2C; @@ -193,88 +184,63 @@ static struct i2c_algorithm ec168_i2c_algo = { }; /* Callbacks for DVB USB */ -static struct ec100_config ec168_ec100_config = { - .demod_address = 0xff, /* not real address, demod is integrated */ -}; - -static int ec168_ec100_frontend_attach(struct dvb_usb_adapter *adap) +static int ec168_identify_state(struct dvb_usb_device *d, const char **name) { - deb_info("%s:\n", __func__); - adap->fe_adap[0].fe = dvb_attach(ec100_attach, &ec168_ec100_config, - &adap->dev->i2c_adap); - if (adap->fe_adap[0].fe == NULL) - return -ENODEV; + int ret; + u8 reply; + struct ec168_req req = {GET_CONFIG, 0, 1, sizeof(reply), &reply}; + dev_dbg(&d->udev->dev, "%s:\n", __func__); - return 0; -} + ret = ec168_ctrl_msg(d, &req); + if (ret) + goto error; -static struct mxl5005s_config ec168_mxl5003s_config = { - .i2c_address = 0xc6, - .if_freq = IF_FREQ_4570000HZ, - .xtal_freq = CRYSTAL_FREQ_16000000HZ, - .agc_mode = MXL_SINGLE_AGC, - .tracking_filter = MXL_TF_OFF, - .rssi_enable = MXL_RSSI_ENABLE, - .cap_select = MXL_CAP_SEL_ENABLE, - .div_out = MXL_DIV_OUT_4, - .clock_out = MXL_CLOCK_OUT_DISABLE, - .output_load = MXL5005S_IF_OUTPUT_LOAD_200_OHM, - .top = MXL5005S_TOP_25P2, - .mod_mode = MXL_DIGITAL_MODE, - .if_mode = MXL_ZERO_IF, - .AgcMasterByte = 0x00, -}; + dev_dbg(&d->udev->dev, "%s: reply=%02x\n", __func__, reply); -static int ec168_mxl5003s_tuner_attach(struct dvb_usb_adapter *adap) -{ - deb_info("%s:\n", __func__); - return dvb_attach(mxl5005s_attach, adap->fe_adap[0].fe, &adap->dev->i2c_adap, - &ec168_mxl5003s_config) == NULL ? -ENODEV : 0; -} + if (reply == 0x01) + ret = WARM; + else + ret = COLD; -static int ec168_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) -{ - struct ec168_req req = {STREAMING_CTRL, 0x7f01, 0x0202, 0, NULL}; - deb_info("%s: onoff:%d\n", __func__, onoff); - if (onoff) - req.index = 0x0102; - return ec168_ctrl_msg(adap->dev, &req); + return ret; +error: + dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); + return ret; } -static int ec168_download_firmware(struct usb_device *udev, - const struct firmware *fw) +static int ec168_download_firmware(struct dvb_usb_device *d, + const struct firmware *fw) { - int i, len, packets, remainder, ret; - u16 addr = 0x0000; /* firmware start address */ + int ret, len, remaining; struct ec168_req req = {DOWNLOAD_FIRMWARE, 0, 0, 0, NULL}; - deb_info("%s:\n", __func__); + dev_dbg(&d->udev->dev, "%s:\n", __func__); - #define FW_PACKET_MAX_DATA 2048 - packets = fw->size / FW_PACKET_MAX_DATA; - remainder = fw->size % FW_PACKET_MAX_DATA; - len = FW_PACKET_MAX_DATA; - for (i = 0; i <= packets; i++) { - if (i == packets) /* set size of the last packet */ - len = remainder; + #define LEN_MAX 2048 /* max packet size */ + for (remaining = fw->size; remaining > 0; remaining -= LEN_MAX) { + len = remaining; + if (len > LEN_MAX) + len = LEN_MAX; req.size = len; - req.data = (u8 *)(fw->data + i * FW_PACKET_MAX_DATA); - req.index = addr; - addr += FW_PACKET_MAX_DATA; + req.data = (u8 *) &fw->data[fw->size - remaining]; + req.index = fw->size - remaining; - ret = ec168_rw_udev(udev, &req); + ret = ec168_ctrl_msg(d, &req); if (ret) { - err("firmware download failed:%d packet:%d", ret, i); + dev_err(&d->udev->dev, + "%s: firmware download failed=%d\n", + KBUILD_MODNAME, ret); goto error; } } + req.size = 0; /* set "warm"? */ req.cmd = SET_CONFIG; req.value = 0; req.index = 0x0001; - ret = ec168_rw_udev(udev, &req); + ret = ec168_ctrl_msg(d, &req); if (ret) goto error; @@ -282,7 +248,7 @@ static int ec168_download_firmware(struct usb_device *udev, req.cmd = GPIO; req.value = 0; req.index = 0x0206; - ret = ec168_rw_udev(udev, &req); + ret = ec168_ctrl_msg(d, &req); if (ret) goto error; @@ -290,146 +256,130 @@ static int ec168_download_firmware(struct usb_device *udev, req.cmd = WRITE_I2C; req.value = 0; req.index = 0x00c6; - ret = ec168_rw_udev(udev, &req); + ret = ec168_ctrl_msg(d, &req); if (ret) goto error; return ret; error: - deb_info("%s: failed:%d\n", __func__, ret); + dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); return ret; } -static int ec168_identify_state(struct usb_device *udev, - struct dvb_usb_device_properties *props, - struct dvb_usb_device_description **desc, int *cold) -{ - int ret; - u8 reply; - struct ec168_req req = {GET_CONFIG, 0, 1, sizeof(reply), &reply}; - deb_info("%s:\n", __func__); - - ret = ec168_rw_udev(udev, &req); - if (ret) - goto error; +static struct ec100_config ec168_ec100_config = { + .demod_address = 0xff, /* not real address, demod is integrated */ +}; - deb_info("%s: reply:%02x\n", __func__, reply); +static int ec168_ec100_frontend_attach(struct dvb_usb_adapter *adap) +{ + struct dvb_usb_device *d = adap_to_d(adap); + dev_dbg(&d->udev->dev, "%s:\n", __func__); - if (reply == 0x01) - *cold = 0; - else - *cold = 1; + adap->fe[0] = dvb_attach(ec100_attach, &ec168_ec100_config, + &d->i2c_adap); + if (adap->fe[0] == NULL) + return -ENODEV; - return ret; -error: - deb_info("%s: failed:%d\n", __func__, ret); - return ret; + return 0; } -/* DVB USB Driver stuff */ -static struct dvb_usb_device_properties ec168_properties; +static struct mxl5005s_config ec168_mxl5003s_config = { + .i2c_address = 0xc6, + .if_freq = IF_FREQ_4570000HZ, + .xtal_freq = CRYSTAL_FREQ_16000000HZ, + .agc_mode = MXL_SINGLE_AGC, + .tracking_filter = MXL_TF_OFF, + .rssi_enable = MXL_RSSI_ENABLE, + .cap_select = MXL_CAP_SEL_ENABLE, + .div_out = MXL_DIV_OUT_4, + .clock_out = MXL_CLOCK_OUT_DISABLE, + .output_load = MXL5005S_IF_OUTPUT_LOAD_200_OHM, + .top = MXL5005S_TOP_25P2, + .mod_mode = MXL_DIGITAL_MODE, + .if_mode = MXL_ZERO_IF, + .AgcMasterByte = 0x00, +}; -static int ec168_probe(struct usb_interface *intf, - const struct usb_device_id *id) +static int ec168_mxl5003s_tuner_attach(struct dvb_usb_adapter *adap) { - int ret; - deb_info("%s: interface:%d\n", __func__, - intf->cur_altsetting->desc.bInterfaceNumber); - - ret = dvb_usb_device_init(intf, &ec168_properties, THIS_MODULE, NULL, - adapter_nr); - if (ret) - goto error; + struct dvb_usb_device *d = adap_to_d(adap); + dev_dbg(&d->udev->dev, "%s:\n", __func__); - return ret; -error: - deb_info("%s: failed:%d\n", __func__, ret); - return ret; + return dvb_attach(mxl5005s_attach, adap->fe[0], &d->i2c_adap, + &ec168_mxl5003s_config) == NULL ? -ENODEV : 0; } -#define E3C_EC168_1689 0 -#define E3C_EC168_FFFA 1 -#define E3C_EC168_FFFB 2 -#define E3C_EC168_1001 3 -#define E3C_EC168_1002 4 - -static struct usb_device_id ec168_id[] = { - [E3C_EC168_1689] = - {USB_DEVICE(USB_VID_E3C, USB_PID_E3C_EC168)}, - [E3C_EC168_FFFA] = - {USB_DEVICE(USB_VID_E3C, USB_PID_E3C_EC168_2)}, - [E3C_EC168_FFFB] = - {USB_DEVICE(USB_VID_E3C, USB_PID_E3C_EC168_3)}, - [E3C_EC168_1001] = - {USB_DEVICE(USB_VID_E3C, USB_PID_E3C_EC168_4)}, - [E3C_EC168_1002] = - {USB_DEVICE(USB_VID_E3C, USB_PID_E3C_EC168_5)}, - {} /* terminating entry */ -}; +static int ec168_streaming_ctrl(struct dvb_frontend *fe, int onoff) +{ + struct dvb_usb_device *d = fe_to_d(fe); + struct ec168_req req = {STREAMING_CTRL, 0x7f01, 0x0202, 0, NULL}; + dev_dbg(&d->udev->dev, "%s: onoff=%d\n", __func__, onoff); -MODULE_DEVICE_TABLE(usb, ec168_id); + if (onoff) + req.index = 0x0102; + return ec168_ctrl_msg(d, &req); +} -static struct dvb_usb_device_properties ec168_properties = { - .caps = DVB_USB_IS_AN_I2C_ADAPTER, +/* DVB USB Driver stuff */ +/* bInterfaceNumber 0 is HID + * bInterfaceNumber 1 is DVB-T */ +static struct dvb_usb_device_properties ec168_props = { + .driver_name = KBUILD_MODNAME, + .owner = THIS_MODULE, + .adapter_nr = adapter_nr, + .bInterfaceNumber = 1, - .usb_ctrl = DEVICE_SPECIFIC, + .identify_state = ec168_identify_state, + .firmware = EC168_FIRMWARE, .download_firmware = ec168_download_firmware, - .firmware = "dvb-usb-ec168.fw", - .no_reconnect = 1, - .size_of_priv = 0, + .i2c_algo = &ec168_i2c_algo, + .frontend_attach = ec168_ec100_frontend_attach, + .tuner_attach = ec168_mxl5003s_tuner_attach, + .streaming_ctrl = ec168_streaming_ctrl, .num_adapters = 1, .adapter = { { - .num_frontends = 1, - .fe = {{ - .streaming_ctrl = ec168_streaming_ctrl, - .frontend_attach = ec168_ec100_frontend_attach, - .tuner_attach = ec168_mxl5003s_tuner_attach, - .stream = { - .type = USB_BULK, - .count = 6, - .endpoint = 0x82, - .u = { - .bulk = { - .buffersize = (32*512), - } - } - }, - }}, + .stream = DVB_USB_STREAM_BULK(0x82, 6, 32 * 512), } }, +}; - .identify_state = ec168_identify_state, - - .i2c_algo = &ec168_i2c_algo, +static const struct dvb_usb_driver_info ec168_driver_info = { + .name = "E3C EC168 reference design", + .props = &ec168_props, +}; - .num_device_descs = 1, - .devices = { - { - .name = "E3C EC168 DVB-T USB2.0 reference design", - .cold_ids = { - &ec168_id[E3C_EC168_1689], - &ec168_id[E3C_EC168_FFFA], - &ec168_id[E3C_EC168_FFFB], - &ec168_id[E3C_EC168_1001], - &ec168_id[E3C_EC168_1002], - NULL}, - .warm_ids = {NULL}, - }, - } +static const struct usb_device_id ec168_id[] = { + { USB_DEVICE(USB_VID_E3C, USB_PID_E3C_EC168), + .driver_info = (kernel_ulong_t) &ec168_driver_info }, + { USB_DEVICE(USB_VID_E3C, USB_PID_E3C_EC168_2), + .driver_info = (kernel_ulong_t) &ec168_driver_info }, + { USB_DEVICE(USB_VID_E3C, USB_PID_E3C_EC168_3), + .driver_info = (kernel_ulong_t) &ec168_driver_info }, + { USB_DEVICE(USB_VID_E3C, USB_PID_E3C_EC168_4), + .driver_info = (kernel_ulong_t) &ec168_driver_info }, + { USB_DEVICE(USB_VID_E3C, USB_PID_E3C_EC168_5), + .driver_info = (kernel_ulong_t) &ec168_driver_info }, + {} }; +MODULE_DEVICE_TABLE(usb, ec168_id); static struct usb_driver ec168_driver = { - .name = "dvb_usb_ec168", - .probe = ec168_probe, - .disconnect = dvb_usb_device_exit, - .id_table = ec168_id, + .name = KBUILD_MODNAME, + .id_table = ec168_id, + .probe = dvb_usbv2_probe, + .disconnect = dvb_usbv2_disconnect, + .suspend = dvb_usbv2_suspend, + .resume = dvb_usbv2_resume, + .no_dynamic_id = 1, + .soft_unbind = 1, }; module_usb_driver(ec168_driver); MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>"); -MODULE_DESCRIPTION("E3C EC168 DVB-T USB2.0 driver"); +MODULE_DESCRIPTION("E3C EC168 driver"); MODULE_LICENSE("GPL"); +MODULE_FIRMWARE(EC168_FIRMWARE); diff --git a/drivers/media/dvb/dvb-usb/ec168.h b/drivers/media/usb/dvb-usb-v2/ec168.h index e7e0b831314e..615a6569421f 100644 --- a/drivers/media/dvb/dvb-usb/ec168.h +++ b/drivers/media/usb/dvb-usb-v2/ec168.h @@ -22,30 +22,10 @@ #ifndef EC168_H #define EC168_H -#define DVB_USB_LOG_PREFIX "ec168" -#include "dvb-usb.h" - -#define deb_info(args...) dprintk(dvb_usb_ec168_debug, 0x01, args) -#define deb_rc(args...) dprintk(dvb_usb_ec168_debug, 0x02, args) -#define deb_xfer(args...) dprintk(dvb_usb_ec168_debug, 0x04, args) -#define deb_reg(args...) dprintk(dvb_usb_ec168_debug, 0x08, args) -#define deb_i2c(args...) dprintk(dvb_usb_ec168_debug, 0x10, args) -#define deb_fw(args...) dprintk(dvb_usb_ec168_debug, 0x20, args) - -#define ec168_debug_dump(r, t, v, i, b, l, func) { \ - int loop_; \ - func("%02x %02x %02x %02x %02x %02x %02x %02x", \ - t, r, v & 0xff, v >> 8, i & 0xff, i >> 8, l & 0xff, l >> 8); \ - if (t == (USB_TYPE_VENDOR | USB_DIR_OUT)) \ - func(" >>> "); \ - else \ - func(" <<< "); \ - for (loop_ = 0; loop_ < l; loop_++) \ - func("%02x ", b[loop_]); \ - func("\n");\ -} +#include "dvb_usb.h" #define EC168_USB_TIMEOUT 1000 +#define EC168_FIRMWARE "dvb-usb-ec168.fw" struct ec168_req { u8 cmd; /* [1] */ diff --git a/drivers/media/dvb/dvb-usb/gl861.c b/drivers/media/usb/dvb-usb-v2/gl861.c index c1f5582e1cdf..b1b09c547861 100644 --- a/drivers/media/dvb/dvb-usb/gl861.c +++ b/drivers/media/usb/dvb-usb-v2/gl861.c @@ -11,11 +11,6 @@ #include "zl10353.h" #include "qt1010.h" -/* debug */ -static int dvb_usb_gl861_debug; -module_param_named(debug, dvb_usb_gl861_debug, int, 0644); -MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." - DVB_USB_DEBUG_STATUS); DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); static int gl861_i2c_msg(struct dvb_usb_device *d, u8 addr, @@ -43,7 +38,8 @@ static int gl861_i2c_msg(struct dvb_usb_device *d, u8 addr, value = value + wbuf[1]; break; default: - warn("wlen = %x, aborting.", wlen); + dev_err(&d->udev->dev, "%s: wlen=%d, aborting\n", + KBUILD_MODNAME, wlen); return -EINVAL; } @@ -103,9 +99,9 @@ static struct zl10353_config gl861_zl10353_config = { static int gl861_frontend_attach(struct dvb_usb_adapter *adap) { - adap->fe_adap[0].fe = dvb_attach(zl10353_attach, &gl861_zl10353_config, - &adap->dev->i2c_adap); - if (adap->fe_adap[0].fe == NULL) + adap->fe[0] = dvb_attach(zl10353_attach, &gl861_zl10353_config, + &adap_to_d(adap)->i2c_adap); + if (adap->fe[0] == NULL) return -EIO; return 0; @@ -118,98 +114,62 @@ static struct qt1010_config gl861_qt1010_config = { static int gl861_tuner_attach(struct dvb_usb_adapter *adap) { return dvb_attach(qt1010_attach, - adap->fe_adap[0].fe, &adap->dev->i2c_adap, + adap->fe[0], &adap_to_d(adap)->i2c_adap, &gl861_qt1010_config) == NULL ? -ENODEV : 0; } -/* DVB USB Driver stuff */ -static struct dvb_usb_device_properties gl861_properties; - -static int gl861_probe(struct usb_interface *intf, - const struct usb_device_id *id) +static int gl861_init(struct dvb_usb_device *d) { - struct dvb_usb_device *d; - struct usb_host_interface *alt; - int ret; - - if (intf->num_altsetting < 2) - return -ENODEV; - - ret = dvb_usb_device_init(intf, &gl861_properties, THIS_MODULE, &d, - adapter_nr); - if (ret == 0) { - alt = usb_altnum_to_altsetting(intf, 0); - - if (alt == NULL) { - deb_rc("not alt found!\n"); - return -ENODEV; - } - - ret = usb_set_interface(d->udev, alt->desc.bInterfaceNumber, - alt->desc.bAlternateSetting); - } - - return ret; + /* + * There is 2 interfaces. Interface 0 is for TV and interface 1 is + * for HID remote controller. Interface 0 has 2 alternate settings. + * For some reason we need to set interface explicitly, defaulted + * as alternate setting 1? + */ + return usb_set_interface(d->udev, 0, 0); } -static struct usb_device_id gl861_table [] = { - { USB_DEVICE(USB_VID_MSI, USB_PID_MSI_MEGASKY580_55801) }, - { USB_DEVICE(USB_VID_ALINK, USB_VID_ALINK_DTU) }, - { } /* Terminating entry */ -}; -MODULE_DEVICE_TABLE(usb, gl861_table); - -static struct dvb_usb_device_properties gl861_properties = { - .caps = DVB_USB_IS_AN_I2C_ADAPTER, - .usb_ctrl = DEVICE_SPECIFIC, +/* DVB USB Driver stuff */ +static struct dvb_usb_device_properties gl861_props = { + .driver_name = KBUILD_MODNAME, + .owner = THIS_MODULE, + .adapter_nr = adapter_nr, - .size_of_priv = 0, + .i2c_algo = &gl861_i2c_algo, + .frontend_attach = gl861_frontend_attach, + .tuner_attach = gl861_tuner_attach, + .init = gl861_init, .num_adapters = 1, - .adapter = {{ - .num_frontends = 1, - .fe = {{ - - .frontend_attach = gl861_frontend_attach, - .tuner_attach = gl861_tuner_attach, - - .stream = { - .type = USB_BULK, - .count = 7, - .endpoint = 0x81, - .u = { - .bulk = { - .buffersize = 512, - } - } - }, - }}, - } }, - .i2c_algo = &gl861_i2c_algo, - - .num_device_descs = 2, - .devices = { + .adapter = { { - .name = "MSI Mega Sky 55801 DVB-T USB2.0", - .cold_ids = { NULL }, - .warm_ids = { &gl861_table[0], NULL }, - }, - { - .name = "A-LINK DTU DVB-T USB2.0", - .cold_ids = { NULL }, - .warm_ids = { &gl861_table[1], NULL }, - }, + .stream = DVB_USB_STREAM_BULK(0x81, 7, 512), + } } }; -static struct usb_driver gl861_driver = { - .name = "dvb_usb_gl861", - .probe = gl861_probe, - .disconnect = dvb_usb_device_exit, - .id_table = gl861_table, +static const struct usb_device_id gl861_id_table[] = { + { DVB_USB_DEVICE(USB_VID_MSI, USB_PID_MSI_MEGASKY580_55801, + &gl861_props, "MSI Mega Sky 55801 DVB-T USB2.0", NULL) }, + { DVB_USB_DEVICE(USB_VID_ALINK, USB_VID_ALINK_DTU, + &gl861_props, "A-LINK DTU DVB-T USB2.0", NULL) }, + { } +}; +MODULE_DEVICE_TABLE(usb, gl861_id_table); + +static struct usb_driver gl861_usb_driver = { + .name = KBUILD_MODNAME, + .id_table = gl861_id_table, + .probe = dvb_usbv2_probe, + .disconnect = dvb_usbv2_disconnect, + .suspend = dvb_usbv2_suspend, + .resume = dvb_usbv2_resume, + .reset_resume = dvb_usbv2_reset_resume, + .no_dynamic_id = 1, + .soft_unbind = 1, }; -module_usb_driver(gl861_driver); +module_usb_driver(gl861_usb_driver); MODULE_AUTHOR("Carl Lundqvist <comabug@gmail.com>"); MODULE_DESCRIPTION("Driver MSI Mega Sky 580 DVB-T USB2.0 / GL861"); diff --git a/drivers/media/dvb/dvb-usb/gl861.h b/drivers/media/usb/dvb-usb-v2/gl861.h index c54855e2c233..b0b80d87bb7e 100644 --- a/drivers/media/dvb/dvb-usb/gl861.h +++ b/drivers/media/usb/dvb-usb-v2/gl861.h @@ -1,10 +1,7 @@ #ifndef _DVB_USB_GL861_H_ #define _DVB_USB_GL861_H_ -#define DVB_USB_LOG_PREFIX "gl861" -#include "dvb-usb.h" - -#define deb_rc(args...) dprintk(dvb_usb_gl861_debug, 0x01, args) +#include "dvb_usb.h" #define GL861_WRITE 0x40 #define GL861_READ 0xc0 diff --git a/drivers/media/usb/dvb-usb-v2/it913x.c b/drivers/media/usb/dvb-usb-v2/it913x.c new file mode 100644 index 000000000000..695f9106bc54 --- /dev/null +++ b/drivers/media/usb/dvb-usb-v2/it913x.c @@ -0,0 +1,799 @@ +/* + * DVB USB compliant linux driver for ITE IT9135 and IT9137 + * + * Copyright (C) 2011 Malcolm Priestley (tvboxspy@gmail.com) + * IT9135 (C) ITE Tech Inc. + * IT9137 (C) ITE Tech Inc. + * + * 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. + * + * 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. + * + * + * see Documentation/dvb/README.dvb-usb for more information + * see Documentation/dvb/it9137.txt for firmware information + * + */ +#define DVB_USB_LOG_PREFIX "it913x" + +#include <linux/usb.h> +#include <linux/usb/input.h> +#include <media/rc-core.h> + +#include "dvb_usb.h" +#include "it913x-fe.h" + +/* debug */ +static int dvb_usb_it913x_debug; +#define it_debug(var, level, args...) \ + do { if ((var & level)) pr_debug(DVB_USB_LOG_PREFIX": " args); \ +} while (0) +#define deb_info(level, args...) it_debug(dvb_usb_it913x_debug, level, args) +#define info(args...) pr_info(DVB_USB_LOG_PREFIX": " args) + +module_param_named(debug, dvb_usb_it913x_debug, int, 0644); +MODULE_PARM_DESC(debug, "set debugging level (1=info (or-able))."); + +static int dvb_usb_it913x_firmware; +module_param_named(firmware, dvb_usb_it913x_firmware, int, 0644); +MODULE_PARM_DESC(firmware, "set firmware 0=auto"\ + "1=IT9137 2=IT9135 V1 3=IT9135 V2"); +#define FW_IT9137 "dvb-usb-it9137-01.fw" +#define FW_IT9135_V1 "dvb-usb-it9135-01.fw" +#define FW_IT9135_V2 "dvb-usb-it9135-02.fw" + +DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); + +struct it913x_state { + struct ite_config it913x_config; + u8 pid_filter_onoff; + bool proprietary_ir; + int cmd_counter; +}; + +static u16 check_sum(u8 *p, u8 len) +{ + u16 sum = 0; + u8 i = 1; + while (i < len) + sum += (i++ & 1) ? (*p++) << 8 : *p++; + return ~sum; +} + +static int it913x_io(struct dvb_usb_device *d, u8 mode, u8 pro, + u8 cmd, u32 reg, u8 addr, u8 *data, u8 len) +{ + struct it913x_state *st = d->priv; + int ret = 0, i, buf_size = 1; + u8 *buff; + u8 rlen; + u16 chk_sum; + + buff = kzalloc(256, GFP_KERNEL); + if (!buff) { + info("USB Buffer Failed"); + return -ENOMEM; + } + + buff[buf_size++] = pro; + buff[buf_size++] = cmd; + buff[buf_size++] = st->cmd_counter; + + switch (mode) { + case READ_LONG: + case WRITE_LONG: + buff[buf_size++] = len; + buff[buf_size++] = 2; + buff[buf_size++] = (reg >> 24); + buff[buf_size++] = (reg >> 16) & 0xff; + buff[buf_size++] = (reg >> 8) & 0xff; + buff[buf_size++] = reg & 0xff; + break; + case READ_SHORT: + buff[buf_size++] = addr; + break; + case WRITE_SHORT: + buff[buf_size++] = len; + buff[buf_size++] = addr; + buff[buf_size++] = (reg >> 8) & 0xff; + buff[buf_size++] = reg & 0xff; + break; + case READ_DATA: + case WRITE_DATA: + break; + case WRITE_CMD: + mode = 7; + break; + default: + kfree(buff); + return -EINVAL; + } + + if (mode & 1) { + for (i = 0; i < len ; i++) + buff[buf_size++] = data[i]; + } + chk_sum = check_sum(&buff[1], buf_size); + + buff[buf_size++] = chk_sum >> 8; + buff[0] = buf_size; + buff[buf_size++] = (chk_sum & 0xff); + + ret = dvb_usbv2_generic_rw(d, buff, buf_size, buff, (mode & 1) ? + 5 : len + 5); + if (ret < 0) + goto error; + + rlen = (mode & 0x1) ? 0x1 : len; + + if (mode & 1) + ret = buff[2]; + else + memcpy(data, &buff[3], rlen); + + st->cmd_counter++; + +error: kfree(buff); + + return ret; +} + +static int it913x_wr_reg(struct dvb_usb_device *d, u8 pro, u32 reg , u8 data) +{ + int ret; + u8 b[1]; + b[0] = data; + ret = it913x_io(d, WRITE_LONG, pro, + CMD_DEMOD_WRITE, reg, 0, b, sizeof(b)); + + return ret; +} + +static int it913x_read_reg(struct dvb_usb_device *d, u32 reg) +{ + int ret; + u8 data[1]; + + ret = it913x_io(d, READ_LONG, DEV_0, + CMD_DEMOD_READ, reg, 0, &data[0], sizeof(data)); + + return (ret < 0) ? ret : data[0]; +} + +static int it913x_query(struct dvb_usb_device *d, u8 pro) +{ + struct it913x_state *st = d->priv; + int ret, i; + u8 data[4]; + u8 ver; + + for (i = 0; i < 5; i++) { + ret = it913x_io(d, READ_LONG, pro, CMD_DEMOD_READ, + 0x1222, 0, &data[0], 3); + ver = data[0]; + if (ver > 0 && ver < 3) + break; + msleep(100); + } + + if (ver < 1 || ver > 2) { + info("Failed to identify chip version applying 1"); + st->it913x_config.chip_ver = 0x1; + st->it913x_config.chip_type = 0x9135; + return 0; + } + + st->it913x_config.chip_ver = ver; + st->it913x_config.chip_type = (u16)(data[2] << 8) + data[1]; + + info("Chip Version=%02x Chip Type=%04x", st->it913x_config.chip_ver, + st->it913x_config.chip_type); + + ret = it913x_io(d, READ_SHORT, pro, + CMD_QUERYINFO, 0, 0x1, &data[0], 4); + + st->it913x_config.firmware = (data[0] << 24) | (data[1] << 16) | + (data[2] << 8) | data[3]; + + return ret; +} + +static int it913x_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff) +{ + struct dvb_usb_device *d = adap_to_d(adap); + struct it913x_state *st = adap_to_priv(adap); + int ret; + u8 pro = (adap->id == 0) ? DEV_0_DMOD : DEV_1_DMOD; + + mutex_lock(&d->i2c_mutex); + + deb_info(1, "PID_C (%02x)", onoff); + + ret = it913x_wr_reg(d, pro, PID_EN, st->pid_filter_onoff); + + mutex_unlock(&d->i2c_mutex); + return ret; +} + +static int it913x_pid_filter(struct dvb_usb_adapter *adap, + int index, u16 pid, int onoff) +{ + struct dvb_usb_device *d = adap_to_d(adap); + struct it913x_state *st = adap_to_priv(adap); + int ret; + u8 pro = (adap->id == 0) ? DEV_0_DMOD : DEV_1_DMOD; + + mutex_lock(&d->i2c_mutex); + + deb_info(1, "PID_F (%02x)", onoff); + + ret = it913x_wr_reg(d, pro, PID_LSB, (u8)(pid & 0xff)); + + ret |= it913x_wr_reg(d, pro, PID_MSB, (u8)(pid >> 8)); + + ret |= it913x_wr_reg(d, pro, PID_INX_EN, (u8)onoff); + + ret |= it913x_wr_reg(d, pro, PID_INX, (u8)(index & 0x1f)); + + if (d->udev->speed == USB_SPEED_HIGH && pid == 0x2000) { + ret |= it913x_wr_reg(d , pro, PID_EN, !onoff); + st->pid_filter_onoff = !onoff; + } else + st->pid_filter_onoff = + adap->pid_filtering; + + mutex_unlock(&d->i2c_mutex); + return 0; +} + + +static int it913x_return_status(struct dvb_usb_device *d) +{ + struct it913x_state *st = d->priv; + int ret = it913x_query(d, DEV_0); + if (st->it913x_config.firmware > 0) + info("Firmware Version %d", st->it913x_config.firmware); + + return ret; +} + +static int it913x_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], + int num) +{ + struct dvb_usb_device *d = i2c_get_adapdata(adap); + static u8 data[256]; + int ret; + u32 reg; + u8 pro; + + mutex_lock(&d->i2c_mutex); + + deb_info(2, "num of messages %d address %02x", num, msg[0].addr); + + pro = (msg[0].addr & 0x2) ? DEV_0_DMOD : 0x0; + pro |= (msg[0].addr & 0x20) ? DEV_1 : DEV_0; + memcpy(data, msg[0].buf, msg[0].len); + reg = (data[0] << 24) + (data[1] << 16) + + (data[2] << 8) + data[3]; + if (num == 2) { + ret = it913x_io(d, READ_LONG, pro, + CMD_DEMOD_READ, reg, 0, data, msg[1].len); + memcpy(msg[1].buf, data, msg[1].len); + } else + ret = it913x_io(d, WRITE_LONG, pro, CMD_DEMOD_WRITE, + reg, 0, &data[4], msg[0].len - 4); + + mutex_unlock(&d->i2c_mutex); + + return ret; +} + +static u32 it913x_i2c_func(struct i2c_adapter *adapter) +{ + return I2C_FUNC_I2C; +} + +static struct i2c_algorithm it913x_i2c_algo = { + .master_xfer = it913x_i2c_xfer, + .functionality = it913x_i2c_func, +}; + +/* Callbacks for DVB USB */ +#define IT913X_POLL 250 +static int it913x_rc_query(struct dvb_usb_device *d) +{ + u8 ibuf[4]; + int ret; + u32 key; + /* Avoid conflict with frontends*/ + mutex_lock(&d->i2c_mutex); + + ret = it913x_io(d, READ_LONG, PRO_LINK, CMD_IR_GET, + 0, 0, &ibuf[0], sizeof(ibuf)); + + if ((ibuf[2] + ibuf[3]) == 0xff) { + key = ibuf[2]; + key += ibuf[0] << 16; + key += ibuf[1] << 8; + deb_info(1, "NEC Extended Key =%08x", key); + if (d->rc_dev != NULL) + rc_keydown(d->rc_dev, key, 0); + } + + mutex_unlock(&d->i2c_mutex); + + return ret; +} + +/* Firmware sets raw */ +static const char fw_it9135_v1[] = FW_IT9135_V1; +static const char fw_it9135_v2[] = FW_IT9135_V2; +static const char fw_it9137[] = FW_IT9137; + +static void ite_get_firmware_name(struct dvb_usb_device *d, + const char **name) +{ + struct it913x_state *st = d->priv; + int sw; + /* auto switch */ + if (le16_to_cpu(d->udev->descriptor.idVendor) == USB_VID_KWORLD_2) + sw = IT9137_FW; + else if (st->it913x_config.chip_ver == 1) + sw = IT9135_V1_FW; + else + sw = IT9135_V2_FW; + + /* force switch */ + if (dvb_usb_it913x_firmware != IT9135_AUTO) + sw = dvb_usb_it913x_firmware; + + switch (sw) { + case IT9135_V1_FW: + st->it913x_config.firmware_ver = 1; + st->it913x_config.adc_x2 = 1; + st->it913x_config.read_slevel = false; + *name = fw_it9135_v1; + break; + case IT9135_V2_FW: + st->it913x_config.firmware_ver = 1; + st->it913x_config.adc_x2 = 1; + st->it913x_config.read_slevel = false; + *name = fw_it9135_v2; + switch (st->it913x_config.tuner_id_0) { + case IT9135_61: + case IT9135_62: + break; + default: + info("Unknown tuner ID applying default 0x60"); + case IT9135_60: + st->it913x_config.tuner_id_0 = IT9135_60; + } + break; + case IT9137_FW: + default: + st->it913x_config.firmware_ver = 0; + st->it913x_config.adc_x2 = 0; + st->it913x_config.read_slevel = true; + *name = fw_it9137; + } + + return; +} + +#define TS_MPEG_PKT_SIZE 188 +#define EP_LOW 21 +#define TS_BUFFER_SIZE_PID (EP_LOW*TS_MPEG_PKT_SIZE) +#define EP_HIGH 348 +#define TS_BUFFER_SIZE_MAX (EP_HIGH*TS_MPEG_PKT_SIZE) + +static int it913x_get_stream_config(struct dvb_frontend *fe, u8 *ts_type, + struct usb_data_stream_properties *stream) +{ + struct dvb_usb_adapter *adap = fe_to_adap(fe); + if (adap->pid_filtering) + stream->u.bulk.buffersize = TS_BUFFER_SIZE_PID; + else + stream->u.bulk.buffersize = TS_BUFFER_SIZE_MAX; + + return 0; +} + +static int it913x_select_config(struct dvb_usb_device *d) +{ + struct it913x_state *st = d->priv; + int ret, reg; + + ret = it913x_return_status(d); + if (ret < 0) + return ret; + + if (st->it913x_config.chip_ver == 0x02 + && st->it913x_config.chip_type == 0x9135) + reg = it913x_read_reg(d, 0x461d); + else + reg = it913x_read_reg(d, 0x461b); + + if (reg < 0) + return reg; + + if (reg == 0) { + st->it913x_config.dual_mode = 0; + st->it913x_config.tuner_id_0 = IT9135_38; + st->proprietary_ir = true; + } else { + /* TS mode */ + reg = it913x_read_reg(d, 0x49c5); + if (reg < 0) + return reg; + st->it913x_config.dual_mode = reg; + + /* IR mode type */ + reg = it913x_read_reg(d, 0x49ac); + if (reg < 0) + return reg; + if (reg == 5) { + info("Remote propriety (raw) mode"); + st->proprietary_ir = true; + } else if (reg == 1) { + info("Remote HID mode NOT SUPPORTED"); + st->proprietary_ir = false; + } + + /* Tuner_id */ + reg = it913x_read_reg(d, 0x49d0); + if (reg < 0) + return reg; + st->it913x_config.tuner_id_0 = reg; + } + + info("Dual mode=%x Tuner Type=%x", st->it913x_config.dual_mode, + st->it913x_config.tuner_id_0); + + return ret; +} + +static int it913x_streaming_ctrl(struct dvb_frontend *fe, int onoff) +{ + struct dvb_usb_adapter *adap = fe_to_adap(fe); + struct dvb_usb_device *d = adap_to_d(adap); + struct it913x_state *st = fe_to_priv(fe); + int ret = 0; + u8 pro = (adap->id == 0) ? DEV_0_DMOD : DEV_1_DMOD; + + deb_info(1, "STM (%02x)", onoff); + + if (!onoff) { + mutex_lock(&d->i2c_mutex); + + ret = it913x_wr_reg(d, pro, PID_RST, 0x1); + + mutex_unlock(&d->i2c_mutex); + st->pid_filter_onoff = + adap->pid_filtering; + + } + + return ret; +} + +static int it913x_identify_state(struct dvb_usb_device *d, const char **name) +{ + struct it913x_state *st = d->priv; + int ret; + u8 reg; + + /* Read and select config */ + ret = it913x_select_config(d); + if (ret < 0) + return ret; + + ite_get_firmware_name(d, name); + + if (st->it913x_config.firmware > 0) + return WARM; + + if (st->it913x_config.dual_mode) { + st->it913x_config.tuner_id_1 = it913x_read_reg(d, 0x49e0); + ret = it913x_wr_reg(d, DEV_0, GPIOH1_EN, 0x1); + ret |= it913x_wr_reg(d, DEV_0, GPIOH1_ON, 0x1); + ret |= it913x_wr_reg(d, DEV_0, GPIOH1_O, 0x1); + msleep(50); + ret |= it913x_wr_reg(d, DEV_0, GPIOH1_O, 0x0); + msleep(50); + reg = it913x_read_reg(d, GPIOH1_O); + if (reg == 0) { + ret |= it913x_wr_reg(d, DEV_0, GPIOH1_O, 0x1); + ret |= it913x_return_status(d); + if (ret != 0) + ret = it913x_wr_reg(d, DEV_0, + GPIOH1_O, 0x0); + } + } + + reg = it913x_read_reg(d, IO_MUX_POWER_CLK); + + if (st->it913x_config.dual_mode) { + ret |= it913x_wr_reg(d, DEV_0, 0x4bfb, CHIP2_I2C_ADDR); + if (st->it913x_config.firmware_ver == 1) + ret |= it913x_wr_reg(d, DEV_0, 0xcfff, 0x1); + else + ret |= it913x_wr_reg(d, DEV_0, CLK_O_EN, 0x1); + } else { + ret |= it913x_wr_reg(d, DEV_0, 0x4bfb, 0x0); + if (st->it913x_config.firmware_ver == 1) + ret |= it913x_wr_reg(d, DEV_0, 0xcfff, 0x0); + else + ret |= it913x_wr_reg(d, DEV_0, CLK_O_EN, 0x0); + } + + ret |= it913x_wr_reg(d, DEV_0, I2C_CLK, I2C_CLK_100); + + return (ret < 0) ? ret : COLD; +} + +static int it913x_download_firmware(struct dvb_usb_device *d, + const struct firmware *fw) +{ + struct it913x_state *st = d->priv; + int ret = 0, i = 0, pos = 0; + u8 packet_size, min_pkt; + u8 *fw_data; + + ret = it913x_wr_reg(d, DEV_0, I2C_CLK, I2C_CLK_100); + + info("FRM Starting Firmware Download"); + + /* Multi firmware loader */ + /* This uses scatter write firmware headers */ + /* The firmware must start with 03 XX 00 */ + /* and be the extact firmware length */ + + if (st->it913x_config.chip_ver == 2) + min_pkt = 0x11; + else + min_pkt = 0x19; + + while (i <= fw->size) { + if (((fw->data[i] == 0x3) && (fw->data[i + 2] == 0x0)) + || (i == fw->size)) { + packet_size = i - pos; + if ((packet_size > min_pkt) || (i == fw->size)) { + fw_data = (u8 *)(fw->data + pos); + pos += packet_size; + if (packet_size > 0) { + ret = it913x_io(d, WRITE_DATA, + DEV_0, CMD_SCATTER_WRITE, 0, + 0, fw_data, packet_size); + if (ret < 0) + break; + } + udelay(1000); + } + } + i++; + } + + if (ret < 0) + info("FRM Firmware Download Failed (%d)" , ret); + else + info("FRM Firmware Download Completed - Resetting Device"); + + msleep(30); + + ret = it913x_io(d, WRITE_CMD, DEV_0, CMD_BOOT, 0, 0, NULL, 0); + if (ret < 0) + info("FRM Device not responding to reboot"); + + ret = it913x_return_status(d); + if (st->it913x_config.firmware == 0) { + info("FRM Failed to reboot device"); + return -ENODEV; + } + + msleep(30); + + ret = it913x_wr_reg(d, DEV_0, I2C_CLK, I2C_CLK_400); + + msleep(30); + + /* Tuner function */ + if (st->it913x_config.dual_mode) + ret |= it913x_wr_reg(d, DEV_0_DMOD , 0xec4c, 0xa0); + else + ret |= it913x_wr_reg(d, DEV_0_DMOD , 0xec4c, 0x68); + + if ((st->it913x_config.chip_ver == 1) && + (st->it913x_config.chip_type == 0x9135)) { + ret |= it913x_wr_reg(d, DEV_0, PADODPU, 0x0); + ret |= it913x_wr_reg(d, DEV_0, AGC_O_D, 0x0); + if (st->it913x_config.dual_mode) { + ret |= it913x_wr_reg(d, DEV_1, PADODPU, 0x0); + ret |= it913x_wr_reg(d, DEV_1, AGC_O_D, 0x0); + } + } + + return (ret < 0) ? -ENODEV : 0; +} + +static int it913x_name(struct dvb_usb_adapter *adap) +{ + struct dvb_usb_device *d = adap_to_d(adap); + const char *desc = d->name; + char *fe_name[] = {"_1", "_2", "_3", "_4"}; + char *name = adap->fe[0]->ops.info.name; + + strlcpy(name, desc, 128); + strlcat(name, fe_name[adap->id], 128); + + return 0; +} + +static int it913x_frontend_attach(struct dvb_usb_adapter *adap) +{ + struct dvb_usb_device *d = adap_to_d(adap); + struct it913x_state *st = d->priv; + int ret = 0; + u8 adap_addr = I2C_BASE_ADDR + (adap->id << 5); + u16 ep_size = adap->stream.buf_size / 4; + u8 pkt_size = 0x80; + + if (d->udev->speed != USB_SPEED_HIGH) + pkt_size = 0x10; + + st->it913x_config.adf = it913x_read_reg(d, IO_MUX_POWER_CLK); + + adap->fe[0] = dvb_attach(it913x_fe_attach, + &d->i2c_adap, adap_addr, &st->it913x_config); + + if (adap->id == 0 && adap->fe[0]) { + it913x_wr_reg(d, DEV_0_DMOD, MP2_SW_RST, 0x1); + it913x_wr_reg(d, DEV_0_DMOD, MP2IF2_SW_RST, 0x1); + it913x_wr_reg(d, DEV_0, EP0_TX_EN, 0x0f); + it913x_wr_reg(d, DEV_0, EP0_TX_NAK, 0x1b); + it913x_wr_reg(d, DEV_0, EP0_TX_EN, 0x2f); + it913x_wr_reg(d, DEV_0, EP4_TX_LEN_LSB, + ep_size & 0xff); + it913x_wr_reg(d, DEV_0, EP4_TX_LEN_MSB, ep_size >> 8); + ret = it913x_wr_reg(d, DEV_0, EP4_MAX_PKT, pkt_size); + } else if (adap->id == 1 && adap->fe[0]) { + it913x_wr_reg(d, DEV_0, EP0_TX_EN, 0x6f); + it913x_wr_reg(d, DEV_0, EP5_TX_LEN_LSB, + ep_size & 0xff); + it913x_wr_reg(d, DEV_0, EP5_TX_LEN_MSB, ep_size >> 8); + it913x_wr_reg(d, DEV_0, EP5_MAX_PKT, pkt_size); + it913x_wr_reg(d, DEV_0_DMOD, MP2IF2_EN, 0x1); + it913x_wr_reg(d, DEV_1_DMOD, MP2IF_SERIAL, 0x1); + it913x_wr_reg(d, DEV_1, TOP_HOSTB_SER_MODE, 0x1); + it913x_wr_reg(d, DEV_0_DMOD, TSIS_ENABLE, 0x1); + it913x_wr_reg(d, DEV_0_DMOD, MP2_SW_RST, 0x0); + it913x_wr_reg(d, DEV_0_DMOD, MP2IF2_SW_RST, 0x0); + it913x_wr_reg(d, DEV_0_DMOD, MP2IF2_HALF_PSB, 0x0); + it913x_wr_reg(d, DEV_0_DMOD, MP2IF_STOP_EN, 0x1); + it913x_wr_reg(d, DEV_1_DMOD, MPEG_FULL_SPEED, 0x0); + ret = it913x_wr_reg(d, DEV_1_DMOD, MP2IF_STOP_EN, 0x0); + } else + return -ENODEV; + + ret |= it913x_name(adap); + + return ret; +} + +/* DVB USB Driver */ +static int it913x_get_rc_config(struct dvb_usb_device *d, struct dvb_usb_rc *rc) +{ + struct it913x_state *st = d->priv; + + if (st->proprietary_ir == false) { + rc->map_name = NULL; + return 0; + } + + rc->allowed_protos = RC_TYPE_NEC; + rc->query = it913x_rc_query; + rc->interval = 250; + + return 0; +} + +static int it913x_get_adapter_count(struct dvb_usb_device *d) +{ + struct it913x_state *st = d->priv; + if (st->it913x_config.dual_mode) + return 2; + return 1; +} + +static struct dvb_usb_device_properties it913x_properties = { + .driver_name = KBUILD_MODNAME, + .owner = THIS_MODULE, + .bInterfaceNumber = 0, + .generic_bulk_ctrl_endpoint = 0x02, + .generic_bulk_ctrl_endpoint_response = 0x81, + + .adapter_nr = adapter_nr, + .size_of_priv = sizeof(struct it913x_state), + + .identify_state = it913x_identify_state, + .i2c_algo = &it913x_i2c_algo, + + .download_firmware = it913x_download_firmware, + + .frontend_attach = it913x_frontend_attach, + .get_rc_config = it913x_get_rc_config, + .get_stream_config = it913x_get_stream_config, + .get_adapter_count = it913x_get_adapter_count, + .streaming_ctrl = it913x_streaming_ctrl, + + + .adapter = { + { + .caps = DVB_USB_ADAP_HAS_PID_FILTER| + DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, + .pid_filter_count = 32, + .pid_filter = it913x_pid_filter, + .pid_filter_ctrl = it913x_pid_filter_ctrl, + .stream = + DVB_USB_STREAM_BULK(0x84, 10, TS_BUFFER_SIZE_MAX), + }, + { + .caps = DVB_USB_ADAP_HAS_PID_FILTER| + DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, + .pid_filter_count = 32, + .pid_filter = it913x_pid_filter, + .pid_filter_ctrl = it913x_pid_filter_ctrl, + .stream = + DVB_USB_STREAM_BULK(0x85, 10, TS_BUFFER_SIZE_MAX), + } + } +}; + +static const struct usb_device_id it913x_id_table[] = { + { DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_UB499_2T_T09, + &it913x_properties, "Kworld UB499-2T T09(IT9137)", + RC_MAP_IT913X_V1) }, + { DVB_USB_DEVICE(USB_VID_ITETECH, USB_PID_ITETECH_IT9135, + &it913x_properties, "ITE 9135 Generic", + RC_MAP_IT913X_V1) }, + { DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_SVEON_STV22_IT9137, + &it913x_properties, "Sveon STV22 Dual DVB-T HDTV(IT9137)", + RC_MAP_IT913X_V1) }, + { DVB_USB_DEVICE(USB_VID_ITETECH, USB_PID_ITETECH_IT9135_9005, + &it913x_properties, "ITE 9135(9005) Generic", + RC_MAP_IT913X_V2) }, + { DVB_USB_DEVICE(USB_VID_ITETECH, USB_PID_ITETECH_IT9135_9006, + &it913x_properties, "ITE 9135(9006) Generic", + RC_MAP_IT913X_V1) }, + {} /* Terminating entry */ +}; + +MODULE_DEVICE_TABLE(usb, it913x_id_table); + +static struct usb_driver it913x_driver = { + .name = KBUILD_MODNAME, + .probe = dvb_usbv2_probe, + .disconnect = dvb_usbv2_disconnect, + .suspend = dvb_usbv2_suspend, + .resume = dvb_usbv2_resume, + .id_table = it913x_id_table, +}; + +module_usb_driver(it913x_driver); + +MODULE_AUTHOR("Malcolm Priestley <tvboxspy@gmail.com>"); +MODULE_DESCRIPTION("it913x USB 2 Driver"); +MODULE_VERSION("1.32"); +MODULE_LICENSE("GPL"); +MODULE_FIRMWARE(FW_IT9135_V1); +MODULE_FIRMWARE(FW_IT9135_V2); +MODULE_FIRMWARE(FW_IT9137); + diff --git a/drivers/media/dvb/dvb-usb/lmedm04.c b/drivers/media/usb/dvb-usb-v2/lmedm04.c index 25d1031460f8..c41d9d9ec7b5 100644 --- a/drivers/media/dvb/dvb-usb/lmedm04.c +++ b/drivers/media/usb/dvb-usb-v2/lmedm04.c @@ -19,6 +19,8 @@ * * MVB0194 (LME2510C+SHARP0194) * + * LME2510C + M88RS2000 + * * For firmware see Documentation/dvb/lmedm04.txt * * I2C addresses: @@ -62,13 +64,14 @@ * LME2510: SHARP:BS2F7HZ0194(MV0194) cannot cold reset and share system * with other tuners. After a cold reset streaming will not start. * + * M88RS2000 suffers from loss of lock. */ #define DVB_USB_LOG_PREFIX "LME2510(C)" #include <linux/usb.h> #include <linux/usb/input.h> #include <media/rc-core.h> -#include "dvb-usb.h" +#include "dvb_usb.h" #include "lmedm04.h" #include "tda826x.h" #include "tda10086.h" @@ -80,24 +83,28 @@ #include "m88rs2000.h" +#define LME2510_C_S7395 "dvb-usb-lme2510c-s7395.fw"; +#define LME2510_C_LG "dvb-usb-lme2510c-lg.fw"; +#define LME2510_C_S0194 "dvb-usb-lme2510c-s0194.fw"; +#define LME2510_C_RS2000 "dvb-usb-lme2510c-rs2000.fw"; +#define LME2510_LG "dvb-usb-lme2510-lg.fw"; +#define LME2510_S0194 "dvb-usb-lme2510-s0194.fw"; /* debug */ static int dvb_usb_lme2510_debug; -#define l_dprintk(var, level, args...) do { \ +#define lme_debug(var, level, args...) do { \ if ((var >= level)) \ - printk(KERN_DEBUG DVB_USB_LOG_PREFIX ": " args); \ + pr_debug(DVB_USB_LOG_PREFIX": " args); \ } while (0) - -#define deb_info(level, args...) l_dprintk(dvb_usb_lme2510_debug, level, args) +#define deb_info(level, args...) lme_debug(dvb_usb_lme2510_debug, level, args) #define debug_data_snipet(level, name, p) \ deb_info(level, name" (%02x%02x%02x%02x%02x%02x%02x%02x)", \ *p, *(p+1), *(p+2), *(p+3), *(p+4), \ *(p+5), *(p+6), *(p+7)); - +#define info(args...) pr_info(DVB_USB_LOG_PREFIX": "args) module_param_named(debug, dvb_usb_lme2510_debug, int, 0644); -MODULE_PARM_DESC(debug, "set debugging level (1=info (or-able))." - DVB_USB_DEBUG_STATUS); +MODULE_PARM_DESC(debug, "set debugging level (1=info (or-able))."); static int dvb_usb_lme2510_firmware; module_param_named(firmware, dvb_usb_lme2510_firmware, int, 0644); @@ -136,7 +143,8 @@ struct lme2510_state { void *buffer; struct urb *lme_urb; void *usb_buffer; - + int (*fe_set_voltage)(struct dvb_frontend *, fe_sec_voltage_t); + u8 dvb_usb_lme2510_firmware; }; static int lme2510_bulk_write(struct usb_device *dev, @@ -246,7 +254,7 @@ static int lme2510_enable_pid(struct dvb_usb_device *d, u8 index, u16 pid_out) static void lme2510_int_response(struct urb *lme_urb) { struct dvb_usb_adapter *adap = lme_urb->context; - struct lme2510_state *st = adap->dev->priv; + struct lme2510_state *st = adap_to_priv(adap); static u8 *ibuf, *rbuf; int i = 0, offset; u32 key; @@ -283,8 +291,9 @@ static void lme2510_int_response(struct urb *lme_urb) ? (ibuf[3] ^ 0xff) << 8 : 0; key += (ibuf[2] ^ 0xff) << 16; deb_info(1, "INT Key =%08x", key); - if (adap->dev->rc_dev != NULL) - rc_keydown(adap->dev->rc_dev, key, 0); + if (adap_to_d(adap)->rc_dev != NULL) + rc_keydown(adap_to_d(adap)->rc_dev, + key, 0); } break; case 0xbb: @@ -313,12 +322,12 @@ static void lme2510_int_response(struct urb *lme_urb) } break; case TUNER_RS2000: - if (ibuf[2] > 0) + if (ibuf[1] == 0x3 && ibuf[6] == 0xff) st->signal_lock = 0xff; else - st->signal_lock = 0xf0; - st->signal_level = ibuf[4]; - st->signal_sn = ibuf[5]; + st->signal_lock = 0x00; + st->signal_level = ibuf[5]; + st->signal_sn = ibuf[4]; st->time_key = ibuf[7]; default: break; @@ -338,22 +347,23 @@ static void lme2510_int_response(struct urb *lme_urb) static int lme2510_int_read(struct dvb_usb_adapter *adap) { - struct lme2510_state *lme_int = adap->dev->priv; + struct dvb_usb_device *d = adap_to_d(adap); + struct lme2510_state *lme_int = adap_to_priv(adap); lme_int->lme_urb = usb_alloc_urb(0, GFP_ATOMIC); if (lme_int->lme_urb == NULL) return -ENOMEM; - lme_int->buffer = usb_alloc_coherent(adap->dev->udev, 128, GFP_ATOMIC, + lme_int->buffer = usb_alloc_coherent(d->udev, 128, GFP_ATOMIC, &lme_int->lme_urb->transfer_dma); if (lme_int->buffer == NULL) return -ENOMEM; usb_fill_int_urb(lme_int->lme_urb, - adap->dev->udev, - usb_rcvintpipe(adap->dev->udev, 0xa), + d->udev, + usb_rcvintpipe(d->udev, 0xa), lme_int->buffer, 128, lme2510_int_response, @@ -370,17 +380,18 @@ static int lme2510_int_read(struct dvb_usb_adapter *adap) static int lme2510_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff) { - struct lme2510_state *st = adap->dev->priv; + struct dvb_usb_device *d = adap_to_d(adap); + struct lme2510_state *st = adap_to_priv(adap); static u8 clear_pid_reg[] = LME_ALL_PIDS; static u8 rbuf[1]; int ret = 0; deb_info(1, "PID Clearing Filter"); - mutex_lock(&adap->dev->i2c_mutex); + mutex_lock(&d->i2c_mutex); if (!onoff) { - ret |= lme2510_usb_talk(adap->dev, clear_pid_reg, + ret |= lme2510_usb_talk(d, clear_pid_reg, sizeof(clear_pid_reg), rbuf, sizeof(rbuf)); st->pid_off = true; } else @@ -388,7 +399,7 @@ static int lme2510_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff) st->pid_size = 0; - mutex_unlock(&adap->dev->i2c_mutex); + mutex_unlock(&d->i2c_mutex); return 0; } @@ -396,15 +407,16 @@ static int lme2510_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff) static int lme2510_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid, int onoff) { + struct dvb_usb_device *d = adap_to_d(adap); int ret = 0; deb_info(3, "%s PID=%04x Index=%04x onoff=%02x", __func__, pid, index, onoff); if (onoff) { - mutex_lock(&adap->dev->i2c_mutex); - ret |= lme2510_enable_pid(adap->dev, index, pid); - mutex_unlock(&adap->dev->i2c_mutex); + mutex_lock(&d->i2c_mutex); + ret |= lme2510_enable_pid(d, index, pid); + mutex_unlock(&d->i2c_mutex); } @@ -412,7 +424,7 @@ static int lme2510_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid, } -static int lme2510_return_status(struct usb_device *dev) +static int lme2510_return_status(struct dvb_usb_device *d) { int ret = 0; u8 *data; @@ -421,7 +433,7 @@ static int lme2510_return_status(struct usb_device *dev) if (!data) return -ENOMEM; - ret |= usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), + ret |= usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0), 0x06, 0x80, 0x0302, 0x00, data, 0x0006, 200); info("Firmware Status: %x (%x)", ret , data[2]); @@ -613,10 +625,6 @@ static int lme2510_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], if (gate == 0) gate = 5; - if (num > 2) - warn("more than 2 i2c messages" - "at a time is not handled yet. TODO."); - for (i = 0; i < num; i++) { read_o = 1 & (msg[i].flags & I2C_M_RD); read = i+1 < num && (msg[i+1].flags & I2C_M_RD); @@ -676,22 +684,11 @@ static struct i2c_algorithm lme2510_i2c_algo = { .functionality = lme2510_i2c_func, }; -/* Callbacks for DVB USB */ -static int lme2510_identify_state(struct usb_device *udev, - struct dvb_usb_device_properties *props, - struct dvb_usb_device_description **desc, - int *cold) +static int lme2510_streaming_ctrl(struct dvb_frontend *fe, int onoff) { - if (pid_filter != 2) - props->adapter[0].fe[0].caps &= - ~DVB_USB_ADAP_NEED_PID_FILTERING; - *cold = 0; - return 0; -} - -static int lme2510_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) -{ - struct lme2510_state *st = adap->dev->priv; + struct dvb_usb_adapter *adap = fe_to_adap(fe); + struct dvb_usb_device *d = adap_to_d(adap); + struct lme2510_state *st = adap_to_priv(adap); static u8 clear_reg_3[] = LME_ALL_PIDS; static u8 rbuf[1]; int ret = 0, rlen = sizeof(rbuf); @@ -704,14 +701,14 @@ static int lme2510_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) else { deb_info(1, "STM Steam Off"); /* mutex is here only to avoid collision with I2C */ - mutex_lock(&adap->dev->i2c_mutex); + mutex_lock(&d->i2c_mutex); - ret = lme2510_usb_talk(adap->dev, clear_reg_3, + ret = lme2510_usb_talk(d, clear_reg_3, sizeof(clear_reg_3), rbuf, rlen); st->stream_on = 0; st->i2c_talk_onoff = 1; - mutex_unlock(&adap->dev->i2c_mutex); + mutex_unlock(&d->i2c_mutex); } return (ret < 0) ? -ENODEV : 0; @@ -725,7 +722,7 @@ static u8 check_sum(u8 *p, u8 len) return sum; } -static int lme2510_download_firmware(struct usb_device *dev, +static int lme2510_download_firmware(struct dvb_usb_device *d, const struct firmware *fw) { int ret = 0; @@ -737,9 +734,10 @@ static int lme2510_download_firmware(struct usb_device *dev, packet_size = 0x31; len_in = 1; - data = kzalloc(512, GFP_KERNEL); + data = kzalloc(128, GFP_KERNEL); if (!data) { - info("FRM Could not start Firmware Download (Buffer allocation failed)"); + info("FRM Could not start Firmware Download"\ + "(Buffer allocation failed)"); return -ENOMEM; } @@ -763,21 +761,15 @@ static int lme2510_download_firmware(struct usb_device *dev, data[wlen-1] = check_sum(fw_data, dlen+1); deb_info(1, "Data S=%02x:E=%02x CS= %02x", data[3], data[dlen+2], data[dlen+3]); - ret |= lme2510_bulk_write(dev, data, wlen, 1); - ret |= lme2510_bulk_read(dev, data, len_in , 1); + lme2510_usb_talk(d, data, wlen, data, len_in); ret |= (data[0] == 0x88) ? 0 : -1; } } - usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), - 0x06, 0x80, 0x0200, 0x00, data, 0x0109, 1000); - - data[0] = 0x8a; len_in = 1; msleep(2000); - ret |= lme2510_bulk_write(dev, data , len_in, 1); /*Resetting*/ - ret |= lme2510_bulk_read(dev, data, len_in, 1); + lme2510_usb_talk(d, data, len_in, data, len_in); msleep(400); if (ret < 0) @@ -786,44 +778,42 @@ static int lme2510_download_firmware(struct usb_device *dev, info("FRM Firmware Download Completed - Resetting Device"); kfree(data); - return (ret < 0) ? -ENODEV : 0; + return RECONNECTS_USB; } -static void lme_coldreset(struct usb_device *dev) +static void lme_coldreset(struct dvb_usb_device *d) { - int ret = 0, len_in; - u8 data[512] = {0}; - + u8 data[1] = {0}; data[0] = 0x0a; - len_in = 1; info("FRM Firmware Cold Reset"); - ret |= lme2510_bulk_write(dev, data , len_in, 1); /*Cold Resetting*/ - ret |= lme2510_bulk_read(dev, data, len_in, 1); + + lme2510_usb_talk(d, data, sizeof(data), data, sizeof(data)); return; } -static int lme_firmware_switch(struct usb_device *udev, int cold) +static const char fw_c_s7395[] = LME2510_C_S7395; +static const char fw_c_lg[] = LME2510_C_LG; +static const char fw_c_s0194[] = LME2510_C_S0194; +static const char fw_c_rs2000[] = LME2510_C_RS2000; +static const char fw_lg[] = LME2510_LG; +static const char fw_s0194[] = LME2510_S0194; + +const char *lme_firmware_switch(struct dvb_usb_device *d, int cold) { + struct lme2510_state *st = d->priv; + struct usb_device *udev = d->udev; const struct firmware *fw = NULL; - const char fw_c_s7395[] = "dvb-usb-lme2510c-s7395.fw"; - const char fw_c_lg[] = "dvb-usb-lme2510c-lg.fw"; - const char fw_c_s0194[] = "dvb-usb-lme2510c-s0194.fw"; - const char fw_c_rs2000[] = "dvb-usb-lme2510c-rs2000.fw"; - const char fw_lg[] = "dvb-usb-lme2510-lg.fw"; - const char fw_s0194[] = "dvb-usb-lme2510-s0194.fw"; const char *fw_lme; - int ret = 0, cold_fw; + int ret = 0; cold = (cold > 0) ? (cold & 1) : 0; - cold_fw = !cold; - switch (le16_to_cpu(udev->descriptor.idProduct)) { case 0x1122: - switch (dvb_usb_lme2510_firmware) { + switch (st->dvb_usb_lme2510_firmware) { default: - dvb_usb_lme2510_firmware = TUNER_S0194; + st->dvb_usb_lme2510_firmware = TUNER_S0194; case TUNER_S0194: fw_lme = fw_s0194; ret = request_firmware(&fw, fw_lme, &udev->dev); @@ -831,23 +821,20 @@ static int lme_firmware_switch(struct usb_device *udev, int cold) cold = 0; break; } - dvb_usb_lme2510_firmware = TUNER_LG; + st->dvb_usb_lme2510_firmware = TUNER_LG; case TUNER_LG: fw_lme = fw_lg; ret = request_firmware(&fw, fw_lme, &udev->dev); if (ret == 0) break; - info("FRM No Firmware Found - please install"); - dvb_usb_lme2510_firmware = TUNER_DEFAULT; - cold = 0; - cold_fw = 0; + st->dvb_usb_lme2510_firmware = TUNER_DEFAULT; break; } break; case 0x1120: - switch (dvb_usb_lme2510_firmware) { + switch (st->dvb_usb_lme2510_firmware) { default: - dvb_usb_lme2510_firmware = TUNER_S7395; + st->dvb_usb_lme2510_firmware = TUNER_S7395; case TUNER_S7395: fw_lme = fw_c_s7395; ret = request_firmware(&fw, fw_lme, &udev->dev); @@ -855,49 +842,41 @@ static int lme_firmware_switch(struct usb_device *udev, int cold) cold = 0; break; } - dvb_usb_lme2510_firmware = TUNER_LG; + st->dvb_usb_lme2510_firmware = TUNER_LG; case TUNER_LG: fw_lme = fw_c_lg; ret = request_firmware(&fw, fw_lme, &udev->dev); if (ret == 0) break; - dvb_usb_lme2510_firmware = TUNER_S0194; + st->dvb_usb_lme2510_firmware = TUNER_S0194; case TUNER_S0194: fw_lme = fw_c_s0194; ret = request_firmware(&fw, fw_lme, &udev->dev); if (ret == 0) break; - info("FRM No Firmware Found - please install"); - dvb_usb_lme2510_firmware = TUNER_DEFAULT; + st->dvb_usb_lme2510_firmware = TUNER_DEFAULT; cold = 0; - cold_fw = 0; break; } break; case 0x22f0: fw_lme = fw_c_rs2000; - ret = request_firmware(&fw, fw_lme, &udev->dev); - dvb_usb_lme2510_firmware = TUNER_RS2000; + st->dvb_usb_lme2510_firmware = TUNER_RS2000; break; default: fw_lme = fw_c_s7395; } - - if (cold_fw) { - info("FRM Loading %s file", fw_lme); - ret = lme2510_download_firmware(udev, fw); - } - release_firmware(fw); if (cold) { + dvb_usb_lme2510_firmware = st->dvb_usb_lme2510_firmware; info("FRM Changing to %s firmware", fw_lme); - lme_coldreset(udev); - return -ENODEV; + lme_coldreset(d); + return NULL; } - return ret; + return fw_lme; } static int lme2510_kill_urb(struct usb_data_stream *stream) @@ -949,8 +928,8 @@ static struct stv0299_config sharp_z0194_config = { static int dm04_rs2000_set_ts_param(struct dvb_frontend *fe, int caller) { - struct dvb_usb_adapter *adap = fe->dvb->priv; - struct dvb_usb_device *d = adap->dev; + struct dvb_usb_adapter *adap = fe_to_adap(fe); + struct dvb_usb_device *d = adap_to_d(adap); struct lme2510_state *st = d->priv; mutex_lock(&d->i2c_mutex); @@ -972,29 +951,35 @@ static struct m88rs2000_config m88rs2000_config = { static int dm04_lme2510_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) { - struct dvb_usb_adapter *adap = fe->dvb->priv; - static u8 voltage_low[] = LME_VOLTAGE_L; + struct dvb_usb_device *d = fe_to_d(fe); + struct lme2510_state *st = fe_to_priv(fe); + static u8 voltage_low[] = LME_VOLTAGE_L; static u8 voltage_high[] = LME_VOLTAGE_H; static u8 rbuf[1]; int ret = 0, len = 3, rlen = 1; - mutex_lock(&adap->dev->i2c_mutex); + mutex_lock(&d->i2c_mutex); switch (voltage) { case SEC_VOLTAGE_18: - ret |= lme2510_usb_talk(adap->dev, + ret |= lme2510_usb_talk(d, voltage_high, len, rbuf, rlen); break; case SEC_VOLTAGE_OFF: case SEC_VOLTAGE_13: default: - ret |= lme2510_usb_talk(adap->dev, + ret |= lme2510_usb_talk(d, voltage_low, len, rbuf, rlen); break; } - mutex_unlock(&adap->dev->i2c_mutex); + mutex_unlock(&d->i2c_mutex); + + if (st->tuner_config == TUNER_RS2000) + if (st->fe_set_voltage) + st->fe_set_voltage(fe, voltage); + return (ret < 0) ? -ENODEV : 0; } @@ -1002,29 +987,44 @@ static int dm04_lme2510_set_voltage(struct dvb_frontend *fe, static int dm04_rs2000_read_signal_strength(struct dvb_frontend *fe, u16 *strength) { - struct dvb_usb_adapter *adap = fe->dvb->priv; - struct lme2510_state *st = adap->dev->priv; + struct lme2510_state *st = fe_to_priv(fe); + + *strength = (u16)((u32)st->signal_level * 0xffff / 0xff); - *strength = (u16)((u32)st->signal_level * 0xffff / 0x7f); return 0; } static int dm04_rs2000_read_snr(struct dvb_frontend *fe, u16 *snr) { - struct dvb_usb_adapter *adap = fe->dvb->priv; - struct lme2510_state *st = adap->dev->priv; + struct lme2510_state *st = fe_to_priv(fe); + + *snr = (u16)((u32)st->signal_sn * 0xffff / 0x7f); + + return 0; +} + +static int dm04_read_ber(struct dvb_frontend *fe, u32 *ber) +{ + *ber = 0; + + return 0; +} + +static int dm04_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) +{ + *ucblocks = 0; - *snr = (u16)((u32)st->signal_sn * 0xffff / 0xff); return 0; } static int lme_name(struct dvb_usb_adapter *adap) { - struct lme2510_state *st = adap->dev->priv; - const char *desc = adap->dev->desc->name; + struct dvb_usb_device *d = adap_to_d(adap); + struct lme2510_state *st = adap_to_priv(adap); + const char *desc = d->name; char *fe_name[] = {"", " LG TDQY-P001F", " SHARP:BS2F7HZ7395", " SHARP:BS2F7HZ0194", " RS2000"}; - char *name = adap->fe_adap[0].fe->ops.info.name; + char *name = adap->fe[0]->ops.info.name; strlcpy(name, desc, 128); strlcat(name, fe_name[st->tuner_config], 128); @@ -1034,120 +1034,128 @@ static int lme_name(struct dvb_usb_adapter *adap) static int dm04_lme2510_frontend_attach(struct dvb_usb_adapter *adap) { - struct lme2510_state *st = adap->dev->priv; - + struct dvb_usb_device *d = adap_to_d(adap); + struct lme2510_state *st = d->priv; int ret = 0; st->i2c_talk_onoff = 1; - switch (le16_to_cpu(adap->dev->udev->descriptor.idProduct)) { + switch (le16_to_cpu(d->udev->descriptor.idProduct)) { case 0x1122: case 0x1120: st->i2c_gate = 4; - adap->fe_adap[0].fe = dvb_attach(tda10086_attach, - &tda10086_config, &adap->dev->i2c_adap); - if (adap->fe_adap[0].fe) { + adap->fe[0] = dvb_attach(tda10086_attach, + &tda10086_config, &d->i2c_adap); + if (adap->fe[0]) { info("TUN Found Frontend TDA10086"); st->i2c_tuner_gate_w = 4; st->i2c_tuner_gate_r = 4; st->i2c_tuner_addr = 0xc0; st->tuner_config = TUNER_LG; - if (dvb_usb_lme2510_firmware != TUNER_LG) { - dvb_usb_lme2510_firmware = TUNER_LG; - ret = lme_firmware_switch(adap->dev->udev, 1); + if (st->dvb_usb_lme2510_firmware != TUNER_LG) { + st->dvb_usb_lme2510_firmware = TUNER_LG; + ret = lme_firmware_switch(d, 1) ? 0 : -ENODEV; } break; } st->i2c_gate = 4; - adap->fe_adap[0].fe = dvb_attach(stv0299_attach, - &sharp_z0194_config, &adap->dev->i2c_adap); - if (adap->fe_adap[0].fe) { + adap->fe[0] = dvb_attach(stv0299_attach, + &sharp_z0194_config, &d->i2c_adap); + if (adap->fe[0]) { info("FE Found Stv0299"); st->i2c_tuner_gate_w = 4; st->i2c_tuner_gate_r = 5; st->i2c_tuner_addr = 0xc0; st->tuner_config = TUNER_S0194; - if (dvb_usb_lme2510_firmware != TUNER_S0194) { - dvb_usb_lme2510_firmware = TUNER_S0194; - ret = lme_firmware_switch(adap->dev->udev, 1); + if (st->dvb_usb_lme2510_firmware != TUNER_S0194) { + st->dvb_usb_lme2510_firmware = TUNER_S0194; + ret = lme_firmware_switch(d, 1) ? 0 : -ENODEV; } break; } st->i2c_gate = 5; - adap->fe_adap[0].fe = dvb_attach(stv0288_attach, &lme_config, - &adap->dev->i2c_adap); + adap->fe[0] = dvb_attach(stv0288_attach, &lme_config, + &d->i2c_adap); - if (adap->fe_adap[0].fe) { + if (adap->fe[0]) { info("FE Found Stv0288"); st->i2c_tuner_gate_w = 4; st->i2c_tuner_gate_r = 5; st->i2c_tuner_addr = 0xc0; st->tuner_config = TUNER_S7395; - if (dvb_usb_lme2510_firmware != TUNER_S7395) { - dvb_usb_lme2510_firmware = TUNER_S7395; - ret = lme_firmware_switch(adap->dev->udev, 1); + if (st->dvb_usb_lme2510_firmware != TUNER_S7395) { + st->dvb_usb_lme2510_firmware = TUNER_S7395; + ret = lme_firmware_switch(d, 1) ? 0 : -ENODEV; } break; } case 0x22f0: st->i2c_gate = 5; - adap->fe_adap[0].fe = dvb_attach(m88rs2000_attach, - &m88rs2000_config, &adap->dev->i2c_adap); + adap->fe[0] = dvb_attach(m88rs2000_attach, + &m88rs2000_config, &d->i2c_adap); - if (adap->fe_adap[0].fe) { + if (adap->fe[0]) { info("FE Found M88RS2000"); st->i2c_tuner_gate_w = 5; st->i2c_tuner_gate_r = 5; st->i2c_tuner_addr = 0xc0; st->tuner_config = TUNER_RS2000; - adap->fe_adap[0].fe->ops.read_signal_strength = + st->fe_set_voltage = + adap->fe[0]->ops.set_voltage; + + adap->fe[0]->ops.read_signal_strength = dm04_rs2000_read_signal_strength; - adap->fe_adap[0].fe->ops.read_snr = + adap->fe[0]->ops.read_snr = dm04_rs2000_read_snr; + adap->fe[0]->ops.read_ber = + dm04_read_ber; + adap->fe[0]->ops.read_ucblocks = + dm04_read_ucblocks; } break; } - if (adap->fe_adap[0].fe == NULL) { - info("DM04/QQBOX Not Powered up or not Supported"); - return -ENODEV; + if (adap->fe[0] == NULL) { + info("DM04/QQBOX Not Powered up or not Supported"); + return -ENODEV; } if (ret) { - if (adap->fe_adap[0].fe) { - dvb_frontend_detach(adap->fe_adap[0].fe); - adap->fe_adap[0].fe = NULL; + if (adap->fe[0]) { + dvb_frontend_detach(adap->fe[0]); + adap->fe[0] = NULL; } - adap->dev->props.rc.core.rc_codes = NULL; + d->rc_map = NULL; return -ENODEV; } - adap->fe_adap[0].fe->ops.set_voltage = dm04_lme2510_set_voltage; + adap->fe[0]->ops.set_voltage = dm04_lme2510_set_voltage; ret = lme_name(adap); return ret; } static int dm04_lme2510_tuner(struct dvb_usb_adapter *adap) { - struct lme2510_state *st = adap->dev->priv; + struct dvb_usb_device *d = adap_to_d(adap); + struct lme2510_state *st = adap_to_priv(adap); char *tun_msg[] = {"", "TDA8263", "IX2505V", "DVB_PLL_OPERA", "RS2000"}; int ret = 0; switch (st->tuner_config) { case TUNER_LG: - if (dvb_attach(tda826x_attach, adap->fe_adap[0].fe, 0xc0, - &adap->dev->i2c_adap, 1)) + if (dvb_attach(tda826x_attach, adap->fe[0], 0xc0, + &d->i2c_adap, 1)) ret = st->tuner_config; break; case TUNER_S7395: - if (dvb_attach(ix2505v_attach , adap->fe_adap[0].fe, &lme_tuner, - &adap->dev->i2c_adap)) + if (dvb_attach(ix2505v_attach , adap->fe[0], &lme_tuner, + &d->i2c_adap)) ret = st->tuner_config; break; case TUNER_S0194: - if (dvb_attach(dvb_pll_attach , adap->fe_adap[0].fe, 0xc0, - &adap->dev->i2c_adap, DVB_PLL_OPERA1)) + if (dvb_attach(dvb_pll_attach , adap->fe[0], 0xc0, + &d->i2c_adap, DVB_PLL_OPERA1)) ret = st->tuner_config; break; case TUNER_RS2000: @@ -1161,7 +1169,7 @@ static int dm04_lme2510_tuner(struct dvb_usb_adapter *adap) info("TUN Found %s tuner", tun_msg[ret]); else { info("TUN No tuner found --- resetting device"); - lme_coldreset(adap->dev->udev); + lme_coldreset(d); return -ENODEV; } @@ -1197,158 +1205,57 @@ static int lme2510_powerup(struct dvb_usb_device *d, int onoff) return ret; } -/* DVB USB Driver stuff */ -static struct dvb_usb_device_properties lme2510_properties; -static struct dvb_usb_device_properties lme2510c_properties; - -static int lme2510_probe(struct usb_interface *intf, - const struct usb_device_id *id) +static int lme2510_get_adapter_count(struct dvb_usb_device *d) { - struct usb_device *udev = interface_to_usbdev(intf); + return 1; +} - usb_reset_configuration(udev); +static int lme2510_identify_state(struct dvb_usb_device *d, const char **name) +{ + struct lme2510_state *st = d->priv; - usb_set_interface(udev, intf->cur_altsetting->desc.bInterfaceNumber, 1); + usb_reset_configuration(d->udev); - if (udev->speed != USB_SPEED_HIGH) { - usb_reset_device(udev); - info("DEV Failed to connect in HIGH SPEED mode"); - return -ENODEV; - } + usb_set_interface(d->udev, + d->intf->cur_altsetting->desc.bInterfaceNumber, 1); - if (lme2510_return_status(udev) == 0x44) { - lme_firmware_switch(udev, 0); - return -ENODEV; - } + st->dvb_usb_lme2510_firmware = dvb_usb_lme2510_firmware; - if (0 == dvb_usb_device_init(intf, &lme2510_properties, - THIS_MODULE, NULL, adapter_nr)) { - info("DEV registering device driver"); - return 0; - } - if (0 == dvb_usb_device_init(intf, &lme2510c_properties, - THIS_MODULE, NULL, adapter_nr)) { - info("DEV registering device driver"); - return 0; + if (lme2510_return_status(d) == 0x44) { + *name = lme_firmware_switch(d, 0); + return COLD; } - info("DEV lme2510 Error"); - return -ENODEV; - + return 0; } -static struct usb_device_id lme2510_table[] = { - { USB_DEVICE(0x3344, 0x1122) }, /* LME2510 */ - { USB_DEVICE(0x3344, 0x1120) }, /* LME2510C */ - { USB_DEVICE(0x3344, 0x22f0) }, /* LME2510C RS2000 */ - {} /* Terminating entry */ -}; - -MODULE_DEVICE_TABLE(usb, lme2510_table); - -static struct dvb_usb_device_properties lme2510_properties = { - .caps = DVB_USB_IS_AN_I2C_ADAPTER, - .size_of_priv = sizeof(struct lme2510_state), - .num_adapters = 1, - .adapter = { - { - .num_frontends = 1, - .fe = {{ - .caps = DVB_USB_ADAP_HAS_PID_FILTER| - DVB_USB_ADAP_NEED_PID_FILTERING| - DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, - .streaming_ctrl = lme2510_streaming_ctrl, - .pid_filter_count = 32, - .pid_filter = lme2510_pid_filter, - .pid_filter_ctrl = lme2510_pid_filter_ctrl, - .frontend_attach = dm04_lme2510_frontend_attach, - .tuner_attach = dm04_lme2510_tuner, - /* parameter for the MPEG2-data transfer */ - .stream = { - .type = USB_BULK, - .count = 10, - .endpoint = 0x06, - .u = { - .bulk = { - .buffersize = 4096, - - } - } - } - }}, - } - }, - .rc.core = { - .protocol = RC_TYPE_NEC, - .module_name = "LME2510 Remote Control", - .allowed_protos = RC_TYPE_NEC, - .rc_codes = RC_MAP_LME2510, - }, - .power_ctrl = lme2510_powerup, - .identify_state = lme2510_identify_state, - .i2c_algo = &lme2510_i2c_algo, - .generic_bulk_ctrl_endpoint = 0, - .num_device_descs = 1, - .devices = { - { "DM04_LME2510_DVB-S", - { &lme2510_table[0], NULL }, - }, +static int lme2510_get_stream_config(struct dvb_frontend *fe, u8 *ts_type, + struct usb_data_stream_properties *stream) +{ + struct dvb_usb_adapter *adap = fe_to_adap(fe); + struct dvb_usb_device *d = adap_to_d(adap); + if (adap == NULL) + return 0; + /* Turn PID filter on the fly by module option */ + if (pid_filter == 2) { + adap->pid_filtering = 1; + adap->max_feed_count = 15; } -}; -static struct dvb_usb_device_properties lme2510c_properties = { - .caps = DVB_USB_IS_AN_I2C_ADAPTER, - .size_of_priv = sizeof(struct lme2510_state), - .num_adapters = 1, - .adapter = { - { - .num_frontends = 1, - .fe = {{ - .caps = DVB_USB_ADAP_HAS_PID_FILTER| - DVB_USB_ADAP_NEED_PID_FILTERING| - DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, - .streaming_ctrl = lme2510_streaming_ctrl, - .pid_filter_count = 32, - .pid_filter = lme2510_pid_filter, - .pid_filter_ctrl = lme2510_pid_filter_ctrl, - .frontend_attach = dm04_lme2510_frontend_attach, - .tuner_attach = dm04_lme2510_tuner, - /* parameter for the MPEG2-data transfer */ - .stream = { - .type = USB_BULK, - .count = 10, - .endpoint = 0x8, - .u = { - .bulk = { - .buffersize = 4096, + if (!(le16_to_cpu(d->udev->descriptor.idProduct) + == 0x1122)) + stream->endpoint = 0x8; - } - } - } - }}, - } - }, - .rc.core = { - .protocol = RC_TYPE_NEC, - .module_name = "LME2510 Remote Control", - .allowed_protos = RC_TYPE_NEC, - .rc_codes = RC_MAP_LME2510, - }, - .power_ctrl = lme2510_powerup, - .identify_state = lme2510_identify_state, - .i2c_algo = &lme2510_i2c_algo, - .generic_bulk_ctrl_endpoint = 0, - .num_device_descs = 2, - .devices = { - { "DM04_LME2510C_DVB-S", - { &lme2510_table[1], NULL }, - }, - { "DM04_LME2510C_DVB-S RS2000", - { &lme2510_table[2], NULL }, - }, - } -}; + return 0; +} + +static int lme2510_get_rc_config(struct dvb_usb_device *d, + struct dvb_usb_rc *rc) +{ + rc->allowed_protos = RC_TYPE_NEC; + return 0; +} static void *lme2510_exit_int(struct dvb_usb_device *d) { @@ -1357,8 +1264,7 @@ static void *lme2510_exit_int(struct dvb_usb_device *d) void *buffer = NULL; if (adap != NULL) { - lme2510_kill_urb(&adap->fe_adap[0].stream); - adap->feedcount = 0; + lme2510_kill_urb(&adap->stream); } if (st->usb_buffer != NULL) { @@ -1379,29 +1285,85 @@ static void *lme2510_exit_int(struct dvb_usb_device *d) return buffer; } -static void lme2510_exit(struct usb_interface *intf) +static void lme2510_exit(struct dvb_usb_device *d) { - struct dvb_usb_device *d = usb_get_intfdata(intf); void *usb_buffer; if (d != NULL) { usb_buffer = lme2510_exit_int(d); - dvb_usb_device_exit(intf); if (usb_buffer != NULL) kfree(usb_buffer); } } +static struct dvb_usb_device_properties lme2510_props = { + .driver_name = KBUILD_MODNAME, + .owner = THIS_MODULE, + .bInterfaceNumber = 0, + .adapter_nr = adapter_nr, + .size_of_priv = sizeof(struct lme2510_state), + + .download_firmware = lme2510_download_firmware, + + .power_ctrl = lme2510_powerup, + .identify_state = lme2510_identify_state, + .i2c_algo = &lme2510_i2c_algo, + + .frontend_attach = dm04_lme2510_frontend_attach, + .tuner_attach = dm04_lme2510_tuner, + .get_stream_config = lme2510_get_stream_config, + .get_adapter_count = lme2510_get_adapter_count, + .streaming_ctrl = lme2510_streaming_ctrl, + + .get_rc_config = lme2510_get_rc_config, + + .exit = lme2510_exit, + .adapter = { + { + .caps = DVB_USB_ADAP_HAS_PID_FILTER| + DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, + .pid_filter_count = 15, + .pid_filter = lme2510_pid_filter, + .pid_filter_ctrl = lme2510_pid_filter_ctrl, + .stream = + DVB_USB_STREAM_BULK(0x86, 10, 4096), + }, + { + } + }, +}; + +static const struct usb_device_id lme2510_id_table[] = { + { DVB_USB_DEVICE(0x3344, 0x1122, &lme2510_props, + "DM04_LME2510_DVB-S", RC_MAP_LME2510) }, + { DVB_USB_DEVICE(0x3344, 0x1120, &lme2510_props, + "DM04_LME2510C_DVB-S", RC_MAP_LME2510) }, + { DVB_USB_DEVICE(0x3344, 0x22f0, &lme2510_props, + "DM04_LME2510C_DVB-S RS2000", RC_MAP_LME2510) }, + {} /* Terminating entry */ +}; + +MODULE_DEVICE_TABLE(usb, lme2510_id_table); + static struct usb_driver lme2510_driver = { - .name = "LME2510C_DVB-S", - .probe = lme2510_probe, - .disconnect = lme2510_exit, - .id_table = lme2510_table, + .name = KBUILD_MODNAME, + .probe = dvb_usbv2_probe, + .disconnect = dvb_usbv2_disconnect, + .id_table = lme2510_id_table, + .no_dynamic_id = 1, + .soft_unbind = 1, }; module_usb_driver(lme2510_driver); MODULE_AUTHOR("Malcolm Priestley <tvboxspy@gmail.com>"); MODULE_DESCRIPTION("LME2510(C) DVB-S USB2.0"); -MODULE_VERSION("1.99"); +MODULE_VERSION("2.06"); MODULE_LICENSE("GPL"); +MODULE_FIRMWARE(LME2510_C_S7395); +MODULE_FIRMWARE(LME2510_C_LG); +MODULE_FIRMWARE(LME2510_C_S0194); +MODULE_FIRMWARE(LME2510_C_RS2000); +MODULE_FIRMWARE(LME2510_LG); +MODULE_FIRMWARE(LME2510_S0194); + diff --git a/drivers/media/dvb/dvb-usb/lmedm04.h b/drivers/media/usb/dvb-usb-v2/lmedm04.h index e9c207205c2f..e9c207205c2f 100644 --- a/drivers/media/dvb/dvb-usb/lmedm04.h +++ b/drivers/media/usb/dvb-usb-v2/lmedm04.h diff --git a/drivers/media/dvb/dvb-usb/mxl111sf-demod.c b/drivers/media/usb/dvb-usb-v2/mxl111sf-demod.c index d83df4bb72d3..d83df4bb72d3 100644 --- a/drivers/media/dvb/dvb-usb/mxl111sf-demod.c +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf-demod.c diff --git a/drivers/media/dvb/dvb-usb/mxl111sf-demod.h b/drivers/media/usb/dvb-usb-v2/mxl111sf-demod.h index 432706ae5274..432706ae5274 100644 --- a/drivers/media/dvb/dvb-usb/mxl111sf-demod.h +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf-demod.h diff --git a/drivers/media/dvb/dvb-usb/mxl111sf-gpio.c b/drivers/media/usb/dvb-usb-v2/mxl111sf-gpio.c index e4121cb8f5ef..e4121cb8f5ef 100644 --- a/drivers/media/dvb/dvb-usb/mxl111sf-gpio.c +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf-gpio.c diff --git a/drivers/media/dvb/dvb-usb/mxl111sf-gpio.h b/drivers/media/usb/dvb-usb-v2/mxl111sf-gpio.h index 0220f54299a5..0220f54299a5 100644 --- a/drivers/media/dvb/dvb-usb/mxl111sf-gpio.h +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf-gpio.h diff --git a/drivers/media/dvb/dvb-usb/mxl111sf-i2c.c b/drivers/media/usb/dvb-usb-v2/mxl111sf-i2c.c index 34434557ef65..34434557ef65 100644 --- a/drivers/media/dvb/dvb-usb/mxl111sf-i2c.c +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf-i2c.c diff --git a/drivers/media/dvb/dvb-usb/mxl111sf-i2c.h b/drivers/media/usb/dvb-usb-v2/mxl111sf-i2c.h index a57a45ffb9e4..a57a45ffb9e4 100644 --- a/drivers/media/dvb/dvb-usb/mxl111sf-i2c.h +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf-i2c.h diff --git a/drivers/media/dvb/dvb-usb/mxl111sf-phy.c b/drivers/media/usb/dvb-usb-v2/mxl111sf-phy.c index b741b3a7a325..b741b3a7a325 100644 --- a/drivers/media/dvb/dvb-usb/mxl111sf-phy.c +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf-phy.c diff --git a/drivers/media/dvb/dvb-usb/mxl111sf-phy.h b/drivers/media/usb/dvb-usb-v2/mxl111sf-phy.h index f0756071d347..f0756071d347 100644 --- a/drivers/media/dvb/dvb-usb/mxl111sf-phy.h +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf-phy.h diff --git a/drivers/media/dvb/dvb-usb/mxl111sf-reg.h b/drivers/media/usb/dvb-usb-v2/mxl111sf-reg.h index 17831b0fb9db..17831b0fb9db 100644 --- a/drivers/media/dvb/dvb-usb/mxl111sf-reg.h +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf-reg.h diff --git a/drivers/media/dvb/dvb-usb/mxl111sf-tuner.c b/drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.c index 74da5bb1ce99..ef4c65fcbb73 100644 --- a/drivers/media/dvb/dvb-usb/mxl111sf-tuner.c +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.c @@ -31,6 +31,8 @@ MODULE_PARM_DESC(debug, "set debugging level (1=info (or-able))."); if (mxl111sf_tuner_debug) \ mxl_printk(KERN_DEBUG, fmt, ##arg) +#define err pr_err + /* ------------------------------------------------------------------------ */ struct mxl111sf_tuner_state { diff --git a/drivers/media/dvb/dvb-usb/mxl111sf-tuner.h b/drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.h index ff333960b184..ff333960b184 100644 --- a/drivers/media/dvb/dvb-usb/mxl111sf-tuner.h +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.h diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf.c b/drivers/media/usb/dvb-usb-v2/mxl111sf.c new file mode 100644 index 000000000000..efdcb15358f1 --- /dev/null +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf.c @@ -0,0 +1,1431 @@ +/* + * Copyright (C) 2010 Michael Krufky (mkrufky@kernellabs.com) + * + * 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, version 2. + * + * see Documentation/dvb/README.dvb-usb for more information + */ + +#include <linux/vmalloc.h> +#include <linux/i2c.h> + +#include "mxl111sf.h" +#include "mxl111sf-reg.h" +#include "mxl111sf-phy.h" +#include "mxl111sf-i2c.h" +#include "mxl111sf-gpio.h" + +#include "mxl111sf-demod.h" +#include "mxl111sf-tuner.h" + +#include "lgdt3305.h" +#include "lg2160.h" + +int dvb_usb_mxl111sf_debug; +module_param_named(debug, dvb_usb_mxl111sf_debug, int, 0644); +MODULE_PARM_DESC(debug, "set debugging level " + "(1=info, 2=xfer, 4=i2c, 8=reg, 16=adv (or-able))."); + +int dvb_usb_mxl111sf_isoc; +module_param_named(isoc, dvb_usb_mxl111sf_isoc, int, 0644); +MODULE_PARM_DESC(isoc, "enable usb isoc xfer (0=bulk, 1=isoc)."); + +int dvb_usb_mxl111sf_spi; +module_param_named(spi, dvb_usb_mxl111sf_spi, int, 0644); +MODULE_PARM_DESC(spi, "use spi rather than tp for data xfer (0=tp, 1=spi)."); + +#define ANT_PATH_AUTO 0 +#define ANT_PATH_EXTERNAL 1 +#define ANT_PATH_INTERNAL 2 + +int dvb_usb_mxl111sf_rfswitch = +#if 0 + ANT_PATH_AUTO; +#else + ANT_PATH_EXTERNAL; +#endif + +module_param_named(rfswitch, dvb_usb_mxl111sf_rfswitch, int, 0644); +MODULE_PARM_DESC(rfswitch, "force rf switch position (0=auto, 1=ext, 2=int)."); + +DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); + +#define deb_info pr_debug +#define deb_reg pr_debug +#define deb_adv pr_debug +#define err pr_err +#define info pr_info + +int mxl111sf_ctrl_msg(struct dvb_usb_device *d, + u8 cmd, u8 *wbuf, int wlen, u8 *rbuf, int rlen) +{ + int wo = (rbuf == NULL || rlen == 0); /* write-only */ + int ret; + u8 sndbuf[1+wlen]; + + deb_adv("%s(wlen = %d, rlen = %d)\n", __func__, wlen, rlen); + + memset(sndbuf, 0, 1+wlen); + + sndbuf[0] = cmd; + memcpy(&sndbuf[1], wbuf, wlen); + + ret = (wo) ? dvb_usbv2_generic_write(d, sndbuf, 1+wlen) : + dvb_usbv2_generic_rw(d, sndbuf, 1+wlen, rbuf, rlen); + mxl_fail(ret); + + return ret; +} + +/* ------------------------------------------------------------------------ */ + +#define MXL_CMD_REG_READ 0xaa +#define MXL_CMD_REG_WRITE 0x55 + +int mxl111sf_read_reg(struct mxl111sf_state *state, u8 addr, u8 *data) +{ + u8 buf[2]; + int ret; + + ret = mxl111sf_ctrl_msg(state->d, MXL_CMD_REG_READ, &addr, 1, buf, 2); + if (mxl_fail(ret)) { + mxl_debug("error reading reg: 0x%02x", addr); + goto fail; + } + + if (buf[0] == addr) + *data = buf[1]; + else { + err("invalid response reading reg: 0x%02x != 0x%02x, 0x%02x", + addr, buf[0], buf[1]); + ret = -EINVAL; + } + + deb_reg("R: (0x%02x, 0x%02x)\n", addr, *data); +fail: + return ret; +} + +int mxl111sf_write_reg(struct mxl111sf_state *state, u8 addr, u8 data) +{ + u8 buf[] = { addr, data }; + int ret; + + deb_reg("W: (0x%02x, 0x%02x)\n", addr, data); + + ret = mxl111sf_ctrl_msg(state->d, MXL_CMD_REG_WRITE, buf, 2, NULL, 0); + if (mxl_fail(ret)) + err("error writing reg: 0x%02x, val: 0x%02x", addr, data); + return ret; +} + +/* ------------------------------------------------------------------------ */ + +int mxl111sf_write_reg_mask(struct mxl111sf_state *state, + u8 addr, u8 mask, u8 data) +{ + int ret; + u8 val; + + if (mask != 0xff) { + ret = mxl111sf_read_reg(state, addr, &val); +#if 1 + /* dont know why this usually errors out on the first try */ + if (mxl_fail(ret)) + err("error writing addr: 0x%02x, mask: 0x%02x, " + "data: 0x%02x, retrying...", addr, mask, data); + + ret = mxl111sf_read_reg(state, addr, &val); +#endif + if (mxl_fail(ret)) + goto fail; + } + val &= ~mask; + val |= data; + + ret = mxl111sf_write_reg(state, addr, val); + mxl_fail(ret); +fail: + return ret; +} + +/* ------------------------------------------------------------------------ */ + +int mxl111sf_ctrl_program_regs(struct mxl111sf_state *state, + struct mxl111sf_reg_ctrl_info *ctrl_reg_info) +{ + int i, ret = 0; + + for (i = 0; ctrl_reg_info[i].addr | + ctrl_reg_info[i].mask | + ctrl_reg_info[i].data; i++) { + + ret = mxl111sf_write_reg_mask(state, + ctrl_reg_info[i].addr, + ctrl_reg_info[i].mask, + ctrl_reg_info[i].data); + if (mxl_fail(ret)) { + err("failed on reg #%d (0x%02x)", i, + ctrl_reg_info[i].addr); + break; + } + } + return ret; +} + +/* ------------------------------------------------------------------------ */ + +static int mxl1x1sf_get_chip_info(struct mxl111sf_state *state) +{ + int ret; + u8 id, ver; + char *mxl_chip, *mxl_rev; + + if ((state->chip_id) && (state->chip_ver)) + return 0; + + ret = mxl111sf_read_reg(state, CHIP_ID_REG, &id); + if (mxl_fail(ret)) + goto fail; + state->chip_id = id; + + ret = mxl111sf_read_reg(state, TOP_CHIP_REV_ID_REG, &ver); + if (mxl_fail(ret)) + goto fail; + state->chip_ver = ver; + + switch (id) { + case 0x61: + mxl_chip = "MxL101SF"; + break; + case 0x63: + mxl_chip = "MxL111SF"; + break; + default: + mxl_chip = "UNKNOWN MxL1X1"; + break; + } + switch (ver) { + case 0x36: + state->chip_rev = MXL111SF_V6; + mxl_rev = "v6"; + break; + case 0x08: + state->chip_rev = MXL111SF_V8_100; + mxl_rev = "v8_100"; + break; + case 0x18: + state->chip_rev = MXL111SF_V8_200; + mxl_rev = "v8_200"; + break; + default: + state->chip_rev = 0; + mxl_rev = "UNKNOWN REVISION"; + break; + } + info("%s detected, %s (0x%x)", mxl_chip, mxl_rev, ver); +fail: + return ret; +} + +#define get_chip_info(state) \ +({ \ + int ___ret; \ + ___ret = mxl1x1sf_get_chip_info(state); \ + if (mxl_fail(___ret)) { \ + mxl_debug("failed to get chip info" \ + " on first probe attempt"); \ + ___ret = mxl1x1sf_get_chip_info(state); \ + if (mxl_fail(___ret)) \ + err("failed to get chip info during probe"); \ + else \ + mxl_debug("probe needed a retry " \ + "in order to succeed."); \ + } \ + ___ret; \ +}) + +/* ------------------------------------------------------------------------ */ +#if 0 +static int mxl111sf_power_ctrl(struct dvb_usb_device *d, int onoff) +{ + /* power control depends on which adapter is being woken: + * save this for init, instead, via mxl111sf_adap_fe_init */ + return 0; +} +#endif + +static int mxl111sf_adap_fe_init(struct dvb_frontend *fe) +{ + struct dvb_usb_device *d = fe_to_d(fe); + struct mxl111sf_state *state = fe_to_priv(fe); + struct mxl111sf_adap_state *adap_state = &state->adap_state[fe->id]; + int err; + + /* exit if we didnt initialize the driver yet */ + if (!state->chip_id) { + mxl_debug("driver not yet initialized, exit."); + goto fail; + } + + deb_info("%s()\n", __func__); + + mutex_lock(&state->fe_lock); + + state->alt_mode = adap_state->alt_mode; + + if (usb_set_interface(d->udev, 0, state->alt_mode) < 0) + err("set interface failed"); + + err = mxl1x1sf_soft_reset(state); + mxl_fail(err); + err = mxl111sf_init_tuner_demod(state); + mxl_fail(err); + err = mxl1x1sf_set_device_mode(state, adap_state->device_mode); + + mxl_fail(err); + mxl111sf_enable_usb_output(state); + mxl_fail(err); + mxl1x1sf_top_master_ctrl(state, 1); + mxl_fail(err); + + if ((MXL111SF_GPIO_MOD_DVBT != adap_state->gpio_mode) && + (state->chip_rev > MXL111SF_V6)) { + mxl111sf_config_pin_mux_modes(state, + PIN_MUX_TS_SPI_IN_MODE_1); + mxl_fail(err); + } + err = mxl111sf_init_port_expander(state); + if (!mxl_fail(err)) { + state->gpio_mode = adap_state->gpio_mode; + err = mxl111sf_gpio_mode_switch(state, state->gpio_mode); + mxl_fail(err); +#if 0 + err = fe->ops.init(fe); +#endif + msleep(100); /* add short delay after enabling + * the demod before touching it */ + } + + return (adap_state->fe_init) ? adap_state->fe_init(fe) : 0; +fail: + return -ENODEV; +} + +static int mxl111sf_adap_fe_sleep(struct dvb_frontend *fe) +{ + struct mxl111sf_state *state = fe_to_priv(fe); + struct mxl111sf_adap_state *adap_state = &state->adap_state[fe->id]; + int err; + + /* exit if we didnt initialize the driver yet */ + if (!state->chip_id) { + mxl_debug("driver not yet initialized, exit."); + goto fail; + } + + deb_info("%s()\n", __func__); + + err = (adap_state->fe_sleep) ? adap_state->fe_sleep(fe) : 0; + + mutex_unlock(&state->fe_lock); + + return err; +fail: + return -ENODEV; +} + + +static int mxl111sf_ep6_streaming_ctrl(struct dvb_frontend *fe, int onoff) +{ + struct mxl111sf_state *state = fe_to_priv(fe); + struct mxl111sf_adap_state *adap_state = &state->adap_state[fe->id]; + int ret = 0; + + deb_info("%s(%d)\n", __func__, onoff); + + if (onoff) { + ret = mxl111sf_enable_usb_output(state); + mxl_fail(ret); + ret = mxl111sf_config_mpeg_in(state, 1, 1, + adap_state->ep6_clockphase, + 0, 0); + mxl_fail(ret); +#if 0 + } else { + ret = mxl111sf_disable_656_port(state); + mxl_fail(ret); +#endif + } + + return ret; +} + +static int mxl111sf_ep5_streaming_ctrl(struct dvb_frontend *fe, int onoff) +{ + struct mxl111sf_state *state = fe_to_priv(fe); + int ret = 0; + + deb_info("%s(%d)\n", __func__, onoff); + + if (onoff) { + ret = mxl111sf_enable_usb_output(state); + mxl_fail(ret); + + ret = mxl111sf_init_i2s_port(state, 200); + mxl_fail(ret); + ret = mxl111sf_config_i2s(state, 0, 15); + mxl_fail(ret); + } else { + ret = mxl111sf_disable_i2s_port(state); + mxl_fail(ret); + } + if (state->chip_rev > MXL111SF_V6) + ret = mxl111sf_config_spi(state, onoff); + mxl_fail(ret); + + return ret; +} + +static int mxl111sf_ep4_streaming_ctrl(struct dvb_frontend *fe, int onoff) +{ + struct mxl111sf_state *state = fe_to_priv(fe); + int ret = 0; + + deb_info("%s(%d)\n", __func__, onoff); + + if (onoff) { + ret = mxl111sf_enable_usb_output(state); + mxl_fail(ret); + } + + return ret; +} + +/* ------------------------------------------------------------------------ */ + +static struct lgdt3305_config hauppauge_lgdt3305_config = { + .i2c_addr = 0xb2 >> 1, + .mpeg_mode = LGDT3305_MPEG_SERIAL, + .tpclk_edge = LGDT3305_TPCLK_RISING_EDGE, + .tpvalid_polarity = LGDT3305_TP_VALID_HIGH, + .deny_i2c_rptr = 1, + .spectral_inversion = 0, + .qam_if_khz = 6000, + .vsb_if_khz = 6000, +}; + +static int mxl111sf_lgdt3305_frontend_attach(struct dvb_usb_adapter *adap, u8 fe_id) +{ + struct dvb_usb_device *d = adap_to_d(adap); + struct mxl111sf_state *state = d_to_priv(d); + struct mxl111sf_adap_state *adap_state = &state->adap_state[fe_id]; + int ret; + + deb_adv("%s()\n", __func__); + + /* save a pointer to the dvb_usb_device in device state */ + state->d = d; + adap_state->alt_mode = (dvb_usb_mxl111sf_isoc) ? 2 : 1; + state->alt_mode = adap_state->alt_mode; + + if (usb_set_interface(d->udev, 0, state->alt_mode) < 0) + err("set interface failed"); + + state->gpio_mode = MXL111SF_GPIO_MOD_ATSC; + adap_state->gpio_mode = state->gpio_mode; + adap_state->device_mode = MXL_TUNER_MODE; + adap_state->ep6_clockphase = 1; + + ret = mxl1x1sf_soft_reset(state); + if (mxl_fail(ret)) + goto fail; + ret = mxl111sf_init_tuner_demod(state); + if (mxl_fail(ret)) + goto fail; + + ret = mxl1x1sf_set_device_mode(state, adap_state->device_mode); + if (mxl_fail(ret)) + goto fail; + + ret = mxl111sf_enable_usb_output(state); + if (mxl_fail(ret)) + goto fail; + ret = mxl1x1sf_top_master_ctrl(state, 1); + if (mxl_fail(ret)) + goto fail; + + ret = mxl111sf_init_port_expander(state); + if (mxl_fail(ret)) + goto fail; + ret = mxl111sf_gpio_mode_switch(state, state->gpio_mode); + if (mxl_fail(ret)) + goto fail; + + adap->fe[fe_id] = dvb_attach(lgdt3305_attach, + &hauppauge_lgdt3305_config, + &d->i2c_adap); + if (adap->fe[fe_id]) { + state->num_frontends++; + adap_state->fe_init = adap->fe[fe_id]->ops.init; + adap->fe[fe_id]->ops.init = mxl111sf_adap_fe_init; + adap_state->fe_sleep = adap->fe[fe_id]->ops.sleep; + adap->fe[fe_id]->ops.sleep = mxl111sf_adap_fe_sleep; + return 0; + } + ret = -EIO; +fail: + return ret; +} + +static struct lg2160_config hauppauge_lg2160_config = { + .lg_chip = LG2160, + .i2c_addr = 0x1c >> 1, + .deny_i2c_rptr = 1, + .spectral_inversion = 0, + .if_khz = 6000, +}; + +static int mxl111sf_lg2160_frontend_attach(struct dvb_usb_adapter *adap, u8 fe_id) +{ + struct dvb_usb_device *d = adap_to_d(adap); + struct mxl111sf_state *state = d_to_priv(d); + struct mxl111sf_adap_state *adap_state = &state->adap_state[fe_id]; + int ret; + + deb_adv("%s()\n", __func__); + + /* save a pointer to the dvb_usb_device in device state */ + state->d = d; + adap_state->alt_mode = (dvb_usb_mxl111sf_isoc) ? 2 : 1; + state->alt_mode = adap_state->alt_mode; + + if (usb_set_interface(d->udev, 0, state->alt_mode) < 0) + err("set interface failed"); + + state->gpio_mode = MXL111SF_GPIO_MOD_MH; + adap_state->gpio_mode = state->gpio_mode; + adap_state->device_mode = MXL_TUNER_MODE; + adap_state->ep6_clockphase = 1; + + ret = mxl1x1sf_soft_reset(state); + if (mxl_fail(ret)) + goto fail; + ret = mxl111sf_init_tuner_demod(state); + if (mxl_fail(ret)) + goto fail; + + ret = mxl1x1sf_set_device_mode(state, adap_state->device_mode); + if (mxl_fail(ret)) + goto fail; + + ret = mxl111sf_enable_usb_output(state); + if (mxl_fail(ret)) + goto fail; + ret = mxl1x1sf_top_master_ctrl(state, 1); + if (mxl_fail(ret)) + goto fail; + + ret = mxl111sf_init_port_expander(state); + if (mxl_fail(ret)) + goto fail; + ret = mxl111sf_gpio_mode_switch(state, state->gpio_mode); + if (mxl_fail(ret)) + goto fail; + + ret = get_chip_info(state); + if (mxl_fail(ret)) + goto fail; + + adap->fe[fe_id] = dvb_attach(lg2160_attach, + &hauppauge_lg2160_config, + &d->i2c_adap); + if (adap->fe[fe_id]) { + state->num_frontends++; + adap_state->fe_init = adap->fe[fe_id]->ops.init; + adap->fe[fe_id]->ops.init = mxl111sf_adap_fe_init; + adap_state->fe_sleep = adap->fe[fe_id]->ops.sleep; + adap->fe[fe_id]->ops.sleep = mxl111sf_adap_fe_sleep; + return 0; + } + ret = -EIO; +fail: + return ret; +} + +static struct lg2160_config hauppauge_lg2161_1019_config = { + .lg_chip = LG2161_1019, + .i2c_addr = 0x1c >> 1, + .deny_i2c_rptr = 1, + .spectral_inversion = 0, + .if_khz = 6000, + .output_if = 2, /* LG2161_OIF_SPI_MAS */ +}; + +static struct lg2160_config hauppauge_lg2161_1040_config = { + .lg_chip = LG2161_1040, + .i2c_addr = 0x1c >> 1, + .deny_i2c_rptr = 1, + .spectral_inversion = 0, + .if_khz = 6000, + .output_if = 4, /* LG2161_OIF_SPI_MAS */ +}; + +static int mxl111sf_lg2161_frontend_attach(struct dvb_usb_adapter *adap, u8 fe_id) +{ + struct dvb_usb_device *d = adap_to_d(adap); + struct mxl111sf_state *state = d_to_priv(d); + struct mxl111sf_adap_state *adap_state = &state->adap_state[fe_id]; + int ret; + + deb_adv("%s()\n", __func__); + + /* save a pointer to the dvb_usb_device in device state */ + state->d = d; + adap_state->alt_mode = (dvb_usb_mxl111sf_isoc) ? 2 : 1; + state->alt_mode = adap_state->alt_mode; + + if (usb_set_interface(d->udev, 0, state->alt_mode) < 0) + err("set interface failed"); + + state->gpio_mode = MXL111SF_GPIO_MOD_MH; + adap_state->gpio_mode = state->gpio_mode; + adap_state->device_mode = MXL_TUNER_MODE; + adap_state->ep6_clockphase = 1; + + ret = mxl1x1sf_soft_reset(state); + if (mxl_fail(ret)) + goto fail; + ret = mxl111sf_init_tuner_demod(state); + if (mxl_fail(ret)) + goto fail; + + ret = mxl1x1sf_set_device_mode(state, adap_state->device_mode); + if (mxl_fail(ret)) + goto fail; + + ret = mxl111sf_enable_usb_output(state); + if (mxl_fail(ret)) + goto fail; + ret = mxl1x1sf_top_master_ctrl(state, 1); + if (mxl_fail(ret)) + goto fail; + + ret = mxl111sf_init_port_expander(state); + if (mxl_fail(ret)) + goto fail; + ret = mxl111sf_gpio_mode_switch(state, state->gpio_mode); + if (mxl_fail(ret)) + goto fail; + + ret = get_chip_info(state); + if (mxl_fail(ret)) + goto fail; + + adap->fe[fe_id] = dvb_attach(lg2160_attach, + (MXL111SF_V8_200 == state->chip_rev) ? + &hauppauge_lg2161_1040_config : + &hauppauge_lg2161_1019_config, + &d->i2c_adap); + if (adap->fe[fe_id]) { + state->num_frontends++; + adap_state->fe_init = adap->fe[fe_id]->ops.init; + adap->fe[fe_id]->ops.init = mxl111sf_adap_fe_init; + adap_state->fe_sleep = adap->fe[fe_id]->ops.sleep; + adap->fe[fe_id]->ops.sleep = mxl111sf_adap_fe_sleep; + return 0; + } + ret = -EIO; +fail: + return ret; +} + +static struct lg2160_config hauppauge_lg2161_1019_ep6_config = { + .lg_chip = LG2161_1019, + .i2c_addr = 0x1c >> 1, + .deny_i2c_rptr = 1, + .spectral_inversion = 0, + .if_khz = 6000, + .output_if = 1, /* LG2161_OIF_SERIAL_TS */ +}; + +static struct lg2160_config hauppauge_lg2161_1040_ep6_config = { + .lg_chip = LG2161_1040, + .i2c_addr = 0x1c >> 1, + .deny_i2c_rptr = 1, + .spectral_inversion = 0, + .if_khz = 6000, + .output_if = 7, /* LG2161_OIF_SERIAL_TS */ +}; + +static int mxl111sf_lg2161_ep6_frontend_attach(struct dvb_usb_adapter *adap, u8 fe_id) +{ + struct dvb_usb_device *d = adap_to_d(adap); + struct mxl111sf_state *state = d_to_priv(d); + struct mxl111sf_adap_state *adap_state = &state->adap_state[fe_id]; + int ret; + + deb_adv("%s()\n", __func__); + + /* save a pointer to the dvb_usb_device in device state */ + state->d = d; + adap_state->alt_mode = (dvb_usb_mxl111sf_isoc) ? 2 : 1; + state->alt_mode = adap_state->alt_mode; + + if (usb_set_interface(d->udev, 0, state->alt_mode) < 0) + err("set interface failed"); + + state->gpio_mode = MXL111SF_GPIO_MOD_MH; + adap_state->gpio_mode = state->gpio_mode; + adap_state->device_mode = MXL_TUNER_MODE; + adap_state->ep6_clockphase = 0; + + ret = mxl1x1sf_soft_reset(state); + if (mxl_fail(ret)) + goto fail; + ret = mxl111sf_init_tuner_demod(state); + if (mxl_fail(ret)) + goto fail; + + ret = mxl1x1sf_set_device_mode(state, adap_state->device_mode); + if (mxl_fail(ret)) + goto fail; + + ret = mxl111sf_enable_usb_output(state); + if (mxl_fail(ret)) + goto fail; + ret = mxl1x1sf_top_master_ctrl(state, 1); + if (mxl_fail(ret)) + goto fail; + + ret = mxl111sf_init_port_expander(state); + if (mxl_fail(ret)) + goto fail; + ret = mxl111sf_gpio_mode_switch(state, state->gpio_mode); + if (mxl_fail(ret)) + goto fail; + + ret = get_chip_info(state); + if (mxl_fail(ret)) + goto fail; + + adap->fe[fe_id] = dvb_attach(lg2160_attach, + (MXL111SF_V8_200 == state->chip_rev) ? + &hauppauge_lg2161_1040_ep6_config : + &hauppauge_lg2161_1019_ep6_config, + &d->i2c_adap); + if (adap->fe[fe_id]) { + state->num_frontends++; + adap_state->fe_init = adap->fe[fe_id]->ops.init; + adap->fe[fe_id]->ops.init = mxl111sf_adap_fe_init; + adap_state->fe_sleep = adap->fe[fe_id]->ops.sleep; + adap->fe[fe_id]->ops.sleep = mxl111sf_adap_fe_sleep; + return 0; + } + ret = -EIO; +fail: + return ret; +} + +static struct mxl111sf_demod_config mxl_demod_config = { + .read_reg = mxl111sf_read_reg, + .write_reg = mxl111sf_write_reg, + .program_regs = mxl111sf_ctrl_program_regs, +}; + +static int mxl111sf_attach_demod(struct dvb_usb_adapter *adap, u8 fe_id) +{ + struct dvb_usb_device *d = adap_to_d(adap); + struct mxl111sf_state *state = d_to_priv(d); + struct mxl111sf_adap_state *adap_state = &state->adap_state[fe_id]; + int ret; + + deb_adv("%s()\n", __func__); + + /* save a pointer to the dvb_usb_device in device state */ + state->d = d; + adap_state->alt_mode = (dvb_usb_mxl111sf_isoc) ? 1 : 2; + state->alt_mode = adap_state->alt_mode; + + if (usb_set_interface(d->udev, 0, state->alt_mode) < 0) + err("set interface failed"); + + state->gpio_mode = MXL111SF_GPIO_MOD_DVBT; + adap_state->gpio_mode = state->gpio_mode; + adap_state->device_mode = MXL_SOC_MODE; + adap_state->ep6_clockphase = 1; + + ret = mxl1x1sf_soft_reset(state); + if (mxl_fail(ret)) + goto fail; + ret = mxl111sf_init_tuner_demod(state); + if (mxl_fail(ret)) + goto fail; + + ret = mxl1x1sf_set_device_mode(state, adap_state->device_mode); + if (mxl_fail(ret)) + goto fail; + + ret = mxl111sf_enable_usb_output(state); + if (mxl_fail(ret)) + goto fail; + ret = mxl1x1sf_top_master_ctrl(state, 1); + if (mxl_fail(ret)) + goto fail; + + /* dont care if this fails */ + mxl111sf_init_port_expander(state); + + adap->fe[fe_id] = dvb_attach(mxl111sf_demod_attach, state, + &mxl_demod_config); + if (adap->fe[fe_id]) { + state->num_frontends++; + adap_state->fe_init = adap->fe[fe_id]->ops.init; + adap->fe[fe_id]->ops.init = mxl111sf_adap_fe_init; + adap_state->fe_sleep = adap->fe[fe_id]->ops.sleep; + adap->fe[fe_id]->ops.sleep = mxl111sf_adap_fe_sleep; + return 0; + } + ret = -EIO; +fail: + return ret; +} + +static inline int mxl111sf_set_ant_path(struct mxl111sf_state *state, + int antpath) +{ + return mxl111sf_idac_config(state, 1, 1, + (antpath == ANT_PATH_INTERNAL) ? + 0x3f : 0x00, 0); +} + +#define DbgAntHunt(x, pwr0, pwr1, pwr2, pwr3) \ + err("%s(%d) FINAL input set to %s rxPwr:%d|%d|%d|%d\n", \ + __func__, __LINE__, \ + (ANT_PATH_EXTERNAL == x) ? "EXTERNAL" : "INTERNAL", \ + pwr0, pwr1, pwr2, pwr3) + +#define ANT_HUNT_SLEEP 90 +#define ANT_EXT_TWEAK 0 + +static int mxl111sf_ant_hunt(struct dvb_frontend *fe) +{ + struct mxl111sf_state *state = fe_to_priv(fe); + int antctrl = dvb_usb_mxl111sf_rfswitch; + + u16 rxPwrA, rxPwr0, rxPwr1, rxPwr2; + + /* FIXME: must force EXTERNAL for QAM - done elsewhere */ + mxl111sf_set_ant_path(state, antctrl == ANT_PATH_AUTO ? + ANT_PATH_EXTERNAL : antctrl); + + if (antctrl == ANT_PATH_AUTO) { +#if 0 + msleep(ANT_HUNT_SLEEP); +#endif + fe->ops.tuner_ops.get_rf_strength(fe, &rxPwrA); + + mxl111sf_set_ant_path(state, ANT_PATH_EXTERNAL); + msleep(ANT_HUNT_SLEEP); + fe->ops.tuner_ops.get_rf_strength(fe, &rxPwr0); + + mxl111sf_set_ant_path(state, ANT_PATH_EXTERNAL); + msleep(ANT_HUNT_SLEEP); + fe->ops.tuner_ops.get_rf_strength(fe, &rxPwr1); + + mxl111sf_set_ant_path(state, ANT_PATH_INTERNAL); + msleep(ANT_HUNT_SLEEP); + fe->ops.tuner_ops.get_rf_strength(fe, &rxPwr2); + + if (rxPwr1+ANT_EXT_TWEAK >= rxPwr2) { + /* return with EXTERNAL enabled */ + mxl111sf_set_ant_path(state, ANT_PATH_EXTERNAL); + DbgAntHunt(ANT_PATH_EXTERNAL, rxPwrA, + rxPwr0, rxPwr1, rxPwr2); + } else { + /* return with INTERNAL enabled */ + DbgAntHunt(ANT_PATH_INTERNAL, rxPwrA, + rxPwr0, rxPwr1, rxPwr2); + } + } + return 0; +} + +static struct mxl111sf_tuner_config mxl_tuner_config = { + .if_freq = MXL_IF_6_0, /* applies to external IF output, only */ + .invert_spectrum = 0, + .read_reg = mxl111sf_read_reg, + .write_reg = mxl111sf_write_reg, + .program_regs = mxl111sf_ctrl_program_regs, + .top_master_ctrl = mxl1x1sf_top_master_ctrl, + .ant_hunt = mxl111sf_ant_hunt, +}; + +static int mxl111sf_attach_tuner(struct dvb_usb_adapter *adap) +{ + struct mxl111sf_state *state = adap_to_priv(adap); + int i; + + deb_adv("%s()\n", __func__); + + for (i = 0; i < state->num_frontends; i++) { + if (dvb_attach(mxl111sf_tuner_attach, adap->fe[i], state, + &mxl_tuner_config) == NULL) + return -EIO; + adap->fe[i]->ops.read_signal_strength = adap->fe[i]->ops.tuner_ops.get_rf_strength; + } + + return 0; +} + +static u32 mxl111sf_i2c_func(struct i2c_adapter *adapter) +{ + return I2C_FUNC_I2C; +} + +struct i2c_algorithm mxl111sf_i2c_algo = { + .master_xfer = mxl111sf_i2c_xfer, + .functionality = mxl111sf_i2c_func, +#ifdef NEED_ALGO_CONTROL + .algo_control = dummy_algo_control, +#endif +}; + +static int mxl111sf_init(struct dvb_usb_device *d) +{ + struct mxl111sf_state *state = d_to_priv(d); + int ret; + static u8 eeprom[256]; + struct i2c_client c; + + ret = get_chip_info(state); + if (mxl_fail(ret)) + err("failed to get chip info during probe"); + + mutex_init(&state->fe_lock); + + if (state->chip_rev > MXL111SF_V6) + mxl111sf_config_pin_mux_modes(state, PIN_MUX_TS_SPI_IN_MODE_1); + + c.adapter = &d->i2c_adap; + c.addr = 0xa0 >> 1; + + ret = tveeprom_read(&c, eeprom, sizeof(eeprom)); + if (mxl_fail(ret)) + return 0; + tveeprom_hauppauge_analog(&c, &state->tv, (0x84 == eeprom[0xa0]) ? + eeprom + 0xa0 : eeprom + 0x80); +#if 0 + switch (state->tv.model) { + case 117001: + case 126001: + case 138001: + break; + default: + printk(KERN_WARNING "%s: warning: " + "unknown hauppauge model #%d\n", + __func__, state->tv.model); + } +#endif + return 0; +} + +static int mxl111sf_frontend_attach_dvbt(struct dvb_usb_adapter *adap) +{ + return mxl111sf_attach_demod(adap, 0); +} + +static int mxl111sf_frontend_attach_atsc(struct dvb_usb_adapter *adap) +{ + return mxl111sf_lgdt3305_frontend_attach(adap, 0); +} + +static int mxl111sf_frontend_attach_mh(struct dvb_usb_adapter *adap) +{ + return mxl111sf_lg2160_frontend_attach(adap, 0); +} + +static int mxl111sf_frontend_attach_atsc_mh(struct dvb_usb_adapter *adap) +{ + int ret; + deb_info("%s\n", __func__); + + ret = mxl111sf_lgdt3305_frontend_attach(adap, 0); + if (ret < 0) + return ret; + + ret = mxl111sf_attach_demod(adap, 1); + if (ret < 0) + return ret; + + ret = mxl111sf_lg2160_frontend_attach(adap, 2); + if (ret < 0) + return ret; + + return ret; +} + +static int mxl111sf_frontend_attach_mercury(struct dvb_usb_adapter *adap) +{ + int ret; + deb_info("%s\n", __func__); + + ret = mxl111sf_lgdt3305_frontend_attach(adap, 0); + if (ret < 0) + return ret; + + ret = mxl111sf_attach_demod(adap, 1); + if (ret < 0) + return ret; + + ret = mxl111sf_lg2161_ep6_frontend_attach(adap, 2); + if (ret < 0) + return ret; + + return ret; +} + +static int mxl111sf_frontend_attach_mercury_mh(struct dvb_usb_adapter *adap) +{ + int ret; + deb_info("%s\n", __func__); + + ret = mxl111sf_attach_demod(adap, 0); + if (ret < 0) + return ret; + + if (dvb_usb_mxl111sf_spi) + ret = mxl111sf_lg2161_frontend_attach(adap, 1); + else + ret = mxl111sf_lg2161_ep6_frontend_attach(adap, 1); + + return ret; +} + +static void mxl111sf_stream_config_bulk(struct usb_data_stream_properties *stream, u8 endpoint) +{ + deb_info("%s: endpoint=%d size=8192\n", __func__, endpoint); + stream->type = USB_BULK; + stream->count = 5; + stream->endpoint = endpoint; + stream->u.bulk.buffersize = 8192; +} + +static void mxl111sf_stream_config_isoc(struct usb_data_stream_properties *stream, + u8 endpoint, int framesperurb, int framesize) +{ + deb_info("%s: endpoint=%d size=%d\n", __func__, endpoint, + framesperurb * framesize); + stream->type = USB_ISOC; + stream->count = 5; + stream->endpoint = endpoint; + stream->u.isoc.framesperurb = framesperurb; + stream->u.isoc.framesize = framesize; + stream->u.isoc.interval = 1; +} + +/* DVB USB Driver stuff */ + +/* dvbt mxl111sf + * bulk EP4/BULK/5/8192 + * isoc EP4/ISOC/5/96/564 + */ +static int mxl111sf_get_stream_config_dvbt(struct dvb_frontend *fe, + u8 *ts_type, struct usb_data_stream_properties *stream) +{ + deb_info("%s: fe=%d\n", __func__, fe->id); + + *ts_type = DVB_USB_FE_TS_TYPE_188; + if (dvb_usb_mxl111sf_isoc) + mxl111sf_stream_config_isoc(stream, 4, 96, 564); + else + mxl111sf_stream_config_bulk(stream, 4); + return 0; +} + +static struct dvb_usb_device_properties mxl111sf_props_dvbt = { + .driver_name = KBUILD_MODNAME, + .owner = THIS_MODULE, + .adapter_nr = adapter_nr, + .size_of_priv = sizeof(struct mxl111sf_state), + + .generic_bulk_ctrl_endpoint = 0x02, + .generic_bulk_ctrl_endpoint_response = 0x81, + + .i2c_algo = &mxl111sf_i2c_algo, + .frontend_attach = mxl111sf_frontend_attach_dvbt, + .tuner_attach = mxl111sf_attach_tuner, + .init = mxl111sf_init, + .streaming_ctrl = mxl111sf_ep4_streaming_ctrl, + .get_stream_config = mxl111sf_get_stream_config_dvbt, + + .num_adapters = 1, + .adapter = { + { + .stream = DVB_USB_STREAM_ISOC(6, 5, 24, 3072, 1), + } + } +}; + +/* atsc lgdt3305 + * bulk EP6/BULK/5/8192 + * isoc EP6/ISOC/5/24/3072 + */ +static int mxl111sf_get_stream_config_atsc(struct dvb_frontend *fe, + u8 *ts_type, struct usb_data_stream_properties *stream) +{ + deb_info("%s: fe=%d\n", __func__, fe->id); + + *ts_type = DVB_USB_FE_TS_TYPE_188; + if (dvb_usb_mxl111sf_isoc) + mxl111sf_stream_config_isoc(stream, 6, 24, 3072); + else + mxl111sf_stream_config_bulk(stream, 6); + return 0; +} + +static struct dvb_usb_device_properties mxl111sf_props_atsc = { + .driver_name = KBUILD_MODNAME, + .owner = THIS_MODULE, + .adapter_nr = adapter_nr, + .size_of_priv = sizeof(struct mxl111sf_state), + + .generic_bulk_ctrl_endpoint = 0x02, + .generic_bulk_ctrl_endpoint_response = 0x81, + + .i2c_algo = &mxl111sf_i2c_algo, + .frontend_attach = mxl111sf_frontend_attach_atsc, + .tuner_attach = mxl111sf_attach_tuner, + .init = mxl111sf_init, + .streaming_ctrl = mxl111sf_ep6_streaming_ctrl, + .get_stream_config = mxl111sf_get_stream_config_atsc, + + .num_adapters = 1, + .adapter = { + { + .stream = DVB_USB_STREAM_ISOC(6, 5, 24, 3072, 1), + } + } +}; + +/* mh lg2160 + * bulk EP5/BULK/5/8192/RAW + * isoc EP5/ISOC/5/96/200/RAW + */ +static int mxl111sf_get_stream_config_mh(struct dvb_frontend *fe, + u8 *ts_type, struct usb_data_stream_properties *stream) +{ + deb_info("%s: fe=%d\n", __func__, fe->id); + + *ts_type = DVB_USB_FE_TS_TYPE_RAW; + if (dvb_usb_mxl111sf_isoc) + mxl111sf_stream_config_isoc(stream, 5, 96, 200); + else + mxl111sf_stream_config_bulk(stream, 5); + return 0; +} + +static struct dvb_usb_device_properties mxl111sf_props_mh = { + .driver_name = KBUILD_MODNAME, + .owner = THIS_MODULE, + .adapter_nr = adapter_nr, + .size_of_priv = sizeof(struct mxl111sf_state), + + .generic_bulk_ctrl_endpoint = 0x02, + .generic_bulk_ctrl_endpoint_response = 0x81, + + .i2c_algo = &mxl111sf_i2c_algo, + .frontend_attach = mxl111sf_frontend_attach_mh, + .tuner_attach = mxl111sf_attach_tuner, + .init = mxl111sf_init, + .streaming_ctrl = mxl111sf_ep5_streaming_ctrl, + .get_stream_config = mxl111sf_get_stream_config_mh, + + .num_adapters = 1, + .adapter = { + { + .stream = DVB_USB_STREAM_ISOC(6, 5, 24, 3072, 1), + } + } +}; + +/* atsc mh lgdt3305 mxl111sf lg2160 + * bulk EP6/BULK/5/8192 EP4/BULK/5/8192 EP5/BULK/5/8192/RAW + * isoc EP6/ISOC/5/24/3072 EP4/ISOC/5/96/564 EP5/ISOC/5/96/200/RAW + */ +static int mxl111sf_get_stream_config_atsc_mh(struct dvb_frontend *fe, + u8 *ts_type, struct usb_data_stream_properties *stream) +{ + deb_info("%s: fe=%d\n", __func__, fe->id); + + if (fe->id == 0) { + *ts_type = DVB_USB_FE_TS_TYPE_188; + if (dvb_usb_mxl111sf_isoc) + mxl111sf_stream_config_isoc(stream, 6, 24, 3072); + else + mxl111sf_stream_config_bulk(stream, 6); + } else if (fe->id == 1) { + *ts_type = DVB_USB_FE_TS_TYPE_188; + if (dvb_usb_mxl111sf_isoc) + mxl111sf_stream_config_isoc(stream, 4, 96, 564); + else + mxl111sf_stream_config_bulk(stream, 4); + } else if (fe->id == 2) { + *ts_type = DVB_USB_FE_TS_TYPE_RAW; + if (dvb_usb_mxl111sf_isoc) + mxl111sf_stream_config_isoc(stream, 5, 96, 200); + else + mxl111sf_stream_config_bulk(stream, 5); + } + return 0; +} + +static int mxl111sf_streaming_ctrl_atsc_mh(struct dvb_frontend *fe, int onoff) +{ + deb_info("%s: fe=%d onoff=%d\n", __func__, fe->id, onoff); + + if (fe->id == 0) + return mxl111sf_ep6_streaming_ctrl(fe, onoff); + else if (fe->id == 1) + return mxl111sf_ep4_streaming_ctrl(fe, onoff); + else if (fe->id == 2) + return mxl111sf_ep5_streaming_ctrl(fe, onoff); + return 0; +} + +static struct dvb_usb_device_properties mxl111sf_props_atsc_mh = { + .driver_name = KBUILD_MODNAME, + .owner = THIS_MODULE, + .adapter_nr = adapter_nr, + .size_of_priv = sizeof(struct mxl111sf_state), + + .generic_bulk_ctrl_endpoint = 0x02, + .generic_bulk_ctrl_endpoint_response = 0x81, + + .i2c_algo = &mxl111sf_i2c_algo, + .frontend_attach = mxl111sf_frontend_attach_atsc_mh, + .tuner_attach = mxl111sf_attach_tuner, + .init = mxl111sf_init, + .streaming_ctrl = mxl111sf_streaming_ctrl_atsc_mh, + .get_stream_config = mxl111sf_get_stream_config_atsc_mh, + + .num_adapters = 1, + .adapter = { + { + .stream = DVB_USB_STREAM_ISOC(6, 5, 24, 3072, 1), + } + } +}; + +/* mercury lgdt3305 mxl111sf lg2161 + * tp bulk EP6/BULK/5/8192 EP4/BULK/5/8192 EP6/BULK/5/8192/RAW + * tp isoc EP6/ISOC/5/24/3072 EP4/ISOC/5/96/564 EP6/ISOC/5/24/3072/RAW + * spi bulk EP6/BULK/5/8192 EP4/BULK/5/8192 EP5/BULK/5/8192/RAW + * spi isoc EP6/ISOC/5/24/3072 EP4/ISOC/5/96/564 EP5/ISOC/5/96/200/RAW + */ +static int mxl111sf_get_stream_config_mercury(struct dvb_frontend *fe, + u8 *ts_type, struct usb_data_stream_properties *stream) +{ + deb_info("%s: fe=%d\n", __func__, fe->id); + + if (fe->id == 0) { + *ts_type = DVB_USB_FE_TS_TYPE_188; + if (dvb_usb_mxl111sf_isoc) + mxl111sf_stream_config_isoc(stream, 6, 24, 3072); + else + mxl111sf_stream_config_bulk(stream, 6); + } else if (fe->id == 1) { + *ts_type = DVB_USB_FE_TS_TYPE_188; + if (dvb_usb_mxl111sf_isoc) + mxl111sf_stream_config_isoc(stream, 4, 96, 564); + else + mxl111sf_stream_config_bulk(stream, 4); + } else if (fe->id == 2 && dvb_usb_mxl111sf_spi) { + *ts_type = DVB_USB_FE_TS_TYPE_RAW; + if (dvb_usb_mxl111sf_isoc) + mxl111sf_stream_config_isoc(stream, 5, 96, 200); + else + mxl111sf_stream_config_bulk(stream, 5); + } else if (fe->id == 2 && !dvb_usb_mxl111sf_spi) { + *ts_type = DVB_USB_FE_TS_TYPE_RAW; + if (dvb_usb_mxl111sf_isoc) + mxl111sf_stream_config_isoc(stream, 6, 24, 3072); + else + mxl111sf_stream_config_bulk(stream, 6); + } + return 0; +} + +static int mxl111sf_streaming_ctrl_mercury(struct dvb_frontend *fe, int onoff) +{ + deb_info("%s: fe=%d onoff=%d\n", __func__, fe->id, onoff); + + if (fe->id == 0) + return mxl111sf_ep6_streaming_ctrl(fe, onoff); + else if (fe->id == 1) + return mxl111sf_ep4_streaming_ctrl(fe, onoff); + else if (fe->id == 2 && dvb_usb_mxl111sf_spi) + return mxl111sf_ep5_streaming_ctrl(fe, onoff); + else if (fe->id == 2 && !dvb_usb_mxl111sf_spi) + return mxl111sf_ep6_streaming_ctrl(fe, onoff); + return 0; +} + +static struct dvb_usb_device_properties mxl111sf_props_mercury = { + .driver_name = KBUILD_MODNAME, + .owner = THIS_MODULE, + .adapter_nr = adapter_nr, + .size_of_priv = sizeof(struct mxl111sf_state), + + .generic_bulk_ctrl_endpoint = 0x02, + .generic_bulk_ctrl_endpoint_response = 0x81, + + .i2c_algo = &mxl111sf_i2c_algo, + .frontend_attach = mxl111sf_frontend_attach_mercury, + .tuner_attach = mxl111sf_attach_tuner, + .init = mxl111sf_init, + .streaming_ctrl = mxl111sf_streaming_ctrl_mercury, + .get_stream_config = mxl111sf_get_stream_config_mercury, + + .num_adapters = 1, + .adapter = { + { + .stream = DVB_USB_STREAM_ISOC(6, 5, 24, 3072, 1), + } + } +}; + +/* mercury mh mxl111sf lg2161 + * tp bulk EP4/BULK/5/8192 EP6/BULK/5/8192/RAW + * tp isoc EP4/ISOC/5/96/564 EP6/ISOC/5/24/3072/RAW + * spi bulk EP4/BULK/5/8192 EP5/BULK/5/8192/RAW + * spi isoc EP4/ISOC/5/96/564 EP5/ISOC/5/96/200/RAW + */ +static int mxl111sf_get_stream_config_mercury_mh(struct dvb_frontend *fe, + u8 *ts_type, struct usb_data_stream_properties *stream) +{ + deb_info("%s: fe=%d\n", __func__, fe->id); + + if (fe->id == 0) { + *ts_type = DVB_USB_FE_TS_TYPE_188; + if (dvb_usb_mxl111sf_isoc) + mxl111sf_stream_config_isoc(stream, 4, 96, 564); + else + mxl111sf_stream_config_bulk(stream, 4); + } else if (fe->id == 1 && dvb_usb_mxl111sf_spi) { + *ts_type = DVB_USB_FE_TS_TYPE_RAW; + if (dvb_usb_mxl111sf_isoc) + mxl111sf_stream_config_isoc(stream, 5, 96, 200); + else + mxl111sf_stream_config_bulk(stream, 5); + } else if (fe->id == 1 && !dvb_usb_mxl111sf_spi) { + *ts_type = DVB_USB_FE_TS_TYPE_RAW; + if (dvb_usb_mxl111sf_isoc) + mxl111sf_stream_config_isoc(stream, 6, 24, 3072); + else + mxl111sf_stream_config_bulk(stream, 6); + } + return 0; +} + +static int mxl111sf_streaming_ctrl_mercury_mh(struct dvb_frontend *fe, int onoff) +{ + deb_info("%s: fe=%d onoff=%d\n", __func__, fe->id, onoff); + + if (fe->id == 0) + return mxl111sf_ep4_streaming_ctrl(fe, onoff); + else if (fe->id == 1 && dvb_usb_mxl111sf_spi) + return mxl111sf_ep5_streaming_ctrl(fe, onoff); + else if (fe->id == 1 && !dvb_usb_mxl111sf_spi) + return mxl111sf_ep6_streaming_ctrl(fe, onoff); + return 0; +} + +static struct dvb_usb_device_properties mxl111sf_props_mercury_mh = { + .driver_name = KBUILD_MODNAME, + .owner = THIS_MODULE, + .adapter_nr = adapter_nr, + .size_of_priv = sizeof(struct mxl111sf_state), + + .generic_bulk_ctrl_endpoint = 0x02, + .generic_bulk_ctrl_endpoint_response = 0x81, + + .i2c_algo = &mxl111sf_i2c_algo, + .frontend_attach = mxl111sf_frontend_attach_mercury_mh, + .tuner_attach = mxl111sf_attach_tuner, + .init = mxl111sf_init, + .streaming_ctrl = mxl111sf_streaming_ctrl_mercury_mh, + .get_stream_config = mxl111sf_get_stream_config_mercury_mh, + + .num_adapters = 1, + .adapter = { + { + .stream = DVB_USB_STREAM_ISOC(6, 5, 24, 3072, 1), + } + } +}; + +static const struct usb_device_id mxl111sf_id_table[] = { + { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xc600, &mxl111sf_props_atsc_mh, "Hauppauge 126xxx ATSC+", NULL) }, + { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xc601, &mxl111sf_props_atsc, "Hauppauge 126xxx ATSC", NULL) }, + { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xc602, &mxl111sf_props_mh, "HCW 126xxx", NULL) }, + { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xc603, &mxl111sf_props_atsc_mh, "Hauppauge 126xxx ATSC+", NULL) }, + { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xc604, &mxl111sf_props_dvbt, "Hauppauge 126xxx DVBT", NULL) }, + { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xc609, &mxl111sf_props_atsc, "Hauppauge 126xxx ATSC", NULL) }, + { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xc60a, &mxl111sf_props_mh, "HCW 126xxx", NULL) }, + { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xc60b, &mxl111sf_props_atsc_mh, "Hauppauge 126xxx ATSC+", NULL) }, + { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xc60c, &mxl111sf_props_dvbt, "Hauppauge 126xxx DVBT", NULL) }, + { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xc653, &mxl111sf_props_atsc_mh, "Hauppauge 126xxx ATSC+", NULL) }, + { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xc65b, &mxl111sf_props_atsc_mh, "Hauppauge 126xxx ATSC+", NULL) }, + { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xb700, &mxl111sf_props_atsc_mh, "Hauppauge 117xxx ATSC+", NULL) }, + { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xb701, &mxl111sf_props_atsc, "Hauppauge 126xxx ATSC", NULL) }, + { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xb702, &mxl111sf_props_mh, "HCW 117xxx", NULL) }, + { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xb703, &mxl111sf_props_atsc_mh, "Hauppauge 117xxx ATSC+", NULL) }, + { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xb704, &mxl111sf_props_dvbt, "Hauppauge 117xxx DVBT", NULL) }, + { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xb753, &mxl111sf_props_atsc_mh, "Hauppauge 117xxx ATSC+", NULL) }, + { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xb763, &mxl111sf_props_atsc_mh, "Hauppauge 117xxx ATSC+", NULL) }, + { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xb764, &mxl111sf_props_dvbt, "Hauppauge 117xxx DVBT", NULL) }, + { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xd853, &mxl111sf_props_mercury, "Hauppauge Mercury", NULL) }, + { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xd854, &mxl111sf_props_dvbt, "Hauppauge 138xxx DVBT", NULL) }, + { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xd863, &mxl111sf_props_mercury, "Hauppauge Mercury", NULL) }, + { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xd864, &mxl111sf_props_dvbt, "Hauppauge 138xxx DVBT", NULL) }, + { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xd8d3, &mxl111sf_props_mercury, "Hauppauge Mercury", NULL) }, + { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xd8d4, &mxl111sf_props_dvbt, "Hauppauge 138xxx DVBT", NULL) }, + { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xd8e3, &mxl111sf_props_mercury, "Hauppauge Mercury", NULL) }, + { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xd8e4, &mxl111sf_props_dvbt, "Hauppauge 138xxx DVBT", NULL) }, + { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xd8ff, &mxl111sf_props_mercury, "Hauppauge Mercury", NULL) }, + { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xc612, &mxl111sf_props_mercury_mh, "Hauppauge 126xxx", NULL) }, + { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xc613, &mxl111sf_props_mercury, "Hauppauge WinTV-Aero-M", NULL) }, + { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xc61a, &mxl111sf_props_mercury_mh, "Hauppauge 126xxx", NULL) }, + { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xc61b, &mxl111sf_props_mercury, "Hauppauge WinTV-Aero-M", NULL) }, + { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xb757, &mxl111sf_props_atsc_mh, "Hauppauge 117xxx ATSC+", NULL) }, + { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xb767, &mxl111sf_props_atsc_mh, "Hauppauge 117xxx ATSC+", NULL) }, + { } +}; +MODULE_DEVICE_TABLE(usb, mxl111sf_id_table); + +static struct usb_driver mxl111sf_usb_driver = { + .name = KBUILD_MODNAME, + .id_table = mxl111sf_id_table, + .probe = dvb_usbv2_probe, + .disconnect = dvb_usbv2_disconnect, + .suspend = dvb_usbv2_suspend, + .resume = dvb_usbv2_resume, + .no_dynamic_id = 1, + .soft_unbind = 1, +}; + +module_usb_driver(mxl111sf_usb_driver); + +MODULE_AUTHOR("Michael Krufky <mkrufky@kernellabs.com>"); +MODULE_DESCRIPTION("Driver for MaxLinear MxL111SF"); +MODULE_VERSION("1.0"); +MODULE_LICENSE("GPL"); + +/* + * Local variables: + * c-basic-offset: 8 + * End: + */ diff --git a/drivers/media/dvb/dvb-usb/mxl111sf.h b/drivers/media/usb/dvb-usb-v2/mxl111sf.h index 364d89f826bd..9816de86e48c 100644 --- a/drivers/media/dvb/dvb-usb/mxl111sf.h +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf.h @@ -15,7 +15,7 @@ #undef DVB_USB_LOG_PREFIX #endif #define DVB_USB_LOG_PREFIX "mxl111sf" -#include "dvb-usb.h" +#include "dvb_usb.h" #include <media/tveeprom.h> #define MXL_EP1_REG_READ 1 @@ -39,6 +39,15 @@ enum mxl111sf_gpio_port_expander { mxl111sf_PCA9534, }; +struct mxl111sf_adap_state { + int alt_mode; + int gpio_mode; + int device_mode; + int ep6_clockphase; + int (*fe_init)(struct dvb_frontend *); + int (*fe_sleep)(struct dvb_frontend *); +}; + struct mxl111sf_state { struct dvb_usb_device *d; @@ -74,15 +83,8 @@ struct mxl111sf_state { struct tveeprom tv; struct mutex fe_lock; -}; - -struct mxl111sf_adap_state { - int alt_mode; - int gpio_mode; - int device_mode; - int ep6_clockphase; - int (*fe_init)(struct dvb_frontend *); - int (*fe_sleep)(struct dvb_frontend *); + u8 num_frontends; + struct mxl111sf_adap_state adap_state[3]; }; int mxl111sf_read_reg(struct mxl111sf_state *state, u8 addr, u8 *data); diff --git a/drivers/media/dvb/dvb-usb/rtl28xxu.c b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c index 6bd0bd792437..adabba8d28bc 100644 --- a/drivers/media/dvb/dvb-usb/rtl28xxu.c +++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c @@ -30,11 +30,10 @@ #include "mxl5005s.h" #include "fc0012.h" #include "fc0013.h" +#include "e4000.h" +#include "fc2580.h" +#include "tua9001.h" -/* debug */ -static int dvb_usb_rtl28xxu_debug; -module_param_named(debug, dvb_usb_rtl28xxu_debug, int, 0644); -MODULE_PARM_DESC(debug, "set debugging level" DVB_USB_DEBUG_STATUS); DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); static int rtl28xxu_ctrl_msg(struct dvb_usb_device *d, struct rtl28xxu_req *req) @@ -63,12 +62,13 @@ static int rtl28xxu_ctrl_msg(struct dvb_usb_device *d, struct rtl28xxu_req *req) ret = usb_control_msg(d->udev, pipe, 0, requesttype, req->value, req->index, buf, req->size, 1000); + + dvb_usb_dbg_usb_control_msg(d->udev, 0, requesttype, req->value, + req->index, buf, req->size); + if (ret > 0) ret = 0; - deb_dump(0, requesttype, req->value, req->index, buf, req->size, - deb_xfer); - /* read request, copy returned data to return buf */ if (!ret && requesttype == (USB_TYPE_VENDOR | USB_DIR_IN)) memcpy(req->data, buf, req->size); @@ -80,7 +80,7 @@ static int rtl28xxu_ctrl_msg(struct dvb_usb_device *d, struct rtl28xxu_req *req) return ret; err: - deb_info("%s: failed=%d\n", __func__, ret); + dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); return ret; } @@ -130,6 +130,26 @@ static int rtl28xx_rd_reg(struct dvb_usb_device *d, u16 reg, u8 *val) return rtl2831_rd_regs(d, reg, val, 1); } +static int rtl28xx_wr_reg_mask(struct dvb_usb_device *d, u16 reg, u8 val, + u8 mask) +{ + int ret; + u8 tmp; + + /* no need for read if whole reg is written */ + if (mask != 0xff) { + ret = rtl28xx_rd_reg(d, reg, &tmp); + if (ret) + return ret; + + val &= mask; + tmp &= ~mask; + val |= tmp; + } + + return rtl28xx_wr_reg(d, reg, val); +} + /* I2C */ static int rtl28xxu_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], int num) @@ -254,54 +274,18 @@ static struct i2c_algorithm rtl28xxu_i2c_algo = { .functionality = rtl28xxu_i2c_func, }; -static struct rtl2830_config rtl28xxu_rtl2830_mt2060_config = { - .i2c_addr = 0x10, /* 0x20 */ - .xtal = 28800000, - .ts_mode = 0, - .spec_inv = 1, - .if_dvbt = 36150000, - .vtop = 0x20, - .krf = 0x04, - .agc_targ_val = 0x2d, - -}; - -static struct rtl2830_config rtl28xxu_rtl2830_qt1010_config = { - .i2c_addr = 0x10, /* 0x20 */ - .xtal = 28800000, - .ts_mode = 0, - .spec_inv = 1, - .if_dvbt = 36125000, - .vtop = 0x20, - .krf = 0x04, - .agc_targ_val = 0x2d, -}; - -static struct rtl2830_config rtl28xxu_rtl2830_mxl5005s_config = { - .i2c_addr = 0x10, /* 0x20 */ - .xtal = 28800000, - .ts_mode = 0, - .spec_inv = 0, - .if_dvbt = 4570000, - .vtop = 0x3f, - .krf = 0x04, - .agc_targ_val = 0x3e, -}; - -static int rtl2831u_frontend_attach(struct dvb_usb_adapter *adap) +static int rtl2831u_read_config(struct dvb_usb_device *d) { + struct rtl28xxu_priv *priv = d_to_priv(d); int ret; - struct rtl28xxu_priv *priv = adap->dev->priv; u8 buf[1]; - struct rtl2830_config *rtl2830_config; /* open RTL2831U/RTL2830 I2C gate */ - struct rtl28xxu_req req_gate = { 0x0120, 0x0011, 0x0001, "\x08" }; - /* for MT2060 tuner probe */ - struct rtl28xxu_req req_mt2060 = { 0x00c0, CMD_I2C_RD, 1, buf }; - /* for QT1010 tuner probe */ - struct rtl28xxu_req req_qt1010 = { 0x0fc4, CMD_I2C_RD, 1, buf }; + struct rtl28xxu_req req_gate_open = {0x0120, 0x0011, 0x0001, "\x08"}; + /* tuner probes */ + struct rtl28xxu_req req_mt2060 = {0x00c0, CMD_I2C_RD, 1, buf}; + struct rtl28xxu_req req_qt1010 = {0x0fc4, CMD_I2C_RD, 1, buf}; - deb_info("%s:\n", __func__); + dev_dbg(&d->udev->dev, "%s:\n", __func__); /* * RTL2831U GPIOs @@ -312,12 +296,12 @@ static int rtl2831u_frontend_attach(struct dvb_usb_adapter *adap) */ /* GPIO direction */ - ret = rtl28xx_wr_reg(adap->dev, SYS_GPIO_DIR, 0x0a); + ret = rtl28xx_wr_reg(d, SYS_GPIO_DIR, 0x0a); if (ret) goto err; /* enable as output GPIO0, GPIO2, GPIO4 */ - ret = rtl28xx_wr_reg(adap->dev, SYS_GPIO_OUT_EN, 0x15); + ret = rtl28xx_wr_reg(d, SYS_GPIO_OUT_EN, 0x15); if (ret) goto err; @@ -329,349 +313,441 @@ static int rtl2831u_frontend_attach(struct dvb_usb_adapter *adap) /* demod needs some time to wake up */ msleep(20); + priv->tuner_name = "NONE"; + /* open demod I2C gate */ - ret = rtl28xxu_ctrl_msg(adap->dev, &req_gate); + ret = rtl28xxu_ctrl_msg(d, &req_gate_open); if (ret) goto err; /* check QT1010 ID(?) register; reg=0f val=2c */ - ret = rtl28xxu_ctrl_msg(adap->dev, &req_qt1010); + ret = rtl28xxu_ctrl_msg(d, &req_qt1010); if (ret == 0 && buf[0] == 0x2c) { priv->tuner = TUNER_RTL2830_QT1010; - rtl2830_config = &rtl28xxu_rtl2830_qt1010_config; - deb_info("%s: QT1010\n", __func__); + priv->tuner_name = "QT1010"; goto found; - } else { - deb_info("%s: QT1010 probe failed=%d - %02x\n", - __func__, ret, buf[0]); } /* open demod I2C gate */ - ret = rtl28xxu_ctrl_msg(adap->dev, &req_gate); + ret = rtl28xxu_ctrl_msg(d, &req_gate_open); if (ret) goto err; /* check MT2060 ID register; reg=00 val=63 */ - ret = rtl28xxu_ctrl_msg(adap->dev, &req_mt2060); + ret = rtl28xxu_ctrl_msg(d, &req_mt2060); if (ret == 0 && buf[0] == 0x63) { priv->tuner = TUNER_RTL2830_MT2060; - rtl2830_config = &rtl28xxu_rtl2830_mt2060_config; - deb_info("%s: MT2060\n", __func__); + priv->tuner_name = "MT2060"; goto found; - } else { - deb_info("%s: MT2060 probe failed=%d - %02x\n", - __func__, ret, buf[0]); } /* assume MXL5005S */ - ret = 0; priv->tuner = TUNER_RTL2830_MXL5005S; - rtl2830_config = &rtl28xxu_rtl2830_mxl5005s_config; - deb_info("%s: MXL5005S\n", __func__); + priv->tuner_name = "MXL5005S"; goto found; found: - /* attach demodulator */ - adap->fe_adap[0].fe = dvb_attach(rtl2830_attach, rtl2830_config, - &adap->dev->i2c_adap); - if (adap->fe_adap[0].fe == NULL) { - ret = -ENODEV; - goto err; - } - - return ret; -err: - deb_info("%s: failed=%d\n", __func__, ret); - return ret; -} - -static struct rtl2832_config rtl28xxu_rtl2832_fc0012_config = { - .i2c_addr = 0x10, /* 0x20 */ - .xtal = 28800000, - .if_dvbt = 0, - .tuner = TUNER_RTL2832_FC0012 -}; + dev_dbg(&d->udev->dev, "%s: tuner=%s\n", __func__, priv->tuner_name); -static struct rtl2832_config rtl28xxu_rtl2832_fc0013_config = { - .i2c_addr = 0x10, /* 0x20 */ - .xtal = 28800000, - .if_dvbt = 0, - .tuner = TUNER_RTL2832_FC0013 -}; - -static int rtl2832u_fc0012_tuner_callback(struct dvb_usb_device *d, - int cmd, int arg) -{ - int ret; - u8 val; - - deb_info("%s cmd=%d arg=%d\n", __func__, cmd, arg); - switch (cmd) { - case FC_FE_CALLBACK_VHF_ENABLE: - /* set output values */ - ret = rtl28xx_rd_reg(d, SYS_GPIO_OUT_VAL, &val); - if (ret) - goto err; - - if (arg) - val &= 0xbf; /* set GPIO6 low */ - else - val |= 0x40; /* set GPIO6 high */ - - - ret = rtl28xx_wr_reg(d, SYS_GPIO_OUT_VAL, val); - if (ret) - goto err; - break; - default: - ret = -EINVAL; - goto err; - } return 0; - err: - err("%s: failed=%d\n", __func__, ret); - + dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); return ret; } - -static int rtl2832u_fc0013_tuner_callback(struct dvb_usb_device *d, - int cmd, int arg) -{ - /* TODO implement*/ - return 0; -} - -static int rtl2832u_tuner_callback(struct dvb_usb_device *d, int cmd, int arg) -{ - struct rtl28xxu_priv *priv = d->priv; - - switch (priv->tuner) { - case TUNER_RTL2832_FC0012: - return rtl2832u_fc0012_tuner_callback(d, cmd, arg); - - case TUNER_RTL2832_FC0013: - return rtl2832u_fc0013_tuner_callback(d, cmd, arg); - default: - break; - } - - return -ENODEV; -} - -static int rtl2832u_frontend_callback(void *adapter_priv, int component, - int cmd, int arg) -{ - struct i2c_adapter *adap = adapter_priv; - struct dvb_usb_device *d = i2c_get_adapdata(adap); - - switch (component) { - case DVB_FRONTEND_COMPONENT_TUNER: - return rtl2832u_tuner_callback(d, cmd, arg); - default: - break; - } - - return -EINVAL; -} - - - - -static int rtl2832u_frontend_attach(struct dvb_usb_adapter *adap) +static int rtl2832u_read_config(struct dvb_usb_device *d) { + struct rtl28xxu_priv *priv = d_to_priv(d); int ret; - struct rtl28xxu_priv *priv = adap->dev->priv; - struct rtl2832_config *rtl2832_config; - - u8 buf[2], val; + u8 buf[2]; /* open RTL2832U/RTL2832 I2C gate */ struct rtl28xxu_req req_gate_open = {0x0120, 0x0011, 0x0001, "\x18"}; /* close RTL2832U/RTL2832 I2C gate */ struct rtl28xxu_req req_gate_close = {0x0120, 0x0011, 0x0001, "\x10"}; - /* for FC0012 tuner probe */ + /* tuner probes */ struct rtl28xxu_req req_fc0012 = {0x00c6, CMD_I2C_RD, 1, buf}; - /* for FC0013 tuner probe */ struct rtl28xxu_req req_fc0013 = {0x00c6, CMD_I2C_RD, 1, buf}; - /* for MT2266 tuner probe */ struct rtl28xxu_req req_mt2266 = {0x00c0, CMD_I2C_RD, 1, buf}; - /* for FC2580 tuner probe */ struct rtl28xxu_req req_fc2580 = {0x01ac, CMD_I2C_RD, 1, buf}; - /* for MT2063 tuner probe */ struct rtl28xxu_req req_mt2063 = {0x00c0, CMD_I2C_RD, 1, buf}; - /* for MAX3543 tuner probe */ struct rtl28xxu_req req_max3543 = {0x00c0, CMD_I2C_RD, 1, buf}; - /* for TUA9001 tuner probe */ struct rtl28xxu_req req_tua9001 = {0x7ec0, CMD_I2C_RD, 2, buf}; - /* for MXL5007T tuner probe */ struct rtl28xxu_req req_mxl5007t = {0xd9c0, CMD_I2C_RD, 1, buf}; - /* for E4000 tuner probe */ struct rtl28xxu_req req_e4000 = {0x02c8, CMD_I2C_RD, 1, buf}; - /* for TDA18272 tuner probe */ struct rtl28xxu_req req_tda18272 = {0x00c0, CMD_I2C_RD, 2, buf}; - deb_info("%s:\n", __func__); - + dev_dbg(&d->udev->dev, "%s:\n", __func__); - ret = rtl28xx_rd_reg(adap->dev, SYS_GPIO_DIR, &val); + /* enable GPIO3 and GPIO6 as output */ + ret = rtl28xx_wr_reg_mask(d, SYS_GPIO_DIR, 0x00, 0x40); if (ret) goto err; - val &= 0xbf; - - ret = rtl28xx_wr_reg(adap->dev, SYS_GPIO_DIR, val); + ret = rtl28xx_wr_reg_mask(d, SYS_GPIO_OUT_EN, 0x48, 0x48); if (ret) goto err; - - /* enable as output GPIO3 and GPIO6*/ - ret = rtl28xx_rd_reg(adap->dev, SYS_GPIO_OUT_EN, &val); - if (ret) - goto err; - - val |= 0x48; - - ret = rtl28xx_wr_reg(adap->dev, SYS_GPIO_OUT_EN, val); - if (ret) - goto err; - - - /* * Probe used tuner. We need to know used tuner before demod attach * since there is some demod params needed to set according to tuner. */ /* open demod I2C gate */ - ret = rtl28xxu_ctrl_msg(adap->dev, &req_gate_open); + ret = rtl28xxu_ctrl_msg(d, &req_gate_open); if (ret) goto err; - priv->tuner = TUNER_NONE; + priv->tuner_name = "NONE"; /* check FC0012 ID register; reg=00 val=a1 */ - ret = rtl28xxu_ctrl_msg(adap->dev, &req_fc0012); + ret = rtl28xxu_ctrl_msg(d, &req_fc0012); if (ret == 0 && buf[0] == 0xa1) { priv->tuner = TUNER_RTL2832_FC0012; - rtl2832_config = &rtl28xxu_rtl2832_fc0012_config; - info("%s: FC0012 tuner found", __func__); + priv->tuner_name = "FC0012"; goto found; } /* check FC0013 ID register; reg=00 val=a3 */ - ret = rtl28xxu_ctrl_msg(adap->dev, &req_fc0013); + ret = rtl28xxu_ctrl_msg(d, &req_fc0013); if (ret == 0 && buf[0] == 0xa3) { priv->tuner = TUNER_RTL2832_FC0013; - rtl2832_config = &rtl28xxu_rtl2832_fc0013_config; - info("%s: FC0013 tuner found", __func__); + priv->tuner_name = "FC0013"; goto found; } /* check MT2266 ID register; reg=00 val=85 */ - ret = rtl28xxu_ctrl_msg(adap->dev, &req_mt2266); + ret = rtl28xxu_ctrl_msg(d, &req_mt2266); if (ret == 0 && buf[0] == 0x85) { priv->tuner = TUNER_RTL2832_MT2266; - /* TODO implement tuner */ - info("%s: MT2266 tuner found", __func__); - goto unsupported; + priv->tuner_name = "MT2266"; + goto found; } /* check FC2580 ID register; reg=01 val=56 */ - ret = rtl28xxu_ctrl_msg(adap->dev, &req_fc2580); + ret = rtl28xxu_ctrl_msg(d, &req_fc2580); if (ret == 0 && buf[0] == 0x56) { priv->tuner = TUNER_RTL2832_FC2580; - /* TODO implement tuner */ - info("%s: FC2580 tuner found", __func__); - goto unsupported; + priv->tuner_name = "FC2580"; + goto found; } /* check MT2063 ID register; reg=00 val=9e || 9c */ - ret = rtl28xxu_ctrl_msg(adap->dev, &req_mt2063); + ret = rtl28xxu_ctrl_msg(d, &req_mt2063); if (ret == 0 && (buf[0] == 0x9e || buf[0] == 0x9c)) { priv->tuner = TUNER_RTL2832_MT2063; - /* TODO implement tuner */ - info("%s: MT2063 tuner found", __func__); - goto unsupported; + priv->tuner_name = "MT2063"; + goto found; } /* check MAX3543 ID register; reg=00 val=38 */ - ret = rtl28xxu_ctrl_msg(adap->dev, &req_max3543); + ret = rtl28xxu_ctrl_msg(d, &req_max3543); if (ret == 0 && buf[0] == 0x38) { priv->tuner = TUNER_RTL2832_MAX3543; - /* TODO implement tuner */ - info("%s: MAX3534 tuner found", __func__); - goto unsupported; + priv->tuner_name = "MAX3543"; + goto found; } /* check TUA9001 ID register; reg=7e val=2328 */ - ret = rtl28xxu_ctrl_msg(adap->dev, &req_tua9001); + ret = rtl28xxu_ctrl_msg(d, &req_tua9001); if (ret == 0 && buf[0] == 0x23 && buf[1] == 0x28) { priv->tuner = TUNER_RTL2832_TUA9001; - /* TODO implement tuner */ - info("%s: TUA9001 tuner found", __func__); - goto unsupported; + priv->tuner_name = "TUA9001"; + goto found; } /* check MXL5007R ID register; reg=d9 val=14 */ - ret = rtl28xxu_ctrl_msg(adap->dev, &req_mxl5007t); + ret = rtl28xxu_ctrl_msg(d, &req_mxl5007t); if (ret == 0 && buf[0] == 0x14) { priv->tuner = TUNER_RTL2832_MXL5007T; - /* TODO implement tuner */ - info("%s: MXL5007T tuner found", __func__); - goto unsupported; + priv->tuner_name = "MXL5007T"; + goto found; } /* check E4000 ID register; reg=02 val=40 */ - ret = rtl28xxu_ctrl_msg(adap->dev, &req_e4000); + ret = rtl28xxu_ctrl_msg(d, &req_e4000); if (ret == 0 && buf[0] == 0x40) { priv->tuner = TUNER_RTL2832_E4000; - /* TODO implement tuner */ - info("%s: E4000 tuner found", __func__); - goto unsupported; + priv->tuner_name = "E4000"; + goto found; } /* check TDA18272 ID register; reg=00 val=c760 */ - ret = rtl28xxu_ctrl_msg(adap->dev, &req_tda18272); + ret = rtl28xxu_ctrl_msg(d, &req_tda18272); if (ret == 0 && (buf[0] == 0xc7 || buf[1] == 0x60)) { priv->tuner = TUNER_RTL2832_TDA18272; - /* TODO implement tuner */ - info("%s: TDA18272 tuner found", __func__); - goto unsupported; + priv->tuner_name = "TDA18272"; + goto found; } -unsupported: +found: + dev_dbg(&d->udev->dev, "%s: tuner=%s\n", __func__, priv->tuner_name); + /* close demod I2C gate */ - ret = rtl28xxu_ctrl_msg(adap->dev, &req_gate_close); - if (ret) + ret = rtl28xxu_ctrl_msg(d, &req_gate_close); + if (ret < 0) goto err; - /* tuner not found */ - deb_info("No compatible tuner found"); - ret = -ENODEV; + return 0; +err: + dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); return ret; +} -found: - /* close demod I2C gate */ - ret = rtl28xxu_ctrl_msg(adap->dev, &req_gate_close); - if (ret) +static struct rtl2830_config rtl28xxu_rtl2830_mt2060_config = { + .i2c_addr = 0x10, /* 0x20 */ + .xtal = 28800000, + .ts_mode = 0, + .spec_inv = 1, + .vtop = 0x20, + .krf = 0x04, + .agc_targ_val = 0x2d, + +}; + +static struct rtl2830_config rtl28xxu_rtl2830_qt1010_config = { + .i2c_addr = 0x10, /* 0x20 */ + .xtal = 28800000, + .ts_mode = 0, + .spec_inv = 1, + .vtop = 0x20, + .krf = 0x04, + .agc_targ_val = 0x2d, +}; + +static struct rtl2830_config rtl28xxu_rtl2830_mxl5005s_config = { + .i2c_addr = 0x10, /* 0x20 */ + .xtal = 28800000, + .ts_mode = 0, + .spec_inv = 0, + .vtop = 0x3f, + .krf = 0x04, + .agc_targ_val = 0x3e, +}; + +static int rtl2831u_frontend_attach(struct dvb_usb_adapter *adap) +{ + struct dvb_usb_device *d = adap_to_d(adap); + struct rtl28xxu_priv *priv = d_to_priv(d); + struct rtl2830_config *rtl2830_config; + int ret; + + dev_dbg(&d->udev->dev, "%s:\n", __func__); + + switch (priv->tuner) { + case TUNER_RTL2830_QT1010: + rtl2830_config = &rtl28xxu_rtl2830_qt1010_config; + break; + case TUNER_RTL2830_MT2060: + rtl2830_config = &rtl28xxu_rtl2830_mt2060_config; + break; + case TUNER_RTL2830_MXL5005S: + rtl2830_config = &rtl28xxu_rtl2830_mxl5005s_config; + break; + default: + dev_err(&d->udev->dev, "%s: unknown tuner=%s\n", + KBUILD_MODNAME, priv->tuner_name); + ret = -ENODEV; goto err; + } /* attach demodulator */ - adap->fe_adap[0].fe = dvb_attach(rtl2832_attach, rtl2832_config, - &adap->dev->i2c_adap); - if (adap->fe_adap[0].fe == NULL) { - ret = -ENODEV; + adap->fe[0] = dvb_attach(rtl2830_attach, rtl2830_config, &d->i2c_adap); + if (!adap->fe[0]) { + ret = -ENODEV; + goto err; + } + + return 0; +err: + dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); + return ret; +} + +static struct rtl2832_config rtl28xxu_rtl2832_fc0012_config = { + .i2c_addr = 0x10, /* 0x20 */ + .xtal = 28800000, + .if_dvbt = 0, + .tuner = TUNER_RTL2832_FC0012 +}; + +static struct rtl2832_config rtl28xxu_rtl2832_fc0013_config = { + .i2c_addr = 0x10, /* 0x20 */ + .xtal = 28800000, + .if_dvbt = 0, + .tuner = TUNER_RTL2832_FC0013 +}; + +static struct rtl2832_config rtl28xxu_rtl2832_tua9001_config = { + .i2c_addr = 0x10, /* 0x20 */ + .xtal = 28800000, + .tuner = TUNER_RTL2832_TUA9001, +}; + +static struct rtl2832_config rtl28xxu_rtl2832_e4000_config = { + .i2c_addr = 0x10, /* 0x20 */ + .xtal = 28800000, + .tuner = TUNER_RTL2832_E4000, +}; + +static int rtl2832u_fc0012_tuner_callback(struct dvb_usb_device *d, + int cmd, int arg) +{ + int ret; + u8 val; + + dev_dbg(&d->udev->dev, "%s: cmd=%d arg=%d\n", __func__, cmd, arg); + + switch (cmd) { + case FC_FE_CALLBACK_VHF_ENABLE: + /* set output values */ + ret = rtl28xx_rd_reg(d, SYS_GPIO_OUT_VAL, &val); + if (ret) goto err; - } - /* set fe callbacks */ - adap->fe_adap[0].fe->callback = rtl2832u_frontend_callback; + if (arg) + val &= 0xbf; /* set GPIO6 low */ + else + val |= 0x40; /* set GPIO6 high */ + + ret = rtl28xx_wr_reg(d, SYS_GPIO_OUT_VAL, val); + if (ret) + goto err; + break; + default: + ret = -EINVAL; + goto err; + } + return 0; +err: + dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); return ret; +} +static int rtl2832u_tua9001_tuner_callback(struct dvb_usb_device *d, + int cmd, int arg) +{ + int ret; + u8 val; + + dev_dbg(&d->udev->dev, "%s: cmd=%d arg=%d\n", __func__, cmd, arg); + + /* + * CEN always enabled by hardware wiring + * RESETN GPIO4 + * RXEN GPIO1 + */ + + switch (cmd) { + case TUA9001_CMD_RESETN: + if (arg) + val = (1 << 4); + else + val = (0 << 4); + + ret = rtl28xx_wr_reg_mask(d, SYS_GPIO_OUT_VAL, val, 0x10); + if (ret) + goto err; + break; + case TUA9001_CMD_RXEN: + if (arg) + val = (1 << 1); + else + val = (0 << 1); + + ret = rtl28xx_wr_reg_mask(d, SYS_GPIO_OUT_VAL, val, 0x02); + if (ret) + goto err; + break; + } + + return 0; err: - deb_info("%s: failed=%d\n", __func__, ret); + dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); + return ret; +} + +static int rtl2832u_tuner_callback(struct dvb_usb_device *d, int cmd, int arg) +{ + struct rtl28xxu_priv *priv = d->priv; + + switch (priv->tuner) { + case TUNER_RTL2832_FC0012: + return rtl2832u_fc0012_tuner_callback(d, cmd, arg); + case TUNER_RTL2832_TUA9001: + return rtl2832u_tua9001_tuner_callback(d, cmd, arg); + default: + break; + } + + return 0; +} + +static int rtl2832u_frontend_callback(void *adapter_priv, int component, + int cmd, int arg) +{ + struct i2c_adapter *adap = adapter_priv; + struct dvb_usb_device *d = i2c_get_adapdata(adap); + + dev_dbg(&d->udev->dev, "%s: component=%d cmd=%d arg=%d\n", + __func__, component, cmd, arg); + + switch (component) { + case DVB_FRONTEND_COMPONENT_TUNER: + return rtl2832u_tuner_callback(d, cmd, arg); + default: + break; + } + + return 0; +} + +static int rtl2832u_frontend_attach(struct dvb_usb_adapter *adap) +{ + int ret; + struct dvb_usb_device *d = adap_to_d(adap); + struct rtl28xxu_priv *priv = d_to_priv(d); + struct rtl2832_config *rtl2832_config; + + dev_dbg(&d->udev->dev, "%s:\n", __func__); + + switch (priv->tuner) { + case TUNER_RTL2832_FC0012: + rtl2832_config = &rtl28xxu_rtl2832_fc0012_config; + break; + case TUNER_RTL2832_FC0013: + rtl2832_config = &rtl28xxu_rtl2832_fc0013_config; + break; + case TUNER_RTL2832_FC2580: + /* FIXME: do not abuse fc0012 settings */ + rtl2832_config = &rtl28xxu_rtl2832_fc0012_config; + break; + case TUNER_RTL2832_TUA9001: + rtl2832_config = &rtl28xxu_rtl2832_tua9001_config; + break; + case TUNER_RTL2832_E4000: + rtl2832_config = &rtl28xxu_rtl2832_e4000_config; + break; + default: + dev_err(&d->udev->dev, "%s: unknown tuner=%s\n", + KBUILD_MODNAME, priv->tuner_name); + ret = -ENODEV; + goto err; + } + + /* attach demodulator */ + adap->fe[0] = dvb_attach(rtl2832_attach, rtl2832_config, &d->i2c_adap); + if (!adap->fe[0]) { + ret = -ENODEV; + goto err; + } + + /* set fe callback */ + adap->fe[0]->callback = rtl2832u_frontend_callback; + + return 0; +err: + dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); return ret; } @@ -704,32 +780,34 @@ static struct mxl5005s_config rtl28xxu_mxl5005s_config = { static int rtl2831u_tuner_attach(struct dvb_usb_adapter *adap) { int ret; - struct rtl28xxu_priv *priv = adap->dev->priv; + struct dvb_usb_device *d = adap_to_d(adap); + struct rtl28xxu_priv *priv = d_to_priv(d); struct i2c_adapter *rtl2830_tuner_i2c; struct dvb_frontend *fe; - deb_info("%s:\n", __func__); + dev_dbg(&d->udev->dev, "%s:\n", __func__); /* use rtl2830 driver I2C adapter, for more info see rtl2830 driver */ - rtl2830_tuner_i2c = rtl2830_get_tuner_i2c_adapter(adap->fe_adap[0].fe); + rtl2830_tuner_i2c = rtl2830_get_tuner_i2c_adapter(adap->fe[0]); switch (priv->tuner) { case TUNER_RTL2830_QT1010: - fe = dvb_attach(qt1010_attach, adap->fe_adap[0].fe, + fe = dvb_attach(qt1010_attach, adap->fe[0], rtl2830_tuner_i2c, &rtl28xxu_qt1010_config); break; case TUNER_RTL2830_MT2060: - fe = dvb_attach(mt2060_attach, adap->fe_adap[0].fe, + fe = dvb_attach(mt2060_attach, adap->fe[0], rtl2830_tuner_i2c, &rtl28xxu_mt2060_config, 1220); break; case TUNER_RTL2830_MXL5005S: - fe = dvb_attach(mxl5005s_attach, adap->fe_adap[0].fe, + fe = dvb_attach(mxl5005s_attach, adap->fe[0], rtl2830_tuner_i2c, &rtl28xxu_mxl5005s_config); break; default: fe = NULL; - err("unknown tuner=%d", priv->tuner); + dev_err(&d->udev->dev, "%s: unknown tuner=%d\n", KBUILD_MODNAME, + priv->tuner); } if (fe == NULL) { @@ -739,40 +817,77 @@ static int rtl2831u_tuner_attach(struct dvb_usb_adapter *adap) return 0; err: - deb_info("%s: failed=%d\n", __func__, ret); + dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); return ret; } +static const struct e4000_config rtl2832u_e4000_config = { + .i2c_addr = 0x64, + .clock = 28800000, +}; + +static const struct fc2580_config rtl2832u_fc2580_config = { + .i2c_addr = 0x56, + .clock = 16384000, +}; + +static struct tua9001_config rtl2832u_tua9001_config = { + .i2c_addr = 0x60, +}; + static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap) { int ret; - struct rtl28xxu_priv *priv = adap->dev->priv; + struct dvb_usb_device *d = adap_to_d(adap); + struct rtl28xxu_priv *priv = d_to_priv(d); struct dvb_frontend *fe; - deb_info("%s:\n", __func__); + dev_dbg(&d->udev->dev, "%s:\n", __func__); switch (priv->tuner) { case TUNER_RTL2832_FC0012: - fe = dvb_attach(fc0012_attach, adap->fe_adap[0].fe, - &adap->dev->i2c_adap, 0xc6>>1, 0, FC_XTAL_28_8_MHZ); + fe = dvb_attach(fc0012_attach, adap->fe[0], + &d->i2c_adap, 0xc6>>1, 0, FC_XTAL_28_8_MHZ); /* since fc0012 includs reading the signal strength delegate * that to the tuner driver */ - adap->fe_adap[0].fe->ops.read_signal_strength = adap->fe_adap[0]. - fe->ops.tuner_ops.get_rf_strength; + adap->fe[0]->ops.read_signal_strength = + adap->fe[0]->ops.tuner_ops.get_rf_strength; return 0; break; case TUNER_RTL2832_FC0013: - fe = dvb_attach(fc0013_attach, adap->fe_adap[0].fe, - &adap->dev->i2c_adap, 0xc6>>1, 0, FC_XTAL_28_8_MHZ); + fe = dvb_attach(fc0013_attach, adap->fe[0], + &d->i2c_adap, 0xc6>>1, 0, FC_XTAL_28_8_MHZ); /* fc0013 also supports signal strength reading */ - adap->fe_adap[0].fe->ops.read_signal_strength = adap->fe_adap[0] - .fe->ops.tuner_ops.get_rf_strength; + adap->fe[0]->ops.read_signal_strength = + adap->fe[0]->ops.tuner_ops.get_rf_strength; return 0; + case TUNER_RTL2832_E4000: + fe = dvb_attach(e4000_attach, adap->fe[0], &d->i2c_adap, + &rtl2832u_e4000_config); + break; + case TUNER_RTL2832_FC2580: + fe = dvb_attach(fc2580_attach, adap->fe[0], &d->i2c_adap, + &rtl2832u_fc2580_config); + break; + case TUNER_RTL2832_TUA9001: + /* enable GPIO1 and GPIO4 as output */ + ret = rtl28xx_wr_reg_mask(d, SYS_GPIO_DIR, 0x00, 0x12); + if (ret) + goto err; + + ret = rtl28xx_wr_reg_mask(d, SYS_GPIO_OUT_EN, 0x12, 0x12); + if (ret) + goto err; + + fe = dvb_attach(tua9001_attach, adap->fe[0], &d->i2c_adap, + &rtl2832u_tua9001_config); + break; default: fe = NULL; - err("unknown tuner=%d", priv->tuner); + dev_err(&d->udev->dev, "%s: unknown tuner=%d\n", KBUILD_MODNAME, + priv->tuner); } if (fe == NULL) { @@ -782,77 +897,50 @@ static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap) return 0; err: - deb_info("%s: failed=%d\n", __func__, ret); + dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); return ret; } -static int rtl2831u_streaming_ctrl(struct dvb_usb_adapter *adap , int onoff) +static int rtl28xxu_init(struct dvb_usb_device *d) { int ret; - u8 buf[2], gpio; + u8 val; - deb_info("%s: onoff=%d\n", __func__, onoff); + dev_dbg(&d->udev->dev, "%s:\n", __func__); - ret = rtl28xx_rd_reg(adap->dev, SYS_GPIO_OUT_VAL, &gpio); + /* init USB endpoints */ + ret = rtl28xx_rd_reg(d, USB_SYSCTL_0, &val); if (ret) goto err; - if (onoff) { - buf[0] = 0x00; - buf[1] = 0x00; - gpio |= 0x04; /* LED on */ - } else { - buf[0] = 0x10; /* stall EPA */ - buf[1] = 0x02; /* reset EPA */ - gpio &= (~0x04); /* LED off */ - } - - ret = rtl28xx_wr_reg(adap->dev, SYS_GPIO_OUT_VAL, gpio); + /* enable DMA and Full Packet Mode*/ + val |= 0x09; + ret = rtl28xx_wr_reg(d, USB_SYSCTL_0, val); if (ret) goto err; - ret = rtl28xx_wr_regs(adap->dev, USB_EPA_CTL, buf, 2); + /* set EPA maximum packet size to 0x0200 */ + ret = rtl28xx_wr_regs(d, USB_EPA_MAXPKT, "\x00\x02\x00\x00", 4); if (ret) goto err; - return ret; -err: - deb_info("%s: failed=%d\n", __func__, ret); - return ret; -} - -static int rtl2832u_streaming_ctrl(struct dvb_usb_adapter *adap , int onoff) -{ - int ret; - u8 buf[2]; - - deb_info("%s: onoff=%d\n", __func__, onoff); - - - if (onoff) { - buf[0] = 0x00; - buf[1] = 0x00; - } else { - buf[0] = 0x10; /* stall EPA */ - buf[1] = 0x02; /* reset EPA */ - } - - ret = rtl28xx_wr_regs(adap->dev, USB_EPA_CTL, buf, 2); + /* change EPA FIFO length */ + ret = rtl28xx_wr_regs(d, USB_EPA_FIFO_CFG, "\x14\x00\x00\x00", 4); if (ret) goto err; return ret; err: - deb_info("%s: failed=%d\n", __func__, ret); + dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); return ret; } static int rtl2831u_power_ctrl(struct dvb_usb_device *d, int onoff) { int ret; - u8 gpio, sys0; + u8 gpio, sys0, epa_ctl[2]; - deb_info("%s: onoff=%d\n", __func__, onoff); + dev_dbg(&d->udev->dev, "%s: onoff=%d\n", __func__, onoff); /* demod adc */ ret = rtl28xx_rd_reg(d, SYS_SYS0, &sys0); @@ -864,20 +952,28 @@ static int rtl2831u_power_ctrl(struct dvb_usb_device *d, int onoff) if (ret) goto err; - deb_info("%s: RD SYS0=%02x GPIO_OUT_VAL=%02x\n", __func__, sys0, gpio); + dev_dbg(&d->udev->dev, "%s: RD SYS0=%02x GPIO_OUT_VAL=%02x\n", __func__, + sys0, gpio); if (onoff) { gpio |= 0x01; /* GPIO0 = 1 */ gpio &= (~0x10); /* GPIO4 = 0 */ + gpio |= 0x04; /* GPIO2 = 1, LED on */ sys0 = sys0 & 0x0f; sys0 |= 0xe0; + epa_ctl[0] = 0x00; /* clear stall */ + epa_ctl[1] = 0x00; /* clear reset */ } else { gpio &= (~0x01); /* GPIO0 = 0 */ gpio |= 0x10; /* GPIO4 = 1 */ + gpio &= (~0x04); /* GPIO2 = 1, LED off */ sys0 = sys0 & (~0xc0); + epa_ctl[0] = 0x10; /* set stall */ + epa_ctl[1] = 0x02; /* set reset */ } - deb_info("%s: WR SYS0=%02x GPIO_OUT_VAL=%02x\n", __func__, sys0, gpio); + dev_dbg(&d->udev->dev, "%s: WR SYS0=%02x GPIO_OUT_VAL=%02x\n", __func__, + sys0, gpio); /* demod adc */ ret = rtl28xx_wr_reg(d, SYS_SYS0, sys0); @@ -889,9 +985,17 @@ static int rtl2831u_power_ctrl(struct dvb_usb_device *d, int onoff) if (ret) goto err; + /* streaming EP: stall & reset */ + ret = rtl28xx_wr_regs(d, USB_EPA_CTL, epa_ctl, 2); + if (ret) + goto err; + + if (onoff) + usb_clear_halt(d->udev, usb_rcvbulkpipe(d->udev, 0x81)); + return ret; err: - deb_info("%s: failed=%d\n", __func__, ret); + dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); return ret; } @@ -900,7 +1004,7 @@ static int rtl2832u_power_ctrl(struct dvb_usb_device *d, int onoff) int ret; u8 val; - deb_info("%s: onoff=%d\n", __func__, onoff); + dev_dbg(&d->udev->dev, "%s: onoff=%d\n", __func__, onoff); if (onoff) { /* set output values */ @@ -939,17 +1043,6 @@ static int rtl2832u_power_ctrl(struct dvb_usb_device *d, int onoff) if (ret) goto err; - /* demod HW reset */ - ret = rtl28xx_rd_reg(d, SYS_DEMOD_CTL, &val); - if (ret) - goto err; - /* bit 5 to 0 */ - val &= 0xdf; - - ret = rtl28xx_wr_reg(d, SYS_DEMOD_CTL, val); - if (ret) - goto err; - ret = rtl28xx_rd_reg(d, SYS_DEMOD_CTL, &val); if (ret) goto err; @@ -973,7 +1066,14 @@ static int rtl2832u_power_ctrl(struct dvb_usb_device *d, int onoff) if (ret) goto err; + /* streaming EP: clear stall & reset */ + ret = rtl28xx_wr_regs(d, USB_EPA_CTL, "\x00\x00", 2); + if (ret) + goto err; + ret = usb_clear_halt(d->udev, usb_rcvbulkpipe(d->udev, 0x81)); + if (ret) + goto err; } else { /* demod_ctl_1 */ ret = rtl28xx_rd_reg(d, SYS_DEMOD_CTL1, &val); @@ -1008,11 +1108,15 @@ static int rtl2832u_power_ctrl(struct dvb_usb_device *d, int onoff) if (ret) goto err; + /* streaming EP: set stall & reset */ + ret = rtl28xx_wr_regs(d, USB_EPA_CTL, "\x10\x02", 2); + if (ret) + goto err; } return ret; err: - deb_info("%s: failed=%d\n", __func__, ret); + dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); return ret; } @@ -1085,10 +1189,21 @@ static int rtl2831u_rc_query(struct dvb_usb_device *d) return ret; err: - deb_info("%s: failed=%d\n", __func__, ret); + dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); return ret; } +static int rtl2831u_get_rc_config(struct dvb_usb_device *d, + struct dvb_usb_rc *rc) +{ + rc->map_name = RC_MAP_EMPTY; + rc->allowed_protos = RC_TYPE_NEC; + rc->query = rtl2831u_rc_query; + rc->interval = 400; + + return 0; +} + static int rtl2832u_rc_query(struct dvb_usb_device *d) { int ret, i; @@ -1146,281 +1261,108 @@ static int rtl2832u_rc_query(struct dvb_usb_device *d) exit: return ret; err: - deb_info("%s: failed=%d\n", __func__, ret); + dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); return ret; } -enum rtl28xxu_usb_table_entry { - RTL2831U_0BDA_2831, - RTL2831U_14AA_0160, - RTL2831U_14AA_0161, - RTL2832U_0CCD_00A9, - RTL2832U_1F4D_B803, - RTL2832U_0CCD_00B3, -}; - -static struct usb_device_id rtl28xxu_table[] = { - /* RTL2831U */ - [RTL2831U_0BDA_2831] = { - USB_DEVICE(USB_VID_REALTEK, USB_PID_REALTEK_RTL2831U)}, - [RTL2831U_14AA_0160] = { - USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_FREECOM_DVBT)}, - [RTL2831U_14AA_0161] = { - USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_FREECOM_DVBT_2)}, - - /* RTL2832U */ - [RTL2832U_0CCD_00A9] = { - USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_STICK_BLACK_REV1)}, - [RTL2832U_1F4D_B803] = { - USB_DEVICE(USB_VID_GTEK, USB_PID_DELOCK_USB2_DVBT)}, - [RTL2832U_0CCD_00B3] = { - USB_DEVICE(USB_VID_TERRATEC, USB_PID_NOXON_DAB_STICK)}, - {} /* terminating entry */ -}; - -MODULE_DEVICE_TABLE(usb, rtl28xxu_table); - -static struct dvb_usb_device_properties rtl28xxu_properties[] = { - { - .caps = DVB_USB_IS_AN_I2C_ADAPTER, - - .usb_ctrl = DEVICE_SPECIFIC, - .no_reconnect = 1, - - .size_of_priv = sizeof(struct rtl28xxu_priv), - - .num_adapters = 1, - .adapter = { - { - .num_frontends = 1, - .fe = { - { - .frontend_attach = rtl2831u_frontend_attach, - .tuner_attach = rtl2831u_tuner_attach, - .streaming_ctrl = rtl2831u_streaming_ctrl, - .stream = { - .type = USB_BULK, - .count = 6, - .endpoint = 0x81, - .u = { - .bulk = { - .buffersize = 8*512, - } - } - } - } - } - } - }, +static int rtl2832u_get_rc_config(struct dvb_usb_device *d, + struct dvb_usb_rc *rc) +{ + rc->map_name = RC_MAP_EMPTY; + rc->allowed_protos = RC_TYPE_NEC; + rc->query = rtl2832u_rc_query; + rc->interval = 400; - .power_ctrl = rtl2831u_power_ctrl, + return 0; +} - .rc.core = { - .protocol = RC_TYPE_NEC, - .module_name = "rtl28xxu", - .rc_query = rtl2831u_rc_query, - .rc_interval = 400, - .allowed_protos = RC_TYPE_NEC, - .rc_codes = RC_MAP_EMPTY, +static const struct dvb_usb_device_properties rtl2831u_props = { + .driver_name = KBUILD_MODNAME, + .owner = THIS_MODULE, + .adapter_nr = adapter_nr, + .size_of_priv = sizeof(struct rtl28xxu_priv), + + .power_ctrl = rtl2831u_power_ctrl, + .i2c_algo = &rtl28xxu_i2c_algo, + .read_config = rtl2831u_read_config, + .frontend_attach = rtl2831u_frontend_attach, + .tuner_attach = rtl2831u_tuner_attach, + .init = rtl28xxu_init, + .get_rc_config = rtl2831u_get_rc_config, + + .num_adapters = 1, + .adapter = { + { + .stream = DVB_USB_STREAM_BULK(0x81, 6, 8 * 512), }, - - .i2c_algo = &rtl28xxu_i2c_algo, - - .num_device_descs = 2, - .devices = { - { - .name = "Realtek RTL2831U reference design", - .warm_ids = { - &rtl28xxu_table[RTL2831U_0BDA_2831], - }, - }, - { - .name = "Freecom USB2.0 DVB-T", - .warm_ids = { - &rtl28xxu_table[RTL2831U_14AA_0160], - &rtl28xxu_table[RTL2831U_14AA_0161], - }, - }, - } }, - { - .caps = DVB_USB_IS_AN_I2C_ADAPTER, - - .usb_ctrl = DEVICE_SPECIFIC, - .no_reconnect = 1, - - .size_of_priv = sizeof(struct rtl28xxu_priv), - - .num_adapters = 1, - .adapter = { - { - .num_frontends = 1, - .fe = { - { - .frontend_attach = rtl2832u_frontend_attach, - .tuner_attach = rtl2832u_tuner_attach, - .streaming_ctrl = rtl2832u_streaming_ctrl, - .stream = { - .type = USB_BULK, - .count = 6, - .endpoint = 0x81, - .u = { - .bulk = { - .buffersize = 8*512, - } - } - } - } - } - } - }, - - .power_ctrl = rtl2832u_power_ctrl, +}; - .rc.core = { - .protocol = RC_TYPE_NEC, - .module_name = "rtl28xxu", - .rc_query = rtl2832u_rc_query, - .rc_interval = 400, - .allowed_protos = RC_TYPE_NEC, - .rc_codes = RC_MAP_EMPTY, +static const struct dvb_usb_device_properties rtl2832u_props = { + .driver_name = KBUILD_MODNAME, + .owner = THIS_MODULE, + .adapter_nr = adapter_nr, + .size_of_priv = sizeof(struct rtl28xxu_priv), + + .power_ctrl = rtl2832u_power_ctrl, + .i2c_algo = &rtl28xxu_i2c_algo, + .read_config = rtl2832u_read_config, + .frontend_attach = rtl2832u_frontend_attach, + .tuner_attach = rtl2832u_tuner_attach, + .init = rtl28xxu_init, + .get_rc_config = rtl2832u_get_rc_config, + + .num_adapters = 1, + .adapter = { + { + .stream = DVB_USB_STREAM_BULK(0x81, 6, 8 * 512), }, - - .i2c_algo = &rtl28xxu_i2c_algo, - - .num_device_descs = 3, - .devices = { - { - .name = "Terratec Cinergy T Stick Black", - .warm_ids = { - &rtl28xxu_table[RTL2832U_0CCD_00A9], - }, - }, - { - .name = "G-Tek Electronics Group Lifeview LV5TDLX DVB-T", - .warm_ids = { - &rtl28xxu_table[RTL2832U_1F4D_B803], - }, - }, - { - .name = "NOXON DAB/DAB+ USB dongle", - .warm_ids = { - &rtl28xxu_table[RTL2832U_0CCD_00B3], - }, - }, - } }, - }; -static int rtl28xxu_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - int ret, i; - u8 val; - int properties_count = ARRAY_SIZE(rtl28xxu_properties); - struct dvb_usb_device *d; - struct usb_device *udev; - bool found; - - deb_info("%s: interface=%d\n", __func__, - intf->cur_altsetting->desc.bInterfaceNumber); - - if (intf->cur_altsetting->desc.bInterfaceNumber != 0) - return 0; - - /* Dynamic USB ID support. Replaces first device ID with current one .*/ - udev = interface_to_usbdev(intf); - - for (i = 0, found = false; i < ARRAY_SIZE(rtl28xxu_table) - 1; i++) { - if (rtl28xxu_table[i].idVendor == - le16_to_cpu(udev->descriptor.idVendor) && - rtl28xxu_table[i].idProduct == - le16_to_cpu(udev->descriptor.idProduct)) { - found = true; - break; - } - } - - if (!found) { - deb_info("%s: using dynamic ID %04x:%04x\n", __func__, - le16_to_cpu(udev->descriptor.idVendor), - le16_to_cpu(udev->descriptor.idProduct)); - rtl28xxu_properties[0].devices[0].warm_ids[0]->idVendor = - le16_to_cpu(udev->descriptor.idVendor); - rtl28xxu_properties[0].devices[0].warm_ids[0]->idProduct = - le16_to_cpu(udev->descriptor.idProduct); - } - - for (i = 0; i < properties_count; i++) { - ret = dvb_usb_device_init(intf, &rtl28xxu_properties[i], - THIS_MODULE, &d, adapter_nr); - if (ret == 0 || ret != -ENODEV) - break; - } - - if (ret) - goto err; - - - /* init USB endpoints */ - ret = rtl28xx_rd_reg(d, USB_SYSCTL_0, &val); - if (ret) - goto err; - - /* enable DMA and Full Packet Mode*/ - val |= 0x09; - ret = rtl28xx_wr_reg(d, USB_SYSCTL_0, val); - if (ret) - goto err; - - /* set EPA maximum packet size to 0x0200 */ - ret = rtl28xx_wr_regs(d, USB_EPA_MAXPKT, "\x00\x02\x00\x00", 4); - if (ret) - goto err; - - /* change EPA FIFO length */ - ret = rtl28xx_wr_regs(d, USB_EPA_FIFO_CFG, "\x14\x00\x00\x00", 4); - if (ret) - goto err; - - return ret; -err: - deb_info("%s: failed=%d\n", __func__, ret); - return ret; -} - -static struct usb_driver rtl28xxu_driver = { - .name = "dvb_usb_rtl28xxu", - .probe = rtl28xxu_probe, - .disconnect = dvb_usb_device_exit, - .id_table = rtl28xxu_table, +static const struct usb_device_id rtl28xxu_id_table[] = { + { DVB_USB_DEVICE(USB_VID_REALTEK, USB_PID_REALTEK_RTL2831U, + &rtl2831u_props, "Realtek RTL2831U reference design", NULL) }, + { DVB_USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_FREECOM_DVBT, + &rtl2831u_props, "Freecom USB2.0 DVB-T", NULL) }, + { DVB_USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_FREECOM_DVBT_2, + &rtl2831u_props, "Freecom USB2.0 DVB-T", NULL) }, + + { DVB_USB_DEVICE(USB_VID_REALTEK, 0x2832, + &rtl2832u_props, "Realtek RTL2832U reference design", NULL) }, + { DVB_USB_DEVICE(USB_VID_REALTEK, 0x2838, + &rtl2832u_props, "Realtek RTL2832U reference design", NULL) }, + { DVB_USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_STICK_BLACK_REV1, + &rtl2832u_props, "Terratec Cinergy T Stick Black", NULL) }, + { DVB_USB_DEVICE(USB_VID_GTEK, USB_PID_DELOCK_USB2_DVBT, + &rtl2832u_props, "G-Tek Electronics Group Lifeview LV5TDLX DVB-T", NULL) }, + { DVB_USB_DEVICE(USB_VID_TERRATEC, USB_PID_NOXON_DAB_STICK, + &rtl2832u_props, "NOXON DAB/DAB+ USB dongle", NULL) }, + { DVB_USB_DEVICE(USB_VID_GTEK, USB_PID_TREKSTOR_TERRES_2_0, + &rtl2832u_props, "Trekstor DVB-T Stick Terres 2.0", NULL) }, + { DVB_USB_DEVICE(USB_VID_DEXATEK, 0x1101, + &rtl2832u_props, "Dexatek DK DVB-T Dongle", NULL) }, + { DVB_USB_DEVICE(USB_VID_LEADTEK, 0x6680, + &rtl2832u_props, "DigitalNow Quad DVB-T Receiver", NULL) }, + { DVB_USB_DEVICE(USB_VID_TERRATEC, 0x00d3, + &rtl2832u_props, "TerraTec Cinergy T Stick RC (Rev. 3)", NULL) }, + { } +}; +MODULE_DEVICE_TABLE(usb, rtl28xxu_id_table); + +static struct usb_driver rtl28xxu_usb_driver = { + .name = KBUILD_MODNAME, + .id_table = rtl28xxu_id_table, + .probe = dvb_usbv2_probe, + .disconnect = dvb_usbv2_disconnect, + .suspend = dvb_usbv2_suspend, + .resume = dvb_usbv2_resume, + .reset_resume = dvb_usbv2_reset_resume, + .no_dynamic_id = 1, + .soft_unbind = 1, }; -/* module stuff */ -static int __init rtl28xxu_module_init(void) -{ - int ret; - - deb_info("%s:\n", __func__); - - ret = usb_register(&rtl28xxu_driver); - if (ret) - err("usb_register failed=%d", ret); - - return ret; -} - -static void __exit rtl28xxu_module_exit(void) -{ - deb_info("%s:\n", __func__); - - /* deregister this driver from the USB subsystem */ - usb_deregister(&rtl28xxu_driver); -} - -module_init(rtl28xxu_module_init); -module_exit(rtl28xxu_module_exit); +module_usb_driver(rtl28xxu_usb_driver); MODULE_DESCRIPTION("Realtek RTL28xxU DVB USB driver"); MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>"); diff --git a/drivers/media/dvb/dvb-usb/rtl28xxu.h b/drivers/media/usb/dvb-usb-v2/rtl28xxu.h index 90f3bb4f4c0e..2f3af2d3b6ce 100644 --- a/drivers/media/dvb/dvb-usb/rtl28xxu.h +++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.h @@ -22,28 +22,7 @@ #ifndef RTL28XXU_H #define RTL28XXU_H -#define DVB_USB_LOG_PREFIX "rtl28xxu" -#include "dvb-usb.h" - -#define deb_info(args...) dprintk(dvb_usb_rtl28xxu_debug, 0x01, args) -#define deb_rc(args...) dprintk(dvb_usb_rtl28xxu_debug, 0x02, args) -#define deb_xfer(args...) dprintk(dvb_usb_rtl28xxu_debug, 0x04, args) -#define deb_reg(args...) dprintk(dvb_usb_rtl28xxu_debug, 0x08, args) -#define deb_i2c(args...) dprintk(dvb_usb_rtl28xxu_debug, 0x10, args) -#define deb_fw(args...) dprintk(dvb_usb_rtl28xxu_debug, 0x20, args) - -#define deb_dump(r, t, v, i, b, l, func) { \ - int loop_; \ - func("%02x %02x %02x %02x %02x %02x %02x %02x", \ - t, r, v & 0xff, v >> 8, i & 0xff, i >> 8, l & 0xff, l >> 8); \ - if (t == (USB_TYPE_VENDOR | USB_DIR_OUT)) \ - func(" >>> "); \ - else \ - func(" <<< "); \ - for (loop_ = 0; loop_ < l; loop_++) \ - func("%02x ", b[loop_]); \ - func("\n");\ -} +#include "dvb_usb.h" /* * USB commands @@ -74,6 +53,7 @@ struct rtl28xxu_priv { u8 chip_id; u8 tuner; + char *tuner_name; u8 page; /* integrated demod active register page */ bool rc_active; }; @@ -84,14 +64,15 @@ enum rtl28xxu_chip_id { CHIP_ID_RTL2832U, }; +/* XXX: Hack. This must be keep sync with rtl2832 demod driver. */ enum rtl28xxu_tuner { TUNER_NONE, - TUNER_RTL2830_QT1010, + TUNER_RTL2830_QT1010 = 0x10, TUNER_RTL2830_MT2060, TUNER_RTL2830_MXL5005S, - TUNER_RTL2832_MT2266, + TUNER_RTL2832_MT2266 = 0x20, TUNER_RTL2832_FC2580, TUNER_RTL2832_MT2063, TUNER_RTL2832_MAX3543, diff --git a/drivers/media/usb/dvb-usb-v2/usb_urb.c b/drivers/media/usb/dvb-usb-v2/usb_urb.c new file mode 100644 index 000000000000..5989b6590377 --- /dev/null +++ b/drivers/media/usb/dvb-usb-v2/usb_urb.c @@ -0,0 +1,358 @@ +/* usb-urb.c is part of the DVB USB library. + * + * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@desy.de) + * see dvb-usb-init.c for copyright information. + * + * This file keeps functions for initializing and handling the + * BULK and ISOC USB data transfers in a generic way. + * Can be used for DVB-only and also, that's the plan, for + * Hybrid USB devices (analog and DVB). + */ +#include "dvb_usb_common.h" + +/* URB stuff for streaming */ + +int usb_urb_reconfig(struct usb_data_stream *stream, + struct usb_data_stream_properties *props); + +static void usb_urb_complete(struct urb *urb) +{ + struct usb_data_stream *stream = urb->context; + int ptype = usb_pipetype(urb->pipe); + int i; + u8 *b; + + dev_dbg_ratelimited(&stream->udev->dev, "%s: %s urb completed " \ + "status=%d length=%d/%d pack_num=%d errors=%d\n", + __func__, ptype == PIPE_ISOCHRONOUS ? "isoc" : "bulk", + urb->status, urb->actual_length, + urb->transfer_buffer_length, + urb->number_of_packets, urb->error_count); + + switch (urb->status) { + case 0: /* success */ + case -ETIMEDOUT: /* NAK */ + break; + case -ECONNRESET: /* kill */ + case -ENOENT: + case -ESHUTDOWN: + return; + default: /* error */ + dev_dbg_ratelimited(&stream->udev->dev, + "%s: urb completition failed=%d\n", + __func__, urb->status); + break; + } + + b = (u8 *) urb->transfer_buffer; + switch (ptype) { + case PIPE_ISOCHRONOUS: + for (i = 0; i < urb->number_of_packets; i++) { + if (urb->iso_frame_desc[i].status != 0) + dev_dbg(&stream->udev->dev, "%s: iso frame " \ + "descriptor has an error=%d\n", + __func__, + urb->iso_frame_desc[i].status); + else if (urb->iso_frame_desc[i].actual_length > 0) + stream->complete(stream, + b + urb->iso_frame_desc[i].offset, + urb->iso_frame_desc[i].actual_length); + + urb->iso_frame_desc[i].status = 0; + urb->iso_frame_desc[i].actual_length = 0; + } + break; + case PIPE_BULK: + if (urb->actual_length > 0) + stream->complete(stream, b, urb->actual_length); + break; + default: + dev_err(&stream->udev->dev, "%s: unknown endpoint type in " \ + "completition handler\n", KBUILD_MODNAME); + return; + } + usb_submit_urb(urb, GFP_ATOMIC); +} + +int usb_urb_killv2(struct usb_data_stream *stream) +{ + int i; + for (i = 0; i < stream->urbs_submitted; i++) { + dev_dbg(&stream->udev->dev, "%s: kill urb=%d\n", __func__, i); + /* stop the URB */ + usb_kill_urb(stream->urb_list[i]); + } + stream->urbs_submitted = 0; + return 0; +} + +int usb_urb_submitv2(struct usb_data_stream *stream, + struct usb_data_stream_properties *props) +{ + int i, ret; + + if (props) { + ret = usb_urb_reconfig(stream, props); + if (ret < 0) + return ret; + } + + for (i = 0; i < stream->urbs_initialized; i++) { + dev_dbg(&stream->udev->dev, "%s: submit urb=%d\n", __func__, i); + ret = usb_submit_urb(stream->urb_list[i], GFP_ATOMIC); + if (ret) { + dev_err(&stream->udev->dev, "%s: could not submit " \ + "urb no. %d - get them all back\n", + KBUILD_MODNAME, i); + usb_urb_killv2(stream); + return ret; + } + stream->urbs_submitted++; + } + return 0; +} + +int usb_urb_free_urbs(struct usb_data_stream *stream) +{ + int i; + + usb_urb_killv2(stream); + + for (i = stream->urbs_initialized - 1; i >= 0; i--) { + if (stream->urb_list[i]) { + dev_dbg(&stream->udev->dev, "%s: free urb=%d\n", + __func__, i); + /* free the URBs */ + usb_free_urb(stream->urb_list[i]); + } + } + stream->urbs_initialized = 0; + + return 0; +} + +static int usb_urb_alloc_bulk_urbs(struct usb_data_stream *stream) +{ + int i, j; + + /* allocate the URBs */ + for (i = 0; i < stream->props.count; i++) { + dev_dbg(&stream->udev->dev, "%s: alloc urb=%d\n", __func__, i); + stream->urb_list[i] = usb_alloc_urb(0, GFP_ATOMIC); + if (!stream->urb_list[i]) { + dev_dbg(&stream->udev->dev, "%s: failed\n", __func__); + for (j = 0; j < i; j++) + usb_free_urb(stream->urb_list[j]); + return -ENOMEM; + } + usb_fill_bulk_urb(stream->urb_list[i], + stream->udev, + usb_rcvbulkpipe(stream->udev, + stream->props.endpoint), + stream->buf_list[i], + stream->props.u.bulk.buffersize, + usb_urb_complete, stream); + + stream->urb_list[i]->transfer_flags = URB_NO_TRANSFER_DMA_MAP; + stream->urb_list[i]->transfer_dma = stream->dma_addr[i]; + stream->urbs_initialized++; + } + return 0; +} + +static int usb_urb_alloc_isoc_urbs(struct usb_data_stream *stream) +{ + int i, j; + + /* allocate the URBs */ + for (i = 0; i < stream->props.count; i++) { + struct urb *urb; + int frame_offset = 0; + dev_dbg(&stream->udev->dev, "%s: alloc urb=%d\n", __func__, i); + stream->urb_list[i] = usb_alloc_urb( + stream->props.u.isoc.framesperurb, GFP_ATOMIC); + if (!stream->urb_list[i]) { + dev_dbg(&stream->udev->dev, "%s: failed\n", __func__); + for (j = 0; j < i; j++) + usb_free_urb(stream->urb_list[j]); + return -ENOMEM; + } + + urb = stream->urb_list[i]; + + urb->dev = stream->udev; + urb->context = stream; + urb->complete = usb_urb_complete; + urb->pipe = usb_rcvisocpipe(stream->udev, + stream->props.endpoint); + urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP; + urb->interval = stream->props.u.isoc.interval; + urb->number_of_packets = stream->props.u.isoc.framesperurb; + urb->transfer_buffer_length = stream->props.u.isoc.framesize * + stream->props.u.isoc.framesperurb; + urb->transfer_buffer = stream->buf_list[i]; + urb->transfer_dma = stream->dma_addr[i]; + + for (j = 0; j < stream->props.u.isoc.framesperurb; j++) { + urb->iso_frame_desc[j].offset = frame_offset; + urb->iso_frame_desc[j].length = + stream->props.u.isoc.framesize; + frame_offset += stream->props.u.isoc.framesize; + } + + stream->urbs_initialized++; + } + return 0; +} + +int usb_free_stream_buffers(struct usb_data_stream *stream) +{ + if (stream->state & USB_STATE_URB_BUF) { + while (stream->buf_num) { + stream->buf_num--; + dev_dbg(&stream->udev->dev, "%s: free buf=%d\n", + __func__, stream->buf_num); + usb_free_coherent(stream->udev, stream->buf_size, + stream->buf_list[stream->buf_num], + stream->dma_addr[stream->buf_num]); + } + } + + stream->state &= ~USB_STATE_URB_BUF; + + return 0; +} + +int usb_alloc_stream_buffers(struct usb_data_stream *stream, int num, + unsigned long size) +{ + stream->buf_num = 0; + stream->buf_size = size; + + dev_dbg(&stream->udev->dev, "%s: all in all I will use %lu bytes for " \ + "streaming\n", __func__, num * size); + + for (stream->buf_num = 0; stream->buf_num < num; stream->buf_num++) { + stream->buf_list[stream->buf_num] = usb_alloc_coherent( + stream->udev, size, GFP_ATOMIC, + &stream->dma_addr[stream->buf_num]); + if (!stream->buf_list[stream->buf_num]) { + dev_dbg(&stream->udev->dev, "%s: alloc buf=%d failed\n", + __func__, stream->buf_num); + usb_free_stream_buffers(stream); + return -ENOMEM; + } + + dev_dbg(&stream->udev->dev, "%s: alloc buf=%d %p (dma %llu)\n", + __func__, stream->buf_num, + stream->buf_list[stream->buf_num], + (long long)stream->dma_addr[stream->buf_num]); + memset(stream->buf_list[stream->buf_num], 0, size); + stream->state |= USB_STATE_URB_BUF; + } + + return 0; +} + +int usb_urb_reconfig(struct usb_data_stream *stream, + struct usb_data_stream_properties *props) +{ + int buf_size; + + if (!props) + return 0; + + /* check allocated buffers are large enough for the request */ + if (props->type == USB_BULK) { + buf_size = stream->props.u.bulk.buffersize; + } else if (props->type == USB_ISOC) { + buf_size = props->u.isoc.framesize * props->u.isoc.framesperurb; + } else { + dev_err(&stream->udev->dev, "%s: invalid endpoint type=%d\n", + KBUILD_MODNAME, props->type); + return -EINVAL; + } + + if (stream->buf_num < props->count || stream->buf_size < buf_size) { + dev_err(&stream->udev->dev, "%s: cannot reconfigure as " \ + "allocated buffers are too small\n", + KBUILD_MODNAME); + return -EINVAL; + } + + /* check if all fields are same */ + if (stream->props.type == props->type && + stream->props.count == props->count && + stream->props.endpoint == props->endpoint) { + if (props->type == USB_BULK && + props->u.bulk.buffersize == + stream->props.u.bulk.buffersize) + return 0; + else if (props->type == USB_ISOC && + props->u.isoc.framesperurb == + stream->props.u.isoc.framesperurb && + props->u.isoc.framesize == + stream->props.u.isoc.framesize && + props->u.isoc.interval == + stream->props.u.isoc.interval) + return 0; + } + + dev_dbg(&stream->udev->dev, "%s: re-alloc urbs\n", __func__); + + usb_urb_free_urbs(stream); + memcpy(&stream->props, props, sizeof(*props)); + if (props->type == USB_BULK) + return usb_urb_alloc_bulk_urbs(stream); + else if (props->type == USB_ISOC) + return usb_urb_alloc_isoc_urbs(stream); + + return 0; +} + +int usb_urb_initv2(struct usb_data_stream *stream, + const struct usb_data_stream_properties *props) +{ + int ret; + + if (!stream || !props) + return -EINVAL; + + memcpy(&stream->props, props, sizeof(*props)); + + if (!stream->complete) { + dev_err(&stream->udev->dev, "%s: there is no data callback - " \ + "this doesn't make sense\n", KBUILD_MODNAME); + return -EINVAL; + } + + switch (stream->props.type) { + case USB_BULK: + ret = usb_alloc_stream_buffers(stream, stream->props.count, + stream->props.u.bulk.buffersize); + if (ret < 0) + return ret; + + return usb_urb_alloc_bulk_urbs(stream); + case USB_ISOC: + ret = usb_alloc_stream_buffers(stream, stream->props.count, + stream->props.u.isoc.framesize * + stream->props.u.isoc.framesperurb); + if (ret < 0) + return ret; + + return usb_urb_alloc_isoc_urbs(stream); + default: + dev_err(&stream->udev->dev, "%s: unknown urb-type for data " \ + "transfer\n", KBUILD_MODNAME); + return -EINVAL; + } +} + +int usb_urb_exitv2(struct usb_data_stream *stream) +{ + usb_urb_free_urbs(stream); + usb_free_stream_buffers(stream); + + return 0; +} diff --git a/drivers/media/usb/dvb-usb/Kconfig b/drivers/media/usb/dvb-usb/Kconfig new file mode 100644 index 000000000000..fa0b2931d305 --- /dev/null +++ b/drivers/media/usb/dvb-usb/Kconfig @@ -0,0 +1,313 @@ +config DVB_USB + tristate "Support for various USB DVB devices" + depends on DVB_CORE && USB && I2C && RC_CORE + help + By enabling this you will be able to choose the various supported + USB1.1 and USB2.0 DVB devices. + + Almost every USB device needs a firmware, please look into + <file:Documentation/dvb/README.dvb-usb>. + + For a complete list of supported USB devices see the LinuxTV DVB Wiki: + <http://www.linuxtv.org/wiki/index.php/DVB_USB> + + Say Y if you own a USB DVB device. + +config DVB_USB_DEBUG + bool "Enable extended debug support for all DVB-USB devices" + depends on DVB_USB + help + Say Y if you want to enable debugging. See modinfo dvb-usb (and the + appropriate drivers) for debug levels. + +config DVB_USB_A800 + tristate "AVerMedia AverTV DVB-T USB 2.0 (A800)" + depends on DVB_USB + select DVB_DIB3000MC + select DVB_PLL if MEDIA_SUBDRV_AUTOSELECT + select MEDIA_TUNER_MT2060 if MEDIA_SUBDRV_AUTOSELECT + help + Say Y here to support the AVerMedia AverTV DVB-T USB 2.0 (A800) receiver. + +config DVB_USB_DIBUSB_MB + tristate "DiBcom USB DVB-T devices (based on the DiB3000M-B) (see help for device list)" + depends on DVB_USB + select DVB_PLL if MEDIA_SUBDRV_AUTOSELECT + select DVB_DIB3000MB + select MEDIA_TUNER_MT2060 if MEDIA_SUBDRV_AUTOSELECT + help + Support for USB 1.1 and 2.0 DVB-T receivers based on reference designs made by + DiBcom (<http://www.dibcom.fr>) equipped with a DiB3000M-B demodulator. + + For an up-to-date list of devices supported by this driver, have a look + on the Linux-DVB Wiki at www.linuxtv.org. + + Say Y if you own such a device and want to use it. You should build it as + a module. + +config DVB_USB_DIBUSB_MB_FAULTY + bool "Support faulty USB IDs" + depends on DVB_USB_DIBUSB_MB + help + Support for faulty USB IDs due to an invalid EEPROM on some Artec devices. + +config DVB_USB_DIBUSB_MC + tristate "DiBcom USB DVB-T devices (based on the DiB3000M-C/P) (see help for device list)" + depends on DVB_USB + select DVB_DIB3000MC + select MEDIA_TUNER_MT2060 if MEDIA_SUBDRV_AUTOSELECT + help + Support for USB2.0 DVB-T receivers based on reference designs made by + DiBcom (<http://www.dibcom.fr>) equipped with a DiB3000M-C/P demodulator. + + For an up-to-date list of devices supported by this driver, have a look + on the Linux-DVB Wiki at www.linuxtv.org. + + Say Y if you own such a device and want to use it. You should build it as + a module. + +config DVB_USB_DIB0700 + tristate "DiBcom DiB0700 USB DVB devices (see help for supported devices)" + depends on DVB_USB + select DVB_DIB7000P if MEDIA_SUBDRV_AUTOSELECT + select DVB_DIB7000M if MEDIA_SUBDRV_AUTOSELECT + select DVB_DIB8000 if MEDIA_SUBDRV_AUTOSELECT + select DVB_DIB3000MC if MEDIA_SUBDRV_AUTOSELECT + select DVB_S5H1411 if MEDIA_SUBDRV_AUTOSELECT + select DVB_LGDT3305 if MEDIA_SUBDRV_AUTOSELECT + select DVB_TUNER_DIB0070 if MEDIA_SUBDRV_AUTOSELECT + select DVB_TUNER_DIB0090 if MEDIA_SUBDRV_AUTOSELECT + select MEDIA_TUNER_MT2060 if MEDIA_SUBDRV_AUTOSELECT + select MEDIA_TUNER_MT2266 if MEDIA_SUBDRV_AUTOSELECT + select MEDIA_TUNER_XC2028 if MEDIA_SUBDRV_AUTOSELECT + select MEDIA_TUNER_XC5000 if MEDIA_SUBDRV_AUTOSELECT + select MEDIA_TUNER_XC4000 if MEDIA_SUBDRV_AUTOSELECT + select MEDIA_TUNER_MXL5007T if MEDIA_SUBDRV_AUTOSELECT + help + Support for USB2.0/1.1 DVB receivers based on the DiB0700 USB bridge. The + USB bridge is also present in devices having the DiB7700 DVB-T-USB + silicon. This chip can be found in devices offered by Hauppauge, + Avermedia and other big and small companies. + + For an up-to-date list of devices supported by this driver, have a look + on the LinuxTV Wiki at www.linuxtv.org. + + Say Y if you own such a device and want to use it. You should build it as + a module. + +config DVB_USB_UMT_010 + tristate "HanfTek UMT-010 DVB-T USB2.0 support" + depends on DVB_USB + select DVB_PLL if MEDIA_SUBDRV_AUTOSELECT + select DVB_DIB3000MC + select MEDIA_TUNER_MT2060 if MEDIA_SUBDRV_AUTOSELECT + select DVB_MT352 if MEDIA_SUBDRV_AUTOSELECT + help + Say Y here to support the HanfTek UMT-010 USB2.0 stick-sized DVB-T receiver. + +config DVB_USB_CXUSB + tristate "Conexant USB2.0 hybrid reference design support" + depends on DVB_USB + select DVB_PLL if MEDIA_SUBDRV_AUTOSELECT + select DVB_CX22702 if MEDIA_SUBDRV_AUTOSELECT + select DVB_LGDT330X if MEDIA_SUBDRV_AUTOSELECT + select DVB_MT352 if MEDIA_SUBDRV_AUTOSELECT + select DVB_ZL10353 if MEDIA_SUBDRV_AUTOSELECT + select DVB_DIB7000P if MEDIA_SUBDRV_AUTOSELECT + select DVB_TUNER_DIB0070 if MEDIA_SUBDRV_AUTOSELECT + select DVB_ATBM8830 if MEDIA_SUBDRV_AUTOSELECT + select DVB_LGS8GXX if MEDIA_SUBDRV_AUTOSELECT + select MEDIA_TUNER_SIMPLE if MEDIA_SUBDRV_AUTOSELECT + select MEDIA_TUNER_XC2028 if MEDIA_SUBDRV_AUTOSELECT + select MEDIA_TUNER_MXL5005S if MEDIA_SUBDRV_AUTOSELECT + select MEDIA_TUNER_MAX2165 if MEDIA_SUBDRV_AUTOSELECT + help + Say Y here to support the Conexant USB2.0 hybrid reference design. + Currently, only DVB and ATSC modes are supported, analog mode + shall be added in the future. Devices that require this module: + + Medion MD95700 hybrid USB2.0 device. + DViCO FusionHDTV (Bluebird) USB2.0 devices + +config DVB_USB_M920X + tristate "Uli m920x DVB-T USB2.0 support" + depends on DVB_USB + select DVB_MT352 if MEDIA_SUBDRV_AUTOSELECT + select DVB_TDA1004X if MEDIA_SUBDRV_AUTOSELECT + select MEDIA_TUNER_QT1010 if MEDIA_SUBDRV_AUTOSELECT + select MEDIA_TUNER_TDA827X if MEDIA_SUBDRV_AUTOSELECT + select MEDIA_TUNER_SIMPLE if MEDIA_SUBDRV_AUTOSELECT + help + Say Y here to support the MSI Mega Sky 580 USB2.0 DVB-T receiver. + Currently, only devices with a product id of + "DTV USB MINI" (in cold state) are supported. + Firmware required. + +config DVB_USB_DIGITV + tristate "Nebula Electronics uDigiTV DVB-T USB2.0 support" + depends on DVB_USB + select DVB_PLL if MEDIA_SUBDRV_AUTOSELECT + select DVB_NXT6000 if MEDIA_SUBDRV_AUTOSELECT + select DVB_MT352 if MEDIA_SUBDRV_AUTOSELECT + help + Say Y here to support the Nebula Electronics uDigitV USB2.0 DVB-T receiver. + +config DVB_USB_VP7045 + tristate "TwinhanDTV Alpha/MagicBoxII, DNTV tinyUSB2, Beetle USB2.0 support" + depends on DVB_USB + help + Say Y here to support the + + TwinhanDTV Alpha (stick) (VP-7045), + TwinhanDTV MagicBox II (VP-7046), + DigitalNow TinyUSB 2 DVB-t, + DigitalRise USB 2.0 Ter (Beetle) and + TYPHOON DVB-T USB DRIVE + + DVB-T USB2.0 receivers. + +config DVB_USB_VP702X + tristate "TwinhanDTV StarBox and clones DVB-S USB2.0 support" + depends on DVB_USB + help + Say Y here to support the + + TwinhanDTV StarBox, + DigitalRise USB Starbox and + TYPHOON DVB-S USB 2.0 BOX + + DVB-S USB2.0 receivers. + +config DVB_USB_GP8PSK + tristate "GENPIX 8PSK->USB module support" + depends on DVB_USB + help + Say Y here to support the + GENPIX 8psk module + + DVB-S USB2.0 receivers. + +config DVB_USB_NOVA_T_USB2 + tristate "Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 support" + depends on DVB_USB + select DVB_DIB3000MC + select DVB_PLL if MEDIA_SUBDRV_AUTOSELECT + select MEDIA_TUNER_MT2060 if MEDIA_SUBDRV_AUTOSELECT + help + Say Y here to support the Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 receiver. + +config DVB_USB_TTUSB2 + tristate "Pinnacle 400e DVB-S USB2.0 support" + depends on DVB_USB + select DVB_TDA10086 if MEDIA_SUBDRV_AUTOSELECT + select DVB_LNBP21 if MEDIA_SUBDRV_AUTOSELECT + select DVB_TDA826X if MEDIA_SUBDRV_AUTOSELECT + help + Say Y here to support the Pinnacle 400e DVB-S USB2.0 receiver. The + firmware protocol used by this module is similar to the one used by the + old ttusb-driver - that's why the module is called dvb-usb-ttusb2. + +config DVB_USB_DTT200U + tristate "WideView WT-200U and WT-220U (pen) DVB-T USB2.0 support (Yakumo/Hama/Typhoon/Yuan)" + depends on DVB_USB + help + Say Y here to support the WideView/Yakumo/Hama/Typhoon/Yuan DVB-T USB2.0 receiver. + + The receivers are also known as DTT200U (Yakumo) and UB300 (Yuan). + + The WT-220U and its clones are pen-sized. + +config DVB_USB_OPERA1 + tristate "Opera1 DVB-S USB2.0 receiver" + depends on DVB_USB + select DVB_STV0299 if MEDIA_SUBDRV_AUTOSELECT + select DVB_PLL if MEDIA_SUBDRV_AUTOSELECT + help + Say Y here to support the Opera DVB-S USB2.0 receiver. + +config DVB_USB_AF9005 + tristate "Afatech AF9005 DVB-T USB1.1 support" + depends on DVB_USB + select MEDIA_TUNER_MT2060 if MEDIA_SUBDRV_AUTOSELECT + select MEDIA_TUNER_QT1010 if MEDIA_SUBDRV_AUTOSELECT + help + Say Y here to support the Afatech AF9005 based DVB-T USB1.1 receiver + and the TerraTec Cinergy T USB XE (Rev.1) + +config DVB_USB_AF9005_REMOTE + tristate "Afatech AF9005 default remote control support" + depends on DVB_USB_AF9005 + help + Say Y here to support the default remote control decoding for the + Afatech AF9005 based receiver. + +config DVB_USB_PCTV452E + tristate "Pinnacle PCTV HDTV Pro USB device/TT Connect S2-3600" + depends on DVB_USB + select TTPCI_EEPROM + select DVB_LNBP22 if MEDIA_SUBDRV_AUTOSELECT + select DVB_STB0899 if MEDIA_SUBDRV_AUTOSELECT + select DVB_STB6100 if MEDIA_SUBDRV_AUTOSELECT + help + Support for external USB adapter designed by Pinnacle, + shipped under the brand name 'PCTV HDTV Pro USB'. + Also supports TT Connect S2-3600/3650 cards. + Say Y if you own such a device and want to use it. + +config DVB_USB_DW2102 + tristate "DvbWorld & TeVii DVB-S/S2 USB2.0 support" + depends on DVB_USB + select DVB_PLL if MEDIA_SUBDRV_AUTOSELECT + select DVB_STV0299 if MEDIA_SUBDRV_AUTOSELECT + select DVB_STV0288 if MEDIA_SUBDRV_AUTOSELECT + select DVB_STB6000 if MEDIA_SUBDRV_AUTOSELECT + select DVB_CX24116 if MEDIA_SUBDRV_AUTOSELECT + select DVB_SI21XX if MEDIA_SUBDRV_AUTOSELECT + select DVB_TDA10023 if MEDIA_SUBDRV_AUTOSELECT + select DVB_MT312 if MEDIA_SUBDRV_AUTOSELECT + select DVB_ZL10039 if MEDIA_SUBDRV_AUTOSELECT + select DVB_DS3000 if MEDIA_SUBDRV_AUTOSELECT + select DVB_STB6100 if MEDIA_SUBDRV_AUTOSELECT + select DVB_STV6110 if MEDIA_SUBDRV_AUTOSELECT + select DVB_STV0900 if MEDIA_SUBDRV_AUTOSELECT + help + Say Y here to support the DvbWorld, TeVii, Prof DVB-S/S2 USB2.0 + receivers. + +config DVB_USB_CINERGY_T2 + tristate "Terratec CinergyT2/qanu USB 2.0 DVB-T receiver" + depends on DVB_USB + help + Support for "TerraTec CinergyT2" USB2.0 Highspeed DVB Receivers + + Say Y if you own such a device and want to use it. + +config DVB_USB_DTV5100 + tristate "AME DTV-5100 USB2.0 DVB-T support" + depends on DVB_USB + select DVB_ZL10353 if MEDIA_SUBDRV_AUTOSELECT + select MEDIA_TUNER_QT1010 if MEDIA_SUBDRV_AUTOSELECT + help + Say Y here to support the AME DTV-5100 USB2.0 DVB-T receiver. + +config DVB_USB_FRIIO + tristate "Friio ISDB-T USB2.0 Receiver support" + depends on DVB_USB + help + Say Y here to support the Japanese DTV receiver Friio. + +config DVB_USB_AZ6027 + tristate "Azurewave DVB-S/S2 USB2.0 AZ6027 support" + depends on DVB_USB + select DVB_STB0899 if MEDIA_SUBDRV_AUTOSELECT + select DVB_STB6100 if MEDIA_SUBDRV_AUTOSELECT + help + Say Y here to support the AZ6027 device + +config DVB_USB_TECHNISAT_USB2 + tristate "Technisat DVB-S/S2 USB2.0 support" + depends on DVB_USB + select DVB_STV090x if MEDIA_SUBDRV_AUTOSELECT + select DVB_STV6110x if MEDIA_SUBDRV_AUTOSELECT + help + Say Y here to support the Technisat USB2 DVB-S/S2 device diff --git a/drivers/media/usb/dvb-usb/Makefile b/drivers/media/usb/dvb-usb/Makefile new file mode 100644 index 000000000000..acdd1efd4e74 --- /dev/null +++ b/drivers/media/usb/dvb-usb/Makefile @@ -0,0 +1,83 @@ +dvb-usb-objs += dvb-usb-firmware.o dvb-usb-init.o dvb-usb-urb.o dvb-usb-i2c.o +dvb-usb-objs += dvb-usb-dvb.o dvb-usb-remote.o usb-urb.o +obj-$(CONFIG_DVB_USB) += dvb-usb.o + +dvb-usb-vp7045-objs := vp7045.o vp7045-fe.o +obj-$(CONFIG_DVB_USB_VP7045) += dvb-usb-vp7045.o + +dvb-usb-vp702x-objs := vp702x.o vp702x-fe.o +obj-$(CONFIG_DVB_USB_VP702X) += dvb-usb-vp702x.o + +dvb-usb-gp8psk-objs := gp8psk.o gp8psk-fe.o +obj-$(CONFIG_DVB_USB_GP8PSK) += dvb-usb-gp8psk.o + +dvb-usb-dtt200u-objs := dtt200u.o dtt200u-fe.o +obj-$(CONFIG_DVB_USB_DTT200U) += dvb-usb-dtt200u.o + +dvb-usb-dibusb-common-objs := dibusb-common.o + +dvb-usb-a800-objs := a800.o +obj-$(CONFIG_DVB_USB_A800) += dvb-usb-dibusb-common.o dvb-usb-a800.o + +dvb-usb-dibusb-mb-objs := dibusb-mb.o +obj-$(CONFIG_DVB_USB_DIBUSB_MB) += dvb-usb-dibusb-common.o dvb-usb-dibusb-mb.o + +dvb-usb-dibusb-mc-objs := dibusb-mc.o +obj-$(CONFIG_DVB_USB_DIBUSB_MC) += dvb-usb-dibusb-common.o dvb-usb-dibusb-mc.o + +dvb-usb-nova-t-usb2-objs := nova-t-usb2.o +obj-$(CONFIG_DVB_USB_NOVA_T_USB2) += dvb-usb-dibusb-common.o dvb-usb-nova-t-usb2.o + +dvb-usb-umt-010-objs := umt-010.o +obj-$(CONFIG_DVB_USB_UMT_010) += dvb-usb-dibusb-common.o dvb-usb-umt-010.o + +dvb-usb-m920x-objs := m920x.o +obj-$(CONFIG_DVB_USB_M920X) += dvb-usb-m920x.o + +dvb-usb-digitv-objs := digitv.o +obj-$(CONFIG_DVB_USB_DIGITV) += dvb-usb-digitv.o + +dvb-usb-cxusb-objs := cxusb.o +obj-$(CONFIG_DVB_USB_CXUSB) += dvb-usb-cxusb.o + +dvb-usb-ttusb2-objs := ttusb2.o +obj-$(CONFIG_DVB_USB_TTUSB2) += dvb-usb-ttusb2.o + +dvb-usb-dib0700-objs := dib0700_core.o dib0700_devices.o +obj-$(CONFIG_DVB_USB_DIB0700) += dvb-usb-dib0700.o + +dvb-usb-opera-objs := opera1.o +obj-$(CONFIG_DVB_USB_OPERA1) += dvb-usb-opera.o + +dvb-usb-af9005-objs := af9005.o af9005-fe.o +obj-$(CONFIG_DVB_USB_AF9005) += dvb-usb-af9005.o + +dvb-usb-af9005-remote-objs := af9005-remote.o +obj-$(CONFIG_DVB_USB_AF9005_REMOTE) += dvb-usb-af9005-remote.o + +dvb-usb-pctv452e-objs := pctv452e.o +obj-$(CONFIG_DVB_USB_PCTV452E) += dvb-usb-pctv452e.o + +dvb-usb-dw2102-objs := dw2102.o +obj-$(CONFIG_DVB_USB_DW2102) += dvb-usb-dw2102.o + +dvb-usb-dtv5100-objs := dtv5100.o +obj-$(CONFIG_DVB_USB_DTV5100) += dvb-usb-dtv5100.o + +dvb-usb-cinergyT2-objs := cinergyT2-core.o cinergyT2-fe.o +obj-$(CONFIG_DVB_USB_CINERGY_T2) += dvb-usb-cinergyT2.o + +dvb-usb-friio-objs := friio.o friio-fe.o +obj-$(CONFIG_DVB_USB_FRIIO) += dvb-usb-friio.o + +dvb-usb-az6027-objs := az6027.o +obj-$(CONFIG_DVB_USB_AZ6027) += dvb-usb-az6027.o + +dvb-usb-technisat-usb2-objs := technisat-usb2.o +obj-$(CONFIG_DVB_USB_TECHNISAT_USB2) += dvb-usb-technisat-usb2.o + +ccflags-y += -I$(srctree)/drivers/media/dvb-core +ccflags-y += -I$(srctree)/drivers/media/dvb-frontends/ +# due to tuner-xc3028 +ccflags-y += -I$(srctree)/drivers/media/tuners +ccflags-y += -I$(srctree)/drivers/media/pci/ttpci diff --git a/drivers/media/dvb/dvb-usb/a800.c b/drivers/media/usb/dvb-usb/a800.c index 8d7fef84afd8..8d7fef84afd8 100644 --- a/drivers/media/dvb/dvb-usb/a800.c +++ b/drivers/media/usb/dvb-usb/a800.c diff --git a/drivers/media/dvb/dvb-usb/af9005-fe.c b/drivers/media/usb/dvb-usb/af9005-fe.c index 740f3f496f12..740f3f496f12 100644 --- a/drivers/media/dvb/dvb-usb/af9005-fe.c +++ b/drivers/media/usb/dvb-usb/af9005-fe.c diff --git a/drivers/media/dvb/dvb-usb/af9005-remote.c b/drivers/media/usb/dvb-usb/af9005-remote.c index 7e3961d0db6b..7e3961d0db6b 100644 --- a/drivers/media/dvb/dvb-usb/af9005-remote.c +++ b/drivers/media/usb/dvb-usb/af9005-remote.c diff --git a/drivers/media/dvb/dvb-usb/af9005-script.h b/drivers/media/usb/dvb-usb/af9005-script.h index 4d69045426dd..4d69045426dd 100644 --- a/drivers/media/dvb/dvb-usb/af9005-script.h +++ b/drivers/media/usb/dvb-usb/af9005-script.h diff --git a/drivers/media/dvb/dvb-usb/af9005.c b/drivers/media/usb/dvb-usb/af9005.c index af176b6ce738..af176b6ce738 100644 --- a/drivers/media/dvb/dvb-usb/af9005.c +++ b/drivers/media/usb/dvb-usb/af9005.c diff --git a/drivers/media/dvb/dvb-usb/af9005.h b/drivers/media/usb/dvb-usb/af9005.h index 6a2bf3de8456..6a2bf3de8456 100644 --- a/drivers/media/dvb/dvb-usb/af9005.h +++ b/drivers/media/usb/dvb-usb/af9005.h diff --git a/drivers/media/dvb/dvb-usb/az6027.c b/drivers/media/usb/dvb-usb/az6027.c index 5e45ae605427..5e45ae605427 100644 --- a/drivers/media/dvb/dvb-usb/az6027.c +++ b/drivers/media/usb/dvb-usb/az6027.c diff --git a/drivers/media/dvb/dvb-usb/az6027.h b/drivers/media/usb/dvb-usb/az6027.h index f3afe17f3f3d..f3afe17f3f3d 100644 --- a/drivers/media/dvb/dvb-usb/az6027.h +++ b/drivers/media/usb/dvb-usb/az6027.h diff --git a/drivers/media/dvb/dvb-usb/cinergyT2-core.c b/drivers/media/usb/dvb-usb/cinergyT2-core.c index 0a98548ecd17..0a98548ecd17 100644 --- a/drivers/media/dvb/dvb-usb/cinergyT2-core.c +++ b/drivers/media/usb/dvb-usb/cinergyT2-core.c diff --git a/drivers/media/dvb/dvb-usb/cinergyT2-fe.c b/drivers/media/usb/dvb-usb/cinergyT2-fe.c index 1efc028a76c9..1efc028a76c9 100644 --- a/drivers/media/dvb/dvb-usb/cinergyT2-fe.c +++ b/drivers/media/usb/dvb-usb/cinergyT2-fe.c diff --git a/drivers/media/dvb/dvb-usb/cinergyT2.h b/drivers/media/usb/dvb-usb/cinergyT2.h index 84efe03771eb..84efe03771eb 100644 --- a/drivers/media/dvb/dvb-usb/cinergyT2.h +++ b/drivers/media/usb/dvb-usb/cinergyT2.h diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/usb/dvb-usb/cxusb.c index 3940bb0f9ef6..3940bb0f9ef6 100644 --- a/drivers/media/dvb/dvb-usb/cxusb.c +++ b/drivers/media/usb/dvb-usb/cxusb.c diff --git a/drivers/media/dvb/dvb-usb/cxusb.h b/drivers/media/usb/dvb-usb/cxusb.h index 1a51eafd31b9..1a51eafd31b9 100644 --- a/drivers/media/dvb/dvb-usb/cxusb.h +++ b/drivers/media/usb/dvb-usb/cxusb.h diff --git a/drivers/media/dvb/dvb-usb/dib0700.h b/drivers/media/usb/dvb-usb/dib0700.h index 7de125c0b36f..7de125c0b36f 100644 --- a/drivers/media/dvb/dvb-usb/dib0700.h +++ b/drivers/media/usb/dvb-usb/dib0700.h diff --git a/drivers/media/dvb/dvb-usb/dib0700_core.c b/drivers/media/usb/dvb-usb/dib0700_core.c index 7e9e00fae04e..ef87229de6af 100644 --- a/drivers/media/dvb/dvb-usb/dib0700_core.c +++ b/drivers/media/usb/dvb-usb/dib0700_core.c @@ -768,13 +768,13 @@ int dib0700_rc_setup(struct dvb_usb_device *d) /* Starting in firmware 1.20, the RC info is provided on a bulk pipe */ purb = usb_alloc_urb(0, GFP_KERNEL); if (purb == NULL) { - err("rc usb alloc urb failed\n"); + err("rc usb alloc urb failed"); return -ENOMEM; } purb->transfer_buffer = kzalloc(RC_MSG_SIZE_V1_20, GFP_KERNEL); if (purb->transfer_buffer == NULL) { - err("rc kzalloc failed\n"); + err("rc kzalloc failed"); usb_free_urb(purb); return -ENOMEM; } @@ -786,7 +786,7 @@ int dib0700_rc_setup(struct dvb_usb_device *d) ret = usb_submit_urb(purb, GFP_ATOMIC); if (ret) { - err("rc submit urb failed\n"); + err("rc submit urb failed"); kfree(purb->transfer_buffer); usb_free_urb(purb); } diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/usb/dvb-usb/dib0700_devices.c index 510001da6e83..510001da6e83 100644 --- a/drivers/media/dvb/dvb-usb/dib0700_devices.c +++ b/drivers/media/usb/dvb-usb/dib0700_devices.c diff --git a/drivers/media/dvb/dvb-usb/dib07x0.h b/drivers/media/usb/dvb-usb/dib07x0.h index 7e62c1018520..7e62c1018520 100644 --- a/drivers/media/dvb/dvb-usb/dib07x0.h +++ b/drivers/media/usb/dvb-usb/dib07x0.h diff --git a/drivers/media/dvb/dvb-usb/dibusb-common.c b/drivers/media/usb/dvb-usb/dibusb-common.c index a76bbb29ca36..a76bbb29ca36 100644 --- a/drivers/media/dvb/dvb-usb/dibusb-common.c +++ b/drivers/media/usb/dvb-usb/dibusb-common.c diff --git a/drivers/media/dvb/dvb-usb/dibusb-mb.c b/drivers/media/usb/dvb-usb/dibusb-mb.c index a4ac37e0e98b..a4ac37e0e98b 100644 --- a/drivers/media/dvb/dvb-usb/dibusb-mb.c +++ b/drivers/media/usb/dvb-usb/dibusb-mb.c diff --git a/drivers/media/dvb/dvb-usb/dibusb-mc.c b/drivers/media/usb/dvb-usb/dibusb-mc.c index 9d1a59d09c52..9d1a59d09c52 100644 --- a/drivers/media/dvb/dvb-usb/dibusb-mc.c +++ b/drivers/media/usb/dvb-usb/dibusb-mc.c diff --git a/drivers/media/dvb/dvb-usb/dibusb.h b/drivers/media/usb/dvb-usb/dibusb.h index e47c321b3ffc..e47c321b3ffc 100644 --- a/drivers/media/dvb/dvb-usb/dibusb.h +++ b/drivers/media/usb/dvb-usb/dibusb.h diff --git a/drivers/media/dvb/dvb-usb/digitv.c b/drivers/media/usb/dvb-usb/digitv.c index ff34419a4c88..ff34419a4c88 100644 --- a/drivers/media/dvb/dvb-usb/digitv.c +++ b/drivers/media/usb/dvb-usb/digitv.c diff --git a/drivers/media/dvb/dvb-usb/digitv.h b/drivers/media/usb/dvb-usb/digitv.h index 908c09f4966b..908c09f4966b 100644 --- a/drivers/media/dvb/dvb-usb/digitv.h +++ b/drivers/media/usb/dvb-usb/digitv.h diff --git a/drivers/media/dvb/dvb-usb/dtt200u-fe.c b/drivers/media/usb/dvb-usb/dtt200u-fe.c index 3d81daa49172..3d81daa49172 100644 --- a/drivers/media/dvb/dvb-usb/dtt200u-fe.c +++ b/drivers/media/usb/dvb-usb/dtt200u-fe.c diff --git a/drivers/media/dvb/dvb-usb/dtt200u.c b/drivers/media/usb/dvb-usb/dtt200u.c index 66f205c112b2..66f205c112b2 100644 --- a/drivers/media/dvb/dvb-usb/dtt200u.c +++ b/drivers/media/usb/dvb-usb/dtt200u.c diff --git a/drivers/media/dvb/dvb-usb/dtt200u.h b/drivers/media/usb/dvb-usb/dtt200u.h index 005b0a7df358..005b0a7df358 100644 --- a/drivers/media/dvb/dvb-usb/dtt200u.h +++ b/drivers/media/usb/dvb-usb/dtt200u.h diff --git a/drivers/media/dvb/dvb-usb/dtv5100.c b/drivers/media/usb/dvb-usb/dtv5100.c index 3d11df41cac0..3d11df41cac0 100644 --- a/drivers/media/dvb/dvb-usb/dtv5100.c +++ b/drivers/media/usb/dvb-usb/dtv5100.c diff --git a/drivers/media/dvb/dvb-usb/dtv5100.h b/drivers/media/usb/dvb-usb/dtv5100.h index 93e96e04a82a..93e96e04a82a 100644 --- a/drivers/media/dvb/dvb-usb/dtv5100.h +++ b/drivers/media/usb/dvb-usb/dtv5100.h diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-common.h b/drivers/media/usb/dvb-usb/dvb-usb-common.h index 6b7b2a89242e..6b7b2a89242e 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-common.h +++ b/drivers/media/usb/dvb-usb/dvb-usb-common.h diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c b/drivers/media/usb/dvb-usb/dvb-usb-dvb.c index ddf282f355b3..719413b15f20 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c +++ b/drivers/media/usb/dvb-usb/dvb-usb-dvb.c @@ -106,7 +106,6 @@ int dvb_usb_adapter_dvb_init(struct dvb_usb_adapter *adap, short *adapter_nums) goto err; } adap->dvb_adap.priv = adap; - adap->dvb_adap.fe_ioctl_override = adap->props.fe_ioctl_override; if (adap->dev->props.read_mac_address) { if (adap->dev->props.read_mac_address(adap->dev,adap->dvb_adap.proposed_mac) == 0) diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-firmware.c b/drivers/media/usb/dvb-usb/dvb-usb-firmware.c index 733a7ff7b207..733a7ff7b207 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-firmware.c +++ b/drivers/media/usb/dvb-usb/dvb-usb-firmware.c diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c b/drivers/media/usb/dvb-usb/dvb-usb-i2c.c index 88e4a62abc44..88e4a62abc44 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c +++ b/drivers/media/usb/dvb-usb/dvb-usb-i2c.c diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-init.c b/drivers/media/usb/dvb-usb/dvb-usb-init.c index 169196ec2d4e..169196ec2d4e 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-init.c +++ b/drivers/media/usb/dvb-usb/dvb-usb-init.c diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-remote.c b/drivers/media/usb/dvb-usb/dvb-usb-remote.c index 41bacff24960..41bacff24960 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-remote.c +++ b/drivers/media/usb/dvb-usb/dvb-usb-remote.c diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-urb.c b/drivers/media/usb/dvb-usb/dvb-usb-urb.c index 5c8f651344fc..5c8f651344fc 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-urb.c +++ b/drivers/media/usb/dvb-usb/dvb-usb-urb.c diff --git a/drivers/media/dvb/dvb-usb/dvb-usb.h b/drivers/media/usb/dvb-usb/dvb-usb.h index 99f94409efa1..aab0f99bc892 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb.h +++ b/drivers/media/usb/dvb-usb/dvb-usb.h @@ -162,8 +162,6 @@ struct dvb_usb_adapter_properties { int size_of_priv; int (*frontend_ctrl) (struct dvb_frontend *, int); - int (*fe_ioctl_override) (struct dvb_frontend *, - unsigned int, void *, unsigned int); int num_frontends; struct dvb_usb_adapter_fe_properties fe[MAX_NO_OF_FE_PER_ADAP]; diff --git a/drivers/media/dvb/dvb-usb/dw2102.c b/drivers/media/usb/dvb-usb/dw2102.c index 9382895b1b88..9382895b1b88 100644 --- a/drivers/media/dvb/dvb-usb/dw2102.c +++ b/drivers/media/usb/dvb-usb/dw2102.c diff --git a/drivers/media/dvb/dvb-usb/dw2102.h b/drivers/media/usb/dvb-usb/dw2102.h index 5cd0b0eb6ce1..5cd0b0eb6ce1 100644 --- a/drivers/media/dvb/dvb-usb/dw2102.h +++ b/drivers/media/usb/dvb-usb/dw2102.h diff --git a/drivers/media/dvb/dvb-usb/friio-fe.c b/drivers/media/usb/dvb-usb/friio-fe.c index 90a70c66a96e..90a70c66a96e 100644 --- a/drivers/media/dvb/dvb-usb/friio-fe.c +++ b/drivers/media/usb/dvb-usb/friio-fe.c diff --git a/drivers/media/dvb/dvb-usb/friio.c b/drivers/media/usb/dvb-usb/friio.c index 474a17e4db0c..474a17e4db0c 100644 --- a/drivers/media/dvb/dvb-usb/friio.c +++ b/drivers/media/usb/dvb-usb/friio.c diff --git a/drivers/media/dvb/dvb-usb/friio.h b/drivers/media/usb/dvb-usb/friio.h index 0f461ca10cb9..0f461ca10cb9 100644 --- a/drivers/media/dvb/dvb-usb/friio.h +++ b/drivers/media/usb/dvb-usb/friio.h diff --git a/drivers/media/dvb/dvb-usb/gp8psk-fe.c b/drivers/media/usb/dvb-usb/gp8psk-fe.c index 67957dd99ede..67957dd99ede 100644 --- a/drivers/media/dvb/dvb-usb/gp8psk-fe.c +++ b/drivers/media/usb/dvb-usb/gp8psk-fe.c diff --git a/drivers/media/dvb/dvb-usb/gp8psk.c b/drivers/media/usb/dvb-usb/gp8psk.c index 5d0384dd45b5..5d0384dd45b5 100644 --- a/drivers/media/dvb/dvb-usb/gp8psk.c +++ b/drivers/media/usb/dvb-usb/gp8psk.c diff --git a/drivers/media/dvb/dvb-usb/gp8psk.h b/drivers/media/usb/dvb-usb/gp8psk.h index ed32b9da4843..ed32b9da4843 100644 --- a/drivers/media/dvb/dvb-usb/gp8psk.h +++ b/drivers/media/usb/dvb-usb/gp8psk.h diff --git a/drivers/media/dvb/dvb-usb/m920x.c b/drivers/media/usb/dvb-usb/m920x.c index 288af29a8bb7..288af29a8bb7 100644 --- a/drivers/media/dvb/dvb-usb/m920x.c +++ b/drivers/media/usb/dvb-usb/m920x.c diff --git a/drivers/media/dvb/dvb-usb/m920x.h b/drivers/media/usb/dvb-usb/m920x.h index 3c061518ffc1..3c061518ffc1 100644 --- a/drivers/media/dvb/dvb-usb/m920x.h +++ b/drivers/media/usb/dvb-usb/m920x.h diff --git a/drivers/media/dvb/dvb-usb/nova-t-usb2.c b/drivers/media/usb/dvb-usb/nova-t-usb2.c index 6c55384e2fca..6c55384e2fca 100644 --- a/drivers/media/dvb/dvb-usb/nova-t-usb2.c +++ b/drivers/media/usb/dvb-usb/nova-t-usb2.c diff --git a/drivers/media/dvb/dvb-usb/opera1.c b/drivers/media/usb/dvb-usb/opera1.c index c8a95042dfbc..c8a95042dfbc 100644 --- a/drivers/media/dvb/dvb-usb/opera1.c +++ b/drivers/media/usb/dvb-usb/opera1.c diff --git a/drivers/media/dvb/dvb-usb/pctv452e.c b/drivers/media/usb/dvb-usb/pctv452e.c index f526eb05cc7a..02e878577c3d 100644 --- a/drivers/media/dvb/dvb-usb/pctv452e.c +++ b/drivers/media/usb/dvb-usb/pctv452e.c @@ -136,8 +136,8 @@ static int tt3650_ci_msg(struct dvb_usb_device *d, u8 cmd, u8 *data, return 0; failed: - err("CI error %d; %02X %02X %02X -> %02X %02X %02X.", - ret, SYNC_BYTE_OUT, id, cmd, buf[0], buf[1], buf[2]); + err("CI error %d; %02X %02X %02X -> %*ph.", + ret, SYNC_BYTE_OUT, id, cmd, 3, buf); return ret; } @@ -556,8 +556,7 @@ static int pctv452e_rc_query(struct dvb_usb_device *d) return ret; if (debug > 3) { - info("%s: read: %2d: %02x %02x %02x: ", __func__, - ret, rx[0], rx[1], rx[2]); + info("%s: read: %2d: %*ph: ", __func__, ret, 3, rx); for (i = 0; (i < rx[3]) && ((i+3) < PCTV_ANSWER_LEN); i++) info(" %02x", rx[i+3]); diff --git a/drivers/media/dvb/dvb-usb/technisat-usb2.c b/drivers/media/usb/dvb-usb/technisat-usb2.c index acefaa89cc53..acefaa89cc53 100644 --- a/drivers/media/dvb/dvb-usb/technisat-usb2.c +++ b/drivers/media/usb/dvb-usb/technisat-usb2.c diff --git a/drivers/media/dvb/dvb-usb/ttusb2.c b/drivers/media/usb/dvb-usb/ttusb2.c index e53a1061cb8e..6a50cdea3bce 100644 --- a/drivers/media/dvb/dvb-usb/ttusb2.c +++ b/drivers/media/usb/dvb-usb/ttusb2.c @@ -440,7 +440,7 @@ static int tt3650_rc_query(struct dvb_usb_device *d) /* got a "press" event */ st->last_rc_key = (rx[3] << 8) | rx[2]; deb_info("%s: cmd=0x%02x sys=0x%02x\n", __func__, rx[2], rx[3]); - rc_keydown(d->rc_dev, st->last_rc_key, 0); + rc_keydown(d->rc_dev, st->last_rc_key, rx[1]); } else if (st->last_rc_key) { rc_keyup(d->rc_dev); st->last_rc_key = 0; diff --git a/drivers/media/dvb/dvb-usb/ttusb2.h b/drivers/media/usb/dvb-usb/ttusb2.h index 52a63af40896..52a63af40896 100644 --- a/drivers/media/dvb/dvb-usb/ttusb2.h +++ b/drivers/media/usb/dvb-usb/ttusb2.h diff --git a/drivers/media/dvb/dvb-usb/umt-010.c b/drivers/media/usb/dvb-usb/umt-010.c index 9b042292e788..9b042292e788 100644 --- a/drivers/media/dvb/dvb-usb/umt-010.c +++ b/drivers/media/usb/dvb-usb/umt-010.c diff --git a/drivers/media/dvb/dvb-usb/usb-urb.c b/drivers/media/usb/dvb-usb/usb-urb.c index d62ee0f5a165..d62ee0f5a165 100644 --- a/drivers/media/dvb/dvb-usb/usb-urb.c +++ b/drivers/media/usb/dvb-usb/usb-urb.c diff --git a/drivers/media/dvb/dvb-usb/vp702x-fe.c b/drivers/media/usb/dvb-usb/vp702x-fe.c index 5eab468dd904..5eab468dd904 100644 --- a/drivers/media/dvb/dvb-usb/vp702x-fe.c +++ b/drivers/media/usb/dvb-usb/vp702x-fe.c diff --git a/drivers/media/dvb/dvb-usb/vp702x.c b/drivers/media/usb/dvb-usb/vp702x.c index 07c673a6e764..07c673a6e764 100644 --- a/drivers/media/dvb/dvb-usb/vp702x.c +++ b/drivers/media/usb/dvb-usb/vp702x.c diff --git a/drivers/media/dvb/dvb-usb/vp702x.h b/drivers/media/usb/dvb-usb/vp702x.h index 20b90055e7ac..20b90055e7ac 100644 --- a/drivers/media/dvb/dvb-usb/vp702x.h +++ b/drivers/media/usb/dvb-usb/vp702x.h diff --git a/drivers/media/dvb/dvb-usb/vp7045-fe.c b/drivers/media/usb/dvb-usb/vp7045-fe.c index b8825b18c003..b8825b18c003 100644 --- a/drivers/media/dvb/dvb-usb/vp7045-fe.c +++ b/drivers/media/usb/dvb-usb/vp7045-fe.c diff --git a/drivers/media/dvb/dvb-usb/vp7045.c b/drivers/media/usb/dvb-usb/vp7045.c index d750724132ee..d750724132ee 100644 --- a/drivers/media/dvb/dvb-usb/vp7045.c +++ b/drivers/media/usb/dvb-usb/vp7045.c diff --git a/drivers/media/dvb/dvb-usb/vp7045.h b/drivers/media/usb/dvb-usb/vp7045.h index cf5ec46f8bb1..cf5ec46f8bb1 100644 --- a/drivers/media/dvb/dvb-usb/vp7045.h +++ b/drivers/media/usb/dvb-usb/vp7045.h diff --git a/drivers/media/video/em28xx/Kconfig b/drivers/media/usb/em28xx/Kconfig index 928ef0d0429f..7a5bd61bd3bb 100644 --- a/drivers/media/video/em28xx/Kconfig +++ b/drivers/media/usb/em28xx/Kconfig @@ -4,10 +4,10 @@ config VIDEO_EM28XX select VIDEO_TUNER select VIDEO_TVEEPROM select VIDEOBUF_VMALLOC - select VIDEO_SAA711X if VIDEO_HELPER_CHIPS_AUTO - select VIDEO_TVP5150 if VIDEO_HELPER_CHIPS_AUTO - select VIDEO_MSP3400 if VIDEO_HELPER_CHIPS_AUTO - select VIDEO_MT9V011 if VIDEO_HELPER_CHIPS_AUTO + select VIDEO_SAA711X if MEDIA_SUBDRV_AUTOSELECT + select VIDEO_TVP5150 if MEDIA_SUBDRV_AUTOSELECT + select VIDEO_MSP3400 if MEDIA_SUBDRV_AUTOSELECT + select VIDEO_MT9V011 if MEDIA_SUBDRV_AUTOSELECT ---help--- This is a video4linux driver for Empia 28xx based TV cards. @@ -33,16 +33,16 @@ config VIDEO_EM28XX_ALSA config VIDEO_EM28XX_DVB tristate "DVB/ATSC Support for em28xx based TV cards" depends on VIDEO_EM28XX && DVB_CORE - select DVB_LGDT330X if !DVB_FE_CUSTOMISE - select DVB_ZL10353 if !DVB_FE_CUSTOMISE - select DVB_TDA10023 if !DVB_FE_CUSTOMISE - select DVB_S921 if !DVB_FE_CUSTOMISE - select DVB_DRXD if !DVB_FE_CUSTOMISE - select DVB_CXD2820R if !DVB_FE_CUSTOMISE - select DVB_DRXK if !DVB_FE_CUSTOMISE - select DVB_TDA18271C2DD if !DVB_FE_CUSTOMISE - select DVB_TDA10071 if !DVB_FE_CUSTOMISE - select DVB_A8293 if !DVB_FE_CUSTOMISE + select DVB_LGDT330X if MEDIA_SUBDRV_AUTOSELECT + select DVB_ZL10353 if MEDIA_SUBDRV_AUTOSELECT + select DVB_TDA10023 if MEDIA_SUBDRV_AUTOSELECT + select DVB_S921 if MEDIA_SUBDRV_AUTOSELECT + select DVB_DRXD if MEDIA_SUBDRV_AUTOSELECT + select DVB_CXD2820R if MEDIA_SUBDRV_AUTOSELECT + select DVB_DRXK if MEDIA_SUBDRV_AUTOSELECT + select DVB_TDA18271C2DD if MEDIA_SUBDRV_AUTOSELECT + select DVB_TDA10071 if MEDIA_SUBDRV_AUTOSELECT + select DVB_A8293 if MEDIA_SUBDRV_AUTOSELECT select VIDEOBUF_DVB ---help--- This adds support for DVB cards based on the diff --git a/drivers/media/video/em28xx/Makefile b/drivers/media/usb/em28xx/Makefile index c8b338d4be05..634fb920dd39 100644 --- a/drivers/media/video/em28xx/Makefile +++ b/drivers/media/usb/em28xx/Makefile @@ -1,4 +1,4 @@ -em28xx-y := em28xx-video.o em28xx-i2c.o em28xx-cards.o +em28xx-y += em28xx-video.o em28xx-i2c.o em28xx-cards.o em28xx-y += em28xx-core.o em28xx-vbi.o em28xx-alsa-objs := em28xx-audio.o @@ -9,7 +9,7 @@ obj-$(CONFIG_VIDEO_EM28XX_ALSA) += em28xx-alsa.o obj-$(CONFIG_VIDEO_EM28XX_DVB) += em28xx-dvb.o obj-$(CONFIG_VIDEO_EM28XX_RC) += em28xx-rc.o -ccflags-y += -Idrivers/media/video -ccflags-y += -Idrivers/media/common/tuners -ccflags-y += -Idrivers/media/dvb/dvb-core -ccflags-y += -Idrivers/media/dvb/frontends +ccflags-y += -Idrivers/media/i2c +ccflags-y += -Idrivers/media/tuners +ccflags-y += -Idrivers/media/dvb-core +ccflags-y += -Idrivers/media/dvb-frontends diff --git a/drivers/media/video/em28xx/em28xx-audio.c b/drivers/media/usb/em28xx/em28xx-audio.c index 07dc594e79f0..2fdb66ee44ab 100644 --- a/drivers/media/video/em28xx/em28xx-audio.c +++ b/drivers/media/usb/em28xx/em28xx-audio.c @@ -306,7 +306,6 @@ static int snd_em28xx_capture_open(struct snd_pcm_substream *substream) snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); dev->adev.capture_pcm_substream = substream; - runtime->private_data = dev; return 0; err: diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/usb/em28xx/em28xx-cards.c index f7831e73f077..f7297ae76b48 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/usb/em28xx/em28xx-cards.c @@ -2875,12 +2875,20 @@ static void em28xx_card_setup(struct em28xx *dev) } -#if defined(CONFIG_MODULES) && defined(MODULE) static void request_module_async(struct work_struct *work) { struct em28xx *dev = container_of(work, struct em28xx, request_module_wk); + /* + * The em28xx extensions can be modules or builtin. If the + * modules are already loaded or are built in, those extensions + * can be initialised right now. Otherwise, the module init + * code will do it. + */ + em28xx_init_extension(dev); + +#if defined(CONFIG_MODULES) && defined(MODULE) if (dev->has_audio_class) request_module("snd-usb-audio"); else if (dev->has_alsa_audio) @@ -2890,6 +2898,7 @@ static void request_module_async(struct work_struct *work) request_module("em28xx-dvb"); if (dev->board.ir_codes && !disable_ir) request_module("em28xx-rc"); +#endif /* CONFIG_MODULES */ } static void request_modules(struct em28xx *dev) @@ -2902,10 +2911,6 @@ static void flush_request_modules(struct em28xx *dev) { flush_work(&dev->request_module_wk); } -#else -#define request_modules(dev) -#define flush_request_modules(dev) -#endif /* CONFIG_MODULES */ /* * em28xx_release_resources() @@ -3324,13 +3329,6 @@ static int em28xx_usb_probe(struct usb_interface *interface, */ mutex_unlock(&dev->lock); - /* - * These extensions can be modules. If the modules are already - * loaded then we can initialise the device now, otherwise we - * will initialise it when the modules load instead. - */ - em28xx_init_extension(dev); - return 0; unlock_and_free: diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/usb/em28xx/em28xx-core.c index de2cb20ad2cc..bed07a6c33f8 100644 --- a/drivers/media/video/em28xx/em28xx-core.c +++ b/drivers/media/usb/em28xx/em28xx-core.c @@ -785,12 +785,8 @@ int em28xx_resolution_set(struct em28xx *dev) else dev->vbi_height = 18; - if (!dev->progressive) - height >>= norm_maxh(dev); - em28xx_set_outfmt(dev); - em28xx_accumulator_set(dev, 1, (width - 4) >> 2, 1, (height - 4) >> 2); /* If we don't set the start position to 2 in VBI mode, we end up diff --git a/drivers/media/video/em28xx/em28xx-dvb.c b/drivers/media/usb/em28xx/em28xx-dvb.c index a16531fa937a..913e5227897a 100644 --- a/drivers/media/video/em28xx/em28xx-dvb.c +++ b/drivers/media/usb/em28xx/em28xx-dvb.c @@ -28,6 +28,7 @@ #include <media/videobuf-vmalloc.h> #include <media/tuner.h> #include "tuner-simple.h" +#include <linux/gpio.h> #include "lgdt330x.h" #include "lgdt3305.h" @@ -80,6 +81,7 @@ struct em28xx_dvb { int (*gate_ctrl)(struct dvb_frontend *, int); struct semaphore pll_mutex; bool dont_attach_fe1; + int lna_gpio; }; @@ -316,6 +318,7 @@ static struct drxk_config terratec_h5_drxk = { .no_i2c_bridge = 1, .microcode_name = "dvb-usb-terratec-h5-drxk.fw", .qam_demod_parameter_count = 2, + .load_firmware_sync = true, }; static struct drxk_config hauppauge_930c_drxk = { @@ -325,6 +328,7 @@ static struct drxk_config hauppauge_930c_drxk = { .microcode_name = "dvb-usb-hauppauge-hvr930c-drxk.fw", .chunk_size = 56, .qam_demod_parameter_count = 2, + .load_firmware_sync = true, }; struct drxk_config terratec_htc_stick_drxk = { @@ -338,12 +342,14 @@ struct drxk_config terratec_htc_stick_drxk = { .antenna_dvbt = true, /* The windows driver uses the same. This will disable LNA. */ .antenna_gpio = 0x6, + .load_firmware_sync = true, }; static struct drxk_config maxmedia_ub425_tc_drxk = { .adr = 0x29, .single_master = 1, .no_i2c_bridge = 1, + .load_firmware_sync = true, }; static struct drxk_config pctv_520e_drxk = { @@ -354,6 +360,7 @@ static struct drxk_config pctv_520e_drxk = { .chunk_size = 58, .antenna_dvbt = true, /* disable LNA */ .antenna_gpio = (1 << 2), /* disable LNA */ + .load_firmware_sync = true, }; static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable) @@ -567,6 +574,33 @@ static void pctv_520e_init(struct em28xx *dev) i2c_master_send(&dev->i2c_client, regs[i].r, regs[i].len); }; +static int em28xx_pctv_290e_set_lna(struct dvb_frontend *fe, int val) +{ + struct em28xx *dev = fe->dvb->priv; +#ifdef CONFIG_GPIOLIB + struct em28xx_dvb *dvb = dev->dvb; + int ret; + unsigned long flags; + + if (val) + flags = GPIOF_OUT_INIT_LOW; + else + flags = GPIOF_OUT_INIT_HIGH; + + ret = gpio_request_one(dvb->lna_gpio, flags, NULL); + if (ret) + em28xx_errdev("gpio request failed %d\n", ret); + else + gpio_free(dvb->lna_gpio); + + return ret; +#else + dev_warn(&dev->udev->dev, "%s: LNA control is disabled\n", + KBUILD_MODNAME); + return 0; +#endif +} + static int em28xx_mt352_terratec_xs_init(struct dvb_frontend *fe) { /* Values extracted from a USB trace of the Terratec Windows driver */ @@ -610,11 +644,6 @@ static struct tda10023_config em28xx_tda10023_config = { static struct cxd2820r_config em28xx_cxd2820r_config = { .i2c_address = (0xd8 >> 1), .ts_mode = CXD2820R_TS_SERIAL, - - /* enable LNA for DVB-T, DVB-T2 and DVB-C */ - .gpio_dvbt[0] = CXD2820R_GPIO_E | CXD2820R_GPIO_O | CXD2820R_GPIO_L, - .gpio_dvbt2[0] = CXD2820R_GPIO_E | CXD2820R_GPIO_O | CXD2820R_GPIO_L, - .gpio_dvbc[0] = CXD2820R_GPIO_E | CXD2820R_GPIO_O | CXD2820R_GPIO_L, }; static struct tda18271_config em28xx_cxd2820r_tda18271_config = { @@ -959,9 +988,13 @@ static int em28xx_dvb_init(struct em28xx *dev) &dev->i2c_adap, &kworld_a340_config); break; case EM28174_BOARD_PCTV_290E: + /* set default GPIO0 for LNA, used if GPIOLIB is undefined */ + dvb->lna_gpio = CXD2820R_GPIO_E | CXD2820R_GPIO_O | + CXD2820R_GPIO_L; dvb->fe[0] = dvb_attach(cxd2820r_attach, &em28xx_cxd2820r_config, - &dev->i2c_adap); + &dev->i2c_adap, + &dvb->lna_gpio); if (dvb->fe[0]) { /* FE 0 attach tuner */ if (!dvb_attach(tda18271_attach, @@ -974,7 +1007,22 @@ static int em28xx_dvb_init(struct em28xx *dev) result = -EINVAL; goto out_free; } + +#ifdef CONFIG_GPIOLIB + /* enable LNA for DVB-T, DVB-T2 and DVB-C */ + result = gpio_request_one(dvb->lna_gpio, + GPIOF_OUT_INIT_LOW, NULL); + if (result) + em28xx_errdev("gpio request failed %d\n", + result); + else + gpio_free(dvb->lna_gpio); + + result = 0; /* continue even set LNA fails */ +#endif + dvb->fe[0]->ops.set_lna = em28xx_pctv_290e_set_lna; } + break; case EM2884_BOARD_HAUPPAUGE_WINTV_HVR_930C: { diff --git a/drivers/media/video/em28xx/em28xx-i2c.c b/drivers/media/usb/em28xx/em28xx-i2c.c index 1683bd9d51ee..1683bd9d51ee 100644 --- a/drivers/media/video/em28xx/em28xx-i2c.c +++ b/drivers/media/usb/em28xx/em28xx-i2c.c diff --git a/drivers/media/video/em28xx/em28xx-input.c b/drivers/media/usb/em28xx/em28xx-input.c index 97d36b4f19db..97d36b4f19db 100644 --- a/drivers/media/video/em28xx/em28xx-input.c +++ b/drivers/media/usb/em28xx/em28xx-input.c diff --git a/drivers/media/video/em28xx/em28xx-reg.h b/drivers/media/usb/em28xx/em28xx-reg.h index 6ff368297f6e..6ff368297f6e 100644 --- a/drivers/media/video/em28xx/em28xx-reg.h +++ b/drivers/media/usb/em28xx/em28xx-reg.h diff --git a/drivers/media/video/em28xx/em28xx-vbi.c b/drivers/media/usb/em28xx/em28xx-vbi.c index 2b4c9cba2d67..2b4c9cba2d67 100644 --- a/drivers/media/video/em28xx/em28xx-vbi.c +++ b/drivers/media/usb/em28xx/em28xx-vbi.c diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/usb/em28xx/em28xx-video.c index 50f5f4fc2148..1e553d357380 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/usb/em28xx/em28xx-video.c @@ -1352,7 +1352,7 @@ static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a) return 0; } -static int vidioc_s_audio(struct file *file, void *priv, struct v4l2_audio *a) +static int vidioc_s_audio(struct file *file, void *priv, const struct v4l2_audio *a) { struct em28xx_fh *fh = priv; struct em28xx *dev = fh->dev; @@ -2087,7 +2087,7 @@ static int radio_s_tuner(struct file *file, void *priv, } static int radio_s_audio(struct file *file, void *fh, - struct v4l2_audio *a) + const struct v4l2_audio *a) { return 0; } @@ -2146,9 +2146,12 @@ static int em28xx_v4l2_open(struct file *filp) dev->users); + if (mutex_lock_interruptible(&dev->lock)) + return -ERESTARTSYS; fh = kzalloc(sizeof(struct em28xx_fh), GFP_KERNEL); if (!fh) { em28xx_errdev("em28xx-video.c: Out of memory?!\n"); + mutex_unlock(&dev->lock); return -ENOMEM; } fh->dev = dev; @@ -2189,6 +2192,7 @@ static int em28xx_v4l2_open(struct file *filp) V4L2_BUF_TYPE_VBI_CAPTURE, V4L2_FIELD_SEQ_TB, sizeof(struct em28xx_buffer), fh, &dev->lock); + mutex_unlock(&dev->lock); return errCode; } @@ -2243,6 +2247,7 @@ static int em28xx_v4l2_close(struct file *filp) em28xx_videodbg("users=%d\n", dev->users); + mutex_lock(&dev->lock); if (res_check(fh, EM28XX_RESOURCE_VIDEO)) { videobuf_stop(&fh->vb_vidq); res_free(fh, EM28XX_RESOURCE_VIDEO); @@ -2259,6 +2264,7 @@ static int em28xx_v4l2_close(struct file *filp) if (dev->state & DEV_DISCONNECTED) { em28xx_release_resources(dev); kfree(dev->alt_max_pkt_size); + mutex_unlock(&dev->lock); kfree(dev); kfree(fh); return 0; @@ -2285,6 +2291,7 @@ static int em28xx_v4l2_close(struct file *filp) videobuf_mmap_free(&fh->vb_vbiq); kfree(fh); dev->users--; + mutex_unlock(&dev->lock); return 0; } @@ -2304,35 +2311,35 @@ em28xx_v4l2_read(struct file *filp, char __user *buf, size_t count, if (rc < 0) return rc; + if (mutex_lock_interruptible(&dev->lock)) + return -ERESTARTSYS; /* FIXME: read() is not prepared to allow changing the video resolution while streaming. Seems a bug at em28xx_set_fmt */ if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { if (res_locked(dev, EM28XX_RESOURCE_VIDEO)) - return -EBUSY; - - return videobuf_read_stream(&fh->vb_vidq, buf, count, pos, 0, + rc = -EBUSY; + else + rc = videobuf_read_stream(&fh->vb_vidq, buf, count, pos, 0, filp->f_flags & O_NONBLOCK); - } - - - if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) { + } else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) { if (!res_get(fh, EM28XX_RESOURCE_VBI)) - return -EBUSY; - - return videobuf_read_stream(&fh->vb_vbiq, buf, count, pos, 0, + rc = -EBUSY; + else + rc = videobuf_read_stream(&fh->vb_vbiq, buf, count, pos, 0, filp->f_flags & O_NONBLOCK); } + mutex_unlock(&dev->lock); - return 0; + return rc; } /* - * em28xx_v4l2_poll() + * em28xx_poll() * will allocate buffers when called for the first time */ -static unsigned int em28xx_v4l2_poll(struct file *filp, poll_table *wait) +static unsigned int em28xx_poll(struct file *filp, poll_table *wait) { struct em28xx_fh *fh = filp->private_data; struct em28xx *dev = fh->dev; @@ -2355,6 +2362,18 @@ static unsigned int em28xx_v4l2_poll(struct file *filp, poll_table *wait) } } +static unsigned int em28xx_v4l2_poll(struct file *filp, poll_table *wait) +{ + struct em28xx_fh *fh = filp->private_data; + struct em28xx *dev = fh->dev; + unsigned int res; + + mutex_lock(&dev->lock); + res = em28xx_poll(filp, wait); + mutex_unlock(&dev->lock); + return res; +} + /* * em28xx_v4l2_mmap() */ @@ -2368,10 +2387,13 @@ static int em28xx_v4l2_mmap(struct file *filp, struct vm_area_struct *vma) if (rc < 0) return rc; + if (mutex_lock_interruptible(&dev->lock)) + return -ERESTARTSYS; if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) rc = videobuf_mmap_mapper(&fh->vb_vidq, vma); else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) rc = videobuf_mmap_mapper(&fh->vb_vbiq, vma); + mutex_unlock(&dev->lock); em28xx_videodbg("vma start=0x%08lx, size=%ld, ret=%d\n", (unsigned long)vma->vm_start, @@ -2495,10 +2517,6 @@ static struct video_device *em28xx_vdev_init(struct em28xx *dev, vfd->release = video_device_release; vfd->debug = video_debug; vfd->lock = &dev->lock; - /* Locking in file operations other than ioctl should be done - by the driver, not the V4L2 core. - This driver needs auditing so that this flag can be removed. */ - set_bit(V4L2_FL_LOCK_ALL_FOPS, &vfd->flags); snprintf(vfd->name, sizeof(vfd->name), "%s %s", dev->name, type_name); diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/usb/em28xx/em28xx.h index 8757523e6863..8757523e6863 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/usb/em28xx/em28xx.h diff --git a/drivers/media/video/gspca/Kconfig b/drivers/media/usb/gspca/Kconfig index dfe268bfa4f8..6345f9331e7f 100644 --- a/drivers/media/video/gspca/Kconfig +++ b/drivers/media/usb/gspca/Kconfig @@ -17,9 +17,9 @@ menuconfig USB_GSPCA if USB_GSPCA && VIDEO_V4L2 -source "drivers/media/video/gspca/m5602/Kconfig" -source "drivers/media/video/gspca/stv06xx/Kconfig" -source "drivers/media/video/gspca/gl860/Kconfig" +source "drivers/media/usb/gspca/m5602/Kconfig" +source "drivers/media/usb/gspca/stv06xx/Kconfig" +source "drivers/media/usb/gspca/gl860/Kconfig" config USB_GSPCA_BENQ tristate "Benq USB Camera Driver" diff --git a/drivers/media/video/gspca/Makefile b/drivers/media/usb/gspca/Makefile index c901da0bd657..c901da0bd657 100644 --- a/drivers/media/video/gspca/Makefile +++ b/drivers/media/usb/gspca/Makefile diff --git a/drivers/media/video/gspca/autogain_functions.c b/drivers/media/usb/gspca/autogain_functions.c index 67db674bb044..67db674bb044 100644 --- a/drivers/media/video/gspca/autogain_functions.c +++ b/drivers/media/usb/gspca/autogain_functions.c diff --git a/drivers/media/video/gspca/autogain_functions.h b/drivers/media/usb/gspca/autogain_functions.h index d625eafe63eb..d625eafe63eb 100644 --- a/drivers/media/video/gspca/autogain_functions.h +++ b/drivers/media/usb/gspca/autogain_functions.h diff --git a/drivers/media/video/gspca/benq.c b/drivers/media/usb/gspca/benq.c index 352f32190e68..352f32190e68 100644 --- a/drivers/media/video/gspca/benq.c +++ b/drivers/media/usb/gspca/benq.c diff --git a/drivers/media/video/gspca/conex.c b/drivers/media/usb/gspca/conex.c index c9052f20435e..c9052f20435e 100644 --- a/drivers/media/video/gspca/conex.c +++ b/drivers/media/usb/gspca/conex.c diff --git a/drivers/media/video/gspca/cpia1.c b/drivers/media/usb/gspca/cpia1.c index 2499a881d9a3..b3ba47d4d6a2 100644 --- a/drivers/media/video/gspca/cpia1.c +++ b/drivers/media/usb/gspca/cpia1.c @@ -751,7 +751,7 @@ static int goto_high_power(struct gspca_dev *gspca_dev) if (signal_pending(current)) return -EINTR; - do_command(gspca_dev, CPIA_COMMAND_GetCameraStatus, 0, 0, 0, 0); + ret = do_command(gspca_dev, CPIA_COMMAND_GetCameraStatus, 0, 0, 0, 0); if (ret) return ret; diff --git a/drivers/media/video/gspca/etoms.c b/drivers/media/usb/gspca/etoms.c index 38f68e11c3a2..38f68e11c3a2 100644 --- a/drivers/media/video/gspca/etoms.c +++ b/drivers/media/usb/gspca/etoms.c diff --git a/drivers/media/video/gspca/finepix.c b/drivers/media/usb/gspca/finepix.c index c8f2201cc35a..52bdb569760b 100644 --- a/drivers/media/video/gspca/finepix.c +++ b/drivers/media/usb/gspca/finepix.c @@ -77,7 +77,14 @@ static int command(struct gspca_dev *gspca_dev, 12, FPIX_TIMEOUT); } -/* workqueue */ +/* + * This function is called as a workqueue function and runs whenever the camera + * is streaming data. Because it is a workqueue function it is allowed to sleep + * so we can use synchronous USB calls. To avoid possible collisions with other + * threads attempting to use gspca_dev->usb_buf we take the usb_lock when + * performing USB operations using it. In practice we don't really need this + * as the camera doesn't provide any controls. + */ static void dostream(struct work_struct *work) { struct usb_fpix *dev = container_of(work, struct usb_fpix, work_struct); @@ -87,14 +94,11 @@ static void dostream(struct work_struct *work) int ret = 0; int len; - /* synchronize with the main driver */ - mutex_lock(&gspca_dev->usb_lock); - mutex_unlock(&gspca_dev->usb_lock); PDEBUG(D_STREAM, "dostream started"); /* loop reading a frame */ again: - while (gspca_dev->dev && gspca_dev->streaming) { + while (gspca_dev->present && gspca_dev->streaming) { #ifdef CONFIG_PM if (gspca_dev->frozen) break; @@ -110,7 +114,7 @@ again: if (gspca_dev->frozen) break; #endif - if (!gspca_dev->dev || !gspca_dev->streaming) + if (!gspca_dev->present || !gspca_dev->streaming) break; /* the frame comes in parts */ @@ -129,7 +133,7 @@ again: if (gspca_dev->frozen) goto out; #endif - if (!gspca_dev->dev || !gspca_dev->streaming) + if (!gspca_dev->present || !gspca_dev->streaming) goto out; if (len < FPIX_MAX_TRANSFER || (data[len - 2] == 0xff && diff --git a/drivers/media/video/gspca/gl860/Kconfig b/drivers/media/usb/gspca/gl860/Kconfig index 22772f53ec7b..22772f53ec7b 100644 --- a/drivers/media/video/gspca/gl860/Kconfig +++ b/drivers/media/usb/gspca/gl860/Kconfig diff --git a/drivers/media/video/gspca/gl860/Makefile b/drivers/media/usb/gspca/gl860/Makefile index 773ea3426561..cf6397415aad 100644 --- a/drivers/media/video/gspca/gl860/Makefile +++ b/drivers/media/usb/gspca/gl860/Makefile @@ -6,5 +6,5 @@ gspca_gl860-objs := gl860.o \ gl860-ov9655.o \ gl860-mi2020.o -ccflags-y += -I$(srctree)/drivers/media/video/gspca +ccflags-y += -I$(srctree)/drivers/media/usb/gspca diff --git a/drivers/media/video/gspca/gl860/gl860-mi1320.c b/drivers/media/usb/gspca/gl860/gl860-mi1320.c index b57160e04866..b57160e04866 100644 --- a/drivers/media/video/gspca/gl860/gl860-mi1320.c +++ b/drivers/media/usb/gspca/gl860/gl860-mi1320.c diff --git a/drivers/media/video/gspca/gl860/gl860-mi2020.c b/drivers/media/usb/gspca/gl860/gl860-mi2020.c index 2edda6b7d653..2edda6b7d653 100644 --- a/drivers/media/video/gspca/gl860/gl860-mi2020.c +++ b/drivers/media/usb/gspca/gl860/gl860-mi2020.c diff --git a/drivers/media/video/gspca/gl860/gl860-ov2640.c b/drivers/media/usb/gspca/gl860/gl860-ov2640.c index 768cac5cd72b..768cac5cd72b 100644 --- a/drivers/media/video/gspca/gl860/gl860-ov2640.c +++ b/drivers/media/usb/gspca/gl860/gl860-ov2640.c diff --git a/drivers/media/video/gspca/gl860/gl860-ov9655.c b/drivers/media/usb/gspca/gl860/gl860-ov9655.c index 5ae9619d72a5..5ae9619d72a5 100644 --- a/drivers/media/video/gspca/gl860/gl860-ov9655.c +++ b/drivers/media/usb/gspca/gl860/gl860-ov9655.c diff --git a/drivers/media/video/gspca/gl860/gl860.c b/drivers/media/usb/gspca/gl860/gl860.c index ced3b71f14e5..ced3b71f14e5 100644 --- a/drivers/media/video/gspca/gl860/gl860.c +++ b/drivers/media/usb/gspca/gl860/gl860.c diff --git a/drivers/media/video/gspca/gl860/gl860.h b/drivers/media/usb/gspca/gl860/gl860.h index 0330a0293b9c..0330a0293b9c 100644 --- a/drivers/media/video/gspca/gl860/gl860.h +++ b/drivers/media/usb/gspca/gl860/gl860.h diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/usb/gspca/gspca.c index d4e8343f5b10..a2b934146ebf 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/usb/gspca/gspca.c @@ -1686,7 +1686,7 @@ static int vidioc_g_jpegcomp(struct file *file, void *priv, } static int vidioc_s_jpegcomp(struct file *file, void *priv, - struct v4l2_jpegcompression *jpegcomp) + const struct v4l2_jpegcompression *jpegcomp) { struct gspca_dev *gspca_dev = video_drvdata(file); @@ -2358,8 +2358,6 @@ void gspca_disconnect(struct usb_interface *intf) mutex_lock(&gspca_dev->usb_lock); - usb_set_intfdata(intf, NULL); - gspca_dev->dev = NULL; gspca_dev->present = 0; destroy_urbs(gspca_dev); @@ -2375,6 +2373,7 @@ void gspca_disconnect(struct usb_interface *intf) if (gspca_dev->sd_desc->stop0 && gspca_dev->streaming) gspca_dev->sd_desc->stop0(gspca_dev); gspca_dev->streaming = 0; + gspca_dev->dev = NULL; wake_up_interruptible(&gspca_dev->wq); v4l2_device_disconnect(&gspca_dev->v4l2_dev); @@ -2392,19 +2391,22 @@ int gspca_suspend(struct usb_interface *intf, pm_message_t message) { struct gspca_dev *gspca_dev = usb_get_intfdata(intf); + gspca_input_destroy_urb(gspca_dev); + if (!gspca_dev->streaming) return 0; + mutex_lock(&gspca_dev->usb_lock); gspca_dev->frozen = 1; /* avoid urb error messages */ gspca_dev->usb_err = 0; if (gspca_dev->sd_desc->stopN) gspca_dev->sd_desc->stopN(gspca_dev); destroy_urbs(gspca_dev); - gspca_input_destroy_urb(gspca_dev); gspca_set_alt0(gspca_dev); if (gspca_dev->sd_desc->stop0) gspca_dev->sd_desc->stop0(gspca_dev); mutex_unlock(&gspca_dev->usb_lock); + return 0; } EXPORT_SYMBOL(gspca_suspend); @@ -2418,7 +2420,6 @@ int gspca_resume(struct usb_interface *intf) gspca_dev->frozen = 0; gspca_dev->usb_err = 0; gspca_dev->sd_desc->init(gspca_dev); - gspca_input_create_urb(gspca_dev); /* * Most subdrivers send all ctrl values on sd_start and thus * only write to the device registers on s_ctrl when streaming -> @@ -2428,7 +2429,10 @@ int gspca_resume(struct usb_interface *intf) gspca_dev->streaming = 0; if (streaming) ret = gspca_init_transfer(gspca_dev); + else + gspca_input_create_urb(gspca_dev); mutex_unlock(&gspca_dev->usb_lock); + return ret; } EXPORT_SYMBOL(gspca_resume); diff --git a/drivers/media/video/gspca/gspca.h b/drivers/media/usb/gspca/gspca.h index dc688c7f5e48..e3eab82cd4e5 100644 --- a/drivers/media/video/gspca/gspca.h +++ b/drivers/media/usb/gspca/gspca.h @@ -83,8 +83,10 @@ struct gspca_frame; typedef int (*cam_op) (struct gspca_dev *); typedef void (*cam_v_op) (struct gspca_dev *); typedef int (*cam_cf_op) (struct gspca_dev *, const struct usb_device_id *); -typedef int (*cam_jpg_op) (struct gspca_dev *, +typedef int (*cam_get_jpg_op) (struct gspca_dev *, struct v4l2_jpegcompression *); +typedef int (*cam_set_jpg_op) (struct gspca_dev *, + const struct v4l2_jpegcompression *); typedef int (*cam_reg_op) (struct gspca_dev *, struct v4l2_dbg_register *); typedef int (*cam_ident_op) (struct gspca_dev *, @@ -126,8 +128,8 @@ struct sd_desc { cam_v_op stopN; /* called on stream off - main alt */ cam_v_op stop0; /* called on stream off & disconnect - alt 0 */ cam_v_op dq_callback; /* called when a frame has been dequeued */ - cam_jpg_op get_jcomp; - cam_jpg_op set_jcomp; + cam_get_jpg_op get_jcomp; + cam_set_jpg_op set_jcomp; cam_qmnu_op querymenu; cam_streamparm_op get_streamparm; cam_streamparm_op set_streamparm; diff --git a/drivers/media/video/gspca/jeilinj.c b/drivers/media/usb/gspca/jeilinj.c index 26b99310d628..b897aa86f315 100644 --- a/drivers/media/video/gspca/jeilinj.c +++ b/drivers/media/usb/gspca/jeilinj.c @@ -474,7 +474,7 @@ static int sd_init_controls(struct gspca_dev *gspca_dev) } static int sd_set_jcomp(struct gspca_dev *gspca_dev, - struct v4l2_jpegcompression *jcomp) + const struct v4l2_jpegcompression *jcomp) { struct sd *sd = (struct sd *) gspca_dev; diff --git a/drivers/media/video/gspca/jl2005bcd.c b/drivers/media/usb/gspca/jl2005bcd.c index 234777116e5f..62ba80d9b998 100644 --- a/drivers/media/video/gspca/jl2005bcd.c +++ b/drivers/media/usb/gspca/jl2005bcd.c @@ -306,15 +306,13 @@ static int jl2005c_stop(struct gspca_dev *gspca_dev) return retval; } -/* This function is called as a workqueue function and runs whenever the camera +/* + * This function is called as a workqueue function and runs whenever the camera * is streaming data. Because it is a workqueue function it is allowed to sleep * so we can use synchronous USB calls. To avoid possible collisions with other - * threads attempting to use the camera's USB interface the gspca usb_lock is - * used when performing the one USB control operation inside the workqueue, - * which tells the camera to close the stream. In practice the only thing - * which needs to be protected against is the usb_set_interface call that - * gspca makes during stream_off. Otherwise the camera doesn't provide any - * controls that the user could try to change. + * threads attempting to use gspca_dev->usb_buf we take the usb_lock when + * performing USB operations using it. In practice we don't really need this + * as the camera doesn't provide any controls. */ static void jl2005c_dostream(struct work_struct *work) { @@ -335,7 +333,7 @@ static void jl2005c_dostream(struct work_struct *work) goto quit_stream; } - while (gspca_dev->dev && gspca_dev->streaming) { + while (gspca_dev->present && gspca_dev->streaming) { #ifdef CONFIG_PM if (gspca_dev->frozen) break; @@ -371,7 +369,7 @@ static void jl2005c_dostream(struct work_struct *work) buffer, act_len); header_read = 1; } - while (bytes_left > 0 && gspca_dev->dev) { + while (bytes_left > 0 && gspca_dev->present) { data_len = bytes_left > JL2005C_MAX_TRANSFER ? JL2005C_MAX_TRANSFER : bytes_left; ret = usb_bulk_msg(gspca_dev->dev, @@ -394,7 +392,7 @@ static void jl2005c_dostream(struct work_struct *work) } } quit_stream: - if (gspca_dev->dev) { + if (gspca_dev->present) { mutex_lock(&gspca_dev->usb_lock); jl2005c_stop(gspca_dev); mutex_unlock(&gspca_dev->usb_lock); diff --git a/drivers/media/video/gspca/jpeg.h b/drivers/media/usb/gspca/jpeg.h index ab54910418b4..ab54910418b4 100644 --- a/drivers/media/video/gspca/jpeg.h +++ b/drivers/media/usb/gspca/jpeg.h diff --git a/drivers/media/video/gspca/kinect.c b/drivers/media/usb/gspca/kinect.c index 40ad6687ee5d..40ad6687ee5d 100644 --- a/drivers/media/video/gspca/kinect.c +++ b/drivers/media/usb/gspca/kinect.c diff --git a/drivers/media/video/gspca/konica.c b/drivers/media/usb/gspca/konica.c index bbf91e07e38b..bbf91e07e38b 100644 --- a/drivers/media/video/gspca/konica.c +++ b/drivers/media/usb/gspca/konica.c diff --git a/drivers/media/video/gspca/m5602/Kconfig b/drivers/media/usb/gspca/m5602/Kconfig index 5a69016ed75f..5a69016ed75f 100644 --- a/drivers/media/video/gspca/m5602/Kconfig +++ b/drivers/media/usb/gspca/m5602/Kconfig diff --git a/drivers/media/video/gspca/m5602/Makefile b/drivers/media/usb/gspca/m5602/Makefile index 575b75bacb62..8e1fb5a1d2a1 100644 --- a/drivers/media/video/gspca/m5602/Makefile +++ b/drivers/media/usb/gspca/m5602/Makefile @@ -8,4 +8,4 @@ gspca_m5602-objs := m5602_core.o \ m5602_s5k83a.o \ m5602_s5k4aa.o -ccflags-y += -I$(srctree)/drivers/media/video/gspca +ccflags-y += -I$(srctree)/drivers/media/usb/gspca diff --git a/drivers/media/video/gspca/m5602/m5602_bridge.h b/drivers/media/usb/gspca/m5602/m5602_bridge.h index 51af3ee3ab85..51af3ee3ab85 100644 --- a/drivers/media/video/gspca/m5602/m5602_bridge.h +++ b/drivers/media/usb/gspca/m5602/m5602_bridge.h diff --git a/drivers/media/video/gspca/m5602/m5602_core.c b/drivers/media/usb/gspca/m5602/m5602_core.c index ed22638978ce..ed22638978ce 100644 --- a/drivers/media/video/gspca/m5602/m5602_core.c +++ b/drivers/media/usb/gspca/m5602/m5602_core.c diff --git a/drivers/media/video/gspca/m5602/m5602_mt9m111.c b/drivers/media/usb/gspca/m5602/m5602_mt9m111.c index 6268aa24ec5d..6268aa24ec5d 100644 --- a/drivers/media/video/gspca/m5602/m5602_mt9m111.c +++ b/drivers/media/usb/gspca/m5602/m5602_mt9m111.c diff --git a/drivers/media/video/gspca/m5602/m5602_mt9m111.h b/drivers/media/usb/gspca/m5602/m5602_mt9m111.h index 8c672b5c8c6a..8c672b5c8c6a 100644 --- a/drivers/media/video/gspca/m5602/m5602_mt9m111.h +++ b/drivers/media/usb/gspca/m5602/m5602_mt9m111.h diff --git a/drivers/media/video/gspca/m5602/m5602_ov7660.c b/drivers/media/usb/gspca/m5602/m5602_ov7660.c index 9a14835c128f..9a14835c128f 100644 --- a/drivers/media/video/gspca/m5602/m5602_ov7660.c +++ b/drivers/media/usb/gspca/m5602/m5602_ov7660.c diff --git a/drivers/media/video/gspca/m5602/m5602_ov7660.h b/drivers/media/usb/gspca/m5602/m5602_ov7660.h index 2b6a13b508f7..2b6a13b508f7 100644 --- a/drivers/media/video/gspca/m5602/m5602_ov7660.h +++ b/drivers/media/usb/gspca/m5602/m5602_ov7660.h diff --git a/drivers/media/video/gspca/m5602/m5602_ov9650.c b/drivers/media/usb/gspca/m5602/m5602_ov9650.c index 2114a8b90ec9..2114a8b90ec9 100644 --- a/drivers/media/video/gspca/m5602/m5602_ov9650.c +++ b/drivers/media/usb/gspca/m5602/m5602_ov9650.c diff --git a/drivers/media/video/gspca/m5602/m5602_ov9650.h b/drivers/media/usb/gspca/m5602/m5602_ov9650.h index f7aa5bf68983..f7aa5bf68983 100644 --- a/drivers/media/video/gspca/m5602/m5602_ov9650.h +++ b/drivers/media/usb/gspca/m5602/m5602_ov9650.h diff --git a/drivers/media/video/gspca/m5602/m5602_po1030.c b/drivers/media/usb/gspca/m5602/m5602_po1030.c index b8771698cbcb..b8771698cbcb 100644 --- a/drivers/media/video/gspca/m5602/m5602_po1030.c +++ b/drivers/media/usb/gspca/m5602/m5602_po1030.c diff --git a/drivers/media/video/gspca/m5602/m5602_po1030.h b/drivers/media/usb/gspca/m5602/m5602_po1030.h index 81a2bcb88fe3..81a2bcb88fe3 100644 --- a/drivers/media/video/gspca/m5602/m5602_po1030.h +++ b/drivers/media/usb/gspca/m5602/m5602_po1030.h diff --git a/drivers/media/video/gspca/m5602/m5602_s5k4aa.c b/drivers/media/usb/gspca/m5602/m5602_s5k4aa.c index cc8ec3f7e8dc..cc8ec3f7e8dc 100644 --- a/drivers/media/video/gspca/m5602/m5602_s5k4aa.c +++ b/drivers/media/usb/gspca/m5602/m5602_s5k4aa.c diff --git a/drivers/media/video/gspca/m5602/m5602_s5k4aa.h b/drivers/media/usb/gspca/m5602/m5602_s5k4aa.h index 8e0035e731c7..8e0035e731c7 100644 --- a/drivers/media/video/gspca/m5602/m5602_s5k4aa.h +++ b/drivers/media/usb/gspca/m5602/m5602_s5k4aa.h diff --git a/drivers/media/video/gspca/m5602/m5602_s5k83a.c b/drivers/media/usb/gspca/m5602/m5602_s5k83a.c index 1de743a02b02..1de743a02b02 100644 --- a/drivers/media/video/gspca/m5602/m5602_s5k83a.c +++ b/drivers/media/usb/gspca/m5602/m5602_s5k83a.c diff --git a/drivers/media/video/gspca/m5602/m5602_s5k83a.h b/drivers/media/usb/gspca/m5602/m5602_s5k83a.h index 79952247b534..79952247b534 100644 --- a/drivers/media/video/gspca/m5602/m5602_s5k83a.h +++ b/drivers/media/usb/gspca/m5602/m5602_s5k83a.h diff --git a/drivers/media/video/gspca/m5602/m5602_sensor.h b/drivers/media/usb/gspca/m5602/m5602_sensor.h index edff4f1f586f..edff4f1f586f 100644 --- a/drivers/media/video/gspca/m5602/m5602_sensor.h +++ b/drivers/media/usb/gspca/m5602/m5602_sensor.h diff --git a/drivers/media/video/gspca/mars.c b/drivers/media/usb/gspca/mars.c index ff2c5abf115b..ff2c5abf115b 100644 --- a/drivers/media/video/gspca/mars.c +++ b/drivers/media/usb/gspca/mars.c diff --git a/drivers/media/video/gspca/mr97310a.c b/drivers/media/usb/gspca/mr97310a.c index 8f4714df5990..8f4714df5990 100644 --- a/drivers/media/video/gspca/mr97310a.c +++ b/drivers/media/usb/gspca/mr97310a.c diff --git a/drivers/media/video/gspca/nw80x.c b/drivers/media/usb/gspca/nw80x.c index 44c9964b1b3e..44c9964b1b3e 100644 --- a/drivers/media/video/gspca/nw80x.c +++ b/drivers/media/usb/gspca/nw80x.c diff --git a/drivers/media/video/gspca/ov519.c b/drivers/media/usb/gspca/ov519.c index bfc7cefa59f8..9aa09f845ce4 100644 --- a/drivers/media/video/gspca/ov519.c +++ b/drivers/media/usb/gspca/ov519.c @@ -141,14 +141,14 @@ enum sensors { /* table of the disabled controls */ struct ctrl_valid { - int has_brightness:1; - int has_contrast:1; - int has_exposure:1; - int has_autogain:1; - int has_sat:1; - int has_hvflip:1; - int has_autobright:1; - int has_freq:1; + unsigned int has_brightness:1; + unsigned int has_contrast:1; + unsigned int has_exposure:1; + unsigned int has_autogain:1; + unsigned int has_sat:1; + unsigned int has_hvflip:1; + unsigned int has_autobright:1; + unsigned int has_freq:1; }; static const struct ctrl_valid valid_controls[] = { @@ -4762,7 +4762,7 @@ static int sd_get_jcomp(struct gspca_dev *gspca_dev, } static int sd_set_jcomp(struct gspca_dev *gspca_dev, - struct v4l2_jpegcompression *jcomp) + const struct v4l2_jpegcompression *jcomp) { struct sd *sd = (struct sd *) gspca_dev; diff --git a/drivers/media/video/gspca/ov534.c b/drivers/media/usb/gspca/ov534.c index bb09d7884b89..bb09d7884b89 100644 --- a/drivers/media/video/gspca/ov534.c +++ b/drivers/media/usb/gspca/ov534.c diff --git a/drivers/media/video/gspca/ov534_9.c b/drivers/media/usb/gspca/ov534_9.c index c4cd028fe0b4..c4cd028fe0b4 100644 --- a/drivers/media/video/gspca/ov534_9.c +++ b/drivers/media/usb/gspca/ov534_9.c diff --git a/drivers/media/video/gspca/pac207.c b/drivers/media/usb/gspca/pac207.c index d236d1791f78..d236d1791f78 100644 --- a/drivers/media/video/gspca/pac207.c +++ b/drivers/media/usb/gspca/pac207.c diff --git a/drivers/media/video/gspca/pac7302.c b/drivers/media/usb/gspca/pac7302.c index 4877f7ab3d59..2d5c6d8343a0 100644 --- a/drivers/media/video/gspca/pac7302.c +++ b/drivers/media/usb/gspca/pac7302.c @@ -26,6 +26,20 @@ /* * Some documentation about various registers as determined by trial and error. * + * Register page 0: + * + * Address Description + * 0x02 Red balance control + * 0x03 Green balance control + * 0x04 Blue balance control + * Valus are inverted (0=max, 255=min). + * The Windows driver uses a quadratic approach to map + * the settable values (0-200) on register values: + * min=0x80, default=0x40, max=0x20 + * 0x0f-0x20 Colors, saturation and exposure control + * 0xa2-0xab Brightness, contrast and gamma control + * 0xb6 Sharpness control (bits 0-4) + * * Register page 1: * * Address Description @@ -66,6 +80,7 @@ * -----+------------+--------------------------------------------------- * 0 | 0x0f..0x20 | setcolors() * 0 | 0xa2..0xab | setbrightcont() + * 0 | 0xb6 | setsharpness() * 0 | 0xc5 | setredbalance() * 0 | 0xc6 | setwhitebalance() * 0 | 0xc7 | setbluebalance() @@ -109,6 +124,7 @@ struct sd { struct v4l2_ctrl *hflip; struct v4l2_ctrl *vflip; }; + struct v4l2_ctrl *sharpness; u8 flags; #define FL_HFLIP 0x01 /* mirrored by default */ #define FL_VFLIP 0x02 /* vertical flipped by default */ @@ -531,6 +547,16 @@ static void sethvflip(struct gspca_dev *gspca_dev) reg_w(gspca_dev, 0x11, 0x01); } +static void setsharpness(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + + reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ + reg_w(gspca_dev, 0xb6, sd->sharpness->val); + + reg_w(gspca_dev, 0xdc, 0x01); +} + /* this function is called at probe and resume time for pac7302 */ static int sd_init(struct gspca_dev *gspca_dev) { @@ -584,6 +610,9 @@ static int sd_s_ctrl(struct v4l2_ctrl *ctrl) case V4L2_CID_HFLIP: sethvflip(gspca_dev); break; + case V4L2_CID_SHARPNESS: + setsharpness(gspca_dev); + break; default: return -EINVAL; } @@ -601,7 +630,7 @@ static int sd_init_controls(struct gspca_dev *gspca_dev) struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler; gspca_dev->vdev.ctrl_handler = hdl; - v4l2_ctrl_handler_init(hdl, 11); + v4l2_ctrl_handler_init(hdl, 12); sd->brightness = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, V4L2_CID_BRIGHTNESS, 0, 32, 1, 16); @@ -612,11 +641,11 @@ static int sd_init_controls(struct gspca_dev *gspca_dev) V4L2_CID_SATURATION, 0, 255, 1, 127); sd->white_balance = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, V4L2_CID_WHITE_BALANCE_TEMPERATURE, - 0, 255, 1, 4); + 0, 255, 1, 55); sd->red_balance = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, V4L2_CID_RED_BALANCE, 0, 3, 1, 1); sd->blue_balance = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_RED_BALANCE, 0, 3, 1, 1); + V4L2_CID_BLUE_BALANCE, 0, 3, 1, 1); gspca_dev->autogain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, V4L2_CID_AUTOGAIN, 0, 1, 1, 1); @@ -632,6 +661,9 @@ static int sd_init_controls(struct gspca_dev *gspca_dev) sd->vflip = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, V4L2_CID_VFLIP, 0, 1, 1, 0); + sd->sharpness = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, + V4L2_CID_SHARPNESS, 0, 15, 1, 8); + if (hdl->error) { pr_err("Could not initialize controls\n"); return hdl->error; @@ -650,14 +682,6 @@ static int sd_start(struct gspca_dev *gspca_dev) reg_w_var(gspca_dev, start_7302, page3_7302, sizeof(page3_7302)); - setbrightcont(gspca_dev); - setcolors(gspca_dev); - setwhitebalance(gspca_dev); - setredbalance(gspca_dev); - setbluebalance(gspca_dev); - setexposure(gspca_dev); - setgain(gspca_dev); - sethvflip(gspca_dev); sd->sof_read = 0; sd->autogain_ignore_frames = 0; @@ -905,6 +929,7 @@ static const struct usb_device_id device_table[] = { {USB_DEVICE(0x093a, 0x262a)}, {USB_DEVICE(0x093a, 0x262c)}, {USB_DEVICE(0x145f, 0x013c)}, + {USB_DEVICE(0x1ae7, 0x2001)}, /* SpeedLink Snappy Mic SL-6825-SBK */ {} }; MODULE_DEVICE_TABLE(usb, device_table); diff --git a/drivers/media/video/gspca/pac7311.c b/drivers/media/usb/gspca/pac7311.c index ba3558d3f017..ba3558d3f017 100644 --- a/drivers/media/video/gspca/pac7311.c +++ b/drivers/media/usb/gspca/pac7311.c diff --git a/drivers/media/video/gspca/pac_common.h b/drivers/media/usb/gspca/pac_common.h index 8462a7c1a338..8462a7c1a338 100644 --- a/drivers/media/video/gspca/pac_common.h +++ b/drivers/media/usb/gspca/pac_common.h diff --git a/drivers/media/video/gspca/se401.c b/drivers/media/usb/gspca/se401.c index a33cb78a839c..a33cb78a839c 100644 --- a/drivers/media/video/gspca/se401.c +++ b/drivers/media/usb/gspca/se401.c diff --git a/drivers/media/video/gspca/se401.h b/drivers/media/usb/gspca/se401.h index 96d8ebf3cf59..96d8ebf3cf59 100644 --- a/drivers/media/video/gspca/se401.h +++ b/drivers/media/usb/gspca/se401.h diff --git a/drivers/media/video/gspca/sn9c2028.c b/drivers/media/usb/gspca/sn9c2028.c index 03fa3fd940b4..03fa3fd940b4 100644 --- a/drivers/media/video/gspca/sn9c2028.c +++ b/drivers/media/usb/gspca/sn9c2028.c diff --git a/drivers/media/video/gspca/sn9c2028.h b/drivers/media/usb/gspca/sn9c2028.h index 8fd1d3e05665..8fd1d3e05665 100644 --- a/drivers/media/video/gspca/sn9c2028.h +++ b/drivers/media/usb/gspca/sn9c2028.h diff --git a/drivers/media/video/gspca/sn9c20x.c b/drivers/media/usb/gspca/sn9c20x.c index b9c6f17eabb2..41f769fe340c 100644 --- a/drivers/media/video/gspca/sn9c20x.c +++ b/drivers/media/usb/gspca/sn9c20x.c @@ -2197,8 +2197,10 @@ static void qual_upd(struct work_struct *work) struct gspca_dev *gspca_dev = &sd->gspca_dev; s32 qual = v4l2_ctrl_g_ctrl(sd->jpegqual); + /* To protect gspca_dev->usb_buf and gspca_dev->usb_err */ mutex_lock(&gspca_dev->usb_lock); PDEBUG(D_STREAM, "qual_upd %d%%", qual); + gspca_dev->usb_err = 0; set_quality(gspca_dev, qual); mutex_unlock(&gspca_dev->usb_lock); } diff --git a/drivers/media/video/gspca/sonixb.c b/drivers/media/usb/gspca/sonixb.c index fd1f8d2d3b0b..fd1f8d2d3b0b 100644 --- a/drivers/media/video/gspca/sonixb.c +++ b/drivers/media/usb/gspca/sonixb.c diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/usb/gspca/sonixj.c index 150b2df40f7f..5a86047b846f 100644 --- a/drivers/media/video/gspca/sonixj.c +++ b/drivers/media/usb/gspca/sonixj.c @@ -2380,8 +2380,10 @@ static void qual_upd(struct work_struct *work) struct sd *sd = container_of(work, struct sd, work); struct gspca_dev *gspca_dev = &sd->gspca_dev; + /* To protect gspca_dev->usb_buf and gspca_dev->usb_err */ mutex_lock(&gspca_dev->usb_lock); PDEBUG(D_STREAM, "qual_upd %d%%", sd->quality); + gspca_dev->usb_err = 0; setjpegqual(gspca_dev); mutex_unlock(&gspca_dev->usb_lock); } diff --git a/drivers/media/video/gspca/spca1528.c b/drivers/media/usb/gspca/spca1528.c index 14d635277d71..14d635277d71 100644 --- a/drivers/media/video/gspca/spca1528.c +++ b/drivers/media/usb/gspca/spca1528.c diff --git a/drivers/media/video/gspca/spca500.c b/drivers/media/usb/gspca/spca500.c index 25cb68d0556d..25cb68d0556d 100644 --- a/drivers/media/video/gspca/spca500.c +++ b/drivers/media/usb/gspca/spca500.c diff --git a/drivers/media/video/gspca/spca501.c b/drivers/media/usb/gspca/spca501.c index 3b7f777785b4..3b7f777785b4 100644 --- a/drivers/media/video/gspca/spca501.c +++ b/drivers/media/usb/gspca/spca501.c diff --git a/drivers/media/video/gspca/spca505.c b/drivers/media/usb/gspca/spca505.c index bc7d67c3cb04..bc7d67c3cb04 100644 --- a/drivers/media/video/gspca/spca505.c +++ b/drivers/media/usb/gspca/spca505.c diff --git a/drivers/media/video/gspca/spca506.c b/drivers/media/usb/gspca/spca506.c index bab01c86c315..bab01c86c315 100644 --- a/drivers/media/video/gspca/spca506.c +++ b/drivers/media/usb/gspca/spca506.c diff --git a/drivers/media/video/gspca/spca508.c b/drivers/media/usb/gspca/spca508.c index 1286b4170b88..1286b4170b88 100644 --- a/drivers/media/video/gspca/spca508.c +++ b/drivers/media/usb/gspca/spca508.c diff --git a/drivers/media/video/gspca/spca561.c b/drivers/media/usb/gspca/spca561.c index cfe71dd6747d..cfe71dd6747d 100644 --- a/drivers/media/video/gspca/spca561.c +++ b/drivers/media/usb/gspca/spca561.c diff --git a/drivers/media/video/gspca/sq905.c b/drivers/media/usb/gspca/sq905.c index a8ac97931ad6..1d99f10a3e19 100644 --- a/drivers/media/video/gspca/sq905.c +++ b/drivers/media/usb/gspca/sq905.c @@ -201,14 +201,13 @@ sq905_read_data(struct gspca_dev *gspca_dev, u8 *data, int size, int need_lock) return 0; } -/* This function is called as a workqueue function and runs whenever the camera +/* + * This function is called as a workqueue function and runs whenever the camera * is streaming data. Because it is a workqueue function it is allowed to sleep * so we can use synchronous USB calls. To avoid possible collisions with other - * threads attempting to use the camera's USB interface we take the gspca - * usb_lock when performing USB operations. In practice the only thing we need - * to protect against is the usb_set_interface call that gspca makes during - * stream_off as the camera doesn't provide any controls that the user could try - * to change. + * threads attempting to use gspca_dev->usb_buf we take the usb_lock when + * performing USB operations using it. In practice we don't really need this + * as the camera doesn't provide any controls. */ static void sq905_dostream(struct work_struct *work) { @@ -232,7 +231,7 @@ static void sq905_dostream(struct work_struct *work) frame_sz = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].sizeimage + FRAME_HEADER_LEN; - while (gspca_dev->dev && gspca_dev->streaming) { + while (gspca_dev->present && gspca_dev->streaming) { #ifdef CONFIG_PM if (gspca_dev->frozen) break; @@ -246,7 +245,7 @@ static void sq905_dostream(struct work_struct *work) we must finish reading an entire frame, otherwise the next time we stream we start reading in the middle of a frame. */ - while (bytes_left > 0 && gspca_dev->dev) { + while (bytes_left > 0 && gspca_dev->present) { data_len = bytes_left > SQ905_MAX_TRANSFER ? SQ905_MAX_TRANSFER : bytes_left; ret = sq905_read_data(gspca_dev, buffer, data_len, 1); @@ -278,7 +277,7 @@ static void sq905_dostream(struct work_struct *work) gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0); } - if (gspca_dev->dev) { + if (gspca_dev->present) { /* acknowledge the frame */ mutex_lock(&gspca_dev->usb_lock); ret = sq905_ack_frame(gspca_dev); @@ -288,7 +287,7 @@ static void sq905_dostream(struct work_struct *work) } } quit_stream: - if (gspca_dev->dev) { + if (gspca_dev->present) { mutex_lock(&gspca_dev->usb_lock); sq905_command(gspca_dev, SQ905_CLEAR); mutex_unlock(&gspca_dev->usb_lock); diff --git a/drivers/media/video/gspca/sq905c.c b/drivers/media/usb/gspca/sq905c.c index 2c2f3d2f357f..410cdcbb55d4 100644 --- a/drivers/media/video/gspca/sq905c.c +++ b/drivers/media/usb/gspca/sq905c.c @@ -123,15 +123,13 @@ static int sq905c_read(struct gspca_dev *gspca_dev, u16 command, u16 index, return 0; } -/* This function is called as a workqueue function and runs whenever the camera +/* + * This function is called as a workqueue function and runs whenever the camera * is streaming data. Because it is a workqueue function it is allowed to sleep * so we can use synchronous USB calls. To avoid possible collisions with other - * threads attempting to use the camera's USB interface the gspca usb_lock is - * used when performing the one USB control operation inside the workqueue, - * which tells the camera to close the stream. In practice the only thing - * which needs to be protected against is the usb_set_interface call that - * gspca makes during stream_off. Otherwise the camera doesn't provide any - * controls that the user could try to change. + * threads attempting to use gspca_dev->usb_buf we take the usb_lock when + * performing USB operations using it. In practice we don't really need this + * as the camera doesn't provide any controls. */ static void sq905c_dostream(struct work_struct *work) { @@ -150,7 +148,7 @@ static void sq905c_dostream(struct work_struct *work) goto quit_stream; } - while (gspca_dev->dev && gspca_dev->streaming) { + while (gspca_dev->present && gspca_dev->streaming) { #ifdef CONFIG_PM if (gspca_dev->frozen) break; @@ -173,7 +171,7 @@ static void sq905c_dostream(struct work_struct *work) packet_type = FIRST_PACKET; gspca_frame_add(gspca_dev, packet_type, buffer, FRAME_HEADER_LEN); - while (bytes_left > 0 && gspca_dev->dev) { + while (bytes_left > 0 && gspca_dev->present) { data_len = bytes_left > SQ905C_MAX_TRANSFER ? SQ905C_MAX_TRANSFER : bytes_left; ret = usb_bulk_msg(gspca_dev->dev, @@ -195,7 +193,7 @@ static void sq905c_dostream(struct work_struct *work) } } quit_stream: - if (gspca_dev->dev) { + if (gspca_dev->present) { mutex_lock(&gspca_dev->usb_lock); sq905c_command(gspca_dev, SQ905C_CLEAR, 0); mutex_unlock(&gspca_dev->usb_lock); @@ -228,11 +226,8 @@ static int sd_config(struct gspca_dev *gspca_dev, } /* Note we leave out the usb id and the manufacturing date */ PDEBUG(D_PROBE, - "SQ9050 ID string: %02x - %02x %02x %02x %02x %02x %02x", - gspca_dev->usb_buf[3], - gspca_dev->usb_buf[14], gspca_dev->usb_buf[15], - gspca_dev->usb_buf[16], gspca_dev->usb_buf[17], - gspca_dev->usb_buf[18], gspca_dev->usb_buf[19]); + "SQ9050 ID string: %02x - %*ph", + gspca_dev->usb_buf[3], 6, gspca_dev->usb_buf + 14); cam->cam_mode = sq905c_mode; cam->nmodes = 2; diff --git a/drivers/media/video/gspca/sq930x.c b/drivers/media/usb/gspca/sq930x.c index 3e1e486af883..7e8748b31e85 100644 --- a/drivers/media/video/gspca/sq930x.c +++ b/drivers/media/usb/gspca/sq930x.c @@ -863,15 +863,7 @@ static int sd_init(struct gspca_dev *gspca_dev) * 6: c8 / c9 / ca / cf = mode webcam?, sensor? webcam? * 7: 00 */ - PDEBUG(D_PROBE, "info: %02x %02x %02x %02x %02x %02x %02x %02x", - gspca_dev->usb_buf[0], - gspca_dev->usb_buf[1], - gspca_dev->usb_buf[2], - gspca_dev->usb_buf[3], - gspca_dev->usb_buf[4], - gspca_dev->usb_buf[5], - gspca_dev->usb_buf[6], - gspca_dev->usb_buf[7]); + PDEBUG(D_PROBE, "info: %*ph", 8, gspca_dev->usb_buf); bridge_init(sd); diff --git a/drivers/media/video/gspca/stk014.c b/drivers/media/usb/gspca/stk014.c index 8c0982607f25..8c0982607f25 100644 --- a/drivers/media/video/gspca/stk014.c +++ b/drivers/media/usb/gspca/stk014.c diff --git a/drivers/media/video/gspca/stv0680.c b/drivers/media/usb/gspca/stv0680.c index 67605272aaa8..67605272aaa8 100644 --- a/drivers/media/video/gspca/stv0680.c +++ b/drivers/media/usb/gspca/stv0680.c diff --git a/drivers/media/video/gspca/stv06xx/Kconfig b/drivers/media/usb/gspca/stv06xx/Kconfig index 634ad38d9fb8..634ad38d9fb8 100644 --- a/drivers/media/video/gspca/stv06xx/Kconfig +++ b/drivers/media/usb/gspca/stv06xx/Kconfig diff --git a/drivers/media/video/gspca/stv06xx/Makefile b/drivers/media/usb/gspca/stv06xx/Makefile index 38bc41061d83..3a4b2f899049 100644 --- a/drivers/media/video/gspca/stv06xx/Makefile +++ b/drivers/media/usb/gspca/stv06xx/Makefile @@ -6,5 +6,5 @@ gspca_stv06xx-objs := stv06xx.o \ stv06xx_pb0100.o \ stv06xx_st6422.o -ccflags-y += -I$(srctree)/drivers/media/video/gspca +ccflags-y += -I$(srctree)/drivers/media/usb/gspca diff --git a/drivers/media/video/gspca/stv06xx/stv06xx.c b/drivers/media/usb/gspca/stv06xx/stv06xx.c index 999ec7764449..999ec7764449 100644 --- a/drivers/media/video/gspca/stv06xx/stv06xx.c +++ b/drivers/media/usb/gspca/stv06xx/stv06xx.c diff --git a/drivers/media/video/gspca/stv06xx/stv06xx.h b/drivers/media/usb/gspca/stv06xx/stv06xx.h index 34957a4ec150..34957a4ec150 100644 --- a/drivers/media/video/gspca/stv06xx/stv06xx.h +++ b/drivers/media/usb/gspca/stv06xx/stv06xx.h diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c b/drivers/media/usb/gspca/stv06xx/stv06xx_hdcs.c index 06fa54c5efb2..06fa54c5efb2 100644 --- a/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c +++ b/drivers/media/usb/gspca/stv06xx/stv06xx_hdcs.c diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.h b/drivers/media/usb/gspca/stv06xx/stv06xx_hdcs.h index 1ba9158d0102..1ba9158d0102 100644 --- a/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.h +++ b/drivers/media/usb/gspca/stv06xx/stv06xx_hdcs.h diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.c b/drivers/media/usb/gspca/stv06xx/stv06xx_pb0100.c index cdfc3d05ab6b..cdfc3d05ab6b 100644 --- a/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.c +++ b/drivers/media/usb/gspca/stv06xx/stv06xx_pb0100.c diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.h b/drivers/media/usb/gspca/stv06xx/stv06xx_pb0100.h index 5071e5353fd3..5071e5353fd3 100644 --- a/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.h +++ b/drivers/media/usb/gspca/stv06xx/stv06xx_pb0100.h diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_sensor.h b/drivers/media/usb/gspca/stv06xx/stv06xx_sensor.h index 3a498c2495c6..3a498c2495c6 100644 --- a/drivers/media/video/gspca/stv06xx/stv06xx_sensor.h +++ b/drivers/media/usb/gspca/stv06xx/stv06xx_sensor.h diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_st6422.c b/drivers/media/usb/gspca/stv06xx/stv06xx_st6422.c index 8a57990dfe0f..8a57990dfe0f 100644 --- a/drivers/media/video/gspca/stv06xx/stv06xx_st6422.c +++ b/drivers/media/usb/gspca/stv06xx/stv06xx_st6422.c diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_st6422.h b/drivers/media/usb/gspca/stv06xx/stv06xx_st6422.h index 8f20fbf30f33..8f20fbf30f33 100644 --- a/drivers/media/video/gspca/stv06xx/stv06xx_st6422.h +++ b/drivers/media/usb/gspca/stv06xx/stv06xx_st6422.h diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.c b/drivers/media/usb/gspca/stv06xx/stv06xx_vv6410.c index 748e1421d6d8..748e1421d6d8 100644 --- a/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.c +++ b/drivers/media/usb/gspca/stv06xx/stv06xx_vv6410.c diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h b/drivers/media/usb/gspca/stv06xx/stv06xx_vv6410.h index 53e67b40ca05..53e67b40ca05 100644 --- a/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h +++ b/drivers/media/usb/gspca/stv06xx/stv06xx_vv6410.h diff --git a/drivers/media/video/gspca/sunplus.c b/drivers/media/usb/gspca/sunplus.c index 9ccfcb1c6479..9ccfcb1c6479 100644 --- a/drivers/media/video/gspca/sunplus.c +++ b/drivers/media/usb/gspca/sunplus.c diff --git a/drivers/media/video/gspca/t613.c b/drivers/media/usb/gspca/t613.c index 8bc6c3ceec2c..8bc6c3ceec2c 100644 --- a/drivers/media/video/gspca/t613.c +++ b/drivers/media/usb/gspca/t613.c diff --git a/drivers/media/video/gspca/topro.c b/drivers/media/usb/gspca/topro.c index a6055246cb9d..4cb511ccc5f6 100644 --- a/drivers/media/video/gspca/topro.c +++ b/drivers/media/usb/gspca/topro.c @@ -4806,7 +4806,7 @@ static void sd_set_streamparm(struct gspca_dev *gspca_dev, } static int sd_set_jcomp(struct gspca_dev *gspca_dev, - struct v4l2_jpegcompression *jcomp) + const struct v4l2_jpegcompression *jcomp) { struct sd *sd = (struct sd *) gspca_dev; diff --git a/drivers/media/video/gspca/tv8532.c b/drivers/media/usb/gspca/tv8532.c index 8591324a53e1..8591324a53e1 100644 --- a/drivers/media/video/gspca/tv8532.c +++ b/drivers/media/usb/gspca/tv8532.c diff --git a/drivers/media/video/gspca/vc032x.c b/drivers/media/usb/gspca/vc032x.c index f21fd1677c38..e50079503d96 100644 --- a/drivers/media/video/gspca/vc032x.c +++ b/drivers/media/usb/gspca/vc032x.c @@ -2934,11 +2934,8 @@ static void reg_r(struct gspca_dev *gspca_dev, PDEBUG(D_USBI, "GET %02x 0001 %04x %02x", req, index, gspca_dev->usb_buf[0]); else - PDEBUG(D_USBI, "GET %02x 0001 %04x %02x %02x %02x", - req, index, - gspca_dev->usb_buf[0], - gspca_dev->usb_buf[1], - gspca_dev->usb_buf[2]); + PDEBUG(D_USBI, "GET %02x 0001 %04x %*ph", + req, index, 3, gspca_dev->usb_buf); #endif } diff --git a/drivers/media/video/gspca/vicam.c b/drivers/media/usb/gspca/vicam.c index b1a64b912666..d6890bc37198 100644 --- a/drivers/media/video/gspca/vicam.c +++ b/drivers/media/usb/gspca/vicam.c @@ -110,7 +110,7 @@ static int vicam_set_camera_power(struct gspca_dev *gspca_dev, int state) } /* - * request and read a block of data - see warning on vicam_command. + * request and read a block of data */ static int vicam_read_frame(struct gspca_dev *gspca_dev, u8 *data, int size) { @@ -170,14 +170,13 @@ static int vicam_read_frame(struct gspca_dev *gspca_dev, u8 *data, int size) return 0; } -/* This function is called as a workqueue function and runs whenever the camera +/* + * This function is called as a workqueue function and runs whenever the camera * is streaming data. Because it is a workqueue function it is allowed to sleep * so we can use synchronous USB calls. To avoid possible collisions with other - * threads attempting to use the camera's USB interface we take the gspca - * usb_lock when performing USB operations. In practice the only thing we need - * to protect against is the usb_set_interface call that gspca makes during - * stream_off as the camera doesn't provide any controls that the user could try - * to change. + * threads attempting to use gspca_dev->usb_buf we take the usb_lock when + * performing USB operations using it. In practice we don't really need this + * as the cameras controls are only written from the workqueue. */ static void vicam_dostream(struct work_struct *work) { @@ -194,7 +193,7 @@ static void vicam_dostream(struct work_struct *work) goto exit; } - while (gspca_dev->dev && gspca_dev->streaming) { + while (gspca_dev->present && gspca_dev->streaming) { #ifdef CONFIG_PM if (gspca_dev->frozen) break; @@ -299,7 +298,7 @@ static void sd_stop0(struct gspca_dev *gspca_dev) dev->work_thread = NULL; mutex_lock(&gspca_dev->usb_lock); - if (gspca_dev->dev) + if (gspca_dev->present) vicam_set_camera_power(gspca_dev, 0); } diff --git a/drivers/media/video/gspca/w996Xcf.c b/drivers/media/usb/gspca/w996Xcf.c index 9e3a909e0a00..9e3a909e0a00 100644 --- a/drivers/media/video/gspca/w996Xcf.c +++ b/drivers/media/usb/gspca/w996Xcf.c diff --git a/drivers/media/video/gspca/xirlink_cit.c b/drivers/media/usb/gspca/xirlink_cit.c index 13b8d395d210..d4b23c9bf90c 100644 --- a/drivers/media/video/gspca/xirlink_cit.c +++ b/drivers/media/usb/gspca/xirlink_cit.c @@ -2697,9 +2697,7 @@ static void sd_stop0(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; - /* We cannot use gspca_dev->present here as that is not set when - sd_init gets called and we get called from sd_init */ - if (!gspca_dev->dev) + if (!gspca_dev->present) return; switch (sd->model) { diff --git a/drivers/media/video/gspca/zc3xx-reg.h b/drivers/media/usb/gspca/zc3xx-reg.h index a1bd94e8ce52..a1bd94e8ce52 100644 --- a/drivers/media/video/gspca/zc3xx-reg.h +++ b/drivers/media/usb/gspca/zc3xx-reg.h diff --git a/drivers/media/video/gspca/zc3xx.c b/drivers/media/usb/gspca/zc3xx.c index f0bacee33ef9..77c57755e7b4 100644 --- a/drivers/media/video/gspca/zc3xx.c +++ b/drivers/media/usb/gspca/zc3xx.c @@ -5945,12 +5945,13 @@ static void transfer_update(struct work_struct *work) for (;;) { msleep(100); + /* To protect gspca_dev->usb_buf and gspca_dev->usb_err */ mutex_lock(&gspca_dev->usb_lock); #ifdef CONFIG_PM if (gspca_dev->frozen) goto err; #endif - if (!gspca_dev->dev || !gspca_dev->streaming) + if (!gspca_dev->present || !gspca_dev->streaming) goto err; /* Bit 0 of register 11 indicates FIFO overflow */ @@ -6831,7 +6832,8 @@ static int sd_start(struct gspca_dev *gspca_dev) return 0; } -/* called on streamoff with alt 0 and on disconnect */ +/* called on streamoff with alt==0 and on disconnect */ +/* the usb_lock is held at entry - restore on exit */ static void sd_stop0(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; @@ -6842,7 +6844,7 @@ static void sd_stop0(struct gspca_dev *gspca_dev) mutex_lock(&gspca_dev->usb_lock); sd->work_thread = NULL; } - if (!gspca_dev->dev) + if (!gspca_dev->present) return; send_unknown(gspca_dev, sd->sensor); } @@ -6881,16 +6883,11 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, } static int sd_set_jcomp(struct gspca_dev *gspca_dev, - struct v4l2_jpegcompression *jcomp) + const struct v4l2_jpegcompression *jcomp) { struct sd *sd = (struct sd *) gspca_dev; - int ret; - ret = v4l2_ctrl_s_ctrl(sd->jpegqual, jcomp->quality); - if (ret) - return ret; - jcomp->quality = v4l2_ctrl_g_ctrl(sd->jpegqual); - return 0; + return v4l2_ctrl_s_ctrl(sd->jpegqual, jcomp->quality); } static int sd_get_jcomp(struct gspca_dev *gspca_dev, diff --git a/drivers/media/video/hdpvr/Kconfig b/drivers/media/usb/hdpvr/Kconfig index de247f3c7d05..de247f3c7d05 100644 --- a/drivers/media/video/hdpvr/Kconfig +++ b/drivers/media/usb/hdpvr/Kconfig diff --git a/drivers/media/video/hdpvr/Makefile b/drivers/media/usb/hdpvr/Makefile index 52f057f24e39..9b8d1463c526 100644 --- a/drivers/media/video/hdpvr/Makefile +++ b/drivers/media/usb/hdpvr/Makefile @@ -2,6 +2,6 @@ hdpvr-objs := hdpvr-control.o hdpvr-core.o hdpvr-video.o hdpvr-i2c.o obj-$(CONFIG_VIDEO_HDPVR) += hdpvr.o -ccflags-y += -Idrivers/media/video +ccflags-y += -Idrivers/media/i2c ccflags-y += $(extra-cflags-y) $(extra-cflags-m) diff --git a/drivers/media/video/hdpvr/hdpvr-control.c b/drivers/media/usb/hdpvr/hdpvr-control.c index ae8f229d1141..ae8f229d1141 100644 --- a/drivers/media/video/hdpvr/hdpvr-control.c +++ b/drivers/media/usb/hdpvr/hdpvr-control.c diff --git a/drivers/media/video/hdpvr/hdpvr-core.c b/drivers/media/usb/hdpvr/hdpvr-core.c index 304f43ef59eb..304f43ef59eb 100644 --- a/drivers/media/video/hdpvr/hdpvr-core.c +++ b/drivers/media/usb/hdpvr/hdpvr-core.c diff --git a/drivers/media/video/hdpvr/hdpvr-i2c.c b/drivers/media/usb/hdpvr/hdpvr-i2c.c index 82e819fa91c0..82e819fa91c0 100644 --- a/drivers/media/video/hdpvr/hdpvr-i2c.c +++ b/drivers/media/usb/hdpvr/hdpvr-i2c.c diff --git a/drivers/media/video/hdpvr/hdpvr-video.c b/drivers/media/usb/hdpvr/hdpvr-video.c index 0e9e156bb2aa..da6b77912222 100644 --- a/drivers/media/video/hdpvr/hdpvr-video.c +++ b/drivers/media/usb/hdpvr/hdpvr-video.c @@ -677,7 +677,7 @@ static int vidioc_enumaudio(struct file *file, void *priv, } static int vidioc_s_audio(struct file *file, void *private_data, - struct v4l2_audio *audio) + const struct v4l2_audio *audio) { struct hdpvr_fh *fh = file->private_data; struct hdpvr_device *dev = fh->dev; diff --git a/drivers/media/video/hdpvr/hdpvr.h b/drivers/media/usb/hdpvr/hdpvr.h index fea3c6926997..fea3c6926997 100644 --- a/drivers/media/video/hdpvr/hdpvr.h +++ b/drivers/media/usb/hdpvr/hdpvr.h diff --git a/drivers/media/video/pvrusb2/Kconfig b/drivers/media/usb/pvrusb2/Kconfig index 25e412ecad2c..32b11c15bb1a 100644 --- a/drivers/media/video/pvrusb2/Kconfig +++ b/drivers/media/usb/pvrusb2/Kconfig @@ -36,13 +36,13 @@ config VIDEO_PVRUSB2_DVB bool "pvrusb2 ATSC/DVB support (EXPERIMENTAL)" default y depends on VIDEO_PVRUSB2 && DVB_CORE && EXPERIMENTAL - select DVB_LGDT330X if !DVB_FE_CUSTOMISE - select DVB_S5H1409 if !DVB_FE_CUSTOMISE - select DVB_S5H1411 if !DVB_FE_CUSTOMISE - select DVB_TDA10048 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_TDA18271 if !MEDIA_TUNER_CUSTOMISE - select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMISE - select MEDIA_TUNER_TDA8290 if !MEDIA_TUNER_CUSTOMISE + select DVB_LGDT330X if MEDIA_SUBDRV_AUTOSELECT + select DVB_S5H1409 if MEDIA_SUBDRV_AUTOSELECT + select DVB_S5H1411 if MEDIA_SUBDRV_AUTOSELECT + select DVB_TDA10048 if MEDIA_SUBDRV_AUTOSELECT + select MEDIA_TUNER_TDA18271 if MEDIA_SUBDRV_AUTOSELECT + select MEDIA_TUNER_SIMPLE if MEDIA_SUBDRV_AUTOSELECT + select MEDIA_TUNER_TDA8290 if MEDIA_SUBDRV_AUTOSELECT ---help--- This option enables a DVB interface for the pvrusb2 driver. diff --git a/drivers/media/video/pvrusb2/Makefile b/drivers/media/usb/pvrusb2/Makefile index c17f37d964ad..ad705547bdce 100644 --- a/drivers/media/video/pvrusb2/Makefile +++ b/drivers/media/usb/pvrusb2/Makefile @@ -16,7 +16,7 @@ pvrusb2-objs := pvrusb2-i2c-core.o \ obj-$(CONFIG_VIDEO_PVRUSB2) += pvrusb2.o -ccflags-y += -Idrivers/media/video -ccflags-y += -Idrivers/media/common/tuners -ccflags-y += -Idrivers/media/dvb/dvb-core -ccflags-y += -Idrivers/media/dvb/frontends +ccflags-y += -Idrivers/media/i2c +ccflags-y += -Idrivers/media/tuners +ccflags-y += -Idrivers/media/dvb-core +ccflags-y += -Idrivers/media/dvb-frontends diff --git a/drivers/media/video/pvrusb2/pvrusb2-audio.c b/drivers/media/usb/pvrusb2/pvrusb2-audio.c index cc06d5e4adcc..cc06d5e4adcc 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-audio.c +++ b/drivers/media/usb/pvrusb2/pvrusb2-audio.c diff --git a/drivers/media/video/pvrusb2/pvrusb2-audio.h b/drivers/media/usb/pvrusb2/pvrusb2-audio.h index e3e63d750891..e3e63d750891 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-audio.h +++ b/drivers/media/usb/pvrusb2/pvrusb2-audio.h diff --git a/drivers/media/video/pvrusb2/pvrusb2-context.c b/drivers/media/usb/pvrusb2/pvrusb2-context.c index 7c19ff72e6b3..7c19ff72e6b3 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-context.c +++ b/drivers/media/usb/pvrusb2/pvrusb2-context.c diff --git a/drivers/media/video/pvrusb2/pvrusb2-context.h b/drivers/media/usb/pvrusb2/pvrusb2-context.h index d657e53bbfa3..d657e53bbfa3 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-context.h +++ b/drivers/media/usb/pvrusb2/pvrusb2-context.h diff --git a/drivers/media/video/pvrusb2/pvrusb2-cs53l32a.c b/drivers/media/usb/pvrusb2/pvrusb2-cs53l32a.c index 88320900dbd4..88320900dbd4 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-cs53l32a.c +++ b/drivers/media/usb/pvrusb2/pvrusb2-cs53l32a.c diff --git a/drivers/media/video/pvrusb2/pvrusb2-cs53l32a.h b/drivers/media/usb/pvrusb2/pvrusb2-cs53l32a.h index 53ba548b72a7..53ba548b72a7 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-cs53l32a.h +++ b/drivers/media/usb/pvrusb2/pvrusb2-cs53l32a.h diff --git a/drivers/media/video/pvrusb2/pvrusb2-ctrl.c b/drivers/media/usb/pvrusb2/pvrusb2-ctrl.c index 7d5a7139a45a..7d5a7139a45a 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-ctrl.c +++ b/drivers/media/usb/pvrusb2/pvrusb2-ctrl.c diff --git a/drivers/media/video/pvrusb2/pvrusb2-ctrl.h b/drivers/media/usb/pvrusb2/pvrusb2-ctrl.h index 794ff90121c7..794ff90121c7 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-ctrl.h +++ b/drivers/media/usb/pvrusb2/pvrusb2-ctrl.h diff --git a/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c b/drivers/media/usb/pvrusb2/pvrusb2-cx2584x-v4l.c index c514d0b9ffdc..c514d0b9ffdc 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c +++ b/drivers/media/usb/pvrusb2/pvrusb2-cx2584x-v4l.c diff --git a/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.h b/drivers/media/usb/pvrusb2/pvrusb2-cx2584x-v4l.h index e35c2322a08c..e35c2322a08c 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.h +++ b/drivers/media/usb/pvrusb2/pvrusb2-cx2584x-v4l.h diff --git a/drivers/media/video/pvrusb2/pvrusb2-debug.h b/drivers/media/usb/pvrusb2/pvrusb2-debug.h index be79249f8628..be79249f8628 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-debug.h +++ b/drivers/media/usb/pvrusb2/pvrusb2-debug.h diff --git a/drivers/media/video/pvrusb2/pvrusb2-debugifc.c b/drivers/media/usb/pvrusb2/pvrusb2-debugifc.c index 4279ebb811a1..4279ebb811a1 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-debugifc.c +++ b/drivers/media/usb/pvrusb2/pvrusb2-debugifc.c diff --git a/drivers/media/video/pvrusb2/pvrusb2-debugifc.h b/drivers/media/usb/pvrusb2/pvrusb2-debugifc.h index 2f8d46761cd0..2f8d46761cd0 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-debugifc.h +++ b/drivers/media/usb/pvrusb2/pvrusb2-debugifc.h diff --git a/drivers/media/video/pvrusb2/pvrusb2-devattr.c b/drivers/media/usb/pvrusb2/pvrusb2-devattr.c index d8c898278e8c..adc501d3c287 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-devattr.c +++ b/drivers/media/usb/pvrusb2/pvrusb2-devattr.c @@ -54,8 +54,9 @@ static const struct pvr2_device_client_desc pvr2_cli_29xxx[] = { { .module_id = PVR2_CLIENT_ID_DEMOD }, }; +#define PVR2_FIRMWARE_29xxx "v4l-pvrusb2-29xxx-01.fw" static const char *pvr2_fw1_names_29xxx[] = { - "v4l-pvrusb2-29xxx-01.fw", + PVR2_FIRMWARE_29xxx, }; static const struct pvr2_device_desc pvr2_device_29xxx = { @@ -87,8 +88,9 @@ static const struct pvr2_device_client_desc pvr2_cli_24xxx[] = { { .module_id = PVR2_CLIENT_ID_DEMOD }, }; +#define PVR2_FIRMWARE_24xxx "v4l-pvrusb2-24xxx-01.fw" static const char *pvr2_fw1_names_24xxx[] = { - "v4l-pvrusb2-24xxx-01.fw", + PVR2_FIRMWARE_24xxx, }; static const struct pvr2_device_desc pvr2_device_24xxx = { @@ -369,8 +371,9 @@ static const struct pvr2_device_client_desc pvr2_cli_73xxx[] = { .i2c_address_list = "\x42"}, }; +#define PVR2_FIRMWARE_73xxx "v4l-pvrusb2-73xxx-01.fw" static const char *pvr2_fw1_names_73xxx[] = { - "v4l-pvrusb2-73xxx-01.fw", + PVR2_FIRMWARE_73xxx, }; static const struct pvr2_device_desc pvr2_device_73xxx = { @@ -475,8 +478,9 @@ static const struct pvr2_dvb_props pvr2_751xx_dvb_props = { }; #endif +#define PVR2_FIRMWARE_75xxx "v4l-pvrusb2-73xxx-01.fw" static const char *pvr2_fw1_names_75xxx[] = { - "v4l-pvrusb2-73xxx-01.fw", + PVR2_FIRMWARE_75xxx, }; static const struct pvr2_device_desc pvr2_device_750xx = { @@ -556,7 +560,10 @@ struct usb_device_id pvr2_device_table[] = { }; MODULE_DEVICE_TABLE(usb, pvr2_device_table); - +MODULE_FIRMWARE(PVR2_FIRMWARE_29xxx); +MODULE_FIRMWARE(PVR2_FIRMWARE_24xxx); +MODULE_FIRMWARE(PVR2_FIRMWARE_73xxx); +MODULE_FIRMWARE(PVR2_FIRMWARE_75xxx); /* Stuff for Emacs to see, in order to encourage consistent editing style: diff --git a/drivers/media/video/pvrusb2/pvrusb2-devattr.h b/drivers/media/usb/pvrusb2/pvrusb2-devattr.h index 273c8d4b3853..273c8d4b3853 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-devattr.h +++ b/drivers/media/usb/pvrusb2/pvrusb2-devattr.h diff --git a/drivers/media/video/pvrusb2/pvrusb2-dvb.c b/drivers/media/usb/pvrusb2/pvrusb2-dvb.c index 8c95793433e7..8c95793433e7 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-dvb.c +++ b/drivers/media/usb/pvrusb2/pvrusb2-dvb.c diff --git a/drivers/media/video/pvrusb2/pvrusb2-dvb.h b/drivers/media/usb/pvrusb2/pvrusb2-dvb.h index 884ff916a352..884ff916a352 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-dvb.h +++ b/drivers/media/usb/pvrusb2/pvrusb2-dvb.h diff --git a/drivers/media/video/pvrusb2/pvrusb2-eeprom.c b/drivers/media/usb/pvrusb2/pvrusb2-eeprom.c index 9515f3a68f8f..9515f3a68f8f 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-eeprom.c +++ b/drivers/media/usb/pvrusb2/pvrusb2-eeprom.c diff --git a/drivers/media/video/pvrusb2/pvrusb2-eeprom.h b/drivers/media/usb/pvrusb2/pvrusb2-eeprom.h index cca3216f94cc..cca3216f94cc 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-eeprom.h +++ b/drivers/media/usb/pvrusb2/pvrusb2-eeprom.h diff --git a/drivers/media/video/pvrusb2/pvrusb2-encoder.c b/drivers/media/usb/pvrusb2/pvrusb2-encoder.c index e046fdaec5ae..e046fdaec5ae 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-encoder.c +++ b/drivers/media/usb/pvrusb2/pvrusb2-encoder.c diff --git a/drivers/media/video/pvrusb2/pvrusb2-encoder.h b/drivers/media/usb/pvrusb2/pvrusb2-encoder.h index 232fefbcd1ac..232fefbcd1ac 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-encoder.h +++ b/drivers/media/usb/pvrusb2/pvrusb2-encoder.h diff --git a/drivers/media/video/pvrusb2/pvrusb2-fx2-cmd.h b/drivers/media/usb/pvrusb2/pvrusb2-fx2-cmd.h index 614755ea2ea3..614755ea2ea3 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-fx2-cmd.h +++ b/drivers/media/usb/pvrusb2/pvrusb2-fx2-cmd.h diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h b/drivers/media/usb/pvrusb2/pvrusb2-hdw-internal.h index 036952f2a3cb..036952f2a3cb 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h +++ b/drivers/media/usb/pvrusb2/pvrusb2-hdw-internal.h diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/usb/pvrusb2/pvrusb2-hdw.c index fb828ba1dbbe..fb828ba1dbbe 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/usb/pvrusb2/pvrusb2-hdw.c diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.h b/drivers/media/usb/pvrusb2/pvrusb2-hdw.h index 8060fc666eeb..8060fc666eeb 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.h +++ b/drivers/media/usb/pvrusb2/pvrusb2-hdw.h diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c b/drivers/media/usb/pvrusb2/pvrusb2-i2c-core.c index 885ce11f222d..885ce11f222d 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c +++ b/drivers/media/usb/pvrusb2/pvrusb2-i2c-core.c diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.h b/drivers/media/usb/pvrusb2/pvrusb2-i2c-core.h index 6a75769200bd..6a75769200bd 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.h +++ b/drivers/media/usb/pvrusb2/pvrusb2-i2c-core.h diff --git a/drivers/media/video/pvrusb2/pvrusb2-io.c b/drivers/media/usb/pvrusb2/pvrusb2-io.c index 20b6ae0bb40d..20b6ae0bb40d 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-io.c +++ b/drivers/media/usb/pvrusb2/pvrusb2-io.c diff --git a/drivers/media/video/pvrusb2/pvrusb2-io.h b/drivers/media/usb/pvrusb2/pvrusb2-io.h index afb7e87c0394..afb7e87c0394 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-io.h +++ b/drivers/media/usb/pvrusb2/pvrusb2-io.h diff --git a/drivers/media/video/pvrusb2/pvrusb2-ioread.c b/drivers/media/usb/pvrusb2/pvrusb2-ioread.c index bba6115c9ae8..bba6115c9ae8 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-ioread.c +++ b/drivers/media/usb/pvrusb2/pvrusb2-ioread.c diff --git a/drivers/media/video/pvrusb2/pvrusb2-ioread.h b/drivers/media/usb/pvrusb2/pvrusb2-ioread.h index 100e0780e1aa..100e0780e1aa 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-ioread.h +++ b/drivers/media/usb/pvrusb2/pvrusb2-ioread.h diff --git a/drivers/media/video/pvrusb2/pvrusb2-main.c b/drivers/media/usb/pvrusb2/pvrusb2-main.c index c1d9bb61cd77..c1d9bb61cd77 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-main.c +++ b/drivers/media/usb/pvrusb2/pvrusb2-main.c diff --git a/drivers/media/video/pvrusb2/pvrusb2-std.c b/drivers/media/usb/pvrusb2/pvrusb2-std.c index 453627b07833..453627b07833 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-std.c +++ b/drivers/media/usb/pvrusb2/pvrusb2-std.c diff --git a/drivers/media/video/pvrusb2/pvrusb2-std.h b/drivers/media/usb/pvrusb2/pvrusb2-std.h index a35c53d0b320..a35c53d0b320 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-std.h +++ b/drivers/media/usb/pvrusb2/pvrusb2-std.h diff --git a/drivers/media/video/pvrusb2/pvrusb2-sysfs.c b/drivers/media/usb/pvrusb2/pvrusb2-sysfs.c index 6ef1335b2858..6ef1335b2858 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-sysfs.c +++ b/drivers/media/usb/pvrusb2/pvrusb2-sysfs.c diff --git a/drivers/media/video/pvrusb2/pvrusb2-sysfs.h b/drivers/media/usb/pvrusb2/pvrusb2-sysfs.h index 6d875bfe7991..6d875bfe7991 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-sysfs.h +++ b/drivers/media/usb/pvrusb2/pvrusb2-sysfs.h diff --git a/drivers/media/video/pvrusb2/pvrusb2-util.h b/drivers/media/usb/pvrusb2/pvrusb2-util.h index 92b75544ee2e..92b75544ee2e 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-util.h +++ b/drivers/media/usb/pvrusb2/pvrusb2-util.h diff --git a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c b/drivers/media/usb/pvrusb2/pvrusb2-v4l2.c index f344aed32a93..db249cad3cd9 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c +++ b/drivers/media/usb/pvrusb2/pvrusb2-v4l2.c @@ -333,7 +333,7 @@ static int pvr2_g_audio(struct file *file, void *priv, struct v4l2_audio *vin) return 0; } -static int pvr2_s_audio(struct file *file, void *priv, struct v4l2_audio *vout) +static int pvr2_s_audio(struct file *file, void *priv, const struct v4l2_audio *vout) { if (vout->index) return -EINVAL; @@ -760,7 +760,7 @@ static int pvr2_g_crop(struct file *file, void *priv, struct v4l2_crop *crop) return 0; } -static int pvr2_s_crop(struct file *file, void *priv, struct v4l2_crop *crop) +static int pvr2_s_crop(struct file *file, void *priv, const struct v4l2_crop *crop) { struct pvr2_v4l2_fh *fh = file->private_data; struct pvr2_hdw *hdw = fh->channel.mc_head->hdw; diff --git a/drivers/media/video/pvrusb2/pvrusb2-v4l2.h b/drivers/media/usb/pvrusb2/pvrusb2-v4l2.h index 34c011a7b107..34c011a7b107 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-v4l2.h +++ b/drivers/media/usb/pvrusb2/pvrusb2-v4l2.h diff --git a/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c b/drivers/media/usb/pvrusb2/pvrusb2-video-v4l.c index 2e205c99eb96..2e205c99eb96 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c +++ b/drivers/media/usb/pvrusb2/pvrusb2-video-v4l.c diff --git a/drivers/media/video/pvrusb2/pvrusb2-video-v4l.h b/drivers/media/usb/pvrusb2/pvrusb2-video-v4l.h index 3b0bd5db602b..3b0bd5db602b 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-video-v4l.h +++ b/drivers/media/usb/pvrusb2/pvrusb2-video-v4l.h diff --git a/drivers/media/video/pvrusb2/pvrusb2-wm8775.c b/drivers/media/usb/pvrusb2/pvrusb2-wm8775.c index 3ac8d751a5c0..3ac8d751a5c0 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-wm8775.c +++ b/drivers/media/usb/pvrusb2/pvrusb2-wm8775.c diff --git a/drivers/media/video/pvrusb2/pvrusb2-wm8775.h b/drivers/media/usb/pvrusb2/pvrusb2-wm8775.h index 0577bc7246fb..0577bc7246fb 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-wm8775.h +++ b/drivers/media/usb/pvrusb2/pvrusb2-wm8775.h diff --git a/drivers/media/video/pvrusb2/pvrusb2.h b/drivers/media/usb/pvrusb2/pvrusb2.h index 240de9b35661..240de9b35661 100644 --- a/drivers/media/video/pvrusb2/pvrusb2.h +++ b/drivers/media/usb/pvrusb2/pvrusb2.h diff --git a/drivers/media/video/pwc/Kconfig b/drivers/media/usb/pwc/Kconfig index d63d0a850035..d63d0a850035 100644 --- a/drivers/media/video/pwc/Kconfig +++ b/drivers/media/usb/pwc/Kconfig diff --git a/drivers/media/video/pwc/Makefile b/drivers/media/usb/pwc/Makefile index f5c8ec261e87..d7fdbcb9edd3 100644 --- a/drivers/media/video/pwc/Makefile +++ b/drivers/media/usb/pwc/Makefile @@ -1,4 +1,4 @@ -pwc-objs := pwc-if.o pwc-misc.o pwc-ctrl.o pwc-v4l.o pwc-uncompress.o +pwc-objs += pwc-if.o pwc-misc.o pwc-ctrl.o pwc-v4l.o pwc-uncompress.o pwc-objs += pwc-dec1.o pwc-dec23.o pwc-kiara.o pwc-timon.o obj-$(CONFIG_USB_PWC) += pwc.o diff --git a/drivers/media/video/pwc/philips.txt b/drivers/media/usb/pwc/philips.txt index d38dd791511e..d38dd791511e 100644 --- a/drivers/media/video/pwc/philips.txt +++ b/drivers/media/usb/pwc/philips.txt diff --git a/drivers/media/video/pwc/pwc-ctrl.c b/drivers/media/usb/pwc/pwc-ctrl.c index 1f506fde97d0..1f506fde97d0 100644 --- a/drivers/media/video/pwc/pwc-ctrl.c +++ b/drivers/media/usb/pwc/pwc-ctrl.c diff --git a/drivers/media/video/pwc/pwc-dec1.c b/drivers/media/usb/pwc/pwc-dec1.c index e899036aadf4..e899036aadf4 100644 --- a/drivers/media/video/pwc/pwc-dec1.c +++ b/drivers/media/usb/pwc/pwc-dec1.c diff --git a/drivers/media/video/pwc/pwc-dec1.h b/drivers/media/usb/pwc/pwc-dec1.h index c565ef8f52fb..c565ef8f52fb 100644 --- a/drivers/media/video/pwc/pwc-dec1.h +++ b/drivers/media/usb/pwc/pwc-dec1.h diff --git a/drivers/media/video/pwc/pwc-dec23.c b/drivers/media/usb/pwc/pwc-dec23.c index 3792fedff951..3792fedff951 100644 --- a/drivers/media/video/pwc/pwc-dec23.c +++ b/drivers/media/usb/pwc/pwc-dec23.c diff --git a/drivers/media/video/pwc/pwc-dec23.h b/drivers/media/usb/pwc/pwc-dec23.h index c655b1c1e6a9..c655b1c1e6a9 100644 --- a/drivers/media/video/pwc/pwc-dec23.h +++ b/drivers/media/usb/pwc/pwc-dec23.h diff --git a/drivers/media/video/pwc/pwc-if.c b/drivers/media/usb/pwc/pwc-if.c index de7c7ba99ef4..42e36bac4d72 100644 --- a/drivers/media/video/pwc/pwc-if.c +++ b/drivers/media/usb/pwc/pwc-if.c @@ -994,7 +994,6 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id pdev->power_save = my_power_save; /* Init videobuf2 queue structure */ - memset(&pdev->vb_queue, 0, sizeof(pdev->vb_queue)); pdev->vb_queue.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; pdev->vb_queue.io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ; pdev->vb_queue.drv_priv = pdev; @@ -1127,7 +1126,7 @@ static void usb_pwc_disconnect(struct usb_interface *intf) v4l2_device_disconnect(&pdev->v4l2_dev); video_unregister_device(&pdev->vdev); mutex_unlock(&pdev->v4l2_lock); - mutex_unlock(pdev->vb_queue.lock); + mutex_unlock(&pdev->vb_queue_lock); #ifdef CONFIG_USB_PWC_INPUT_EVDEV if (pdev->button_dev) diff --git a/drivers/media/video/pwc/pwc-kiara.c b/drivers/media/usb/pwc/pwc-kiara.c index e5f4fd817125..e5f4fd817125 100644 --- a/drivers/media/video/pwc/pwc-kiara.c +++ b/drivers/media/usb/pwc/pwc-kiara.c diff --git a/drivers/media/video/pwc/pwc-kiara.h b/drivers/media/usb/pwc/pwc-kiara.h index 8e02b7ac2139..8e02b7ac2139 100644 --- a/drivers/media/video/pwc/pwc-kiara.h +++ b/drivers/media/usb/pwc/pwc-kiara.h diff --git a/drivers/media/video/pwc/pwc-misc.c b/drivers/media/usb/pwc/pwc-misc.c index 9be5adffa874..9be5adffa874 100644 --- a/drivers/media/video/pwc/pwc-misc.c +++ b/drivers/media/usb/pwc/pwc-misc.c diff --git a/drivers/media/video/pwc/pwc-nala.h b/drivers/media/usb/pwc/pwc-nala.h index 168c73ef75d8..168c73ef75d8 100644 --- a/drivers/media/video/pwc/pwc-nala.h +++ b/drivers/media/usb/pwc/pwc-nala.h diff --git a/drivers/media/video/pwc/pwc-timon.c b/drivers/media/usb/pwc/pwc-timon.c index c56c174b161c..c56c174b161c 100644 --- a/drivers/media/video/pwc/pwc-timon.c +++ b/drivers/media/usb/pwc/pwc-timon.c diff --git a/drivers/media/video/pwc/pwc-timon.h b/drivers/media/usb/pwc/pwc-timon.h index 270c5b9010f6..270c5b9010f6 100644 --- a/drivers/media/video/pwc/pwc-timon.h +++ b/drivers/media/usb/pwc/pwc-timon.h diff --git a/drivers/media/video/pwc/pwc-uncompress.c b/drivers/media/usb/pwc/pwc-uncompress.c index b65903fbcf0d..b65903fbcf0d 100644 --- a/drivers/media/video/pwc/pwc-uncompress.c +++ b/drivers/media/usb/pwc/pwc-uncompress.c diff --git a/drivers/media/video/pwc/pwc-v4l.c b/drivers/media/usb/pwc/pwc-v4l.c index 545e9bbdeede..545e9bbdeede 100644 --- a/drivers/media/video/pwc/pwc-v4l.c +++ b/drivers/media/usb/pwc/pwc-v4l.c diff --git a/drivers/media/video/pwc/pwc.h b/drivers/media/usb/pwc/pwc.h index 7a6a0d39c2c6..7a6a0d39c2c6 100644 --- a/drivers/media/video/pwc/pwc.h +++ b/drivers/media/usb/pwc/pwc.h diff --git a/drivers/media/usb/s2255/Kconfig b/drivers/media/usb/s2255/Kconfig new file mode 100644 index 000000000000..7e8ee1f864ab --- /dev/null +++ b/drivers/media/usb/s2255/Kconfig @@ -0,0 +1,9 @@ +config USB_S2255 + tristate "USB Sensoray 2255 video capture device" + depends on VIDEO_V4L2 + select VIDEOBUF_VMALLOC + default n + help + Say Y here if you want support for the Sensoray 2255 USB device. + This driver can be compiled as a module, called s2255drv. + diff --git a/drivers/media/usb/s2255/Makefile b/drivers/media/usb/s2255/Makefile new file mode 100644 index 000000000000..197d0bb2adfd --- /dev/null +++ b/drivers/media/usb/s2255/Makefile @@ -0,0 +1,2 @@ +obj-$(CONFIG_USB_S2255) += s2255drv.o + diff --git a/drivers/media/video/s2255drv.c b/drivers/media/usb/s2255/s2255drv.c index 95007dda0c93..2191f6ddf9e7 100644 --- a/drivers/media/video/s2255drv.c +++ b/drivers/media/usb/s2255/s2255drv.c @@ -258,7 +258,6 @@ struct s2255_dev { atomic_t num_channels; int frames; struct mutex lock; /* channels[].vdev.lock */ - struct mutex open_lock; struct usb_device *udev; struct usb_interface *interface; u8 read_endpoint; @@ -1557,7 +1556,7 @@ static int vidioc_g_jpegcomp(struct file *file, void *priv, } static int vidioc_s_jpegcomp(struct file *file, void *priv, - struct v4l2_jpegcompression *jc) + const struct v4l2_jpegcompression *jc) { struct s2255_fh *fh = priv; struct s2255_channel *channel = fh->channel; @@ -1684,7 +1683,7 @@ static int vidioc_enum_frameintervals(struct file *file, void *priv, return 0; } -static int s2255_open(struct file *file) +static int __s2255_open(struct file *file) { struct video_device *vdev = video_devdata(file); struct s2255_channel *channel = video_drvdata(file); @@ -1694,16 +1693,9 @@ static int s2255_open(struct file *file) int state; dprintk(1, "s2255: open called (dev=%s)\n", video_device_node_name(vdev)); - /* - * open lock necessary to prevent multiple instances - * of v4l-conf (or other programs) from simultaneously - * reloading firmware. - */ - mutex_lock(&dev->open_lock); state = atomic_read(&dev->fw_data->fw_state); switch (state) { case S2255_FW_DISCONNECTING: - mutex_unlock(&dev->open_lock); return -ENODEV; case S2255_FW_FAILED: s2255_dev_err(&dev->udev->dev, @@ -1742,11 +1734,9 @@ static int s2255_open(struct file *file) break; case S2255_FW_FAILED: printk(KERN_INFO "2255 firmware load failed.\n"); - mutex_unlock(&dev->open_lock); return -ENODEV; case S2255_FW_DISCONNECTING: printk(KERN_INFO "%s: disconnecting\n", __func__); - mutex_unlock(&dev->open_lock); return -ENODEV; case S2255_FW_LOADED_DSPWAIT: case S2255_FW_NOTLOADED: @@ -1760,14 +1750,11 @@ static int s2255_open(struct file *file) */ atomic_set(&dev->fw_data->fw_state, S2255_FW_FAILED); - mutex_unlock(&dev->open_lock); return -EAGAIN; default: printk(KERN_INFO "%s: unknown state\n", __func__); - mutex_unlock(&dev->open_lock); return -EFAULT; } - mutex_unlock(&dev->open_lock); /* allocate + initialize per filehandle data */ fh = kzalloc(sizeof(*fh), GFP_KERNEL); if (NULL == fh) @@ -1798,16 +1785,30 @@ static int s2255_open(struct file *file) return 0; } +static int s2255_open(struct file *file) +{ + struct video_device *vdev = video_devdata(file); + int ret; + + if (mutex_lock_interruptible(vdev->lock)) + return -ERESTARTSYS; + ret = __s2255_open(file); + mutex_unlock(vdev->lock); + return ret; +} static unsigned int s2255_poll(struct file *file, struct poll_table_struct *wait) { struct s2255_fh *fh = file->private_data; + struct s2255_dev *dev = fh->dev; int rc; dprintk(100, "%s\n", __func__); if (V4L2_BUF_TYPE_VIDEO_CAPTURE != fh->type) return POLLERR; + mutex_lock(&dev->lock); rc = videobuf_poll_stream(file, &fh->vb_vidq, wait); + mutex_unlock(&dev->lock); return rc; } @@ -1827,7 +1828,6 @@ static void s2255_destroy(struct s2255_dev *dev) kfree(dev->fw_data); /* reset the DSP so firmware can be reloaded next time */ s2255_reset_dsppower(dev); - mutex_destroy(&dev->open_lock); mutex_destroy(&dev->lock); usb_put_dev(dev->udev); v4l2_device_unregister(&dev->v4l2_dev); @@ -1843,6 +1843,7 @@ static int s2255_release(struct file *file) struct s2255_channel *channel = fh->channel; if (!dev) return -ENODEV; + mutex_lock(&dev->lock); /* turn off stream */ if (res_check(fh)) { if (channel->b_acquire) @@ -1851,6 +1852,7 @@ static int s2255_release(struct file *file) res_free(fh); } videobuf_mmap_free(&fh->vb_vidq); + mutex_unlock(&dev->lock); dprintk(1, "%s (dev=%s)\n", __func__, video_device_node_name(vdev)); kfree(fh); return 0; @@ -1859,12 +1861,17 @@ static int s2255_release(struct file *file) static int s2255_mmap_v4l(struct file *file, struct vm_area_struct *vma) { struct s2255_fh *fh = file->private_data; + struct s2255_dev *dev; int ret; if (!fh) return -ENODEV; + dev = fh->dev; dprintk(4, "%s, vma=0x%08lx\n", __func__, (unsigned long)vma); + if (mutex_lock_interruptible(&dev->lock)) + return -ERESTARTSYS; ret = videobuf_mmap_mapper(&fh->vb_vidq, vma); + mutex_unlock(&dev->lock); dprintk(4, "%s vma start=0x%08lx, size=%ld, ret=%d\n", __func__, (unsigned long)vma->vm_start, (unsigned long)vma->vm_end - (unsigned long)vma->vm_start, ret); @@ -1944,10 +1951,6 @@ static int s2255_probe_v4l(struct s2255_dev *dev) /* register 4 video devices */ channel->vdev = template; channel->vdev.lock = &dev->lock; - /* Locking in file operations other than ioctl should be done - by the driver, not the V4L2 core. - This driver needs auditing so that this flag can be removed. */ - set_bit(V4L2_FL_LOCK_ALL_FOPS, &channel->vdev.flags); channel->vdev.v4l2_dev = &dev->v4l2_dev; video_set_drvdata(&channel->vdev, channel); if (video_nr == -1) @@ -2535,7 +2538,6 @@ static int s2255_probe(struct usb_interface *interface, if (!dev->fw_data) goto errorFWDATA1; mutex_init(&dev->lock); - mutex_init(&dev->open_lock); /* grab usb_device and save it */ dev->udev = usb_get_dev(interface_to_usbdev(interface)); if (dev->udev == NULL) { @@ -2637,7 +2639,6 @@ errorEP: usb_put_dev(dev->udev); errorUDEV: kfree(dev->fw_data); - mutex_destroy(&dev->open_lock); mutex_destroy(&dev->lock); errorFWDATA1: kfree(dev); diff --git a/drivers/media/usb/siano/Kconfig b/drivers/media/usb/siano/Kconfig new file mode 100644 index 000000000000..3c76e62d820d --- /dev/null +++ b/drivers/media/usb/siano/Kconfig @@ -0,0 +1,10 @@ +# +# Siano Mobile Silicon Digital TV device configuration +# + +config SMS_USB_DRV + tristate "Siano SMS1xxx based MDTV receiver" + depends on DVB_CORE && RC_CORE && HAS_DMA + ---help--- + Choose if you would like to have Siano's support for USB interface + diff --git a/drivers/media/usb/siano/Makefile b/drivers/media/usb/siano/Makefile new file mode 100644 index 000000000000..758b6a090c59 --- /dev/null +++ b/drivers/media/usb/siano/Makefile @@ -0,0 +1,6 @@ +obj-$(CONFIG_SMS_USB_DRV) += smsusb.o + +ccflags-y += -Idrivers/media/dvb-core +ccflags-y += -Idrivers/media/common/siano +ccflags-y += $(extra-cflags-y) $(extra-cflags-m) + diff --git a/drivers/media/dvb/siano/smsusb.c b/drivers/media/usb/siano/smsusb.c index aac622200e99..aac622200e99 100644 --- a/drivers/media/dvb/siano/smsusb.c +++ b/drivers/media/usb/siano/smsusb.c diff --git a/drivers/media/video/sn9c102/Kconfig b/drivers/media/usb/sn9c102/Kconfig index 6ebaf2940d06..6ebaf2940d06 100644 --- a/drivers/media/video/sn9c102/Kconfig +++ b/drivers/media/usb/sn9c102/Kconfig diff --git a/drivers/media/video/sn9c102/Makefile b/drivers/media/usb/sn9c102/Makefile index 7ecd5a90c7c9..7ecd5a90c7c9 100644 --- a/drivers/media/video/sn9c102/Makefile +++ b/drivers/media/usb/sn9c102/Makefile diff --git a/drivers/media/video/sn9c102/sn9c102.h b/drivers/media/usb/sn9c102/sn9c102.h index 2bc153e869be..2bc153e869be 100644 --- a/drivers/media/video/sn9c102/sn9c102.h +++ b/drivers/media/usb/sn9c102/sn9c102.h diff --git a/drivers/media/video/sn9c102/sn9c102_config.h b/drivers/media/usb/sn9c102/sn9c102_config.h index 0f4e0378b071..0f4e0378b071 100644 --- a/drivers/media/video/sn9c102/sn9c102_config.h +++ b/drivers/media/usb/sn9c102/sn9c102_config.h diff --git a/drivers/media/video/sn9c102/sn9c102_core.c b/drivers/media/usb/sn9c102/sn9c102_core.c index 19ea780b16ff..19ea780b16ff 100644 --- a/drivers/media/video/sn9c102/sn9c102_core.c +++ b/drivers/media/usb/sn9c102/sn9c102_core.c diff --git a/drivers/media/video/sn9c102/sn9c102_devtable.h b/drivers/media/usb/sn9c102/sn9c102_devtable.h index b3d2cc729657..b3d2cc729657 100644 --- a/drivers/media/video/sn9c102/sn9c102_devtable.h +++ b/drivers/media/usb/sn9c102/sn9c102_devtable.h diff --git a/drivers/media/video/sn9c102/sn9c102_hv7131d.c b/drivers/media/usb/sn9c102/sn9c102_hv7131d.c index 2dce5c908c8e..2dce5c908c8e 100644 --- a/drivers/media/video/sn9c102/sn9c102_hv7131d.c +++ b/drivers/media/usb/sn9c102/sn9c102_hv7131d.c diff --git a/drivers/media/video/sn9c102/sn9c102_hv7131r.c b/drivers/media/usb/sn9c102/sn9c102_hv7131r.c index 4295887ff609..4295887ff609 100644 --- a/drivers/media/video/sn9c102/sn9c102_hv7131r.c +++ b/drivers/media/usb/sn9c102/sn9c102_hv7131r.c diff --git a/drivers/media/video/sn9c102/sn9c102_mi0343.c b/drivers/media/usb/sn9c102/sn9c102_mi0343.c index 1f5b09bec89c..1f5b09bec89c 100644 --- a/drivers/media/video/sn9c102/sn9c102_mi0343.c +++ b/drivers/media/usb/sn9c102/sn9c102_mi0343.c diff --git a/drivers/media/video/sn9c102/sn9c102_mi0360.c b/drivers/media/usb/sn9c102/sn9c102_mi0360.c index d973fc1973d9..d973fc1973d9 100644 --- a/drivers/media/video/sn9c102/sn9c102_mi0360.c +++ b/drivers/media/usb/sn9c102/sn9c102_mi0360.c diff --git a/drivers/media/video/sn9c102/sn9c102_mt9v111.c b/drivers/media/usb/sn9c102/sn9c102_mt9v111.c index 95986eb492e4..95986eb492e4 100644 --- a/drivers/media/video/sn9c102/sn9c102_mt9v111.c +++ b/drivers/media/usb/sn9c102/sn9c102_mt9v111.c diff --git a/drivers/media/video/sn9c102/sn9c102_ov7630.c b/drivers/media/usb/sn9c102/sn9c102_ov7630.c index 803712c29f02..803712c29f02 100644 --- a/drivers/media/video/sn9c102/sn9c102_ov7630.c +++ b/drivers/media/usb/sn9c102/sn9c102_ov7630.c diff --git a/drivers/media/video/sn9c102/sn9c102_ov7660.c b/drivers/media/usb/sn9c102/sn9c102_ov7660.c index 7977795d342b..7977795d342b 100644 --- a/drivers/media/video/sn9c102/sn9c102_ov7660.c +++ b/drivers/media/usb/sn9c102/sn9c102_ov7660.c diff --git a/drivers/media/video/sn9c102/sn9c102_pas106b.c b/drivers/media/usb/sn9c102/sn9c102_pas106b.c index 81cd969c1b7b..81cd969c1b7b 100644 --- a/drivers/media/video/sn9c102/sn9c102_pas106b.c +++ b/drivers/media/usb/sn9c102/sn9c102_pas106b.c diff --git a/drivers/media/video/sn9c102/sn9c102_pas202bcb.c b/drivers/media/usb/sn9c102/sn9c102_pas202bcb.c index 2e86fdc86989..2e86fdc86989 100644 --- a/drivers/media/video/sn9c102/sn9c102_pas202bcb.c +++ b/drivers/media/usb/sn9c102/sn9c102_pas202bcb.c diff --git a/drivers/media/video/sn9c102/sn9c102_sensor.h b/drivers/media/usb/sn9c102/sn9c102_sensor.h index 3679970dba2c..3679970dba2c 100644 --- a/drivers/media/video/sn9c102/sn9c102_sensor.h +++ b/drivers/media/usb/sn9c102/sn9c102_sensor.h diff --git a/drivers/media/video/sn9c102/sn9c102_tas5110c1b.c b/drivers/media/usb/sn9c102/sn9c102_tas5110c1b.c index 04cdfdde8564..04cdfdde8564 100644 --- a/drivers/media/video/sn9c102/sn9c102_tas5110c1b.c +++ b/drivers/media/usb/sn9c102/sn9c102_tas5110c1b.c diff --git a/drivers/media/video/sn9c102/sn9c102_tas5110d.c b/drivers/media/usb/sn9c102/sn9c102_tas5110d.c index 9372e6f9fcff..9372e6f9fcff 100644 --- a/drivers/media/video/sn9c102/sn9c102_tas5110d.c +++ b/drivers/media/usb/sn9c102/sn9c102_tas5110d.c diff --git a/drivers/media/video/sn9c102/sn9c102_tas5130d1b.c b/drivers/media/usb/sn9c102/sn9c102_tas5130d1b.c index a30bbc4389f5..a30bbc4389f5 100644 --- a/drivers/media/video/sn9c102/sn9c102_tas5130d1b.c +++ b/drivers/media/usb/sn9c102/sn9c102_tas5130d1b.c diff --git a/drivers/media/usb/stk1160/Kconfig b/drivers/media/usb/stk1160/Kconfig new file mode 100644 index 000000000000..1c3a1ec00237 --- /dev/null +++ b/drivers/media/usb/stk1160/Kconfig @@ -0,0 +1,20 @@ +config VIDEO_STK1160 + tristate "STK1160 USB video capture support" + depends on VIDEO_DEV && I2C + select VIDEOBUF2_VMALLOC + select VIDEO_SAA711X + + ---help--- + This is a video4linux driver for STK1160 based video capture devices. + + To compile this driver as a module, choose M here: the + module will be called stk1160 + +config VIDEO_STK1160_AC97 + bool "STK1160 AC97 codec support" + depends on VIDEO_STK1160 && SND + select SND_AC97_CODEC + + ---help--- + Enables AC97 codec support for stk1160 driver. +. diff --git a/drivers/media/usb/stk1160/Makefile b/drivers/media/usb/stk1160/Makefile new file mode 100644 index 000000000000..dfe3e90ff392 --- /dev/null +++ b/drivers/media/usb/stk1160/Makefile @@ -0,0 +1,11 @@ +obj-stk1160-ac97-$(CONFIG_VIDEO_STK1160_AC97) := stk1160-ac97.o + +stk1160-y := stk1160-core.o \ + stk1160-v4l.o \ + stk1160-video.o \ + stk1160-i2c.o \ + $(obj-stk1160-ac97-y) + +obj-$(CONFIG_VIDEO_STK1160) += stk1160.o + +ccflags-y += -Idrivers/media/i2c diff --git a/drivers/media/usb/stk1160/stk1160-ac97.c b/drivers/media/usb/stk1160/stk1160-ac97.c new file mode 100644 index 000000000000..c8583c262c3d --- /dev/null +++ b/drivers/media/usb/stk1160/stk1160-ac97.c @@ -0,0 +1,152 @@ +/* + * STK1160 driver + * + * Copyright (C) 2012 Ezequiel Garcia + * <elezegarcia--a.t--gmail.com> + * + * Based on Easycap driver by R.M. Thomas + * Copyright (C) 2010 R.M. Thomas + * <rmthomas--a.t--sciolus.org> + * + * 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. + * + */ + +#include <linux/module.h> +#include <sound/core.h> +#include <sound/initval.h> +#include <sound/ac97_codec.h> + +#include "stk1160.h" +#include "stk1160-reg.h" + +static struct snd_ac97 *stk1160_ac97; + +static void stk1160_write_ac97(struct snd_ac97 *ac97, u16 reg, u16 value) +{ + struct stk1160 *dev = ac97->private_data; + + /* Set codec register address */ + stk1160_write_reg(dev, STK1160_AC97_ADDR, reg); + + /* Set codec command */ + stk1160_write_reg(dev, STK1160_AC97_CMD, value & 0xff); + stk1160_write_reg(dev, STK1160_AC97_CMD + 1, (value & 0xff00) >> 8); + + /* + * Set command write bit to initiate write operation. + * The bit will be cleared when transfer is done. + */ + stk1160_write_reg(dev, STK1160_AC97CTL_0, 0x8c); +} + +static u16 stk1160_read_ac97(struct snd_ac97 *ac97, u16 reg) +{ + struct stk1160 *dev = ac97->private_data; + u8 vall = 0; + u8 valh = 0; + + /* Set codec register address */ + stk1160_write_reg(dev, STK1160_AC97_ADDR, reg); + + /* + * Set command read bit to initiate read operation. + * The bit will be cleared when transfer is done. + */ + stk1160_write_reg(dev, STK1160_AC97CTL_0, 0x8b); + + /* Retrieve register value */ + stk1160_read_reg(dev, STK1160_AC97_CMD, &vall); + stk1160_read_reg(dev, STK1160_AC97_CMD + 1, &valh); + + return (valh << 8) | vall; +} + +static void stk1160_reset_ac97(struct snd_ac97 *ac97) +{ + struct stk1160 *dev = ac97->private_data; + /* Two-step reset AC97 interface and hardware codec */ + stk1160_write_reg(dev, STK1160_AC97CTL_0, 0x94); + stk1160_write_reg(dev, STK1160_AC97CTL_0, 0x88); + + /* Set 16-bit audio data and choose L&R channel*/ + stk1160_write_reg(dev, STK1160_AC97CTL_1 + 2, 0x01); +} + +static struct snd_ac97_bus_ops stk1160_ac97_ops = { + .read = stk1160_read_ac97, + .write = stk1160_write_ac97, + .reset = stk1160_reset_ac97, +}; + +int stk1160_ac97_register(struct stk1160 *dev) +{ + struct snd_card *card = NULL; + struct snd_ac97_bus *ac97_bus; + struct snd_ac97_template ac97_template; + int rc; + + /* + * Just want a card to access ac96 controls, + * the actual capture interface will be handled by snd-usb-audio + */ + rc = snd_card_create(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1, + THIS_MODULE, 0, &card); + if (rc < 0) + return rc; + + snd_card_set_dev(card, dev->dev); + + /* TODO: I'm not sure where should I get these names :-( */ + snprintf(card->shortname, sizeof(card->shortname), + "stk1160-mixer"); + snprintf(card->longname, sizeof(card->longname), + "stk1160 ac97 codec mixer control"); + strncpy(card->driver, dev->dev->driver->name, sizeof(card->driver)); + + rc = snd_ac97_bus(card, 0, &stk1160_ac97_ops, NULL, &ac97_bus); + if (rc) + goto err; + + /* We must set private_data before calling snd_ac97_mixer */ + memset(&ac97_template, 0, sizeof(ac97_template)); + ac97_template.private_data = dev; + ac97_template.scaps = AC97_SCAP_SKIP_MODEM; + rc = snd_ac97_mixer(ac97_bus, &ac97_template, &stk1160_ac97); + if (rc) + goto err; + + dev->snd_card = card; + rc = snd_card_register(card); + if (rc) + goto err; + + return 0; + +err: + dev->snd_card = NULL; + snd_card_free(card); + return rc; +} + +int stk1160_ac97_unregister(struct stk1160 *dev) +{ + struct snd_card *card = dev->snd_card; + + /* + * We need to check usb_device, + * because ac97 release attempts to communicate with codec + */ + if (card && dev->udev) + snd_card_free(card); + + return 0; +} diff --git a/drivers/media/usb/stk1160/stk1160-core.c b/drivers/media/usb/stk1160/stk1160-core.c new file mode 100644 index 000000000000..b62740846061 --- /dev/null +++ b/drivers/media/usb/stk1160/stk1160-core.c @@ -0,0 +1,430 @@ +/* + * STK1160 driver + * + * Copyright (C) 2012 Ezequiel Garcia + * <elezegarcia--a.t--gmail.com> + * + * Based on Easycap driver by R.M. Thomas + * Copyright (C) 2010 R.M. Thomas + * <rmthomas--a.t--sciolus.org> + * + * 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. + * + * TODO: + * + * 1. (Try to) detect if we must register ac97 mixer + * 2. Support stream at lower speed: lower frame rate or lower frame size. + * + */ + +#include <linux/module.h> +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/errno.h> +#include <linux/slab.h> + +#include <linux/usb.h> +#include <linux/mm.h> +#include <linux/vmalloc.h> +#include <media/saa7115.h> + +#include "stk1160.h" +#include "stk1160-reg.h" + +static unsigned int input; +module_param(input, int, 0644); +MODULE_PARM_DESC(input, "Set default input"); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Ezequiel Garcia"); +MODULE_DESCRIPTION("STK1160 driver"); + +/* Devices supported by this driver */ +static struct usb_device_id stk1160_id_table[] = { + { USB_DEVICE(0x05e1, 0x0408) }, + { } +}; +MODULE_DEVICE_TABLE(usb, stk1160_id_table); + +/* saa7113 I2C address */ +static unsigned short saa7113_addrs[] = { + 0x4a >> 1, + I2C_CLIENT_END +}; + +/* + * Read/Write stk registers + */ +int stk1160_read_reg(struct stk1160 *dev, u16 reg, u8 *value) +{ + int ret; + int pipe = usb_rcvctrlpipe(dev->udev, 0); + + *value = 0; + ret = usb_control_msg(dev->udev, pipe, 0x00, + USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + 0x00, reg, value, sizeof(u8), HZ); + if (ret < 0) { + stk1160_err("read failed on reg 0x%x (%d)\n", + reg, ret); + return ret; + } + + return 0; +} + +int stk1160_write_reg(struct stk1160 *dev, u16 reg, u16 value) +{ + int ret; + int pipe = usb_sndctrlpipe(dev->udev, 0); + + ret = usb_control_msg(dev->udev, pipe, 0x01, + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + value, reg, NULL, 0, HZ); + if (ret < 0) { + stk1160_err("write failed on reg 0x%x (%d)\n", + reg, ret); + return ret; + } + + return 0; +} + +void stk1160_select_input(struct stk1160 *dev) +{ + static const u8 gctrl[] = { + 0x98, 0x90, 0x88, 0x80 + }; + + if (dev->ctl_input < ARRAY_SIZE(gctrl)) + stk1160_write_reg(dev, STK1160_GCTRL, gctrl[dev->ctl_input]); +} + +/* TODO: We should break this into pieces */ +static void stk1160_reg_reset(struct stk1160 *dev) +{ + int i; + + static const struct regval ctl[] = { + {STK1160_GCTRL+2, 0x0078}, + + {STK1160_RMCTL+1, 0x0000}, + {STK1160_RMCTL+3, 0x0002}, + + {STK1160_PLLSO, 0x0010}, + {STK1160_PLLSO+1, 0x0000}, + {STK1160_PLLSO+2, 0x0014}, + {STK1160_PLLSO+3, 0x000E}, + + {STK1160_PLLFD, 0x0046}, + + /* Timing generator setup */ + {STK1160_TIGEN, 0x0012}, + {STK1160_TICTL, 0x002D}, + {STK1160_TICTL+1, 0x0001}, + {STK1160_TICTL+2, 0x0000}, + {STK1160_TICTL+3, 0x0000}, + {STK1160_TIGEN, 0x0080}, + + {0xffff, 0xffff} + }; + + for (i = 0; ctl[i].reg != 0xffff; i++) + stk1160_write_reg(dev, ctl[i].reg, ctl[i].val); +} + +static void stk1160_release(struct v4l2_device *v4l2_dev) +{ + struct stk1160 *dev = container_of(v4l2_dev, struct stk1160, v4l2_dev); + + stk1160_info("releasing all resources\n"); + + stk1160_i2c_unregister(dev); + + v4l2_ctrl_handler_free(&dev->ctrl_handler); + v4l2_device_unregister(&dev->v4l2_dev); + kfree(dev->alt_max_pkt_size); + kfree(dev); +} + +/* high bandwidth multiplier, as encoded in highspeed endpoint descriptors */ +#define hb_mult(wMaxPacketSize) (1 + (((wMaxPacketSize) >> 11) & 0x03)) + +/* + * Scan usb interface and populate max_pkt_size array + * with information on each alternate setting. + * The array should be allocated by the caller. + */ +static int stk1160_scan_usb(struct usb_interface *intf, struct usb_device *udev, + unsigned int *max_pkt_size) +{ + int i, e, sizedescr, size, ifnum; + const struct usb_endpoint_descriptor *desc; + + bool has_video = false, has_audio = false; + const char *speed; + + ifnum = intf->altsetting[0].desc.bInterfaceNumber; + + /* Get endpoints */ + for (i = 0; i < intf->num_altsetting; i++) { + + for (e = 0; e < intf->altsetting[i].desc.bNumEndpoints; e++) { + + /* This isn't clear enough, at least to me */ + desc = &intf->altsetting[i].endpoint[e].desc; + sizedescr = le16_to_cpu(desc->wMaxPacketSize); + size = sizedescr & 0x7ff; + + if (udev->speed == USB_SPEED_HIGH) + size = size * hb_mult(sizedescr); + + if (usb_endpoint_xfer_isoc(desc) && + usb_endpoint_dir_in(desc)) { + switch (desc->bEndpointAddress) { + case STK1160_EP_AUDIO: + has_audio = true; + break; + case STK1160_EP_VIDEO: + has_video = true; + max_pkt_size[i] = size; + break; + } + } + } + } + + /* Is this even possible? */ + if (!(has_audio || has_video)) { + dev_err(&udev->dev, "no audio or video endpoints found\n"); + return -ENODEV; + } + + switch (udev->speed) { + case USB_SPEED_LOW: + speed = "1.5"; + break; + case USB_SPEED_FULL: + speed = "12"; + break; + case USB_SPEED_HIGH: + speed = "480"; + break; + default: + speed = "unknown"; + } + + dev_info(&udev->dev, "New device %s %s @ %s Mbps (%04x:%04x, interface %d, class %d)\n", + udev->manufacturer ? udev->manufacturer : "", + udev->product ? udev->product : "", + speed, + le16_to_cpu(udev->descriptor.idVendor), + le16_to_cpu(udev->descriptor.idProduct), + ifnum, + intf->altsetting->desc.bInterfaceNumber); + + /* This should never happen, since we rejected audio interfaces */ + if (has_audio) + dev_warn(&udev->dev, "audio interface %d found.\n\ + This is not implemented by this driver,\ + you should use snd-usb-audio instead\n", ifnum); + + if (has_video) + dev_info(&udev->dev, "video interface %d found\n", + ifnum); + + /* + * Make sure we have 480 Mbps of bandwidth, otherwise things like + * video stream wouldn't likely work, since 12 Mbps is generally + * not enough even for most streams. + */ + if (udev->speed != USB_SPEED_HIGH) + dev_warn(&udev->dev, "must be connected to a high-speed USB 2.0 port\n\ + You may not be able to stream video smoothly\n"); + + return 0; +} + +static int stk1160_probe(struct usb_interface *interface, + const struct usb_device_id *id) +{ + int rc = 0; + + unsigned int *alt_max_pkt_size; /* array of wMaxPacketSize */ + struct usb_device *udev; + struct stk1160 *dev; + + udev = interface_to_usbdev(interface); + + /* + * Since usb audio class is supported by snd-usb-audio, + * we reject audio interface. + */ + if (interface->altsetting[0].desc.bInterfaceClass == USB_CLASS_AUDIO) + return -ENODEV; + + /* Alloc an array for all possible max_pkt_size */ + alt_max_pkt_size = kmalloc(sizeof(alt_max_pkt_size[0]) * + interface->num_altsetting, GFP_KERNEL); + if (alt_max_pkt_size == NULL) + return -ENOMEM; + + /* + * Scan usb posibilities and populate alt_max_pkt_size array. + * Also, check if device speed is fast enough. + */ + rc = stk1160_scan_usb(interface, udev, alt_max_pkt_size); + if (rc < 0) { + kfree(alt_max_pkt_size); + return rc; + } + + dev = kzalloc(sizeof(struct stk1160), GFP_KERNEL); + if (dev == NULL) { + kfree(alt_max_pkt_size); + return -ENOMEM; + } + + dev->alt_max_pkt_size = alt_max_pkt_size; + dev->udev = udev; + dev->num_alt = interface->num_altsetting; + dev->ctl_input = input; + + /* We save struct device for debug purposes only */ + dev->dev = &interface->dev; + + usb_set_intfdata(interface, dev); + + /* initialize videobuf2 stuff */ + rc = stk1160_vb2_setup(dev); + if (rc < 0) + goto free_err; + + /* + * There is no need to take any locks here in probe + * because we register the device node as the *last* thing. + */ + spin_lock_init(&dev->buf_lock); + mutex_init(&dev->v4l_lock); + mutex_init(&dev->vb_queue_lock); + + rc = v4l2_ctrl_handler_init(&dev->ctrl_handler, 0); + if (rc) { + stk1160_err("v4l2_ctrl_handler_init failed (%d)\n", rc); + goto free_err; + } + + /* + * We obtain a v4l2_dev but defer + * registration of video device node as the last thing. + * There is no need to set the name if we give a device struct + */ + dev->v4l2_dev.release = stk1160_release; + dev->v4l2_dev.ctrl_handler = &dev->ctrl_handler; + rc = v4l2_device_register(dev->dev, &dev->v4l2_dev); + if (rc) { + stk1160_err("v4l2_device_register failed (%d)\n", rc); + goto free_ctrl; + } + + rc = stk1160_i2c_register(dev); + if (rc < 0) + goto unreg_v4l2; + + /* + * To the best of my knowledge stk1160 boards only have + * saa7113, but it doesn't hurt to support them all. + */ + dev->sd_saa7115 = v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, + "saa7115_auto", 0, saa7113_addrs); + + stk1160_info("driver ver %s successfully loaded\n", + STK1160_VERSION); + + /* i2c reset saa711x */ + v4l2_device_call_all(&dev->v4l2_dev, 0, core, reset, 0); + v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_routing, + 0, 0, 0); + v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 0); + + /* reset stk1160 to default values */ + stk1160_reg_reset(dev); + + /* select default input */ + stk1160_select_input(dev); + + stk1160_ac97_register(dev); + + rc = stk1160_video_register(dev); + if (rc < 0) + goto unreg_i2c; + + return 0; + +unreg_i2c: + stk1160_i2c_unregister(dev); +unreg_v4l2: + v4l2_device_unregister(&dev->v4l2_dev); +free_ctrl: + v4l2_ctrl_handler_free(&dev->ctrl_handler); +free_err: + kfree(alt_max_pkt_size); + kfree(dev); + + return rc; +} + +static void stk1160_disconnect(struct usb_interface *interface) +{ + struct stk1160 *dev; + + dev = usb_get_intfdata(interface); + usb_set_intfdata(interface, NULL); + + /* + * Wait until all current v4l2 operation are finished + * then deallocate resources + */ + mutex_lock(&dev->vb_queue_lock); + mutex_lock(&dev->v4l_lock); + + /* Here is the only place where isoc get released */ + stk1160_uninit_isoc(dev); + + /* ac97 unregister needs to be done before usb_device is cleared */ + stk1160_ac97_unregister(dev); + + stk1160_clear_queue(dev); + + video_unregister_device(&dev->vdev); + v4l2_device_disconnect(&dev->v4l2_dev); + + /* This way current users can detect device is gone */ + dev->udev = NULL; + + mutex_unlock(&dev->v4l_lock); + mutex_unlock(&dev->vb_queue_lock); + + /* + * This calls stk1160_release if it's the last reference. + * therwise, release is posponed until there are no users left. + */ + v4l2_device_put(&dev->v4l2_dev); +} + +static struct usb_driver stk1160_usb_driver = { + .name = "stk1160", + .id_table = stk1160_id_table, + .probe = stk1160_probe, + .disconnect = stk1160_disconnect, +}; + +module_usb_driver(stk1160_usb_driver); diff --git a/drivers/media/usb/stk1160/stk1160-i2c.c b/drivers/media/usb/stk1160/stk1160-i2c.c new file mode 100644 index 000000000000..176ac937306b --- /dev/null +++ b/drivers/media/usb/stk1160/stk1160-i2c.c @@ -0,0 +1,294 @@ +/* + * STK1160 driver + * + * Copyright (C) 2012 Ezequiel Garcia + * <elezegarcia--a.t--gmail.com> + * + * Based on Easycap driver by R.M. Thomas + * Copyright (C) 2010 R.M. Thomas + * <rmthomas--a.t--sciolus.org> + * + * 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. + * + */ + +#include <linux/module.h> +#include <linux/usb.h> +#include <linux/i2c.h> + +#include "stk1160.h" +#include "stk1160-reg.h" + +static unsigned int i2c_debug; +module_param(i2c_debug, int, 0644); +MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]"); + +#define dprintk_i2c(fmt, args...) \ +do { \ + if (i2c_debug) \ + printk(KERN_DEBUG fmt, ##args); \ +} while (0) + +static int stk1160_i2c_busy_wait(struct stk1160 *dev, u8 wait_bit_mask) +{ + unsigned long end; + u8 flag; + + /* Wait until read/write finish bit is set */ + end = jiffies + msecs_to_jiffies(STK1160_I2C_TIMEOUT); + while (time_is_after_jiffies(end)) { + + stk1160_read_reg(dev, STK1160_SICTL+1, &flag); + /* read/write done? */ + if (flag & wait_bit_mask) + goto done; + + usleep_range(10 * USEC_PER_MSEC, 20 * USEC_PER_MSEC); + } + + return -ETIMEDOUT; + +done: + return 0; +} + +static int stk1160_i2c_write_reg(struct stk1160 *dev, u8 addr, + u8 reg, u8 value) +{ + int rc; + + /* Set serial device address */ + rc = stk1160_write_reg(dev, STK1160_SICTL_SDA, addr); + if (rc < 0) + return rc; + + /* Set i2c device register sub-address */ + rc = stk1160_write_reg(dev, STK1160_SBUSW_WA, reg); + if (rc < 0) + return rc; + + /* Set i2c device register value */ + rc = stk1160_write_reg(dev, STK1160_SBUSW_WD, value); + if (rc < 0) + return rc; + + /* Start write now */ + rc = stk1160_write_reg(dev, STK1160_SICTL, 0x01); + if (rc < 0) + return rc; + + rc = stk1160_i2c_busy_wait(dev, 0x04); + if (rc < 0) + return rc; + + return 0; +} + +static int stk1160_i2c_read_reg(struct stk1160 *dev, u8 addr, + u8 reg, u8 *value) +{ + int rc; + + /* Set serial device address */ + rc = stk1160_write_reg(dev, STK1160_SICTL_SDA, addr); + if (rc < 0) + return rc; + + /* Set i2c device register sub-address */ + rc = stk1160_write_reg(dev, STK1160_SBUSR_RA, reg); + if (rc < 0) + return rc; + + /* Start read now */ + rc = stk1160_write_reg(dev, STK1160_SICTL, 0x20); + if (rc < 0) + return rc; + + rc = stk1160_i2c_busy_wait(dev, 0x01); + if (rc < 0) + return rc; + + stk1160_read_reg(dev, STK1160_SBUSR_RD, value); + if (rc < 0) + return rc; + + return 0; +} + +/* + * stk1160_i2c_check_for_device() + * check if there is a i2c_device at the supplied address + */ +static int stk1160_i2c_check_for_device(struct stk1160 *dev, + unsigned char addr) +{ + int rc; + + /* Set serial device address */ + rc = stk1160_write_reg(dev, STK1160_SICTL_SDA, addr); + if (rc < 0) + return rc; + + /* Set device sub-address, we'll chip version reg */ + rc = stk1160_write_reg(dev, STK1160_SBUSR_RA, 0x00); + if (rc < 0) + return rc; + + /* Start read now */ + rc = stk1160_write_reg(dev, STK1160_SICTL, 0x20); + if (rc < 0) + return rc; + + rc = stk1160_i2c_busy_wait(dev, 0x01); + if (rc < 0) + return -ENODEV; + + return 0; +} + +/* + * stk1160_i2c_xfer() + * the main i2c transfer function + */ +static int stk1160_i2c_xfer(struct i2c_adapter *i2c_adap, + struct i2c_msg msgs[], int num) +{ + struct stk1160 *dev = i2c_adap->algo_data; + int addr, rc, i; + + for (i = 0; i < num; i++) { + addr = msgs[i].addr << 1; + dprintk_i2c("%s: addr=%x", __func__, addr); + + if (!msgs[i].len) { + /* no len: check only for device presence */ + rc = stk1160_i2c_check_for_device(dev, addr); + if (rc < 0) { + dprintk_i2c(" no device\n"); + return rc; + } + + } else if (msgs[i].flags & I2C_M_RD) { + /* read request without preceding register selection */ + dprintk_i2c(" subaddr not selected"); + rc = -EOPNOTSUPP; + goto err; + + } else if (i + 1 < num && msgs[i].len <= 2 && + (msgs[i + 1].flags & I2C_M_RD) && + msgs[i].addr == msgs[i + 1].addr) { + + if (msgs[i].len != 1 || msgs[i + 1].len != 1) { + dprintk_i2c(" len not supported"); + rc = -EOPNOTSUPP; + goto err; + } + + dprintk_i2c(" subaddr=%x", msgs[i].buf[0]); + + rc = stk1160_i2c_read_reg(dev, addr, msgs[i].buf[0], + msgs[i + 1].buf); + + dprintk_i2c(" read=%x", *msgs[i + 1].buf); + + /* consumed two msgs, so we skip one of them */ + i++; + + } else { + if (msgs[i].len != 2) { + dprintk_i2c(" len not supported"); + rc = -EOPNOTSUPP; + goto err; + } + + dprintk_i2c(" subaddr=%x write=%x", + msgs[i].buf[0], msgs[i].buf[1]); + + rc = stk1160_i2c_write_reg(dev, addr, msgs[i].buf[0], + msgs[i].buf[1]); + } + + if (rc < 0) + goto err; + dprintk_i2c(" OK\n"); + } + + return num; +err: + dprintk_i2c(" ERROR: %d\n", rc); + return num; +} + +/* + * functionality(), what da heck is this? + */ +static u32 functionality(struct i2c_adapter *adap) +{ + return I2C_FUNC_SMBUS_EMUL; +} + +static struct i2c_algorithm algo = { + .master_xfer = stk1160_i2c_xfer, + .functionality = functionality, +}; + +static struct i2c_adapter adap_template = { + .owner = THIS_MODULE, + .name = "stk1160", + .algo = &algo, +}; + +static struct i2c_client client_template = { + .name = "stk1160 internal", +}; + +/* + * stk1160_i2c_register() + * register i2c bus + */ +int stk1160_i2c_register(struct stk1160 *dev) +{ + int rc; + + dev->i2c_adap = adap_template; + dev->i2c_adap.dev.parent = dev->dev; + strcpy(dev->i2c_adap.name, "stk1160"); + dev->i2c_adap.algo_data = dev; + + i2c_set_adapdata(&dev->i2c_adap, &dev->v4l2_dev); + + rc = i2c_add_adapter(&dev->i2c_adap); + if (rc < 0) { + stk1160_err("cannot add i2c adapter (%d)\n", rc); + return rc; + } + + dev->i2c_client = client_template; + dev->i2c_client.adapter = &dev->i2c_adap; + + /* Set i2c clock divider device address */ + stk1160_write_reg(dev, STK1160_SICTL_CD, 0x0f); + + /* ??? */ + stk1160_write_reg(dev, STK1160_ASIC + 3, 0x00); + + return 0; +} + +/* + * stk1160_i2c_unregister() + * unregister i2c_bus + */ +int stk1160_i2c_unregister(struct stk1160 *dev) +{ + i2c_del_adapter(&dev->i2c_adap); + return 0; +} diff --git a/drivers/media/usb/stk1160/stk1160-reg.h b/drivers/media/usb/stk1160/stk1160-reg.h new file mode 100644 index 000000000000..3e49da6e7edd --- /dev/null +++ b/drivers/media/usb/stk1160/stk1160-reg.h @@ -0,0 +1,93 @@ +/* + * STK1160 driver + * + * Copyright (C) 2012 Ezequiel Garcia + * <elezegarcia--a.t--gmail.com> + * + * Based on Easycap driver by R.M. Thomas + * Copyright (C) 2010 R.M. Thomas + * <rmthomas--a.t--sciolus.org> + * + * 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. + * + */ + +/* GPIO Control */ +#define STK1160_GCTRL 0x000 + +/* Remote Wakup Control */ +#define STK1160_RMCTL 0x00c + +/* + * Decoder Control Register: + * This byte controls capture start/stop + * with bit #7 (0x?? OR 0x80 to activate). + */ +#define STK1160_DCTRL 0x100 + +/* Capture Frame Start Position */ +#define STK116_CFSPO 0x110 +#define STK116_CFSPO_STX_L 0x110 +#define STK116_CFSPO_STX_H 0x111 +#define STK116_CFSPO_STY_L 0x112 +#define STK116_CFSPO_STY_H 0x113 + +/* Capture Frame End Position */ +#define STK116_CFEPO 0x114 +#define STK116_CFEPO_ENX_L 0x114 +#define STK116_CFEPO_ENX_H 0x115 +#define STK116_CFEPO_ENY_L 0x116 +#define STK116_CFEPO_ENY_H 0x117 + +/* Serial Interface Control */ +#define STK1160_SICTL 0x200 +#define STK1160_SICTL_CD 0x202 +#define STK1160_SICTL_SDA 0x203 + +/* Serial Bus Write */ +#define STK1160_SBUSW 0x204 +#define STK1160_SBUSW_WA 0x204 +#define STK1160_SBUSW_WD 0x205 + +/* Serial Bus Read */ +#define STK1160_SBUSR 0x208 +#define STK1160_SBUSR_RA 0x208 +#define STK1160_SBUSR_RD 0x209 + +/* Alternate Serial Inteface Control */ +#define STK1160_ASIC 0x2fc + +/* PLL Select Options */ +#define STK1160_PLLSO 0x018 + +/* PLL Frequency Divider */ +#define STK1160_PLLFD 0x01c + +/* Timing Generator */ +#define STK1160_TIGEN 0x300 + +/* Timing Control Parameter */ +#define STK1160_TICTL 0x350 + +/* AC97 Audio Control */ +#define STK1160_AC97CTL_0 0x500 +#define STK1160_AC97CTL_1 0x504 + +/* Use [0:6] bits of register 0x504 to set codec command address */ +#define STK1160_AC97_ADDR 0x504 +/* Use [16:31] bits of register 0x500 to set codec command data */ +#define STK1160_AC97_CMD 0x502 + +/* Audio I2S Interface */ +#define STK1160_I2SCTL 0x50c + +/* EEPROM Interface */ +#define STK1160_EEPROM_SZ 0x5f0 diff --git a/drivers/media/usb/stk1160/stk1160-v4l.c b/drivers/media/usb/stk1160/stk1160-v4l.c new file mode 100644 index 000000000000..fe6e857969ca --- /dev/null +++ b/drivers/media/usb/stk1160/stk1160-v4l.c @@ -0,0 +1,739 @@ +/* + * STK1160 driver + * + * Copyright (C) 2012 Ezequiel Garcia + * <elezegarcia--a.t--gmail.com> + * + * Based on Easycap driver by R.M. Thomas + * Copyright (C) 2010 R.M. Thomas + * <rmthomas--a.t--sciolus.org> + * + * 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. + * + */ + +#include <linux/module.h> +#include <linux/usb.h> +#include <linux/mm.h> +#include <linux/slab.h> + +#include <linux/videodev2.h> +#include <media/v4l2-device.h> +#include <media/v4l2-common.h> +#include <media/v4l2-ioctl.h> +#include <media/v4l2-fh.h> +#include <media/v4l2-event.h> +#include <media/v4l2-chip-ident.h> +#include <media/videobuf2-vmalloc.h> + +#include <media/saa7115.h> + +#include "stk1160.h" +#include "stk1160-reg.h" + +static unsigned int vidioc_debug; +module_param(vidioc_debug, int, 0644); +MODULE_PARM_DESC(vidioc_debug, "enable debug messages [vidioc]"); + +static bool keep_buffers; +module_param(keep_buffers, bool, 0644); +MODULE_PARM_DESC(keep_buffers, "don't release buffers upon stop streaming"); + +/* supported video standards */ +static struct stk1160_fmt format[] = { + { + .name = "16 bpp YUY2, 4:2:2, packed", + .fourcc = V4L2_PIX_FMT_UYVY, + .depth = 16, + } +}; + +static void stk1160_set_std(struct stk1160 *dev) +{ + int i; + + static struct regval std525[] = { + + /* 720x480 */ + + /* Frame start */ + {STK116_CFSPO_STX_L, 0x0000}, + {STK116_CFSPO_STX_H, 0x0000}, + {STK116_CFSPO_STY_L, 0x0003}, + {STK116_CFSPO_STY_H, 0x0000}, + + /* Frame end */ + {STK116_CFEPO_ENX_L, 0x05a0}, + {STK116_CFEPO_ENX_H, 0x0005}, + {STK116_CFEPO_ENY_L, 0x00f3}, + {STK116_CFEPO_ENY_H, 0x0000}, + + {0xffff, 0xffff} + }; + + static struct regval std625[] = { + + /* 720x576 */ + + /* TODO: Each line of frame has some junk at the end */ + /* Frame start */ + {STK116_CFSPO, 0x0000}, + {STK116_CFSPO+1, 0x0000}, + {STK116_CFSPO+2, 0x0001}, + {STK116_CFSPO+3, 0x0000}, + + /* Frame end */ + {STK116_CFEPO, 0x05a0}, + {STK116_CFEPO+1, 0x0005}, + {STK116_CFEPO+2, 0x0121}, + {STK116_CFEPO+3, 0x0001}, + + {0xffff, 0xffff} + }; + + if (dev->norm & V4L2_STD_525_60) { + stk1160_dbg("registers to NTSC like standard\n"); + for (i = 0; std525[i].reg != 0xffff; i++) + stk1160_write_reg(dev, std525[i].reg, std525[i].val); + } else { + stk1160_dbg("registers to PAL like standard\n"); + for (i = 0; std625[i].reg != 0xffff; i++) + stk1160_write_reg(dev, std625[i].reg, std625[i].val); + } + +} + +/* + * Set a new alternate setting. + * Returns true is dev->max_pkt_size has changed, false otherwise. + */ +static bool stk1160_set_alternate(struct stk1160 *dev) +{ + int i, prev_alt = dev->alt; + unsigned int min_pkt_size; + bool new_pkt_size; + + /* + * If we don't set right alternate, + * then we will get a green screen with junk. + */ + min_pkt_size = STK1160_MIN_PKT_SIZE; + + for (i = 0; i < dev->num_alt; i++) { + /* stop when the selected alt setting offers enough bandwidth */ + if (dev->alt_max_pkt_size[i] >= min_pkt_size) { + dev->alt = i; + break; + /* + * otherwise make sure that we end up with the maximum bandwidth + * because the min_pkt_size equation might be wrong... + */ + } else if (dev->alt_max_pkt_size[i] > + dev->alt_max_pkt_size[dev->alt]) + dev->alt = i; + } + + stk1160_info("setting alternate %d\n", dev->alt); + + if (dev->alt != prev_alt) { + stk1160_dbg("minimum isoc packet size: %u (alt=%d)\n", + min_pkt_size, dev->alt); + stk1160_dbg("setting alt %d with wMaxPacketSize=%u\n", + dev->alt, dev->alt_max_pkt_size[dev->alt]); + usb_set_interface(dev->udev, 0, dev->alt); + } + + new_pkt_size = dev->max_pkt_size != dev->alt_max_pkt_size[dev->alt]; + dev->max_pkt_size = dev->alt_max_pkt_size[dev->alt]; + + return new_pkt_size; +} + +static int stk1160_start_streaming(struct stk1160 *dev) +{ + bool new_pkt_size; + int rc = 0; + int i; + + /* Check device presence */ + if (!dev->udev) + return -ENODEV; + + if (mutex_lock_interruptible(&dev->v4l_lock)) + return -ERESTARTSYS; + /* + * For some reason it is mandatory to set alternate *first* + * and only *then* initialize isoc urbs. + * Someone please explain me why ;) + */ + new_pkt_size = stk1160_set_alternate(dev); + + /* + * We (re)allocate isoc urbs if: + * there is no allocated isoc urbs, OR + * a new dev->max_pkt_size is detected + */ + if (!dev->isoc_ctl.num_bufs || new_pkt_size) { + rc = stk1160_alloc_isoc(dev); + if (rc < 0) + goto out_stop_hw; + } + + /* submit urbs and enables IRQ */ + for (i = 0; i < dev->isoc_ctl.num_bufs; i++) { + rc = usb_submit_urb(dev->isoc_ctl.urb[i], GFP_KERNEL); + if (rc) { + stk1160_err("cannot submit urb[%d] (%d)\n", i, rc); + goto out_uninit; + } + } + + /* Start saa711x */ + v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 1); + + /* Start stk1160 */ + stk1160_write_reg(dev, STK1160_DCTRL, 0xb3); + stk1160_write_reg(dev, STK1160_DCTRL+3, 0x00); + + stk1160_dbg("streaming started\n"); + + mutex_unlock(&dev->v4l_lock); + + return 0; + +out_uninit: + stk1160_uninit_isoc(dev); +out_stop_hw: + usb_set_interface(dev->udev, 0, 0); + stk1160_clear_queue(dev); + + mutex_unlock(&dev->v4l_lock); + + return rc; +} + +/* Must be called with v4l_lock hold */ +static void stk1160_stop_hw(struct stk1160 *dev) +{ + /* If the device is not physically present, there is nothing to do */ + if (!dev->udev) + return; + + /* set alternate 0 */ + dev->alt = 0; + stk1160_info("setting alternate %d\n", dev->alt); + usb_set_interface(dev->udev, 0, 0); + + /* Stop stk1160 */ + stk1160_write_reg(dev, STK1160_DCTRL, 0x00); + stk1160_write_reg(dev, STK1160_DCTRL+3, 0x00); + + /* Stop saa711x */ + v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 0); +} + +static int stk1160_stop_streaming(struct stk1160 *dev) +{ + if (mutex_lock_interruptible(&dev->v4l_lock)) + return -ERESTARTSYS; + + stk1160_cancel_isoc(dev); + + /* + * It is possible to keep buffers around using a module parameter. + * This is intended to avoid memory fragmentation. + */ + if (!keep_buffers) + stk1160_free_isoc(dev); + + stk1160_stop_hw(dev); + + stk1160_clear_queue(dev); + + stk1160_dbg("streaming stopped\n"); + + mutex_unlock(&dev->v4l_lock); + + return 0; +} + +static struct v4l2_file_operations stk1160_fops = { + .owner = THIS_MODULE, + .open = v4l2_fh_open, + .release = vb2_fop_release, + .read = vb2_fop_read, + .poll = vb2_fop_poll, + .mmap = vb2_fop_mmap, + .unlocked_ioctl = video_ioctl2, +}; + +/* + * vidioc ioctls + */ +static int vidioc_querycap(struct file *file, + void *priv, struct v4l2_capability *cap) +{ + struct stk1160 *dev = video_drvdata(file); + + strcpy(cap->driver, "stk1160"); + strcpy(cap->card, "stk1160"); + usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info)); + cap->device_caps = + V4L2_CAP_VIDEO_CAPTURE | + V4L2_CAP_STREAMING | + V4L2_CAP_READWRITE; + cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; + return 0; +} + +static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_fmtdesc *f) +{ + if (f->index != 0) + return -EINVAL; + + strlcpy(f->description, format[f->index].name, sizeof(f->description)); + f->pixelformat = format[f->index].fourcc; + return 0; +} + +static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct stk1160 *dev = video_drvdata(file); + + f->fmt.pix.width = dev->width; + f->fmt.pix.height = dev->height; + f->fmt.pix.field = V4L2_FIELD_INTERLACED; + f->fmt.pix.pixelformat = dev->fmt->fourcc; + f->fmt.pix.bytesperline = dev->width * 2; + f->fmt.pix.sizeimage = dev->height * f->fmt.pix.bytesperline; + f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; + + return 0; +} + +static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct stk1160 *dev = video_drvdata(file); + + /* + * User can't choose size at his own will, + * so we just return him the current size chosen + * at standard selection. + * TODO: Implement frame scaling? + */ + + f->fmt.pix.pixelformat = dev->fmt->fourcc; + f->fmt.pix.width = dev->width; + f->fmt.pix.height = dev->height; + f->fmt.pix.field = V4L2_FIELD_INTERLACED; + f->fmt.pix.bytesperline = dev->width * 2; + f->fmt.pix.sizeimage = dev->height * f->fmt.pix.bytesperline; + f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; + + return 0; +} + +static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct stk1160 *dev = video_drvdata(file); + struct vb2_queue *q = &dev->vb_vidq; + + if (vb2_is_busy(q)) + return -EBUSY; + + vidioc_try_fmt_vid_cap(file, priv, f); + + /* We don't support any format changes */ + + return 0; +} + +static int vidioc_querystd(struct file *file, void *priv, v4l2_std_id *norm) +{ + struct stk1160 *dev = video_drvdata(file); + v4l2_device_call_all(&dev->v4l2_dev, 0, video, querystd, norm); + return 0; +} + +static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *norm) +{ + struct stk1160 *dev = video_drvdata(file); + + *norm = dev->norm; + return 0; +} + +static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *norm) +{ + struct stk1160 *dev = video_drvdata(file); + struct vb2_queue *q = &dev->vb_vidq; + + if (vb2_is_busy(q)) + return -EBUSY; + + /* Check device presence */ + if (!dev->udev) + return -ENODEV; + + /* We need to set this now, before we call stk1160_set_std */ + dev->norm = *norm; + + /* This is taken from saa7115 video decoder */ + if (dev->norm & V4L2_STD_525_60) { + dev->width = 720; + dev->height = 480; + } else if (dev->norm & V4L2_STD_625_50) { + dev->width = 720; + dev->height = 576; + } else { + stk1160_err("invalid standard\n"); + return -EINVAL; + } + + stk1160_set_std(dev); + + v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_std, + dev->norm); + + return 0; +} + + +static int vidioc_enum_input(struct file *file, void *priv, + struct v4l2_input *i) +{ + struct stk1160 *dev = video_drvdata(file); + + if (i->index > STK1160_MAX_INPUT) + return -EINVAL; + + sprintf(i->name, "Composite%d", i->index); + i->type = V4L2_INPUT_TYPE_CAMERA; + i->std = dev->vdev.tvnorms; + return 0; +} + +static int vidioc_g_input(struct file *file, void *priv, unsigned int *i) +{ + struct stk1160 *dev = video_drvdata(file); + *i = dev->ctl_input; + return 0; +} + +static int vidioc_s_input(struct file *file, void *priv, unsigned int i) +{ + struct stk1160 *dev = video_drvdata(file); + + if (vb2_is_busy(&dev->vb_vidq)) + return -EBUSY; + + if (i > STK1160_MAX_INPUT) + return -EINVAL; + + dev->ctl_input = i; + + stk1160_select_input(dev); + + return 0; +} + +static int vidioc_g_chip_ident(struct file *file, void *priv, + struct v4l2_dbg_chip_ident *chip) +{ + switch (chip->match.type) { + case V4L2_CHIP_MATCH_HOST: + chip->ident = V4L2_IDENT_NONE; + chip->revision = 0; + return 0; + default: + return -EINVAL; + } +} + +#ifdef CONFIG_VIDEO_ADV_DEBUG +static int vidioc_g_register(struct file *file, void *priv, + struct v4l2_dbg_register *reg) +{ + struct stk1160 *dev = video_drvdata(file); + int rc; + u8 val; + + switch (reg->match.type) { + case V4L2_CHIP_MATCH_AC97: + /* TODO: Support me please :-( */ + return -EINVAL; + case V4L2_CHIP_MATCH_I2C_DRIVER: + v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_register, reg); + return 0; + case V4L2_CHIP_MATCH_I2C_ADDR: + /* TODO: is this correct? */ + v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_register, reg); + return 0; + default: + if (!v4l2_chip_match_host(®->match)) + return -EINVAL; + } + + /* Match host */ + rc = stk1160_read_reg(dev, reg->reg, &val); + reg->val = val; + reg->size = 1; + + return rc; +} + +static int vidioc_s_register(struct file *file, void *priv, + struct v4l2_dbg_register *reg) +{ + struct stk1160 *dev = video_drvdata(file); + + switch (reg->match.type) { + case V4L2_CHIP_MATCH_AC97: + return -EINVAL; + case V4L2_CHIP_MATCH_I2C_DRIVER: + v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_register, reg); + return 0; + case V4L2_CHIP_MATCH_I2C_ADDR: + /* TODO: is this correct? */ + v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_register, reg); + return 0; + default: + if (!v4l2_chip_match_host(®->match)) + return -EINVAL; + } + + /* Match host */ + return stk1160_write_reg(dev, reg->reg, cpu_to_le16(reg->val)); +} +#endif + +static const struct v4l2_ioctl_ops stk1160_ioctl_ops = { + .vidioc_querycap = vidioc_querycap, + .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, + .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, + .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, + .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, + .vidioc_querystd = vidioc_querystd, + .vidioc_g_std = vidioc_g_std, + .vidioc_s_std = vidioc_s_std, + .vidioc_enum_input = vidioc_enum_input, + .vidioc_g_input = vidioc_g_input, + .vidioc_s_input = vidioc_s_input, + + /* vb2 takes care of these */ + .vidioc_reqbufs = vb2_ioctl_reqbufs, + .vidioc_querybuf = vb2_ioctl_querybuf, + .vidioc_qbuf = vb2_ioctl_qbuf, + .vidioc_dqbuf = vb2_ioctl_dqbuf, + .vidioc_streamon = vb2_ioctl_streamon, + .vidioc_streamoff = vb2_ioctl_streamoff, + + .vidioc_log_status = v4l2_ctrl_log_status, + .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, + .vidioc_unsubscribe_event = v4l2_event_unsubscribe, + .vidioc_g_chip_ident = vidioc_g_chip_ident, + +#ifdef CONFIG_VIDEO_ADV_DEBUG + .vidioc_g_register = vidioc_g_register, + .vidioc_s_register = vidioc_s_register, +#endif +}; + +/********************************************************************/ + +/* + * Videobuf2 operations + */ +static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *v4l_fmt, + unsigned int *nbuffers, unsigned int *nplanes, + unsigned int sizes[], void *alloc_ctxs[]) +{ + struct stk1160 *dev = vb2_get_drv_priv(vq); + unsigned long size; + + size = dev->width * dev->height * 2; + + /* + * Here we can change the number of buffers being requested. + * So, we set a minimum and a maximum like this: + */ + *nbuffers = clamp_t(unsigned int, *nbuffers, + STK1160_MIN_VIDEO_BUFFERS, STK1160_MAX_VIDEO_BUFFERS); + + /* This means a packed colorformat */ + *nplanes = 1; + + sizes[0] = size; + + stk1160_info("%s: buffer count %d, each %ld bytes\n", + __func__, *nbuffers, size); + + return 0; +} + +static void buffer_queue(struct vb2_buffer *vb) +{ + unsigned long flags; + struct stk1160 *dev = vb2_get_drv_priv(vb->vb2_queue); + struct stk1160_buffer *buf = + container_of(vb, struct stk1160_buffer, vb); + + spin_lock_irqsave(&dev->buf_lock, flags); + if (!dev->udev) { + /* + * If the device is disconnected return the buffer to userspace + * directly. The next QBUF call will fail with -ENODEV. + */ + vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); + } else { + + buf->mem = vb2_plane_vaddr(vb, 0); + buf->length = vb2_plane_size(vb, 0); + buf->bytesused = 0; + buf->pos = 0; + + /* + * If buffer length is less from expected then we return + * the buffer to userspace directly. + */ + if (buf->length < dev->width * dev->height * 2) + vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); + else + list_add_tail(&buf->list, &dev->avail_bufs); + + } + spin_unlock_irqrestore(&dev->buf_lock, flags); +} + +static int start_streaming(struct vb2_queue *vq, unsigned int count) +{ + struct stk1160 *dev = vb2_get_drv_priv(vq); + return stk1160_start_streaming(dev); +} + +/* abort streaming and wait for last buffer */ +static int stop_streaming(struct vb2_queue *vq) +{ + struct stk1160 *dev = vb2_get_drv_priv(vq); + return stk1160_stop_streaming(dev); +} + +static struct vb2_ops stk1160_video_qops = { + .queue_setup = queue_setup, + .buf_queue = buffer_queue, + .start_streaming = start_streaming, + .stop_streaming = stop_streaming, + .wait_prepare = vb2_ops_wait_prepare, + .wait_finish = vb2_ops_wait_finish, +}; + +static struct video_device v4l_template = { + .name = "stk1160", + .tvnorms = V4L2_STD_525_60 | V4L2_STD_625_50, + .fops = &stk1160_fops, + .ioctl_ops = &stk1160_ioctl_ops, + .release = video_device_release_empty, +}; + +/********************************************************************/ + +/* Must be called with both v4l_lock and vb_queue_lock hold */ +void stk1160_clear_queue(struct stk1160 *dev) +{ + struct stk1160_buffer *buf; + unsigned long flags; + + /* Release all active buffers */ + spin_lock_irqsave(&dev->buf_lock, flags); + while (!list_empty(&dev->avail_bufs)) { + buf = list_first_entry(&dev->avail_bufs, + struct stk1160_buffer, list); + list_del(&buf->list); + vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); + stk1160_info("buffer [%p/%d] aborted\n", + buf, buf->vb.v4l2_buf.index); + } + /* It's important to clear current buffer */ + dev->isoc_ctl.buf = NULL; + spin_unlock_irqrestore(&dev->buf_lock, flags); +} + +int stk1160_vb2_setup(struct stk1160 *dev) +{ + int rc; + struct vb2_queue *q; + + q = &dev->vb_vidq; + q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + q->io_modes = VB2_READ | VB2_MMAP | VB2_USERPTR; + q->drv_priv = dev; + q->buf_struct_size = sizeof(struct stk1160_buffer); + q->ops = &stk1160_video_qops; + q->mem_ops = &vb2_vmalloc_memops; + + rc = vb2_queue_init(q); + if (rc < 0) + return rc; + + /* initialize video dma queue */ + INIT_LIST_HEAD(&dev->avail_bufs); + + return 0; +} + +int stk1160_video_register(struct stk1160 *dev) +{ + int rc; + + /* Initialize video_device with a template structure */ + dev->vdev = v4l_template; + dev->vdev.debug = vidioc_debug; + dev->vdev.queue = &dev->vb_vidq; + + /* + * Provide mutexes for v4l2 core and for videobuf2 queue. + * It will be used to protect *only* v4l2 ioctls. + */ + dev->vdev.lock = &dev->v4l_lock; + dev->vdev.queue->lock = &dev->vb_queue_lock; + + /* This will be used to set video_device parent */ + dev->vdev.v4l2_dev = &dev->v4l2_dev; + set_bit(V4L2_FL_USE_FH_PRIO, &dev->vdev.flags); + + /* NTSC is default */ + dev->norm = V4L2_STD_NTSC_M; + dev->width = 720; + dev->height = 480; + + /* set default format */ + dev->fmt = &format[0]; + stk1160_set_std(dev); + + v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_std, + dev->norm); + + video_set_drvdata(&dev->vdev, dev); + rc = video_register_device(&dev->vdev, VFL_TYPE_GRABBER, -1); + if (rc < 0) { + stk1160_err("video_register_device failed (%d)\n", rc); + return rc; + } + + v4l2_info(&dev->v4l2_dev, "V4L2 device registered as %s\n", + video_device_node_name(&dev->vdev)); + + return 0; +} diff --git a/drivers/media/usb/stk1160/stk1160-video.c b/drivers/media/usb/stk1160/stk1160-video.c new file mode 100644 index 000000000000..8bdfb0275313 --- /dev/null +++ b/drivers/media/usb/stk1160/stk1160-video.c @@ -0,0 +1,522 @@ +/* + * STK1160 driver + * + * Copyright (C) 2012 Ezequiel Garcia + * <elezegarcia--a.t--gmail.com> + * + * Based on Easycap driver by R.M. Thomas + * Copyright (C) 2010 R.M. Thomas + * <rmthomas--a.t--sciolus.org> + * + * 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. + * + */ + +#include <linux/module.h> +#include <linux/usb.h> +#include <linux/slab.h> +#include <linux/ratelimit.h> + +#include "stk1160.h" + +static unsigned int debug; +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "enable debug messages"); + +static inline void print_err_status(struct stk1160 *dev, + int packet, int status) +{ + char *errmsg = "Unknown"; + + switch (status) { + case -ENOENT: + errmsg = "unlinked synchronuously"; + break; + case -ECONNRESET: + errmsg = "unlinked asynchronuously"; + break; + case -ENOSR: + errmsg = "Buffer error (overrun)"; + break; + case -EPIPE: + errmsg = "Stalled (device not responding)"; + break; + case -EOVERFLOW: + errmsg = "Babble (bad cable?)"; + break; + case -EPROTO: + errmsg = "Bit-stuff error (bad cable?)"; + break; + case -EILSEQ: + errmsg = "CRC/Timeout (could be anything)"; + break; + case -ETIME: + errmsg = "Device does not respond"; + break; + } + + if (packet < 0) + printk_ratelimited(KERN_WARNING "URB status %d [%s].\n", + status, errmsg); + else + printk_ratelimited(KERN_INFO "URB packet %d, status %d [%s].\n", + packet, status, errmsg); +} + +static inline +struct stk1160_buffer *stk1160_next_buffer(struct stk1160 *dev) +{ + struct stk1160_buffer *buf = NULL; + unsigned long flags = 0; + + /* Current buffer must be NULL when this functions gets called */ + BUG_ON(dev->isoc_ctl.buf); + + spin_lock_irqsave(&dev->buf_lock, flags); + if (!list_empty(&dev->avail_bufs)) { + buf = list_first_entry(&dev->avail_bufs, + struct stk1160_buffer, list); + list_del(&buf->list); + } + spin_unlock_irqrestore(&dev->buf_lock, flags); + + return buf; +} + +static inline +void stk1160_buffer_done(struct stk1160 *dev) +{ + struct stk1160_buffer *buf = dev->isoc_ctl.buf; + + dev->field_count++; + + buf->vb.v4l2_buf.sequence = dev->field_count >> 1; + buf->vb.v4l2_buf.field = V4L2_FIELD_INTERLACED; + buf->vb.v4l2_buf.bytesused = buf->bytesused; + do_gettimeofday(&buf->vb.v4l2_buf.timestamp); + + vb2_set_plane_payload(&buf->vb, 0, buf->bytesused); + vb2_buffer_done(&buf->vb, VB2_BUF_STATE_DONE); + + dev->isoc_ctl.buf = NULL; +} + +static inline +void stk1160_copy_video(struct stk1160 *dev, u8 *src, int len) +{ + int linesdone, lineoff, lencopy; + int bytesperline = dev->width * 2; + struct stk1160_buffer *buf = dev->isoc_ctl.buf; + u8 *dst = buf->mem; + int remain; + + /* + * TODO: These stk1160_dbg are very spammy! + * We should 1) check why we are getting them + * and 2) add ratelimit. + * + * UPDATE: One of the reasons (the only one?) for getting these + * is incorrect standard (mismatch between expected and configured). + * So perhaps, we could add a counter for errors. When the counter + * reaches some value, we simply stop streaming. + */ + + len -= 4; + src += 4; + + remain = len; + + linesdone = buf->pos / bytesperline; + lineoff = buf->pos % bytesperline; /* offset in current line */ + + if (!buf->odd) + dst += bytesperline; + + /* Multiply linesdone by two, to take account of the other field */ + dst += linesdone * bytesperline * 2 + lineoff; + + /* Copy the remaining of current line */ + if (remain < (bytesperline - lineoff)) + lencopy = remain; + else + lencopy = bytesperline - lineoff; + + /* + * Check if we have enough space left in the buffer. + * In that case, we force loop exit after copy. + */ + if (lencopy > buf->bytesused - buf->length) { + lencopy = buf->bytesused - buf->length; + remain = lencopy; + } + + /* Check if the copy is done */ + if (lencopy == 0 || remain == 0) + return; + + /* Let the bug hunt begin! sanity checks! */ + if (lencopy < 0) { + stk1160_dbg("copy skipped: negative lencopy\n"); + return; + } + + if ((unsigned long)dst + lencopy > + (unsigned long)buf->mem + buf->length) { + printk_ratelimited(KERN_WARNING "stk1160: buffer overflow detected\n"); + return; + } + + memcpy(dst, src, lencopy); + + buf->bytesused += lencopy; + buf->pos += lencopy; + remain -= lencopy; + + /* Copy current field line by line, interlacing with the other field */ + while (remain > 0) { + + dst += lencopy + bytesperline; + src += lencopy; + + /* Copy one line at a time */ + if (remain < bytesperline) + lencopy = remain; + else + lencopy = bytesperline; + + /* + * Check if we have enough space left in the buffer. + * In that case, we force loop exit after copy. + */ + if (lencopy > buf->bytesused - buf->length) { + lencopy = buf->bytesused - buf->length; + remain = lencopy; + } + + /* Check if the copy is done */ + if (lencopy == 0 || remain == 0) + return; + + if (lencopy < 0) { + printk_ratelimited(KERN_WARNING "stk1160: negative lencopy detected\n"); + return; + } + + if ((unsigned long)dst + lencopy > + (unsigned long)buf->mem + buf->length) { + printk_ratelimited(KERN_WARNING "stk1160: buffer overflow detected\n"); + return; + } + + memcpy(dst, src, lencopy); + remain -= lencopy; + + buf->bytesused += lencopy; + buf->pos += lencopy; + } +} + +/* + * Controls the isoc copy of each urb packet + */ +static void stk1160_process_isoc(struct stk1160 *dev, struct urb *urb) +{ + int i, len, status; + u8 *p; + + if (!dev) { + stk1160_warn("%s called with null device\n", __func__); + return; + } + + if (urb->status < 0) { + /* Print status and drop current packet (or field?) */ + print_err_status(dev, -1, urb->status); + return; + } + + for (i = 0; i < urb->number_of_packets; i++) { + status = urb->iso_frame_desc[i].status; + if (status < 0) { + print_err_status(dev, i, status); + continue; + } + + /* Get packet actual length and pointer to data */ + p = urb->transfer_buffer + urb->iso_frame_desc[i].offset; + len = urb->iso_frame_desc[i].actual_length; + + /* Empty packet */ + if (len <= 4) + continue; + + /* + * An 8-byte packet sequence means end of field. + * So if we don't have any packet, we start receiving one now + * and if we do have a packet, then we are done with it. + * + * These end of field packets are always 0xc0 or 0x80, + * but not always 8-byte long so we don't check packet length. + */ + if (p[0] == 0xc0) { + + /* + * If first byte is 0xc0 then we received + * second field, and frame has ended. + */ + if (dev->isoc_ctl.buf != NULL) + stk1160_buffer_done(dev); + + dev->isoc_ctl.buf = stk1160_next_buffer(dev); + if (dev->isoc_ctl.buf == NULL) + return; + } + + /* + * If we don't have a buffer here, then it means we + * haven't found the start mark sequence. + */ + if (dev->isoc_ctl.buf == NULL) + continue; + + if (p[0] == 0xc0 || p[0] == 0x80) { + + /* We set next packet parity and + * continue to get next one + */ + dev->isoc_ctl.buf->odd = *p & 0x40; + dev->isoc_ctl.buf->pos = 0; + continue; + } + + stk1160_copy_video(dev, p, len); + } +} + + +/* + * IRQ callback, called by URB callback + */ +static void stk1160_isoc_irq(struct urb *urb) +{ + int i, rc; + struct stk1160 *dev = urb->context; + + switch (urb->status) { + case 0: + break; + case -ECONNRESET: /* kill */ + case -ENOENT: + case -ESHUTDOWN: + /* TODO: check uvc driver: he frees the queue here */ + return; + default: + stk1160_err("urb error! status %d\n", urb->status); + return; + } + + stk1160_process_isoc(dev, urb); + + /* Reset urb buffers */ + for (i = 0; i < urb->number_of_packets; i++) { + urb->iso_frame_desc[i].status = 0; + urb->iso_frame_desc[i].actual_length = 0; + } + + rc = usb_submit_urb(urb, GFP_ATOMIC); + if (rc) + stk1160_err("urb re-submit failed (%d)\n", rc); +} + +/* + * Cancel urbs + * This function can't be called in atomic context + */ +void stk1160_cancel_isoc(struct stk1160 *dev) +{ + int i, num_bufs = dev->isoc_ctl.num_bufs; + + /* + * This check is not necessary, but we add it + * to avoid a spurious debug message + */ + if (!num_bufs) + return; + + stk1160_dbg("killing %d urbs...\n", num_bufs); + + for (i = 0; i < num_bufs; i++) { + + /* + * To kill urbs we can't be in atomic context. + * We don't care for NULL pointer since + * usb_kill_urb allows it. + */ + usb_kill_urb(dev->isoc_ctl.urb[i]); + } + + stk1160_dbg("all urbs killed\n"); +} + +/* + * Releases urb and transfer buffers + * Obviusly, associated urb must be killed before releasing it. + */ +void stk1160_free_isoc(struct stk1160 *dev) +{ + struct urb *urb; + int i, num_bufs = dev->isoc_ctl.num_bufs; + + stk1160_dbg("freeing %d urb buffers...\n", num_bufs); + + for (i = 0; i < num_bufs; i++) { + + urb = dev->isoc_ctl.urb[i]; + if (urb) { + + if (dev->isoc_ctl.transfer_buffer[i]) { +#ifndef CONFIG_DMA_NONCOHERENT + usb_free_coherent(dev->udev, + urb->transfer_buffer_length, + dev->isoc_ctl.transfer_buffer[i], + urb->transfer_dma); +#else + kfree(dev->isoc_ctl.transfer_buffer[i]); +#endif + } + usb_free_urb(urb); + dev->isoc_ctl.urb[i] = NULL; + } + dev->isoc_ctl.transfer_buffer[i] = NULL; + } + + kfree(dev->isoc_ctl.urb); + kfree(dev->isoc_ctl.transfer_buffer); + + dev->isoc_ctl.urb = NULL; + dev->isoc_ctl.transfer_buffer = NULL; + dev->isoc_ctl.num_bufs = 0; + + stk1160_dbg("all urb buffers freed\n"); +} + +/* + * Helper for cancelling and freeing urbs + * This function can't be called in atomic context + */ +void stk1160_uninit_isoc(struct stk1160 *dev) +{ + stk1160_cancel_isoc(dev); + stk1160_free_isoc(dev); +} + +/* + * Allocate URBs + */ +int stk1160_alloc_isoc(struct stk1160 *dev) +{ + struct urb *urb; + int i, j, k, sb_size, max_packets, num_bufs; + + /* + * It may be necessary to release isoc here, + * since isoc are only released on disconnection. + * (see new_pkt_size flag) + */ + if (dev->isoc_ctl.num_bufs) + stk1160_uninit_isoc(dev); + + stk1160_dbg("allocating urbs...\n"); + + num_bufs = STK1160_NUM_BUFS; + max_packets = STK1160_NUM_PACKETS; + sb_size = max_packets * dev->max_pkt_size; + + dev->isoc_ctl.buf = NULL; + dev->isoc_ctl.max_pkt_size = dev->max_pkt_size; + dev->isoc_ctl.urb = kzalloc(sizeof(void *)*num_bufs, GFP_KERNEL); + if (!dev->isoc_ctl.urb) { + stk1160_err("out of memory for urb array\n"); + return -ENOMEM; + } + + dev->isoc_ctl.transfer_buffer = kzalloc(sizeof(void *)*num_bufs, + GFP_KERNEL); + if (!dev->isoc_ctl.transfer_buffer) { + stk1160_err("out of memory for usb transfers\n"); + kfree(dev->isoc_ctl.urb); + return -ENOMEM; + } + + /* allocate urbs and transfer buffers */ + for (i = 0; i < num_bufs; i++) { + + urb = usb_alloc_urb(max_packets, GFP_KERNEL); + if (!urb) { + stk1160_err("cannot alloc urb[%d]\n", i); + goto free_i_bufs; + } + dev->isoc_ctl.urb[i] = urb; + +#ifndef CONFIG_DMA_NONCOHERENT + dev->isoc_ctl.transfer_buffer[i] = usb_alloc_coherent(dev->udev, + sb_size, GFP_KERNEL, &urb->transfer_dma); +#else + dev->isoc_ctl.transfer_buffer[i] = kmalloc(sb_size, GFP_KERNEL); +#endif + if (!dev->isoc_ctl.transfer_buffer[i]) { + stk1160_err("cannot alloc %d bytes for tx[%d] buffer\n", + sb_size, i); + goto free_i_bufs; + } + memset(dev->isoc_ctl.transfer_buffer[i], 0, sb_size); + + /* + * FIXME: Where can I get the endpoint? + */ + urb->dev = dev->udev; + urb->pipe = usb_rcvisocpipe(dev->udev, STK1160_EP_VIDEO); + urb->transfer_buffer = dev->isoc_ctl.transfer_buffer[i]; + urb->transfer_buffer_length = sb_size; + urb->complete = stk1160_isoc_irq; + urb->context = dev; + urb->interval = 1; + urb->start_frame = 0; + urb->number_of_packets = max_packets; +#ifndef CONFIG_DMA_NONCOHERENT + urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP; +#else + urb->transfer_flags = URB_ISO_ASAP; +#endif + + k = 0; + for (j = 0; j < max_packets; j++) { + urb->iso_frame_desc[j].offset = k; + urb->iso_frame_desc[j].length = + dev->isoc_ctl.max_pkt_size; + k += dev->isoc_ctl.max_pkt_size; + } + } + + stk1160_dbg("urbs allocated\n"); + + /* At last we can say we have some buffers */ + dev->isoc_ctl.num_bufs = num_bufs; + + return 0; + +free_i_bufs: + /* Save the allocated buffers so far, so we can properly free them */ + dev->isoc_ctl.num_bufs = i+1; + stk1160_free_isoc(dev); + return -ENOMEM; +} + diff --git a/drivers/media/usb/stk1160/stk1160.h b/drivers/media/usb/stk1160/stk1160.h new file mode 100644 index 000000000000..3feba0033f98 --- /dev/null +++ b/drivers/media/usb/stk1160/stk1160.h @@ -0,0 +1,208 @@ +/* + * STK1160 driver + * + * Copyright (C) 2012 Ezequiel Garcia + * <elezegarcia--a.t--gmail.com> + * + * Based on Easycap driver by R.M. Thomas + * Copyright (C) 2010 R.M. Thomas + * <rmthomas--a.t--sciolus.org> + * + * 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. + * + */ + +#include <linux/i2c.h> +#include <sound/core.h> +#include <sound/ac97_codec.h> +#include <media/videobuf2-core.h> +#include <media/v4l2-device.h> +#include <media/v4l2-ctrls.h> + +#define STK1160_VERSION "0.9.5" +#define STK1160_VERSION_NUM 0x000905 + +/* TODO: Decide on number of packets for each buffer */ +#define STK1160_NUM_PACKETS 64 + +/* Number of buffers for isoc transfers */ +#define STK1160_NUM_BUFS 16 /* TODO */ + +/* TODO: This endpoint address should be retrieved */ +#define STK1160_EP_VIDEO 0x82 +#define STK1160_EP_AUDIO 0x81 + +/* Max and min video buffers */ +#define STK1160_MIN_VIDEO_BUFFERS 8 +#define STK1160_MAX_VIDEO_BUFFERS 32 + +#define STK1160_MIN_PKT_SIZE 3072 + +#define STK1160_MAX_INPUT 3 + +#define STK1160_I2C_TIMEOUT 100 + +/* TODO: Print helpers + * I could use dev_xxx, pr_xxx, v4l2_xxx or printk. + * However, there isn't a solid consensus on which + * new drivers should use. + * + */ +#define DEBUG +#ifdef DEBUG +#define stk1160_dbg(fmt, args...) \ + printk(KERN_DEBUG "stk1160: " fmt, ## args) +#else +#define stk1160_dbg(fmt, args...) +#endif + +#define stk1160_info(fmt, args...) \ + pr_info("stk1160: " fmt, ## args) + +#define stk1160_warn(fmt, args...) \ + pr_warn("stk1160: " fmt, ## args) + +#define stk1160_err(fmt, args...) \ + pr_err("stk1160: " fmt, ## args) + +/* Buffer for one video frame */ +struct stk1160_buffer { + /* common v4l buffer stuff -- must be first */ + struct vb2_buffer vb; + struct list_head list; + + void *mem; + unsigned int length; /* buffer length */ + unsigned int bytesused; /* bytes written */ + int odd; /* current oddity */ + + /* + * Since we interlace two fields per frame, + * this is different from bytesused. + */ + unsigned int pos; /* current pos inside buffer */ +}; + +struct stk1160_isoc_ctl { + /* max packet size of isoc transaction */ + int max_pkt_size; + + /* number of allocated urbs */ + int num_bufs; + + /* urb for isoc transfers */ + struct urb **urb; + + /* transfer buffers for isoc transfer */ + char **transfer_buffer; + + /* current buffer */ + struct stk1160_buffer *buf; +}; + +struct stk1160_fmt { + char *name; + u32 fourcc; /* v4l2 format id */ + int depth; +}; + +struct stk1160 { + struct v4l2_device v4l2_dev; + struct video_device vdev; + struct v4l2_ctrl_handler ctrl_handler; + + struct device *dev; + struct usb_device *udev; + + /* saa7115 subdev */ + struct v4l2_subdev *sd_saa7115; + + /* isoc control struct */ + struct list_head avail_bufs; + + /* video capture */ + struct vb2_queue vb_vidq; + + /* max packet size of isoc transaction */ + int max_pkt_size; + /* array of wMaxPacketSize */ + unsigned int *alt_max_pkt_size; + /* alternate */ + int alt; + /* Number of alternative settings */ + int num_alt; + + struct stk1160_isoc_ctl isoc_ctl; + char urb_buf[255]; /* urb control msg buffer */ + + /* frame properties */ + int width; /* current frame width */ + int height; /* current frame height */ + unsigned int ctl_input; /* selected input */ + v4l2_std_id norm; /* current norm */ + struct stk1160_fmt *fmt; /* selected format */ + + unsigned int field_count; /* not sure ??? */ + enum v4l2_field field; /* also not sure :/ */ + + /* i2c i/o */ + struct i2c_adapter i2c_adap; + struct i2c_client i2c_client; + + struct mutex v4l_lock; + struct mutex vb_queue_lock; + spinlock_t buf_lock; + + struct file *fh_owner; /* filehandle ownership */ + + /* EXPERIMENTAL */ + struct snd_card *snd_card; +}; + +struct regval { + u16 reg; + u16 val; +}; + +/* Provided by stk1160-v4l.c */ +int stk1160_vb2_setup(struct stk1160 *dev); +int stk1160_video_register(struct stk1160 *dev); +void stk1160_video_unregister(struct stk1160 *dev); +void stk1160_clear_queue(struct stk1160 *dev); + +/* Provided by stk1160-video.c */ +int stk1160_alloc_isoc(struct stk1160 *dev); +void stk1160_free_isoc(struct stk1160 *dev); +void stk1160_cancel_isoc(struct stk1160 *dev); +void stk1160_uninit_isoc(struct stk1160 *dev); + +/* Provided by stk1160-i2c.c */ +int stk1160_i2c_register(struct stk1160 *dev); +int stk1160_i2c_unregister(struct stk1160 *dev); + +/* Provided by stk1160-core.c */ +int stk1160_read_reg(struct stk1160 *dev, u16 reg, u8 *value); +int stk1160_write_reg(struct stk1160 *dev, u16 reg, u16 value); +int stk1160_write_regs_req(struct stk1160 *dev, u8 req, u16 reg, + char *buf, int len); +int stk1160_read_reg_req_len(struct stk1160 *dev, u8 req, u16 reg, + char *buf, int len); +void stk1160_select_input(struct stk1160 *dev); + +/* Provided by stk1160-ac97.c */ +#ifdef CONFIG_VIDEO_STK1160_AC97 +int stk1160_ac97_register(struct stk1160 *dev); +int stk1160_ac97_unregister(struct stk1160 *dev); +#else +static inline int stk1160_ac97_register(struct stk1160 *dev) { return 0; } +static inline int stk1160_ac97_unregister(struct stk1160 *dev) { return 0; } +#endif + diff --git a/drivers/media/usb/stkwebcam/Kconfig b/drivers/media/usb/stkwebcam/Kconfig new file mode 100644 index 000000000000..a6a00aa4fce6 --- /dev/null +++ b/drivers/media/usb/stkwebcam/Kconfig @@ -0,0 +1,13 @@ +config USB_STKWEBCAM + tristate "USB Syntek DC1125 Camera support" + depends on VIDEO_V4L2 + ---help--- + Say Y here if you want to use this type of camera. + Supported devices are typically found in some Asus laptops, + with USB id 174f:a311 and 05e1:0501. Other Syntek cameras + may be supported by the stk11xx driver, from which this is + derived, see <http://sourceforge.net/projects/syntekdriver/> + + To compile this driver as a module, choose M here: the + module will be called stkwebcam. + diff --git a/drivers/media/usb/stkwebcam/Makefile b/drivers/media/usb/stkwebcam/Makefile new file mode 100644 index 000000000000..20ef8a4b990c --- /dev/null +++ b/drivers/media/usb/stkwebcam/Makefile @@ -0,0 +1,4 @@ +stkwebcam-objs := stk-webcam.o stk-sensor.o + +obj-$(CONFIG_USB_STKWEBCAM) += stkwebcam.o + diff --git a/drivers/media/video/stk-sensor.c b/drivers/media/usb/stkwebcam/stk-sensor.c index e546b014d7ad..e546b014d7ad 100644 --- a/drivers/media/video/stk-sensor.c +++ b/drivers/media/usb/stkwebcam/stk-sensor.c diff --git a/drivers/media/video/stk-webcam.c b/drivers/media/usb/stkwebcam/stk-webcam.c index 86a0fc56c330..86a0fc56c330 100644 --- a/drivers/media/video/stk-webcam.c +++ b/drivers/media/usb/stkwebcam/stk-webcam.c diff --git a/drivers/media/video/stk-webcam.h b/drivers/media/usb/stkwebcam/stk-webcam.h index 9f6736637571..9f6736637571 100644 --- a/drivers/media/video/stk-webcam.h +++ b/drivers/media/usb/stkwebcam/stk-webcam.h diff --git a/drivers/media/video/tlg2300/Kconfig b/drivers/media/usb/tlg2300/Kconfig index 645d915267e6..645d915267e6 100644 --- a/drivers/media/video/tlg2300/Kconfig +++ b/drivers/media/usb/tlg2300/Kconfig diff --git a/drivers/media/usb/tlg2300/Makefile b/drivers/media/usb/tlg2300/Makefile new file mode 100644 index 000000000000..137f8e38cdec --- /dev/null +++ b/drivers/media/usb/tlg2300/Makefile @@ -0,0 +1,9 @@ +poseidon-objs := pd-video.o pd-alsa.o pd-dvb.o pd-radio.o pd-main.o + +obj-$(CONFIG_VIDEO_TLG2300) += poseidon.o + +ccflags-y += -Idrivers/media/i2c +ccflags-y += -Idrivers/media/tuners +ccflags-y += -Idrivers/media/dvb-core +ccflags-y += -Idrivers/media/dvb-frontends + diff --git a/drivers/media/video/tlg2300/pd-alsa.c b/drivers/media/usb/tlg2300/pd-alsa.c index 9f8b7da56b67..3f3e141f70fb 100644 --- a/drivers/media/video/tlg2300/pd-alsa.c +++ b/drivers/media/usb/tlg2300/pd-alsa.c @@ -305,6 +305,10 @@ int poseidon_audio_init(struct poseidon *p) return ret; ret = snd_pcm_new(card, "poseidon audio", 0, 0, 1, &pcm); + if (ret < 0) { + snd_card_free(card); + return ret; + } snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &pcm_capture_ops); pcm->info_flags = 0; pcm->private_data = p; diff --git a/drivers/media/video/tlg2300/pd-common.h b/drivers/media/usb/tlg2300/pd-common.h index 5dd73b7857d1..5dd73b7857d1 100644 --- a/drivers/media/video/tlg2300/pd-common.h +++ b/drivers/media/usb/tlg2300/pd-common.h diff --git a/drivers/media/video/tlg2300/pd-dvb.c b/drivers/media/usb/tlg2300/pd-dvb.c index 30fcb117e898..30fcb117e898 100644 --- a/drivers/media/video/tlg2300/pd-dvb.c +++ b/drivers/media/usb/tlg2300/pd-dvb.c diff --git a/drivers/media/video/tlg2300/pd-main.c b/drivers/media/usb/tlg2300/pd-main.c index 7b1f6ebd0e2c..7b1f6ebd0e2c 100644 --- a/drivers/media/video/tlg2300/pd-main.c +++ b/drivers/media/usb/tlg2300/pd-main.c diff --git a/drivers/media/video/tlg2300/pd-radio.c b/drivers/media/usb/tlg2300/pd-radio.c index 4fad1dfb92cf..25eeb166aa0b 100644 --- a/drivers/media/video/tlg2300/pd-radio.c +++ b/drivers/media/usb/tlg2300/pd-radio.c @@ -348,7 +348,7 @@ static int vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *vt) { return vt->index > 0 ? -EINVAL : 0; } -static int vidioc_s_audio(struct file *file, void *priv, struct v4l2_audio *va) +static int vidioc_s_audio(struct file *file, void *priv, const struct v4l2_audio *va) { return (va->index != 0) ? -EINVAL : 0; } diff --git a/drivers/media/video/tlg2300/pd-video.c b/drivers/media/usb/tlg2300/pd-video.c index bfbf9e56b0a4..1f448ac7a496 100644 --- a/drivers/media/video/tlg2300/pd-video.c +++ b/drivers/media/usb/tlg2300/pd-video.c @@ -1029,7 +1029,7 @@ static int vidioc_g_audio(struct file *file, void *fh, struct v4l2_audio *a) return 0; } -static int vidioc_s_audio(struct file *file, void *fh, struct v4l2_audio *a) +static int vidioc_s_audio(struct file *file, void *fh, const struct v4l2_audio *a) { return (0 == a->index) ? 0 : -EINVAL; } diff --git a/drivers/media/video/tlg2300/vendorcmds.h b/drivers/media/usb/tlg2300/vendorcmds.h index ba6f4ae3b2c2..ba6f4ae3b2c2 100644 --- a/drivers/media/video/tlg2300/vendorcmds.h +++ b/drivers/media/usb/tlg2300/vendorcmds.h diff --git a/drivers/media/video/tm6000/Kconfig b/drivers/media/usb/tm6000/Kconfig index a43b77abd931..a43b77abd931 100644 --- a/drivers/media/video/tm6000/Kconfig +++ b/drivers/media/usb/tm6000/Kconfig diff --git a/drivers/media/video/tm6000/Makefile b/drivers/media/usb/tm6000/Makefile index 395515b4a888..f2644933b8d1 100644 --- a/drivers/media/video/tm6000/Makefile +++ b/drivers/media/usb/tm6000/Makefile @@ -9,7 +9,7 @@ obj-$(CONFIG_VIDEO_TM6000) += tm6000.o obj-$(CONFIG_VIDEO_TM6000_ALSA) += tm6000-alsa.o obj-$(CONFIG_VIDEO_TM6000_DVB) += tm6000-dvb.o -ccflags-y := -Idrivers/media/video -ccflags-y += -Idrivers/media/common/tuners -ccflags-y += -Idrivers/media/dvb/dvb-core -ccflags-y += -Idrivers/media/dvb/frontends +ccflags-y += -Idrivers/media/i2c +ccflags-y += -Idrivers/media/tuners +ccflags-y += -Idrivers/media/dvb-core +ccflags-y += -Idrivers/media/dvb-frontends diff --git a/drivers/media/video/tm6000/tm6000-alsa.c b/drivers/media/usb/tm6000/tm6000-alsa.c index bd07ec707956..813c1ec53608 100644 --- a/drivers/media/video/tm6000/tm6000-alsa.c +++ b/drivers/media/usb/tm6000/tm6000-alsa.c @@ -487,10 +487,11 @@ error: static int tm6000_audio_fini(struct tm6000_core *dev) { - struct snd_tm6000_card *chip = dev->adev; + struct snd_tm6000_card *chip; if (!dev) return 0; + chip = dev->adev; if (!chip) return 0; diff --git a/drivers/media/video/tm6000/tm6000-cards.c b/drivers/media/usb/tm6000/tm6000-cards.c index 307d8c5fb7cd..307d8c5fb7cd 100644 --- a/drivers/media/video/tm6000/tm6000-cards.c +++ b/drivers/media/usb/tm6000/tm6000-cards.c diff --git a/drivers/media/video/tm6000/tm6000-core.c b/drivers/media/usb/tm6000/tm6000-core.c index 22cc0116deb6..22cc0116deb6 100644 --- a/drivers/media/video/tm6000/tm6000-core.c +++ b/drivers/media/usb/tm6000/tm6000-core.c diff --git a/drivers/media/video/tm6000/tm6000-dvb.c b/drivers/media/usb/tm6000/tm6000-dvb.c index e1f3f66e1e63..e1f3f66e1e63 100644 --- a/drivers/media/video/tm6000/tm6000-dvb.c +++ b/drivers/media/usb/tm6000/tm6000-dvb.c diff --git a/drivers/media/video/tm6000/tm6000-i2c.c b/drivers/media/usb/tm6000/tm6000-i2c.c index c7e23e3dd75e..c7e23e3dd75e 100644 --- a/drivers/media/video/tm6000/tm6000-i2c.c +++ b/drivers/media/usb/tm6000/tm6000-i2c.c diff --git a/drivers/media/video/tm6000/tm6000-input.c b/drivers/media/usb/tm6000/tm6000-input.c index e80b7e190471..dffbd4bd47b1 100644 --- a/drivers/media/video/tm6000/tm6000-input.c +++ b/drivers/media/usb/tm6000/tm6000-input.c @@ -319,12 +319,13 @@ static int tm6000_ir_change_protocol(struct rc_dev *rc, u64 rc_type) static int __tm6000_ir_int_start(struct rc_dev *rc) { struct tm6000_IR *ir = rc->priv; - struct tm6000_core *dev = ir->dev; + struct tm6000_core *dev; int pipe, size; int err = -ENOMEM; if (!ir) return -ENODEV; + dev = ir->dev; dprintk(2, "%s\n",__func__); diff --git a/drivers/media/video/tm6000/tm6000-regs.h b/drivers/media/usb/tm6000/tm6000-regs.h index a38c251ed57b..a38c251ed57b 100644 --- a/drivers/media/video/tm6000/tm6000-regs.h +++ b/drivers/media/usb/tm6000/tm6000-regs.h diff --git a/drivers/media/video/tm6000/tm6000-stds.c b/drivers/media/usb/tm6000/tm6000-stds.c index 5e28d6a2412f..5e28d6a2412f 100644 --- a/drivers/media/video/tm6000/tm6000-stds.c +++ b/drivers/media/usb/tm6000/tm6000-stds.c diff --git a/drivers/media/video/tm6000/tm6000-usb-isoc.h b/drivers/media/usb/tm6000/tm6000-usb-isoc.h index 99d15a55aa03..99d15a55aa03 100644 --- a/drivers/media/video/tm6000/tm6000-usb-isoc.h +++ b/drivers/media/usb/tm6000/tm6000-usb-isoc.h diff --git a/drivers/media/video/tm6000/tm6000-video.c b/drivers/media/usb/tm6000/tm6000-video.c index f7034df94e0a..4342cd4f5c8a 100644 --- a/drivers/media/video/tm6000/tm6000-video.c +++ b/drivers/media/usb/tm6000/tm6000-video.c @@ -1401,7 +1401,7 @@ static int radio_g_audio(struct file *file, void *priv, } static int radio_s_audio(struct file *file, void *priv, - struct v4l2_audio *a) + const struct v4l2_audio *a) { return 0; } @@ -1448,7 +1448,7 @@ static int radio_queryctrl(struct file *file, void *priv, File operations for the device ------------------------------------------------------------------*/ -static int tm6000_open(struct file *file) +static int __tm6000_open(struct file *file) { struct video_device *vdev = video_devdata(file); struct tm6000_core *dev = video_drvdata(file); @@ -1540,23 +1540,41 @@ static int tm6000_open(struct file *file) return 0; } +static int tm6000_open(struct file *file) +{ + struct video_device *vdev = video_devdata(file); + int res; + + mutex_lock(vdev->lock); + res = __tm6000_open(file); + mutex_unlock(vdev->lock); + return res; +} + static ssize_t tm6000_read(struct file *file, char __user *data, size_t count, loff_t *pos) { - struct tm6000_fh *fh = file->private_data; + struct tm6000_fh *fh = file->private_data; + struct tm6000_core *dev = fh->dev; if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { + int res; + if (!res_get(fh->dev, fh, true)) return -EBUSY; - return videobuf_read_stream(&fh->vb_vidq, data, count, pos, 0, + if (mutex_lock_interruptible(&dev->lock)) + return -ERESTARTSYS; + res = videobuf_read_stream(&fh->vb_vidq, data, count, pos, 0, file->f_flags & O_NONBLOCK); + mutex_unlock(&dev->lock); + return res; } return 0; } static unsigned int -tm6000_poll(struct file *file, struct poll_table_struct *wait) +__tm6000_poll(struct file *file, struct poll_table_struct *wait) { struct tm6000_fh *fh = file->private_data; struct tm6000_buffer *buf; @@ -1583,6 +1601,18 @@ tm6000_poll(struct file *file, struct poll_table_struct *wait) return 0; } +static unsigned int tm6000_poll(struct file *file, struct poll_table_struct *wait) +{ + struct tm6000_fh *fh = file->private_data; + struct tm6000_core *dev = fh->dev; + unsigned int res; + + mutex_lock(&dev->lock); + res = __tm6000_poll(file, wait); + mutex_unlock(&dev->lock); + return res; +} + static int tm6000_release(struct file *file) { struct tm6000_fh *fh = file->private_data; @@ -1592,6 +1622,7 @@ static int tm6000_release(struct file *file) dprintk(dev, V4L2_DEBUG_OPEN, "tm6000: close called (dev=%s, users=%d)\n", video_device_node_name(vdev), dev->users); + mutex_lock(&dev->lock); dev->users--; res_free(dev, fh); @@ -1619,6 +1650,7 @@ static int tm6000_release(struct file *file) } kfree(fh); + mutex_unlock(&dev->lock); return 0; } @@ -1626,8 +1658,14 @@ static int tm6000_release(struct file *file) static int tm6000_mmap(struct file *file, struct vm_area_struct * vma) { struct tm6000_fh *fh = file->private_data; + struct tm6000_core *dev = fh->dev; + int res; - return videobuf_mmap_mapper(&fh->vb_vidq, vma); + if (mutex_lock_interruptible(&dev->lock)) + return -ERESTARTSYS; + res = videobuf_mmap_mapper(&fh->vb_vidq, vma); + mutex_unlock(&dev->lock); + return res; } static struct v4l2_file_operations tm6000_fops = { @@ -1724,10 +1762,6 @@ static struct video_device *vdev_init(struct tm6000_core *dev, vfd->release = video_device_release; vfd->debug = tm6000_debug; vfd->lock = &dev->lock; - /* Locking in file operations other than ioctl should be done - by the driver, not the V4L2 core. - This driver needs auditing so that this flag can be removed. */ - set_bit(V4L2_FL_LOCK_ALL_FOPS, &vfd->flags); snprintf(vfd->name, sizeof(vfd->name), "%s %s", dev->name, type_name); diff --git a/drivers/media/video/tm6000/tm6000.h b/drivers/media/usb/tm6000/tm6000.h index 6df418658c9c..6df418658c9c 100644 --- a/drivers/media/video/tm6000/tm6000.h +++ b/drivers/media/usb/tm6000/tm6000.h diff --git a/drivers/media/dvb/ttusb-budget/Kconfig b/drivers/media/usb/ttusb-budget/Kconfig index 2663ae39b886..97bad7da689c 100644 --- a/drivers/media/dvb/ttusb-budget/Kconfig +++ b/drivers/media/usb/ttusb-budget/Kconfig @@ -1,13 +1,13 @@ config DVB_TTUSB_BUDGET tristate "Technotrend/Hauppauge Nova-USB devices" depends on DVB_CORE && USB && I2C && PCI - select DVB_CX22700 if !DVB_FE_CUSTOMISE - select DVB_TDA1004X if !DVB_FE_CUSTOMISE - select DVB_VES1820 if !DVB_FE_CUSTOMISE - select DVB_TDA8083 if !DVB_FE_CUSTOMISE - select DVB_STV0299 if !DVB_FE_CUSTOMISE - select DVB_STV0297 if !DVB_FE_CUSTOMISE - select DVB_LNBP21 if !DVB_FE_CUSTOMISE + select DVB_CX22700 if MEDIA_SUBDRV_AUTOSELECT + select DVB_TDA1004X if MEDIA_SUBDRV_AUTOSELECT + select DVB_VES1820 if MEDIA_SUBDRV_AUTOSELECT + select DVB_TDA8083 if MEDIA_SUBDRV_AUTOSELECT + select DVB_STV0299 if MEDIA_SUBDRV_AUTOSELECT + select DVB_STV0297 if MEDIA_SUBDRV_AUTOSELECT + select DVB_LNBP21 if MEDIA_SUBDRV_AUTOSELECT help Support for external USB adapters designed by Technotrend and produced by Hauppauge, shipped under the brand name 'Nova-USB'. diff --git a/drivers/media/usb/ttusb-budget/Makefile b/drivers/media/usb/ttusb-budget/Makefile new file mode 100644 index 000000000000..f47bbf62dcde --- /dev/null +++ b/drivers/media/usb/ttusb-budget/Makefile @@ -0,0 +1,3 @@ +obj-$(CONFIG_DVB_TTUSB_BUDGET) += dvb-ttusb-budget.o + +ccflags-y += -Idrivers/media/dvb-core/ -Idrivers/media/dvb-frontends diff --git a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c b/drivers/media/usb/ttusb-budget/dvb-ttusb-budget.c index 5b682cc4c814..5b682cc4c814 100644 --- a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c +++ b/drivers/media/usb/ttusb-budget/dvb-ttusb-budget.c diff --git a/drivers/media/dvb/ttusb-dec/Kconfig b/drivers/media/usb/ttusb-dec/Kconfig index 290254ab06db..290254ab06db 100644 --- a/drivers/media/dvb/ttusb-dec/Kconfig +++ b/drivers/media/usb/ttusb-dec/Kconfig diff --git a/drivers/media/dvb/ttusb-dec/Makefile b/drivers/media/usb/ttusb-dec/Makefile index ed28b5384d20..5352740d2353 100644 --- a/drivers/media/dvb/ttusb-dec/Makefile +++ b/drivers/media/usb/ttusb-dec/Makefile @@ -1,3 +1,3 @@ obj-$(CONFIG_DVB_TTUSB_DEC) += ttusb_dec.o ttusbdecfe.o -ccflags-y += -Idrivers/media/dvb/dvb-core/ +ccflags-y += -Idrivers/media/dvb-core/ diff --git a/drivers/media/dvb/ttusb-dec/ttusb_dec.c b/drivers/media/usb/ttusb-dec/ttusb_dec.c index 504c81230339..504c81230339 100644 --- a/drivers/media/dvb/ttusb-dec/ttusb_dec.c +++ b/drivers/media/usb/ttusb-dec/ttusb_dec.c diff --git a/drivers/media/dvb/ttusb-dec/ttusbdecfe.c b/drivers/media/usb/ttusb-dec/ttusbdecfe.c index 5c45c9d0712d..5c45c9d0712d 100644 --- a/drivers/media/dvb/ttusb-dec/ttusbdecfe.c +++ b/drivers/media/usb/ttusb-dec/ttusbdecfe.c diff --git a/drivers/media/dvb/ttusb-dec/ttusbdecfe.h b/drivers/media/usb/ttusb-dec/ttusbdecfe.h index 15ccc3d1a20e..15ccc3d1a20e 100644 --- a/drivers/media/dvb/ttusb-dec/ttusbdecfe.h +++ b/drivers/media/usb/ttusb-dec/ttusbdecfe.h diff --git a/drivers/media/video/usbvision/Kconfig b/drivers/media/usb/usbvision/Kconfig index fc24ef05b3f3..6b6afc5d8f7e 100644 --- a/drivers/media/video/usbvision/Kconfig +++ b/drivers/media/usb/usbvision/Kconfig @@ -2,7 +2,7 @@ config VIDEO_USBVISION tristate "USB video devices based on Nogatech NT1003/1004/1005" depends on I2C && VIDEO_V4L2 select VIDEO_TUNER - select VIDEO_SAA711X if VIDEO_HELPER_CHIPS_AUTO + select VIDEO_SAA711X if MEDIA_SUBDRV_AUTOSELECT ---help--- There are more than 50 different USB video devices based on NT1003/1004/1005 USB Bridges. This driver enables using those diff --git a/drivers/media/video/usbvision/Makefile b/drivers/media/usb/usbvision/Makefile index aea1e3b5f06b..9b3a5581df42 100644 --- a/drivers/media/video/usbvision/Makefile +++ b/drivers/media/usb/usbvision/Makefile @@ -2,5 +2,5 @@ usbvision-objs := usbvision-core.o usbvision-video.o usbvision-i2c.o usbvision- obj-$(CONFIG_VIDEO_USBVISION) += usbvision.o -ccflags-y += -Idrivers/media/video -ccflags-y += -Idrivers/media/common/tuners +ccflags-y += -Idrivers/media/i2c +ccflags-y += -Idrivers/media/tuners diff --git a/drivers/media/video/usbvision/usbvision-cards.c b/drivers/media/usb/usbvision/usbvision-cards.c index 3103d0d020e8..3103d0d020e8 100644 --- a/drivers/media/video/usbvision/usbvision-cards.c +++ b/drivers/media/usb/usbvision/usbvision-cards.c diff --git a/drivers/media/video/usbvision/usbvision-cards.h b/drivers/media/usb/usbvision/usbvision-cards.h index a51cc1185cce..a51cc1185cce 100644 --- a/drivers/media/video/usbvision/usbvision-cards.h +++ b/drivers/media/usb/usbvision/usbvision-cards.h diff --git a/drivers/media/video/usbvision/usbvision-core.c b/drivers/media/usb/usbvision/usbvision-core.c index c9b2042f8bdf..c9b2042f8bdf 100644 --- a/drivers/media/video/usbvision/usbvision-core.c +++ b/drivers/media/usb/usbvision/usbvision-core.c diff --git a/drivers/media/video/usbvision/usbvision-i2c.c b/drivers/media/usb/usbvision/usbvision-i2c.c index 89fec029e924..89fec029e924 100644 --- a/drivers/media/video/usbvision/usbvision-i2c.c +++ b/drivers/media/usb/usbvision/usbvision-i2c.c diff --git a/drivers/media/video/usbvision/usbvision-video.c b/drivers/media/usb/usbvision/usbvision-video.c index 9bd8f084f348..f67018ed3795 100644 --- a/drivers/media/video/usbvision/usbvision-video.c +++ b/drivers/media/usb/usbvision/usbvision-video.c @@ -349,6 +349,8 @@ static int usbvision_v4l2_open(struct file *file) PDEBUG(DBG_IO, "open"); + if (mutex_lock_interruptible(&usbvision->v4l2_lock)) + return -ERESTARTSYS; usbvision_reset_power_off_timer(usbvision); if (usbvision->user) @@ -402,6 +404,7 @@ static int usbvision_v4l2_open(struct file *file) /* prepare queues */ usbvision_empty_framequeues(usbvision); + mutex_unlock(&usbvision->v4l2_lock); PDEBUG(DBG_IO, "success"); return err_code; @@ -421,6 +424,7 @@ static int usbvision_v4l2_close(struct file *file) PDEBUG(DBG_IO, "close"); + mutex_lock(&usbvision->v4l2_lock); usbvision_audio_off(usbvision); usbvision_restart_isoc(usbvision); usbvision_stop_isoc(usbvision); @@ -443,6 +447,7 @@ static int usbvision_v4l2_close(struct file *file) printk(KERN_INFO "%s: Final disconnect\n", __func__); usbvision_release(usbvision); } + mutex_unlock(&usbvision->v4l2_lock); PDEBUG(DBG_IO, "success"); return 0; @@ -679,7 +684,7 @@ static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a) } static int vidioc_s_audio(struct file *file, void *fh, - struct v4l2_audio *a) + const struct v4l2_audio *a) { if (a->index) return -EINVAL; @@ -956,7 +961,7 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, return 0; } -static ssize_t usbvision_v4l2_read(struct file *file, char __user *buf, +static ssize_t usbvision_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { struct usb_usbvision *usbvision = video_drvdata(file); @@ -1060,7 +1065,20 @@ static ssize_t usbvision_v4l2_read(struct file *file, char __user *buf, return count; } -static int usbvision_v4l2_mmap(struct file *file, struct vm_area_struct *vma) +static ssize_t usbvision_v4l2_read(struct file *file, char __user *buf, + size_t count, loff_t *ppos) +{ + struct usb_usbvision *usbvision = video_drvdata(file); + int res; + + if (mutex_lock_interruptible(&usbvision->v4l2_lock)) + return -ERESTARTSYS; + res = usbvision_read(file, buf, count, ppos); + mutex_unlock(&usbvision->v4l2_lock); + return res; +} + +static int usbvision_mmap(struct file *file, struct vm_area_struct *vma) { unsigned long size = vma->vm_end - vma->vm_start, start = vma->vm_start; @@ -1107,6 +1125,17 @@ static int usbvision_v4l2_mmap(struct file *file, struct vm_area_struct *vma) return 0; } +static int usbvision_v4l2_mmap(struct file *file, struct vm_area_struct *vma) +{ + struct usb_usbvision *usbvision = video_drvdata(file); + int res; + + if (mutex_lock_interruptible(&usbvision->v4l2_lock)) + return -ERESTARTSYS; + res = usbvision_mmap(file, vma); + mutex_unlock(&usbvision->v4l2_lock); + return res; +} /* * Here comes the stuff for radio on usbvision based devices @@ -1119,6 +1148,8 @@ static int usbvision_radio_open(struct file *file) PDEBUG(DBG_IO, "%s:", __func__); + if (mutex_lock_interruptible(&usbvision->v4l2_lock)) + return -ERESTARTSYS; if (usbvision->user) { dev_err(&usbvision->rdev->dev, "%s: Someone tried to open an already opened USBVision Radio!\n", @@ -1156,6 +1187,7 @@ static int usbvision_radio_open(struct file *file) } } out: + mutex_unlock(&usbvision->v4l2_lock); return err_code; } @@ -1167,6 +1199,7 @@ static int usbvision_radio_close(struct file *file) PDEBUG(DBG_IO, ""); + mutex_lock(&usbvision->v4l2_lock); /* Set packet size to 0 */ usbvision->iface_alt = 0; err_code = usb_set_interface(usbvision->dev, usbvision->iface, @@ -1186,6 +1219,7 @@ static int usbvision_radio_close(struct file *file) usbvision_release(usbvision); } + mutex_unlock(&usbvision->v4l2_lock); PDEBUG(DBG_IO, "success"); return err_code; } @@ -1296,10 +1330,6 @@ static struct video_device *usbvision_vdev_init(struct usb_usbvision *usbvision, if (NULL == vdev) return NULL; *vdev = *vdev_template; - /* Locking in file operations other than ioctl should be done - by the driver, not the V4L2 core. - This driver needs auditing so that this flag can be removed. */ - set_bit(V4L2_FL_LOCK_ALL_FOPS, &vdev->flags); vdev->lock = &usbvision->v4l2_lock; vdev->v4l2_dev = &usbvision->v4l2_dev; snprintf(vdev->name, sizeof(vdev->name), "%s", name); diff --git a/drivers/media/video/usbvision/usbvision.h b/drivers/media/usb/usbvision/usbvision.h index 43cf61fe4943..43cf61fe4943 100644 --- a/drivers/media/video/usbvision/usbvision.h +++ b/drivers/media/usb/usbvision/usbvision.h diff --git a/drivers/media/video/uvc/Kconfig b/drivers/media/usb/uvc/Kconfig index 541c9f1e4c6a..541c9f1e4c6a 100644 --- a/drivers/media/video/uvc/Kconfig +++ b/drivers/media/usb/uvc/Kconfig diff --git a/drivers/media/video/uvc/Makefile b/drivers/media/usb/uvc/Makefile index c26d12fdb8f4..c26d12fdb8f4 100644 --- a/drivers/media/video/uvc/Makefile +++ b/drivers/media/usb/uvc/Makefile diff --git a/drivers/media/video/uvc/uvc_ctrl.c b/drivers/media/usb/uvc/uvc_ctrl.c index f7061a5ef1d2..f7061a5ef1d2 100644 --- a/drivers/media/video/uvc/uvc_ctrl.c +++ b/drivers/media/usb/uvc/uvc_ctrl.c diff --git a/drivers/media/video/uvc/uvc_debugfs.c b/drivers/media/usb/uvc/uvc_debugfs.c index 14561a5abb79..14561a5abb79 100644 --- a/drivers/media/video/uvc/uvc_debugfs.c +++ b/drivers/media/usb/uvc/uvc_debugfs.c diff --git a/drivers/media/video/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c index 1d131720b6d7..5967081747ce 100644 --- a/drivers/media/video/uvc/uvc_driver.c +++ b/drivers/media/usb/uvc/uvc_driver.c @@ -11,18 +11,6 @@ * */ -/* - * This driver aims to support video input and ouput devices compliant with the - * 'USB Video Class' specification. - * - * The driver doesn't support the deprecated v4l1 interface. It implements the - * mmap capture method only, and doesn't do any image format conversion in - * software. If your user-space application doesn't support YUYV or MJPEG, fix - * it :-). Please note that the MJPEG data have been stripped from their - * Huffman tables (DHT marker), you will need to add it back if your JPEG - * codec can't handle MJPEG data. - */ - #include <linux/atomic.h> #include <linux/kernel.h> #include <linux/list.h> @@ -95,12 +83,27 @@ static struct uvc_format_desc uvc_fmts[] = { .fcc = V4L2_PIX_FMT_UYVY, }, { - .name = "Greyscale (8-bit)", + .name = "Greyscale 8-bit (Y800)", .guid = UVC_GUID_FORMAT_Y800, .fcc = V4L2_PIX_FMT_GREY, }, { - .name = "Greyscale (16-bit)", + .name = "Greyscale 8-bit (Y8 )", + .guid = UVC_GUID_FORMAT_Y8, + .fcc = V4L2_PIX_FMT_GREY, + }, + { + .name = "Greyscale 10-bit (Y10 )", + .guid = UVC_GUID_FORMAT_Y10, + .fcc = V4L2_PIX_FMT_Y10, + }, + { + .name = "Greyscale 12-bit (Y12 )", + .guid = UVC_GUID_FORMAT_Y12, + .fcc = V4L2_PIX_FMT_Y12, + }, + { + .name = "Greyscale 16-bit (Y16 )", .guid = UVC_GUID_FORMAT_Y16, .fcc = V4L2_PIX_FMT_Y16, }, @@ -1719,6 +1722,8 @@ static int uvc_register_video(struct uvc_device *dev, vdev->v4l2_dev = &dev->vdev; vdev->fops = &uvc_fops; vdev->release = uvc_release; + if (stream->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) + vdev->vfl_dir = VFL_DIR_TX; strlcpy(vdev->name, dev->name, sizeof vdev->name); /* Set the driver data before calling video_register_device, otherwise @@ -2212,6 +2217,15 @@ static struct usb_device_id uvc_ids[] = { .bInterfaceSubClass = 1, .bInterfaceProtocol = 0, .driver_info = UVC_QUIRK_FIX_BANDWIDTH }, + /* Ophir Optronics - SPCAM 620U */ + { .match_flags = USB_DEVICE_ID_MATCH_DEVICE + | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = 0x0bd3, + .idProduct = 0x0555, + .bInterfaceClass = USB_CLASS_VIDEO, + .bInterfaceSubClass = 1, + .bInterfaceProtocol = 0, + .driver_info = UVC_QUIRK_PROBE_MINMAX }, /* MT6227 */ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, diff --git a/drivers/media/video/uvc/uvc_entity.c b/drivers/media/usb/uvc/uvc_entity.c index 29e239911d0e..29e239911d0e 100644 --- a/drivers/media/video/uvc/uvc_entity.c +++ b/drivers/media/usb/uvc/uvc_entity.c diff --git a/drivers/media/video/uvc/uvc_isight.c b/drivers/media/usb/uvc/uvc_isight.c index 8510e7259e76..8510e7259e76 100644 --- a/drivers/media/video/uvc/uvc_isight.c +++ b/drivers/media/usb/uvc/uvc_isight.c diff --git a/drivers/media/video/uvc/uvc_queue.c b/drivers/media/usb/uvc/uvc_queue.c index 5577381b5bf0..5577381b5bf0 100644 --- a/drivers/media/video/uvc/uvc_queue.c +++ b/drivers/media/usb/uvc/uvc_queue.c diff --git a/drivers/media/video/uvc/uvc_status.c b/drivers/media/usb/uvc/uvc_status.c index b7492775e6ae..b7492775e6ae 100644 --- a/drivers/media/video/uvc/uvc_status.c +++ b/drivers/media/usb/uvc/uvc_status.c diff --git a/drivers/media/video/uvc/uvc_v4l2.c b/drivers/media/usb/uvc/uvc_v4l2.c index f00db3060e0e..f00db3060e0e 100644 --- a/drivers/media/video/uvc/uvc_v4l2.c +++ b/drivers/media/usb/uvc/uvc_v4l2.c diff --git a/drivers/media/video/uvc/uvc_video.c b/drivers/media/usb/uvc/uvc_video.c index 7ac4347ca09e..1c15b4227bdb 100644 --- a/drivers/media/video/uvc/uvc_video.c +++ b/drivers/media/usb/uvc/uvc_video.c @@ -1439,6 +1439,26 @@ static void uvc_uninit_video(struct uvc_streaming *stream, int free_buffers) } /* + * Compute the maximum number of bytes per interval for an endpoint. + */ +static unsigned int uvc_endpoint_max_bpi(struct usb_device *dev, + struct usb_host_endpoint *ep) +{ + u16 psize; + + switch (dev->speed) { + case USB_SPEED_SUPER: + return ep->ss_ep_comp.wBytesPerInterval; + case USB_SPEED_HIGH: + psize = usb_endpoint_maxp(&ep->desc); + return (psize & 0x07ff) * (1 + ((psize >> 11) & 3)); + default: + psize = usb_endpoint_maxp(&ep->desc); + return psize & 0x07ff; + } +} + +/* * Initialize isochronous URBs and allocate transfer buffers. The packet size * is given by the endpoint. */ @@ -1450,8 +1470,7 @@ static int uvc_init_video_isoc(struct uvc_streaming *stream, u16 psize; u32 size; - psize = le16_to_cpu(ep->desc.wMaxPacketSize); - psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3)); + psize = uvc_endpoint_max_bpi(stream->dev->udev, ep); size = stream->ctrl.dwMaxVideoFrameSize; npackets = uvc_alloc_urb_buffers(stream, size, psize, gfp_flags); @@ -1506,7 +1525,7 @@ static int uvc_init_video_bulk(struct uvc_streaming *stream, u16 psize; u32 size; - psize = le16_to_cpu(ep->desc.wMaxPacketSize) & 0x07ff; + psize = usb_endpoint_maxp(&ep->desc) & 0x7ff; size = stream->ctrl.dwMaxPayloadTransferSize; stream->bulk.max_payload_size = size; @@ -1567,7 +1586,7 @@ static int uvc_init_video(struct uvc_streaming *stream, gfp_t gfp_flags) if (intf->num_altsetting > 1) { struct usb_host_endpoint *best_ep = NULL; - unsigned int best_psize = 3 * 1024; + unsigned int best_psize = UINT_MAX; unsigned int bandwidth; unsigned int uninitialized_var(altsetting); int intfnum = stream->intfnum; @@ -1595,8 +1614,7 @@ static int uvc_init_video(struct uvc_streaming *stream, gfp_t gfp_flags) continue; /* Check if the bandwidth is high enough. */ - psize = le16_to_cpu(ep->desc.wMaxPacketSize); - psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3)); + psize = uvc_endpoint_max_bpi(stream->dev->udev, ep); if (psize >= bandwidth && psize <= best_psize) { altsetting = alts->desc.bAlternateSetting; best_psize = psize; diff --git a/drivers/media/video/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h index 7c3d082505b7..3764040475bb 100644 --- a/drivers/media/video/uvc/uvcvideo.h +++ b/drivers/media/usb/uvc/uvcvideo.h @@ -79,6 +79,15 @@ #define UVC_GUID_FORMAT_Y800 \ { 'Y', '8', '0', '0', 0x00, 0x00, 0x10, 0x00, \ 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71} +#define UVC_GUID_FORMAT_Y8 \ + { 'Y', '8', ' ', ' ', 0x00, 0x00, 0x10, 0x00, \ + 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71} +#define UVC_GUID_FORMAT_Y10 \ + { 'Y', '1', '0', ' ', 0x00, 0x00, 0x10, 0x00, \ + 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71} +#define UVC_GUID_FORMAT_Y12 \ + { 'Y', '1', '2', ' ', 0x00, 0x00, 0x10, 0x00, \ + 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71} #define UVC_GUID_FORMAT_Y16 \ { 'Y', '1', '6', ' ', 0x00, 0x00, 0x10, 0x00, \ 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71} diff --git a/drivers/media/usb/zr364xx/Kconfig b/drivers/media/usb/zr364xx/Kconfig new file mode 100644 index 000000000000..0f585662881d --- /dev/null +++ b/drivers/media/usb/zr364xx/Kconfig @@ -0,0 +1,14 @@ +config USB_ZR364XX + tristate "USB ZR364XX Camera support" + depends on VIDEO_V4L2 + select VIDEOBUF_GEN + select VIDEOBUF_VMALLOC + ---help--- + Say Y here if you want to connect this type of camera to your + computer's USB port. + See <file:Documentation/video4linux/zr364xx.txt> for more info + and list of supported cameras. + + To compile this driver as a module, choose M here: the + module will be called zr364xx. + diff --git a/drivers/media/usb/zr364xx/Makefile b/drivers/media/usb/zr364xx/Makefile new file mode 100644 index 000000000000..a5777883a1f8 --- /dev/null +++ b/drivers/media/usb/zr364xx/Makefile @@ -0,0 +1,2 @@ +obj-$(CONFIG_USB_ZR364XX) += zr364xx.o + diff --git a/drivers/media/video/zr364xx.c b/drivers/media/usb/zr364xx/zr364xx.c index 9afab35878b4..9afab35878b4 100644 --- a/drivers/media/video/zr364xx.c +++ b/drivers/media/usb/zr364xx/zr364xx.c diff --git a/drivers/media/v4l2-core/Kconfig b/drivers/media/v4l2-core/Kconfig new file mode 100644 index 000000000000..0c54e19d9944 --- /dev/null +++ b/drivers/media/v4l2-core/Kconfig @@ -0,0 +1,81 @@ +# +# Generic video config states +# + +# Enable the V4L2 core and API +config VIDEO_V4L2 + tristate + depends on (I2C || I2C=n) && VIDEO_DEV + default (I2C || I2C=n) && VIDEO_DEV + +config VIDEO_ADV_DEBUG + bool "Enable advanced debug functionality on V4L2 drivers" + default n + ---help--- + Say Y here to enable advanced debugging functionality on some + V4L devices. + In doubt, say N. + +config VIDEO_FIXED_MINOR_RANGES + bool "Enable old-style fixed minor ranges on drivers/video devices" + default n + ---help--- + Say Y here to enable the old-style fixed-range minor assignments. + Only useful if you rely on the old behavior and use mknod instead of udev. + + When in doubt, say N. + +# Used by drivers that need tuner.ko +config VIDEO_TUNER + tristate + depends on MEDIA_TUNER + +# Used by drivers that need v4l2-mem2mem.ko +config V4L2_MEM2MEM_DEV + tristate + depends on VIDEOBUF2_CORE + +# Used by drivers that need Videobuf modules +config VIDEOBUF_GEN + tristate + +config VIDEOBUF_DMA_SG + tristate + depends on HAS_DMA + select VIDEOBUF_GEN + +config VIDEOBUF_VMALLOC + tristate + select VIDEOBUF_GEN + +config VIDEOBUF_DMA_CONTIG + tristate + depends on HAS_DMA + select VIDEOBUF_GEN + +config VIDEOBUF_DVB + tristate + select VIDEOBUF_GEN + +# Used by drivers that need Videobuf2 modules +config VIDEOBUF2_CORE + tristate + +config VIDEOBUF2_MEMOPS + tristate + +config VIDEOBUF2_DMA_CONTIG + tristate + select VIDEOBUF2_CORE + select VIDEOBUF2_MEMOPS + +config VIDEOBUF2_VMALLOC + tristate + select VIDEOBUF2_CORE + select VIDEOBUF2_MEMOPS + +config VIDEOBUF2_DMA_SG + tristate + #depends on HAS_DMA + select VIDEOBUF2_CORE + select VIDEOBUF2_MEMOPS diff --git a/drivers/media/v4l2-core/Makefile b/drivers/media/v4l2-core/Makefile new file mode 100644 index 000000000000..c2d61d4f03d1 --- /dev/null +++ b/drivers/media/v4l2-core/Makefile @@ -0,0 +1,35 @@ +# +# Makefile for the V4L2 core +# + +tuner-objs := tuner-core.o + +videodev-objs := v4l2-dev.o v4l2-ioctl.o v4l2-device.o v4l2-fh.o \ + v4l2-event.o v4l2-ctrls.o v4l2-subdev.o +ifeq ($(CONFIG_COMPAT),y) + videodev-objs += v4l2-compat-ioctl32.o +endif + +obj-$(CONFIG_VIDEO_DEV) += videodev.o v4l2-int-device.o +obj-$(CONFIG_VIDEO_V4L2) += v4l2-common.o + +obj-$(CONFIG_VIDEO_TUNER) += tuner.o + +obj-$(CONFIG_V4L2_MEM2MEM_DEV) += v4l2-mem2mem.o + +obj-$(CONFIG_VIDEOBUF_GEN) += videobuf-core.o +obj-$(CONFIG_VIDEOBUF_DMA_SG) += videobuf-dma-sg.o +obj-$(CONFIG_VIDEOBUF_DMA_CONTIG) += videobuf-dma-contig.o +obj-$(CONFIG_VIDEOBUF_VMALLOC) += videobuf-vmalloc.o +obj-$(CONFIG_VIDEOBUF_DVB) += videobuf-dvb.o + +obj-$(CONFIG_VIDEOBUF2_CORE) += videobuf2-core.o +obj-$(CONFIG_VIDEOBUF2_MEMOPS) += videobuf2-memops.o +obj-$(CONFIG_VIDEOBUF2_VMALLOC) += videobuf2-vmalloc.o +obj-$(CONFIG_VIDEOBUF2_DMA_CONTIG) += videobuf2-dma-contig.o +obj-$(CONFIG_VIDEOBUF2_DMA_SG) += videobuf2-dma-sg.o + +ccflags-y += -I$(srctree)/drivers/media/dvb-core +ccflags-y += -I$(srctree)/drivers/media/dvb-frontends +ccflags-y += -I$(srctree)/drivers/media/tuners + diff --git a/drivers/media/video/tuner-core.c b/drivers/media/v4l2-core/tuner-core.c index b5a819af2b8c..b5a819af2b8c 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/v4l2-core/tuner-core.c diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/v4l2-core/v4l2-common.c index 1baec8393306..f995dd31151d 100644 --- a/drivers/media/video/v4l2-common.c +++ b/drivers/media/v4l2-core/v4l2-common.c @@ -418,7 +418,7 @@ EXPORT_SYMBOL_GPL(v4l2_i2c_tuner_addrs); #if defined(CONFIG_SPI) -/* Load a spi sub-device. */ +/* Load an spi sub-device. */ void v4l2_spi_subdev_init(struct v4l2_subdev *sd, struct spi_device *spi, const struct v4l2_subdev_ops *ops) @@ -443,7 +443,7 @@ struct v4l2_subdev *v4l2_spi_new_subdev(struct v4l2_device *v4l2_dev, BUG_ON(!v4l2_dev); - if (info->modalias) + if (info->modalias[0]) request_module(info->modalias); spi = spi_new_device(master, info); @@ -597,6 +597,364 @@ int v4l_fill_dv_preset_info(u32 preset, struct v4l2_dv_enum_preset *info) } EXPORT_SYMBOL_GPL(v4l_fill_dv_preset_info); +/** + * v4l_match_dv_timings - check if two timings match + * @t1 - compare this v4l2_dv_timings struct... + * @t2 - with this struct. + * @pclock_delta - the allowed pixelclock deviation. + * + * Compare t1 with t2 with a given margin of error for the pixelclock. + */ +bool v4l_match_dv_timings(const struct v4l2_dv_timings *t1, + const struct v4l2_dv_timings *t2, + unsigned pclock_delta) +{ + if (t1->type != t2->type || t1->type != V4L2_DV_BT_656_1120) + return false; + if (t1->bt.width == t2->bt.width && + t1->bt.height == t2->bt.height && + t1->bt.interlaced == t2->bt.interlaced && + t1->bt.polarities == t2->bt.polarities && + t1->bt.pixelclock >= t2->bt.pixelclock - pclock_delta && + t1->bt.pixelclock <= t2->bt.pixelclock + pclock_delta && + t1->bt.hfrontporch == t2->bt.hfrontporch && + t1->bt.vfrontporch == t2->bt.vfrontporch && + t1->bt.vsync == t2->bt.vsync && + t1->bt.vbackporch == t2->bt.vbackporch && + (!t1->bt.interlaced || + (t1->bt.il_vfrontporch == t2->bt.il_vfrontporch && + t1->bt.il_vsync == t2->bt.il_vsync && + t1->bt.il_vbackporch == t2->bt.il_vbackporch))) + return true; + return false; +} +EXPORT_SYMBOL_GPL(v4l_match_dv_timings); + +/* + * CVT defines + * Based on Coordinated Video Timings Standard + * version 1.1 September 10, 2003 + */ + +#define CVT_PXL_CLK_GRAN 250000 /* pixel clock granularity */ + +/* Normal blanking */ +#define CVT_MIN_V_BPORCH 7 /* lines */ +#define CVT_MIN_V_PORCH_RND 3 /* lines */ +#define CVT_MIN_VSYNC_BP 550 /* min time of vsync + back porch (us) */ + +/* Normal blanking for CVT uses GTF to calculate horizontal blanking */ +#define CVT_CELL_GRAN 8 /* character cell granularity */ +#define CVT_M 600 /* blanking formula gradient */ +#define CVT_C 40 /* blanking formula offset */ +#define CVT_K 128 /* blanking formula scaling factor */ +#define CVT_J 20 /* blanking formula scaling factor */ +#define CVT_C_PRIME (((CVT_C - CVT_J) * CVT_K / 256) + CVT_J) +#define CVT_M_PRIME (CVT_K * CVT_M / 256) + +/* Reduced Blanking */ +#define CVT_RB_MIN_V_BPORCH 7 /* lines */ +#define CVT_RB_V_FPORCH 3 /* lines */ +#define CVT_RB_MIN_V_BLANK 460 /* us */ +#define CVT_RB_H_SYNC 32 /* pixels */ +#define CVT_RB_H_BPORCH 80 /* pixels */ +#define CVT_RB_H_BLANK 160 /* pixels */ + +/** v4l2_detect_cvt - detect if the given timings follow the CVT standard + * @frame_height - the total height of the frame (including blanking) in lines. + * @hfreq - the horizontal frequency in Hz. + * @vsync - the height of the vertical sync in lines. + * @polarities - the horizontal and vertical polarities (same as struct + * v4l2_bt_timings polarities). + * @fmt - the resulting timings. + * + * This function will attempt to detect if the given values correspond to a + * valid CVT format. If so, then it will return true, and fmt will be filled + * in with the found CVT timings. + */ +bool v4l2_detect_cvt(unsigned frame_height, unsigned hfreq, unsigned vsync, + u32 polarities, struct v4l2_dv_timings *fmt) +{ + int v_fp, v_bp, h_fp, h_bp, hsync; + int frame_width, image_height, image_width; + bool reduced_blanking; + unsigned pix_clk; + + if (vsync < 4 || vsync > 7) + return false; + + if (polarities == V4L2_DV_VSYNC_POS_POL) + reduced_blanking = false; + else if (polarities == V4L2_DV_HSYNC_POS_POL) + reduced_blanking = true; + else + return false; + + /* Vertical */ + if (reduced_blanking) { + v_fp = CVT_RB_V_FPORCH; + v_bp = (CVT_RB_MIN_V_BLANK * hfreq + 999999) / 1000000; + v_bp -= vsync + v_fp; + + if (v_bp < CVT_RB_MIN_V_BPORCH) + v_bp = CVT_RB_MIN_V_BPORCH; + } else { + v_fp = CVT_MIN_V_PORCH_RND; + v_bp = (CVT_MIN_VSYNC_BP * hfreq + 999999) / 1000000 - vsync; + + if (v_bp < CVT_MIN_V_BPORCH) + v_bp = CVT_MIN_V_BPORCH; + } + image_height = (frame_height - v_fp - vsync - v_bp + 1) & ~0x1; + + /* Aspect ratio based on vsync */ + switch (vsync) { + case 4: + image_width = (image_height * 4) / 3; + break; + case 5: + image_width = (image_height * 16) / 9; + break; + case 6: + image_width = (image_height * 16) / 10; + break; + case 7: + /* special case */ + if (image_height == 1024) + image_width = (image_height * 5) / 4; + else if (image_height == 768) + image_width = (image_height * 15) / 9; + else + return false; + break; + default: + return false; + } + + image_width = image_width & ~7; + + /* Horizontal */ + if (reduced_blanking) { + pix_clk = (image_width + CVT_RB_H_BLANK) * hfreq; + pix_clk = (pix_clk / CVT_PXL_CLK_GRAN) * CVT_PXL_CLK_GRAN; + + h_bp = CVT_RB_H_BPORCH; + hsync = CVT_RB_H_SYNC; + h_fp = CVT_RB_H_BLANK - h_bp - hsync; + + frame_width = image_width + CVT_RB_H_BLANK; + } else { + int h_blank; + unsigned ideal_duty_cycle = CVT_C_PRIME - (CVT_M_PRIME * 1000) / hfreq; + + h_blank = (image_width * ideal_duty_cycle + (100 - ideal_duty_cycle) / 2) / + (100 - ideal_duty_cycle); + h_blank = h_blank - h_blank % (2 * CVT_CELL_GRAN); + + if (h_blank * 100 / image_width < 20) { + h_blank = image_width / 5; + h_blank = (h_blank + 0x7) & ~0x7; + } + + pix_clk = (image_width + h_blank) * hfreq; + pix_clk = (pix_clk / CVT_PXL_CLK_GRAN) * CVT_PXL_CLK_GRAN; + + h_bp = h_blank / 2; + frame_width = image_width + h_blank; + + hsync = (frame_width * 8 + 50) / 100; + hsync = hsync - hsync % CVT_CELL_GRAN; + h_fp = h_blank - hsync - h_bp; + } + + fmt->bt.polarities = polarities; + fmt->bt.width = image_width; + fmt->bt.height = image_height; + fmt->bt.hfrontporch = h_fp; + fmt->bt.vfrontporch = v_fp; + fmt->bt.hsync = hsync; + fmt->bt.vsync = vsync; + fmt->bt.hbackporch = frame_width - image_width - h_fp - hsync; + fmt->bt.vbackporch = frame_height - image_height - v_fp - vsync; + fmt->bt.pixelclock = pix_clk; + fmt->bt.standards = V4L2_DV_BT_STD_CVT; + if (reduced_blanking) + fmt->bt.flags |= V4L2_DV_FL_REDUCED_BLANKING; + return true; +} +EXPORT_SYMBOL_GPL(v4l2_detect_cvt); + +/* + * GTF defines + * Based on Generalized Timing Formula Standard + * Version 1.1 September 2, 1999 + */ + +#define GTF_PXL_CLK_GRAN 250000 /* pixel clock granularity */ + +#define GTF_MIN_VSYNC_BP 550 /* min time of vsync + back porch (us) */ +#define GTF_V_FP 1 /* vertical front porch (lines) */ +#define GTF_CELL_GRAN 8 /* character cell granularity */ + +/* Default */ +#define GTF_D_M 600 /* blanking formula gradient */ +#define GTF_D_C 40 /* blanking formula offset */ +#define GTF_D_K 128 /* blanking formula scaling factor */ +#define GTF_D_J 20 /* blanking formula scaling factor */ +#define GTF_D_C_PRIME ((((GTF_D_C - GTF_D_J) * GTF_D_K) / 256) + GTF_D_J) +#define GTF_D_M_PRIME ((GTF_D_K * GTF_D_M) / 256) + +/* Secondary */ +#define GTF_S_M 3600 /* blanking formula gradient */ +#define GTF_S_C 40 /* blanking formula offset */ +#define GTF_S_K 128 /* blanking formula scaling factor */ +#define GTF_S_J 35 /* blanking formula scaling factor */ +#define GTF_S_C_PRIME ((((GTF_S_C - GTF_S_J) * GTF_S_K) / 256) + GTF_S_J) +#define GTF_S_M_PRIME ((GTF_S_K * GTF_S_M) / 256) + +/** v4l2_detect_gtf - detect if the given timings follow the GTF standard + * @frame_height - the total height of the frame (including blanking) in lines. + * @hfreq - the horizontal frequency in Hz. + * @vsync - the height of the vertical sync in lines. + * @polarities - the horizontal and vertical polarities (same as struct + * v4l2_bt_timings polarities). + * @aspect - preferred aspect ratio. GTF has no method of determining the + * aspect ratio in order to derive the image width from the + * image height, so it has to be passed explicitly. Usually + * the native screen aspect ratio is used for this. If it + * is not filled in correctly, then 16:9 will be assumed. + * @fmt - the resulting timings. + * + * This function will attempt to detect if the given values correspond to a + * valid GTF format. If so, then it will return true, and fmt will be filled + * in with the found GTF timings. + */ +bool v4l2_detect_gtf(unsigned frame_height, + unsigned hfreq, + unsigned vsync, + u32 polarities, + struct v4l2_fract aspect, + struct v4l2_dv_timings *fmt) +{ + int pix_clk; + int v_fp, v_bp, h_fp, h_bp, hsync; + int frame_width, image_height, image_width; + bool default_gtf; + int h_blank; + + if (vsync != 3) + return false; + + if (polarities == V4L2_DV_VSYNC_POS_POL) + default_gtf = true; + else if (polarities == V4L2_DV_HSYNC_POS_POL) + default_gtf = false; + else + return false; + + /* Vertical */ + v_fp = GTF_V_FP; + v_bp = (GTF_MIN_VSYNC_BP * hfreq + 999999) / 1000000 - vsync; + image_height = (frame_height - v_fp - vsync - v_bp + 1) & ~0x1; + + if (aspect.numerator == 0 || aspect.denominator == 0) { + aspect.numerator = 16; + aspect.denominator = 9; + } + image_width = ((image_height * aspect.numerator) / aspect.denominator); + + /* Horizontal */ + if (default_gtf) + h_blank = ((image_width * GTF_D_C_PRIME * hfreq) - + (image_width * GTF_D_M_PRIME * 1000) + + (hfreq * (100 - GTF_D_C_PRIME) + GTF_D_M_PRIME * 1000) / 2) / + (hfreq * (100 - GTF_D_C_PRIME) + GTF_D_M_PRIME * 1000); + else + h_blank = ((image_width * GTF_S_C_PRIME * hfreq) - + (image_width * GTF_S_M_PRIME * 1000) + + (hfreq * (100 - GTF_S_C_PRIME) + GTF_S_M_PRIME * 1000) / 2) / + (hfreq * (100 - GTF_S_C_PRIME) + GTF_S_M_PRIME * 1000); + + h_blank = h_blank - h_blank % (2 * GTF_CELL_GRAN); + frame_width = image_width + h_blank; + + pix_clk = (image_width + h_blank) * hfreq; + pix_clk = pix_clk / GTF_PXL_CLK_GRAN * GTF_PXL_CLK_GRAN; + + hsync = (frame_width * 8 + 50) / 100; + hsync = hsync - hsync % GTF_CELL_GRAN; + + h_fp = h_blank / 2 - hsync; + h_bp = h_blank / 2; + + fmt->bt.polarities = polarities; + fmt->bt.width = image_width; + fmt->bt.height = image_height; + fmt->bt.hfrontporch = h_fp; + fmt->bt.vfrontporch = v_fp; + fmt->bt.hsync = hsync; + fmt->bt.vsync = vsync; + fmt->bt.hbackporch = frame_width - image_width - h_fp - hsync; + fmt->bt.vbackporch = frame_height - image_height - v_fp - vsync; + fmt->bt.pixelclock = pix_clk; + fmt->bt.standards = V4L2_DV_BT_STD_GTF; + if (!default_gtf) + fmt->bt.flags |= V4L2_DV_FL_REDUCED_BLANKING; + return true; +} +EXPORT_SYMBOL_GPL(v4l2_detect_gtf); + +/** v4l2_calc_aspect_ratio - calculate the aspect ratio based on bytes + * 0x15 and 0x16 from the EDID. + * @hor_landscape - byte 0x15 from the EDID. + * @vert_portrait - byte 0x16 from the EDID. + * + * Determines the aspect ratio from the EDID. + * See VESA Enhanced EDID standard, release A, rev 2, section 3.6.2: + * "Horizontal and Vertical Screen Size or Aspect Ratio" + */ +struct v4l2_fract v4l2_calc_aspect_ratio(u8 hor_landscape, u8 vert_portrait) +{ + struct v4l2_fract aspect = { 16, 9 }; + u32 tmp; + u8 ratio; + + /* Nothing filled in, fallback to 16:9 */ + if (!hor_landscape && !vert_portrait) + return aspect; + /* Both filled in, so they are interpreted as the screen size in cm */ + if (hor_landscape && vert_portrait) { + aspect.numerator = hor_landscape; + aspect.denominator = vert_portrait; + return aspect; + } + /* Only one is filled in, so interpret them as a ratio: + (val + 99) / 100 */ + ratio = hor_landscape | vert_portrait; + /* Change some rounded values into the exact aspect ratio */ + if (ratio == 79) { + aspect.numerator = 16; + aspect.denominator = 9; + } else if (ratio == 34) { + aspect.numerator = 4; + aspect.numerator = 3; + } else if (ratio == 68) { + aspect.numerator = 15; + aspect.numerator = 9; + } else { + aspect.numerator = hor_landscape + 99; + aspect.denominator = 100; + } + if (hor_landscape) + return aspect; + /* The aspect ratio is for portrait, so swap numerator and denominator */ + tmp = aspect.denominator; + aspect.denominator = aspect.numerator; + aspect.numerator = tmp; + return aspect; +} +EXPORT_SYMBOL_GPL(v4l2_calc_aspect_ratio); + const struct v4l2_frmsize_discrete *v4l2_find_nearest_format( const struct v4l2_discrete_probe *probe, s32 width, s32 height) diff --git a/drivers/media/video/v4l2-compat-ioctl32.c b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c index 9ebd5c540d10..83ffb6436baf 100644 --- a/drivers/media/video/v4l2-compat-ioctl32.c +++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c @@ -16,6 +16,7 @@ #include <linux/compat.h> #include <linux/module.h> #include <linux/videodev2.h> +#include <linux/v4l2-subdev.h> #include <media/v4l2-dev.h> #include <media/v4l2-ioctl.h> @@ -194,10 +195,6 @@ static int __get_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __us case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: return get_v4l2_sliced_vbi_format(&kp->fmt.sliced, &up->fmt.sliced); - case V4L2_BUF_TYPE_PRIVATE: - if (copy_from_user(kp, up, sizeof(kp->fmt.raw_data))) - return -EFAULT; - return 0; default: printk(KERN_INFO "compat_ioctl32: unexpected VIDIOC_FMT type %d\n", kp->type); @@ -240,10 +237,6 @@ static int __put_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __us case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: return put_v4l2_sliced_vbi_format(&kp->fmt.sliced, &up->fmt.sliced); - case V4L2_BUF_TYPE_PRIVATE: - if (copy_to_user(up, kp, sizeof(up->fmt.raw_data))) - return -EFAULT; - return 0; default: printk(KERN_INFO "compat_ioctl32: unexpected VIDIOC_FMT type %d\n", kp->type); @@ -729,6 +722,44 @@ static int put_v4l2_event32(struct v4l2_event *kp, struct v4l2_event32 __user *u return 0; } +struct v4l2_subdev_edid32 { + __u32 pad; + __u32 start_block; + __u32 blocks; + __u32 reserved[5]; + compat_caddr_t edid; +}; + +static int get_v4l2_subdev_edid32(struct v4l2_subdev_edid *kp, struct v4l2_subdev_edid32 __user *up) +{ + u32 tmp; + + if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_subdev_edid32)) || + get_user(kp->pad, &up->pad) || + get_user(kp->start_block, &up->start_block) || + get_user(kp->blocks, &up->blocks) || + get_user(tmp, &up->edid) || + copy_from_user(kp->reserved, up->reserved, sizeof(kp->reserved))) + return -EFAULT; + kp->edid = compat_ptr(tmp); + return 0; +} + +static int put_v4l2_subdev_edid32(struct v4l2_subdev_edid *kp, struct v4l2_subdev_edid32 __user *up) +{ + u32 tmp = (u32)((unsigned long)kp->edid); + + if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_subdev_edid32)) || + put_user(kp->pad, &up->pad) || + put_user(kp->start_block, &up->start_block) || + put_user(kp->blocks, &up->blocks) || + put_user(tmp, &up->edid) || + copy_to_user(kp->reserved, up->reserved, sizeof(kp->reserved))) + return -EFAULT; + return 0; +} + + #define VIDIOC_G_FMT32 _IOWR('V', 4, struct v4l2_format32) #define VIDIOC_S_FMT32 _IOWR('V', 5, struct v4l2_format32) #define VIDIOC_QUERYBUF32 _IOWR('V', 9, struct v4l2_buffer32) @@ -738,6 +769,8 @@ static int put_v4l2_event32(struct v4l2_event *kp, struct v4l2_event32 __user *u #define VIDIOC_DQBUF32 _IOWR('V', 17, struct v4l2_buffer32) #define VIDIOC_ENUMSTD32 _IOWR('V', 25, struct v4l2_standard32) #define VIDIOC_ENUMINPUT32 _IOWR('V', 26, struct v4l2_input32) +#define VIDIOC_SUBDEV_G_EDID32 _IOWR('V', 63, struct v4l2_subdev_edid32) +#define VIDIOC_SUBDEV_S_EDID32 _IOWR('V', 64, struct v4l2_subdev_edid32) #define VIDIOC_TRY_FMT32 _IOWR('V', 64, struct v4l2_format32) #define VIDIOC_G_EXT_CTRLS32 _IOWR('V', 71, struct v4l2_ext_controls32) #define VIDIOC_S_EXT_CTRLS32 _IOWR('V', 72, struct v4l2_ext_controls32) @@ -765,6 +798,7 @@ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar struct v4l2_ext_controls v2ecs; struct v4l2_event v2ev; struct v4l2_create_buffers v2crt; + struct v4l2_subdev_edid v2edid; unsigned long vx; int vi; } karg; @@ -797,6 +831,8 @@ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar case VIDIOC_S_OUTPUT32: cmd = VIDIOC_S_OUTPUT; break; case VIDIOC_CREATE_BUFS32: cmd = VIDIOC_CREATE_BUFS; break; case VIDIOC_PREPARE_BUF32: cmd = VIDIOC_PREPARE_BUF; break; + case VIDIOC_SUBDEV_G_EDID32: cmd = VIDIOC_SUBDEV_G_EDID; break; + case VIDIOC_SUBDEV_S_EDID32: cmd = VIDIOC_SUBDEV_S_EDID; break; } switch (cmd) { @@ -814,6 +850,12 @@ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar compatible_arg = 0; break; + case VIDIOC_SUBDEV_G_EDID: + case VIDIOC_SUBDEV_S_EDID: + err = get_v4l2_subdev_edid32(&karg.v2edid, up); + compatible_arg = 0; + break; + case VIDIOC_G_FMT: case VIDIOC_S_FMT: case VIDIOC_TRY_FMT: @@ -906,6 +948,11 @@ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar err = put_v4l2_event32(&karg.v2ev, up); break; + case VIDIOC_SUBDEV_G_EDID: + case VIDIOC_SUBDEV_S_EDID: + err = put_v4l2_subdev_edid32(&karg.v2edid, up); + break; + case VIDIOC_G_FMT: case VIDIOC_S_FMT: case VIDIOC_TRY_FMT: @@ -1026,6 +1073,8 @@ long v4l2_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg) case VIDIOC_QUERY_DV_TIMINGS: case VIDIOC_DV_TIMINGS_CAP: case VIDIOC_ENUM_FREQ_BANDS: + case VIDIOC_SUBDEV_G_EDID32: + case VIDIOC_SUBDEV_S_EDID32: ret = do_video_ioctl(file, cmd, arg); break; diff --git a/drivers/media/video/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c index b6a2ee71e5c3..631cdc0e0bda 100644 --- a/drivers/media/video/v4l2-ctrls.c +++ b/drivers/media/v4l2-core/v4l2-ctrls.c @@ -425,6 +425,18 @@ const char * const *v4l2_ctrl_get_menu(u32 id) "Gray", NULL, }; + static const char * const dv_tx_mode[] = { + "DVI-D", + "HDMI", + NULL, + }; + static const char * const dv_rgb_range[] = { + "Automatic", + "RGB limited range (16-235)", + "RGB full range (0-255)", + NULL, + }; + switch (id) { case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: @@ -502,6 +514,11 @@ const char * const *v4l2_ctrl_get_menu(u32 id) return mpeg4_profile; case V4L2_CID_JPEG_CHROMA_SUBSAMPLING: return jpeg_chroma_subsampling; + case V4L2_CID_DV_TX_MODE: + return dv_tx_mode; + case V4L2_CID_DV_TX_RGB_RANGE: + case V4L2_CID_DV_RX_RGB_RANGE: + return dv_rgb_range; default: return NULL; @@ -733,6 +750,16 @@ const char *v4l2_ctrl_get_name(u32 id) case V4L2_CID_LINK_FREQ: return "Link Frequency"; case V4L2_CID_PIXEL_RATE: return "Pixel Rate"; + /* DV controls */ + case V4L2_CID_DV_CLASS: return "Digital Video Controls"; + case V4L2_CID_DV_TX_HOTPLUG: return "Hotplug Present"; + case V4L2_CID_DV_TX_RXSENSE: return "RxSense Present"; + case V4L2_CID_DV_TX_EDID_PRESENT: return "EDID Present"; + case V4L2_CID_DV_TX_MODE: return "Transmit Mode"; + case V4L2_CID_DV_TX_RGB_RANGE: return "Tx RGB Quantization Range"; + case V4L2_CID_DV_RX_POWER_PRESENT: return "Power Present"; + case V4L2_CID_DV_RX_RGB_RANGE: return "Rx RGB Quantization Range"; + default: return NULL; } @@ -832,6 +859,9 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type, case V4L2_CID_ISO_SENSITIVITY_AUTO: case V4L2_CID_EXPOSURE_METERING: case V4L2_CID_SCENE_MODE: + case V4L2_CID_DV_TX_MODE: + case V4L2_CID_DV_TX_RGB_RANGE: + case V4L2_CID_DV_RX_RGB_RANGE: *type = V4L2_CTRL_TYPE_MENU; break; case V4L2_CID_LINK_FREQ: @@ -853,6 +883,7 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type, case V4L2_CID_JPEG_CLASS: case V4L2_CID_IMAGE_SOURCE_CLASS: case V4L2_CID_IMAGE_PROC_CLASS: + case V4L2_CID_DV_CLASS: *type = V4L2_CTRL_TYPE_CTRL_CLASS; /* You can neither read not write these */ *flags |= V4L2_CTRL_FLAG_READ_ONLY | V4L2_CTRL_FLAG_WRITE_ONLY; @@ -869,6 +900,10 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type, case V4L2_CID_JPEG_ACTIVE_MARKER: case V4L2_CID_3A_LOCK: case V4L2_CID_AUTO_FOCUS_STATUS: + case V4L2_CID_DV_TX_HOTPLUG: + case V4L2_CID_DV_TX_RXSENSE: + case V4L2_CID_DV_TX_EDID_PRESENT: + case V4L2_CID_DV_RX_POWER_PRESENT: *type = V4L2_CTRL_TYPE_BITMASK; break; case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE: @@ -933,6 +968,10 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type, case V4L2_CID_FLASH_STROBE_STATUS: case V4L2_CID_AUTO_FOCUS_STATUS: case V4L2_CID_FLASH_READY: + case V4L2_CID_DV_TX_HOTPLUG: + case V4L2_CID_DV_TX_RXSENSE: + case V4L2_CID_DV_TX_EDID_PRESENT: + case V4L2_CID_DV_RX_POWER_PRESENT: *flags |= V4L2_CTRL_FLAG_READ_ONLY; break; } @@ -1174,76 +1213,53 @@ static int cluster_changed(struct v4l2_ctrl *master) return diff; } -/* Validate integer-type control */ -static int validate_new_int(const struct v4l2_ctrl *ctrl, s32 *pval) +/* Validate a new control */ +static int validate_new(const struct v4l2_ctrl *ctrl, + struct v4l2_ext_control *c) { - s32 val = *pval; + size_t len; u32 offset; + s32 val; switch (ctrl->type) { case V4L2_CTRL_TYPE_INTEGER: /* Round towards the closest legal value */ - val += ctrl->step / 2; - if (val < ctrl->minimum) - val = ctrl->minimum; - if (val > ctrl->maximum) - val = ctrl->maximum; + val = c->value + ctrl->step / 2; + val = clamp(val, ctrl->minimum, ctrl->maximum); offset = val - ctrl->minimum; offset = ctrl->step * (offset / ctrl->step); - val = ctrl->minimum + offset; - *pval = val; + c->value = ctrl->minimum + offset; return 0; case V4L2_CTRL_TYPE_BOOLEAN: - *pval = !!val; + c->value = !!c->value; return 0; case V4L2_CTRL_TYPE_MENU: case V4L2_CTRL_TYPE_INTEGER_MENU: - if (val < ctrl->minimum || val > ctrl->maximum) + if (c->value < ctrl->minimum || c->value > ctrl->maximum) return -ERANGE; - if (ctrl->menu_skip_mask & (1 << val)) + if (ctrl->menu_skip_mask & (1 << c->value)) return -EINVAL; if (ctrl->type == V4L2_CTRL_TYPE_MENU && - ctrl->qmenu[val][0] == '\0') + ctrl->qmenu[c->value][0] == '\0') return -EINVAL; return 0; case V4L2_CTRL_TYPE_BITMASK: - *pval &= ctrl->maximum; + c->value &= ctrl->maximum; return 0; case V4L2_CTRL_TYPE_BUTTON: case V4L2_CTRL_TYPE_CTRL_CLASS: - *pval = 0; + c->value = 0; return 0; - default: - return -EINVAL; - } -} - -/* Validate a new control */ -static int validate_new(const struct v4l2_ctrl *ctrl, struct v4l2_ext_control *c) -{ - char *s = c->string; - size_t len; - - switch (ctrl->type) { - case V4L2_CTRL_TYPE_INTEGER: - case V4L2_CTRL_TYPE_BOOLEAN: - case V4L2_CTRL_TYPE_MENU: - case V4L2_CTRL_TYPE_INTEGER_MENU: - case V4L2_CTRL_TYPE_BITMASK: - case V4L2_CTRL_TYPE_BUTTON: - case V4L2_CTRL_TYPE_CTRL_CLASS: - return validate_new_int(ctrl, &c->value); - case V4L2_CTRL_TYPE_INTEGER64: return 0; case V4L2_CTRL_TYPE_STRING: - len = strlen(s); + len = strlen(c->string); if (len < ctrl->minimum) return -ERANGE; if ((len - ctrl->minimum) % ctrl->step) @@ -1671,7 +1687,8 @@ EXPORT_SYMBOL(v4l2_ctrl_add_ctrl); /* Add the controls from another handler to our own. */ int v4l2_ctrl_add_handler(struct v4l2_ctrl_handler *hdl, - struct v4l2_ctrl_handler *add) + struct v4l2_ctrl_handler *add, + bool (*filter)(const struct v4l2_ctrl *ctrl)) { struct v4l2_ctrl_ref *ref; int ret = 0; @@ -1691,6 +1708,9 @@ int v4l2_ctrl_add_handler(struct v4l2_ctrl_handler *hdl, /* And control classes */ if (ctrl->type == V4L2_CTRL_TYPE_CTRL_CLASS) continue; + /* Filter any unwanted controls */ + if (filter && !filter(ctrl)) + continue; ret = handler_new_ref(hdl, ctrl); if (ret) break; @@ -1700,6 +1720,25 @@ int v4l2_ctrl_add_handler(struct v4l2_ctrl_handler *hdl, } EXPORT_SYMBOL(v4l2_ctrl_add_handler); +bool v4l2_ctrl_radio_filter(const struct v4l2_ctrl *ctrl) +{ + if (V4L2_CTRL_ID2CLASS(ctrl->id) == V4L2_CTRL_CLASS_FM_TX) + return true; + switch (ctrl->id) { + case V4L2_CID_AUDIO_MUTE: + case V4L2_CID_AUDIO_VOLUME: + case V4L2_CID_AUDIO_BALANCE: + case V4L2_CID_AUDIO_BASS: + case V4L2_CID_AUDIO_TREBLE: + case V4L2_CID_AUDIO_LOUDNESS: + return true; + default: + break; + } + return false; +} +EXPORT_SYMBOL(v4l2_ctrl_radio_filter); + /* Cluster controls */ void v4l2_ctrl_cluster(unsigned ncontrols, struct v4l2_ctrl **controls) { @@ -2235,12 +2274,19 @@ int v4l2_subdev_g_ext_ctrls(struct v4l2_subdev *sd, struct v4l2_ext_controls *cs EXPORT_SYMBOL(v4l2_subdev_g_ext_ctrls); /* Helper function to get a single control */ -static int get_ctrl(struct v4l2_ctrl *ctrl, s32 *val) +static int get_ctrl(struct v4l2_ctrl *ctrl, struct v4l2_ext_control *c) { struct v4l2_ctrl *master = ctrl->cluster[0]; int ret = 0; int i; + /* String controls are not supported. The new_to_user() and + * cur_to_user() calls below would need to be modified not to access + * userspace memory when called from get_ctrl(). + */ + if (ctrl->type == V4L2_CTRL_TYPE_STRING) + return -EINVAL; + if (ctrl->flags & V4L2_CTRL_FLAG_WRITE_ONLY) return -EACCES; @@ -2250,9 +2296,9 @@ static int get_ctrl(struct v4l2_ctrl *ctrl, s32 *val) for (i = 0; i < master->ncontrols; i++) cur_to_new(master->cluster[i]); ret = call_op(master, g_volatile_ctrl); - *val = ctrl->val; + new_to_user(c, ctrl); } else { - *val = ctrl->cur.val; + cur_to_user(c, ctrl); } v4l2_ctrl_unlock(master); return ret; @@ -2261,10 +2307,14 @@ static int get_ctrl(struct v4l2_ctrl *ctrl, s32 *val) int v4l2_g_ctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_control *control) { struct v4l2_ctrl *ctrl = v4l2_ctrl_find(hdl, control->id); + struct v4l2_ext_control c; + int ret; if (ctrl == NULL || !type_is_int(ctrl)) return -EINVAL; - return get_ctrl(ctrl, &control->value); + ret = get_ctrl(ctrl, &c); + control->value = c.value; + return ret; } EXPORT_SYMBOL(v4l2_g_ctrl); @@ -2276,15 +2326,28 @@ EXPORT_SYMBOL(v4l2_subdev_g_ctrl); s32 v4l2_ctrl_g_ctrl(struct v4l2_ctrl *ctrl) { - s32 val = 0; + struct v4l2_ext_control c; /* It's a driver bug if this happens. */ WARN_ON(!type_is_int(ctrl)); - get_ctrl(ctrl, &val); - return val; + c.value = 0; + get_ctrl(ctrl, &c); + return c.value; } EXPORT_SYMBOL(v4l2_ctrl_g_ctrl); +s64 v4l2_ctrl_g_ctrl_int64(struct v4l2_ctrl *ctrl) +{ + struct v4l2_ext_control c; + + /* It's a driver bug if this happens. */ + WARN_ON(ctrl->type != V4L2_CTRL_TYPE_INTEGER64); + c.value = 0; + get_ctrl(ctrl, &c); + return c.value; +} +EXPORT_SYMBOL(v4l2_ctrl_g_ctrl_int64); + /* Core function that calls try/s_ctrl and ensures that the new value is copied to the current value on a set. @@ -2500,13 +2563,21 @@ int v4l2_subdev_s_ext_ctrls(struct v4l2_subdev *sd, struct v4l2_ext_controls *cs EXPORT_SYMBOL(v4l2_subdev_s_ext_ctrls); /* Helper function for VIDIOC_S_CTRL compatibility */ -static int set_ctrl(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl, s32 *val) +static int set_ctrl(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl, + struct v4l2_ext_control *c) { struct v4l2_ctrl *master = ctrl->cluster[0]; int ret; int i; - ret = validate_new_int(ctrl, val); + /* String controls are not supported. The user_to_new() and + * cur_to_user() calls below would need to be modified not to access + * userspace memory when called from set_ctrl(). + */ + if (ctrl->type == V4L2_CTRL_TYPE_STRING) + return -EINVAL; + + ret = validate_new(ctrl, c); if (ret) return ret; @@ -2521,12 +2592,13 @@ static int set_ctrl(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl, s32 *val) manual mode we have to update the current volatile values since those will become the initial manual values after such a switch. */ if (master->is_auto && master->has_volatiles && ctrl == master && - !is_cur_manual(master) && *val == master->manual_mode_value) + !is_cur_manual(master) && c->value == master->manual_mode_value) update_from_auto_cluster(master); - ctrl->val = *val; - ctrl->is_new = 1; + + user_to_new(c, ctrl); ret = try_or_set_cluster(fh, master, true); - *val = ctrl->cur.val; + cur_to_user(c, ctrl); + v4l2_ctrl_unlock(ctrl); return ret; } @@ -2535,6 +2607,8 @@ int v4l2_s_ctrl(struct v4l2_fh *fh, struct v4l2_ctrl_handler *hdl, struct v4l2_control *control) { struct v4l2_ctrl *ctrl = v4l2_ctrl_find(hdl, control->id); + struct v4l2_ext_control c; + int ret; if (ctrl == NULL || !type_is_int(ctrl)) return -EINVAL; @@ -2542,7 +2616,10 @@ int v4l2_s_ctrl(struct v4l2_fh *fh, struct v4l2_ctrl_handler *hdl, if (ctrl->flags & V4L2_CTRL_FLAG_READ_ONLY) return -EACCES; - return set_ctrl(fh, ctrl, &control->value); + c.value = control->value; + ret = set_ctrl(fh, ctrl, &c); + control->value = c.value; + return ret; } EXPORT_SYMBOL(v4l2_s_ctrl); @@ -2554,12 +2631,26 @@ EXPORT_SYMBOL(v4l2_subdev_s_ctrl); int v4l2_ctrl_s_ctrl(struct v4l2_ctrl *ctrl, s32 val) { + struct v4l2_ext_control c; + /* It's a driver bug if this happens. */ WARN_ON(!type_is_int(ctrl)); - return set_ctrl(NULL, ctrl, &val); + c.value = val; + return set_ctrl(NULL, ctrl, &c); } EXPORT_SYMBOL(v4l2_ctrl_s_ctrl); +int v4l2_ctrl_s_ctrl_int64(struct v4l2_ctrl *ctrl, s64 val) +{ + struct v4l2_ext_control c; + + /* It's a driver bug if this happens. */ + WARN_ON(ctrl->type != V4L2_CTRL_TYPE_INTEGER64); + c.value64 = val; + return set_ctrl(NULL, ctrl, &c); +} +EXPORT_SYMBOL(v4l2_ctrl_s_ctrl_int64); + static int v4l2_ctrl_add_event(struct v4l2_subscribed_event *sev, unsigned elems) { struct v4l2_ctrl *ctrl = v4l2_ctrl_find(sev->fh->ctrl_handler, sev->id); @@ -2631,7 +2722,7 @@ int v4l2_ctrl_log_status(struct file *file, void *fh) EXPORT_SYMBOL(v4l2_ctrl_log_status); int v4l2_ctrl_subscribe_event(struct v4l2_fh *fh, - struct v4l2_event_subscription *sub) + const struct v4l2_event_subscription *sub) { if (sub->type == V4L2_EVENT_CTRL) return v4l2_event_subscribe(fh, sub, 0, &v4l2_ctrl_sub_ev_ops); diff --git a/drivers/media/video/v4l2-dev.c b/drivers/media/v4l2-core/v4l2-dev.c index 07aeafca9eaa..a2df842e5100 100644 --- a/drivers/media/video/v4l2-dev.c +++ b/drivers/media/v4l2-core/v4l2-dev.c @@ -298,13 +298,8 @@ static ssize_t v4l2_read(struct file *filp, char __user *buf, if (!vdev->fops->read) return -EINVAL; - if (test_bit(V4L2_FL_LOCK_ALL_FOPS, &vdev->flags) && - mutex_lock_interruptible(vdev->lock)) - return -ERESTARTSYS; if (video_is_registered(vdev)) ret = vdev->fops->read(filp, buf, sz, off); - if (test_bit(V4L2_FL_LOCK_ALL_FOPS, &vdev->flags)) - mutex_unlock(vdev->lock); if (vdev->debug) printk(KERN_DEBUG "%s: read: %zd (%d)\n", video_device_node_name(vdev), sz, ret); @@ -319,13 +314,8 @@ static ssize_t v4l2_write(struct file *filp, const char __user *buf, if (!vdev->fops->write) return -EINVAL; - if (test_bit(V4L2_FL_LOCK_ALL_FOPS, &vdev->flags) && - mutex_lock_interruptible(vdev->lock)) - return -ERESTARTSYS; if (video_is_registered(vdev)) ret = vdev->fops->write(filp, buf, sz, off); - if (test_bit(V4L2_FL_LOCK_ALL_FOPS, &vdev->flags)) - mutex_unlock(vdev->lock); if (vdev->debug) printk(KERN_DEBUG "%s: write: %zd (%d)\n", video_device_node_name(vdev), sz, ret); @@ -335,20 +325,16 @@ static ssize_t v4l2_write(struct file *filp, const char __user *buf, static unsigned int v4l2_poll(struct file *filp, struct poll_table_struct *poll) { struct video_device *vdev = video_devdata(filp); - int ret = POLLERR | POLLHUP; + unsigned int res = POLLERR | POLLHUP; if (!vdev->fops->poll) return DEFAULT_POLLMASK; - if (test_bit(V4L2_FL_LOCK_ALL_FOPS, &vdev->flags)) - mutex_lock(vdev->lock); if (video_is_registered(vdev)) - ret = vdev->fops->poll(filp, poll); - if (test_bit(V4L2_FL_LOCK_ALL_FOPS, &vdev->flags)) - mutex_unlock(vdev->lock); + res = vdev->fops->poll(filp, poll); if (vdev->debug) printk(KERN_DEBUG "%s: poll: %08x\n", - video_device_node_name(vdev), ret); - return ret; + video_device_node_name(vdev), res); + return res; } static long v4l2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) @@ -432,14 +418,9 @@ static int v4l2_mmap(struct file *filp, struct vm_area_struct *vm) int ret = -ENODEV; if (!vdev->fops->mmap) - return ret; - if (test_bit(V4L2_FL_LOCK_ALL_FOPS, &vdev->flags) && - mutex_lock_interruptible(vdev->lock)) - return -ERESTARTSYS; + return -ENODEV; if (video_is_registered(vdev)) ret = vdev->fops->mmap(filp, vm); - if (test_bit(V4L2_FL_LOCK_ALL_FOPS, &vdev->flags)) - mutex_unlock(vdev->lock); if (vdev->debug) printk(KERN_DEBUG "%s: mmap (%d)\n", video_device_node_name(vdev), ret); @@ -464,20 +445,12 @@ static int v4l2_open(struct inode *inode, struct file *filp) video_get(vdev); mutex_unlock(&videodev_lock); if (vdev->fops->open) { - if (test_bit(V4L2_FL_LOCK_ALL_FOPS, &vdev->flags) && - mutex_lock_interruptible(vdev->lock)) { - ret = -ERESTARTSYS; - goto err; - } if (video_is_registered(vdev)) ret = vdev->fops->open(filp); else ret = -ENODEV; - if (test_bit(V4L2_FL_LOCK_ALL_FOPS, &vdev->flags)) - mutex_unlock(vdev->lock); } -err: if (vdev->debug) printk(KERN_DEBUG "%s: open (%d)\n", video_device_node_name(vdev), ret); @@ -493,16 +466,12 @@ static int v4l2_release(struct inode *inode, struct file *filp) struct video_device *vdev = video_devdata(filp); int ret = 0; - if (vdev->fops->release) { - if (test_bit(V4L2_FL_LOCK_ALL_FOPS, &vdev->flags)) - mutex_lock(vdev->lock); - vdev->fops->release(filp); - if (test_bit(V4L2_FL_LOCK_ALL_FOPS, &vdev->flags)) - mutex_unlock(vdev->lock); - } + if (vdev->fops->release) + ret = vdev->fops->release(filp); if (vdev->debug) printk(KERN_DEBUG "%s: release\n", video_device_node_name(vdev)); + /* decrease the refcount unconditionally since the release() return value is ignored. */ video_put(vdev); @@ -582,9 +551,16 @@ static void determine_valid_ioctls(struct video_device *vdev) { DECLARE_BITMAP(valid_ioctls, BASE_VIDIOC_PRIVATE); const struct v4l2_ioctl_ops *ops = vdev->ioctl_ops; + bool is_vid = vdev->vfl_type == VFL_TYPE_GRABBER; + bool is_vbi = vdev->vfl_type == VFL_TYPE_VBI; + bool is_radio = vdev->vfl_type == VFL_TYPE_RADIO; + bool is_rx = vdev->vfl_dir != VFL_DIR_TX; + bool is_tx = vdev->vfl_dir != VFL_DIR_RX; bitmap_zero(valid_ioctls, BASE_VIDIOC_PRIVATE); + /* vfl_type and vfl_dir independent ioctls */ + SET_VALID_IOCTL(ops, VIDIOC_QUERYCAP, vidioc_querycap); if (ops->vidioc_g_priority || test_bit(V4L2_FL_USE_FH_PRIO, &vdev->flags)) @@ -592,70 +568,12 @@ static void determine_valid_ioctls(struct video_device *vdev) if (ops->vidioc_s_priority || test_bit(V4L2_FL_USE_FH_PRIO, &vdev->flags)) set_bit(_IOC_NR(VIDIOC_S_PRIORITY), valid_ioctls); - if (ops->vidioc_enum_fmt_vid_cap || - ops->vidioc_enum_fmt_vid_out || - ops->vidioc_enum_fmt_vid_cap_mplane || - ops->vidioc_enum_fmt_vid_out_mplane || - ops->vidioc_enum_fmt_vid_overlay || - ops->vidioc_enum_fmt_type_private) - set_bit(_IOC_NR(VIDIOC_ENUM_FMT), valid_ioctls); - if (ops->vidioc_g_fmt_vid_cap || - ops->vidioc_g_fmt_vid_out || - ops->vidioc_g_fmt_vid_cap_mplane || - ops->vidioc_g_fmt_vid_out_mplane || - ops->vidioc_g_fmt_vid_overlay || - ops->vidioc_g_fmt_vbi_cap || - ops->vidioc_g_fmt_vid_out_overlay || - ops->vidioc_g_fmt_vbi_out || - ops->vidioc_g_fmt_sliced_vbi_cap || - ops->vidioc_g_fmt_sliced_vbi_out || - ops->vidioc_g_fmt_type_private) - set_bit(_IOC_NR(VIDIOC_G_FMT), valid_ioctls); - if (ops->vidioc_s_fmt_vid_cap || - ops->vidioc_s_fmt_vid_out || - ops->vidioc_s_fmt_vid_cap_mplane || - ops->vidioc_s_fmt_vid_out_mplane || - ops->vidioc_s_fmt_vid_overlay || - ops->vidioc_s_fmt_vbi_cap || - ops->vidioc_s_fmt_vid_out_overlay || - ops->vidioc_s_fmt_vbi_out || - ops->vidioc_s_fmt_sliced_vbi_cap || - ops->vidioc_s_fmt_sliced_vbi_out || - ops->vidioc_s_fmt_type_private) - set_bit(_IOC_NR(VIDIOC_S_FMT), valid_ioctls); - if (ops->vidioc_try_fmt_vid_cap || - ops->vidioc_try_fmt_vid_out || - ops->vidioc_try_fmt_vid_cap_mplane || - ops->vidioc_try_fmt_vid_out_mplane || - ops->vidioc_try_fmt_vid_overlay || - ops->vidioc_try_fmt_vbi_cap || - ops->vidioc_try_fmt_vid_out_overlay || - ops->vidioc_try_fmt_vbi_out || - ops->vidioc_try_fmt_sliced_vbi_cap || - ops->vidioc_try_fmt_sliced_vbi_out || - ops->vidioc_try_fmt_type_private) - set_bit(_IOC_NR(VIDIOC_TRY_FMT), valid_ioctls); SET_VALID_IOCTL(ops, VIDIOC_REQBUFS, vidioc_reqbufs); SET_VALID_IOCTL(ops, VIDIOC_QUERYBUF, vidioc_querybuf); SET_VALID_IOCTL(ops, VIDIOC_QBUF, vidioc_qbuf); SET_VALID_IOCTL(ops, VIDIOC_DQBUF, vidioc_dqbuf); - SET_VALID_IOCTL(ops, VIDIOC_OVERLAY, vidioc_overlay); - SET_VALID_IOCTL(ops, VIDIOC_G_FBUF, vidioc_g_fbuf); - SET_VALID_IOCTL(ops, VIDIOC_S_FBUF, vidioc_s_fbuf); SET_VALID_IOCTL(ops, VIDIOC_STREAMON, vidioc_streamon); SET_VALID_IOCTL(ops, VIDIOC_STREAMOFF, vidioc_streamoff); - if (vdev->tvnorms) - set_bit(_IOC_NR(VIDIOC_ENUMSTD), valid_ioctls); - if (ops->vidioc_g_std || vdev->current_norm) - set_bit(_IOC_NR(VIDIOC_G_STD), valid_ioctls); - SET_VALID_IOCTL(ops, VIDIOC_S_STD, vidioc_s_std); - SET_VALID_IOCTL(ops, VIDIOC_QUERYSTD, vidioc_querystd); - SET_VALID_IOCTL(ops, VIDIOC_ENUMINPUT, vidioc_enum_input); - SET_VALID_IOCTL(ops, VIDIOC_G_INPUT, vidioc_g_input); - SET_VALID_IOCTL(ops, VIDIOC_S_INPUT, vidioc_s_input); - SET_VALID_IOCTL(ops, VIDIOC_ENUMOUTPUT, vidioc_enum_output); - SET_VALID_IOCTL(ops, VIDIOC_G_OUTPUT, vidioc_g_output); - SET_VALID_IOCTL(ops, VIDIOC_S_OUTPUT, vidioc_s_output); /* Note: the control handler can also be passed through the filehandle, and that can't be tested here. If the bit for these control ioctls is set, then the ioctl is valid. But if it is 0, then it can still @@ -674,56 +592,14 @@ static void determine_valid_ioctls(struct video_device *vdev) set_bit(_IOC_NR(VIDIOC_TRY_EXT_CTRLS), valid_ioctls); if (vdev->ctrl_handler || ops->vidioc_querymenu) set_bit(_IOC_NR(VIDIOC_QUERYMENU), valid_ioctls); - SET_VALID_IOCTL(ops, VIDIOC_ENUMAUDIO, vidioc_enumaudio); - SET_VALID_IOCTL(ops, VIDIOC_G_AUDIO, vidioc_g_audio); - SET_VALID_IOCTL(ops, VIDIOC_S_AUDIO, vidioc_s_audio); - SET_VALID_IOCTL(ops, VIDIOC_ENUMAUDOUT, vidioc_enumaudout); - SET_VALID_IOCTL(ops, VIDIOC_G_AUDOUT, vidioc_g_audout); - SET_VALID_IOCTL(ops, VIDIOC_S_AUDOUT, vidioc_s_audout); - SET_VALID_IOCTL(ops, VIDIOC_G_MODULATOR, vidioc_g_modulator); - SET_VALID_IOCTL(ops, VIDIOC_S_MODULATOR, vidioc_s_modulator); - if (ops->vidioc_g_crop || ops->vidioc_g_selection) - set_bit(_IOC_NR(VIDIOC_G_CROP), valid_ioctls); - if (ops->vidioc_s_crop || ops->vidioc_s_selection) - set_bit(_IOC_NR(VIDIOC_S_CROP), valid_ioctls); - SET_VALID_IOCTL(ops, VIDIOC_G_SELECTION, vidioc_g_selection); - SET_VALID_IOCTL(ops, VIDIOC_S_SELECTION, vidioc_s_selection); - if (ops->vidioc_cropcap || ops->vidioc_g_selection) - set_bit(_IOC_NR(VIDIOC_CROPCAP), valid_ioctls); - SET_VALID_IOCTL(ops, VIDIOC_G_JPEGCOMP, vidioc_g_jpegcomp); - SET_VALID_IOCTL(ops, VIDIOC_S_JPEGCOMP, vidioc_s_jpegcomp); - SET_VALID_IOCTL(ops, VIDIOC_G_ENC_INDEX, vidioc_g_enc_index); - SET_VALID_IOCTL(ops, VIDIOC_ENCODER_CMD, vidioc_encoder_cmd); - SET_VALID_IOCTL(ops, VIDIOC_TRY_ENCODER_CMD, vidioc_try_encoder_cmd); - SET_VALID_IOCTL(ops, VIDIOC_DECODER_CMD, vidioc_decoder_cmd); - SET_VALID_IOCTL(ops, VIDIOC_TRY_DECODER_CMD, vidioc_try_decoder_cmd); - if (ops->vidioc_g_parm || (vdev->vfl_type == VFL_TYPE_GRABBER && - (ops->vidioc_g_std || vdev->tvnorms))) - set_bit(_IOC_NR(VIDIOC_G_PARM), valid_ioctls); - SET_VALID_IOCTL(ops, VIDIOC_S_PARM, vidioc_s_parm); - SET_VALID_IOCTL(ops, VIDIOC_G_TUNER, vidioc_g_tuner); - SET_VALID_IOCTL(ops, VIDIOC_S_TUNER, vidioc_s_tuner); SET_VALID_IOCTL(ops, VIDIOC_G_FREQUENCY, vidioc_g_frequency); SET_VALID_IOCTL(ops, VIDIOC_S_FREQUENCY, vidioc_s_frequency); - SET_VALID_IOCTL(ops, VIDIOC_G_SLICED_VBI_CAP, vidioc_g_sliced_vbi_cap); SET_VALID_IOCTL(ops, VIDIOC_LOG_STATUS, vidioc_log_status); #ifdef CONFIG_VIDEO_ADV_DEBUG SET_VALID_IOCTL(ops, VIDIOC_DBG_G_REGISTER, vidioc_g_register); SET_VALID_IOCTL(ops, VIDIOC_DBG_S_REGISTER, vidioc_s_register); #endif SET_VALID_IOCTL(ops, VIDIOC_DBG_G_CHIP_IDENT, vidioc_g_chip_ident); - SET_VALID_IOCTL(ops, VIDIOC_S_HW_FREQ_SEEK, vidioc_s_hw_freq_seek); - SET_VALID_IOCTL(ops, VIDIOC_ENUM_FRAMESIZES, vidioc_enum_framesizes); - SET_VALID_IOCTL(ops, VIDIOC_ENUM_FRAMEINTERVALS, vidioc_enum_frameintervals); - SET_VALID_IOCTL(ops, VIDIOC_ENUM_DV_PRESETS, vidioc_enum_dv_presets); - SET_VALID_IOCTL(ops, VIDIOC_S_DV_PRESET, vidioc_s_dv_preset); - SET_VALID_IOCTL(ops, VIDIOC_G_DV_PRESET, vidioc_g_dv_preset); - SET_VALID_IOCTL(ops, VIDIOC_QUERY_DV_PRESET, vidioc_query_dv_preset); - SET_VALID_IOCTL(ops, VIDIOC_S_DV_TIMINGS, vidioc_s_dv_timings); - SET_VALID_IOCTL(ops, VIDIOC_G_DV_TIMINGS, vidioc_g_dv_timings); - SET_VALID_IOCTL(ops, VIDIOC_ENUM_DV_TIMINGS, vidioc_enum_dv_timings); - SET_VALID_IOCTL(ops, VIDIOC_QUERY_DV_TIMINGS, vidioc_query_dv_timings); - SET_VALID_IOCTL(ops, VIDIOC_DV_TIMINGS_CAP, vidioc_dv_timings_cap); /* yes, really vidioc_subscribe_event */ SET_VALID_IOCTL(ops, VIDIOC_DQEVENT, vidioc_subscribe_event); SET_VALID_IOCTL(ops, VIDIOC_SUBSCRIBE_EVENT, vidioc_subscribe_event); @@ -732,6 +608,125 @@ static void determine_valid_ioctls(struct video_device *vdev) SET_VALID_IOCTL(ops, VIDIOC_PREPARE_BUF, vidioc_prepare_buf); if (ops->vidioc_enum_freq_bands || ops->vidioc_g_tuner || ops->vidioc_g_modulator) set_bit(_IOC_NR(VIDIOC_ENUM_FREQ_BANDS), valid_ioctls); + + if (is_vid) { + /* video specific ioctls */ + if ((is_rx && (ops->vidioc_enum_fmt_vid_cap || + ops->vidioc_enum_fmt_vid_cap_mplane || + ops->vidioc_enum_fmt_vid_overlay)) || + (is_tx && (ops->vidioc_enum_fmt_vid_out || + ops->vidioc_enum_fmt_vid_out_mplane))) + set_bit(_IOC_NR(VIDIOC_ENUM_FMT), valid_ioctls); + if ((is_rx && (ops->vidioc_g_fmt_vid_cap || + ops->vidioc_g_fmt_vid_cap_mplane || + ops->vidioc_g_fmt_vid_overlay)) || + (is_tx && (ops->vidioc_g_fmt_vid_out || + ops->vidioc_g_fmt_vid_out_mplane || + ops->vidioc_g_fmt_vid_out_overlay))) + set_bit(_IOC_NR(VIDIOC_G_FMT), valid_ioctls); + if ((is_rx && (ops->vidioc_s_fmt_vid_cap || + ops->vidioc_s_fmt_vid_cap_mplane || + ops->vidioc_s_fmt_vid_overlay)) || + (is_tx && (ops->vidioc_s_fmt_vid_out || + ops->vidioc_s_fmt_vid_out_mplane || + ops->vidioc_s_fmt_vid_out_overlay))) + set_bit(_IOC_NR(VIDIOC_S_FMT), valid_ioctls); + if ((is_rx && (ops->vidioc_try_fmt_vid_cap || + ops->vidioc_try_fmt_vid_cap_mplane || + ops->vidioc_try_fmt_vid_overlay)) || + (is_tx && (ops->vidioc_try_fmt_vid_out || + ops->vidioc_try_fmt_vid_out_mplane || + ops->vidioc_try_fmt_vid_out_overlay))) + set_bit(_IOC_NR(VIDIOC_TRY_FMT), valid_ioctls); + SET_VALID_IOCTL(ops, VIDIOC_OVERLAY, vidioc_overlay); + SET_VALID_IOCTL(ops, VIDIOC_G_FBUF, vidioc_g_fbuf); + SET_VALID_IOCTL(ops, VIDIOC_S_FBUF, vidioc_s_fbuf); + SET_VALID_IOCTL(ops, VIDIOC_G_JPEGCOMP, vidioc_g_jpegcomp); + SET_VALID_IOCTL(ops, VIDIOC_S_JPEGCOMP, vidioc_s_jpegcomp); + SET_VALID_IOCTL(ops, VIDIOC_G_ENC_INDEX, vidioc_g_enc_index); + SET_VALID_IOCTL(ops, VIDIOC_ENCODER_CMD, vidioc_encoder_cmd); + SET_VALID_IOCTL(ops, VIDIOC_TRY_ENCODER_CMD, vidioc_try_encoder_cmd); + SET_VALID_IOCTL(ops, VIDIOC_DECODER_CMD, vidioc_decoder_cmd); + SET_VALID_IOCTL(ops, VIDIOC_TRY_DECODER_CMD, vidioc_try_decoder_cmd); + SET_VALID_IOCTL(ops, VIDIOC_ENUM_FRAMESIZES, vidioc_enum_framesizes); + SET_VALID_IOCTL(ops, VIDIOC_ENUM_FRAMEINTERVALS, vidioc_enum_frameintervals); + } else if (is_vbi) { + /* vbi specific ioctls */ + if ((is_rx && (ops->vidioc_g_fmt_vbi_cap || + ops->vidioc_g_fmt_sliced_vbi_cap)) || + (is_tx && (ops->vidioc_g_fmt_vbi_out || + ops->vidioc_g_fmt_sliced_vbi_out))) + set_bit(_IOC_NR(VIDIOC_G_FMT), valid_ioctls); + if ((is_rx && (ops->vidioc_s_fmt_vbi_cap || + ops->vidioc_s_fmt_sliced_vbi_cap)) || + (is_tx && (ops->vidioc_s_fmt_vbi_out || + ops->vidioc_s_fmt_sliced_vbi_out))) + set_bit(_IOC_NR(VIDIOC_S_FMT), valid_ioctls); + if ((is_rx && (ops->vidioc_try_fmt_vbi_cap || + ops->vidioc_try_fmt_sliced_vbi_cap)) || + (is_tx && (ops->vidioc_try_fmt_vbi_out || + ops->vidioc_try_fmt_sliced_vbi_out))) + set_bit(_IOC_NR(VIDIOC_TRY_FMT), valid_ioctls); + SET_VALID_IOCTL(ops, VIDIOC_G_SLICED_VBI_CAP, vidioc_g_sliced_vbi_cap); + } + if (!is_radio) { + /* ioctls valid for video or vbi */ + if (ops->vidioc_s_std) + set_bit(_IOC_NR(VIDIOC_ENUMSTD), valid_ioctls); + if (ops->vidioc_g_std || vdev->current_norm) + set_bit(_IOC_NR(VIDIOC_G_STD), valid_ioctls); + SET_VALID_IOCTL(ops, VIDIOC_S_STD, vidioc_s_std); + if (is_rx) { + SET_VALID_IOCTL(ops, VIDIOC_QUERYSTD, vidioc_querystd); + SET_VALID_IOCTL(ops, VIDIOC_ENUMINPUT, vidioc_enum_input); + SET_VALID_IOCTL(ops, VIDIOC_G_INPUT, vidioc_g_input); + SET_VALID_IOCTL(ops, VIDIOC_S_INPUT, vidioc_s_input); + SET_VALID_IOCTL(ops, VIDIOC_ENUMAUDIO, vidioc_enumaudio); + SET_VALID_IOCTL(ops, VIDIOC_G_AUDIO, vidioc_g_audio); + SET_VALID_IOCTL(ops, VIDIOC_S_AUDIO, vidioc_s_audio); + SET_VALID_IOCTL(ops, VIDIOC_QUERY_DV_PRESET, vidioc_query_dv_preset); + SET_VALID_IOCTL(ops, VIDIOC_QUERY_DV_TIMINGS, vidioc_query_dv_timings); + } + if (is_tx) { + SET_VALID_IOCTL(ops, VIDIOC_ENUMOUTPUT, vidioc_enum_output); + SET_VALID_IOCTL(ops, VIDIOC_G_OUTPUT, vidioc_g_output); + SET_VALID_IOCTL(ops, VIDIOC_S_OUTPUT, vidioc_s_output); + SET_VALID_IOCTL(ops, VIDIOC_ENUMAUDOUT, vidioc_enumaudout); + SET_VALID_IOCTL(ops, VIDIOC_G_AUDOUT, vidioc_g_audout); + SET_VALID_IOCTL(ops, VIDIOC_S_AUDOUT, vidioc_s_audout); + } + if (ops->vidioc_g_crop || ops->vidioc_g_selection) + set_bit(_IOC_NR(VIDIOC_G_CROP), valid_ioctls); + if (ops->vidioc_s_crop || ops->vidioc_s_selection) + set_bit(_IOC_NR(VIDIOC_S_CROP), valid_ioctls); + SET_VALID_IOCTL(ops, VIDIOC_G_SELECTION, vidioc_g_selection); + SET_VALID_IOCTL(ops, VIDIOC_S_SELECTION, vidioc_s_selection); + if (ops->vidioc_cropcap || ops->vidioc_g_selection) + set_bit(_IOC_NR(VIDIOC_CROPCAP), valid_ioctls); + if (ops->vidioc_g_parm || (vdev->vfl_type == VFL_TYPE_GRABBER && + (ops->vidioc_g_std || vdev->current_norm))) + set_bit(_IOC_NR(VIDIOC_G_PARM), valid_ioctls); + SET_VALID_IOCTL(ops, VIDIOC_S_PARM, vidioc_s_parm); + SET_VALID_IOCTL(ops, VIDIOC_ENUM_DV_PRESETS, vidioc_enum_dv_presets); + SET_VALID_IOCTL(ops, VIDIOC_S_DV_PRESET, vidioc_s_dv_preset); + SET_VALID_IOCTL(ops, VIDIOC_G_DV_PRESET, vidioc_g_dv_preset); + SET_VALID_IOCTL(ops, VIDIOC_S_DV_TIMINGS, vidioc_s_dv_timings); + SET_VALID_IOCTL(ops, VIDIOC_G_DV_TIMINGS, vidioc_g_dv_timings); + SET_VALID_IOCTL(ops, VIDIOC_ENUM_DV_TIMINGS, vidioc_enum_dv_timings); + SET_VALID_IOCTL(ops, VIDIOC_DV_TIMINGS_CAP, vidioc_dv_timings_cap); + } + if (is_tx) { + /* transmitter only ioctls */ + SET_VALID_IOCTL(ops, VIDIOC_G_MODULATOR, vidioc_g_modulator); + SET_VALID_IOCTL(ops, VIDIOC_S_MODULATOR, vidioc_s_modulator); + } + if (is_rx) { + /* receiver only ioctls */ + SET_VALID_IOCTL(ops, VIDIOC_G_TUNER, vidioc_g_tuner); + SET_VALID_IOCTL(ops, VIDIOC_S_TUNER, vidioc_s_tuner); + SET_VALID_IOCTL(ops, VIDIOC_S_HW_FREQ_SEEK, vidioc_s_hw_freq_seek); + } + bitmap_andnot(vdev->valid_ioctls, valid_ioctls, vdev->valid_ioctls, BASE_VIDIOC_PRIVATE); } @@ -882,10 +877,6 @@ int __video_register_device(struct video_device *vdev, int type, int nr, WARN_ON(video_device[vdev->minor] != NULL); vdev->index = get_index(vdev); mutex_unlock(&videodev_lock); - /* if no lock was passed, then make sure the LOCK_ALL_FOPS bit is - clear and warn if it wasn't. */ - if (vdev->lock == NULL) - WARN_ON(test_and_clear_bit(V4L2_FL_LOCK_ALL_FOPS, &vdev->flags)); if (vdev->ioctl_ops) determine_valid_ioctls(vdev); diff --git a/drivers/media/video/v4l2-device.c b/drivers/media/v4l2-core/v4l2-device.c index 1f203b85a637..513969fa695d 100644 --- a/drivers/media/video/v4l2-device.c +++ b/drivers/media/v4l2-core/v4l2-device.c @@ -166,7 +166,7 @@ int v4l2_device_register_subdev(struct v4l2_device *v4l2_dev, } /* This just returns 0 if either of the two args is NULL */ - err = v4l2_ctrl_add_handler(v4l2_dev->ctrl_handler, sd->ctrl_handler); + err = v4l2_ctrl_add_handler(v4l2_dev->ctrl_handler, sd->ctrl_handler, NULL); if (err) { if (sd->internal_ops && sd->internal_ops->unregistered) sd->internal_ops->unregistered(sd); diff --git a/drivers/media/video/v4l2-event.c b/drivers/media/v4l2-core/v4l2-event.c index ef2a33c94045..18a040b935a3 100644 --- a/drivers/media/video/v4l2-event.c +++ b/drivers/media/v4l2-core/v4l2-event.c @@ -203,7 +203,7 @@ int v4l2_event_pending(struct v4l2_fh *fh) EXPORT_SYMBOL_GPL(v4l2_event_pending); int v4l2_event_subscribe(struct v4l2_fh *fh, - struct v4l2_event_subscription *sub, unsigned elems, + const struct v4l2_event_subscription *sub, unsigned elems, const struct v4l2_subscribed_event_ops *ops) { struct v4l2_subscribed_event *sev, *found_ev; @@ -278,7 +278,7 @@ void v4l2_event_unsubscribe_all(struct v4l2_fh *fh) EXPORT_SYMBOL_GPL(v4l2_event_unsubscribe_all); int v4l2_event_unsubscribe(struct v4l2_fh *fh, - struct v4l2_event_subscription *sub) + const struct v4l2_event_subscription *sub) { struct v4l2_subscribed_event *sev; unsigned long flags; diff --git a/drivers/media/video/v4l2-fh.c b/drivers/media/v4l2-core/v4l2-fh.c index 9e3fc040ea20..9e3fc040ea20 100644 --- a/drivers/media/video/v4l2-fh.c +++ b/drivers/media/v4l2-core/v4l2-fh.c diff --git a/drivers/media/video/v4l2-int-device.c b/drivers/media/v4l2-core/v4l2-int-device.c index f4473494af7a..f4473494af7a 100644 --- a/drivers/media/video/v4l2-int-device.c +++ b/drivers/media/v4l2-core/v4l2-int-device.c diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c index 6bc47fc82fe2..9d3e46c446ad 100644 --- a/drivers/media/video/v4l2-ioctl.c +++ b/drivers/media/v4l2-core/v4l2-ioctl.c @@ -316,9 +316,6 @@ static void v4l_print_format(const void *arg, bool write_only) sliced->service_lines[0][i], sliced->service_lines[1][i]); break; - case V4L2_BUF_TYPE_PRIVATE: - pr_cont("\n"); - break; } } @@ -879,57 +876,62 @@ static int check_ext_ctrls(struct v4l2_ext_controls *c, int allow_priv) return 1; } -static int check_fmt(const struct v4l2_ioctl_ops *ops, enum v4l2_buf_type type) +static int check_fmt(struct file *file, enum v4l2_buf_type type) { + struct video_device *vfd = video_devdata(file); + const struct v4l2_ioctl_ops *ops = vfd->ioctl_ops; + bool is_vid = vfd->vfl_type == VFL_TYPE_GRABBER; + bool is_vbi = vfd->vfl_type == VFL_TYPE_VBI; + bool is_rx = vfd->vfl_dir != VFL_DIR_TX; + bool is_tx = vfd->vfl_dir != VFL_DIR_RX; + if (ops == NULL) return -EINVAL; switch (type) { case V4L2_BUF_TYPE_VIDEO_CAPTURE: - if (ops->vidioc_g_fmt_vid_cap || - ops->vidioc_g_fmt_vid_cap_mplane) + if (is_vid && is_rx && + (ops->vidioc_g_fmt_vid_cap || ops->vidioc_g_fmt_vid_cap_mplane)) return 0; break; case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: - if (ops->vidioc_g_fmt_vid_cap_mplane) + if (is_vid && is_rx && ops->vidioc_g_fmt_vid_cap_mplane) return 0; break; case V4L2_BUF_TYPE_VIDEO_OVERLAY: - if (ops->vidioc_g_fmt_vid_overlay) + if (is_vid && is_rx && ops->vidioc_g_fmt_vid_overlay) return 0; break; case V4L2_BUF_TYPE_VIDEO_OUTPUT: - if (ops->vidioc_g_fmt_vid_out || - ops->vidioc_g_fmt_vid_out_mplane) + if (is_vid && is_tx && + (ops->vidioc_g_fmt_vid_out || ops->vidioc_g_fmt_vid_out_mplane)) return 0; break; case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: - if (ops->vidioc_g_fmt_vid_out_mplane) + if (is_vid && is_tx && ops->vidioc_g_fmt_vid_out_mplane) return 0; break; case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: - if (ops->vidioc_g_fmt_vid_out_overlay) + if (is_vid && is_tx && ops->vidioc_g_fmt_vid_out_overlay) return 0; break; case V4L2_BUF_TYPE_VBI_CAPTURE: - if (ops->vidioc_g_fmt_vbi_cap) + if (is_vbi && is_rx && ops->vidioc_g_fmt_vbi_cap) return 0; break; case V4L2_BUF_TYPE_VBI_OUTPUT: - if (ops->vidioc_g_fmt_vbi_out) + if (is_vbi && is_tx && ops->vidioc_g_fmt_vbi_out) return 0; break; case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: - if (ops->vidioc_g_fmt_sliced_vbi_cap) + if (is_vbi && is_rx && ops->vidioc_g_fmt_sliced_vbi_cap) return 0; break; case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: - if (ops->vidioc_g_fmt_sliced_vbi_out) + if (is_vbi && is_tx && ops->vidioc_g_fmt_sliced_vbi_out) return 0; break; - case V4L2_BUF_TYPE_PRIVATE: - if (ops->vidioc_g_fmt_type_private) - return 0; + default: break; } return -EINVAL; @@ -989,7 +991,7 @@ static int v4l_enuminput(const struct v4l2_ioctl_ops *ops, struct v4l2_input *p = arg; /* - * We set the flags for CAP_PRESETS, CAP_CUSTOM_TIMINGS & + * We set the flags for CAP_PRESETS, CAP_DV_TIMINGS & * CAP_STD here based on ioctl handler provided by the * driver. If the driver doesn't support these * for a specific input, it must override these flags. @@ -999,7 +1001,7 @@ static int v4l_enuminput(const struct v4l2_ioctl_ops *ops, if (ops->vidioc_s_dv_preset) p->capabilities |= V4L2_IN_CAP_PRESETS; if (ops->vidioc_s_dv_timings) - p->capabilities |= V4L2_IN_CAP_CUSTOM_TIMINGS; + p->capabilities |= V4L2_IN_CAP_DV_TIMINGS; return ops->vidioc_enum_input(file, fh, p); } @@ -1010,7 +1012,7 @@ static int v4l_enumoutput(const struct v4l2_ioctl_ops *ops, struct v4l2_output *p = arg; /* - * We set the flags for CAP_PRESETS, CAP_CUSTOM_TIMINGS & + * We set the flags for CAP_PRESETS, CAP_DV_TIMINGS & * CAP_STD here based on ioctl handler provided by the * driver. If the driver doesn't support these * for a specific output, it must override these flags. @@ -1020,7 +1022,7 @@ static int v4l_enumoutput(const struct v4l2_ioctl_ops *ops, if (ops->vidioc_s_dv_preset) p->capabilities |= V4L2_OUT_CAP_PRESETS; if (ops->vidioc_s_dv_timings) - p->capabilities |= V4L2_OUT_CAP_CUSTOM_TIMINGS; + p->capabilities |= V4L2_OUT_CAP_DV_TIMINGS; return ops->vidioc_enum_output(file, fh, p); } @@ -1029,32 +1031,31 @@ static int v4l_enum_fmt(const struct v4l2_ioctl_ops *ops, struct file *file, void *fh, void *arg) { struct v4l2_fmtdesc *p = arg; + struct video_device *vfd = video_devdata(file); + bool is_rx = vfd->vfl_dir != VFL_DIR_TX; + bool is_tx = vfd->vfl_dir != VFL_DIR_RX; switch (p->type) { case V4L2_BUF_TYPE_VIDEO_CAPTURE: - if (unlikely(!ops->vidioc_enum_fmt_vid_cap)) + if (unlikely(!is_rx || !ops->vidioc_enum_fmt_vid_cap)) break; return ops->vidioc_enum_fmt_vid_cap(file, fh, arg); case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: - if (unlikely(!ops->vidioc_enum_fmt_vid_cap_mplane)) + if (unlikely(!is_rx || !ops->vidioc_enum_fmt_vid_cap_mplane)) break; return ops->vidioc_enum_fmt_vid_cap_mplane(file, fh, arg); case V4L2_BUF_TYPE_VIDEO_OVERLAY: - if (unlikely(!ops->vidioc_enum_fmt_vid_overlay)) + if (unlikely(!is_rx || !ops->vidioc_enum_fmt_vid_overlay)) break; return ops->vidioc_enum_fmt_vid_overlay(file, fh, arg); case V4L2_BUF_TYPE_VIDEO_OUTPUT: - if (unlikely(!ops->vidioc_enum_fmt_vid_out)) + if (unlikely(!is_tx || !ops->vidioc_enum_fmt_vid_out)) break; return ops->vidioc_enum_fmt_vid_out(file, fh, arg); case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: - if (unlikely(!ops->vidioc_enum_fmt_vid_out_mplane)) + if (unlikely(!is_tx || !ops->vidioc_enum_fmt_vid_out_mplane)) break; return ops->vidioc_enum_fmt_vid_out_mplane(file, fh, arg); - case V4L2_BUF_TYPE_PRIVATE: - if (unlikely(!ops->vidioc_enum_fmt_type_private)) - break; - return ops->vidioc_enum_fmt_type_private(file, fh, arg); } return -EINVAL; } @@ -1063,52 +1064,52 @@ static int v4l_g_fmt(const struct v4l2_ioctl_ops *ops, struct file *file, void *fh, void *arg) { struct v4l2_format *p = arg; + struct video_device *vfd = video_devdata(file); + bool is_vid = vfd->vfl_type == VFL_TYPE_GRABBER; + bool is_rx = vfd->vfl_dir != VFL_DIR_TX; + bool is_tx = vfd->vfl_dir != VFL_DIR_RX; switch (p->type) { case V4L2_BUF_TYPE_VIDEO_CAPTURE: - if (unlikely(!ops->vidioc_g_fmt_vid_cap)) + if (unlikely(!is_rx || !is_vid || !ops->vidioc_g_fmt_vid_cap)) break; return ops->vidioc_g_fmt_vid_cap(file, fh, arg); case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: - if (unlikely(!ops->vidioc_g_fmt_vid_cap_mplane)) + if (unlikely(!is_rx || !is_vid || !ops->vidioc_g_fmt_vid_cap_mplane)) break; return ops->vidioc_g_fmt_vid_cap_mplane(file, fh, arg); case V4L2_BUF_TYPE_VIDEO_OVERLAY: - if (unlikely(!ops->vidioc_g_fmt_vid_overlay)) + if (unlikely(!is_rx || !is_vid || !ops->vidioc_g_fmt_vid_overlay)) break; return ops->vidioc_g_fmt_vid_overlay(file, fh, arg); + case V4L2_BUF_TYPE_VBI_CAPTURE: + if (unlikely(!is_rx || is_vid || !ops->vidioc_g_fmt_vbi_cap)) + break; + return ops->vidioc_g_fmt_vbi_cap(file, fh, arg); + case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: + if (unlikely(!is_rx || is_vid || !ops->vidioc_g_fmt_sliced_vbi_cap)) + break; + return ops->vidioc_g_fmt_sliced_vbi_cap(file, fh, arg); case V4L2_BUF_TYPE_VIDEO_OUTPUT: - if (unlikely(!ops->vidioc_g_fmt_vid_out)) + if (unlikely(!is_tx || !is_vid || !ops->vidioc_g_fmt_vid_out)) break; return ops->vidioc_g_fmt_vid_out(file, fh, arg); case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: - if (unlikely(!ops->vidioc_g_fmt_vid_out_mplane)) + if (unlikely(!is_tx || !is_vid || !ops->vidioc_g_fmt_vid_out_mplane)) break; return ops->vidioc_g_fmt_vid_out_mplane(file, fh, arg); case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: - if (unlikely(!ops->vidioc_g_fmt_vid_out_overlay)) + if (unlikely(!is_tx || !is_vid || !ops->vidioc_g_fmt_vid_out_overlay)) break; return ops->vidioc_g_fmt_vid_out_overlay(file, fh, arg); - case V4L2_BUF_TYPE_VBI_CAPTURE: - if (unlikely(!ops->vidioc_g_fmt_vbi_cap)) - break; - return ops->vidioc_g_fmt_vbi_cap(file, fh, arg); case V4L2_BUF_TYPE_VBI_OUTPUT: - if (unlikely(!ops->vidioc_g_fmt_vbi_out)) + if (unlikely(!is_tx || is_vid || !ops->vidioc_g_fmt_vbi_out)) break; return ops->vidioc_g_fmt_vbi_out(file, fh, arg); - case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: - if (unlikely(!ops->vidioc_g_fmt_sliced_vbi_cap)) - break; - return ops->vidioc_g_fmt_sliced_vbi_cap(file, fh, arg); case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: - if (unlikely(!ops->vidioc_g_fmt_sliced_vbi_out)) + if (unlikely(!is_tx || is_vid || !ops->vidioc_g_fmt_sliced_vbi_out)) break; return ops->vidioc_g_fmt_sliced_vbi_out(file, fh, arg); - case V4L2_BUF_TYPE_PRIVATE: - if (unlikely(!ops->vidioc_g_fmt_type_private)) - break; - return ops->vidioc_g_fmt_type_private(file, fh, arg); } return -EINVAL; } @@ -1117,62 +1118,62 @@ static int v4l_s_fmt(const struct v4l2_ioctl_ops *ops, struct file *file, void *fh, void *arg) { struct v4l2_format *p = arg; + struct video_device *vfd = video_devdata(file); + bool is_vid = vfd->vfl_type == VFL_TYPE_GRABBER; + bool is_rx = vfd->vfl_dir != VFL_DIR_TX; + bool is_tx = vfd->vfl_dir != VFL_DIR_RX; switch (p->type) { case V4L2_BUF_TYPE_VIDEO_CAPTURE: - if (unlikely(!ops->vidioc_s_fmt_vid_cap)) + if (unlikely(!is_rx || !is_vid || !ops->vidioc_s_fmt_vid_cap)) break; CLEAR_AFTER_FIELD(p, fmt.pix); return ops->vidioc_s_fmt_vid_cap(file, fh, arg); case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: - if (unlikely(!ops->vidioc_s_fmt_vid_cap_mplane)) + if (unlikely(!is_rx || !is_vid || !ops->vidioc_s_fmt_vid_cap_mplane)) break; CLEAR_AFTER_FIELD(p, fmt.pix_mp); return ops->vidioc_s_fmt_vid_cap_mplane(file, fh, arg); case V4L2_BUF_TYPE_VIDEO_OVERLAY: - if (unlikely(!ops->vidioc_s_fmt_vid_overlay)) + if (unlikely(!is_rx || !is_vid || !ops->vidioc_s_fmt_vid_overlay)) break; CLEAR_AFTER_FIELD(p, fmt.win); return ops->vidioc_s_fmt_vid_overlay(file, fh, arg); + case V4L2_BUF_TYPE_VBI_CAPTURE: + if (unlikely(!is_rx || is_vid || !ops->vidioc_s_fmt_vbi_cap)) + break; + CLEAR_AFTER_FIELD(p, fmt.vbi); + return ops->vidioc_s_fmt_vbi_cap(file, fh, arg); + case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: + if (unlikely(!is_rx || is_vid || !ops->vidioc_s_fmt_sliced_vbi_cap)) + break; + CLEAR_AFTER_FIELD(p, fmt.sliced); + return ops->vidioc_s_fmt_sliced_vbi_cap(file, fh, arg); case V4L2_BUF_TYPE_VIDEO_OUTPUT: - if (unlikely(!ops->vidioc_s_fmt_vid_out)) + if (unlikely(!is_tx || !is_vid || !ops->vidioc_s_fmt_vid_out)) break; CLEAR_AFTER_FIELD(p, fmt.pix); return ops->vidioc_s_fmt_vid_out(file, fh, arg); case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: - if (unlikely(!ops->vidioc_s_fmt_vid_out_mplane)) + if (unlikely(!is_tx || !is_vid || !ops->vidioc_s_fmt_vid_out_mplane)) break; CLEAR_AFTER_FIELD(p, fmt.pix_mp); return ops->vidioc_s_fmt_vid_out_mplane(file, fh, arg); case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: - if (unlikely(!ops->vidioc_s_fmt_vid_out_overlay)) + if (unlikely(!is_tx || !is_vid || !ops->vidioc_s_fmt_vid_out_overlay)) break; CLEAR_AFTER_FIELD(p, fmt.win); return ops->vidioc_s_fmt_vid_out_overlay(file, fh, arg); - case V4L2_BUF_TYPE_VBI_CAPTURE: - if (unlikely(!ops->vidioc_s_fmt_vbi_cap)) - break; - CLEAR_AFTER_FIELD(p, fmt.vbi); - return ops->vidioc_s_fmt_vbi_cap(file, fh, arg); case V4L2_BUF_TYPE_VBI_OUTPUT: - if (unlikely(!ops->vidioc_s_fmt_vbi_out)) + if (unlikely(!is_tx || is_vid || !ops->vidioc_s_fmt_vbi_out)) break; CLEAR_AFTER_FIELD(p, fmt.vbi); return ops->vidioc_s_fmt_vbi_out(file, fh, arg); - case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: - if (unlikely(!ops->vidioc_s_fmt_sliced_vbi_cap)) - break; - CLEAR_AFTER_FIELD(p, fmt.sliced); - return ops->vidioc_s_fmt_sliced_vbi_cap(file, fh, arg); case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: - if (unlikely(!ops->vidioc_s_fmt_sliced_vbi_out)) + if (unlikely(!is_tx || is_vid || !ops->vidioc_s_fmt_sliced_vbi_out)) break; CLEAR_AFTER_FIELD(p, fmt.sliced); return ops->vidioc_s_fmt_sliced_vbi_out(file, fh, arg); - case V4L2_BUF_TYPE_PRIVATE: - if (unlikely(!ops->vidioc_s_fmt_type_private)) - break; - return ops->vidioc_s_fmt_type_private(file, fh, arg); } return -EINVAL; } @@ -1181,62 +1182,62 @@ static int v4l_try_fmt(const struct v4l2_ioctl_ops *ops, struct file *file, void *fh, void *arg) { struct v4l2_format *p = arg; + struct video_device *vfd = video_devdata(file); + bool is_vid = vfd->vfl_type == VFL_TYPE_GRABBER; + bool is_rx = vfd->vfl_dir != VFL_DIR_TX; + bool is_tx = vfd->vfl_dir != VFL_DIR_RX; switch (p->type) { case V4L2_BUF_TYPE_VIDEO_CAPTURE: - if (unlikely(!ops->vidioc_try_fmt_vid_cap)) + if (unlikely(!is_rx || !is_vid || !ops->vidioc_try_fmt_vid_cap)) break; CLEAR_AFTER_FIELD(p, fmt.pix); return ops->vidioc_try_fmt_vid_cap(file, fh, arg); case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: - if (unlikely(!ops->vidioc_try_fmt_vid_cap_mplane)) + if (unlikely(!is_rx || !is_vid || !ops->vidioc_try_fmt_vid_cap_mplane)) break; CLEAR_AFTER_FIELD(p, fmt.pix_mp); return ops->vidioc_try_fmt_vid_cap_mplane(file, fh, arg); case V4L2_BUF_TYPE_VIDEO_OVERLAY: - if (unlikely(!ops->vidioc_try_fmt_vid_overlay)) + if (unlikely(!is_rx || !is_vid || !ops->vidioc_try_fmt_vid_overlay)) break; CLEAR_AFTER_FIELD(p, fmt.win); return ops->vidioc_try_fmt_vid_overlay(file, fh, arg); + case V4L2_BUF_TYPE_VBI_CAPTURE: + if (unlikely(!is_rx || is_vid || !ops->vidioc_try_fmt_vbi_cap)) + break; + CLEAR_AFTER_FIELD(p, fmt.vbi); + return ops->vidioc_try_fmt_vbi_cap(file, fh, arg); + case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: + if (unlikely(!is_rx || is_vid || !ops->vidioc_try_fmt_sliced_vbi_cap)) + break; + CLEAR_AFTER_FIELD(p, fmt.sliced); + return ops->vidioc_try_fmt_sliced_vbi_cap(file, fh, arg); case V4L2_BUF_TYPE_VIDEO_OUTPUT: - if (unlikely(!ops->vidioc_try_fmt_vid_out)) + if (unlikely(!is_tx || !is_vid || !ops->vidioc_try_fmt_vid_out)) break; CLEAR_AFTER_FIELD(p, fmt.pix); return ops->vidioc_try_fmt_vid_out(file, fh, arg); case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: - if (unlikely(!ops->vidioc_try_fmt_vid_out_mplane)) + if (unlikely(!is_tx || !is_vid || !ops->vidioc_try_fmt_vid_out_mplane)) break; CLEAR_AFTER_FIELD(p, fmt.pix_mp); return ops->vidioc_try_fmt_vid_out_mplane(file, fh, arg); case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: - if (unlikely(!ops->vidioc_try_fmt_vid_out_overlay)) + if (unlikely(!is_tx || !is_vid || !ops->vidioc_try_fmt_vid_out_overlay)) break; CLEAR_AFTER_FIELD(p, fmt.win); return ops->vidioc_try_fmt_vid_out_overlay(file, fh, arg); - case V4L2_BUF_TYPE_VBI_CAPTURE: - if (unlikely(!ops->vidioc_try_fmt_vbi_cap)) - break; - CLEAR_AFTER_FIELD(p, fmt.vbi); - return ops->vidioc_try_fmt_vbi_cap(file, fh, arg); case V4L2_BUF_TYPE_VBI_OUTPUT: - if (unlikely(!ops->vidioc_try_fmt_vbi_out)) + if (unlikely(!is_tx || is_vid || !ops->vidioc_try_fmt_vbi_out)) break; CLEAR_AFTER_FIELD(p, fmt.vbi); return ops->vidioc_try_fmt_vbi_out(file, fh, arg); - case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: - if (unlikely(!ops->vidioc_try_fmt_sliced_vbi_cap)) - break; - CLEAR_AFTER_FIELD(p, fmt.sliced); - return ops->vidioc_try_fmt_sliced_vbi_cap(file, fh, arg); case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: - if (unlikely(!ops->vidioc_try_fmt_sliced_vbi_out)) + if (unlikely(!is_tx || is_vid || !ops->vidioc_try_fmt_sliced_vbi_out)) break; CLEAR_AFTER_FIELD(p, fmt.sliced); return ops->vidioc_try_fmt_sliced_vbi_out(file, fh, arg); - case V4L2_BUF_TYPE_PRIVATE: - if (unlikely(!ops->vidioc_try_fmt_type_private)) - break; - return ops->vidioc_try_fmt_type_private(file, fh, arg); } return -EINVAL; } @@ -1325,6 +1326,11 @@ static int v4l_enumstd(const struct v4l2_ioctl_ops *ops, unsigned int index = p->index, i, j = 0; const char *descr = ""; + /* Return -ENODATA if the tvnorms for the current input + or output is 0, meaning that it doesn't support this API. */ + if (id == 0) + return -ENODATA; + /* Return norm array in a canonical way */ for (i = 0; i <= index && id; i++) { /* last std value in the standards array is 0, so this @@ -1416,17 +1422,22 @@ static int v4l_s_hw_freq_seek(const struct v4l2_ioctl_ops *ops, return ops->vidioc_s_hw_freq_seek(file, fh, p); } +static int v4l_overlay(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) +{ + return ops->vidioc_overlay(file, fh, *(unsigned int *)arg); +} + static int v4l_reqbufs(const struct v4l2_ioctl_ops *ops, struct file *file, void *fh, void *arg) { struct v4l2_requestbuffers *p = arg; - int ret = check_fmt(ops, p->type); + int ret = check_fmt(file, p->type); if (ret) return ret; - if (p->type < V4L2_BUF_TYPE_PRIVATE) - CLEAR_AFTER_FIELD(p, memory); + CLEAR_AFTER_FIELD(p, memory); return ops->vidioc_reqbufs(file, fh, p); } @@ -1435,7 +1446,7 @@ static int v4l_querybuf(const struct v4l2_ioctl_ops *ops, struct file *file, void *fh, void *arg) { struct v4l2_buffer *p = arg; - int ret = check_fmt(ops, p->type); + int ret = check_fmt(file, p->type); return ret ? ret : ops->vidioc_querybuf(file, fh, p); } @@ -1444,7 +1455,7 @@ static int v4l_qbuf(const struct v4l2_ioctl_ops *ops, struct file *file, void *fh, void *arg) { struct v4l2_buffer *p = arg; - int ret = check_fmt(ops, p->type); + int ret = check_fmt(file, p->type); return ret ? ret : ops->vidioc_qbuf(file, fh, p); } @@ -1453,7 +1464,7 @@ static int v4l_dqbuf(const struct v4l2_ioctl_ops *ops, struct file *file, void *fh, void *arg) { struct v4l2_buffer *p = arg; - int ret = check_fmt(ops, p->type); + int ret = check_fmt(file, p->type); return ret ? ret : ops->vidioc_dqbuf(file, fh, p); } @@ -1462,7 +1473,7 @@ static int v4l_create_bufs(const struct v4l2_ioctl_ops *ops, struct file *file, void *fh, void *arg) { struct v4l2_create_buffers *create = arg; - int ret = check_fmt(ops, create->format.type); + int ret = check_fmt(file, create->format.type); return ret ? ret : ops->vidioc_create_bufs(file, fh, create); } @@ -1471,7 +1482,7 @@ static int v4l_prepare_buf(const struct v4l2_ioctl_ops *ops, struct file *file, void *fh, void *arg) { struct v4l2_buffer *b = arg; - int ret = check_fmt(ops, b->type); + int ret = check_fmt(file, b->type); return ret ? ret : ops->vidioc_prepare_buf(file, fh, b); } @@ -1482,7 +1493,7 @@ static int v4l_g_parm(const struct v4l2_ioctl_ops *ops, struct video_device *vfd = video_devdata(file); struct v4l2_streamparm *p = arg; v4l2_std_id std; - int ret = check_fmt(ops, p->type); + int ret = check_fmt(file, p->type); if (ret) return ret; @@ -1505,7 +1516,7 @@ static int v4l_s_parm(const struct v4l2_ioctl_ops *ops, struct file *file, void *fh, void *arg) { struct v4l2_streamparm *p = arg; - int ret = check_fmt(ops, p->type); + int ret = check_fmt(file, p->type); return ret ? ret : ops->vidioc_s_parm(file, fh, p); } @@ -1827,6 +1838,10 @@ static int v4l_g_sliced_vbi_cap(const struct v4l2_ioctl_ops *ops, struct file *file, void *fh, void *arg) { struct v4l2_sliced_vbi_cap *p = arg; + int ret = check_fmt(file, p->type); + + if (ret) + return ret; /* Clear up to type, everything after type is zeroed already */ memset(p, 0, offsetof(struct v4l2_sliced_vbi_cap, type)); @@ -1944,7 +1959,7 @@ static struct v4l2_ioctl_info v4l2_ioctls[] = { IOCTL_INFO_FNC(VIDIOC_QUERYBUF, v4l_querybuf, v4l_print_buffer, INFO_FL_QUEUE | INFO_FL_CLEAR(v4l2_buffer, length)), IOCTL_INFO_STD(VIDIOC_G_FBUF, vidioc_g_fbuf, v4l_print_framebuffer, 0), IOCTL_INFO_STD(VIDIOC_S_FBUF, vidioc_s_fbuf, v4l_print_framebuffer, INFO_FL_PRIO), - IOCTL_INFO_STD(VIDIOC_OVERLAY, vidioc_overlay, v4l_print_u32, INFO_FL_PRIO), + IOCTL_INFO_FNC(VIDIOC_OVERLAY, v4l_overlay, v4l_print_u32, INFO_FL_PRIO), IOCTL_INFO_FNC(VIDIOC_QBUF, v4l_qbuf, v4l_print_buffer, INFO_FL_QUEUE), IOCTL_INFO_FNC(VIDIOC_DQBUF, v4l_dqbuf, v4l_print_buffer, INFO_FL_QUEUE), IOCTL_INFO_FNC(VIDIOC_STREAMON, v4l_streamon, v4l_print_buftype, INFO_FL_PRIO | INFO_FL_QUEUE), @@ -2191,6 +2206,19 @@ static int check_array_args(unsigned int cmd, void *parg, size_t *array_size, break; } + case VIDIOC_SUBDEV_G_EDID: + case VIDIOC_SUBDEV_S_EDID: { + struct v4l2_subdev_edid *edid = parg; + + if (edid->blocks) { + *user_ptr = (void __user *)edid->edid; + *kernel_ptr = (void *)&edid->edid; + *array_size = edid->blocks * 128; + ret = 1; + } + break; + } + case VIDIOC_S_EXT_CTRLS: case VIDIOC_G_EXT_CTRLS: case VIDIOC_TRY_EXT_CTRLS: { diff --git a/drivers/media/video/v4l2-mem2mem.c b/drivers/media/v4l2-core/v4l2-mem2mem.c index 97b48318aee1..3ac83583ad7a 100644 --- a/drivers/media/video/v4l2-mem2mem.c +++ b/drivers/media/v4l2-core/v4l2-mem2mem.c @@ -105,7 +105,7 @@ void *v4l2_m2m_next_buf(struct v4l2_m2m_queue_ctx *q_ctx) return NULL; } - b = list_entry(q_ctx->rdy_queue.next, struct v4l2_m2m_buffer, list); + b = list_first_entry(&q_ctx->rdy_queue, struct v4l2_m2m_buffer, list); spin_unlock_irqrestore(&q_ctx->rdy_spinlock, flags); return &b->vb; } @@ -125,7 +125,7 @@ void *v4l2_m2m_buf_remove(struct v4l2_m2m_queue_ctx *q_ctx) spin_unlock_irqrestore(&q_ctx->rdy_spinlock, flags); return NULL; } - b = list_entry(q_ctx->rdy_queue.next, struct v4l2_m2m_buffer, list); + b = list_first_entry(&q_ctx->rdy_queue, struct v4l2_m2m_buffer, list); list_del(&b->list); q_ctx->num_rdy--; spin_unlock_irqrestore(&q_ctx->rdy_spinlock, flags); @@ -178,7 +178,7 @@ static void v4l2_m2m_try_run(struct v4l2_m2m_dev *m2m_dev) return; } - m2m_dev->curr_ctx = list_entry(m2m_dev->job_queue.next, + m2m_dev->curr_ctx = list_first_entry(&m2m_dev->job_queue, struct v4l2_m2m_ctx, queue); m2m_dev->curr_ctx->job_flags |= TRANS_RUNNING; spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags); diff --git a/drivers/media/video/v4l2-subdev.c b/drivers/media/v4l2-core/v4l2-subdev.c index 9182f81deb5b..dced41c1d993 100644 --- a/drivers/media/video/v4l2-subdev.c +++ b/drivers/media/v4l2-core/v4l2-subdev.c @@ -348,6 +348,12 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg) return v4l2_subdev_call( sd, pad, set_selection, subdev_fh, sel); } + + case VIDIOC_SUBDEV_G_EDID: + return v4l2_subdev_call(sd, pad, get_edid, arg); + + case VIDIOC_SUBDEV_S_EDID: + return v4l2_subdev_call(sd, pad, set_edid, arg); #endif default: return v4l2_subdev_call(sd, core, ioctl, cmd, arg); diff --git a/drivers/media/video/videobuf-core.c b/drivers/media/v4l2-core/videobuf-core.c index bf7a326b1cdc..bf7a326b1cdc 100644 --- a/drivers/media/video/videobuf-core.c +++ b/drivers/media/v4l2-core/videobuf-core.c diff --git a/drivers/media/video/videobuf-dma-contig.c b/drivers/media/v4l2-core/videobuf-dma-contig.c index 3a43ba0959bf..3a43ba0959bf 100644 --- a/drivers/media/video/videobuf-dma-contig.c +++ b/drivers/media/v4l2-core/videobuf-dma-contig.c diff --git a/drivers/media/video/videobuf-dma-sg.c b/drivers/media/v4l2-core/videobuf-dma-sg.c index f300deafd268..f300deafd268 100644 --- a/drivers/media/video/videobuf-dma-sg.c +++ b/drivers/media/v4l2-core/videobuf-dma-sg.c diff --git a/drivers/media/video/videobuf-dvb.c b/drivers/media/v4l2-core/videobuf-dvb.c index 94d83a41381b..b7efa4516d36 100644 --- a/drivers/media/video/videobuf-dvb.c +++ b/drivers/media/v4l2-core/videobuf-dvb.c @@ -139,9 +139,7 @@ static int videobuf_dvb_register_adapter(struct videobuf_dvb_frontends *fe, struct device *device, char *adapter_name, short *adapter_nr, - int mfe_shared, - int (*fe_ioctl_override)(struct dvb_frontend *, - unsigned int, void *, unsigned int)) + int mfe_shared) { int result; @@ -156,7 +154,6 @@ static int videobuf_dvb_register_adapter(struct videobuf_dvb_frontends *fe, } fe->adapter.priv = adapter_priv; fe->adapter.mfe_shared = mfe_shared; - fe->adapter.fe_ioctl_override = fe_ioctl_override; return result; } @@ -257,9 +254,7 @@ int videobuf_dvb_register_bus(struct videobuf_dvb_frontends *f, void *adapter_priv, struct device *device, short *adapter_nr, - int mfe_shared, - int (*fe_ioctl_override)(struct dvb_frontend *, - unsigned int, void *, unsigned int)) + int mfe_shared) { struct list_head *list, *q; struct videobuf_dvb_frontend *fe; @@ -273,7 +268,7 @@ int videobuf_dvb_register_bus(struct videobuf_dvb_frontends *f, /* Bring up the adapter */ res = videobuf_dvb_register_adapter(f, module, adapter_priv, device, - fe->dvb.name, adapter_nr, mfe_shared, fe_ioctl_override); + fe->dvb.name, adapter_nr, mfe_shared); if (res < 0) { printk(KERN_WARNING "videobuf_dvb_register_adapter failed (errno = %d)\n", res); return res; diff --git a/drivers/media/video/videobuf-vmalloc.c b/drivers/media/v4l2-core/videobuf-vmalloc.c index df142580e44c..df142580e44c 100644 --- a/drivers/media/video/videobuf-vmalloc.c +++ b/drivers/media/v4l2-core/videobuf-vmalloc.c diff --git a/drivers/media/video/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c index 268c7dd4f823..e6a26b433e87 100644 --- a/drivers/media/video/videobuf2-core.c +++ b/drivers/media/v4l2-core/videobuf2-core.c @@ -1738,14 +1738,17 @@ EXPORT_SYMBOL_GPL(vb2_poll); */ int vb2_queue_init(struct vb2_queue *q) { - BUG_ON(!q); - BUG_ON(!q->ops); - BUG_ON(!q->mem_ops); - BUG_ON(!q->type); - BUG_ON(!q->io_modes); - - BUG_ON(!q->ops->queue_setup); - BUG_ON(!q->ops->buf_queue); + /* + * Sanity check + */ + if (WARN_ON(!q) || + WARN_ON(!q->ops) || + WARN_ON(!q->mem_ops) || + WARN_ON(!q->type) || + WARN_ON(!q->io_modes) || + WARN_ON(!q->ops->queue_setup) || + WARN_ON(!q->ops->buf_queue)) + return -EINVAL; INIT_LIST_HEAD(&q->queued_list); INIT_LIST_HEAD(&q->done_list); @@ -2270,19 +2273,18 @@ ssize_t vb2_fop_write(struct file *file, char __user *buf, { struct video_device *vdev = video_devdata(file); struct mutex *lock = vdev->queue->lock ? vdev->queue->lock : vdev->lock; - bool must_lock = !test_bit(V4L2_FL_LOCK_ALL_FOPS, &vdev->flags) && lock; int err = -EBUSY; - if (must_lock && mutex_lock_interruptible(lock)) + if (lock && mutex_lock_interruptible(lock)) return -ERESTARTSYS; if (vb2_queue_is_busy(vdev, file)) goto exit; err = vb2_write(vdev->queue, buf, count, ppos, file->f_flags & O_NONBLOCK); - if (err >= 0) + if (vdev->queue->fileio) vdev->queue->owner = file->private_data; exit: - if (must_lock) + if (lock) mutex_unlock(lock); return err; } @@ -2293,19 +2295,18 @@ ssize_t vb2_fop_read(struct file *file, char __user *buf, { struct video_device *vdev = video_devdata(file); struct mutex *lock = vdev->queue->lock ? vdev->queue->lock : vdev->lock; - bool must_lock = !test_bit(V4L2_FL_LOCK_ALL_FOPS, &vdev->flags) && vdev->lock; int err = -EBUSY; - if (must_lock && mutex_lock_interruptible(lock)) + if (lock && mutex_lock_interruptible(lock)) return -ERESTARTSYS; if (vb2_queue_is_busy(vdev, file)) goto exit; err = vb2_read(vdev->queue, buf, count, ppos, file->f_flags & O_NONBLOCK); - if (err >= 0) + if (vdev->queue->fileio) vdev->queue->owner = file->private_data; exit: - if (must_lock) + if (lock) mutex_unlock(lock); return err; } @@ -2319,11 +2320,6 @@ unsigned int vb2_fop_poll(struct file *file, poll_table *wait) unsigned long req_events = poll_requested_events(wait); unsigned res; void *fileio; - /* Yuck. We really need to get rid of this flag asap. If it is - set, then the core took the serialization lock before calling - poll(). This is being phased out, but for now we have to handle - this case. */ - bool locked = test_bit(V4L2_FL_LOCK_ALL_FOPS, &vdev->flags); bool must_lock = false; /* Try to be smart: only lock if polling might start fileio, @@ -2339,9 +2335,9 @@ unsigned int vb2_fop_poll(struct file *file, poll_table *wait) /* If locking is needed, but this helper doesn't know how, then you shouldn't be using this helper but you should write your own. */ - WARN_ON(must_lock && !locked && !lock); + WARN_ON(must_lock && !lock); - if (must_lock && !locked && lock && mutex_lock_interruptible(lock)) + if (must_lock && lock && mutex_lock_interruptible(lock)) return POLLERR; fileio = q->fileio; @@ -2351,7 +2347,7 @@ unsigned int vb2_fop_poll(struct file *file, poll_table *wait) /* If fileio was started, then we have a new queue owner. */ if (must_lock && !fileio && q->fileio) q->owner = file->private_data; - if (must_lock && !locked && lock) + if (must_lock && lock) mutex_unlock(lock); return res; } diff --git a/drivers/media/video/videobuf2-dma-contig.c b/drivers/media/v4l2-core/videobuf2-dma-contig.c index 4b7132660a93..4b7132660a93 100644 --- a/drivers/media/video/videobuf2-dma-contig.c +++ b/drivers/media/v4l2-core/videobuf2-dma-contig.c diff --git a/drivers/media/video/videobuf2-dma-sg.c b/drivers/media/v4l2-core/videobuf2-dma-sg.c index 25c3b360e1ad..25c3b360e1ad 100644 --- a/drivers/media/video/videobuf2-dma-sg.c +++ b/drivers/media/v4l2-core/videobuf2-dma-sg.c diff --git a/drivers/media/video/videobuf2-memops.c b/drivers/media/v4l2-core/videobuf2-memops.c index 504cd4cbe29e..504cd4cbe29e 100644 --- a/drivers/media/video/videobuf2-memops.c +++ b/drivers/media/v4l2-core/videobuf2-memops.c diff --git a/drivers/media/video/videobuf2-vmalloc.c b/drivers/media/v4l2-core/videobuf2-vmalloc.c index 6b5ca6c70a46..94efa04d8d55 100644 --- a/drivers/media/video/videobuf2-vmalloc.c +++ b/drivers/media/v4l2-core/videobuf2-vmalloc.c @@ -18,6 +18,7 @@ #include <linux/vmalloc.h> #include <media/videobuf2-core.h> +#include <media/videobuf2-vmalloc.h> #include <media/videobuf2-memops.h> struct vb2_vmalloc_buf { diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig deleted file mode 100644 index c128fac0ce2c..000000000000 --- a/drivers/media/video/Kconfig +++ /dev/null @@ -1,1263 +0,0 @@ -# -# Generic video config states -# - -config VIDEO_V4L2 - tristate - depends on VIDEO_DEV && VIDEO_V4L2_COMMON - default y - -config VIDEOBUF_GEN - tristate - -config VIDEOBUF_DMA_SG - depends on HAS_DMA - select VIDEOBUF_GEN - tristate - -config VIDEOBUF_VMALLOC - select VIDEOBUF_GEN - tristate - -config VIDEOBUF_DMA_CONTIG - depends on HAS_DMA - select VIDEOBUF_GEN - tristate - -config VIDEOBUF_DVB - tristate - select VIDEOBUF_GEN - -config VIDEO_BTCX - depends on PCI - tristate - -config VIDEO_TVEEPROM - tristate - depends on I2C - -config VIDEO_TUNER - tristate - depends on MEDIA_TUNER - -config V4L2_MEM2MEM_DEV - tristate - depends on VIDEOBUF2_CORE - -config VIDEOBUF2_CORE - tristate - -config VIDEOBUF2_MEMOPS - tristate - -config VIDEOBUF2_DMA_CONTIG - select VIDEOBUF2_CORE - select VIDEOBUF2_MEMOPS - tristate - -config VIDEOBUF2_VMALLOC - select VIDEOBUF2_CORE - select VIDEOBUF2_MEMOPS - tristate - - -config VIDEOBUF2_DMA_SG - #depends on HAS_DMA - select VIDEOBUF2_CORE - select VIDEOBUF2_MEMOPS - tristate -# -# Multimedia Video device configuration -# - -menuconfig VIDEO_CAPTURE_DRIVERS - bool "Video capture adapters" - depends on VIDEO_V4L2 - depends on MEDIA_CAMERA_SUPPORT || MEDIA_ANALOG_TV_SUPPORT - default y - ---help--- - Say Y here to enable selecting the video adapters for - webcams, analog TV, and hybrid analog/digital TV. - Some of those devices also supports FM radio. - -if VIDEO_CAPTURE_DRIVERS && VIDEO_V4L2 - -config VIDEO_ADV_DEBUG - bool "Enable advanced debug functionality" - default n - ---help--- - Say Y here to enable advanced debugging functionality on some - V4L devices. - In doubt, say N. - -config VIDEO_FIXED_MINOR_RANGES - bool "Enable old-style fixed minor ranges for video devices" - default n - ---help--- - Say Y here to enable the old-style fixed-range minor assignments. - Only useful if you rely on the old behavior and use mknod instead of udev. - - When in doubt, say N. - -config VIDEO_HELPER_CHIPS_AUTO - bool "Autoselect pertinent encoders/decoders and other helper chips" - default y if !EXPERT - ---help--- - Most video cards may require additional modules to encode or - decode audio/video standards. This option will autoselect - all pertinent modules to each selected video module. - - Unselect this only if you know exactly what you are doing, since - it may break support on some boards. - - In doubt, say Y. - -config VIDEO_IR_I2C - tristate "I2C module for IR" if !VIDEO_HELPER_CHIPS_AUTO - depends on I2C && RC_CORE - default y - ---help--- - Most boards have an IR chip directly connected via GPIO. However, - some video boards have the IR connected via I2C bus. - - If your board doesn't have an I2C IR chip, you may disable this - option. - - In doubt, say Y. - -# -# Encoder / Decoder module configuration -# - -menu "Encoders, decoders, sensors and other helper chips" - visible if !VIDEO_HELPER_CHIPS_AUTO - -comment "Audio decoders, processors and mixers" - -config VIDEO_TVAUDIO - tristate "Simple audio decoder chips" - depends on VIDEO_V4L2 && I2C - ---help--- - Support for several audio decoder chips found on some bt8xx boards: - Philips: tda9840, tda9873h, tda9874h/a, tda9850, tda985x, tea6300, - tea6320, tea6420, tda8425, ta8874z. - Microchip: pic16c54 based design on ProVideo PV951 board. - - To compile this driver as a module, choose M here: the - module will be called tvaudio. - -config VIDEO_TDA7432 - tristate "Philips TDA7432 audio processor" - depends on VIDEO_V4L2 && I2C - ---help--- - Support for tda7432 audio decoder chip found on some bt8xx boards. - - To compile this driver as a module, choose M here: the - module will be called tda7432. - -config VIDEO_TDA9840 - tristate "Philips TDA9840 audio processor" - depends on I2C - ---help--- - Support for tda9840 audio decoder chip found on some Zoran boards. - - To compile this driver as a module, choose M here: the - module will be called tda9840. - -config VIDEO_TEA6415C - tristate "Philips TEA6415C audio processor" - depends on I2C - ---help--- - Support for tea6415c audio decoder chip found on some bt8xx boards. - - To compile this driver as a module, choose M here: the - module will be called tea6415c. - -config VIDEO_TEA6420 - tristate "Philips TEA6420 audio processor" - depends on I2C - ---help--- - Support for tea6420 audio decoder chip found on some bt8xx boards. - - To compile this driver as a module, choose M here: the - module will be called tea6420. - -config VIDEO_MSP3400 - tristate "Micronas MSP34xx audio decoders" - depends on VIDEO_V4L2 && I2C - ---help--- - Support for the Micronas MSP34xx series of audio decoders. - - To compile this driver as a module, choose M here: the - module will be called msp3400. - -config VIDEO_CS5345 - tristate "Cirrus Logic CS5345 audio ADC" - depends on VIDEO_V4L2 && I2C - ---help--- - Support for the Cirrus Logic CS5345 24-bit, 192 kHz - stereo A/D converter. - - To compile this driver as a module, choose M here: the - module will be called cs5345. - -config VIDEO_CS53L32A - tristate "Cirrus Logic CS53L32A audio ADC" - depends on VIDEO_V4L2 && I2C - ---help--- - Support for the Cirrus Logic CS53L32A low voltage - stereo A/D converter. - - To compile this driver as a module, choose M here: the - module will be called cs53l32a. - -config VIDEO_TLV320AIC23B - tristate "Texas Instruments TLV320AIC23B audio codec" - depends on VIDEO_V4L2 && I2C && EXPERIMENTAL - ---help--- - Support for the Texas Instruments TLV320AIC23B audio codec. - - To compile this driver as a module, choose M here: the - module will be called tlv320aic23b. - -config VIDEO_WM8775 - tristate "Wolfson Microelectronics WM8775 audio ADC with input mixer" - depends on VIDEO_V4L2 && I2C - ---help--- - Support for the Wolfson Microelectronics WM8775 high - performance stereo A/D Converter with a 4 channel input mixer. - - To compile this driver as a module, choose M here: the - module will be called wm8775. - -config VIDEO_WM8739 - tristate "Wolfson Microelectronics WM8739 stereo audio ADC" - depends on VIDEO_V4L2 && I2C - ---help--- - Support for the Wolfson Microelectronics WM8739 - stereo A/D Converter. - - To compile this driver as a module, choose M here: the - module will be called wm8739. - -config VIDEO_VP27SMPX - tristate "Panasonic VP27s internal MPX" - depends on VIDEO_V4L2 && I2C - ---help--- - Support for the internal MPX of the Panasonic VP27s tuner. - - To compile this driver as a module, choose M here: the - module will be called vp27smpx. - -comment "RDS decoders" - -config VIDEO_SAA6588 - tristate "SAA6588 Radio Chip RDS decoder support" - depends on VIDEO_V4L2 && I2C - - help - Support for this Radio Data System (RDS) decoder. This allows - seeing radio station identification transmitted using this - standard. - - To compile this driver as a module, choose M here: the - module will be called saa6588. - -comment "Video decoders" - -config VIDEO_ADV7180 - tristate "Analog Devices ADV7180 decoder" - depends on VIDEO_V4L2 && I2C - ---help--- - Support for the Analog Devices ADV7180 video decoder. - - To compile this driver as a module, choose M here: the - module will be called adv7180. - -config VIDEO_ADV7183 - tristate "Analog Devices ADV7183 decoder" - depends on VIDEO_V4L2 && I2C - ---help--- - V4l2 subdevice driver for the Analog Devices - ADV7183 video decoder. - - To compile this driver as a module, choose M here: the - module will be called adv7183. - -config VIDEO_BT819 - tristate "BT819A VideoStream decoder" - depends on VIDEO_V4L2 && I2C - ---help--- - Support for BT819A video decoder. - - To compile this driver as a module, choose M here: the - module will be called bt819. - -config VIDEO_BT856 - tristate "BT856 VideoStream decoder" - depends on VIDEO_V4L2 && I2C - ---help--- - Support for BT856 video decoder. - - To compile this driver as a module, choose M here: the - module will be called bt856. - -config VIDEO_BT866 - tristate "BT866 VideoStream decoder" - depends on VIDEO_V4L2 && I2C - ---help--- - Support for BT866 video decoder. - - To compile this driver as a module, choose M here: the - module will be called bt866. - -config VIDEO_KS0127 - tristate "KS0127 video decoder" - depends on VIDEO_V4L2 && I2C - ---help--- - Support for KS0127 video decoder. - - This chip is used on AverMedia AVS6EYES Zoran-based MJPEG - cards. - - To compile this driver as a module, choose M here: the - module will be called ks0127. - -config VIDEO_SAA7110 - tristate "Philips SAA7110 video decoder" - depends on VIDEO_V4L2 && I2C - ---help--- - Support for the Philips SAA7110 video decoders. - - To compile this driver as a module, choose M here: the - module will be called saa7110. - -config VIDEO_SAA711X - tristate "Philips SAA7111/3/4/5 video decoders" - depends on VIDEO_V4L2 && I2C - ---help--- - Support for the Philips SAA7111/3/4/5 video decoders. - - To compile this driver as a module, choose M here: the - module will be called saa7115. - -config VIDEO_SAA7191 - tristate "Philips SAA7191 video decoder" - depends on VIDEO_V4L2 && I2C - ---help--- - Support for the Philips SAA7191 video decoder. - - To compile this driver as a module, choose M here: the - module will be called saa7191. - -config VIDEO_TVP514X - tristate "Texas Instruments TVP514x video decoder" - depends on VIDEO_V4L2 && I2C - ---help--- - This is a Video4Linux2 sensor-level driver for the TI TVP5146/47 - decoder. It is currently working with the TI OMAP3 camera - controller. - - To compile this driver as a module, choose M here: the - module will be called tvp514x. - -config VIDEO_TVP5150 - tristate "Texas Instruments TVP5150 video decoder" - depends on VIDEO_V4L2 && I2C - ---help--- - Support for the Texas Instruments TVP5150 video decoder. - - To compile this driver as a module, choose M here: the - module will be called tvp5150. - -config VIDEO_TVP7002 - tristate "Texas Instruments TVP7002 video decoder" - depends on VIDEO_V4L2 && I2C - ---help--- - Support for the Texas Instruments TVP7002 video decoder. - - To compile this driver as a module, choose M here: the - module will be called tvp7002. - -config VIDEO_VPX3220 - tristate "vpx3220a, vpx3216b & vpx3214c video decoders" - depends on VIDEO_V4L2 && I2C - ---help--- - Support for VPX322x video decoders. - - To compile this driver as a module, choose M here: the - module will be called vpx3220. - -comment "Video and audio decoders" - -config VIDEO_SAA717X - tristate "Philips SAA7171/3/4 audio/video decoders" - depends on VIDEO_V4L2 && I2C - ---help--- - Support for the Philips SAA7171/3/4 audio/video decoders. - - To compile this driver as a module, choose M here: the - module will be called saa717x. - -source "drivers/media/video/cx25840/Kconfig" - -comment "MPEG video encoders" - -config VIDEO_CX2341X - tristate "Conexant CX2341x MPEG encoders" - depends on VIDEO_V4L2 && VIDEO_V4L2_COMMON - ---help--- - Support for the Conexant CX23416 MPEG encoders - and CX23415 MPEG encoder/decoders. - - This module currently supports the encoding functions only. - - To compile this driver as a module, choose M here: the - module will be called cx2341x. - -comment "Video encoders" - -config VIDEO_SAA7127 - tristate "Philips SAA7127/9 digital video encoders" - depends on VIDEO_V4L2 && I2C - ---help--- - Support for the Philips SAA7127/9 digital video encoders. - - To compile this driver as a module, choose M here: the - module will be called saa7127. - -config VIDEO_SAA7185 - tristate "Philips SAA7185 video encoder" - depends on VIDEO_V4L2 && I2C - ---help--- - Support for the Philips SAA7185 video encoder. - - To compile this driver as a module, choose M here: the - module will be called saa7185. - -config VIDEO_ADV7170 - tristate "Analog Devices ADV7170 video encoder" - depends on VIDEO_V4L2 && I2C - ---help--- - Support for the Analog Devices ADV7170 video encoder driver - - To compile this driver as a module, choose M here: the - module will be called adv7170. - -config VIDEO_ADV7175 - tristate "Analog Devices ADV7175 video encoder" - depends on VIDEO_V4L2 && I2C - ---help--- - Support for the Analog Devices ADV7175 video encoder driver - - To compile this driver as a module, choose M here: the - module will be called adv7175. - -config VIDEO_ADV7343 - tristate "ADV7343 video encoder" - depends on I2C - help - Support for Analog Devices I2C bus based ADV7343 encoder. - - To compile this driver as a module, choose M here: the - module will be called adv7343. - -config VIDEO_ADV7393 - tristate "ADV7393 video encoder" - depends on I2C - help - Support for Analog Devices I2C bus based ADV7393 encoder. - - To compile this driver as a module, choose M here: the - module will be called adv7393. - -config VIDEO_AK881X - tristate "AK8813/AK8814 video encoders" - depends on I2C - help - Video output driver for AKM AK8813 and AK8814 TV encoders - -comment "Camera sensor devices" - -config VIDEO_APTINA_PLL - tristate - -config VIDEO_SMIAPP_PLL - tristate - -config VIDEO_OV7670 - tristate "OmniVision OV7670 sensor support" - depends on I2C && VIDEO_V4L2 - depends on MEDIA_CAMERA_SUPPORT - ---help--- - This is a Video4Linux2 sensor-level driver for the OmniVision - OV7670 VGA camera. It currently only works with the M88ALP01 - controller. - -config VIDEO_VS6624 - tristate "ST VS6624 sensor support" - depends on VIDEO_V4L2 && I2C - depends on MEDIA_CAMERA_SUPPORT - ---help--- - This is a Video4Linux2 sensor-level driver for the ST VS6624 - camera. - - To compile this driver as a module, choose M here: the - module will be called vs6624. - -config VIDEO_MT9M032 - tristate "MT9M032 camera sensor support" - depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API - depends on MEDIA_CAMERA_SUPPORT - select VIDEO_APTINA_PLL - ---help--- - This driver supports MT9M032 camera sensors from Aptina, monochrome - models only. - -config VIDEO_MT9P031 - tristate "Aptina MT9P031 support" - depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API - depends on MEDIA_CAMERA_SUPPORT - select VIDEO_APTINA_PLL - ---help--- - This is a Video4Linux2 sensor-level driver for the Aptina - (Micron) mt9p031 5 Mpixel camera. - -config VIDEO_MT9T001 - tristate "Aptina MT9T001 support" - depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API - depends on MEDIA_CAMERA_SUPPORT - ---help--- - This is a Video4Linux2 sensor-level driver for the Aptina - (Micron) mt0t001 3 Mpixel camera. - -config VIDEO_MT9V011 - tristate "Micron mt9v011 sensor support" - depends on I2C && VIDEO_V4L2 - depends on MEDIA_CAMERA_SUPPORT - ---help--- - This is a Video4Linux2 sensor-level driver for the Micron - mt0v011 1.3 Mpixel camera. It currently only works with the - em28xx driver. - -config VIDEO_MT9V032 - tristate "Micron MT9V032 sensor support" - depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API - depends on MEDIA_CAMERA_SUPPORT - ---help--- - This is a Video4Linux2 sensor-level driver for the Micron - MT9V032 752x480 CMOS sensor. - -config VIDEO_TCM825X - tristate "TCM825x camera sensor support" - depends on I2C && VIDEO_V4L2 - depends on MEDIA_CAMERA_SUPPORT - ---help--- - This is a driver for the Toshiba TCM825x VGA camera sensor. - It is used for example in Nokia N800. - -config VIDEO_SR030PC30 - tristate "Siliconfile SR030PC30 sensor support" - depends on I2C && VIDEO_V4L2 - depends on MEDIA_CAMERA_SUPPORT - ---help--- - This driver supports SR030PC30 VGA camera from Siliconfile - -config VIDEO_NOON010PC30 - tristate "Siliconfile NOON010PC30 sensor support" - depends on I2C && VIDEO_V4L2 && EXPERIMENTAL && VIDEO_V4L2_SUBDEV_API - depends on MEDIA_CAMERA_SUPPORT - ---help--- - This driver supports NOON010PC30 CIF camera from Siliconfile - -source "drivers/media/video/m5mols/Kconfig" - -config VIDEO_S5K6AA - tristate "Samsung S5K6AAFX sensor support" - depends on MEDIA_CAMERA_SUPPORT - depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API - ---help--- - This is a V4L2 sensor-level driver for Samsung S5K6AA(FX) 1.3M - camera sensor with an embedded SoC image signal processor. - -source "drivers/media/video/smiapp/Kconfig" - -comment "Flash devices" - -config VIDEO_ADP1653 - tristate "ADP1653 flash support" - depends on I2C && VIDEO_V4L2 && MEDIA_CONTROLLER - depends on MEDIA_CAMERA_SUPPORT - ---help--- - This is a driver for the ADP1653 flash controller. It is used for - example in Nokia N900. - -config VIDEO_AS3645A - tristate "AS3645A flash driver support" - depends on I2C && VIDEO_V4L2 && MEDIA_CONTROLLER - depends on MEDIA_CAMERA_SUPPORT - ---help--- - This is a driver for the AS3645A and LM3555 flash controllers. It has - build in control for flash, torch and indicator LEDs. - -comment "Video improvement chips" - -config VIDEO_UPD64031A - tristate "NEC Electronics uPD64031A Ghost Reduction" - depends on VIDEO_V4L2 && I2C - ---help--- - Support for the NEC Electronics uPD64031A Ghost Reduction - video chip. It is most often found in NTSC TV cards made for - Japan and is used to reduce the 'ghosting' effect that can - be present in analog TV broadcasts. - - To compile this driver as a module, choose M here: the - module will be called upd64031a. - -config VIDEO_UPD64083 - tristate "NEC Electronics uPD64083 3-Dimensional Y/C separation" - depends on VIDEO_V4L2 && I2C - ---help--- - Support for the NEC Electronics uPD64083 3-Dimensional Y/C - separation video chip. It is used to improve the quality of - the colors of a composite signal. - - To compile this driver as a module, choose M here: the - module will be called upd64083. - -comment "Miscelaneous helper chips" - -config VIDEO_THS7303 - tristate "THS7303 Video Amplifier" - depends on I2C - help - Support for TI THS7303 video amplifier - - To compile this driver as a module, choose M here: the - module will be called ths7303. - -config VIDEO_M52790 - tristate "Mitsubishi M52790 A/V switch" - depends on VIDEO_V4L2 && I2C - ---help--- - Support for the Mitsubishi M52790 A/V switch. - - To compile this driver as a module, choose M here: the - module will be called m52790. - -endmenu # encoder / decoder chips - -config VIDEO_VIVI - tristate "Virtual Video Driver" - depends on VIDEO_DEV && VIDEO_V4L2 && !SPARC32 && !SPARC64 - depends on FRAMEBUFFER_CONSOLE || STI_CONSOLE - select FONT_8x16 - select VIDEOBUF2_VMALLOC - default n - ---help--- - Enables a virtual video driver. This device shows a color bar - and a timestamp, as a real device would generate by using V4L2 - api. - Say Y here if you want to test video apps or debug V4L devices. - In doubt, say N. - -# -# USB Multimedia device configuration -# - -menuconfig V4L_USB_DRIVERS - bool "V4L USB devices" - depends on USB - default y - -if V4L_USB_DRIVERS && MEDIA_CAMERA_SUPPORT - - comment "Webcam devices" - -source "drivers/media/video/uvc/Kconfig" - -source "drivers/media/video/gspca/Kconfig" - -source "drivers/media/video/pwc/Kconfig" - -source "drivers/media/video/cpia2/Kconfig" - -config USB_ZR364XX - tristate "USB ZR364XX Camera support" - depends on VIDEO_V4L2 - select VIDEOBUF_GEN - select VIDEOBUF_VMALLOC - ---help--- - Say Y here if you want to connect this type of camera to your - computer's USB port. - See <file:Documentation/video4linux/zr364xx.txt> for more info - and list of supported cameras. - - To compile this driver as a module, choose M here: the - module will be called zr364xx. - -config USB_STKWEBCAM - tristate "USB Syntek DC1125 Camera support" - depends on VIDEO_V4L2 && EXPERIMENTAL - ---help--- - Say Y here if you want to use this type of camera. - Supported devices are typically found in some Asus laptops, - with USB id 174f:a311 and 05e1:0501. Other Syntek cameras - may be supported by the stk11xx driver, from which this is - derived, see <http://sourceforge.net/projects/syntekdriver/> - - To compile this driver as a module, choose M here: the - module will be called stkwebcam. - -config USB_S2255 - tristate "USB Sensoray 2255 video capture device" - depends on VIDEO_V4L2 - select VIDEOBUF_VMALLOC - default n - help - Say Y here if you want support for the Sensoray 2255 USB device. - This driver can be compiled as a module, called s2255drv. - -source "drivers/media/video/sn9c102/Kconfig" - -endif # V4L_USB_DRIVERS && MEDIA_CAMERA_SUPPORT - -if V4L_USB_DRIVERS - - comment "Webcam and/or TV USB devices" - -source "drivers/media/video/em28xx/Kconfig" - -endif - -if V4L_USB_DRIVERS && MEDIA_ANALOG_TV_SUPPORT - - comment "TV USB devices" - -source "drivers/media/video/au0828/Kconfig" - -source "drivers/media/video/pvrusb2/Kconfig" - -source "drivers/media/video/hdpvr/Kconfig" - -source "drivers/media/video/tlg2300/Kconfig" - -source "drivers/media/video/cx231xx/Kconfig" - -source "drivers/media/video/tm6000/Kconfig" - -source "drivers/media/video/usbvision/Kconfig" - -endif # V4L_USB_DRIVERS - -# -# PCI drivers configuration - No devices here are for webcams -# - -menuconfig V4L_PCI_DRIVERS - bool "V4L PCI(e) devices" - depends on PCI - depends on MEDIA_ANALOG_TV_SUPPORT - default y - ---help--- - Say Y here to enable support for these PCI(e) drivers. - -if V4L_PCI_DRIVERS - -source "drivers/media/video/bt8xx/Kconfig" - -source "drivers/media/video/cx18/Kconfig" - -source "drivers/media/video/cx23885/Kconfig" - -source "drivers/media/video/cx25821/Kconfig" - -source "drivers/media/video/cx88/Kconfig" - -config VIDEO_HEXIUM_GEMINI - tristate "Hexium Gemini frame grabber" - depends on PCI && VIDEO_V4L2 && I2C - select VIDEO_SAA7146_VV - ---help--- - This is a video4linux driver for the Hexium Gemini frame - grabber card by Hexium. Please note that the Gemini Dual - card is *not* fully supported. - - To compile this driver as a module, choose M here: the - module will be called hexium_gemini. - -config VIDEO_HEXIUM_ORION - tristate "Hexium HV-PCI6 and Orion frame grabber" - depends on PCI && VIDEO_V4L2 && I2C - select VIDEO_SAA7146_VV - ---help--- - This is a video4linux driver for the Hexium HV-PCI6 and - Orion frame grabber cards by Hexium. - - To compile this driver as a module, choose M here: the - module will be called hexium_orion. - -source "drivers/media/video/ivtv/Kconfig" - -config VIDEO_MEYE - tristate "Sony Vaio Picturebook Motion Eye Video For Linux" - depends on PCI && SONY_LAPTOP && VIDEO_V4L2 - ---help--- - This is the video4linux driver for the Motion Eye camera found - in the Vaio Picturebook laptops. Please read the material in - <file:Documentation/video4linux/meye.txt> for more information. - - If you say Y or M here, you need to say Y or M to "Sony Laptop - Extras" in the misc device section. - - To compile this driver as a module, choose M here: the - module will be called meye. - -config VIDEO_MXB - tristate "Siemens-Nixdorf 'Multimedia eXtension Board'" - depends on PCI && VIDEO_V4L2 && I2C - select VIDEO_SAA7146_VV - select VIDEO_TUNER - select VIDEO_SAA711X if VIDEO_HELPER_CHIPS_AUTO - select VIDEO_TDA9840 if VIDEO_HELPER_CHIPS_AUTO - select VIDEO_TEA6415C if VIDEO_HELPER_CHIPS_AUTO - select VIDEO_TEA6420 if VIDEO_HELPER_CHIPS_AUTO - ---help--- - This is a video4linux driver for the 'Multimedia eXtension Board' - TV card by Siemens-Nixdorf. - - To compile this driver as a module, choose M here: the - module will be called mxb. - -source "drivers/media/video/saa7134/Kconfig" - -source "drivers/media/video/saa7164/Kconfig" - -source "drivers/media/video/zoran/Kconfig" - -config STA2X11_VIP - tristate "STA2X11 VIP Video For Linux" - depends on STA2X11 - select VIDEO_ADV7180 if VIDEO_HELPER_CHIPS_AUTO - select VIDEOBUF_DMA_CONTIG - depends on PCI && VIDEO_V4L2 && VIRT_TO_BUS - help - Say Y for support for STA2X11 VIP (Video Input Port) capture - device. - - To compile this driver as a module, choose M here: the - module will be called sta2x11_vip. - -endif # V4L_PCI_DRIVERS - -# -# ISA & parallel port drivers configuration -# All devices here are webcam or grabber devices -# - -menuconfig V4L_ISA_PARPORT_DRIVERS - bool "V4L ISA and parallel port devices" - depends on ISA || PARPORT - depends on MEDIA_CAMERA_SUPPORT - default n - ---help--- - Say Y here to enable support for these ISA and parallel port drivers. - -if V4L_ISA_PARPORT_DRIVERS - -config VIDEO_BWQCAM - tristate "Quickcam BW Video For Linux" - depends on PARPORT && VIDEO_V4L2 - help - Say Y have if you the black and white version of the QuickCam - camera. See the next option for the color version. - - To compile this driver as a module, choose M here: the - module will be called bw-qcam. - -config VIDEO_CQCAM - tristate "QuickCam Colour Video For Linux" - depends on PARPORT && VIDEO_V4L2 - help - This is the video4linux driver for the colour version of the - Connectix QuickCam. If you have one of these cameras, say Y here, - otherwise say N. This driver does not work with the original - monochrome QuickCam, QuickCam VC or QuickClip. It is also available - as a module (c-qcam). - Read <file:Documentation/video4linux/CQcam.txt> for more information. - -config VIDEO_PMS - tristate "Mediavision Pro Movie Studio Video For Linux" - depends on ISA && VIDEO_V4L2 - help - Say Y if you have the ISA Mediavision Pro Movie Studio - capture card. - - To compile this driver as a module, choose M here: the - module will be called pms. - -config VIDEO_W9966 - tristate "W9966CF Webcam (FlyCam Supra and others) Video For Linux" - depends on PARPORT_1284 && PARPORT && VIDEO_V4L2 - help - Video4linux driver for Winbond's w9966 based Webcams. - Currently tested with the LifeView FlyCam Supra. - If you have one of these cameras, say Y here - otherwise say N. - This driver is also available as a module (w9966). - - Check out <file:Documentation/video4linux/w9966.txt> for more - information. - -endif # V4L_ISA_PARPORT_DRIVERS - -# -# Platform drivers -# All drivers here are currently for webcam support - -menuconfig V4L_PLATFORM_DRIVERS - bool "V4L platform devices" - depends on MEDIA_CAMERA_SUPPORT - default n - ---help--- - Say Y here to enable support for platform-specific V4L drivers. - -if V4L_PLATFORM_DRIVERS - -source "drivers/media/video/marvell-ccic/Kconfig" - -config VIDEO_VIA_CAMERA - tristate "VIAFB camera controller support" - depends on FB_VIA - select VIDEOBUF_DMA_SG - select VIDEO_OV7670 - help - Driver support for the integrated camera controller in VIA - Chrome9 chipsets. Currently only tested on OLPC xo-1.5 systems - with ov7670 sensors. - -# -# Platform multimedia device configuration -# - -source "drivers/media/video/davinci/Kconfig" - -source "drivers/media/video/omap/Kconfig" - -source "drivers/media/video/blackfin/Kconfig" - -config VIDEO_SH_VOU - tristate "SuperH VOU video output driver" - depends on VIDEO_DEV && ARCH_SHMOBILE - select VIDEOBUF_DMA_CONTIG - help - Support for the Video Output Unit (VOU) on SuperH SoCs. - -config VIDEO_VIU - tristate "Freescale VIU Video Driver" - depends on VIDEO_V4L2 && PPC_MPC512x - select VIDEOBUF_DMA_CONTIG - default y - ---help--- - Support for Freescale VIU video driver. This device captures - video data, or overlays video on DIU frame buffer. - - Say Y here if you want to enable VIU device on MPC5121e Rev2+. - In doubt, say N. - -config VIDEO_TIMBERDALE - tristate "Support for timberdale Video In/LogiWIN" - depends on VIDEO_V4L2 && I2C && DMADEVICES - select DMA_ENGINE - select TIMB_DMA - select VIDEO_ADV7180 - select VIDEOBUF_DMA_CONTIG - ---help--- - Add support for the Video In peripherial of the timberdale FPGA. - -config VIDEO_VINO - tristate "SGI Vino Video For Linux" - depends on I2C && SGI_IP22 && VIDEO_V4L2 - select VIDEO_SAA7191 if VIDEO_HELPER_CHIPS_AUTO - help - Say Y here to build in support for the Vino video input system found - on SGI Indy machines. - -config VIDEO_M32R_AR - tristate "AR devices" - depends on M32R && VIDEO_V4L2 - ---help--- - This is a video4linux driver for the Renesas AR (Artificial Retina) - camera module. - -config VIDEO_M32R_AR_M64278 - tristate "AR device with color module M64278(VGA)" - depends on PLAT_M32700UT - select VIDEO_M32R_AR - ---help--- - This is a video4linux driver for the Renesas AR (Artificial - Retina) with M64278E-800 camera module. - This module supports VGA(640x480 pixels) resolutions. - - To compile this driver as a module, choose M here: the - module will be called arv. - -config VIDEO_OMAP3 - tristate "OMAP 3 Camera support (EXPERIMENTAL)" - depends on OMAP_IOVMM && VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API && ARCH_OMAP3 && EXPERIMENTAL - ---help--- - Driver for an OMAP 3 camera controller. - -config VIDEO_OMAP3_DEBUG - bool "OMAP 3 Camera debug messages" - depends on VIDEO_OMAP3 - ---help--- - Enable debug messages on OMAP 3 camera controller driver. - -config SOC_CAMERA - tristate "SoC camera support" - depends on VIDEO_V4L2 && HAS_DMA && I2C - select VIDEOBUF_GEN - select VIDEOBUF2_CORE - 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_IMX074 - tristate "imx074 support" - depends on SOC_CAMERA && I2C - help - This driver supports IMX074 cameras from Sony - -config SOC_CAMERA_MT9M001 - tristate "mt9m001 support" - depends on SOC_CAMERA && I2C - select GPIO_PCA953X if MT9M001_PCA9536_SWITCH - help - This driver supports MT9M001 cameras from Micron, monochrome - and colour models. - -config SOC_CAMERA_MT9M111 - tristate "mt9m111, mt9m112 and mt9m131 support" - depends on SOC_CAMERA && I2C - help - This driver supports MT9M111, MT9M112 and MT9M131 cameras from - Micron/Aptina - -config SOC_CAMERA_MT9T031 - tristate "mt9t031 support" - depends on SOC_CAMERA && I2C - help - This driver supports MT9T031 cameras from Micron. - -config SOC_CAMERA_MT9T112 - tristate "mt9t112 support" - depends on SOC_CAMERA && I2C - help - This driver supports MT9T112 cameras from Aptina. - -config SOC_CAMERA_MT9V022 - tristate "mt9v022 support" - depends on SOC_CAMERA && I2C - select GPIO_PCA953X if MT9V022_PCA9536_SWITCH - help - This driver supports MT9V022 cameras from Micron - -config SOC_CAMERA_RJ54N1 - tristate "rj54n1cb0c support" - depends on SOC_CAMERA && I2C - help - This is a rj54n1cb0c video driver - -config SOC_CAMERA_TW9910 - tristate "tw9910 support" - depends on SOC_CAMERA && I2C - help - This is a tw9910 video driver - -config SOC_CAMERA_PLATFORM - tristate "platform camera support" - depends on SOC_CAMERA - help - This is a generic SoC camera platform driver, useful for testing - -config SOC_CAMERA_OV2640 - tristate "ov2640 camera support" - depends on SOC_CAMERA && I2C - help - This is a ov2640 camera driver - -config SOC_CAMERA_OV5642 - tristate "ov5642 camera support" - depends on SOC_CAMERA && I2C - help - This is a V4L2 camera driver for the OmniVision OV5642 sensor - -config SOC_CAMERA_OV6650 - tristate "ov6650 sensor support" - depends on SOC_CAMERA && I2C - ---help--- - This is a V4L2 SoC camera driver for the OmniVision OV6650 sensor - -config SOC_CAMERA_OV772X - tristate "ov772x camera support" - depends on SOC_CAMERA && I2C - help - This is a ov772x camera driver - -config SOC_CAMERA_OV9640 - tristate "ov9640 camera support" - depends on SOC_CAMERA && I2C - help - This is a ov9640 camera driver - -config SOC_CAMERA_OV9740 - tristate "ov9740 camera support" - depends on SOC_CAMERA && I2C - help - This is a ov9740 camera driver - -config MX1_VIDEO - bool - -config VIDEO_MX1 - tristate "i.MX1/i.MXL CMOS Sensor Interface driver" - depends on VIDEO_DEV && ARCH_MX1 && SOC_CAMERA - select FIQ - select VIDEOBUF_DMA_CONTIG - select MX1_VIDEO - ---help--- - This is a v4l2 driver for the i.MX1/i.MXL CMOS Sensor Interface - -config MX3_VIDEO - bool - -config VIDEO_MX3 - tristate "i.MX3x Camera Sensor Interface driver" - depends on VIDEO_DEV && MX3_IPU && SOC_CAMERA - select VIDEOBUF2_DMA_CONTIG - select MX3_VIDEO - ---help--- - This is a v4l2 driver for the i.MX3x Camera Sensor Interface - -config VIDEO_PXA27x - tristate "PXA27x Quick Capture Interface driver" - depends on VIDEO_DEV && PXA27x && SOC_CAMERA - select VIDEOBUF_DMA_SG - ---help--- - This is a v4l2 driver for the PXA27x Quick Capture Interface - -config VIDEO_SH_MOBILE_CSI2 - tristate "SuperH Mobile MIPI CSI-2 Interface driver" - depends on VIDEO_DEV && SOC_CAMERA && HAVE_CLK - ---help--- - This is a v4l2 driver for the SuperH MIPI CSI-2 Interface - -config VIDEO_SH_MOBILE_CEU - tristate "SuperH Mobile CEU Interface driver" - depends on VIDEO_DEV && SOC_CAMERA && HAS_DMA && HAVE_CLK - select VIDEOBUF2_DMA_CONTIG - ---help--- - This is a v4l2 driver for the SuperH Mobile CEU Interface - -config VIDEO_OMAP1 - tristate "OMAP1 Camera Interface driver" - depends on VIDEO_DEV && ARCH_OMAP1 && SOC_CAMERA - select VIDEOBUF_DMA_CONTIG - select VIDEOBUF_DMA_SG - ---help--- - This is a v4l2 driver for the TI OMAP1 camera interface - -config VIDEO_OMAP2 - tristate "OMAP2 Camera Capture Interface driver" - depends on VIDEO_DEV && ARCH_OMAP2 - select VIDEOBUF_DMA_SG - ---help--- - This is a v4l2 driver for the TI OMAP2 camera capture interface - -config VIDEO_MX2_HOSTSUPPORT - bool - -config VIDEO_MX2 - tristate "i.MX27/i.MX25 Camera Sensor Interface driver" - depends on VIDEO_DEV && SOC_CAMERA && (MACH_MX27 || ARCH_MX25) - select VIDEOBUF2_DMA_CONTIG - select VIDEO_MX2_HOSTSUPPORT - ---help--- - This is a v4l2 driver for the i.MX27 and the i.MX25 Camera Sensor - Interface - -config VIDEO_ATMEL_ISI - tristate "ATMEL Image Sensor Interface (ISI) support" - depends on VIDEO_DEV && SOC_CAMERA && ARCH_AT91 - select VIDEOBUF2_DMA_CONTIG - ---help--- - This module makes the ATMEL Image Sensor Interface available - as a v4l2 device. - -source "drivers/media/video/s5p-fimc/Kconfig" -source "drivers/media/video/s5p-tv/Kconfig" - -endif # V4L_PLATFORM_DRIVERS -endif # VIDEO_CAPTURE_DRIVERS - -menuconfig V4L_MEM2MEM_DRIVERS - bool "Memory-to-memory multimedia devices" - depends on VIDEO_V4L2 - default n - ---help--- - Say Y here to enable selecting drivers for V4L devices that - use system memory for both source and destination buffers, as opposed - to capture and output drivers, which use memory buffers for just - one of those. - -if V4L_MEM2MEM_DRIVERS - -config VIDEO_MEM2MEM_TESTDEV - tristate "Virtual test device for mem2mem framework" - depends on VIDEO_DEV && VIDEO_V4L2 - select VIDEOBUF2_VMALLOC - select V4L2_MEM2MEM_DEV - default n - ---help--- - This is a virtual test device for the memory-to-memory driver - framework. - -config VIDEO_SAMSUNG_S5P_G2D - tristate "Samsung S5P and EXYNOS4 G2D 2d graphics accelerator driver" - depends on VIDEO_DEV && VIDEO_V4L2 && PLAT_S5P - select VIDEOBUF2_DMA_CONTIG - select V4L2_MEM2MEM_DEV - default n - ---help--- - This is a v4l2 driver for Samsung S5P and EXYNOS4 G2D - 2d graphics accelerator. - -config VIDEO_SAMSUNG_S5P_JPEG - tristate "Samsung S5P/Exynos4 JPEG codec driver (EXPERIMENTAL)" - depends on VIDEO_DEV && VIDEO_V4L2 && PLAT_S5P && EXPERIMENTAL - select VIDEOBUF2_DMA_CONTIG - select V4L2_MEM2MEM_DEV - ---help--- - This is a v4l2 driver for Samsung S5P and EXYNOS4 JPEG codec - -config VIDEO_SAMSUNG_S5P_MFC - tristate "Samsung S5P MFC 5.1 Video Codec" - depends on VIDEO_DEV && VIDEO_V4L2 && PLAT_S5P - select VIDEOBUF2_DMA_CONTIG - default n - help - MFC 5.1 driver for V4L2. - -config VIDEO_MX2_EMMAPRP - tristate "MX2 eMMa-PrP support" - depends on VIDEO_DEV && VIDEO_V4L2 && SOC_IMX27 - select VIDEOBUF2_DMA_CONTIG - select V4L2_MEM2MEM_DEV - help - MX2X chips have a PrP that can be used to process buffers from - memory to memory. Operations include resizing and format - conversion. - -endif # V4L_MEM2MEM_DRIVERS diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile deleted file mode 100644 index b7da9faa3b0a..000000000000 --- a/drivers/media/video/Makefile +++ /dev/null @@ -1,218 +0,0 @@ -# -# Makefile for the video capture/playback device drivers. -# - -tuner-objs := tuner-core.o - -msp3400-objs := msp3400-driver.o msp3400-kthreads.o - -stkwebcam-objs := stk-webcam.o stk-sensor.o - -omap2cam-objs := omap24xxcam.o omap24xxcam-dma.o - -videodev-objs := v4l2-dev.o v4l2-ioctl.o v4l2-device.o v4l2-fh.o \ - v4l2-event.o v4l2-ctrls.o v4l2-subdev.o -ifeq ($(CONFIG_COMPAT),y) - videodev-objs += v4l2-compat-ioctl32.o -endif - -# V4L2 core modules - -obj-$(CONFIG_VIDEO_DEV) += videodev.o v4l2-int-device.o -obj-$(CONFIG_VIDEO_V4L2_COMMON) += v4l2-common.o - -# Helper modules - -obj-$(CONFIG_VIDEO_APTINA_PLL) += aptina-pll.o - -# All i2c modules must come first: - -obj-$(CONFIG_VIDEO_TUNER) += tuner.o -obj-$(CONFIG_VIDEO_TVAUDIO) += tvaudio.o -obj-$(CONFIG_VIDEO_TDA7432) += tda7432.o -obj-$(CONFIG_VIDEO_SAA6588) += saa6588.o -obj-$(CONFIG_VIDEO_TDA9840) += tda9840.o -obj-$(CONFIG_VIDEO_TEA6415C) += tea6415c.o -obj-$(CONFIG_VIDEO_TEA6420) += tea6420.o -obj-$(CONFIG_VIDEO_SAA7110) += saa7110.o -obj-$(CONFIG_VIDEO_SAA711X) += saa7115.o -obj-$(CONFIG_VIDEO_SAA717X) += saa717x.o -obj-$(CONFIG_VIDEO_SAA7127) += saa7127.o -obj-$(CONFIG_VIDEO_SAA7185) += saa7185.o -obj-$(CONFIG_VIDEO_SAA7191) += saa7191.o -obj-$(CONFIG_VIDEO_ADV7170) += adv7170.o -obj-$(CONFIG_VIDEO_ADV7175) += adv7175.o -obj-$(CONFIG_VIDEO_ADV7180) += adv7180.o -obj-$(CONFIG_VIDEO_ADV7183) += adv7183.o -obj-$(CONFIG_VIDEO_ADV7343) += adv7343.o -obj-$(CONFIG_VIDEO_ADV7393) += adv7393.o -obj-$(CONFIG_VIDEO_VPX3220) += vpx3220.o -obj-$(CONFIG_VIDEO_VS6624) += vs6624.o -obj-$(CONFIG_VIDEO_BT819) += bt819.o -obj-$(CONFIG_VIDEO_BT856) += bt856.o -obj-$(CONFIG_VIDEO_BT866) += bt866.o -obj-$(CONFIG_VIDEO_KS0127) += ks0127.o -obj-$(CONFIG_VIDEO_THS7303) += ths7303.o -obj-$(CONFIG_VIDEO_VINO) += indycam.o -obj-$(CONFIG_VIDEO_TVP5150) += tvp5150.o -obj-$(CONFIG_VIDEO_TVP514X) += tvp514x.o -obj-$(CONFIG_VIDEO_TVP7002) += tvp7002.o -obj-$(CONFIG_VIDEO_MSP3400) += msp3400.o -obj-$(CONFIG_VIDEO_CS5345) += cs5345.o -obj-$(CONFIG_VIDEO_CS53L32A) += cs53l32a.o -obj-$(CONFIG_VIDEO_M52790) += m52790.o -obj-$(CONFIG_VIDEO_TLV320AIC23B) += tlv320aic23b.o -obj-$(CONFIG_VIDEO_WM8775) += wm8775.o -obj-$(CONFIG_VIDEO_WM8739) += wm8739.o -obj-$(CONFIG_VIDEO_VP27SMPX) += vp27smpx.o -obj-$(CONFIG_VIDEO_CX25840) += cx25840/ -obj-$(CONFIG_VIDEO_UPD64031A) += upd64031a.o -obj-$(CONFIG_VIDEO_UPD64083) += upd64083.o -obj-$(CONFIG_VIDEO_OV7670) += ov7670.o -obj-$(CONFIG_VIDEO_TCM825X) += tcm825x.o -obj-$(CONFIG_VIDEO_TVEEPROM) += tveeprom.o -obj-$(CONFIG_VIDEO_MT9M032) += mt9m032.o -obj-$(CONFIG_VIDEO_MT9P031) += mt9p031.o -obj-$(CONFIG_VIDEO_MT9T001) += mt9t001.o -obj-$(CONFIG_VIDEO_MT9V011) += mt9v011.o -obj-$(CONFIG_VIDEO_MT9V032) += mt9v032.o -obj-$(CONFIG_VIDEO_SR030PC30) += sr030pc30.o -obj-$(CONFIG_VIDEO_NOON010PC30) += noon010pc30.o -obj-$(CONFIG_VIDEO_M5MOLS) += m5mols/ -obj-$(CONFIG_VIDEO_S5K6AA) += s5k6aa.o -obj-$(CONFIG_VIDEO_SMIAPP) += smiapp/ -obj-$(CONFIG_VIDEO_ADP1653) += adp1653.o -obj-$(CONFIG_VIDEO_AS3645A) += as3645a.o - -obj-$(CONFIG_VIDEO_SMIAPP_PLL) += smiapp-pll.o - -obj-$(CONFIG_SOC_CAMERA_IMX074) += imx074.o -obj-$(CONFIG_SOC_CAMERA_MT9M001) += mt9m001.o -obj-$(CONFIG_SOC_CAMERA_MT9M111) += mt9m111.o -obj-$(CONFIG_SOC_CAMERA_MT9T031) += mt9t031.o -obj-$(CONFIG_SOC_CAMERA_MT9T112) += mt9t112.o -obj-$(CONFIG_SOC_CAMERA_MT9V022) += mt9v022.o -obj-$(CONFIG_SOC_CAMERA_OV2640) += ov2640.o -obj-$(CONFIG_SOC_CAMERA_OV5642) += ov5642.o -obj-$(CONFIG_SOC_CAMERA_OV6650) += ov6650.o -obj-$(CONFIG_SOC_CAMERA_OV772X) += ov772x.o -obj-$(CONFIG_SOC_CAMERA_OV9640) += ov9640.o -obj-$(CONFIG_SOC_CAMERA_OV9740) += ov9740.o -obj-$(CONFIG_SOC_CAMERA_RJ54N1) += rj54n1cb0c.o -obj-$(CONFIG_SOC_CAMERA_TW9910) += tw9910.o - -# And now the v4l2 drivers: - -obj-$(CONFIG_VIDEO_BT848) += bt8xx/ -obj-$(CONFIG_VIDEO_ZORAN) += zoran/ -obj-$(CONFIG_VIDEO_CQCAM) += c-qcam.o -obj-$(CONFIG_VIDEO_BWQCAM) += bw-qcam.o -obj-$(CONFIG_VIDEO_W9966) += w9966.o -obj-$(CONFIG_VIDEO_PMS) += pms.o -obj-$(CONFIG_VIDEO_VINO) += vino.o -obj-$(CONFIG_VIDEO_MEYE) += meye.o -obj-$(CONFIG_VIDEO_SAA7134) += saa7134/ -obj-$(CONFIG_VIDEO_CX88) += cx88/ -obj-$(CONFIG_VIDEO_EM28XX) += em28xx/ -obj-$(CONFIG_VIDEO_TLG2300) += tlg2300/ -obj-$(CONFIG_VIDEO_CX231XX) += cx231xx/ -obj-$(CONFIG_VIDEO_CX25821) += cx25821/ -obj-$(CONFIG_VIDEO_USBVISION) += usbvision/ -obj-$(CONFIG_VIDEO_PVRUSB2) += pvrusb2/ -obj-$(CONFIG_VIDEO_CPIA2) += cpia2/ -obj-$(CONFIG_VIDEO_TM6000) += tm6000/ -obj-$(CONFIG_VIDEO_MXB) += mxb.o -obj-$(CONFIG_VIDEO_HEXIUM_ORION) += hexium_orion.o -obj-$(CONFIG_VIDEO_HEXIUM_GEMINI) += hexium_gemini.o -obj-$(CONFIG_STA2X11_VIP) += sta2x11_vip.o -obj-$(CONFIG_VIDEO_TIMBERDALE) += timblogiw.o - -obj-$(CONFIG_VIDEOBUF_GEN) += videobuf-core.o -obj-$(CONFIG_VIDEOBUF_DMA_SG) += videobuf-dma-sg.o -obj-$(CONFIG_VIDEOBUF_DMA_CONTIG) += videobuf-dma-contig.o -obj-$(CONFIG_VIDEOBUF_VMALLOC) += videobuf-vmalloc.o -obj-$(CONFIG_VIDEOBUF_DVB) += videobuf-dvb.o -obj-$(CONFIG_VIDEO_BTCX) += btcx-risc.o - -obj-$(CONFIG_VIDEOBUF2_CORE) += videobuf2-core.o -obj-$(CONFIG_VIDEOBUF2_MEMOPS) += videobuf2-memops.o -obj-$(CONFIG_VIDEOBUF2_VMALLOC) += videobuf2-vmalloc.o -obj-$(CONFIG_VIDEOBUF2_DMA_CONTIG) += videobuf2-dma-contig.o -obj-$(CONFIG_VIDEOBUF2_DMA_SG) += videobuf2-dma-sg.o - -obj-$(CONFIG_V4L2_MEM2MEM_DEV) += v4l2-mem2mem.o - -obj-$(CONFIG_VIDEO_M32R_AR_M64278) += arv.o - -obj-$(CONFIG_VIDEO_CX2341X) += cx2341x.o - -obj-$(CONFIG_VIDEO_CAFE_CCIC) += marvell-ccic/ -obj-$(CONFIG_VIDEO_MMP_CAMERA) += marvell-ccic/ - -obj-$(CONFIG_VIDEO_VIA_CAMERA) += via-camera.o - -obj-$(CONFIG_VIDEO_OMAP3) += omap3isp/ - -obj-$(CONFIG_USB_ZR364XX) += zr364xx.o -obj-$(CONFIG_USB_STKWEBCAM) += stkwebcam.o - -obj-$(CONFIG_USB_SN9C102) += sn9c102/ -obj-$(CONFIG_USB_PWC) += pwc/ -obj-$(CONFIG_USB_GSPCA) += gspca/ - -obj-$(CONFIG_VIDEO_HDPVR) += hdpvr/ - -obj-$(CONFIG_USB_S2255) += s2255drv.o - -obj-$(CONFIG_VIDEO_IVTV) += ivtv/ -obj-$(CONFIG_VIDEO_CX18) += cx18/ - -obj-$(CONFIG_VIDEO_VIU) += fsl-viu.o -obj-$(CONFIG_VIDEO_VIVI) += vivi.o -obj-$(CONFIG_VIDEO_MEM2MEM_TESTDEV) += mem2mem_testdev.o -obj-$(CONFIG_VIDEO_CX23885) += cx23885/ - -obj-$(CONFIG_VIDEO_AK881X) += ak881x.o - -obj-$(CONFIG_VIDEO_OMAP2) += omap2cam.o -obj-$(CONFIG_SOC_CAMERA) += soc_camera.o soc_mediabus.o -obj-$(CONFIG_SOC_CAMERA_PLATFORM) += soc_camera_platform.o -# soc-camera host drivers have to be linked after camera drivers -obj-$(CONFIG_VIDEO_MX1) += mx1_camera.o -obj-$(CONFIG_VIDEO_MX2) += mx2_camera.o -obj-$(CONFIG_VIDEO_MX3) += mx3_camera.o -obj-$(CONFIG_VIDEO_PXA27x) += pxa_camera.o -obj-$(CONFIG_VIDEO_SH_MOBILE_CSI2) += sh_mobile_csi2.o -obj-$(CONFIG_VIDEO_SH_MOBILE_CEU) += sh_mobile_ceu_camera.o -obj-$(CONFIG_VIDEO_OMAP1) += omap1_camera.o -obj-$(CONFIG_VIDEO_ATMEL_ISI) += atmel-isi.o - -obj-$(CONFIG_VIDEO_MX2_EMMAPRP) += mx2_emmaprp.o - -obj-$(CONFIG_VIDEO_SAMSUNG_S5P_FIMC) += s5p-fimc/ -obj-$(CONFIG_VIDEO_SAMSUNG_S5P_JPEG) += s5p-jpeg/ -obj-$(CONFIG_VIDEO_SAMSUNG_S5P_MFC) += s5p-mfc/ -obj-$(CONFIG_VIDEO_SAMSUNG_S5P_TV) += s5p-tv/ - -obj-$(CONFIG_VIDEO_SAMSUNG_S5P_G2D) += s5p-g2d/ - -obj-$(CONFIG_BLACKFIN) += blackfin/ - -obj-$(CONFIG_ARCH_DAVINCI) += davinci/ - -obj-$(CONFIG_VIDEO_SH_VOU) += sh_vou.o - -obj-$(CONFIG_VIDEO_AU0828) += au0828/ - -obj-$(CONFIG_USB_VIDEO_CLASS) += uvc/ -obj-$(CONFIG_VIDEO_SAA7164) += saa7164/ - -obj-$(CONFIG_VIDEO_IR_I2C) += ir-kbd-i2c.o - -obj-y += davinci/ - -obj-$(CONFIG_ARCH_OMAP) += omap/ - -ccflags-y += -I$(srctree)/drivers/media/dvb/dvb-core -ccflags-y += -I$(srctree)/drivers/media/dvb/frontends -ccflags-y += -I$(srctree)/drivers/media/common/tuners diff --git a/drivers/media/video/bt8xx/Kconfig b/drivers/media/video/bt8xx/Kconfig deleted file mode 100644 index 7da5c2e1fc12..000000000000 --- a/drivers/media/video/bt8xx/Kconfig +++ /dev/null @@ -1,27 +0,0 @@ -config VIDEO_BT848 - tristate "BT848 Video For Linux" - depends on VIDEO_DEV && PCI && I2C && VIDEO_V4L2 - select I2C_ALGOBIT - select VIDEO_BTCX - select VIDEOBUF_DMA_SG - depends on RC_CORE - select VIDEO_TUNER - select VIDEO_TVEEPROM - select VIDEO_MSP3400 if VIDEO_HELPER_CHIPS_AUTO - select VIDEO_TVAUDIO if VIDEO_HELPER_CHIPS_AUTO - select VIDEO_TDA7432 if VIDEO_HELPER_CHIPS_AUTO - select VIDEO_SAA6588 if VIDEO_HELPER_CHIPS_AUTO - ---help--- - Support for BT848 based frame grabber/overlay boards. This includes - the Miro, Hauppauge and STB boards. Please read the material in - <file:Documentation/video4linux/bttv/> for more information. - - To compile this driver as a module, choose M here: the - module will be called bttv. - -config VIDEO_BT848_DVB - bool "DVB/ATSC Support for bt878 based TV cards" - depends on VIDEO_BT848 && DVB_CORE - select DVB_BT8XX - ---help--- - This adds support for DVB/ATSC cards based on the BT878 chip. diff --git a/drivers/media/video/bt8xx/Makefile b/drivers/media/video/bt8xx/Makefile deleted file mode 100644 index 3f9a2b22d3d4..000000000000 --- a/drivers/media/video/bt8xx/Makefile +++ /dev/null @@ -1,13 +0,0 @@ -# -# Makefile for the video capture/playback device drivers. -# - -bttv-objs := bttv-driver.o bttv-cards.o bttv-if.o \ - bttv-risc.o bttv-vbi.o bttv-i2c.o bttv-gpio.o \ - bttv-input.o bttv-audio-hook.o - -obj-$(CONFIG_VIDEO_BT848) += bttv.o - -ccflags-y += -Idrivers/media/video -ccflags-y += -Idrivers/media/common/tuners -ccflags-y += -Idrivers/media/dvb/dvb-core diff --git a/drivers/media/video/cx23885/Kconfig b/drivers/media/video/cx23885/Kconfig deleted file mode 100644 index b391e9bda877..000000000000 --- a/drivers/media/video/cx23885/Kconfig +++ /dev/null @@ -1,46 +0,0 @@ -config VIDEO_CX23885 - tristate "Conexant cx23885 (2388x successor) support" - depends on DVB_CORE && VIDEO_DEV && PCI && I2C && INPUT && SND - select SND_PCM - select I2C_ALGOBIT - select VIDEO_BTCX - select VIDEO_TUNER - select VIDEO_TVEEPROM - depends on RC_CORE - select VIDEOBUF_DVB - select VIDEOBUF_DMA_SG - select VIDEO_CX25840 - select VIDEO_CX2341X - select DVB_DIB7000P if !DVB_FE_CUSTOMISE - select DVB_S5H1409 if !DVB_FE_CUSTOMISE - select DVB_S5H1411 if !DVB_FE_CUSTOMISE - select DVB_LGDT330X if !DVB_FE_CUSTOMISE - select DVB_ZL10353 if !DVB_FE_CUSTOMISE - select DVB_TDA10048 if !DVB_FE_CUSTOMISE - select DVB_LNBP21 if !DVB_FE_CUSTOMISE - select DVB_STV6110 if !DVB_FE_CUSTOMISE - select DVB_CX24116 if !DVB_FE_CUSTOMISE - select DVB_STV0900 if !DVB_FE_CUSTOMISE - select DVB_DS3000 if !DVB_FE_CUSTOMISE - select DVB_STV0367 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_MT2131 if !MEDIA_TUNER_CUSTOMISE - select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMISE - select MEDIA_TUNER_TDA8290 if !MEDIA_TUNER_CUSTOMISE - select MEDIA_TUNER_TDA18271 if !MEDIA_TUNER_CUSTOMISE - select MEDIA_TUNER_XC5000 if !MEDIA_TUNER_CUSTOMISE - ---help--- - This is a video4linux driver for Conexant 23885 based - TV cards. - - To compile this driver as a module, choose M here: the - module will be called cx23885 - -config MEDIA_ALTERA_CI - tristate "Altera FPGA based CI module" - depends on VIDEO_CX23885 && DVB_CORE - select ALTERA_STAPL - ---help--- - An Altera FPGA CI module for NetUP Dual DVB-T/C RF CI card. - - To compile this driver as a module, choose M here: the - module will be called altera-ci diff --git a/drivers/media/video/tlg2300/Makefile b/drivers/media/video/tlg2300/Makefile deleted file mode 100644 index ea09b9af2d30..000000000000 --- a/drivers/media/video/tlg2300/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -poseidon-objs := pd-video.o pd-alsa.o pd-dvb.o pd-radio.o pd-main.o - -obj-$(CONFIG_VIDEO_TLG2300) += poseidon.o - -ccflags-y += -Idrivers/media/video -ccflags-y += -Idrivers/media/common/tuners -ccflags-y += -Idrivers/media/dvb/dvb-core -ccflags-y += -Idrivers/media/dvb/frontends - diff --git a/drivers/staging/media/Kconfig b/drivers/staging/media/Kconfig index 4f4b7d6281a7..427218b8b10f 100644 --- a/drivers/staging/media/Kconfig +++ b/drivers/staging/media/Kconfig @@ -25,8 +25,6 @@ source "drivers/staging/media/cxd2099/Kconfig" source "drivers/staging/media/dt3155v4l/Kconfig" -source "drivers/staging/media/easycap/Kconfig" - source "drivers/staging/media/go7007/Kconfig" source "drivers/staging/media/solo6x10/Kconfig" diff --git a/drivers/staging/media/Makefile b/drivers/staging/media/Makefile index c69124cdb0d3..aec6eb963940 100644 --- a/drivers/staging/media/Makefile +++ b/drivers/staging/media/Makefile @@ -1,6 +1,5 @@ obj-$(CONFIG_DVB_AS102) += as102/ obj-$(CONFIG_DVB_CXD2099) += cxd2099/ -obj-$(CONFIG_EASYCAP) += easycap/ obj-$(CONFIG_LIRC_STAGING) += lirc/ obj-$(CONFIG_SOLO6X10) += solo6x10/ obj-$(CONFIG_VIDEO_DT3155) += dt3155v4l/ diff --git a/drivers/staging/media/as102/Makefile b/drivers/staging/media/as102/Makefile index 1bca43e847c7..d8dfb757f1e2 100644 --- a/drivers/staging/media/as102/Makefile +++ b/drivers/staging/media/as102/Makefile @@ -3,4 +3,4 @@ dvb-as102-objs := as102_drv.o as102_fw.o as10x_cmd.o as10x_cmd_stream.o \ obj-$(CONFIG_DVB_AS102) += dvb-as102.o -EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core +EXTRA_CFLAGS += -Idrivers/media/dvb-core diff --git a/drivers/staging/media/cxd2099/Makefile b/drivers/staging/media/cxd2099/Makefile index 64cfc77be357..b2905e65057c 100644 --- a/drivers/staging/media/cxd2099/Makefile +++ b/drivers/staging/media/cxd2099/Makefile @@ -1,5 +1,5 @@ obj-$(CONFIG_DVB_CXD2099) += cxd2099.o -ccflags-y += -Idrivers/media/dvb/dvb-core/ -ccflags-y += -Idrivers/media/dvb/frontends/ -ccflags-y += -Idrivers/media/common/tuners/ +ccflags-y += -Idrivers/media/dvb-core/ +ccflags-y += -Idrivers/media/dvb-frontends/ +ccflags-y += -Idrivers/media/tuners/ diff --git a/drivers/staging/media/cxd2099/cxd2099.c b/drivers/staging/media/cxd2099/cxd2099.c index 1c04185bcfd7..0ff19724992f 100644 --- a/drivers/staging/media/cxd2099/cxd2099.c +++ b/drivers/staging/media/cxd2099/cxd2099.c @@ -683,27 +683,26 @@ struct dvb_ca_en50221 *cxd2099_attach(struct cxd2099_cfg *cfg, void *priv, struct i2c_adapter *i2c) { - struct cxd *ci = 0; + struct cxd *ci; u8 val; if (i2c_read_reg(i2c, cfg->adr, 0, &val) < 0) { printk(KERN_INFO "No CXD2099 detected at %02x\n", cfg->adr); - return 0; + return NULL; } - ci = kmalloc(sizeof(struct cxd), GFP_KERNEL); + ci = kzalloc(sizeof(struct cxd), GFP_KERNEL); if (!ci) - return 0; - memset(ci, 0, sizeof(*ci)); + return NULL; mutex_init(&ci->lock); - memcpy(&ci->cfg, cfg, sizeof(struct cxd2099_cfg)); + ci->cfg = *cfg; ci->i2c = i2c; ci->lastaddress = 0xff; ci->clk_reg_b = 0x4a; ci->clk_reg_f = 0x1b; - memcpy(&ci->en, &en_templ, sizeof(en_templ)); + ci->en = en_templ; ci->en.data = ci; init(ci); printk(KERN_INFO "Attached CXD2099AR at %02x\n", ci->cfg.adr); diff --git a/drivers/staging/media/dt3155v4l/dt3155v4l.c b/drivers/staging/media/dt3155v4l/dt3155v4l.c index ebe5a27c06f5..2e7b711c8501 100644 --- a/drivers/staging/media/dt3155v4l/dt3155v4l.c +++ b/drivers/staging/media/dt3155v4l/dt3155v4l.c @@ -381,6 +381,8 @@ dt3155_open(struct file *filp) int ret = 0; struct dt3155_priv *pd = video_drvdata(filp); + if (mutex_lock_interruptible(&pd->mux)) + return -ERESTARTSYS; if (!pd->users) { pd->q = kzalloc(sizeof(*pd->q), GFP_KERNEL); if (!pd->q) { @@ -411,6 +413,7 @@ err_request_irq: kfree(pd->q); pd->q = NULL; err_alloc_queue: + mutex_unlock(&pd->mux); return ret; } @@ -419,6 +422,7 @@ dt3155_release(struct file *filp) { struct dt3155_priv *pd = video_drvdata(filp); + mutex_lock(&pd->mux); pd->users--; BUG_ON(pd->users < 0); if (!pd->users) { @@ -429,6 +433,7 @@ dt3155_release(struct file *filp) kfree(pd->q); pd->q = NULL; } + mutex_unlock(&pd->mux); return 0; } @@ -436,24 +441,38 @@ static ssize_t dt3155_read(struct file *filp, char __user *user, size_t size, loff_t *loff) { struct dt3155_priv *pd = video_drvdata(filp); + ssize_t res; - return vb2_read(pd->q, user, size, loff, filp->f_flags & O_NONBLOCK); + if (mutex_lock_interruptible(&pd->mux)) + return -ERESTARTSYS; + res = vb2_read(pd->q, user, size, loff, filp->f_flags & O_NONBLOCK); + mutex_unlock(&pd->mux); + return res; } static unsigned int dt3155_poll(struct file *filp, struct poll_table_struct *polltbl) { struct dt3155_priv *pd = video_drvdata(filp); + unsigned int res; - return vb2_poll(pd->q, filp, polltbl); + mutex_lock(&pd->mux); + res = vb2_poll(pd->q, filp, polltbl); + mutex_unlock(&pd->mux); + return res; } static int dt3155_mmap(struct file *filp, struct vm_area_struct *vma) { struct dt3155_priv *pd = video_drvdata(filp); + int res; - return vb2_mmap(pd->q, vma); + if (mutex_lock_interruptible(&pd->mux)) + return -ERESTARTSYS; + res = vb2_mmap(pd->q, vma); + mutex_unlock(&pd->mux); + return res; } static const struct v4l2_file_operations dt3155_fops = { @@ -898,10 +917,6 @@ dt3155_probe(struct pci_dev *pdev, const struct pci_device_id *id) INIT_LIST_HEAD(&pd->dmaq); mutex_init(&pd->mux); pd->vdev->lock = &pd->mux; /* for locking v4l2_file_operations */ - /* Locking in file operations other than ioctl should be done - by the driver, not the V4L2 core. - This driver needs auditing so that this flag can be removed. */ - set_bit(V4L2_FL_LOCK_ALL_FOPS, &pd->vdev->flags); spin_lock_init(&pd->lock); pd->csr2 = csr2_init; pd->config = config_init; diff --git a/drivers/staging/media/easycap/Kconfig b/drivers/staging/media/easycap/Kconfig deleted file mode 100644 index a425a6f9cdca..000000000000 --- a/drivers/staging/media/easycap/Kconfig +++ /dev/null @@ -1,30 +0,0 @@ -config EASYCAP - tristate "EasyCAP USB ID 05e1:0408 support" - depends on USB && VIDEO_DEV && SND - select SND_PCM - - ---help--- - This is an integrated audio/video driver for EasyCAP cards with - USB ID 05e1:0408. It supports two hardware variants: - - * EasyCAP USB 2.0 Video Adapter with Audio, Model DC60, - having input cables labelled CVBS, S-VIDEO, AUDIO(L), AUDIO(R) - - * EasyCAP002 4-Channel USB 2.0 DVR, having input cables labelled - 1, 2, 3, 4 and an unlabelled input cable for a microphone. - - To compile this driver as a module, choose M here: the - module will be called easycap - -config EASYCAP_DEBUG - bool "Enable EasyCAP driver debugging" - depends on EASYCAP - - ---help--- - This option enables debug printouts - - To enable debug, pass the debug level to the debug module - parameter: - - modprobe easycap debug=[0..9] - diff --git a/drivers/staging/media/easycap/Makefile b/drivers/staging/media/easycap/Makefile deleted file mode 100644 index a34e75f59c18..000000000000 --- a/drivers/staging/media/easycap/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -easycap-objs := easycap_main.o -easycap-objs += easycap_low.o -easycap-objs += easycap_ioctl.o -easycap-objs += easycap_settings.o -easycap-objs += easycap_testcard.o -easycap-objs += easycap_sound.o -obj-$(CONFIG_EASYCAP) += easycap.o - -ccflags-y := -Wall - diff --git a/drivers/staging/media/easycap/README b/drivers/staging/media/easycap/README deleted file mode 100644 index 796b032384bd..000000000000 --- a/drivers/staging/media/easycap/README +++ /dev/null @@ -1,141 +0,0 @@ - - *********************************************************** - * EasyCAP USB 2.0 Video Adapter with Audio, Model DC60 * - * and * - * EasyCAP002 4-Channel USB 2.0 DVR * - *********************************************************** - Mike Thomas <rmthomas@sciolus.org> - - - -SUPPORTED HARDWARE ------------------- - -This driver is intended for use with hardware having USB ID 05e1:0408. -Two kinds of EasyCAP have this USB ID, namely: - - * EasyCAP USB 2.0 Video Adapter with Audio, Model DC60, - having input cables labelled CVBS, S-VIDEO, AUDIO(L), AUDIO(R) - - * EasyCAP002 4-Channel USB 2.0 DVR, having input cables labelled - 1, 2, 3, 4 and an unlabelled input cable for a microphone. - - -BUILD OPTIONS AND DEPENDENCIES ------------------------------- - -Unless EASYCAP_DEBUG is defined during compilation it will not be possible -to select a debug level at the time of module installation. - - -KNOWN RUNTIME ISSUES --------------------- - -(1) Intentionally, this driver will not stream material which is unambiguously -identified by the hardware as copy-protected. Normal video output will be -present for about a minute but will then freeze when this situation arises. - -(2) The controls for luminance, contrast, saturation, hue and volume may not -always work properly. - -(3) Reduced-resolution S-Video seems to suffer from moire artefacts. - - -INPUT NUMBERING ---------------- - -For the EasyCAP with S-VIDEO input cable the driver regards a request for -inputs numbered 0 or 1 as referring to CVBS and a request for input -numbered 5 as referring to S-VIDEO. - -For the EasyCAP with four CVBS inputs the driver expects to be asked for -any one of inputs numbered 1,2,3,4. If input 0 is asked for, it is -interpreted as input 1. - - -MODULE PARAMETERS ------------------ - -Three module parameters are defined: - -debug the easycap module is configured at diagnostic level n (0 to 9) -gain audio gain level n (0 to 31, default is 16) -bars whether to display testcard bars when incoming video signal is lost - 0 => no, 1 => yes (default) - - -SUPPORTED TV STANDARDS AND RESOLUTIONS --------------------------------------- - -The following TV standards are natively supported by the hardware and are -usable as (for example) the "norm=" parameter in the mplayer command: - - PAL_BGHIN, NTSC_N_443, - PAL_Nc, NTSC_N, - SECAM, NTSC_M, NTSC_M_JP, - PAL_60, NTSC_443, - PAL_M. - -In addition, the driver offers "custom" pseudo-standards with a framerate -which is 20% of the usual framerate. These pseudo-standards are named: - - PAL_BGHIN_SLOW, NTSC_N_443_SLOW, - PAL_Nc_SLOW, NTSC_N_SLOW, - SECAM_SLOW, NTSC_M_SLOW, NTSC_M_JP_SLOW, - PAL_60_SLOW, NTSC_443_SLOW, - PAL_M_SLOW. - - -The available picture sizes are: - - at 25 frames per second: 720x576, 704x576, 640x480, 360x288, 320x240; - at 30 frames per second: 720x480, 640x480, 360x240, 320x240. - - -WHAT'S TESTED AND WHAT'S NOT ----------------------------- - -This driver is known to work with mplayer, mencoder, tvtime, zoneminder, -xawtv, gstreamer and sufficiently recent versions of vlc. An interface -to ffmpeg is implemented, but serious audio-video synchronization problems -remain. - -The driver is designed to support all the TV standards accepted by the -hardware, but as yet it has actually been tested on only a few of these. - -I have been unable to test and calibrate the S-video input myself because I -do not possess any equipment with S-video output. - - -UDEV RULES ----------- - -In order that the special files /dev/easycap0 and /dev/easysnd1 are created -with conveniently relaxed permissions when the EasyCAP is plugged in, a file -is preferably to be provided in directory /etc/udev/rules.d with content: - -ACTION!="add|change", GOTO="easycap_rules_end" -ATTRS{idVendor}=="05e1", ATTRS{idProduct}=="0408", \ - MODE="0666", OWNER="root", GROUP="root" -LABEL="easycap_rules_end" - - -MODPROBE CONFIGURATION ----------------------- - -The easycap module is in competition with the module snd-usb-audio for the -EasyCAP's audio channel, and its installation can be aided by providing a -file in directory /etc/modprobe.d with content: - -options easycap gain=16 bars=1 -install easycap /sbin/rmmod snd-usb-audio; /sbin/modprobe --ignore-install easycap - - -ACKNOWLEGEMENTS AND REFERENCES ------------------------------- -This driver makes use of information contained in the Syntek Semicon DC-1125 -Driver, presently maintained at http://sourceforge.net/projects/syntekdriver/ -by Nicolas Vivien. Particularly useful has been a patch to the latter driver -provided by Ivor Hewitt in January 2009. The NTSC implementation is taken -from the work of Ben Trask. - diff --git a/drivers/staging/media/easycap/easycap.h b/drivers/staging/media/easycap/easycap.h deleted file mode 100644 index a007e7442be8..000000000000 --- a/drivers/staging/media/easycap/easycap.h +++ /dev/null @@ -1,567 +0,0 @@ -/***************************************************************************** -* * -* easycap.h * -* * -*****************************************************************************/ -/* - * - * Copyright (C) 2010 R.M. Thomas <rmthomas@sciolus.org> - * - * - * This 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. - * - * The software 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 software; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * -*/ -/*****************************************************************************/ -/*---------------------------------------------------------------------------*/ -/* - * THE FOLLOWING PARAMETERS ARE UNDEFINED: - * - * EASYCAP_DEBUG - * - * IF REQUIRED THEY MUST BE EXTERNALLY DEFINED, FOR EXAMPLE AS COMPILER - * OPTIONS. - */ -/*---------------------------------------------------------------------------*/ - -#ifndef __EASYCAP_H__ -#define __EASYCAP_H__ - -/*---------------------------------------------------------------------------*/ -/* - * THESE ARE NORMALLY DEFINED - */ -/*---------------------------------------------------------------------------*/ -#define PATIENCE 500 -#define PERSEVERE -/*---------------------------------------------------------------------------*/ -/* - * THESE ARE FOR MAINTENANCE ONLY - NORMALLY UNDEFINED: - */ -/*---------------------------------------------------------------------------*/ -#undef EASYCAP_TESTCARD -/*---------------------------------------------------------------------------*/ -#include <linux/kernel.h> -#include <linux/errno.h> -#include <linux/init.h> -#include <linux/slab.h> -#include <linux/module.h> -#include <linux/kref.h> -#include <linux/usb.h> -#include <linux/uaccess.h> - -#include <linux/i2c.h> -#include <linux/workqueue.h> -#include <linux/poll.h> -#include <linux/mm.h> -#include <linux/fs.h> -#include <linux/delay.h> -#include <linux/types.h> - -#include <linux/vmalloc.h> -#include <linux/sound.h> -#include <sound/core.h> -#include <sound/pcm.h> -#include <sound/pcm_params.h> -#include <sound/info.h> -#include <sound/initval.h> -#include <sound/control.h> -#include <media/v4l2-dev.h> -#include <media/v4l2-device.h> -#include <linux/videodev2.h> -#include <linux/soundcard.h> - -/*---------------------------------------------------------------------------*/ -/* VENDOR, PRODUCT: Syntek Semiconductor Co., Ltd - * - * EITHER EasyCAP USB 2.0 Video Adapter with Audio, Model No. DC60 - * with input cabling: AUDIO(L), AUDIO(R), CVBS, S-VIDEO. - * - * OR EasyCAP 4CHANNEL USB 2.0 DVR, Model No. EasyCAP002 - * with input cabling: MICROPHONE, CVBS1, CVBS2, CVBS3, CVBS4. - */ -/*---------------------------------------------------------------------------*/ -#define USB_EASYCAP_VENDOR_ID 0x05e1 -#define USB_EASYCAP_PRODUCT_ID 0x0408 - -#define EASYCAP_DRIVER_VERSION "0.9.01" -#define EASYCAP_DRIVER_DESCRIPTION "easycapdc60" - -#define DONGLE_MANY 8 -#define INPUT_MANY 6 -/*---------------------------------------------------------------------------*/ -/* - * DEFAULT LUMINANCE, CONTRAST, SATURATION AND HUE - */ -/*---------------------------------------------------------------------------*/ -#define SAA_0A_DEFAULT 0x7F -#define SAA_0B_DEFAULT 0x3F -#define SAA_0C_DEFAULT 0x2F -#define SAA_0D_DEFAULT 0x00 -/*---------------------------------------------------------------------------*/ -/* - * VIDEO STREAMING PARAMETERS: - * USB 2.0 PROVIDES FOR HIGH-BANDWIDTH ENDPOINTS WITH AN UPPER LIMIT - * OF 3072 BYTES PER MICROFRAME for wMaxPacketSize. - */ -/*---------------------------------------------------------------------------*/ -#define VIDEO_ISOC_BUFFER_MANY 16 -#define VIDEO_ISOC_ORDER 3 -#define VIDEO_ISOC_FRAMESPERDESC ((unsigned int) 1 << VIDEO_ISOC_ORDER) -#define USB_2_0_MAXPACKETSIZE 3072 -#if (USB_2_0_MAXPACKETSIZE > PAGE_SIZE) -#error video_isoc_buffer[.] will not be big enough -#endif -#define VIDEO_JUNK_TOLERATE VIDEO_ISOC_BUFFER_MANY -#define VIDEO_LOST_TOLERATE 50 -/*---------------------------------------------------------------------------*/ -/* - * VIDEO BUFFERS - */ -/*---------------------------------------------------------------------------*/ -#define FIELD_BUFFER_SIZE (203 * PAGE_SIZE) -#define FRAME_BUFFER_SIZE (405 * PAGE_SIZE) -#define FIELD_BUFFER_MANY 4 -#define FRAME_BUFFER_MANY 6 -/*---------------------------------------------------------------------------*/ -/* - * AUDIO STREAMING PARAMETERS - */ -/*---------------------------------------------------------------------------*/ -#define AUDIO_ISOC_BUFFER_MANY 16 -#define AUDIO_ISOC_ORDER 1 -#define AUDIO_ISOC_FRAMESPERDESC 32 -#define AUDIO_ISOC_BUFFER_SIZE (PAGE_SIZE << AUDIO_ISOC_ORDER) -/*---------------------------------------------------------------------------*/ -/* - * AUDIO BUFFERS - */ -/*---------------------------------------------------------------------------*/ -#define AUDIO_FRAGMENT_MANY 32 -#define PAGES_PER_AUDIO_FRAGMENT 4 -/*---------------------------------------------------------------------------*/ -/* - * IT IS ESSENTIAL THAT EVEN-NUMBERED STANDARDS ARE 25 FRAMES PER SECOND, - * ODD-NUMBERED STANDARDS ARE 30 FRAMES PER SECOND. - * THE NUMBERING OF STANDARDS MUST NOT BE CHANGED WITHOUT DUE CARE. NOT - * ONLY MUST THE PARAMETER - * STANDARD_MANY - * BE CHANGED TO CORRESPOND TO THE NEW NUMBER OF STANDARDS, BUT ALSO THE - * NUMBERING MUST REMAIN AN UNBROKEN ASCENDING SEQUENCE: DUMMY STANDARDS - * MAY NEED TO BE ADDED. APPROPRIATE CHANGES WILL ALWAYS BE REQUIRED IN - * ROUTINE fillin_formats() AND POSSIBLY ELSEWHERE. BEWARE. - */ -/*---------------------------------------------------------------------------*/ -#define PAL_BGHIN 0 -#define PAL_Nc 2 -#define SECAM 4 -#define NTSC_N 6 -#define NTSC_N_443 8 -#define NTSC_M 1 -#define NTSC_443 3 -#define NTSC_M_JP 5 -#define PAL_60 7 -#define PAL_M 9 -#define PAL_BGHIN_SLOW 10 -#define PAL_Nc_SLOW 12 -#define SECAM_SLOW 14 -#define NTSC_N_SLOW 16 -#define NTSC_N_443_SLOW 18 -#define NTSC_M_SLOW 11 -#define NTSC_443_SLOW 13 -#define NTSC_M_JP_SLOW 15 -#define PAL_60_SLOW 17 -#define PAL_M_SLOW 19 -#define STANDARD_MANY 20 -/*---------------------------------------------------------------------------*/ -/* - * ENUMS - */ -/*---------------------------------------------------------------------------*/ -enum { - AT_720x576, - AT_704x576, - AT_640x480, - AT_720x480, - AT_360x288, - AT_320x240, - AT_360x240, - RESOLUTION_MANY -}; -enum { - FMT_UYVY, - FMT_YUY2, - FMT_RGB24, - FMT_RGB32, - FMT_BGR24, - FMT_BGR32, - PIXELFORMAT_MANY -}; -enum { - FIELD_NONE, - FIELD_INTERLACED, - INTERLACE_MANY -}; -#define SETTINGS_MANY (STANDARD_MANY * \ - RESOLUTION_MANY * \ - 2 * \ - PIXELFORMAT_MANY * \ - INTERLACE_MANY) -/*---------------------------------------------------------------------------*/ -/* - * STRUCTURE DEFINITIONS - */ -/*---------------------------------------------------------------------------*/ -struct easycap_dongle { - struct easycap *peasycap; - struct mutex mutex_video; - struct mutex mutex_audio; -}; -/*---------------------------------------------------------------------------*/ -struct data_buffer { - struct list_head list_head; - void *pgo; - void *pto; - u16 kount; - u16 input; -}; -/*---------------------------------------------------------------------------*/ -struct data_urb { - struct list_head list_head; - struct urb *purb; - int isbuf; - int length; -}; -/*---------------------------------------------------------------------------*/ -struct easycap_standard { - u16 mask; -struct v4l2_standard v4l2_standard; -}; -struct easycap_format { - u16 mask; - char name[128]; -struct v4l2_format v4l2_format; -}; -struct inputset { - int input; - int input_ok; - int standard_offset; - int standard_offset_ok; - int format_offset; - int format_offset_ok; - int brightness; - int brightness_ok; - int contrast; - int contrast_ok; - int saturation; - int saturation_ok; - int hue; - int hue_ok; -}; -/*---------------------------------------------------------------------------*/ -/* - * easycap.ilk == 0 => CVBS+S-VIDEO HARDWARE, AUDIO wMaxPacketSize=256 - * easycap.ilk == 2 => CVBS+S-VIDEO HARDWARE, AUDIO wMaxPacketSize=9 - * easycap.ilk == 3 => FOUR-CVBS HARDWARE, AUDIO wMaxPacketSize=9 - */ -/*---------------------------------------------------------------------------*/ -struct easycap { - int isdongle; - int minor; - - struct video_device video_device; - struct v4l2_device v4l2_device; - - int status; - unsigned int audio_pages_per_fragment; - unsigned int audio_bytes_per_fragment; - unsigned int audio_buffer_page_many; - -#define UPSAMPLE -#ifdef UPSAMPLE - s16 oldaudio; -#endif /*UPSAMPLE*/ - - int ilk; - bool microphone; - - struct usb_device *pusb_device; - struct usb_interface *pusb_interface; - - struct kref kref; - - int queued[FRAME_BUFFER_MANY]; - int done[FRAME_BUFFER_MANY]; - - wait_queue_head_t wq_video; - wait_queue_head_t wq_audio; - wait_queue_head_t wq_trigger; - - int input; - int polled; - int standard_offset; - int format_offset; - struct inputset inputset[INPUT_MANY]; - - bool ntsc; - int fps; - int usec; - int tolerate; - int skip; - int skipped; - int lost[INPUT_MANY]; - int merit[180]; - - int video_interface; - int video_altsetting_on; - int video_altsetting_off; - int video_endpointnumber; - int video_isoc_maxframesize; - int video_isoc_buffer_size; - int video_isoc_framesperdesc; - - int video_isoc_streaming; - int video_isoc_sequence; - int video_idle; - int video_eof; - int video_junk; - - struct data_buffer video_isoc_buffer[VIDEO_ISOC_BUFFER_MANY]; - struct data_buffer field_buffer[FIELD_BUFFER_MANY] - [(FIELD_BUFFER_SIZE/PAGE_SIZE)]; - struct data_buffer frame_buffer[FRAME_BUFFER_MANY] - [(FRAME_BUFFER_SIZE/PAGE_SIZE)]; - - struct list_head urb_video_head; - struct list_head *purb_video_head; - - u8 cache[8]; - u8 *pcache; - int video_mt; - int audio_mt; - u32 isequence; - - int vma_many; -/*---------------------------------------------------------------------------*/ -/* - * BUFFER INDICATORS - */ -/*---------------------------------------------------------------------------*/ - int field_fill; /* Field buffer being filled by easycap_complete(). */ - /* Bumped only by easycap_complete(). */ - int field_page; /* Page of field buffer page being filled by */ - /* easycap_complete(). */ - int field_read; /* Field buffer to be read by field2frame(). */ - /* Bumped only by easycap_complete(). */ - int frame_fill; /* Frame buffer being filled by field2frame(). */ - /* Bumped only by easycap_dqbuf() when */ - /* field2frame() has created a complete frame. */ - int frame_read; /* Frame buffer offered to user by DQBUF. */ - /* Set only by easycap_dqbuf() to trail frame_fill.*/ - int frame_lock; /* Flag set to 1 by DQBUF and cleared by QBUF */ -/*---------------------------------------------------------------------------*/ -/* - * IMAGE PROPERTIES - */ -/*---------------------------------------------------------------------------*/ - u32 pixelformat; - int width; - int height; - int bytesperpixel; - bool byteswaporder; - bool decimatepixel; - bool offerfields; - int frame_buffer_used; - int frame_buffer_many; - int videofieldamount; - - int brightness; - int contrast; - int saturation; - int hue; - - int allocation_video_urb; - int allocation_video_page; - int allocation_video_struct; - int registered_video; -/*---------------------------------------------------------------------------*/ -/* - * ALSA - */ -/*---------------------------------------------------------------------------*/ - struct snd_pcm_hardware alsa_hardware; - struct snd_card *psnd_card; - struct snd_pcm *psnd_pcm; - struct snd_pcm_substream *psubstream; - int dma_fill; - int dma_next; - int dma_read; -/*---------------------------------------------------------------------------*/ -/* - * SOUND PROPERTIES - */ -/*---------------------------------------------------------------------------*/ - int audio_interface; - int audio_altsetting_on; - int audio_altsetting_off; - int audio_endpointnumber; - int audio_isoc_maxframesize; - int audio_isoc_buffer_size; - int audio_isoc_framesperdesc; - - int audio_isoc_streaming; - int audio_idle; - int audio_eof; - int volume; - int mute; - s8 gain; - - struct data_buffer audio_isoc_buffer[AUDIO_ISOC_BUFFER_MANY]; - - struct list_head urb_audio_head; - struct list_head *purb_audio_head; -/*---------------------------------------------------------------------------*/ -/* - * BUFFER INDICATORS - */ -/*---------------------------------------------------------------------------*/ - int audio_fill; /* Audio buffer being filled by easycap_complete(). */ - /* Bumped only by easycap_complete(). */ - int audio_read; /* Audio buffer page being read by easycap_read(). */ - /* Set by easycap_read() to trail audio_fill by */ - /* one fragment. */ -/*---------------------------------------------------------------------------*/ -/* - * SOUND PROPERTIES - */ -/*---------------------------------------------------------------------------*/ - int allocation_audio_urb; - int allocation_audio_page; - int allocation_audio_struct; - int registered_audio; - - long long int audio_sample; - long long int audio_niveau; - long long int audio_square; - - struct data_buffer audio_buffer[]; -}; -/*---------------------------------------------------------------------------*/ -/* - * VIDEO FUNCTION PROTOTYPES - */ -/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ -int easycap_newinput(struct easycap *, int); -void easycap_testcard(struct easycap *, int); -int easycap_isdongle(struct easycap *); - -long easycap_unlocked_ioctl(struct file *, unsigned int, unsigned long); - -int easycap_video_dqbuf(struct easycap *, int); -int easycap_video_submit_urbs(struct easycap *); -int easycap_video_kill_urbs(struct easycap *); -int easycap_video_fillin_formats(void); - -int adjust_standard(struct easycap *, v4l2_std_id); -int adjust_format(struct easycap *, u32, u32, u32, int, bool); -int adjust_brightness(struct easycap *, int); -int adjust_contrast(struct easycap *, int); -int adjust_saturation(struct easycap *, int); -int adjust_hue(struct easycap *, int); -/*---------------------------------------------------------------------------*/ -/* - * AUDIO FUNCTION PROTOTYPES - */ -/*---------------------------------------------------------------------------*/ -int easycap_alsa_probe(struct easycap *); -int easycap_audio_kill_urbs(struct easycap *); -void easycap_alsa_complete(struct urb *); -/*---------------------------------------------------------------------------*/ -/* - * LOW-LEVEL FUNCTION PROTOTYPES - */ -/*---------------------------------------------------------------------------*/ -int easycap_audio_gainset(struct usb_device *, s8); -int easycap_audio_setup(struct easycap *); - -int easycap_wakeup_device(struct usb_device *); - -int setup_stk(struct usb_device *, bool); -int setup_saa(struct usb_device *, bool); -int ready_saa(struct usb_device *); -int merit_saa(struct usb_device *); -int check_vt(struct usb_device *); -int select_input(struct usb_device *, int, int); -int set_resolution(struct usb_device *, u16, u16, u16, u16); - -int read_saa(struct usb_device *, u16); -int write_saa(struct usb_device *, u16, u16); -int start_100(struct usb_device *); -int stop_100(struct usb_device *); -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* - * MACROS SAM(...) AND JOM(...) ALLOW DIAGNOSTIC OUTPUT TO BE TAGGED WITH - * THE IDENTITY OF THE DONGLE TO WHICH IT APPLIES, BUT IF INVOKED WHEN THE - * POINTER peasycap IS INVALID AN Oops IS LIKELY, AND ITS CAUSE MAY NOT BE - * IMMEDIATELY OBVIOUS FROM A CASUAL READING OF THE SOURCE CODE. BEWARE. -*/ -/*---------------------------------------------------------------------------*/ -const char *strerror(int err); - -#define SAY(format, args...) do { \ - printk(KERN_DEBUG "easycap:: %s: " \ - format, __func__, ##args); \ -} while (0) -#define SAM(format, args...) do { \ - printk(KERN_DEBUG "easycap::%i%s: " \ - format, peasycap->isdongle, __func__, ##args);\ -} while (0) - -#ifdef CONFIG_EASYCAP_DEBUG -extern int easycap_debug; -#define JOT(n, format, args...) do { \ - if (n <= easycap_debug) { \ - printk(KERN_DEBUG "easycap:: %s: " \ - format, __func__, ##args);\ - } \ -} while (0) -#define JOM(n, format, args...) do { \ - if (n <= easycap_debug) { \ - printk(KERN_DEBUG "easycap::%i%s: " \ - format, peasycap->isdongle, __func__, ##args);\ - } \ -} while (0) - -#else -#define JOT(n, format, args...) do {} while (0) -#define JOM(n, format, args...) do {} while (0) -#endif /* CONFIG_EASYCAP_DEBUG */ - -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* globals - */ -/*---------------------------------------------------------------------------*/ - -extern bool easycap_readback; -extern const struct easycap_standard easycap_standard[]; -extern struct easycap_format easycap_format[]; -extern struct v4l2_queryctrl easycap_control[]; -extern struct easycap_dongle easycapdc60_dongle[]; - -#endif /* !__EASYCAP_H__ */ diff --git a/drivers/staging/media/easycap/easycap_ioctl.c b/drivers/staging/media/easycap/easycap_ioctl.c deleted file mode 100644 index 3cee3cd986d2..000000000000 --- a/drivers/staging/media/easycap/easycap_ioctl.c +++ /dev/null @@ -1,2443 +0,0 @@ -/****************************************************************************** -* * -* easycap_ioctl.c * -* * -******************************************************************************/ -/* - * - * Copyright (C) 2010 R.M. Thomas <rmthomas@sciolus.org> - * - * - * This 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. - * - * The software 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 software; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * -*/ -/*****************************************************************************/ - -#include "easycap.h" -#include <linux/version.h> - -/*--------------------------------------------------------------------------*/ -/* - * UNLESS THERE IS A PREMATURE ERROR RETURN THIS ROUTINE UPDATES THE - * FOLLOWING: - * peasycap->standard_offset - * peasycap->inputset[peasycap->input].standard_offset - * peasycap->fps - * peasycap->usec - * peasycap->tolerate - * peasycap->skip - */ -/*---------------------------------------------------------------------------*/ -int adjust_standard(struct easycap *peasycap, v4l2_std_id std_id) -{ - struct easycap_standard const *peasycap_standard; - u16 reg, set; - int ir, rc, need, k; - unsigned int itwas, isnow; - bool resubmit; - - if (!peasycap) { - SAY("ERROR: peasycap is NULL\n"); - return -EFAULT; - } - if (!peasycap->pusb_device) { - SAM("ERROR: peasycap->pusb_device is NULL\n"); - return -EFAULT; - } - peasycap_standard = &easycap_standard[0]; - while (0xFFFF != peasycap_standard->mask) { - if (std_id == peasycap_standard->v4l2_standard.id) - break; - peasycap_standard++; - } - if (0xFFFF == peasycap_standard->mask) { - peasycap_standard = &easycap_standard[0]; - while (0xFFFF != peasycap_standard->mask) { - if (std_id & peasycap_standard->v4l2_standard.id) - break; - peasycap_standard++; - } - } - if (0xFFFF == peasycap_standard->mask) { - SAM("ERROR: 0x%08X=std_id: standard not found\n", - (unsigned int)std_id); - return -EINVAL; - } - SAM("selected standard: %s\n", - &(peasycap_standard->v4l2_standard.name[0])); - if (peasycap->standard_offset == peasycap_standard - easycap_standard) { - SAM("requested standard already in effect\n"); - return 0; - } - peasycap->standard_offset = peasycap_standard - easycap_standard; - for (k = 0; k < INPUT_MANY; k++) { - if (!peasycap->inputset[k].standard_offset_ok) { - peasycap->inputset[k].standard_offset = - peasycap->standard_offset; - } - } - if ((0 <= peasycap->input) && (INPUT_MANY > peasycap->input)) { - peasycap->inputset[peasycap->input].standard_offset = - peasycap->standard_offset; - peasycap->inputset[peasycap->input].standard_offset_ok = 1; - } else - JOM(8, "%i=peasycap->input\n", peasycap->input); - - peasycap->fps = peasycap_standard->v4l2_standard.frameperiod.denominator / - peasycap_standard->v4l2_standard.frameperiod.numerator; - switch (peasycap->fps) { - case 6: - case 30: { - peasycap->ntsc = true; - break; - } - case 5: - case 25: { - peasycap->ntsc = false; - break; - } - default: { - SAM("MISTAKE: %i=frames-per-second\n", peasycap->fps); - return -ENOENT; - } - } - JOM(8, "%i frames-per-second\n", peasycap->fps); - if (0x8000 & peasycap_standard->mask) { - peasycap->skip = 5; - peasycap->usec = 1000000 / (2 * (5 * peasycap->fps)); - peasycap->tolerate = 1000 * (25 / (5 * peasycap->fps)); - } else { - peasycap->skip = 0; - peasycap->usec = 1000000 / (2 * peasycap->fps); - peasycap->tolerate = 1000 * (25 / peasycap->fps); - } - if (peasycap->video_isoc_streaming) { - resubmit = true; - easycap_video_kill_urbs(peasycap); - } else - resubmit = false; -/*--------------------------------------------------------------------------*/ -/* - * SAA7113H DATASHEET PAGE 44, TABLE 42 - */ -/*--------------------------------------------------------------------------*/ - need = 0; - itwas = 0; - reg = 0x00; - set = 0x00; - switch (peasycap_standard->mask & 0x000F) { - case NTSC_M_JP: { - reg = 0x0A; - set = 0x95; - ir = read_saa(peasycap->pusb_device, reg); - if (0 > ir) - SAM("ERROR: cannot read SAA register 0x%02X\n", reg); - else - itwas = (unsigned int)ir; - rc = write_saa(peasycap->pusb_device, reg, set); - if (rc) - SAM("ERROR: failed to set SAA register " - "0x%02X to 0x%02X for JP standard\n", reg, set); - else { - isnow = (unsigned int)read_saa(peasycap->pusb_device, reg); - if (0 > ir) - JOM(8, "SAA register 0x%02X changed " - "to 0x%02X\n", reg, isnow); - else - JOM(8, "SAA register 0x%02X changed " - "from 0x%02X to 0x%02X\n", reg, itwas, isnow); - } - - reg = 0x0B; - set = 0x48; - ir = read_saa(peasycap->pusb_device, reg); - if (0 > ir) - SAM("ERROR: cannot read SAA register 0x%02X\n", reg); - else - itwas = (unsigned int)ir; - rc = write_saa(peasycap->pusb_device, reg, set); - if (rc) - SAM("ERROR: failed to set SAA register 0x%02X to 0x%02X " - "for JP standard\n", reg, set); - else { - isnow = (unsigned int)read_saa(peasycap->pusb_device, reg); - if (0 > ir) - JOM(8, "SAA register 0x%02X changed " - "to 0x%02X\n", reg, isnow); - else - JOM(8, "SAA register 0x%02X changed " - "from 0x%02X to 0x%02X\n", reg, itwas, isnow); - } -/*--------------------------------------------------------------------------*/ -/* - * NOTE: NO break HERE: RUN ON TO NEXT CASE - */ -/*--------------------------------------------------------------------------*/ - } - case NTSC_M: - case PAL_BGHIN: { - reg = 0x0E; - set = 0x01; - need = 1; - break; - } - case NTSC_N_443: - case PAL_60: { - reg = 0x0E; - set = 0x11; - need = 1; - break; - } - case NTSC_443: - case PAL_Nc: { - reg = 0x0E; - set = 0x21; - need = 1; - break; - } - case NTSC_N: - case PAL_M: { - reg = 0x0E; - set = 0x31; - need = 1; - break; - } - case SECAM: { - reg = 0x0E; - set = 0x51; - need = 1; - break; - } - default: - break; - } -/*--------------------------------------------------------------------------*/ - if (need) { - ir = read_saa(peasycap->pusb_device, reg); - if (0 > ir) - SAM("ERROR: failed to read SAA register 0x%02X\n", reg); - else - itwas = (unsigned int)ir; - rc = write_saa(peasycap->pusb_device, reg, set); - if (0 != write_saa(peasycap->pusb_device, reg, set)) { - SAM("ERROR: failed to set SAA register " - "0x%02X to 0x%02X for table 42\n", reg, set); - } else { - isnow = (unsigned int)read_saa(peasycap->pusb_device, reg); - if (0 > ir) - JOM(8, "SAA register 0x%02X changed " - "to 0x%02X\n", reg, isnow); - else - JOM(8, "SAA register 0x%02X changed " - "from 0x%02X to 0x%02X\n", reg, itwas, isnow); - } - } -/*--------------------------------------------------------------------------*/ -/* - * SAA7113H DATASHEET PAGE 41 - */ -/*--------------------------------------------------------------------------*/ - reg = 0x08; - ir = read_saa(peasycap->pusb_device, reg); - if (0 > ir) - SAM("ERROR: failed to read SAA register 0x%02X " - "so cannot reset\n", reg); - else { - itwas = (unsigned int)ir; - if (peasycap_standard->mask & 0x0001) - set = itwas | 0x40 ; - else - set = itwas & ~0x40 ; - rc = write_saa(peasycap->pusb_device, reg, set); - if (rc) - SAM("ERROR: failed to set SAA register 0x%02X to 0x%02X\n", - reg, set); - else { - isnow = (unsigned int)read_saa(peasycap->pusb_device, reg); - if (0 > ir) - JOM(8, "SAA register 0x%02X changed to 0x%02X\n", - reg, isnow); - else - JOM(8, "SAA register 0x%02X changed " - "from 0x%02X to 0x%02X\n", reg, itwas, isnow); - } - } -/*--------------------------------------------------------------------------*/ -/* - * SAA7113H DATASHEET PAGE 51, TABLE 57 - */ -/*---------------------------------------------------------------------------*/ - reg = 0x40; - ir = read_saa(peasycap->pusb_device, reg); - if (0 > ir) - SAM("ERROR: failed to read SAA register 0x%02X " - "so cannot reset\n", reg); - else { - itwas = (unsigned int)ir; - if (peasycap_standard->mask & 0x0001) - set = itwas | 0x80 ; - else - set = itwas & ~0x80 ; - rc = write_saa(peasycap->pusb_device, reg, set); - if (rc) - SAM("ERROR: failed to set SAA register 0x%02X to 0x%02X\n", - reg, set); - else { - isnow = (unsigned int)read_saa(peasycap->pusb_device, reg); - if (0 > ir) - JOM(8, "SAA register 0x%02X changed to 0x%02X\n", - reg, isnow); - else - JOM(8, "SAA register 0x%02X changed " - "from 0x%02X to 0x%02X\n", reg, itwas, isnow); - } - } -/*--------------------------------------------------------------------------*/ -/* - * SAA7113H DATASHEET PAGE 53, TABLE 66 - */ -/*--------------------------------------------------------------------------*/ - reg = 0x5A; - ir = read_saa(peasycap->pusb_device, reg); - if (0 > ir) - SAM("ERROR: failed to read SAA register 0x%02X but continuing\n", reg); - itwas = (unsigned int)ir; - if (peasycap_standard->mask & 0x0001) - set = 0x0A ; - else - set = 0x07 ; - if (0 != write_saa(peasycap->pusb_device, reg, set)) - SAM("ERROR: failed to set SAA register 0x%02X to 0x%02X\n", - reg, set); - else { - isnow = (unsigned int)read_saa(peasycap->pusb_device, reg); - if (0 > ir) - JOM(8, "SAA register 0x%02X changed " - "to 0x%02X\n", reg, isnow); - else - JOM(8, "SAA register 0x%02X changed " - "from 0x%02X to 0x%02X\n", reg, itwas, isnow); - } - if (resubmit) - easycap_video_submit_urbs(peasycap); - return 0; -} -/*****************************************************************************/ -/*--------------------------------------------------------------------------*/ -/* - * THE ALGORITHM FOR RESPONDING TO THE VIDIO_S_FMT IOCTL REQUIRES - * A VALID VALUE OF peasycap->standard_offset, OTHERWISE -EBUSY IS RETURNED. - * - * PROVIDED THE ARGUMENT try IS false AND THERE IS NO PREMATURE ERROR RETURN - * THIS ROUTINE UPDATES THE FOLLOWING: - * peasycap->format_offset - * peasycap->inputset[peasycap->input].format_offset - * peasycap->pixelformat - * peasycap->height - * peasycap->width - * peasycap->bytesperpixel - * peasycap->byteswaporder - * peasycap->decimatepixel - * peasycap->frame_buffer_used - * peasycap->videofieldamount - * peasycap->offerfields - * - * IF SUCCESSFUL THE FUNCTION RETURNS THE OFFSET IN easycap_format[] - * IDENTIFYING THE FORMAT WHICH IS TO RETURNED TO THE USER. - * ERRORS RETURN A NEGATIVE NUMBER. - */ -/*--------------------------------------------------------------------------*/ -int adjust_format(struct easycap *peasycap, - u32 width, u32 height, u32 pixelformat, int field, bool try) -{ - struct easycap_format *peasycap_format, *peasycap_best_format; - u16 mask; - struct usb_device *p; - int miss, multiplier, best, k; - char bf[5], fo[32], *pc; - u32 uc; - bool resubmit; - - if (!peasycap) { - SAY("ERROR: peasycap is NULL\n"); - return -EFAULT; - } - if (0 > peasycap->standard_offset) { - JOM(8, "%i=peasycap->standard_offset\n", peasycap->standard_offset); - return -EBUSY; - } - p = peasycap->pusb_device; - if (!p) { - SAM("ERROR: peaycap->pusb_device is NULL\n"); - return -EFAULT; - } - pc = &bf[0]; - uc = pixelformat; - memcpy((void *)pc, (void *)(&uc), 4); - bf[4] = 0; - mask = 0xFF & easycap_standard[peasycap->standard_offset].mask; - SAM("sought: %ix%i,%s(0x%08X),%i=field,0x%02X=std mask\n", - width, height, pc, pixelformat, field, mask); - switch (field) { - case V4L2_FIELD_ANY: { - strcpy(&fo[0], "V4L2_FIELD_ANY "); - break; - } - case V4L2_FIELD_NONE: { - strcpy(&fo[0], "V4L2_FIELD_NONE"); - break; - } - case V4L2_FIELD_TOP: { - strcpy(&fo[0], "V4L2_FIELD_TOP"); - break; - } - case V4L2_FIELD_BOTTOM: { - strcpy(&fo[0], "V4L2_FIELD_BOTTOM"); - break; - } - case V4L2_FIELD_INTERLACED: { - strcpy(&fo[0], "V4L2_FIELD_INTERLACED"); - break; - } - case V4L2_FIELD_SEQ_TB: { - strcpy(&fo[0], "V4L2_FIELD_SEQ_TB"); - break; - } - case V4L2_FIELD_SEQ_BT: { - strcpy(&fo[0], "V4L2_FIELD_SEQ_BT"); - break; - } - case V4L2_FIELD_ALTERNATE: { - strcpy(&fo[0], "V4L2_FIELD_ALTERNATE"); - break; - } - case V4L2_FIELD_INTERLACED_TB: { - strcpy(&fo[0], "V4L2_FIELD_INTERLACED_TB"); - break; - } - case V4L2_FIELD_INTERLACED_BT: { - strcpy(&fo[0], "V4L2_FIELD_INTERLACED_BT"); - break; - } - default: { - strcpy(&fo[0], "V4L2_FIELD_... UNKNOWN "); - break; - } - } - SAM("sought: %s\n", &fo[0]); - if (V4L2_FIELD_ANY == field) { - field = V4L2_FIELD_NONE; - SAM("prefer: V4L2_FIELD_NONE=field, was V4L2_FIELD_ANY\n"); - } - peasycap_best_format = NULL; - peasycap_format = &easycap_format[0]; - while (0 != peasycap_format->v4l2_format.fmt.pix.width) { - JOM(16, ".> %i %i 0x%08X %ix%i\n", - peasycap_format->mask & 0x01, - peasycap_format->v4l2_format.fmt.pix.field, - peasycap_format->v4l2_format.fmt.pix.pixelformat, - peasycap_format->v4l2_format.fmt.pix.width, - peasycap_format->v4l2_format.fmt.pix.height); - - if (((peasycap_format->mask & 0x1F) == (mask & 0x1F)) && - (peasycap_format->v4l2_format.fmt.pix.field == field) && - (peasycap_format->v4l2_format.fmt.pix.pixelformat == pixelformat) && - (peasycap_format->v4l2_format.fmt.pix.width == width) && - (peasycap_format->v4l2_format.fmt.pix.height == height)) { - - peasycap_best_format = peasycap_format; - break; - } - peasycap_format++; - } - if (0 == peasycap_format->v4l2_format.fmt.pix.width) { - SAM("cannot do: %ix%i with standard mask 0x%02X\n", - width, height, mask); - peasycap_format = &easycap_format[0]; - best = -1; - while (0 != peasycap_format->v4l2_format.fmt.pix.width) { - if (((peasycap_format->mask & 0x1F) == (mask & 0x1F)) && - (peasycap_format->v4l2_format.fmt.pix.field == field) && - (peasycap_format->v4l2_format.fmt.pix.pixelformat == pixelformat)) { - - miss = abs(peasycap_format->v4l2_format.fmt.pix.width - width); - if ((best > miss) || (best < 0)) { - best = miss; - peasycap_best_format = peasycap_format; - if (!miss) - break; - } - } - peasycap_format++; - } - if (-1 == best) { - SAM("cannot do %ix... with standard mask 0x%02X\n", - width, mask); - SAM("cannot do ...x%i with standard mask 0x%02X\n", - height, mask); - SAM(" %ix%i unmatched\n", width, height); - return peasycap->format_offset; - } - } - if (!peasycap_best_format) { - SAM("MISTAKE: peasycap_best_format is NULL"); - return -EINVAL; - } - peasycap_format = peasycap_best_format; - -/*...........................................................................*/ - if (try) - return peasycap_best_format - easycap_format; -/*...........................................................................*/ - - if (false != try) { - SAM("MISTAKE: true==try where is should be false\n"); - return -EINVAL; - } - SAM("actioning: %ix%i %s\n", - peasycap_format->v4l2_format.fmt.pix.width, - peasycap_format->v4l2_format.fmt.pix.height, - &peasycap_format->name[0]); - peasycap->height = peasycap_format->v4l2_format.fmt.pix.height; - peasycap->width = peasycap_format->v4l2_format.fmt.pix.width; - peasycap->pixelformat = peasycap_format->v4l2_format.fmt.pix.pixelformat; - peasycap->format_offset = peasycap_format - easycap_format; - - - for (k = 0; k < INPUT_MANY; k++) { - if (!peasycap->inputset[k].format_offset_ok) { - peasycap->inputset[k].format_offset = - peasycap->format_offset; - } - } - if ((0 <= peasycap->input) && (INPUT_MANY > peasycap->input)) { - peasycap->inputset[peasycap->input].format_offset = - peasycap->format_offset; - peasycap->inputset[peasycap->input].format_offset_ok = 1; - } else - JOM(8, "%i=peasycap->input\n", peasycap->input); - - - - peasycap->bytesperpixel = (0x00E0 & peasycap_format->mask) >> 5 ; - if (0x0100 & peasycap_format->mask) - peasycap->byteswaporder = true; - else - peasycap->byteswaporder = false; - if (0x0200 & peasycap_format->mask) - peasycap->skip = 5; - else - peasycap->skip = 0; - if (0x0800 & peasycap_format->mask) - peasycap->decimatepixel = true; - else - peasycap->decimatepixel = false; - if (0x1000 & peasycap_format->mask) - peasycap->offerfields = true; - else - peasycap->offerfields = false; - if (peasycap->decimatepixel) - multiplier = 2; - else - multiplier = 1; - peasycap->videofieldamount = - multiplier * peasycap->width * multiplier * peasycap->height; - peasycap->frame_buffer_used = - peasycap->bytesperpixel * peasycap->width * peasycap->height; - if (peasycap->video_isoc_streaming) { - resubmit = true; - easycap_video_kill_urbs(peasycap); - } else - resubmit = false; -/*---------------------------------------------------------------------------*/ -/* - * PAL - */ -/*---------------------------------------------------------------------------*/ - if (0 == (0x01 & peasycap_format->mask)) { - if (((720 == peasycap_format->v4l2_format.fmt.pix.width) && - (576 == peasycap_format->v4l2_format.fmt.pix.height)) || - ((360 == peasycap_format->v4l2_format.fmt.pix.width) && - (288 == peasycap_format->v4l2_format.fmt.pix.height))) { - if (set_resolution(p, 0x0000, 0x0001, 0x05A0, 0x0121)) { - SAM("ERROR: set_resolution() failed\n"); - return -EINVAL; - } - } else if ((704 == peasycap_format->v4l2_format.fmt.pix.width) && - (576 == peasycap_format->v4l2_format.fmt.pix.height)) { - if (set_resolution(p, 0x0004, 0x0001, 0x0584, 0x0121)) { - SAM("ERROR: set_resolution() failed\n"); - return -EINVAL; - } - } else if (((640 == peasycap_format->v4l2_format.fmt.pix.width) && - (480 == peasycap_format->v4l2_format.fmt.pix.height)) || - ((320 == peasycap_format->v4l2_format.fmt.pix.width) && - (240 == peasycap_format->v4l2_format.fmt.pix.height))) { - if (set_resolution(p, 0x0014, 0x0020, 0x0514, 0x0110)) { - SAM("ERROR: set_resolution() failed\n"); - return -EINVAL; - } - } else { - SAM("MISTAKE: bad format, cannot set resolution\n"); - return -EINVAL; - } -/*---------------------------------------------------------------------------*/ -/* - * NTSC - */ -/*---------------------------------------------------------------------------*/ - } else { - if (((720 == peasycap_format->v4l2_format.fmt.pix.width) && - (480 == peasycap_format->v4l2_format.fmt.pix.height)) || - ((360 == peasycap_format->v4l2_format.fmt.pix.width) && - (240 == peasycap_format->v4l2_format.fmt.pix.height))) { - if (set_resolution(p, 0x0000, 0x0003, 0x05A0, 0x00F3)) { - SAM("ERROR: set_resolution() failed\n"); - return -EINVAL; - } - } else if (((640 == peasycap_format->v4l2_format.fmt.pix.width) && - (480 == peasycap_format->v4l2_format.fmt.pix.height)) || - ((320 == peasycap_format->v4l2_format.fmt.pix.width) && - (240 == peasycap_format->v4l2_format.fmt.pix.height))) { - if (set_resolution(p, 0x0014, 0x0003, 0x0514, 0x00F3)) { - SAM("ERROR: set_resolution() failed\n"); - return -EINVAL; - } - } else { - SAM("MISTAKE: bad format, cannot set resolution\n"); - return -EINVAL; - } - } -/*---------------------------------------------------------------------------*/ - if (resubmit) - easycap_video_submit_urbs(peasycap); - - return peasycap_best_format - easycap_format; -} -/*****************************************************************************/ -int adjust_brightness(struct easycap *peasycap, int value) -{ - unsigned int mood; - int i1, k; - - if (!peasycap) { - SAY("ERROR: peasycap is NULL\n"); - return -EFAULT; - } - if (!peasycap->pusb_device) { - SAM("ERROR: peasycap->pusb_device is NULL\n"); - return -EFAULT; - } - i1 = 0; - while (0xFFFFFFFF != easycap_control[i1].id) { - if (V4L2_CID_BRIGHTNESS == easycap_control[i1].id) { - if ((easycap_control[i1].minimum > value) || - (easycap_control[i1].maximum < value)) - value = easycap_control[i1].default_value; - - if ((easycap_control[i1].minimum <= peasycap->brightness) && - (easycap_control[i1].maximum >= peasycap->brightness)) { - if (peasycap->brightness == value) { - SAM("unchanged brightness at 0x%02X\n", - value); - return 0; - } - } - peasycap->brightness = value; - for (k = 0; k < INPUT_MANY; k++) { - if (!peasycap->inputset[k].brightness_ok) - peasycap->inputset[k].brightness = - peasycap->brightness; - } - if ((0 <= peasycap->input) && (INPUT_MANY > peasycap->input)) { - peasycap->inputset[peasycap->input].brightness = - peasycap->brightness; - peasycap->inputset[peasycap->input].brightness_ok = 1; - } else - JOM(8, "%i=peasycap->input\n", peasycap->input); - - mood = 0x00FF & (unsigned int)peasycap->brightness; - if (write_saa(peasycap->pusb_device, 0x0A, mood)) { - SAM("WARNING: failed to adjust brightness " - "to 0x%02X\n", mood); - return -ENOENT; - } - SAM("adjusting brightness to 0x%02X\n", mood); - return 0; - } - i1++; - } - SAM("WARNING: failed to adjust brightness: control not found\n"); - return -ENOENT; -} -/*****************************************************************************/ -int adjust_contrast(struct easycap *peasycap, int value) -{ - unsigned int mood; - int i1, k; - - if (!peasycap) { - SAY("ERROR: peasycap is NULL\n"); - return -EFAULT; - } - if (!peasycap->pusb_device) { - SAM("ERROR: peasycap->pusb_device is NULL\n"); - return -EFAULT; - } - i1 = 0; - while (0xFFFFFFFF != easycap_control[i1].id) { - if (V4L2_CID_CONTRAST == easycap_control[i1].id) { - if ((easycap_control[i1].minimum > value) || - (easycap_control[i1].maximum < value)) - value = easycap_control[i1].default_value; - - - if ((easycap_control[i1].minimum <= peasycap->contrast) && - (easycap_control[i1].maximum >= peasycap->contrast)) { - if (peasycap->contrast == value) { - SAM("unchanged contrast at 0x%02X\n", value); - return 0; - } - } - peasycap->contrast = value; - for (k = 0; k < INPUT_MANY; k++) { - if (!peasycap->inputset[k].contrast_ok) - peasycap->inputset[k].contrast = peasycap->contrast; - } - - if ((0 <= peasycap->input) && (INPUT_MANY > peasycap->input)) { - peasycap->inputset[peasycap->input].contrast = - peasycap->contrast; - peasycap->inputset[peasycap->input].contrast_ok = 1; - } else - JOM(8, "%i=peasycap->input\n", peasycap->input); - - mood = 0x00FF & (unsigned int) (peasycap->contrast - 128); - if (write_saa(peasycap->pusb_device, 0x0B, mood)) { - SAM("WARNING: failed to adjust contrast to " - "0x%02X\n", mood); - return -ENOENT; - } - SAM("adjusting contrast to 0x%02X\n", mood); - return 0; - } - i1++; - } - SAM("WARNING: failed to adjust contrast: control not found\n"); - return -ENOENT; -} -/*****************************************************************************/ -int adjust_saturation(struct easycap *peasycap, int value) -{ - unsigned int mood; - int i1, k; - - if (!peasycap) { - SAY("ERROR: peasycap is NULL\n"); - return -EFAULT; - } - if (!peasycap->pusb_device) { - SAM("ERROR: peasycap->pusb_device is NULL\n"); - return -EFAULT; - } - i1 = 0; - while (0xFFFFFFFF != easycap_control[i1].id) { - if (V4L2_CID_SATURATION == easycap_control[i1].id) { - if ((easycap_control[i1].minimum > value) || - (easycap_control[i1].maximum < value)) - value = easycap_control[i1].default_value; - - - if ((easycap_control[i1].minimum <= peasycap->saturation) && - (easycap_control[i1].maximum >= peasycap->saturation)) { - if (peasycap->saturation == value) { - SAM("unchanged saturation at 0x%02X\n", - value); - return 0; - } - } - peasycap->saturation = value; - for (k = 0; k < INPUT_MANY; k++) { - if (!peasycap->inputset[k].saturation_ok) - peasycap->inputset[k].saturation = - peasycap->saturation; - } - if ((0 <= peasycap->input) && (INPUT_MANY > peasycap->input)) { - peasycap->inputset[peasycap->input].saturation = - peasycap->saturation; - peasycap->inputset[peasycap->input].saturation_ok = 1; - } else - JOM(8, "%i=peasycap->input\n", peasycap->input); - mood = 0x00FF & (unsigned int) (peasycap->saturation - 128); - if (write_saa(peasycap->pusb_device, 0x0C, mood)) { - SAM("WARNING: failed to adjust saturation to " - "0x%02X\n", mood); - return -ENOENT; - } - SAM("adjusting saturation to 0x%02X\n", mood); - return 0; - break; - } - i1++; - } - SAM("WARNING: failed to adjust saturation: control not found\n"); - return -ENOENT; -} -/*****************************************************************************/ -int adjust_hue(struct easycap *peasycap, int value) -{ - unsigned int mood; - int i1, i2, k; - - if (!peasycap) { - SAY("ERROR: peasycap is NULL\n"); - return -EFAULT; - } - if (!peasycap->pusb_device) { - SAM("ERROR: peasycap->pusb_device is NULL\n"); - return -EFAULT; - } - i1 = 0; - while (0xFFFFFFFF != easycap_control[i1].id) { - if (V4L2_CID_HUE == easycap_control[i1].id) { - if ((easycap_control[i1].minimum > value) || - (easycap_control[i1].maximum < value)) - value = easycap_control[i1].default_value; - - if ((easycap_control[i1].minimum <= peasycap->hue) && - (easycap_control[i1].maximum >= peasycap->hue)) { - if (peasycap->hue == value) { - SAM("unchanged hue at 0x%02X\n", value); - return 0; - } - } - peasycap->hue = value; - for (k = 0; k < INPUT_MANY; k++) { - if (!peasycap->inputset[k].hue_ok) - peasycap->inputset[k].hue = peasycap->hue; - } - if (0 <= peasycap->input && INPUT_MANY > peasycap->input) { - peasycap->inputset[peasycap->input].hue = peasycap->hue; - peasycap->inputset[peasycap->input].hue_ok = 1; - } else - JOM(8, "%i=peasycap->input\n", peasycap->input); - i2 = peasycap->hue - 128; - mood = 0x00FF & ((int) i2); - if (write_saa(peasycap->pusb_device, 0x0D, mood)) { - SAM("WARNING: failed to adjust hue to 0x%02X\n", mood); - return -ENOENT; - } - SAM("adjusting hue to 0x%02X\n", mood); - return 0; - break; - } - i1++; - } - SAM("WARNING: failed to adjust hue: control not found\n"); - return -ENOENT; -} -/*****************************************************************************/ -static int adjust_volume(struct easycap *peasycap, int value) -{ - s8 mood; - int i1; - - if (!peasycap) { - SAY("ERROR: peasycap is NULL\n"); - return -EFAULT; - } - if (!peasycap->pusb_device) { - SAM("ERROR: peasycap->pusb_device is NULL\n"); - return -EFAULT; - } - i1 = 0; - while (0xFFFFFFFF != easycap_control[i1].id) { - if (V4L2_CID_AUDIO_VOLUME == easycap_control[i1].id) { - if ((easycap_control[i1].minimum > value) || - (easycap_control[i1].maximum < value)) - value = easycap_control[i1].default_value; - - if ((easycap_control[i1].minimum <= peasycap->volume) && - (easycap_control[i1].maximum >= peasycap->volume)) { - if (peasycap->volume == value) { - SAM("unchanged volume at 0x%02X\n", value); - return 0; - } - } - peasycap->volume = value; - mood = (16 > peasycap->volume) ? 16 : - ((31 < peasycap->volume) ? 31 : - (s8) peasycap->volume); - if (!easycap_audio_gainset(peasycap->pusb_device, mood)) { - SAM("WARNING: failed to adjust volume to " - "0x%2X\n", mood); - return -ENOENT; - } - SAM("adjusting volume to 0x%02X\n", mood); - return 0; - } - i1++; - } - SAM("WARNING: failed to adjust volume: control not found\n"); - return -ENOENT; -} -/*****************************************************************************/ -/*---------------------------------------------------------------------------*/ -/* - * AN ALTERNATIVE METHOD OF MUTING MIGHT SEEM TO BE: - * usb_set_interface(peasycap->pusb_device, - * peasycap->audio_interface, - * peasycap->audio_altsetting_off); - * HOWEVER, AFTER THIS COMMAND IS ISSUED ALL SUBSEQUENT URBS RECEIVE STATUS - * -ESHUTDOWN. THE HANDLER ROUTINE easyxxx_complete() DECLINES TO RESUBMIT - * THE URB AND THE PIPELINE COLLAPSES IRRETRIEVABLY. BEWARE. - */ -/*---------------------------------------------------------------------------*/ -static int adjust_mute(struct easycap *peasycap, int value) -{ - int i1; - - if (!peasycap) { - SAY("ERROR: peasycap is NULL\n"); - return -EFAULT; - } - if (!peasycap->pusb_device) { - SAM("ERROR: peasycap->pusb_device is NULL\n"); - return -EFAULT; - } - i1 = 0; - while (0xFFFFFFFF != easycap_control[i1].id) { - if (V4L2_CID_AUDIO_MUTE == easycap_control[i1].id) { - peasycap->mute = value; - switch (peasycap->mute) { - case 1: { - peasycap->audio_idle = 1; - SAM("adjusting mute: %i=peasycap->audio_idle\n", - peasycap->audio_idle); - return 0; - } - default: { - peasycap->audio_idle = 0; - SAM("adjusting mute: %i=peasycap->audio_idle\n", - peasycap->audio_idle); - return 0; - } - } - break; - } - i1++; - } - SAM("WARNING: failed to adjust mute: control not found\n"); - return -ENOENT; -} -/*---------------------------------------------------------------------------*/ -long easycap_unlocked_ioctl(struct file *file, - unsigned int cmd, unsigned long arg) -{ - struct easycap *peasycap; - struct usb_device *p; - int kd; - - if (!file) { - SAY("ERROR: file is NULL\n"); - return -ERESTARTSYS; - } - peasycap = file->private_data; - if (!peasycap) { - SAY("ERROR: peasycap is NULL\n"); - return -1; - } - p = peasycap->pusb_device; - if (!p) { - SAM("ERROR: peasycap->pusb_device is NULL\n"); - return -EFAULT; - } - kd = easycap_isdongle(peasycap); - if (0 <= kd && DONGLE_MANY > kd) { - if (mutex_lock_interruptible(&easycapdc60_dongle[kd].mutex_video)) { - SAY("ERROR: cannot lock " - "easycapdc60_dongle[%i].mutex_video\n", kd); - return -ERESTARTSYS; - } - JOM(4, "locked easycapdc60_dongle[%i].mutex_video\n", kd); -/*---------------------------------------------------------------------------*/ -/* - * MEANWHILE, easycap_usb_disconnect() MAY HAVE FREED POINTER peasycap, - * IN WHICH CASE A REPEAT CALL TO isdongle() WILL FAIL. - * IF NECESSARY, BAIL OUT. - */ -/*---------------------------------------------------------------------------*/ - if (kd != easycap_isdongle(peasycap)) - return -ERESTARTSYS; - if (!file) { - SAY("ERROR: file is NULL\n"); - mutex_unlock(&easycapdc60_dongle[kd].mutex_video); - return -ERESTARTSYS; - } - peasycap = file->private_data; - if (!peasycap) { - SAY("ERROR: peasycap is NULL\n"); - mutex_unlock(&easycapdc60_dongle[kd].mutex_video); - return -ERESTARTSYS; - } - if (!peasycap->pusb_device) { - SAM("ERROR: peasycap->pusb_device is NULL\n"); - mutex_unlock(&easycapdc60_dongle[kd].mutex_video); - return -ERESTARTSYS; - } - } else { -/*---------------------------------------------------------------------------*/ -/* - * IF easycap_usb_disconnect() HAS ALREADY FREED POINTER peasycap BEFORE THE - * ATTEMPT TO ACQUIRE THE SEMAPHORE, isdongle() WILL HAVE FAILED. BAIL OUT. - */ -/*---------------------------------------------------------------------------*/ - return -ERESTARTSYS; - } -/*---------------------------------------------------------------------------*/ - switch (cmd) { - case VIDIOC_QUERYCAP: { - struct v4l2_capability v4l2_capability; - char version[16], *p1, *p2; - int i, rc, k[3]; - long lng; - - JOM(8, "VIDIOC_QUERYCAP\n"); - - if (16 <= strlen(EASYCAP_DRIVER_VERSION)) { - SAM("ERROR: bad driver version string\n"); - mutex_unlock(&easycapdc60_dongle[kd].mutex_video); - return -EINVAL; - } - strcpy(&version[0], EASYCAP_DRIVER_VERSION); - for (i = 0; i < 3; i++) - k[i] = 0; - p2 = &version[0]; - i = 0; - while (*p2) { - p1 = p2; - while (*p2 && ('.' != *p2)) - p2++; - if (*p2) - *p2++ = 0; - if (3 > i) { - rc = (int) strict_strtol(p1, 10, &lng); - if (rc) { - SAM("ERROR: %i=strict_strtol(%s,.,,)\n", - rc, p1); - mutex_unlock(&easycapdc60_dongle[kd].mutex_video); - return -EINVAL; - } - k[i] = (int)lng; - } - i++; - } - - memset(&v4l2_capability, 0, sizeof(struct v4l2_capability)); - strlcpy(&v4l2_capability.driver[0], - "easycap", sizeof(v4l2_capability.driver)); - - v4l2_capability.capabilities = V4L2_CAP_VIDEO_CAPTURE | - V4L2_CAP_STREAMING | - V4L2_CAP_AUDIO | - V4L2_CAP_READWRITE; - - v4l2_capability.version = KERNEL_VERSION(k[0], k[1], k[2]); - JOM(8, "v4l2_capability.version=(%i,%i,%i)\n", k[0], k[1], k[2]); - - strlcpy(&v4l2_capability.card[0], - "EasyCAP DC60", sizeof(v4l2_capability.card)); - - if (usb_make_path(peasycap->pusb_device, - &v4l2_capability.bus_info[0], - sizeof(v4l2_capability.bus_info)) < 0) { - - strlcpy(&v4l2_capability.bus_info[0], "EasyCAP bus_info", - sizeof(v4l2_capability.bus_info)); - JOM(8, "%s=v4l2_capability.bus_info\n", - &v4l2_capability.bus_info[0]); - } - if (copy_to_user((void __user *)arg, &v4l2_capability, - sizeof(struct v4l2_capability))) { - mutex_unlock(&easycapdc60_dongle[kd].mutex_video); - return -EFAULT; - } - break; - } -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - case VIDIOC_ENUMINPUT: { - struct v4l2_input v4l2_input; - u32 index; - - JOM(8, "VIDIOC_ENUMINPUT\n"); - - if (copy_from_user(&v4l2_input, (void __user *)arg, - sizeof(struct v4l2_input))) { - mutex_unlock(&easycapdc60_dongle[kd].mutex_video); - return -EFAULT; - } - - index = v4l2_input.index; - memset(&v4l2_input, 0, sizeof(struct v4l2_input)); - - switch (index) { - case 0: { - v4l2_input.index = index; - strcpy(&v4l2_input.name[0], "CVBS0"); - v4l2_input.type = V4L2_INPUT_TYPE_CAMERA; - v4l2_input.audioset = 0x01; - v4l2_input.tuner = 0; - v4l2_input.std = V4L2_STD_PAL | - V4L2_STD_SECAM | - V4L2_STD_NTSC ; - v4l2_input.status = 0; - JOM(8, "%i=index: %s\n", index, &v4l2_input.name[0]); - break; - } - case 1: { - v4l2_input.index = index; - strcpy(&v4l2_input.name[0], "CVBS1"); - v4l2_input.type = V4L2_INPUT_TYPE_CAMERA; - v4l2_input.audioset = 0x01; - v4l2_input.tuner = 0; - v4l2_input.std = V4L2_STD_PAL | V4L2_STD_SECAM | - V4L2_STD_NTSC; - v4l2_input.status = 0; - JOM(8, "%i=index: %s\n", index, &v4l2_input.name[0]); - break; - } - case 2: { - v4l2_input.index = index; - strcpy(&v4l2_input.name[0], "CVBS2"); - v4l2_input.type = V4L2_INPUT_TYPE_CAMERA; - v4l2_input.audioset = 0x01; - v4l2_input.tuner = 0; - v4l2_input.std = V4L2_STD_PAL | V4L2_STD_SECAM | - V4L2_STD_NTSC ; - v4l2_input.status = 0; - JOM(8, "%i=index: %s\n", index, &v4l2_input.name[0]); - break; - } - case 3: { - v4l2_input.index = index; - strcpy(&v4l2_input.name[0], "CVBS3"); - v4l2_input.type = V4L2_INPUT_TYPE_CAMERA; - v4l2_input.audioset = 0x01; - v4l2_input.tuner = 0; - v4l2_input.std = V4L2_STD_PAL | V4L2_STD_SECAM | - V4L2_STD_NTSC ; - v4l2_input.status = 0; - JOM(8, "%i=index: %s\n", index, &v4l2_input.name[0]); - break; - } - case 4: { - v4l2_input.index = index; - strcpy(&v4l2_input.name[0], "CVBS4"); - v4l2_input.type = V4L2_INPUT_TYPE_CAMERA; - v4l2_input.audioset = 0x01; - v4l2_input.tuner = 0; - v4l2_input.std = V4L2_STD_PAL | V4L2_STD_SECAM | - V4L2_STD_NTSC ; - v4l2_input.status = 0; - JOM(8, "%i=index: %s\n", index, &v4l2_input.name[0]); - break; - } - case 5: { - v4l2_input.index = index; - strcpy(&v4l2_input.name[0], "S-VIDEO"); - v4l2_input.type = V4L2_INPUT_TYPE_CAMERA; - v4l2_input.audioset = 0x01; - v4l2_input.tuner = 0; - v4l2_input.std = V4L2_STD_PAL | V4L2_STD_SECAM | - V4L2_STD_NTSC ; - v4l2_input.status = 0; - JOM(8, "%i=index: %s\n", index, &v4l2_input.name[0]); - break; - } - default: { - JOM(8, "%i=index: exhausts inputs\n", index); - mutex_unlock(&easycapdc60_dongle[kd].mutex_video); - return -EINVAL; - } - } - - if (copy_to_user((void __user *)arg, &v4l2_input, - sizeof(struct v4l2_input))) { - mutex_unlock(&easycapdc60_dongle[kd].mutex_video); - return -EFAULT; - } - break; - } -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - case VIDIOC_G_INPUT: { - u32 index; - - JOM(8, "VIDIOC_G_INPUT\n"); - index = (u32)peasycap->input; - JOM(8, "user is told: %i\n", index); - if (copy_to_user((void __user *)arg, &index, sizeof(u32))) { - mutex_unlock(&easycapdc60_dongle[kd].mutex_video); - return -EFAULT; - } - break; - } -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - case VIDIOC_S_INPUT: - { - u32 index; - int rc; - - JOM(8, "VIDIOC_S_INPUT\n"); - - if (0 != copy_from_user(&index, (void __user *)arg, sizeof(u32))) { - mutex_unlock(&easycapdc60_dongle[kd].mutex_video); - return -EFAULT; - } - - JOM(8, "user requests input %i\n", index); - - if ((int)index == peasycap->input) { - SAM("requested input already in effect\n"); - break; - } - - if ((0 > index) || (INPUT_MANY <= index)) { - JOM(8, "ERROR: bad requested input: %i\n", index); - mutex_unlock(&easycapdc60_dongle[kd].mutex_video); - return -EINVAL; - } - - rc = easycap_newinput(peasycap, (int)index); - if (0 == rc) { - JOM(8, "newinput(.,%i) OK\n", (int)index); - } else { - SAM("ERROR: newinput(.,%i) returned %i\n", (int)index, rc); - mutex_unlock(&easycapdc60_dongle[kd].mutex_video); - return -EFAULT; - } - break; - } -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - case VIDIOC_ENUMAUDIO: { - JOM(8, "VIDIOC_ENUMAUDIO\n"); - mutex_unlock(&easycapdc60_dongle[kd].mutex_video); - return -EINVAL; - } -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - case VIDIOC_ENUMAUDOUT: { - struct v4l2_audioout v4l2_audioout; - - JOM(8, "VIDIOC_ENUMAUDOUT\n"); - - if (copy_from_user(&v4l2_audioout, (void __user *)arg, - sizeof(struct v4l2_audioout))) { - mutex_unlock(&easycapdc60_dongle[kd].mutex_video); - return -EFAULT; - } - - if (0 != v4l2_audioout.index) { - mutex_unlock(&easycapdc60_dongle[kd].mutex_video); - return -EINVAL; - } - memset(&v4l2_audioout, 0, sizeof(struct v4l2_audioout)); - v4l2_audioout.index = 0; - strcpy(&v4l2_audioout.name[0], "Soundtrack"); - - if (copy_to_user((void __user *)arg, &v4l2_audioout, - sizeof(struct v4l2_audioout))) { - mutex_unlock(&easycapdc60_dongle[kd].mutex_video); - return -EFAULT; - } - break; - } -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - case VIDIOC_QUERYCTRL: { - int i1; - struct v4l2_queryctrl v4l2_queryctrl; - - JOM(8, "VIDIOC_QUERYCTRL\n"); - - if (0 != copy_from_user(&v4l2_queryctrl, (void __user *)arg, - sizeof(struct v4l2_queryctrl))) { - mutex_unlock(&easycapdc60_dongle[kd].mutex_video); - return -EFAULT; - } - - i1 = 0; - while (0xFFFFFFFF != easycap_control[i1].id) { - if (easycap_control[i1].id == v4l2_queryctrl.id) { - JOM(8, "VIDIOC_QUERYCTRL %s=easycap_control[%i]" - ".name\n", &easycap_control[i1].name[0], i1); - memcpy(&v4l2_queryctrl, &easycap_control[i1], - sizeof(struct v4l2_queryctrl)); - break; - } - i1++; - } - if (0xFFFFFFFF == easycap_control[i1].id) { - JOM(8, "%i=index: exhausts controls\n", i1); - mutex_unlock(&easycapdc60_dongle[kd].mutex_video); - return -EINVAL; - } - if (copy_to_user((void __user *)arg, &v4l2_queryctrl, - sizeof(struct v4l2_queryctrl))) { - mutex_unlock(&easycapdc60_dongle[kd].mutex_video); - return -EFAULT; - } - break; - } -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - case VIDIOC_QUERYMENU: { - JOM(8, "VIDIOC_QUERYMENU unsupported\n"); - mutex_unlock(&easycapdc60_dongle[kd].mutex_video); - return -EINVAL; - } -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - case VIDIOC_G_CTRL: { - struct v4l2_control *pv4l2_control; - - JOM(8, "VIDIOC_G_CTRL\n"); - pv4l2_control = memdup_user((void __user *)arg, - sizeof(struct v4l2_control)); - if (IS_ERR(pv4l2_control)) { - SAM("ERROR: copy from user failed\n"); - mutex_unlock(&easycapdc60_dongle[kd].mutex_video); - return PTR_ERR(pv4l2_control); - } - - switch (pv4l2_control->id) { - case V4L2_CID_BRIGHTNESS: { - pv4l2_control->value = peasycap->brightness; - JOM(8, "user enquires brightness: %i\n", pv4l2_control->value); - break; - } - case V4L2_CID_CONTRAST: { - pv4l2_control->value = peasycap->contrast; - JOM(8, "user enquires contrast: %i\n", pv4l2_control->value); - break; - } - case V4L2_CID_SATURATION: { - pv4l2_control->value = peasycap->saturation; - JOM(8, "user enquires saturation: %i\n", pv4l2_control->value); - break; - } - case V4L2_CID_HUE: { - pv4l2_control->value = peasycap->hue; - JOM(8, "user enquires hue: %i\n", pv4l2_control->value); - break; - } - case V4L2_CID_AUDIO_VOLUME: { - pv4l2_control->value = peasycap->volume; - JOM(8, "user enquires volume: %i\n", pv4l2_control->value); - break; - } - case V4L2_CID_AUDIO_MUTE: { - if (1 == peasycap->mute) - pv4l2_control->value = true; - else - pv4l2_control->value = false; - JOM(8, "user enquires mute: %i\n", pv4l2_control->value); - break; - } - default: { - SAM("ERROR: unknown V4L2 control: 0x%08X=id\n", - pv4l2_control->id); - kfree(pv4l2_control); - mutex_unlock(&easycapdc60_dongle[kd].mutex_video); - return -EINVAL; - } - } - if (copy_to_user((void __user *)arg, pv4l2_control, - sizeof(struct v4l2_control))) { - kfree(pv4l2_control); - mutex_unlock(&easycapdc60_dongle[kd].mutex_video); - return -EFAULT; - } - kfree(pv4l2_control); - break; - } -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - case VIDIOC_S_CTRL: { - struct v4l2_control v4l2_control; - - JOM(8, "VIDIOC_S_CTRL\n"); - - if (0 != copy_from_user(&v4l2_control, (void __user *)arg, - sizeof(struct v4l2_control))) { - mutex_unlock(&easycapdc60_dongle[kd].mutex_video); - return -EFAULT; - } - - switch (v4l2_control.id) { - case V4L2_CID_BRIGHTNESS: { - JOM(8, "user requests brightness %i\n", v4l2_control.value); - if (0 != adjust_brightness(peasycap, v4l2_control.value)) - ; - break; - } - case V4L2_CID_CONTRAST: { - JOM(8, "user requests contrast %i\n", v4l2_control.value); - if (0 != adjust_contrast(peasycap, v4l2_control.value)) - ; - break; - } - case V4L2_CID_SATURATION: { - JOM(8, "user requests saturation %i\n", v4l2_control.value); - if (0 != adjust_saturation(peasycap, v4l2_control.value)) - ; - break; - } - case V4L2_CID_HUE: { - JOM(8, "user requests hue %i\n", v4l2_control.value); - if (0 != adjust_hue(peasycap, v4l2_control.value)) - ; - break; - } - case V4L2_CID_AUDIO_VOLUME: { - JOM(8, "user requests volume %i\n", v4l2_control.value); - if (0 != adjust_volume(peasycap, v4l2_control.value)) - ; - break; - } - case V4L2_CID_AUDIO_MUTE: { - int mute; - - JOM(8, "user requests mute %i\n", v4l2_control.value); - if (v4l2_control.value) - mute = 1; - else - mute = 0; - - if (0 != adjust_mute(peasycap, mute)) - SAM("WARNING: failed to adjust mute to %i\n", mute); - break; - } - default: { - SAM("ERROR: unknown V4L2 control: 0x%08X=id\n", - v4l2_control.id); - mutex_unlock(&easycapdc60_dongle[kd].mutex_video); - return -EINVAL; - } - } - break; - } -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - case VIDIOC_S_EXT_CTRLS: { - JOM(8, "VIDIOC_S_EXT_CTRLS unsupported\n"); - mutex_unlock(&easycapdc60_dongle[kd].mutex_video); - return -EINVAL; - } -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - case VIDIOC_ENUM_FMT: { - u32 index; - struct v4l2_fmtdesc v4l2_fmtdesc; - - JOM(8, "VIDIOC_ENUM_FMT\n"); - - if (0 != copy_from_user(&v4l2_fmtdesc, (void __user *)arg, - sizeof(struct v4l2_fmtdesc))) { - mutex_unlock(&easycapdc60_dongle[kd].mutex_video); - return -EFAULT; - } - - index = v4l2_fmtdesc.index; - memset(&v4l2_fmtdesc, 0, sizeof(struct v4l2_fmtdesc)); - - v4l2_fmtdesc.index = index; - v4l2_fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - - switch (index) { - case 0: { - v4l2_fmtdesc.flags = 0; - strcpy(&v4l2_fmtdesc.description[0], "uyvy"); - v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_UYVY; - JOM(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]); - break; - } - case 1: { - v4l2_fmtdesc.flags = 0; - strcpy(&v4l2_fmtdesc.description[0], "yuy2"); - v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_YUYV; - JOM(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]); - break; - } - case 2: { - v4l2_fmtdesc.flags = 0; - strcpy(&v4l2_fmtdesc.description[0], "rgb24"); - v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_RGB24; - JOM(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]); - break; - } - case 3: { - v4l2_fmtdesc.flags = 0; - strcpy(&v4l2_fmtdesc.description[0], "rgb32"); - v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_RGB32; - JOM(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]); - break; - } - case 4: { - v4l2_fmtdesc.flags = 0; - strcpy(&v4l2_fmtdesc.description[0], "bgr24"); - v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_BGR24; - JOM(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]); - break; - } - case 5: { - v4l2_fmtdesc.flags = 0; - strcpy(&v4l2_fmtdesc.description[0], "bgr32"); - v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_BGR32; - JOM(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]); - break; - } - default: { - JOM(8, "%i=index: exhausts formats\n", index); - mutex_unlock(&easycapdc60_dongle[kd].mutex_video); - return -EINVAL; - } - } - if (copy_to_user((void __user *)arg, &v4l2_fmtdesc, - sizeof(struct v4l2_fmtdesc))) { - mutex_unlock(&easycapdc60_dongle[kd].mutex_video); - return -EFAULT; - } - break; - } -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ -/* - * THE RESPONSE TO VIDIOC_ENUM_FRAMESIZES MUST BE CONDITIONED ON THE - * THE CURRENT STANDARD, BECAUSE THAT IS WHAT gstreamer EXPECTS. BEWARE. - */ -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - case VIDIOC_ENUM_FRAMESIZES: { - u32 index; - struct v4l2_frmsizeenum v4l2_frmsizeenum; - - JOM(8, "VIDIOC_ENUM_FRAMESIZES\n"); - - if (0 != copy_from_user(&v4l2_frmsizeenum, (void __user *)arg, - sizeof(struct v4l2_frmsizeenum))) { - mutex_unlock(&easycapdc60_dongle[kd].mutex_video); - return -EFAULT; - } - - index = v4l2_frmsizeenum.index; - - v4l2_frmsizeenum.type = (u32) V4L2_FRMSIZE_TYPE_DISCRETE; - - if (peasycap->ntsc) { - switch (index) { - case 0: { - v4l2_frmsizeenum.discrete.width = 640; - v4l2_frmsizeenum.discrete.height = 480; - JOM(8, "%i=index: %ix%i\n", index, - (int)(v4l2_frmsizeenum. - discrete.width), - (int)(v4l2_frmsizeenum. - discrete.height)); - break; - } - case 1: { - v4l2_frmsizeenum.discrete.width = 320; - v4l2_frmsizeenum.discrete.height = 240; - JOM(8, "%i=index: %ix%i\n", index, - (int)(v4l2_frmsizeenum. - discrete.width), - (int)(v4l2_frmsizeenum. - discrete.height)); - break; - } - case 2: { - v4l2_frmsizeenum.discrete.width = 720; - v4l2_frmsizeenum.discrete.height = 480; - JOM(8, "%i=index: %ix%i\n", index, - (int)(v4l2_frmsizeenum. - discrete.width), - (int)(v4l2_frmsizeenum. - discrete.height)); - break; - } - case 3: { - v4l2_frmsizeenum.discrete.width = 360; - v4l2_frmsizeenum.discrete.height = 240; - JOM(8, "%i=index: %ix%i\n", index, - (int)(v4l2_frmsizeenum. - discrete.width), - (int)(v4l2_frmsizeenum. - discrete.height)); - break; - } - default: { - JOM(8, "%i=index: exhausts framesizes\n", index); - mutex_unlock(&easycapdc60_dongle[kd].mutex_video); - return -EINVAL; - } - } - } else { - switch (index) { - case 0: { - v4l2_frmsizeenum.discrete.width = 640; - v4l2_frmsizeenum.discrete.height = 480; - JOM(8, "%i=index: %ix%i\n", index, - (int)(v4l2_frmsizeenum. - discrete.width), - (int)(v4l2_frmsizeenum. - discrete.height)); - break; - } - case 1: { - v4l2_frmsizeenum.discrete.width = 320; - v4l2_frmsizeenum.discrete.height = 240; - JOM(8, "%i=index: %ix%i\n", index, - (int)(v4l2_frmsizeenum. - discrete.width), - (int)(v4l2_frmsizeenum. - discrete.height)); - break; - } - case 2: { - v4l2_frmsizeenum.discrete.width = 704; - v4l2_frmsizeenum.discrete.height = 576; - JOM(8, "%i=index: %ix%i\n", index, - (int)(v4l2_frmsizeenum. - discrete.width), - (int)(v4l2_frmsizeenum. - discrete.height)); - break; - } - case 3: { - v4l2_frmsizeenum.discrete.width = 720; - v4l2_frmsizeenum.discrete.height = 576; - JOM(8, "%i=index: %ix%i\n", index, - (int)(v4l2_frmsizeenum. - discrete.width), - (int)(v4l2_frmsizeenum. - discrete.height)); - break; - } - case 4: { - v4l2_frmsizeenum.discrete.width = 360; - v4l2_frmsizeenum.discrete.height = 288; - JOM(8, "%i=index: %ix%i\n", index, - (int)(v4l2_frmsizeenum. - discrete.width), - (int)(v4l2_frmsizeenum. - discrete.height)); - break; - } - default: { - JOM(8, "%i=index: exhausts framesizes\n", index); - mutex_unlock(&easycapdc60_dongle[kd].mutex_video); - return -EINVAL; - } - } - } - if (copy_to_user((void __user *)arg, &v4l2_frmsizeenum, - sizeof(struct v4l2_frmsizeenum))) { - mutex_unlock(&easycapdc60_dongle[kd].mutex_video); - return -EFAULT; - } - break; - } -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ -/* - * THE RESPONSE TO VIDIOC_ENUM_FRAMEINTERVALS MUST BE CONDITIONED ON THE - * THE CURRENT STANDARD, BECAUSE THAT IS WHAT gstreamer EXPECTS. BEWARE. - */ -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - case VIDIOC_ENUM_FRAMEINTERVALS: { - u32 index; - int denominator; - struct v4l2_frmivalenum v4l2_frmivalenum; - - JOM(8, "VIDIOC_ENUM_FRAMEINTERVALS\n"); - - if (peasycap->fps) - denominator = peasycap->fps; - else { - if (peasycap->ntsc) - denominator = 30; - else - denominator = 25; - } - - if (0 != copy_from_user(&v4l2_frmivalenum, (void __user *)arg, - sizeof(struct v4l2_frmivalenum))) { - mutex_unlock(&easycapdc60_dongle[kd].mutex_video); - return -EFAULT; - } - - index = v4l2_frmivalenum.index; - - v4l2_frmivalenum.type = (u32) V4L2_FRMIVAL_TYPE_DISCRETE; - - switch (index) { - case 0: { - v4l2_frmivalenum.discrete.numerator = 1; - v4l2_frmivalenum.discrete.denominator = denominator; - JOM(8, "%i=index: %i/%i\n", index, - (int)(v4l2_frmivalenum.discrete.numerator), - (int)(v4l2_frmivalenum.discrete.denominator)); - break; - } - case 1: { - v4l2_frmivalenum.discrete.numerator = 1; - v4l2_frmivalenum.discrete.denominator = denominator/5; - JOM(8, "%i=index: %i/%i\n", index, - (int)(v4l2_frmivalenum.discrete.numerator), - (int)(v4l2_frmivalenum.discrete.denominator)); - break; - } - default: { - JOM(8, "%i=index: exhausts frameintervals\n", index); - mutex_unlock(&easycapdc60_dongle[kd].mutex_video); - return -EINVAL; - } - } - if (copy_to_user((void __user *)arg, &v4l2_frmivalenum, - sizeof(struct v4l2_frmivalenum))) { - mutex_unlock(&easycapdc60_dongle[kd].mutex_video); - return -EFAULT; - } - break; - } -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - case VIDIOC_G_FMT: { - struct v4l2_format *pv4l2_format; - struct v4l2_pix_format *pv4l2_pix_format; - - JOM(8, "VIDIOC_G_FMT\n"); - pv4l2_format = kzalloc(sizeof(struct v4l2_format), GFP_KERNEL); - if (!pv4l2_format) { - SAM("ERROR: out of memory\n"); - mutex_unlock(&easycapdc60_dongle[kd].mutex_video); - return -ENOMEM; - } - pv4l2_pix_format = kzalloc(sizeof(struct v4l2_pix_format), GFP_KERNEL); - if (!pv4l2_pix_format) { - SAM("ERROR: out of memory\n"); - kfree(pv4l2_format); - mutex_unlock(&easycapdc60_dongle[kd].mutex_video); - return -ENOMEM; - } - if (0 != copy_from_user(pv4l2_format, (void __user *)arg, - sizeof(struct v4l2_format))) { - kfree(pv4l2_format); - kfree(pv4l2_pix_format); - mutex_unlock(&easycapdc60_dongle[kd].mutex_video); - return -EFAULT; - } - - if (pv4l2_format->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { - kfree(pv4l2_format); - kfree(pv4l2_pix_format); - mutex_unlock(&easycapdc60_dongle[kd].mutex_video); - return -EINVAL; - } - - memset(pv4l2_pix_format, 0, sizeof(struct v4l2_pix_format)); - pv4l2_format->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - memcpy(&pv4l2_format->fmt.pix, - &easycap_format[peasycap->format_offset] - .v4l2_format.fmt.pix, sizeof(struct v4l2_pix_format)); - JOM(8, "user is told: %s\n", - &easycap_format[peasycap->format_offset].name[0]); - - if (copy_to_user((void __user *)arg, pv4l2_format, - sizeof(struct v4l2_format))) { - kfree(pv4l2_format); - kfree(pv4l2_pix_format); - mutex_unlock(&easycapdc60_dongle[kd].mutex_video); - return -EFAULT; - } - kfree(pv4l2_format); - kfree(pv4l2_pix_format); - break; - } -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - case VIDIOC_TRY_FMT: - case VIDIOC_S_FMT: { - struct v4l2_format v4l2_format; - struct v4l2_pix_format v4l2_pix_format; - bool try; - int best_format; - - if (VIDIOC_TRY_FMT == cmd) { - JOM(8, "VIDIOC_TRY_FMT\n"); - try = true; - } else { - JOM(8, "VIDIOC_S_FMT\n"); - try = false; - } - - if (0 != copy_from_user(&v4l2_format, (void __user *)arg, - sizeof(struct v4l2_format))) { - mutex_unlock(&easycapdc60_dongle[kd].mutex_video); - return -EFAULT; - } - - best_format = adjust_format(peasycap, - v4l2_format.fmt.pix.width, - v4l2_format.fmt.pix.height, - v4l2_format.fmt.pix.pixelformat, - v4l2_format.fmt.pix.field, - try); - if (0 > best_format) { - if (-EBUSY == best_format) { - mutex_unlock(&easycapdc60_dongle[kd].mutex_video); - return -EBUSY; - } - JOM(8, "WARNING: adjust_format() returned %i\n", best_format); - mutex_unlock(&easycapdc60_dongle[kd].mutex_video); - return -ENOENT; - } -/*...........................................................................*/ - memset(&v4l2_pix_format, 0, sizeof(struct v4l2_pix_format)); - v4l2_format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - - memcpy(&(v4l2_format.fmt.pix), - &(easycap_format[best_format].v4l2_format.fmt.pix), - sizeof(v4l2_pix_format)); - JOM(8, "user is told: %s\n", &easycap_format[best_format].name[0]); - - if (copy_to_user((void __user *)arg, &v4l2_format, - sizeof(struct v4l2_format))) { - mutex_unlock(&easycapdc60_dongle[kd].mutex_video); - return -EFAULT; - } - break; - } -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - case VIDIOC_CROPCAP: { - struct v4l2_cropcap v4l2_cropcap; - - JOM(8, "VIDIOC_CROPCAP\n"); - - if (0 != copy_from_user(&v4l2_cropcap, (void __user *)arg, - sizeof(struct v4l2_cropcap))) { - mutex_unlock(&easycapdc60_dongle[kd].mutex_video); - return -EFAULT; - } - - if (v4l2_cropcap.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - JOM(8, "v4l2_cropcap.type != V4L2_BUF_TYPE_VIDEO_CAPTURE\n"); - - memset(&v4l2_cropcap, 0, sizeof(struct v4l2_cropcap)); - v4l2_cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - v4l2_cropcap.bounds.left = 0; - v4l2_cropcap.bounds.top = 0; - v4l2_cropcap.bounds.width = peasycap->width; - v4l2_cropcap.bounds.height = peasycap->height; - v4l2_cropcap.defrect.left = 0; - v4l2_cropcap.defrect.top = 0; - v4l2_cropcap.defrect.width = peasycap->width; - v4l2_cropcap.defrect.height = peasycap->height; - v4l2_cropcap.pixelaspect.numerator = 1; - v4l2_cropcap.pixelaspect.denominator = 1; - - JOM(8, "user is told: %ix%i\n", peasycap->width, peasycap->height); - - if (copy_to_user((void __user *)arg, &v4l2_cropcap, - sizeof(struct v4l2_cropcap))) { - mutex_unlock(&easycapdc60_dongle[kd].mutex_video); - return -EFAULT; - } - break; - } -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - case VIDIOC_G_CROP: - case VIDIOC_S_CROP: { - JOM(8, "VIDIOC_G_CROP|VIDIOC_S_CROP unsupported\n"); - mutex_unlock(&easycapdc60_dongle[kd].mutex_video); - return -EINVAL; - } -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - case VIDIOC_QUERYSTD: { - JOM(8, "VIDIOC_QUERYSTD: " - "EasyCAP is incapable of detecting standard\n"); - mutex_unlock(&easycapdc60_dongle[kd].mutex_video); - return -EINVAL; - break; - } - /*-------------------------------------------------------------------*/ - /* - * THE MANIPULATIONS INVOLVING last0,last1,last2,last3 - * CONSTITUTE A WORKAROUND * FOR WHAT APPEARS TO BE - * A BUG IN 64-BIT mplayer. - * NOT NEEDED, BUT HOPEFULLY HARMLESS, FOR 32-BIT mplayer. - */ - /*------------------------------------------------------------------*/ - case VIDIOC_ENUMSTD: { - int last0 = -1, last1 = -1, last2 = -1, last3 = -1; - struct v4l2_standard v4l2_standard; - u32 index; - struct easycap_standard const *peasycap_standard; - - JOM(8, "VIDIOC_ENUMSTD\n"); - - if (0 != copy_from_user(&v4l2_standard, (void __user *)arg, - sizeof(struct v4l2_standard))) { - mutex_unlock(&easycapdc60_dongle[kd].mutex_video); - return -EFAULT; - } - index = v4l2_standard.index; - - last3 = last2; - last2 = last1; - last1 = last0; - last0 = index; - if ((index == last3) && (index == last2) && - (index == last1) && (index == last0)) { - index++; - last3 = last2; - last2 = last1; - last1 = last0; - last0 = index; - } - - memset(&v4l2_standard, 0, sizeof(struct v4l2_standard)); - - peasycap_standard = &easycap_standard[0]; - while (0xFFFF != peasycap_standard->mask) { - if ((int)(peasycap_standard - &easycap_standard[0]) == index) - break; - peasycap_standard++; - } - if (0xFFFF == peasycap_standard->mask) { - JOM(8, "%i=index: exhausts standards\n", index); - mutex_unlock(&easycapdc60_dongle[kd].mutex_video); - return -EINVAL; - } - JOM(8, "%i=index: %s\n", index, - &(peasycap_standard->v4l2_standard.name[0])); - memcpy(&v4l2_standard, &(peasycap_standard->v4l2_standard), - sizeof(struct v4l2_standard)); - - v4l2_standard.index = index; - - if (copy_to_user((void __user *)arg, &v4l2_standard, - sizeof(struct v4l2_standard))) { - mutex_unlock(&easycapdc60_dongle[kd].mutex_video); - return -EFAULT; - } - break; - } -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - case VIDIOC_G_STD: { - v4l2_std_id std_id; - struct easycap_standard const *peasycap_standard; - - JOM(8, "VIDIOC_G_STD\n"); - - if (0 > peasycap->standard_offset) { - JOM(8, "%i=peasycap->standard_offset\n", - peasycap->standard_offset); - mutex_unlock(&easycapdc60_dongle[kd].mutex_video); - return -EBUSY; - } - - if (0 != copy_from_user(&std_id, (void __user *)arg, - sizeof(v4l2_std_id))) { - mutex_unlock(&easycapdc60_dongle[kd].mutex_video); - return -EFAULT; - } - - peasycap_standard = &easycap_standard[peasycap->standard_offset]; - std_id = peasycap_standard->v4l2_standard.id; - - JOM(8, "user is told: %s\n", - &peasycap_standard->v4l2_standard.name[0]); - - if (copy_to_user((void __user *)arg, &std_id, - sizeof(v4l2_std_id))) { - mutex_unlock(&easycapdc60_dongle[kd].mutex_video); - return -EFAULT; - } - break; - } -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - case VIDIOC_S_STD: { - v4l2_std_id std_id; - int rc; - - JOM(8, "VIDIOC_S_STD\n"); - - if (0 != copy_from_user(&std_id, (void __user *)arg, - sizeof(v4l2_std_id))) { - mutex_unlock(&easycapdc60_dongle[kd].mutex_video); - return -EFAULT; - } - - JOM(8, "User requests standard: 0x%08X%08X\n", - (int)((std_id & (((v4l2_std_id)0xFFFFFFFF) << 32)) >> 32), - (int)(std_id & ((v4l2_std_id)0xFFFFFFFF))); - - rc = adjust_standard(peasycap, std_id); - if (0 > rc) { - JOM(8, "WARNING: adjust_standard() returned %i\n", rc); - mutex_unlock(&easycapdc60_dongle[kd].mutex_video); - return -ENOENT; - } - break; - } -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - case VIDIOC_REQBUFS: { - int nbuffers; - struct v4l2_requestbuffers v4l2_requestbuffers; - - JOM(8, "VIDIOC_REQBUFS\n"); - - if (0 != copy_from_user(&v4l2_requestbuffers, - (void __user *)arg, - sizeof(struct v4l2_requestbuffers))) { - mutex_unlock(&easycapdc60_dongle[kd].mutex_video); - return -EFAULT; - } - - if (v4l2_requestbuffers.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { - mutex_unlock(&easycapdc60_dongle[kd].mutex_video); - return -EINVAL; - } - if (v4l2_requestbuffers.memory != V4L2_MEMORY_MMAP) { - mutex_unlock(&easycapdc60_dongle[kd].mutex_video); - return -EINVAL; - } - nbuffers = v4l2_requestbuffers.count; - JOM(8, " User requests %i buffers ...\n", nbuffers); - if (nbuffers < 2) - nbuffers = 2; - if (nbuffers > FRAME_BUFFER_MANY) - nbuffers = FRAME_BUFFER_MANY; - if (v4l2_requestbuffers.count == nbuffers) { - JOM(8, " ... agree to %i buffers\n", - nbuffers); - } else { - JOM(8, " ... insist on %i buffers\n", - nbuffers); - v4l2_requestbuffers.count = nbuffers; - } - peasycap->frame_buffer_many = nbuffers; - - if (copy_to_user((void __user *)arg, &v4l2_requestbuffers, - sizeof(struct v4l2_requestbuffers))) { - mutex_unlock(&easycapdc60_dongle[kd].mutex_video); - return -EFAULT; - } - break; - } -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - case VIDIOC_QUERYBUF: { - u32 index; - struct v4l2_buffer v4l2_buffer; - - JOM(8, "VIDIOC_QUERYBUF\n"); - - if (peasycap->video_eof) { - JOM(8, "returning -EIO because %i=video_eof\n", - peasycap->video_eof); - mutex_unlock(&easycapdc60_dongle[kd].mutex_video); - return -EIO; - } - - if (0 != copy_from_user(&v4l2_buffer, (void __user *)arg, - sizeof(struct v4l2_buffer))) { - mutex_unlock(&easycapdc60_dongle[kd].mutex_video); - return -EFAULT; - } - - if (v4l2_buffer.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { - mutex_unlock(&easycapdc60_dongle[kd].mutex_video); - return -EINVAL; - } - index = v4l2_buffer.index; - if (index < 0 || index >= peasycap->frame_buffer_many) - return -EINVAL; - memset(&v4l2_buffer, 0, sizeof(struct v4l2_buffer)); - v4l2_buffer.index = index; - v4l2_buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - v4l2_buffer.bytesused = peasycap->frame_buffer_used; - v4l2_buffer.flags = V4L2_BUF_FLAG_MAPPED | - peasycap->done[index] | - peasycap->queued[index]; - v4l2_buffer.field = V4L2_FIELD_NONE; - v4l2_buffer.memory = V4L2_MEMORY_MMAP; - v4l2_buffer.m.offset = index * FRAME_BUFFER_SIZE; - v4l2_buffer.length = FRAME_BUFFER_SIZE; - - JOM(16, " %10i=index\n", v4l2_buffer.index); - JOM(16, " 0x%08X=type\n", v4l2_buffer.type); - JOM(16, " %10i=bytesused\n", v4l2_buffer.bytesused); - JOM(16, " 0x%08X=flags\n", v4l2_buffer.flags); - JOM(16, " %10i=field\n", v4l2_buffer.field); - JOM(16, " %10li=timestamp.tv_usec\n", - (long)v4l2_buffer.timestamp.tv_usec); - JOM(16, " %10i=sequence\n", v4l2_buffer.sequence); - JOM(16, " 0x%08X=memory\n", v4l2_buffer.memory); - JOM(16, " %10i=m.offset\n", v4l2_buffer.m.offset); - JOM(16, " %10i=length\n", v4l2_buffer.length); - - if (copy_to_user((void __user *)arg, &v4l2_buffer, - sizeof(struct v4l2_buffer))) { - mutex_unlock(&easycapdc60_dongle[kd].mutex_video); - return -EFAULT; - } - break; - } -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - case VIDIOC_QBUF: { - struct v4l2_buffer v4l2_buffer; - - JOM(8, "VIDIOC_QBUF\n"); - - if (0 != copy_from_user(&v4l2_buffer, (void __user *)arg, - sizeof(struct v4l2_buffer))) { - mutex_unlock(&easycapdc60_dongle[kd].mutex_video); - return -EFAULT; - } - - if (v4l2_buffer.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { - mutex_unlock(&easycapdc60_dongle[kd].mutex_video); - return -EINVAL; - } - if (v4l2_buffer.memory != V4L2_MEMORY_MMAP) { - mutex_unlock(&easycapdc60_dongle[kd].mutex_video); - return -EINVAL; - } - if (v4l2_buffer.index < 0 || - v4l2_buffer.index >= peasycap->frame_buffer_many) { - mutex_unlock(&easycapdc60_dongle[kd].mutex_video); - return -EINVAL; - } - v4l2_buffer.flags = V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_QUEUED; - - peasycap->done[v4l2_buffer.index] = 0; - peasycap->queued[v4l2_buffer.index] = V4L2_BUF_FLAG_QUEUED; - - if (copy_to_user((void __user *)arg, &v4l2_buffer, - sizeof(struct v4l2_buffer))) { - mutex_unlock(&easycapdc60_dongle[kd].mutex_video); - return -EFAULT; - } - - JOM(8, "..... user queueing frame buffer %i\n", - (int)v4l2_buffer.index); - - peasycap->frame_lock = 0; - - break; - } -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - case VIDIOC_DQBUF: - { - struct timeval timeval, timeval2; - int i, j; - struct v4l2_buffer v4l2_buffer; - int rcdq; - u16 input; - - JOM(8, "VIDIOC_DQBUF\n"); - - if ((peasycap->video_idle) || (peasycap->video_eof)) { - JOM(8, "returning -EIO because " - "%i=video_idle %i=video_eof\n", - peasycap->video_idle, peasycap->video_eof); - mutex_unlock(&easycapdc60_dongle[kd].mutex_video); - return -EIO; - } - - if (copy_from_user(&v4l2_buffer, (void __user *)arg, - sizeof(struct v4l2_buffer))) { - mutex_unlock(&easycapdc60_dongle[kd].mutex_video); - return -EFAULT; - } - - if (v4l2_buffer.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { - mutex_unlock(&easycapdc60_dongle[kd].mutex_video); - return -EINVAL; - } - - if (peasycap->offerfields) { - /*---------------------------------------------------*/ - /* - * IN ITS 50 "fps" MODE tvtime SEEMS ALWAYS TO REQUEST - * V4L2_FIELD_BOTTOM - */ - /*---------------------------------------------------*/ - if (V4L2_FIELD_TOP == v4l2_buffer.field) - JOM(8, "user wants V4L2_FIELD_TOP\n"); - else if (V4L2_FIELD_BOTTOM == v4l2_buffer.field) - JOM(8, "user wants V4L2_FIELD_BOTTOM\n"); - else if (V4L2_FIELD_ANY == v4l2_buffer.field) - JOM(8, "user wants V4L2_FIELD_ANY\n"); - else - JOM(8, "user wants V4L2_FIELD_...UNKNOWN: %i\n", - v4l2_buffer.field); - } - - if (!peasycap->video_isoc_streaming) { - JOM(16, "returning -EIO because video urbs not streaming\n"); - mutex_unlock(&easycapdc60_dongle[kd].mutex_video); - return -EIO; - } - /*-------------------------------------------------------------------*/ - /* - * IF THE USER HAS PREVIOUSLY CALLED easycap_poll(), - * AS DETERMINED BY FINDING - * THE FLAG peasycap->polled SET, THERE MUST BE - * NO FURTHER WAIT HERE. IN THIS - * CASE, JUST CHOOSE THE FRAME INDICATED BY peasycap->frame_read - */ - /*-------------------------------------------------------------------*/ - - if (!peasycap->polled) { - do { - rcdq = easycap_video_dqbuf(peasycap, 0); - if (-EIO == rcdq) { - JOM(8, "returning -EIO because " - "dqbuf() returned -EIO\n"); - mutex_unlock(&easycapdc60_dongle[kd].mutex_video); - return -EIO; - } - } while (0 != rcdq); - } else { - if (peasycap->video_eof) { - mutex_unlock(&easycapdc60_dongle[kd].mutex_video); - return -EIO; - } - } - if (V4L2_BUF_FLAG_DONE != peasycap->done[peasycap->frame_read]) { - JOM(8, "V4L2_BUF_FLAG_DONE != 0x%08X\n", - peasycap->done[peasycap->frame_read]); - } - peasycap->polled = 0; - - if (!(peasycap->isequence % 10)) { - for (i = 0; i < 179; i++) - peasycap->merit[i] = peasycap->merit[i+1]; - peasycap->merit[179] = merit_saa(peasycap->pusb_device); - j = 0; - for (i = 0; i < 180; i++) - j += peasycap->merit[i]; - if (90 < j) { - SAM("easycap driver shutting down " - "on condition blue\n"); - peasycap->video_eof = 1; - peasycap->audio_eof = 1; - } - } - - v4l2_buffer.index = peasycap->frame_read; - v4l2_buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - v4l2_buffer.bytesused = peasycap->frame_buffer_used; - v4l2_buffer.flags = V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_DONE; - if (peasycap->offerfields) - v4l2_buffer.field = V4L2_FIELD_BOTTOM; - else - v4l2_buffer.field = V4L2_FIELD_NONE; - do_gettimeofday(&timeval); - timeval2 = timeval; - - v4l2_buffer.timestamp = timeval2; - v4l2_buffer.sequence = peasycap->isequence++; - v4l2_buffer.memory = V4L2_MEMORY_MMAP; - v4l2_buffer.m.offset = v4l2_buffer.index * FRAME_BUFFER_SIZE; - v4l2_buffer.length = FRAME_BUFFER_SIZE; - - JOM(16, " %10i=index\n", v4l2_buffer.index); - JOM(16, " 0x%08X=type\n", v4l2_buffer.type); - JOM(16, " %10i=bytesused\n", v4l2_buffer.bytesused); - JOM(16, " 0x%08X=flags\n", v4l2_buffer.flags); - JOM(16, " %10i=field\n", v4l2_buffer.field); - JOM(16, " %10li=timestamp.tv_sec\n", - (long)v4l2_buffer.timestamp.tv_sec); - JOM(16, " %10li=timestamp.tv_usec\n", - (long)v4l2_buffer.timestamp.tv_usec); - JOM(16, " %10i=sequence\n", v4l2_buffer.sequence); - JOM(16, " 0x%08X=memory\n", v4l2_buffer.memory); - JOM(16, " %10i=m.offset\n", v4l2_buffer.m.offset); - JOM(16, " %10i=length\n", v4l2_buffer.length); - - if (copy_to_user((void __user *)arg, &v4l2_buffer, - sizeof(struct v4l2_buffer))) { - mutex_unlock(&easycapdc60_dongle[kd].mutex_video); - return -EFAULT; - } - - input = peasycap->frame_buffer[peasycap->frame_read][0].input; - if (0x08 & input) { - JOM(8, "user is offered frame buffer %i, input %i\n", - peasycap->frame_read, (0x07 & input)); - } else { - JOM(8, "user is offered frame buffer %i\n", - peasycap->frame_read); - } - peasycap->frame_lock = 1; - JOM(8, "%i=peasycap->frame_fill\n", peasycap->frame_fill); - if (peasycap->frame_read == peasycap->frame_fill) { - if (peasycap->frame_lock) { - JOM(8, "WORRY: filling frame buffer " - "while offered to user\n"); - } - } - break; - } -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - case VIDIOC_STREAMON: { - int i; - - JOM(8, "VIDIOC_STREAMON\n"); - - peasycap->isequence = 0; - for (i = 0; i < 180; i++) - peasycap->merit[i] = 0; - if (!peasycap->pusb_device) { - SAM("ERROR: peasycap->pusb_device is NULL\n"); - mutex_unlock(&easycapdc60_dongle[kd].mutex_video); - return -EFAULT; - } - easycap_video_submit_urbs(peasycap); - peasycap->video_idle = 0; - peasycap->audio_idle = 0; - peasycap->video_eof = 0; - peasycap->audio_eof = 0; - break; - } -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - case VIDIOC_STREAMOFF: { - JOM(8, "VIDIOC_STREAMOFF\n"); - - if (!peasycap->pusb_device) { - SAM("ERROR: peasycap->pusb_device is NULL\n"); - mutex_unlock(&easycapdc60_dongle[kd].mutex_video); - return -EFAULT; - } - - peasycap->video_idle = 1; - peasycap->audio_idle = 1; -/*---------------------------------------------------------------------------*/ -/* - * IF THE WAIT QUEUES ARE NOT CLEARED IN RESPONSE TO THE STREAMOFF COMMAND - * THE USERSPACE PROGRAM, E.G. mplayer, MAY HANG ON EXIT. BEWARE. - */ -/*---------------------------------------------------------------------------*/ - JOM(8, "calling wake_up on wq_video and wq_audio\n"); - wake_up_interruptible(&(peasycap->wq_video)); - if (peasycap->psubstream) - snd_pcm_period_elapsed(peasycap->psubstream); - break; - } -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - case VIDIOC_G_PARM: { - struct v4l2_streamparm *pv4l2_streamparm; - - JOM(8, "VIDIOC_G_PARM\n"); - pv4l2_streamparm = memdup_user((void __user *)arg, - sizeof(struct v4l2_streamparm)); - if (IS_ERR(pv4l2_streamparm)) { - SAM("ERROR: copy from user failed\n"); - mutex_unlock(&easycapdc60_dongle[kd].mutex_video); - return PTR_ERR(pv4l2_streamparm); - } - - if (pv4l2_streamparm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { - kfree(pv4l2_streamparm); - mutex_unlock(&easycapdc60_dongle[kd].mutex_video); - return -EINVAL; - } - pv4l2_streamparm->parm.capture.capability = 0; - pv4l2_streamparm->parm.capture.capturemode = 0; - pv4l2_streamparm->parm.capture.timeperframe.numerator = 1; - - if (peasycap->fps) { - pv4l2_streamparm->parm.capture.timeperframe. - denominator = peasycap->fps; - } else { - if (peasycap->ntsc) { - pv4l2_streamparm->parm.capture.timeperframe. - denominator = 30; - } else { - pv4l2_streamparm->parm.capture.timeperframe. - denominator = 25; - } - } - - pv4l2_streamparm->parm.capture.readbuffers = - peasycap->frame_buffer_many; - pv4l2_streamparm->parm.capture.extendedmode = 0; - if (copy_to_user((void __user *)arg, - pv4l2_streamparm, - sizeof(struct v4l2_streamparm))) { - kfree(pv4l2_streamparm); - mutex_unlock(&easycapdc60_dongle[kd].mutex_video); - return -EFAULT; - } - kfree(pv4l2_streamparm); - break; - } -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - case VIDIOC_S_PARM: { - JOM(8, "VIDIOC_S_PARM unsupported\n"); - mutex_unlock(&easycapdc60_dongle[kd].mutex_video); - return -EINVAL; - } -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - case VIDIOC_G_AUDIO: { - JOM(8, "VIDIOC_G_AUDIO unsupported\n"); - mutex_unlock(&easycapdc60_dongle[kd].mutex_video); - return -EINVAL; - } -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - case VIDIOC_S_AUDIO: { - JOM(8, "VIDIOC_S_AUDIO unsupported\n"); - mutex_unlock(&easycapdc60_dongle[kd].mutex_video); - return -EINVAL; - } -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - case VIDIOC_S_TUNER: { - JOM(8, "VIDIOC_S_TUNER unsupported\n"); - mutex_unlock(&easycapdc60_dongle[kd].mutex_video); - return -EINVAL; - } -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - case VIDIOC_G_FBUF: - case VIDIOC_S_FBUF: - case VIDIOC_OVERLAY: { - JOM(8, "VIDIOC_G_FBUF|VIDIOC_S_FBUF|VIDIOC_OVERLAY unsupported\n"); - mutex_unlock(&easycapdc60_dongle[kd].mutex_video); - return -EINVAL; - } -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - case VIDIOC_G_TUNER: { - JOM(8, "VIDIOC_G_TUNER unsupported\n"); - mutex_unlock(&easycapdc60_dongle[kd].mutex_video); - return -EINVAL; - } - case VIDIOC_G_FREQUENCY: - case VIDIOC_S_FREQUENCY: { - JOM(8, "VIDIOC_G_FREQUENCY|VIDIOC_S_FREQUENCY unsupported\n"); - mutex_unlock(&easycapdc60_dongle[kd].mutex_video); - return -EINVAL; - } -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - default: { - JOM(8, "ERROR: unrecognized V4L2 IOCTL command: 0x%08X\n", cmd); - mutex_unlock(&easycapdc60_dongle[kd].mutex_video); - return -ENOIOCTLCMD; - } - } - mutex_unlock(&easycapdc60_dongle[kd].mutex_video); - JOM(4, "unlocked easycapdc60_dongle[%i].mutex_video\n", kd); - return 0; -} -/*****************************************************************************/ diff --git a/drivers/staging/media/easycap/easycap_low.c b/drivers/staging/media/easycap/easycap_low.c deleted file mode 100644 index 0380babed22c..000000000000 --- a/drivers/staging/media/easycap/easycap_low.c +++ /dev/null @@ -1,968 +0,0 @@ -/***************************************************************************** -* * -* * -* easycap_low.c * -* * -* * -*****************************************************************************/ -/* - * - * Copyright (C) 2010 R.M. Thomas <rmthomas@sciolus.org> - * - * - * This 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. - * - * The software 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 software; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * -*/ -/*****************************************************************************/ -/* - * ACKNOWLEGEMENTS AND REFERENCES - * ------------------------------ - * This driver makes use of register information contained in the Syntek - * Semicon DC-1125 driver hosted at - * http://sourceforge.net/projects/syntekdriver/. - * Particularly useful has been a patch to the latter driver provided by - * Ivor Hewitt in January 2009. The NTSC implementation is taken from the - * work of Ben Trask. -*/ -/****************************************************************************/ - -#include "easycap.h" - - -#define GET(X, Y, Z) do { \ - int __rc; \ - *(Z) = (u16)0; \ - __rc = regget(X, Y, Z, sizeof(u8)); \ - if (0 > __rc) { \ - JOT(8, ":-(%i\n", __LINE__); return __rc; \ - } \ -} while (0) - -#define SET(X, Y, Z) do { \ - int __rc; \ - __rc = regset(X, Y, Z); \ - if (0 > __rc) { \ - JOT(8, ":-(%i\n", __LINE__); return __rc; \ - } \ -} while (0) - -/*--------------------------------------------------------------------------*/ -static const struct stk1160config { - u16 reg; - u16 set; -} stk1160configPAL[] = { - {0x000, 0x0098}, - {0x002, 0x0093}, - - {0x001, 0x0003}, - {0x003, 0x0080}, - {0x00D, 0x0000}, - {0x00F, 0x0002}, - {0x018, 0x0010}, - {0x019, 0x0000}, - {0x01A, 0x0014}, - {0x01B, 0x000E}, - {0x01C, 0x0046}, - - {0x100, 0x0033}, - {0x103, 0x0000}, - {0x104, 0x0000}, - {0x105, 0x0000}, - {0x106, 0x0000}, - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ -/* - * RESOLUTION 640x480 -*/ -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - {0x110, 0x0008}, - {0x111, 0x0000}, - {0x112, 0x0020}, - {0x113, 0x0000}, - {0x114, 0x0508}, - {0x115, 0x0005}, - {0x116, 0x0110}, - {0x117, 0x0001}, -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - - {0x202, 0x000F}, - {0x203, 0x004A}, - {0x2FF, 0x0000}, - - {0xFFF, 0xFFFF} -}; -/*--------------------------------------------------------------------------*/ -static const struct stk1160config stk1160configNTSC[] = { - {0x000, 0x0098}, - {0x002, 0x0093}, - - {0x001, 0x0003}, - {0x003, 0x0080}, - {0x00D, 0x0000}, - {0x00F, 0x0002}, - {0x018, 0x0010}, - {0x019, 0x0000}, - {0x01A, 0x0014}, - {0x01B, 0x000E}, - {0x01C, 0x0046}, - - {0x100, 0x0033}, - {0x103, 0x0000}, - {0x104, 0x0000}, - {0x105, 0x0000}, - {0x106, 0x0000}, - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ -/* - * RESOLUTION 640x480 -*/ -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - {0x110, 0x0008}, - {0x111, 0x0000}, - {0x112, 0x0003}, - {0x113, 0x0000}, - {0x114, 0x0508}, - {0x115, 0x0005}, - {0x116, 0x00F3}, - {0x117, 0x0000}, -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - - {0x202, 0x000F}, - {0x203, 0x004A}, - {0x2FF, 0x0000}, - - {0xFFF, 0xFFFF} -}; -/*--------------------------------------------------------------------------*/ -static const struct saa7113config { - u8 reg; - u8 set; -} saa7113configPAL[] = { - {0x01, 0x08}, - {0x02, 0x80}, - {0x03, 0x33}, - {0x04, 0x00}, - {0x05, 0x00}, - {0x06, 0xE9}, - {0x07, 0x0D}, - {0x08, 0x38}, - {0x09, 0x00}, - {0x0A, SAA_0A_DEFAULT}, - {0x0B, SAA_0B_DEFAULT}, - {0x0C, SAA_0C_DEFAULT}, - {0x0D, SAA_0D_DEFAULT}, - {0x0E, 0x01}, - {0x0F, 0x36}, - {0x10, 0x00}, - {0x11, 0x0C}, - {0x12, 0xE7}, - {0x13, 0x00}, - {0x15, 0x00}, - {0x16, 0x00}, - {0x40, 0x02}, - {0x41, 0xFF}, - {0x42, 0xFF}, - {0x43, 0xFF}, - {0x44, 0xFF}, - {0x45, 0xFF}, - {0x46, 0xFF}, - {0x47, 0xFF}, - {0x48, 0xFF}, - {0x49, 0xFF}, - {0x4A, 0xFF}, - {0x4B, 0xFF}, - {0x4C, 0xFF}, - {0x4D, 0xFF}, - {0x4E, 0xFF}, - {0x4F, 0xFF}, - {0x50, 0xFF}, - {0x51, 0xFF}, - {0x52, 0xFF}, - {0x53, 0xFF}, - {0x54, 0xFF}, - {0x55, 0xFF}, - {0x56, 0xFF}, - {0x57, 0xFF}, - {0x58, 0x40}, - {0x59, 0x54}, - {0x5A, 0x07}, - {0x5B, 0x83}, - - {0xFF, 0xFF} -}; -/*--------------------------------------------------------------------------*/ -static const struct saa7113config saa7113configNTSC[] = { - {0x01, 0x08}, - {0x02, 0x80}, - {0x03, 0x33}, - {0x04, 0x00}, - {0x05, 0x00}, - {0x06, 0xE9}, - {0x07, 0x0D}, - {0x08, 0x78}, - {0x09, 0x00}, - {0x0A, SAA_0A_DEFAULT}, - {0x0B, SAA_0B_DEFAULT}, - {0x0C, SAA_0C_DEFAULT}, - {0x0D, SAA_0D_DEFAULT}, - {0x0E, 0x01}, - {0x0F, 0x36}, - {0x10, 0x00}, - {0x11, 0x0C}, - {0x12, 0xE7}, - {0x13, 0x00}, - {0x15, 0x00}, - {0x16, 0x00}, - {0x40, 0x82}, - {0x41, 0xFF}, - {0x42, 0xFF}, - {0x43, 0xFF}, - {0x44, 0xFF}, - {0x45, 0xFF}, - {0x46, 0xFF}, - {0x47, 0xFF}, - {0x48, 0xFF}, - {0x49, 0xFF}, - {0x4A, 0xFF}, - {0x4B, 0xFF}, - {0x4C, 0xFF}, - {0x4D, 0xFF}, - {0x4E, 0xFF}, - {0x4F, 0xFF}, - {0x50, 0xFF}, - {0x51, 0xFF}, - {0x52, 0xFF}, - {0x53, 0xFF}, - {0x54, 0xFF}, - {0x55, 0xFF}, - {0x56, 0xFF}, - {0x57, 0xFF}, - {0x58, 0x40}, - {0x59, 0x54}, - {0x5A, 0x0A}, - {0x5B, 0x83}, - - {0xFF, 0xFF} -}; - -static int regget(struct usb_device *pusb_device, - u16 index, void *reg, int reg_size) -{ - int rc; - - if (!pusb_device) - return -ENODEV; - - rc = usb_control_msg(pusb_device, usb_rcvctrlpipe(pusb_device, 0), - 0x00, - (USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE), - 0x00, - index, reg, reg_size, 50000); - - return rc; -} - -static int regset(struct usb_device *pusb_device, u16 index, u16 value) -{ - int rc; - - if (!pusb_device) - return -ENODEV; - - rc = usb_control_msg(pusb_device, usb_sndctrlpipe(pusb_device, 0), - 0x01, - (USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE), - value, index, NULL, 0, 500); - - if (rc < 0) - return rc; - - if (easycap_readback) { - u16 igot = 0; - rc = regget(pusb_device, index, &igot, sizeof(igot)); - igot = 0xFF & igot; - switch (index) { - case 0x000: - case 0x500: - case 0x502: - case 0x503: - case 0x504: - case 0x506: - case 0x507: - break; - - case 0x204: - case 0x205: - case 0x350: - case 0x351: - if (igot) - JOT(8, "unexpected 0x%02X " - "for STK register 0x%03X\n", - igot, index); - break; - - default: - if ((0xFF & value) != igot) - JOT(8, "unexpected 0x%02X != 0x%02X " - "for STK register 0x%03X\n", - igot, value, index); - break; - } - } - - return rc; -} -/*--------------------------------------------------------------------------*/ -/* - * FUNCTION wait_i2c() RETURNS 0 ON SUCCESS -*/ -/*--------------------------------------------------------------------------*/ -static int wait_i2c(struct usb_device *p) -{ - u16 get0; - u8 igot; - const int max = 2; - int k; - - if (!p) - return -ENODEV; - - for (k = 0; k < max; k++) { - GET(p, 0x0201, &igot); get0 = igot; - switch (get0) { - case 0x04: - case 0x01: - return 0; - case 0x00: - msleep(20); - continue; - default: - return get0 - 1; - } - } - return -1; -} - -/****************************************************************************/ -int write_saa(struct usb_device *p, u16 reg0, u16 set0) -{ - if (!p) - return -ENODEV; - SET(p, 0x200, 0x00); - SET(p, 0x204, reg0); - SET(p, 0x205, set0); - SET(p, 0x200, 0x01); - return wait_i2c(p); -} -/****************************************************************************/ -/*--------------------------------------------------------------------------*/ -/* - * REGISTER 500: SETTING VALUE TO 0x008B READS FROM VT1612A (?) - * REGISTER 500: SETTING VALUE TO 0x008C WRITES TO VT1612A - * REGISTER 502: LEAST SIGNIFICANT BYTE OF VALUE TO SET - * REGISTER 503: MOST SIGNIFICANT BYTE OF VALUE TO SET - * REGISTER 504: TARGET ADDRESS ON VT1612A - */ -/*--------------------------------------------------------------------------*/ -static int write_vt(struct usb_device *p, u16 reg0, u16 set0) -{ - u8 igot; - u16 got502, got503; - u16 set502, set503; - - if (!p) - return -ENODEV; - SET(p, 0x0504, reg0); - SET(p, 0x0500, 0x008B); - - GET(p, 0x0502, &igot); got502 = (0xFF & igot); - GET(p, 0x0503, &igot); got503 = (0xFF & igot); - - JOT(16, "write_vt(., 0x%04X, 0x%04X): was 0x%04X\n", - reg0, set0, ((got503 << 8) | got502)); - - set502 = (0x00FF & set0); - set503 = ((0xFF00 & set0) >> 8); - - SET(p, 0x0504, reg0); - SET(p, 0x0502, set502); - SET(p, 0x0503, set503); - SET(p, 0x0500, 0x008C); - - return 0; -} -/****************************************************************************/ -/*--------------------------------------------------------------------------*/ -/* - * REGISTER 500: SETTING VALUE TO 0x008B READS FROM VT1612A (?) - * REGISTER 500: SETTING VALUE TO 0x008C WRITES TO VT1612A - * REGISTER 502: LEAST SIGNIFICANT BYTE OF VALUE TO GET - * REGISTER 503: MOST SIGNIFICANT BYTE OF VALUE TO GET - * REGISTER 504: TARGET ADDRESS ON VT1612A - */ -/*--------------------------------------------------------------------------*/ -static int read_vt(struct usb_device *p, u16 reg0) -{ - u8 igot; - u16 got502, got503; - - if (!p) - return -ENODEV; - SET(p, 0x0504, reg0); - SET(p, 0x0500, 0x008B); - - GET(p, 0x0502, &igot); got502 = (0xFF & igot); - GET(p, 0x0503, &igot); got503 = (0xFF & igot); - - JOT(16, "read_vt(., 0x%04X): has 0x%04X\n", - reg0, ((got503 << 8) | got502)); - - return (got503 << 8) | got502; -} -/****************************************************************************/ -/*--------------------------------------------------------------------------*/ -/* - * THESE APPEAR TO HAVE NO EFFECT ON EITHER VIDEO OR AUDIO. - */ -/*--------------------------------------------------------------------------*/ -static int write_300(struct usb_device *p) -{ - if (!p) - return -ENODEV; - SET(p, 0x300, 0x0012); - SET(p, 0x350, 0x002D); - SET(p, 0x351, 0x0001); - SET(p, 0x352, 0x0000); - SET(p, 0x353, 0x0000); - SET(p, 0x300, 0x0080); - return 0; -} -/****************************************************************************/ -/****************************************************************************/ -int setup_stk(struct usb_device *p, bool ntsc) -{ - int i; - const struct stk1160config *cfg; - if (!p) - return -ENODEV; - cfg = (ntsc) ? stk1160configNTSC : stk1160configPAL; - for (i = 0; cfg[i].reg != 0xFFF; i++) - SET(p, cfg[i].reg, cfg[i].set); - - write_300(p); - - return 0; -} -/****************************************************************************/ -int setup_saa(struct usb_device *p, bool ntsc) -{ - int i, rc; - const struct saa7113config *cfg; - if (!p) - return -ENODEV; - cfg = (ntsc) ? saa7113configNTSC : saa7113configPAL; - for (i = 0; cfg[i].reg != 0xFF; i++) { - rc = write_saa(p, cfg[i].reg, cfg[i].set); - if (rc) - dev_err(&p->dev, - "Failed to set SAA register %d", cfg[i].reg); - } - return 0; -} -/****************************************************************************/ -int merit_saa(struct usb_device *p) -{ - int rc; - - if (!p) - return -ENODEV; - rc = read_saa(p, 0x1F); - return ((0 > rc) || (0x02 & rc)) ? 1 : 0; -} -/****************************************************************************/ -int ready_saa(struct usb_device *p) -{ - int j, rc, rate; - const int max = 5, marktime = PATIENCE/5; -/*--------------------------------------------------------------------------*/ -/* - * RETURNS 0 FOR INTERLACED 50 Hz - * 1 FOR NON-INTERLACED 50 Hz - * 2 FOR INTERLACED 60 Hz - * 3 FOR NON-INTERLACED 60 Hz -*/ -/*--------------------------------------------------------------------------*/ - if (!p) - return -ENODEV; - j = 0; - while (max > j) { - rc = read_saa(p, 0x1F); - if (0 <= rc) { - if (0 == (0x40 & rc)) - break; - if (1 == (0x01 & rc)) - break; - } - msleep(marktime); - j++; - } - - if (max == j) - return -1; - - if (0x20 & rc) { - rate = 2; - JOT(8, "hardware detects 60 Hz\n"); - } else { - rate = 0; - JOT(8, "hardware detects 50 Hz\n"); - } - if (0x80 & rc) - JOT(8, "hardware detects interlacing\n"); - else { - rate++; - JOT(8, "hardware detects no interlacing\n"); - } - return 0; -} -/****************************************************************************/ -int read_saa(struct usb_device *p, u16 reg0) -{ - u8 igot; - - if (!p) - return -ENODEV; - SET(p, 0x208, reg0); - SET(p, 0x200, 0x20); - if (0 != wait_i2c(p)) - return -1; - igot = 0; - GET(p, 0x0209, &igot); - return igot; -} -/****************************************************************************/ -static int read_stk(struct usb_device *p, u32 reg0) -{ - u8 igot; - - if (!p) - return -ENODEV; - igot = 0; - GET(p, reg0, &igot); - return igot; -} -int select_input(struct usb_device *p, int input, int mode) -{ - int ir; - - if (!p) - return -ENODEV; - stop_100(p); - switch (input) { - case 0: - case 1: { - if (0 != write_saa(p, 0x02, 0x80)) - SAY("ERROR: failed to set SAA register 0x02 " - "for input %i\n", input); - - SET(p, 0x0000, 0x0098); - SET(p, 0x0002, 0x0078); - break; - } - case 2: { - if (0 != write_saa(p, 0x02, 0x80)) - SAY("ERROR: failed to set SAA register 0x02 " - "for input %i\n", input); - - SET(p, 0x0000, 0x0090); - SET(p, 0x0002, 0x0078); - break; - } - case 3: { - if (0 != write_saa(p, 0x02, 0x80)) - SAY("ERROR: failed to set SAA register 0x02 " - " for input %i\n", input); - - SET(p, 0x0000, 0x0088); - SET(p, 0x0002, 0x0078); - break; - } - case 4: { - if (0 != write_saa(p, 0x02, 0x80)) { - SAY("ERROR: failed to set SAA register 0x02 " - "for input %i\n", input); - } - SET(p, 0x0000, 0x0080); - SET(p, 0x0002, 0x0078); - break; - } - case 5: { - if (9 != mode) - mode = 7; - switch (mode) { - case 7: { - if (0 != write_saa(p, 0x02, 0x87)) - SAY("ERROR: failed to set SAA register 0x02 " - "for input %i\n", input); - - if (0 != write_saa(p, 0x05, 0xFF)) - SAY("ERROR: failed to set SAA register 0x05 " - "for input %i\n", input); - - break; - } - case 9: { - if (0 != write_saa(p, 0x02, 0x89)) - SAY("ERROR: failed to set SAA register 0x02 " - "for input %i\n", input); - - if (0 != write_saa(p, 0x05, 0x00)) - SAY("ERROR: failed to set SAA register 0x05 " - "for input %i\n", input); - - break; - } - default: - SAY("MISTAKE: bad mode: %i\n", mode); - return -1; - } - - if (0 != write_saa(p, 0x04, 0x00)) - SAY("ERROR: failed to set SAA register 0x04 " - "for input %i\n", input); - - if (0 != write_saa(p, 0x09, 0x80)) - SAY("ERROR: failed to set SAA register 0x09 " - "for input %i\n", input); - - SET(p, 0x0002, 0x0093); - break; - } - default: - SAY("ERROR: bad input: %i\n", input); - return -1; - } - - ir = read_stk(p, 0x00); - JOT(8, "STK register 0x00 has 0x%02X\n", ir); - ir = read_saa(p, 0x02); - JOT(8, "SAA register 0x02 has 0x%02X\n", ir); - - start_100(p); - - return 0; -} -/****************************************************************************/ -int set_resolution(struct usb_device *p, - u16 set0, u16 set1, u16 set2, u16 set3) -{ - u16 u0x0111, u0x0113, u0x0115, u0x0117; - - if (!p) - return -ENODEV; - u0x0111 = ((0xFF00 & set0) >> 8); - u0x0113 = ((0xFF00 & set1) >> 8); - u0x0115 = ((0xFF00 & set2) >> 8); - u0x0117 = ((0xFF00 & set3) >> 8); - - SET(p, 0x0110, (0x00FF & set0)); - SET(p, 0x0111, u0x0111); - SET(p, 0x0112, (0x00FF & set1)); - SET(p, 0x0113, u0x0113); - SET(p, 0x0114, (0x00FF & set2)); - SET(p, 0x0115, u0x0115); - SET(p, 0x0116, (0x00FF & set3)); - SET(p, 0x0117, u0x0117); - - return 0; -} -/****************************************************************************/ -int start_100(struct usb_device *p) -{ - u16 get116, get117, get0; - u8 igot116, igot117, igot; - - if (!p) - return -ENODEV; - GET(p, 0x0116, &igot116); - get116 = igot116; - GET(p, 0x0117, &igot117); - get117 = igot117; - SET(p, 0x0116, 0x0000); - SET(p, 0x0117, 0x0000); - - GET(p, 0x0100, &igot); - get0 = igot; - SET(p, 0x0100, (0x80 | get0)); - - SET(p, 0x0116, get116); - SET(p, 0x0117, get117); - - return 0; -} -/****************************************************************************/ -int stop_100(struct usb_device *p) -{ - u16 get0; - u8 igot; - - if (!p) - return -ENODEV; - GET(p, 0x0100, &igot); - get0 = igot; - SET(p, 0x0100, (0x7F & get0)); - return 0; -} -/****************************************************************************/ -/****************************************************************************/ -/*****************************************************************************/ -int easycap_wakeup_device(struct usb_device *pusb_device) -{ - if (!pusb_device) - return -ENODEV; - - return usb_control_msg(pusb_device, usb_sndctrlpipe(pusb_device, 0), - USB_REQ_SET_FEATURE, - USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE, - USB_DEVICE_REMOTE_WAKEUP, - 0, NULL, 0, 50000); -} -/*****************************************************************************/ -int easycap_audio_setup(struct easycap *peasycap) -{ - struct usb_device *pusb_device; - u8 buffer[1]; - int rc, id1, id2; -/*---------------------------------------------------------------------------*/ -/* - * IMPORTANT: - * THE MESSAGE OF TYPE (USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) - * CAUSES MUTING IF THE VALUE 0x0100 IS SENT. - * TO ENABLE AUDIO THE VALUE 0x0200 MUST BE SENT. - */ -/*---------------------------------------------------------------------------*/ - const u8 request = 0x01; - const u8 requesttype = USB_DIR_OUT | - USB_TYPE_CLASS | - USB_RECIP_INTERFACE; - const u16 value_unmute = 0x0200; - const u16 index = 0x0301; - const u16 length = 1; - - if (!peasycap) - return -EFAULT; - - pusb_device = peasycap->pusb_device; - if (!pusb_device) - return -ENODEV; - - JOM(8, "%02X %02X %02X %02X %02X %02X %02X %02X\n", - requesttype, request, - (0x00FF & value_unmute), - (0xFF00 & value_unmute) >> 8, - (0x00FF & index), - (0xFF00 & index) >> 8, - (0x00FF & length), - (0xFF00 & length) >> 8); - - buffer[0] = 0x01; - - rc = usb_control_msg(pusb_device, usb_sndctrlpipe(pusb_device, 0), - request, requesttype, value_unmute, - index, &buffer[0], length, 50000); - - JOT(8, "0x%02X=buffer\n", buffer[0]); - if (rc != (int)length) { - switch (rc) { - case -EPIPE: - SAY("usb_control_msg returned -EPIPE\n"); - break; - default: - SAY("ERROR: usb_control_msg returned %i\n", rc); - break; - } - } -/*--------------------------------------------------------------------------*/ -/* - * REGISTER 500: SETTING VALUE TO 0x0094 RESETS AUDIO CONFIGURATION ??? - * REGISTER 506: ANALOGUE AUDIO ATTENTUATOR ??? - * FOR THE CVBS+S-VIDEO HARDWARE: - * SETTING VALUE TO 0x0000 GIVES QUIET SOUND. - * THE UPPER BYTE SEEMS TO HAVE NO EFFECT. - * FOR THE FOUR-CVBS HARDWARE: - * SETTING VALUE TO 0x0000 SEEMS TO HAVE NO EFFECT. - * REGISTER 507: ANALOGUE AUDIO PREAMPLIFIER ON/OFF ??? - * FOR THE CVBS-S-VIDEO HARDWARE: - * SETTING VALUE TO 0x0001 GIVES VERY LOUD, DISTORTED SOUND. - * THE UPPER BYTE SEEMS TO HAVE NO EFFECT. - */ -/*--------------------------------------------------------------------------*/ - SET(pusb_device, 0x0500, 0x0094); - SET(pusb_device, 0x0500, 0x008C); - SET(pusb_device, 0x0506, 0x0001); - SET(pusb_device, 0x0507, 0x0000); - id1 = read_vt(pusb_device, 0x007C); - id2 = read_vt(pusb_device, 0x007E); - SAM("0x%04X:0x%04X is audio vendor id\n", id1, id2); -/*---------------------------------------------------------------------------*/ -/* - * SELECT AUDIO SOURCE "LINE IN" AND SET THE AUDIO GAIN. -*/ -/*---------------------------------------------------------------------------*/ - if (easycap_audio_gainset(pusb_device, peasycap->gain)) - SAY("ERROR: audio_gainset() failed\n"); - check_vt(pusb_device); - return 0; -} -/*****************************************************************************/ -int check_vt(struct usb_device *pusb_device) -{ - int igot; - - if (!pusb_device) - return -ENODEV; - igot = read_vt(pusb_device, 0x0002); - if (0 > igot) - SAY("ERROR: failed to read VT1612A register 0x02\n"); - if (0x8000 & igot) - SAY("register 0x%02X muted\n", 0x02); - - igot = read_vt(pusb_device, 0x000E); - if (0 > igot) - SAY("ERROR: failed to read VT1612A register 0x0E\n"); - if (0x8000 & igot) - SAY("register 0x%02X muted\n", 0x0E); - - igot = read_vt(pusb_device, 0x0010); - if (0 > igot) - SAY("ERROR: failed to read VT1612A register 0x10\n"); - if (0x8000 & igot) - SAY("register 0x%02X muted\n", 0x10); - - igot = read_vt(pusb_device, 0x0012); - if (0 > igot) - SAY("ERROR: failed to read VT1612A register 0x12\n"); - if (0x8000 & igot) - SAY("register 0x%02X muted\n", 0x12); - - igot = read_vt(pusb_device, 0x0014); - if (0 > igot) - SAY("ERROR: failed to read VT1612A register 0x14\n"); - if (0x8000 & igot) - SAY("register 0x%02X muted\n", 0x14); - - igot = read_vt(pusb_device, 0x0016); - if (0 > igot) - SAY("ERROR: failed to read VT1612A register 0x16\n"); - if (0x8000 & igot) - SAY("register 0x%02X muted\n", 0x16); - - igot = read_vt(pusb_device, 0x0018); - if (0 > igot) - SAY("ERROR: failed to read VT1612A register 0x18\n"); - if (0x8000 & igot) - SAY("register 0x%02X muted\n", 0x18); - - igot = read_vt(pusb_device, 0x001C); - if (0 > igot) - SAY("ERROR: failed to read VT1612A register 0x1C\n"); - if (0x8000 & igot) - SAY("register 0x%02X muted\n", 0x1C); - - return 0; -} -/*****************************************************************************/ -/*---------------------------------------------------------------------------*/ -/* NOTE: THIS DOES INCREASE THE VOLUME DRAMATICALLY: - * audio_gainset(pusb_device, 0x000F); - * - * loud dB register 0x10 dB register 0x1C dB total - * 0 -34.5 0 -34.5 - * .. .... . .... - * 15 10.5 0 10.5 - * 16 12.0 0 12.0 - * 17 12.0 1.5 13.5 - * .. .... .... .... - * 31 12.0 22.5 34.5 -*/ -/*---------------------------------------------------------------------------*/ -int easycap_audio_gainset(struct usb_device *pusb_device, s8 loud) -{ - int igot; - u8 tmp; - u16 mute; - - if (!pusb_device) - return -ENODEV; - if (0 > loud) - loud = 0; - if (31 < loud) - loud = 31; - - write_vt(pusb_device, 0x0002, 0x8000); -/*---------------------------------------------------------------------------*/ - igot = read_vt(pusb_device, 0x000E); - if (0 > igot) { - SAY("ERROR: failed to read VT1612A register 0x0E\n"); - mute = 0x0000; - } else - mute = 0x8000 & ((unsigned int)igot); - mute = 0; - - if (16 > loud) - tmp = 0x01 | (0x001F & (((u8)(15 - loud)) << 1)); - else - tmp = 0; - - JOT(8, "0x%04X=(mute|tmp) for VT1612A register 0x0E\n", mute | tmp); - write_vt(pusb_device, 0x000E, (mute | tmp)); -/*---------------------------------------------------------------------------*/ - igot = read_vt(pusb_device, 0x0010); - if (0 > igot) { - SAY("ERROR: failed to read VT1612A register 0x10\n"); - mute = 0x0000; - } else - mute = 0x8000 & ((unsigned int)igot); - mute = 0; - - JOT(8, "0x%04X=(mute|tmp|(tmp<<8)) for VT1612A register 0x10,...0x18\n", - mute | tmp | (tmp << 8)); - write_vt(pusb_device, 0x0010, (mute | tmp | (tmp << 8))); - write_vt(pusb_device, 0x0012, (mute | tmp | (tmp << 8))); - write_vt(pusb_device, 0x0014, (mute | tmp | (tmp << 8))); - write_vt(pusb_device, 0x0016, (mute | tmp | (tmp << 8))); - write_vt(pusb_device, 0x0018, (mute | tmp | (tmp << 8))); -/*---------------------------------------------------------------------------*/ - igot = read_vt(pusb_device, 0x001C); - if (0 > igot) { - SAY("ERROR: failed to read VT1612A register 0x1C\n"); - mute = 0x0000; - } else - mute = 0x8000 & ((unsigned int)igot); - mute = 0; - - if (16 <= loud) - tmp = 0x000F & (u8)(loud - 16); - else - tmp = 0; - - JOT(8, "0x%04X=(mute|tmp|(tmp<<8)) for VT1612A register 0x1C\n", - mute | tmp | (tmp << 8)); - write_vt(pusb_device, 0x001C, (mute | tmp | (tmp << 8))); - write_vt(pusb_device, 0x001A, 0x0404); - write_vt(pusb_device, 0x0002, 0x0000); - return 0; -} -/*****************************************************************************/ diff --git a/drivers/staging/media/easycap/easycap_main.c b/drivers/staging/media/easycap/easycap_main.c deleted file mode 100644 index 8269c77dbf7d..000000000000 --- a/drivers/staging/media/easycap/easycap_main.c +++ /dev/null @@ -1,4239 +0,0 @@ -/****************************************************************************** -* * -* easycap_main.c * -* * -* Video driver for EasyCAP USB2.0 Video Capture Device DC60 * -* * -* * -******************************************************************************/ -/* - * - * Copyright (C) 2010 R.M. Thomas <rmthomas@sciolus.org> - * - * - * This 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. - * - * The software 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 software; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * -*/ -/*****************************************************************************/ - -#include "easycap.h" -#include <linux/usb/audio.h> - - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("R.M. Thomas <rmthomas@sciolus.org>"); -MODULE_DESCRIPTION(EASYCAP_DRIVER_DESCRIPTION); -MODULE_VERSION(EASYCAP_DRIVER_VERSION); - -#ifdef CONFIG_EASYCAP_DEBUG -int easycap_debug; -module_param_named(debug, easycap_debug, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "Debug level: 0(default),1,2,...,9"); -#endif /* CONFIG_EASYCAP_DEBUG */ - -bool easycap_readback; -module_param_named(readback, easycap_readback, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(readback, "read back written registers: (default false)"); - -static int easycap_bars = 1; -module_param_named(bars, easycap_bars, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(bars, - "Testcard bars on input signal failure: 0=>no, 1=>yes(default)"); - -static int easycap_gain = 16; -module_param_named(gain, easycap_gain, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(gain, "Audio gain: 0,...,16(default),...31"); - -static bool easycap_ntsc; -module_param_named(ntsc, easycap_ntsc, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(ntsc, "NTSC default encoding (default PAL)"); - - - -struct easycap_dongle easycapdc60_dongle[DONGLE_MANY]; -static struct mutex mutex_dongle; -static void easycap_complete(struct urb *purb); -static int reset(struct easycap *peasycap); -static int field2frame(struct easycap *peasycap); -static int redaub(struct easycap *peasycap, - void *pad, void *pex, int much, int more, - u8 mask, u8 margin, bool isuy); - -const char *strerror(int err) -{ -#define ERRNOSTR(_e) case _e: return # _e - switch (err) { - case 0: return "OK"; - ERRNOSTR(ENOMEM); - ERRNOSTR(ENODEV); - ERRNOSTR(ENXIO); - ERRNOSTR(EINVAL); - ERRNOSTR(EAGAIN); - ERRNOSTR(EFBIG); - ERRNOSTR(EPIPE); - ERRNOSTR(EMSGSIZE); - ERRNOSTR(ENOSPC); - ERRNOSTR(EINPROGRESS); - ERRNOSTR(ENOSR); - ERRNOSTR(EOVERFLOW); - ERRNOSTR(EPROTO); - ERRNOSTR(EILSEQ); - ERRNOSTR(ETIMEDOUT); - ERRNOSTR(EOPNOTSUPP); - ERRNOSTR(EPFNOSUPPORT); - ERRNOSTR(EAFNOSUPPORT); - ERRNOSTR(EADDRINUSE); - ERRNOSTR(EADDRNOTAVAIL); - ERRNOSTR(ENOBUFS); - ERRNOSTR(EISCONN); - ERRNOSTR(ENOTCONN); - ERRNOSTR(ESHUTDOWN); - ERRNOSTR(ENOENT); - ERRNOSTR(ECONNRESET); - ERRNOSTR(ETIME); - ERRNOSTR(ECOMM); - ERRNOSTR(EREMOTEIO); - ERRNOSTR(EXDEV); - ERRNOSTR(EPERM); - default: return "unknown"; - } - -#undef ERRNOSTR -} - -/****************************************************************************/ -/*---------------------------------------------------------------------------*/ -/* - * THIS ROUTINE DOES NOT DETECT DUPLICATE OCCURRENCES OF POINTER peasycap -*/ -/*---------------------------------------------------------------------------*/ -int easycap_isdongle(struct easycap *peasycap) -{ - int k; - if (!peasycap) - return -2; - for (k = 0; k < DONGLE_MANY; k++) { - if (easycapdc60_dongle[k].peasycap == peasycap) { - peasycap->isdongle = k; - return k; - } - } - return -1; -} -/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ -static int easycap_open(struct inode *inode, struct file *file) -{ - struct video_device *pvideo_device; - struct easycap *peasycap; - int rc; - - JOT(4, "\n"); - SAY("==========OPEN=========\n"); - - pvideo_device = video_devdata(file); - if (!pvideo_device) { - SAY("ERROR: pvideo_device is NULL.\n"); - return -EFAULT; - } - peasycap = (struct easycap *)video_get_drvdata(pvideo_device); - if (!peasycap) { - SAY("ERROR: peasycap is NULL\n"); - return -EFAULT; - } - if (!peasycap->pusb_device) { - SAM("ERROR: peasycap->pusb_device is NULL\n"); - return -EFAULT; - } - - JOM(16, "peasycap->pusb_device=%p\n", peasycap->pusb_device); - - file->private_data = peasycap; - rc = easycap_wakeup_device(peasycap->pusb_device); - if (rc) { - SAM("ERROR: wakeup_device() rc = %i\n", rc); - if (-ENODEV == rc) - SAM("ERROR: wakeup_device() returned -ENODEV\n"); - else - SAM("ERROR: wakeup_device() rc = %i\n", rc); - return rc; - } - JOM(8, "wakeup_device() OK\n"); - peasycap->input = 0; - rc = reset(peasycap); - if (rc) { - SAM("ERROR: reset() rc = %i\n", rc); - return -EFAULT; - } - return 0; -} - -/*****************************************************************************/ -/*---------------------------------------------------------------------------*/ -/* - * RESET THE HARDWARE TO ITS REFERENCE STATE. - * - * THIS ROUTINE MAY BE CALLED REPEATEDLY IF easycap_complete() DETECTS - * A BAD VIDEO FRAME SIZE. -*/ -/*---------------------------------------------------------------------------*/ -static int reset(struct easycap *peasycap) -{ - struct easycap_standard const *peasycap_standard; - int fmtidx, input, rate; - bool ntsc, other; - int rc; - - if (!peasycap) { - SAY("ERROR: peasycap is NULL\n"); - return -EFAULT; - } - input = peasycap->input; - -/*---------------------------------------------------------------------------*/ -/* - * IF THE SAA7113H HAS ALREADY ACQUIRED SYNC, USE ITS HARDWARE-DETECTED - * FIELD FREQUENCY TO DISTINGUISH NTSC FROM PAL. THIS IS ESSENTIAL FOR - * gstreamer AND OTHER USERSPACE PROGRAMS WHICH MAY NOT ATTEMPT TO INITIATE - * A SWITCH BETWEEN PAL AND NTSC. - * - * FUNCTION ready_saa() MAY REQUIRE A SUBSTANTIAL FRACTION OF A SECOND TO - * COMPLETE, SO SHOULD NOT BE INVOKED WITHOUT GOOD REASON. -*/ -/*---------------------------------------------------------------------------*/ - other = false; - JOM(8, "peasycap->ntsc=%d\n", peasycap->ntsc); - - rate = ready_saa(peasycap->pusb_device); - if (rate < 0) { - JOM(8, "not ready to capture after %i ms ...\n", PATIENCE); - ntsc = !peasycap->ntsc; - JOM(8, "... trying %s ..\n", ntsc ? "NTSC" : "PAL"); - rc = setup_stk(peasycap->pusb_device, ntsc); - if (rc) { - SAM("ERROR: setup_stk() rc = %i\n", rc); - return -EFAULT; - } - rc = setup_saa(peasycap->pusb_device, ntsc); - if (rc) { - SAM("ERROR: setup_saa() rc = %i\n", rc); - return -EFAULT; - } - - rate = ready_saa(peasycap->pusb_device); - if (rate < 0) { - JOM(8, "not ready to capture after %i ms\n", PATIENCE); - JOM(8, "... saa register 0x1F has 0x%02X\n", - read_saa(peasycap->pusb_device, 0x1F)); - ntsc = peasycap->ntsc; - } else { - JOM(8, "... success at second try: %i=rate\n", rate); - ntsc = (0 < (rate/2)) ? true : false ; - other = true; - } - } else { - JOM(8, "... success at first try: %i=rate\n", rate); - ntsc = (0 < rate/2) ? true : false ; - } - JOM(8, "ntsc=%d\n", ntsc); -/*---------------------------------------------------------------------------*/ - - rc = setup_stk(peasycap->pusb_device, ntsc); - if (rc) { - SAM("ERROR: setup_stk() rc = %i\n", rc); - return -EFAULT; - } - rc = setup_saa(peasycap->pusb_device, ntsc); - if (rc) { - SAM("ERROR: setup_saa() rc = %i\n", rc); - return -EFAULT; - } - - memset(peasycap->merit, 0, sizeof(peasycap->merit)); - - peasycap->video_eof = 0; - peasycap->audio_eof = 0; -/*---------------------------------------------------------------------------*/ -/* - * RESTORE INPUT AND FORCE REFRESH OF STANDARD, FORMAT, ETC. - * - * WHILE THIS PROCEDURE IS IN PROGRESS, SOME IOCTL COMMANDS WILL RETURN -EBUSY. -*/ -/*---------------------------------------------------------------------------*/ - peasycap->input = -8192; - peasycap->standard_offset = -8192; - fmtidx = ntsc ? NTSC_M : PAL_BGHIN; - if (other) { - peasycap_standard = &easycap_standard[0]; - while (0xFFFF != peasycap_standard->mask) { - if (fmtidx == peasycap_standard->v4l2_standard.index) { - peasycap->inputset[input].standard_offset = - peasycap_standard - easycap_standard; - break; - } - peasycap_standard++; - } - if (0xFFFF == peasycap_standard->mask) { - SAM("ERROR: standard not found\n"); - return -EINVAL; - } - JOM(8, "%i=peasycap->inputset[%i].standard_offset\n", - peasycap->inputset[input].standard_offset, input); - } - peasycap->format_offset = -8192; - peasycap->brightness = -8192; - peasycap->contrast = -8192; - peasycap->saturation = -8192; - peasycap->hue = -8192; - - rc = easycap_newinput(peasycap, input); - - if (rc) { - SAM("ERROR: newinput(.,%i) rc = %i\n", rc, input); - return -EFAULT; - } - JOM(4, "restored input, standard and format\n"); - - JOM(8, "true=peasycap->ntsc %d\n", peasycap->ntsc); - - if (0 > peasycap->input) { - SAM("MISTAKE: %i=peasycap->input\n", peasycap->input); - return -ENOENT; - } - if (0 > peasycap->standard_offset) { - SAM("MISTAKE: %i=peasycap->standard_offset\n", - peasycap->standard_offset); - return -ENOENT; - } - if (0 > peasycap->format_offset) { - SAM("MISTAKE: %i=peasycap->format_offset\n", - peasycap->format_offset); - return -ENOENT; - } - if (0 > peasycap->brightness) { - SAM("MISTAKE: %i=peasycap->brightness\n", - peasycap->brightness); - return -ENOENT; - } - if (0 > peasycap->contrast) { - SAM("MISTAKE: %i=peasycap->contrast\n", peasycap->contrast); - return -ENOENT; - } - if (0 > peasycap->saturation) { - SAM("MISTAKE: %i=peasycap->saturation\n", - peasycap->saturation); - return -ENOENT; - } - if (0 > peasycap->hue) { - SAM("MISTAKE: %i=peasycap->hue\n", peasycap->hue); - return -ENOENT; - } - return 0; -} -/*****************************************************************************/ -/*---------------------------------------------------------------------------*/ -/* - * IF THE REQUESTED INPUT IS THE SAME AS THE EXISTING INPUT, DO NOTHING. - * OTHERWISE: - * KILL URBS, CLEAR FIELD AND FRAME BUFFERS AND RESET THEIR - * _read AND _fill POINTERS. - * SELECT THE NEW INPUT. - * ADJUST THE STANDARD, FORMAT, BRIGHTNESS, CONTRAST, SATURATION AND HUE - * ON THE BASIS OF INFORMATION IN STRUCTURE easycap.inputset[input]. - * RESUBMIT THE URBS IF STREAMING WAS ALREADY IN PROGRESS. - * - * NOTE: - * THIS ROUTINE MAY BE CALLED FREQUENTLY BY ZONEMINDER VIA IOCTL, - * SO IT SHOULD WRITE ONLY SPARINGLY TO THE LOGFILE. -*/ -/*---------------------------------------------------------------------------*/ -int easycap_newinput(struct easycap *peasycap, int input) -{ - int rc, k, m, mood, off; - int inputnow, video_idlenow, audio_idlenow; - bool resubmit; - - if (!peasycap) { - SAY("ERROR: peasycap is NULL\n"); - return -EFAULT; - } - JOM(8, "%i=input sought\n", input); - - if (0 > input && INPUT_MANY <= input) - return -ENOENT; - inputnow = peasycap->input; - if (input == inputnow) - return 0; -/*---------------------------------------------------------------------------*/ -/* - * IF STREAMING IS IN PROGRESS THE URBS ARE KILLED AT THIS - * STAGE AND WILL BE RESUBMITTED PRIOR TO EXIT FROM THE ROUTINE. - * IF NO STREAMING IS IN PROGRESS NO URBS WILL BE SUBMITTED BY THE - * ROUTINE. -*/ -/*---------------------------------------------------------------------------*/ - video_idlenow = peasycap->video_idle; - audio_idlenow = peasycap->audio_idle; - - peasycap->video_idle = 1; - peasycap->audio_idle = 1; - if (peasycap->video_isoc_streaming) { - resubmit = true; - easycap_video_kill_urbs(peasycap); - } else { - resubmit = false; - } -/*---------------------------------------------------------------------------*/ - if (!peasycap->pusb_device) { - SAM("ERROR: peasycap->pusb_device is NULL\n"); - return -ENODEV; - } - rc = usb_set_interface(peasycap->pusb_device, - peasycap->video_interface, - peasycap->video_altsetting_off); - if (rc) { - SAM("ERROR: usb_set_interface() rc = %i\n", rc); - return -EFAULT; - } - rc = stop_100(peasycap->pusb_device); - if (rc) { - SAM("ERROR: stop_100() rc = %i\n", rc); - return -EFAULT; - } - for (k = 0; k < FIELD_BUFFER_MANY; k++) { - for (m = 0; m < FIELD_BUFFER_SIZE/PAGE_SIZE; m++) - memset(peasycap->field_buffer[k][m].pgo, 0, PAGE_SIZE); - } - for (k = 0; k < FRAME_BUFFER_MANY; k++) { - for (m = 0; m < FRAME_BUFFER_SIZE/PAGE_SIZE; m++) - memset(peasycap->frame_buffer[k][m].pgo, 0, PAGE_SIZE); - } - peasycap->field_page = 0; - peasycap->field_read = 0; - peasycap->field_fill = 0; - - peasycap->frame_read = 0; - peasycap->frame_fill = 0; - for (k = 0; k < peasycap->input; k++) { - (peasycap->frame_fill)++; - if (peasycap->frame_buffer_many <= peasycap->frame_fill) - peasycap->frame_fill = 0; - } - peasycap->input = input; - select_input(peasycap->pusb_device, peasycap->input, 9); -/*---------------------------------------------------------------------------*/ - if (input == peasycap->inputset[input].input) { - off = peasycap->inputset[input].standard_offset; - if (off != peasycap->standard_offset) { - rc = adjust_standard(peasycap, - easycap_standard[off].v4l2_standard.id); - if (rc) { - SAM("ERROR: adjust_standard() rc = %i\n", rc); - return -EFAULT; - } - JOM(8, "%i=peasycap->standard_offset\n", - peasycap->standard_offset); - } else { - JOM(8, "%i=peasycap->standard_offset unchanged\n", - peasycap->standard_offset); - } - off = peasycap->inputset[input].format_offset; - if (off != peasycap->format_offset) { - struct v4l2_pix_format *pix = - &easycap_format[off].v4l2_format.fmt.pix; - rc = adjust_format(peasycap, - pix->width, pix->height, - pix->pixelformat, pix->field, false); - if (0 > rc) { - SAM("ERROR: adjust_format() rc = %i\n", rc); - return -EFAULT; - } - JOM(8, "%i=peasycap->format_offset\n", - peasycap->format_offset); - } else { - JOM(8, "%i=peasycap->format_offset unchanged\n", - peasycap->format_offset); - } - mood = peasycap->inputset[input].brightness; - if (mood != peasycap->brightness) { - rc = adjust_brightness(peasycap, mood); - if (rc) { - SAM("ERROR: adjust_brightness rc = %i\n", rc); - return -EFAULT; - } - JOM(8, "%i=peasycap->brightness\n", - peasycap->brightness); - } - mood = peasycap->inputset[input].contrast; - if (mood != peasycap->contrast) { - rc = adjust_contrast(peasycap, mood); - if (rc) { - SAM("ERROR: adjust_contrast rc = %i\n", rc); - return -EFAULT; - } - JOM(8, "%i=peasycap->contrast\n", peasycap->contrast); - } - mood = peasycap->inputset[input].saturation; - if (mood != peasycap->saturation) { - rc = adjust_saturation(peasycap, mood); - if (rc) { - SAM("ERROR: adjust_saturation rc = %i\n", rc); - return -EFAULT; - } - JOM(8, "%i=peasycap->saturation\n", - peasycap->saturation); - } - mood = peasycap->inputset[input].hue; - if (mood != peasycap->hue) { - rc = adjust_hue(peasycap, mood); - if (rc) { - SAM("ERROR: adjust_hue rc = %i\n", rc); - return -EFAULT; - } - JOM(8, "%i=peasycap->hue\n", peasycap->hue); - } - } else { - SAM("MISTAKE: easycap.inputset[%i] unpopulated\n", input); - return -ENOENT; - } -/*---------------------------------------------------------------------------*/ - if (!peasycap->pusb_device) { - SAM("ERROR: peasycap->pusb_device is NULL\n"); - return -ENODEV; - } - rc = usb_set_interface(peasycap->pusb_device, - peasycap->video_interface, - peasycap->video_altsetting_on); - if (rc) { - SAM("ERROR: usb_set_interface() rc = %i\n", rc); - return -EFAULT; - } - rc = start_100(peasycap->pusb_device); - if (rc) { - SAM("ERROR: start_100() rc = %i\n", rc); - return -EFAULT; - } - if (resubmit) - easycap_video_submit_urbs(peasycap); - - peasycap->video_isoc_sequence = VIDEO_ISOC_BUFFER_MANY - 1; - peasycap->video_idle = video_idlenow; - peasycap->audio_idle = audio_idlenow; - peasycap->video_junk = 0; - - return 0; -} -/*****************************************************************************/ -int easycap_video_submit_urbs(struct easycap *peasycap) -{ - struct data_urb *pdata_urb; - struct urb *purb; - struct list_head *plist_head; - int j, isbad, nospc, m, rc; - int isbuf; - - if (!peasycap) { - SAY("ERROR: peasycap is NULL\n"); - return -EFAULT; - } - - if (!peasycap->purb_video_head) { - SAY("ERROR: peasycap->urb_video_head uninitialized\n"); - return -EFAULT; - } - if (!peasycap->pusb_device) { - SAY("ERROR: peasycap->pusb_device is NULL\n"); - return -ENODEV; - } - if (!peasycap->video_isoc_streaming) { - JOM(4, "submission of all video urbs\n"); - isbad = 0; nospc = 0; m = 0; - list_for_each(plist_head, (peasycap->purb_video_head)) { - pdata_urb = list_entry(plist_head, - struct data_urb, list_head); - if (pdata_urb && pdata_urb->purb) { - purb = pdata_urb->purb; - isbuf = pdata_urb->isbuf; - purb->interval = 1; - purb->dev = peasycap->pusb_device; - purb->pipe = - usb_rcvisocpipe(peasycap->pusb_device, - peasycap->video_endpointnumber); - purb->transfer_flags = URB_ISO_ASAP; - purb->transfer_buffer = - peasycap->video_isoc_buffer[isbuf].pgo; - purb->transfer_buffer_length = - peasycap->video_isoc_buffer_size; - purb->complete = easycap_complete; - purb->context = peasycap; - purb->start_frame = 0; - purb->number_of_packets = - peasycap->video_isoc_framesperdesc; - - for (j = 0; j < peasycap->video_isoc_framesperdesc; j++) { - purb->iso_frame_desc[j]. offset = - j * peasycap->video_isoc_maxframesize; - purb->iso_frame_desc[j]. length = - peasycap->video_isoc_maxframesize; - } - - rc = usb_submit_urb(purb, GFP_KERNEL); - if (rc) { - isbad++; - SAM("ERROR: usb_submit_urb() failed " - "for urb with rc:-%s\n", - strerror(rc)); - if (rc == -ENOSPC) - nospc++; - } else { - m++; - } - } else { - isbad++; - } - } - if (nospc) { - SAM("-ENOSPC=usb_submit_urb() for %i urbs\n", nospc); - SAM("..... possibly inadequate USB bandwidth\n"); - peasycap->video_eof = 1; - } - - if (isbad) - easycap_video_kill_urbs(peasycap); - else - peasycap->video_isoc_streaming = 1; - } else { - JOM(4, "already streaming video urbs\n"); - } - return 0; -} -/*****************************************************************************/ -int easycap_audio_kill_urbs(struct easycap *peasycap) -{ - int m; - struct list_head *plist_head; - struct data_urb *pdata_urb; - - if (!peasycap->audio_isoc_streaming) - return 0; - - if (!peasycap->purb_audio_head) { - SAM("ERROR: peasycap->purb_audio_head is NULL\n"); - return -EFAULT; - } - - peasycap->audio_isoc_streaming = 0; - m = 0; - list_for_each(plist_head, peasycap->purb_audio_head) { - pdata_urb = list_entry(plist_head, struct data_urb, list_head); - if (pdata_urb && pdata_urb->purb) { - usb_kill_urb(pdata_urb->purb); - m++; - } - } - - JOM(4, "%i audio urbs killed\n", m); - - return 0; -} -int easycap_video_kill_urbs(struct easycap *peasycap) -{ - int m; - struct list_head *plist_head; - struct data_urb *pdata_urb; - - if (!peasycap->video_isoc_streaming) - return 0; - - if (!peasycap->purb_video_head) { - SAM("ERROR: peasycap->purb_video_head is NULL\n"); - return -EFAULT; - } - - peasycap->video_isoc_streaming = 0; - JOM(4, "killing video urbs\n"); - m = 0; - list_for_each(plist_head, (peasycap->purb_video_head)) { - pdata_urb = list_entry(plist_head, struct data_urb, list_head); - if (pdata_urb && pdata_urb->purb) { - usb_kill_urb(pdata_urb->purb); - m++; - } - } - JOM(4, "%i video urbs killed\n", m); - - return 0; -} -/****************************************************************************/ -/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ -/*--------------------------------------------------------------------------*/ -static int easycap_open_noinode(struct file *file) -{ - return easycap_open(NULL, file); -} - -static int videodev_release(struct video_device *pvideo_device) -{ - struct easycap *peasycap; - - peasycap = video_get_drvdata(pvideo_device); - if (!peasycap) { - SAY("ERROR: peasycap is NULL\n"); - SAY("ending unsuccessfully\n"); - return -EFAULT; - } - if (easycap_video_kill_urbs(peasycap)) { - SAM("ERROR: easycap_video_kill_urbs() failed\n"); - return -EFAULT; - } - JOM(4, "ending successfully\n"); - return 0; -} - -/*****************************************************************************/ -static unsigned int easycap_poll(struct file *file, poll_table *wait) -{ - struct easycap *peasycap; - int rc, kd; - - JOT(8, "\n"); - - if (NULL == ((poll_table *)wait)) - JOT(8, "WARNING: poll table pointer is NULL ... continuing\n"); - if (!file) { - SAY("ERROR: file pointer is NULL\n"); - return -ERESTARTSYS; - } - peasycap = file->private_data; - if (!peasycap) { - SAY("ERROR: peasycap is NULL\n"); - return -EFAULT; - } - if (!peasycap->pusb_device) { - SAY("ERROR: peasycap->pusb_device is NULL\n"); - return -EFAULT; - } -/*---------------------------------------------------------------------------*/ - kd = easycap_isdongle(peasycap); - if (0 <= kd && DONGLE_MANY > kd) { - if (mutex_lock_interruptible(&easycapdc60_dongle[kd].mutex_video)) { - SAY("ERROR: cannot down dongle[%i].mutex_video\n", kd); - return -ERESTARTSYS; - } - JOM(4, "locked dongle[%i].mutex_video\n", kd); - /* - * MEANWHILE, easycap_usb_disconnect() MAY HAVE FREED POINTER - * peasycap, IN WHICH CASE A REPEAT CALL TO isdongle() WILL FAIL. - * IF NECESSARY, BAIL OUT. - */ - if (kd != easycap_isdongle(peasycap)) { - mutex_unlock(&easycapdc60_dongle[kd].mutex_video); - return -ERESTARTSYS; - } - if (!file) { - SAY("ERROR: file is NULL\n"); - mutex_unlock(&easycapdc60_dongle[kd].mutex_video); - return -ERESTARTSYS; - } - peasycap = file->private_data; - if (!peasycap) { - SAY("ERROR: peasycap is NULL\n"); - mutex_unlock(&easycapdc60_dongle[kd].mutex_video); - return -ERESTARTSYS; - } - if (!peasycap->pusb_device) { - SAM("ERROR: peasycap->pusb_device is NULL\n"); - mutex_unlock(&easycapdc60_dongle[kd].mutex_video); - return -ERESTARTSYS; - } - } else - /* - * IF easycap_usb_disconnect() HAS ALREADY FREED POINTER peasycap - * BEFORE THE ATTEMPT TO ACQUIRE THE SEMAPHORE, isdongle() WILL - * HAVE FAILED. BAIL OUT. - */ - return -ERESTARTSYS; -/*---------------------------------------------------------------------------*/ - rc = easycap_video_dqbuf(peasycap, 0); - peasycap->polled = 1; - mutex_unlock(&easycapdc60_dongle[kd].mutex_video); - if (rc) - return POLLERR; - - return POLLIN | POLLRDNORM; -} -/*****************************************************************************/ -/*---------------------------------------------------------------------------*/ -/* - * IF mode IS NONZERO THIS ROUTINE RETURNS -EAGAIN RATHER THAN BLOCKING. - */ -/*---------------------------------------------------------------------------*/ -int easycap_video_dqbuf(struct easycap *peasycap, int mode) -{ - int input, ifield, miss, rc; - - - if (!peasycap) { - SAY("ERROR: peasycap is NULL\n"); - return -EFAULT; - } - if (!peasycap->pusb_device) { - SAY("ERROR: peasycap->pusb_device is NULL\n"); - return -EFAULT; - } - ifield = 0; - JOM(8, "%i=ifield\n", ifield); -/*---------------------------------------------------------------------------*/ -/* - * CHECK FOR LOST INPUT SIGNAL. - * - * FOR THE FOUR-CVBS EasyCAP, THIS DOES NOT WORK AS EXPECTED. - * IF INPUT 0 IS PRESENT AND SYNC ACQUIRED, UNPLUGGING INPUT 4 DOES NOT - * RESULT IN SETTING BIT 0x40 ON REGISTER 0x1F, PRESUMABLY BECAUSE THERE - * IS FLYWHEELING ON INPUT 0. THE UPSHOT IS: - * - * INPUT 0 PLUGGED, INPUT 4 PLUGGED => SCREEN 0 OK, SCREEN 4 OK - * INPUT 0 PLUGGED, INPUT 4 UNPLUGGED => SCREEN 0 OK, SCREEN 4 BLACK - * INPUT 0 UNPLUGGED, INPUT 4 PLUGGED => SCREEN 0 BARS, SCREEN 4 OK - * INPUT 0 UNPLUGGED, INPUT 4 UNPLUGGED => SCREEN 0 BARS, SCREEN 4 BARS -*/ -/*---------------------------------------------------------------------------*/ - input = peasycap->input; - if (0 <= input && INPUT_MANY > input) { - rc = read_saa(peasycap->pusb_device, 0x1F); - if (0 <= rc) { - if (rc & 0x40) - peasycap->lost[input] += 1; - else - peasycap->lost[input] -= 2; - - if (0 > peasycap->lost[input]) - peasycap->lost[input] = 0; - else if ((2 * VIDEO_LOST_TOLERATE) < peasycap->lost[input]) - peasycap->lost[input] = (2 * VIDEO_LOST_TOLERATE); - } - } -/*---------------------------------------------------------------------------*/ -/* - * WAIT FOR FIELD ifield (0 => TOP, 1 => BOTTOM) - */ -/*---------------------------------------------------------------------------*/ - miss = 0; - while ((peasycap->field_read == peasycap->field_fill) || - (0 != (0xFF00 & peasycap->field_buffer - [peasycap->field_read][0].kount)) || - (ifield != (0x00FF & peasycap->field_buffer - [peasycap->field_read][0].kount))) { - if (mode) - return -EAGAIN; - - JOM(8, "first wait on wq_video, %i=field_read %i=field_fill\n", - peasycap->field_read, peasycap->field_fill); - - if (0 != (wait_event_interruptible(peasycap->wq_video, - (peasycap->video_idle || peasycap->video_eof || - ((peasycap->field_read != peasycap->field_fill) && - (0 == (0xFF00 & peasycap->field_buffer[peasycap->field_read][0].kount)) && - (ifield == (0x00FF & peasycap->field_buffer[peasycap->field_read][0].kount))))))) { - SAM("aborted by signal\n"); - return -EIO; - } - if (peasycap->video_idle) { - JOM(8, "%i=peasycap->video_idle returning -EAGAIN\n", - peasycap->video_idle); - return -EAGAIN; - } - if (peasycap->video_eof) { - JOM(8, "%i=peasycap->video_eof\n", peasycap->video_eof); - #if defined(PERSEVERE) - if (1 == peasycap->status) { - JOM(8, "persevering ...\n"); - peasycap->video_eof = 0; - peasycap->audio_eof = 0; - if (0 != reset(peasycap)) { - JOM(8, " ... failed returning -EIO\n"); - peasycap->video_eof = 1; - peasycap->audio_eof = 1; - easycap_video_kill_urbs(peasycap); - return -EIO; - } - peasycap->status = 0; - JOM(8, " ... OK returning -EAGAIN\n"); - return -EAGAIN; - } - #endif /*PERSEVERE*/ - peasycap->video_eof = 1; - peasycap->audio_eof = 1; - easycap_video_kill_urbs(peasycap); - JOM(8, "returning -EIO\n"); - return -EIO; - } - miss++; - } - JOM(8, "first awakening on wq_video after %i waits\n", miss); - - rc = field2frame(peasycap); - if (rc) - SAM("ERROR: field2frame() rc = %i\n", rc); -/*---------------------------------------------------------------------------*/ -/* - * WAIT FOR THE OTHER FIELD - */ -/*---------------------------------------------------------------------------*/ - if (ifield) - ifield = 0; - else - ifield = 1; - miss = 0; - while ((peasycap->field_read == peasycap->field_fill) || - (0 != (0xFF00 & peasycap->field_buffer[peasycap->field_read][0].kount)) || - (ifield != (0x00FF & peasycap->field_buffer[peasycap->field_read][0].kount))) { - if (mode) - return -EAGAIN; - - JOM(8, "second wait on wq_video %i=field_read %i=field_fill\n", - peasycap->field_read, peasycap->field_fill); - if (0 != (wait_event_interruptible(peasycap->wq_video, - (peasycap->video_idle || peasycap->video_eof || - ((peasycap->field_read != peasycap->field_fill) && - (0 == (0xFF00 & peasycap->field_buffer[peasycap->field_read][0].kount)) && - (ifield == (0x00FF & peasycap->field_buffer[peasycap->field_read][0].kount))))))) { - SAM("aborted by signal\n"); - return -EIO; - } - if (peasycap->video_idle) { - JOM(8, "%i=peasycap->video_idle returning -EAGAIN\n", - peasycap->video_idle); - return -EAGAIN; - } - if (peasycap->video_eof) { - JOM(8, "%i=peasycap->video_eof\n", peasycap->video_eof); -#if defined(PERSEVERE) - if (1 == peasycap->status) { - JOM(8, "persevering ...\n"); - peasycap->video_eof = 0; - peasycap->audio_eof = 0; - if (0 != reset(peasycap)) { - JOM(8, " ... failed returning -EIO\n"); - peasycap->video_eof = 1; - peasycap->audio_eof = 1; - easycap_video_kill_urbs(peasycap); - return -EIO; - } - peasycap->status = 0; - JOM(8, " ... OK ... returning -EAGAIN\n"); - return -EAGAIN; - } -#endif /*PERSEVERE*/ - peasycap->video_eof = 1; - peasycap->audio_eof = 1; - easycap_video_kill_urbs(peasycap); - JOM(8, "returning -EIO\n"); - return -EIO; - } - miss++; - } - JOM(8, "second awakening on wq_video after %i waits\n", miss); - - rc = field2frame(peasycap); - if (rc) - SAM("ERROR: field2frame() rc = %i\n", rc); -/*---------------------------------------------------------------------------*/ -/* - * WASTE THIS FRAME -*/ -/*---------------------------------------------------------------------------*/ - if (peasycap->skip) { - peasycap->skipped++; - if (peasycap->skip != peasycap->skipped) - return peasycap->skip - peasycap->skipped; - else - peasycap->skipped = 0; - } -/*---------------------------------------------------------------------------*/ - peasycap->frame_read = peasycap->frame_fill; - peasycap->queued[peasycap->frame_read] = 0; - peasycap->done[peasycap->frame_read] = V4L2_BUF_FLAG_DONE; - - peasycap->frame_fill++; - if (peasycap->frame_buffer_many <= peasycap->frame_fill) - peasycap->frame_fill = 0; - - if (0x01 & easycap_standard[peasycap->standard_offset].mask) - peasycap->frame_buffer[peasycap->frame_read][0].kount = - V4L2_FIELD_TOP; - else - peasycap->frame_buffer[peasycap->frame_read][0].kount = - V4L2_FIELD_BOTTOM; - - - JOM(8, "setting: %i=peasycap->frame_read\n", peasycap->frame_read); - JOM(8, "bumped to: %i=peasycap->frame_fill\n", peasycap->frame_fill); - - return 0; -} -/*****************************************************************************/ -/*---------------------------------------------------------------------------*/ -/* - * BY DEFINITION, odd IS true FOR THE FIELD OCCUPYING LINES 1,3,5,...,479 - * odd IS false FOR THE FIELD OCCUPYING LINES 0,2,4,...,478 - * - * WHEN BOOLEAN PARAMETER decimatepixel IS true, ONLY THE FIELD FOR WHICH - * odd==false IS TRANSFERRED TO THE FRAME BUFFER. - * - */ -/*---------------------------------------------------------------------------*/ -static int field2frame(struct easycap *peasycap) -{ - - void *pex, *pad; - int kex, kad, mex, mad, rex, rad, rad2; - int c2, c3, w2, w3, cz, wz; - int rc, bytesperpixel, multiplier; - int much, more, over, rump, caches, input; - u8 mask, margin; - bool odd, isuy, decimatepixel, badinput; - - if (!peasycap) { - SAY("ERROR: peasycap is NULL\n"); - return -EFAULT; - } - - badinput = false; - input = 0x07 & peasycap->field_buffer[peasycap->field_read][0].input; - - JOM(8, "===== parity %i, input 0x%02X, field buffer %i --> " - "frame buffer %i\n", - peasycap->field_buffer[peasycap->field_read][0].kount, - peasycap->field_buffer[peasycap->field_read][0].input, - peasycap->field_read, peasycap->frame_fill); - JOM(8, "===== %i=bytesperpixel\n", peasycap->bytesperpixel); - -/*---------------------------------------------------------------------------*/ -/* - * REJECT OR CLEAN BAD FIELDS - */ -/*---------------------------------------------------------------------------*/ - if (peasycap->field_read == peasycap->field_fill) { - SAM("ERROR: on entry, still filling field buffer %i\n", - peasycap->field_read); - return 0; - } -#ifdef EASYCAP_TESTCARD - easycap_testcard(peasycap, peasycap->field_read); -#else - if (0 <= input && INPUT_MANY > input) { - if (easycap_bars && VIDEO_LOST_TOLERATE <= peasycap->lost[input]) - easycap_testcard(peasycap, peasycap->field_read); - } -#endif /*EASYCAP_TESTCARD*/ -/*---------------------------------------------------------------------------*/ - - bytesperpixel = peasycap->bytesperpixel; - decimatepixel = peasycap->decimatepixel; - - if ((2 != bytesperpixel) && - (3 != bytesperpixel) && - (4 != bytesperpixel)) { - SAM("MISTAKE: %i=bytesperpixel\n", bytesperpixel); - return -EFAULT; - } - if (decimatepixel) - multiplier = 2; - else - multiplier = 1; - - w2 = 2 * multiplier * (peasycap->width); - w3 = bytesperpixel * multiplier * (peasycap->width); - wz = multiplier * (peasycap->height) * - multiplier * (peasycap->width); - - kex = peasycap->field_read; mex = 0; - kad = peasycap->frame_fill; mad = 0; - - pex = peasycap->field_buffer[kex][0].pgo; rex = PAGE_SIZE; - pad = peasycap->frame_buffer[kad][0].pgo; rad = PAGE_SIZE; - odd = !!(peasycap->field_buffer[kex][0].kount); - - if (odd && (!decimatepixel)) { - JOM(8, "initial skipping %4i bytes p.%4i\n", - w3/multiplier, mad); - pad += (w3 / multiplier); rad -= (w3 / multiplier); - } - isuy = true; - mask = 0; rump = 0; caches = 0; - - cz = 0; - while (cz < wz) { - /* - * PROCESS ONE LINE OF FRAME AT FULL RESOLUTION: - * READ w2 BYTES FROM FIELD BUFFER, - * WRITE w3 BYTES TO FRAME BUFFER - */ - if (!decimatepixel) { - over = w2; - do { - much = over; more = 0; - margin = 0; mask = 0x00; - if (rex < much) - much = rex; - rump = 0; - - if (much % 2) { - SAM("MISTAKE: much is odd\n"); - return -EFAULT; - } - - more = (bytesperpixel * - much) / 2; -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - if (1 < bytesperpixel) { - if (rad * 2 < much * bytesperpixel) { - /* - * INJUDICIOUS ALTERATION OF - * THIS STATEMENT BLOCK WILL - * CAUSE BREAKAGE. BEWARE. - */ - rad2 = rad + bytesperpixel - 1; - much = ((((2 * rad2)/bytesperpixel)/2) * 2); - rump = ((bytesperpixel * much) / 2) - rad; - more = rad; - } - mask = (u8)rump; - margin = 0; - if (much == rex) { - mask |= 0x04; - if ((mex + 1) < FIELD_BUFFER_SIZE / PAGE_SIZE) - margin = *((u8 *)(peasycap->field_buffer[kex][mex + 1].pgo)); - else - mask |= 0x08; - } - } else { - SAM("MISTAKE: %i=bytesperpixel\n", - bytesperpixel); - return -EFAULT; - } - if (rump) - caches++; - if (badinput) { - JOM(8, "ERROR: 0x%02X=->field_buffer" - "[%i][%i].input, " - "0x%02X=(0x08|->input)\n", - peasycap->field_buffer - [kex][mex].input, kex, mex, - (0x08|peasycap->input)); - } - rc = redaub(peasycap, pad, pex, much, more, - mask, margin, isuy); - if (0 > rc) { - SAM("ERROR: redaub() failed\n"); - return -EFAULT; - } - if (much % 4) - isuy = !isuy; - - over -= much; cz += much; - pex += much; rex -= much; - if (!rex) { - mex++; - pex = peasycap->field_buffer[kex][mex].pgo; - rex = PAGE_SIZE; - if (peasycap->field_buffer[kex][mex].input != (0x08|peasycap->input)) - badinput = true; - } - pad += more; - rad -= more; - if (!rad) { - mad++; - pad = peasycap->frame_buffer[kad][mad].pgo; - rad = PAGE_SIZE; - if (rump) { - pad += rump; - rad -= rump; - } - } - } while (over); -/*---------------------------------------------------------------------------*/ -/* - * SKIP w3 BYTES IN TARGET FRAME BUFFER, - * UNLESS IT IS THE LAST LINE OF AN ODD FRAME - */ -/*---------------------------------------------------------------------------*/ - if (!odd || (cz != wz)) { - over = w3; - do { - if (!rad) { - mad++; - pad = peasycap->frame_buffer - [kad][mad].pgo; - rad = PAGE_SIZE; - } - more = over; - if (rad < more) - more = rad; - over -= more; - pad += more; - rad -= more; - } while (over); - } -/*---------------------------------------------------------------------------*/ -/* - * PROCESS ONE LINE OF FRAME AT REDUCED RESOLUTION: - * ONLY IF false==odd, - * READ w2 BYTES FROM FIELD BUFFER, - * WRITE w3 / 2 BYTES TO FRAME BUFFER - */ -/*---------------------------------------------------------------------------*/ - } else if (!odd) { - over = w2; - do { - much = over; more = 0; margin = 0; mask = 0x00; - if (rex < much) - much = rex; - rump = 0; - - if (much % 2) { - SAM("MISTAKE: much is odd\n"); - return -EFAULT; - } - - more = (bytesperpixel * much) / 4; -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - if (1 < bytesperpixel) { - if (rad * 4 < much * bytesperpixel) { - /* - * INJUDICIOUS ALTERATION OF - * THIS STATEMENT BLOCK - * WILL CAUSE BREAKAGE. - * BEWARE. - */ - rad2 = rad + bytesperpixel - 1; - much = ((((2 * rad2) / bytesperpixel) / 2) * 4); - rump = ((bytesperpixel * much) / 4) - rad; - more = rad; - } - mask = (u8)rump; - margin = 0; - if (much == rex) { - mask |= 0x04; - if ((mex + 1) < FIELD_BUFFER_SIZE / PAGE_SIZE) - margin = *((u8 *)(peasycap->field_buffer[kex][mex + 1].pgo)); - else - mask |= 0x08; - } -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - } else { - SAM("MISTAKE: %i=bytesperpixel\n", - bytesperpixel); - return -EFAULT; - } -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - if (rump) - caches++; - - if (badinput) { - JOM(8, "ERROR: 0x%02X=->field_buffer" - "[%i][%i].input, " - "0x%02X=(0x08|->input)\n", - peasycap->field_buffer - [kex][mex].input, kex, mex, - (0x08|peasycap->input)); - } - rc = redaub(peasycap, pad, pex, much, more, - mask, margin, isuy); - if (0 > rc) { - SAM("ERROR: redaub() failed\n"); - return -EFAULT; - } - over -= much; cz += much; - pex += much; rex -= much; - if (!rex) { - mex++; - pex = peasycap->field_buffer[kex][mex].pgo; - rex = PAGE_SIZE; - if (peasycap->field_buffer[kex][mex].input != - (0x08|peasycap->input)) - badinput = true; - } - pad += more; - rad -= more; - if (!rad) { - mad++; - pad = peasycap->frame_buffer[kad][mad].pgo; - rad = PAGE_SIZE; - if (rump) { - pad += rump; - rad -= rump; - } - } - } while (over); -/*---------------------------------------------------------------------------*/ -/* - * OTHERWISE JUST - * READ w2 BYTES FROM FIELD BUFFER AND DISCARD THEM - */ -/*---------------------------------------------------------------------------*/ - } else { - over = w2; - do { - if (!rex) { - mex++; - pex = peasycap->field_buffer[kex][mex].pgo; - rex = PAGE_SIZE; - if (peasycap->field_buffer[kex][mex].input != - (0x08|peasycap->input)) { - JOM(8, "ERROR: 0x%02X=->field_buffer" - "[%i][%i].input, " - "0x%02X=(0x08|->input)\n", - peasycap->field_buffer - [kex][mex].input, kex, mex, - (0x08|peasycap->input)); - badinput = true; - } - } - much = over; - if (rex < much) - much = rex; - over -= much; - cz += much; - pex += much; - rex -= much; - } while (over); - } - } -/*---------------------------------------------------------------------------*/ -/* - * SANITY CHECKS - */ -/*---------------------------------------------------------------------------*/ - c2 = (mex + 1)*PAGE_SIZE - rex; - if (cz != c2) - SAM("ERROR: discrepancy %i in bytes read\n", c2 - cz); - c3 = (mad + 1)*PAGE_SIZE - rad; - - if (!decimatepixel) { - if (bytesperpixel * cz != c3) - SAM("ERROR: discrepancy %i in bytes written\n", - c3 - (bytesperpixel * cz)); - } else { - if (!odd) { - if (bytesperpixel * - cz != (4 * c3)) - SAM("ERROR: discrepancy %i in bytes written\n", - (2*c3)-(bytesperpixel * cz)); - } else { - if (0 != c3) - SAM("ERROR: discrepancy %i " - "in bytes written\n", c3); - } - } - if (rump) - SAM("WORRY: undischarged cache at end of line in frame buffer\n"); - - JOM(8, "===== field2frame(): %i bytes --> %i bytes (incl skip)\n", c2, c3); - JOM(8, "===== field2frame(): %i=mad %i=rad\n", mad, rad); - - if (odd) - JOM(8, "+++++ field2frame(): frame buffer %i is full\n", kad); - - if (peasycap->field_read == peasycap->field_fill) - SAM("WARNING: on exit, filling field buffer %i\n", - peasycap->field_read); - - if (caches) - JOM(8, "%i=caches\n", caches); - return 0; -} -/*---------------------------------------------------------------------------*/ -/* - * DECIMATION AND COLOURSPACE CONVERSION. - * - * THIS ROUTINE REQUIRES THAT ALL THE DATA TO BE READ RESIDES ON ONE PAGE - * AND THAT ALL THE DATA TO BE WRITTEN RESIDES ON ONE (DIFFERENT) PAGE. - * THE CALLING ROUTINE MUST ENSURE THAT THIS REQUIREMENT IS MET, AND MUST - * ALSO ENSURE THAT much IS EVEN. - * - * much BYTES ARE READ, AT LEAST (bytesperpixel * much)/2 BYTES ARE WRITTEN - * IF THERE IS NO DECIMATION, HALF THIS AMOUNT IF THERE IS DECIMATION. - * - * mask IS ZERO WHEN NO SPECIAL BEHAVIOUR REQUIRED. OTHERWISE IT IS SET THUS: - * 0x03 & mask = number of bytes to be written to cache instead of to - * frame buffer - * 0x04 & mask => use argument margin to set the chrominance for last pixel - * 0x08 & mask => do not set the chrominance for last pixel - * - * YUV to RGB CONVERSION IS (OR SHOULD BE) ITU-R BT 601. - * - * THERE IS A LOT OF CODE REPETITION IN THIS ROUTINE IN ORDER TO AVOID - * INEFFICIENT SWITCHING INSIDE INNER LOOPS. REARRANGING THE LOGIC TO - * REDUCE CODE LENGTH WILL GENERALLY IMPAIR RUNTIME PERFORMANCE. BEWARE. - */ -/*---------------------------------------------------------------------------*/ -static int redaub(struct easycap *peasycap, - void *pad, void *pex, int much, int more, - u8 mask, u8 margin, bool isuy) -{ - static s32 ay[256], bu[256], rv[256], gu[256], gv[256]; - u8 *pcache; - u8 r, g, b, y, u, v, c, *p2, *p3, *pz, *pr; - int bytesperpixel; - bool byteswaporder, decimatepixel, last; - int j, rump; - s32 tmp; - - if (much % 2) { - SAM("MISTAKE: much is odd\n"); - return -EFAULT; - } - bytesperpixel = peasycap->bytesperpixel; - byteswaporder = peasycap->byteswaporder; - decimatepixel = peasycap->decimatepixel; - -/*---------------------------------------------------------------------------*/ - if (!bu[255]) { - for (j = 0; j < 112; j++) { - tmp = (0xFF00 & (453 * j)) >> 8; - bu[j + 128] = tmp; bu[127 - j] = -tmp; - tmp = (0xFF00 & (359 * j)) >> 8; - rv[j + 128] = tmp; rv[127 - j] = -tmp; - tmp = (0xFF00 & (88 * j)) >> 8; - gu[j + 128] = tmp; gu[127 - j] = -tmp; - tmp = (0xFF00 & (183 * j)) >> 8; - gv[j + 128] = tmp; gv[127 - j] = -tmp; - } - for (j = 0; j < 16; j++) { - bu[j] = bu[16]; rv[j] = rv[16]; - gu[j] = gu[16]; gv[j] = gv[16]; - } - for (j = 240; j < 256; j++) { - bu[j] = bu[239]; rv[j] = rv[239]; - gu[j] = gu[239]; gv[j] = gv[239]; - } - for (j = 16; j < 236; j++) - ay[j] = j; - for (j = 0; j < 16; j++) - ay[j] = ay[16]; - for (j = 236; j < 256; j++) - ay[j] = ay[235]; - JOM(8, "lookup tables are prepared\n"); - } - pcache = peasycap->pcache; - if (!pcache) - pcache = &peasycap->cache[0]; -/*---------------------------------------------------------------------------*/ -/* - * TRANSFER CONTENTS OF CACHE TO THE FRAME BUFFER - */ -/*---------------------------------------------------------------------------*/ - if (!pcache) { - SAM("MISTAKE: pcache is NULL\n"); - return -EFAULT; - } - - if (pcache != &peasycap->cache[0]) - JOM(16, "cache has %i bytes\n", (int)(pcache - &peasycap->cache[0])); - p2 = &peasycap->cache[0]; - p3 = (u8 *)pad - (int)(pcache - &peasycap->cache[0]); - while (p2 < pcache) { - *p3++ = *p2; p2++; - } - pcache = &peasycap->cache[0]; - if (p3 != pad) { - SAM("MISTAKE: pointer misalignment\n"); - return -EFAULT; - } -/*---------------------------------------------------------------------------*/ - rump = (int)(0x03 & mask); - u = 0; v = 0; - p2 = (u8 *)pex; pz = p2 + much; pr = p3 + more; last = false; - p2++; - - if (isuy) - u = *(p2 - 1); - else - v = *(p2 - 1); - - if (rump) - JOM(16, "%4i=much %4i=more %i=rump\n", much, more, rump); - -/*---------------------------------------------------------------------------*/ - switch (bytesperpixel) { - case 2: { - if (!decimatepixel) { - memcpy(pad, pex, (size_t)much); - if (!byteswaporder) { - /* UYVY */ - return 0; - } else { - /* YUYV */ - p3 = (u8 *)pad; pz = p3 + much; - while (pz > p3) { - c = *p3; - *p3 = *(p3 + 1); - *(p3 + 1) = c; - p3 += 2; - } - return 0; - } - } else { - if (!byteswaporder) { - /* UYVY DECIMATED */ - p2 = (u8 *)pex; p3 = (u8 *)pad; pz = p2 + much; - while (pz > p2) { - *p3 = *p2; - *(p3 + 1) = *(p2 + 1); - *(p3 + 2) = *(p2 + 2); - *(p3 + 3) = *(p2 + 3); - p3 += 4; p2 += 8; - } - return 0; - } else { - /* YUYV DECIMATED */ - p2 = (u8 *)pex; p3 = (u8 *)pad; pz = p2 + much; - while (pz > p2) { - *p3 = *(p2 + 1); - *(p3 + 1) = *p2; - *(p3 + 2) = *(p2 + 3); - *(p3 + 3) = *(p2 + 2); - p3 += 4; p2 += 8; - } - return 0; - } - } - break; - } - case 3: - { - if (!decimatepixel) { - if (!byteswaporder) { - /* RGB */ - while (pz > p2) { - if (pr <= (p3 + bytesperpixel)) - last = true; - else - last = false; - y = *p2; - if (last && (0x0C & mask)) { - if (0x04 & mask) { - if (isuy) - v = margin; - else - u = margin; - } else - if (0x08 & mask) - ; - } else { - if (isuy) - v = *(p2 + 1); - else - u = *(p2 + 1); - } - - tmp = ay[(int)y] + rv[(int)v]; - r = (255 < tmp) ? 255 : ((0 > tmp) ? - 0 : (u8)tmp); - tmp = ay[(int)y] - gu[(int)u] - gv[(int)v]; - g = (255 < tmp) ? 255 : ((0 > tmp) ? - 0 : (u8)tmp); - tmp = ay[(int)y] + bu[(int)u]; - b = (255 < tmp) ? 255 : ((0 > tmp) ? - 0 : (u8)tmp); - - if (last && rump) { - pcache = &peasycap->cache[0]; - switch (bytesperpixel - rump) { - case 1: { - *p3 = r; - *pcache++ = g; - *pcache++ = b; - break; - } - case 2: { - *p3 = r; - *(p3 + 1) = g; - *pcache++ = b; - break; - } - default: { - SAM("MISTAKE: %i=rump\n", - bytesperpixel - rump); - return -EFAULT; - } - } - } else { - *p3 = r; - *(p3 + 1) = g; - *(p3 + 2) = b; - } - p2 += 2; - if (isuy) - isuy = false; - else - isuy = true; - p3 += bytesperpixel; - } - return 0; - } else { - /* BGR */ - while (pz > p2) { - if (pr <= (p3 + bytesperpixel)) - last = true; - else - last = false; - y = *p2; - if (last && (0x0C & mask)) { - if (0x04 & mask) { - if (isuy) - v = margin; - else - u = margin; - } - else - if (0x08 & mask) - ; - } else { - if (isuy) - v = *(p2 + 1); - else - u = *(p2 + 1); - } - - tmp = ay[(int)y] + rv[(int)v]; - r = (255 < tmp) ? 255 : ((0 > tmp) ? - 0 : (u8)tmp); - tmp = ay[(int)y] - gu[(int)u] - gv[(int)v]; - g = (255 < tmp) ? 255 : ((0 > tmp) ? - 0 : (u8)tmp); - tmp = ay[(int)y] + bu[(int)u]; - b = (255 < tmp) ? 255 : ((0 > tmp) ? - 0 : (u8)tmp); - - if (last && rump) { - pcache = &peasycap->cache[0]; - switch (bytesperpixel - rump) { - case 1: { - *p3 = b; - *pcache++ = g; - *pcache++ = r; - break; - } - case 2: { - *p3 = b; - *(p3 + 1) = g; - *pcache++ = r; - break; - } - default: { - SAM("MISTAKE: %i=rump\n", - bytesperpixel - rump); - return -EFAULT; - } - } - } else { - *p3 = b; - *(p3 + 1) = g; - *(p3 + 2) = r; - } - p2 += 2; - if (isuy) - isuy = false; - else - isuy = true; - p3 += bytesperpixel; - } - } - return 0; - } else { - if (!byteswaporder) { - /* RGB DECIMATED */ - while (pz > p2) { - if (pr <= (p3 + bytesperpixel)) - last = true; - else - last = false; - y = *p2; - if (last && (0x0C & mask)) { - if (0x04 & mask) { - if (isuy) - v = margin; - else - u = margin; - } else - if (0x08 & mask) - ; - } else { - if (isuy) - v = *(p2 + 1); - else - u = *(p2 + 1); - } - - if (isuy) { - tmp = ay[(int)y] + rv[(int)v]; - r = (255 < tmp) ? 255 : ((0 > tmp) ? - 0 : (u8)tmp); - tmp = ay[(int)y] - gu[(int)u] - - gv[(int)v]; - g = (255 < tmp) ? 255 : ((0 > tmp) ? - 0 : (u8)tmp); - tmp = ay[(int)y] + bu[(int)u]; - b = (255 < tmp) ? 255 : ((0 > tmp) ? - 0 : (u8)tmp); - - if (last && rump) { - pcache = &peasycap->cache[0]; - switch (bytesperpixel - rump) { - case 1: { - *p3 = r; - *pcache++ = g; - *pcache++ = b; - break; - } - case 2: { - *p3 = r; - *(p3 + 1) = g; - *pcache++ = b; - break; - } - default: { - SAM("MISTAKE: " - "%i=rump\n", - bytesperpixel - rump); - return -EFAULT; - } - } - } else { - *p3 = r; - *(p3 + 1) = g; - *(p3 + 2) = b; - } - isuy = false; - p3 += bytesperpixel; - } else { - isuy = true; - } - p2 += 2; - } - return 0; - } else { - /* BGR DECIMATED */ - while (pz > p2) { - if (pr <= (p3 + bytesperpixel)) - last = true; - else - last = false; - y = *p2; - if (last && (0x0C & mask)) { - if (0x04 & mask) { - if (isuy) - v = margin; - else - u = margin; - } else - if (0x08 & mask) - ; - } else { - if (isuy) - v = *(p2 + 1); - else - u = *(p2 + 1); - } - - if (isuy) { - - tmp = ay[(int)y] + rv[(int)v]; - r = (255 < tmp) ? 255 : ((0 > tmp) ? - 0 : (u8)tmp); - tmp = ay[(int)y] - gu[(int)u] - - gv[(int)v]; - g = (255 < tmp) ? 255 : ((0 > tmp) ? - 0 : (u8)tmp); - tmp = ay[(int)y] + bu[(int)u]; - b = (255 < tmp) ? 255 : ((0 > tmp) ? - 0 : (u8)tmp); - - if (last && rump) { - pcache = &peasycap->cache[0]; - switch (bytesperpixel - rump) { - case 1: { - *p3 = b; - *pcache++ = g; - *pcache++ = r; - break; - } - case 2: { - *p3 = b; - *(p3 + 1) = g; - *pcache++ = r; - break; - } - default: { - SAM("MISTAKE: " - "%i=rump\n", - bytesperpixel - rump); - return -EFAULT; - } - } - } else { - *p3 = b; - *(p3 + 1) = g; - *(p3 + 2) = r; - } - isuy = false; - p3 += bytesperpixel; - } - else - isuy = true; - p2 += 2; - } - return 0; - } - } - break; - } - case 4: - { - if (!decimatepixel) { - if (!byteswaporder) { - /* RGBA */ - while (pz > p2) { - if (pr <= (p3 + bytesperpixel)) - last = true; - else - last = false; - y = *p2; - if (last && (0x0C & mask)) { - if (0x04 & mask) { - if (isuy) - v = margin; - else - u = margin; - } else - if (0x08 & mask) - ; - } else { - if (isuy) - v = *(p2 + 1); - else - u = *(p2 + 1); - } - - tmp = ay[(int)y] + rv[(int)v]; - r = (255 < tmp) ? 255 : ((0 > tmp) ? - 0 : (u8)tmp); - tmp = ay[(int)y] - gu[(int)u] - gv[(int)v]; - g = (255 < tmp) ? 255 : ((0 > tmp) ? - 0 : (u8)tmp); - tmp = ay[(int)y] + bu[(int)u]; - b = (255 < tmp) ? 255 : ((0 > tmp) ? - 0 : (u8)tmp); - - if (last && rump) { - pcache = &peasycap->cache[0]; - switch (bytesperpixel - rump) { - case 1: { - *p3 = r; - *pcache++ = g; - *pcache++ = b; - *pcache++ = 0; - break; - } - case 2: { - *p3 = r; - *(p3 + 1) = g; - *pcache++ = b; - *pcache++ = 0; - break; - } - case 3: { - *p3 = r; - *(p3 + 1) = g; - *(p3 + 2) = b; - *pcache++ = 0; - break; - } - default: { - SAM("MISTAKE: %i=rump\n", - bytesperpixel - rump); - return -EFAULT; - } - } - } else { - *p3 = r; - *(p3 + 1) = g; - *(p3 + 2) = b; - *(p3 + 3) = 0; - } - p2 += 2; - if (isuy) - isuy = false; - else - isuy = true; - p3 += bytesperpixel; - } - return 0; - } else { - /* - * BGRA - */ - while (pz > p2) { - if (pr <= (p3 + bytesperpixel)) - last = true; - else - last = false; - y = *p2; - if (last && (0x0C & mask)) { - if (0x04 & mask) { - if (isuy) - v = margin; - else - u = margin; - } else - if (0x08 & mask) - ; - } else { - if (isuy) - v = *(p2 + 1); - else - u = *(p2 + 1); - } - - tmp = ay[(int)y] + rv[(int)v]; - r = (255 < tmp) ? 255 : ((0 > tmp) ? - 0 : (u8)tmp); - tmp = ay[(int)y] - gu[(int)u] - gv[(int)v]; - g = (255 < tmp) ? 255 : ((0 > tmp) ? - 0 : (u8)tmp); - tmp = ay[(int)y] + bu[(int)u]; - b = (255 < tmp) ? 255 : ((0 > tmp) ? - 0 : (u8)tmp); - - if (last && rump) { - pcache = &peasycap->cache[0]; - switch (bytesperpixel - rump) { - case 1: { - *p3 = b; - *pcache++ = g; - *pcache++ = r; - *pcache++ = 0; - break; - } - case 2: { - *p3 = b; - *(p3 + 1) = g; - *pcache++ = r; - *pcache++ = 0; - break; - } - case 3: { - *p3 = b; - *(p3 + 1) = g; - *(p3 + 2) = r; - *pcache++ = 0; - break; - } - default: - SAM("MISTAKE: %i=rump\n", - bytesperpixel - rump); - return -EFAULT; - } - } else { - *p3 = b; - *(p3 + 1) = g; - *(p3 + 2) = r; - *(p3 + 3) = 0; - } - p2 += 2; - if (isuy) - isuy = false; - else - isuy = true; - p3 += bytesperpixel; - } - } - return 0; - } else { - if (!byteswaporder) { - /* - * RGBA DECIMATED - */ - while (pz > p2) { - if (pr <= (p3 + bytesperpixel)) - last = true; - else - last = false; - y = *p2; - if (last && (0x0C & mask)) { - if (0x04 & mask) { - if (isuy) - v = margin; - else - u = margin; - } else - if (0x08 & mask) - ; - } else { - if (isuy) - v = *(p2 + 1); - else - u = *(p2 + 1); - } - - if (isuy) { - - tmp = ay[(int)y] + rv[(int)v]; - r = (255 < tmp) ? 255 : ((0 > tmp) ? - 0 : (u8)tmp); - tmp = ay[(int)y] - gu[(int)u] - - gv[(int)v]; - g = (255 < tmp) ? 255 : ((0 > tmp) ? - 0 : (u8)tmp); - tmp = ay[(int)y] + bu[(int)u]; - b = (255 < tmp) ? 255 : ((0 > tmp) ? - 0 : (u8)tmp); - - if (last && rump) { - pcache = &peasycap->cache[0]; - switch (bytesperpixel - rump) { - case 1: { - *p3 = r; - *pcache++ = g; - *pcache++ = b; - *pcache++ = 0; - break; - } - case 2: { - *p3 = r; - *(p3 + 1) = g; - *pcache++ = b; - *pcache++ = 0; - break; - } - case 3: { - *p3 = r; - *(p3 + 1) = g; - *(p3 + 2) = b; - *pcache++ = 0; - break; - } - default: { - SAM("MISTAKE: " - "%i=rump\n", - bytesperpixel - - rump); - return -EFAULT; - } - } - } else { - *p3 = r; - *(p3 + 1) = g; - *(p3 + 2) = b; - *(p3 + 3) = 0; - } - isuy = false; - p3 += bytesperpixel; - } else - isuy = true; - p2 += 2; - } - return 0; - } else { - /* - * BGRA DECIMATED - */ - while (pz > p2) { - if (pr <= (p3 + bytesperpixel)) - last = true; - else - last = false; - y = *p2; - if (last && (0x0C & mask)) { - if (0x04 & mask) { - if (isuy) - v = margin; - else - u = margin; - } else - if (0x08 & mask) - ; - } else { - if (isuy) - v = *(p2 + 1); - else - u = *(p2 + 1); - } - - if (isuy) { - tmp = ay[(int)y] + rv[(int)v]; - r = (255 < tmp) ? 255 : ((0 > tmp) ? - 0 : (u8)tmp); - tmp = ay[(int)y] - gu[(int)u] - - gv[(int)v]; - g = (255 < tmp) ? 255 : ((0 > tmp) ? - 0 : (u8)tmp); - tmp = ay[(int)y] + bu[(int)u]; - b = (255 < tmp) ? 255 : ((0 > tmp) ? - 0 : (u8)tmp); - - if (last && rump) { - pcache = &peasycap->cache[0]; - switch (bytesperpixel - rump) { - case 1: { - *p3 = b; - *pcache++ = g; - *pcache++ = r; - *pcache++ = 0; - break; - } - case 2: { - *p3 = b; - *(p3 + 1) = g; - *pcache++ = r; - *pcache++ = 0; - break; - } - case 3: { - *p3 = b; - *(p3 + 1) = g; - *(p3 + 2) = r; - *pcache++ = 0; - break; - } - default: { - SAM("MISTAKE: " - "%i=rump\n", - bytesperpixel - rump); - return -EFAULT; - } - } - } else { - *p3 = b; - *(p3 + 1) = g; - *(p3 + 2) = r; - *(p3 + 3) = 0; - } - isuy = false; - p3 += bytesperpixel; - } else - isuy = true; - p2 += 2; - } - return 0; - } - } - break; - } - default: { - SAM("MISTAKE: %i=bytesperpixel\n", bytesperpixel); - return -EFAULT; - } - } - return 0; -} -/*****************************************************************************/ -/* - * SEE CORBET ET AL. "LINUX DEVICE DRIVERS", 3rd EDITION, PAGES 430-434 - */ -/*****************************************************************************/ -static void easycap_vma_open(struct vm_area_struct *pvma) -{ - struct easycap *peasycap; - - peasycap = pvma->vm_private_data; - if (!peasycap) { - SAY("ERROR: peasycap is NULL\n"); - return; - } - peasycap->vma_many++; - JOT(8, "%i=peasycap->vma_many\n", peasycap->vma_many); - return; -} -/*****************************************************************************/ -static void easycap_vma_close(struct vm_area_struct *pvma) -{ - struct easycap *peasycap; - - peasycap = pvma->vm_private_data; - if (!peasycap) { - SAY("ERROR: peasycap is NULL\n"); - return; - } - peasycap->vma_many--; - JOT(8, "%i=peasycap->vma_many\n", peasycap->vma_many); - return; -} -/*****************************************************************************/ -static int easycap_vma_fault(struct vm_area_struct *pvma, struct vm_fault *pvmf) -{ - int k, m, retcode; - void *pbuf; - struct page *page; - struct easycap *peasycap; - - retcode = VM_FAULT_NOPAGE; - - if (!pvma) { - SAY("pvma is NULL\n"); - return retcode; - } - if (!pvmf) { - SAY("pvmf is NULL\n"); - return retcode; - } - - k = (pvmf->pgoff) / (FRAME_BUFFER_SIZE/PAGE_SIZE); - m = (pvmf->pgoff) % (FRAME_BUFFER_SIZE/PAGE_SIZE); - - if (!m) - JOT(4, "%4i=k, %4i=m\n", k, m); - else - JOT(16, "%4i=k, %4i=m\n", k, m); - - if ((0 > k) || (FRAME_BUFFER_MANY <= k)) { - SAY("ERROR: buffer index %i out of range\n", k); - return retcode; - } - if ((0 > m) || (FRAME_BUFFER_SIZE/PAGE_SIZE <= m)) { - SAY("ERROR: page number %i out of range\n", m); - return retcode; - } - peasycap = pvma->vm_private_data; - if (!peasycap) { - SAY("ERROR: peasycap is NULL\n"); - return retcode; - } -/*---------------------------------------------------------------------------*/ - pbuf = peasycap->frame_buffer[k][m].pgo; - if (!pbuf) { - SAM("ERROR: pbuf is NULL\n"); - return retcode; - } - page = virt_to_page(pbuf); - if (!page) { - SAM("ERROR: page is NULL\n"); - return retcode; - } - get_page(page); -/*---------------------------------------------------------------------------*/ - if (!page) { - SAM("ERROR: page is NULL after get_page(page)\n"); - } else { - pvmf->page = page; - retcode = VM_FAULT_MINOR; - } - return retcode; -} - -static const struct vm_operations_struct easycap_vm_ops = { - .open = easycap_vma_open, - .close = easycap_vma_close, - .fault = easycap_vma_fault, -}; - -static int easycap_mmap(struct file *file, struct vm_area_struct *pvma) -{ - JOT(8, "\n"); - - pvma->vm_ops = &easycap_vm_ops; - pvma->vm_flags |= VM_RESERVED; - if (file) - pvma->vm_private_data = file->private_data; - easycap_vma_open(pvma); - return 0; -} -/*****************************************************************************/ -/*---------------------------------------------------------------------------*/ -/* - * ON COMPLETION OF A VIDEO URB ITS DATA IS COPIED TO THE FIELD BUFFERS - * PROVIDED peasycap->video_idle IS ZERO. REGARDLESS OF THIS BEING TRUE, - * IT IS RESUBMITTED PROVIDED peasycap->video_isoc_streaming IS NOT ZERO. - * - * THIS FUNCTION IS AN INTERRUPT SERVICE ROUTINE AND MUST NOT SLEEP. - * - * INFORMATION ABOUT THE VALIDITY OF THE CONTENTS OF THE FIELD BUFFER ARE - * STORED IN THE TWO-BYTE STATUS PARAMETER - * peasycap->field_buffer[peasycap->field_fill][0].kount - * NOTICE THAT THE INFORMATION IS STORED ONLY WITH PAGE 0 OF THE FIELD BUFFER. - * - * THE LOWER BYTE CONTAINS THE FIELD PARITY BYTE FURNISHED BY THE SAA7113H - * CHIP. - * - * THE UPPER BYTE IS ZERO IF NO PROBLEMS, OTHERWISE: - * 0 != (kount & 0x8000) => AT LEAST ONE URB COMPLETED WITH ERRORS - * 0 != (kount & 0x4000) => BUFFER HAS TOO MUCH DATA - * 0 != (kount & 0x2000) => BUFFER HAS NOT ENOUGH DATA - * 0 != (kount & 0x1000) => BUFFER HAS DATA FROM DISPARATE INPUTS - * 0 != (kount & 0x0400) => RESERVED - * 0 != (kount & 0x0200) => FIELD BUFFER NOT YET CHECKED - * 0 != (kount & 0x0100) => BUFFER HAS TWO EXTRA BYTES - WHY? - */ -/*---------------------------------------------------------------------------*/ -static void easycap_complete(struct urb *purb) -{ - struct easycap *peasycap; - struct data_buffer *pfield_buffer; - char errbuf[16]; - int i, more, much, leap, rc, last; - int videofieldamount; - unsigned int override, bad; - int framestatus, framelength, frameactual, frameoffset; - u8 *pu; - - if (!purb) { - SAY("ERROR: easycap_complete(): purb is NULL\n"); - return; - } - peasycap = purb->context; - if (!peasycap) { - SAY("ERROR: easycap_complete(): peasycap is NULL\n"); - return; - } - if (peasycap->video_eof) - return; - for (i = 0; i < VIDEO_ISOC_BUFFER_MANY; i++) - if (purb->transfer_buffer == peasycap->video_isoc_buffer[i].pgo) - break; - JOM(16, "%2i=urb\n", i); - last = peasycap->video_isoc_sequence; - if ((((VIDEO_ISOC_BUFFER_MANY - 1) == last) && (0 != i)) || - (((VIDEO_ISOC_BUFFER_MANY - 1) != last) && ((last + 1) != i))) { - JOM(16, "ERROR: out-of-order urbs %i,%i ... continuing\n", - last, i); - } - peasycap->video_isoc_sequence = i; - - if (peasycap->video_idle) { - JOM(16, "%i=video_idle %i=video_isoc_streaming\n", - peasycap->video_idle, peasycap->video_isoc_streaming); - if (peasycap->video_isoc_streaming) { - rc = usb_submit_urb(purb, GFP_ATOMIC); - if (rc) { - SAM("%s:%d ENOMEM\n", strerror(rc), rc); - if (-ENODEV != rc) - SAM("ERROR: while %i=video_idle, " - "usb_submit_urb() " - "failed with rc:\n", - peasycap->video_idle); - } - } - return; - } - override = 0; -/*---------------------------------------------------------------------------*/ - if (FIELD_BUFFER_MANY <= peasycap->field_fill) { - SAM("ERROR: bad peasycap->field_fill\n"); - return; - } - if (purb->status) { - if ((-ESHUTDOWN == purb->status) || (-ENOENT == purb->status)) { - JOM(8, "urb status -ESHUTDOWN or -ENOENT\n"); - return; - } - - (peasycap->field_buffer[peasycap->field_fill][0].kount) |= 0x8000 ; - SAM("ERROR: bad urb status -%s: %d\n", - strerror(purb->status), purb->status); -/*---------------------------------------------------------------------------*/ - } else { - for (i = 0; i < purb->number_of_packets; i++) { - if (0 != purb->iso_frame_desc[i].status) { - (peasycap->field_buffer - [peasycap->field_fill][0].kount) |= 0x8000 ; - /* FIXME: 1. missing '-' check boundaries */ - strcpy(&errbuf[0], - strerror(purb->iso_frame_desc[i].status)); - } - framestatus = purb->iso_frame_desc[i].status; - framelength = purb->iso_frame_desc[i].length; - frameactual = purb->iso_frame_desc[i].actual_length; - frameoffset = purb->iso_frame_desc[i].offset; - - JOM(16, "frame[%2i]:" - "%4i=status " - "%4i=actual " - "%4i=length " - "%5i=offset\n", - i, framestatus, frameactual, framelength, frameoffset); - if (!purb->iso_frame_desc[i].status) { - more = purb->iso_frame_desc[i].actual_length; - pfield_buffer = &peasycap->field_buffer - [peasycap->field_fill][peasycap->field_page]; - videofieldamount = (peasycap->field_page * - PAGE_SIZE) + - (int)(pfield_buffer->pto - pfield_buffer->pgo); - if (4 == more) - peasycap->video_mt++; - if (4 < more) { - if (peasycap->video_mt) { - JOM(8, "%4i empty video urb frames\n", - peasycap->video_mt); - peasycap->video_mt = 0; - } - if (FIELD_BUFFER_MANY <= peasycap->field_fill) { - SAM("ERROR: bad peasycap->field_fill\n"); - return; - } - if (FIELD_BUFFER_SIZE/PAGE_SIZE <= - peasycap->field_page) { - SAM("ERROR: bad peasycap->field_page\n"); - return; - } - pfield_buffer = &peasycap->field_buffer - [peasycap->field_fill][peasycap->field_page]; - pu = (u8 *)(purb->transfer_buffer + - purb->iso_frame_desc[i].offset); - if (0x80 & *pu) - leap = 8; - else - leap = 4; -/*--------------------------------------------------------------------------*/ -/* - * EIGHT-BYTE END-OF-VIDEOFIELD MARKER. - * NOTE: A SUCCESSION OF URB FRAMES FOLLOWING THIS ARE EMPTY, - * CORRESPONDING TO THE FIELD FLYBACK (VERTICAL BLANKING) PERIOD. - * - * PROVIDED THE FIELD BUFFER CONTAINS GOOD DATA AS INDICATED BY A ZERO UPPER - * BYTE OF - * peasycap->field_buffer[peasycap->field_fill][0].kount - * THE CONTENTS OF THE FIELD BUFFER ARE OFFERED TO dqbuf(), field_read IS - * UPDATED AND field_fill IS BUMPED. IF THE FIELD BUFFER CONTAINS BAD DATA - * NOTHING IS OFFERED TO dqbuf(). - * - * THE DECISION ON WHETHER THE PARITY OF THE OFFERED FIELD BUFFER IS RIGHT - * RESTS WITH dqbuf(). - */ -/*---------------------------------------------------------------------------*/ - if ((8 == more) || override) { - if (videofieldamount > - peasycap->videofieldamount) { - if (2 == videofieldamount - - peasycap-> - videofieldamount) { - (peasycap->field_buffer - [peasycap->field_fill] - [0].kount) |= 0x0100; - peasycap->video_junk += (1 + - VIDEO_JUNK_TOLERATE); - } else - (peasycap->field_buffer - [peasycap->field_fill] - [0].kount) |= 0x4000; - } else if (videofieldamount < - peasycap-> - videofieldamount) { - (peasycap->field_buffer - [peasycap->field_fill] - [0].kount) |= 0x2000; - } - bad = 0xFF00 & peasycap->field_buffer - [peasycap->field_fill] - [0].kount; - if (!bad) { - (peasycap->video_junk)--; - if (-VIDEO_JUNK_TOLERATE > - peasycap->video_junk) - peasycap->video_junk = - -VIDEO_JUNK_TOLERATE; - peasycap->field_read = - (peasycap-> - field_fill)++; - if (FIELD_BUFFER_MANY <= - peasycap-> - field_fill) - peasycap-> - field_fill = 0; - peasycap->field_page = 0; - pfield_buffer = &peasycap-> - field_buffer - [peasycap-> - field_fill] - [peasycap-> - field_page]; - pfield_buffer->pto = - pfield_buffer->pgo; - JOM(8, "bumped to: %i=" - "peasycap->" - "field_fill %i=" - "parity\n", - peasycap->field_fill, - 0x00FF & - pfield_buffer->kount); - JOM(8, "field buffer %i has " - "%i bytes fit to be " - "read\n", - peasycap->field_read, - videofieldamount); - JOM(8, "wakeup call to " - "wq_video, " - "%i=field_read " - "%i=field_fill " - "%i=parity\n", - peasycap->field_read, - peasycap->field_fill, - 0x00FF & peasycap-> - field_buffer - [peasycap-> - field_read][0].kount); - wake_up_interruptible - (&(peasycap-> - wq_video)); - } else { - peasycap->video_junk++; - if (bad & 0x0010) - peasycap->video_junk += - (1 + VIDEO_JUNK_TOLERATE/2); - JOM(8, "field buffer %i had %i " - "bytes, now discarded: " - "0x%04X\n", - peasycap->field_fill, - videofieldamount, - (0xFF00 & - peasycap->field_buffer - [peasycap->field_fill][0]. - kount)); - (peasycap->field_fill)++; - - if (FIELD_BUFFER_MANY <= - peasycap->field_fill) - peasycap->field_fill = 0; - peasycap->field_page = 0; - pfield_buffer = - &peasycap->field_buffer - [peasycap->field_fill] - [peasycap->field_page]; - pfield_buffer->pto = - pfield_buffer->pgo; - - JOM(8, "bumped to: %i=peasycap->" - "field_fill %i=parity\n", - peasycap->field_fill, - 0x00FF & pfield_buffer->kount); - } - if (8 == more) { - JOM(8, "end-of-field: received " - "parity byte 0x%02X\n", - (0xFF & *pu)); - if (0x40 & *pu) - pfield_buffer->kount = 0x0000; - else - pfield_buffer->kount = 0x0001; - pfield_buffer->input = 0x08 | - (0x07 & peasycap->input); - JOM(8, "end-of-field: 0x%02X=kount\n", - 0xFF & pfield_buffer->kount); - } - } -/*---------------------------------------------------------------------------*/ -/* - * COPY more BYTES FROM ISOC BUFFER TO FIELD BUFFER - */ -/*---------------------------------------------------------------------------*/ - pu += leap; - more -= leap; - - if (FIELD_BUFFER_MANY <= peasycap->field_fill) { - SAM("ERROR: bad peasycap->field_fill\n"); - return; - } - if (FIELD_BUFFER_SIZE/PAGE_SIZE <= peasycap->field_page) { - SAM("ERROR: bad peasycap->field_page\n"); - return; - } - pfield_buffer = &peasycap->field_buffer - [peasycap->field_fill][peasycap->field_page]; - while (more) { - pfield_buffer = &peasycap->field_buffer - [peasycap->field_fill] - [peasycap->field_page]; - if (PAGE_SIZE < (pfield_buffer->pto - - pfield_buffer->pgo)) { - SAM("ERROR: bad pfield_buffer->pto\n"); - return; - } - if (PAGE_SIZE == (pfield_buffer->pto - - pfield_buffer->pgo)) { - (peasycap->field_page)++; - if (FIELD_BUFFER_SIZE/PAGE_SIZE <= - peasycap->field_page) { - JOM(16, "wrapping peasycap->" - "field_page\n"); - peasycap->field_page = 0; - } - pfield_buffer = &peasycap-> - field_buffer - [peasycap->field_fill] - [peasycap->field_page]; - pfield_buffer->pto = pfield_buffer->pgo; - pfield_buffer->input = 0x08 | - (0x07 & peasycap->input); - if ((peasycap->field_buffer[peasycap-> - field_fill][0]). - input != - pfield_buffer->input) - (peasycap->field_buffer - [peasycap->field_fill] - [0]).kount |= 0x1000; - } - - much = PAGE_SIZE - - (int)(pfield_buffer->pto - - pfield_buffer->pgo); - - if (much > more) - much = more; - memcpy(pfield_buffer->pto, pu, much); - pu += much; - (pfield_buffer->pto) += much; - more -= much; - } - } - } - } - } -/*---------------------------------------------------------------------------*/ -/* - * RESUBMIT THIS URB, UNLESS A SEVERE PERSISTENT ERROR CONDITION EXISTS. - * - * IF THE WAIT QUEUES ARE NOT CLEARED IN RESPONSE TO AN ERROR CONDITION - * THE USERSPACE PROGRAM, E.G. mplayer, MAY HANG ON EXIT. BEWARE. - */ -/*---------------------------------------------------------------------------*/ - if (VIDEO_ISOC_BUFFER_MANY <= peasycap->video_junk) { - SAM("easycap driver shutting down on condition green\n"); - peasycap->status = 1; - peasycap->video_eof = 1; - peasycap->video_junk = 0; - wake_up_interruptible(&peasycap->wq_video); -#if !defined(PERSEVERE) - peasycap->audio_eof = 1; - wake_up_interruptible(&peasycap->wq_audio); -#endif /*PERSEVERE*/ - return; - } - if (peasycap->video_isoc_streaming) { - rc = usb_submit_urb(purb, GFP_ATOMIC); - if (rc) { - SAM("%s: %d\n", strerror(rc), rc); - if (-ENODEV != rc) - SAM("ERROR: while %i=video_idle, " - "usb_submit_urb() " - "failed with rc:\n", - peasycap->video_idle); - } - } - return; -} - -static struct easycap *alloc_easycap(u8 bInterfaceNumber) -{ - struct easycap *peasycap; - int i; - - peasycap = kzalloc(sizeof(struct easycap), GFP_KERNEL); - if (!peasycap) { - SAY("ERROR: Could not allocate peasycap\n"); - return NULL; - } - - if (mutex_lock_interruptible(&mutex_dongle)) { - SAY("ERROR: cannot lock mutex_dongle\n"); - kfree(peasycap); - return NULL; - } - - /* Find a free dongle in easycapdc60_dongle array */ - for (i = 0; i < DONGLE_MANY; i++) { - - if ((!easycapdc60_dongle[i].peasycap) && - (!mutex_is_locked(&easycapdc60_dongle[i].mutex_video)) && - (!mutex_is_locked(&easycapdc60_dongle[i].mutex_audio))) { - - easycapdc60_dongle[i].peasycap = peasycap; - peasycap->isdongle = i; - JOM(8, "intf[%i]: peasycap-->easycap" - "_dongle[%i].peasycap\n", - bInterfaceNumber, i); - break; - } - } - - mutex_unlock(&mutex_dongle); - - if (i >= DONGLE_MANY) { - SAM("ERROR: too many dongles\n"); - kfree(peasycap); - return NULL; - } - - return peasycap; -} - -static void free_easycap(struct easycap *peasycap) -{ - int allocation_video_urb; - int allocation_video_page; - int allocation_video_struct; - int allocation_audio_urb; - int allocation_audio_page; - int allocation_audio_struct; - int registered_video, registered_audio; - int kd; - - JOM(4, "freeing easycap structure.\n"); - allocation_video_urb = peasycap->allocation_video_urb; - allocation_video_page = peasycap->allocation_video_page; - allocation_video_struct = peasycap->allocation_video_struct; - registered_video = peasycap->registered_video; - allocation_audio_urb = peasycap->allocation_audio_urb; - allocation_audio_page = peasycap->allocation_audio_page; - allocation_audio_struct = peasycap->allocation_audio_struct; - registered_audio = peasycap->registered_audio; - - kd = easycap_isdongle(peasycap); - if (0 <= kd && DONGLE_MANY > kd) { - if (mutex_lock_interruptible(&mutex_dongle)) { - SAY("ERROR: cannot down mutex_dongle\n"); - } else { - JOM(4, "locked mutex_dongle\n"); - easycapdc60_dongle[kd].peasycap = NULL; - mutex_unlock(&mutex_dongle); - JOM(4, "unlocked mutex_dongle\n"); - JOT(4, " null-->dongle[%i].peasycap\n", kd); - allocation_video_struct -= sizeof(struct easycap); - } - } else { - SAY("ERROR: cannot purge dongle[].peasycap"); - } - - /* Free device structure */ - kfree(peasycap); - - SAY("%8i=video urbs after all deletions\n", allocation_video_urb); - SAY("%8i=video pages after all deletions\n", allocation_video_page); - SAY("%8i=video structs after all deletions\n", allocation_video_struct); - SAY("%8i=video devices after all deletions\n", registered_video); - SAY("%8i=audio urbs after all deletions\n", allocation_audio_urb); - SAY("%8i=audio pages after all deletions\n", allocation_audio_page); - SAY("%8i=audio structs after all deletions\n", allocation_audio_struct); - SAY("%8i=audio devices after all deletions\n", registered_audio); -} - -/* - * FIXME: Identify the appropriate pointer peasycap for interfaces - * 1 and 2. The address of peasycap->pusb_device is reluctantly used - * for this purpose. - */ -static struct easycap *get_easycap(struct usb_device *usbdev, - u8 bInterfaceNumber) -{ - int i; - struct easycap *peasycap; - - for (i = 0; i < DONGLE_MANY; i++) { - if (easycapdc60_dongle[i].peasycap->pusb_device == usbdev) { - peasycap = easycapdc60_dongle[i].peasycap; - JOT(8, "intf[%i]: dongle[%i].peasycap\n", - bInterfaceNumber, i); - break; - } - } - if (i >= DONGLE_MANY) { - SAY("ERROR: peasycap is unknown when probing interface %i\n", - bInterfaceNumber); - return NULL; - } - if (!peasycap) { - SAY("ERROR: peasycap is NULL when probing interface %i\n", - bInterfaceNumber); - return NULL; - } - - return peasycap; -} - -static void init_easycap(struct easycap *peasycap, - struct usb_device *usbdev, - struct usb_interface *intf, - u8 bInterfaceNumber) -{ - /* Save usb_device and usb_interface */ - peasycap->pusb_device = usbdev; - peasycap->pusb_interface = intf; - - peasycap->minor = -1; - kref_init(&peasycap->kref); - JOM(8, "intf[%i]: after kref_init(..._video) " - "%i=peasycap->kref.refcount.counter\n", - bInterfaceNumber, peasycap->kref.refcount.counter); - - /* module params */ - peasycap->gain = (s8)clamp(easycap_gain, 0, 31); - - init_waitqueue_head(&peasycap->wq_video); - init_waitqueue_head(&peasycap->wq_audio); - init_waitqueue_head(&peasycap->wq_trigger); - - peasycap->allocation_video_struct = sizeof(struct easycap); - - peasycap->microphone = false; - - peasycap->video_interface = -1; - peasycap->video_altsetting_on = -1; - peasycap->video_altsetting_off = -1; - peasycap->video_endpointnumber = -1; - peasycap->video_isoc_maxframesize = -1; - peasycap->video_isoc_buffer_size = -1; - - peasycap->audio_interface = -1; - peasycap->audio_altsetting_on = -1; - peasycap->audio_altsetting_off = -1; - peasycap->audio_endpointnumber = -1; - peasycap->audio_isoc_maxframesize = -1; - peasycap->audio_isoc_buffer_size = -1; - - peasycap->frame_buffer_many = FRAME_BUFFER_MANY; - - peasycap->ntsc = easycap_ntsc; - JOM(8, "defaulting initially to %s\n", - easycap_ntsc ? "NTSC" : "PAL"); -} - -static int populate_inputset(struct easycap *peasycap) -{ - struct inputset *inputset; - struct easycap_format *peasycap_format; - struct v4l2_pix_format *pix; - int m, i, k, mask, fmtidx; - s32 value; - - inputset = peasycap->inputset; - - fmtidx = peasycap->ntsc ? NTSC_M : PAL_BGHIN; - - m = 0; - mask = 0; - for (i = 0; easycap_standard[i].mask != 0xffff; i++) { - if (fmtidx == easycap_standard[i].v4l2_standard.index) { - m++; - for (k = 0; k < INPUT_MANY; k++) - inputset[k].standard_offset = i; - mask = easycap_standard[i].mask; - } - } - - if (m != 1) { - SAM("ERROR: inputset->standard_offset unpopulated, %i=m\n", m); - return -ENOENT; - } - - peasycap_format = &easycap_format[0]; - m = 0; - for (i = 0; peasycap_format->v4l2_format.fmt.pix.width; i++) { - pix = &peasycap_format->v4l2_format.fmt.pix; - if (((peasycap_format->mask & 0x0F) == (mask & 0x0F)) - && pix->field == V4L2_FIELD_NONE - && pix->pixelformat == V4L2_PIX_FMT_UYVY - && pix->width == 640 && pix->height == 480) { - m++; - for (k = 0; k < INPUT_MANY; k++) - inputset[k].format_offset = i; - break; - } - peasycap_format++; - } - if (m != 1) { - SAM("ERROR: inputset[]->format_offset unpopulated\n"); - return -ENOENT; - } - - m = 0; - for (i = 0; easycap_control[i].id != 0xffffffff; i++) { - value = easycap_control[i].default_value; - if (V4L2_CID_BRIGHTNESS == easycap_control[i].id) { - m++; - for (k = 0; k < INPUT_MANY; k++) - inputset[k].brightness = value; - } else if (V4L2_CID_CONTRAST == easycap_control[i].id) { - m++; - for (k = 0; k < INPUT_MANY; k++) - inputset[k].contrast = value; - } else if (V4L2_CID_SATURATION == easycap_control[i].id) { - m++; - for (k = 0; k < INPUT_MANY; k++) - inputset[k].saturation = value; - } else if (V4L2_CID_HUE == easycap_control[i].id) { - m++; - for (k = 0; k < INPUT_MANY; k++) - inputset[k].hue = value; - } - } - - if (m != 4) { - SAM("ERROR: inputset[]->brightness underpopulated\n"); - return -ENOENT; - } - - for (k = 0; k < INPUT_MANY; k++) - inputset[k].input = k; - JOM(4, "populated inputset[]\n"); - - return 0; -} - -static int alloc_framebuffers(struct easycap *peasycap) -{ - int i, j; - void *pbuf; - - JOM(4, "allocating %i frame buffers of size %li\n", - FRAME_BUFFER_MANY, (long int)FRAME_BUFFER_SIZE); - JOM(4, ".... each scattered over %li pages\n", - FRAME_BUFFER_SIZE/PAGE_SIZE); - - for (i = 0; i < FRAME_BUFFER_MANY; i++) { - for (j = 0; j < FRAME_BUFFER_SIZE/PAGE_SIZE; j++) { - if (peasycap->frame_buffer[i][j].pgo) - SAM("attempting to reallocate framebuffers\n"); - else { - pbuf = (void *)__get_free_page(GFP_KERNEL); - if (!pbuf) { - SAM("ERROR: Could not allocate " - "framebuffer %i page %i\n", i, j); - return -ENOMEM; - } - peasycap->allocation_video_page += 1; - peasycap->frame_buffer[i][j].pgo = pbuf; - } - peasycap->frame_buffer[i][j].pto = - peasycap->frame_buffer[i][j].pgo; - } - } - - peasycap->frame_fill = 0; - peasycap->frame_read = 0; - JOM(4, "allocation of frame buffers done: %i pages\n", i*j); - - return 0; -} - -static void free_framebuffers(struct easycap *peasycap) -{ - int k, m, gone; - - JOM(4, "freeing video frame buffers.\n"); - gone = 0; - for (k = 0; k < FRAME_BUFFER_MANY; k++) { - for (m = 0; m < FRAME_BUFFER_SIZE/PAGE_SIZE; m++) { - if (peasycap->frame_buffer[k][m].pgo) { - free_page((unsigned long) - peasycap->frame_buffer[k][m].pgo); - peasycap->frame_buffer[k][m].pgo = NULL; - peasycap->allocation_video_page -= 1; - gone++; - } - } - } - JOM(4, "video frame buffers freed: %i pages\n", gone); -} - -static int alloc_fieldbuffers(struct easycap *peasycap) -{ - int i, j; - void *pbuf; - - JOM(4, "allocating %i field buffers of size %li\n", - FIELD_BUFFER_MANY, (long int)FIELD_BUFFER_SIZE); - JOM(4, ".... each scattered over %li pages\n", - FIELD_BUFFER_SIZE/PAGE_SIZE); - - for (i = 0; i < FIELD_BUFFER_MANY; i++) { - for (j = 0; j < FIELD_BUFFER_SIZE/PAGE_SIZE; j++) { - if (peasycap->field_buffer[i][j].pgo) { - SAM("ERROR: attempting to reallocate " - "fieldbuffers\n"); - } else { - pbuf = (void *) __get_free_page(GFP_KERNEL); - if (!pbuf) { - SAM("ERROR: Could not allocate " - "fieldbuffer %i page %i\n", i, j); - return -ENOMEM; - } - peasycap->allocation_video_page += 1; - peasycap->field_buffer[i][j].pgo = pbuf; - } - peasycap->field_buffer[i][j].pto = - peasycap->field_buffer[i][j].pgo; - } - /* TODO: Hardcoded 0x0200 meaning? */ - peasycap->field_buffer[i][0].kount = 0x0200; - } - peasycap->field_fill = 0; - peasycap->field_page = 0; - peasycap->field_read = 0; - JOM(4, "allocation of field buffers done: %i pages\n", i*j); - - return 0; -} - -static void free_fieldbuffers(struct easycap *peasycap) -{ - int k, m, gone; - - JOM(4, "freeing video field buffers.\n"); - gone = 0; - for (k = 0; k < FIELD_BUFFER_MANY; k++) { - for (m = 0; m < FIELD_BUFFER_SIZE/PAGE_SIZE; m++) { - if (peasycap->field_buffer[k][m].pgo) { - free_page((unsigned long) - peasycap->field_buffer[k][m].pgo); - peasycap->field_buffer[k][m].pgo = NULL; - peasycap->allocation_video_page -= 1; - gone++; - } - } - } - JOM(4, "video field buffers freed: %i pages\n", gone); -} - -static int alloc_isocbuffers(struct easycap *peasycap) -{ - int i; - void *pbuf; - - JOM(4, "allocating %i isoc video buffers of size %i\n", - VIDEO_ISOC_BUFFER_MANY, - peasycap->video_isoc_buffer_size); - JOM(4, ".... each occupying contiguous memory pages\n"); - - for (i = 0; i < VIDEO_ISOC_BUFFER_MANY; i++) { - pbuf = (void *)__get_free_pages(GFP_KERNEL, - VIDEO_ISOC_ORDER); - if (!pbuf) { - SAM("ERROR: Could not allocate isoc " - "video buffer %i\n", i); - return -ENOMEM; - } - peasycap->allocation_video_page += BIT(VIDEO_ISOC_ORDER); - - peasycap->video_isoc_buffer[i].pgo = pbuf; - peasycap->video_isoc_buffer[i].pto = - pbuf + peasycap->video_isoc_buffer_size; - peasycap->video_isoc_buffer[i].kount = i; - } - JOM(4, "allocation of isoc video buffers done: %i pages\n", - i * (0x01 << VIDEO_ISOC_ORDER)); - return 0; -} - -static void free_isocbuffers(struct easycap *peasycap) -{ - int k, m; - - JOM(4, "freeing video isoc buffers.\n"); - m = 0; - for (k = 0; k < VIDEO_ISOC_BUFFER_MANY; k++) { - if (peasycap->video_isoc_buffer[k].pgo) { - free_pages((unsigned long) - peasycap->video_isoc_buffer[k].pgo, - VIDEO_ISOC_ORDER); - peasycap->video_isoc_buffer[k].pgo = NULL; - peasycap->allocation_video_page -= - BIT(VIDEO_ISOC_ORDER); - m++; - } - } - JOM(4, "isoc video buffers freed: %i pages\n", - m * (0x01 << VIDEO_ISOC_ORDER)); -} - -static int create_video_urbs(struct easycap *peasycap) -{ - struct urb *purb; - struct data_urb *pdata_urb; - int i, j; - - JOM(4, "allocating %i struct urb.\n", VIDEO_ISOC_BUFFER_MANY); - JOM(4, "using %i=peasycap->video_isoc_framesperdesc\n", - peasycap->video_isoc_framesperdesc); - JOM(4, "using %i=peasycap->video_isoc_maxframesize\n", - peasycap->video_isoc_maxframesize); - JOM(4, "using %i=peasycap->video_isoc_buffer_sizen", - peasycap->video_isoc_buffer_size); - - for (i = 0; i < VIDEO_ISOC_BUFFER_MANY; i++) { - purb = usb_alloc_urb(peasycap->video_isoc_framesperdesc, - GFP_KERNEL); - if (!purb) { - SAM("ERROR: usb_alloc_urb returned NULL for buffer " - "%i\n", i); - return -ENOMEM; - } - - peasycap->allocation_video_urb += 1; - pdata_urb = kzalloc(sizeof(struct data_urb), GFP_KERNEL); - if (!pdata_urb) { - usb_free_urb(purb); - SAM("ERROR: Could not allocate struct data_urb.\n"); - return -ENOMEM; - } - - peasycap->allocation_video_struct += - sizeof(struct data_urb); - - pdata_urb->purb = purb; - pdata_urb->isbuf = i; - pdata_urb->length = 0; - list_add_tail(&(pdata_urb->list_head), - peasycap->purb_video_head); - - if (!i) { - JOM(4, "initializing video urbs thus:\n"); - JOM(4, " purb->interval = 1;\n"); - JOM(4, " purb->dev = peasycap->pusb_device;\n"); - JOM(4, " purb->pipe = usb_rcvisocpipe" - "(peasycap->pusb_device,%i);\n", - peasycap->video_endpointnumber); - JOM(4, " purb->transfer_flags = URB_ISO_ASAP;\n"); - JOM(4, " purb->transfer_buffer = peasycap->" - "video_isoc_buffer[.].pgo;\n"); - JOM(4, " purb->transfer_buffer_length = %i;\n", - peasycap->video_isoc_buffer_size); - JOM(4, " purb->complete = easycap_complete;\n"); - JOM(4, " purb->context = peasycap;\n"); - JOM(4, " purb->start_frame = 0;\n"); - JOM(4, " purb->number_of_packets = %i;\n", - peasycap->video_isoc_framesperdesc); - JOM(4, " for (j = 0; j < %i; j++)\n", - peasycap->video_isoc_framesperdesc); - JOM(4, " {\n"); - JOM(4, " purb->iso_frame_desc[j].offset = j*%i;\n", - peasycap->video_isoc_maxframesize); - JOM(4, " purb->iso_frame_desc[j].length = %i;\n", - peasycap->video_isoc_maxframesize); - JOM(4, " }\n"); - } - - purb->interval = 1; - purb->dev = peasycap->pusb_device; - purb->pipe = usb_rcvisocpipe(peasycap->pusb_device, - peasycap->video_endpointnumber); - - purb->transfer_flags = URB_ISO_ASAP; - purb->transfer_buffer = peasycap->video_isoc_buffer[i].pgo; - purb->transfer_buffer_length = - peasycap->video_isoc_buffer_size; - - purb->complete = easycap_complete; - purb->context = peasycap; - purb->start_frame = 0; - purb->number_of_packets = peasycap->video_isoc_framesperdesc; - - for (j = 0; j < peasycap->video_isoc_framesperdesc; j++) { - purb->iso_frame_desc[j].offset = - j * peasycap->video_isoc_maxframesize; - purb->iso_frame_desc[j].length = - peasycap->video_isoc_maxframesize; - } - } - JOM(4, "allocation of %i struct urb done.\n", i); - return 0; -} - -static void free_video_urbs(struct easycap *peasycap) -{ - struct list_head *plist_head, *plist_next; - struct data_urb *pdata_urb; - int m; - - if (peasycap->purb_video_head) { - m = 0; - list_for_each(plist_head, peasycap->purb_video_head) { - pdata_urb = list_entry(plist_head, - struct data_urb, list_head); - if (pdata_urb && pdata_urb->purb) { - usb_free_urb(pdata_urb->purb); - pdata_urb->purb = NULL; - peasycap->allocation_video_urb--; - m++; - } - } - - JOM(4, "%i video urbs freed\n", m); - JOM(4, "freeing video data_urb structures.\n"); - m = 0; - list_for_each_safe(plist_head, plist_next, - peasycap->purb_video_head) { - pdata_urb = list_entry(plist_head, - struct data_urb, list_head); - if (pdata_urb) { - peasycap->allocation_video_struct -= - sizeof(struct data_urb); - kfree(pdata_urb); - m++; - } - } - JOM(4, "%i video data_urb structures freed\n", m); - JOM(4, "setting peasycap->purb_video_head=NULL\n"); - peasycap->purb_video_head = NULL; - } -} - -static int alloc_audio_buffers(struct easycap *peasycap) -{ - void *pbuf; - int k; - - JOM(4, "allocating %i isoc audio buffers of size %i\n", - AUDIO_ISOC_BUFFER_MANY, - peasycap->audio_isoc_buffer_size); - JOM(4, ".... each occupying contiguous memory pages\n"); - - for (k = 0; k < AUDIO_ISOC_BUFFER_MANY; k++) { - pbuf = (void *)__get_free_pages(GFP_KERNEL, AUDIO_ISOC_ORDER); - if (!pbuf) { - SAM("ERROR: Could not allocate isoc audio buffer %i\n", - k); - return -ENOMEM; - } - peasycap->allocation_audio_page += BIT(AUDIO_ISOC_ORDER); - - peasycap->audio_isoc_buffer[k].pgo = pbuf; - peasycap->audio_isoc_buffer[k].pto = - pbuf + peasycap->audio_isoc_buffer_size; - peasycap->audio_isoc_buffer[k].kount = k; - } - - JOM(4, "allocation of isoc audio buffers done.\n"); - return 0; -} - -static void free_audio_buffers(struct easycap *peasycap) -{ - int k, m; - - JOM(4, "freeing audio isoc buffers.\n"); - m = 0; - for (k = 0; k < AUDIO_ISOC_BUFFER_MANY; k++) { - if (peasycap->audio_isoc_buffer[k].pgo) { - free_pages((unsigned long) - (peasycap->audio_isoc_buffer[k].pgo), - AUDIO_ISOC_ORDER); - peasycap->audio_isoc_buffer[k].pgo = NULL; - peasycap->allocation_audio_page -= - BIT(AUDIO_ISOC_ORDER); - m++; - } - } - JOM(4, "easyoss_delete(): isoc audio buffers freed: %i pages\n", - m * (0x01 << AUDIO_ISOC_ORDER)); -} - -static int create_audio_urbs(struct easycap *peasycap) -{ - struct urb *purb; - struct data_urb *pdata_urb; - int k, j; - - JOM(4, "allocating %i struct urb.\n", AUDIO_ISOC_BUFFER_MANY); - JOM(4, "using %i=peasycap->audio_isoc_framesperdesc\n", - peasycap->audio_isoc_framesperdesc); - JOM(4, "using %i=peasycap->audio_isoc_maxframesize\n", - peasycap->audio_isoc_maxframesize); - JOM(4, "using %i=peasycap->audio_isoc_buffer_size\n", - peasycap->audio_isoc_buffer_size); - - for (k = 0; k < AUDIO_ISOC_BUFFER_MANY; k++) { - purb = usb_alloc_urb(peasycap->audio_isoc_framesperdesc, - GFP_KERNEL); - if (!purb) { - SAM("ERROR: usb_alloc_urb returned NULL for buffer " - "%i\n", k); - return -ENOMEM; - } - peasycap->allocation_audio_urb += 1 ; - pdata_urb = kzalloc(sizeof(struct data_urb), GFP_KERNEL); - if (!pdata_urb) { - usb_free_urb(purb); - SAM("ERROR: Could not allocate struct data_urb.\n"); - return -ENOMEM; - } - peasycap->allocation_audio_struct += - sizeof(struct data_urb); - - pdata_urb->purb = purb; - pdata_urb->isbuf = k; - pdata_urb->length = 0; - list_add_tail(&(pdata_urb->list_head), - peasycap->purb_audio_head); - - if (!k) { - JOM(4, "initializing audio urbs thus:\n"); - JOM(4, " purb->interval = 1;\n"); - JOM(4, " purb->dev = peasycap->pusb_device;\n"); - JOM(4, " purb->pipe = usb_rcvisocpipe(peasycap->" - "pusb_device,%i);\n", - peasycap->audio_endpointnumber); - JOM(4, " purb->transfer_flags = URB_ISO_ASAP;\n"); - JOM(4, " purb->transfer_buffer = " - "peasycap->audio_isoc_buffer[.].pgo;\n"); - JOM(4, " purb->transfer_buffer_length = %i;\n", - peasycap->audio_isoc_buffer_size); - JOM(4, " purb->complete = easycap_alsa_complete;\n"); - JOM(4, " purb->context = peasycap;\n"); - JOM(4, " purb->start_frame = 0;\n"); - JOM(4, " purb->number_of_packets = %i;\n", - peasycap->audio_isoc_framesperdesc); - JOM(4, " for (j = 0; j < %i; j++)\n", - peasycap->audio_isoc_framesperdesc); - JOM(4, " {\n"); - JOM(4, " purb->iso_frame_desc[j].offset = j*%i;\n", - peasycap->audio_isoc_maxframesize); - JOM(4, " purb->iso_frame_desc[j].length = %i;\n", - peasycap->audio_isoc_maxframesize); - JOM(4, " }\n"); - } - - purb->interval = 1; - purb->dev = peasycap->pusb_device; - purb->pipe = usb_rcvisocpipe(peasycap->pusb_device, - peasycap->audio_endpointnumber); - purb->transfer_flags = URB_ISO_ASAP; - purb->transfer_buffer = peasycap->audio_isoc_buffer[k].pgo; - purb->transfer_buffer_length = - peasycap->audio_isoc_buffer_size; - purb->complete = easycap_alsa_complete; - purb->context = peasycap; - purb->start_frame = 0; - purb->number_of_packets = peasycap->audio_isoc_framesperdesc; - for (j = 0; j < peasycap->audio_isoc_framesperdesc; j++) { - purb->iso_frame_desc[j].offset = - j * peasycap->audio_isoc_maxframesize; - purb->iso_frame_desc[j].length = - peasycap->audio_isoc_maxframesize; - } - } - JOM(4, "allocation of %i struct urb done.\n", k); - return 0; -} - -static void free_audio_urbs(struct easycap *peasycap) -{ - struct list_head *plist_head, *plist_next; - struct data_urb *pdata_urb; - int m; - - if (peasycap->purb_audio_head) { - JOM(4, "freeing audio urbs\n"); - m = 0; - list_for_each(plist_head, (peasycap->purb_audio_head)) { - pdata_urb = list_entry(plist_head, - struct data_urb, list_head); - if (pdata_urb && pdata_urb->purb) { - usb_free_urb(pdata_urb->purb); - pdata_urb->purb = NULL; - peasycap->allocation_audio_urb--; - m++; - } - } - JOM(4, "%i audio urbs freed\n", m); - JOM(4, "freeing audio data_urb structures.\n"); - m = 0; - list_for_each_safe(plist_head, plist_next, - peasycap->purb_audio_head) { - pdata_urb = list_entry(plist_head, - struct data_urb, list_head); - if (pdata_urb) { - peasycap->allocation_audio_struct -= - sizeof(struct data_urb); - kfree(pdata_urb); - m++; - } - } - JOM(4, "%i audio data_urb structures freed\n", m); - JOM(4, "setting peasycap->purb_audio_head=NULL\n"); - peasycap->purb_audio_head = NULL; - } -} - -static void config_easycap(struct easycap *peasycap, - u8 bInterfaceNumber, - u8 bInterfaceClass, - u8 bInterfaceSubClass) -{ - if ((USB_CLASS_VIDEO == bInterfaceClass) || - (USB_CLASS_VENDOR_SPEC == bInterfaceClass)) { - if (-1 == peasycap->video_interface) { - peasycap->video_interface = bInterfaceNumber; - JOM(4, "setting peasycap->video_interface=%i\n", - peasycap->video_interface); - } else { - if (peasycap->video_interface != bInterfaceNumber) { - SAM("ERROR: attempting to reset " - "peasycap->video_interface\n"); - SAM("...... continuing with " - "%i=peasycap->video_interface\n", - peasycap->video_interface); - } - } - } else if ((USB_CLASS_AUDIO == bInterfaceClass) && - (USB_SUBCLASS_AUDIOSTREAMING == bInterfaceSubClass)) { - if (-1 == peasycap->audio_interface) { - peasycap->audio_interface = bInterfaceNumber; - JOM(4, "setting peasycap->audio_interface=%i\n", - peasycap->audio_interface); - } else { - if (peasycap->audio_interface != bInterfaceNumber) { - SAM("ERROR: attempting to reset " - "peasycap->audio_interface\n"); - SAM("...... continuing with " - "%i=peasycap->audio_interface\n", - peasycap->audio_interface); - } - } - } -} - -/* - * This function is called from within easycap_usb_disconnect() and is - * protected by semaphores set and cleared by easycap_usb_disconnect(). - * By this stage the device has already been physically unplugged, - * so peasycap->pusb_device is no longer valid. - */ -static void easycap_delete(struct kref *pkref) -{ - struct easycap *peasycap; - - peasycap = container_of(pkref, struct easycap, kref); - if (!peasycap) { - SAM("ERROR: peasycap is NULL: cannot perform deletions\n"); - return; - } - - /* Free video urbs */ - free_video_urbs(peasycap); - - /* Free video isoc buffers */ - free_isocbuffers(peasycap); - - /* Free video field buffers */ - free_fieldbuffers(peasycap); - - /* Free video frame buffers */ - free_framebuffers(peasycap); - - /* Free audio urbs */ - free_audio_urbs(peasycap); - - /* Free audio isoc buffers */ - free_audio_buffers(peasycap); - - free_easycap(peasycap); - - JOT(4, "ending.\n"); -} - -static const struct v4l2_file_operations v4l2_fops = { - .owner = THIS_MODULE, - .open = easycap_open_noinode, - .unlocked_ioctl = easycap_unlocked_ioctl, - .poll = easycap_poll, - .mmap = easycap_mmap, -}; - -static int easycap_register_video(struct easycap *peasycap) -{ - /* - * FIXME: This is believed to be harmless, - * but may well be unnecessary or wrong. - */ - peasycap->video_device.v4l2_dev = NULL; - - strcpy(&peasycap->video_device.name[0], "easycapdc60"); - peasycap->video_device.fops = &v4l2_fops; - peasycap->video_device.minor = -1; - peasycap->video_device.release = (void *)(&videodev_release); - - video_set_drvdata(&(peasycap->video_device), (void *)peasycap); - - if (0 != (video_register_device(&(peasycap->video_device), - VFL_TYPE_GRABBER, -1))) { - videodev_release(&(peasycap->video_device)); - return -ENODEV; - } - - peasycap->registered_video++; - - SAM("registered with videodev: %i=minor\n", - peasycap->video_device.minor); - peasycap->minor = peasycap->video_device.minor; - - return 0; -} - -/* - * When the device is plugged, this function is called three times, - * one for each interface. - */ -static int easycap_usb_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - struct usb_device *usbdev; - struct usb_host_interface *alt; - struct usb_endpoint_descriptor *ep; - struct usb_interface_descriptor *interface; - struct easycap *peasycap; - int i, j, rc; - u8 bInterfaceNumber; - u8 bInterfaceClass; - u8 bInterfaceSubClass; - int okalt[8], isokalt; - int okepn[8]; - int okmps[8]; - int maxpacketsize; - - usbdev = interface_to_usbdev(intf); - - alt = usb_altnum_to_altsetting(intf, 0); - if (!alt) { - SAY("ERROR: usb_host_interface not found\n"); - return -EFAULT; - } - - interface = &alt->desc; - if (!interface) { - SAY("ERROR: intf_descriptor is NULL\n"); - return -EFAULT; - } - - /* Get properties of probed interface */ - bInterfaceNumber = interface->bInterfaceNumber; - bInterfaceClass = interface->bInterfaceClass; - bInterfaceSubClass = interface->bInterfaceSubClass; - - JOT(4, "intf[%i]: num_altsetting=%i\n", - bInterfaceNumber, intf->num_altsetting); - JOT(4, "intf[%i]: cur_altsetting - altsetting=%li\n", - bInterfaceNumber, - (long int)(intf->cur_altsetting - intf->altsetting)); - JOT(4, "intf[%i]: bInterfaceClass=0x%02X bInterfaceSubClass=0x%02X\n", - bInterfaceNumber, bInterfaceClass, bInterfaceSubClass); - - /* - * A new struct easycap is always allocated when interface 0 is probed. - * It is not possible here to free any existing struct easycap. - * This should have been done by easycap_delete() when the device was - * physically unplugged. - * The allocated struct easycap is saved for later usage when - * interfaces 1 and 2 are probed. - */ - if (0 == bInterfaceNumber) { - /* - * Alloc structure and save it in a free slot in - * easycapdc60_dongle array - */ - peasycap = alloc_easycap(bInterfaceNumber); - if (!peasycap) - return -ENOMEM; - - /* Perform basic struct initialization */ - init_easycap(peasycap, usbdev, intf, bInterfaceNumber); - - /* Dynamically fill in the available formats */ - rc = easycap_video_fillin_formats(); - if (0 > rc) { - SAM("ERROR: fillin_formats() rc = %i\n", rc); - return -EFAULT; - } - JOM(4, "%i formats available\n", rc); - - /* Populate easycap.inputset[] */ - rc = populate_inputset(peasycap); - if (rc < 0) - return rc; - JOM(4, "finished initialization\n"); - } else { - peasycap = get_easycap(usbdev, bInterfaceNumber); - if (!peasycap) - return -ENODEV; - } - - config_easycap(peasycap, bInterfaceNumber, - bInterfaceClass, - bInterfaceSubClass); - - /* - * Investigate all altsettings. This is done in detail - * because USB device 05e1:0408 has disparate incarnations. - */ - isokalt = 0; - for (i = 0; i < intf->num_altsetting; i++) { - alt = usb_altnum_to_altsetting(intf, i); - if (!alt) { - SAM("ERROR: alt is NULL\n"); - return -EFAULT; - } - interface = &alt->desc; - if (!interface) { - SAM("ERROR: intf_descriptor is NULL\n"); - return -EFAULT; - } - - if (0 == interface->bNumEndpoints) - JOM(4, "intf[%i]alt[%i] has no endpoints\n", - bInterfaceNumber, i); - for (j = 0; j < interface->bNumEndpoints; j++) { - ep = &alt->endpoint[j].desc; - if (!ep) { - SAM("ERROR: ep is NULL.\n"); - SAM("...... skipping\n"); - continue; - } - - if (!usb_endpoint_is_isoc_in(ep)) { - JOM(4, "intf[%i]alt[%i]end[%i] is a %d endpoint\n", - bInterfaceNumber, - i, j, ep->bmAttributes); - if (usb_endpoint_dir_out(ep)) { - SAM("ERROR: OUT endpoint unexpected\n"); - SAM("...... continuing\n"); - } - continue; - } - switch (bInterfaceClass) { - case USB_CLASS_VIDEO: - case USB_CLASS_VENDOR_SPEC: { - if (ep->wMaxPacketSize) { - if (8 > isokalt) { - okalt[isokalt] = i; - JOM(4, - "%i=okalt[%i]\n", - okalt[isokalt], - isokalt); - okepn[isokalt] = - ep-> - bEndpointAddress & - 0x0F; - JOM(4, - "%i=okepn[%i]\n", - okepn[isokalt], - isokalt); - okmps[isokalt] = - le16_to_cpu(ep-> - wMaxPacketSize); - JOM(4, - "%i=okmps[%i]\n", - okmps[isokalt], - isokalt); - isokalt++; - } - } else { - if (-1 == peasycap-> - video_altsetting_off) { - peasycap-> - video_altsetting_off = - i; - JOM(4, "%i=video_" - "altsetting_off " - "<====\n", - peasycap-> - video_altsetting_off); - } else { - SAM("ERROR: peasycap" - "->video_altsetting_" - "off already set\n"); - SAM("...... " - "continuing with " - "%i=peasycap->video_" - "altsetting_off\n", - peasycap-> - video_altsetting_off); - } - } - break; - } - case USB_CLASS_AUDIO: { - if (bInterfaceSubClass != - USB_SUBCLASS_AUDIOSTREAMING) - break; - if (!peasycap) { - SAM("MISTAKE: " - "peasycap is NULL\n"); - return -EFAULT; - } - if (ep->wMaxPacketSize) { - if (8 > isokalt) { - okalt[isokalt] = i ; - JOM(4, - "%i=okalt[%i]\n", - okalt[isokalt], - isokalt); - okepn[isokalt] = - ep-> - bEndpointAddress & - 0x0F; - JOM(4, - "%i=okepn[%i]\n", - okepn[isokalt], - isokalt); - okmps[isokalt] = - le16_to_cpu(ep-> - wMaxPacketSize); - JOM(4, - "%i=okmps[%i]\n", - okmps[isokalt], - isokalt); - isokalt++; - } - } else { - if (-1 == peasycap-> - audio_altsetting_off) { - peasycap-> - audio_altsetting_off = - i; - JOM(4, "%i=audio_" - "altsetting_off " - "<====\n", - peasycap-> - audio_altsetting_off); - } else { - SAM("ERROR: peasycap" - "->audio_altsetting_" - "off already set\n"); - SAM("...... " - "continuing with " - "%i=peasycap->" - "audio_altsetting_" - "off\n", - peasycap-> - audio_altsetting_off); - } - } - break; - } - default: - break; - } - if (0 == ep->wMaxPacketSize) { - JOM(4, "intf[%i]alt[%i]end[%i] " - "has zero packet size\n", - bInterfaceNumber, i, j); - } - } - } - - /* Perform initialization of the probed interface */ - JOM(4, "initialization begins for interface %i\n", - interface->bInterfaceNumber); - switch (bInterfaceNumber) { - /* 0: Video interface */ - case 0: { - if (!peasycap) { - SAM("MISTAKE: peasycap is NULL\n"); - return -EFAULT; - } - if (!isokalt) { - SAM("ERROR: no viable video_altsetting_on\n"); - return -ENOENT; - } - peasycap->video_altsetting_on = okalt[isokalt - 1]; - JOM(4, "%i=video_altsetting_on <====\n", - peasycap->video_altsetting_on); - - /* Decide video streaming parameters */ - peasycap->video_endpointnumber = okepn[isokalt - 1]; - JOM(4, "%i=video_endpointnumber\n", peasycap->video_endpointnumber); - maxpacketsize = okmps[isokalt - 1]; - - peasycap->video_isoc_maxframesize = - min(maxpacketsize, USB_2_0_MAXPACKETSIZE); - if (0 >= peasycap->video_isoc_maxframesize) { - SAM("ERROR: bad video_isoc_maxframesize\n"); - SAM(" possibly because port is USB 1.1\n"); - return -ENOENT; - } - JOM(4, "%i=video_isoc_maxframesize\n", - peasycap->video_isoc_maxframesize); - - peasycap->video_isoc_framesperdesc = VIDEO_ISOC_FRAMESPERDESC; - JOM(4, "%i=video_isoc_framesperdesc\n", - peasycap->video_isoc_framesperdesc); - if (0 >= peasycap->video_isoc_framesperdesc) { - SAM("ERROR: bad video_isoc_framesperdesc\n"); - return -ENOENT; - } - peasycap->video_isoc_buffer_size = - peasycap->video_isoc_maxframesize * - peasycap->video_isoc_framesperdesc; - JOM(4, "%i=video_isoc_buffer_size\n", - peasycap->video_isoc_buffer_size); - if ((PAGE_SIZE << VIDEO_ISOC_ORDER) < - peasycap->video_isoc_buffer_size) { - SAM("MISTAKE: peasycap->video_isoc_buffer_size too big\n"); - return -EFAULT; - } - if (-1 == peasycap->video_interface) { - SAM("MISTAKE: video_interface is unset\n"); - return -EFAULT; - } - if (-1 == peasycap->video_altsetting_on) { - SAM("MISTAKE: video_altsetting_on is unset\n"); - return -EFAULT; - } - if (-1 == peasycap->video_altsetting_off) { - SAM("MISTAKE: video_interface_off is unset\n"); - return -EFAULT; - } - if (-1 == peasycap->video_endpointnumber) { - SAM("MISTAKE: video_endpointnumber is unset\n"); - return -EFAULT; - } - if (-1 == peasycap->video_isoc_maxframesize) { - SAM("MISTAKE: video_isoc_maxframesize is unset\n"); - return -EFAULT; - } - if (-1 == peasycap->video_isoc_buffer_size) { - SAM("MISTAKE: video_isoc_buffer_size is unset\n"); - return -EFAULT; - } - - /* - * Allocate memory for video buffers. - * Lists must be initialized first. - */ - INIT_LIST_HEAD(&(peasycap->urb_video_head)); - peasycap->purb_video_head = &(peasycap->urb_video_head); - - rc = alloc_framebuffers(peasycap); - if (rc < 0) - return rc; - - rc = alloc_fieldbuffers(peasycap); - if (rc < 0) - return rc; - - rc = alloc_isocbuffers(peasycap); - if (rc < 0) - return rc; - - /* Allocate and initialize video urbs */ - rc = create_video_urbs(peasycap); - if (rc < 0) - return rc; - - /* Save pointer peasycap in this interface */ - usb_set_intfdata(intf, peasycap); - - /* - * It is essential to initialize the hardware before, - * rather than after, the device is registered, - * because some udev rules triggers easycap_open() - * immediately after registration, causing a clash. - */ - rc = reset(peasycap); - if (rc) { - SAM("ERROR: reset() rc = %i\n", rc); - return -EFAULT; - } - - /* The video device can now be registered */ - if (v4l2_device_register(&intf->dev, &peasycap->v4l2_device)) { - SAM("v4l2_device_register() failed\n"); - return -ENODEV; - } - JOM(4, "registered device instance: %s\n", - peasycap->v4l2_device.name); - - rc = easycap_register_video(peasycap); - if (rc < 0) { - dev_err(&intf->dev, - "Not able to register with videodev\n"); - return -ENODEV; - } - break; - } - /* 1: Audio control */ - case 1: { - if (!peasycap) { - SAM("MISTAKE: peasycap is NULL\n"); - return -EFAULT; - } - /* Save pointer peasycap in this interface */ - usb_set_intfdata(intf, peasycap); - JOM(4, "no initialization required for interface %i\n", - interface->bInterfaceNumber); - break; - } - /* 2: Audio streaming */ - case 2: { - if (!peasycap) { - SAM("MISTAKE: peasycap is NULL\n"); - return -EFAULT; - } - if (!isokalt) { - SAM("ERROR: no viable audio_altsetting_on\n"); - return -ENOENT; - } - peasycap->audio_altsetting_on = okalt[isokalt - 1]; - JOM(4, "%i=audio_altsetting_on <====\n", - peasycap->audio_altsetting_on); - - peasycap->audio_endpointnumber = okepn[isokalt - 1]; - JOM(4, "%i=audio_endpointnumber\n", peasycap->audio_endpointnumber); - - peasycap->audio_isoc_maxframesize = okmps[isokalt - 1]; - JOM(4, "%i=audio_isoc_maxframesize\n", - peasycap->audio_isoc_maxframesize); - if (0 >= peasycap->audio_isoc_maxframesize) { - SAM("ERROR: bad audio_isoc_maxframesize\n"); - return -ENOENT; - } - if (9 == peasycap->audio_isoc_maxframesize) { - peasycap->ilk |= 0x02; - SAM("audio hardware is microphone\n"); - peasycap->microphone = true; - peasycap->audio_pages_per_fragment = - PAGES_PER_AUDIO_FRAGMENT; - } else if (256 == peasycap->audio_isoc_maxframesize) { - peasycap->ilk &= ~0x02; - SAM("audio hardware is AC'97\n"); - peasycap->microphone = false; - peasycap->audio_pages_per_fragment = - PAGES_PER_AUDIO_FRAGMENT; - } else { - SAM("hardware is unidentified:\n"); - SAM("%i=audio_isoc_maxframesize\n", - peasycap->audio_isoc_maxframesize); - return -ENOENT; - } - - peasycap->audio_bytes_per_fragment = - peasycap->audio_pages_per_fragment * PAGE_SIZE; - peasycap->audio_buffer_page_many = (AUDIO_FRAGMENT_MANY * - peasycap->audio_pages_per_fragment); - - JOM(4, "%6i=AUDIO_FRAGMENT_MANY\n", AUDIO_FRAGMENT_MANY); - JOM(4, "%6i=audio_pages_per_fragment\n", - peasycap->audio_pages_per_fragment); - JOM(4, "%6i=audio_bytes_per_fragment\n", - peasycap->audio_bytes_per_fragment); - JOM(4, "%6i=audio_buffer_page_many\n", - peasycap->audio_buffer_page_many); - - peasycap->audio_isoc_framesperdesc = AUDIO_ISOC_FRAMESPERDESC; - - JOM(4, "%i=audio_isoc_framesperdesc\n", - peasycap->audio_isoc_framesperdesc); - if (0 >= peasycap->audio_isoc_framesperdesc) { - SAM("ERROR: bad audio_isoc_framesperdesc\n"); - return -ENOENT; - } - - peasycap->audio_isoc_buffer_size = - peasycap->audio_isoc_maxframesize * - peasycap->audio_isoc_framesperdesc; - JOM(4, "%i=audio_isoc_buffer_size\n", - peasycap->audio_isoc_buffer_size); - if (AUDIO_ISOC_BUFFER_SIZE < peasycap->audio_isoc_buffer_size) { - SAM("MISTAKE: audio_isoc_buffer_size bigger " - "than %li=AUDIO_ISOC_BUFFER_SIZE\n", - AUDIO_ISOC_BUFFER_SIZE); - return -EFAULT; - } - if (-1 == peasycap->audio_interface) { - SAM("MISTAKE: audio_interface is unset\n"); - return -EFAULT; - } - if (-1 == peasycap->audio_altsetting_on) { - SAM("MISTAKE: audio_altsetting_on is unset\n"); - return -EFAULT; - } - if (-1 == peasycap->audio_altsetting_off) { - SAM("MISTAKE: audio_interface_off is unset\n"); - return -EFAULT; - } - if (-1 == peasycap->audio_endpointnumber) { - SAM("MISTAKE: audio_endpointnumber is unset\n"); - return -EFAULT; - } - if (-1 == peasycap->audio_isoc_maxframesize) { - SAM("MISTAKE: audio_isoc_maxframesize is unset\n"); - return -EFAULT; - } - if (-1 == peasycap->audio_isoc_buffer_size) { - SAM("MISTAKE: audio_isoc_buffer_size is unset\n"); - return -EFAULT; - } - - /* - * Allocate memory for audio buffers. - * Lists must be initialized first. - */ - INIT_LIST_HEAD(&(peasycap->urb_audio_head)); - peasycap->purb_audio_head = &(peasycap->urb_audio_head); - - alloc_audio_buffers(peasycap); - if (rc < 0) - return rc; - - /* Allocate and initialize urbs */ - rc = create_audio_urbs(peasycap); - if (rc < 0) - return rc; - - /* Save pointer peasycap in this interface */ - usb_set_intfdata(intf, peasycap); - - /* The audio device can now be registered */ - JOM(4, "initializing ALSA card\n"); - - rc = easycap_alsa_probe(peasycap); - if (rc) { - dev_err(&intf->dev, "easycap_alsa_probe() rc = %i\n", - rc); - return -ENODEV; - } - - - JOM(8, "kref_get() with %i=kref.refcount.counter\n", - peasycap->kref.refcount.counter); - kref_get(&peasycap->kref); - peasycap->registered_audio++; - break; - } - /* Interfaces other than 0,1,2 are unexpected */ - default: - JOM(4, "ERROR: unexpected interface %i\n", bInterfaceNumber); - return -EINVAL; - } - SAM("ends successfully for interface %i\n", bInterfaceNumber); - return 0; -} - -/* - * When this function is called the device has already been - * physically unplugged. - * Hence, peasycap->pusb_device is no longer valid. - * This function affects alsa. - */ -static void easycap_usb_disconnect(struct usb_interface *pusb_interface) -{ - struct usb_host_interface *pusb_host_interface; - struct usb_interface_descriptor *pusb_interface_descriptor; - struct easycap *peasycap; - int minor, kd; - u8 bInterfaceNumber; - - JOT(4, "\n"); - - pusb_host_interface = pusb_interface->cur_altsetting; - if (!pusb_host_interface) { - JOT(4, "ERROR: pusb_host_interface is NULL\n"); - return; - } - pusb_interface_descriptor = &(pusb_host_interface->desc); - if (!pusb_interface_descriptor) { - JOT(4, "ERROR: pusb_interface_descriptor is NULL\n"); - return; - } - bInterfaceNumber = pusb_interface_descriptor->bInterfaceNumber; - minor = pusb_interface->minor; - JOT(4, "intf[%i]: minor=%i\n", bInterfaceNumber, minor); - - /* There is nothing to do for Interface Number 1 */ - if (1 == bInterfaceNumber) - return; - - peasycap = usb_get_intfdata(pusb_interface); - if (!peasycap) { - SAY("ERROR: peasycap is NULL\n"); - return; - } - - /* If the waitqueues are not cleared a deadlock is possible */ - peasycap->video_eof = 1; - peasycap->audio_eof = 1; - wake_up_interruptible(&(peasycap->wq_video)); - wake_up_interruptible(&(peasycap->wq_audio)); - - switch (bInterfaceNumber) { - case 0: - easycap_video_kill_urbs(peasycap); - break; - case 2: - easycap_audio_kill_urbs(peasycap); - break; - default: - break; - } - - /* - * Deregister - * This procedure will block until easycap_poll(), - * video and audio ioctl are all unlocked. - * If this is not done an oops can occur when an easycap - * is unplugged while the urbs are running. - */ - kd = easycap_isdongle(peasycap); - switch (bInterfaceNumber) { - case 0: { - if (0 <= kd && DONGLE_MANY > kd) { - wake_up_interruptible(&peasycap->wq_video); - JOM(4, "about to lock dongle[%i].mutex_video\n", kd); - if (mutex_lock_interruptible(&easycapdc60_dongle[kd]. - mutex_video)) { - SAY("ERROR: " - "cannot lock dongle[%i].mutex_video\n", kd); - return; - } - JOM(4, "locked dongle[%i].mutex_video\n", kd); - } else { - SAY("ERROR: %i=kd is bad: cannot lock dongle\n", kd); - } - if (!peasycap->v4l2_device.name[0]) { - SAM("ERROR: peasycap->v4l2_device.name is empty\n"); - if (0 <= kd && DONGLE_MANY > kd) - mutex_unlock(&easycapdc60_dongle[kd].mutex_video); - return; - } - v4l2_device_disconnect(&peasycap->v4l2_device); - JOM(4, "v4l2_device_disconnect() OK\n"); - v4l2_device_unregister(&peasycap->v4l2_device); - JOM(4, "v4l2_device_unregister() OK\n"); - - video_unregister_device(&peasycap->video_device); - JOM(4, "intf[%i]: video_unregister_device() minor=%i\n", - bInterfaceNumber, minor); - peasycap->registered_video--; - - if (0 <= kd && DONGLE_MANY > kd) { - mutex_unlock(&easycapdc60_dongle[kd].mutex_video); - JOM(4, "unlocked dongle[%i].mutex_video\n", kd); - } - break; - } - case 2: { - if (0 <= kd && DONGLE_MANY > kd) { - wake_up_interruptible(&peasycap->wq_audio); - JOM(4, "about to lock dongle[%i].mutex_audio\n", kd); - if (mutex_lock_interruptible(&easycapdc60_dongle[kd]. - mutex_audio)) { - SAY("ERROR: " - "cannot lock dongle[%i].mutex_audio\n", kd); - return; - } - JOM(4, "locked dongle[%i].mutex_audio\n", kd); - } else - SAY("ERROR: %i=kd is bad: cannot lock dongle\n", kd); - if (0 != snd_card_free(peasycap->psnd_card)) { - SAY("ERROR: snd_card_free() failed\n"); - } else { - peasycap->psnd_card = NULL; - (peasycap->registered_audio)--; - } - if (0 <= kd && DONGLE_MANY > kd) { - mutex_unlock(&easycapdc60_dongle[kd].mutex_audio); - JOM(4, "unlocked dongle[%i].mutex_audio\n", kd); - } - break; - } - default: - break; - } - - /* - * If no remaining references to peasycap, - * call easycap_delete. - * (Also when alsa has been in use) - */ - if (!peasycap->kref.refcount.counter) { - SAM("ERROR: peasycap->kref.refcount.counter is zero " - "so cannot call kref_put()\n"); - SAM("ending unsuccessfully: may cause memory leak\n"); - return; - } - if (0 <= kd && DONGLE_MANY > kd) { - JOM(4, "about to lock dongle[%i].mutex_video\n", kd); - if (mutex_lock_interruptible(&easycapdc60_dongle[kd].mutex_video)) { - SAY("ERROR: cannot lock dongle[%i].mutex_video\n", kd); - SAM("ending unsuccessfully: may cause memory leak\n"); - return; - } - JOM(4, "locked dongle[%i].mutex_video\n", kd); - JOM(4, "about to lock dongle[%i].mutex_audio\n", kd); - if (mutex_lock_interruptible(&easycapdc60_dongle[kd].mutex_audio)) { - SAY("ERROR: cannot lock dongle[%i].mutex_audio\n", kd); - mutex_unlock(&(easycapdc60_dongle[kd].mutex_video)); - JOM(4, "unlocked dongle[%i].mutex_video\n", kd); - SAM("ending unsuccessfully: may cause memory leak\n"); - return; - } - JOM(4, "locked dongle[%i].mutex_audio\n", kd); - } - JOM(4, "intf[%i]: %i=peasycap->kref.refcount.counter\n", - bInterfaceNumber, (int)peasycap->kref.refcount.counter); - kref_put(&peasycap->kref, easycap_delete); - JOT(4, "intf[%i]: kref_put() done.\n", bInterfaceNumber); - if (0 <= kd && DONGLE_MANY > kd) { - mutex_unlock(&(easycapdc60_dongle[kd].mutex_audio)); - JOT(4, "unlocked dongle[%i].mutex_audio\n", kd); - mutex_unlock(&easycapdc60_dongle[kd].mutex_video); - JOT(4, "unlocked dongle[%i].mutex_video\n", kd); - } - JOM(4, "ends\n"); - return; -} - -/* Devices supported by this driver */ -static struct usb_device_id easycap_usb_device_id_table[] = { - {USB_DEVICE(USB_EASYCAP_VENDOR_ID, USB_EASYCAP_PRODUCT_ID)}, - { } -}; - -MODULE_DEVICE_TABLE(usb, easycap_usb_device_id_table); -static struct usb_driver easycap_usb_driver = { - .name = "easycap", - .id_table = easycap_usb_device_id_table, - .probe = easycap_usb_probe, - .disconnect = easycap_usb_disconnect, -}; - -static int __init easycap_module_init(void) -{ - int k, rc; - - printk(KERN_INFO "Easycap version: "EASYCAP_DRIVER_VERSION "\n"); - - JOT(4, "begins. %i=debug %i=bars %i=gain\n", - easycap_debug, easycap_bars, easycap_gain); - - mutex_init(&mutex_dongle); - for (k = 0; k < DONGLE_MANY; k++) { - easycapdc60_dongle[k].peasycap = NULL; - mutex_init(&easycapdc60_dongle[k].mutex_video); - mutex_init(&easycapdc60_dongle[k].mutex_audio); - } - rc = usb_register(&easycap_usb_driver); - if (rc) - printk(KERN_ERR "Easycap: usb_register failed rc=%d\n", rc); - - return rc; -} - -static void __exit easycap_module_exit(void) -{ - usb_deregister(&easycap_usb_driver); -} - -module_init(easycap_module_init); -module_exit(easycap_module_exit); diff --git a/drivers/staging/media/easycap/easycap_settings.c b/drivers/staging/media/easycap/easycap_settings.c deleted file mode 100644 index 3f5f5b3e5a35..000000000000 --- a/drivers/staging/media/easycap/easycap_settings.c +++ /dev/null @@ -1,696 +0,0 @@ -/****************************************************************************** -* * -* easycap_settings.c * -* * -******************************************************************************/ -/* - * - * Copyright (C) 2010 R.M. Thomas <rmthomas@sciolus.org> - * - * - * This 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. - * - * The software 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 software; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * -*/ -/*****************************************************************************/ - -#include "easycap.h" - -/*---------------------------------------------------------------------------*/ -/* - * THE LEAST SIGNIFICANT BIT OF easycap_standard.mask HAS MEANING: - * 0 => 25 fps - * 1 => 30 fps - * - * THE MOST SIGNIFICANT BIT OF easycap_standard.mask HAS MEANING: - * 0 => full framerate - * 1 => 20% framerate - */ -/*---------------------------------------------------------------------------*/ -const struct easycap_standard easycap_standard[] = { - { - .mask = 0x00FF & PAL_BGHIN , - .v4l2_standard = { - .index = PAL_BGHIN, - .id = (V4L2_STD_PAL_B | - V4L2_STD_PAL_G | V4L2_STD_PAL_H | - V4L2_STD_PAL_I | V4L2_STD_PAL_N), - .name = "PAL_BGHIN", - .frameperiod = {1, 25}, - .framelines = 625, - .reserved = {0, 0, 0, 0} - } - }, -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - { - .mask = 0x00FF & NTSC_N_443 , - .v4l2_standard = { - .index = NTSC_N_443, - .id = V4L2_STD_UNKNOWN, - .name = "NTSC_N_443", - .frameperiod = {1, 25}, - .framelines = 480, - .reserved = {0, 0, 0, 0} - } - }, -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - { - .mask = 0x00FF & PAL_Nc , - .v4l2_standard = { - .index = PAL_Nc, - .id = V4L2_STD_PAL_Nc, - .name = "PAL_Nc", - .frameperiod = {1, 25}, - .framelines = 625, - .reserved = {0, 0, 0, 0} - } - }, -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - { - .mask = 0x00FF & NTSC_N , - .v4l2_standard = { - .index = NTSC_N, - .id = V4L2_STD_UNKNOWN, - .name = "NTSC_N", - .frameperiod = {1, 25}, - .framelines = 525, - .reserved = {0, 0, 0, 0} - } - }, -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - { - .mask = 0x00FF & SECAM , - .v4l2_standard = { - .index = SECAM, - .id = V4L2_STD_SECAM, - .name = "SECAM", - .frameperiod = {1, 25}, - .framelines = 625, - .reserved = {0, 0, 0, 0} - } - }, -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - { - .mask = 0x00FF & NTSC_M , - .v4l2_standard = { - .index = NTSC_M, - .id = V4L2_STD_NTSC_M, - .name = "NTSC_M", - .frameperiod = {1, 30}, - .framelines = 525, - .reserved = {0, 0, 0, 0} - } - }, -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - { - .mask = 0x00FF & NTSC_M_JP , - .v4l2_standard = { - .index = NTSC_M_JP, - .id = V4L2_STD_NTSC_M_JP, - .name = "NTSC_M_JP", - .frameperiod = {1, 30}, - .framelines = 525, - .reserved = {0, 0, 0, 0} - } - }, -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - { - .mask = 0x00FF & PAL_60 , - .v4l2_standard = { - .index = PAL_60, - .id = V4L2_STD_PAL_60, - .name = "PAL_60", - .frameperiod = {1, 30}, - .framelines = 525, - .reserved = {0, 0, 0, 0} - } - }, -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - { - .mask = 0x00FF & NTSC_443 , - .v4l2_standard = { - .index = NTSC_443, - .id = V4L2_STD_NTSC_443, - .name = "NTSC_443", - .frameperiod = {1, 30}, - .framelines = 525, - .reserved = {0, 0, 0, 0} - } - }, -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - { - .mask = 0x00FF & PAL_M , - .v4l2_standard = { - .index = PAL_M, - .id = V4L2_STD_PAL_M, - .name = "PAL_M", - .frameperiod = {1, 30}, - .framelines = 525, - .reserved = {0, 0, 0, 0} - } - }, -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - { - .mask = 0x8000 | (0x00FF & PAL_BGHIN_SLOW), - .v4l2_standard = { - .index = PAL_BGHIN_SLOW, - .id = (V4L2_STD_PAL_B | V4L2_STD_PAL_G | - V4L2_STD_PAL_H | - V4L2_STD_PAL_I | V4L2_STD_PAL_N | - (((v4l2_std_id)0x01) << 32)), - .name = "PAL_BGHIN_SLOW", - .frameperiod = {1, 5}, - .framelines = 625, - .reserved = {0, 0, 0, 0} - } - }, -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - { - .mask = 0x8000 | (0x00FF & NTSC_N_443_SLOW), - .v4l2_standard = { - .index = NTSC_N_443_SLOW, - .id = (V4L2_STD_UNKNOWN | (((v4l2_std_id)0x11) << 32)), - .name = "NTSC_N_443_SLOW", - .frameperiod = {1, 5}, - .framelines = 480, - .reserved = {0, 0, 0, 0} - } - }, -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - { - .mask = 0x8000 | (0x00FF & PAL_Nc_SLOW), - .v4l2_standard = { - .index = PAL_Nc_SLOW, - .id = (V4L2_STD_PAL_Nc | (((v4l2_std_id)0x01) << 32)), - .name = "PAL_Nc_SLOW", - .frameperiod = {1, 5}, - .framelines = 625, - .reserved = {0, 0, 0, 0} - } - }, -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - { - .mask = 0x8000 | (0x00FF & NTSC_N_SLOW), - .v4l2_standard = { - .index = NTSC_N_SLOW, - .id = (V4L2_STD_UNKNOWN | (((v4l2_std_id)0x21) << 32)), - .name = "NTSC_N_SLOW", - .frameperiod = {1, 5}, - .framelines = 525, - .reserved = {0, 0, 0, 0} - } - }, -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - { - .mask = 0x8000 | (0x00FF & SECAM_SLOW), - .v4l2_standard = { - .index = SECAM_SLOW, - .id = (V4L2_STD_SECAM | (((v4l2_std_id)0x01) << 32)), - .name = "SECAM_SLOW", - .frameperiod = {1, 5}, - .framelines = 625, - .reserved = {0, 0, 0, 0} - } - }, -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - { - .mask = 0x8000 | (0x00FF & NTSC_M_SLOW), - .v4l2_standard = { - .index = NTSC_M_SLOW, - .id = (V4L2_STD_NTSC_M | (((v4l2_std_id)0x01) << 32)), - .name = "NTSC_M_SLOW", - .frameperiod = {1, 6}, - .framelines = 525, - .reserved = {0, 0, 0, 0} - } - }, -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - { - .mask = 0x8000 | (0x00FF & NTSC_M_JP_SLOW), - .v4l2_standard = { - .index = NTSC_M_JP_SLOW, - .id = (V4L2_STD_NTSC_M_JP | - (((v4l2_std_id)0x01) << 32)), - .name = "NTSC_M_JP_SLOW", - .frameperiod = {1, 6}, - .framelines = 525, - .reserved = {0, 0, 0, 0} - } - }, -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - { - .mask = 0x8000 | (0x00FF & PAL_60_SLOW), - .v4l2_standard = { - .index = PAL_60_SLOW, - .id = (V4L2_STD_PAL_60 | (((v4l2_std_id)0x01) << 32)), - .name = "PAL_60_SLOW", - .frameperiod = {1, 6}, - .framelines = 525, - .reserved = {0, 0, 0, 0} - } - }, -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - { - .mask = 0x8000 | (0x00FF & NTSC_443_SLOW), - .v4l2_standard = { - .index = NTSC_443_SLOW, - .id = (V4L2_STD_NTSC_443 | (((v4l2_std_id)0x01) << 32)), - .name = "NTSC_443_SLOW", - .frameperiod = {1, 6}, - .framelines = 525, - .reserved = {0, 0, 0, 0} - } - }, -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - { - .mask = 0x8000 | (0x00FF & PAL_M_SLOW), - .v4l2_standard = { - .index = PAL_M_SLOW, - .id = (V4L2_STD_PAL_M | (((v4l2_std_id)0x01) << 32)), - .name = "PAL_M_SLOW", - .frameperiod = {1, 6}, - .framelines = 525, - .reserved = {0, 0, 0, 0} - } - }, -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - { - .mask = 0xFFFF - } -}; -/*---------------------------------------------------------------------------*/ -/* - * THE 16-BIT easycap_format.mask HAS MEANING: - * (least significant) BIT 0: 0 => PAL, 25 FPS; 1 => NTSC, 30 FPS - * BITS 2-4: RESERVED FOR DIFFERENTIATING STANDARDS - * BITS 5-7: NUMBER OF BYTES PER PIXEL - * BIT 8: 0 => NATIVE BYTE ORDER; 1 => SWAPPED - * BITS 9-10: RESERVED FOR OTHER BYTE PERMUTATIONS - * BIT 11: 0 => UNDECIMATED; 1 => DECIMATED - * BIT 12: 0 => OFFER FRAMES; 1 => OFFER FIELDS - * BIT 13: 0 => FULL FRAMERATE; 1 => REDUCED - * (most significant) BITS 14-15: RESERVED FOR OTHER FIELD/FRAME OPTIONS - * IT FOLLOWS THAT: - * bytesperpixel IS ((0x00E0 & easycap_format.mask) >> 5) - * byteswaporder IS true IF (0 != (0x0100 & easycap_format.mask)) - * - * decimatepixel IS true IF (0 != (0x0800 & easycap_format.mask)) - * - * offerfields IS true IF (0 != (0x1000 & easycap_format.mask)) - */ -/*---------------------------------------------------------------------------*/ - -struct easycap_format easycap_format[1 + SETTINGS_MANY]; - -int easycap_video_fillin_formats(void) -{ - const char *name1, *name2, *name3, *name4; - struct v4l2_format *fmt; - int i, j, k, m, n; - u32 width, height, pixelformat, bytesperline, sizeimage; - u16 mask1, mask2, mask3, mask4; - enum v4l2_field field; - enum v4l2_colorspace colorspace; - - for (i = 0, n = 0; i < STANDARD_MANY; i++) { - mask1 = 0x0000; - switch (i) { - case PAL_BGHIN: { - mask1 = 0x1F & PAL_BGHIN; - name1 = "PAL_BGHIN"; - colorspace = V4L2_COLORSPACE_470_SYSTEM_BG; - break; - } - case SECAM: { - mask1 = 0x1F & SECAM; - name1 = "SECAM"; - colorspace = V4L2_COLORSPACE_470_SYSTEM_BG; - break; - } - case PAL_Nc: { - mask1 = 0x1F & PAL_Nc; - name1 = "PAL_Nc"; - colorspace = V4L2_COLORSPACE_470_SYSTEM_BG; - break; - } - case PAL_60: { - mask1 = 0x1F & PAL_60; - name1 = "PAL_60"; - colorspace = V4L2_COLORSPACE_470_SYSTEM_BG; - break; - } - case PAL_M: { - mask1 = 0x1F & PAL_M; - name1 = "PAL_M"; - colorspace = V4L2_COLORSPACE_470_SYSTEM_BG; - break; - } - case NTSC_M: { - mask1 = 0x1F & NTSC_M; - name1 = "NTSC_M"; - colorspace = V4L2_COLORSPACE_470_SYSTEM_M; - break; - } - case NTSC_443: { - mask1 = 0x1F & NTSC_443; - name1 = "NTSC_443"; - colorspace = V4L2_COLORSPACE_470_SYSTEM_M; - break; - } - case NTSC_M_JP: { - mask1 = 0x1F & NTSC_M_JP; - name1 = "NTSC_M_JP"; - colorspace = V4L2_COLORSPACE_470_SYSTEM_M; - break; - } - case NTSC_N: { - mask1 = 0x1F & NTSC_M; - name1 = "NTSC_N"; - colorspace = V4L2_COLORSPACE_470_SYSTEM_M; - break; - } - case NTSC_N_443: { - mask1 = 0x1F & NTSC_N_443; - name1 = "NTSC_N_443"; - colorspace = V4L2_COLORSPACE_470_SYSTEM_M; - break; - } - case PAL_BGHIN_SLOW: { - mask1 = 0x001F & PAL_BGHIN_SLOW; - mask1 |= 0x0200; - name1 = "PAL_BGHIN_SLOW"; - colorspace = V4L2_COLORSPACE_470_SYSTEM_BG; - break; - } - case SECAM_SLOW: { - mask1 = 0x001F & SECAM_SLOW; - mask1 |= 0x0200; - name1 = "SECAM_SLOW"; - colorspace = V4L2_COLORSPACE_470_SYSTEM_BG; - break; - } - case PAL_Nc_SLOW: { - mask1 = 0x001F & PAL_Nc_SLOW; - mask1 |= 0x0200; - name1 = "PAL_Nc_SLOW"; - colorspace = V4L2_COLORSPACE_470_SYSTEM_BG; - break; - } - case PAL_60_SLOW: { - mask1 = 0x001F & PAL_60_SLOW; - mask1 |= 0x0200; - name1 = "PAL_60_SLOW"; - colorspace = V4L2_COLORSPACE_470_SYSTEM_BG; - break; - } - case PAL_M_SLOW: { - mask1 = 0x001F & PAL_M_SLOW; - mask1 |= 0x0200; - name1 = "PAL_M_SLOW"; - colorspace = V4L2_COLORSPACE_470_SYSTEM_BG; - break; - } - case NTSC_M_SLOW: { - mask1 = 0x001F & NTSC_M_SLOW; - mask1 |= 0x0200; - name1 = "NTSC_M_SLOW"; - colorspace = V4L2_COLORSPACE_470_SYSTEM_M; - break; - } - case NTSC_443_SLOW: { - mask1 = 0x001F & NTSC_443_SLOW; - mask1 |= 0x0200; - name1 = "NTSC_443_SLOW"; - colorspace = V4L2_COLORSPACE_470_SYSTEM_M; - break; - } - case NTSC_M_JP_SLOW: { - mask1 = 0x001F & NTSC_M_JP_SLOW; - mask1 |= 0x0200; - name1 = "NTSC_M_JP_SLOW"; - colorspace = V4L2_COLORSPACE_470_SYSTEM_M; - break; - } - case NTSC_N_SLOW: { - mask1 = 0x001F & NTSC_N_SLOW; - mask1 |= 0x0200; - name1 = "NTSC_N_SLOW"; - colorspace = V4L2_COLORSPACE_470_SYSTEM_M; - break; - } - case NTSC_N_443_SLOW: { - mask1 = 0x001F & NTSC_N_443_SLOW; - mask1 |= 0x0200; - name1 = "NTSC_N_443_SLOW"; - colorspace = V4L2_COLORSPACE_470_SYSTEM_M; - break; - } - default: - return -1; - } - - for (j = 0; j < RESOLUTION_MANY; j++) { - mask2 = 0x0000; - switch (j) { - case AT_720x576: { - if (0x1 & mask1) - continue; - name2 = "_AT_720x576"; - width = 720; - height = 576; - break; - } - case AT_704x576: { - if (0x1 & mask1) - continue; - name2 = "_AT_704x576"; - width = 704; - height = 576; - break; - } - case AT_640x480: { - name2 = "_AT_640x480"; - width = 640; - height = 480; - break; - } - case AT_720x480: { - if (!(0x1 & mask1)) - continue; - name2 = "_AT_720x480"; - width = 720; - height = 480; - break; - } - case AT_360x288: { - if (0x1 & mask1) - continue; - name2 = "_AT_360x288"; - width = 360; - height = 288; - mask2 = 0x0800; - break; - } - case AT_320x240: { - name2 = "_AT_320x240"; - width = 320; - height = 240; - mask2 = 0x0800; - break; - } - case AT_360x240: { - if (!(0x1 & mask1)) - continue; - name2 = "_AT_360x240"; - width = 360; - height = 240; - mask2 = 0x0800; - break; - } - default: - return -2; - } - - for (k = 0; k < PIXELFORMAT_MANY; k++) { - mask3 = 0x0000; - switch (k) { - case FMT_UYVY: { - name3 = __stringify(FMT_UYVY); - pixelformat = V4L2_PIX_FMT_UYVY; - mask3 |= (0x02 << 5); - break; - } - case FMT_YUY2: { - name3 = __stringify(FMT_YUY2); - pixelformat = V4L2_PIX_FMT_YUYV; - mask3 |= (0x02 << 5); - mask3 |= 0x0100; - break; - } - case FMT_RGB24: { - name3 = __stringify(FMT_RGB24); - pixelformat = V4L2_PIX_FMT_RGB24; - mask3 |= (0x03 << 5); - break; - } - case FMT_RGB32: { - name3 = __stringify(FMT_RGB32); - pixelformat = V4L2_PIX_FMT_RGB32; - mask3 |= (0x04 << 5); - break; - } - case FMT_BGR24: { - name3 = __stringify(FMT_BGR24); - pixelformat = V4L2_PIX_FMT_BGR24; - mask3 |= (0x03 << 5); - mask3 |= 0x0100; - break; - } - case FMT_BGR32: { - name3 = __stringify(FMT_BGR32); - pixelformat = V4L2_PIX_FMT_BGR32; - mask3 |= (0x04 << 5); - mask3 |= 0x0100; - break; - } - default: - return -3; - } - bytesperline = width * ((mask3 & 0x00E0) >> 5); - sizeimage = bytesperline * height; - - for (m = 0; m < INTERLACE_MANY; m++) { - mask4 = 0x0000; - switch (m) { - case FIELD_NONE: { - name4 = "-n"; - field = V4L2_FIELD_NONE; - break; - } - case FIELD_INTERLACED: { - name4 = "-i"; - mask4 |= 0x1000; - field = V4L2_FIELD_INTERLACED; - break; - } - default: - return -4; - } - if (SETTINGS_MANY <= n) - return -5; - - strcpy(easycap_format[n].name, name1); - strcat(easycap_format[n].name, name2); - strcat(easycap_format[n].name, "_"); - strcat(easycap_format[n].name, name3); - strcat(easycap_format[n].name, name4); - easycap_format[n].mask = - mask1 | mask2 | mask3 | mask4; - fmt = &easycap_format[n].v4l2_format; - - fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - fmt->fmt.pix.width = width; - fmt->fmt.pix.height = height; - fmt->fmt.pix.pixelformat = pixelformat; - fmt->fmt.pix.field = field; - fmt->fmt.pix.bytesperline = bytesperline; - fmt->fmt.pix.sizeimage = sizeimage; - fmt->fmt.pix.colorspace = colorspace; - fmt->fmt.pix.priv = 0; - n++; - } - } - } - } - if ((1 + SETTINGS_MANY) <= n) - return -6; - easycap_format[n].mask = 0xFFFF; - return n; -} -/*---------------------------------------------------------------------------*/ -struct v4l2_queryctrl easycap_control[] = { - { - .id = V4L2_CID_BRIGHTNESS, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Brightness", - .minimum = 0, - .maximum = 255, - .step = 1, - .default_value = SAA_0A_DEFAULT, - .flags = 0, - .reserved = {0, 0} - }, -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - { - .id = V4L2_CID_CONTRAST, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Contrast", - .minimum = 0, - .maximum = 255, - .step = 1, - .default_value = SAA_0B_DEFAULT + 128, - .flags = 0, - .reserved = {0, 0} - }, -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - { - .id = V4L2_CID_SATURATION, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Saturation", - .minimum = 0, - .maximum = 255, - .step = 1, - .default_value = SAA_0C_DEFAULT + 128, - .flags = 0, - .reserved = {0, 0} - }, -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - { - .id = V4L2_CID_HUE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Hue", - .minimum = 0, - .maximum = 255, - .step = 1, - .default_value = SAA_0D_DEFAULT + 128, - .flags = 0, - .reserved = {0, 0} - }, -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - { - .id = V4L2_CID_AUDIO_VOLUME, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Volume", - .minimum = 0, - .maximum = 31, - .step = 1, - .default_value = 16, - .flags = 0, - .reserved = {0, 0} - }, -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - { - .id = V4L2_CID_AUDIO_MUTE, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "Mute", - .default_value = true, - .flags = 0, - .reserved = {0, 0} - }, -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - { - .id = 0xFFFFFFFF - } -}; -/*****************************************************************************/ diff --git a/drivers/staging/media/easycap/easycap_sound.c b/drivers/staging/media/easycap/easycap_sound.c deleted file mode 100644 index 8c8bcae8ded8..000000000000 --- a/drivers/staging/media/easycap/easycap_sound.c +++ /dev/null @@ -1,750 +0,0 @@ -/****************************************************************************** -* * -* easycap_sound.c * -* * -* Audio driver for EasyCAP USB2.0 Video Capture Device DC60 * -* * -* * -******************************************************************************/ -/* - * - * Copyright (C) 2010 R.M. Thomas <rmthomas@sciolus.org> - * - * - * This 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. - * - * The software 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 software; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * -*/ -/*****************************************************************************/ - -#include "easycap.h" - -/*--------------------------------------------------------------------------*/ -/* - * PARAMETERS USED WHEN REGISTERING THE AUDIO INTERFACE - */ -/*--------------------------------------------------------------------------*/ -static const struct snd_pcm_hardware alsa_hardware = { - .info = SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_MMAP_VALID, - .formats = SNDRV_PCM_FMTBIT_S16_LE, - .rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000, - .rate_min = 32000, - .rate_max = 48000, - .channels_min = 2, - .channels_max = 2, - .buffer_bytes_max = PAGE_SIZE * - PAGES_PER_AUDIO_FRAGMENT * - AUDIO_FRAGMENT_MANY, - .period_bytes_min = PAGE_SIZE * PAGES_PER_AUDIO_FRAGMENT, - .period_bytes_max = PAGE_SIZE * PAGES_PER_AUDIO_FRAGMENT * 2, - .periods_min = AUDIO_FRAGMENT_MANY, - .periods_max = AUDIO_FRAGMENT_MANY * 2, -}; - - -/*---------------------------------------------------------------------------*/ -/* - * SUBMIT ALL AUDIO URBS. - */ -/*---------------------------------------------------------------------------*/ -static int easycap_audio_submit_urbs(struct easycap *peasycap) -{ - struct data_urb *pdata_urb; - struct urb *purb; - struct list_head *plist_head; - int j, isbad, nospc, m, rc; - int isbuf; - - if (!peasycap->purb_audio_head) { - SAM("ERROR: peasycap->urb_audio_head uninitialized\n"); - return -EFAULT; - } - if (!peasycap->pusb_device) { - SAM("ERROR: peasycap->pusb_device is NULL\n"); - return -EFAULT; - } - - if (peasycap->audio_isoc_streaming) { - JOM(4, "already streaming audio urbs\n"); - return 0; - } - - JOM(4, "initial submission of all audio urbs\n"); - rc = usb_set_interface(peasycap->pusb_device, - peasycap->audio_interface, - peasycap->audio_altsetting_on); - JOM(8, "usb_set_interface(.,%i,%i) returned %i\n", - peasycap->audio_interface, - peasycap->audio_altsetting_on, rc); - - isbad = 0; - nospc = 0; - m = 0; - list_for_each(plist_head, peasycap->purb_audio_head) { - pdata_urb = list_entry(plist_head, struct data_urb, list_head); - if (pdata_urb && pdata_urb->purb) { - purb = pdata_urb->purb; - isbuf = pdata_urb->isbuf; - - purb->interval = 1; - purb->dev = peasycap->pusb_device; - purb->pipe = usb_rcvisocpipe(peasycap->pusb_device, - peasycap->audio_endpointnumber); - purb->transfer_flags = URB_ISO_ASAP; - purb->transfer_buffer = peasycap->audio_isoc_buffer[isbuf].pgo; - purb->transfer_buffer_length = peasycap->audio_isoc_buffer_size; - purb->complete = easycap_alsa_complete; - purb->context = peasycap; - purb->start_frame = 0; - purb->number_of_packets = peasycap->audio_isoc_framesperdesc; - for (j = 0; j < peasycap->audio_isoc_framesperdesc; j++) { - purb->iso_frame_desc[j].offset = j * peasycap->audio_isoc_maxframesize; - purb->iso_frame_desc[j].length = peasycap->audio_isoc_maxframesize; - } - - rc = usb_submit_urb(purb, GFP_KERNEL); - if (rc) { - isbad++; - SAM("ERROR: usb_submit_urb() failed" - " for urb with rc: -%s: %d\n", - strerror(rc), rc); - } else { - m++; - } - } else { - isbad++; - } - } - if (nospc) { - SAM("-ENOSPC=usb_submit_urb() for %i urbs\n", nospc); - SAM("..... possibly inadequate USB bandwidth\n"); - peasycap->audio_eof = 1; - } - - if (isbad) - easycap_audio_kill_urbs(peasycap); - else - peasycap->audio_isoc_streaming = m; - - return 0; -} -/*---------------------------------------------------------------------------*/ -/* - * COMMON AUDIO INITIALIZATION - */ -/*---------------------------------------------------------------------------*/ -static int easycap_sound_setup(struct easycap *peasycap) -{ - int rc; - - JOM(4, "starting initialization\n"); - - if (!peasycap) { - SAY("ERROR: peasycap is NULL.\n"); - return -EFAULT; - } - if (!peasycap->pusb_device) { - SAM("ERROR: peasycap->pusb_device is NULL\n"); - return -ENODEV; - } - JOM(16, "0x%08lX=peasycap->pusb_device\n", (long int)peasycap->pusb_device); - - rc = easycap_audio_setup(peasycap); - JOM(8, "audio_setup() returned %i\n", rc); - - if (!peasycap->pusb_device) { - SAM("ERROR: peasycap->pusb_device has become NULL\n"); - return -ENODEV; - } -/*---------------------------------------------------------------------------*/ - if (!peasycap->pusb_device) { - SAM("ERROR: peasycap->pusb_device has become NULL\n"); - return -ENODEV; - } - rc = usb_set_interface(peasycap->pusb_device, peasycap->audio_interface, - peasycap->audio_altsetting_on); - JOM(8, "usb_set_interface(.,%i,%i) returned %i\n", peasycap->audio_interface, - peasycap->audio_altsetting_on, rc); - - rc = easycap_wakeup_device(peasycap->pusb_device); - JOM(8, "wakeup_device() returned %i\n", rc); - - peasycap->audio_eof = 0; - peasycap->audio_idle = 0; - - easycap_audio_submit_urbs(peasycap); - - JOM(4, "finished initialization\n"); - return 0; -} -/*****************************************************************************/ -/*---------------------------------------------------------------------------*/ -/* - * ON COMPLETION OF AN AUDIO URB ITS DATA IS COPIED TO THE DAM BUFFER - * PROVIDED peasycap->audio_idle IS ZERO. REGARDLESS OF THIS BEING TRUE, - * IT IS RESUBMITTED PROVIDED peasycap->audio_isoc_streaming IS NOT ZERO. - */ -/*---------------------------------------------------------------------------*/ -void easycap_alsa_complete(struct urb *purb) -{ - struct easycap *peasycap; - struct snd_pcm_substream *pss; - struct snd_pcm_runtime *prt; - int dma_bytes, fragment_bytes; - int isfragment; - u8 *p1, *p2; - s16 tmp; - int i, j, more, much, rc; -#ifdef UPSAMPLE - int k; - s16 oldaudio, newaudio, delta; -#endif /*UPSAMPLE*/ - - JOT(16, "\n"); - - if (!purb) { - SAY("ERROR: purb is NULL\n"); - return; - } - peasycap = purb->context; - if (!peasycap) { - SAY("ERROR: peasycap is NULL\n"); - return; - } - much = 0; - if (peasycap->audio_idle) { - JOM(16, "%i=audio_idle %i=audio_isoc_streaming\n", - peasycap->audio_idle, peasycap->audio_isoc_streaming); - if (peasycap->audio_isoc_streaming) - goto resubmit; - } -/*---------------------------------------------------------------------------*/ - pss = peasycap->psubstream; - if (!pss) - goto resubmit; - prt = pss->runtime; - if (!prt) - goto resubmit; - dma_bytes = (int)prt->dma_bytes; - if (0 == dma_bytes) - goto resubmit; - fragment_bytes = 4 * ((int)prt->period_size); - if (0 == fragment_bytes) - goto resubmit; -/* -------------------------------------------------------------------------*/ - if (purb->status) { - if ((-ESHUTDOWN == purb->status) || (-ENOENT == purb->status)) { - JOM(16, "urb status -ESHUTDOWN or -ENOENT\n"); - return; - } - SAM("ERROR: non-zero urb status: -%s: %d\n", - strerror(purb->status), purb->status); - goto resubmit; - } -/*---------------------------------------------------------------------------*/ -/* - * PROCEED HERE WHEN NO ERROR - */ -/*---------------------------------------------------------------------------*/ - -#ifdef UPSAMPLE - oldaudio = peasycap->oldaudio; -#endif /*UPSAMPLE*/ - - for (i = 0; i < purb->number_of_packets; i++) { - if (purb->iso_frame_desc[i].status < 0) { - SAM("-%s: %d\n", - strerror(purb->iso_frame_desc[i].status), - purb->iso_frame_desc[i].status); - } - if (purb->iso_frame_desc[i].status) { - JOM(12, "discarding audio samples because " - "%i=purb->iso_frame_desc[i].status\n", - purb->iso_frame_desc[i].status); - continue; - } - more = purb->iso_frame_desc[i].actual_length; - if (more == 0) { - peasycap->audio_mt++; - continue; - } - if (0 > more) { - SAM("MISTAKE: more is negative\n"); - return; - } - - if (peasycap->audio_mt) { - JOM(12, "%4i empty audio urb frames\n", - peasycap->audio_mt); - peasycap->audio_mt = 0; - } - - p1 = (u8 *)(purb->transfer_buffer + - purb->iso_frame_desc[i].offset); - - /* - * COPY more BYTES FROM ISOC BUFFER - * TO THE DMA BUFFER, CONVERTING - * 8-BIT MONO TO 16-BIT SIGNED - * LITTLE-ENDIAN SAMPLES IF NECESSARY - */ - while (more) { - much = dma_bytes - peasycap->dma_fill; - if (0 > much) { - SAM("MISTAKE: much is negative\n"); - return; - } - if (0 == much) { - peasycap->dma_fill = 0; - peasycap->dma_next = fragment_bytes; - JOM(8, "wrapped dma buffer\n"); - } - if (!peasycap->microphone) { - if (much > more) - much = more; - memcpy(prt->dma_area + peasycap->dma_fill, - p1, much); - p1 += much; - more -= much; - } else { -#ifdef UPSAMPLE - if (much % 16) - JOM(8, "MISTAKE? much" - " is not divisible by 16\n"); - if (much > (16 * more)) - much = 16 * more; - p2 = (u8 *)(prt->dma_area + peasycap->dma_fill); - - for (j = 0; j < (much / 16); j++) { - newaudio = ((int) *p1) - 128; - newaudio = 128 * newaudio; - - delta = (newaudio - oldaudio) / 4; - tmp = oldaudio + delta; - - for (k = 0; k < 4; k++) { - *p2 = (0x00FF & tmp); - *(p2 + 1) = (0xFF00 & tmp) >> 8; - p2 += 2; - *p2 = (0x00FF & tmp); - *(p2 + 1) = (0xFF00 & tmp) >> 8; - p2 += 2; - tmp += delta; - } - p1++; - more--; - oldaudio = tmp; - } -#else /*!UPSAMPLE*/ - if (much > (2 * more)) - much = 2 * more; - p2 = (u8 *)(prt->dma_area + peasycap->dma_fill); - - for (j = 0; j < (much / 2); j++) { - tmp = ((int) *p1) - 128; - tmp = 128 * tmp; - *p2 = (0x00FF & tmp); - *(p2 + 1) = (0xFF00 & tmp) >> 8; - p1++; - p2 += 2; - more--; - } -#endif /*UPSAMPLE*/ - } - peasycap->dma_fill += much; - if (peasycap->dma_fill >= peasycap->dma_next) { - isfragment = peasycap->dma_fill / fragment_bytes; - if (0 > isfragment) { - SAM("MISTAKE: isfragment is negative\n"); - return; - } - peasycap->dma_read = (isfragment - 1) * fragment_bytes; - peasycap->dma_next = (isfragment + 1) * fragment_bytes; - if (dma_bytes < peasycap->dma_next) - peasycap->dma_next = fragment_bytes; - - if (0 <= peasycap->dma_read) { - JOM(8, "snd_pcm_period_elapsed(), %i=" - "isfragment\n", isfragment); - snd_pcm_period_elapsed(pss); - } - } - } - -#ifdef UPSAMPLE - peasycap->oldaudio = oldaudio; -#endif /*UPSAMPLE*/ - - } -/*---------------------------------------------------------------------------*/ -/* - * RESUBMIT THIS URB - */ -/*---------------------------------------------------------------------------*/ -resubmit: - if (peasycap->audio_isoc_streaming == 0) - return; - - rc = usb_submit_urb(purb, GFP_ATOMIC); - if (rc) { - if ((-ENODEV != rc) && (-ENOENT != rc)) { - SAM("ERROR: while %i=audio_idle, usb_submit_urb failed " - "with rc: -%s :%d\n", - peasycap->audio_idle, strerror(rc), rc); - } - if (0 < peasycap->audio_isoc_streaming) - peasycap->audio_isoc_streaming--; - } - return; -} -/*****************************************************************************/ -static int easycap_alsa_open(struct snd_pcm_substream *pss) -{ - struct snd_pcm *psnd_pcm; - struct snd_card *psnd_card; - struct easycap *peasycap; - - JOT(4, "\n"); - if (!pss) { - SAY("ERROR: pss is NULL\n"); - return -EFAULT; - } - psnd_pcm = pss->pcm; - if (!psnd_pcm) { - SAY("ERROR: psnd_pcm is NULL\n"); - return -EFAULT; - } - psnd_card = psnd_pcm->card; - if (!psnd_card) { - SAY("ERROR: psnd_card is NULL\n"); - return -EFAULT; - } - - peasycap = psnd_card->private_data; - if (!peasycap) { - SAY("ERROR: peasycap is NULL\n"); - return -EFAULT; - } - if (peasycap->psnd_card != psnd_card) { - SAM("ERROR: bad peasycap->psnd_card\n"); - return -EFAULT; - } - if (peasycap->psubstream) { - SAM("ERROR: bad peasycap->psubstream\n"); - return -EFAULT; - } - pss->private_data = peasycap; - peasycap->psubstream = pss; - pss->runtime->hw = peasycap->alsa_hardware; - pss->runtime->private_data = peasycap; - pss->private_data = peasycap; - - if (0 != easycap_sound_setup(peasycap)) { - JOM(4, "ending unsuccessfully\n"); - return -EFAULT; - } - JOM(4, "ending successfully\n"); - return 0; -} -/*****************************************************************************/ -static int easycap_alsa_close(struct snd_pcm_substream *pss) -{ - struct easycap *peasycap; - - JOT(4, "\n"); - if (!pss) { - SAY("ERROR: pss is NULL\n"); - return -EFAULT; - } - peasycap = snd_pcm_substream_chip(pss); - if (!peasycap) { - SAY("ERROR: peasycap is NULL\n"); - return -EFAULT; - } - pss->private_data = NULL; - peasycap->psubstream = NULL; - JOT(4, "ending successfully\n"); - return 0; -} -/*****************************************************************************/ -static int easycap_alsa_vmalloc(struct snd_pcm_substream *pss, size_t sz) -{ - struct snd_pcm_runtime *prt; - JOT(4, "\n"); - - if (!pss) { - SAY("ERROR: pss is NULL\n"); - return -EFAULT; - } - prt = pss->runtime; - if (!prt) { - SAY("ERROR: substream.runtime is NULL\n"); - return -EFAULT; - } - if (prt->dma_area) { - if (prt->dma_bytes > sz) - return 0; - vfree(prt->dma_area); - } - prt->dma_area = vmalloc(sz); - if (!prt->dma_area) - return -ENOMEM; - prt->dma_bytes = sz; - return 0; -} -/*****************************************************************************/ -static int easycap_alsa_hw_params(struct snd_pcm_substream *pss, - struct snd_pcm_hw_params *phw) -{ - int rc; - - JOT(4, "%i\n", (params_buffer_bytes(phw))); - if (!pss) { - SAY("ERROR: pss is NULL\n"); - return -EFAULT; - } - rc = easycap_alsa_vmalloc(pss, params_buffer_bytes(phw)); - if (rc) - return rc; - return 0; -} -/*****************************************************************************/ -static int easycap_alsa_hw_free(struct snd_pcm_substream *pss) -{ - struct snd_pcm_runtime *prt; - JOT(4, "\n"); - - if (!pss) { - SAY("ERROR: pss is NULL\n"); - return -EFAULT; - } - prt = pss->runtime; - if (!prt) { - SAY("ERROR: substream.runtime is NULL\n"); - return -EFAULT; - } - if (prt->dma_area) { - JOT(8, "prt->dma_area = %p\n", prt->dma_area); - vfree(prt->dma_area); - prt->dma_area = NULL; - } else - JOT(8, "dma_area already freed\n"); - return 0; -} -/*****************************************************************************/ -static int easycap_alsa_prepare(struct snd_pcm_substream *pss) -{ - struct easycap *peasycap; - struct snd_pcm_runtime *prt; - - JOT(4, "\n"); - if (!pss) { - SAY("ERROR: pss is NULL\n"); - return -EFAULT; - } - prt = pss->runtime; - peasycap = snd_pcm_substream_chip(pss); - if (!peasycap) { - SAY("ERROR: peasycap is NULL\n"); - return -EFAULT; - } - - JOM(16, "ALSA decides %8i Hz=rate\n", pss->runtime->rate); - JOM(16, "ALSA decides %8ld =period_size\n", pss->runtime->period_size); - JOM(16, "ALSA decides %8i =periods\n", pss->runtime->periods); - JOM(16, "ALSA decides %8ld =buffer_size\n", pss->runtime->buffer_size); - JOM(16, "ALSA decides %8zd =dma_bytes\n", pss->runtime->dma_bytes); - JOM(16, "ALSA decides %8ld =boundary\n", pss->runtime->boundary); - JOM(16, "ALSA decides %8i =period_step\n", pss->runtime->period_step); - JOM(16, "ALSA decides %8i =sample_bits\n", pss->runtime->sample_bits); - JOM(16, "ALSA decides %8i =frame_bits\n", pss->runtime->frame_bits); - JOM(16, "ALSA decides %8ld =min_align\n", pss->runtime->min_align); - JOM(12, "ALSA decides %8ld =hw_ptr_base\n", pss->runtime->hw_ptr_base); - JOM(12, "ALSA decides %8ld =hw_ptr_interrupt\n", - pss->runtime->hw_ptr_interrupt); - - if (prt->dma_bytes != 4 * ((int)prt->period_size) * ((int)prt->periods)) { - SAY("MISTAKE: unexpected ALSA parameters\n"); - return -ENOENT; - } - return 0; -} -/*****************************************************************************/ -static int easycap_alsa_ack(struct snd_pcm_substream *pss) -{ - return 0; -} -/*****************************************************************************/ -static int easycap_alsa_trigger(struct snd_pcm_substream *pss, int cmd) -{ - struct easycap *peasycap; - - JOT(4, "%i=cmd cf %i=START %i=STOP\n", cmd, SNDRV_PCM_TRIGGER_START, - SNDRV_PCM_TRIGGER_STOP); - if (!pss) { - SAY("ERROR: pss is NULL\n"); - return -EFAULT; - } - peasycap = snd_pcm_substream_chip(pss); - if (!peasycap) { - SAY("ERROR: peasycap is NULL\n"); - return -EFAULT; - } - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: { - peasycap->audio_idle = 0; - break; - } - case SNDRV_PCM_TRIGGER_STOP: { - peasycap->audio_idle = 1; - break; - } - default: - return -EINVAL; - } - return 0; -} -/*****************************************************************************/ -static snd_pcm_uframes_t easycap_alsa_pointer(struct snd_pcm_substream *pss) -{ - struct easycap *peasycap; - snd_pcm_uframes_t offset; - - JOT(16, "\n"); - if (!pss) { - SAY("ERROR: pss is NULL\n"); - return -EFAULT; - } - peasycap = snd_pcm_substream_chip(pss); - if (!peasycap) { - SAY("ERROR: peasycap is NULL\n"); - return -EFAULT; - } - if ((0 != peasycap->audio_eof) || (0 != peasycap->audio_idle)) { - JOM(8, "returning -EIO because " - "%i=audio_idle %i=audio_eof\n", - peasycap->audio_idle, peasycap->audio_eof); - return -EIO; - } -/*---------------------------------------------------------------------------*/ - if (0 > peasycap->dma_read) { - JOM(8, "returning -EBUSY\n"); - return -EBUSY; - } - offset = ((snd_pcm_uframes_t)peasycap->dma_read)/4; - JOM(8, "ALSA decides %8i =hw_ptr_base\n", (int)pss->runtime->hw_ptr_base); - JOM(8, "ALSA decides %8i =hw_ptr_interrupt\n", - (int)pss->runtime->hw_ptr_interrupt); - JOM(8, "%7i=offset %7i=dma_read %7i=dma_next\n", - (int)offset, peasycap->dma_read, peasycap->dma_next); - return offset; -} -/*****************************************************************************/ -static struct page * -easycap_alsa_page(struct snd_pcm_substream *pss, unsigned long offset) -{ - return vmalloc_to_page(pss->runtime->dma_area + offset); -} -/*****************************************************************************/ - -static struct snd_pcm_ops easycap_alsa_pcm_ops = { - .open = easycap_alsa_open, - .close = easycap_alsa_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = easycap_alsa_hw_params, - .hw_free = easycap_alsa_hw_free, - .prepare = easycap_alsa_prepare, - .ack = easycap_alsa_ack, - .trigger = easycap_alsa_trigger, - .pointer = easycap_alsa_pointer, - .page = easycap_alsa_page, -}; - -/*****************************************************************************/ -/*---------------------------------------------------------------------------*/ -/* - * THE FUNCTION snd_card_create() HAS THIS_MODULE AS AN ARGUMENT. THIS - * MEANS MODULE easycap. BEWARE. -*/ -/*---------------------------------------------------------------------------*/ -int easycap_alsa_probe(struct easycap *peasycap) -{ - int rc; - struct snd_card *psnd_card; - struct snd_pcm *psnd_pcm; - - if (!peasycap) { - SAY("ERROR: peasycap is NULL\n"); - return -ENODEV; - } - if (0 > peasycap->minor) { - SAY("ERROR: no minor\n"); - return -ENODEV; - } - - peasycap->alsa_hardware = alsa_hardware; - if (peasycap->microphone) { - peasycap->alsa_hardware.rates = SNDRV_PCM_RATE_32000; - peasycap->alsa_hardware.rate_min = 32000; - peasycap->alsa_hardware.rate_max = 32000; - } else { - peasycap->alsa_hardware.rates = SNDRV_PCM_RATE_48000; - peasycap->alsa_hardware.rate_min = 48000; - peasycap->alsa_hardware.rate_max = 48000; - } - - if (0 != snd_card_create(SNDRV_DEFAULT_IDX1, "easycap_alsa", - THIS_MODULE, 0, &psnd_card)) { - SAY("ERROR: Cannot do ALSA snd_card_create()\n"); - return -EFAULT; - } - - sprintf(&psnd_card->id[0], "EasyALSA%i", peasycap->minor); - strcpy(&psnd_card->driver[0], EASYCAP_DRIVER_DESCRIPTION); - strcpy(&psnd_card->shortname[0], "easycap_alsa"); - sprintf(&psnd_card->longname[0], "%s", &psnd_card->shortname[0]); - - psnd_card->dev = &peasycap->pusb_device->dev; - psnd_card->private_data = peasycap; - peasycap->psnd_card = psnd_card; - - rc = snd_pcm_new(psnd_card, "easycap_pcm", 0, 0, 1, &psnd_pcm); - if (rc) { - SAM("ERROR: Cannot do ALSA snd_pcm_new()\n"); - snd_card_free(psnd_card); - return -EFAULT; - } - - snd_pcm_set_ops(psnd_pcm, SNDRV_PCM_STREAM_CAPTURE, - &easycap_alsa_pcm_ops); - psnd_pcm->info_flags = 0; - strcpy(&psnd_pcm->name[0], &psnd_card->id[0]); - psnd_pcm->private_data = peasycap; - peasycap->psnd_pcm = psnd_pcm; - peasycap->psubstream = NULL; - - rc = snd_card_register(psnd_card); - if (rc) { - SAM("ERROR: Cannot do ALSA snd_card_register()\n"); - snd_card_free(psnd_card); - return -EFAULT; - } - - SAM("registered %s\n", &psnd_card->id[0]); - return 0; -} - diff --git a/drivers/staging/media/easycap/easycap_testcard.c b/drivers/staging/media/easycap/easycap_testcard.c deleted file mode 100644 index 0f71470ace39..000000000000 --- a/drivers/staging/media/easycap/easycap_testcard.c +++ /dev/null @@ -1,155 +0,0 @@ -/****************************************************************************** -* * -* easycap_testcard.c * -* * -******************************************************************************/ -/* - * - * Copyright (C) 2010 R.M. Thomas <rmthomas@sciolus.org> - * - * - * This 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. - * - * The software 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 software; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * -*/ -/*****************************************************************************/ - -#include "easycap.h" - -/*****************************************************************************/ -#define TESTCARD_BYTESPERLINE (2 * 720) -void -easycap_testcard(struct easycap *peasycap, int field) -{ - int total; - int y, u, v, r, g, b; - unsigned char uyvy[4]; - int i1, line, k, m, n, more, much, barwidth, barheight; - unsigned char bfbar[TESTCARD_BYTESPERLINE / 8], *p1, *p2; - struct data_buffer *pfield_buffer; - - if (!peasycap) { - SAY("ERROR: peasycap is NULL\n"); - return; - } - JOM(8, "%i=field\n", field); - switch (peasycap->width) { - case 720: - case 360: { - barwidth = (2 * 720) / 8; - break; - } - case 704: - case 352: { - barwidth = (2 * 704) / 8; - break; - } - case 640: - case 320: { - barwidth = (2 * 640) / 8; - break; - } - default: { - SAM("ERROR: cannot set barwidth\n"); - return; - } - } - if (TESTCARD_BYTESPERLINE < barwidth) { - SAM("ERROR: barwidth is too large\n"); - return; - } - switch (peasycap->height) { - case 576: - case 288: { - barheight = 576; - break; - } - case 480: - case 240: { - barheight = 480; - break; - } - default: { - SAM("ERROR: cannot set barheight\n"); - return; - } - } - total = 0; - k = field; - m = 0; - n = 0; - - for (line = 0; line < (barheight / 2); line++) { - for (i1 = 0; i1 < 8; i1++) { - r = (i1 * 256)/8; - g = (i1 * 256)/8; - b = (i1 * 256)/8; - - y = 299*r/1000 + 587*g/1000 + 114*b/1000 ; - u = -147*r/1000 - 289*g/1000 + 436*b/1000 ; - u = u + 128; - v = 615*r/1000 - 515*g/1000 - 100*b/1000 ; - v = v + 128; - - uyvy[0] = 0xFF & u ; - uyvy[1] = 0xFF & y ; - uyvy[2] = 0xFF & v ; - uyvy[3] = 0xFF & y ; - - p1 = &bfbar[0]; - while (p1 < &bfbar[barwidth]) { - *p1++ = uyvy[0] ; - *p1++ = uyvy[1] ; - *p1++ = uyvy[2] ; - *p1++ = uyvy[3] ; - total += 4; - } - - p1 = &bfbar[0]; - more = barwidth; - - while (more) { - if ((FIELD_BUFFER_SIZE/PAGE_SIZE) <= m) { - SAM("ERROR: bad m reached\n"); - return; - } - if (PAGE_SIZE < n) { - SAM("ERROR: bad n reached\n"); - return; - } - - if (0 > more) { - SAM("ERROR: internal fault\n"); - return; - } - - much = PAGE_SIZE - n; - if (much > more) - much = more; - pfield_buffer = &peasycap->field_buffer[k][m]; - p2 = pfield_buffer->pgo + n; - memcpy(p2, p1, much); - - p1 += much; - n += much; - more -= much; - if (PAGE_SIZE == n) { - m++; - n = 0; - } - } - } - } - return; -} diff --git a/drivers/staging/media/go7007/Makefile b/drivers/staging/media/go7007/Makefile index 6ee837c56706..3fdbef5306a0 100644 --- a/drivers/staging/media/go7007/Makefile +++ b/drivers/staging/media/go7007/Makefile @@ -24,7 +24,7 @@ s2250-y := s2250-board.o #ccflags-$(CONFIG_VIDEO_SAA7134:m=y) += -Idrivers/media/video/saa7134 -DSAA7134_MPEG_GO7007=3 # S2250 needs cypress ezusb loader from dvb-usb -ccflags-$(CONFIG_VIDEO_GO7007_USB_S2250_BOARD:m=y) += -Idrivers/media/dvb/dvb-usb +ccflags-$(CONFIG_VIDEO_GO7007_USB_S2250_BOARD:m=y) += -Idrivers/media/usb/dvb-usb -ccflags-y += -Idrivers/media/dvb/frontends -ccflags-y += -Idrivers/media/dvb/dvb-core +ccflags-y += -Idrivers/media/dvb-frontends +ccflags-y += -Idrivers/media/dvb-core diff --git a/drivers/staging/media/go7007/go7007-v4l2.c b/drivers/staging/media/go7007/go7007-v4l2.c index c184ad30fbd8..980371b02749 100644 --- a/drivers/staging/media/go7007/go7007-v4l2.c +++ b/drivers/staging/media/go7007/go7007-v4l2.c @@ -1372,7 +1372,7 @@ static int vidioc_g_crop(struct file *file, void *priv, struct v4l2_crop *crop) /* FIXME: vidioc_s_crop is not really implemented!!! */ -static int vidioc_s_crop(struct file *file, void *priv, struct v4l2_crop *crop) +static int vidioc_s_crop(struct file *file, void *priv, const struct v4l2_crop *crop) { if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; @@ -1392,7 +1392,7 @@ static int vidioc_g_jpegcomp(struct file *file, void *priv, } static int vidioc_s_jpegcomp(struct file *file, void *priv, - struct v4l2_jpegcompression *params) + const struct v4l2_jpegcompression *params) { if (params->quality != 50 || params->jpeg_markers != (V4L2_JPEG_MARKER_DHT | diff --git a/drivers/staging/media/lirc/Kconfig b/drivers/staging/media/lirc/Kconfig index 526ec0fc2f04..e60a59fc252b 100644 --- a/drivers/staging/media/lirc/Kconfig +++ b/drivers/staging/media/lirc/Kconfig @@ -63,12 +63,6 @@ config LIRC_SIR help Driver for the SIR IrDA port -config LIRC_TTUSBIR - tristate "Technotrend USB IR Receiver" - depends on LIRC && USB - help - Driver for the Technotrend USB IR Receiver - config LIRC_ZILOG tristate "Zilog/Hauppauge IR Transmitter" depends on LIRC && I2C diff --git a/drivers/staging/media/lirc/Makefile b/drivers/staging/media/lirc/Makefile index d76b0fa2af53..b90fcabddab6 100644 --- a/drivers/staging/media/lirc/Makefile +++ b/drivers/staging/media/lirc/Makefile @@ -10,5 +10,4 @@ obj-$(CONFIG_LIRC_PARALLEL) += lirc_parallel.o obj-$(CONFIG_LIRC_SASEM) += lirc_sasem.o obj-$(CONFIG_LIRC_SERIAL) += lirc_serial.o obj-$(CONFIG_LIRC_SIR) += lirc_sir.o -obj-$(CONFIG_LIRC_TTUSBIR) += lirc_ttusbir.o obj-$(CONFIG_LIRC_ZILOG) += lirc_zilog.o diff --git a/drivers/staging/media/lirc/lirc_ene0100.h b/drivers/staging/media/lirc/lirc_ene0100.h deleted file mode 100644 index 06bebd6acc46..000000000000 --- a/drivers/staging/media/lirc/lirc_ene0100.h +++ /dev/null @@ -1,169 +0,0 @@ -/* - * driver for ENE KB3926 B/C/D CIR (also known as ENE0100) - * - * Copyright (C) 2009 Maxim Levitsky <maximlevitsky@gmail.com> - * - * 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 - */ - -#include <media/lirc.h> -#include <media/lirc_dev.h> - -/* hardware address */ -#define ENE_STATUS 0 /* hardware status - unused */ -#define ENE_ADDR_HI 1 /* hi byte of register address */ -#define ENE_ADDR_LO 2 /* low byte of register address */ -#define ENE_IO 3 /* read/write window */ -#define ENE_MAX_IO 4 - -/* 8 bytes of samples, divided in 2 halfs*/ -#define ENE_SAMPLE_BUFFER 0xF8F0 /* regular sample buffer */ -#define ENE_SAMPLE_SPC_MASK (1 << 7) /* sample is space */ -#define ENE_SAMPLE_VALUE_MASK 0x7F -#define ENE_SAMPLE_OVERFLOW 0x7F -#define ENE_SAMPLES_SIZE 4 - -/* fan input sample buffer */ -#define ENE_SAMPLE_BUFFER_FAN 0xF8FB /* this buffer holds high byte of */ - /* each sample of normal buffer */ - -#define ENE_FAN_SMPL_PULS_MSK 0x8000 /* this bit of combined sample */ - /* if set, says that sample is pulse */ -#define ENE_FAN_VALUE_MASK 0x0FFF /* mask for valid bits of the value */ - -/* first firmware register */ -#define ENE_FW1 0xF8F8 -#define ENE_FW1_ENABLE (1 << 0) /* enable fw processing */ -#define ENE_FW1_TXIRQ (1 << 1) /* TX interrupt pending */ -#define ENE_FW1_WAKE (1 << 6) /* enable wake from S3 */ -#define ENE_FW1_IRQ (1 << 7) /* enable interrupt */ - -/* second firmware register */ -#define ENE_FW2 0xF8F9 -#define ENE_FW2_BUF_HIGH (1 << 0) /* which half of the buffer to read */ -#define ENE_FW2_IRQ_CLR (1 << 2) /* clear this on IRQ */ -#define ENE_FW2_GP40_AS_LEARN (1 << 4) /* normal input is used as */ - /* learning input */ -#define ENE_FW2_FAN_AS_NRML_IN (1 << 6) /* fan is used as normal input */ -#define ENE_FW2_LEARNING (1 << 7) /* hardware supports learning and TX */ - -/* fan as input settings - only if learning capable */ -#define ENE_FAN_AS_IN1 0xFE30 /* fan init reg 1 */ -#define ENE_FAN_AS_IN1_EN 0xCD -#define ENE_FAN_AS_IN2 0xFE31 /* fan init reg 2 */ -#define ENE_FAN_AS_IN2_EN 0x03 -#define ENE_SAMPLE_PERIOD_FAN 61 /* fan input has fixed sample period */ - -/* IRQ registers block (for revision B) */ -#define ENEB_IRQ 0xFD09 /* IRQ number */ -#define ENEB_IRQ_UNK1 0xFD17 /* unknown setting = 1 */ -#define ENEB_IRQ_STATUS 0xFD80 /* irq status */ -#define ENEB_IRQ_STATUS_IR (1 << 5) /* IR irq */ - -/* IRQ registers block (for revision C,D) */ -#define ENEC_IRQ 0xFE9B /* new irq settings register */ -#define ENEC_IRQ_MASK 0x0F /* irq number mask */ -#define ENEC_IRQ_UNK_EN (1 << 4) /* always enabled */ -#define ENEC_IRQ_STATUS (1 << 5) /* irq status and ACK */ - -/* CIR block settings */ -#define ENE_CIR_CONF1 0xFEC0 -#define ENE_CIR_CONF1_ADC_ON 0x7 /* receiver on gpio40 enabled */ -#define ENE_CIR_CONF1_LEARN1 (1 << 3) /* enabled on learning mode */ -#define ENE_CIR_CONF1_TX_ON 0x30 /* enabled on transmit */ -#define ENE_CIR_CONF1_TX_CARR (1 << 7) /* send TX carrier or not */ - -#define ENE_CIR_CONF2 0xFEC1 /* unknown setting = 0 */ -#define ENE_CIR_CONF2_LEARN2 (1 << 4) /* set on enable learning */ -#define ENE_CIR_CONF2_GPIO40DIS (1 << 5) /* disable normal input via gpio40 */ - -#define ENE_CIR_SAMPLE_PERIOD 0xFEC8 /* sample period in us */ -#define ENE_CIR_SAMPLE_OVERFLOW (1 << 7) /* interrupt on overflows if set */ - - -/* transmitter - not implemented yet */ -/* KB3926C and higher */ -/* transmission is very similar to receiving, a byte is written to */ -/* ENE_TX_INPUT, in same manner as it is read from sample buffer */ -/* sample period is fixed*/ - - -/* transmitter ports */ -#define ENE_TX_PORT1 0xFC01 /* this enables one or both */ -#define ENE_TX_PORT1_EN (1 << 5) /* TX ports */ -#define ENE_TX_PORT2 0xFC08 -#define ENE_TX_PORT2_EN (1 << 1) - -#define ENE_TX_INPUT 0xFEC9 /* next byte to transmit */ -#define ENE_TX_SPC_MASK (1 << 7) /* Transmitted sample is space */ -#define ENE_TX_UNK1 0xFECB /* set to 0x63 */ -#define ENE_TX_SMPL_PERIOD 50 /* transmit sample period */ - - -#define ENE_TX_CARRIER 0xFECE /* TX carrier * 2 (khz) */ -#define ENE_TX_CARRIER_UNKBIT 0x80 /* This bit set on transmit */ -#define ENE_TX_CARRIER_LOW 0xFECF /* TX carrier / 2 */ - -/* Hardware versions */ -#define ENE_HW_VERSION 0xFF00 /* hardware revision */ -#define ENE_HW_UNK 0xFF1D -#define ENE_HW_UNK_CLR (1 << 2) -#define ENE_HW_VER_MAJOR 0xFF1E /* chip version */ -#define ENE_HW_VER_MINOR 0xFF1F -#define ENE_HW_VER_OLD 0xFD00 - -#define same_sign(a, b) ((((a) > 0) && (b) > 0) || ((a) < 0 && (b) < 0)) - -#define ENE_DRIVER_NAME "enecir" -#define ENE_MAXGAP 250000 /* this is amount of time we wait - before turning the sampler, chosen - arbitry */ - -#define space(len) (-(len)) /* add a space */ - -/* software defines */ -#define ENE_IRQ_RX 1 -#define ENE_IRQ_TX 2 - -#define ENE_HW_B 1 /* 3926B */ -#define ENE_HW_C 2 /* 3926C */ -#define ENE_HW_D 3 /* 3926D */ - -#define ene_printk(level, text, ...) \ - printk(level ENE_DRIVER_NAME ": " text, ## __VA_ARGS__) - -struct ene_device { - struct pnp_dev *pnp_dev; - struct lirc_driver *lirc_driver; - - /* hw settings */ - unsigned long hw_io; - int irq; - - int hw_revision; /* hardware revision */ - int hw_learning_and_tx_capable; /* learning capable */ - int hw_gpio40_learning; /* gpio40 is learning */ - int hw_fan_as_normal_input; /* fan input is used as regular input */ - - /* device data */ - int idle; - int fan_input_inuse; - - int sample; - int in_use; - - struct timeval gap_start; -}; diff --git a/drivers/staging/media/lirc/lirc_igorplugusb.c b/drivers/staging/media/lirc/lirc_igorplugusb.c index 7a2501776679..939a801c23e4 100644 --- a/drivers/staging/media/lirc/lirc_igorplugusb.c +++ b/drivers/staging/media/lirc/lirc_igorplugusb.c @@ -325,8 +325,8 @@ static int igorplugusb_remote_poll(void *data, struct lirc_buffer *buf) if (ret < DEVICE_HEADERLEN) return -ENODATA; - dprintk(DRIVER_NAME ": Got %d bytes. Header: %02x %02x %02x\n", - ret, ir->buf_in[0], ir->buf_in[1], ir->buf_in[2]); + dprintk(DRIVER_NAME ": Got %d bytes. Header: %*ph\n", + ret, 3, ir->buf_in); do_gettimeofday(&now); timediff = now.tv_sec - ir->last_time.tv_sec; diff --git a/drivers/staging/media/lirc/lirc_ttusbir.c b/drivers/staging/media/lirc/lirc_ttusbir.c deleted file mode 100644 index 3bb865c02173..000000000000 --- a/drivers/staging/media/lirc/lirc_ttusbir.c +++ /dev/null @@ -1,376 +0,0 @@ -/* - * lirc_ttusbir.c - * - * lirc_ttusbir - LIRC device driver for the TechnoTrend USB IR Receiver - * - * Copyright (C) 2007 Stefan Macher <st_maker-lirc@yahoo.de> - * - * This LIRC driver provides access to the TechnoTrend USB IR Receiver. - * The receiver delivers the IR signal as raw sampled true/false data in - * isochronous USB packets each of size 128 byte. - * Currently the driver reduces the sampling rate by factor of 8 as this - * is still more than enough to decode RC-5 - others should be analyzed. - * But the driver does not rely on RC-5 it should be able to decode every - * IR signal that is not too fast. - */ - -/* - * 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 - */ - -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/module.h> -#include <linux/errno.h> -#include <linux/slab.h> -#include <linux/usb.h> - -#include <media/lirc.h> -#include <media/lirc_dev.h> - -MODULE_DESCRIPTION("TechnoTrend USB IR device driver for LIRC"); -MODULE_AUTHOR("Stefan Macher (st_maker-lirc@yahoo.de)"); -MODULE_LICENSE("GPL"); - -/* #define DEBUG */ -#ifdef DEBUG -#define DPRINTK printk -#else -#define DPRINTK(_x_, a...) -#endif - -/* function declarations */ -static int probe(struct usb_interface *intf, const struct usb_device_id *id); -static void disconnect(struct usb_interface *intf); -static void urb_complete(struct urb *urb); -static int set_use_inc(void *data); -static void set_use_dec(void *data); - -static int num_urbs = 2; -module_param(num_urbs, int, S_IRUGO); -MODULE_PARM_DESC(num_urbs, - "Number of URBs in queue. Try to increase to 4 in case " - "of problems (default: 2; minimum: 2)"); - -/* table of devices that work with this driver */ -static struct usb_device_id device_id_table[] = { - /* TechnoTrend USB IR Receiver */ - { USB_DEVICE(0x0B48, 0x2003) }, - /* Terminating entry */ - { } -}; -MODULE_DEVICE_TABLE(usb, device_id_table); - -/* USB driver definition */ -static struct usb_driver usb_driver = { - .name = "TTUSBIR", - .id_table = &(device_id_table[0]), - .probe = probe, - .disconnect = disconnect, -}; - -/* USB device definition */ -struct ttusbir_device { - struct usb_driver *usb_driver; - struct usb_device *udev; - struct usb_interface *interf; - struct usb_class_driver class_driver; - unsigned int ifnum; /* Interface number to use */ - unsigned int alt_setting; /* alternate setting to use */ - unsigned int endpoint; /* Endpoint to use */ - struct urb **urb; /* num_urb URB pointers*/ - char **buffer; /* 128 byte buffer for each URB */ - struct lirc_buffer rbuf; /* Buffer towards LIRC */ - struct lirc_driver driver; - int minor; - int last_pulse; /* remembers if last received byte was pulse or space */ - int last_num; /* remembers how many last bytes appeared */ - int opened; -}; - -/*** LIRC specific functions ***/ -static int set_use_inc(void *data) -{ - int i, retval; - struct ttusbir_device *ttusbir = data; - - DPRINTK("Sending first URBs\n"); - /* @TODO Do I need to check if I am already opened */ - ttusbir->opened = 1; - - for (i = 0; i < num_urbs; i++) { - retval = usb_submit_urb(ttusbir->urb[i], GFP_KERNEL); - if (retval) { - dev_err(&ttusbir->interf->dev, - "%s: usb_submit_urb failed on urb %d\n", - __func__, i); - return retval; - } - } - return 0; -} - -static void set_use_dec(void *data) -{ - struct ttusbir_device *ttusbir = data; - - DPRINTK("Device closed\n"); - - ttusbir->opened = 0; -} - -/*** USB specific functions ***/ - -/* - * This mapping table is used to do a very simple filtering of the - * input signal. - * For a value with at least 4 bits set it returns 0xFF otherwise - * 0x00. For faster IR signals this can not be used. But for RC-5 we - * still have about 14 samples per pulse/space, i.e. we sample with 14 - * times higher frequency than the signal frequency - */ -const unsigned char map_table[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, - 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, - 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, - 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, - 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, - 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, - 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, - 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, - 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, - 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, - 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, - 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, - 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, - 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF -}; - -static void urb_complete(struct urb *urb) -{ - struct ttusbir_device *ttusbir; - unsigned char *buf; - int i; - int l; - - ttusbir = urb->context; - - if (!ttusbir->opened) - return; - - buf = (unsigned char *)urb->transfer_buffer; - - for (i = 0; i < 128; i++) { - /* Here we do the filtering and some kind of down sampling */ - buf[i] = ~map_table[buf[i]]; - if (ttusbir->last_pulse == buf[i]) { - if (ttusbir->last_num < PULSE_MASK/63) - ttusbir->last_num++; - /* - * else we are in a idle period and do not need to - * increment any longer - */ - } else { - l = ttusbir->last_num * 62; /* about 62 = us/byte */ - if (ttusbir->last_pulse) /* pulse or space? */ - l |= PULSE_BIT; - if (!lirc_buffer_full(&ttusbir->rbuf)) { - lirc_buffer_write(&ttusbir->rbuf, (void *)&l); - wake_up_interruptible(&ttusbir->rbuf.wait_poll); - } - ttusbir->last_num = 0; - ttusbir->last_pulse = buf[i]; - } - } - usb_submit_urb(urb, GFP_ATOMIC); /* keep data rolling :-) */ -} - -/* - * Called whenever the USB subsystem thinks we could be the right driver - * to handle this device - */ -static int probe(struct usb_interface *intf, const struct usb_device_id *id) -{ - int alt_set, endp; - int found = 0; - int i, j; - int struct_size; - struct usb_host_interface *host_interf; - struct usb_interface_descriptor *interf_desc; - struct usb_host_endpoint *host_endpoint; - struct ttusbir_device *ttusbir; - - DPRINTK("Module ttusbir probe\n"); - - /* To reduce memory fragmentation we use only one allocation */ - struct_size = sizeof(struct ttusbir_device) + - (sizeof(struct urb *) * num_urbs) + - (sizeof(char *) * num_urbs) + - (num_urbs * 128); - ttusbir = kzalloc(struct_size, GFP_KERNEL); - if (!ttusbir) - return -ENOMEM; - - ttusbir->urb = (struct urb **)((char *)ttusbir + - sizeof(struct ttusbir_device)); - ttusbir->buffer = (char **)((char *)ttusbir->urb + - (sizeof(struct urb *) * num_urbs)); - for (i = 0; i < num_urbs; i++) - ttusbir->buffer[i] = (char *)ttusbir->buffer + - (sizeof(char *)*num_urbs) + (i * 128); - - ttusbir->usb_driver = &usb_driver; - ttusbir->alt_setting = -1; - /* @TODO check if error can be returned */ - ttusbir->udev = usb_get_dev(interface_to_usbdev(intf)); - ttusbir->interf = intf; - ttusbir->last_pulse = 0x00; - ttusbir->last_num = 0; - - /* - * Now look for interface setting we can handle - * We are searching for the alt setting where end point - * 0x82 has max packet size 16 - */ - for (alt_set = 0; alt_set < intf->num_altsetting && !found; alt_set++) { - host_interf = &intf->altsetting[alt_set]; - interf_desc = &host_interf->desc; - for (endp = 0; endp < interf_desc->bNumEndpoints; endp++) { - host_endpoint = &host_interf->endpoint[endp]; - if ((host_endpoint->desc.bEndpointAddress == 0x82) && - (host_endpoint->desc.wMaxPacketSize == 0x10)) { - ttusbir->alt_setting = alt_set; - ttusbir->endpoint = endp; - found = 1; - break; - } - } - } - if (ttusbir->alt_setting != -1) - DPRINTK("alt setting: %d\n", ttusbir->alt_setting); - else { - dev_err(&intf->dev, "Could not find alternate setting\n"); - kfree(ttusbir); - return -EINVAL; - } - - /* OK lets setup this interface setting */ - usb_set_interface(ttusbir->udev, 0, ttusbir->alt_setting); - - /* Store device info in interface structure */ - usb_set_intfdata(intf, ttusbir); - - /* Register as a LIRC driver */ - if (lirc_buffer_init(&ttusbir->rbuf, sizeof(int), 256) < 0) { - dev_err(&intf->dev, "Could not get memory for LIRC data buffer\n"); - usb_set_intfdata(intf, NULL); - kfree(ttusbir); - return -ENOMEM; - } - strcpy(ttusbir->driver.name, "TTUSBIR"); - ttusbir->driver.minor = -1; - ttusbir->driver.code_length = 1; - ttusbir->driver.sample_rate = 0; - ttusbir->driver.data = ttusbir; - ttusbir->driver.add_to_buf = NULL; - ttusbir->driver.rbuf = &ttusbir->rbuf; - ttusbir->driver.set_use_inc = set_use_inc; - ttusbir->driver.set_use_dec = set_use_dec; - ttusbir->driver.dev = &intf->dev; - ttusbir->driver.owner = THIS_MODULE; - ttusbir->driver.features = LIRC_CAN_REC_MODE2; - ttusbir->minor = lirc_register_driver(&ttusbir->driver); - if (ttusbir->minor < 0) { - dev_err(&intf->dev, "Error registering as LIRC driver\n"); - usb_set_intfdata(intf, NULL); - lirc_buffer_free(&ttusbir->rbuf); - kfree(ttusbir); - return -EIO; - } - - /* Allocate and setup the URB that we will use to talk to the device */ - for (i = 0; i < num_urbs; i++) { - ttusbir->urb[i] = usb_alloc_urb(8, GFP_KERNEL); - if (!ttusbir->urb[i]) { - dev_err(&intf->dev, "Could not allocate memory for the URB\n"); - for (j = i - 1; j >= 0; j--) - kfree(ttusbir->urb[j]); - lirc_buffer_free(&ttusbir->rbuf); - lirc_unregister_driver(ttusbir->minor); - kfree(ttusbir); - usb_set_intfdata(intf, NULL); - return -ENOMEM; - } - ttusbir->urb[i]->dev = ttusbir->udev; - ttusbir->urb[i]->context = ttusbir; - ttusbir->urb[i]->pipe = usb_rcvisocpipe(ttusbir->udev, - ttusbir->endpoint); - ttusbir->urb[i]->interval = 1; - ttusbir->urb[i]->transfer_flags = URB_ISO_ASAP; - ttusbir->urb[i]->transfer_buffer = &ttusbir->buffer[i][0]; - ttusbir->urb[i]->complete = urb_complete; - ttusbir->urb[i]->number_of_packets = 8; - ttusbir->urb[i]->transfer_buffer_length = 128; - for (j = 0; j < 8; j++) { - ttusbir->urb[i]->iso_frame_desc[j].offset = j*16; - ttusbir->urb[i]->iso_frame_desc[j].length = 16; - } - } - return 0; -} - -/** - * Called when the driver is unloaded or the device is unplugged - */ -static void disconnect(struct usb_interface *intf) -{ - int i; - struct ttusbir_device *ttusbir; - - DPRINTK("Module ttusbir disconnect\n"); - - ttusbir = (struct ttusbir_device *) usb_get_intfdata(intf); - usb_set_intfdata(intf, NULL); - lirc_unregister_driver(ttusbir->minor); - DPRINTK("unregistered\n"); - - for (i = 0; i < num_urbs; i++) { - usb_kill_urb(ttusbir->urb[i]); - usb_free_urb(ttusbir->urb[i]); - } - DPRINTK("URBs killed\n"); - lirc_buffer_free(&ttusbir->rbuf); - kfree(ttusbir); -} - -module_usb_driver(usb_driver); diff --git a/drivers/staging/media/lirc/lirc_zilog.c b/drivers/staging/media/lirc/lirc_zilog.c index 76ea4a8f2c75..11d5338b4f2f 100644 --- a/drivers/staging/media/lirc/lirc_zilog.c +++ b/drivers/staging/media/lirc/lirc_zilog.c @@ -658,8 +658,7 @@ static int send_data_block(struct IR_tx *tx, unsigned char *data_block) buf[0] = (unsigned char)(i + 1); for (j = 0; j < tosend; ++j) buf[1 + j] = data_block[i + j]; - dprintk("%02x %02x %02x %02x %02x", - buf[0], buf[1], buf[2], buf[3], buf[4]); + dprintk("%*ph", 5, buf); ret = i2c_master_send(tx->c, buf, tosend + 1); if (ret != tosend + 1) { zilog_error("i2c_master_send failed with %d\n", ret); |