diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-10-13 17:03:59 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-10-13 17:03:59 -0400 |
commit | cf2fa66055d718ae13e62451bb546505f63906a2 (patch) | |
tree | e206d3f04e74a34e9aa88d21af6c26eea21d4121 /drivers/media/video | |
parent | 4501a466f28788485604ee42641d7a5fe7258d16 (diff) | |
parent | 57f51dbc45f65f7ee1e8c8f77200bb8000e3e271 (diff) |
Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6
* 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6: (313 commits)
V4L/DVB (9186): Added support for Prof 7300 DVB-S/S2 cards
V4L/DVB (9185): S2API: Ensure we have a reasonable ROLLOFF default
V4L/DVB (9184): cx24116: Change the default SNR units back to percentage by default.
V4L/DVB (9183): S2API: Return error of the caller provides 0 commands.
V4L/DVB (9182): S2API: Added support for DTV_HIERARCHY
V4L/DVB (9181): S2API: Add support fot DTV_GUARD_INTERVAL and DTV_TRANSMISSION_MODE
V4L/DVB (9180): S2API: Added support for DTV_CODE_RATE_HP/LP
V4L/DVB (9179): S2API: frontend.h cleanup
V4L/DVB (9178): cx24116: Add module parameter to return SNR as ESNO.
V4L/DVB (9177): S2API: Change _8PSK / _16APSK to PSK_8 and APSK_16
V4L/DVB (9176): Add support for DvbWorld USB cards with STV0288 demodulator.
V4L/DVB (9175): Remove NULL pointer in stb6000 driver.
V4L/DVB (9174): Allow custom inittab for ST STV0288 demodulator.
V4L/DVB (9173): S2API: Remove the hardcoded command limit during validation
V4L/DVB (9172): S2API: Bugfix related to DVB-S / DVB-S2 tuning for the legacy API.
V4L/DVB (9171): S2API: Stop an OOPS if illegal commands are dumped in S2API.
V4L/DVB (9170): cx24116: Sanity checking to data input via S2API to the cx24116 demod.
V4L/DVB (9169): uvcvideo: Support two new Bison Electronics webcams.
V4L/DVB (9168): Add support for MSI TV@nywhere Plus remote
V4L/DVB: v4l2-dev: remove duplicated #include
...
Diffstat (limited to 'drivers/media/video')
236 files changed, 14582 insertions, 4910 deletions
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index 3e9e0dcd217e..47102c2c8250 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig | |||
@@ -34,6 +34,7 @@ config VIDEOBUF_DVB | |||
34 | select VIDEOBUF_GEN | 34 | select VIDEOBUF_GEN |
35 | 35 | ||
36 | config VIDEO_BTCX | 36 | config VIDEO_BTCX |
37 | depends on PCI | ||
37 | tristate | 38 | tristate |
38 | 39 | ||
39 | config VIDEO_IR | 40 | config VIDEO_IR |
@@ -71,6 +72,15 @@ config VIDEO_ADV_DEBUG | |||
71 | V4L devices. | 72 | V4L devices. |
72 | In doubt, say N. | 73 | In doubt, say N. |
73 | 74 | ||
75 | config VIDEO_FIXED_MINOR_RANGES | ||
76 | bool "Enable old-style fixed minor ranges for video devices" | ||
77 | default n | ||
78 | ---help--- | ||
79 | Say Y here to enable the old-style fixed-range minor assignments. | ||
80 | Only useful if you rely on the old behavior and use mknod instead of udev. | ||
81 | |||
82 | When in doubt, say N. | ||
83 | |||
74 | config VIDEO_HELPER_CHIPS_AUTO | 84 | config VIDEO_HELPER_CHIPS_AUTO |
75 | bool "Autoselect pertinent encoders/decoders and other helper chips" | 85 | bool "Autoselect pertinent encoders/decoders and other helper chips" |
76 | default y | 86 | default y |
@@ -578,13 +588,6 @@ config VIDEO_SAA5249 | |||
578 | To compile this driver as a module, choose M here: the | 588 | To compile this driver as a module, choose M here: the |
579 | module will be called saa5249. | 589 | module will be called saa5249. |
580 | 590 | ||
581 | config TUNER_3036 | ||
582 | tristate "SAB3036 tuner" | ||
583 | depends on I2C && VIDEO_V4L1 | ||
584 | help | ||
585 | Say Y here to include support for Philips SAB3036 compatible tuners. | ||
586 | If in doubt, say N. | ||
587 | |||
588 | config VIDEO_VINO | 591 | config VIDEO_VINO |
589 | tristate "SGI Vino Video For Linux (EXPERIMENTAL)" | 592 | tristate "SGI Vino Video For Linux (EXPERIMENTAL)" |
590 | depends on I2C && SGI_IP22 && EXPERIMENTAL && VIDEO_V4L2 | 593 | depends on I2C && SGI_IP22 && EXPERIMENTAL && VIDEO_V4L2 |
@@ -602,79 +605,7 @@ config VIDEO_STRADIS | |||
602 | driver for PCI. There is a product page at | 605 | driver for PCI. There is a product page at |
603 | <http://www.stradis.com/>. | 606 | <http://www.stradis.com/>. |
604 | 607 | ||
605 | config VIDEO_ZORAN | 608 | source "drivers/media/video/zoran/Kconfig" |
606 | tristate "Zoran ZR36057/36067 Video For Linux" | ||
607 | depends on PCI && I2C_ALGOBIT && VIDEO_V4L1 && VIRT_TO_BUS | ||
608 | help | ||
609 | Say Y for support for MJPEG capture cards based on the Zoran | ||
610 | 36057/36067 PCI controller chipset. This includes the Iomega | ||
611 | Buz, Pinnacle DC10+ and the Linux Media Labs LML33. There is | ||
612 | a driver homepage at <http://mjpeg.sf.net/driver-zoran/>. For | ||
613 | more information, check <file:Documentation/video4linux/Zoran>. | ||
614 | |||
615 | To compile this driver as a module, choose M here: the | ||
616 | module will be called zr36067. | ||
617 | |||
618 | config VIDEO_ZORAN_DC30 | ||
619 | tristate "Pinnacle/Miro DC30(+) support" | ||
620 | depends on VIDEO_ZORAN | ||
621 | select VIDEO_ADV7175 if VIDEO_HELPER_CHIPS_AUTO | ||
622 | select VIDEO_VPX3220 if VIDEO_HELPER_CHIPS_AUTO | ||
623 | help | ||
624 | Support for the Pinnacle/Miro DC30(+) MJPEG capture/playback | ||
625 | card. This also supports really old DC10 cards based on the | ||
626 | zr36050 MJPEG codec and zr36016 VFE. | ||
627 | |||
628 | config VIDEO_ZORAN_ZR36060 | ||
629 | tristate "Zoran ZR36060" | ||
630 | depends on VIDEO_ZORAN | ||
631 | help | ||
632 | Say Y to support Zoran boards based on 36060 chips. | ||
633 | This includes Iomega Buz, Pinnacle DC10, Linux media Labs 33 | ||
634 | and 33 R10 and AverMedia 6 boards. | ||
635 | |||
636 | config VIDEO_ZORAN_BUZ | ||
637 | tristate "Iomega Buz support" | ||
638 | depends on VIDEO_ZORAN_ZR36060 | ||
639 | select VIDEO_SAA7111 if VIDEO_HELPER_CHIPS_AUTO | ||
640 | select VIDEO_SAA7185 if VIDEO_HELPER_CHIPS_AUTO | ||
641 | help | ||
642 | Support for the Iomega Buz MJPEG capture/playback card. | ||
643 | |||
644 | config VIDEO_ZORAN_DC10 | ||
645 | tristate "Pinnacle/Miro DC10(+) support" | ||
646 | depends on VIDEO_ZORAN_ZR36060 | ||
647 | select VIDEO_SAA7110 if VIDEO_HELPER_CHIPS_AUTO | ||
648 | select VIDEO_ADV7175 if VIDEO_HELPER_CHIPS_AUTO | ||
649 | help | ||
650 | Support for the Pinnacle/Miro DC10(+) MJPEG capture/playback | ||
651 | card. | ||
652 | |||
653 | config VIDEO_ZORAN_LML33 | ||
654 | tristate "Linux Media Labs LML33 support" | ||
655 | depends on VIDEO_ZORAN_ZR36060 | ||
656 | select VIDEO_BT819 if VIDEO_HELPER_CHIPS_AUTO | ||
657 | select VIDEO_BT856 if VIDEO_HELPER_CHIPS_AUTO | ||
658 | help | ||
659 | Support for the Linux Media Labs LML33 MJPEG capture/playback | ||
660 | card. | ||
661 | |||
662 | config VIDEO_ZORAN_LML33R10 | ||
663 | tristate "Linux Media Labs LML33R10 support" | ||
664 | depends on VIDEO_ZORAN_ZR36060 | ||
665 | select VIDEO_SAA7114 if VIDEO_HELPER_CHIPS_AUTO | ||
666 | select VIDEO_ADV7170 if VIDEO_HELPER_CHIPS_AUTO | ||
667 | help | ||
668 | support for the Linux Media Labs LML33R10 MJPEG capture/playback | ||
669 | card. | ||
670 | |||
671 | config VIDEO_ZORAN_AVS6EYES | ||
672 | tristate "AverMedia 6 Eyes support (EXPERIMENTAL)" | ||
673 | depends on VIDEO_ZORAN_ZR36060 && EXPERIMENTAL && VIDEO_V4L1 | ||
674 | select VIDEO_BT856 if VIDEO_HELPER_CHIPS_AUTO | ||
675 | select VIDEO_KS0127 if VIDEO_HELPER_CHIPS_AUTO | ||
676 | help | ||
677 | Support for the AverMedia 6 Eyes video surveillance card. | ||
678 | 609 | ||
679 | config VIDEO_MEYE | 610 | config VIDEO_MEYE |
680 | tristate "Sony Vaio Picturebook Motion Eye Video For Linux" | 611 | tristate "Sony Vaio Picturebook Motion Eye Video For Linux" |
@@ -697,7 +628,7 @@ config VIDEO_MXB | |||
697 | depends on PCI && VIDEO_V4L1 && I2C | 628 | depends on PCI && VIDEO_V4L1 && I2C |
698 | select VIDEO_SAA7146_VV | 629 | select VIDEO_SAA7146_VV |
699 | select VIDEO_TUNER | 630 | select VIDEO_TUNER |
700 | select VIDEO_SAA7111 if VIDEO_HELPER_CHIPS_AUTO | 631 | select VIDEO_SAA7115 if VIDEO_HELPER_CHIPS_AUTO |
701 | select VIDEO_TDA9840 if VIDEO_HELPER_CHIPS_AUTO | 632 | select VIDEO_TDA9840 if VIDEO_HELPER_CHIPS_AUTO |
702 | select VIDEO_TEA6415C if VIDEO_HELPER_CHIPS_AUTO | 633 | select VIDEO_TEA6415C if VIDEO_HELPER_CHIPS_AUTO |
703 | select VIDEO_TEA6420 if VIDEO_HELPER_CHIPS_AUTO | 634 | select VIDEO_TEA6420 if VIDEO_HELPER_CHIPS_AUTO |
@@ -708,21 +639,6 @@ config VIDEO_MXB | |||
708 | To compile this driver as a module, choose M here: the | 639 | To compile this driver as a module, choose M here: the |
709 | module will be called mxb. | 640 | module will be called mxb. |
710 | 641 | ||
711 | config VIDEO_DPC | ||
712 | tristate "Philips-Semiconductors 'dpc7146 demonstration board'" | ||
713 | depends on PCI && VIDEO_V4L1 && I2C | ||
714 | select VIDEO_SAA7146_VV | ||
715 | select VIDEO_SAA7111 if VIDEO_HELPER_CHIPS_AUTO | ||
716 | ---help--- | ||
717 | This is a video4linux driver for the 'dpc7146 demonstration | ||
718 | board' by Philips-Semiconductors. It's the reference design | ||
719 | for SAA7146 bases boards, so if you have some unsupported | ||
720 | saa7146 based, analog video card, chances are good that it | ||
721 | will work with this skeleton driver. | ||
722 | |||
723 | To compile this driver as a module, choose M here: the | ||
724 | module will be called dpc7146. | ||
725 | |||
726 | config VIDEO_HEXIUM_ORION | 642 | config VIDEO_HEXIUM_ORION |
727 | tristate "Hexium HV-PCI6 and Orion frame grabber" | 643 | tristate "Hexium HV-PCI6 and Orion frame grabber" |
728 | depends on PCI && VIDEO_V4L2 && I2C | 644 | depends on PCI && VIDEO_V4L2 && I2C |
@@ -784,6 +700,70 @@ config VIDEO_CAFE_CCIC | |||
784 | CMOS camera controller. This is the controller found on first- | 700 | CMOS camera controller. This is the controller found on first- |
785 | generation OLPC systems. | 701 | generation OLPC systems. |
786 | 702 | ||
703 | config SOC_CAMERA | ||
704 | tristate "SoC camera support" | ||
705 | depends on VIDEO_V4L2 && HAS_DMA | ||
706 | select VIDEOBUF_GEN | ||
707 | help | ||
708 | SoC Camera is a common API to several cameras, not connecting | ||
709 | over a bus like PCI or USB. For example some i2c camera connected | ||
710 | directly to the data bus of an SoC. | ||
711 | |||
712 | config SOC_CAMERA_MT9M001 | ||
713 | tristate "mt9m001 support" | ||
714 | depends on SOC_CAMERA && I2C | ||
715 | select GPIO_PCA953X if MT9M001_PCA9536_SWITCH | ||
716 | help | ||
717 | This driver supports MT9M001 cameras from Micron, monochrome | ||
718 | and colour models. | ||
719 | |||
720 | config MT9M001_PCA9536_SWITCH | ||
721 | bool "pca9536 datawidth switch for mt9m001" | ||
722 | depends on SOC_CAMERA_MT9M001 && GENERIC_GPIO | ||
723 | help | ||
724 | Select this if your MT9M001 camera uses a PCA9536 I2C GPIO | ||
725 | extender to switch between 8 and 10 bit datawidth modes | ||
726 | |||
727 | config SOC_CAMERA_MT9M111 | ||
728 | tristate "mt9m111 support" | ||
729 | depends on SOC_CAMERA && I2C | ||
730 | help | ||
731 | This driver supports MT9M111 cameras from Micron | ||
732 | |||
733 | config SOC_CAMERA_MT9V022 | ||
734 | tristate "mt9v022 support" | ||
735 | depends on SOC_CAMERA && I2C | ||
736 | select GPIO_PCA953X if MT9V022_PCA9536_SWITCH | ||
737 | help | ||
738 | This driver supports MT9V022 cameras from Micron | ||
739 | |||
740 | config MT9V022_PCA9536_SWITCH | ||
741 | bool "pca9536 datawidth switch for mt9v022" | ||
742 | depends on SOC_CAMERA_MT9V022 && GENERIC_GPIO | ||
743 | help | ||
744 | Select this if your MT9V022 camera uses a PCA9536 I2C GPIO | ||
745 | extender to switch between 8 and 10 bit datawidth modes | ||
746 | |||
747 | config SOC_CAMERA_PLATFORM | ||
748 | tristate "platform camera support" | ||
749 | depends on SOC_CAMERA | ||
750 | help | ||
751 | This is a generic SoC camera platform driver, useful for testing | ||
752 | |||
753 | config VIDEO_PXA27x | ||
754 | tristate "PXA27x Quick Capture Interface driver" | ||
755 | depends on VIDEO_DEV && PXA27x && SOC_CAMERA | ||
756 | select VIDEOBUF_DMA_SG | ||
757 | ---help--- | ||
758 | This is a v4l2 driver for the PXA27x Quick Capture Interface | ||
759 | |||
760 | config VIDEO_SH_MOBILE_CEU | ||
761 | tristate "SuperH Mobile CEU Interface driver" | ||
762 | depends on VIDEO_DEV && SOC_CAMERA && HAS_DMA | ||
763 | select VIDEOBUF_DMA_CONTIG | ||
764 | ---help--- | ||
765 | This is a v4l2 driver for the SuperH Mobile CEU Interface | ||
766 | |||
787 | # | 767 | # |
788 | # USB Multimedia device configuration | 768 | # USB Multimedia device configuration |
789 | # | 769 | # |
@@ -822,8 +802,7 @@ config VIDEO_OVCAMCHIP | |||
822 | 802 | ||
823 | config USB_W9968CF | 803 | config USB_W9968CF |
824 | tristate "USB W996[87]CF JPEG Dual Mode Camera support" | 804 | tristate "USB W996[87]CF JPEG Dual Mode Camera support" |
825 | depends on VIDEO_V4L1 && I2C | 805 | depends on VIDEO_V4L1 && I2C && VIDEO_OVCAMCHIP |
826 | select VIDEO_OVCAMCHIP | ||
827 | ---help--- | 806 | ---help--- |
828 | Say Y here if you want support for cameras based on OV681 or | 807 | Say Y here if you want support for cameras based on OV681 or |
829 | Winbond W9967CF/W9968CF JPEG USB Dual Mode Camera Chips. | 808 | Winbond W9967CF/W9968CF JPEG USB Dual Mode Camera Chips. |
@@ -914,64 +893,4 @@ config USB_S2255 | |||
914 | 893 | ||
915 | endif # V4L_USB_DRIVERS | 894 | endif # V4L_USB_DRIVERS |
916 | 895 | ||
917 | config SOC_CAMERA | ||
918 | tristate "SoC camera support" | ||
919 | depends on VIDEO_V4L2 && HAS_DMA | ||
920 | select VIDEOBUF_GEN | ||
921 | help | ||
922 | SoC Camera is a common API to several cameras, not connecting | ||
923 | over a bus like PCI or USB. For example some i2c camera connected | ||
924 | directly to the data bus of an SoC. | ||
925 | |||
926 | config SOC_CAMERA_MT9M001 | ||
927 | tristate "mt9m001 support" | ||
928 | depends on SOC_CAMERA && I2C | ||
929 | select GPIO_PCA953X if MT9M001_PCA9536_SWITCH | ||
930 | help | ||
931 | This driver supports MT9M001 cameras from Micron, monochrome | ||
932 | and colour models. | ||
933 | |||
934 | config MT9M001_PCA9536_SWITCH | ||
935 | bool "pca9536 datawidth switch for mt9m001" | ||
936 | depends on SOC_CAMERA_MT9M001 && GENERIC_GPIO | ||
937 | help | ||
938 | Select this if your MT9M001 camera uses a PCA9536 I2C GPIO | ||
939 | extender to switch between 8 and 10 bit datawidth modes | ||
940 | |||
941 | config SOC_CAMERA_MT9V022 | ||
942 | tristate "mt9v022 support" | ||
943 | depends on SOC_CAMERA && I2C | ||
944 | select GPIO_PCA953X if MT9V022_PCA9536_SWITCH | ||
945 | help | ||
946 | This driver supports MT9V022 cameras from Micron | ||
947 | |||
948 | config MT9V022_PCA9536_SWITCH | ||
949 | bool "pca9536 datawidth switch for mt9v022" | ||
950 | depends on SOC_CAMERA_MT9V022 && GENERIC_GPIO | ||
951 | help | ||
952 | Select this if your MT9V022 camera uses a PCA9536 I2C GPIO | ||
953 | extender to switch between 8 and 10 bit datawidth modes | ||
954 | |||
955 | config SOC_CAMERA_PLATFORM | ||
956 | tristate "platform camera support" | ||
957 | depends on SOC_CAMERA | ||
958 | help | ||
959 | This is a generic SoC camera platform driver, useful for testing | ||
960 | |||
961 | config VIDEO_PXA27x | ||
962 | tristate "PXA27x Quick Capture Interface driver" | ||
963 | depends on VIDEO_DEV && PXA27x | ||
964 | select SOC_CAMERA | ||
965 | select VIDEOBUF_DMA_SG | ||
966 | ---help--- | ||
967 | This is a v4l2 driver for the PXA27x Quick Capture Interface | ||
968 | |||
969 | config VIDEO_SH_MOBILE_CEU | ||
970 | tristate "SuperH Mobile CEU Interface driver" | ||
971 | depends on VIDEO_DEV && HAS_DMA | ||
972 | select SOC_CAMERA | ||
973 | select VIDEOBUF_DMA_CONTIG | ||
974 | ---help--- | ||
975 | This is a v4l2 driver for the SuperH Mobile CEU Interface | ||
976 | |||
977 | endif # VIDEO_CAPTURE_DRIVERS | 896 | endif # VIDEO_CAPTURE_DRIVERS |
diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index ef7c8d3ffb18..16962f3aa157 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile | |||
@@ -2,8 +2,6 @@ | |||
2 | # Makefile for the video capture/playback device drivers. | 2 | # Makefile for the video capture/playback device drivers. |
3 | # | 3 | # |
4 | 4 | ||
5 | zr36067-objs := zoran_procfs.o zoran_device.o \ | ||
6 | zoran_driver.o zoran_card.o | ||
7 | tuner-objs := tuner-core.o | 5 | tuner-objs := tuner-core.o |
8 | 6 | ||
9 | msp3400-objs := msp3400-driver.o msp3400-kthreads.o | 7 | msp3400-objs := msp3400-driver.o msp3400-kthreads.o |
@@ -54,9 +52,7 @@ obj-$(CONFIG_VIDEO_BT856) += bt856.o | |||
54 | obj-$(CONFIG_VIDEO_BT866) += bt866.o | 52 | obj-$(CONFIG_VIDEO_BT866) += bt866.o |
55 | obj-$(CONFIG_VIDEO_KS0127) += ks0127.o | 53 | obj-$(CONFIG_VIDEO_KS0127) += ks0127.o |
56 | 54 | ||
57 | obj-$(CONFIG_VIDEO_ZORAN) += zr36067.o videocodec.o | 55 | obj-$(CONFIG_VIDEO_ZORAN) += zoran/ |
58 | obj-$(CONFIG_VIDEO_ZORAN_DC30) += zr36050.o zr36016.o | ||
59 | obj-$(CONFIG_VIDEO_ZORAN_ZR36060) += zr36060.o | ||
60 | 56 | ||
61 | obj-$(CONFIG_VIDEO_PMS) += pms.o | 57 | obj-$(CONFIG_VIDEO_PMS) += pms.o |
62 | obj-$(CONFIG_VIDEO_VINO) += vino.o indycam.o | 58 | obj-$(CONFIG_VIDEO_VINO) += vino.o indycam.o |
@@ -84,8 +80,6 @@ obj-$(CONFIG_VIDEO_CPIA2) += cpia2/ | |||
84 | obj-$(CONFIG_VIDEO_MXB) += mxb.o | 80 | obj-$(CONFIG_VIDEO_MXB) += mxb.o |
85 | obj-$(CONFIG_VIDEO_HEXIUM_ORION) += hexium_orion.o | 81 | obj-$(CONFIG_VIDEO_HEXIUM_ORION) += hexium_orion.o |
86 | obj-$(CONFIG_VIDEO_HEXIUM_GEMINI) += hexium_gemini.o | 82 | obj-$(CONFIG_VIDEO_HEXIUM_GEMINI) += hexium_gemini.o |
87 | obj-$(CONFIG_VIDEO_DPC) += dpc7146.o | ||
88 | obj-$(CONFIG_TUNER_3036) += tuner-3036.o | ||
89 | 83 | ||
90 | obj-$(CONFIG_VIDEOBUF_GEN) += videobuf-core.o | 84 | obj-$(CONFIG_VIDEOBUF_GEN) += videobuf-core.o |
91 | obj-$(CONFIG_VIDEOBUF_DMA_SG) += videobuf-dma-sg.o | 85 | obj-$(CONFIG_VIDEOBUF_DMA_SG) += videobuf-dma-sg.o |
@@ -137,6 +131,7 @@ obj-$(CONFIG_VIDEO_PXA27x) += pxa_camera.o | |||
137 | obj-$(CONFIG_VIDEO_SH_MOBILE_CEU) += sh_mobile_ceu_camera.o | 131 | obj-$(CONFIG_VIDEO_SH_MOBILE_CEU) += sh_mobile_ceu_camera.o |
138 | obj-$(CONFIG_SOC_CAMERA) += soc_camera.o | 132 | obj-$(CONFIG_SOC_CAMERA) += soc_camera.o |
139 | obj-$(CONFIG_SOC_CAMERA_MT9M001) += mt9m001.o | 133 | obj-$(CONFIG_SOC_CAMERA_MT9M001) += mt9m001.o |
134 | obj-$(CONFIG_SOC_CAMERA_MT9M111) += mt9m111.o | ||
140 | obj-$(CONFIG_SOC_CAMERA_MT9V022) += mt9v022.o | 135 | obj-$(CONFIG_SOC_CAMERA_MT9V022) += mt9v022.o |
141 | obj-$(CONFIG_SOC_CAMERA_PLATFORM) += soc_camera_platform.o | 136 | obj-$(CONFIG_SOC_CAMERA_PLATFORM) += soc_camera_platform.o |
142 | 137 | ||
diff --git a/drivers/media/video/arv.c b/drivers/media/video/arv.c index 9e436ad3d34b..218754b4906a 100644 --- a/drivers/media/video/arv.c +++ b/drivers/media/video/arv.c | |||
@@ -116,6 +116,7 @@ struct ar_device { | |||
116 | int width, height; | 116 | int width, height; |
117 | int frame_bytes, line_bytes; | 117 | int frame_bytes, line_bytes; |
118 | wait_queue_head_t wait; | 118 | wait_queue_head_t wait; |
119 | unsigned long in_use; | ||
119 | struct mutex lock; | 120 | struct mutex lock; |
120 | }; | 121 | }; |
121 | 122 | ||
@@ -269,7 +270,7 @@ static inline void wait_for_vertical_sync(int exp_line) | |||
269 | static ssize_t ar_read(struct file *file, char *buf, size_t count, loff_t *ppos) | 270 | static ssize_t ar_read(struct file *file, char *buf, size_t count, loff_t *ppos) |
270 | { | 271 | { |
271 | struct video_device *v = video_devdata(file); | 272 | struct video_device *v = video_devdata(file); |
272 | struct ar_device *ar = v->priv; | 273 | struct ar_device *ar = video_get_drvdata(v); |
273 | long ret = ar->frame_bytes; /* return read bytes */ | 274 | long ret = ar->frame_bytes; /* return read bytes */ |
274 | unsigned long arvcr1 = 0; | 275 | unsigned long arvcr1 = 0; |
275 | unsigned long flags; | 276 | unsigned long flags; |
@@ -399,7 +400,7 @@ static int ar_do_ioctl(struct inode *inode, struct file *file, | |||
399 | unsigned int cmd, void *arg) | 400 | unsigned int cmd, void *arg) |
400 | { | 401 | { |
401 | struct video_device *dev = video_devdata(file); | 402 | struct video_device *dev = video_devdata(file); |
402 | struct ar_device *ar = dev->priv; | 403 | struct ar_device *ar = video_get_drvdata(dev); |
403 | 404 | ||
404 | DEBUG(1, "ar_ioctl()\n"); | 405 | DEBUG(1, "ar_ioctl()\n"); |
405 | switch(cmd) { | 406 | switch(cmd) { |
@@ -625,7 +626,7 @@ static void ar_interrupt(int irq, void *dev) | |||
625 | */ | 626 | */ |
626 | static int ar_initialize(struct video_device *dev) | 627 | static int ar_initialize(struct video_device *dev) |
627 | { | 628 | { |
628 | struct ar_device *ar = dev->priv; | 629 | struct ar_device *ar = video_get_drvdata(dev); |
629 | unsigned long cr = 0; | 630 | unsigned long cr = 0; |
630 | int i,found=0; | 631 | int i,found=0; |
631 | 632 | ||
@@ -732,7 +733,7 @@ static int ar_initialize(struct video_device *dev) | |||
732 | 733 | ||
733 | void ar_release(struct video_device *vfd) | 734 | void ar_release(struct video_device *vfd) |
734 | { | 735 | { |
735 | struct ar_device *ar = vfd->priv; | 736 | struct ar_device *ar = video_get_drvdata(vfd); |
736 | mutex_lock(&ar->lock); | 737 | mutex_lock(&ar->lock); |
737 | video_device_release(vfd); | 738 | video_device_release(vfd); |
738 | } | 739 | } |
@@ -742,10 +743,23 @@ void ar_release(struct video_device *vfd) | |||
742 | * Video4Linux Module functions | 743 | * Video4Linux Module functions |
743 | * | 744 | * |
744 | ****************************************************************************/ | 745 | ****************************************************************************/ |
746 | static struct ar_device ardev; | ||
747 | |||
748 | static int ar_exclusive_open(struct inode *inode, struct file *file) | ||
749 | { | ||
750 | return test_and_set_bit(0, &ardev.in_use) ? -EBUSY : 0; | ||
751 | } | ||
752 | |||
753 | static int ar_exclusive_release(struct inode *inode, struct file *file) | ||
754 | { | ||
755 | clear_bit(0, &ardev.in_use); | ||
756 | return 0; | ||
757 | } | ||
758 | |||
745 | static const struct file_operations ar_fops = { | 759 | static const struct file_operations ar_fops = { |
746 | .owner = THIS_MODULE, | 760 | .owner = THIS_MODULE, |
747 | .open = video_exclusive_open, | 761 | .open = ar_exclusive_open, |
748 | .release = video_exclusive_release, | 762 | .release = ar_exclusive_release, |
749 | .read = ar_read, | 763 | .read = ar_read, |
750 | .ioctl = ar_ioctl, | 764 | .ioctl = ar_ioctl, |
751 | #ifdef CONFIG_COMPAT | 765 | #ifdef CONFIG_COMPAT |
@@ -762,7 +776,6 @@ static struct video_device ar_template = { | |||
762 | }; | 776 | }; |
763 | 777 | ||
764 | #define ALIGN4(x) ((((int)(x)) & 0x3) == 0) | 778 | #define ALIGN4(x) ((((int)(x)) & 0x3) == 0) |
765 | static struct ar_device ardev; | ||
766 | 779 | ||
767 | static int __init ar_init(void) | 780 | static int __init ar_init(void) |
768 | { | 781 | { |
@@ -802,7 +815,7 @@ static int __init ar_init(void) | |||
802 | return -ENOMEM; | 815 | return -ENOMEM; |
803 | } | 816 | } |
804 | memcpy(ar->vdev, &ar_template, sizeof(ar_template)); | 817 | memcpy(ar->vdev, &ar_template, sizeof(ar_template)); |
805 | ar->vdev->priv = ar; | 818 | video_set_drvdata(ar->vdev, ar); |
806 | 819 | ||
807 | if (vga) { | 820 | if (vga) { |
808 | ar->width = AR_WIDTH_VGA; | 821 | ar->width = AR_WIDTH_VGA; |
diff --git a/drivers/media/video/au0828/au0828-cards.c b/drivers/media/video/au0828/au0828-cards.c index ed48908a9034..5f07a8a072b6 100644 --- a/drivers/media/video/au0828/au0828-cards.c +++ b/drivers/media/video/au0828/au0828-cards.c | |||
@@ -46,7 +46,7 @@ struct au0828_board au0828_boards[] = { | |||
46 | /* Tuner callback function for au0828 boards. Currently only needed | 46 | /* Tuner callback function for au0828 boards. Currently only needed |
47 | * for HVR1500Q, which has an xc5000 tuner. | 47 | * for HVR1500Q, which has an xc5000 tuner. |
48 | */ | 48 | */ |
49 | int au0828_tuner_callback(void *priv, int command, int arg) | 49 | int au0828_tuner_callback(void *priv, int component, int command, int arg) |
50 | { | 50 | { |
51 | struct au0828_dev *dev = priv; | 51 | struct au0828_dev *dev = priv; |
52 | 52 | ||
diff --git a/drivers/media/video/au0828/au0828-dvb.c b/drivers/media/video/au0828/au0828-dvb.c index ba94be7e0ac1..f0fcdb4769d7 100644 --- a/drivers/media/video/au0828/au0828-dvb.c +++ b/drivers/media/video/au0828/au0828-dvb.c | |||
@@ -36,11 +36,39 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | |||
36 | #define _AU0828_BULKPIPE 0x83 | 36 | #define _AU0828_BULKPIPE 0x83 |
37 | #define _BULKPIPESIZE 0xe522 | 37 | #define _BULKPIPESIZE 0xe522 |
38 | 38 | ||
39 | static u8 hauppauge_hvr950q_led_states[] = { | ||
40 | 0x00, /* off */ | ||
41 | 0x02, /* yellow */ | ||
42 | 0x04, /* green */ | ||
43 | }; | ||
44 | |||
45 | static struct au8522_led_config hauppauge_hvr950q_led_cfg = { | ||
46 | .gpio_output = 0x00e0, | ||
47 | .gpio_output_enable = 0x6006, | ||
48 | .gpio_output_disable = 0x0660, | ||
49 | |||
50 | .gpio_leds = 0x00e2, | ||
51 | .led_states = hauppauge_hvr950q_led_states, | ||
52 | .num_led_states = sizeof(hauppauge_hvr950q_led_states), | ||
53 | |||
54 | .vsb8_strong = 20 /* dB */ * 10, | ||
55 | .qam64_strong = 25 /* dB */ * 10, | ||
56 | .qam256_strong = 32 /* dB */ * 10, | ||
57 | }; | ||
58 | |||
39 | static struct au8522_config hauppauge_hvr950q_config = { | 59 | static struct au8522_config hauppauge_hvr950q_config = { |
40 | .demod_address = 0x8e >> 1, | 60 | .demod_address = 0x8e >> 1, |
41 | .status_mode = AU8522_DEMODLOCKING, | 61 | .status_mode = AU8522_DEMODLOCKING, |
42 | .qam_if = AU8522_IF_6MHZ, | 62 | .qam_if = AU8522_IF_6MHZ, |
43 | .vsb_if = AU8522_IF_6MHZ, | 63 | .vsb_if = AU8522_IF_6MHZ, |
64 | .led_cfg = &hauppauge_hvr950q_led_cfg, | ||
65 | }; | ||
66 | |||
67 | static struct au8522_config fusionhdtv7usb_config = { | ||
68 | .demod_address = 0x8e >> 1, | ||
69 | .status_mode = AU8522_DEMODLOCKING, | ||
70 | .qam_if = AU8522_IF_6MHZ, | ||
71 | .vsb_if = AU8522_IF_6MHZ, | ||
44 | }; | 72 | }; |
45 | 73 | ||
46 | static struct au8522_config hauppauge_woodbury_config = { | 74 | static struct au8522_config hauppauge_woodbury_config = { |
@@ -53,7 +81,6 @@ static struct au8522_config hauppauge_woodbury_config = { | |||
53 | static struct xc5000_config hauppauge_hvr950q_tunerconfig = { | 81 | static struct xc5000_config hauppauge_hvr950q_tunerconfig = { |
54 | .i2c_address = 0x61, | 82 | .i2c_address = 0x61, |
55 | .if_khz = 6000, | 83 | .if_khz = 6000, |
56 | .tuner_callback = au0828_tuner_callback | ||
57 | }; | 84 | }; |
58 | 85 | ||
59 | static struct mxl5007t_config mxl5007t_hvr950q_config = { | 86 | static struct mxl5007t_config mxl5007t_hvr950q_config = { |
@@ -353,14 +380,12 @@ int au0828_dvb_register(struct au0828_dev *dev) | |||
353 | switch (dev->board) { | 380 | switch (dev->board) { |
354 | case AU0828_BOARD_HAUPPAUGE_HVR850: | 381 | case AU0828_BOARD_HAUPPAUGE_HVR850: |
355 | case AU0828_BOARD_HAUPPAUGE_HVR950Q: | 382 | case AU0828_BOARD_HAUPPAUGE_HVR950Q: |
356 | case AU0828_BOARD_DVICO_FUSIONHDTV7: | ||
357 | dvb->frontend = dvb_attach(au8522_attach, | 383 | dvb->frontend = dvb_attach(au8522_attach, |
358 | &hauppauge_hvr950q_config, | 384 | &hauppauge_hvr950q_config, |
359 | &dev->i2c_adap); | 385 | &dev->i2c_adap); |
360 | if (dvb->frontend != NULL) | 386 | if (dvb->frontend != NULL) |
361 | dvb_attach(xc5000_attach, dvb->frontend, | 387 | dvb_attach(xc5000_attach, dvb->frontend, &dev->i2c_adap, |
362 | &dev->i2c_adap, | 388 | &hauppauge_hvr950q_tunerconfig); |
363 | &hauppauge_hvr950q_tunerconfig, dev); | ||
364 | break; | 389 | break; |
365 | case AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL: | 390 | case AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL: |
366 | dvb->frontend = dvb_attach(au8522_attach, | 391 | dvb->frontend = dvb_attach(au8522_attach, |
@@ -380,6 +405,16 @@ int au0828_dvb_register(struct au0828_dev *dev) | |||
380 | 0x60, &dev->i2c_adap, | 405 | 0x60, &dev->i2c_adap, |
381 | &hauppauge_woodbury_tunerconfig); | 406 | &hauppauge_woodbury_tunerconfig); |
382 | break; | 407 | break; |
408 | case AU0828_BOARD_DVICO_FUSIONHDTV7: | ||
409 | dvb->frontend = dvb_attach(au8522_attach, | ||
410 | &fusionhdtv7usb_config, | ||
411 | &dev->i2c_adap); | ||
412 | if (dvb->frontend != NULL) { | ||
413 | dvb_attach(xc5000_attach, dvb->frontend, | ||
414 | &dev->i2c_adap, | ||
415 | &hauppauge_hvr950q_tunerconfig); | ||
416 | } | ||
417 | break; | ||
383 | default: | 418 | default: |
384 | printk(KERN_WARNING "The frontend of your DVB/ATSC card " | 419 | printk(KERN_WARNING "The frontend of your DVB/ATSC card " |
385 | "isn't supported yet\n"); | 420 | "isn't supported yet\n"); |
@@ -390,6 +425,8 @@ int au0828_dvb_register(struct au0828_dev *dev) | |||
390 | __func__); | 425 | __func__); |
391 | return -1; | 426 | return -1; |
392 | } | 427 | } |
428 | /* define general-purpose callback pointer */ | ||
429 | dvb->frontend->callback = au0828_tuner_callback; | ||
393 | 430 | ||
394 | /* register everything */ | 431 | /* register everything */ |
395 | ret = dvb_register(dev); | 432 | ret = dvb_register(dev); |
diff --git a/drivers/media/video/au0828/au0828.h b/drivers/media/video/au0828/au0828.h index 4f10ff300135..9d6a1161dc98 100644 --- a/drivers/media/video/au0828/au0828.h +++ b/drivers/media/video/au0828/au0828.h | |||
@@ -103,7 +103,8 @@ extern int au0828_debug; | |||
103 | extern struct au0828_board au0828_boards[]; | 103 | extern struct au0828_board au0828_boards[]; |
104 | extern struct usb_device_id au0828_usb_id_table[]; | 104 | extern struct usb_device_id au0828_usb_id_table[]; |
105 | extern void au0828_gpio_setup(struct au0828_dev *dev); | 105 | extern void au0828_gpio_setup(struct au0828_dev *dev); |
106 | extern int au0828_tuner_callback(void *priv, int command, int arg); | 106 | extern int au0828_tuner_callback(void *priv, int component, |
107 | int command, int arg); | ||
107 | extern void au0828_card_setup(struct au0828_dev *dev); | 108 | extern void au0828_card_setup(struct au0828_dev *dev); |
108 | 109 | ||
109 | /* ----------------------------------------------------------- */ | 110 | /* ----------------------------------------------------------- */ |
diff --git a/drivers/media/video/bt856.c b/drivers/media/video/bt856.c index 98ee2d8feb34..ab2ce4d7b5de 100644 --- a/drivers/media/video/bt856.c +++ b/drivers/media/video/bt856.c | |||
@@ -68,8 +68,8 @@ MODULE_PARM_DESC(debug, "Debug level (0-1)"); | |||
68 | 68 | ||
69 | /* ----------------------------------------------------------------------- */ | 69 | /* ----------------------------------------------------------------------- */ |
70 | 70 | ||
71 | #define REG_OFFSET 0xDA | 71 | #define BT856_REG_OFFSET 0xDA |
72 | #define BT856_NR_REG 6 | 72 | #define BT856_NR_REG 6 |
73 | 73 | ||
74 | struct bt856 { | 74 | struct bt856 { |
75 | unsigned char reg[BT856_NR_REG]; | 75 | unsigned char reg[BT856_NR_REG]; |
@@ -89,7 +89,7 @@ bt856_write (struct i2c_client *client, | |||
89 | { | 89 | { |
90 | struct bt856 *encoder = i2c_get_clientdata(client); | 90 | struct bt856 *encoder = i2c_get_clientdata(client); |
91 | 91 | ||
92 | encoder->reg[reg - REG_OFFSET] = value; | 92 | encoder->reg[reg - BT856_REG_OFFSET] = value; |
93 | return i2c_smbus_write_byte_data(client, reg, value); | 93 | return i2c_smbus_write_byte_data(client, reg, value); |
94 | } | 94 | } |
95 | 95 | ||
@@ -103,7 +103,7 @@ bt856_setbit (struct i2c_client *client, | |||
103 | 103 | ||
104 | return bt856_write(client, reg, | 104 | return bt856_write(client, reg, |
105 | (encoder-> | 105 | (encoder-> |
106 | reg[reg - REG_OFFSET] & ~(1 << bit)) | | 106 | reg[reg - BT856_REG_OFFSET] & ~(1 << bit)) | |
107 | (value ? (1 << bit) : 0)); | 107 | (value ? (1 << bit) : 0)); |
108 | } | 108 | } |
109 | 109 | ||
diff --git a/drivers/media/video/bt8xx/bttv-cards.c b/drivers/media/video/bt8xx/bttv-cards.c index 6081edc362df..13742b0bbe3e 100644 --- a/drivers/media/video/bt8xx/bttv-cards.c +++ b/drivers/media/video/bt8xx/bttv-cards.c | |||
@@ -305,7 +305,7 @@ static struct CARD { | |||
305 | { 0x00261822, BTTV_BOARD_TWINHAN_DST, "DNTV Live! Mini "}, | 305 | { 0x00261822, BTTV_BOARD_TWINHAN_DST, "DNTV Live! Mini "}, |
306 | { 0xd200dbc0, BTTV_BOARD_DVICO_FUSIONHDTV_2, "DViCO FusionHDTV 2" }, | 306 | { 0xd200dbc0, BTTV_BOARD_DVICO_FUSIONHDTV_2, "DViCO FusionHDTV 2" }, |
307 | { 0x763c008a, BTTV_BOARD_GEOVISION_GV600, "GeoVision GV-600" }, | 307 | { 0x763c008a, BTTV_BOARD_GEOVISION_GV600, "GeoVision GV-600" }, |
308 | 308 | { 0x18011000, BTTV_BOARD_ENLTV_FM_2, "Encore ENL TV-FM-2" }, | |
309 | { 0, -1, NULL } | 309 | { 0, -1, NULL } |
310 | }; | 310 | }; |
311 | 311 | ||
@@ -3037,6 +3037,31 @@ struct tvcard bttv_tvcards[] = { | |||
3037 | .has_radio = 1, | 3037 | .has_radio = 1, |
3038 | .has_remote = 1, | 3038 | .has_remote = 1, |
3039 | }, | 3039 | }, |
3040 | [BTTV_BOARD_ENLTV_FM_2] = { | ||
3041 | /* Encore TV Tuner Pro ENL TV-FM-2 | ||
3042 | Mauro Carvalho Chehab <mchehab@infradead.org */ | ||
3043 | .name = "Encore ENL TV-FM-2", | ||
3044 | .video_inputs = 3, | ||
3045 | .audio_inputs = 1, | ||
3046 | .tuner = 0, | ||
3047 | .svhs = 2, | ||
3048 | /* bit 6 -> IR disabled | ||
3049 | bit 18/17 = 00 -> mute | ||
3050 | 01 -> enable external audio input | ||
3051 | 10 -> internal audio input (mono?) | ||
3052 | 11 -> internal audio input | ||
3053 | */ | ||
3054 | .gpiomask = 0x060040, | ||
3055 | .muxsel = { 2, 3, 3 }, | ||
3056 | .gpiomux = { 0x60000, 0x60000, 0x20000, 0x20000 }, | ||
3057 | .gpiomute = 0, | ||
3058 | .tuner_type = TUNER_TCL_MF02GIP_5N, | ||
3059 | .tuner_addr = ADDR_UNSET, | ||
3060 | .radio_addr = ADDR_UNSET, | ||
3061 | .pll = PLL_28, | ||
3062 | .has_radio = 1, | ||
3063 | .has_remote = 1, | ||
3064 | } | ||
3040 | }; | 3065 | }; |
3041 | 3066 | ||
3042 | static const unsigned int bttv_num_tvcards = ARRAY_SIZE(bttv_tvcards); | 3067 | static const unsigned int bttv_num_tvcards = ARRAY_SIZE(bttv_tvcards); |
diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c index 933eaef41ead..5858bf5ff41c 100644 --- a/drivers/media/video/bt8xx/bttv-driver.c +++ b/drivers/media/video/bt8xx/bttv-driver.c | |||
@@ -76,9 +76,9 @@ static unsigned int gbuffers = 8; | |||
76 | static unsigned int gbufsize = 0x208000; | 76 | static unsigned int gbufsize = 0x208000; |
77 | static unsigned int reset_crop = 1; | 77 | static unsigned int reset_crop = 1; |
78 | 78 | ||
79 | static int video_nr = -1; | 79 | static int video_nr[BTTV_MAX] = { [0 ... (BTTV_MAX-1)] = -1 }; |
80 | static int radio_nr = -1; | 80 | static int radio_nr[BTTV_MAX] = { [0 ... (BTTV_MAX-1)] = -1 }; |
81 | static int vbi_nr = -1; | 81 | static int vbi_nr[BTTV_MAX] = { [0 ... (BTTV_MAX-1)] = -1 }; |
82 | static int debug_latency; | 82 | static int debug_latency; |
83 | 83 | ||
84 | static unsigned int fdsr; | 84 | static unsigned int fdsr; |
@@ -108,9 +108,6 @@ module_param(irq_debug, int, 0644); | |||
108 | module_param(debug_latency, int, 0644); | 108 | module_param(debug_latency, int, 0644); |
109 | 109 | ||
110 | module_param(fdsr, int, 0444); | 110 | module_param(fdsr, int, 0444); |
111 | module_param(video_nr, int, 0444); | ||
112 | module_param(radio_nr, int, 0444); | ||
113 | module_param(vbi_nr, int, 0444); | ||
114 | module_param(gbuffers, int, 0444); | 111 | module_param(gbuffers, int, 0444); |
115 | module_param(gbufsize, int, 0444); | 112 | module_param(gbufsize, int, 0444); |
116 | module_param(reset_crop, int, 0444); | 113 | module_param(reset_crop, int, 0444); |
@@ -130,7 +127,10 @@ module_param(uv_ratio, int, 0444); | |||
130 | module_param(full_luma_range, int, 0444); | 127 | module_param(full_luma_range, int, 0444); |
131 | module_param(coring, int, 0444); | 128 | module_param(coring, int, 0444); |
132 | 129 | ||
133 | module_param_array(radio, int, NULL, 0444); | 130 | module_param_array(radio, int, NULL, 0444); |
131 | module_param_array(video_nr, int, NULL, 0444); | ||
132 | module_param_array(radio_nr, int, NULL, 0444); | ||
133 | module_param_array(vbi_nr, int, NULL, 0444); | ||
134 | 134 | ||
135 | MODULE_PARM_DESC(radio,"The TV card supports radio, default is 0 (no)"); | 135 | MODULE_PARM_DESC(radio,"The TV card supports radio, default is 0 (no)"); |
136 | MODULE_PARM_DESC(bigendian,"byte order of the framebuffer, default is native endian"); | 136 | MODULE_PARM_DESC(bigendian,"byte order of the framebuffer, default is native endian"); |
@@ -152,6 +152,9 @@ MODULE_PARM_DESC(irq_iswitch,"switch inputs in irq handler"); | |||
152 | MODULE_PARM_DESC(uv_ratio,"ratio between u and v gains, default is 50"); | 152 | MODULE_PARM_DESC(uv_ratio,"ratio between u and v gains, default is 50"); |
153 | MODULE_PARM_DESC(full_luma_range,"use the full luma range, default is 0 (no)"); | 153 | MODULE_PARM_DESC(full_luma_range,"use the full luma range, default is 0 (no)"); |
154 | MODULE_PARM_DESC(coring,"set the luma coring level, default is 0 (no)"); | 154 | MODULE_PARM_DESC(coring,"set the luma coring level, default is 0 (no)"); |
155 | MODULE_PARM_DESC(video_nr, "video device numbers"); | ||
156 | MODULE_PARM_DESC(vbi_nr, "vbi device numbers"); | ||
157 | MODULE_PARM_DESC(radio_nr, "radio device numbers"); | ||
155 | 158 | ||
156 | MODULE_DESCRIPTION("bttv - v4l/v4l2 driver module for bt848/878 based cards"); | 159 | MODULE_DESCRIPTION("bttv - v4l/v4l2 driver module for bt848/878 based cards"); |
157 | MODULE_AUTHOR("Ralph Metzler & Marcus Metzler & Gerd Knorr"); | 160 | MODULE_AUTHOR("Ralph Metzler & Marcus Metzler & Gerd Knorr"); |
@@ -1367,7 +1370,7 @@ static void init_irqreg(struct bttv *btv) | |||
1367 | (btv->gpioirq ? BT848_INT_GPINT : 0) | | 1370 | (btv->gpioirq ? BT848_INT_GPINT : 0) | |
1368 | BT848_INT_SCERR | | 1371 | BT848_INT_SCERR | |
1369 | (fdsr ? BT848_INT_FDSR : 0) | | 1372 | (fdsr ? BT848_INT_FDSR : 0) | |
1370 | BT848_INT_RISCI|BT848_INT_OCERR|BT848_INT_VPRES| | 1373 | BT848_INT_RISCI | BT848_INT_OCERR | |
1371 | BT848_INT_FMTCHG|BT848_INT_HLOCK| | 1374 | BT848_INT_FMTCHG|BT848_INT_HLOCK| |
1372 | BT848_INT_I2CDONE, | 1375 | BT848_INT_I2CDONE, |
1373 | BT848_INT_MASK); | 1376 | BT848_INT_MASK); |
@@ -2661,18 +2664,6 @@ static int bttv_querycap(struct file *file, void *priv, | |||
2661 | return 0; | 2664 | return 0; |
2662 | } | 2665 | } |
2663 | 2666 | ||
2664 | static int bttv_enum_fmt_vbi_cap(struct file *file, void *priv, | ||
2665 | struct v4l2_fmtdesc *f) | ||
2666 | { | ||
2667 | if (0 != f->index) | ||
2668 | return -EINVAL; | ||
2669 | |||
2670 | f->pixelformat = V4L2_PIX_FMT_GREY; | ||
2671 | strcpy(f->description, "vbi data"); | ||
2672 | |||
2673 | return 0; | ||
2674 | } | ||
2675 | |||
2676 | static int bttv_enum_fmt_cap_ovr(struct v4l2_fmtdesc *f) | 2667 | static int bttv_enum_fmt_cap_ovr(struct v4l2_fmtdesc *f) |
2677 | { | 2668 | { |
2678 | int index = -1, i; | 2669 | int index = -1, i; |
@@ -3227,6 +3218,7 @@ static int bttv_open(struct inode *inode, struct file *file) | |||
3227 | 3218 | ||
3228 | dprintk(KERN_DEBUG "bttv: open minor=%d\n",minor); | 3219 | dprintk(KERN_DEBUG "bttv: open minor=%d\n",minor); |
3229 | 3220 | ||
3221 | lock_kernel(); | ||
3230 | for (i = 0; i < bttv_num; i++) { | 3222 | for (i = 0; i < bttv_num; i++) { |
3231 | if (bttvs[i].video_dev && | 3223 | if (bttvs[i].video_dev && |
3232 | bttvs[i].video_dev->minor == minor) { | 3224 | bttvs[i].video_dev->minor == minor) { |
@@ -3241,16 +3233,20 @@ static int bttv_open(struct inode *inode, struct file *file) | |||
3241 | break; | 3233 | break; |
3242 | } | 3234 | } |
3243 | } | 3235 | } |
3244 | if (NULL == btv) | 3236 | if (NULL == btv) { |
3237 | unlock_kernel(); | ||
3245 | return -ENODEV; | 3238 | return -ENODEV; |
3239 | } | ||
3246 | 3240 | ||
3247 | dprintk(KERN_DEBUG "bttv%d: open called (type=%s)\n", | 3241 | dprintk(KERN_DEBUG "bttv%d: open called (type=%s)\n", |
3248 | btv->c.nr,v4l2_type_names[type]); | 3242 | btv->c.nr,v4l2_type_names[type]); |
3249 | 3243 | ||
3250 | /* allocate per filehandle data */ | 3244 | /* allocate per filehandle data */ |
3251 | fh = kmalloc(sizeof(*fh),GFP_KERNEL); | 3245 | fh = kmalloc(sizeof(*fh),GFP_KERNEL); |
3252 | if (NULL == fh) | 3246 | if (NULL == fh) { |
3247 | unlock_kernel(); | ||
3253 | return -ENOMEM; | 3248 | return -ENOMEM; |
3249 | } | ||
3254 | file->private_data = fh; | 3250 | file->private_data = fh; |
3255 | *fh = btv->init; | 3251 | *fh = btv->init; |
3256 | fh->type = type; | 3252 | fh->type = type; |
@@ -3270,6 +3266,7 @@ static int bttv_open(struct inode *inode, struct file *file) | |||
3270 | sizeof(struct bttv_buffer), | 3266 | sizeof(struct bttv_buffer), |
3271 | fh); | 3267 | fh); |
3272 | set_tvnorm(btv,btv->tvnorm); | 3268 | set_tvnorm(btv,btv->tvnorm); |
3269 | set_input(btv, btv->input, btv->tvnorm); | ||
3273 | 3270 | ||
3274 | btv->users++; | 3271 | btv->users++; |
3275 | 3272 | ||
@@ -3290,6 +3287,7 @@ static int bttv_open(struct inode *inode, struct file *file) | |||
3290 | bttv_vbi_fmt_reset(&fh->vbi_fmt, btv->tvnorm); | 3287 | bttv_vbi_fmt_reset(&fh->vbi_fmt, btv->tvnorm); |
3291 | 3288 | ||
3292 | bttv_field_count(btv); | 3289 | bttv_field_count(btv); |
3290 | unlock_kernel(); | ||
3293 | return 0; | 3291 | return 0; |
3294 | } | 3292 | } |
3295 | 3293 | ||
@@ -3330,6 +3328,10 @@ static int bttv_release(struct inode *inode, struct file *file) | |||
3330 | 3328 | ||
3331 | btv->users--; | 3329 | btv->users--; |
3332 | bttv_field_count(btv); | 3330 | bttv_field_count(btv); |
3331 | |||
3332 | if (!btv->users) | ||
3333 | audio_mute(btv, 1); | ||
3334 | |||
3333 | return 0; | 3335 | return 0; |
3334 | } | 3336 | } |
3335 | 3337 | ||
@@ -3367,7 +3369,6 @@ static const struct v4l2_ioctl_ops bttv_ioctl_ops = { | |||
3367 | .vidioc_g_fmt_vid_overlay = bttv_g_fmt_vid_overlay, | 3369 | .vidioc_g_fmt_vid_overlay = bttv_g_fmt_vid_overlay, |
3368 | .vidioc_try_fmt_vid_overlay = bttv_try_fmt_vid_overlay, | 3370 | .vidioc_try_fmt_vid_overlay = bttv_try_fmt_vid_overlay, |
3369 | .vidioc_s_fmt_vid_overlay = bttv_s_fmt_vid_overlay, | 3371 | .vidioc_s_fmt_vid_overlay = bttv_s_fmt_vid_overlay, |
3370 | .vidioc_enum_fmt_vbi_cap = bttv_enum_fmt_vbi_cap, | ||
3371 | .vidioc_g_fmt_vbi_cap = bttv_g_fmt_vbi_cap, | 3372 | .vidioc_g_fmt_vbi_cap = bttv_g_fmt_vbi_cap, |
3372 | .vidioc_try_fmt_vbi_cap = bttv_try_fmt_vbi_cap, | 3373 | .vidioc_try_fmt_vbi_cap = bttv_try_fmt_vbi_cap, |
3373 | .vidioc_s_fmt_vbi_cap = bttv_s_fmt_vbi_cap, | 3374 | .vidioc_s_fmt_vbi_cap = bttv_s_fmt_vbi_cap, |
@@ -3430,21 +3431,26 @@ static int radio_open(struct inode *inode, struct file *file) | |||
3430 | 3431 | ||
3431 | dprintk("bttv: open minor=%d\n",minor); | 3432 | dprintk("bttv: open minor=%d\n",minor); |
3432 | 3433 | ||
3434 | lock_kernel(); | ||
3433 | for (i = 0; i < bttv_num; i++) { | 3435 | for (i = 0; i < bttv_num; i++) { |
3434 | if (bttvs[i].radio_dev && bttvs[i].radio_dev->minor == minor) { | 3436 | if (bttvs[i].radio_dev && bttvs[i].radio_dev->minor == minor) { |
3435 | btv = &bttvs[i]; | 3437 | btv = &bttvs[i]; |
3436 | break; | 3438 | break; |
3437 | } | 3439 | } |
3438 | } | 3440 | } |
3439 | if (NULL == btv) | 3441 | if (NULL == btv) { |
3442 | unlock_kernel(); | ||
3440 | return -ENODEV; | 3443 | return -ENODEV; |
3444 | } | ||
3441 | 3445 | ||
3442 | dprintk("bttv%d: open called (radio)\n",btv->c.nr); | 3446 | dprintk("bttv%d: open called (radio)\n",btv->c.nr); |
3443 | 3447 | ||
3444 | /* allocate per filehandle data */ | 3448 | /* allocate per filehandle data */ |
3445 | fh = kmalloc(sizeof(*fh), GFP_KERNEL); | 3449 | fh = kmalloc(sizeof(*fh), GFP_KERNEL); |
3446 | if (NULL == fh) | 3450 | if (NULL == fh) { |
3451 | unlock_kernel(); | ||
3447 | return -ENOMEM; | 3452 | return -ENOMEM; |
3453 | } | ||
3448 | file->private_data = fh; | 3454 | file->private_data = fh; |
3449 | *fh = btv->init; | 3455 | *fh = btv->init; |
3450 | v4l2_prio_open(&btv->prio, &fh->prio); | 3456 | v4l2_prio_open(&btv->prio, &fh->prio); |
@@ -3457,6 +3463,7 @@ static int radio_open(struct inode *inode, struct file *file) | |||
3457 | audio_input(btv,TVAUDIO_INPUT_RADIO); | 3463 | audio_input(btv,TVAUDIO_INPUT_RADIO); |
3458 | 3464 | ||
3459 | mutex_unlock(&btv->lock); | 3465 | mutex_unlock(&btv->lock); |
3466 | unlock_kernel(); | ||
3460 | return 0; | 3467 | return 0; |
3461 | } | 3468 | } |
3462 | 3469 | ||
@@ -4235,7 +4242,8 @@ static int __devinit bttv_register_video(struct bttv *btv) | |||
4235 | 4242 | ||
4236 | if (NULL == btv->video_dev) | 4243 | if (NULL == btv->video_dev) |
4237 | goto err; | 4244 | goto err; |
4238 | if (video_register_device(btv->video_dev,VFL_TYPE_GRABBER,video_nr)<0) | 4245 | if (video_register_device(btv->video_dev, VFL_TYPE_GRABBER, |
4246 | video_nr[btv->c.nr]) < 0) | ||
4239 | goto err; | 4247 | goto err; |
4240 | printk(KERN_INFO "bttv%d: registered device video%d\n", | 4248 | printk(KERN_INFO "bttv%d: registered device video%d\n", |
4241 | btv->c.nr,btv->video_dev->minor & 0x1f); | 4249 | btv->c.nr,btv->video_dev->minor & 0x1f); |
@@ -4251,7 +4259,8 @@ static int __devinit bttv_register_video(struct bttv *btv) | |||
4251 | 4259 | ||
4252 | if (NULL == btv->vbi_dev) | 4260 | if (NULL == btv->vbi_dev) |
4253 | goto err; | 4261 | goto err; |
4254 | if (video_register_device(btv->vbi_dev,VFL_TYPE_VBI,vbi_nr)<0) | 4262 | if (video_register_device(btv->vbi_dev, VFL_TYPE_VBI, |
4263 | vbi_nr[btv->c.nr]) < 0) | ||
4255 | goto err; | 4264 | goto err; |
4256 | printk(KERN_INFO "bttv%d: registered device vbi%d\n", | 4265 | printk(KERN_INFO "bttv%d: registered device vbi%d\n", |
4257 | btv->c.nr,btv->vbi_dev->minor & 0x1f); | 4266 | btv->c.nr,btv->vbi_dev->minor & 0x1f); |
@@ -4262,7 +4271,8 @@ static int __devinit bttv_register_video(struct bttv *btv) | |||
4262 | btv->radio_dev = vdev_init(btv, &radio_template, "radio"); | 4271 | btv->radio_dev = vdev_init(btv, &radio_template, "radio"); |
4263 | if (NULL == btv->radio_dev) | 4272 | if (NULL == btv->radio_dev) |
4264 | goto err; | 4273 | goto err; |
4265 | if (video_register_device(btv->radio_dev, VFL_TYPE_RADIO,radio_nr)<0) | 4274 | if (video_register_device(btv->radio_dev, VFL_TYPE_RADIO, |
4275 | radio_nr[btv->c.nr]) < 0) | ||
4266 | goto err; | 4276 | goto err; |
4267 | printk(KERN_INFO "bttv%d: registered device radio%d\n", | 4277 | printk(KERN_INFO "bttv%d: registered device radio%d\n", |
4268 | btv->c.nr,btv->radio_dev->minor & 0x1f); | 4278 | btv->c.nr,btv->radio_dev->minor & 0x1f); |
diff --git a/drivers/media/video/bt8xx/bttv-input.c b/drivers/media/video/bt8xx/bttv-input.c index a38af98f4cae..2f289d981fe6 100644 --- a/drivers/media/video/bt8xx/bttv-input.c +++ b/drivers/media/video/bt8xx/bttv-input.c | |||
@@ -28,8 +28,8 @@ | |||
28 | #include "bttvp.h" | 28 | #include "bttvp.h" |
29 | 29 | ||
30 | 30 | ||
31 | static int debug; | 31 | static int ir_debug; |
32 | module_param(debug, int, 0644); /* debug level (0,1,2) */ | 32 | module_param(ir_debug, int, 0644); |
33 | static int repeat_delay = 500; | 33 | static int repeat_delay = 500; |
34 | module_param(repeat_delay, int, 0644); | 34 | module_param(repeat_delay, int, 0644); |
35 | static int repeat_period = 33; | 35 | static int repeat_period = 33; |
@@ -40,6 +40,12 @@ module_param(ir_rc5_remote_gap, int, 0644); | |||
40 | static int ir_rc5_key_timeout = 200; | 40 | static int ir_rc5_key_timeout = 200; |
41 | module_param(ir_rc5_key_timeout, int, 0644); | 41 | module_param(ir_rc5_key_timeout, int, 0644); |
42 | 42 | ||
43 | #undef dprintk | ||
44 | #define dprintk(arg...) do { \ | ||
45 | if (ir_debug >= 1) \ | ||
46 | printk(arg); \ | ||
47 | } while (0) | ||
48 | |||
43 | #define DEVNAME "bttv-input" | 49 | #define DEVNAME "bttv-input" |
44 | 50 | ||
45 | /* ---------------------------------------------------------------------- */ | 51 | /* ---------------------------------------------------------------------- */ |
@@ -79,6 +85,45 @@ static void ir_handle_key(struct bttv *btv) | |||
79 | 85 | ||
80 | } | 86 | } |
81 | 87 | ||
88 | static void ir_enltv_handle_key(struct bttv *btv) | ||
89 | { | ||
90 | struct card_ir *ir = btv->remote; | ||
91 | u32 gpio, data, keyup; | ||
92 | |||
93 | /* read gpio value */ | ||
94 | gpio = bttv_gpio_read(&btv->c); | ||
95 | |||
96 | /* extract data */ | ||
97 | data = ir_extract_bits(gpio, ir->mask_keycode); | ||
98 | |||
99 | /* Check if it is keyup */ | ||
100 | keyup = (gpio & ir->mask_keyup) ? 1 << 31 : 0; | ||
101 | |||
102 | if ((ir->last_gpio & 0x7f) != data) { | ||
103 | dprintk(KERN_INFO DEVNAME ": gpio=0x%x code=%d | %s\n", | ||
104 | gpio, data, | ||
105 | (gpio & ir->mask_keyup) ? " up" : "up/down"); | ||
106 | |||
107 | ir_input_keydown(ir->dev, &ir->ir, data, data); | ||
108 | if (keyup) | ||
109 | ir_input_nokey(ir->dev, &ir->ir); | ||
110 | } else { | ||
111 | if ((ir->last_gpio & 1 << 31) == keyup) | ||
112 | return; | ||
113 | |||
114 | dprintk(KERN_INFO DEVNAME ":(cnt) gpio=0x%x code=%d | %s\n", | ||
115 | gpio, data, | ||
116 | (gpio & ir->mask_keyup) ? " up" : "down"); | ||
117 | |||
118 | if (keyup) | ||
119 | ir_input_nokey(ir->dev, &ir->ir); | ||
120 | else | ||
121 | ir_input_keydown(ir->dev, &ir->ir, data, data); | ||
122 | } | ||
123 | |||
124 | ir->last_gpio = data | keyup; | ||
125 | } | ||
126 | |||
82 | void bttv_input_irq(struct bttv *btv) | 127 | void bttv_input_irq(struct bttv *btv) |
83 | { | 128 | { |
84 | struct card_ir *ir = btv->remote; | 129 | struct card_ir *ir = btv->remote; |
@@ -92,7 +137,10 @@ static void bttv_input_timer(unsigned long data) | |||
92 | struct bttv *btv = (struct bttv*)data; | 137 | struct bttv *btv = (struct bttv*)data; |
93 | struct card_ir *ir = btv->remote; | 138 | struct card_ir *ir = btv->remote; |
94 | 139 | ||
95 | ir_handle_key(btv); | 140 | if (btv->c.type == BTTV_BOARD_ENLTV_FM_2) |
141 | ir_enltv_handle_key(btv); | ||
142 | else | ||
143 | ir_handle_key(btv); | ||
96 | mod_timer(&ir->timer, jiffies + msecs_to_jiffies(ir->polling)); | 144 | mod_timer(&ir->timer, jiffies + msecs_to_jiffies(ir->polling)); |
97 | } | 145 | } |
98 | 146 | ||
@@ -284,6 +332,14 @@ int bttv_input_init(struct bttv *btv) | |||
284 | ir->mask_keyup = 0x006000; | 332 | ir->mask_keyup = 0x006000; |
285 | ir->polling = 50; /* ms */ | 333 | ir->polling = 50; /* ms */ |
286 | break; | 334 | break; |
335 | case BTTV_BOARD_ENLTV_FM_2: | ||
336 | ir_codes = ir_codes_encore_enltv2; | ||
337 | ir->mask_keycode = 0x00fd00; | ||
338 | ir->mask_keyup = 0x000080; | ||
339 | ir->polling = 1; /* ms */ | ||
340 | ir->last_gpio = ir_extract_bits(bttv_gpio_read(&btv->c), | ||
341 | ir->mask_keycode); | ||
342 | break; | ||
287 | } | 343 | } |
288 | if (NULL == ir_codes) { | 344 | if (NULL == ir_codes) { |
289 | dprintk(KERN_INFO "Ooops: IR config error [card=%d]\n", btv->c.type); | 345 | dprintk(KERN_INFO "Ooops: IR config error [card=%d]\n", btv->c.type); |
diff --git a/drivers/media/video/bt8xx/bttv.h b/drivers/media/video/bt8xx/bttv.h index 6d93d16c96e4..46cb90e0985b 100644 --- a/drivers/media/video/bt8xx/bttv.h +++ b/drivers/media/video/bt8xx/bttv.h | |||
@@ -176,7 +176,7 @@ | |||
176 | #define BTTV_BOARD_TYPHOON_TVTUNERPCI 0x95 | 176 | #define BTTV_BOARD_TYPHOON_TVTUNERPCI 0x95 |
177 | #define BTTV_BOARD_GEOVISION_GV600 0x96 | 177 | #define BTTV_BOARD_GEOVISION_GV600 0x96 |
178 | #define BTTV_BOARD_KOZUMI_KTV_01C 0x97 | 178 | #define BTTV_BOARD_KOZUMI_KTV_01C 0x97 |
179 | 179 | #define BTTV_BOARD_ENLTV_FM_2 0x98 | |
180 | 180 | ||
181 | /* more card-specific defines */ | 181 | /* more card-specific defines */ |
182 | #define PT2254_L_CHANNEL 0x10 | 182 | #define PT2254_L_CHANNEL 0x10 |
diff --git a/drivers/media/video/btcx-risc.c b/drivers/media/video/btcx-risc.c index 3324ab38f58c..ac1b2687a20d 100644 --- a/drivers/media/video/btcx-risc.c +++ b/drivers/media/video/btcx-risc.c | |||
@@ -64,7 +64,7 @@ int btcx_riscmem_alloc(struct pci_dev *pci, | |||
64 | unsigned int size) | 64 | unsigned int size) |
65 | { | 65 | { |
66 | __le32 *cpu; | 66 | __le32 *cpu; |
67 | dma_addr_t dma; | 67 | dma_addr_t dma = 0; |
68 | 68 | ||
69 | if (NULL != risc->cpu && risc->size < size) | 69 | if (NULL != risc->cpu && risc->size < size) |
70 | btcx_riscmem_free(pci,risc); | 70 | btcx_riscmem_free(pci,risc); |
diff --git a/drivers/media/video/bw-qcam.c b/drivers/media/video/bw-qcam.c index 6e39e253ce53..ace4ff9ea023 100644 --- a/drivers/media/video/bw-qcam.c +++ b/drivers/media/video/bw-qcam.c | |||
@@ -495,7 +495,7 @@ static void qc_set(struct qcam_device *q) | |||
495 | val2 = (((q->port_mode & QC_MODE_MASK) == QC_BIDIR) ? 24 : 8) * | 495 | val2 = (((q->port_mode & QC_MODE_MASK) == QC_BIDIR) ? 24 : 8) * |
496 | q->transfer_scale; | 496 | q->transfer_scale; |
497 | } | 497 | } |
498 | val = (val + val2 - 1) / val2; | 498 | val = DIV_ROUND_UP(val, val2); |
499 | qc_command(q, 0x13); | 499 | qc_command(q, 0x13); |
500 | qc_command(q, val); | 500 | qc_command(q, val); |
501 | 501 | ||
@@ -651,7 +651,7 @@ static long qc_capture(struct qcam_device * q, char __user *buf, unsigned long l | |||
651 | transperline = q->width * q->bpp; | 651 | transperline = q->width * q->bpp; |
652 | divisor = (((q->port_mode & QC_MODE_MASK) == QC_BIDIR) ? 24 : 8) * | 652 | divisor = (((q->port_mode & QC_MODE_MASK) == QC_BIDIR) ? 24 : 8) * |
653 | q->transfer_scale; | 653 | q->transfer_scale; |
654 | transperline = (transperline + divisor - 1) / divisor; | 654 | transperline = DIV_ROUND_UP(transperline, divisor); |
655 | 655 | ||
656 | for (i = 0, yield = yieldlines; i < linestotrans; i++) | 656 | for (i = 0, yield = yieldlines; i < linestotrans; i++) |
657 | { | 657 | { |
@@ -894,10 +894,27 @@ static ssize_t qcam_read(struct file *file, char __user *buf, | |||
894 | return len; | 894 | return len; |
895 | } | 895 | } |
896 | 896 | ||
897 | static int qcam_exclusive_open(struct inode *inode, struct file *file) | ||
898 | { | ||
899 | struct video_device *dev = video_devdata(file); | ||
900 | struct qcam_device *qcam = (struct qcam_device *)dev; | ||
901 | |||
902 | return test_and_set_bit(0, &qcam->in_use) ? -EBUSY : 0; | ||
903 | } | ||
904 | |||
905 | static int qcam_exclusive_release(struct inode *inode, struct file *file) | ||
906 | { | ||
907 | struct video_device *dev = video_devdata(file); | ||
908 | struct qcam_device *qcam = (struct qcam_device *)dev; | ||
909 | |||
910 | clear_bit(0, &qcam->in_use); | ||
911 | return 0; | ||
912 | } | ||
913 | |||
897 | static const struct file_operations qcam_fops = { | 914 | static const struct file_operations qcam_fops = { |
898 | .owner = THIS_MODULE, | 915 | .owner = THIS_MODULE, |
899 | .open = video_exclusive_open, | 916 | .open = qcam_exclusive_open, |
900 | .release = video_exclusive_release, | 917 | .release = qcam_exclusive_release, |
901 | .ioctl = qcam_ioctl, | 918 | .ioctl = qcam_ioctl, |
902 | #ifdef CONFIG_COMPAT | 919 | #ifdef CONFIG_COMPAT |
903 | .compat_ioctl = v4l_compat_ioctl32, | 920 | .compat_ioctl = v4l_compat_ioctl32, |
@@ -909,6 +926,7 @@ static struct video_device qcam_template= | |||
909 | { | 926 | { |
910 | .name = "Connectix Quickcam", | 927 | .name = "Connectix Quickcam", |
911 | .fops = &qcam_fops, | 928 | .fops = &qcam_fops, |
929 | .release = video_device_release_empty, | ||
912 | }; | 930 | }; |
913 | 931 | ||
914 | #define MAX_CAMS 4 | 932 | #define MAX_CAMS 4 |
diff --git a/drivers/media/video/bw-qcam.h b/drivers/media/video/bw-qcam.h index 6701dafbc0da..8a60c5de0935 100644 --- a/drivers/media/video/bw-qcam.h +++ b/drivers/media/video/bw-qcam.h | |||
@@ -65,4 +65,5 @@ struct qcam_device { | |||
65 | int top, left; | 65 | int top, left; |
66 | int status; | 66 | int status; |
67 | unsigned int saved_bits; | 67 | unsigned int saved_bits; |
68 | unsigned long in_use; | ||
68 | }; | 69 | }; |
diff --git a/drivers/media/video/c-qcam.c b/drivers/media/video/c-qcam.c index 7f6c6b4bec10..17aa0adb3467 100644 --- a/drivers/media/video/c-qcam.c +++ b/drivers/media/video/c-qcam.c | |||
@@ -51,6 +51,7 @@ struct qcam_device { | |||
51 | int contrast, brightness, whitebal; | 51 | int contrast, brightness, whitebal; |
52 | int top, left; | 52 | int top, left; |
53 | unsigned int bidirectional; | 53 | unsigned int bidirectional; |
54 | unsigned long in_use; | ||
54 | struct mutex lock; | 55 | struct mutex lock; |
55 | }; | 56 | }; |
56 | 57 | ||
@@ -687,11 +688,28 @@ static ssize_t qcam_read(struct file *file, char __user *buf, | |||
687 | return len; | 688 | return len; |
688 | } | 689 | } |
689 | 690 | ||
691 | static int qcam_exclusive_open(struct inode *inode, struct file *file) | ||
692 | { | ||
693 | struct video_device *dev = video_devdata(file); | ||
694 | struct qcam_device *qcam = (struct qcam_device *)dev; | ||
695 | |||
696 | return test_and_set_bit(0, &qcam->in_use) ? -EBUSY : 0; | ||
697 | } | ||
698 | |||
699 | static int qcam_exclusive_release(struct inode *inode, struct file *file) | ||
700 | { | ||
701 | struct video_device *dev = video_devdata(file); | ||
702 | struct qcam_device *qcam = (struct qcam_device *)dev; | ||
703 | |||
704 | clear_bit(0, &qcam->in_use); | ||
705 | return 0; | ||
706 | } | ||
707 | |||
690 | /* video device template */ | 708 | /* video device template */ |
691 | static const struct file_operations qcam_fops = { | 709 | static const struct file_operations qcam_fops = { |
692 | .owner = THIS_MODULE, | 710 | .owner = THIS_MODULE, |
693 | .open = video_exclusive_open, | 711 | .open = qcam_exclusive_open, |
694 | .release = video_exclusive_release, | 712 | .release = qcam_exclusive_release, |
695 | .ioctl = qcam_ioctl, | 713 | .ioctl = qcam_ioctl, |
696 | #ifdef CONFIG_COMPAT | 714 | #ifdef CONFIG_COMPAT |
697 | .compat_ioctl = v4l_compat_ioctl32, | 715 | .compat_ioctl = v4l_compat_ioctl32, |
@@ -704,6 +722,7 @@ static struct video_device qcam_template= | |||
704 | { | 722 | { |
705 | .name = "Colour QuickCam", | 723 | .name = "Colour QuickCam", |
706 | .fops = &qcam_fops, | 724 | .fops = &qcam_fops, |
725 | .release = video_device_release_empty, | ||
707 | }; | 726 | }; |
708 | 727 | ||
709 | /* Initialize the QuickCam driver control structure. */ | 728 | /* Initialize the QuickCam driver control structure. */ |
diff --git a/drivers/media/video/cafe_ccic.c b/drivers/media/video/cafe_ccic.c index 08efbe7254ff..fc9497bdd322 100644 --- a/drivers/media/video/cafe_ccic.c +++ b/drivers/media/video/cafe_ccic.c | |||
@@ -1476,9 +1476,12 @@ static int cafe_v4l_open(struct inode *inode, struct file *filp) | |||
1476 | { | 1476 | { |
1477 | struct cafe_camera *cam; | 1477 | struct cafe_camera *cam; |
1478 | 1478 | ||
1479 | lock_kernel(); | ||
1479 | cam = cafe_find_dev(iminor(inode)); | 1480 | cam = cafe_find_dev(iminor(inode)); |
1480 | if (cam == NULL) | 1481 | if (cam == NULL) { |
1482 | unlock_kernel(); | ||
1481 | return -ENODEV; | 1483 | return -ENODEV; |
1484 | } | ||
1482 | filp->private_data = cam; | 1485 | filp->private_data = cam; |
1483 | 1486 | ||
1484 | mutex_lock(&cam->s_mutex); | 1487 | mutex_lock(&cam->s_mutex); |
@@ -1490,6 +1493,7 @@ static int cafe_v4l_open(struct inode *inode, struct file *filp) | |||
1490 | } | 1493 | } |
1491 | (cam->users)++; | 1494 | (cam->users)++; |
1492 | mutex_unlock(&cam->s_mutex); | 1495 | mutex_unlock(&cam->s_mutex); |
1496 | unlock_kernel(); | ||
1493 | return 0; | 1497 | return 0; |
1494 | } | 1498 | } |
1495 | 1499 | ||
diff --git a/drivers/media/video/cpia.c b/drivers/media/video/cpia.c index a661800b0e69..c325e926de8a 100644 --- a/drivers/media/video/cpia.c +++ b/drivers/media/video/cpia.c | |||
@@ -3155,7 +3155,7 @@ static void put_cam(struct cpia_camera_ops* ops) | |||
3155 | static int cpia_open(struct inode *inode, struct file *file) | 3155 | static int cpia_open(struct inode *inode, struct file *file) |
3156 | { | 3156 | { |
3157 | struct video_device *dev = video_devdata(file); | 3157 | struct video_device *dev = video_devdata(file); |
3158 | struct cam_data *cam = dev->priv; | 3158 | struct cam_data *cam = video_get_drvdata(dev); |
3159 | int err; | 3159 | int err; |
3160 | 3160 | ||
3161 | if (!cam) { | 3161 | if (!cam) { |
@@ -3202,7 +3202,7 @@ static int cpia_open(struct inode *inode, struct file *file) | |||
3202 | 3202 | ||
3203 | /* Set ownership of /proc/cpia/videoX to current user */ | 3203 | /* Set ownership of /proc/cpia/videoX to current user */ |
3204 | if(cam->proc_entry) | 3204 | if(cam->proc_entry) |
3205 | cam->proc_entry->uid = current->uid; | 3205 | cam->proc_entry->uid = current_uid(); |
3206 | 3206 | ||
3207 | /* set mark for loading first frame uncompressed */ | 3207 | /* set mark for loading first frame uncompressed */ |
3208 | cam->first_frame = 1; | 3208 | cam->first_frame = 1; |
@@ -3232,7 +3232,7 @@ static int cpia_open(struct inode *inode, struct file *file) | |||
3232 | static int cpia_close(struct inode *inode, struct file *file) | 3232 | static int cpia_close(struct inode *inode, struct file *file) |
3233 | { | 3233 | { |
3234 | struct video_device *dev = file->private_data; | 3234 | struct video_device *dev = file->private_data; |
3235 | struct cam_data *cam = dev->priv; | 3235 | struct cam_data *cam = video_get_drvdata(dev); |
3236 | 3236 | ||
3237 | if (cam->ops) { | 3237 | if (cam->ops) { |
3238 | /* Return ownership of /proc/cpia/videoX to root */ | 3238 | /* Return ownership of /proc/cpia/videoX to root */ |
@@ -3284,7 +3284,7 @@ static ssize_t cpia_read(struct file *file, char __user *buf, | |||
3284 | size_t count, loff_t *ppos) | 3284 | size_t count, loff_t *ppos) |
3285 | { | 3285 | { |
3286 | struct video_device *dev = file->private_data; | 3286 | struct video_device *dev = file->private_data; |
3287 | struct cam_data *cam = dev->priv; | 3287 | struct cam_data *cam = video_get_drvdata(dev); |
3288 | int err; | 3288 | int err; |
3289 | 3289 | ||
3290 | /* make this _really_ smp and multithread-safe */ | 3290 | /* make this _really_ smp and multithread-safe */ |
@@ -3341,7 +3341,7 @@ static int cpia_do_ioctl(struct inode *inode, struct file *file, | |||
3341 | unsigned int ioctlnr, void *arg) | 3341 | unsigned int ioctlnr, void *arg) |
3342 | { | 3342 | { |
3343 | struct video_device *dev = file->private_data; | 3343 | struct video_device *dev = file->private_data; |
3344 | struct cam_data *cam = dev->priv; | 3344 | struct cam_data *cam = video_get_drvdata(dev); |
3345 | int retval = 0; | 3345 | int retval = 0; |
3346 | 3346 | ||
3347 | if (!cam || !cam->ops) | 3347 | if (!cam || !cam->ops) |
@@ -3739,7 +3739,7 @@ static int cpia_mmap(struct file *file, struct vm_area_struct *vma) | |||
3739 | unsigned long start = vma->vm_start; | 3739 | unsigned long start = vma->vm_start; |
3740 | unsigned long size = vma->vm_end - vma->vm_start; | 3740 | unsigned long size = vma->vm_end - vma->vm_start; |
3741 | unsigned long page, pos; | 3741 | unsigned long page, pos; |
3742 | struct cam_data *cam = dev->priv; | 3742 | struct cam_data *cam = video_get_drvdata(dev); |
3743 | int retval; | 3743 | int retval; |
3744 | 3744 | ||
3745 | if (!cam || !cam->ops) | 3745 | if (!cam || !cam->ops) |
@@ -3801,6 +3801,7 @@ static const struct file_operations cpia_fops = { | |||
3801 | static struct video_device cpia_template = { | 3801 | static struct video_device cpia_template = { |
3802 | .name = "CPiA Camera", | 3802 | .name = "CPiA Camera", |
3803 | .fops = &cpia_fops, | 3803 | .fops = &cpia_fops, |
3804 | .release = video_device_release_empty, | ||
3804 | }; | 3805 | }; |
3805 | 3806 | ||
3806 | /* initialise cam_data structure */ | 3807 | /* initialise cam_data structure */ |
@@ -3928,7 +3929,7 @@ static void init_camera_struct(struct cam_data *cam, | |||
3928 | cam->proc_entry = NULL; | 3929 | cam->proc_entry = NULL; |
3929 | 3930 | ||
3930 | memcpy(&cam->vdev, &cpia_template, sizeof(cpia_template)); | 3931 | memcpy(&cam->vdev, &cpia_template, sizeof(cpia_template)); |
3931 | cam->vdev.priv = cam; | 3932 | video_set_drvdata(&cam->vdev, cam); |
3932 | 3933 | ||
3933 | cam->curframe = 0; | 3934 | cam->curframe = 0; |
3934 | for (i = 0; i < FRAME_NUM; i++) { | 3935 | for (i = 0; i < FRAME_NUM; i++) { |
diff --git a/drivers/media/video/cpia2/cpia2_core.c b/drivers/media/video/cpia2/cpia2_core.c index af8b9ec8e358..7e791b6923f9 100644 --- a/drivers/media/video/cpia2/cpia2_core.c +++ b/drivers/media/video/cpia2/cpia2_core.c | |||
@@ -1537,7 +1537,7 @@ static int config_sensor_500(struct camera_data *cam, | |||
1537 | * | 1537 | * |
1538 | * This sets all user changeable properties to the values in cam->params. | 1538 | * This sets all user changeable properties to the values in cam->params. |
1539 | *****************************************************************************/ | 1539 | *****************************************************************************/ |
1540 | int set_all_properties(struct camera_data *cam) | 1540 | static int set_all_properties(struct camera_data *cam) |
1541 | { | 1541 | { |
1542 | /** | 1542 | /** |
1543 | * Don't set target_kb here, it will be set later. | 1543 | * Don't set target_kb here, it will be set later. |
@@ -1588,7 +1588,7 @@ void cpia2_save_camera_state(struct camera_data *cam) | |||
1588 | * get_color_params | 1588 | * get_color_params |
1589 | * | 1589 | * |
1590 | *****************************************************************************/ | 1590 | *****************************************************************************/ |
1591 | void get_color_params(struct camera_data *cam) | 1591 | static void get_color_params(struct camera_data *cam) |
1592 | { | 1592 | { |
1593 | cpia2_do_command(cam, CPIA2_CMD_GET_VP_BRIGHTNESS, TRANSFER_READ, 0); | 1593 | cpia2_do_command(cam, CPIA2_CMD_GET_VP_BRIGHTNESS, TRANSFER_READ, 0); |
1594 | cpia2_do_command(cam, CPIA2_CMD_GET_VP_SATURATION, TRANSFER_READ, 0); | 1594 | cpia2_do_command(cam, CPIA2_CMD_GET_VP_SATURATION, TRANSFER_READ, 0); |
@@ -1881,7 +1881,7 @@ void cpia2_set_saturation(struct camera_data *cam, unsigned char value) | |||
1881 | * wake_system | 1881 | * wake_system |
1882 | * | 1882 | * |
1883 | *****************************************************************************/ | 1883 | *****************************************************************************/ |
1884 | void wake_system(struct camera_data *cam) | 1884 | static void wake_system(struct camera_data *cam) |
1885 | { | 1885 | { |
1886 | cpia2_do_command(cam, CPIA2_CMD_SET_WAKEUP, TRANSFER_WRITE, 0); | 1886 | cpia2_do_command(cam, CPIA2_CMD_SET_WAKEUP, TRANSFER_WRITE, 0); |
1887 | } | 1887 | } |
@@ -1892,7 +1892,7 @@ void wake_system(struct camera_data *cam) | |||
1892 | * | 1892 | * |
1893 | * Valid for STV500 sensor only | 1893 | * Valid for STV500 sensor only |
1894 | *****************************************************************************/ | 1894 | *****************************************************************************/ |
1895 | void set_lowlight_boost(struct camera_data *cam) | 1895 | static void set_lowlight_boost(struct camera_data *cam) |
1896 | { | 1896 | { |
1897 | struct cpia2_command cmd; | 1897 | struct cpia2_command cmd; |
1898 | 1898 | ||
@@ -2169,7 +2169,7 @@ void cpia2_dbg_dump_registers(struct camera_data *cam) | |||
2169 | * | 2169 | * |
2170 | * Sets all values to the defaults | 2170 | * Sets all values to the defaults |
2171 | *****************************************************************************/ | 2171 | *****************************************************************************/ |
2172 | void reset_camera_struct(struct camera_data *cam) | 2172 | static void reset_camera_struct(struct camera_data *cam) |
2173 | { | 2173 | { |
2174 | /*** | 2174 | /*** |
2175 | * The following parameter values are the defaults from the register map. | 2175 | * The following parameter values are the defaults from the register map. |
diff --git a/drivers/media/video/cpia2/cpia2_usb.c b/drivers/media/video/cpia2/cpia2_usb.c index a8a199047cbd..73511a542077 100644 --- a/drivers/media/video/cpia2/cpia2_usb.c +++ b/drivers/media/video/cpia2/cpia2_usb.c | |||
@@ -478,7 +478,7 @@ int cpia2_usb_change_streaming_alternate(struct camera_data *cam, | |||
478 | * set_alternate | 478 | * set_alternate |
479 | * | 479 | * |
480 | *****************************************************************************/ | 480 | *****************************************************************************/ |
481 | int set_alternate(struct camera_data *cam, unsigned int alt) | 481 | static int set_alternate(struct camera_data *cam, unsigned int alt) |
482 | { | 482 | { |
483 | int ret = 0; | 483 | int ret = 0; |
484 | 484 | ||
diff --git a/drivers/media/video/cpia2/cpia2_v4l.c b/drivers/media/video/cpia2/cpia2_v4l.c index eb9f15cd4c45..897e8d1a5c3c 100644 --- a/drivers/media/video/cpia2/cpia2_v4l.c +++ b/drivers/media/video/cpia2/cpia2_v4l.c | |||
@@ -241,8 +241,7 @@ static struct v4l2_queryctrl controls[] = { | |||
241 | *****************************************************************************/ | 241 | *****************************************************************************/ |
242 | static int cpia2_open(struct inode *inode, struct file *file) | 242 | static int cpia2_open(struct inode *inode, struct file *file) |
243 | { | 243 | { |
244 | struct video_device *dev = video_devdata(file); | 244 | struct camera_data *cam = video_drvdata(file); |
245 | struct camera_data *cam = video_get_drvdata(dev); | ||
246 | int retval = 0; | 245 | int retval = 0; |
247 | 246 | ||
248 | if (!cam) { | 247 | if (!cam) { |
@@ -357,8 +356,7 @@ static int cpia2_close(struct inode *inode, struct file *file) | |||
357 | static ssize_t cpia2_v4l_read(struct file *file, char __user *buf, size_t count, | 356 | static ssize_t cpia2_v4l_read(struct file *file, char __user *buf, size_t count, |
358 | loff_t *off) | 357 | loff_t *off) |
359 | { | 358 | { |
360 | struct video_device *dev = video_devdata(file); | 359 | struct camera_data *cam = video_drvdata(file); |
361 | struct camera_data *cam = video_get_drvdata(dev); | ||
362 | int noblock = file->f_flags&O_NONBLOCK; | 360 | int noblock = file->f_flags&O_NONBLOCK; |
363 | 361 | ||
364 | struct cpia2_fh *fh = file->private_data; | 362 | struct cpia2_fh *fh = file->private_data; |
@@ -382,9 +380,7 @@ static ssize_t cpia2_v4l_read(struct file *file, char __user *buf, size_t count, | |||
382 | *****************************************************************************/ | 380 | *****************************************************************************/ |
383 | static unsigned int cpia2_v4l_poll(struct file *filp, struct poll_table_struct *wait) | 381 | static unsigned int cpia2_v4l_poll(struct file *filp, struct poll_table_struct *wait) |
384 | { | 382 | { |
385 | struct video_device *dev = video_devdata(filp); | 383 | struct camera_data *cam = video_drvdata(filp); |
386 | struct camera_data *cam = video_get_drvdata(dev); | ||
387 | |||
388 | struct cpia2_fh *fh = filp->private_data; | 384 | struct cpia2_fh *fh = filp->private_data; |
389 | 385 | ||
390 | if(!cam) | 386 | if(!cam) |
@@ -1579,8 +1575,7 @@ static int ioctl_dqbuf(void *arg,struct camera_data *cam, struct file *file) | |||
1579 | static int cpia2_do_ioctl(struct inode *inode, struct file *file, | 1575 | static int cpia2_do_ioctl(struct inode *inode, struct file *file, |
1580 | unsigned int ioctl_nr, void *arg) | 1576 | unsigned int ioctl_nr, void *arg) |
1581 | { | 1577 | { |
1582 | struct video_device *dev = video_devdata(file); | 1578 | struct camera_data *cam = video_drvdata(file); |
1583 | struct camera_data *cam = video_get_drvdata(dev); | ||
1584 | int retval = 0; | 1579 | int retval = 0; |
1585 | 1580 | ||
1586 | if (!cam) | 1581 | if (!cam) |
@@ -1860,9 +1855,8 @@ static int cpia2_ioctl(struct inode *inode, struct file *file, | |||
1860 | *****************************************************************************/ | 1855 | *****************************************************************************/ |
1861 | static int cpia2_mmap(struct file *file, struct vm_area_struct *area) | 1856 | static int cpia2_mmap(struct file *file, struct vm_area_struct *area) |
1862 | { | 1857 | { |
1858 | struct camera_data *cam = video_drvdata(file); | ||
1863 | int retval; | 1859 | int retval; |
1864 | struct video_device *dev = video_devdata(file); | ||
1865 | struct camera_data *cam = video_get_drvdata(dev); | ||
1866 | 1860 | ||
1867 | /* Priority check */ | 1861 | /* Priority check */ |
1868 | struct cpia2_fh *fh = file->private_data; | 1862 | struct cpia2_fh *fh = file->private_data; |
diff --git a/drivers/media/video/cx18/Makefile b/drivers/media/video/cx18/Makefile index b23d2e26120f..f7bf0edf93f9 100644 --- a/drivers/media/video/cx18/Makefile +++ b/drivers/media/video/cx18/Makefile | |||
@@ -2,7 +2,7 @@ cx18-objs := cx18-driver.o cx18-cards.o cx18-i2c.o cx18-firmware.o cx18-gpio. | |||
2 | cx18-queue.o cx18-streams.o cx18-fileops.o cx18-ioctl.o cx18-controls.o \ | 2 | cx18-queue.o cx18-streams.o cx18-fileops.o cx18-ioctl.o cx18-controls.o \ |
3 | cx18-mailbox.o cx18-vbi.o cx18-audio.o cx18-video.o cx18-irq.o \ | 3 | cx18-mailbox.o cx18-vbi.o cx18-audio.o cx18-video.o cx18-irq.o \ |
4 | cx18-av-core.o cx18-av-audio.o cx18-av-firmware.o cx18-av-vbi.o cx18-scb.o \ | 4 | cx18-av-core.o cx18-av-audio.o cx18-av-firmware.o cx18-av-vbi.o cx18-scb.o \ |
5 | cx18-dvb.o | 5 | cx18-dvb.o cx18-io.o |
6 | 6 | ||
7 | obj-$(CONFIG_VIDEO_CX18) += cx18.o | 7 | obj-$(CONFIG_VIDEO_CX18) += cx18.o |
8 | 8 | ||
diff --git a/drivers/media/video/cx18/cx18-audio.c b/drivers/media/video/cx18/cx18-audio.c index 6d5b94fc7087..57beddf0af4d 100644 --- a/drivers/media/video/cx18/cx18-audio.c +++ b/drivers/media/video/cx18/cx18-audio.c | |||
@@ -22,6 +22,7 @@ | |||
22 | */ | 22 | */ |
23 | 23 | ||
24 | #include "cx18-driver.h" | 24 | #include "cx18-driver.h" |
25 | #include "cx18-io.h" | ||
25 | #include "cx18-i2c.h" | 26 | #include "cx18-i2c.h" |
26 | #include "cx18-cards.h" | 27 | #include "cx18-cards.h" |
27 | #include "cx18-audio.h" | 28 | #include "cx18-audio.h" |
@@ -60,10 +61,10 @@ int cx18_audio_set_io(struct cx18 *cx) | |||
60 | if (err) | 61 | if (err) |
61 | return err; | 62 | return err; |
62 | 63 | ||
63 | val = read_reg(CX18_AUDIO_ENABLE) & ~0x30; | 64 | val = cx18_read_reg(cx, CX18_AUDIO_ENABLE) & ~0x30; |
64 | val |= (audio_input > CX18_AV_AUDIO_SERIAL2) ? 0x20 : | 65 | val |= (audio_input > CX18_AV_AUDIO_SERIAL2) ? 0x20 : |
65 | (audio_input << 4); | 66 | (audio_input << 4); |
66 | write_reg(val | 0xb00, CX18_AUDIO_ENABLE); | 67 | cx18_write_reg(cx, val | 0xb00, CX18_AUDIO_ENABLE); |
67 | cx18_vapi(cx, CX18_APU_RESETAI, 1, 0); | 68 | cx18_vapi(cx, CX18_APU_RESETAI, 1, 0); |
68 | return 0; | 69 | return 0; |
69 | } | 70 | } |
diff --git a/drivers/media/video/cx18/cx18-av-core.c b/drivers/media/video/cx18/cx18-av-core.c index 3b0a2c450605..73f5141a42d1 100644 --- a/drivers/media/video/cx18/cx18-av-core.c +++ b/drivers/media/video/cx18/cx18-av-core.c | |||
@@ -22,27 +22,35 @@ | |||
22 | */ | 22 | */ |
23 | 23 | ||
24 | #include "cx18-driver.h" | 24 | #include "cx18-driver.h" |
25 | #include "cx18-io.h" | ||
25 | 26 | ||
26 | int cx18_av_write(struct cx18 *cx, u16 addr, u8 value) | 27 | int cx18_av_write(struct cx18 *cx, u16 addr, u8 value) |
27 | { | 28 | { |
28 | u32 x = readl(cx->reg_mem + 0xc40000 + (addr & ~3)); | 29 | u32 reg = 0xc40000 + (addr & ~3); |
29 | u32 mask = 0xff; | 30 | u32 mask = 0xff; |
30 | int shift = (addr & 3) * 8; | 31 | int shift = (addr & 3) * 8; |
32 | u32 x = cx18_read_reg(cx, reg); | ||
31 | 33 | ||
32 | x = (x & ~(mask << shift)) | ((u32)value << shift); | 34 | x = (x & ~(mask << shift)) | ((u32)value << shift); |
33 | writel(x, cx->reg_mem + 0xc40000 + (addr & ~3)); | 35 | cx18_write_reg(cx, x, reg); |
34 | return 0; | 36 | return 0; |
35 | } | 37 | } |
36 | 38 | ||
37 | int cx18_av_write4(struct cx18 *cx, u16 addr, u32 value) | 39 | int cx18_av_write4(struct cx18 *cx, u16 addr, u32 value) |
38 | { | 40 | { |
39 | writel(value, cx->reg_mem + 0xc40000 + addr); | 41 | cx18_write_reg(cx, value, 0xc40000 + addr); |
42 | return 0; | ||
43 | } | ||
44 | |||
45 | int cx18_av_write4_noretry(struct cx18 *cx, u16 addr, u32 value) | ||
46 | { | ||
47 | cx18_write_reg_noretry(cx, value, 0xc40000 + addr); | ||
40 | return 0; | 48 | return 0; |
41 | } | 49 | } |
42 | 50 | ||
43 | u8 cx18_av_read(struct cx18 *cx, u16 addr) | 51 | u8 cx18_av_read(struct cx18 *cx, u16 addr) |
44 | { | 52 | { |
45 | u32 x = readl(cx->reg_mem + 0xc40000 + (addr & ~3)); | 53 | u32 x = cx18_read_reg(cx, 0xc40000 + (addr & ~3)); |
46 | int shift = (addr & 3) * 8; | 54 | int shift = (addr & 3) * 8; |
47 | 55 | ||
48 | return (x >> shift) & 0xff; | 56 | return (x >> shift) & 0xff; |
@@ -50,7 +58,12 @@ u8 cx18_av_read(struct cx18 *cx, u16 addr) | |||
50 | 58 | ||
51 | u32 cx18_av_read4(struct cx18 *cx, u16 addr) | 59 | u32 cx18_av_read4(struct cx18 *cx, u16 addr) |
52 | { | 60 | { |
53 | return readl(cx->reg_mem + 0xc40000 + addr); | 61 | return cx18_read_reg(cx, 0xc40000 + addr); |
62 | } | ||
63 | |||
64 | u32 cx18_av_read4_noretry(struct cx18 *cx, u16 addr) | ||
65 | { | ||
66 | return cx18_read_reg_noretry(cx, 0xc40000 + addr); | ||
54 | } | 67 | } |
55 | 68 | ||
56 | int cx18_av_and_or(struct cx18 *cx, u16 addr, unsigned and_mask, | 69 | int cx18_av_and_or(struct cx18 *cx, u16 addr, unsigned and_mask, |
diff --git a/drivers/media/video/cx18/cx18-av-core.h b/drivers/media/video/cx18/cx18-av-core.h index eb61fa1e0965..b67d8df20cc6 100644 --- a/drivers/media/video/cx18/cx18-av-core.h +++ b/drivers/media/video/cx18/cx18-av-core.h | |||
@@ -301,8 +301,10 @@ struct cx18_av_state { | |||
301 | /* cx18_av-core.c */ | 301 | /* cx18_av-core.c */ |
302 | int cx18_av_write(struct cx18 *cx, u16 addr, u8 value); | 302 | int cx18_av_write(struct cx18 *cx, u16 addr, u8 value); |
303 | int cx18_av_write4(struct cx18 *cx, u16 addr, u32 value); | 303 | int cx18_av_write4(struct cx18 *cx, u16 addr, u32 value); |
304 | int cx18_av_write4_noretry(struct cx18 *cx, u16 addr, u32 value); | ||
304 | u8 cx18_av_read(struct cx18 *cx, u16 addr); | 305 | u8 cx18_av_read(struct cx18 *cx, u16 addr); |
305 | u32 cx18_av_read4(struct cx18 *cx, u16 addr); | 306 | u32 cx18_av_read4(struct cx18 *cx, u16 addr); |
307 | u32 cx18_av_read4_noretry(struct cx18 *cx, u16 addr); | ||
306 | int cx18_av_and_or(struct cx18 *cx, u16 addr, unsigned mask, u8 value); | 308 | int cx18_av_and_or(struct cx18 *cx, u16 addr, unsigned mask, u8 value); |
307 | int cx18_av_and_or4(struct cx18 *cx, u16 addr, u32 mask, u32 value); | 309 | int cx18_av_and_or4(struct cx18 *cx, u16 addr, u32 mask, u32 value); |
308 | int cx18_av_cmd(struct cx18 *cx, unsigned int cmd, void *arg); | 310 | int cx18_av_cmd(struct cx18 *cx, unsigned int cmd, void *arg); |
diff --git a/drivers/media/video/cx18/cx18-av-firmware.c b/drivers/media/video/cx18/cx18-av-firmware.c index e996a4e3123a..522a035b2e8f 100644 --- a/drivers/media/video/cx18/cx18-av-firmware.c +++ b/drivers/media/video/cx18/cx18-av-firmware.c | |||
@@ -20,6 +20,7 @@ | |||
20 | */ | 20 | */ |
21 | 21 | ||
22 | #include "cx18-driver.h" | 22 | #include "cx18-driver.h" |
23 | #include "cx18-io.h" | ||
23 | #include <linux/firmware.h> | 24 | #include <linux/firmware.h> |
24 | 25 | ||
25 | #define CX18_AUDIO_ENABLE 0xc72014 | 26 | #define CX18_AUDIO_ENABLE 0xc72014 |
@@ -49,7 +50,7 @@ int cx18_av_loadfw(struct cx18 *cx) | |||
49 | cx18_av_write4(cx, 0x8100, 0x00010000); | 50 | cx18_av_write4(cx, 0x8100, 0x00010000); |
50 | 51 | ||
51 | /* Put the 8051 in reset and enable firmware upload */ | 52 | /* Put the 8051 in reset and enable firmware upload */ |
52 | cx18_av_write4(cx, CXADEC_DL_CTL, 0x0F000000); | 53 | cx18_av_write4_noretry(cx, CXADEC_DL_CTL, 0x0F000000); |
53 | 54 | ||
54 | ptr = fw->data; | 55 | ptr = fw->data; |
55 | size = fw->size; | 56 | size = fw->size; |
@@ -58,22 +59,28 @@ int cx18_av_loadfw(struct cx18 *cx) | |||
58 | u32 dl_control = 0x0F000000 | i | ((u32)ptr[i] << 16); | 59 | u32 dl_control = 0x0F000000 | i | ((u32)ptr[i] << 16); |
59 | u32 value = 0; | 60 | u32 value = 0; |
60 | int retries2; | 61 | int retries2; |
62 | int unrec_err = 0; | ||
61 | 63 | ||
62 | for (retries2 = 0; retries2 < 5; retries2++) { | 64 | for (retries2 = 0; retries2 < CX18_MAX_MMIO_RETRIES; |
63 | cx18_av_write4(cx, CXADEC_DL_CTL, dl_control); | 65 | retries2++) { |
66 | cx18_av_write4_noretry(cx, CXADEC_DL_CTL, | ||
67 | dl_control); | ||
64 | udelay(10); | 68 | udelay(10); |
65 | value = cx18_av_read4(cx, CXADEC_DL_CTL); | 69 | value = cx18_av_read4_noretry(cx, |
70 | CXADEC_DL_CTL); | ||
66 | if (value == dl_control) | 71 | if (value == dl_control) |
67 | break; | 72 | break; |
68 | /* Check if we can correct the byte by changing | 73 | /* Check if we can correct the byte by changing |
69 | the address. We can only write the lower | 74 | the address. We can only write the lower |
70 | address byte of the address. */ | 75 | address byte of the address. */ |
71 | if ((value & 0x3F00) != (dl_control & 0x3F00)) { | 76 | if ((value & 0x3F00) != (dl_control & 0x3F00)) { |
72 | retries2 = 5; | 77 | unrec_err = 1; |
73 | break; | 78 | break; |
74 | } | 79 | } |
75 | } | 80 | } |
76 | if (retries2 >= 5) | 81 | cx18_log_write_retries(cx, retries2, |
82 | cx->reg_mem + 0xc40000 + CXADEC_DL_CTL); | ||
83 | if (unrec_err || retries2 >= CX18_MAX_MMIO_RETRIES) | ||
77 | break; | 84 | break; |
78 | } | 85 | } |
79 | if (i == size) | 86 | if (i == size) |
@@ -119,10 +126,10 @@ int cx18_av_loadfw(struct cx18 *cx) | |||
119 | have a name in the spec. */ | 126 | have a name in the spec. */ |
120 | cx18_av_write4(cx, 0x09CC, 1); | 127 | cx18_av_write4(cx, 0x09CC, 1); |
121 | 128 | ||
122 | v = read_reg(CX18_AUDIO_ENABLE); | 129 | v = cx18_read_reg(cx, CX18_AUDIO_ENABLE); |
123 | /* If bit 11 is 1 */ | 130 | /* If bit 11 is 1, clear bit 10 */ |
124 | if (v & 0x800) | 131 | if (v & 0x800) |
125 | write_reg(v & 0xFFFFFBFF, CX18_AUDIO_ENABLE); /* Clear bit 10 */ | 132 | cx18_write_reg(cx, v & 0xFFFFFBFF, CX18_AUDIO_ENABLE); |
126 | 133 | ||
127 | /* Enable WW auto audio standard detection */ | 134 | /* Enable WW auto audio standard detection */ |
128 | v = cx18_av_read4(cx, CXADEC_STD_DET_CTL); | 135 | v = cx18_av_read4(cx, CXADEC_STD_DET_CTL); |
diff --git a/drivers/media/video/cx18/cx18-cards.c b/drivers/media/video/cx18/cx18-cards.c index 3cb9734ec07b..5efe01ebe9db 100644 --- a/drivers/media/video/cx18/cx18-cards.c +++ b/drivers/media/video/cx18/cx18-cards.c | |||
@@ -292,12 +292,111 @@ static const struct cx18_card cx18_card_cnxt_raptor_pal = { | |||
292 | 292 | ||
293 | /* ------------------------------------------------------------------------- */ | 293 | /* ------------------------------------------------------------------------- */ |
294 | 294 | ||
295 | /* Toshiba Qosmio laptop internal DVB-T/Analog Hybrid Tuner */ | ||
296 | |||
297 | static const struct cx18_card_pci_info cx18_pci_toshiba_qosmio_dvbt[] = { | ||
298 | { PCI_DEVICE_ID_CX23418, CX18_PCI_ID_TOSHIBA, 0x0110 }, | ||
299 | { 0, 0, 0 } | ||
300 | }; | ||
301 | |||
302 | static const struct cx18_card cx18_card_toshiba_qosmio_dvbt = { | ||
303 | .type = CX18_CARD_TOSHIBA_QOSMIO_DVBT, | ||
304 | .name = "Toshiba Qosmio DVB-T/Analog", | ||
305 | .comment = "Experimenters and photos needed for device to work well.\n" | ||
306 | "\tTo help, mail the ivtv-devel list (www.ivtvdriver.org).\n", | ||
307 | .v4l2_capabilities = CX18_CAP_ENCODER, | ||
308 | .hw_audio_ctrl = CX18_HW_CX23418, | ||
309 | .hw_all = CX18_HW_TUNER, | ||
310 | .video_inputs = { | ||
311 | { CX18_CARD_INPUT_VID_TUNER, 0, CX18_AV_COMPOSITE6 }, | ||
312 | { CX18_CARD_INPUT_SVIDEO1, 1, | ||
313 | CX18_AV_SVIDEO_LUMA3 | CX18_AV_SVIDEO_CHROMA4 }, | ||
314 | { CX18_CARD_INPUT_COMPOSITE1, 1, CX18_AV_COMPOSITE1 }, | ||
315 | }, | ||
316 | .audio_inputs = { | ||
317 | { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO5, 0 }, | ||
318 | { CX18_CARD_INPUT_LINE_IN1, CX18_AV_AUDIO_SERIAL1, 1 }, | ||
319 | }, | ||
320 | .tuners = { | ||
321 | { .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 }, | ||
322 | }, | ||
323 | .ddr = { | ||
324 | .chip_config = 0x202, | ||
325 | .refresh = 0x3bb, | ||
326 | .timing1 = 0x33320a63, | ||
327 | .timing2 = 0x0a, | ||
328 | .tune_lane = 0, | ||
329 | .initial_emrs = 0x42, | ||
330 | }, | ||
331 | .xceive_pin = 15, | ||
332 | .pci_list = cx18_pci_toshiba_qosmio_dvbt, | ||
333 | .i2c = &cx18_i2c_std, | ||
334 | }; | ||
335 | |||
336 | /* ------------------------------------------------------------------------- */ | ||
337 | |||
338 | /* Leadtek WinFast PVR2100 */ | ||
339 | |||
340 | static const struct cx18_card_pci_info cx18_pci_leadtek_pvr2100[] = { | ||
341 | { PCI_DEVICE_ID_CX23418, CX18_PCI_ID_LEADTEK, 0x6f27 }, | ||
342 | { 0, 0, 0 } | ||
343 | }; | ||
344 | |||
345 | static const struct cx18_card cx18_card_leadtek_pvr2100 = { | ||
346 | .type = CX18_CARD_LEADTEK_PVR2100, | ||
347 | .name = "Leadtek WinFast PVR2100", | ||
348 | .comment = "Experimenters and photos needed for device to work well.\n" | ||
349 | "\tTo help, mail the ivtv-devel list (www.ivtvdriver.org).\n", | ||
350 | .v4l2_capabilities = CX18_CAP_ENCODER, | ||
351 | .hw_audio_ctrl = CX18_HW_CX23418, | ||
352 | .hw_muxer = CX18_HW_GPIO, | ||
353 | .hw_all = CX18_HW_TUNER | CX18_HW_GPIO, | ||
354 | .video_inputs = { | ||
355 | { CX18_CARD_INPUT_VID_TUNER, 0, CX18_AV_COMPOSITE2 }, | ||
356 | { CX18_CARD_INPUT_SVIDEO1, 1, | ||
357 | CX18_AV_SVIDEO_LUMA3 | CX18_AV_SVIDEO_CHROMA4 }, | ||
358 | { CX18_CARD_INPUT_COMPOSITE1, 1, CX18_AV_COMPOSITE7 }, | ||
359 | }, | ||
360 | .audio_inputs = { | ||
361 | { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO5, 0 }, | ||
362 | { CX18_CARD_INPUT_LINE_IN1, CX18_AV_AUDIO_SERIAL1, 1 }, | ||
363 | }, | ||
364 | .tuners = { | ||
365 | /* XC3028 tuner */ | ||
366 | { .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 }, | ||
367 | }, | ||
368 | .radio_input = { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO5, 2 }, | ||
369 | .ddr = { | ||
370 | /* | ||
371 | * Pointer to proper DDR config values provided by | ||
372 | * Terry Wu <terrywu at leadtek.com.tw> | ||
373 | */ | ||
374 | .chip_config = 0x303, | ||
375 | .refresh = 0x3bb, | ||
376 | .timing1 = 0x24220e83, | ||
377 | .timing2 = 0x1f, | ||
378 | .tune_lane = 0, | ||
379 | .initial_emrs = 0x2, | ||
380 | }, | ||
381 | .gpio_init.initial_value = 0x6, | ||
382 | .gpio_init.direction = 0x7, | ||
383 | .gpio_audio_input = { .mask = 0x7, | ||
384 | .tuner = 0x6, .linein = 0x2, .radio = 0x2 }, | ||
385 | .xceive_pin = 15, | ||
386 | .pci_list = cx18_pci_leadtek_pvr2100, | ||
387 | .i2c = &cx18_i2c_std, | ||
388 | }; | ||
389 | |||
390 | /* ------------------------------------------------------------------------- */ | ||
391 | |||
295 | static const struct cx18_card *cx18_card_list[] = { | 392 | static const struct cx18_card *cx18_card_list[] = { |
296 | &cx18_card_hvr1600_esmt, | 393 | &cx18_card_hvr1600_esmt, |
297 | &cx18_card_hvr1600_samsung, | 394 | &cx18_card_hvr1600_samsung, |
298 | &cx18_card_h900, | 395 | &cx18_card_h900, |
299 | &cx18_card_mpc718, | 396 | &cx18_card_mpc718, |
300 | &cx18_card_cnxt_raptor_pal, | 397 | &cx18_card_cnxt_raptor_pal, |
398 | &cx18_card_toshiba_qosmio_dvbt, | ||
399 | &cx18_card_leadtek_pvr2100, | ||
301 | }; | 400 | }; |
302 | 401 | ||
303 | const struct cx18_card *cx18_get_card(u16 index) | 402 | const struct cx18_card *cx18_get_card(u16 index) |
diff --git a/drivers/media/video/cx18/cx18-driver.c b/drivers/media/video/cx18/cx18-driver.c index bd18afebbf86..085121c2b47f 100644 --- a/drivers/media/video/cx18/cx18-driver.c +++ b/drivers/media/video/cx18/cx18-driver.c | |||
@@ -4,6 +4,7 @@ | |||
4 | * Derived from ivtv-driver.c | 4 | * Derived from ivtv-driver.c |
5 | * | 5 | * |
6 | * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> | 6 | * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> |
7 | * Copyright (C) 2008 Andy Walls <awalls@radix.net> | ||
7 | * | 8 | * |
8 | * This program is free software; you can redistribute it and/or modify | 9 | * This program is free software; you can redistribute it and/or modify |
9 | * it under the terms of the GNU General Public License as published by | 10 | * it under the terms of the GNU General Public License as published by |
@@ -22,6 +23,7 @@ | |||
22 | */ | 23 | */ |
23 | 24 | ||
24 | #include "cx18-driver.h" | 25 | #include "cx18-driver.h" |
26 | #include "cx18-io.h" | ||
25 | #include "cx18-version.h" | 27 | #include "cx18-version.h" |
26 | #include "cx18-cards.h" | 28 | #include "cx18-cards.h" |
27 | #include "cx18-i2c.h" | 29 | #include "cx18-i2c.h" |
@@ -73,10 +75,14 @@ static int radio[CX18_MAX_CARDS] = { -1, -1, -1, -1, -1, -1, -1, -1, | |||
73 | -1, -1, -1, -1, -1, -1, -1, -1, | 75 | -1, -1, -1, -1, -1, -1, -1, -1, |
74 | -1, -1, -1, -1, -1, -1, -1, -1, | 76 | -1, -1, -1, -1, -1, -1, -1, -1, |
75 | -1, -1, -1, -1, -1, -1, -1, -1 }; | 77 | -1, -1, -1, -1, -1, -1, -1, -1 }; |
76 | 78 | static int mmio_ndelay[CX18_MAX_CARDS] = { -1, -1, -1, -1, -1, -1, -1, -1, | |
79 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
80 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
81 | -1, -1, -1, -1, -1, -1, -1, -1 }; | ||
77 | static unsigned cardtype_c = 1; | 82 | static unsigned cardtype_c = 1; |
78 | static unsigned tuner_c = 1; | 83 | static unsigned tuner_c = 1; |
79 | static unsigned radio_c = 1; | 84 | static unsigned radio_c = 1; |
85 | static unsigned mmio_ndelay_c = 1; | ||
80 | static char pal[] = "--"; | 86 | static char pal[] = "--"; |
81 | static char secam[] = "--"; | 87 | static char secam[] = "--"; |
82 | static char ntsc[] = "-"; | 88 | static char ntsc[] = "-"; |
@@ -90,15 +96,18 @@ static int enc_pcm_buffers = CX18_DEFAULT_ENC_PCM_BUFFERS; | |||
90 | 96 | ||
91 | static int cx18_pci_latency = 1; | 97 | static int cx18_pci_latency = 1; |
92 | 98 | ||
99 | int cx18_retry_mmio = 1; | ||
93 | int cx18_debug; | 100 | int cx18_debug; |
94 | 101 | ||
95 | module_param_array(tuner, int, &tuner_c, 0644); | 102 | module_param_array(tuner, int, &tuner_c, 0644); |
96 | module_param_array(radio, bool, &radio_c, 0644); | 103 | module_param_array(radio, bool, &radio_c, 0644); |
97 | module_param_array(cardtype, int, &cardtype_c, 0644); | 104 | module_param_array(cardtype, int, &cardtype_c, 0644); |
105 | module_param_array(mmio_ndelay, int, &mmio_ndelay_c, 0644); | ||
98 | module_param_string(pal, pal, sizeof(pal), 0644); | 106 | module_param_string(pal, pal, sizeof(pal), 0644); |
99 | module_param_string(secam, secam, sizeof(secam), 0644); | 107 | module_param_string(secam, secam, sizeof(secam), 0644); |
100 | module_param_string(ntsc, ntsc, sizeof(ntsc), 0644); | 108 | module_param_string(ntsc, ntsc, sizeof(ntsc), 0644); |
101 | module_param_named(debug, cx18_debug, int, 0644); | 109 | module_param_named(debug, cx18_debug, int, 0644); |
110 | module_param_named(retry_mmio, cx18_retry_mmio, int, 0644); | ||
102 | module_param(cx18_pci_latency, int, 0644); | 111 | module_param(cx18_pci_latency, int, 0644); |
103 | module_param(cx18_first_minor, int, 0644); | 112 | module_param(cx18_first_minor, int, 0644); |
104 | 113 | ||
@@ -121,6 +130,8 @@ MODULE_PARM_DESC(cardtype, | |||
121 | "\t\t\t 3 = Compro VideoMate H900\n" | 130 | "\t\t\t 3 = Compro VideoMate H900\n" |
122 | "\t\t\t 4 = Yuan MPC718\n" | 131 | "\t\t\t 4 = Yuan MPC718\n" |
123 | "\t\t\t 5 = Conexant Raptor PAL/SECAM\n" | 132 | "\t\t\t 5 = Conexant Raptor PAL/SECAM\n" |
133 | "\t\t\t 6 = Toshiba Qosmio DVB-T/Analog\n" | ||
134 | "\t\t\t 7 = Leadtek WinFast PVR2100\n" | ||
124 | "\t\t\t 0 = Autodetect (default)\n" | 135 | "\t\t\t 0 = Autodetect (default)\n" |
125 | "\t\t\t-1 = Ignore this card\n\t\t"); | 136 | "\t\t\t-1 = Ignore this card\n\t\t"); |
126 | MODULE_PARM_DESC(pal, "Set PAL standard: B, G, H, D, K, I, M, N, Nc, 60"); | 137 | MODULE_PARM_DESC(pal, "Set PAL standard: B, G, H, D, K, I, M, N, Nc, 60"); |
@@ -140,6 +151,14 @@ MODULE_PARM_DESC(debug, | |||
140 | MODULE_PARM_DESC(cx18_pci_latency, | 151 | MODULE_PARM_DESC(cx18_pci_latency, |
141 | "Change the PCI latency to 64 if lower: 0 = No, 1 = Yes,\n" | 152 | "Change the PCI latency to 64 if lower: 0 = No, 1 = Yes,\n" |
142 | "\t\t\tDefault: Yes"); | 153 | "\t\t\tDefault: Yes"); |
154 | MODULE_PARM_DESC(retry_mmio, | ||
155 | "Check and retry memory mapped IO accesses\n" | ||
156 | "\t\t\tDefault: 1 [Yes]"); | ||
157 | MODULE_PARM_DESC(mmio_ndelay, | ||
158 | "Delay (ns) for each CX23418 memory mapped IO access.\n" | ||
159 | "\t\t\tTry larger values that are close to a multiple of the\n" | ||
160 | "\t\t\tPCI clock period, 30.3 ns, if your card doesn't work.\n" | ||
161 | "\t\t\tDefault: " __stringify(CX18_DEFAULT_MMIO_NDELAY)); | ||
143 | MODULE_PARM_DESC(enc_mpg_buffers, | 162 | MODULE_PARM_DESC(enc_mpg_buffers, |
144 | "Encoder MPG Buffers (in MB)\n" | 163 | "Encoder MPG Buffers (in MB)\n" |
145 | "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_MPG_BUFFERS)); | 164 | "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_MPG_BUFFERS)); |
@@ -156,7 +175,7 @@ MODULE_PARM_DESC(enc_pcm_buffers, | |||
156 | "Encoder PCM buffers (in MB)\n" | 175 | "Encoder PCM buffers (in MB)\n" |
157 | "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_PCM_BUFFERS)); | 176 | "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_PCM_BUFFERS)); |
158 | 177 | ||
159 | MODULE_PARM_DESC(cx18_first_minor, "Set minor assigned to first card"); | 178 | MODULE_PARM_DESC(cx18_first_minor, "Set kernel number assigned to first card"); |
160 | 179 | ||
161 | MODULE_AUTHOR("Hans Verkuil"); | 180 | MODULE_AUTHOR("Hans Verkuil"); |
162 | MODULE_DESCRIPTION("CX23418 driver"); | 181 | MODULE_DESCRIPTION("CX23418 driver"); |
@@ -356,6 +375,11 @@ static void cx18_process_options(struct cx18 *cx) | |||
356 | cx->options.tuner = tuner[cx->num]; | 375 | cx->options.tuner = tuner[cx->num]; |
357 | cx->options.radio = radio[cx->num]; | 376 | cx->options.radio = radio[cx->num]; |
358 | 377 | ||
378 | if (mmio_ndelay[cx->num] < 0) | ||
379 | cx->options.mmio_ndelay = CX18_DEFAULT_MMIO_NDELAY; | ||
380 | else | ||
381 | cx->options.mmio_ndelay = mmio_ndelay[cx->num]; | ||
382 | |||
359 | cx->std = cx18_parse_std(cx); | 383 | cx->std = cx18_parse_std(cx); |
360 | if (cx->options.cardtype == -1) { | 384 | if (cx->options.cardtype == -1) { |
361 | CX18_INFO("Ignore card\n"); | 385 | CX18_INFO("Ignore card\n"); |
@@ -395,9 +419,9 @@ done: | |||
395 | 419 | ||
396 | if (cx->card == NULL) { | 420 | if (cx->card == NULL) { |
397 | cx->card = cx18_get_card(CX18_CARD_HVR_1600_ESMT); | 421 | cx->card = cx18_get_card(CX18_CARD_HVR_1600_ESMT); |
398 | CX18_ERR("Unknown card: vendor/device: %04x/%04x\n", | 422 | CX18_ERR("Unknown card: vendor/device: [%04x:%04x]\n", |
399 | cx->dev->vendor, cx->dev->device); | 423 | cx->dev->vendor, cx->dev->device); |
400 | CX18_ERR(" subsystem vendor/device: %04x/%04x\n", | 424 | CX18_ERR(" subsystem vendor/device: [%04x:%04x]\n", |
401 | cx->dev->subsystem_vendor, cx->dev->subsystem_device); | 425 | cx->dev->subsystem_vendor, cx->dev->subsystem_device); |
402 | CX18_ERR("Defaulting to %s card\n", cx->card->name); | 426 | CX18_ERR("Defaulting to %s card\n", cx->card->name); |
403 | CX18_ERR("Please mail the vendor/device and subsystem vendor/device IDs and what kind of\n"); | 427 | CX18_ERR("Please mail the vendor/device and subsystem vendor/device IDs and what kind of\n"); |
@@ -511,9 +535,9 @@ static int cx18_setup_pci(struct cx18 *cx, struct pci_dev *dev, | |||
511 | return -EIO; | 535 | return -EIO; |
512 | } | 536 | } |
513 | 537 | ||
514 | /* Check for bus mastering */ | 538 | /* Enable bus mastering and memory mapped IO for the CX23418 */ |
515 | pci_read_config_word(dev, PCI_COMMAND, &cmd); | 539 | pci_read_config_word(dev, PCI_COMMAND, &cmd); |
516 | cmd |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; | 540 | cmd |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; |
517 | pci_write_config_word(dev, PCI_COMMAND, cmd); | 541 | pci_write_config_word(dev, PCI_COMMAND, cmd); |
518 | 542 | ||
519 | pci_read_config_byte(dev, PCI_CLASS_REVISION, &cx->card_rev); | 543 | pci_read_config_byte(dev, PCI_CLASS_REVISION, &cx->card_rev); |
@@ -525,11 +549,6 @@ static int cx18_setup_pci(struct cx18 *cx, struct pci_dev *dev, | |||
525 | pci_write_config_byte(dev, PCI_LATENCY_TIMER, 64); | 549 | pci_write_config_byte(dev, PCI_LATENCY_TIMER, 64); |
526 | pci_read_config_byte(dev, PCI_LATENCY_TIMER, &pci_latency); | 550 | pci_read_config_byte(dev, PCI_LATENCY_TIMER, &pci_latency); |
527 | } | 551 | } |
528 | /* This config space value relates to DMA latencies. The | ||
529 | default value 0x8080 is too low however and will lead | ||
530 | to DMA errors. 0xffff is the max value which solves | ||
531 | these problems. */ | ||
532 | pci_write_config_dword(dev, 0x40, 0xffff); | ||
533 | 552 | ||
534 | CX18_DEBUG_INFO("cx%d (rev %d) at %02x:%02x.%x, " | 553 | CX18_DEBUG_INFO("cx%d (rev %d) at %02x:%02x.%x, " |
535 | "irq: %d, latency: %d, memory: 0x%lx\n", | 554 | "irq: %d, latency: %d, memory: 0x%lx\n", |
@@ -656,7 +675,7 @@ static int __devinit cx18_probe(struct pci_dev *dev, | |||
656 | goto free_mem; | 675 | goto free_mem; |
657 | } | 676 | } |
658 | cx->reg_mem = cx->enc_mem + CX18_REG_OFFSET; | 677 | cx->reg_mem = cx->enc_mem + CX18_REG_OFFSET; |
659 | devtype = read_reg(0xC72028); | 678 | devtype = cx18_read_reg(cx, 0xC72028); |
660 | switch (devtype & 0xff000000) { | 679 | switch (devtype & 0xff000000) { |
661 | case 0xff000000: | 680 | case 0xff000000: |
662 | CX18_INFO("cx23418 revision %08x (A)\n", devtype); | 681 | CX18_INFO("cx23418 revision %08x (A)\n", devtype); |
@@ -815,6 +834,7 @@ err: | |||
815 | if (retval == 0) | 834 | if (retval == 0) |
816 | retval = -ENODEV; | 835 | retval = -ENODEV; |
817 | CX18_ERR("Error %d on initialization\n", retval); | 836 | CX18_ERR("Error %d on initialization\n", retval); |
837 | cx18_log_statistics(cx); | ||
818 | 838 | ||
819 | kfree(cx18_cards[cx18_cards_active]); | 839 | kfree(cx18_cards[cx18_cards_active]); |
820 | cx18_cards[cx18_cards_active] = NULL; | 840 | cx18_cards[cx18_cards_active] = NULL; |
@@ -902,8 +922,8 @@ static void cx18_remove(struct pci_dev *pci_dev) | |||
902 | cx18_stop_all_captures(cx); | 922 | cx18_stop_all_captures(cx); |
903 | 923 | ||
904 | /* Interrupts */ | 924 | /* Interrupts */ |
905 | sw1_irq_disable(IRQ_CPU_TO_EPU | IRQ_APU_TO_EPU); | 925 | cx18_sw1_irq_disable(cx, IRQ_CPU_TO_EPU | IRQ_APU_TO_EPU); |
906 | sw2_irq_disable(IRQ_CPU_TO_EPU_ACK | IRQ_APU_TO_EPU_ACK); | 926 | cx18_sw2_irq_disable(cx, IRQ_CPU_TO_EPU_ACK | IRQ_APU_TO_EPU_ACK); |
907 | 927 | ||
908 | cx18_halt_firmware(cx); | 928 | cx18_halt_firmware(cx); |
909 | 929 | ||
@@ -919,6 +939,7 @@ static void cx18_remove(struct pci_dev *pci_dev) | |||
919 | 939 | ||
920 | pci_disable_device(cx->dev); | 940 | pci_disable_device(cx->dev); |
921 | 941 | ||
942 | cx18_log_statistics(cx); | ||
922 | CX18_INFO("Removed %s, card #%d\n", cx->card_name, cx->num); | 943 | CX18_INFO("Removed %s, card #%d\n", cx->card_name, cx->num); |
923 | } | 944 | } |
924 | 945 | ||
@@ -938,7 +959,7 @@ static int module_start(void) | |||
938 | 959 | ||
939 | /* Validate parameters */ | 960 | /* Validate parameters */ |
940 | if (cx18_first_minor < 0 || cx18_first_minor >= CX18_MAX_CARDS) { | 961 | if (cx18_first_minor < 0 || cx18_first_minor >= CX18_MAX_CARDS) { |
941 | printk(KERN_ERR "cx18: Exiting, ivtv_first_minor must be between 0 and %d\n", | 962 | printk(KERN_ERR "cx18: Exiting, cx18_first_minor must be between 0 and %d\n", |
942 | CX18_MAX_CARDS - 1); | 963 | CX18_MAX_CARDS - 1); |
943 | return -1; | 964 | return -1; |
944 | } | 965 | } |
diff --git a/drivers/media/video/cx18/cx18-driver.h b/drivers/media/video/cx18/cx18-driver.h index 4801bc7fb5b2..fa8be0731a3f 100644 --- a/drivers/media/video/cx18/cx18-driver.h +++ b/drivers/media/video/cx18/cx18-driver.h | |||
@@ -38,7 +38,6 @@ | |||
38 | #include <linux/i2c-algo-bit.h> | 38 | #include <linux/i2c-algo-bit.h> |
39 | #include <linux/list.h> | 39 | #include <linux/list.h> |
40 | #include <linux/unistd.h> | 40 | #include <linux/unistd.h> |
41 | #include <linux/byteorder/swab.h> | ||
42 | #include <linux/pagemap.h> | 41 | #include <linux/pagemap.h> |
43 | #include <linux/workqueue.h> | 42 | #include <linux/workqueue.h> |
44 | #include <linux/mutex.h> | 43 | #include <linux/mutex.h> |
@@ -64,6 +63,9 @@ | |||
64 | # error "This driver requires kernel PCI support." | 63 | # error "This driver requires kernel PCI support." |
65 | #endif | 64 | #endif |
66 | 65 | ||
66 | /* Default delay to throttle mmio access to the CX23418 */ | ||
67 | #define CX18_DEFAULT_MMIO_NDELAY 0 /* 0 ns = 0 PCI clock(s) / 33 MHz */ | ||
68 | |||
67 | #define CX18_MEM_OFFSET 0x00000000 | 69 | #define CX18_MEM_OFFSET 0x00000000 |
68 | #define CX18_MEM_SIZE 0x04000000 | 70 | #define CX18_MEM_SIZE 0x04000000 |
69 | #define CX18_REG_OFFSET 0x02000000 | 71 | #define CX18_REG_OFFSET 0x02000000 |
@@ -77,7 +79,9 @@ | |||
77 | #define CX18_CARD_COMPRO_H900 2 /* Compro VideoMate H900 */ | 79 | #define CX18_CARD_COMPRO_H900 2 /* Compro VideoMate H900 */ |
78 | #define CX18_CARD_YUAN_MPC718 3 /* Yuan MPC718 */ | 80 | #define CX18_CARD_YUAN_MPC718 3 /* Yuan MPC718 */ |
79 | #define CX18_CARD_CNXT_RAPTOR_PAL 4 /* Conexant Raptor PAL */ | 81 | #define CX18_CARD_CNXT_RAPTOR_PAL 4 /* Conexant Raptor PAL */ |
80 | #define CX18_CARD_LAST 4 | 82 | #define CX18_CARD_TOSHIBA_QOSMIO_DVBT 5 /* Toshiba Qosmio Interal DVB-T/Analog*/ |
83 | #define CX18_CARD_LEADTEK_PVR2100 6 /* Leadtek WinFast PVR2100 */ | ||
84 | #define CX18_CARD_LAST 6 | ||
81 | 85 | ||
82 | #define CX18_ENC_STREAM_TYPE_MPG 0 | 86 | #define CX18_ENC_STREAM_TYPE_MPG 0 |
83 | #define CX18_ENC_STREAM_TYPE_TS 1 | 87 | #define CX18_ENC_STREAM_TYPE_TS 1 |
@@ -97,6 +101,8 @@ | |||
97 | #define CX18_PCI_ID_COMPRO 0x185b | 101 | #define CX18_PCI_ID_COMPRO 0x185b |
98 | #define CX18_PCI_ID_YUAN 0x12ab | 102 | #define CX18_PCI_ID_YUAN 0x12ab |
99 | #define CX18_PCI_ID_CONEXANT 0x14f1 | 103 | #define CX18_PCI_ID_CONEXANT 0x14f1 |
104 | #define CX18_PCI_ID_TOSHIBA 0x1179 | ||
105 | #define CX18_PCI_ID_LEADTEK 0x107D | ||
100 | 106 | ||
101 | /* ======================================================================== */ | 107 | /* ======================================================================== */ |
102 | /* ========================== START USER SETTABLE DMA VARIABLES =========== */ | 108 | /* ========================== START USER SETTABLE DMA VARIABLES =========== */ |
@@ -169,6 +175,7 @@ | |||
169 | 175 | ||
170 | #define CX18_MAX_PGM_INDEX (400) | 176 | #define CX18_MAX_PGM_INDEX (400) |
171 | 177 | ||
178 | extern int cx18_retry_mmio; /* enable check & retry of mmio accesses */ | ||
172 | extern int cx18_debug; | 179 | extern int cx18_debug; |
173 | 180 | ||
174 | 181 | ||
@@ -177,6 +184,7 @@ struct cx18_options { | |||
177 | int cardtype; /* force card type on load */ | 184 | int cardtype; /* force card type on load */ |
178 | int tuner; /* set tuner on load */ | 185 | int tuner; /* set tuner on load */ |
179 | int radio; /* enable/disable radio */ | 186 | int radio; /* enable/disable radio */ |
187 | unsigned long mmio_ndelay; /* delay in ns after every PCI mmio access */ | ||
180 | }; | 188 | }; |
181 | 189 | ||
182 | /* per-buffer bit flags */ | 190 | /* per-buffer bit flags */ |
@@ -216,8 +224,7 @@ struct cx18_buffer { | |||
216 | 224 | ||
217 | struct cx18_queue { | 225 | struct cx18_queue { |
218 | struct list_head list; | 226 | struct list_head list; |
219 | u32 buffers; | 227 | atomic_t buffers; |
220 | u32 length; | ||
221 | u32 bytesused; | 228 | u32 bytesused; |
222 | }; | 229 | }; |
223 | 230 | ||
@@ -237,6 +244,8 @@ struct cx18_dvb { | |||
237 | struct cx18; /* forward reference */ | 244 | struct cx18; /* forward reference */ |
238 | struct cx18_scb; /* forward reference */ | 245 | struct cx18_scb; /* forward reference */ |
239 | 246 | ||
247 | #define CX18_INVALID_TASK_HANDLE 0xffffffff | ||
248 | |||
240 | struct cx18_stream { | 249 | struct cx18_stream { |
241 | /* These first four fields are always set, even if the stream | 250 | /* These first four fields are always set, even if the stream |
242 | is not actually created. */ | 251 | is not actually created. */ |
@@ -259,7 +268,6 @@ struct cx18_stream { | |||
259 | /* Buffer Stats */ | 268 | /* Buffer Stats */ |
260 | u32 buffers; | 269 | u32 buffers; |
261 | u32 buf_size; | 270 | u32 buf_size; |
262 | u32 buffers_stolen; | ||
263 | 271 | ||
264 | /* Buffer Queues */ | 272 | /* Buffer Queues */ |
265 | struct cx18_queue q_free; /* free buffers */ | 273 | struct cx18_queue q_free; /* free buffers */ |
@@ -341,6 +349,13 @@ struct cx18_i2c_algo_callback_data { | |||
341 | int bus_index; /* 0 or 1 for the cx23418's 1st or 2nd I2C bus */ | 349 | int bus_index; /* 0 or 1 for the cx23418's 1st or 2nd I2C bus */ |
342 | }; | 350 | }; |
343 | 351 | ||
352 | #define CX18_MAX_MMIO_RETRIES 10 | ||
353 | |||
354 | struct cx18_mmio_stats { | ||
355 | atomic_t retried_write[CX18_MAX_MMIO_RETRIES+1]; | ||
356 | atomic_t retried_read[CX18_MAX_MMIO_RETRIES+1]; | ||
357 | }; | ||
358 | |||
344 | /* Struct to hold info about cx18 cards */ | 359 | /* Struct to hold info about cx18 cards */ |
345 | struct cx18 { | 360 | struct cx18 { |
346 | int num; /* board number, -1 during init! */ | 361 | int num; /* board number, -1 during init! */ |
@@ -430,6 +445,9 @@ struct cx18 { | |||
430 | u32 gpio_val; | 445 | u32 gpio_val; |
431 | struct mutex gpio_lock; | 446 | struct mutex gpio_lock; |
432 | 447 | ||
448 | /* Statistics */ | ||
449 | struct cx18_mmio_stats mmio_stats; | ||
450 | |||
433 | /* v4l2 and User settings */ | 451 | /* v4l2 and User settings */ |
434 | 452 | ||
435 | /* codec settings */ | 453 | /* codec settings */ |
@@ -458,47 +476,4 @@ void cx18_read_eeprom(struct cx18 *cx, struct tveeprom *tv); | |||
458 | /* First-open initialization: load firmware, etc. */ | 476 | /* First-open initialization: load firmware, etc. */ |
459 | int cx18_init_on_first_open(struct cx18 *cx); | 477 | int cx18_init_on_first_open(struct cx18 *cx); |
460 | 478 | ||
461 | /* This is a PCI post thing, where if the pci register is not read, then | ||
462 | the write doesn't always take effect right away. By reading back the | ||
463 | register any pending PCI writes will be performed (in order), and so | ||
464 | you can be sure that the writes are guaranteed to be done. | ||
465 | |||
466 | Rarely needed, only in some timing sensitive cases. | ||
467 | Apparently if this is not done some motherboards seem | ||
468 | to kill the firmware and get into the broken state until computer is | ||
469 | rebooted. */ | ||
470 | #define write_sync(val, reg) \ | ||
471 | do { writel(val, reg); readl(reg); } while (0) | ||
472 | |||
473 | #define read_reg(reg) readl(cx->reg_mem + (reg)) | ||
474 | #define write_reg(val, reg) writel(val, cx->reg_mem + (reg)) | ||
475 | #define write_reg_sync(val, reg) \ | ||
476 | do { write_reg(val, reg); read_reg(reg); } while (0) | ||
477 | |||
478 | #define read_enc(addr) readl(cx->enc_mem + (u32)(addr)) | ||
479 | #define write_enc(val, addr) writel(val, cx->enc_mem + (u32)(addr)) | ||
480 | #define write_enc_sync(val, addr) \ | ||
481 | do { write_enc(val, addr); read_enc(addr); } while (0) | ||
482 | |||
483 | #define sw1_irq_enable(val) do { \ | ||
484 | write_reg(val, SW1_INT_STATUS); \ | ||
485 | write_reg(read_reg(SW1_INT_ENABLE_PCI) | (val), SW1_INT_ENABLE_PCI); \ | ||
486 | } while (0) | ||
487 | |||
488 | #define sw1_irq_disable(val) \ | ||
489 | write_reg(read_reg(SW1_INT_ENABLE_PCI) & ~(val), SW1_INT_ENABLE_PCI); | ||
490 | |||
491 | #define sw2_irq_enable(val) do { \ | ||
492 | write_reg(val, SW2_INT_STATUS); \ | ||
493 | write_reg(read_reg(SW2_INT_ENABLE_PCI) | (val), SW2_INT_ENABLE_PCI); \ | ||
494 | } while (0) | ||
495 | |||
496 | #define sw2_irq_disable(val) \ | ||
497 | write_reg(read_reg(SW2_INT_ENABLE_PCI) & ~(val), SW2_INT_ENABLE_PCI); | ||
498 | |||
499 | #define setup_page(addr) do { \ | ||
500 | u32 val = read_reg(0xD000F8) & ~0x1f00; \ | ||
501 | write_reg(val | (((addr) >> 17) & 0x1f00), 0xD000F8); \ | ||
502 | } while (0) | ||
503 | |||
504 | #endif /* CX18_DRIVER_H */ | 479 | #endif /* CX18_DRIVER_H */ |
diff --git a/drivers/media/video/cx18/cx18-dvb.c b/drivers/media/video/cx18/cx18-dvb.c index 1e420a804fc9..afc694e7bdb2 100644 --- a/drivers/media/video/cx18/cx18-dvb.c +++ b/drivers/media/video/cx18/cx18-dvb.c | |||
@@ -21,6 +21,7 @@ | |||
21 | 21 | ||
22 | #include "cx18-version.h" | 22 | #include "cx18-version.h" |
23 | #include "cx18-dvb.h" | 23 | #include "cx18-dvb.h" |
24 | #include "cx18-io.h" | ||
24 | #include "cx18-streams.h" | 25 | #include "cx18-streams.h" |
25 | #include "cx18-cards.h" | 26 | #include "cx18-cards.h" |
26 | #include "s5h1409.h" | 27 | #include "s5h1409.h" |
@@ -87,13 +88,13 @@ static int cx18_dvb_start_feed(struct dvb_demux_feed *feed) | |||
87 | switch (cx->card->type) { | 88 | switch (cx->card->type) { |
88 | case CX18_CARD_HVR_1600_ESMT: | 89 | case CX18_CARD_HVR_1600_ESMT: |
89 | case CX18_CARD_HVR_1600_SAMSUNG: | 90 | case CX18_CARD_HVR_1600_SAMSUNG: |
90 | v = read_reg(CX18_REG_DMUX_NUM_PORT_0_CONTROL); | 91 | v = cx18_read_reg(cx, CX18_REG_DMUX_NUM_PORT_0_CONTROL); |
91 | v |= 0x00400000; /* Serial Mode */ | 92 | v |= 0x00400000; /* Serial Mode */ |
92 | v |= 0x00002000; /* Data Length - Byte */ | 93 | v |= 0x00002000; /* Data Length - Byte */ |
93 | v |= 0x00010000; /* Error - Polarity */ | 94 | v |= 0x00010000; /* Error - Polarity */ |
94 | v |= 0x00020000; /* Error - Passthru */ | 95 | v |= 0x00020000; /* Error - Passthru */ |
95 | v |= 0x000c0000; /* Error - Ignore */ | 96 | v |= 0x000c0000; /* Error - Ignore */ |
96 | write_reg(v, CX18_REG_DMUX_NUM_PORT_0_CONTROL); | 97 | cx18_write_reg(cx, v, CX18_REG_DMUX_NUM_PORT_0_CONTROL); |
97 | break; | 98 | break; |
98 | 99 | ||
99 | default: | 100 | default: |
diff --git a/drivers/media/video/cx18/cx18-fileops.c b/drivers/media/video/cx18/cx18-fileops.c index 1e537fe04a23..5f9089907544 100644 --- a/drivers/media/video/cx18/cx18-fileops.c +++ b/drivers/media/video/cx18/cx18-fileops.c | |||
@@ -132,6 +132,7 @@ static void cx18_dualwatch(struct cx18 *cx) | |||
132 | u16 new_stereo_mode; | 132 | u16 new_stereo_mode; |
133 | const u16 stereo_mask = 0x0300; | 133 | const u16 stereo_mask = 0x0300; |
134 | const u16 dual = 0x0200; | 134 | const u16 dual = 0x0200; |
135 | u32 h; | ||
135 | 136 | ||
136 | new_stereo_mode = cx->params.audio_properties & stereo_mask; | 137 | new_stereo_mode = cx->params.audio_properties & stereo_mask; |
137 | memset(&vt, 0, sizeof(vt)); | 138 | memset(&vt, 0, sizeof(vt)); |
@@ -143,13 +144,21 @@ static void cx18_dualwatch(struct cx18 *cx) | |||
143 | if (new_stereo_mode == cx->dualwatch_stereo_mode) | 144 | if (new_stereo_mode == cx->dualwatch_stereo_mode) |
144 | return; | 145 | return; |
145 | 146 | ||
146 | new_bitmap = new_stereo_mode | (cx->params.audio_properties & ~stereo_mask); | 147 | new_bitmap = new_stereo_mode |
148 | | (cx->params.audio_properties & ~stereo_mask); | ||
147 | 149 | ||
148 | CX18_DEBUG_INFO("dualwatch: change stereo flag from 0x%x to 0x%x. new audio_bitmask=0x%ux\n", | 150 | CX18_DEBUG_INFO("dualwatch: change stereo flag from 0x%x to 0x%x. " |
149 | cx->dualwatch_stereo_mode, new_stereo_mode, new_bitmap); | 151 | "new audio_bitmask=0x%ux\n", |
152 | cx->dualwatch_stereo_mode, new_stereo_mode, new_bitmap); | ||
150 | 153 | ||
151 | if (cx18_vapi(cx, CX18_CPU_SET_AUDIO_PARAMETERS, 2, | 154 | h = cx18_find_handle(cx); |
152 | cx18_find_handle(cx), new_bitmap) == 0) { | 155 | if (h == CX18_INVALID_TASK_HANDLE) { |
156 | CX18_DEBUG_INFO("dualwatch: can't find valid task handle\n"); | ||
157 | return; | ||
158 | } | ||
159 | |||
160 | if (cx18_vapi(cx, | ||
161 | CX18_CPU_SET_AUDIO_PARAMETERS, 2, h, new_bitmap) == 0) { | ||
153 | cx->dualwatch_stereo_mode = new_stereo_mode; | 162 | cx->dualwatch_stereo_mode = new_stereo_mode; |
154 | return; | 163 | return; |
155 | } | 164 | } |
@@ -223,7 +232,7 @@ static struct cx18_buffer *cx18_get_buffer(struct cx18_stream *s, int non_block, | |||
223 | prepare_to_wait(&s->waitq, &wait, TASK_INTERRUPTIBLE); | 232 | prepare_to_wait(&s->waitq, &wait, TASK_INTERRUPTIBLE); |
224 | /* New buffers might have become available before we were added | 233 | /* New buffers might have become available before we were added |
225 | to the waitqueue */ | 234 | to the waitqueue */ |
226 | if (!s->q_full.buffers) | 235 | if (!atomic_read(&s->q_full.buffers)) |
227 | schedule(); | 236 | schedule(); |
228 | finish_wait(&s->waitq, &wait); | 237 | finish_wait(&s->waitq, &wait); |
229 | if (signal_pending(current)) { | 238 | if (signal_pending(current)) { |
@@ -509,7 +518,7 @@ unsigned int cx18_v4l2_enc_poll(struct file *filp, poll_table *wait) | |||
509 | CX18_DEBUG_HI_FILE("Encoder poll\n"); | 518 | CX18_DEBUG_HI_FILE("Encoder poll\n"); |
510 | poll_wait(filp, &s->waitq, wait); | 519 | poll_wait(filp, &s->waitq, wait); |
511 | 520 | ||
512 | if (s->q_full.length || s->q_io.length) | 521 | if (atomic_read(&s->q_full.buffers) || atomic_read(&s->q_io.buffers)) |
513 | return POLLIN | POLLRDNORM; | 522 | return POLLIN | POLLRDNORM; |
514 | if (eof) | 523 | if (eof) |
515 | return POLLHUP; | 524 | return POLLHUP; |
@@ -695,20 +704,28 @@ int cx18_v4l2_open(struct inode *inode, struct file *filp) | |||
695 | 704 | ||
696 | void cx18_mute(struct cx18 *cx) | 705 | void cx18_mute(struct cx18 *cx) |
697 | { | 706 | { |
698 | if (atomic_read(&cx->ana_capturing)) | 707 | u32 h; |
699 | cx18_vapi(cx, CX18_CPU_SET_AUDIO_MUTE, 2, | 708 | if (atomic_read(&cx->ana_capturing)) { |
700 | cx18_find_handle(cx), 1); | 709 | h = cx18_find_handle(cx); |
710 | if (h != CX18_INVALID_TASK_HANDLE) | ||
711 | cx18_vapi(cx, CX18_CPU_SET_AUDIO_MUTE, 2, h, 1); | ||
712 | else | ||
713 | CX18_ERR("Can't find valid task handle for mute\n"); | ||
714 | } | ||
701 | CX18_DEBUG_INFO("Mute\n"); | 715 | CX18_DEBUG_INFO("Mute\n"); |
702 | } | 716 | } |
703 | 717 | ||
704 | void cx18_unmute(struct cx18 *cx) | 718 | void cx18_unmute(struct cx18 *cx) |
705 | { | 719 | { |
720 | u32 h; | ||
706 | if (atomic_read(&cx->ana_capturing)) { | 721 | if (atomic_read(&cx->ana_capturing)) { |
707 | cx18_msleep_timeout(100, 0); | 722 | h = cx18_find_handle(cx); |
708 | cx18_vapi(cx, CX18_CPU_SET_MISC_PARAMETERS, 2, | 723 | if (h != CX18_INVALID_TASK_HANDLE) { |
709 | cx18_find_handle(cx), 12); | 724 | cx18_msleep_timeout(100, 0); |
710 | cx18_vapi(cx, CX18_CPU_SET_AUDIO_MUTE, 2, | 725 | cx18_vapi(cx, CX18_CPU_SET_MISC_PARAMETERS, 2, h, 12); |
711 | cx18_find_handle(cx), 0); | 726 | cx18_vapi(cx, CX18_CPU_SET_AUDIO_MUTE, 2, h, 0); |
727 | } else | ||
728 | CX18_ERR("Can't find valid task handle for unmute\n"); | ||
712 | } | 729 | } |
713 | CX18_DEBUG_INFO("Unmute\n"); | 730 | CX18_DEBUG_INFO("Unmute\n"); |
714 | } | 731 | } |
diff --git a/drivers/media/video/cx18/cx18-firmware.c b/drivers/media/video/cx18/cx18-firmware.c index 78fadd2ada5d..51534428cd00 100644 --- a/drivers/media/video/cx18/cx18-firmware.c +++ b/drivers/media/video/cx18/cx18-firmware.c | |||
@@ -20,6 +20,7 @@ | |||
20 | */ | 20 | */ |
21 | 21 | ||
22 | #include "cx18-driver.h" | 22 | #include "cx18-driver.h" |
23 | #include "cx18-io.h" | ||
23 | #include "cx18-scb.h" | 24 | #include "cx18-scb.h" |
24 | #include "cx18-irq.h" | 25 | #include "cx18-irq.h" |
25 | #include "cx18-firmware.h" | 26 | #include "cx18-firmware.h" |
@@ -113,11 +114,11 @@ static int load_cpu_fw_direct(const char *fn, u8 __iomem *mem, struct cx18 *cx) | |||
113 | src = (const u32 *)fw->data; | 114 | src = (const u32 *)fw->data; |
114 | 115 | ||
115 | for (i = 0; i < fw->size; i += 4096) { | 116 | for (i = 0; i < fw->size; i += 4096) { |
116 | setup_page(i); | 117 | cx18_setup_page(cx, i); |
117 | for (j = i; j < fw->size && j < i + 4096; j += 4) { | 118 | for (j = i; j < fw->size && j < i + 4096; j += 4) { |
118 | /* no need for endianness conversion on the ppc */ | 119 | /* no need for endianness conversion on the ppc */ |
119 | __raw_writel(*src, dst); | 120 | cx18_raw_writel(cx, *src, dst); |
120 | if (__raw_readl(dst) != *src) { | 121 | if (cx18_raw_readl(cx, dst) != *src) { |
121 | CX18_ERR("Mismatch at offset %x\n", i); | 122 | CX18_ERR("Mismatch at offset %x\n", i); |
122 | release_firmware(fw); | 123 | release_firmware(fw); |
123 | return -EIO; | 124 | return -EIO; |
@@ -170,12 +171,15 @@ static int load_apu_fw_direct(const char *fn, u8 __iomem *dst, struct cx18 *cx) | |||
170 | if (offset + seghdr.size > sz) | 171 | if (offset + seghdr.size > sz) |
171 | break; | 172 | break; |
172 | for (i = 0; i < seghdr.size; i += 4096) { | 173 | for (i = 0; i < seghdr.size; i += 4096) { |
173 | setup_page(offset + i); | 174 | cx18_setup_page(cx, offset + i); |
174 | for (j = i; j < seghdr.size && j < i + 4096; j += 4) { | 175 | for (j = i; j < seghdr.size && j < i + 4096; j += 4) { |
175 | /* no need for endianness conversion on the ppc */ | 176 | /* no need for endianness conversion on the ppc */ |
176 | __raw_writel(src[(offset + j) / 4], dst + seghdr.addr + j); | 177 | cx18_raw_writel(cx, src[(offset + j) / 4], |
177 | if (__raw_readl(dst + seghdr.addr + j) != src[(offset + j) / 4]) { | 178 | dst + seghdr.addr + j); |
178 | CX18_ERR("Mismatch at offset %x\n", offset + j); | 179 | if (cx18_raw_readl(cx, dst + seghdr.addr + j) |
180 | != src[(offset + j) / 4]) { | ||
181 | CX18_ERR("Mismatch at offset %x\n", | ||
182 | offset + j); | ||
179 | release_firmware(fw); | 183 | release_firmware(fw); |
180 | return -EIO; | 184 | return -EIO; |
181 | } | 185 | } |
@@ -189,43 +193,45 @@ static int load_apu_fw_direct(const char *fn, u8 __iomem *dst, struct cx18 *cx) | |||
189 | size = fw->size; | 193 | size = fw->size; |
190 | release_firmware(fw); | 194 | release_firmware(fw); |
191 | /* Clear bit0 for APU to start from 0 */ | 195 | /* Clear bit0 for APU to start from 0 */ |
192 | write_reg(read_reg(0xc72030) & ~1, 0xc72030); | 196 | cx18_write_reg(cx, cx18_read_reg(cx, 0xc72030) & ~1, 0xc72030); |
193 | return size; | 197 | return size; |
194 | } | 198 | } |
195 | 199 | ||
196 | void cx18_halt_firmware(struct cx18 *cx) | 200 | void cx18_halt_firmware(struct cx18 *cx) |
197 | { | 201 | { |
198 | CX18_DEBUG_INFO("Preparing for firmware halt.\n"); | 202 | CX18_DEBUG_INFO("Preparing for firmware halt.\n"); |
199 | write_reg(0x000F000F, CX18_PROC_SOFT_RESET); /* stop the fw */ | 203 | cx18_write_reg(cx, 0x000F000F, CX18_PROC_SOFT_RESET); /* stop the fw */ |
200 | write_reg(0x00020002, CX18_ADEC_CONTROL); | 204 | cx18_write_reg(cx, 0x00020002, CX18_ADEC_CONTROL); |
201 | } | 205 | } |
202 | 206 | ||
203 | void cx18_init_power(struct cx18 *cx, int lowpwr) | 207 | void cx18_init_power(struct cx18 *cx, int lowpwr) |
204 | { | 208 | { |
205 | /* power-down Spare and AOM PLLs */ | 209 | /* power-down Spare and AOM PLLs */ |
206 | /* power-up fast, slow and mpeg PLLs */ | 210 | /* power-up fast, slow and mpeg PLLs */ |
207 | write_reg(0x00000008, CX18_PLL_POWER_DOWN); | 211 | cx18_write_reg(cx, 0x00000008, CX18_PLL_POWER_DOWN); |
208 | 212 | ||
209 | /* ADEC out of sleep */ | 213 | /* ADEC out of sleep */ |
210 | write_reg(0x00020000, CX18_ADEC_CONTROL); | 214 | cx18_write_reg(cx, 0x00020000, CX18_ADEC_CONTROL); |
211 | 215 | ||
212 | /* The fast clock is at 200/245 MHz */ | 216 | /* The fast clock is at 200/245 MHz */ |
213 | write_reg(lowpwr ? 0xD : 0x11, CX18_FAST_CLOCK_PLL_INT); | 217 | cx18_write_reg(cx, lowpwr ? 0xD : 0x11, CX18_FAST_CLOCK_PLL_INT); |
214 | write_reg(lowpwr ? 0x1EFBF37 : 0x038E3D7, CX18_FAST_CLOCK_PLL_FRAC); | 218 | cx18_write_reg(cx, lowpwr ? 0x1EFBF37 : 0x038E3D7, |
219 | CX18_FAST_CLOCK_PLL_FRAC); | ||
215 | 220 | ||
216 | write_reg(2, CX18_FAST_CLOCK_PLL_POST); | 221 | cx18_write_reg(cx, 2, CX18_FAST_CLOCK_PLL_POST); |
217 | write_reg(1, CX18_FAST_CLOCK_PLL_PRESCALE); | 222 | cx18_write_reg(cx, 1, CX18_FAST_CLOCK_PLL_PRESCALE); |
218 | write_reg(4, CX18_FAST_CLOCK_PLL_ADJUST_BANDWIDTH); | 223 | cx18_write_reg(cx, 4, CX18_FAST_CLOCK_PLL_ADJUST_BANDWIDTH); |
219 | 224 | ||
220 | /* set slow clock to 125/120 MHz */ | 225 | /* set slow clock to 125/120 MHz */ |
221 | write_reg(lowpwr ? 0x11 : 0x10, CX18_SLOW_CLOCK_PLL_INT); | 226 | cx18_write_reg(cx, lowpwr ? 0x11 : 0x10, CX18_SLOW_CLOCK_PLL_INT); |
222 | write_reg(lowpwr ? 0xEBAF05 : 0x18618A8, CX18_SLOW_CLOCK_PLL_FRAC); | 227 | cx18_write_reg(cx, lowpwr ? 0xEBAF05 : 0x18618A8, |
223 | write_reg(4, CX18_SLOW_CLOCK_PLL_POST); | 228 | CX18_SLOW_CLOCK_PLL_FRAC); |
229 | cx18_write_reg(cx, 4, CX18_SLOW_CLOCK_PLL_POST); | ||
224 | 230 | ||
225 | /* mpeg clock pll 54MHz */ | 231 | /* mpeg clock pll 54MHz */ |
226 | write_reg(0xF, CX18_MPEG_CLOCK_PLL_INT); | 232 | cx18_write_reg(cx, 0xF, CX18_MPEG_CLOCK_PLL_INT); |
227 | write_reg(0x2BCFEF, CX18_MPEG_CLOCK_PLL_FRAC); | 233 | cx18_write_reg(cx, 0x2BCFEF, CX18_MPEG_CLOCK_PLL_FRAC); |
228 | write_reg(8, CX18_MPEG_CLOCK_PLL_POST); | 234 | cx18_write_reg(cx, 8, CX18_MPEG_CLOCK_PLL_POST); |
229 | 235 | ||
230 | /* Defaults */ | 236 | /* Defaults */ |
231 | /* APU = SC or SC/2 = 125/62.5 */ | 237 | /* APU = SC or SC/2 = 125/62.5 */ |
@@ -242,81 +248,84 @@ void cx18_init_power(struct cx18 *cx, int lowpwr) | |||
242 | /* VFC = disabled */ | 248 | /* VFC = disabled */ |
243 | /* USB = disabled */ | 249 | /* USB = disabled */ |
244 | 250 | ||
245 | write_reg(lowpwr ? 0xFFFF0020 : 0x00060004, CX18_CLOCK_SELECT1); | 251 | cx18_write_reg(cx, lowpwr ? 0xFFFF0020 : 0x00060004, |
246 | write_reg(lowpwr ? 0xFFFF0004 : 0x00060006, CX18_CLOCK_SELECT2); | 252 | CX18_CLOCK_SELECT1); |
253 | cx18_write_reg(cx, lowpwr ? 0xFFFF0004 : 0x00060006, | ||
254 | CX18_CLOCK_SELECT2); | ||
247 | 255 | ||
248 | write_reg(0xFFFF0002, CX18_HALF_CLOCK_SELECT1); | 256 | cx18_write_reg(cx, 0xFFFF0002, CX18_HALF_CLOCK_SELECT1); |
249 | write_reg(0xFFFF0104, CX18_HALF_CLOCK_SELECT2); | 257 | cx18_write_reg(cx, 0xFFFF0104, CX18_HALF_CLOCK_SELECT2); |
250 | 258 | ||
251 | write_reg(0xFFFF9026, CX18_CLOCK_ENABLE1); | 259 | cx18_write_reg(cx, 0xFFFF9026, CX18_CLOCK_ENABLE1); |
252 | write_reg(0xFFFF3105, CX18_CLOCK_ENABLE2); | 260 | cx18_write_reg(cx, 0xFFFF3105, CX18_CLOCK_ENABLE2); |
253 | } | 261 | } |
254 | 262 | ||
255 | void cx18_init_memory(struct cx18 *cx) | 263 | void cx18_init_memory(struct cx18 *cx) |
256 | { | 264 | { |
257 | cx18_msleep_timeout(10, 0); | 265 | cx18_msleep_timeout(10, 0); |
258 | write_reg(0x10000, CX18_DDR_SOFT_RESET); | 266 | cx18_write_reg(cx, 0x10000, CX18_DDR_SOFT_RESET); |
259 | cx18_msleep_timeout(10, 0); | 267 | cx18_msleep_timeout(10, 0); |
260 | 268 | ||
261 | write_reg(cx->card->ddr.chip_config, CX18_DDR_CHIP_CONFIG); | 269 | cx18_write_reg(cx, cx->card->ddr.chip_config, CX18_DDR_CHIP_CONFIG); |
262 | 270 | ||
263 | cx18_msleep_timeout(10, 0); | 271 | cx18_msleep_timeout(10, 0); |
264 | 272 | ||
265 | write_reg(cx->card->ddr.refresh, CX18_DDR_REFRESH); | 273 | cx18_write_reg(cx, cx->card->ddr.refresh, CX18_DDR_REFRESH); |
266 | write_reg(cx->card->ddr.timing1, CX18_DDR_TIMING1); | 274 | cx18_write_reg(cx, cx->card->ddr.timing1, CX18_DDR_TIMING1); |
267 | write_reg(cx->card->ddr.timing2, CX18_DDR_TIMING2); | 275 | cx18_write_reg(cx, cx->card->ddr.timing2, CX18_DDR_TIMING2); |
268 | 276 | ||
269 | cx18_msleep_timeout(10, 0); | 277 | cx18_msleep_timeout(10, 0); |
270 | 278 | ||
271 | /* Initialize DQS pad time */ | 279 | /* Initialize DQS pad time */ |
272 | write_reg(cx->card->ddr.tune_lane, CX18_DDR_TUNE_LANE); | 280 | cx18_write_reg(cx, cx->card->ddr.tune_lane, CX18_DDR_TUNE_LANE); |
273 | write_reg(cx->card->ddr.initial_emrs, CX18_DDR_INITIAL_EMRS); | 281 | cx18_write_reg(cx, cx->card->ddr.initial_emrs, CX18_DDR_INITIAL_EMRS); |
274 | 282 | ||
275 | cx18_msleep_timeout(10, 0); | 283 | cx18_msleep_timeout(10, 0); |
276 | 284 | ||
277 | write_reg(0x20000, CX18_DDR_SOFT_RESET); | 285 | cx18_write_reg(cx, 0x20000, CX18_DDR_SOFT_RESET); |
278 | cx18_msleep_timeout(10, 0); | 286 | cx18_msleep_timeout(10, 0); |
279 | 287 | ||
280 | /* use power-down mode when idle */ | 288 | /* use power-down mode when idle */ |
281 | write_reg(0x00000010, CX18_DDR_POWER_REG); | 289 | cx18_write_reg(cx, 0x00000010, CX18_DDR_POWER_REG); |
282 | 290 | ||
283 | write_reg(0x10001, CX18_REG_BUS_TIMEOUT_EN); | 291 | cx18_write_reg(cx, 0x10001, CX18_REG_BUS_TIMEOUT_EN); |
284 | 292 | ||
285 | write_reg(0x48, CX18_DDR_MB_PER_ROW_7); | 293 | cx18_write_reg(cx, 0x48, CX18_DDR_MB_PER_ROW_7); |
286 | write_reg(0xE0000, CX18_DDR_BASE_63_ADDR); | 294 | cx18_write_reg(cx, 0xE0000, CX18_DDR_BASE_63_ADDR); |
287 | 295 | ||
288 | write_reg(0x00000101, CX18_WMB_CLIENT02); /* AO */ | 296 | cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT02); /* AO */ |
289 | write_reg(0x00000101, CX18_WMB_CLIENT09); /* AI2 */ | 297 | cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT09); /* AI2 */ |
290 | write_reg(0x00000101, CX18_WMB_CLIENT05); /* VIM1 */ | 298 | cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT05); /* VIM1 */ |
291 | write_reg(0x00000101, CX18_WMB_CLIENT06); /* AI1 */ | 299 | cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT06); /* AI1 */ |
292 | write_reg(0x00000101, CX18_WMB_CLIENT07); /* 3D comb */ | 300 | cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT07); /* 3D comb */ |
293 | write_reg(0x00000101, CX18_WMB_CLIENT10); /* ME */ | 301 | cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT10); /* ME */ |
294 | write_reg(0x00000101, CX18_WMB_CLIENT12); /* ENC */ | 302 | cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT12); /* ENC */ |
295 | write_reg(0x00000101, CX18_WMB_CLIENT13); /* PK */ | 303 | cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT13); /* PK */ |
296 | write_reg(0x00000101, CX18_WMB_CLIENT11); /* RC */ | 304 | cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT11); /* RC */ |
297 | write_reg(0x00000101, CX18_WMB_CLIENT14); /* AVO */ | 305 | cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT14); /* AVO */ |
298 | } | 306 | } |
299 | 307 | ||
300 | int cx18_firmware_init(struct cx18 *cx) | 308 | int cx18_firmware_init(struct cx18 *cx) |
301 | { | 309 | { |
302 | /* Allow chip to control CLKRUN */ | 310 | /* Allow chip to control CLKRUN */ |
303 | write_reg(0x5, CX18_DSP0_INTERRUPT_MASK); | 311 | cx18_write_reg(cx, 0x5, CX18_DSP0_INTERRUPT_MASK); |
304 | 312 | ||
305 | write_reg(0x000F000F, CX18_PROC_SOFT_RESET); /* stop the fw */ | 313 | cx18_write_reg(cx, 0x000F000F, CX18_PROC_SOFT_RESET); /* stop the fw */ |
306 | 314 | ||
307 | cx18_msleep_timeout(1, 0); | 315 | cx18_msleep_timeout(1, 0); |
308 | 316 | ||
309 | sw1_irq_enable(IRQ_CPU_TO_EPU | IRQ_APU_TO_EPU); | 317 | cx18_sw1_irq_enable(cx, IRQ_CPU_TO_EPU | IRQ_APU_TO_EPU); |
310 | sw2_irq_enable(IRQ_CPU_TO_EPU_ACK | IRQ_APU_TO_EPU_ACK); | 318 | cx18_sw2_irq_enable(cx, IRQ_CPU_TO_EPU_ACK | IRQ_APU_TO_EPU_ACK); |
311 | 319 | ||
312 | /* Only if the processor is not running */ | 320 | /* Only if the processor is not running */ |
313 | if (read_reg(CX18_PROC_SOFT_RESET) & 8) { | 321 | if (cx18_read_reg(cx, CX18_PROC_SOFT_RESET) & 8) { |
314 | int sz = load_apu_fw_direct("v4l-cx23418-apu.fw", | 322 | int sz = load_apu_fw_direct("v4l-cx23418-apu.fw", |
315 | cx->enc_mem, cx); | 323 | cx->enc_mem, cx); |
316 | 324 | ||
317 | write_enc(0xE51FF004, 0); | 325 | cx18_write_enc(cx, 0xE51FF004, 0); |
318 | write_enc(0xa00000, 4); /* todo: not hardcoded */ | 326 | cx18_write_enc(cx, 0xa00000, 4); /* todo: not hardcoded */ |
319 | write_reg(0x00010000, CX18_PROC_SOFT_RESET); /* Start APU */ | 327 | /* Start APU */ |
328 | cx18_write_reg(cx, 0x00010000, CX18_PROC_SOFT_RESET); | ||
320 | cx18_msleep_timeout(500, 0); | 329 | cx18_msleep_timeout(500, 0); |
321 | 330 | ||
322 | sz = sz <= 0 ? sz : load_cpu_fw_direct("v4l-cx23418-cpu.fw", | 331 | sz = sz <= 0 ? sz : load_cpu_fw_direct("v4l-cx23418-cpu.fw", |
@@ -326,9 +335,10 @@ int cx18_firmware_init(struct cx18 *cx) | |||
326 | int retries = 0; | 335 | int retries = 0; |
327 | 336 | ||
328 | /* start the CPU */ | 337 | /* start the CPU */ |
329 | write_reg(0x00080000, CX18_PROC_SOFT_RESET); | 338 | cx18_write_reg(cx, 0x00080000, CX18_PROC_SOFT_RESET); |
330 | while (retries++ < 50) { /* Loop for max 500mS */ | 339 | while (retries++ < 50) { /* Loop for max 500mS */ |
331 | if ((read_reg(CX18_PROC_SOFT_RESET) & 1) == 0) | 340 | if ((cx18_read_reg(cx, CX18_PROC_SOFT_RESET) |
341 | & 1) == 0) | ||
332 | break; | 342 | break; |
333 | cx18_msleep_timeout(10, 0); | 343 | cx18_msleep_timeout(10, 0); |
334 | } | 344 | } |
@@ -342,6 +352,6 @@ int cx18_firmware_init(struct cx18 *cx) | |||
342 | return -EIO; | 352 | return -EIO; |
343 | } | 353 | } |
344 | /* initialize GPIO */ | 354 | /* initialize GPIO */ |
345 | write_reg(0x14001400, 0xC78110); | 355 | cx18_write_reg(cx, 0x14001400, 0xC78110); |
346 | return 0; | 356 | return 0; |
347 | } | 357 | } |
diff --git a/drivers/media/video/cx18/cx18-gpio.c b/drivers/media/video/cx18/cx18-gpio.c index 3d495dba4983..0e560421989e 100644 --- a/drivers/media/video/cx18/cx18-gpio.c +++ b/drivers/media/video/cx18/cx18-gpio.c | |||
@@ -22,6 +22,7 @@ | |||
22 | */ | 22 | */ |
23 | 23 | ||
24 | #include "cx18-driver.h" | 24 | #include "cx18-driver.h" |
25 | #include "cx18-io.h" | ||
25 | #include "cx18-cards.h" | 26 | #include "cx18-cards.h" |
26 | #include "cx18-gpio.h" | 27 | #include "cx18-gpio.h" |
27 | #include "tuner-xc2028.h" | 28 | #include "tuner-xc2028.h" |
@@ -49,11 +50,11 @@ static void gpio_write(struct cx18 *cx) | |||
49 | u32 dir = cx->gpio_dir; | 50 | u32 dir = cx->gpio_dir; |
50 | u32 val = cx->gpio_val; | 51 | u32 val = cx->gpio_val; |
51 | 52 | ||
52 | write_reg((dir & 0xffff) << 16, CX18_REG_GPIO_DIR1); | 53 | cx18_write_reg(cx, (dir & 0xffff) << 16, CX18_REG_GPIO_DIR1); |
53 | write_reg(((dir & 0xffff) << 16) | (val & 0xffff), | 54 | cx18_write_reg(cx, ((dir & 0xffff) << 16) | (val & 0xffff), |
54 | CX18_REG_GPIO_OUT1); | 55 | CX18_REG_GPIO_OUT1); |
55 | write_reg(dir & 0xffff0000, CX18_REG_GPIO_DIR2); | 56 | cx18_write_reg(cx, dir & 0xffff0000, CX18_REG_GPIO_DIR2); |
56 | write_reg_sync((dir & 0xffff0000) | ((val & 0xffff0000) >> 16), | 57 | cx18_write_reg_sync(cx, (dir & 0xffff0000) | ((val & 0xffff0000) >> 16), |
57 | CX18_REG_GPIO_OUT2); | 58 | CX18_REG_GPIO_OUT2); |
58 | } | 59 | } |
59 | 60 | ||
@@ -141,15 +142,17 @@ void cx18_gpio_init(struct cx18 *cx) | |||
141 | } | 142 | } |
142 | 143 | ||
143 | CX18_DEBUG_INFO("GPIO initial dir: %08x/%08x out: %08x/%08x\n", | 144 | CX18_DEBUG_INFO("GPIO initial dir: %08x/%08x out: %08x/%08x\n", |
144 | read_reg(CX18_REG_GPIO_DIR1), read_reg(CX18_REG_GPIO_DIR2), | 145 | cx18_read_reg(cx, CX18_REG_GPIO_DIR1), |
145 | read_reg(CX18_REG_GPIO_OUT1), read_reg(CX18_REG_GPIO_OUT2)); | 146 | cx18_read_reg(cx, CX18_REG_GPIO_DIR2), |
147 | cx18_read_reg(cx, CX18_REG_GPIO_OUT1), | ||
148 | cx18_read_reg(cx, CX18_REG_GPIO_OUT2)); | ||
146 | 149 | ||
147 | gpio_write(cx); | 150 | gpio_write(cx); |
148 | mutex_unlock(&cx->gpio_lock); | 151 | mutex_unlock(&cx->gpio_lock); |
149 | } | 152 | } |
150 | 153 | ||
151 | /* Xceive tuner reset function */ | 154 | /* Xceive tuner reset function */ |
152 | int cx18_reset_tuner_gpio(void *dev, int cmd, int value) | 155 | int cx18_reset_tuner_gpio(void *dev, int component, int cmd, int value) |
153 | { | 156 | { |
154 | struct i2c_algo_bit_data *algo = dev; | 157 | struct i2c_algo_bit_data *algo = dev; |
155 | struct cx18_i2c_algo_callback_data *cb_data = algo->data; | 158 | struct cx18_i2c_algo_callback_data *cb_data = algo->data; |
diff --git a/drivers/media/video/cx18/cx18-gpio.h b/drivers/media/video/cx18/cx18-gpio.h index 22cd7ddf8554..beb7424b9944 100644 --- a/drivers/media/video/cx18/cx18-gpio.h +++ b/drivers/media/video/cx18/cx18-gpio.h | |||
@@ -23,5 +23,5 @@ | |||
23 | void cx18_gpio_init(struct cx18 *cx); | 23 | void cx18_gpio_init(struct cx18 *cx); |
24 | void cx18_reset_i2c_slaves_gpio(struct cx18 *cx); | 24 | void cx18_reset_i2c_slaves_gpio(struct cx18 *cx); |
25 | void cx18_reset_ir_gpio(void *data); | 25 | void cx18_reset_ir_gpio(void *data); |
26 | int cx18_reset_tuner_gpio(void *dev, int cmd, int value); | 26 | int cx18_reset_tuner_gpio(void *dev, int component, int cmd, int value); |
27 | int cx18_gpio(struct cx18 *cx, unsigned int command, void *arg); | 27 | int cx18_gpio(struct cx18 *cx, unsigned int command, void *arg); |
diff --git a/drivers/media/video/cx18/cx18-i2c.c b/drivers/media/video/cx18/cx18-i2c.c index 6023ba3bd3a6..aa09e557b195 100644 --- a/drivers/media/video/cx18/cx18-i2c.c +++ b/drivers/media/video/cx18/cx18-i2c.c | |||
@@ -22,13 +22,12 @@ | |||
22 | */ | 22 | */ |
23 | 23 | ||
24 | #include "cx18-driver.h" | 24 | #include "cx18-driver.h" |
25 | #include "cx18-io.h" | ||
25 | #include "cx18-cards.h" | 26 | #include "cx18-cards.h" |
26 | #include "cx18-gpio.h" | 27 | #include "cx18-gpio.h" |
27 | #include "cx18-av-core.h" | 28 | #include "cx18-av-core.h" |
28 | #include "cx18-i2c.h" | 29 | #include "cx18-i2c.h" |
29 | 30 | ||
30 | #include <media/ir-kbd-i2c.h> | ||
31 | |||
32 | #define CX18_REG_I2C_1_WR 0xf15000 | 31 | #define CX18_REG_I2C_1_WR 0xf15000 |
33 | #define CX18_REG_I2C_1_RD 0xf15008 | 32 | #define CX18_REG_I2C_1_RD 0xf15008 |
34 | #define CX18_REG_I2C_2_WR 0xf25100 | 33 | #define CX18_REG_I2C_2_WR 0xf25100 |
@@ -158,12 +157,12 @@ static void cx18_setscl(void *data, int state) | |||
158 | struct cx18 *cx = ((struct cx18_i2c_algo_callback_data *)data)->cx; | 157 | struct cx18 *cx = ((struct cx18_i2c_algo_callback_data *)data)->cx; |
159 | int bus_index = ((struct cx18_i2c_algo_callback_data *)data)->bus_index; | 158 | int bus_index = ((struct cx18_i2c_algo_callback_data *)data)->bus_index; |
160 | u32 addr = bus_index ? CX18_REG_I2C_2_WR : CX18_REG_I2C_1_WR; | 159 | u32 addr = bus_index ? CX18_REG_I2C_2_WR : CX18_REG_I2C_1_WR; |
161 | u32 r = read_reg(addr); | 160 | u32 r = cx18_read_reg(cx, addr); |
162 | 161 | ||
163 | if (state) | 162 | if (state) |
164 | write_reg_sync(r | SETSCL_BIT, addr); | 163 | cx18_write_reg_sync(cx, r | SETSCL_BIT, addr); |
165 | else | 164 | else |
166 | write_reg_sync(r & ~SETSCL_BIT, addr); | 165 | cx18_write_reg_sync(cx, r & ~SETSCL_BIT, addr); |
167 | } | 166 | } |
168 | 167 | ||
169 | static void cx18_setsda(void *data, int state) | 168 | static void cx18_setsda(void *data, int state) |
@@ -171,12 +170,12 @@ static void cx18_setsda(void *data, int state) | |||
171 | struct cx18 *cx = ((struct cx18_i2c_algo_callback_data *)data)->cx; | 170 | struct cx18 *cx = ((struct cx18_i2c_algo_callback_data *)data)->cx; |
172 | int bus_index = ((struct cx18_i2c_algo_callback_data *)data)->bus_index; | 171 | int bus_index = ((struct cx18_i2c_algo_callback_data *)data)->bus_index; |
173 | u32 addr = bus_index ? CX18_REG_I2C_2_WR : CX18_REG_I2C_1_WR; | 172 | u32 addr = bus_index ? CX18_REG_I2C_2_WR : CX18_REG_I2C_1_WR; |
174 | u32 r = read_reg(addr); | 173 | u32 r = cx18_read_reg(cx, addr); |
175 | 174 | ||
176 | if (state) | 175 | if (state) |
177 | write_reg_sync(r | SETSDL_BIT, addr); | 176 | cx18_write_reg_sync(cx, r | SETSDL_BIT, addr); |
178 | else | 177 | else |
179 | write_reg_sync(r & ~SETSDL_BIT, addr); | 178 | cx18_write_reg_sync(cx, r & ~SETSDL_BIT, addr); |
180 | } | 179 | } |
181 | 180 | ||
182 | static int cx18_getscl(void *data) | 181 | static int cx18_getscl(void *data) |
@@ -185,7 +184,7 @@ static int cx18_getscl(void *data) | |||
185 | int bus_index = ((struct cx18_i2c_algo_callback_data *)data)->bus_index; | 184 | int bus_index = ((struct cx18_i2c_algo_callback_data *)data)->bus_index; |
186 | u32 addr = bus_index ? CX18_REG_I2C_2_RD : CX18_REG_I2C_1_RD; | 185 | u32 addr = bus_index ? CX18_REG_I2C_2_RD : CX18_REG_I2C_1_RD; |
187 | 186 | ||
188 | return read_reg(addr) & GETSCL_BIT; | 187 | return cx18_read_reg(cx, addr) & GETSCL_BIT; |
189 | } | 188 | } |
190 | 189 | ||
191 | static int cx18_getsda(void *data) | 190 | static int cx18_getsda(void *data) |
@@ -194,7 +193,7 @@ static int cx18_getsda(void *data) | |||
194 | int bus_index = ((struct cx18_i2c_algo_callback_data *)data)->bus_index; | 193 | int bus_index = ((struct cx18_i2c_algo_callback_data *)data)->bus_index; |
195 | u32 addr = bus_index ? CX18_REG_I2C_2_RD : CX18_REG_I2C_1_RD; | 194 | u32 addr = bus_index ? CX18_REG_I2C_2_RD : CX18_REG_I2C_1_RD; |
196 | 195 | ||
197 | return read_reg(addr) & GETSDL_BIT; | 196 | return cx18_read_reg(cx, addr) & GETSDL_BIT; |
198 | } | 197 | } |
199 | 198 | ||
200 | /* template for i2c-bit-algo */ | 199 | /* template for i2c-bit-algo */ |
@@ -394,29 +393,33 @@ int init_cx18_i2c(struct cx18 *cx) | |||
394 | cx->i2c_adap[i].dev.parent = &cx->dev->dev; | 393 | cx->i2c_adap[i].dev.parent = &cx->dev->dev; |
395 | } | 394 | } |
396 | 395 | ||
397 | if (read_reg(CX18_REG_I2C_2_WR) != 0x0003c02f) { | 396 | if (cx18_read_reg(cx, CX18_REG_I2C_2_WR) != 0x0003c02f) { |
398 | /* Reset/Unreset I2C hardware block */ | 397 | /* Reset/Unreset I2C hardware block */ |
399 | write_reg(0x10000000, 0xc71004); /* Clock select 220MHz */ | 398 | /* Clock select 220MHz */ |
400 | write_reg_sync(0x10001000, 0xc71024); /* Clock Enable */ | 399 | cx18_write_reg(cx, 0x10000000, 0xc71004); |
400 | /* Clock Enable */ | ||
401 | cx18_write_reg_sync(cx, 0x10001000, 0xc71024); | ||
401 | } | 402 | } |
402 | /* courtesy of Steven Toth <stoth@hauppauge.com> */ | 403 | /* courtesy of Steven Toth <stoth@hauppauge.com> */ |
403 | write_reg_sync(0x00c00000, 0xc7001c); | 404 | cx18_write_reg_sync(cx, 0x00c00000, 0xc7001c); |
404 | mdelay(10); | 405 | mdelay(10); |
405 | write_reg_sync(0x00c000c0, 0xc7001c); | 406 | cx18_write_reg_sync(cx, 0x00c000c0, 0xc7001c); |
406 | mdelay(10); | 407 | mdelay(10); |
407 | write_reg_sync(0x00c00000, 0xc7001c); | 408 | cx18_write_reg_sync(cx, 0x00c00000, 0xc7001c); |
408 | mdelay(10); | 409 | mdelay(10); |
409 | 410 | ||
410 | write_reg_sync(0x00c00000, 0xc730c8); /* Set to edge-triggered intrs. */ | 411 | /* Set to edge-triggered intrs. */ |
411 | write_reg_sync(0x00c00000, 0xc730c4); /* Clear any stale intrs */ | 412 | cx18_write_reg_sync(cx, 0x00c00000, 0xc730c8); |
413 | /* Clear any stale intrs */ | ||
414 | cx18_write_reg_sync(cx, 0x00c00000, 0xc730c4); | ||
412 | 415 | ||
413 | /* Hw I2C1 Clock Freq ~100kHz */ | 416 | /* Hw I2C1 Clock Freq ~100kHz */ |
414 | write_reg_sync(0x00021c0f & ~4, CX18_REG_I2C_1_WR); | 417 | cx18_write_reg_sync(cx, 0x00021c0f & ~4, CX18_REG_I2C_1_WR); |
415 | cx18_setscl(&cx->i2c_algo_cb_data[0], 1); | 418 | cx18_setscl(&cx->i2c_algo_cb_data[0], 1); |
416 | cx18_setsda(&cx->i2c_algo_cb_data[0], 1); | 419 | cx18_setsda(&cx->i2c_algo_cb_data[0], 1); |
417 | 420 | ||
418 | /* Hw I2C2 Clock Freq ~100kHz */ | 421 | /* Hw I2C2 Clock Freq ~100kHz */ |
419 | write_reg_sync(0x00021c0f & ~4, CX18_REG_I2C_2_WR); | 422 | cx18_write_reg_sync(cx, 0x00021c0f & ~4, CX18_REG_I2C_2_WR); |
420 | cx18_setscl(&cx->i2c_algo_cb_data[1], 1); | 423 | cx18_setscl(&cx->i2c_algo_cb_data[1], 1); |
421 | cx18_setsda(&cx->i2c_algo_cb_data[1], 1); | 424 | cx18_setsda(&cx->i2c_algo_cb_data[1], 1); |
422 | 425 | ||
@@ -430,8 +433,10 @@ void exit_cx18_i2c(struct cx18 *cx) | |||
430 | { | 433 | { |
431 | int i; | 434 | int i; |
432 | CX18_DEBUG_I2C("i2c exit\n"); | 435 | CX18_DEBUG_I2C("i2c exit\n"); |
433 | write_reg(read_reg(CX18_REG_I2C_1_WR) | 4, CX18_REG_I2C_1_WR); | 436 | cx18_write_reg(cx, cx18_read_reg(cx, CX18_REG_I2C_1_WR) | 4, |
434 | write_reg(read_reg(CX18_REG_I2C_2_WR) | 4, CX18_REG_I2C_2_WR); | 437 | CX18_REG_I2C_1_WR); |
438 | cx18_write_reg(cx, cx18_read_reg(cx, CX18_REG_I2C_2_WR) | 4, | ||
439 | CX18_REG_I2C_2_WR); | ||
435 | 440 | ||
436 | for (i = 0; i < 2; i++) { | 441 | for (i = 0; i < 2; i++) { |
437 | i2c_del_adapter(&cx->i2c_adap[i]); | 442 | i2c_del_adapter(&cx->i2c_adap[i]); |
diff --git a/drivers/media/video/cx18/cx18-io.c b/drivers/media/video/cx18/cx18-io.c new file mode 100644 index 000000000000..700ab9439c16 --- /dev/null +++ b/drivers/media/video/cx18/cx18-io.c | |||
@@ -0,0 +1,254 @@ | |||
1 | /* | ||
2 | * cx18 driver PCI memory mapped IO access routines | ||
3 | * | ||
4 | * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> | ||
5 | * Copyright (C) 2008 Andy Walls <awalls@radix.net> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA | ||
20 | * 02111-1307 USA | ||
21 | */ | ||
22 | |||
23 | #include "cx18-driver.h" | ||
24 | #include "cx18-io.h" | ||
25 | #include "cx18-irq.h" | ||
26 | |||
27 | void cx18_log_statistics(struct cx18 *cx) | ||
28 | { | ||
29 | int i; | ||
30 | |||
31 | if (!(cx18_debug & CX18_DBGFLG_INFO)) | ||
32 | return; | ||
33 | |||
34 | for (i = 0; i <= CX18_MAX_MMIO_RETRIES; i++) | ||
35 | CX18_DEBUG_INFO("retried_write[%d] = %d\n", i, | ||
36 | atomic_read(&cx->mmio_stats.retried_write[i])); | ||
37 | for (i = 0; i <= CX18_MAX_MMIO_RETRIES; i++) | ||
38 | CX18_DEBUG_INFO("retried_read[%d] = %d\n", i, | ||
39 | atomic_read(&cx->mmio_stats.retried_read[i])); | ||
40 | return; | ||
41 | } | ||
42 | |||
43 | void cx18_raw_writel_retry(struct cx18 *cx, u32 val, void __iomem *addr) | ||
44 | { | ||
45 | int i; | ||
46 | for (i = 0; i < CX18_MAX_MMIO_RETRIES; i++) { | ||
47 | cx18_raw_writel_noretry(cx, val, addr); | ||
48 | if (val == cx18_raw_readl_noretry(cx, addr)) | ||
49 | break; | ||
50 | } | ||
51 | cx18_log_write_retries(cx, i, addr); | ||
52 | } | ||
53 | |||
54 | u32 cx18_raw_readl_retry(struct cx18 *cx, const void __iomem *addr) | ||
55 | { | ||
56 | int i; | ||
57 | u32 val; | ||
58 | for (i = 0; i < CX18_MAX_MMIO_RETRIES; i++) { | ||
59 | val = cx18_raw_readl_noretry(cx, addr); | ||
60 | if (val != 0xffffffff) /* PCI bus read error */ | ||
61 | break; | ||
62 | } | ||
63 | cx18_log_read_retries(cx, i, addr); | ||
64 | return val; | ||
65 | } | ||
66 | |||
67 | u16 cx18_raw_readw_retry(struct cx18 *cx, const void __iomem *addr) | ||
68 | { | ||
69 | int i; | ||
70 | u16 val; | ||
71 | for (i = 0; i < CX18_MAX_MMIO_RETRIES; i++) { | ||
72 | val = cx18_raw_readw_noretry(cx, addr); | ||
73 | if (val != 0xffff) /* PCI bus read error */ | ||
74 | break; | ||
75 | } | ||
76 | cx18_log_read_retries(cx, i, addr); | ||
77 | return val; | ||
78 | } | ||
79 | |||
80 | void cx18_writel_retry(struct cx18 *cx, u32 val, void __iomem *addr) | ||
81 | { | ||
82 | int i; | ||
83 | for (i = 0; i < CX18_MAX_MMIO_RETRIES; i++) { | ||
84 | cx18_writel_noretry(cx, val, addr); | ||
85 | if (val == cx18_readl_noretry(cx, addr)) | ||
86 | break; | ||
87 | } | ||
88 | cx18_log_write_retries(cx, i, addr); | ||
89 | } | ||
90 | |||
91 | void cx18_writew_retry(struct cx18 *cx, u16 val, void __iomem *addr) | ||
92 | { | ||
93 | int i; | ||
94 | for (i = 0; i < CX18_MAX_MMIO_RETRIES; i++) { | ||
95 | cx18_writew_noretry(cx, val, addr); | ||
96 | if (val == cx18_readw_noretry(cx, addr)) | ||
97 | break; | ||
98 | } | ||
99 | cx18_log_write_retries(cx, i, addr); | ||
100 | } | ||
101 | |||
102 | void cx18_writeb_retry(struct cx18 *cx, u8 val, void __iomem *addr) | ||
103 | { | ||
104 | int i; | ||
105 | for (i = 0; i < CX18_MAX_MMIO_RETRIES; i++) { | ||
106 | cx18_writeb_noretry(cx, val, addr); | ||
107 | if (val == cx18_readb_noretry(cx, addr)) | ||
108 | break; | ||
109 | } | ||
110 | cx18_log_write_retries(cx, i, addr); | ||
111 | } | ||
112 | |||
113 | u32 cx18_readl_retry(struct cx18 *cx, const void __iomem *addr) | ||
114 | { | ||
115 | int i; | ||
116 | u32 val; | ||
117 | for (i = 0; i < CX18_MAX_MMIO_RETRIES; i++) { | ||
118 | val = cx18_readl_noretry(cx, addr); | ||
119 | if (val != 0xffffffff) /* PCI bus read error */ | ||
120 | break; | ||
121 | } | ||
122 | cx18_log_read_retries(cx, i, addr); | ||
123 | return val; | ||
124 | } | ||
125 | |||
126 | u16 cx18_readw_retry(struct cx18 *cx, const void __iomem *addr) | ||
127 | { | ||
128 | int i; | ||
129 | u16 val; | ||
130 | for (i = 0; i < CX18_MAX_MMIO_RETRIES; i++) { | ||
131 | val = cx18_readw_noretry(cx, addr); | ||
132 | if (val != 0xffff) /* PCI bus read error */ | ||
133 | break; | ||
134 | } | ||
135 | cx18_log_read_retries(cx, i, addr); | ||
136 | return val; | ||
137 | } | ||
138 | |||
139 | u8 cx18_readb_retry(struct cx18 *cx, const void __iomem *addr) | ||
140 | { | ||
141 | int i; | ||
142 | u8 val; | ||
143 | for (i = 0; i < CX18_MAX_MMIO_RETRIES; i++) { | ||
144 | val = cx18_readb_noretry(cx, addr); | ||
145 | if (val != 0xff) /* PCI bus read error */ | ||
146 | break; | ||
147 | } | ||
148 | cx18_log_read_retries(cx, i, addr); | ||
149 | return val; | ||
150 | } | ||
151 | |||
152 | void cx18_memcpy_fromio(struct cx18 *cx, void *to, | ||
153 | const void __iomem *from, unsigned int len) | ||
154 | { | ||
155 | const u8 __iomem *src = from; | ||
156 | u8 *dst = to; | ||
157 | |||
158 | /* Align reads on the CX23418's addresses */ | ||
159 | if ((len > 0) && ((unsigned long) src & 1)) { | ||
160 | *dst = cx18_readb(cx, src); | ||
161 | len--; | ||
162 | dst++; | ||
163 | src++; | ||
164 | } | ||
165 | if ((len > 1) && ((unsigned long) src & 2)) { | ||
166 | *((u16 *)dst) = cx18_raw_readw(cx, src); | ||
167 | len -= 2; | ||
168 | dst += 2; | ||
169 | src += 2; | ||
170 | } | ||
171 | while (len > 3) { | ||
172 | *((u32 *)dst) = cx18_raw_readl(cx, src); | ||
173 | len -= 4; | ||
174 | dst += 4; | ||
175 | src += 4; | ||
176 | } | ||
177 | if (len > 1) { | ||
178 | *((u16 *)dst) = cx18_raw_readw(cx, src); | ||
179 | len -= 2; | ||
180 | dst += 2; | ||
181 | src += 2; | ||
182 | } | ||
183 | if (len > 0) | ||
184 | *dst = cx18_readb(cx, src); | ||
185 | } | ||
186 | |||
187 | void cx18_memset_io(struct cx18 *cx, void __iomem *addr, int val, size_t count) | ||
188 | { | ||
189 | u8 __iomem *dst = addr; | ||
190 | u16 val2 = val | (val << 8); | ||
191 | u32 val4 = val2 | (val2 << 16); | ||
192 | |||
193 | /* Align writes on the CX23418's addresses */ | ||
194 | if ((count > 0) && ((unsigned long)dst & 1)) { | ||
195 | cx18_writeb(cx, (u8) val, dst); | ||
196 | count--; | ||
197 | dst++; | ||
198 | } | ||
199 | if ((count > 1) && ((unsigned long)dst & 2)) { | ||
200 | cx18_writew(cx, val2, dst); | ||
201 | count -= 2; | ||
202 | dst += 2; | ||
203 | } | ||
204 | while (count > 3) { | ||
205 | cx18_writel(cx, val4, dst); | ||
206 | count -= 4; | ||
207 | dst += 4; | ||
208 | } | ||
209 | if (count > 1) { | ||
210 | cx18_writew(cx, val2, dst); | ||
211 | count -= 2; | ||
212 | dst += 2; | ||
213 | } | ||
214 | if (count > 0) | ||
215 | cx18_writeb(cx, (u8) val, dst); | ||
216 | } | ||
217 | |||
218 | void cx18_sw1_irq_enable(struct cx18 *cx, u32 val) | ||
219 | { | ||
220 | u32 r; | ||
221 | cx18_write_reg(cx, val, SW1_INT_STATUS); | ||
222 | r = cx18_read_reg(cx, SW1_INT_ENABLE_PCI); | ||
223 | cx18_write_reg(cx, r | val, SW1_INT_ENABLE_PCI); | ||
224 | } | ||
225 | |||
226 | void cx18_sw1_irq_disable(struct cx18 *cx, u32 val) | ||
227 | { | ||
228 | u32 r; | ||
229 | r = cx18_read_reg(cx, SW1_INT_ENABLE_PCI); | ||
230 | cx18_write_reg(cx, r & ~val, SW1_INT_ENABLE_PCI); | ||
231 | } | ||
232 | |||
233 | void cx18_sw2_irq_enable(struct cx18 *cx, u32 val) | ||
234 | { | ||
235 | u32 r; | ||
236 | cx18_write_reg(cx, val, SW2_INT_STATUS); | ||
237 | r = cx18_read_reg(cx, SW2_INT_ENABLE_PCI); | ||
238 | cx18_write_reg(cx, r | val, SW2_INT_ENABLE_PCI); | ||
239 | } | ||
240 | |||
241 | void cx18_sw2_irq_disable(struct cx18 *cx, u32 val) | ||
242 | { | ||
243 | u32 r; | ||
244 | r = cx18_read_reg(cx, SW2_INT_ENABLE_PCI); | ||
245 | cx18_write_reg(cx, r & ~val, SW2_INT_ENABLE_PCI); | ||
246 | } | ||
247 | |||
248 | void cx18_setup_page(struct cx18 *cx, u32 addr) | ||
249 | { | ||
250 | u32 val; | ||
251 | val = cx18_read_reg(cx, 0xD000F8); | ||
252 | val = (val & ~0x1f00) | ((addr >> 17) & 0x1f00); | ||
253 | cx18_write_reg(cx, val, 0xD000F8); | ||
254 | } | ||
diff --git a/drivers/media/video/cx18/cx18-io.h b/drivers/media/video/cx18/cx18-io.h new file mode 100644 index 000000000000..197d4fbd9f95 --- /dev/null +++ b/drivers/media/video/cx18/cx18-io.h | |||
@@ -0,0 +1,378 @@ | |||
1 | /* | ||
2 | * cx18 driver PCI memory mapped IO access routines | ||
3 | * | ||
4 | * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> | ||
5 | * Copyright (C) 2008 Andy Walls <awalls@radix.net> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA | ||
20 | * 02111-1307 USA | ||
21 | */ | ||
22 | |||
23 | #ifndef CX18_IO_H | ||
24 | #define CX18_IO_H | ||
25 | |||
26 | #include "cx18-driver.h" | ||
27 | |||
28 | static inline void cx18_io_delay(struct cx18 *cx) | ||
29 | { | ||
30 | if (cx->options.mmio_ndelay) | ||
31 | ndelay(cx->options.mmio_ndelay); | ||
32 | } | ||
33 | |||
34 | /* | ||
35 | * Readback and retry of MMIO access for reliability: | ||
36 | * The concept was suggested by Steve Toth <stoth@linuxtv.org>. | ||
37 | * The implmentation is the fault of Andy Walls <awalls@radix.net>. | ||
38 | */ | ||
39 | |||
40 | /* Statistics gathering */ | ||
41 | static inline | ||
42 | void cx18_log_write_retries(struct cx18 *cx, int i, const void *addr) | ||
43 | { | ||
44 | if (i > CX18_MAX_MMIO_RETRIES) | ||
45 | i = CX18_MAX_MMIO_RETRIES; | ||
46 | atomic_inc(&cx->mmio_stats.retried_write[i]); | ||
47 | return; | ||
48 | } | ||
49 | |||
50 | static inline | ||
51 | void cx18_log_read_retries(struct cx18 *cx, int i, const void *addr) | ||
52 | { | ||
53 | if (i > CX18_MAX_MMIO_RETRIES) | ||
54 | i = CX18_MAX_MMIO_RETRIES; | ||
55 | atomic_inc(&cx->mmio_stats.retried_read[i]); | ||
56 | return; | ||
57 | } | ||
58 | |||
59 | void cx18_log_statistics(struct cx18 *cx); | ||
60 | |||
61 | /* Non byteswapping memory mapped IO */ | ||
62 | static inline | ||
63 | void cx18_raw_writel_noretry(struct cx18 *cx, u32 val, void __iomem *addr) | ||
64 | { | ||
65 | __raw_writel(val, addr); | ||
66 | cx18_io_delay(cx); | ||
67 | } | ||
68 | |||
69 | void cx18_raw_writel_retry(struct cx18 *cx, u32 val, void __iomem *addr); | ||
70 | |||
71 | static inline void cx18_raw_writel(struct cx18 *cx, u32 val, void __iomem *addr) | ||
72 | { | ||
73 | if (cx18_retry_mmio) | ||
74 | cx18_raw_writel_retry(cx, val, addr); | ||
75 | else | ||
76 | cx18_raw_writel_noretry(cx, val, addr); | ||
77 | } | ||
78 | |||
79 | |||
80 | static inline | ||
81 | u32 cx18_raw_readl_noretry(struct cx18 *cx, const void __iomem *addr) | ||
82 | { | ||
83 | u32 ret = __raw_readl(addr); | ||
84 | cx18_io_delay(cx); | ||
85 | return ret; | ||
86 | } | ||
87 | |||
88 | u32 cx18_raw_readl_retry(struct cx18 *cx, const void __iomem *addr); | ||
89 | |||
90 | static inline u32 cx18_raw_readl(struct cx18 *cx, const void __iomem *addr) | ||
91 | { | ||
92 | if (cx18_retry_mmio) | ||
93 | return cx18_raw_readl_retry(cx, addr); | ||
94 | |||
95 | return cx18_raw_readl_noretry(cx, addr); | ||
96 | } | ||
97 | |||
98 | |||
99 | static inline | ||
100 | u16 cx18_raw_readw_noretry(struct cx18 *cx, const void __iomem *addr) | ||
101 | { | ||
102 | u16 ret = __raw_readw(addr); | ||
103 | cx18_io_delay(cx); | ||
104 | return ret; | ||
105 | } | ||
106 | |||
107 | u16 cx18_raw_readw_retry(struct cx18 *cx, const void __iomem *addr); | ||
108 | |||
109 | static inline u16 cx18_raw_readw(struct cx18 *cx, const void __iomem *addr) | ||
110 | { | ||
111 | if (cx18_retry_mmio) | ||
112 | return cx18_raw_readw_retry(cx, addr); | ||
113 | |||
114 | return cx18_raw_readw_noretry(cx, addr); | ||
115 | } | ||
116 | |||
117 | |||
118 | /* Normal memory mapped IO */ | ||
119 | static inline | ||
120 | void cx18_writel_noretry(struct cx18 *cx, u32 val, void __iomem *addr) | ||
121 | { | ||
122 | writel(val, addr); | ||
123 | cx18_io_delay(cx); | ||
124 | } | ||
125 | |||
126 | void cx18_writel_retry(struct cx18 *cx, u32 val, void __iomem *addr); | ||
127 | |||
128 | static inline void cx18_writel(struct cx18 *cx, u32 val, void __iomem *addr) | ||
129 | { | ||
130 | if (cx18_retry_mmio) | ||
131 | cx18_writel_retry(cx, val, addr); | ||
132 | else | ||
133 | cx18_writel_noretry(cx, val, addr); | ||
134 | } | ||
135 | |||
136 | |||
137 | static inline | ||
138 | void cx18_writew_noretry(struct cx18 *cx, u16 val, void __iomem *addr) | ||
139 | { | ||
140 | writew(val, addr); | ||
141 | cx18_io_delay(cx); | ||
142 | } | ||
143 | |||
144 | void cx18_writew_retry(struct cx18 *cx, u16 val, void __iomem *addr); | ||
145 | |||
146 | static inline void cx18_writew(struct cx18 *cx, u16 val, void __iomem *addr) | ||
147 | { | ||
148 | if (cx18_retry_mmio) | ||
149 | cx18_writew_retry(cx, val, addr); | ||
150 | else | ||
151 | cx18_writew_noretry(cx, val, addr); | ||
152 | } | ||
153 | |||
154 | |||
155 | static inline | ||
156 | void cx18_writeb_noretry(struct cx18 *cx, u8 val, void __iomem *addr) | ||
157 | { | ||
158 | writeb(val, addr); | ||
159 | cx18_io_delay(cx); | ||
160 | } | ||
161 | |||
162 | void cx18_writeb_retry(struct cx18 *cx, u8 val, void __iomem *addr); | ||
163 | |||
164 | static inline void cx18_writeb(struct cx18 *cx, u8 val, void __iomem *addr) | ||
165 | { | ||
166 | if (cx18_retry_mmio) | ||
167 | cx18_writeb_retry(cx, val, addr); | ||
168 | else | ||
169 | cx18_writeb_noretry(cx, val, addr); | ||
170 | } | ||
171 | |||
172 | |||
173 | static inline u32 cx18_readl_noretry(struct cx18 *cx, const void __iomem *addr) | ||
174 | { | ||
175 | u32 ret = readl(addr); | ||
176 | cx18_io_delay(cx); | ||
177 | return ret; | ||
178 | } | ||
179 | |||
180 | u32 cx18_readl_retry(struct cx18 *cx, const void __iomem *addr); | ||
181 | |||
182 | static inline u32 cx18_readl(struct cx18 *cx, const void __iomem *addr) | ||
183 | { | ||
184 | if (cx18_retry_mmio) | ||
185 | return cx18_readl_retry(cx, addr); | ||
186 | |||
187 | return cx18_readl_noretry(cx, addr); | ||
188 | } | ||
189 | |||
190 | |||
191 | static inline u16 cx18_readw_noretry(struct cx18 *cx, const void __iomem *addr) | ||
192 | { | ||
193 | u16 ret = readw(addr); | ||
194 | cx18_io_delay(cx); | ||
195 | return ret; | ||
196 | } | ||
197 | |||
198 | u16 cx18_readw_retry(struct cx18 *cx, const void __iomem *addr); | ||
199 | |||
200 | static inline u16 cx18_readw(struct cx18 *cx, const void __iomem *addr) | ||
201 | { | ||
202 | if (cx18_retry_mmio) | ||
203 | return cx18_readw_retry(cx, addr); | ||
204 | |||
205 | return cx18_readw_noretry(cx, addr); | ||
206 | } | ||
207 | |||
208 | |||
209 | static inline u8 cx18_readb_noretry(struct cx18 *cx, const void __iomem *addr) | ||
210 | { | ||
211 | u8 ret = readb(addr); | ||
212 | cx18_io_delay(cx); | ||
213 | return ret; | ||
214 | } | ||
215 | |||
216 | u8 cx18_readb_retry(struct cx18 *cx, const void __iomem *addr); | ||
217 | |||
218 | static inline u8 cx18_readb(struct cx18 *cx, const void __iomem *addr) | ||
219 | { | ||
220 | if (cx18_retry_mmio) | ||
221 | return cx18_readb_retry(cx, addr); | ||
222 | |||
223 | return cx18_readb_noretry(cx, addr); | ||
224 | } | ||
225 | |||
226 | |||
227 | static inline | ||
228 | u32 cx18_write_sync_noretry(struct cx18 *cx, u32 val, void __iomem *addr) | ||
229 | { | ||
230 | cx18_writel_noretry(cx, val, addr); | ||
231 | return cx18_readl_noretry(cx, addr); | ||
232 | } | ||
233 | |||
234 | static inline | ||
235 | u32 cx18_write_sync_retry(struct cx18 *cx, u32 val, void __iomem *addr) | ||
236 | { | ||
237 | cx18_writel_retry(cx, val, addr); | ||
238 | return cx18_readl_retry(cx, addr); | ||
239 | } | ||
240 | |||
241 | static inline u32 cx18_write_sync(struct cx18 *cx, u32 val, void __iomem *addr) | ||
242 | { | ||
243 | if (cx18_retry_mmio) | ||
244 | return cx18_write_sync_retry(cx, val, addr); | ||
245 | |||
246 | return cx18_write_sync_noretry(cx, val, addr); | ||
247 | } | ||
248 | |||
249 | |||
250 | void cx18_memcpy_fromio(struct cx18 *cx, void *to, | ||
251 | const void __iomem *from, unsigned int len); | ||
252 | void cx18_memset_io(struct cx18 *cx, void __iomem *addr, int val, size_t count); | ||
253 | |||
254 | |||
255 | /* Access "register" region of CX23418 memory mapped I/O */ | ||
256 | static inline void cx18_write_reg_noretry(struct cx18 *cx, u32 val, u32 reg) | ||
257 | { | ||
258 | cx18_writel_noretry(cx, val, cx->reg_mem + reg); | ||
259 | } | ||
260 | |||
261 | static inline void cx18_write_reg_retry(struct cx18 *cx, u32 val, u32 reg) | ||
262 | { | ||
263 | cx18_writel_retry(cx, val, cx->reg_mem + reg); | ||
264 | } | ||
265 | |||
266 | static inline void cx18_write_reg(struct cx18 *cx, u32 val, u32 reg) | ||
267 | { | ||
268 | if (cx18_retry_mmio) | ||
269 | cx18_write_reg_retry(cx, val, reg); | ||
270 | else | ||
271 | cx18_write_reg_noretry(cx, val, reg); | ||
272 | } | ||
273 | |||
274 | |||
275 | static inline u32 cx18_read_reg_noretry(struct cx18 *cx, u32 reg) | ||
276 | { | ||
277 | return cx18_readl_noretry(cx, cx->reg_mem + reg); | ||
278 | } | ||
279 | |||
280 | static inline u32 cx18_read_reg_retry(struct cx18 *cx, u32 reg) | ||
281 | { | ||
282 | return cx18_readl_retry(cx, cx->reg_mem + reg); | ||
283 | } | ||
284 | |||
285 | static inline u32 cx18_read_reg(struct cx18 *cx, u32 reg) | ||
286 | { | ||
287 | if (cx18_retry_mmio) | ||
288 | return cx18_read_reg_retry(cx, reg); | ||
289 | |||
290 | return cx18_read_reg_noretry(cx, reg); | ||
291 | } | ||
292 | |||
293 | |||
294 | static inline u32 cx18_write_reg_sync_noretry(struct cx18 *cx, u32 val, u32 reg) | ||
295 | { | ||
296 | return cx18_write_sync_noretry(cx, val, cx->reg_mem + reg); | ||
297 | } | ||
298 | |||
299 | static inline u32 cx18_write_reg_sync_retry(struct cx18 *cx, u32 val, u32 reg) | ||
300 | { | ||
301 | return cx18_write_sync_retry(cx, val, cx->reg_mem + reg); | ||
302 | } | ||
303 | |||
304 | static inline u32 cx18_write_reg_sync(struct cx18 *cx, u32 val, u32 reg) | ||
305 | { | ||
306 | if (cx18_retry_mmio) | ||
307 | return cx18_write_reg_sync_retry(cx, val, reg); | ||
308 | |||
309 | return cx18_write_reg_sync_noretry(cx, val, reg); | ||
310 | } | ||
311 | |||
312 | |||
313 | /* Access "encoder memory" region of CX23418 memory mapped I/O */ | ||
314 | static inline void cx18_write_enc_noretry(struct cx18 *cx, u32 val, u32 addr) | ||
315 | { | ||
316 | cx18_writel_noretry(cx, val, cx->enc_mem + addr); | ||
317 | } | ||
318 | |||
319 | static inline void cx18_write_enc_retry(struct cx18 *cx, u32 val, u32 addr) | ||
320 | { | ||
321 | cx18_writel_retry(cx, val, cx->enc_mem + addr); | ||
322 | } | ||
323 | |||
324 | static inline void cx18_write_enc(struct cx18 *cx, u32 val, u32 addr) | ||
325 | { | ||
326 | if (cx18_retry_mmio) | ||
327 | cx18_write_enc_retry(cx, val, addr); | ||
328 | else | ||
329 | cx18_write_enc_noretry(cx, val, addr); | ||
330 | } | ||
331 | |||
332 | |||
333 | static inline u32 cx18_read_enc_noretry(struct cx18 *cx, u32 addr) | ||
334 | { | ||
335 | return cx18_readl_noretry(cx, cx->enc_mem + addr); | ||
336 | } | ||
337 | |||
338 | static inline u32 cx18_read_enc_retry(struct cx18 *cx, u32 addr) | ||
339 | { | ||
340 | return cx18_readl_retry(cx, cx->enc_mem + addr); | ||
341 | } | ||
342 | |||
343 | static inline u32 cx18_read_enc(struct cx18 *cx, u32 addr) | ||
344 | { | ||
345 | if (cx18_retry_mmio) | ||
346 | return cx18_read_enc_retry(cx, addr); | ||
347 | |||
348 | return cx18_read_enc_noretry(cx, addr); | ||
349 | } | ||
350 | |||
351 | static inline | ||
352 | u32 cx18_write_enc_sync_noretry(struct cx18 *cx, u32 val, u32 addr) | ||
353 | { | ||
354 | return cx18_write_sync_noretry(cx, val, cx->enc_mem + addr); | ||
355 | } | ||
356 | |||
357 | static inline | ||
358 | u32 cx18_write_enc_sync_retry(struct cx18 *cx, u32 val, u32 addr) | ||
359 | { | ||
360 | return cx18_write_sync_retry(cx, val, cx->enc_mem + addr); | ||
361 | } | ||
362 | |||
363 | static inline | ||
364 | u32 cx18_write_enc_sync(struct cx18 *cx, u32 val, u32 addr) | ||
365 | { | ||
366 | if (cx18_retry_mmio) | ||
367 | return cx18_write_enc_sync_retry(cx, val, addr); | ||
368 | |||
369 | return cx18_write_enc_sync_noretry(cx, val, addr); | ||
370 | } | ||
371 | |||
372 | void cx18_sw1_irq_enable(struct cx18 *cx, u32 val); | ||
373 | void cx18_sw1_irq_disable(struct cx18 *cx, u32 val); | ||
374 | void cx18_sw2_irq_enable(struct cx18 *cx, u32 val); | ||
375 | void cx18_sw2_irq_disable(struct cx18 *cx, u32 val); | ||
376 | void cx18_setup_page(struct cx18 *cx, u32 addr); | ||
377 | |||
378 | #endif /* CX18_IO_H */ | ||
diff --git a/drivers/media/video/cx18/cx18-ioctl.c b/drivers/media/video/cx18/cx18-ioctl.c index a7f839631d6a..f0ca50f5fdde 100644 --- a/drivers/media/video/cx18/cx18-ioctl.c +++ b/drivers/media/video/cx18/cx18-ioctl.c | |||
@@ -22,6 +22,7 @@ | |||
22 | */ | 22 | */ |
23 | 23 | ||
24 | #include "cx18-driver.h" | 24 | #include "cx18-driver.h" |
25 | #include "cx18-io.h" | ||
25 | #include "cx18-version.h" | 26 | #include "cx18-version.h" |
26 | #include "cx18-mailbox.h" | 27 | #include "cx18-mailbox.h" |
27 | #include "cx18-i2c.h" | 28 | #include "cx18-i2c.h" |
@@ -170,7 +171,6 @@ static int cx18_try_fmt_vid_cap(struct file *file, void *fh, | |||
170 | { | 171 | { |
171 | struct cx18_open_id *id = fh; | 172 | struct cx18_open_id *id = fh; |
172 | struct cx18 *cx = id->cx; | 173 | struct cx18 *cx = id->cx; |
173 | |||
174 | int w = fmt->fmt.pix.width; | 174 | int w = fmt->fmt.pix.width; |
175 | int h = fmt->fmt.pix.height; | 175 | int h = fmt->fmt.pix.height; |
176 | 176 | ||
@@ -202,8 +202,7 @@ static int cx18_s_fmt_vid_cap(struct file *file, void *fh, | |||
202 | struct cx18_open_id *id = fh; | 202 | struct cx18_open_id *id = fh; |
203 | struct cx18 *cx = id->cx; | 203 | struct cx18 *cx = id->cx; |
204 | int ret; | 204 | int ret; |
205 | int w = fmt->fmt.pix.width; | 205 | int w, h; |
206 | int h = fmt->fmt.pix.height; | ||
207 | 206 | ||
208 | ret = v4l2_prio_check(&cx->prio, &id->prio); | 207 | ret = v4l2_prio_check(&cx->prio, &id->prio); |
209 | if (ret) | 208 | if (ret) |
@@ -212,6 +211,8 @@ static int cx18_s_fmt_vid_cap(struct file *file, void *fh, | |||
212 | ret = cx18_try_fmt_vid_cap(file, fh, fmt); | 211 | ret = cx18_try_fmt_vid_cap(file, fh, fmt); |
213 | if (ret) | 212 | if (ret) |
214 | return ret; | 213 | return ret; |
214 | w = fmt->fmt.pix.width; | ||
215 | h = fmt->fmt.pix.height; | ||
215 | 216 | ||
216 | if (cx->params.width == w && cx->params.height == h) | 217 | if (cx->params.width == w && cx->params.height == h) |
217 | return 0; | 218 | return 0; |
@@ -286,9 +287,9 @@ static int cx18_cxc(struct cx18 *cx, unsigned int cmd, void *arg) | |||
286 | 287 | ||
287 | spin_lock_irqsave(&cx18_cards_lock, flags); | 288 | spin_lock_irqsave(&cx18_cards_lock, flags); |
288 | if (cmd == VIDIOC_DBG_G_REGISTER) | 289 | if (cmd == VIDIOC_DBG_G_REGISTER) |
289 | regs->val = read_enc(regs->reg); | 290 | regs->val = cx18_read_enc(cx, regs->reg); |
290 | else | 291 | else |
291 | write_enc(regs->val, regs->reg); | 292 | cx18_write_enc(cx, regs->val, regs->reg); |
292 | spin_unlock_irqrestore(&cx18_cards_lock, flags); | 293 | spin_unlock_irqrestore(&cx18_cards_lock, flags); |
293 | return 0; | 294 | return 0; |
294 | } | 295 | } |
@@ -345,7 +346,7 @@ static int cx18_querycap(struct file *file, void *fh, | |||
345 | 346 | ||
346 | strlcpy(vcap->driver, CX18_DRIVER_NAME, sizeof(vcap->driver)); | 347 | strlcpy(vcap->driver, CX18_DRIVER_NAME, sizeof(vcap->driver)); |
347 | strlcpy(vcap->card, cx->card_name, sizeof(vcap->card)); | 348 | strlcpy(vcap->card, cx->card_name, sizeof(vcap->card)); |
348 | strlcpy(vcap->bus_info, pci_name(cx->dev), sizeof(vcap->bus_info)); | 349 | snprintf(vcap->bus_info, sizeof(vcap->bus_info), "PCI:%s", pci_name(cx->dev)); |
349 | vcap->version = CX18_DRIVER_VERSION; /* version */ | 350 | vcap->version = CX18_DRIVER_VERSION; /* version */ |
350 | vcap->capabilities = cx->v4l2_cap; /* capabilities */ | 351 | vcap->capabilities = cx->v4l2_cap; /* capabilities */ |
351 | return 0; | 352 | return 0; |
@@ -622,6 +623,7 @@ static int cx18_encoder_cmd(struct file *file, void *fh, | |||
622 | { | 623 | { |
623 | struct cx18_open_id *id = fh; | 624 | struct cx18_open_id *id = fh; |
624 | struct cx18 *cx = id->cx; | 625 | struct cx18 *cx = id->cx; |
626 | u32 h; | ||
625 | 627 | ||
626 | switch (enc->cmd) { | 628 | switch (enc->cmd) { |
627 | case V4L2_ENC_CMD_START: | 629 | case V4L2_ENC_CMD_START: |
@@ -643,8 +645,14 @@ static int cx18_encoder_cmd(struct file *file, void *fh, | |||
643 | return -EPERM; | 645 | return -EPERM; |
644 | if (test_and_set_bit(CX18_F_I_ENC_PAUSED, &cx->i_flags)) | 646 | if (test_and_set_bit(CX18_F_I_ENC_PAUSED, &cx->i_flags)) |
645 | return 0; | 647 | return 0; |
648 | h = cx18_find_handle(cx); | ||
649 | if (h == CX18_INVALID_TASK_HANDLE) { | ||
650 | CX18_ERR("Can't find valid task handle for " | ||
651 | "V4L2_ENC_CMD_PAUSE\n"); | ||
652 | return -EBADFD; | ||
653 | } | ||
646 | cx18_mute(cx); | 654 | cx18_mute(cx); |
647 | cx18_vapi(cx, CX18_CPU_CAPTURE_PAUSE, 1, cx18_find_handle(cx)); | 655 | cx18_vapi(cx, CX18_CPU_CAPTURE_PAUSE, 1, h); |
648 | break; | 656 | break; |
649 | 657 | ||
650 | case V4L2_ENC_CMD_RESUME: | 658 | case V4L2_ENC_CMD_RESUME: |
@@ -654,7 +662,13 @@ static int cx18_encoder_cmd(struct file *file, void *fh, | |||
654 | return -EPERM; | 662 | return -EPERM; |
655 | if (!test_and_clear_bit(CX18_F_I_ENC_PAUSED, &cx->i_flags)) | 663 | if (!test_and_clear_bit(CX18_F_I_ENC_PAUSED, &cx->i_flags)) |
656 | return 0; | 664 | return 0; |
657 | cx18_vapi(cx, CX18_CPU_CAPTURE_RESUME, 1, cx18_find_handle(cx)); | 665 | h = cx18_find_handle(cx); |
666 | if (h == CX18_INVALID_TASK_HANDLE) { | ||
667 | CX18_ERR("Can't find valid task handle for " | ||
668 | "V4L2_ENC_CMD_RESUME\n"); | ||
669 | return -EBADFD; | ||
670 | } | ||
671 | cx18_vapi(cx, CX18_CPU_CAPTURE_RESUME, 1, h); | ||
658 | cx18_unmute(cx); | 672 | cx18_unmute(cx); |
659 | break; | 673 | break; |
660 | 674 | ||
@@ -731,12 +745,14 @@ static int cx18_log_status(struct file *file, void *fh) | |||
731 | continue; | 745 | continue; |
732 | CX18_INFO("Stream %s: status 0x%04lx, %d%% of %d KiB (%d buffers) in use\n", | 746 | CX18_INFO("Stream %s: status 0x%04lx, %d%% of %d KiB (%d buffers) in use\n", |
733 | s->name, s->s_flags, | 747 | s->name, s->s_flags, |
734 | (s->buffers - s->q_free.buffers) * 100 / s->buffers, | 748 | (s->buffers - atomic_read(&s->q_free.buffers)) |
749 | * 100 / s->buffers, | ||
735 | (s->buffers * s->buf_size) / 1024, s->buffers); | 750 | (s->buffers * s->buf_size) / 1024, s->buffers); |
736 | } | 751 | } |
737 | CX18_INFO("Read MPEG/VBI: %lld/%lld bytes\n", | 752 | CX18_INFO("Read MPEG/VBI: %lld/%lld bytes\n", |
738 | (long long)cx->mpg_data_received, | 753 | (long long)cx->mpg_data_received, |
739 | (long long)cx->vbi_data_inserted); | 754 | (long long)cx->vbi_data_inserted); |
755 | cx18_log_statistics(cx); | ||
740 | CX18_INFO("================== END STATUS CARD #%d ==================\n", cx->num); | 756 | CX18_INFO("================== END STATUS CARD #%d ==================\n", cx->num); |
741 | return 0; | 757 | return 0; |
742 | } | 758 | } |
diff --git a/drivers/media/video/cx18/cx18-irq.c b/drivers/media/video/cx18/cx18-irq.c index ab218315c84b..360330f5463f 100644 --- a/drivers/media/video/cx18/cx18-irq.c +++ b/drivers/media/video/cx18/cx18-irq.c | |||
@@ -20,6 +20,7 @@ | |||
20 | */ | 20 | */ |
21 | 21 | ||
22 | #include "cx18-driver.h" | 22 | #include "cx18-driver.h" |
23 | #include "cx18-io.h" | ||
23 | #include "cx18-firmware.h" | 24 | #include "cx18-firmware.h" |
24 | #include "cx18-fileops.h" | 25 | #include "cx18-fileops.h" |
25 | #include "cx18-queue.h" | 26 | #include "cx18-queue.h" |
@@ -48,8 +49,8 @@ static void epu_dma_done(struct cx18 *cx, struct cx18_mailbox *mb) | |||
48 | break; | 49 | break; |
49 | } | 50 | } |
50 | if (i == CX18_MAX_STREAMS) { | 51 | if (i == CX18_MAX_STREAMS) { |
51 | CX18_WARN("DMA done for unknown handle %d for stream %s\n", | 52 | CX18_WARN("Got DMA done notification for unknown/inactive" |
52 | handle, s->name); | 53 | " handle %d\n", handle); |
53 | mb->error = CXERR_NOT_OPEN; | 54 | mb->error = CXERR_NOT_OPEN; |
54 | mb->cmd = 0; | 55 | mb->cmd = 0; |
55 | cx18_mb_ack(cx, mb); | 56 | cx18_mb_ack(cx, mb); |
@@ -60,8 +61,8 @@ static void epu_dma_done(struct cx18 *cx, struct cx18_mailbox *mb) | |||
60 | if (mb->args[2] != 1) | 61 | if (mb->args[2] != 1) |
61 | CX18_WARN("Ack struct = %d for %s\n", | 62 | CX18_WARN("Ack struct = %d for %s\n", |
62 | mb->args[2], s->name); | 63 | mb->args[2], s->name); |
63 | id = read_enc(off); | 64 | id = cx18_read_enc(cx, off); |
64 | buf = cx18_queue_get_buf_irq(s, id, read_enc(off + 4)); | 65 | buf = cx18_queue_get_buf_irq(s, id, cx18_read_enc(cx, off + 4)); |
65 | CX18_DEBUG_HI_DMA("DMA DONE for %s (buffer %d)\n", s->name, id); | 66 | CX18_DEBUG_HI_DMA("DMA DONE for %s (buffer %d)\n", s->name, id); |
66 | if (buf) { | 67 | if (buf) { |
67 | cx18_buf_sync_for_cpu(s, buf); | 68 | cx18_buf_sync_for_cpu(s, buf); |
@@ -81,7 +82,7 @@ static void epu_dma_done(struct cx18 *cx, struct cx18_mailbox *mb) | |||
81 | set_bit(CX18_F_B_NEED_BUF_SWAP, &buf->b_flags); | 82 | set_bit(CX18_F_B_NEED_BUF_SWAP, &buf->b_flags); |
82 | } else { | 83 | } else { |
83 | CX18_WARN("Could not find buf %d for stream %s\n", | 84 | CX18_WARN("Could not find buf %d for stream %s\n", |
84 | read_enc(off), s->name); | 85 | cx18_read_enc(cx, off), s->name); |
85 | } | 86 | } |
86 | mb->error = 0; | 87 | mb->error = 0; |
87 | mb->cmd = 0; | 88 | mb->cmd = 0; |
@@ -97,8 +98,8 @@ static void epu_debug(struct cx18 *cx, struct cx18_mailbox *mb) | |||
97 | char *p; | 98 | char *p; |
98 | 99 | ||
99 | if (mb->args[1]) { | 100 | if (mb->args[1]) { |
100 | setup_page(mb->args[1]); | 101 | cx18_setup_page(cx, mb->args[1]); |
101 | memcpy_fromio(str, cx->enc_mem + mb->args[1], 252); | 102 | cx18_memcpy_fromio(cx, str, cx->enc_mem + mb->args[1], 252); |
102 | str[252] = 0; | 103 | str[252] = 0; |
103 | } | 104 | } |
104 | cx18_mb_ack(cx, mb); | 105 | cx18_mb_ack(cx, mb); |
@@ -113,7 +114,7 @@ static void hpu_cmd(struct cx18 *cx, u32 sw1) | |||
113 | struct cx18_mailbox mb; | 114 | struct cx18_mailbox mb; |
114 | 115 | ||
115 | if (sw1 & IRQ_CPU_TO_EPU) { | 116 | if (sw1 & IRQ_CPU_TO_EPU) { |
116 | memcpy_fromio(&mb, &cx->scb->cpu2epu_mb, sizeof(mb)); | 117 | cx18_memcpy_fromio(cx, &mb, &cx->scb->cpu2epu_mb, sizeof(mb)); |
117 | mb.error = 0; | 118 | mb.error = 0; |
118 | 119 | ||
119 | switch (mb.cmd) { | 120 | switch (mb.cmd) { |
@@ -141,16 +142,16 @@ irqreturn_t cx18_irq_handler(int irq, void *dev_id) | |||
141 | 142 | ||
142 | spin_lock(&cx->dma_reg_lock); | 143 | spin_lock(&cx->dma_reg_lock); |
143 | 144 | ||
144 | hw2_mask = read_reg(HW2_INT_MASK5_PCI); | 145 | hw2_mask = cx18_read_reg(cx, HW2_INT_MASK5_PCI); |
145 | hw2 = read_reg(HW2_INT_CLR_STATUS) & hw2_mask; | 146 | hw2 = cx18_read_reg(cx, HW2_INT_CLR_STATUS) & hw2_mask; |
146 | sw2_mask = read_reg(SW2_INT_ENABLE_PCI) | IRQ_EPU_TO_HPU_ACK; | 147 | sw2_mask = cx18_read_reg(cx, SW2_INT_ENABLE_PCI) | IRQ_EPU_TO_HPU_ACK; |
147 | sw2 = read_reg(SW2_INT_STATUS) & sw2_mask; | 148 | sw2 = cx18_read_reg(cx, SW2_INT_STATUS) & sw2_mask; |
148 | sw1_mask = read_reg(SW1_INT_ENABLE_PCI) | IRQ_EPU_TO_HPU; | 149 | sw1_mask = cx18_read_reg(cx, SW1_INT_ENABLE_PCI) | IRQ_EPU_TO_HPU; |
149 | sw1 = read_reg(SW1_INT_STATUS) & sw1_mask; | 150 | sw1 = cx18_read_reg(cx, SW1_INT_STATUS) & sw1_mask; |
150 | 151 | ||
151 | write_reg(sw2&sw2_mask, SW2_INT_STATUS); | 152 | cx18_write_reg(cx, sw2&sw2_mask, SW2_INT_STATUS); |
152 | write_reg(sw1&sw1_mask, SW1_INT_STATUS); | 153 | cx18_write_reg(cx, sw1&sw1_mask, SW1_INT_STATUS); |
153 | write_reg(hw2&hw2_mask, HW2_INT_CLR_STATUS); | 154 | cx18_write_reg(cx, hw2&hw2_mask, HW2_INT_CLR_STATUS); |
154 | 155 | ||
155 | if (sw1 || sw2 || hw2) | 156 | if (sw1 || sw2 || hw2) |
156 | CX18_DEBUG_HI_IRQ("SW1: %x SW2: %x HW2: %x\n", sw1, sw2, hw2); | 157 | CX18_DEBUG_HI_IRQ("SW1: %x SW2: %x HW2: %x\n", sw1, sw2, hw2); |
@@ -161,15 +162,15 @@ irqreturn_t cx18_irq_handler(int irq, void *dev_id) | |||
161 | */ | 162 | */ |
162 | 163 | ||
163 | if (sw2) { | 164 | if (sw2) { |
164 | if (sw2 & (readl(&cx->scb->cpu2hpu_irq_ack) | | 165 | if (sw2 & (cx18_readl(cx, &cx->scb->cpu2hpu_irq_ack) | |
165 | readl(&cx->scb->cpu2epu_irq_ack))) | 166 | cx18_readl(cx, &cx->scb->cpu2epu_irq_ack))) |
166 | wake_up(&cx->mb_cpu_waitq); | 167 | wake_up(&cx->mb_cpu_waitq); |
167 | if (sw2 & (readl(&cx->scb->apu2hpu_irq_ack) | | 168 | if (sw2 & (cx18_readl(cx, &cx->scb->apu2hpu_irq_ack) | |
168 | readl(&cx->scb->apu2epu_irq_ack))) | 169 | cx18_readl(cx, &cx->scb->apu2epu_irq_ack))) |
169 | wake_up(&cx->mb_apu_waitq); | 170 | wake_up(&cx->mb_apu_waitq); |
170 | if (sw2 & readl(&cx->scb->epu2hpu_irq_ack)) | 171 | if (sw2 & cx18_readl(cx, &cx->scb->epu2hpu_irq_ack)) |
171 | wake_up(&cx->mb_epu_waitq); | 172 | wake_up(&cx->mb_epu_waitq); |
172 | if (sw2 & readl(&cx->scb->hpu2epu_irq_ack)) | 173 | if (sw2 & cx18_readl(cx, &cx->scb->hpu2epu_irq_ack)) |
173 | wake_up(&cx->mb_hpu_waitq); | 174 | wake_up(&cx->mb_hpu_waitq); |
174 | } | 175 | } |
175 | 176 | ||
diff --git a/drivers/media/video/cx18/cx18-mailbox.c b/drivers/media/video/cx18/cx18-mailbox.c index 93177514e846..9d18dd22de76 100644 --- a/drivers/media/video/cx18/cx18-mailbox.c +++ b/drivers/media/video/cx18/cx18-mailbox.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <stdarg.h> | 22 | #include <stdarg.h> |
23 | 23 | ||
24 | #include "cx18-driver.h" | 24 | #include "cx18-driver.h" |
25 | #include "cx18-io.h" | ||
25 | #include "cx18-scb.h" | 26 | #include "cx18-scb.h" |
26 | #include "cx18-irq.h" | 27 | #include "cx18-irq.h" |
27 | #include "cx18-mailbox.h" | 28 | #include "cx18-mailbox.h" |
@@ -82,6 +83,7 @@ static const struct cx18_api_info api_info[] = { | |||
82 | API_ENTRY(CPU, CX18_CPU_DE_SET_MDL_ACK, 0), | 83 | API_ENTRY(CPU, CX18_CPU_DE_SET_MDL_ACK, 0), |
83 | API_ENTRY(CPU, CX18_CPU_DE_SET_MDL, API_FAST), | 84 | API_ENTRY(CPU, CX18_CPU_DE_SET_MDL, API_FAST), |
84 | API_ENTRY(CPU, CX18_APU_RESETAI, API_FAST), | 85 | API_ENTRY(CPU, CX18_APU_RESETAI, API_FAST), |
86 | API_ENTRY(CPU, CX18_CPU_DE_RELEASE_MDL, 0), | ||
85 | API_ENTRY(0, 0, 0), | 87 | API_ENTRY(0, 0, 0), |
86 | }; | 88 | }; |
87 | 89 | ||
@@ -105,20 +107,20 @@ static struct cx18_mailbox __iomem *cx18_mb_is_complete(struct cx18 *cx, int rpu | |||
105 | switch (rpu) { | 107 | switch (rpu) { |
106 | case APU: | 108 | case APU: |
107 | mb = &cx->scb->epu2apu_mb; | 109 | mb = &cx->scb->epu2apu_mb; |
108 | *state = readl(&cx->scb->apu_state); | 110 | *state = cx18_readl(cx, &cx->scb->apu_state); |
109 | *irq = readl(&cx->scb->epu2apu_irq); | 111 | *irq = cx18_readl(cx, &cx->scb->epu2apu_irq); |
110 | break; | 112 | break; |
111 | 113 | ||
112 | case CPU: | 114 | case CPU: |
113 | mb = &cx->scb->epu2cpu_mb; | 115 | mb = &cx->scb->epu2cpu_mb; |
114 | *state = readl(&cx->scb->cpu_state); | 116 | *state = cx18_readl(cx, &cx->scb->cpu_state); |
115 | *irq = readl(&cx->scb->epu2cpu_irq); | 117 | *irq = cx18_readl(cx, &cx->scb->epu2cpu_irq); |
116 | break; | 118 | break; |
117 | 119 | ||
118 | case HPU: | 120 | case HPU: |
119 | mb = &cx->scb->epu2hpu_mb; | 121 | mb = &cx->scb->epu2hpu_mb; |
120 | *state = readl(&cx->scb->hpu_state); | 122 | *state = cx18_readl(cx, &cx->scb->hpu_state); |
121 | *irq = readl(&cx->scb->epu2hpu_irq); | 123 | *irq = cx18_readl(cx, &cx->scb->epu2hpu_irq); |
122 | break; | 124 | break; |
123 | } | 125 | } |
124 | 126 | ||
@@ -126,8 +128,8 @@ static struct cx18_mailbox __iomem *cx18_mb_is_complete(struct cx18 *cx, int rpu | |||
126 | return mb; | 128 | return mb; |
127 | 129 | ||
128 | do { | 130 | do { |
129 | *req = readl(&mb->request); | 131 | *req = cx18_readl(cx, &mb->request); |
130 | ack = readl(&mb->ack); | 132 | ack = cx18_readl(cx, &mb->ack); |
131 | wait_count++; | 133 | wait_count++; |
132 | } while (*req != ack && wait_count < 600); | 134 | } while (*req != ack && wait_count < 600); |
133 | 135 | ||
@@ -172,9 +174,9 @@ long cx18_mb_ack(struct cx18 *cx, const struct cx18_mailbox *mb) | |||
172 | return -EINVAL; | 174 | return -EINVAL; |
173 | } | 175 | } |
174 | 176 | ||
175 | setup_page(SCB_OFFSET); | 177 | cx18_setup_page(cx, SCB_OFFSET); |
176 | write_sync(mb->request, &ack_mb->ack); | 178 | cx18_write_sync(cx, mb->request, &ack_mb->ack); |
177 | write_reg(ack_irq, SW2_INT_SET); | 179 | cx18_write_reg(cx, ack_irq, SW2_INT_SET); |
178 | return 0; | 180 | return 0; |
179 | } | 181 | } |
180 | 182 | ||
@@ -199,7 +201,7 @@ static int cx18_api_call(struct cx18 *cx, u32 cmd, int args, u32 data[]) | |||
199 | CX18_DEBUG_HI_API("%s\n", info->name); | 201 | CX18_DEBUG_HI_API("%s\n", info->name); |
200 | else | 202 | else |
201 | CX18_DEBUG_API("%s\n", info->name); | 203 | CX18_DEBUG_API("%s\n", info->name); |
202 | setup_page(SCB_OFFSET); | 204 | cx18_setup_page(cx, SCB_OFFSET); |
203 | mb = cx18_mb_is_complete(cx, info->rpu, &state, &irq, &req); | 205 | mb = cx18_mb_is_complete(cx, info->rpu, &state, &irq, &req); |
204 | 206 | ||
205 | if (mb == NULL) { | 207 | if (mb == NULL) { |
@@ -208,11 +210,11 @@ static int cx18_api_call(struct cx18 *cx, u32 cmd, int args, u32 data[]) | |||
208 | } | 210 | } |
209 | 211 | ||
210 | oldreq = req - 1; | 212 | oldreq = req - 1; |
211 | writel(cmd, &mb->cmd); | 213 | cx18_writel(cx, cmd, &mb->cmd); |
212 | for (i = 0; i < args; i++) | 214 | for (i = 0; i < args; i++) |
213 | writel(data[i], &mb->args[i]); | 215 | cx18_writel(cx, data[i], &mb->args[i]); |
214 | writel(0, &mb->error); | 216 | cx18_writel(cx, 0, &mb->error); |
215 | writel(req, &mb->request); | 217 | cx18_writel(cx, req, &mb->request); |
216 | 218 | ||
217 | switch (info->rpu) { | 219 | switch (info->rpu) { |
218 | case APU: waitq = &cx->mb_apu_waitq; break; | 220 | case APU: waitq = &cx->mb_apu_waitq; break; |
@@ -223,9 +225,10 @@ static int cx18_api_call(struct cx18 *cx, u32 cmd, int args, u32 data[]) | |||
223 | } | 225 | } |
224 | if (info->flags & API_FAST) | 226 | if (info->flags & API_FAST) |
225 | timeout /= 2; | 227 | timeout /= 2; |
226 | write_reg(irq, SW1_INT_SET); | 228 | cx18_write_reg(cx, irq, SW1_INT_SET); |
227 | 229 | ||
228 | while (!sig && readl(&mb->ack) != readl(&mb->request) && cnt < 660) { | 230 | while (!sig && cx18_readl(cx, &mb->ack) != cx18_readl(cx, &mb->request) |
231 | && cnt < 660) { | ||
229 | if (cnt > 200 && !in_atomic()) | 232 | if (cnt > 200 && !in_atomic()) |
230 | sig = cx18_msleep_timeout(10, 1); | 233 | sig = cx18_msleep_timeout(10, 1); |
231 | cnt++; | 234 | cnt++; |
@@ -233,13 +236,13 @@ static int cx18_api_call(struct cx18 *cx, u32 cmd, int args, u32 data[]) | |||
233 | if (sig) | 236 | if (sig) |
234 | return -EINTR; | 237 | return -EINTR; |
235 | if (cnt == 660) { | 238 | if (cnt == 660) { |
236 | writel(oldreq, &mb->request); | 239 | cx18_writel(cx, oldreq, &mb->request); |
237 | CX18_ERR("mb %s failed\n", info->name); | 240 | CX18_ERR("mb %s failed\n", info->name); |
238 | return -EINVAL; | 241 | return -EINVAL; |
239 | } | 242 | } |
240 | for (i = 0; i < MAX_MB_ARGUMENTS; i++) | 243 | for (i = 0; i < MAX_MB_ARGUMENTS; i++) |
241 | data[i] = readl(&mb->args[i]); | 244 | data[i] = cx18_readl(cx, &mb->args[i]); |
242 | err = readl(&mb->error); | 245 | err = cx18_readl(cx, &mb->error); |
243 | if (!in_atomic() && (info->flags & API_SLOW)) | 246 | if (!in_atomic() && (info->flags & API_SLOW)) |
244 | cx18_msleep_timeout(300, 0); | 247 | cx18_msleep_timeout(300, 0); |
245 | if (err) | 248 | if (err) |
diff --git a/drivers/media/video/cx18/cx18-queue.c b/drivers/media/video/cx18/cx18-queue.c index dbe792ac3001..a33ba04a2686 100644 --- a/drivers/media/video/cx18/cx18-queue.c +++ b/drivers/media/video/cx18/cx18-queue.c | |||
@@ -37,8 +37,7 @@ void cx18_buf_swap(struct cx18_buffer *buf) | |||
37 | void cx18_queue_init(struct cx18_queue *q) | 37 | void cx18_queue_init(struct cx18_queue *q) |
38 | { | 38 | { |
39 | INIT_LIST_HEAD(&q->list); | 39 | INIT_LIST_HEAD(&q->list); |
40 | q->buffers = 0; | 40 | atomic_set(&q->buffers, 0); |
41 | q->length = 0; | ||
42 | q->bytesused = 0; | 41 | q->bytesused = 0; |
43 | } | 42 | } |
44 | 43 | ||
@@ -55,8 +54,7 @@ void cx18_enqueue(struct cx18_stream *s, struct cx18_buffer *buf, | |||
55 | } | 54 | } |
56 | spin_lock_irqsave(&s->qlock, flags); | 55 | spin_lock_irqsave(&s->qlock, flags); |
57 | list_add_tail(&buf->list, &q->list); | 56 | list_add_tail(&buf->list, &q->list); |
58 | q->buffers++; | 57 | atomic_inc(&q->buffers); |
59 | q->length += s->buf_size; | ||
60 | q->bytesused += buf->bytesused - buf->readpos; | 58 | q->bytesused += buf->bytesused - buf->readpos; |
61 | spin_unlock_irqrestore(&s->qlock, flags); | 59 | spin_unlock_irqrestore(&s->qlock, flags); |
62 | } | 60 | } |
@@ -70,8 +68,7 @@ struct cx18_buffer *cx18_dequeue(struct cx18_stream *s, struct cx18_queue *q) | |||
70 | if (!list_empty(&q->list)) { | 68 | if (!list_empty(&q->list)) { |
71 | buf = list_entry(q->list.next, struct cx18_buffer, list); | 69 | buf = list_entry(q->list.next, struct cx18_buffer, list); |
72 | list_del_init(q->list.next); | 70 | list_del_init(q->list.next); |
73 | q->buffers--; | 71 | atomic_dec(&q->buffers); |
74 | q->length -= s->buf_size; | ||
75 | q->bytesused -= buf->bytesused - buf->readpos; | 72 | q->bytesused -= buf->bytesused - buf->readpos; |
76 | } | 73 | } |
77 | spin_unlock_irqrestore(&s->qlock, flags); | 74 | spin_unlock_irqrestore(&s->qlock, flags); |
@@ -95,10 +92,8 @@ struct cx18_buffer *cx18_queue_get_buf_irq(struct cx18_stream *s, u32 id, | |||
95 | /* the transport buffers are handled differently, | 92 | /* the transport buffers are handled differently, |
96 | they are not moved to the full queue */ | 93 | they are not moved to the full queue */ |
97 | if (s->type != CX18_ENC_STREAM_TYPE_TS) { | 94 | if (s->type != CX18_ENC_STREAM_TYPE_TS) { |
98 | s->q_free.buffers--; | 95 | atomic_dec(&s->q_free.buffers); |
99 | s->q_free.length -= s->buf_size; | 96 | atomic_inc(&s->q_full.buffers); |
100 | s->q_full.buffers++; | ||
101 | s->q_full.length += s->buf_size; | ||
102 | s->q_full.bytesused += buf->bytesused; | 97 | s->q_full.bytesused += buf->bytesused; |
103 | list_move_tail(&buf->list, &s->q_full.list); | 98 | list_move_tail(&buf->list, &s->q_full.list); |
104 | } | 99 | } |
@@ -124,8 +119,7 @@ static void cx18_queue_flush(struct cx18_stream *s, struct cx18_queue *q) | |||
124 | buf = list_entry(q->list.next, struct cx18_buffer, list); | 119 | buf = list_entry(q->list.next, struct cx18_buffer, list); |
125 | list_move_tail(q->list.next, &s->q_free.list); | 120 | list_move_tail(q->list.next, &s->q_free.list); |
126 | buf->bytesused = buf->readpos = buf->b_flags = 0; | 121 | buf->bytesused = buf->readpos = buf->b_flags = 0; |
127 | s->q_free.buffers++; | 122 | atomic_inc(&s->q_free.buffers); |
128 | s->q_free.length += s->buf_size; | ||
129 | } | 123 | } |
130 | cx18_queue_init(q); | 124 | cx18_queue_init(q); |
131 | spin_unlock_irqrestore(&s->qlock, flags); | 125 | spin_unlock_irqrestore(&s->qlock, flags); |
diff --git a/drivers/media/video/cx18/cx18-scb.c b/drivers/media/video/cx18/cx18-scb.c index 30bc803e30da..f56d3772aa67 100644 --- a/drivers/media/video/cx18/cx18-scb.c +++ b/drivers/media/video/cx18/cx18-scb.c | |||
@@ -20,102 +20,103 @@ | |||
20 | */ | 20 | */ |
21 | 21 | ||
22 | #include "cx18-driver.h" | 22 | #include "cx18-driver.h" |
23 | #include "cx18-io.h" | ||
23 | #include "cx18-scb.h" | 24 | #include "cx18-scb.h" |
24 | 25 | ||
25 | void cx18_init_scb(struct cx18 *cx) | 26 | void cx18_init_scb(struct cx18 *cx) |
26 | { | 27 | { |
27 | setup_page(SCB_OFFSET); | 28 | cx18_setup_page(cx, SCB_OFFSET); |
28 | memset_io(cx->scb, 0, 0x10000); | 29 | cx18_memset_io(cx, cx->scb, 0, 0x10000); |
29 | 30 | ||
30 | writel(IRQ_APU_TO_CPU, &cx->scb->apu2cpu_irq); | 31 | cx18_writel(cx, IRQ_APU_TO_CPU, &cx->scb->apu2cpu_irq); |
31 | writel(IRQ_CPU_TO_APU_ACK, &cx->scb->cpu2apu_irq_ack); | 32 | cx18_writel(cx, IRQ_CPU_TO_APU_ACK, &cx->scb->cpu2apu_irq_ack); |
32 | writel(IRQ_HPU_TO_CPU, &cx->scb->hpu2cpu_irq); | 33 | cx18_writel(cx, IRQ_HPU_TO_CPU, &cx->scb->hpu2cpu_irq); |
33 | writel(IRQ_CPU_TO_HPU_ACK, &cx->scb->cpu2hpu_irq_ack); | 34 | cx18_writel(cx, IRQ_CPU_TO_HPU_ACK, &cx->scb->cpu2hpu_irq_ack); |
34 | writel(IRQ_PPU_TO_CPU, &cx->scb->ppu2cpu_irq); | 35 | cx18_writel(cx, IRQ_PPU_TO_CPU, &cx->scb->ppu2cpu_irq); |
35 | writel(IRQ_CPU_TO_PPU_ACK, &cx->scb->cpu2ppu_irq_ack); | 36 | cx18_writel(cx, IRQ_CPU_TO_PPU_ACK, &cx->scb->cpu2ppu_irq_ack); |
36 | writel(IRQ_EPU_TO_CPU, &cx->scb->epu2cpu_irq); | 37 | cx18_writel(cx, IRQ_EPU_TO_CPU, &cx->scb->epu2cpu_irq); |
37 | writel(IRQ_CPU_TO_EPU_ACK, &cx->scb->cpu2epu_irq_ack); | 38 | cx18_writel(cx, IRQ_CPU_TO_EPU_ACK, &cx->scb->cpu2epu_irq_ack); |
38 | 39 | ||
39 | writel(IRQ_CPU_TO_APU, &cx->scb->cpu2apu_irq); | 40 | cx18_writel(cx, IRQ_CPU_TO_APU, &cx->scb->cpu2apu_irq); |
40 | writel(IRQ_APU_TO_CPU_ACK, &cx->scb->apu2cpu_irq_ack); | 41 | cx18_writel(cx, IRQ_APU_TO_CPU_ACK, &cx->scb->apu2cpu_irq_ack); |
41 | writel(IRQ_HPU_TO_APU, &cx->scb->hpu2apu_irq); | 42 | cx18_writel(cx, IRQ_HPU_TO_APU, &cx->scb->hpu2apu_irq); |
42 | writel(IRQ_APU_TO_HPU_ACK, &cx->scb->apu2hpu_irq_ack); | 43 | cx18_writel(cx, IRQ_APU_TO_HPU_ACK, &cx->scb->apu2hpu_irq_ack); |
43 | writel(IRQ_PPU_TO_APU, &cx->scb->ppu2apu_irq); | 44 | cx18_writel(cx, IRQ_PPU_TO_APU, &cx->scb->ppu2apu_irq); |
44 | writel(IRQ_APU_TO_PPU_ACK, &cx->scb->apu2ppu_irq_ack); | 45 | cx18_writel(cx, IRQ_APU_TO_PPU_ACK, &cx->scb->apu2ppu_irq_ack); |
45 | writel(IRQ_EPU_TO_APU, &cx->scb->epu2apu_irq); | 46 | cx18_writel(cx, IRQ_EPU_TO_APU, &cx->scb->epu2apu_irq); |
46 | writel(IRQ_APU_TO_EPU_ACK, &cx->scb->apu2epu_irq_ack); | 47 | cx18_writel(cx, IRQ_APU_TO_EPU_ACK, &cx->scb->apu2epu_irq_ack); |
47 | 48 | ||
48 | writel(IRQ_CPU_TO_HPU, &cx->scb->cpu2hpu_irq); | 49 | cx18_writel(cx, IRQ_CPU_TO_HPU, &cx->scb->cpu2hpu_irq); |
49 | writel(IRQ_HPU_TO_CPU_ACK, &cx->scb->hpu2cpu_irq_ack); | 50 | cx18_writel(cx, IRQ_HPU_TO_CPU_ACK, &cx->scb->hpu2cpu_irq_ack); |
50 | writel(IRQ_APU_TO_HPU, &cx->scb->apu2hpu_irq); | 51 | cx18_writel(cx, IRQ_APU_TO_HPU, &cx->scb->apu2hpu_irq); |
51 | writel(IRQ_HPU_TO_APU_ACK, &cx->scb->hpu2apu_irq_ack); | 52 | cx18_writel(cx, IRQ_HPU_TO_APU_ACK, &cx->scb->hpu2apu_irq_ack); |
52 | writel(IRQ_PPU_TO_HPU, &cx->scb->ppu2hpu_irq); | 53 | cx18_writel(cx, IRQ_PPU_TO_HPU, &cx->scb->ppu2hpu_irq); |
53 | writel(IRQ_HPU_TO_PPU_ACK, &cx->scb->hpu2ppu_irq_ack); | 54 | cx18_writel(cx, IRQ_HPU_TO_PPU_ACK, &cx->scb->hpu2ppu_irq_ack); |
54 | writel(IRQ_EPU_TO_HPU, &cx->scb->epu2hpu_irq); | 55 | cx18_writel(cx, IRQ_EPU_TO_HPU, &cx->scb->epu2hpu_irq); |
55 | writel(IRQ_HPU_TO_EPU_ACK, &cx->scb->hpu2epu_irq_ack); | 56 | cx18_writel(cx, IRQ_HPU_TO_EPU_ACK, &cx->scb->hpu2epu_irq_ack); |
56 | 57 | ||
57 | writel(IRQ_CPU_TO_PPU, &cx->scb->cpu2ppu_irq); | 58 | cx18_writel(cx, IRQ_CPU_TO_PPU, &cx->scb->cpu2ppu_irq); |
58 | writel(IRQ_PPU_TO_CPU_ACK, &cx->scb->ppu2cpu_irq_ack); | 59 | cx18_writel(cx, IRQ_PPU_TO_CPU_ACK, &cx->scb->ppu2cpu_irq_ack); |
59 | writel(IRQ_APU_TO_PPU, &cx->scb->apu2ppu_irq); | 60 | cx18_writel(cx, IRQ_APU_TO_PPU, &cx->scb->apu2ppu_irq); |
60 | writel(IRQ_PPU_TO_APU_ACK, &cx->scb->ppu2apu_irq_ack); | 61 | cx18_writel(cx, IRQ_PPU_TO_APU_ACK, &cx->scb->ppu2apu_irq_ack); |
61 | writel(IRQ_HPU_TO_PPU, &cx->scb->hpu2ppu_irq); | 62 | cx18_writel(cx, IRQ_HPU_TO_PPU, &cx->scb->hpu2ppu_irq); |
62 | writel(IRQ_PPU_TO_HPU_ACK, &cx->scb->ppu2hpu_irq_ack); | 63 | cx18_writel(cx, IRQ_PPU_TO_HPU_ACK, &cx->scb->ppu2hpu_irq_ack); |
63 | writel(IRQ_EPU_TO_PPU, &cx->scb->epu2ppu_irq); | 64 | cx18_writel(cx, IRQ_EPU_TO_PPU, &cx->scb->epu2ppu_irq); |
64 | writel(IRQ_PPU_TO_EPU_ACK, &cx->scb->ppu2epu_irq_ack); | 65 | cx18_writel(cx, IRQ_PPU_TO_EPU_ACK, &cx->scb->ppu2epu_irq_ack); |
65 | 66 | ||
66 | writel(IRQ_CPU_TO_EPU, &cx->scb->cpu2epu_irq); | 67 | cx18_writel(cx, IRQ_CPU_TO_EPU, &cx->scb->cpu2epu_irq); |
67 | writel(IRQ_EPU_TO_CPU_ACK, &cx->scb->epu2cpu_irq_ack); | 68 | cx18_writel(cx, IRQ_EPU_TO_CPU_ACK, &cx->scb->epu2cpu_irq_ack); |
68 | writel(IRQ_APU_TO_EPU, &cx->scb->apu2epu_irq); | 69 | cx18_writel(cx, IRQ_APU_TO_EPU, &cx->scb->apu2epu_irq); |
69 | writel(IRQ_EPU_TO_APU_ACK, &cx->scb->epu2apu_irq_ack); | 70 | cx18_writel(cx, IRQ_EPU_TO_APU_ACK, &cx->scb->epu2apu_irq_ack); |
70 | writel(IRQ_HPU_TO_EPU, &cx->scb->hpu2epu_irq); | 71 | cx18_writel(cx, IRQ_HPU_TO_EPU, &cx->scb->hpu2epu_irq); |
71 | writel(IRQ_EPU_TO_HPU_ACK, &cx->scb->epu2hpu_irq_ack); | 72 | cx18_writel(cx, IRQ_EPU_TO_HPU_ACK, &cx->scb->epu2hpu_irq_ack); |
72 | writel(IRQ_PPU_TO_EPU, &cx->scb->ppu2epu_irq); | 73 | cx18_writel(cx, IRQ_PPU_TO_EPU, &cx->scb->ppu2epu_irq); |
73 | writel(IRQ_EPU_TO_PPU_ACK, &cx->scb->epu2ppu_irq_ack); | 74 | cx18_writel(cx, IRQ_EPU_TO_PPU_ACK, &cx->scb->epu2ppu_irq_ack); |
74 | 75 | ||
75 | writel(SCB_OFFSET + offsetof(struct cx18_scb, apu2cpu_mb), | 76 | cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, apu2cpu_mb), |
76 | &cx->scb->apu2cpu_mb_offset); | 77 | &cx->scb->apu2cpu_mb_offset); |
77 | writel(SCB_OFFSET + offsetof(struct cx18_scb, hpu2cpu_mb), | 78 | cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, hpu2cpu_mb), |
78 | &cx->scb->hpu2cpu_mb_offset); | 79 | &cx->scb->hpu2cpu_mb_offset); |
79 | writel(SCB_OFFSET + offsetof(struct cx18_scb, ppu2cpu_mb), | 80 | cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, ppu2cpu_mb), |
80 | &cx->scb->ppu2cpu_mb_offset); | 81 | &cx->scb->ppu2cpu_mb_offset); |
81 | writel(SCB_OFFSET + offsetof(struct cx18_scb, epu2cpu_mb), | 82 | cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, epu2cpu_mb), |
82 | &cx->scb->epu2cpu_mb_offset); | 83 | &cx->scb->epu2cpu_mb_offset); |
83 | writel(SCB_OFFSET + offsetof(struct cx18_scb, cpu2apu_mb), | 84 | cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, cpu2apu_mb), |
84 | &cx->scb->cpu2apu_mb_offset); | 85 | &cx->scb->cpu2apu_mb_offset); |
85 | writel(SCB_OFFSET + offsetof(struct cx18_scb, hpu2apu_mb), | 86 | cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, hpu2apu_mb), |
86 | &cx->scb->hpu2apu_mb_offset); | 87 | &cx->scb->hpu2apu_mb_offset); |
87 | writel(SCB_OFFSET + offsetof(struct cx18_scb, ppu2apu_mb), | 88 | cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, ppu2apu_mb), |
88 | &cx->scb->ppu2apu_mb_offset); | 89 | &cx->scb->ppu2apu_mb_offset); |
89 | writel(SCB_OFFSET + offsetof(struct cx18_scb, epu2apu_mb), | 90 | cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, epu2apu_mb), |
90 | &cx->scb->epu2apu_mb_offset); | 91 | &cx->scb->epu2apu_mb_offset); |
91 | writel(SCB_OFFSET + offsetof(struct cx18_scb, cpu2hpu_mb), | 92 | cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, cpu2hpu_mb), |
92 | &cx->scb->cpu2hpu_mb_offset); | 93 | &cx->scb->cpu2hpu_mb_offset); |
93 | writel(SCB_OFFSET + offsetof(struct cx18_scb, apu2hpu_mb), | 94 | cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, apu2hpu_mb), |
94 | &cx->scb->apu2hpu_mb_offset); | 95 | &cx->scb->apu2hpu_mb_offset); |
95 | writel(SCB_OFFSET + offsetof(struct cx18_scb, ppu2hpu_mb), | 96 | cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, ppu2hpu_mb), |
96 | &cx->scb->ppu2hpu_mb_offset); | 97 | &cx->scb->ppu2hpu_mb_offset); |
97 | writel(SCB_OFFSET + offsetof(struct cx18_scb, epu2hpu_mb), | 98 | cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, epu2hpu_mb), |
98 | &cx->scb->epu2hpu_mb_offset); | 99 | &cx->scb->epu2hpu_mb_offset); |
99 | writel(SCB_OFFSET + offsetof(struct cx18_scb, cpu2ppu_mb), | 100 | cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, cpu2ppu_mb), |
100 | &cx->scb->cpu2ppu_mb_offset); | 101 | &cx->scb->cpu2ppu_mb_offset); |
101 | writel(SCB_OFFSET + offsetof(struct cx18_scb, apu2ppu_mb), | 102 | cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, apu2ppu_mb), |
102 | &cx->scb->apu2ppu_mb_offset); | 103 | &cx->scb->apu2ppu_mb_offset); |
103 | writel(SCB_OFFSET + offsetof(struct cx18_scb, hpu2ppu_mb), | 104 | cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, hpu2ppu_mb), |
104 | &cx->scb->hpu2ppu_mb_offset); | 105 | &cx->scb->hpu2ppu_mb_offset); |
105 | writel(SCB_OFFSET + offsetof(struct cx18_scb, epu2ppu_mb), | 106 | cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, epu2ppu_mb), |
106 | &cx->scb->epu2ppu_mb_offset); | 107 | &cx->scb->epu2ppu_mb_offset); |
107 | writel(SCB_OFFSET + offsetof(struct cx18_scb, cpu2epu_mb), | 108 | cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, cpu2epu_mb), |
108 | &cx->scb->cpu2epu_mb_offset); | 109 | &cx->scb->cpu2epu_mb_offset); |
109 | writel(SCB_OFFSET + offsetof(struct cx18_scb, apu2epu_mb), | 110 | cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, apu2epu_mb), |
110 | &cx->scb->apu2epu_mb_offset); | 111 | &cx->scb->apu2epu_mb_offset); |
111 | writel(SCB_OFFSET + offsetof(struct cx18_scb, hpu2epu_mb), | 112 | cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, hpu2epu_mb), |
112 | &cx->scb->hpu2epu_mb_offset); | 113 | &cx->scb->hpu2epu_mb_offset); |
113 | writel(SCB_OFFSET + offsetof(struct cx18_scb, ppu2epu_mb), | 114 | cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, ppu2epu_mb), |
114 | &cx->scb->ppu2epu_mb_offset); | 115 | &cx->scb->ppu2epu_mb_offset); |
115 | 116 | ||
116 | writel(SCB_OFFSET + offsetof(struct cx18_scb, cpu_state), | 117 | cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, cpu_state), |
117 | &cx->scb->ipc_offset); | 118 | &cx->scb->ipc_offset); |
118 | 119 | ||
119 | writel(1, &cx->scb->hpu_state); | 120 | cx18_writel(cx, 1, &cx->scb->hpu_state); |
120 | writel(1, &cx->scb->epu_state); | 121 | cx18_writel(cx, 1, &cx->scb->epu_state); |
121 | } | 122 | } |
diff --git a/drivers/media/video/cx18/cx18-streams.c b/drivers/media/video/cx18/cx18-streams.c index 0da57f583bf7..0c8e7542cf60 100644 --- a/drivers/media/video/cx18/cx18-streams.c +++ b/drivers/media/video/cx18/cx18-streams.c | |||
@@ -22,6 +22,7 @@ | |||
22 | */ | 22 | */ |
23 | 23 | ||
24 | #include "cx18-driver.h" | 24 | #include "cx18-driver.h" |
25 | #include "cx18-io.h" | ||
25 | #include "cx18-fileops.h" | 26 | #include "cx18-fileops.h" |
26 | #include "cx18-mailbox.h" | 27 | #include "cx18-mailbox.h" |
27 | #include "cx18-i2c.h" | 28 | #include "cx18-i2c.h" |
@@ -56,7 +57,7 @@ static struct file_operations cx18_v4l2_enc_fops = { | |||
56 | static struct { | 57 | static struct { |
57 | const char *name; | 58 | const char *name; |
58 | int vfl_type; | 59 | int vfl_type; |
59 | int minor_offset; | 60 | int num_offset; |
60 | int dma; | 61 | int dma; |
61 | enum v4l2_buf_type buf_type; | 62 | enum v4l2_buf_type buf_type; |
62 | struct file_operations *fops; | 63 | struct file_operations *fops; |
@@ -119,7 +120,7 @@ static void cx18_stream_init(struct cx18 *cx, int type) | |||
119 | s->cx = cx; | 120 | s->cx = cx; |
120 | s->type = type; | 121 | s->type = type; |
121 | s->name = cx18_stream_info[type].name; | 122 | s->name = cx18_stream_info[type].name; |
122 | s->handle = 0xffffffff; | 123 | s->handle = CX18_INVALID_TASK_HANDLE; |
123 | 124 | ||
124 | s->dma = cx18_stream_info[type].dma; | 125 | s->dma = cx18_stream_info[type].dma; |
125 | s->buf_size = cx->stream_buf_size[type]; | 126 | s->buf_size = cx->stream_buf_size[type]; |
@@ -143,8 +144,8 @@ static int cx18_prep_dev(struct cx18 *cx, int type) | |||
143 | { | 144 | { |
144 | struct cx18_stream *s = &cx->streams[type]; | 145 | struct cx18_stream *s = &cx->streams[type]; |
145 | u32 cap = cx->v4l2_cap; | 146 | u32 cap = cx->v4l2_cap; |
146 | int minor_offset = cx18_stream_info[type].minor_offset; | 147 | int num_offset = cx18_stream_info[type].num_offset; |
147 | int minor; | 148 | int num = cx->num + cx18_first_minor + num_offset; |
148 | 149 | ||
149 | /* These four fields are always initialized. If v4l2dev == NULL, then | 150 | /* These four fields are always initialized. If v4l2dev == NULL, then |
150 | this stream is not in use. In that case no other fields but these | 151 | this stream is not in use. In that case no other fields but these |
@@ -163,9 +164,6 @@ static int cx18_prep_dev(struct cx18 *cx, int type) | |||
163 | !(cap & (V4L2_CAP_VBI_CAPTURE | V4L2_CAP_SLICED_VBI_CAPTURE))) | 164 | !(cap & (V4L2_CAP_VBI_CAPTURE | V4L2_CAP_SLICED_VBI_CAPTURE))) |
164 | return 0; | 165 | return 0; |
165 | 166 | ||
166 | /* card number + user defined offset + device offset */ | ||
167 | minor = cx->num + cx18_first_minor + minor_offset; | ||
168 | |||
169 | /* User explicitly selected 0 buffers for these streams, so don't | 167 | /* User explicitly selected 0 buffers for these streams, so don't |
170 | create them. */ | 168 | create them. */ |
171 | if (cx18_stream_info[type].dma != PCI_DMA_NONE && | 169 | if (cx18_stream_info[type].dma != PCI_DMA_NONE && |
@@ -176,7 +174,7 @@ static int cx18_prep_dev(struct cx18 *cx, int type) | |||
176 | 174 | ||
177 | cx18_stream_init(cx, type); | 175 | cx18_stream_init(cx, type); |
178 | 176 | ||
179 | if (minor_offset == -1) | 177 | if (num_offset == -1) |
180 | return 0; | 178 | return 0; |
181 | 179 | ||
182 | /* allocate and initialize the v4l2 video device structure */ | 180 | /* allocate and initialize the v4l2 video device structure */ |
@@ -190,7 +188,7 @@ static int cx18_prep_dev(struct cx18 *cx, int type) | |||
190 | snprintf(s->v4l2dev->name, sizeof(s->v4l2dev->name), "cx18-%d", | 188 | snprintf(s->v4l2dev->name, sizeof(s->v4l2dev->name), "cx18-%d", |
191 | cx->num); | 189 | cx->num); |
192 | 190 | ||
193 | s->v4l2dev->minor = minor; | 191 | s->v4l2dev->num = num; |
194 | s->v4l2dev->parent = &cx->dev->dev; | 192 | s->v4l2dev->parent = &cx->dev->dev; |
195 | s->v4l2dev->fops = cx18_stream_info[type].fops; | 193 | s->v4l2dev->fops = cx18_stream_info[type].fops; |
196 | s->v4l2dev->release = video_device_release; | 194 | s->v4l2dev->release = video_device_release; |
@@ -226,7 +224,7 @@ static int cx18_reg_dev(struct cx18 *cx, int type) | |||
226 | { | 224 | { |
227 | struct cx18_stream *s = &cx->streams[type]; | 225 | struct cx18_stream *s = &cx->streams[type]; |
228 | int vfl_type = cx18_stream_info[type].vfl_type; | 226 | int vfl_type = cx18_stream_info[type].vfl_type; |
229 | int minor; | 227 | int num; |
230 | 228 | ||
231 | /* TODO: Shouldn't this be a VFL_TYPE_TRANSPORT or something? | 229 | /* TODO: Shouldn't this be a VFL_TYPE_TRANSPORT or something? |
232 | * We need a VFL_TYPE_TS defined. | 230 | * We need a VFL_TYPE_TS defined. |
@@ -244,38 +242,44 @@ static int cx18_reg_dev(struct cx18 *cx, int type) | |||
244 | if (s->v4l2dev == NULL) | 242 | if (s->v4l2dev == NULL) |
245 | return 0; | 243 | return 0; |
246 | 244 | ||
247 | minor = s->v4l2dev->minor; | 245 | num = s->v4l2dev->num; |
246 | /* card number + user defined offset + device offset */ | ||
247 | if (type != CX18_ENC_STREAM_TYPE_MPG) { | ||
248 | struct cx18_stream *s_mpg = &cx->streams[CX18_ENC_STREAM_TYPE_MPG]; | ||
249 | |||
250 | if (s_mpg->v4l2dev) | ||
251 | num = s_mpg->v4l2dev->num + cx18_stream_info[type].num_offset; | ||
252 | } | ||
248 | 253 | ||
249 | /* Register device. First try the desired minor, then any free one. */ | 254 | /* Register device. First try the desired minor, then any free one. */ |
250 | if (video_register_device(s->v4l2dev, vfl_type, minor) && | 255 | if (video_register_device(s->v4l2dev, vfl_type, num)) { |
251 | video_register_device(s->v4l2dev, vfl_type, -1)) { | 256 | CX18_ERR("Couldn't register v4l2 device for %s kernel number %d\n", |
252 | CX18_ERR("Couldn't register v4l2 device for %s minor %d\n", | 257 | s->name, num); |
253 | s->name, minor); | ||
254 | video_device_release(s->v4l2dev); | 258 | video_device_release(s->v4l2dev); |
255 | s->v4l2dev = NULL; | 259 | s->v4l2dev = NULL; |
256 | return -ENOMEM; | 260 | return -ENOMEM; |
257 | } | 261 | } |
258 | minor = s->v4l2dev->minor; | 262 | num = s->v4l2dev->num; |
259 | 263 | ||
260 | switch (vfl_type) { | 264 | switch (vfl_type) { |
261 | case VFL_TYPE_GRABBER: | 265 | case VFL_TYPE_GRABBER: |
262 | CX18_INFO("Registered device video%d for %s (%d MB)\n", | 266 | CX18_INFO("Registered device video%d for %s (%d MB)\n", |
263 | minor, s->name, cx->options.megabytes[type]); | 267 | num, s->name, cx->options.megabytes[type]); |
264 | break; | 268 | break; |
265 | 269 | ||
266 | case VFL_TYPE_RADIO: | 270 | case VFL_TYPE_RADIO: |
267 | CX18_INFO("Registered device radio%d for %s\n", | 271 | CX18_INFO("Registered device radio%d for %s\n", |
268 | minor - MINOR_VFL_TYPE_RADIO_MIN, s->name); | 272 | num, s->name); |
269 | break; | 273 | break; |
270 | 274 | ||
271 | case VFL_TYPE_VBI: | 275 | case VFL_TYPE_VBI: |
272 | if (cx->options.megabytes[type]) | 276 | if (cx->options.megabytes[type]) |
273 | CX18_INFO("Registered device vbi%d for %s (%d MB)\n", | 277 | CX18_INFO("Registered device vbi%d for %s (%d MB)\n", |
274 | minor - MINOR_VFL_TYPE_VBI_MIN, | 278 | num, |
275 | s->name, cx->options.megabytes[type]); | 279 | s->name, cx->options.megabytes[type]); |
276 | else | 280 | else |
277 | CX18_INFO("Registered device vbi%d for %s\n", | 281 | CX18_INFO("Registered device vbi%d for %s\n", |
278 | minor - MINOR_VFL_TYPE_VBI_MIN, s->name); | 282 | num, s->name); |
279 | break; | 283 | break; |
280 | } | 284 | } |
281 | 285 | ||
@@ -432,7 +436,6 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s) | |||
432 | default: | 436 | default: |
433 | return -EINVAL; | 437 | return -EINVAL; |
434 | } | 438 | } |
435 | s->buffers_stolen = 0; | ||
436 | 439 | ||
437 | /* mute/unmute video */ | 440 | /* mute/unmute video */ |
438 | cx18_vapi(cx, CX18_CPU_SET_VIDEO_MUTE, 2, | 441 | cx18_vapi(cx, CX18_CPU_SET_VIDEO_MUTE, 2, |
@@ -470,7 +473,7 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s) | |||
470 | 473 | ||
471 | if (atomic_read(&cx->tot_capturing) == 0) { | 474 | if (atomic_read(&cx->tot_capturing) == 0) { |
472 | clear_bit(CX18_F_I_EOS, &cx->i_flags); | 475 | clear_bit(CX18_F_I_EOS, &cx->i_flags); |
473 | write_reg(7, CX18_DSP0_INTERRUPT_MASK); | 476 | cx18_write_reg(cx, 7, CX18_DSP0_INTERRUPT_MASK); |
474 | } | 477 | } |
475 | 478 | ||
476 | cx18_vapi(cx, CX18_CPU_DE_SET_MDL_ACK, 3, s->handle, | 479 | cx18_vapi(cx, CX18_CPU_DE_SET_MDL_ACK, 3, s->handle, |
@@ -480,8 +483,9 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s) | |||
480 | list_for_each(p, &s->q_free.list) { | 483 | list_for_each(p, &s->q_free.list) { |
481 | struct cx18_buffer *buf = list_entry(p, struct cx18_buffer, list); | 484 | struct cx18_buffer *buf = list_entry(p, struct cx18_buffer, list); |
482 | 485 | ||
483 | writel(buf->dma_handle, &cx->scb->cpu_mdl[buf->id].paddr); | 486 | cx18_writel(cx, buf->dma_handle, |
484 | writel(s->buf_size, &cx->scb->cpu_mdl[buf->id].length); | 487 | &cx->scb->cpu_mdl[buf->id].paddr); |
488 | cx18_writel(cx, s->buf_size, &cx->scb->cpu_mdl[buf->id].length); | ||
485 | cx18_vapi(cx, CX18_CPU_DE_SET_MDL, 5, s->handle, | 489 | cx18_vapi(cx, CX18_CPU_DE_SET_MDL, 5, s->handle, |
486 | (void __iomem *)&cx->scb->cpu_mdl[buf->id] - cx->enc_mem, | 490 | (void __iomem *)&cx->scb->cpu_mdl[buf->id] - cx->enc_mem, |
487 | 1, buf->id, s->buf_size); | 491 | 1, buf->id, s->buf_size); |
@@ -489,7 +493,14 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s) | |||
489 | /* begin_capture */ | 493 | /* begin_capture */ |
490 | if (cx18_vapi(cx, CX18_CPU_CAPTURE_START, 1, s->handle)) { | 494 | if (cx18_vapi(cx, CX18_CPU_CAPTURE_START, 1, s->handle)) { |
491 | CX18_DEBUG_WARN("Error starting capture!\n"); | 495 | CX18_DEBUG_WARN("Error starting capture!\n"); |
496 | /* Ensure we're really not capturing before releasing MDLs */ | ||
497 | if (s->type == CX18_ENC_STREAM_TYPE_MPG) | ||
498 | cx18_vapi(cx, CX18_CPU_CAPTURE_STOP, 2, s->handle, 1); | ||
499 | else | ||
500 | cx18_vapi(cx, CX18_CPU_CAPTURE_STOP, 1, s->handle); | ||
501 | cx18_vapi(cx, CX18_CPU_DE_RELEASE_MDL, 1, s->handle); | ||
492 | cx18_vapi(cx, CX18_DESTROY_TASK, 1, s->handle); | 502 | cx18_vapi(cx, CX18_DESTROY_TASK, 1, s->handle); |
503 | /* FIXME - clean-up DSP0_INT mask, i_flags, s_flags, etc. */ | ||
493 | return -EINVAL; | 504 | return -EINVAL; |
494 | } | 505 | } |
495 | 506 | ||
@@ -541,6 +552,9 @@ int cx18_stop_v4l2_encode_stream(struct cx18_stream *s, int gop_end) | |||
541 | CX18_INFO("ignoring gop_end: not (yet?) supported by the firmware\n"); | 552 | CX18_INFO("ignoring gop_end: not (yet?) supported by the firmware\n"); |
542 | } | 553 | } |
543 | 554 | ||
555 | /* Tell the CX23418 it can't use our buffers anymore */ | ||
556 | cx18_vapi(cx, CX18_CPU_DE_RELEASE_MDL, 1, s->handle); | ||
557 | |||
544 | if (s->type != CX18_ENC_STREAM_TYPE_TS) | 558 | if (s->type != CX18_ENC_STREAM_TYPE_TS) |
545 | atomic_dec(&cx->ana_capturing); | 559 | atomic_dec(&cx->ana_capturing); |
546 | atomic_dec(&cx->tot_capturing); | 560 | atomic_dec(&cx->tot_capturing); |
@@ -549,12 +563,12 @@ int cx18_stop_v4l2_encode_stream(struct cx18_stream *s, int gop_end) | |||
549 | clear_bit(CX18_F_S_STREAMING, &s->s_flags); | 563 | clear_bit(CX18_F_S_STREAMING, &s->s_flags); |
550 | 564 | ||
551 | cx18_vapi(cx, CX18_DESTROY_TASK, 1, s->handle); | 565 | cx18_vapi(cx, CX18_DESTROY_TASK, 1, s->handle); |
552 | s->handle = 0xffffffff; | 566 | s->handle = CX18_INVALID_TASK_HANDLE; |
553 | 567 | ||
554 | if (atomic_read(&cx->tot_capturing) > 0) | 568 | if (atomic_read(&cx->tot_capturing) > 0) |
555 | return 0; | 569 | return 0; |
556 | 570 | ||
557 | write_reg(5, CX18_DSP0_INTERRUPT_MASK); | 571 | cx18_write_reg(cx, 5, CX18_DSP0_INTERRUPT_MASK); |
558 | wake_up(&s->waitq); | 572 | wake_up(&s->waitq); |
559 | 573 | ||
560 | return 0; | 574 | return 0; |
@@ -568,8 +582,8 @@ u32 cx18_find_handle(struct cx18 *cx) | |||
568 | for (i = 0; i < CX18_MAX_STREAMS; i++) { | 582 | for (i = 0; i < CX18_MAX_STREAMS; i++) { |
569 | struct cx18_stream *s = &cx->streams[i]; | 583 | struct cx18_stream *s = &cx->streams[i]; |
570 | 584 | ||
571 | if (s->v4l2dev && s->handle) | 585 | if (s->v4l2dev && (s->handle != CX18_INVALID_TASK_HANDLE)) |
572 | return s->handle; | 586 | return s->handle; |
573 | } | 587 | } |
574 | return 0; | 588 | return CX18_INVALID_TASK_HANDLE; |
575 | } | 589 | } |
diff --git a/drivers/media/video/cx18/cx18-version.h b/drivers/media/video/cx18/cx18-version.h index d5c7a6f968dd..9f6be2d457fb 100644 --- a/drivers/media/video/cx18/cx18-version.h +++ b/drivers/media/video/cx18/cx18-version.h | |||
@@ -25,7 +25,7 @@ | |||
25 | #define CX18_DRIVER_NAME "cx18" | 25 | #define CX18_DRIVER_NAME "cx18" |
26 | #define CX18_DRIVER_VERSION_MAJOR 1 | 26 | #define CX18_DRIVER_VERSION_MAJOR 1 |
27 | #define CX18_DRIVER_VERSION_MINOR 0 | 27 | #define CX18_DRIVER_VERSION_MINOR 0 |
28 | #define CX18_DRIVER_VERSION_PATCHLEVEL 0 | 28 | #define CX18_DRIVER_VERSION_PATCHLEVEL 1 |
29 | 29 | ||
30 | #define CX18_VERSION __stringify(CX18_DRIVER_VERSION_MAJOR) "." __stringify(CX18_DRIVER_VERSION_MINOR) "." __stringify(CX18_DRIVER_VERSION_PATCHLEVEL) | 30 | #define CX18_VERSION __stringify(CX18_DRIVER_VERSION_MAJOR) "." __stringify(CX18_DRIVER_VERSION_MINOR) "." __stringify(CX18_DRIVER_VERSION_PATCHLEVEL) |
31 | #define CX18_DRIVER_VERSION KERNEL_VERSION(CX18_DRIVER_VERSION_MAJOR, \ | 31 | #define CX18_DRIVER_VERSION KERNEL_VERSION(CX18_DRIVER_VERSION_MAJOR, \ |
diff --git a/drivers/media/video/cx18/cx23418.h b/drivers/media/video/cx18/cx23418.h index e7ed053059a8..668f968d7761 100644 --- a/drivers/media/video/cx18/cx23418.h +++ b/drivers/media/video/cx18/cx23418.h | |||
@@ -351,7 +351,7 @@ | |||
351 | Descriptor Lists to the driver | 351 | Descriptor Lists to the driver |
352 | IN[0] - Task handle. Handle of the task to start | 352 | IN[0] - Task handle. Handle of the task to start |
353 | ReturnCode - One of the ERR_DE_... */ | 353 | ReturnCode - One of the ERR_DE_... */ |
354 | /* #define CX18_CPU_DE_ReleaseMDL (CPU_CMD_MASK_DE | 0x0006) */ | 354 | #define CX18_CPU_DE_RELEASE_MDL (CPU_CMD_MASK_DE | 0x0006) |
355 | 355 | ||
356 | /* Description: This command signals the cpu that the dat buffer has been | 356 | /* Description: This command signals the cpu that the dat buffer has been |
357 | consumed and ready for re-use. | 357 | consumed and ready for re-use. |
diff --git a/drivers/media/video/cx2341x.c b/drivers/media/video/cx2341x.c index 22847a0444f5..cbbe47fb87b7 100644 --- a/drivers/media/video/cx2341x.c +++ b/drivers/media/video/cx2341x.c | |||
@@ -508,7 +508,10 @@ int cx2341x_ctrl_query(const struct cx2341x_mpeg_params *params, | |||
508 | /* this setting is read-only for the cx2341x since the | 508 | /* this setting is read-only for the cx2341x since the |
509 | V4L2_CID_MPEG_STREAM_TYPE really determines the | 509 | V4L2_CID_MPEG_STREAM_TYPE really determines the |
510 | MPEG-1/2 setting */ | 510 | MPEG-1/2 setting */ |
511 | err = v4l2_ctrl_query_fill_std(qctrl); | 511 | err = v4l2_ctrl_query_fill(qctrl, |
512 | V4L2_MPEG_VIDEO_ENCODING_MPEG_1, | ||
513 | V4L2_MPEG_VIDEO_ENCODING_MPEG_2, 1, | ||
514 | V4L2_MPEG_VIDEO_ENCODING_MPEG_2); | ||
512 | if (err == 0) | 515 | if (err == 0) |
513 | qctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY; | 516 | qctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY; |
514 | return err; | 517 | return err; |
diff --git a/drivers/media/video/cx23885/Kconfig b/drivers/media/video/cx23885/Kconfig index e60bd31b51a3..8c1b7fa47a41 100644 --- a/drivers/media/video/cx23885/Kconfig +++ b/drivers/media/video/cx23885/Kconfig | |||
@@ -15,6 +15,7 @@ config VIDEO_CX23885 | |||
15 | select DVB_S5H1409 if !DVB_FE_CUSTOMISE | 15 | select DVB_S5H1409 if !DVB_FE_CUSTOMISE |
16 | select DVB_S5H1411 if !DVB_FE_CUSTOMISE | 16 | select DVB_S5H1411 if !DVB_FE_CUSTOMISE |
17 | select DVB_LGDT330X if !DVB_FE_CUSTOMISE | 17 | select DVB_LGDT330X if !DVB_FE_CUSTOMISE |
18 | select DVB_ZL10353 if !DVB_FE_CUSTOMISE | ||
18 | select MEDIA_TUNER_XC2028 if !DVB_FE_CUSTOMIZE | 19 | select MEDIA_TUNER_XC2028 if !DVB_FE_CUSTOMIZE |
19 | select MEDIA_TUNER_TDA8290 if !DVB_FE_CUSTOMIZE | 20 | select MEDIA_TUNER_TDA8290 if !DVB_FE_CUSTOMIZE |
20 | select MEDIA_TUNER_TDA18271 if !DVB_FE_CUSTOMIZE | 21 | select MEDIA_TUNER_TDA18271 if !DVB_FE_CUSTOMIZE |
diff --git a/drivers/media/video/cx23885/cx23885-417.c b/drivers/media/video/cx23885/cx23885-417.c index 7b0e8c01692e..395c11fa47ce 100644 --- a/drivers/media/video/cx23885/cx23885-417.c +++ b/drivers/media/video/cx23885/cx23885-417.c | |||
@@ -36,7 +36,6 @@ | |||
36 | #include <media/cx2341x.h> | 36 | #include <media/cx2341x.h> |
37 | 37 | ||
38 | #include "cx23885.h" | 38 | #include "cx23885.h" |
39 | #include "media/cx2341x.h" | ||
40 | 39 | ||
41 | #define CX23885_FIRM_IMAGE_SIZE 376836 | 40 | #define CX23885_FIRM_IMAGE_SIZE 376836 |
42 | #define CX23885_FIRM_IMAGE_NAME "v4l-cx23885-enc.fw" | 41 | #define CX23885_FIRM_IMAGE_NAME "v4l-cx23885-enc.fw" |
@@ -632,7 +631,7 @@ int mc417_memory_read(struct cx23885_dev *dev, u32 address, u32 *value) | |||
632 | /* ------------------------------------------------------------------ */ | 631 | /* ------------------------------------------------------------------ */ |
633 | 632 | ||
634 | /* MPEG encoder API */ | 633 | /* MPEG encoder API */ |
635 | char *cmd_to_str(int cmd) | 634 | static char *cmd_to_str(int cmd) |
636 | { | 635 | { |
637 | switch (cmd) { | 636 | switch (cmd) { |
638 | case CX2341X_ENC_PING_FW: | 637 | case CX2341X_ENC_PING_FW: |
@@ -1583,6 +1582,7 @@ static int mpeg_open(struct inode *inode, struct file *file) | |||
1583 | 1582 | ||
1584 | dprintk(2, "%s()\n", __func__); | 1583 | dprintk(2, "%s()\n", __func__); |
1585 | 1584 | ||
1585 | lock_kernel(); | ||
1586 | list_for_each(list, &cx23885_devlist) { | 1586 | list_for_each(list, &cx23885_devlist) { |
1587 | h = list_entry(list, struct cx23885_dev, devlist); | 1587 | h = list_entry(list, struct cx23885_dev, devlist); |
1588 | if (h->v4l_device->minor == minor) { | 1588 | if (h->v4l_device->minor == minor) { |
@@ -1591,13 +1591,17 @@ static int mpeg_open(struct inode *inode, struct file *file) | |||
1591 | } | 1591 | } |
1592 | } | 1592 | } |
1593 | 1593 | ||
1594 | if (dev == NULL) | 1594 | if (dev == NULL) { |
1595 | unlock_kernel(); | ||
1595 | return -ENODEV; | 1596 | return -ENODEV; |
1597 | } | ||
1596 | 1598 | ||
1597 | /* allocate + initialize per filehandle data */ | 1599 | /* allocate + initialize per filehandle data */ |
1598 | fh = kzalloc(sizeof(*fh), GFP_KERNEL); | 1600 | fh = kzalloc(sizeof(*fh), GFP_KERNEL); |
1599 | if (NULL == fh) | 1601 | if (NULL == fh) { |
1602 | unlock_kernel(); | ||
1600 | return -ENOMEM; | 1603 | return -ENOMEM; |
1604 | } | ||
1601 | 1605 | ||
1602 | file->private_data = fh; | 1606 | file->private_data = fh; |
1603 | fh->dev = dev; | 1607 | fh->dev = dev; |
@@ -1608,6 +1612,7 @@ static int mpeg_open(struct inode *inode, struct file *file) | |||
1608 | V4L2_FIELD_INTERLACED, | 1612 | V4L2_FIELD_INTERLACED, |
1609 | sizeof(struct cx23885_buffer), | 1613 | sizeof(struct cx23885_buffer), |
1610 | fh); | 1614 | fh); |
1615 | unlock_kernel(); | ||
1611 | 1616 | ||
1612 | return 0; | 1617 | return 0; |
1613 | } | 1618 | } |
diff --git a/drivers/media/video/cx23885/cx23885-cards.c b/drivers/media/video/cx23885/cx23885-cards.c index c36d3f632104..2cda15f829fd 100644 --- a/drivers/media/video/cx23885/cx23885-cards.c +++ b/drivers/media/video/cx23885/cx23885-cards.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <media/cx25840.h> | 26 | #include <media/cx25840.h> |
27 | 27 | ||
28 | #include "cx23885.h" | 28 | #include "cx23885.h" |
29 | #include "tuner-xc2028.h" | ||
29 | 30 | ||
30 | /* ------------------------------------------------------------------ */ | 31 | /* ------------------------------------------------------------------ */ |
31 | /* board config info */ | 32 | /* board config info */ |
@@ -148,6 +149,15 @@ struct cx23885_board cx23885_boards[] = { | |||
148 | .portb = CX23885_MPEG_DVB, | 149 | .portb = CX23885_MPEG_DVB, |
149 | .portc = CX23885_MPEG_DVB, | 150 | .portc = CX23885_MPEG_DVB, |
150 | }, | 151 | }, |
152 | [CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP] = { | ||
153 | .name = "DViCO FusionHDTV DVB-T Dual Express", | ||
154 | .portb = CX23885_MPEG_DVB, | ||
155 | .portc = CX23885_MPEG_DVB, | ||
156 | }, | ||
157 | [CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H] = { | ||
158 | .name = "Leadtek Winfast PxDVR3200 H", | ||
159 | .portc = CX23885_MPEG_DVB, | ||
160 | }, | ||
151 | }; | 161 | }; |
152 | const unsigned int cx23885_bcount = ARRAY_SIZE(cx23885_boards); | 162 | const unsigned int cx23885_bcount = ARRAY_SIZE(cx23885_boards); |
153 | 163 | ||
@@ -219,6 +229,14 @@ struct cx23885_subid cx23885_subids[] = { | |||
219 | .subvendor = 0x18ac, | 229 | .subvendor = 0x18ac, |
220 | .subdevice = 0xd618, | 230 | .subdevice = 0xd618, |
221 | .card = CX23885_BOARD_DVICO_FUSIONHDTV_7_DUAL_EXP, | 231 | .card = CX23885_BOARD_DVICO_FUSIONHDTV_7_DUAL_EXP, |
232 | },{ | ||
233 | .subvendor = 0x18ac, | ||
234 | .subdevice = 0xdb78, | ||
235 | .card = CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP, | ||
236 | }, { | ||
237 | .subvendor = 0x107d, | ||
238 | .subdevice = 0x6681, | ||
239 | .card = CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H, | ||
222 | }, | 240 | }, |
223 | }; | 241 | }; |
224 | const unsigned int cx23885_idcount = ARRAY_SIZE(cx23885_subids); | 242 | const unsigned int cx23885_idcount = ARRAY_SIZE(cx23885_subids); |
@@ -319,15 +337,15 @@ static void hauppauge_eeprom(struct cx23885_dev *dev, u8 *eeprom_data) | |||
319 | dev->name, tv.model); | 337 | dev->name, tv.model); |
320 | } | 338 | } |
321 | 339 | ||
322 | /* Tuner callback function for cx23885 boards. Currently only needed | 340 | int cx23885_tuner_callback(void *priv, int component, int command, int arg) |
323 | * for HVR1500Q, which has an xc5000 tuner. | ||
324 | */ | ||
325 | int cx23885_tuner_callback(void *priv, int command, int arg) | ||
326 | { | 341 | { |
327 | struct cx23885_i2c *bus = priv; | 342 | struct cx23885_tsport *port = priv; |
328 | struct cx23885_dev *dev = bus->dev; | 343 | struct cx23885_dev *dev = port->dev; |
329 | u32 bitmask = 0; | 344 | u32 bitmask = 0; |
330 | 345 | ||
346 | if (command == XC2028_RESET_CLK) | ||
347 | return 0; | ||
348 | |||
331 | if (command != 0) { | 349 | if (command != 0) { |
332 | printk(KERN_ERR "%s(): Unknown command 0x%x.\n", | 350 | printk(KERN_ERR "%s(): Unknown command 0x%x.\n", |
333 | __func__, command); | 351 | __func__, command); |
@@ -335,21 +353,21 @@ int cx23885_tuner_callback(void *priv, int command, int arg) | |||
335 | } | 353 | } |
336 | 354 | ||
337 | switch(dev->board) { | 355 | switch(dev->board) { |
356 | case CX23885_BOARD_HAUPPAUGE_HVR1400: | ||
357 | case CX23885_BOARD_HAUPPAUGE_HVR1500: | ||
338 | case CX23885_BOARD_HAUPPAUGE_HVR1500Q: | 358 | case CX23885_BOARD_HAUPPAUGE_HVR1500Q: |
339 | /* Tuner Reset Command from xc5000 */ | 359 | case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H: |
340 | if (command == 0) | 360 | /* Tuner Reset Command */ |
341 | bitmask = 0x04; | 361 | bitmask = 0x04; |
342 | break; | 362 | break; |
343 | case CX23885_BOARD_DVICO_FUSIONHDTV_7_DUAL_EXP: | 363 | case CX23885_BOARD_DVICO_FUSIONHDTV_7_DUAL_EXP: |
344 | if (command == 0) { | 364 | case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP: |
345 | 365 | /* Two identical tuners on two different i2c buses, | |
346 | /* Two identical tuners on two different i2c buses, | 366 | * we need to reset the correct gpio. */ |
347 | * we need to reset the correct gpio. */ | 367 | if (port->nr == 0) |
348 | if (bus->nr == 0) | 368 | bitmask = 0x01; |
349 | bitmask = 0x01; | 369 | else if (port->nr == 1) |
350 | else if (bus->nr == 1) | 370 | bitmask = 0x04; |
351 | bitmask = 0x04; | ||
352 | } | ||
353 | break; | 371 | break; |
354 | } | 372 | } |
355 | 373 | ||
@@ -465,6 +483,32 @@ void cx23885_gpio_setup(struct cx23885_dev *dev) | |||
465 | mdelay(20); | 483 | mdelay(20); |
466 | cx_set(GP0_IO, 0x000f000f); | 484 | cx_set(GP0_IO, 0x000f000f); |
467 | break; | 485 | break; |
486 | case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP: | ||
487 | /* GPIO-0 portb xc3028 reset */ | ||
488 | /* GPIO-1 portb zl10353 reset */ | ||
489 | /* GPIO-2 portc xc3028 reset */ | ||
490 | /* GPIO-3 portc zl10353 reset */ | ||
491 | |||
492 | /* Put the parts into reset and back */ | ||
493 | cx_set(GP0_IO, 0x000f0000); | ||
494 | mdelay(20); | ||
495 | cx_clear(GP0_IO, 0x0000000f); | ||
496 | mdelay(20); | ||
497 | cx_set(GP0_IO, 0x000f000f); | ||
498 | break; | ||
499 | case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H: | ||
500 | /* GPIO-2 xc3028 tuner reset */ | ||
501 | |||
502 | /* The following GPIO's are on the internal AVCore (cx25840) */ | ||
503 | /* GPIO-? zl10353 demod reset */ | ||
504 | |||
505 | /* Put the parts into reset and back */ | ||
506 | cx_set(GP0_IO, 0x00040000); | ||
507 | mdelay(20); | ||
508 | cx_clear(GP0_IO, 0x00000004); | ||
509 | mdelay(20); | ||
510 | cx_set(GP0_IO, 0x00040004); | ||
511 | break; | ||
468 | } | 512 | } |
469 | } | 513 | } |
470 | 514 | ||
@@ -479,6 +523,9 @@ int cx23885_ir_init(struct cx23885_dev *dev) | |||
479 | case CX23885_BOARD_HAUPPAUGE_HVR1400: | 523 | case CX23885_BOARD_HAUPPAUGE_HVR1400: |
480 | /* FIXME: Implement me */ | 524 | /* FIXME: Implement me */ |
481 | break; | 525 | break; |
526 | case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP: | ||
527 | request_module("ir-kbd-i2c"); | ||
528 | break; | ||
482 | } | 529 | } |
483 | 530 | ||
484 | return 0; | 531 | return 0; |
@@ -516,6 +563,7 @@ void cx23885_card_setup(struct cx23885_dev *dev) | |||
516 | 563 | ||
517 | switch (dev->board) { | 564 | switch (dev->board) { |
518 | case CX23885_BOARD_DVICO_FUSIONHDTV_7_DUAL_EXP: | 565 | case CX23885_BOARD_DVICO_FUSIONHDTV_7_DUAL_EXP: |
566 | case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP: | ||
519 | ts2->gen_ctrl_val = 0xc; /* Serial bus + punctured clock */ | 567 | ts2->gen_ctrl_val = 0xc; /* Serial bus + punctured clock */ |
520 | ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */ | 568 | ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */ |
521 | ts2->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO; | 569 | ts2->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO; |
@@ -548,6 +596,7 @@ void cx23885_card_setup(struct cx23885_dev *dev) | |||
548 | case CX23885_BOARD_HAUPPAUGE_HVR1200: | 596 | case CX23885_BOARD_HAUPPAUGE_HVR1200: |
549 | case CX23885_BOARD_HAUPPAUGE_HVR1700: | 597 | case CX23885_BOARD_HAUPPAUGE_HVR1700: |
550 | case CX23885_BOARD_HAUPPAUGE_HVR1400: | 598 | case CX23885_BOARD_HAUPPAUGE_HVR1400: |
599 | case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H: | ||
551 | default: | 600 | default: |
552 | ts2->gen_ctrl_val = 0xc; /* Serial bus + punctured clock */ | 601 | ts2->gen_ctrl_val = 0xc; /* Serial bus + punctured clock */ |
553 | ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */ | 602 | ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */ |
@@ -561,6 +610,7 @@ void cx23885_card_setup(struct cx23885_dev *dev) | |||
561 | case CX23885_BOARD_HAUPPAUGE_HVR1800: | 610 | case CX23885_BOARD_HAUPPAUGE_HVR1800: |
562 | case CX23885_BOARD_HAUPPAUGE_HVR1800lp: | 611 | case CX23885_BOARD_HAUPPAUGE_HVR1800lp: |
563 | case CX23885_BOARD_HAUPPAUGE_HVR1700: | 612 | case CX23885_BOARD_HAUPPAUGE_HVR1700: |
613 | case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H: | ||
564 | request_module("cx25840"); | 614 | request_module("cx25840"); |
565 | break; | 615 | break; |
566 | } | 616 | } |
diff --git a/drivers/media/video/cx23885/cx23885-core.c b/drivers/media/video/cx23885/cx23885-core.c index 25fb09938744..beb3e61669a3 100644 --- a/drivers/media/video/cx23885/cx23885-core.c +++ b/drivers/media/video/cx23885/cx23885-core.c | |||
@@ -1442,7 +1442,7 @@ void cx23885_cancel_buffers(struct cx23885_tsport *port) | |||
1442 | struct cx23885_dev *dev = port->dev; | 1442 | struct cx23885_dev *dev = port->dev; |
1443 | struct cx23885_dmaqueue *q = &port->mpegq; | 1443 | struct cx23885_dmaqueue *q = &port->mpegq; |
1444 | 1444 | ||
1445 | dprintk(1, "%s()\n", __FUNCTION__); | 1445 | dprintk(1, "%s()\n", __func__); |
1446 | del_timer_sync(&q->timeout); | 1446 | del_timer_sync(&q->timeout); |
1447 | cx23885_stop_dma(port); | 1447 | cx23885_stop_dma(port); |
1448 | do_cancel_buffers(port, "cancel", 0); | 1448 | do_cancel_buffers(port, "cancel", 0); |
diff --git a/drivers/media/video/cx23885/cx23885-dvb.c b/drivers/media/video/cx23885/cx23885-dvb.c index 291b9d008da8..24bd18327aa0 100644 --- a/drivers/media/video/cx23885/cx23885-dvb.c +++ b/drivers/media/video/cx23885/cx23885-dvb.c | |||
@@ -42,6 +42,7 @@ | |||
42 | #include "tuner-simple.h" | 42 | #include "tuner-simple.h" |
43 | #include "dib7000p.h" | 43 | #include "dib7000p.h" |
44 | #include "dibx000_common.h" | 44 | #include "dibx000_common.h" |
45 | #include "zl10353.h" | ||
45 | 46 | ||
46 | static unsigned int debug; | 47 | static unsigned int debug; |
47 | 48 | ||
@@ -188,13 +189,11 @@ static struct s5h1411_config dvico_s5h1411_config = { | |||
188 | static struct xc5000_config hauppauge_hvr1500q_tunerconfig = { | 189 | static struct xc5000_config hauppauge_hvr1500q_tunerconfig = { |
189 | .i2c_address = 0x61, | 190 | .i2c_address = 0x61, |
190 | .if_khz = 5380, | 191 | .if_khz = 5380, |
191 | .tuner_callback = cx23885_tuner_callback | ||
192 | }; | 192 | }; |
193 | 193 | ||
194 | static struct xc5000_config dvico_xc5000_tunerconfig = { | 194 | static struct xc5000_config dvico_xc5000_tunerconfig = { |
195 | .i2c_address = 0x64, | 195 | .i2c_address = 0x64, |
196 | .if_khz = 5380, | 196 | .if_khz = 5380, |
197 | .tuner_callback = cx23885_tuner_callback | ||
198 | }; | 197 | }; |
199 | 198 | ||
200 | static struct tda829x_config tda829x_no_probe = { | 199 | static struct tda829x_config tda829x_no_probe = { |
@@ -303,35 +302,11 @@ static struct dib7000p_config hauppauge_hvr1400_dib7000_config = { | |||
303 | .output_mode = OUTMODE_MPEG2_SERIAL, | 302 | .output_mode = OUTMODE_MPEG2_SERIAL, |
304 | }; | 303 | }; |
305 | 304 | ||
306 | static int cx23885_hvr1500_xc3028_callback(void *ptr, int command, int arg) | 305 | static struct zl10353_config dvico_fusionhdtv_xc3028 = { |
307 | { | 306 | .demod_address = 0x0f, |
308 | struct cx23885_tsport *port = ptr; | 307 | .if2 = 45600, |
309 | struct cx23885_dev *dev = port->dev; | 308 | .no_tuner = 1, |
310 | 309 | }; | |
311 | switch (command) { | ||
312 | case XC2028_TUNER_RESET: | ||
313 | /* Send the tuner in then out of reset */ | ||
314 | /* GPIO-2 xc3028 tuner */ | ||
315 | dprintk(1, "%s: XC2028_TUNER_RESET %d\n", __func__, arg); | ||
316 | |||
317 | cx_set(GP0_IO, 0x00040000); | ||
318 | cx_clear(GP0_IO, 0x00000004); | ||
319 | msleep(5); | ||
320 | |||
321 | cx_set(GP0_IO, 0x00040004); | ||
322 | msleep(5); | ||
323 | break; | ||
324 | case XC2028_RESET_CLK: | ||
325 | dprintk(1, "%s: XC2028_RESET_CLK %d\n", __func__, arg); | ||
326 | break; | ||
327 | default: | ||
328 | dprintk(1, "%s: unknown command %d, arg %d\n", __func__, | ||
329 | command, arg); | ||
330 | return -EINVAL; | ||
331 | } | ||
332 | |||
333 | return 0; | ||
334 | } | ||
335 | 310 | ||
336 | static int dvb_register(struct cx23885_tsport *port) | 311 | static int dvb_register(struct cx23885_tsport *port) |
337 | { | 312 | { |
@@ -413,8 +388,8 @@ static int dvb_register(struct cx23885_tsport *port) | |||
413 | &dev->i2c_bus[0].i2c_adap); | 388 | &dev->i2c_bus[0].i2c_adap); |
414 | if (port->dvb.frontend != NULL) | 389 | if (port->dvb.frontend != NULL) |
415 | dvb_attach(xc5000_attach, port->dvb.frontend, | 390 | dvb_attach(xc5000_attach, port->dvb.frontend, |
416 | &i2c_bus->i2c_adap, | 391 | &i2c_bus->i2c_adap, |
417 | &hauppauge_hvr1500q_tunerconfig, i2c_bus); | 392 | &hauppauge_hvr1500q_tunerconfig); |
418 | break; | 393 | break; |
419 | case CX23885_BOARD_HAUPPAUGE_HVR1500: | 394 | case CX23885_BOARD_HAUPPAUGE_HVR1500: |
420 | i2c_bus = &dev->i2c_bus[1]; | 395 | i2c_bus = &dev->i2c_bus[1]; |
@@ -426,10 +401,9 @@ static int dvb_register(struct cx23885_tsport *port) | |||
426 | struct xc2028_config cfg = { | 401 | struct xc2028_config cfg = { |
427 | .i2c_adap = &i2c_bus->i2c_adap, | 402 | .i2c_adap = &i2c_bus->i2c_adap, |
428 | .i2c_addr = 0x61, | 403 | .i2c_addr = 0x61, |
429 | .callback = cx23885_hvr1500_xc3028_callback, | ||
430 | }; | 404 | }; |
431 | static struct xc2028_ctrl ctl = { | 405 | static struct xc2028_ctrl ctl = { |
432 | .fname = "xc3028-v27.fw", | 406 | .fname = XC2028_DEFAULT_FIRMWARE, |
433 | .max_len = 64, | 407 | .max_len = 64, |
434 | .scode_table = XC3028_FE_OREN538, | 408 | .scode_table = XC3028_FE_OREN538, |
435 | }; | 409 | }; |
@@ -465,13 +439,13 @@ static int dvb_register(struct cx23885_tsport *port) | |||
465 | struct xc2028_config cfg = { | 439 | struct xc2028_config cfg = { |
466 | .i2c_adap = &dev->i2c_bus[1].i2c_adap, | 440 | .i2c_adap = &dev->i2c_bus[1].i2c_adap, |
467 | .i2c_addr = 0x64, | 441 | .i2c_addr = 0x64, |
468 | .callback = cx23885_hvr1500_xc3028_callback, | ||
469 | }; | 442 | }; |
470 | static struct xc2028_ctrl ctl = { | 443 | static struct xc2028_ctrl ctl = { |
471 | .fname = "xc3028L-v36.fw", | 444 | .fname = XC3028L_DEFAULT_FIRMWARE, |
472 | .max_len = 64, | 445 | .max_len = 64, |
473 | .demod = 5000, | 446 | .demod = 5000, |
474 | .d2633 = 1 | 447 | /* This is true for all demods with v36 firmware? */ |
448 | .type = XC2028_D2633, | ||
475 | }; | 449 | }; |
476 | 450 | ||
477 | fe = dvb_attach(xc2028_attach, | 451 | fe = dvb_attach(xc2028_attach, |
@@ -492,8 +466,57 @@ static int dvb_register(struct cx23885_tsport *port) | |||
492 | &i2c_bus->i2c_adap); | 466 | &i2c_bus->i2c_adap); |
493 | if (port->dvb.frontend != NULL) | 467 | if (port->dvb.frontend != NULL) |
494 | dvb_attach(xc5000_attach, port->dvb.frontend, | 468 | dvb_attach(xc5000_attach, port->dvb.frontend, |
495 | &i2c_bus->i2c_adap, | 469 | &i2c_bus->i2c_adap, |
496 | &dvico_xc5000_tunerconfig, i2c_bus); | 470 | &dvico_xc5000_tunerconfig); |
471 | break; | ||
472 | case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP: { | ||
473 | i2c_bus = &dev->i2c_bus[port->nr - 1]; | ||
474 | |||
475 | port->dvb.frontend = dvb_attach(zl10353_attach, | ||
476 | &dvico_fusionhdtv_xc3028, | ||
477 | &i2c_bus->i2c_adap); | ||
478 | if (port->dvb.frontend != NULL) { | ||
479 | struct dvb_frontend *fe; | ||
480 | struct xc2028_config cfg = { | ||
481 | .i2c_adap = &i2c_bus->i2c_adap, | ||
482 | .i2c_addr = 0x61, | ||
483 | }; | ||
484 | static struct xc2028_ctrl ctl = { | ||
485 | .fname = XC2028_DEFAULT_FIRMWARE, | ||
486 | .max_len = 64, | ||
487 | .demod = XC3028_FE_ZARLINK456, | ||
488 | }; | ||
489 | |||
490 | fe = dvb_attach(xc2028_attach, port->dvb.frontend, | ||
491 | &cfg); | ||
492 | if (fe != NULL && fe->ops.tuner_ops.set_config != NULL) | ||
493 | fe->ops.tuner_ops.set_config(fe, &ctl); | ||
494 | } | ||
495 | break; | ||
496 | } | ||
497 | case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H: | ||
498 | i2c_bus = &dev->i2c_bus[0]; | ||
499 | |||
500 | port->dvb.frontend = dvb_attach(zl10353_attach, | ||
501 | &dvico_fusionhdtv_xc3028, | ||
502 | &i2c_bus->i2c_adap); | ||
503 | if (port->dvb.frontend != NULL) { | ||
504 | struct dvb_frontend *fe; | ||
505 | struct xc2028_config cfg = { | ||
506 | .i2c_adap = &dev->i2c_bus[1].i2c_adap, | ||
507 | .i2c_addr = 0x61, | ||
508 | }; | ||
509 | static struct xc2028_ctrl ctl = { | ||
510 | .fname = XC2028_DEFAULT_FIRMWARE, | ||
511 | .max_len = 64, | ||
512 | .demod = XC3028_FE_ZARLINK456, | ||
513 | }; | ||
514 | |||
515 | fe = dvb_attach(xc2028_attach, port->dvb.frontend, | ||
516 | &cfg); | ||
517 | if (fe != NULL && fe->ops.tuner_ops.set_config != NULL) | ||
518 | fe->ops.tuner_ops.set_config(fe, &ctl); | ||
519 | } | ||
497 | break; | 520 | break; |
498 | default: | 521 | default: |
499 | printk("%s: The frontend of your DVB/ATSC card isn't supported yet\n", | 522 | printk("%s: The frontend of your DVB/ATSC card isn't supported yet\n", |
@@ -504,6 +527,8 @@ static int dvb_register(struct cx23885_tsport *port) | |||
504 | printk("%s: frontend initialization failed\n", dev->name); | 527 | printk("%s: frontend initialization failed\n", dev->name); |
505 | return -1; | 528 | return -1; |
506 | } | 529 | } |
530 | /* define general-purpose callback pointer */ | ||
531 | port->dvb.frontend->callback = cx23885_tuner_callback; | ||
507 | 532 | ||
508 | /* Put the analog decoder in standby to keep it quiet */ | 533 | /* Put the analog decoder in standby to keep it quiet */ |
509 | cx23885_call_i2c_clients(i2c_bus, TUNER_SET_STANDBY, NULL); | 534 | cx23885_call_i2c_clients(i2c_bus, TUNER_SET_STANDBY, NULL); |
diff --git a/drivers/media/video/cx23885/cx23885-vbi.c b/drivers/media/video/cx23885/cx23885-vbi.c index 35e61cd112fc..5b297f0323b6 100644 --- a/drivers/media/video/cx23885/cx23885-vbi.c +++ b/drivers/media/video/cx23885/cx23885-vbi.c | |||
@@ -85,18 +85,8 @@ static int cx23885_start_vbi_dma(struct cx23885_dev *dev, | |||
85 | return 0; | 85 | return 0; |
86 | } | 86 | } |
87 | 87 | ||
88 | int cx23885_stop_vbi_dma(struct cx23885_dev *dev) | ||
89 | { | ||
90 | /* stop dma */ | ||
91 | cx_clear(VID_A_DMA_CTL, 0x00000022); | ||
92 | |||
93 | /* disable irqs */ | ||
94 | cx_clear(PCI_INT_MSK, 0x000001); | ||
95 | cx_clear(VID_A_INT_MSK, 0x00000022); | ||
96 | return 0; | ||
97 | } | ||
98 | 88 | ||
99 | int cx23885_restart_vbi_queue(struct cx23885_dev *dev, | 89 | static int cx23885_restart_vbi_queue(struct cx23885_dev *dev, |
100 | struct cx23885_dmaqueue *q) | 90 | struct cx23885_dmaqueue *q) |
101 | { | 91 | { |
102 | struct cx23885_buffer *buf; | 92 | struct cx23885_buffer *buf; |
diff --git a/drivers/media/video/cx23885/cx23885-video.c b/drivers/media/video/cx23885/cx23885-video.c index 6047c78d84bf..f75ed1c9b71a 100644 --- a/drivers/media/video/cx23885/cx23885-video.c +++ b/drivers/media/video/cx23885/cx23885-video.c | |||
@@ -244,7 +244,7 @@ static struct cx23885_ctrl cx23885_ctls[] = { | |||
244 | }; | 244 | }; |
245 | static const int CX23885_CTLS = ARRAY_SIZE(cx23885_ctls); | 245 | static const int CX23885_CTLS = ARRAY_SIZE(cx23885_ctls); |
246 | 246 | ||
247 | const u32 cx23885_user_ctrls[] = { | 247 | static const u32 cx23885_user_ctrls[] = { |
248 | V4L2_CID_USER_CLASS, | 248 | V4L2_CID_USER_CLASS, |
249 | V4L2_CID_BRIGHTNESS, | 249 | V4L2_CID_BRIGHTNESS, |
250 | V4L2_CID_CONTRAST, | 250 | V4L2_CID_CONTRAST, |
@@ -254,14 +254,13 @@ const u32 cx23885_user_ctrls[] = { | |||
254 | V4L2_CID_AUDIO_MUTE, | 254 | V4L2_CID_AUDIO_MUTE, |
255 | 0 | 255 | 0 |
256 | }; | 256 | }; |
257 | EXPORT_SYMBOL(cx23885_user_ctrls); | ||
258 | 257 | ||
259 | static const u32 *ctrl_classes[] = { | 258 | static const u32 *ctrl_classes[] = { |
260 | cx23885_user_ctrls, | 259 | cx23885_user_ctrls, |
261 | NULL | 260 | NULL |
262 | }; | 261 | }; |
263 | 262 | ||
264 | void cx23885_video_wakeup(struct cx23885_dev *dev, | 263 | static void cx23885_video_wakeup(struct cx23885_dev *dev, |
265 | struct cx23885_dmaqueue *q, u32 count) | 264 | struct cx23885_dmaqueue *q, u32 count) |
266 | { | 265 | { |
267 | struct cx23885_buffer *buf; | 266 | struct cx23885_buffer *buf; |
@@ -296,7 +295,7 @@ void cx23885_video_wakeup(struct cx23885_dev *dev, | |||
296 | __func__, bc); | 295 | __func__, bc); |
297 | } | 296 | } |
298 | 297 | ||
299 | int cx23885_set_tvnorm(struct cx23885_dev *dev, v4l2_std_id norm) | 298 | static int cx23885_set_tvnorm(struct cx23885_dev *dev, v4l2_std_id norm) |
300 | { | 299 | { |
301 | dprintk(1, "%s(norm = 0x%08x) name: [%s]\n", | 300 | dprintk(1, "%s(norm = 0x%08x) name: [%s]\n", |
302 | __func__, | 301 | __func__, |
@@ -314,7 +313,7 @@ int cx23885_set_tvnorm(struct cx23885_dev *dev, v4l2_std_id norm) | |||
314 | return 0; | 313 | return 0; |
315 | } | 314 | } |
316 | 315 | ||
317 | struct video_device *cx23885_vdev_init(struct cx23885_dev *dev, | 316 | static struct video_device *cx23885_vdev_init(struct cx23885_dev *dev, |
318 | struct pci_dev *pci, | 317 | struct pci_dev *pci, |
319 | struct video_device *template, | 318 | struct video_device *template, |
320 | char *type) | 319 | char *type) |
@@ -334,7 +333,7 @@ struct video_device *cx23885_vdev_init(struct cx23885_dev *dev, | |||
334 | return vfd; | 333 | return vfd; |
335 | } | 334 | } |
336 | 335 | ||
337 | int cx23885_ctrl_query(struct v4l2_queryctrl *qctrl) | 336 | static int cx23885_ctrl_query(struct v4l2_queryctrl *qctrl) |
338 | { | 337 | { |
339 | int i; | 338 | int i; |
340 | 339 | ||
@@ -351,7 +350,6 @@ int cx23885_ctrl_query(struct v4l2_queryctrl *qctrl) | |||
351 | *qctrl = cx23885_ctls[i].v; | 350 | *qctrl = cx23885_ctls[i].v; |
352 | return 0; | 351 | return 0; |
353 | } | 352 | } |
354 | EXPORT_SYMBOL(cx23885_ctrl_query); | ||
355 | 353 | ||
356 | /* ------------------------------------------------------------------- */ | 354 | /* ------------------------------------------------------------------- */ |
357 | /* resource management */ | 355 | /* resource management */ |
@@ -402,7 +400,7 @@ static void res_free(struct cx23885_dev *dev, struct cx23885_fh *fh, | |||
402 | mutex_unlock(&dev->lock); | 400 | mutex_unlock(&dev->lock); |
403 | } | 401 | } |
404 | 402 | ||
405 | int cx23885_video_mux(struct cx23885_dev *dev, unsigned int input) | 403 | static int cx23885_video_mux(struct cx23885_dev *dev, unsigned int input) |
406 | { | 404 | { |
407 | struct v4l2_routing route; | 405 | struct v4l2_routing route; |
408 | memset(&route, 0, sizeof(route)); | 406 | memset(&route, 0, sizeof(route)); |
@@ -422,10 +420,9 @@ int cx23885_video_mux(struct cx23885_dev *dev, unsigned int input) | |||
422 | 420 | ||
423 | return 0; | 421 | return 0; |
424 | } | 422 | } |
425 | EXPORT_SYMBOL(cx23885_video_mux); | ||
426 | 423 | ||
427 | /* ------------------------------------------------------------------ */ | 424 | /* ------------------------------------------------------------------ */ |
428 | int cx23885_set_scale(struct cx23885_dev *dev, unsigned int width, | 425 | static int cx23885_set_scale(struct cx23885_dev *dev, unsigned int width, |
429 | unsigned int height, enum v4l2_field field) | 426 | unsigned int height, enum v4l2_field field) |
430 | { | 427 | { |
431 | dprintk(1, "%s()\n", __func__); | 428 | dprintk(1, "%s()\n", __func__); |
@@ -731,6 +728,7 @@ static int video_open(struct inode *inode, struct file *file) | |||
731 | enum v4l2_buf_type type = 0; | 728 | enum v4l2_buf_type type = 0; |
732 | int radio = 0; | 729 | int radio = 0; |
733 | 730 | ||
731 | lock_kernel(); | ||
734 | list_for_each(list, &cx23885_devlist) { | 732 | list_for_each(list, &cx23885_devlist) { |
735 | h = list_entry(list, struct cx23885_dev, devlist); | 733 | h = list_entry(list, struct cx23885_dev, devlist); |
736 | if (h->video_dev->minor == minor) { | 734 | if (h->video_dev->minor == minor) { |
@@ -748,16 +746,20 @@ static int video_open(struct inode *inode, struct file *file) | |||
748 | dev = h; | 746 | dev = h; |
749 | } | 747 | } |
750 | } | 748 | } |
751 | if (NULL == dev) | 749 | if (NULL == dev) { |
750 | unlock_kernel(); | ||
752 | return -ENODEV; | 751 | return -ENODEV; |
752 | } | ||
753 | 753 | ||
754 | dprintk(1, "open minor=%d radio=%d type=%s\n", | 754 | dprintk(1, "open minor=%d radio=%d type=%s\n", |
755 | minor, radio, v4l2_type_names[type]); | 755 | minor, radio, v4l2_type_names[type]); |
756 | 756 | ||
757 | /* allocate + initialize per filehandle data */ | 757 | /* allocate + initialize per filehandle data */ |
758 | fh = kzalloc(sizeof(*fh), GFP_KERNEL); | 758 | fh = kzalloc(sizeof(*fh), GFP_KERNEL); |
759 | if (NULL == fh) | 759 | if (NULL == fh) { |
760 | unlock_kernel(); | ||
760 | return -ENOMEM; | 761 | return -ENOMEM; |
762 | } | ||
761 | file->private_data = fh; | 763 | file->private_data = fh; |
762 | fh->dev = dev; | 764 | fh->dev = dev; |
763 | fh->radio = radio; | 765 | fh->radio = radio; |
@@ -775,6 +777,7 @@ static int video_open(struct inode *inode, struct file *file) | |||
775 | 777 | ||
776 | dprintk(1, "post videobuf_queue_init()\n"); | 778 | dprintk(1, "post videobuf_queue_init()\n"); |
777 | 779 | ||
780 | unlock_kernel(); | ||
778 | 781 | ||
779 | return 0; | 782 | return 0; |
780 | } | 783 | } |
@@ -884,21 +887,19 @@ static int video_mmap(struct file *file, struct vm_area_struct *vma) | |||
884 | /* ------------------------------------------------------------------ */ | 887 | /* ------------------------------------------------------------------ */ |
885 | /* VIDEO CTRL IOCTLS */ | 888 | /* VIDEO CTRL IOCTLS */ |
886 | 889 | ||
887 | int cx23885_get_control(struct cx23885_dev *dev, struct v4l2_control *ctl) | 890 | static int cx23885_get_control(struct cx23885_dev *dev, struct v4l2_control *ctl) |
888 | { | 891 | { |
889 | dprintk(1, "%s() calling cx25840(VIDIOC_G_CTRL)\n", __func__); | 892 | dprintk(1, "%s() calling cx25840(VIDIOC_G_CTRL)\n", __func__); |
890 | cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_G_CTRL, ctl); | 893 | cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_G_CTRL, ctl); |
891 | return 0; | 894 | return 0; |
892 | } | 895 | } |
893 | EXPORT_SYMBOL(cx23885_get_control); | ||
894 | 896 | ||
895 | int cx23885_set_control(struct cx23885_dev *dev, struct v4l2_control *ctl) | 897 | static int cx23885_set_control(struct cx23885_dev *dev, struct v4l2_control *ctl) |
896 | { | 898 | { |
897 | dprintk(1, "%s() calling cx25840(VIDIOC_S_CTRL)" | 899 | dprintk(1, "%s() calling cx25840(VIDIOC_S_CTRL)" |
898 | " (disabled - no action)\n", __func__); | 900 | " (disabled - no action)\n", __func__); |
899 | return 0; | 901 | return 0; |
900 | } | 902 | } |
901 | EXPORT_SYMBOL(cx23885_set_control); | ||
902 | 903 | ||
903 | static void init_controls(struct cx23885_dev *dev) | 904 | static void init_controls(struct cx23885_dev *dev) |
904 | { | 905 | { |
@@ -1146,7 +1147,7 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *tvnorms) | |||
1146 | return 0; | 1147 | return 0; |
1147 | } | 1148 | } |
1148 | 1149 | ||
1149 | int cx23885_enum_input(struct cx23885_dev *dev, struct v4l2_input *i) | 1150 | static int cx23885_enum_input(struct cx23885_dev *dev, struct v4l2_input *i) |
1150 | { | 1151 | { |
1151 | static const char *iname[] = { | 1152 | static const char *iname[] = { |
1152 | [CX23885_VMUX_COMPOSITE1] = "Composite1", | 1153 | [CX23885_VMUX_COMPOSITE1] = "Composite1", |
@@ -1179,7 +1180,6 @@ int cx23885_enum_input(struct cx23885_dev *dev, struct v4l2_input *i) | |||
1179 | i->std = CX23885_NORMS; | 1180 | i->std = CX23885_NORMS; |
1180 | return 0; | 1181 | return 0; |
1181 | } | 1182 | } |
1182 | EXPORT_SYMBOL(cx23885_enum_input); | ||
1183 | 1183 | ||
1184 | static int vidioc_enum_input(struct file *file, void *priv, | 1184 | static int vidioc_enum_input(struct file *file, void *priv, |
1185 | struct v4l2_input *i) | 1185 | struct v4l2_input *i) |
@@ -1288,7 +1288,7 @@ static int vidioc_g_frequency(struct file *file, void *priv, | |||
1288 | return 0; | 1288 | return 0; |
1289 | } | 1289 | } |
1290 | 1290 | ||
1291 | int cx23885_set_freq(struct cx23885_dev *dev, struct v4l2_frequency *f) | 1291 | static int cx23885_set_freq(struct cx23885_dev *dev, struct v4l2_frequency *f) |
1292 | { | 1292 | { |
1293 | if (unlikely(UNSET == dev->tuner_type)) | 1293 | if (unlikely(UNSET == dev->tuner_type)) |
1294 | return -EINVAL; | 1294 | return -EINVAL; |
@@ -1307,7 +1307,6 @@ int cx23885_set_freq(struct cx23885_dev *dev, struct v4l2_frequency *f) | |||
1307 | 1307 | ||
1308 | return 0; | 1308 | return 0; |
1309 | } | 1309 | } |
1310 | EXPORT_SYMBOL(cx23885_set_freq); | ||
1311 | 1310 | ||
1312 | static int vidioc_s_frequency(struct file *file, void *priv, | 1311 | static int vidioc_s_frequency(struct file *file, void *priv, |
1313 | struct v4l2_frequency *f) | 1312 | struct v4l2_frequency *f) |
diff --git a/drivers/media/video/cx23885/cx23885.h b/drivers/media/video/cx23885/cx23885.h index e23d97c071e0..ba4e0aaed463 100644 --- a/drivers/media/video/cx23885/cx23885.h +++ b/drivers/media/video/cx23885/cx23885.h | |||
@@ -64,6 +64,8 @@ | |||
64 | #define CX23885_BOARD_HAUPPAUGE_HVR1700 8 | 64 | #define CX23885_BOARD_HAUPPAUGE_HVR1700 8 |
65 | #define CX23885_BOARD_HAUPPAUGE_HVR1400 9 | 65 | #define CX23885_BOARD_HAUPPAUGE_HVR1400 9 |
66 | #define CX23885_BOARD_DVICO_FUSIONHDTV_7_DUAL_EXP 10 | 66 | #define CX23885_BOARD_DVICO_FUSIONHDTV_7_DUAL_EXP 10 |
67 | #define CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP 11 | ||
68 | #define CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H 12 | ||
67 | 69 | ||
68 | /* Currently unsupported by the driver: PAL/H, NTSC/Kr, SECAM B/G/H/LC */ | 70 | /* Currently unsupported by the driver: PAL/H, NTSC/Kr, SECAM B/G/H/LC */ |
69 | #define CX23885_NORMS (\ | 71 | #define CX23885_NORMS (\ |
@@ -409,7 +411,7 @@ extern const unsigned int cx23885_bcount; | |||
409 | extern struct cx23885_subid cx23885_subids[]; | 411 | extern struct cx23885_subid cx23885_subids[]; |
410 | extern const unsigned int cx23885_idcount; | 412 | extern const unsigned int cx23885_idcount; |
411 | 413 | ||
412 | extern int cx23885_tuner_callback(void *priv, int command, int arg); | 414 | extern int cx23885_tuner_callback(void *priv, int component, int command, int arg); |
413 | extern void cx23885_card_list(struct cx23885_dev *dev); | 415 | extern void cx23885_card_list(struct cx23885_dev *dev); |
414 | extern int cx23885_ir_init(struct cx23885_dev *dev); | 416 | extern int cx23885_ir_init(struct cx23885_dev *dev); |
415 | extern void cx23885_gpio_setup(struct cx23885_dev *dev); | 417 | extern void cx23885_gpio_setup(struct cx23885_dev *dev); |
diff --git a/drivers/media/video/cx25840/cx25840-vbi.c b/drivers/media/video/cx25840/cx25840-vbi.c index 69f2bbdbb929..58e6ef1c28a0 100644 --- a/drivers/media/video/cx25840/cx25840-vbi.c +++ b/drivers/media/video/cx25840/cx25840-vbi.c | |||
@@ -141,10 +141,11 @@ int cx25840_vbi(struct i2c_client *client, unsigned int cmd, void *arg) | |||
141 | u8 lcr[24]; | 141 | u8 lcr[24]; |
142 | 142 | ||
143 | fmt = arg; | 143 | fmt = arg; |
144 | if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) | 144 | if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE && |
145 | fmt->type != V4L2_BUF_TYPE_VBI_CAPTURE) | ||
145 | return -EINVAL; | 146 | return -EINVAL; |
146 | svbi = &fmt->fmt.sliced; | 147 | svbi = &fmt->fmt.sliced; |
147 | if (svbi->service_set == 0) { | 148 | if (fmt->type == V4L2_BUF_TYPE_VBI_CAPTURE) { |
148 | /* raw VBI */ | 149 | /* raw VBI */ |
149 | memset(svbi, 0, sizeof(*svbi)); | 150 | memset(svbi, 0, sizeof(*svbi)); |
150 | 151 | ||
diff --git a/drivers/media/video/cx88/Kconfig b/drivers/media/video/cx88/Kconfig index 9dd7bdf659b9..0b9e5fac6239 100644 --- a/drivers/media/video/cx88/Kconfig +++ b/drivers/media/video/cx88/Kconfig | |||
@@ -58,6 +58,10 @@ config VIDEO_CX88_DVB | |||
58 | select DVB_ISL6421 if !DVB_FE_CUSTOMISE | 58 | select DVB_ISL6421 if !DVB_FE_CUSTOMISE |
59 | select MEDIA_TUNER_SIMPLE if !DVB_FE_CUSTOMISE | 59 | select MEDIA_TUNER_SIMPLE if !DVB_FE_CUSTOMISE |
60 | select DVB_S5H1411 if !DVB_FE_CUSTOMISE | 60 | select DVB_S5H1411 if !DVB_FE_CUSTOMISE |
61 | select DVB_CX24116 if !DVB_FE_CUSTOMISE | ||
62 | select DVB_STV0299 if !DVB_FE_CUSTOMISE | ||
63 | select DVB_STV0288 if !DVB_FE_CUSTOMISE | ||
64 | select DVB_STB6000 if !DVB_FE_CUSTOMISE | ||
61 | ---help--- | 65 | ---help--- |
62 | This adds support for DVB/ATSC cards based on the | 66 | This adds support for DVB/ATSC cards based on the |
63 | Conexant 2388x chip. | 67 | Conexant 2388x chip. |
diff --git a/drivers/media/video/cx88/cx88-blackbird.c b/drivers/media/video/cx88/cx88-blackbird.c index 9a1374a38ec7..e71369754305 100644 --- a/drivers/media/video/cx88/cx88-blackbird.c +++ b/drivers/media/video/cx88/cx88-blackbird.c | |||
@@ -1057,12 +1057,15 @@ static int mpeg_open(struct inode *inode, struct file *file) | |||
1057 | struct cx8802_driver *drv = NULL; | 1057 | struct cx8802_driver *drv = NULL; |
1058 | int err; | 1058 | int err; |
1059 | 1059 | ||
1060 | lock_kernel(); | ||
1060 | dev = cx8802_get_device(inode); | 1061 | dev = cx8802_get_device(inode); |
1061 | 1062 | ||
1062 | dprintk( 1, "%s\n", __func__); | 1063 | dprintk( 1, "%s\n", __func__); |
1063 | 1064 | ||
1064 | if (dev == NULL) | 1065 | if (dev == NULL) { |
1066 | unlock_kernel(); | ||
1065 | return -ENODEV; | 1067 | return -ENODEV; |
1068 | } | ||
1066 | 1069 | ||
1067 | /* Make sure we can acquire the hardware */ | 1070 | /* Make sure we can acquire the hardware */ |
1068 | drv = cx8802_get_driver(dev, CX88_MPEG_BLACKBIRD); | 1071 | drv = cx8802_get_driver(dev, CX88_MPEG_BLACKBIRD); |
@@ -1070,6 +1073,7 @@ static int mpeg_open(struct inode *inode, struct file *file) | |||
1070 | err = drv->request_acquire(drv); | 1073 | err = drv->request_acquire(drv); |
1071 | if(err != 0) { | 1074 | if(err != 0) { |
1072 | dprintk(1,"%s: Unable to acquire hardware, %d\n", __func__, err); | 1075 | dprintk(1,"%s: Unable to acquire hardware, %d\n", __func__, err); |
1076 | unlock_kernel(); | ||
1073 | return err; | 1077 | return err; |
1074 | } | 1078 | } |
1075 | } | 1079 | } |
@@ -1077,6 +1081,7 @@ static int mpeg_open(struct inode *inode, struct file *file) | |||
1077 | if (blackbird_initialize_codec(dev) < 0) { | 1081 | if (blackbird_initialize_codec(dev) < 0) { |
1078 | if (drv) | 1082 | if (drv) |
1079 | drv->request_release(drv); | 1083 | drv->request_release(drv); |
1084 | unlock_kernel(); | ||
1080 | return -EINVAL; | 1085 | return -EINVAL; |
1081 | } | 1086 | } |
1082 | dprintk(1,"open minor=%d\n",minor); | 1087 | dprintk(1,"open minor=%d\n",minor); |
@@ -1086,6 +1091,7 @@ static int mpeg_open(struct inode *inode, struct file *file) | |||
1086 | if (NULL == fh) { | 1091 | if (NULL == fh) { |
1087 | if (drv) | 1092 | if (drv) |
1088 | drv->request_release(drv); | 1093 | drv->request_release(drv); |
1094 | unlock_kernel(); | ||
1089 | return -ENOMEM; | 1095 | return -ENOMEM; |
1090 | } | 1096 | } |
1091 | file->private_data = fh; | 1097 | file->private_data = fh; |
@@ -1101,6 +1107,7 @@ static int mpeg_open(struct inode *inode, struct file *file) | |||
1101 | /* FIXME: locking against other video device */ | 1107 | /* FIXME: locking against other video device */ |
1102 | cx88_set_scale(dev->core, dev->width, dev->height, | 1108 | cx88_set_scale(dev->core, dev->width, dev->height, |
1103 | fh->mpegq.field); | 1109 | fh->mpegq.field); |
1110 | unlock_kernel(); | ||
1104 | 1111 | ||
1105 | return 0; | 1112 | return 0; |
1106 | } | 1113 | } |
diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index de199a206a15..5da04e811ca2 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c | |||
@@ -1349,27 +1349,30 @@ static const struct cx88_board cx88_boards[] = { | |||
1349 | .radio_addr = ADDR_UNSET, | 1349 | .radio_addr = ADDR_UNSET, |
1350 | .tda9887_conf = TDA9887_PRESENT, | 1350 | .tda9887_conf = TDA9887_PRESENT, |
1351 | .audio_chip = V4L2_IDENT_WM8775, | 1351 | .audio_chip = V4L2_IDENT_WM8775, |
1352 | /* | ||
1353 | * gpio0 as reported by Mike Crash <mike AT mikecrash.com> | ||
1354 | */ | ||
1352 | .input = {{ | 1355 | .input = {{ |
1353 | .type = CX88_VMUX_TELEVISION, | 1356 | .type = CX88_VMUX_TELEVISION, |
1354 | .vmux = 0, | 1357 | .vmux = 0, |
1355 | .gpio0 = 0xe780, | 1358 | .gpio0 = 0xef88, |
1356 | .audioroute = 1, | 1359 | .audioroute = 1, |
1357 | },{ | 1360 | },{ |
1358 | .type = CX88_VMUX_COMPOSITE1, | 1361 | .type = CX88_VMUX_COMPOSITE1, |
1359 | .vmux = 1, | 1362 | .vmux = 1, |
1360 | .gpio0 = 0xe780, | 1363 | .gpio0 = 0xef88, |
1361 | .audioroute = 2, | 1364 | .audioroute = 2, |
1362 | },{ | 1365 | },{ |
1363 | .type = CX88_VMUX_SVIDEO, | 1366 | .type = CX88_VMUX_SVIDEO, |
1364 | .vmux = 2, | 1367 | .vmux = 2, |
1365 | .gpio0 = 0xe780, | 1368 | .gpio0 = 0xef88, |
1366 | .audioroute = 2, | 1369 | .audioroute = 2, |
1367 | }}, | 1370 | }}, |
1368 | /* fixme: Add radio support */ | 1371 | /* fixme: Add radio support */ |
1369 | .mpeg = CX88_MPEG_DVB | CX88_MPEG_BLACKBIRD, | 1372 | .mpeg = CX88_MPEG_DVB | CX88_MPEG_BLACKBIRD, |
1370 | .radio = { | 1373 | .radio = { |
1371 | .type = CX88_RADIO, | 1374 | .type = CX88_RADIO, |
1372 | .gpio0 = 0xe780, | 1375 | .gpio0 = 0xef88, |
1373 | }, | 1376 | }, |
1374 | }, | 1377 | }, |
1375 | [CX88_BOARD_ADSTECH_PTV_390] = { | 1378 | [CX88_BOARD_ADSTECH_PTV_390] = { |
@@ -1446,15 +1449,26 @@ static const struct cx88_board cx88_boards[] = { | |||
1446 | .name = "Pinnacle Hybrid PCTV", | 1449 | .name = "Pinnacle Hybrid PCTV", |
1447 | .tuner_type = TUNER_XC2028, | 1450 | .tuner_type = TUNER_XC2028, |
1448 | .tuner_addr = 0x61, | 1451 | .tuner_addr = 0x61, |
1452 | .radio_type = TUNER_XC2028, | ||
1453 | .radio_addr = 0x61, | ||
1449 | .input = { { | 1454 | .input = { { |
1450 | .type = CX88_VMUX_TELEVISION, | 1455 | .type = CX88_VMUX_TELEVISION, |
1451 | .vmux = 0, | 1456 | .vmux = 0, |
1457 | .gpio0 = 0x004ff, | ||
1458 | .gpio1 = 0x010ff, | ||
1459 | .gpio2 = 0x00001, | ||
1452 | }, { | 1460 | }, { |
1453 | .type = CX88_VMUX_COMPOSITE1, | 1461 | .type = CX88_VMUX_COMPOSITE1, |
1454 | .vmux = 1, | 1462 | .vmux = 1, |
1463 | .gpio0 = 0x004fb, | ||
1464 | .gpio1 = 0x010ef, | ||
1465 | .audioroute = 1, | ||
1455 | }, { | 1466 | }, { |
1456 | .type = CX88_VMUX_SVIDEO, | 1467 | .type = CX88_VMUX_SVIDEO, |
1457 | .vmux = 2, | 1468 | .vmux = 2, |
1469 | .gpio0 = 0x004fb, | ||
1470 | .gpio1 = 0x010ef, | ||
1471 | .audioroute = 1, | ||
1458 | } }, | 1472 | } }, |
1459 | .radio = { | 1473 | .radio = { |
1460 | .type = CX88_RADIO, | 1474 | .type = CX88_RADIO, |
@@ -1462,6 +1476,7 @@ static const struct cx88_board cx88_boards[] = { | |||
1462 | .gpio1 = 0x010ff, | 1476 | .gpio1 = 0x010ff, |
1463 | .gpio2 = 0x0ff, | 1477 | .gpio2 = 0x0ff, |
1464 | }, | 1478 | }, |
1479 | .mpeg = CX88_MPEG_DVB, | ||
1465 | }, | 1480 | }, |
1466 | [CX88_BOARD_WINFAST_TV2000_XP_GLOBAL] = { | 1481 | [CX88_BOARD_WINFAST_TV2000_XP_GLOBAL] = { |
1467 | .name = "Winfast TV2000 XP Global", | 1482 | .name = "Winfast TV2000 XP Global", |
@@ -1566,9 +1581,9 @@ static const struct cx88_board cx88_boards[] = { | |||
1566 | }, | 1581 | }, |
1567 | [CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO] = { | 1582 | [CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO] = { |
1568 | .name = "DViCO FusionHDTV DVB-T PRO", | 1583 | .name = "DViCO FusionHDTV DVB-T PRO", |
1569 | .tuner_type = TUNER_ABSENT, /* XXX: Has XC3028 */ | 1584 | .tuner_type = TUNER_XC2028, |
1585 | .tuner_addr = 0x61, | ||
1570 | .radio_type = UNSET, | 1586 | .radio_type = UNSET, |
1571 | .tuner_addr = ADDR_UNSET, | ||
1572 | .radio_addr = ADDR_UNSET, | 1587 | .radio_addr = ADDR_UNSET, |
1573 | .input = { { | 1588 | .input = { { |
1574 | .type = CX88_VMUX_COMPOSITE1, | 1589 | .type = CX88_VMUX_COMPOSITE1, |
@@ -1625,6 +1640,36 @@ static const struct cx88_board cx88_boards[] = { | |||
1625 | .gpio2 = 0x0cfb, | 1640 | .gpio2 = 0x0cfb, |
1626 | }, | 1641 | }, |
1627 | }, | 1642 | }, |
1643 | [CX88_BOARD_PROLINK_PV_GLOBAL_XTREME] = { | ||
1644 | .name = "Prolink Pixelview Global Extreme", | ||
1645 | .tuner_type = TUNER_XC2028, | ||
1646 | .tuner_addr = 0x61, | ||
1647 | .input = { { | ||
1648 | .type = CX88_VMUX_TELEVISION, | ||
1649 | .vmux = 0, | ||
1650 | .gpio0 = 0x04fb, | ||
1651 | .gpio1 = 0x04080, | ||
1652 | .gpio2 = 0x0cf7, | ||
1653 | }, { | ||
1654 | .type = CX88_VMUX_COMPOSITE1, | ||
1655 | .vmux = 1, | ||
1656 | .gpio0 = 0x04fb, | ||
1657 | .gpio1 = 0x04080, | ||
1658 | .gpio2 = 0x0cfb, | ||
1659 | }, { | ||
1660 | .type = CX88_VMUX_SVIDEO, | ||
1661 | .vmux = 2, | ||
1662 | .gpio0 = 0x04fb, | ||
1663 | .gpio1 = 0x04080, | ||
1664 | .gpio2 = 0x0cfb, | ||
1665 | } }, | ||
1666 | .radio = { | ||
1667 | .type = CX88_RADIO, | ||
1668 | .gpio0 = 0x04ff, | ||
1669 | .gpio1 = 0x04080, | ||
1670 | .gpio2 = 0x0cf7, | ||
1671 | }, | ||
1672 | }, | ||
1628 | /* Both radio, analog and ATSC work with this board. | 1673 | /* Both radio, analog and ATSC work with this board. |
1629 | However, for analog to work, s5h1409 gate should be open, | 1674 | However, for analog to work, s5h1409 gate should be open, |
1630 | otherwise, tuner-xc3028 won't be detected. | 1675 | otherwise, tuner-xc3028 won't be detected. |
@@ -1664,6 +1709,131 @@ static const struct cx88_board cx88_boards[] = { | |||
1664 | }, | 1709 | }, |
1665 | .mpeg = CX88_MPEG_DVB, | 1710 | .mpeg = CX88_MPEG_DVB, |
1666 | }, | 1711 | }, |
1712 | [CX88_BOARD_HAUPPAUGE_HVR4000] = { | ||
1713 | .name = "Hauppauge WinTV-HVR4000 DVB-S/S2/T/Hybrid", | ||
1714 | .tuner_type = TUNER_PHILIPS_FMD1216ME_MK3, | ||
1715 | .radio_type = UNSET, | ||
1716 | .tuner_addr = ADDR_UNSET, | ||
1717 | .radio_addr = ADDR_UNSET, | ||
1718 | .tda9887_conf = TDA9887_PRESENT, | ||
1719 | /* | ||
1720 | * GPIO0 (WINTV2000) | ||
1721 | * | ||
1722 | * Analogue SAT DVB-T | ||
1723 | * Antenna 0xc4bf 0xc4bb | ||
1724 | * Composite 0xc4bf 0xc4bb | ||
1725 | * S-Video 0xc4bf 0xc4bb | ||
1726 | * Composite1 0xc4ff 0xc4fb | ||
1727 | * S-Video1 0xc4ff 0xc4fb | ||
1728 | * | ||
1729 | * BIT VALUE FUNCTION GP{x}_IO | ||
1730 | * 0 1 I:? | ||
1731 | * 1 1 I:? | ||
1732 | * 2 1 O:DVB-T DEMOD ENABLE LOW/ANALOG DEMOD ENABLE HIGH | ||
1733 | * 3 1 I:? | ||
1734 | * 4 1 I:? | ||
1735 | * 5 1 I:? | ||
1736 | * 6 0 O:INPUT SELECTOR 0=INTERNAL 1=EXPANSION | ||
1737 | * 7 1 O:DVB-T DEMOD RESET LOW | ||
1738 | * | ||
1739 | * BIT VALUE FUNCTION GP{x}_OE | ||
1740 | * 8 0 I | ||
1741 | * 9 0 I | ||
1742 | * a 1 O | ||
1743 | * b 0 I | ||
1744 | * c 0 I | ||
1745 | * d 0 I | ||
1746 | * e 1 O | ||
1747 | * f 1 O | ||
1748 | */ | ||
1749 | .input = {{ | ||
1750 | .type = CX88_VMUX_TELEVISION, | ||
1751 | .vmux = 0, | ||
1752 | .gpio0 = 0xc4bf, | ||
1753 | }, { | ||
1754 | .type = CX88_VMUX_COMPOSITE1, | ||
1755 | .vmux = 1, | ||
1756 | .gpio0 = 0xc4bf, | ||
1757 | }, { | ||
1758 | .type = CX88_VMUX_SVIDEO, | ||
1759 | .vmux = 2, | ||
1760 | .gpio0 = 0xc4bf, | ||
1761 | } }, | ||
1762 | /* fixme: Add radio support */ | ||
1763 | .mpeg = CX88_MPEG_DVB, | ||
1764 | }, | ||
1765 | [CX88_BOARD_HAUPPAUGE_HVR4000LITE] = { | ||
1766 | .name = "Hauppauge WinTV-HVR4000(Lite) DVB-S/S2", | ||
1767 | .tuner_type = UNSET, | ||
1768 | .radio_type = UNSET, | ||
1769 | .tuner_addr = ADDR_UNSET, | ||
1770 | .radio_addr = ADDR_UNSET, | ||
1771 | .input = {{ | ||
1772 | .type = CX88_VMUX_DVB, | ||
1773 | .vmux = 0, | ||
1774 | } }, | ||
1775 | .mpeg = CX88_MPEG_DVB, | ||
1776 | }, | ||
1777 | [CX88_BOARD_TEVII_S420] = { | ||
1778 | .name = "TeVii S420 DVB-S", | ||
1779 | .tuner_type = UNSET, | ||
1780 | .radio_type = UNSET, | ||
1781 | .tuner_addr = ADDR_UNSET, | ||
1782 | .radio_addr = ADDR_UNSET, | ||
1783 | .input = {{ | ||
1784 | .type = CX88_VMUX_DVB, | ||
1785 | .vmux = 0, | ||
1786 | } }, | ||
1787 | .mpeg = CX88_MPEG_DVB, | ||
1788 | }, | ||
1789 | [CX88_BOARD_TEVII_S460] = { | ||
1790 | .name = "TeVii S460 DVB-S/S2", | ||
1791 | .tuner_type = UNSET, | ||
1792 | .radio_type = UNSET, | ||
1793 | .tuner_addr = ADDR_UNSET, | ||
1794 | .radio_addr = ADDR_UNSET, | ||
1795 | .input = {{ | ||
1796 | .type = CX88_VMUX_DVB, | ||
1797 | .vmux = 0, | ||
1798 | } }, | ||
1799 | .mpeg = CX88_MPEG_DVB, | ||
1800 | }, | ||
1801 | [CX88_BOARD_OMICOM_SS4_PCI] = { | ||
1802 | .name = "Omicom SS4 DVB-S/S2 PCI", | ||
1803 | .tuner_type = UNSET, | ||
1804 | .radio_type = UNSET, | ||
1805 | .tuner_addr = ADDR_UNSET, | ||
1806 | .radio_addr = ADDR_UNSET, | ||
1807 | .input = {{ | ||
1808 | .type = CX88_VMUX_DVB, | ||
1809 | .vmux = 0, | ||
1810 | } }, | ||
1811 | .mpeg = CX88_MPEG_DVB, | ||
1812 | }, | ||
1813 | [CX88_BOARD_TBS_8920] = { | ||
1814 | .name = "TBS 8920 DVB-S/S2", | ||
1815 | .tuner_type = TUNER_ABSENT, | ||
1816 | .radio_type = UNSET, | ||
1817 | .tuner_addr = ADDR_UNSET, | ||
1818 | .radio_addr = ADDR_UNSET, | ||
1819 | .input = {{ | ||
1820 | .type = CX88_VMUX_DVB, | ||
1821 | .vmux = 1, | ||
1822 | } }, | ||
1823 | .mpeg = CX88_MPEG_DVB, | ||
1824 | }, | ||
1825 | [CX88_BOARD_PROF_7300] = { | ||
1826 | .name = "PROF 7300 DVB-S/S2", | ||
1827 | .tuner_type = UNSET, | ||
1828 | .radio_type = UNSET, | ||
1829 | .tuner_addr = ADDR_UNSET, | ||
1830 | .radio_addr = ADDR_UNSET, | ||
1831 | .input = {{ | ||
1832 | .type = CX88_VMUX_DVB, | ||
1833 | .vmux = 0, | ||
1834 | } }, | ||
1835 | .mpeg = CX88_MPEG_DVB, | ||
1836 | }, | ||
1667 | }; | 1837 | }; |
1668 | 1838 | ||
1669 | /* ------------------------------------------------------------------ */ | 1839 | /* ------------------------------------------------------------------ */ |
@@ -2010,9 +2180,53 @@ static const struct cx88_subid cx88_subids[] = { | |||
2010 | .subdevice = 0x4935, | 2180 | .subdevice = 0x4935, |
2011 | .card = CX88_BOARD_PROLINK_PV_8000GT, | 2181 | .card = CX88_BOARD_PROLINK_PV_8000GT, |
2012 | }, { | 2182 | }, { |
2183 | .subvendor = 0x1554, | ||
2184 | .subdevice = 0x4976, | ||
2185 | .card = CX88_BOARD_PROLINK_PV_GLOBAL_XTREME, | ||
2186 | }, { | ||
2013 | .subvendor = 0x17de, | 2187 | .subvendor = 0x17de, |
2014 | .subdevice = 0x08c1, | 2188 | .subdevice = 0x08c1, |
2015 | .card = CX88_BOARD_KWORLD_ATSC_120, | 2189 | .card = CX88_BOARD_KWORLD_ATSC_120, |
2190 | }, { | ||
2191 | .subvendor = 0x0070, | ||
2192 | .subdevice = 0x6900, | ||
2193 | .card = CX88_BOARD_HAUPPAUGE_HVR4000, | ||
2194 | }, { | ||
2195 | .subvendor = 0x0070, | ||
2196 | .subdevice = 0x6904, | ||
2197 | .card = CX88_BOARD_HAUPPAUGE_HVR4000, | ||
2198 | }, { | ||
2199 | .subvendor = 0x0070, | ||
2200 | .subdevice = 0x6902, | ||
2201 | .card = CX88_BOARD_HAUPPAUGE_HVR4000, | ||
2202 | }, { | ||
2203 | .subvendor = 0x0070, | ||
2204 | .subdevice = 0x6905, | ||
2205 | .card = CX88_BOARD_HAUPPAUGE_HVR4000LITE, | ||
2206 | }, { | ||
2207 | .subvendor = 0x0070, | ||
2208 | .subdevice = 0x6906, | ||
2209 | .card = CX88_BOARD_HAUPPAUGE_HVR4000LITE, | ||
2210 | }, { | ||
2211 | .subvendor = 0xd420, | ||
2212 | .subdevice = 0x9022, | ||
2213 | .card = CX88_BOARD_TEVII_S420, | ||
2214 | }, { | ||
2215 | .subvendor = 0xd460, | ||
2216 | .subdevice = 0x9022, | ||
2217 | .card = CX88_BOARD_TEVII_S460, | ||
2218 | }, { | ||
2219 | .subvendor = 0xA044, | ||
2220 | .subdevice = 0x2011, | ||
2221 | .card = CX88_BOARD_OMICOM_SS4_PCI, | ||
2222 | }, { | ||
2223 | .subvendor = 0x8920, | ||
2224 | .subdevice = 0x8888, | ||
2225 | .card = CX88_BOARD_TBS_8920, | ||
2226 | }, { | ||
2227 | .subvendor = 0xB033, | ||
2228 | .subdevice = 0x3033, | ||
2229 | .card = CX88_BOARD_PROF_7300, | ||
2016 | }, | 2230 | }, |
2017 | }; | 2231 | }; |
2018 | 2232 | ||
@@ -2065,6 +2279,13 @@ static void hauppauge_eeprom(struct cx88_core *core, u8 *eeprom_data) | |||
2065 | case 14669: /* WinTV-HVR3000 (OEM, no IR, no b/panel video - Low profile) */ | 2279 | case 14669: /* WinTV-HVR3000 (OEM, no IR, no b/panel video - Low profile) */ |
2066 | case 28552: /* WinTV-PVR 'Roslyn' (No IR) */ | 2280 | case 28552: /* WinTV-PVR 'Roslyn' (No IR) */ |
2067 | case 34519: /* WinTV-PCI-FM */ | 2281 | case 34519: /* WinTV-PCI-FM */ |
2282 | case 69009: | ||
2283 | /* WinTV-HVR4000 (DVBS/S2/T, Video and IR, back panel inputs) */ | ||
2284 | case 69100: /* WinTV-HVR4000LITE (DVBS/S2, IR) */ | ||
2285 | case 69500: /* WinTV-HVR4000LITE (DVBS/S2, No IR) */ | ||
2286 | case 69559: | ||
2287 | /* WinTV-HVR4000 (DVBS/S2/T, Video no IR, back panel inputs) */ | ||
2288 | case 69569: /* WinTV-HVR4000 (DVBS/S2/T, Video no IR) */ | ||
2068 | case 90002: /* Nova-T-PCI (9002) */ | 2289 | case 90002: /* Nova-T-PCI (9002) */ |
2069 | case 92001: /* Nova-S-Plus (Video and IR) */ | 2290 | case 92001: /* Nova-S-Plus (Video and IR) */ |
2070 | case 92002: /* Nova-S-Plus (Video and IR) */ | 2291 | case 92002: /* Nova-S-Plus (Video and IR) */ |
@@ -2149,9 +2370,21 @@ static int cx88_dvico_xc2028_callback(struct cx88_core *core, | |||
2149 | { | 2370 | { |
2150 | switch (command) { | 2371 | switch (command) { |
2151 | case XC2028_TUNER_RESET: | 2372 | case XC2028_TUNER_RESET: |
2152 | cx_write(MO_GP0_IO, 0x101000); | 2373 | switch (core->boardnr) { |
2153 | mdelay(5); | 2374 | case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO: |
2154 | cx_set(MO_GP0_IO, 0x101010); | 2375 | /* GPIO-4 xc3028 tuner */ |
2376 | |||
2377 | cx_set(MO_GP0_IO, 0x00001000); | ||
2378 | cx_clear(MO_GP0_IO, 0x00000010); | ||
2379 | msleep(100); | ||
2380 | cx_set(MO_GP0_IO, 0x00000010); | ||
2381 | msleep(100); | ||
2382 | break; | ||
2383 | default: | ||
2384 | cx_write(MO_GP0_IO, 0x101000); | ||
2385 | mdelay(5); | ||
2386 | cx_set(MO_GP0_IO, 0x101010); | ||
2387 | } | ||
2155 | break; | 2388 | break; |
2156 | default: | 2389 | default: |
2157 | return -EINVAL; | 2390 | return -EINVAL; |
@@ -2258,8 +2491,10 @@ static int cx88_xc2028_tuner_callback(struct cx88_core *core, | |||
2258 | return cx88_xc3028_geniatech_tuner_callback(core, | 2491 | return cx88_xc3028_geniatech_tuner_callback(core, |
2259 | command, arg); | 2492 | command, arg); |
2260 | case CX88_BOARD_PROLINK_PV_8000GT: | 2493 | case CX88_BOARD_PROLINK_PV_8000GT: |
2494 | case CX88_BOARD_PROLINK_PV_GLOBAL_XTREME: | ||
2261 | return cx88_pv_8000gt_callback(core, command, arg); | 2495 | return cx88_pv_8000gt_callback(core, command, arg); |
2262 | case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO: | 2496 | case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO: |
2497 | case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO: | ||
2263 | return cx88_dvico_xc2028_callback(core, command, arg); | 2498 | return cx88_dvico_xc2028_callback(core, command, arg); |
2264 | } | 2499 | } |
2265 | 2500 | ||
@@ -2327,7 +2562,7 @@ static int cx88_xc5000_tuner_callback(struct cx88_core *core, | |||
2327 | return 0; /* Should never be here */ | 2562 | return 0; /* Should never be here */ |
2328 | } | 2563 | } |
2329 | 2564 | ||
2330 | int cx88_tuner_callback(void *priv, int command, int arg) | 2565 | int cx88_tuner_callback(void *priv, int component, int command, int arg) |
2331 | { | 2566 | { |
2332 | struct i2c_algo_bit_data *i2c_algo = priv; | 2567 | struct i2c_algo_bit_data *i2c_algo = priv; |
2333 | struct cx88_core *core; | 2568 | struct cx88_core *core; |
@@ -2344,6 +2579,9 @@ int cx88_tuner_callback(void *priv, int command, int arg) | |||
2344 | return -EINVAL; | 2579 | return -EINVAL; |
2345 | } | 2580 | } |
2346 | 2581 | ||
2582 | if (component != DVB_FRONTEND_COMPONENT_TUNER) | ||
2583 | return -EINVAL; | ||
2584 | |||
2347 | switch (core->board.tuner_type) { | 2585 | switch (core->board.tuner_type) { |
2348 | case TUNER_XC2028: | 2586 | case TUNER_XC2028: |
2349 | info_printk(core, "Calling XC2028/3028 callback\n"); | 2587 | info_printk(core, "Calling XC2028/3028 callback\n"); |
@@ -2392,16 +2630,22 @@ static void cx88_card_setup_pre_i2c(struct cx88_core *core) | |||
2392 | { | 2630 | { |
2393 | switch (core->boardnr) { | 2631 | switch (core->boardnr) { |
2394 | case CX88_BOARD_HAUPPAUGE_HVR1300: | 2632 | case CX88_BOARD_HAUPPAUGE_HVR1300: |
2395 | /* Bring the 702 demod up before i2c scanning/attach or devices are hidden */ | 2633 | /* |
2396 | /* We leave here with the 702 on the bus */ | 2634 | * Bring the 702 demod up before i2c scanning/attach or devices are hidden |
2397 | cx_write(MO_GP0_IO, 0x0000e780); | 2635 | * We leave here with the 702 on the bus |
2636 | * | ||
2637 | * "reset the IR receiver on GPIO[3]" | ||
2638 | * Reported by Mike Crash <mike AT mikecrash.com> | ||
2639 | */ | ||
2640 | cx_write(MO_GP0_IO, 0x0000ef88); | ||
2398 | udelay(1000); | 2641 | udelay(1000); |
2399 | cx_clear(MO_GP0_IO, 0x00000080); | 2642 | cx_clear(MO_GP0_IO, 0x00000088); |
2400 | udelay(50); | 2643 | udelay(50); |
2401 | cx_set(MO_GP0_IO, 0x00000080); /* 702 out of reset */ | 2644 | cx_set(MO_GP0_IO, 0x00000088); /* 702 out of reset */ |
2402 | udelay(1000); | 2645 | udelay(1000); |
2403 | break; | 2646 | break; |
2404 | 2647 | ||
2648 | case CX88_BOARD_PROLINK_PV_GLOBAL_XTREME: | ||
2405 | case CX88_BOARD_PROLINK_PV_8000GT: | 2649 | case CX88_BOARD_PROLINK_PV_8000GT: |
2406 | cx_write(MO_GP2_IO, 0xcf7); | 2650 | cx_write(MO_GP2_IO, 0xcf7); |
2407 | mdelay(50); | 2651 | mdelay(50); |
@@ -2411,10 +2655,18 @@ static void cx88_card_setup_pre_i2c(struct cx88_core *core) | |||
2411 | msleep(10); | 2655 | msleep(10); |
2412 | break; | 2656 | break; |
2413 | 2657 | ||
2414 | case CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD: | 2658 | case CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD: |
2415 | /* Enable the xc5000 tuner */ | 2659 | /* Enable the xc5000 tuner */ |
2416 | cx_set(MO_GP0_IO, 0x00001010); | 2660 | cx_set(MO_GP0_IO, 0x00001010); |
2417 | break; | 2661 | break; |
2662 | |||
2663 | case CX88_BOARD_HAUPPAUGE_HVR3000: | ||
2664 | case CX88_BOARD_HAUPPAUGE_HVR4000: | ||
2665 | case CX88_BOARD_HAUPPAUGE_HVR4000LITE: | ||
2666 | /* Init GPIO */ | ||
2667 | cx_write(MO_GP0_IO, core->board.input[0].gpio0); | ||
2668 | udelay(1000); | ||
2669 | break; | ||
2418 | } | 2670 | } |
2419 | } | 2671 | } |
2420 | 2672 | ||
@@ -2435,17 +2687,22 @@ void cx88_setup_xc3028(struct cx88_core *core, struct xc2028_ctrl *ctl) | |||
2435 | core->i2c_algo.udelay = 16; | 2687 | core->i2c_algo.udelay = 16; |
2436 | break; | 2688 | break; |
2437 | case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO: | 2689 | case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO: |
2438 | ctl->scode_table = XC3028_FE_ZARLINK456; | 2690 | ctl->demod = XC3028_FE_ZARLINK456; |
2439 | break; | 2691 | break; |
2440 | case CX88_BOARD_KWORLD_ATSC_120: | 2692 | case CX88_BOARD_KWORLD_ATSC_120: |
2441 | case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO: | 2693 | case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO: |
2442 | ctl->demod = XC3028_FE_OREN538; | 2694 | ctl->demod = XC3028_FE_OREN538; |
2443 | break; | 2695 | break; |
2696 | case CX88_BOARD_PROLINK_PV_GLOBAL_XTREME: | ||
2444 | case CX88_BOARD_PROLINK_PV_8000GT: | 2697 | case CX88_BOARD_PROLINK_PV_8000GT: |
2445 | /* | 2698 | /* |
2446 | * This board uses non-MTS firmware | 2699 | * Those boards uses non-MTS firmware |
2447 | */ | 2700 | */ |
2448 | break; | 2701 | break; |
2702 | case CX88_BOARD_PINNACLE_HYBRID_PCTV: | ||
2703 | ctl->demod = XC3028_FE_ZARLINK456; | ||
2704 | ctl->mts = 1; | ||
2705 | break; | ||
2449 | default: | 2706 | default: |
2450 | ctl->demod = XC3028_FE_OREN538; | 2707 | ctl->demod = XC3028_FE_OREN538; |
2451 | ctl->mts = 1; | 2708 | ctl->mts = 1; |
@@ -2489,6 +2746,8 @@ static void cx88_card_setup(struct cx88_core *core) | |||
2489 | case CX88_BOARD_HAUPPAUGE_HVR1100LP: | 2746 | case CX88_BOARD_HAUPPAUGE_HVR1100LP: |
2490 | case CX88_BOARD_HAUPPAUGE_HVR3000: | 2747 | case CX88_BOARD_HAUPPAUGE_HVR3000: |
2491 | case CX88_BOARD_HAUPPAUGE_HVR1300: | 2748 | case CX88_BOARD_HAUPPAUGE_HVR1300: |
2749 | case CX88_BOARD_HAUPPAUGE_HVR4000: | ||
2750 | case CX88_BOARD_HAUPPAUGE_HVR4000LITE: | ||
2492 | if (0 == core->i2c_rc) | 2751 | if (0 == core->i2c_rc) |
2493 | hauppauge_eeprom(core, eeprom); | 2752 | hauppauge_eeprom(core, eeprom); |
2494 | break; | 2753 | break; |
@@ -2570,7 +2829,18 @@ static void cx88_card_setup(struct cx88_core *core) | |||
2570 | tea5767_cfg.priv = &ctl; | 2829 | tea5767_cfg.priv = &ctl; |
2571 | 2830 | ||
2572 | cx88_call_i2c_clients(core, TUNER_SET_CONFIG, &tea5767_cfg); | 2831 | cx88_call_i2c_clients(core, TUNER_SET_CONFIG, &tea5767_cfg); |
2832 | break; | ||
2573 | } | 2833 | } |
2834 | case CX88_BOARD_TEVII_S420: | ||
2835 | case CX88_BOARD_TEVII_S460: | ||
2836 | case CX88_BOARD_OMICOM_SS4_PCI: | ||
2837 | case CX88_BOARD_TBS_8920: | ||
2838 | case CX88_BOARD_PROF_7300: | ||
2839 | cx_write(MO_SRST_IO, 0); | ||
2840 | msleep(100); | ||
2841 | cx_write(MO_SRST_IO, 1); | ||
2842 | msleep(100); | ||
2843 | break; | ||
2574 | } /*end switch() */ | 2844 | } /*end switch() */ |
2575 | 2845 | ||
2576 | 2846 | ||
diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index d96173ff1dba..344ed2626e59 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c | |||
@@ -48,6 +48,11 @@ | |||
48 | #include "tuner-simple.h" | 48 | #include "tuner-simple.h" |
49 | #include "tda9887.h" | 49 | #include "tda9887.h" |
50 | #include "s5h1411.h" | 50 | #include "s5h1411.h" |
51 | #include "stv0299.h" | ||
52 | #include "z0194a.h" | ||
53 | #include "stv0288.h" | ||
54 | #include "stb6000.h" | ||
55 | #include "cx24116.h" | ||
51 | 56 | ||
52 | MODULE_DESCRIPTION("driver for cx2388x based DVB cards"); | 57 | MODULE_DESCRIPTION("driver for cx2388x based DVB cards"); |
53 | MODULE_AUTHOR("Chris Pascoe <c.pascoe@itee.uq.edu.au>"); | 58 | MODULE_AUTHOR("Chris Pascoe <c.pascoe@itee.uq.edu.au>"); |
@@ -375,37 +380,28 @@ static int geniatech_dvbs_set_voltage(struct dvb_frontend *fe, | |||
375 | return 0; | 380 | return 0; |
376 | } | 381 | } |
377 | 382 | ||
378 | static int cx88_pci_nano_callback(void *ptr, int command, int arg) | 383 | static int tevii_dvbs_set_voltage(struct dvb_frontend *fe, |
384 | fe_sec_voltage_t voltage) | ||
379 | { | 385 | { |
380 | struct cx88_core *core = ptr; | 386 | struct cx8802_dev *dev= fe->dvb->priv; |
381 | 387 | struct cx88_core *core = dev->core; | |
382 | switch (command) { | ||
383 | case XC2028_TUNER_RESET: | ||
384 | /* Send the tuner in then out of reset */ | ||
385 | dprintk(1, "%s: XC2028_TUNER_RESET %d\n", __func__, arg); | ||
386 | |||
387 | switch (core->boardnr) { | ||
388 | case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO: | ||
389 | /* GPIO-4 xc3028 tuner */ | ||
390 | |||
391 | cx_set(MO_GP0_IO, 0x00001000); | ||
392 | cx_clear(MO_GP0_IO, 0x00000010); | ||
393 | msleep(100); | ||
394 | cx_set(MO_GP0_IO, 0x00000010); | ||
395 | msleep(100); | ||
396 | break; | ||
397 | } | ||
398 | 388 | ||
399 | break; | 389 | switch (voltage) { |
400 | case XC2028_RESET_CLK: | 390 | case SEC_VOLTAGE_13: |
401 | dprintk(1, "%s: XC2028_RESET_CLK %d\n", __func__, arg); | 391 | printk("LNB Voltage SEC_VOLTAGE_13\n"); |
402 | break; | 392 | cx_write(MO_GP0_IO, 0x00006040); |
403 | default: | 393 | break; |
404 | dprintk(1, "%s: unknown command %d, arg %d\n", __func__, | 394 | case SEC_VOLTAGE_18: |
405 | command, arg); | 395 | printk("LNB Voltage SEC_VOLTAGE_18\n"); |
406 | return -EINVAL; | 396 | cx_write(MO_GP0_IO, 0x00006060); |
397 | break; | ||
398 | case SEC_VOLTAGE_OFF: | ||
399 | printk("LNB Voltage SEC_VOLTAGE_off\n"); | ||
400 | break; | ||
407 | } | 401 | } |
408 | 402 | ||
403 | if (core->prev_set_voltage) | ||
404 | return core->prev_set_voltage(fe, voltage); | ||
409 | return 0; | 405 | return 0; |
410 | } | 406 | } |
411 | 407 | ||
@@ -456,7 +452,12 @@ static struct s5h1409_config kworld_atsc_120_config = { | |||
456 | static struct xc5000_config pinnacle_pctv_hd_800i_tuner_config = { | 452 | static struct xc5000_config pinnacle_pctv_hd_800i_tuner_config = { |
457 | .i2c_address = 0x64, | 453 | .i2c_address = 0x64, |
458 | .if_khz = 5380, | 454 | .if_khz = 5380, |
459 | .tuner_callback = cx88_tuner_callback, | 455 | }; |
456 | |||
457 | static struct zl10353_config cx88_pinnacle_hybrid_pctv = { | ||
458 | .demod_address = (0x1e >> 1), | ||
459 | .no_tuner = 1, | ||
460 | .if2 = 45600, | ||
460 | }; | 461 | }; |
461 | 462 | ||
462 | static struct zl10353_config cx88_geniatech_x8000_mt = { | 463 | static struct zl10353_config cx88_geniatech_x8000_mt = { |
@@ -477,7 +478,6 @@ static struct s5h1411_config dvico_fusionhdtv7_config = { | |||
477 | static struct xc5000_config dvico_fusionhdtv7_tuner_config = { | 478 | static struct xc5000_config dvico_fusionhdtv7_tuner_config = { |
478 | .i2c_address = 0xc2 >> 1, | 479 | .i2c_address = 0xc2 >> 1, |
479 | .if_khz = 5380, | 480 | .if_khz = 5380, |
480 | .tuner_callback = cx88_tuner_callback, | ||
481 | }; | 481 | }; |
482 | 482 | ||
483 | static int attach_xc3028(u8 addr, struct cx8802_dev *dev) | 483 | static int attach_xc3028(u8 addr, struct cx8802_dev *dev) |
@@ -488,7 +488,6 @@ static int attach_xc3028(u8 addr, struct cx8802_dev *dev) | |||
488 | .i2c_adap = &dev->core->i2c_adap, | 488 | .i2c_adap = &dev->core->i2c_adap, |
489 | .i2c_addr = addr, | 489 | .i2c_addr = addr, |
490 | .ctrl = &ctl, | 490 | .ctrl = &ctl, |
491 | .callback = cx88_tuner_callback, | ||
492 | }; | 491 | }; |
493 | 492 | ||
494 | if (!dev->dvb.frontend) { | 493 | if (!dev->dvb.frontend) { |
@@ -518,6 +517,60 @@ static int attach_xc3028(u8 addr, struct cx8802_dev *dev) | |||
518 | return 0; | 517 | return 0; |
519 | } | 518 | } |
520 | 519 | ||
520 | static int cx24116_set_ts_param(struct dvb_frontend *fe, | ||
521 | int is_punctured) | ||
522 | { | ||
523 | struct cx8802_dev *dev = fe->dvb->priv; | ||
524 | dev->ts_gen_cntrl = 0x2; | ||
525 | |||
526 | return 0; | ||
527 | } | ||
528 | |||
529 | static int cx24116_reset_device(struct dvb_frontend *fe) | ||
530 | { | ||
531 | struct cx8802_dev *dev = fe->dvb->priv; | ||
532 | struct cx88_core *core = dev->core; | ||
533 | |||
534 | /* Reset the part */ | ||
535 | cx_write(MO_SRST_IO, 0); | ||
536 | msleep(10); | ||
537 | cx_write(MO_SRST_IO, 1); | ||
538 | msleep(10); | ||
539 | |||
540 | return 0; | ||
541 | } | ||
542 | |||
543 | static struct cx24116_config hauppauge_hvr4000_config = { | ||
544 | .demod_address = 0x05, | ||
545 | .set_ts_params = cx24116_set_ts_param, | ||
546 | .reset_device = cx24116_reset_device, | ||
547 | }; | ||
548 | |||
549 | static struct cx24116_config tevii_s460_config = { | ||
550 | .demod_address = 0x55, | ||
551 | .set_ts_params = cx24116_set_ts_param, | ||
552 | .reset_device = cx24116_reset_device, | ||
553 | }; | ||
554 | |||
555 | static struct stv0299_config tevii_tuner_sharp_config = { | ||
556 | .demod_address = 0x68, | ||
557 | .inittab = sharp_z0194a__inittab, | ||
558 | .mclk = 88000000UL, | ||
559 | .invert = 1, | ||
560 | .skip_reinit = 0, | ||
561 | .lock_output = 1, | ||
562 | .volt13_op0_op1 = STV0299_VOLT13_OP1, | ||
563 | .min_delay_ms = 100, | ||
564 | .set_symbol_rate = sharp_z0194a__set_symbol_rate, | ||
565 | .set_ts_params = cx24116_set_ts_param, | ||
566 | }; | ||
567 | |||
568 | static struct stv0288_config tevii_tuner_earda_config = { | ||
569 | .demod_address = 0x68, | ||
570 | .min_delay_ms = 100, | ||
571 | .set_ts_params = cx24116_set_ts_param, | ||
572 | }; | ||
573 | |||
521 | static int dvb_register(struct cx8802_dev *dev) | 574 | static int dvb_register(struct cx8802_dev *dev) |
522 | { | 575 | { |
523 | struct cx88_core *core = dev->core; | 576 | struct cx88_core *core = dev->core; |
@@ -786,7 +839,7 @@ static int dvb_register(struct cx8802_dev *dev) | |||
786 | &core->i2c_adap); | 839 | &core->i2c_adap); |
787 | if (dev->dvb.frontend) { | 840 | if (dev->dvb.frontend) { |
788 | if (!dvb_attach(isl6421_attach, dev->dvb.frontend, | 841 | if (!dvb_attach(isl6421_attach, dev->dvb.frontend, |
789 | &core->i2c_adap, 0x08, 0x00, 0x00)) | 842 | &core->i2c_adap, 0x08, ISL6421_DCL, 0x00)) |
790 | goto frontend_detach; | 843 | goto frontend_detach; |
791 | } | 844 | } |
792 | break; | 845 | break; |
@@ -813,13 +866,9 @@ static int dvb_register(struct cx8802_dev *dev) | |||
813 | &pinnacle_pctv_hd_800i_config, | 866 | &pinnacle_pctv_hd_800i_config, |
814 | &core->i2c_adap); | 867 | &core->i2c_adap); |
815 | if (dev->dvb.frontend != NULL) { | 868 | if (dev->dvb.frontend != NULL) { |
816 | /* tuner_config.video_dev must point to | ||
817 | * i2c_adap.algo_data | ||
818 | */ | ||
819 | if (!dvb_attach(xc5000_attach, dev->dvb.frontend, | 869 | if (!dvb_attach(xc5000_attach, dev->dvb.frontend, |
820 | &core->i2c_adap, | 870 | &core->i2c_adap, |
821 | &pinnacle_pctv_hd_800i_tuner_config, | 871 | &pinnacle_pctv_hd_800i_tuner_config)) |
822 | core->i2c_adap.algo_data)) | ||
823 | goto frontend_detach; | 872 | goto frontend_detach; |
824 | } | 873 | } |
825 | break; | 874 | break; |
@@ -832,10 +881,9 @@ static int dvb_register(struct cx8802_dev *dev) | |||
832 | struct xc2028_config cfg = { | 881 | struct xc2028_config cfg = { |
833 | .i2c_adap = &core->i2c_adap, | 882 | .i2c_adap = &core->i2c_adap, |
834 | .i2c_addr = 0x61, | 883 | .i2c_addr = 0x61, |
835 | .callback = cx88_pci_nano_callback, | ||
836 | }; | 884 | }; |
837 | static struct xc2028_ctrl ctl = { | 885 | static struct xc2028_ctrl ctl = { |
838 | .fname = "xc3028-v27.fw", | 886 | .fname = XC2028_DEFAULT_FIRMWARE, |
839 | .max_len = 64, | 887 | .max_len = 64, |
840 | .scode_table = XC3028_FE_OREN538, | 888 | .scode_table = XC3028_FE_OREN538, |
841 | }; | 889 | }; |
@@ -848,10 +896,13 @@ static int dvb_register(struct cx8802_dev *dev) | |||
848 | break; | 896 | break; |
849 | case CX88_BOARD_PINNACLE_HYBRID_PCTV: | 897 | case CX88_BOARD_PINNACLE_HYBRID_PCTV: |
850 | dev->dvb.frontend = dvb_attach(zl10353_attach, | 898 | dev->dvb.frontend = dvb_attach(zl10353_attach, |
851 | &cx88_geniatech_x8000_mt, | 899 | &cx88_pinnacle_hybrid_pctv, |
852 | &core->i2c_adap); | 900 | &core->i2c_adap); |
853 | if (attach_xc3028(0x61, dev) < 0) | 901 | if (dev->dvb.frontend) { |
854 | goto frontend_detach; | 902 | dev->dvb.frontend->ops.i2c_gate_ctrl = NULL; |
903 | if (attach_xc3028(0x61, dev) < 0) | ||
904 | goto frontend_detach; | ||
905 | } | ||
855 | break; | 906 | break; |
856 | case CX88_BOARD_GENIATECH_X8000_MT: | 907 | case CX88_BOARD_GENIATECH_X8000_MT: |
857 | dev->ts_gen_cntrl = 0x00; | 908 | dev->ts_gen_cntrl = 0x00; |
@@ -874,16 +925,69 @@ static int dvb_register(struct cx8802_dev *dev) | |||
874 | &dvico_fusionhdtv7_config, | 925 | &dvico_fusionhdtv7_config, |
875 | &core->i2c_adap); | 926 | &core->i2c_adap); |
876 | if (dev->dvb.frontend != NULL) { | 927 | if (dev->dvb.frontend != NULL) { |
877 | /* tuner_config.video_dev must point to | ||
878 | * i2c_adap.algo_data | ||
879 | */ | ||
880 | if (!dvb_attach(xc5000_attach, dev->dvb.frontend, | 928 | if (!dvb_attach(xc5000_attach, dev->dvb.frontend, |
881 | &core->i2c_adap, | 929 | &core->i2c_adap, |
882 | &dvico_fusionhdtv7_tuner_config, | 930 | &dvico_fusionhdtv7_tuner_config)) |
883 | core->i2c_adap.algo_data)) | ||
884 | goto frontend_detach; | 931 | goto frontend_detach; |
885 | } | 932 | } |
886 | break; | 933 | break; |
934 | case CX88_BOARD_HAUPPAUGE_HVR4000: | ||
935 | case CX88_BOARD_HAUPPAUGE_HVR4000LITE: | ||
936 | /* Support for DVB-S only, not DVB-T support */ | ||
937 | dev->dvb.frontend = dvb_attach(cx24116_attach, | ||
938 | &hauppauge_hvr4000_config, | ||
939 | &dev->core->i2c_adap); | ||
940 | if (dev->dvb.frontend) { | ||
941 | dvb_attach(isl6421_attach, dev->dvb.frontend, | ||
942 | &dev->core->i2c_adap, | ||
943 | 0x08, ISL6421_DCL, 0x00); | ||
944 | } | ||
945 | break; | ||
946 | case CX88_BOARD_TEVII_S420: | ||
947 | dev->dvb.frontend = dvb_attach(stv0299_attach, | ||
948 | &tevii_tuner_sharp_config, | ||
949 | &core->i2c_adap); | ||
950 | if (dev->dvb.frontend != NULL) { | ||
951 | if (!dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x60, | ||
952 | &core->i2c_adap, DVB_PLL_OPERA1)) | ||
953 | goto frontend_detach; | ||
954 | core->prev_set_voltage = dev->dvb.frontend->ops.set_voltage; | ||
955 | dev->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage; | ||
956 | |||
957 | } else { | ||
958 | dev->dvb.frontend = dvb_attach(stv0288_attach, | ||
959 | &tevii_tuner_earda_config, | ||
960 | &core->i2c_adap); | ||
961 | if (dev->dvb.frontend != NULL) { | ||
962 | if (!dvb_attach(stb6000_attach, dev->dvb.frontend, 0x61, | ||
963 | &core->i2c_adap)) | ||
964 | goto frontend_detach; | ||
965 | core->prev_set_voltage = dev->dvb.frontend->ops.set_voltage; | ||
966 | dev->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage; | ||
967 | |||
968 | } | ||
969 | } | ||
970 | break; | ||
971 | case CX88_BOARD_TEVII_S460: | ||
972 | dev->dvb.frontend = dvb_attach(cx24116_attach, | ||
973 | &tevii_s460_config, | ||
974 | &core->i2c_adap); | ||
975 | if (dev->dvb.frontend != NULL) { | ||
976 | core->prev_set_voltage = dev->dvb.frontend->ops.set_voltage; | ||
977 | dev->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage; | ||
978 | } | ||
979 | break; | ||
980 | case CX88_BOARD_OMICOM_SS4_PCI: | ||
981 | case CX88_BOARD_TBS_8920: | ||
982 | case CX88_BOARD_PROF_7300: | ||
983 | dev->dvb.frontend = dvb_attach(cx24116_attach, | ||
984 | &hauppauge_hvr4000_config, | ||
985 | &core->i2c_adap); | ||
986 | if (dev->dvb.frontend != NULL) { | ||
987 | core->prev_set_voltage = dev->dvb.frontend->ops.set_voltage; | ||
988 | dev->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage; | ||
989 | } | ||
990 | break; | ||
887 | default: | 991 | default: |
888 | printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card isn't supported yet\n", | 992 | printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card isn't supported yet\n", |
889 | core->name); | 993 | core->name); |
@@ -895,6 +999,8 @@ static int dvb_register(struct cx8802_dev *dev) | |||
895 | core->name); | 999 | core->name); |
896 | return -EINVAL; | 1000 | return -EINVAL; |
897 | } | 1001 | } |
1002 | /* define general-purpose callback pointer */ | ||
1003 | dev->dvb.frontend->callback = cx88_tuner_callback; | ||
898 | 1004 | ||
899 | /* Ensure all frontends negotiate bus access */ | 1005 | /* Ensure all frontends negotiate bus access */ |
900 | dev->dvb.frontend->ops.ts_bus_ctrl = cx88_dvb_bus_ctrl; | 1006 | dev->dvb.frontend->ops.ts_bus_ctrl = cx88_dvb_bus_ctrl; |
diff --git a/drivers/media/video/cx88/cx88-i2c.c b/drivers/media/video/cx88/cx88-i2c.c index d7406a994f09..8e74d64fdcd2 100644 --- a/drivers/media/video/cx88/cx88-i2c.c +++ b/drivers/media/video/cx88/cx88-i2c.c | |||
@@ -201,7 +201,23 @@ int cx88_i2c_init(struct cx88_core *core, struct pci_dev *pci) | |||
201 | 201 | ||
202 | core->i2c_rc = i2c_bit_add_bus(&core->i2c_adap); | 202 | core->i2c_rc = i2c_bit_add_bus(&core->i2c_adap); |
203 | if (0 == core->i2c_rc) { | 203 | if (0 == core->i2c_rc) { |
204 | static u8 tuner_data[] = | ||
205 | { 0x0b, 0xdc, 0x86, 0x52 }; | ||
206 | static struct i2c_msg tuner_msg = | ||
207 | { .flags = 0, .addr = 0xc2 >> 1, .buf = tuner_data, .len = 4 }; | ||
208 | |||
204 | dprintk(1, "i2c register ok\n"); | 209 | dprintk(1, "i2c register ok\n"); |
210 | switch( core->boardnr ) { | ||
211 | case CX88_BOARD_HAUPPAUGE_HVR1300: | ||
212 | case CX88_BOARD_HAUPPAUGE_HVR3000: | ||
213 | case CX88_BOARD_HAUPPAUGE_HVR4000: | ||
214 | printk("%s: i2c init: enabling analog demod on HVR1300/3000/4000 tuner\n", | ||
215 | core->name); | ||
216 | i2c_transfer(core->i2c_client.adapter, &tuner_msg, 1); | ||
217 | break; | ||
218 | default: | ||
219 | break; | ||
220 | } | ||
205 | if (i2c_scan) | 221 | if (i2c_scan) |
206 | do_i2c_scan(core->name,&core->i2c_client); | 222 | do_i2c_scan(core->name,&core->i2c_client); |
207 | } else | 223 | } else |
diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c index 53526d997a4e..8683d104de72 100644 --- a/drivers/media/video/cx88/cx88-input.c +++ b/drivers/media/video/cx88/cx88-input.c | |||
@@ -224,6 +224,8 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) | |||
224 | case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1: | 224 | case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1: |
225 | case CX88_BOARD_HAUPPAUGE_HVR1100: | 225 | case CX88_BOARD_HAUPPAUGE_HVR1100: |
226 | case CX88_BOARD_HAUPPAUGE_HVR3000: | 226 | case CX88_BOARD_HAUPPAUGE_HVR3000: |
227 | case CX88_BOARD_HAUPPAUGE_HVR4000: | ||
228 | case CX88_BOARD_HAUPPAUGE_HVR4000LITE: | ||
227 | ir_codes = ir_codes_hauppauge_new; | 229 | ir_codes = ir_codes_hauppauge_new; |
228 | ir_type = IR_TYPE_RC5; | 230 | ir_type = IR_TYPE_RC5; |
229 | ir->sampling = 1; | 231 | ir->sampling = 1; |
@@ -259,6 +261,7 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) | |||
259 | ir->polling = 1; /* ms */ | 261 | ir->polling = 1; /* ms */ |
260 | break; | 262 | break; |
261 | case CX88_BOARD_PROLINK_PV_8000GT: | 263 | case CX88_BOARD_PROLINK_PV_8000GT: |
264 | case CX88_BOARD_PROLINK_PV_GLOBAL_XTREME: | ||
262 | ir_codes = ir_codes_pixelview_new; | 265 | ir_codes = ir_codes_pixelview_new; |
263 | ir->gpio_addr = MO_GP1_IO; | 266 | ir->gpio_addr = MO_GP1_IO; |
264 | ir->mask_keycode = 0x3f; | 267 | ir->mask_keycode = 0x3f; |
@@ -392,7 +395,7 @@ void cx88_ir_irq(struct cx88_core *core) | |||
392 | { | 395 | { |
393 | struct cx88_IR *ir = core->ir; | 396 | struct cx88_IR *ir = core->ir; |
394 | u32 samples, ircode; | 397 | u32 samples, ircode; |
395 | int i; | 398 | int i, start, range, toggle, dev, code; |
396 | 399 | ||
397 | if (NULL == ir) | 400 | if (NULL == ir) |
398 | return; | 401 | return; |
@@ -461,6 +464,34 @@ void cx88_ir_irq(struct cx88_core *core) | |||
461 | case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1: | 464 | case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1: |
462 | case CX88_BOARD_HAUPPAUGE_HVR1100: | 465 | case CX88_BOARD_HAUPPAUGE_HVR1100: |
463 | case CX88_BOARD_HAUPPAUGE_HVR3000: | 466 | case CX88_BOARD_HAUPPAUGE_HVR3000: |
467 | case CX88_BOARD_HAUPPAUGE_HVR4000: | ||
468 | case CX88_BOARD_HAUPPAUGE_HVR4000LITE: | ||
469 | ircode = ir_decode_biphase(ir->samples, ir->scount, 5, 7); | ||
470 | ir_dprintk("biphase decoded: %x\n", ircode); | ||
471 | /* | ||
472 | * RC5 has an extension bit which adds a new range | ||
473 | * of available codes, this is detected here. Also | ||
474 | * hauppauge remotes (black/silver) always use | ||
475 | * specific device ids. If we do not filter the | ||
476 | * device ids then messages destined for devices | ||
477 | * such as TVs (id=0) will get through to the | ||
478 | * device causing mis-fired events. | ||
479 | */ | ||
480 | /* split rc5 data block ... */ | ||
481 | start = (ircode & 0x2000) >> 13; | ||
482 | range = (ircode & 0x1000) >> 12; | ||
483 | toggle= (ircode & 0x0800) >> 11; | ||
484 | dev = (ircode & 0x07c0) >> 6; | ||
485 | code = (ircode & 0x003f) | ((range << 6) ^ 0x0040); | ||
486 | if( start != 1) | ||
487 | /* no key pressed */ | ||
488 | break; | ||
489 | if ( dev != 0x1e && dev != 0x1f ) | ||
490 | /* not a hauppauge remote */ | ||
491 | break; | ||
492 | ir_input_keydown(ir->input, &ir->ir, code, ircode); | ||
493 | ir->release = jiffies + msecs_to_jiffies(120); | ||
494 | break; | ||
464 | case CX88_BOARD_PINNACLE_PCTV_HD_800i: | 495 | case CX88_BOARD_PINNACLE_PCTV_HD_800i: |
465 | ircode = ir_decode_biphase(ir->samples, ir->scount, 5, 7); | 496 | ircode = ir_decode_biphase(ir->samples, ir->scount, 5, 7); |
466 | ir_dprintk("biphase decoded: %x\n", ircode); | 497 | ir_dprintk("biphase decoded: %x\n", ircode); |
diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index ef4d56ea0027..be45955dff68 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c | |||
@@ -773,6 +773,7 @@ static int video_open(struct inode *inode, struct file *file) | |||
773 | enum v4l2_buf_type type = 0; | 773 | enum v4l2_buf_type type = 0; |
774 | int radio = 0; | 774 | int radio = 0; |
775 | 775 | ||
776 | lock_kernel(); | ||
776 | list_for_each_entry(h, &cx8800_devlist, devlist) { | 777 | list_for_each_entry(h, &cx8800_devlist, devlist) { |
777 | if (h->video_dev->minor == minor) { | 778 | if (h->video_dev->minor == minor) { |
778 | dev = h; | 779 | dev = h; |
@@ -788,8 +789,10 @@ static int video_open(struct inode *inode, struct file *file) | |||
788 | dev = h; | 789 | dev = h; |
789 | } | 790 | } |
790 | } | 791 | } |
791 | if (NULL == dev) | 792 | if (NULL == dev) { |
793 | unlock_kernel(); | ||
792 | return -ENODEV; | 794 | return -ENODEV; |
795 | } | ||
793 | 796 | ||
794 | core = dev->core; | 797 | core = dev->core; |
795 | 798 | ||
@@ -798,8 +801,10 @@ static int video_open(struct inode *inode, struct file *file) | |||
798 | 801 | ||
799 | /* allocate + initialize per filehandle data */ | 802 | /* allocate + initialize per filehandle data */ |
800 | fh = kzalloc(sizeof(*fh),GFP_KERNEL); | 803 | fh = kzalloc(sizeof(*fh),GFP_KERNEL); |
801 | if (NULL == fh) | 804 | if (NULL == fh) { |
805 | unlock_kernel(); | ||
802 | return -ENOMEM; | 806 | return -ENOMEM; |
807 | } | ||
803 | file->private_data = fh; | 808 | file->private_data = fh; |
804 | fh->dev = dev; | 809 | fh->dev = dev; |
805 | fh->radio = radio; | 810 | fh->radio = radio; |
@@ -832,6 +837,9 @@ static int video_open(struct inode *inode, struct file *file) | |||
832 | cx88_set_stereo(core,V4L2_TUNER_MODE_STEREO,1); | 837 | cx88_set_stereo(core,V4L2_TUNER_MODE_STEREO,1); |
833 | cx88_call_i2c_clients(core,AUDC_SET_RADIO,NULL); | 838 | cx88_call_i2c_clients(core,AUDC_SET_RADIO,NULL); |
834 | } | 839 | } |
840 | unlock_kernel(); | ||
841 | |||
842 | atomic_inc(&core->users); | ||
835 | 843 | ||
836 | return 0; | 844 | return 0; |
837 | } | 845 | } |
@@ -920,7 +928,8 @@ static int video_release(struct inode *inode, struct file *file) | |||
920 | file->private_data = NULL; | 928 | file->private_data = NULL; |
921 | kfree(fh); | 929 | kfree(fh); |
922 | 930 | ||
923 | cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL); | 931 | if(atomic_dec_and_test(&dev->core->users)) |
932 | cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL); | ||
924 | 933 | ||
925 | return 0; | 934 | return 0; |
926 | } | 935 | } |
diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index 54fe65094711..dbf01b8b57a5 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h | |||
@@ -221,6 +221,14 @@ extern struct sram_channel cx88_sram_channels[]; | |||
221 | #define CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD 65 | 221 | #define CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD 65 |
222 | #define CX88_BOARD_PROLINK_PV_8000GT 66 | 222 | #define CX88_BOARD_PROLINK_PV_8000GT 66 |
223 | #define CX88_BOARD_KWORLD_ATSC_120 67 | 223 | #define CX88_BOARD_KWORLD_ATSC_120 67 |
224 | #define CX88_BOARD_HAUPPAUGE_HVR4000 68 | ||
225 | #define CX88_BOARD_HAUPPAUGE_HVR4000LITE 69 | ||
226 | #define CX88_BOARD_TEVII_S460 70 | ||
227 | #define CX88_BOARD_OMICOM_SS4_PCI 71 | ||
228 | #define CX88_BOARD_TBS_8920 72 | ||
229 | #define CX88_BOARD_TEVII_S420 73 | ||
230 | #define CX88_BOARD_PROLINK_PV_GLOBAL_XTREME 74 | ||
231 | #define CX88_BOARD_PROF_7300 75 | ||
224 | 232 | ||
225 | enum cx88_itype { | 233 | enum cx88_itype { |
226 | CX88_VMUX_COMPOSITE1 = 1, | 234 | CX88_VMUX_COMPOSITE1 = 1, |
@@ -342,6 +350,7 @@ struct cx88_core { | |||
342 | struct mutex lock; | 350 | struct mutex lock; |
343 | /* various v4l controls */ | 351 | /* various v4l controls */ |
344 | u32 freq; | 352 | u32 freq; |
353 | atomic_t users; | ||
345 | 354 | ||
346 | /* cx88-video needs to access cx8802 for hybrid tuner pll access. */ | 355 | /* cx88-video needs to access cx8802 for hybrid tuner pll access. */ |
347 | struct cx8802_dev *dvbdev; | 356 | struct cx8802_dev *dvbdev; |
@@ -601,7 +610,7 @@ extern void cx88_call_i2c_clients(struct cx88_core *core, | |||
601 | /* ----------------------------------------------------------- */ | 610 | /* ----------------------------------------------------------- */ |
602 | /* cx88-cards.c */ | 611 | /* cx88-cards.c */ |
603 | 612 | ||
604 | extern int cx88_tuner_callback(void *dev, int command, int arg); | 613 | extern int cx88_tuner_callback(void *dev, int component, int command, int arg); |
605 | extern int cx88_get_resources(const struct cx88_core *core, | 614 | extern int cx88_get_resources(const struct cx88_core *core, |
606 | struct pci_dev *pci); | 615 | struct pci_dev *pci); |
607 | extern struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr); | 616 | extern struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr); |
diff --git a/drivers/media/video/dabusb.c b/drivers/media/video/dabusb.c index 79faedf58521..3aa538afcc0b 100644 --- a/drivers/media/video/dabusb.c +++ b/drivers/media/video/dabusb.c | |||
@@ -866,7 +866,8 @@ static int __init dabusb_init (void) | |||
866 | 866 | ||
867 | dbg("dabusb_init: driver registered"); | 867 | dbg("dabusb_init: driver registered"); |
868 | 868 | ||
869 | info(DRIVER_VERSION ":" DRIVER_DESC); | 869 | printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" |
870 | DRIVER_DESC "\n"); | ||
870 | 871 | ||
871 | out: | 872 | out: |
872 | return retval; | 873 | return retval; |
diff --git a/drivers/media/video/dpc7146.c b/drivers/media/video/dpc7146.c deleted file mode 100644 index 88d6df71d051..000000000000 --- a/drivers/media/video/dpc7146.c +++ /dev/null | |||
@@ -1,408 +0,0 @@ | |||
1 | /* | ||
2 | dpc7146.c - v4l2 driver for the dpc7146 demonstration board | ||
3 | |||
4 | Copyright (C) 2000-2003 Michael Hunold <michael@mihu.de> | ||
5 | |||
6 | This program is free software; you can redistribute it and/or modify | ||
7 | it under the terms of the GNU General Public License as published by | ||
8 | the Free Software Foundation; either version 2 of the License, or | ||
9 | (at your option) any later version. | ||
10 | |||
11 | This program is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program; if not, write to the Free Software | ||
18 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | */ | ||
20 | |||
21 | #define DEBUG_VARIABLE debug | ||
22 | |||
23 | #include <media/saa7146_vv.h> | ||
24 | #include <linux/video_decoder.h> /* for saa7111a */ | ||
25 | |||
26 | #define I2C_SAA7111A 0x24 | ||
27 | |||
28 | /* All unused bytes are reserverd. */ | ||
29 | #define SAA711X_CHIP_VERSION 0x00 | ||
30 | #define SAA711X_ANALOG_INPUT_CONTROL_1 0x02 | ||
31 | #define SAA711X_ANALOG_INPUT_CONTROL_2 0x03 | ||
32 | #define SAA711X_ANALOG_INPUT_CONTROL_3 0x04 | ||
33 | #define SAA711X_ANALOG_INPUT_CONTROL_4 0x05 | ||
34 | #define SAA711X_HORIZONTAL_SYNC_START 0x06 | ||
35 | #define SAA711X_HORIZONTAL_SYNC_STOP 0x07 | ||
36 | #define SAA711X_SYNC_CONTROL 0x08 | ||
37 | #define SAA711X_LUMINANCE_CONTROL 0x09 | ||
38 | #define SAA711X_LUMINANCE_BRIGHTNESS 0x0A | ||
39 | #define SAA711X_LUMINANCE_CONTRAST 0x0B | ||
40 | #define SAA711X_CHROMA_SATURATION 0x0C | ||
41 | #define SAA711X_CHROMA_HUE_CONTROL 0x0D | ||
42 | #define SAA711X_CHROMA_CONTROL 0x0E | ||
43 | #define SAA711X_FORMAT_DELAY_CONTROL 0x10 | ||
44 | #define SAA711X_OUTPUT_CONTROL_1 0x11 | ||
45 | #define SAA711X_OUTPUT_CONTROL_2 0x12 | ||
46 | #define SAA711X_OUTPUT_CONTROL_3 0x13 | ||
47 | #define SAA711X_V_GATE_1_START 0x15 | ||
48 | #define SAA711X_V_GATE_1_STOP 0x16 | ||
49 | #define SAA711X_V_GATE_1_MSB 0x17 | ||
50 | #define SAA711X_TEXT_SLICER_STATUS 0x1A | ||
51 | #define SAA711X_DECODED_BYTES_OF_TS_1 0x1B | ||
52 | #define SAA711X_DECODED_BYTES_OF_TS_2 0x1C | ||
53 | #define SAA711X_STATUS_BYTE 0x1F | ||
54 | |||
55 | #define DPC_BOARD_CAN_DO_VBI(dev) (dev->revision != 0) | ||
56 | |||
57 | static int debug; | ||
58 | module_param(debug, int, 0); | ||
59 | MODULE_PARM_DESC(debug, "debug verbosity"); | ||
60 | |||
61 | static int dpc_num; | ||
62 | |||
63 | #define DPC_INPUTS 2 | ||
64 | static struct v4l2_input dpc_inputs[DPC_INPUTS] = { | ||
65 | { 0, "Port A", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 }, | ||
66 | { 1, "Port B", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 }, | ||
67 | }; | ||
68 | |||
69 | #define DPC_AUDIOS 0 | ||
70 | |||
71 | static struct saa7146_extension_ioctls ioctls[] = { | ||
72 | { VIDIOC_G_INPUT, SAA7146_EXCLUSIVE }, | ||
73 | { VIDIOC_S_INPUT, SAA7146_EXCLUSIVE }, | ||
74 | { VIDIOC_ENUMINPUT, SAA7146_EXCLUSIVE }, | ||
75 | { VIDIOC_S_STD, SAA7146_AFTER }, | ||
76 | { 0, 0 } | ||
77 | }; | ||
78 | |||
79 | struct dpc | ||
80 | { | ||
81 | struct video_device *video_dev; | ||
82 | struct video_device *vbi_dev; | ||
83 | |||
84 | struct i2c_adapter i2c_adapter; | ||
85 | struct i2c_client *saa7111a; | ||
86 | |||
87 | int cur_input; /* current input */ | ||
88 | }; | ||
89 | |||
90 | static int dpc_check_clients(struct device *dev, void *data) | ||
91 | { | ||
92 | struct dpc* dpc = data; | ||
93 | struct i2c_client *client = i2c_verify_client(dev); | ||
94 | |||
95 | if( !client ) | ||
96 | return 0; | ||
97 | |||
98 | if( I2C_SAA7111A == client->addr ) | ||
99 | dpc->saa7111a = client; | ||
100 | |||
101 | return 0; | ||
102 | } | ||
103 | |||
104 | /* fixme: add vbi stuff here */ | ||
105 | static int dpc_probe(struct saa7146_dev* dev) | ||
106 | { | ||
107 | struct dpc* dpc = NULL; | ||
108 | |||
109 | dpc = kzalloc(sizeof(struct dpc), GFP_KERNEL); | ||
110 | if( NULL == dpc ) { | ||
111 | printk("dpc_v4l2.o: dpc_probe: not enough kernel memory.\n"); | ||
112 | return -ENOMEM; | ||
113 | } | ||
114 | |||
115 | /* FIXME: enable i2c-port pins, video-port-pins | ||
116 | video port pins should be enabled here ?! */ | ||
117 | saa7146_write(dev, MC1, (MASK_08 | MASK_24 | MASK_10 | MASK_26)); | ||
118 | |||
119 | dpc->i2c_adapter = (struct i2c_adapter) { | ||
120 | .class = I2C_CLASS_TV_ANALOG, | ||
121 | .name = "dpc7146", | ||
122 | }; | ||
123 | saa7146_i2c_adapter_prepare(dev, &dpc->i2c_adapter, SAA7146_I2C_BUS_BIT_RATE_480); | ||
124 | if(i2c_add_adapter(&dpc->i2c_adapter) < 0) { | ||
125 | DEB_S(("cannot register i2c-device. skipping.\n")); | ||
126 | kfree(dpc); | ||
127 | return -EFAULT; | ||
128 | } | ||
129 | |||
130 | /* loop through all i2c-devices on the bus and look who is there */ | ||
131 | device_for_each_child(&dpc->i2c_adapter.dev, dpc, dpc_check_clients); | ||
132 | |||
133 | /* check if all devices are present */ | ||
134 | if (!dpc->saa7111a) { | ||
135 | DEB_D(("dpc_v4l2.o: dpc_attach failed for this device.\n")); | ||
136 | i2c_del_adapter(&dpc->i2c_adapter); | ||
137 | kfree(dpc); | ||
138 | return -ENODEV; | ||
139 | } | ||
140 | |||
141 | /* all devices are present, probe was successful */ | ||
142 | DEB_D(("dpc_v4l2.o: dpc_probe succeeded for this device.\n")); | ||
143 | |||
144 | /* we store the pointer in our private data field */ | ||
145 | dev->ext_priv = dpc; | ||
146 | |||
147 | return 0; | ||
148 | } | ||
149 | |||
150 | /* bring hardware to a sane state. this has to be done, just in case someone | ||
151 | wants to capture from this device before it has been properly initialized. | ||
152 | the capture engine would badly fail, because no valid signal arrives on the | ||
153 | saa7146, thus leading to timeouts and stuff. */ | ||
154 | static int dpc_init_done(struct saa7146_dev* dev) | ||
155 | { | ||
156 | struct dpc* dpc = (struct dpc*)dev->ext_priv; | ||
157 | |||
158 | DEB_D(("dpc_v4l2.o: dpc_init_done called.\n")); | ||
159 | |||
160 | /* initialize the helper ics to useful values */ | ||
161 | i2c_smbus_write_byte_data(dpc->saa7111a, 0x00, 0x11); | ||
162 | |||
163 | i2c_smbus_write_byte_data(dpc->saa7111a, 0x02, 0xc0); | ||
164 | i2c_smbus_write_byte_data(dpc->saa7111a, 0x03, 0x30); | ||
165 | i2c_smbus_write_byte_data(dpc->saa7111a, 0x04, 0x00); | ||
166 | i2c_smbus_write_byte_data(dpc->saa7111a, 0x05, 0x00); | ||
167 | i2c_smbus_write_byte_data(dpc->saa7111a, 0x06, 0xde); | ||
168 | i2c_smbus_write_byte_data(dpc->saa7111a, 0x07, 0xad); | ||
169 | i2c_smbus_write_byte_data(dpc->saa7111a, 0x08, 0xa8); | ||
170 | i2c_smbus_write_byte_data(dpc->saa7111a, 0x09, 0x00); | ||
171 | i2c_smbus_write_byte_data(dpc->saa7111a, 0x0a, 0x80); | ||
172 | i2c_smbus_write_byte_data(dpc->saa7111a, 0x0b, 0x47); | ||
173 | i2c_smbus_write_byte_data(dpc->saa7111a, 0x0c, 0x40); | ||
174 | i2c_smbus_write_byte_data(dpc->saa7111a, 0x0d, 0x00); | ||
175 | i2c_smbus_write_byte_data(dpc->saa7111a, 0x0e, 0x03); | ||
176 | |||
177 | i2c_smbus_write_byte_data(dpc->saa7111a, 0x10, 0xd0); | ||
178 | i2c_smbus_write_byte_data(dpc->saa7111a, 0x11, 0x1c); | ||
179 | i2c_smbus_write_byte_data(dpc->saa7111a, 0x12, 0xc1); | ||
180 | i2c_smbus_write_byte_data(dpc->saa7111a, 0x13, 0x30); | ||
181 | |||
182 | i2c_smbus_write_byte_data(dpc->saa7111a, 0x1f, 0x81); | ||
183 | |||
184 | return 0; | ||
185 | } | ||
186 | |||
187 | static struct saa7146_ext_vv vv_data; | ||
188 | |||
189 | /* this function only gets called when the probing was successful */ | ||
190 | static int dpc_attach(struct saa7146_dev* dev, struct saa7146_pci_extension_data *info) | ||
191 | { | ||
192 | struct dpc* dpc = (struct dpc*)dev->ext_priv; | ||
193 | |||
194 | DEB_D(("dpc_v4l2.o: dpc_attach called.\n")); | ||
195 | |||
196 | /* checking for i2c-devices can be omitted here, because we | ||
197 | already did this in "dpc_vl42_probe" */ | ||
198 | |||
199 | saa7146_vv_init(dev,&vv_data); | ||
200 | if( 0 != saa7146_register_device(&dpc->video_dev, dev, "dpc", VFL_TYPE_GRABBER)) { | ||
201 | ERR(("cannot register capture v4l2 device. skipping.\n")); | ||
202 | return -1; | ||
203 | } | ||
204 | |||
205 | /* initialization stuff (vbi) (only for revision > 0 and for extensions which want it)*/ | ||
206 | if( 0 != DPC_BOARD_CAN_DO_VBI(dev)) { | ||
207 | if( 0 != saa7146_register_device(&dpc->vbi_dev, dev, "dpc", VFL_TYPE_VBI)) { | ||
208 | ERR(("cannot register vbi v4l2 device. skipping.\n")); | ||
209 | } | ||
210 | } | ||
211 | |||
212 | i2c_use_client(dpc->saa7111a); | ||
213 | |||
214 | printk("dpc: found 'dpc7146 demonstration board'-%d.\n",dpc_num); | ||
215 | dpc_num++; | ||
216 | |||
217 | /* the rest */ | ||
218 | dpc->cur_input = 0; | ||
219 | dpc_init_done(dev); | ||
220 | |||
221 | return 0; | ||
222 | } | ||
223 | |||
224 | static int dpc_detach(struct saa7146_dev* dev) | ||
225 | { | ||
226 | struct dpc* dpc = (struct dpc*)dev->ext_priv; | ||
227 | |||
228 | DEB_EE(("dev:%p\n",dev)); | ||
229 | |||
230 | i2c_release_client(dpc->saa7111a); | ||
231 | |||
232 | saa7146_unregister_device(&dpc->video_dev,dev); | ||
233 | if( 0 != DPC_BOARD_CAN_DO_VBI(dev)) { | ||
234 | saa7146_unregister_device(&dpc->vbi_dev,dev); | ||
235 | } | ||
236 | saa7146_vv_release(dev); | ||
237 | |||
238 | dpc_num--; | ||
239 | |||
240 | i2c_del_adapter(&dpc->i2c_adapter); | ||
241 | kfree(dpc); | ||
242 | return 0; | ||
243 | } | ||
244 | |||
245 | #ifdef axa | ||
246 | int dpc_vbi_bypass(struct saa7146_dev* dev) | ||
247 | { | ||
248 | struct dpc* dpc = (struct dpc*)dev->ext_priv; | ||
249 | |||
250 | int i = 1; | ||
251 | |||
252 | /* switch bypass in saa7111a */ | ||
253 | if ( 0 != dpc->saa7111a->driver->command(dpc->saa7111a,SAA711X_VBI_BYPASS, &i)) { | ||
254 | printk("dpc_v4l2.o: VBI_BYPASS: could not address saa7111a.\n"); | ||
255 | return -1; | ||
256 | } | ||
257 | |||
258 | return 0; | ||
259 | } | ||
260 | #endif | ||
261 | |||
262 | static int dpc_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) | ||
263 | { | ||
264 | struct saa7146_dev *dev = fh->dev; | ||
265 | struct dpc* dpc = (struct dpc*)dev->ext_priv; | ||
266 | /* | ||
267 | struct saa7146_vv *vv = dev->vv_data; | ||
268 | */ | ||
269 | switch(cmd) | ||
270 | { | ||
271 | case VIDIOC_ENUMINPUT: | ||
272 | { | ||
273 | struct v4l2_input *i = arg; | ||
274 | DEB_EE(("VIDIOC_ENUMINPUT %d.\n",i->index)); | ||
275 | |||
276 | if( i->index < 0 || i->index >= DPC_INPUTS) { | ||
277 | return -EINVAL; | ||
278 | } | ||
279 | |||
280 | memcpy(i, &dpc_inputs[i->index], sizeof(struct v4l2_input)); | ||
281 | |||
282 | DEB_D(("dpc_v4l2.o: v4l2_ioctl: VIDIOC_ENUMINPUT %d.\n",i->index)); | ||
283 | return 0; | ||
284 | } | ||
285 | case VIDIOC_G_INPUT: | ||
286 | { | ||
287 | int *input = (int *)arg; | ||
288 | *input = dpc->cur_input; | ||
289 | |||
290 | DEB_D(("dpc_v4l2.o: VIDIOC_G_INPUT: %d\n",*input)); | ||
291 | return 0; | ||
292 | } | ||
293 | case VIDIOC_S_INPUT: | ||
294 | { | ||
295 | int input = *(int *)arg; | ||
296 | |||
297 | if (input < 0 || input >= DPC_INPUTS) { | ||
298 | return -EINVAL; | ||
299 | } | ||
300 | |||
301 | dpc->cur_input = input; | ||
302 | |||
303 | /* fixme: switch input here, switch audio, too! */ | ||
304 | // saa7146_set_hps_source_and_sync(dev, input_port_selection[input].hps_source, input_port_selection[input].hps_sync); | ||
305 | printk("dpc_v4l2.o: VIDIOC_S_INPUT: fixme switch input.\n"); | ||
306 | |||
307 | return 0; | ||
308 | } | ||
309 | default: | ||
310 | /* | ||
311 | DEB_D(("dpc_v4l2.o: v4l2_ioctl does not handle this ioctl.\n")); | ||
312 | */ | ||
313 | return -ENOIOCTLCMD; | ||
314 | } | ||
315 | return 0; | ||
316 | } | ||
317 | |||
318 | static int std_callback(struct saa7146_dev* dev, struct saa7146_standard *std) | ||
319 | { | ||
320 | return 0; | ||
321 | } | ||
322 | |||
323 | static struct saa7146_standard standard[] = { | ||
324 | { | ||
325 | .name = "PAL", .id = V4L2_STD_PAL, | ||
326 | .v_offset = 0x17, .v_field = 288, | ||
327 | .h_offset = 0x14, .h_pixels = 680, | ||
328 | .v_max_out = 576, .h_max_out = 768, | ||
329 | }, { | ||
330 | .name = "NTSC", .id = V4L2_STD_NTSC, | ||
331 | .v_offset = 0x16, .v_field = 240, | ||
332 | .h_offset = 0x06, .h_pixels = 708, | ||
333 | .v_max_out = 480, .h_max_out = 640, | ||
334 | }, { | ||
335 | .name = "SECAM", .id = V4L2_STD_SECAM, | ||
336 | .v_offset = 0x14, .v_field = 288, | ||
337 | .h_offset = 0x14, .h_pixels = 720, | ||
338 | .v_max_out = 576, .h_max_out = 768, | ||
339 | } | ||
340 | }; | ||
341 | |||
342 | static struct saa7146_extension extension; | ||
343 | |||
344 | static struct saa7146_pci_extension_data dpc = { | ||
345 | .ext_priv = "Multimedia eXtension Board", | ||
346 | .ext = &extension, | ||
347 | }; | ||
348 | |||
349 | static struct pci_device_id pci_tbl[] = { | ||
350 | { | ||
351 | .vendor = PCI_VENDOR_ID_PHILIPS, | ||
352 | .device = PCI_DEVICE_ID_PHILIPS_SAA7146, | ||
353 | .subvendor = 0x0000, | ||
354 | .subdevice = 0x0000, | ||
355 | .driver_data = (unsigned long)&dpc, | ||
356 | }, { | ||
357 | .vendor = 0, | ||
358 | } | ||
359 | }; | ||
360 | |||
361 | MODULE_DEVICE_TABLE(pci, pci_tbl); | ||
362 | |||
363 | static struct saa7146_ext_vv vv_data = { | ||
364 | .inputs = DPC_INPUTS, | ||
365 | .capabilities = V4L2_CAP_VBI_CAPTURE, | ||
366 | .stds = &standard[0], | ||
367 | .num_stds = sizeof(standard)/sizeof(struct saa7146_standard), | ||
368 | .std_callback = &std_callback, | ||
369 | .ioctls = &ioctls[0], | ||
370 | .ioctl = dpc_ioctl, | ||
371 | }; | ||
372 | |||
373 | static struct saa7146_extension extension = { | ||
374 | .name = "dpc7146 demonstration board", | ||
375 | .flags = SAA7146_USE_I2C_IRQ, | ||
376 | |||
377 | .pci_tbl = &pci_tbl[0], | ||
378 | .module = THIS_MODULE, | ||
379 | |||
380 | .probe = dpc_probe, | ||
381 | .attach = dpc_attach, | ||
382 | .detach = dpc_detach, | ||
383 | |||
384 | .irq_mask = 0, | ||
385 | .irq_func = NULL, | ||
386 | }; | ||
387 | |||
388 | static int __init dpc_init_module(void) | ||
389 | { | ||
390 | if( 0 != saa7146_register_extension(&extension)) { | ||
391 | DEB_S(("failed to register extension.\n")); | ||
392 | return -ENODEV; | ||
393 | } | ||
394 | |||
395 | return 0; | ||
396 | } | ||
397 | |||
398 | static void __exit dpc_cleanup_module(void) | ||
399 | { | ||
400 | saa7146_unregister_extension(&extension); | ||
401 | } | ||
402 | |||
403 | module_init(dpc_init_module); | ||
404 | module_exit(dpc_cleanup_module); | ||
405 | |||
406 | MODULE_DESCRIPTION("video4linux-2 driver for the 'dpc7146 demonstration board'"); | ||
407 | MODULE_AUTHOR("Michael Hunold <michael@mihu.de>"); | ||
408 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index de943cf6c169..d65d0572403b 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c | |||
@@ -1101,7 +1101,7 @@ struct usb_device_id em28xx_id_table [] = { | |||
1101 | { USB_DEVICE(0xeb1a, 0x2820), | 1101 | { USB_DEVICE(0xeb1a, 0x2820), |
1102 | .driver_info = EM2820_BOARD_UNKNOWN }, | 1102 | .driver_info = EM2820_BOARD_UNKNOWN }, |
1103 | { USB_DEVICE(0xeb1a, 0x2821), | 1103 | { USB_DEVICE(0xeb1a, 0x2821), |
1104 | .driver_info = EM2820_BOARD_UNKNOWN }, | 1104 | .driver_info = EM2820_BOARD_PROLINK_PLAYTV_USB2 }, |
1105 | { USB_DEVICE(0xeb1a, 0x2860), | 1105 | { USB_DEVICE(0xeb1a, 0x2860), |
1106 | .driver_info = EM2820_BOARD_UNKNOWN }, | 1106 | .driver_info = EM2820_BOARD_UNKNOWN }, |
1107 | { USB_DEVICE(0xeb1a, 0x2861), | 1107 | { USB_DEVICE(0xeb1a, 0x2861), |
@@ -1271,7 +1271,7 @@ static struct em28xx_hash_table em28xx_i2c_hash[] = { | |||
1271 | {0x1ba50080, EM2860_BOARD_POINTNIX_INTRAORAL_CAMERA, TUNER_ABSENT}, | 1271 | {0x1ba50080, EM2860_BOARD_POINTNIX_INTRAORAL_CAMERA, TUNER_ABSENT}, |
1272 | }; | 1272 | }; |
1273 | 1273 | ||
1274 | int em28xx_tuner_callback(void *ptr, int command, int arg) | 1274 | int em28xx_tuner_callback(void *ptr, int component, int command, int arg) |
1275 | { | 1275 | { |
1276 | int rc = 0; | 1276 | int rc = 0; |
1277 | struct em28xx *dev = ptr; | 1277 | struct em28xx *dev = ptr; |
diff --git a/drivers/media/video/em28xx/em28xx-dvb.c b/drivers/media/video/em28xx/em28xx-dvb.c index d2b1a1a52689..c99e2383b7ec 100644 --- a/drivers/media/video/em28xx/em28xx-dvb.c +++ b/drivers/media/video/em28xx/em28xx-dvb.c | |||
@@ -249,7 +249,6 @@ static int attach_xc3028(u8 addr, struct em28xx *dev) | |||
249 | memset(&cfg, 0, sizeof(cfg)); | 249 | memset(&cfg, 0, sizeof(cfg)); |
250 | cfg.i2c_adap = &dev->i2c_adap; | 250 | cfg.i2c_adap = &dev->i2c_adap; |
251 | cfg.i2c_addr = addr; | 251 | cfg.i2c_addr = addr; |
252 | cfg.callback = em28xx_tuner_callback; | ||
253 | 252 | ||
254 | if (!dev->dvb->frontend) { | 253 | if (!dev->dvb->frontend) { |
255 | printk(KERN_ERR "%s/2: dvb frontend not attached. " | 254 | printk(KERN_ERR "%s/2: dvb frontend not attached. " |
@@ -274,7 +273,7 @@ static int attach_xc3028(u8 addr, struct em28xx *dev) | |||
274 | 273 | ||
275 | /* ------------------------------------------------------------------ */ | 274 | /* ------------------------------------------------------------------ */ |
276 | 275 | ||
277 | int register_dvb(struct em28xx_dvb *dvb, | 276 | static int register_dvb(struct em28xx_dvb *dvb, |
278 | struct module *module, | 277 | struct module *module, |
279 | struct em28xx *dev, | 278 | struct em28xx *dev, |
280 | struct device *device) | 279 | struct device *device) |
@@ -422,6 +421,8 @@ static int dvb_init(struct em28xx *dev) | |||
422 | } | 421 | } |
423 | break; | 422 | break; |
424 | case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900: | 423 | case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900: |
424 | case EM2880_BOARD_TERRATEC_HYBRID_XS: | ||
425 | case EM2880_BOARD_KWORLD_DVB_310U: | ||
425 | dvb->frontend = dvb_attach(zl10353_attach, | 426 | dvb->frontend = dvb_attach(zl10353_attach, |
426 | &em28xx_zl10353_with_xc3028, | 427 | &em28xx_zl10353_with_xc3028, |
427 | &dev->i2c_adap); | 428 | &dev->i2c_adap); |
@@ -443,24 +444,6 @@ static int dvb_init(struct em28xx *dev) | |||
443 | } | 444 | } |
444 | break; | 445 | break; |
445 | #endif | 446 | #endif |
446 | case EM2880_BOARD_TERRATEC_HYBRID_XS: | ||
447 | dvb->frontend = dvb_attach(zl10353_attach, | ||
448 | &em28xx_zl10353_with_xc3028, | ||
449 | &dev->i2c_adap); | ||
450 | if (attach_xc3028(0x61, dev) < 0) { | ||
451 | result = -EINVAL; | ||
452 | goto out_free; | ||
453 | } | ||
454 | break; | ||
455 | case EM2880_BOARD_KWORLD_DVB_310U: | ||
456 | dvb->frontend = dvb_attach(zl10353_attach, | ||
457 | &em28xx_zl10353_with_xc3028, | ||
458 | &dev->i2c_adap); | ||
459 | if (attach_xc3028(0x61, dev) < 0) { | ||
460 | result = -EINVAL; | ||
461 | goto out_free; | ||
462 | } | ||
463 | break; | ||
464 | default: | 447 | default: |
465 | printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card" | 448 | printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card" |
466 | " isn't supported yet\n", | 449 | " isn't supported yet\n", |
@@ -474,6 +457,8 @@ static int dvb_init(struct em28xx *dev) | |||
474 | result = -EINVAL; | 457 | result = -EINVAL; |
475 | goto out_free; | 458 | goto out_free; |
476 | } | 459 | } |
460 | /* define general-purpose callback pointer */ | ||
461 | dvb->frontend->callback = em28xx_tuner_callback; | ||
477 | 462 | ||
478 | /* register everything */ | 463 | /* register everything */ |
479 | result = register_dvb(dvb, THIS_MODULE, dev, &dev->udev->dev); | 464 | result = register_dvb(dvb, THIS_MODULE, dev, &dev->udev->dev); |
diff --git a/drivers/media/video/em28xx/em28xx-i2c.c b/drivers/media/video/em28xx/em28xx-i2c.c index 97853384c943..3bab56b997fc 100644 --- a/drivers/media/video/em28xx/em28xx-i2c.c +++ b/drivers/media/video/em28xx/em28xx-i2c.c | |||
@@ -143,10 +143,11 @@ static int em2800_i2c_check_for_device(struct em28xx *dev, unsigned char addr) | |||
143 | } | 143 | } |
144 | for (write_timeout = EM2800_I2C_WRITE_TIMEOUT; write_timeout > 0; | 144 | for (write_timeout = EM2800_I2C_WRITE_TIMEOUT; write_timeout > 0; |
145 | write_timeout -= 5) { | 145 | write_timeout -= 5) { |
146 | unsigned msg = dev->em28xx_read_reg(dev, 0x5); | 146 | unsigned reg = dev->em28xx_read_reg(dev, 0x5); |
147 | if (msg == 0x94) | 147 | |
148 | if (reg == 0x94) | ||
148 | return -ENODEV; | 149 | return -ENODEV; |
149 | else if (msg == 0x84) | 150 | else if (reg == 0x84) |
150 | return 0; | 151 | return 0; |
151 | msleep(5); | 152 | msleep(5); |
152 | } | 153 | } |
@@ -335,8 +336,11 @@ static int em28xx_i2c_eeprom(struct em28xx *dev, unsigned char *eedata, int len) | |||
335 | 336 | ||
336 | /* Check if board has eeprom */ | 337 | /* Check if board has eeprom */ |
337 | err = i2c_master_recv(&dev->i2c_client, &buf, 0); | 338 | err = i2c_master_recv(&dev->i2c_client, &buf, 0); |
338 | if (err < 0) | 339 | if (err < 0) { |
339 | return -1; | 340 | em28xx_errdev("%s: i2c_master_recv failed! err [%d]\n", |
341 | __func__, err); | ||
342 | return err; | ||
343 | } | ||
340 | 344 | ||
341 | buf = 0; | 345 | buf = 0; |
342 | 346 | ||
@@ -344,7 +348,7 @@ static int em28xx_i2c_eeprom(struct em28xx *dev, unsigned char *eedata, int len) | |||
344 | if (err != 1) { | 348 | if (err != 1) { |
345 | printk(KERN_INFO "%s: Huh, no eeprom present (err=%d)?\n", | 349 | printk(KERN_INFO "%s: Huh, no eeprom present (err=%d)?\n", |
346 | dev->name, err); | 350 | dev->name, err); |
347 | return -1; | 351 | return err; |
348 | } | 352 | } |
349 | while (size > 0) { | 353 | while (size > 0) { |
350 | if (size > 16) | 354 | if (size > 16) |
@@ -357,7 +361,7 @@ static int em28xx_i2c_eeprom(struct em28xx *dev, unsigned char *eedata, int len) | |||
357 | printk(KERN_WARNING | 361 | printk(KERN_WARNING |
358 | "%s: i2c eeprom read error (err=%d)\n", | 362 | "%s: i2c eeprom read error (err=%d)\n", |
359 | dev->name, err); | 363 | dev->name, err); |
360 | return -1; | 364 | return err; |
361 | } | 365 | } |
362 | size -= block; | 366 | size -= block; |
363 | p += block; | 367 | p += block; |
@@ -585,18 +589,31 @@ void em28xx_i2c_call_clients(struct em28xx *dev, unsigned int cmd, void *arg) | |||
585 | */ | 589 | */ |
586 | int em28xx_i2c_register(struct em28xx *dev) | 590 | int em28xx_i2c_register(struct em28xx *dev) |
587 | { | 591 | { |
592 | int retval; | ||
593 | |||
588 | BUG_ON(!dev->em28xx_write_regs || !dev->em28xx_read_reg); | 594 | BUG_ON(!dev->em28xx_write_regs || !dev->em28xx_read_reg); |
589 | BUG_ON(!dev->em28xx_write_regs_req || !dev->em28xx_read_reg_req); | 595 | BUG_ON(!dev->em28xx_write_regs_req || !dev->em28xx_read_reg_req); |
590 | dev->i2c_adap = em28xx_adap_template; | 596 | dev->i2c_adap = em28xx_adap_template; |
591 | dev->i2c_adap.dev.parent = &dev->udev->dev; | 597 | dev->i2c_adap.dev.parent = &dev->udev->dev; |
592 | strcpy(dev->i2c_adap.name, dev->name); | 598 | strcpy(dev->i2c_adap.name, dev->name); |
593 | dev->i2c_adap.algo_data = dev; | 599 | dev->i2c_adap.algo_data = dev; |
594 | i2c_add_adapter(&dev->i2c_adap); | 600 | |
601 | retval = i2c_add_adapter(&dev->i2c_adap); | ||
602 | if (retval < 0) { | ||
603 | em28xx_errdev("%s: i2c_add_adapter failed! retval [%d]\n", | ||
604 | __func__, retval); | ||
605 | return retval; | ||
606 | } | ||
595 | 607 | ||
596 | dev->i2c_client = em28xx_client_template; | 608 | dev->i2c_client = em28xx_client_template; |
597 | dev->i2c_client.adapter = &dev->i2c_adap; | 609 | dev->i2c_client.adapter = &dev->i2c_adap; |
598 | 610 | ||
599 | em28xx_i2c_eeprom(dev, dev->eedata, sizeof(dev->eedata)); | 611 | retval = em28xx_i2c_eeprom(dev, dev->eedata, sizeof(dev->eedata)); |
612 | if (retval < 0) { | ||
613 | em28xx_errdev("%s: em28xx_i2_eeprom failed! retval [%d]\n", | ||
614 | __func__, retval); | ||
615 | return retval; | ||
616 | } | ||
600 | 617 | ||
601 | if (i2c_scan) | 618 | if (i2c_scan) |
602 | em28xx_do_i2c_scan(dev); | 619 | em28xx_do_i2c_scan(dev); |
diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index 49ab0629702e..c53649e5315b 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c | |||
@@ -513,10 +513,17 @@ static struct videobuf_queue_ops em28xx_video_qops = { | |||
513 | */ | 513 | */ |
514 | static int em28xx_config(struct em28xx *dev) | 514 | static int em28xx_config(struct em28xx *dev) |
515 | { | 515 | { |
516 | int retval; | ||
516 | 517 | ||
517 | /* Sets I2C speed to 100 KHz */ | 518 | /* Sets I2C speed to 100 KHz */ |
518 | if (!dev->is_em2800) | 519 | if (!dev->is_em2800) { |
519 | em28xx_write_regs_req(dev, 0x00, 0x06, "\x40", 1); | 520 | retval = em28xx_write_regs_req(dev, 0x00, 0x06, "\x40", 1); |
521 | if (retval < 0) { | ||
522 | em28xx_errdev("%s: em28xx_write_regs_req failed! retval [%d]\n", | ||
523 | __func__, retval); | ||
524 | return retval; | ||
525 | } | ||
526 | } | ||
520 | 527 | ||
521 | /* enable vbi capturing */ | 528 | /* enable vbi capturing */ |
522 | 529 | ||
@@ -1512,6 +1519,7 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp) | |||
1512 | struct em28xx_fh *fh; | 1519 | struct em28xx_fh *fh; |
1513 | enum v4l2_buf_type fh_type = 0; | 1520 | enum v4l2_buf_type fh_type = 0; |
1514 | 1521 | ||
1522 | lock_kernel(); | ||
1515 | list_for_each_entry(h, &em28xx_devlist, devlist) { | 1523 | list_for_each_entry(h, &em28xx_devlist, devlist) { |
1516 | if (h->vdev->minor == minor) { | 1524 | if (h->vdev->minor == minor) { |
1517 | dev = h; | 1525 | dev = h; |
@@ -1527,8 +1535,10 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp) | |||
1527 | dev = h; | 1535 | dev = h; |
1528 | } | 1536 | } |
1529 | } | 1537 | } |
1530 | if (NULL == dev) | 1538 | if (NULL == dev) { |
1539 | unlock_kernel(); | ||
1531 | return -ENODEV; | 1540 | return -ENODEV; |
1541 | } | ||
1532 | 1542 | ||
1533 | em28xx_videodbg("open minor=%d type=%s users=%d\n", | 1543 | em28xx_videodbg("open minor=%d type=%s users=%d\n", |
1534 | minor, v4l2_type_names[fh_type], dev->users); | 1544 | minor, v4l2_type_names[fh_type], dev->users); |
@@ -1537,6 +1547,7 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp) | |||
1537 | fh = kzalloc(sizeof(struct em28xx_fh), GFP_KERNEL); | 1547 | fh = kzalloc(sizeof(struct em28xx_fh), GFP_KERNEL); |
1538 | if (!fh) { | 1548 | if (!fh) { |
1539 | em28xx_errdev("em28xx-video.c: Out of memory?!\n"); | 1549 | em28xx_errdev("em28xx-video.c: Out of memory?!\n"); |
1550 | unlock_kernel(); | ||
1540 | return -ENOMEM; | 1551 | return -ENOMEM; |
1541 | } | 1552 | } |
1542 | mutex_lock(&dev->lock); | 1553 | mutex_lock(&dev->lock); |
@@ -1573,6 +1584,7 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp) | |||
1573 | sizeof(struct em28xx_buffer), fh); | 1584 | sizeof(struct em28xx_buffer), fh); |
1574 | 1585 | ||
1575 | mutex_unlock(&dev->lock); | 1586 | mutex_unlock(&dev->lock); |
1587 | unlock_kernel(); | ||
1576 | 1588 | ||
1577 | return errCode; | 1589 | return errCode; |
1578 | } | 1590 | } |
@@ -1588,8 +1600,7 @@ static void em28xx_release_resources(struct em28xx *dev) | |||
1588 | /*FIXME: I2C IR should be disconnected */ | 1600 | /*FIXME: I2C IR should be disconnected */ |
1589 | 1601 | ||
1590 | em28xx_info("V4L2 devices /dev/video%d and /dev/vbi%d deregistered\n", | 1602 | em28xx_info("V4L2 devices /dev/video%d and /dev/vbi%d deregistered\n", |
1591 | dev->vdev->minor-MINOR_VFL_TYPE_GRABBER_MIN, | 1603 | dev->vdev->num, dev->vbi_dev->num); |
1592 | dev->vbi_dev->minor-MINOR_VFL_TYPE_VBI_MIN); | ||
1593 | list_del(&dev->devlist); | 1604 | list_del(&dev->devlist); |
1594 | if (dev->sbutton_input_dev) | 1605 | if (dev->sbutton_input_dev) |
1595 | em28xx_deregister_snapshot_button(dev); | 1606 | em28xx_deregister_snapshot_button(dev); |
@@ -1948,13 +1959,23 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, | |||
1948 | } | 1959 | } |
1949 | 1960 | ||
1950 | /* register i2c bus */ | 1961 | /* register i2c bus */ |
1951 | em28xx_i2c_register(dev); | 1962 | errCode = em28xx_i2c_register(dev); |
1963 | if (errCode < 0) { | ||
1964 | em28xx_errdev("%s: em28xx_i2c_register - errCode [%d]!\n", | ||
1965 | __func__, errCode); | ||
1966 | return errCode; | ||
1967 | } | ||
1952 | 1968 | ||
1953 | /* Do board specific init and eeprom reading */ | 1969 | /* Do board specific init and eeprom reading */ |
1954 | em28xx_card_setup(dev); | 1970 | em28xx_card_setup(dev); |
1955 | 1971 | ||
1956 | /* Configure audio */ | 1972 | /* Configure audio */ |
1957 | em28xx_audio_analog_set(dev); | 1973 | errCode = em28xx_audio_analog_set(dev); |
1974 | if (errCode < 0) { | ||
1975 | em28xx_errdev("%s: em28xx_audio_analog_set - errCode [%d]!\n", | ||
1976 | __func__, errCode); | ||
1977 | return errCode; | ||
1978 | } | ||
1958 | 1979 | ||
1959 | /* configure the device */ | 1980 | /* configure the device */ |
1960 | em28xx_config_i2c(dev); | 1981 | em28xx_config_i2c(dev); |
@@ -1974,6 +1995,11 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, | |||
1974 | dev->ctl_input = 2; | 1995 | dev->ctl_input = 2; |
1975 | 1996 | ||
1976 | errCode = em28xx_config(dev); | 1997 | errCode = em28xx_config(dev); |
1998 | if (errCode < 0) { | ||
1999 | em28xx_errdev("%s: em28xx_config - errCode [%d]!\n", | ||
2000 | __func__, errCode); | ||
2001 | return errCode; | ||
2002 | } | ||
1977 | 2003 | ||
1978 | list_add_tail(&dev->devlist, &em28xx_devlist); | 2004 | list_add_tail(&dev->devlist, &em28xx_devlist); |
1979 | 2005 | ||
@@ -2026,17 +2052,27 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, | |||
2026 | 2052 | ||
2027 | if (dev->has_msp34xx) { | 2053 | if (dev->has_msp34xx) { |
2028 | /* Send a reset to other chips via gpio */ | 2054 | /* Send a reset to other chips via gpio */ |
2029 | em28xx_write_regs_req(dev, 0x00, 0x08, "\xf7", 1); | 2055 | errCode = em28xx_write_regs_req(dev, 0x00, 0x08, "\xf7", 1); |
2056 | if (errCode < 0) { | ||
2057 | em28xx_errdev("%s: em28xx_write_regs_req - msp34xx(1) failed! errCode [%d]\n", | ||
2058 | __func__, errCode); | ||
2059 | return errCode; | ||
2060 | } | ||
2030 | msleep(3); | 2061 | msleep(3); |
2031 | em28xx_write_regs_req(dev, 0x00, 0x08, "\xff", 1); | 2062 | |
2063 | errCode = em28xx_write_regs_req(dev, 0x00, 0x08, "\xff", 1); | ||
2064 | if (errCode < 0) { | ||
2065 | em28xx_errdev("%s: em28xx_write_regs_req - msp34xx(2) failed! errCode [%d]\n", | ||
2066 | __func__, errCode); | ||
2067 | return errCode; | ||
2068 | } | ||
2032 | msleep(3); | 2069 | msleep(3); |
2033 | } | 2070 | } |
2034 | 2071 | ||
2035 | video_mux(dev, 0); | 2072 | video_mux(dev, 0); |
2036 | 2073 | ||
2037 | em28xx_info("V4L2 device registered as /dev/video%d and /dev/vbi%d\n", | 2074 | em28xx_info("V4L2 device registered as /dev/video%d and /dev/vbi%d\n", |
2038 | dev->vdev->minor-MINOR_VFL_TYPE_GRABBER_MIN, | 2075 | dev->vdev->num, dev->vbi_dev->num); |
2039 | dev->vbi_dev->minor-MINOR_VFL_TYPE_VBI_MIN); | ||
2040 | 2076 | ||
2041 | mutex_lock(&em28xx_extension_devlist_lock); | 2077 | mutex_lock(&em28xx_extension_devlist_lock); |
2042 | if (!list_empty(&em28xx_extension_devlist)) { | 2078 | if (!list_empty(&em28xx_extension_devlist)) { |
@@ -2236,7 +2272,7 @@ static void em28xx_usb_disconnect(struct usb_interface *interface) | |||
2236 | em28xx_warn | 2272 | em28xx_warn |
2237 | ("device /dev/video%d is open! Deregistration and memory " | 2273 | ("device /dev/video%d is open! Deregistration and memory " |
2238 | "deallocation are deferred on close.\n", | 2274 | "deallocation are deferred on close.\n", |
2239 | dev->vdev->minor-MINOR_VFL_TYPE_GRABBER_MIN); | 2275 | dev->vdev->num); |
2240 | 2276 | ||
2241 | dev->state |= DEV_MISCONFIGURED; | 2277 | dev->state |= DEV_MISCONFIGURED; |
2242 | em28xx_uninit_isoc(dev); | 2278 | em28xx_uninit_isoc(dev); |
diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index 9a3310748685..82781178e0a3 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h | |||
@@ -411,8 +411,8 @@ struct em28xx { | |||
411 | /* frame properties */ | 411 | /* frame properties */ |
412 | int width; /* current frame width */ | 412 | int width; /* current frame width */ |
413 | int height; /* current frame height */ | 413 | int height; /* current frame height */ |
414 | int hscale; /* horizontal scale factor (see datasheet) */ | 414 | unsigned hscale; /* horizontal scale factor (see datasheet) */ |
415 | int vscale; /* vertical scale factor (see datasheet) */ | 415 | unsigned vscale; /* vertical scale factor (see datasheet) */ |
416 | int interlaced; /* 1=interlace fileds, 0=just top fileds */ | 416 | int interlaced; /* 1=interlace fileds, 0=just top fileds */ |
417 | unsigned int video_bytesread; /* Number of bytes read */ | 417 | unsigned int video_bytesread; /* Number of bytes read */ |
418 | 418 | ||
@@ -528,7 +528,7 @@ extern struct em28xx_board em28xx_boards[]; | |||
528 | extern struct usb_device_id em28xx_id_table[]; | 528 | extern struct usb_device_id em28xx_id_table[]; |
529 | extern const unsigned int em28xx_bcount; | 529 | extern const unsigned int em28xx_bcount; |
530 | void em28xx_set_ir(struct em28xx *dev, struct IR_i2c *ir); | 530 | void em28xx_set_ir(struct em28xx *dev, struct IR_i2c *ir); |
531 | int em28xx_tuner_callback(void *ptr, int command, int arg); | 531 | int em28xx_tuner_callback(void *ptr, int component, int command, int arg); |
532 | 532 | ||
533 | /* Provided by em28xx-input.c */ | 533 | /* Provided by em28xx-input.c */ |
534 | /* TODO: Check if the standard get_key handlers on ir-common can be used */ | 534 | /* TODO: Check if the standard get_key handlers on ir-common can be used */ |
diff --git a/drivers/media/video/et61x251/et61x251_core.c b/drivers/media/video/et61x251/et61x251_core.c index 8db2a05bf9c5..7a85c41b0eea 100644 --- a/drivers/media/video/et61x251/et61x251_core.c +++ b/drivers/media/video/et61x251/et61x251_core.c | |||
@@ -1214,7 +1214,7 @@ static int et61x251_open(struct inode* inode, struct file* filp) | |||
1214 | if (!down_read_trylock(&et61x251_dev_lock)) | 1214 | if (!down_read_trylock(&et61x251_dev_lock)) |
1215 | return -ERESTARTSYS; | 1215 | return -ERESTARTSYS; |
1216 | 1216 | ||
1217 | cam = video_get_drvdata(video_devdata(filp)); | 1217 | cam = video_drvdata(filp); |
1218 | 1218 | ||
1219 | if (wait_for_completion_interruptible(&cam->probe)) { | 1219 | if (wait_for_completion_interruptible(&cam->probe)) { |
1220 | up_read(&et61x251_dev_lock); | 1220 | up_read(&et61x251_dev_lock); |
@@ -1297,7 +1297,7 @@ static int et61x251_release(struct inode* inode, struct file* filp) | |||
1297 | 1297 | ||
1298 | down_write(&et61x251_dev_lock); | 1298 | down_write(&et61x251_dev_lock); |
1299 | 1299 | ||
1300 | cam = video_get_drvdata(video_devdata(filp)); | 1300 | cam = video_drvdata(filp); |
1301 | 1301 | ||
1302 | et61x251_stop_transfer(cam); | 1302 | et61x251_stop_transfer(cam); |
1303 | et61x251_release_buffers(cam); | 1303 | et61x251_release_buffers(cam); |
@@ -1318,7 +1318,7 @@ static ssize_t | |||
1318 | et61x251_read(struct file* filp, char __user * buf, | 1318 | et61x251_read(struct file* filp, char __user * buf, |
1319 | size_t count, loff_t* f_pos) | 1319 | size_t count, loff_t* f_pos) |
1320 | { | 1320 | { |
1321 | struct et61x251_device* cam = video_get_drvdata(video_devdata(filp)); | 1321 | struct et61x251_device *cam = video_drvdata(filp); |
1322 | struct et61x251_frame_t* f, * i; | 1322 | struct et61x251_frame_t* f, * i; |
1323 | unsigned long lock_flags; | 1323 | unsigned long lock_flags; |
1324 | long timeout; | 1324 | long timeout; |
@@ -1426,7 +1426,7 @@ exit: | |||
1426 | 1426 | ||
1427 | static unsigned int et61x251_poll(struct file *filp, poll_table *wait) | 1427 | static unsigned int et61x251_poll(struct file *filp, poll_table *wait) |
1428 | { | 1428 | { |
1429 | struct et61x251_device* cam = video_get_drvdata(video_devdata(filp)); | 1429 | struct et61x251_device *cam = video_drvdata(filp); |
1430 | struct et61x251_frame_t* f; | 1430 | struct et61x251_frame_t* f; |
1431 | unsigned long lock_flags; | 1431 | unsigned long lock_flags; |
1432 | unsigned int mask = 0; | 1432 | unsigned int mask = 0; |
@@ -1502,7 +1502,7 @@ static struct vm_operations_struct et61x251_vm_ops = { | |||
1502 | 1502 | ||
1503 | static int et61x251_mmap(struct file* filp, struct vm_area_struct *vma) | 1503 | static int et61x251_mmap(struct file* filp, struct vm_area_struct *vma) |
1504 | { | 1504 | { |
1505 | struct et61x251_device* cam = video_get_drvdata(video_devdata(filp)); | 1505 | struct et61x251_device *cam = video_drvdata(filp); |
1506 | unsigned long size = vma->vm_end - vma->vm_start, | 1506 | unsigned long size = vma->vm_end - vma->vm_start, |
1507 | start = vma->vm_start; | 1507 | start = vma->vm_start; |
1508 | void *pos; | 1508 | void *pos; |
@@ -2395,7 +2395,7 @@ et61x251_vidioc_s_parm(struct et61x251_device* cam, void __user * arg) | |||
2395 | static int et61x251_ioctl_v4l2(struct inode* inode, struct file* filp, | 2395 | static int et61x251_ioctl_v4l2(struct inode* inode, struct file* filp, |
2396 | unsigned int cmd, void __user * arg) | 2396 | unsigned int cmd, void __user * arg) |
2397 | { | 2397 | { |
2398 | struct et61x251_device* cam = video_get_drvdata(video_devdata(filp)); | 2398 | struct et61x251_device *cam = video_drvdata(filp); |
2399 | 2399 | ||
2400 | switch (cmd) { | 2400 | switch (cmd) { |
2401 | 2401 | ||
@@ -2490,7 +2490,7 @@ static int et61x251_ioctl_v4l2(struct inode* inode, struct file* filp, | |||
2490 | static int et61x251_ioctl(struct inode* inode, struct file* filp, | 2490 | static int et61x251_ioctl(struct inode* inode, struct file* filp, |
2491 | unsigned int cmd, unsigned long arg) | 2491 | unsigned int cmd, unsigned long arg) |
2492 | { | 2492 | { |
2493 | struct et61x251_device* cam = video_get_drvdata(video_devdata(filp)); | 2493 | struct et61x251_device *cam = video_drvdata(filp); |
2494 | int err = 0; | 2494 | int err = 0; |
2495 | 2495 | ||
2496 | if (mutex_lock_interruptible(&cam->fileop_mutex)) | 2496 | if (mutex_lock_interruptible(&cam->fileop_mutex)) |
diff --git a/drivers/media/video/gspca/Kconfig b/drivers/media/video/gspca/Kconfig index 42b90742b40b..4d0817471c9f 100644 --- a/drivers/media/video/gspca/Kconfig +++ b/drivers/media/video/gspca/Kconfig | |||
@@ -1,13 +1,212 @@ | |||
1 | config USB_GSPCA | 1 | menuconfig USB_GSPCA |
2 | tristate "USB GSPCA driver" | 2 | tristate "GSPCA based webcams" |
3 | depends on VIDEO_V4L2 | 3 | depends on VIDEO_V4L2 |
4 | default m | ||
4 | ---help--- | 5 | ---help--- |
5 | Say Y here if you want support for various USB webcams. | 6 | Say Y here if you want to enable selecting webcams based |
7 | on the GSPCA framework. | ||
6 | 8 | ||
7 | See <file:Documentation/video4linux/gspca.txt> for more info. | 9 | See <file:Documentation/video4linux/gspca.txt> for more info. |
8 | 10 | ||
9 | This driver uses the Video For Linux API. You must say Y or M to | 11 | This driver uses the Video For Linux API. You must say Y or M to |
10 | "Video For Linux" to use this driver. | 12 | "Video For Linux" to use this driver. |
11 | 13 | ||
12 | To compile this driver as modules, choose M here: the | 14 | To compile this driver as modules, choose M here: the |
13 | modules will be called gspca_xxxx. | 15 | modules will be called gspca_main. |
16 | |||
17 | |||
18 | if USB_GSPCA && VIDEO_V4L2 | ||
19 | |||
20 | source "drivers/media/video/gspca/m5602/Kconfig" | ||
21 | |||
22 | config USB_GSPCA_CONEX | ||
23 | tristate "Conexant Camera Driver" | ||
24 | depends on VIDEO_V4L2 && USB_GSPCA | ||
25 | help | ||
26 | Say Y here if you want support for cameras based on the Conexant chip. | ||
27 | |||
28 | To compile this driver as a module, choose M here: the | ||
29 | module will be called gspca_conex. | ||
30 | |||
31 | config USB_GSPCA_ETOMS | ||
32 | tristate "Etoms USB Camera Driver" | ||
33 | depends on VIDEO_V4L2 && USB_GSPCA | ||
34 | help | ||
35 | Say Y here if you want support for cameras based on the Etoms chip. | ||
36 | |||
37 | To compile this driver as a module, choose M here: the | ||
38 | module will be called gspca_etoms. | ||
39 | |||
40 | config USB_GSPCA_FINEPIX | ||
41 | tristate "Fujifilm FinePix USB V4L2 driver" | ||
42 | depends on VIDEO_V4L2 && USB_GSPCA | ||
43 | help | ||
44 | Say Y here if you want support for cameras based on the FinePix chip. | ||
45 | |||
46 | To compile this driver as a module, choose M here: the | ||
47 | module will be called gspca_finepix. | ||
48 | |||
49 | config USB_GSPCA_MARS | ||
50 | tristate "Mars USB Camera Driver" | ||
51 | depends on VIDEO_V4L2 && USB_GSPCA | ||
52 | help | ||
53 | Say Y here if you want support for cameras based on the Mars chip. | ||
54 | |||
55 | To compile this driver as a module, choose M here: the | ||
56 | module will be called gspca_mars. | ||
57 | |||
58 | config USB_GSPCA_OV519 | ||
59 | tristate "OV519 USB Camera Driver" | ||
60 | depends on VIDEO_V4L2 && USB_GSPCA | ||
61 | help | ||
62 | Say Y here if you want support for cameras based on the OV519 chip. | ||
63 | |||
64 | To compile this driver as a module, choose M here: the | ||
65 | module will be called gspca_ov519. | ||
66 | |||
67 | config USB_GSPCA_PAC207 | ||
68 | tristate "Pixart PAC207 USB Camera Driver" | ||
69 | depends on VIDEO_V4L2 && USB_GSPCA | ||
70 | help | ||
71 | Say Y here if you want support for cameras based on the PAC207 chip. | ||
72 | |||
73 | To compile this driver as a module, choose M here: the | ||
74 | module will be called gspca_pac207. | ||
75 | |||
76 | config USB_GSPCA_PAC7311 | ||
77 | tristate "Pixart PAC7311 USB Camera Driver" | ||
78 | depends on VIDEO_V4L2 && USB_GSPCA | ||
79 | help | ||
80 | Say Y here if you want support for cameras based on the PAC7311 chip. | ||
81 | |||
82 | To compile this driver as a module, choose M here: the | ||
83 | module will be called gspca_pac7311. | ||
84 | |||
85 | config USB_GSPCA_SONIXB | ||
86 | tristate "SN9C102 USB Camera Driver" | ||
87 | depends on VIDEO_V4L2 && USB_GSPCA | ||
88 | help | ||
89 | Say Y here if you want support for cameras based on the SONIXB chip. | ||
90 | |||
91 | To compile this driver as a module, choose M here: the | ||
92 | module will be called gspca_sonixb. | ||
93 | |||
94 | config USB_GSPCA_SONIXJ | ||
95 | tristate "SONIX JPEG USB Camera Driver" | ||
96 | depends on VIDEO_V4L2 && USB_GSPCA | ||
97 | help | ||
98 | Say Y here if you want support for cameras based on the SONIXJ chip. | ||
99 | |||
100 | To compile this driver as a module, choose M here: the | ||
101 | module will be called gspca_sonixj | ||
102 | |||
103 | config USB_GSPCA_SPCA500 | ||
104 | tristate "SPCA500 USB Camera Driver" | ||
105 | depends on VIDEO_V4L2 && USB_GSPCA | ||
106 | help | ||
107 | Say Y here if you want support for cameras based on the SPCA500 chip. | ||
108 | |||
109 | To compile this driver as a module, choose M here: the | ||
110 | module will be called gspca_spca500. | ||
111 | |||
112 | config USB_GSPCA_SPCA501 | ||
113 | tristate "SPCA501 USB Camera Driver" | ||
114 | depends on VIDEO_V4L2 && USB_GSPCA | ||
115 | help | ||
116 | Say Y here if you want support for cameras based on the SPCA501 chip. | ||
117 | |||
118 | To compile this driver as a module, choose M here: the | ||
119 | module will be called gspca_spca501. | ||
120 | |||
121 | config USB_GSPCA_SPCA505 | ||
122 | tristate "SPCA505 USB Camera Driver" | ||
123 | depends on VIDEO_V4L2 && USB_GSPCA | ||
124 | help | ||
125 | Say Y here if you want support for cameras based on the SPCA505 chip. | ||
126 | |||
127 | To compile this driver as a module, choose M here: the | ||
128 | module will be called gspca_spca505. | ||
129 | |||
130 | config USB_GSPCA_SPCA506 | ||
131 | tristate "SPCA506 USB Camera Driver" | ||
132 | depends on VIDEO_V4L2 && USB_GSPCA | ||
133 | help | ||
134 | Say Y here if you want support for cameras based on the SPCA506 chip. | ||
135 | |||
136 | To compile this driver as a module, choose M here: the | ||
137 | module will be called gspca_spca506. | ||
138 | |||
139 | config USB_GSPCA_SPCA508 | ||
140 | tristate "SPCA508 USB Camera Driver" | ||
141 | depends on VIDEO_V4L2 && USB_GSPCA | ||
142 | help | ||
143 | Say Y here if you want support for cameras based on the SPCA508 chip. | ||
144 | |||
145 | To compile this driver as a module, choose M here: the | ||
146 | module will be called gspca_spca508. | ||
147 | |||
148 | config USB_GSPCA_SPCA561 | ||
149 | tristate "SPCA561 USB Camera Driver" | ||
150 | depends on VIDEO_V4L2 && USB_GSPCA | ||
151 | help | ||
152 | Say Y here if you want support for cameras based on the SPCA561 chip. | ||
153 | |||
154 | To compile this driver as a module, choose M here: the | ||
155 | module will be called gspca_spca561. | ||
156 | |||
157 | config USB_GSPCA_STK014 | ||
158 | tristate "Syntek DV4000 (STK014) USB Camera Driver" | ||
159 | depends on VIDEO_V4L2 && USB_GSPCA | ||
160 | help | ||
161 | Say Y here if you want support for cameras based on the STK014 chip. | ||
162 | |||
163 | To compile this driver as a module, choose M here: the | ||
164 | module will be called gspca_stk014. | ||
165 | |||
166 | config USB_GSPCA_SUNPLUS | ||
167 | tristate "SUNPLUS USB Camera Driver" | ||
168 | depends on VIDEO_V4L2 && USB_GSPCA | ||
169 | help | ||
170 | Say Y here if you want support for cameras based on the Sunplus | ||
171 | SPCA504(abc) SPCA533 SPCA536 chips. | ||
172 | |||
173 | To compile this driver as a module, choose M here: the | ||
174 | module will be called gspca_spca5xx. | ||
175 | |||
176 | config USB_GSPCA_T613 | ||
177 | tristate "T613 (JPEG Compliance) USB Camera Driver" | ||
178 | depends on VIDEO_V4L2 && USB_GSPCA | ||
179 | help | ||
180 | Say Y here if you want support for cameras based on the T613 chip. | ||
181 | |||
182 | To compile this driver as a module, choose M here: the | ||
183 | module will be called gspca_t613. | ||
184 | |||
185 | config USB_GSPCA_TV8532 | ||
186 | tristate "TV8532 USB Camera Driver" | ||
187 | depends on VIDEO_V4L2 && USB_GSPCA | ||
188 | help | ||
189 | Say Y here if you want support for cameras based on the TV8531 chip. | ||
190 | |||
191 | To compile this driver as a module, choose M here: the | ||
192 | module will be called gspca_tv8532. | ||
193 | |||
194 | config USB_GSPCA_VC032X | ||
195 | tristate "VC032X USB Camera Driver" | ||
196 | depends on VIDEO_V4L2 && USB_GSPCA | ||
197 | help | ||
198 | Say Y here if you want support for cameras based on the VC032X chip. | ||
199 | |||
200 | To compile this driver as a module, choose M here: the | ||
201 | module will be called gspca_vc032x. | ||
202 | |||
203 | config USB_GSPCA_ZC3XX | ||
204 | tristate "VC3xx USB Camera Driver" | ||
205 | depends on VIDEO_V4L2 && USB_GSPCA | ||
206 | help | ||
207 | Say Y here if you want support for cameras based on the ZC3XX chip. | ||
208 | |||
209 | To compile this driver as a module, choose M here: the | ||
210 | module will be called gspca_zc3xx. | ||
211 | |||
212 | endif | ||
diff --git a/drivers/media/video/gspca/Makefile b/drivers/media/video/gspca/Makefile index e68a8965297a..22734f5a6c32 100644 --- a/drivers/media/video/gspca/Makefile +++ b/drivers/media/video/gspca/Makefile | |||
@@ -1,29 +1,48 @@ | |||
1 | obj-$(CONFIG_USB_GSPCA) += gspca_main.o \ | 1 | obj-$(CONFIG_USB_GSPCA) += gspca_main.o |
2 | gspca_conex.o gspca_etoms.o gspca_mars.o \ | 2 | obj-$(CONFIG_USB_GSPCA_CONEX) += gspca_conex.o |
3 | gspca_ov519.o gspca_pac207.o gspca_pac7311.o \ | 3 | obj-$(CONFIG_USB_GSPCA_ETOMS) += gspca_etoms.o |
4 | gspca_sonixb.o gspca_sonixj.o gspca_spca500.o gspca_spca501.o \ | 4 | obj-$(CONFIG_USB_GSPCA_FINEPIX) += gspca_finepix.o |
5 | gspca_spca505.o gspca_spca506.o gspca_spca508.o gspca_spca561.o \ | 5 | obj-$(CONFIG_USB_GSPCA_MARS) += gspca_mars.o |
6 | gspca_sunplus.o gspca_stk014.o gspca_t613.o gspca_tv8532.o \ | 6 | obj-$(CONFIG_USB_GSPCA_OV519) += gspca_ov519.o |
7 | gspca_vc032x.o gspca_zc3xx.o | 7 | obj-$(CONFIG_USB_GSPCA_PAC207) += gspca_pac207.o |
8 | obj-$(CONFIG_USB_GSPCA_PAC7311) += gspca_pac7311.o | ||
9 | obj-$(CONFIG_USB_GSPCA_SONIXB) += gspca_sonixb.o | ||
10 | obj-$(CONFIG_USB_GSPCA_SONIXJ) += gspca_sonixj.o | ||
11 | obj-$(CONFIG_USB_GSPCA_SPCA500) += gspca_spca500.o | ||
12 | obj-$(CONFIG_USB_GSPCA_SPCA501) += gspca_spca501.o | ||
13 | obj-$(CONFIG_USB_GSPCA_SPCA505) += gspca_spca505.o | ||
14 | obj-$(CONFIG_USB_GSPCA_SPCA506) += gspca_spca506.o | ||
15 | obj-$(CONFIG_USB_GSPCA_SPCA508) += gspca_spca508.o | ||
16 | obj-$(CONFIG_USB_GSPCA_SPCA561) += gspca_spca561.o | ||
17 | obj-$(CONFIG_USB_GSPCA_SUNPLUS) += gspca_sunplus.o | ||
18 | obj-$(CONFIG_USB_GSPCA_STK014) += gspca_stk014.o | ||
19 | obj-$(CONFIG_USB_GSPCA_T613) += gspca_t613.o | ||
20 | obj-$(CONFIG_USB_GSPCA_TV8532) += gspca_tv8532.o | ||
21 | obj-$(CONFIG_USB_GSPCA_VC032X) += gspca_vc032x.o | ||
22 | obj-$(CONFIG_USB_GSPCA_ZC3XX) += gspca_zc3xx.o | ||
23 | |||
24 | gspca_main-objs := gspca.o | ||
25 | gspca_conex-objs := conex.o | ||
26 | gspca_etoms-objs := etoms.o | ||
27 | gspca_finepix-objs := finepix.o | ||
28 | gspca_mars-objs := mars.o | ||
29 | gspca_ov519-objs := ov519.o | ||
30 | gspca_pac207-objs := pac207.o | ||
31 | gspca_pac7311-objs := pac7311.o | ||
32 | gspca_sonixb-objs := sonixb.o | ||
33 | gspca_sonixj-objs := sonixj.o | ||
34 | gspca_spca500-objs := spca500.o | ||
35 | gspca_spca501-objs := spca501.o | ||
36 | gspca_spca505-objs := spca505.o | ||
37 | gspca_spca506-objs := spca506.o | ||
38 | gspca_spca508-objs := spca508.o | ||
39 | gspca_spca561-objs := spca561.o | ||
40 | gspca_stk014-objs := stk014.o | ||
41 | gspca_sunplus-objs := sunplus.o | ||
42 | gspca_t613-objs := t613.o | ||
43 | gspca_tv8532-objs := tv8532.o | ||
44 | gspca_vc032x-objs := vc032x.o | ||
45 | gspca_zc3xx-objs := zc3xx.o | ||
46 | |||
47 | obj-$(CONFIG_USB_M5602) += m5602/ | ||
8 | 48 | ||
9 | gspca_main-objs := gspca.o | ||
10 | gspca_conex-objs := conex.o | ||
11 | gspca_etoms-objs := etoms.o | ||
12 | gspca_mars-objs := mars.o | ||
13 | gspca_ov519-objs := ov519.o | ||
14 | gspca_pac207-objs := pac207.o | ||
15 | gspca_pac7311-objs := pac7311.o | ||
16 | gspca_sonixb-objs := sonixb.o | ||
17 | gspca_sonixj-objs := sonixj.o | ||
18 | gspca_spca500-objs := spca500.o | ||
19 | gspca_spca501-objs := spca501.o | ||
20 | gspca_spca505-objs := spca505.o | ||
21 | gspca_spca506-objs := spca506.o | ||
22 | gspca_spca508-objs := spca508.o | ||
23 | gspca_spca561-objs := spca561.o | ||
24 | gspca_stk014-objs := stk014.o | ||
25 | gspca_sunplus-objs := sunplus.o | ||
26 | gspca_t613-objs := t613.o | ||
27 | gspca_tv8532-objs := tv8532.o | ||
28 | gspca_vc032x-objs := vc032x.o | ||
29 | gspca_zc3xx-objs := zc3xx.o | ||
diff --git a/drivers/media/video/gspca/conex.c b/drivers/media/video/gspca/conex.c index 4d9f4cc255a9..a9d51ba7c57c 100644 --- a/drivers/media/video/gspca/conex.c +++ b/drivers/media/video/gspca/conex.c | |||
@@ -837,12 +837,13 @@ static int sd_init(struct gspca_dev *gspca_dev) | |||
837 | return 0; | 837 | return 0; |
838 | } | 838 | } |
839 | 839 | ||
840 | static void sd_start(struct gspca_dev *gspca_dev) | 840 | static int sd_start(struct gspca_dev *gspca_dev) |
841 | { | 841 | { |
842 | cx11646_initsize(gspca_dev); | 842 | cx11646_initsize(gspca_dev); |
843 | cx11646_fw(gspca_dev); | 843 | cx11646_fw(gspca_dev); |
844 | cx_sensor(gspca_dev); | 844 | cx_sensor(gspca_dev); |
845 | cx11646_jpeg(gspca_dev); | 845 | cx11646_jpeg(gspca_dev); |
846 | return 0; | ||
846 | } | 847 | } |
847 | 848 | ||
848 | static void sd_stop0(struct gspca_dev *gspca_dev) | 849 | static void sd_stop0(struct gspca_dev *gspca_dev) |
diff --git a/drivers/media/video/gspca/etoms.c b/drivers/media/video/gspca/etoms.c index 4ff0e386914b..3be30b420a26 100644 --- a/drivers/media/video/gspca/etoms.c +++ b/drivers/media/video/gspca/etoms.c | |||
@@ -691,7 +691,7 @@ static int sd_init(struct gspca_dev *gspca_dev) | |||
691 | } | 691 | } |
692 | 692 | ||
693 | /* -- start the camera -- */ | 693 | /* -- start the camera -- */ |
694 | static void sd_start(struct gspca_dev *gspca_dev) | 694 | static int sd_start(struct gspca_dev *gspca_dev) |
695 | { | 695 | { |
696 | struct sd *sd = (struct sd *) gspca_dev; | 696 | struct sd *sd = (struct sd *) gspca_dev; |
697 | 697 | ||
@@ -704,6 +704,7 @@ static void sd_start(struct gspca_dev *gspca_dev) | |||
704 | 704 | ||
705 | reg_w_val(gspca_dev, ET_RESET_ALL, 0x08); | 705 | reg_w_val(gspca_dev, ET_RESET_ALL, 0x08); |
706 | et_video(gspca_dev, 1); /* video on */ | 706 | et_video(gspca_dev, 1); /* video on */ |
707 | return 0; | ||
707 | } | 708 | } |
708 | 709 | ||
709 | static void sd_stopN(struct gspca_dev *gspca_dev) | 710 | static void sd_stopN(struct gspca_dev *gspca_dev) |
diff --git a/drivers/media/video/gspca/finepix.c b/drivers/media/video/gspca/finepix.c new file mode 100644 index 000000000000..65d3cbfe6b27 --- /dev/null +++ b/drivers/media/video/gspca/finepix.c | |||
@@ -0,0 +1,466 @@ | |||
1 | /* | ||
2 | * Fujifilm Finepix subdriver | ||
3 | * | ||
4 | * Copyright (C) 2008 Frank Zago | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | */ | ||
20 | |||
21 | #define MODULE_NAME "finepix" | ||
22 | |||
23 | #include "gspca.h" | ||
24 | |||
25 | MODULE_AUTHOR("Frank Zago <frank@zago.net>"); | ||
26 | MODULE_DESCRIPTION("Fujifilm FinePix USB V4L2 driver"); | ||
27 | MODULE_LICENSE("GPL"); | ||
28 | |||
29 | /* Default timeout, in ms */ | ||
30 | #define FPIX_TIMEOUT (HZ / 10) | ||
31 | |||
32 | /* Maximum transfer size to use. The windows driver reads by chunks of | ||
33 | * 0x2000 bytes, so do the same. Note: reading more seems to work | ||
34 | * too. */ | ||
35 | #define FPIX_MAX_TRANSFER 0x2000 | ||
36 | |||
37 | /* Structure to hold all of our device specific stuff */ | ||
38 | struct usb_fpix { | ||
39 | struct gspca_dev gspca_dev; /* !! must be the first item */ | ||
40 | |||
41 | /* | ||
42 | * USB stuff | ||
43 | */ | ||
44 | struct usb_ctrlrequest ctrlreq; | ||
45 | struct urb *control_urb; | ||
46 | struct timer_list bulk_timer; | ||
47 | |||
48 | enum { | ||
49 | FPIX_NOP, /* inactive, else streaming */ | ||
50 | FPIX_RESET, /* must reset */ | ||
51 | FPIX_REQ_FRAME, /* requesting a frame */ | ||
52 | FPIX_READ_FRAME, /* reading frame */ | ||
53 | } state; | ||
54 | |||
55 | /* | ||
56 | * Driver stuff | ||
57 | */ | ||
58 | struct delayed_work wqe; | ||
59 | struct completion can_close; | ||
60 | int streaming; | ||
61 | }; | ||
62 | |||
63 | /* Delay after which claim the next frame. If the delay is too small, | ||
64 | * the camera will return old frames. On the 4800Z, 20ms is bad, 25ms | ||
65 | * will fail every 4 or 5 frames, but 30ms is perfect. */ | ||
66 | #define NEXT_FRAME_DELAY (((HZ * 30) + 999) / 1000) | ||
67 | |||
68 | #define dev_new_state(new_state) { \ | ||
69 | PDEBUG(D_STREAM, "new state from %d to %d at %s:%d", \ | ||
70 | dev->state, new_state, __func__, __LINE__); \ | ||
71 | dev->state = new_state; \ | ||
72 | } | ||
73 | |||
74 | /* These cameras only support 320x200. */ | ||
75 | static struct v4l2_pix_format fpix_mode[1] = { | ||
76 | { 320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, | ||
77 | .bytesperline = 320, | ||
78 | .sizeimage = 320 * 240 * 3 / 8 + 590, | ||
79 | .colorspace = V4L2_COLORSPACE_SRGB, | ||
80 | .priv = 0} | ||
81 | }; | ||
82 | |||
83 | /* Reads part of a frame */ | ||
84 | static void read_frame_part(struct usb_fpix *dev) | ||
85 | { | ||
86 | int ret; | ||
87 | |||
88 | PDEBUG(D_STREAM, "read_frame_part"); | ||
89 | |||
90 | /* Reads part of a frame */ | ||
91 | ret = usb_submit_urb(dev->gspca_dev.urb[0], GFP_ATOMIC); | ||
92 | if (ret) { | ||
93 | dev_new_state(FPIX_RESET); | ||
94 | schedule_delayed_work(&dev->wqe, 1); | ||
95 | PDEBUG(D_STREAM, "usb_submit_urb failed with %d", | ||
96 | ret); | ||
97 | } else { | ||
98 | /* Sometimes we never get a callback, so use a timer. | ||
99 | * Is this masking a bug somewhere else? */ | ||
100 | dev->bulk_timer.expires = jiffies + msecs_to_jiffies(150); | ||
101 | add_timer(&dev->bulk_timer); | ||
102 | } | ||
103 | } | ||
104 | |||
105 | /* Callback for URBs. */ | ||
106 | static void urb_callback(struct urb *urb) | ||
107 | { | ||
108 | struct gspca_dev *gspca_dev = urb->context; | ||
109 | struct usb_fpix *dev = (struct usb_fpix *) gspca_dev; | ||
110 | |||
111 | PDEBUG(D_PACK, | ||
112 | "enter urb_callback - status=%d, length=%d", | ||
113 | urb->status, urb->actual_length); | ||
114 | |||
115 | if (dev->state == FPIX_READ_FRAME) | ||
116 | del_timer(&dev->bulk_timer); | ||
117 | |||
118 | if (urb->status != 0) { | ||
119 | /* We kill a stuck urb every 50 frames on average, so don't | ||
120 | * display a log message for that. */ | ||
121 | if (urb->status != -ECONNRESET) | ||
122 | PDEBUG(D_STREAM, "bad URB status %d", urb->status); | ||
123 | dev_new_state(FPIX_RESET); | ||
124 | schedule_delayed_work(&dev->wqe, 1); | ||
125 | } | ||
126 | |||
127 | switch (dev->state) { | ||
128 | case FPIX_REQ_FRAME: | ||
129 | dev_new_state(FPIX_READ_FRAME); | ||
130 | read_frame_part(dev); | ||
131 | break; | ||
132 | |||
133 | case FPIX_READ_FRAME: { | ||
134 | unsigned char *data = urb->transfer_buffer; | ||
135 | struct gspca_frame *frame; | ||
136 | |||
137 | frame = gspca_get_i_frame(&dev->gspca_dev); | ||
138 | if (frame == NULL) | ||
139 | gspca_dev->last_packet_type = DISCARD_PACKET; | ||
140 | if (urb->actual_length < FPIX_MAX_TRANSFER || | ||
141 | (data[urb->actual_length-2] == 0xff && | ||
142 | data[urb->actual_length-1] == 0xd9)) { | ||
143 | |||
144 | /* If the result is less than what was asked | ||
145 | * for, then it's the end of the | ||
146 | * frame. Sometime the jpeg is not complete, | ||
147 | * but there's nothing we can do. We also end | ||
148 | * here if the the jpeg ends right at the end | ||
149 | * of the frame. */ | ||
150 | if (frame) | ||
151 | gspca_frame_add(gspca_dev, LAST_PACKET, | ||
152 | frame, | ||
153 | data, urb->actual_length); | ||
154 | dev_new_state(FPIX_REQ_FRAME); | ||
155 | schedule_delayed_work(&dev->wqe, NEXT_FRAME_DELAY); | ||
156 | } else { | ||
157 | |||
158 | /* got a partial image */ | ||
159 | if (frame) | ||
160 | gspca_frame_add(gspca_dev, | ||
161 | gspca_dev->last_packet_type | ||
162 | == LAST_PACKET | ||
163 | ? FIRST_PACKET : INTER_PACKET, | ||
164 | frame, | ||
165 | data, urb->actual_length); | ||
166 | read_frame_part(dev); | ||
167 | } | ||
168 | break; | ||
169 | } | ||
170 | |||
171 | case FPIX_NOP: | ||
172 | case FPIX_RESET: | ||
173 | PDEBUG(D_STREAM, "invalid state %d", dev->state); | ||
174 | break; | ||
175 | } | ||
176 | } | ||
177 | |||
178 | /* Request a new frame */ | ||
179 | static void request_frame(struct usb_fpix *dev) | ||
180 | { | ||
181 | int ret; | ||
182 | struct gspca_dev *gspca_dev = &dev->gspca_dev; | ||
183 | |||
184 | /* Setup command packet */ | ||
185 | memset(gspca_dev->usb_buf, 0, 12); | ||
186 | gspca_dev->usb_buf[0] = 0xd3; | ||
187 | gspca_dev->usb_buf[7] = 0x01; | ||
188 | |||
189 | /* Request a frame */ | ||
190 | dev->ctrlreq.bRequestType = | ||
191 | USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE; | ||
192 | dev->ctrlreq.bRequest = USB_REQ_GET_STATUS; | ||
193 | dev->ctrlreq.wValue = 0; | ||
194 | dev->ctrlreq.wIndex = 0; | ||
195 | dev->ctrlreq.wLength = cpu_to_le16(12); | ||
196 | |||
197 | usb_fill_control_urb(dev->control_urb, | ||
198 | gspca_dev->dev, | ||
199 | usb_sndctrlpipe(gspca_dev->dev, 0), | ||
200 | (unsigned char *) &dev->ctrlreq, | ||
201 | gspca_dev->usb_buf, | ||
202 | 12, urb_callback, gspca_dev); | ||
203 | |||
204 | ret = usb_submit_urb(dev->control_urb, GFP_ATOMIC); | ||
205 | if (ret) { | ||
206 | dev_new_state(FPIX_RESET); | ||
207 | schedule_delayed_work(&dev->wqe, 1); | ||
208 | PDEBUG(D_STREAM, "usb_submit_urb failed with %d", ret); | ||
209 | } | ||
210 | } | ||
211 | |||
212 | /*--------------------------------------------------------------------------*/ | ||
213 | |||
214 | /* State machine. */ | ||
215 | static void fpix_sm(struct work_struct *work) | ||
216 | { | ||
217 | struct usb_fpix *dev = container_of(work, struct usb_fpix, wqe.work); | ||
218 | |||
219 | PDEBUG(D_STREAM, "fpix_sm state %d", dev->state); | ||
220 | |||
221 | /* verify that the device wasn't unplugged */ | ||
222 | if (!dev->gspca_dev.present) { | ||
223 | PDEBUG(D_STREAM, "device is gone"); | ||
224 | dev_new_state(FPIX_NOP); | ||
225 | complete(&dev->can_close); | ||
226 | return; | ||
227 | } | ||
228 | |||
229 | if (!dev->streaming) { | ||
230 | PDEBUG(D_STREAM, "stopping state machine"); | ||
231 | dev_new_state(FPIX_NOP); | ||
232 | complete(&dev->can_close); | ||
233 | return; | ||
234 | } | ||
235 | |||
236 | switch (dev->state) { | ||
237 | case FPIX_RESET: | ||
238 | dev_new_state(FPIX_REQ_FRAME); | ||
239 | schedule_delayed_work(&dev->wqe, HZ / 10); | ||
240 | break; | ||
241 | |||
242 | case FPIX_REQ_FRAME: | ||
243 | /* get an image */ | ||
244 | request_frame(dev); | ||
245 | break; | ||
246 | |||
247 | case FPIX_NOP: | ||
248 | case FPIX_READ_FRAME: | ||
249 | PDEBUG(D_STREAM, "invalid state %d", dev->state); | ||
250 | break; | ||
251 | } | ||
252 | } | ||
253 | |||
254 | /* this function is called at probe time */ | ||
255 | static int sd_config(struct gspca_dev *gspca_dev, | ||
256 | const struct usb_device_id *id) | ||
257 | { | ||
258 | struct cam *cam = &gspca_dev->cam; | ||
259 | |||
260 | cam->cam_mode = fpix_mode; | ||
261 | cam->nmodes = 1; | ||
262 | cam->epaddr = 0x01; /* todo: correct for all cams? */ | ||
263 | cam->bulk_size = FPIX_MAX_TRANSFER; | ||
264 | |||
265 | /* gspca_dev->nbalt = 1; * use bulk transfer */ | ||
266 | return 0; | ||
267 | } | ||
268 | |||
269 | /* Stop streaming and free the ressources allocated by sd_start. */ | ||
270 | static void sd_stopN(struct gspca_dev *gspca_dev) | ||
271 | { | ||
272 | struct usb_fpix *dev = (struct usb_fpix *) gspca_dev; | ||
273 | |||
274 | dev->streaming = 0; | ||
275 | |||
276 | /* Stop the state machine */ | ||
277 | if (dev->state != FPIX_NOP) | ||
278 | wait_for_completion(&dev->can_close); | ||
279 | |||
280 | usb_free_urb(dev->control_urb); | ||
281 | dev->control_urb = NULL; | ||
282 | } | ||
283 | |||
284 | /* Kill an URB that hasn't completed. */ | ||
285 | static void timeout_kill(unsigned long data) | ||
286 | { | ||
287 | struct urb *urb = (struct urb *) data; | ||
288 | |||
289 | usb_unlink_urb(urb); | ||
290 | } | ||
291 | |||
292 | /* this function is called at probe and resume time */ | ||
293 | static int sd_init(struct gspca_dev *gspca_dev) | ||
294 | { | ||
295 | struct usb_fpix *dev = (struct usb_fpix *) gspca_dev; | ||
296 | |||
297 | INIT_DELAYED_WORK(&dev->wqe, fpix_sm); | ||
298 | |||
299 | init_timer(&dev->bulk_timer); | ||
300 | dev->bulk_timer.function = timeout_kill; | ||
301 | |||
302 | return 0; | ||
303 | } | ||
304 | |||
305 | static int sd_start(struct gspca_dev *gspca_dev) | ||
306 | { | ||
307 | struct usb_fpix *dev = (struct usb_fpix *) gspca_dev; | ||
308 | int ret; | ||
309 | int size_ret; | ||
310 | |||
311 | /* Reset bulk in endpoint */ | ||
312 | usb_clear_halt(gspca_dev->dev, gspca_dev->cam.epaddr); | ||
313 | |||
314 | /* Init the device */ | ||
315 | memset(gspca_dev->usb_buf, 0, 12); | ||
316 | gspca_dev->usb_buf[0] = 0xc6; | ||
317 | gspca_dev->usb_buf[8] = 0x20; | ||
318 | |||
319 | ret = usb_control_msg(gspca_dev->dev, | ||
320 | usb_sndctrlpipe(gspca_dev->dev, 0), | ||
321 | USB_REQ_GET_STATUS, | ||
322 | USB_DIR_OUT | USB_TYPE_CLASS | | ||
323 | USB_RECIP_INTERFACE, 0, 0, gspca_dev->usb_buf, | ||
324 | 12, FPIX_TIMEOUT); | ||
325 | |||
326 | if (ret != 12) { | ||
327 | PDEBUG(D_STREAM, "usb_control_msg failed (%d)", ret); | ||
328 | ret = -EIO; | ||
329 | goto error; | ||
330 | } | ||
331 | |||
332 | /* Read the result of the command. Ignore the result, for it | ||
333 | * varies with the device. */ | ||
334 | ret = usb_bulk_msg(gspca_dev->dev, | ||
335 | usb_rcvbulkpipe(gspca_dev->dev, | ||
336 | gspca_dev->cam.epaddr), | ||
337 | gspca_dev->usb_buf, FPIX_MAX_TRANSFER, &size_ret, | ||
338 | FPIX_TIMEOUT); | ||
339 | if (ret != 0) { | ||
340 | PDEBUG(D_STREAM, "usb_bulk_msg failed (%d)", ret); | ||
341 | ret = -EIO; | ||
342 | goto error; | ||
343 | } | ||
344 | |||
345 | /* Request a frame, but don't read it */ | ||
346 | memset(gspca_dev->usb_buf, 0, 12); | ||
347 | gspca_dev->usb_buf[0] = 0xd3; | ||
348 | gspca_dev->usb_buf[7] = 0x01; | ||
349 | |||
350 | ret = usb_control_msg(gspca_dev->dev, | ||
351 | usb_sndctrlpipe(gspca_dev->dev, 0), | ||
352 | USB_REQ_GET_STATUS, | ||
353 | USB_DIR_OUT | USB_TYPE_CLASS | | ||
354 | USB_RECIP_INTERFACE, 0, 0, gspca_dev->usb_buf, | ||
355 | 12, FPIX_TIMEOUT); | ||
356 | if (ret != 12) { | ||
357 | PDEBUG(D_STREAM, "usb_control_msg failed (%d)", ret); | ||
358 | ret = -EIO; | ||
359 | goto error; | ||
360 | } | ||
361 | |||
362 | /* Again, reset bulk in endpoint */ | ||
363 | usb_clear_halt(gspca_dev->dev, gspca_dev->cam.epaddr); | ||
364 | |||
365 | /* Allocate a control URB */ | ||
366 | dev->control_urb = usb_alloc_urb(0, GFP_KERNEL); | ||
367 | if (!dev->control_urb) { | ||
368 | PDEBUG(D_STREAM, "No free urbs available"); | ||
369 | ret = -EIO; | ||
370 | goto error; | ||
371 | } | ||
372 | |||
373 | /* Various initializations. */ | ||
374 | init_completion(&dev->can_close); | ||
375 | dev->bulk_timer.data = (unsigned long)dev->gspca_dev.urb[0]; | ||
376 | dev->gspca_dev.urb[0]->complete = urb_callback; | ||
377 | dev->streaming = 1; | ||
378 | |||
379 | /* Schedule a frame request. */ | ||
380 | dev_new_state(FPIX_REQ_FRAME); | ||
381 | schedule_delayed_work(&dev->wqe, 1); | ||
382 | |||
383 | return 0; | ||
384 | |||
385 | error: | ||
386 | /* Free the ressources */ | ||
387 | sd_stopN(gspca_dev); | ||
388 | return ret; | ||
389 | } | ||
390 | |||
391 | /* Table of supported USB devices */ | ||
392 | static const __devinitdata struct usb_device_id device_table[] = { | ||
393 | {USB_DEVICE(0x04cb, 0x0104)}, | ||
394 | {USB_DEVICE(0x04cb, 0x0109)}, | ||
395 | {USB_DEVICE(0x04cb, 0x010b)}, | ||
396 | {USB_DEVICE(0x04cb, 0x010f)}, | ||
397 | {USB_DEVICE(0x04cb, 0x0111)}, | ||
398 | {USB_DEVICE(0x04cb, 0x0113)}, | ||
399 | {USB_DEVICE(0x04cb, 0x0115)}, | ||
400 | {USB_DEVICE(0x04cb, 0x0117)}, | ||
401 | {USB_DEVICE(0x04cb, 0x0119)}, | ||
402 | {USB_DEVICE(0x04cb, 0x011b)}, | ||
403 | {USB_DEVICE(0x04cb, 0x011d)}, | ||
404 | {USB_DEVICE(0x04cb, 0x0121)}, | ||
405 | {USB_DEVICE(0x04cb, 0x0123)}, | ||
406 | {USB_DEVICE(0x04cb, 0x0125)}, | ||
407 | {USB_DEVICE(0x04cb, 0x0127)}, | ||
408 | {USB_DEVICE(0x04cb, 0x0129)}, | ||
409 | {USB_DEVICE(0x04cb, 0x012b)}, | ||
410 | {USB_DEVICE(0x04cb, 0x012d)}, | ||
411 | {USB_DEVICE(0x04cb, 0x012f)}, | ||
412 | {USB_DEVICE(0x04cb, 0x0131)}, | ||
413 | {USB_DEVICE(0x04cb, 0x013b)}, | ||
414 | {USB_DEVICE(0x04cb, 0x013d)}, | ||
415 | {USB_DEVICE(0x04cb, 0x013f)}, | ||
416 | {} | ||
417 | }; | ||
418 | |||
419 | MODULE_DEVICE_TABLE(usb, device_table); | ||
420 | |||
421 | /* sub-driver description */ | ||
422 | static const struct sd_desc sd_desc = { | ||
423 | .name = MODULE_NAME, | ||
424 | .config = sd_config, | ||
425 | .init = sd_init, | ||
426 | .start = sd_start, | ||
427 | .stopN = sd_stopN, | ||
428 | }; | ||
429 | |||
430 | /* -- device connect -- */ | ||
431 | static int sd_probe(struct usb_interface *intf, | ||
432 | const struct usb_device_id *id) | ||
433 | { | ||
434 | return gspca_dev_probe(intf, id, | ||
435 | &sd_desc, | ||
436 | sizeof(struct usb_fpix), | ||
437 | THIS_MODULE); | ||
438 | } | ||
439 | |||
440 | static struct usb_driver sd_driver = { | ||
441 | .name = MODULE_NAME, | ||
442 | .id_table = device_table, | ||
443 | .probe = sd_probe, | ||
444 | .disconnect = gspca_disconnect, | ||
445 | #ifdef CONFIG_PM | ||
446 | .suspend = gspca_suspend, | ||
447 | .resume = gspca_resume, | ||
448 | #endif | ||
449 | }; | ||
450 | |||
451 | /* -- module insert / remove -- */ | ||
452 | static int __init sd_mod_init(void) | ||
453 | { | ||
454 | if (usb_register(&sd_driver) < 0) | ||
455 | return -1; | ||
456 | PDEBUG(D_PROBE, "registered"); | ||
457 | return 0; | ||
458 | } | ||
459 | static void __exit sd_mod_exit(void) | ||
460 | { | ||
461 | usb_deregister(&sd_driver); | ||
462 | PDEBUG(D_PROBE, "deregistered"); | ||
463 | } | ||
464 | |||
465 | module_init(sd_mod_init); | ||
466 | module_exit(sd_mod_exit); | ||
diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index ac95c55887df..c21af312ee7c 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <linux/string.h> | 29 | #include <linux/string.h> |
30 | #include <linux/pagemap.h> | 30 | #include <linux/pagemap.h> |
31 | #include <linux/io.h> | 31 | #include <linux/io.h> |
32 | #include <linux/kref.h> | ||
32 | #include <asm/page.h> | 33 | #include <asm/page.h> |
33 | #include <linux/uaccess.h> | 34 | #include <linux/uaccess.h> |
34 | #include <linux/jiffies.h> | 35 | #include <linux/jiffies.h> |
@@ -43,7 +44,7 @@ MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>"); | |||
43 | MODULE_DESCRIPTION("GSPCA USB Camera Driver"); | 44 | MODULE_DESCRIPTION("GSPCA USB Camera Driver"); |
44 | MODULE_LICENSE("GPL"); | 45 | MODULE_LICENSE("GPL"); |
45 | 46 | ||
46 | #define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 2, 0) | 47 | #define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 3, 0) |
47 | 48 | ||
48 | static int video_nr = -1; | 49 | static int video_nr = -1; |
49 | 50 | ||
@@ -102,6 +103,22 @@ static struct vm_operations_struct gspca_vm_ops = { | |||
102 | .close = gspca_vm_close, | 103 | .close = gspca_vm_close, |
103 | }; | 104 | }; |
104 | 105 | ||
106 | /* get the current input frame buffer */ | ||
107 | struct gspca_frame *gspca_get_i_frame(struct gspca_dev *gspca_dev) | ||
108 | { | ||
109 | struct gspca_frame *frame; | ||
110 | int i; | ||
111 | |||
112 | i = gspca_dev->fr_i; | ||
113 | i = gspca_dev->fr_queue[i]; | ||
114 | frame = &gspca_dev->frame[i]; | ||
115 | if ((frame->v4l2_buf.flags & BUF_ALL_FLAGS) | ||
116 | != V4L2_BUF_FLAG_QUEUED) | ||
117 | return NULL; | ||
118 | return frame; | ||
119 | } | ||
120 | EXPORT_SYMBOL(gspca_get_i_frame); | ||
121 | |||
105 | /* | 122 | /* |
106 | * fill a video frame from an URB and resubmit | 123 | * fill a video frame from an URB and resubmit |
107 | */ | 124 | */ |
@@ -110,7 +127,7 @@ static void fill_frame(struct gspca_dev *gspca_dev, | |||
110 | { | 127 | { |
111 | struct gspca_frame *frame; | 128 | struct gspca_frame *frame; |
112 | __u8 *data; /* address of data in the iso message */ | 129 | __u8 *data; /* address of data in the iso message */ |
113 | int i, j, len, st; | 130 | int i, len, st; |
114 | cam_pkt_op pkt_scan; | 131 | cam_pkt_op pkt_scan; |
115 | 132 | ||
116 | if (urb->status != 0) { | 133 | if (urb->status != 0) { |
@@ -124,11 +141,8 @@ static void fill_frame(struct gspca_dev *gspca_dev, | |||
124 | for (i = 0; i < urb->number_of_packets; i++) { | 141 | for (i = 0; i < urb->number_of_packets; i++) { |
125 | 142 | ||
126 | /* check the availability of the frame buffer */ | 143 | /* check the availability of the frame buffer */ |
127 | j = gspca_dev->fr_i; | 144 | frame = gspca_get_i_frame(gspca_dev); |
128 | j = gspca_dev->fr_queue[j]; | 145 | if (!frame) { |
129 | frame = &gspca_dev->frame[j]; | ||
130 | if ((frame->v4l2_buf.flags & BUF_ALL_FLAGS) | ||
131 | != V4L2_BUF_FLAG_QUEUED) { | ||
132 | gspca_dev->last_packet_type = DISCARD_PACKET; | 146 | gspca_dev->last_packet_type = DISCARD_PACKET; |
133 | break; | 147 | break; |
134 | } | 148 | } |
@@ -178,6 +192,39 @@ static void isoc_irq(struct urb *urb | |||
178 | } | 192 | } |
179 | 193 | ||
180 | /* | 194 | /* |
195 | * bulk message interrupt from the USB device | ||
196 | */ | ||
197 | static void bulk_irq(struct urb *urb | ||
198 | ) | ||
199 | { | ||
200 | struct gspca_dev *gspca_dev = (struct gspca_dev *) urb->context; | ||
201 | struct gspca_frame *frame; | ||
202 | |||
203 | PDEBUG(D_PACK, "bulk irq"); | ||
204 | if (!gspca_dev->streaming) | ||
205 | return; | ||
206 | if (urb->status != 0 && urb->status != -ECONNRESET) { | ||
207 | #ifdef CONFIG_PM | ||
208 | if (!gspca_dev->frozen) | ||
209 | #endif | ||
210 | PDEBUG(D_ERR|D_PACK, "urb status: %d", urb->status); | ||
211 | return; /* disconnection ? */ | ||
212 | } | ||
213 | |||
214 | /* check the availability of the frame buffer */ | ||
215 | frame = gspca_get_i_frame(gspca_dev); | ||
216 | if (!frame) { | ||
217 | gspca_dev->last_packet_type = DISCARD_PACKET; | ||
218 | } else { | ||
219 | PDEBUG(D_PACK, "packet l:%d", urb->actual_length); | ||
220 | gspca_dev->sd_desc->pkt_scan(gspca_dev, | ||
221 | frame, | ||
222 | urb->transfer_buffer, | ||
223 | urb->actual_length); | ||
224 | } | ||
225 | } | ||
226 | |||
227 | /* | ||
181 | * add data to the current frame | 228 | * add data to the current frame |
182 | * | 229 | * |
183 | * This function is called by the subdrivers at interrupt level. | 230 | * This function is called by the subdrivers at interrupt level. |
@@ -190,7 +237,7 @@ static void isoc_irq(struct urb *urb | |||
190 | * On LAST_PACKET, a new frame is returned. | 237 | * On LAST_PACKET, a new frame is returned. |
191 | */ | 238 | */ |
192 | struct gspca_frame *gspca_frame_add(struct gspca_dev *gspca_dev, | 239 | struct gspca_frame *gspca_frame_add(struct gspca_dev *gspca_dev, |
193 | int packet_type, | 240 | enum gspca_packet_type packet_type, |
194 | struct gspca_frame *frame, | 241 | struct gspca_frame *frame, |
195 | const __u8 *data, | 242 | const __u8 *data, |
196 | int len) | 243 | int len) |
@@ -232,7 +279,7 @@ struct gspca_frame *gspca_frame_add(struct gspca_dev *gspca_dev, | |||
232 | } | 279 | } |
233 | gspca_dev->last_packet_type = packet_type; | 280 | gspca_dev->last_packet_type = packet_type; |
234 | 281 | ||
235 | /* if last packet, wake the application and advance in the queue */ | 282 | /* if last packet, wake up the application and advance in the queue */ |
236 | if (packet_type == LAST_PACKET) { | 283 | if (packet_type == LAST_PACKET) { |
237 | frame->v4l2_buf.bytesused = frame->data_end - frame->data; | 284 | frame->v4l2_buf.bytesused = frame->data_end - frame->data; |
238 | frame->v4l2_buf.flags &= ~V4L2_BUF_FLAG_QUEUED; | 285 | frame->v4l2_buf.flags &= ~V4L2_BUF_FLAG_QUEUED; |
@@ -270,7 +317,6 @@ static void *rvmalloc(unsigned long size) | |||
270 | void *mem; | 317 | void *mem; |
271 | unsigned long adr; | 318 | unsigned long adr; |
272 | 319 | ||
273 | /* size = PAGE_ALIGN(size); (already done) */ | ||
274 | mem = vmalloc_32(size); | 320 | mem = vmalloc_32(size); |
275 | if (mem != NULL) { | 321 | if (mem != NULL) { |
276 | adr = (unsigned long) mem; | 322 | adr = (unsigned long) mem; |
@@ -374,10 +420,11 @@ static void destroy_urbs(struct gspca_dev *gspca_dev) | |||
374 | } | 420 | } |
375 | 421 | ||
376 | /* | 422 | /* |
377 | * search an input isochronous endpoint in an alternate setting | 423 | * look for an input transfer endpoint in an alternate setting |
378 | */ | 424 | */ |
379 | static struct usb_host_endpoint *alt_isoc(struct usb_host_interface *alt, | 425 | static struct usb_host_endpoint *alt_xfer(struct usb_host_interface *alt, |
380 | __u8 epaddr) | 426 | __u8 epaddr, |
427 | __u8 xfer) | ||
381 | { | 428 | { |
382 | struct usb_host_endpoint *ep; | 429 | struct usb_host_endpoint *ep; |
383 | int i, attr; | 430 | int i, attr; |
@@ -388,7 +435,7 @@ static struct usb_host_endpoint *alt_isoc(struct usb_host_interface *alt, | |||
388 | if (ep->desc.bEndpointAddress == epaddr) { | 435 | if (ep->desc.bEndpointAddress == epaddr) { |
389 | attr = ep->desc.bmAttributes | 436 | attr = ep->desc.bmAttributes |
390 | & USB_ENDPOINT_XFERTYPE_MASK; | 437 | & USB_ENDPOINT_XFERTYPE_MASK; |
391 | if (attr == USB_ENDPOINT_XFER_ISOC) | 438 | if (attr == xfer) |
392 | return ep; | 439 | return ep; |
393 | break; | 440 | break; |
394 | } | 441 | } |
@@ -397,14 +444,14 @@ static struct usb_host_endpoint *alt_isoc(struct usb_host_interface *alt, | |||
397 | } | 444 | } |
398 | 445 | ||
399 | /* | 446 | /* |
400 | * search an input isochronous endpoint | 447 | * look for an input (isoc or bulk) endpoint |
401 | * | 448 | * |
402 | * The endpoint is defined by the subdriver. | 449 | * The endpoint is defined by the subdriver. |
403 | * Use only the first isoc (some Zoran - 0x0572:0x0001 - have two such ep). | 450 | * Use only the first isoc (some Zoran - 0x0572:0x0001 - have two such ep). |
404 | * This routine may be called many times when the bandwidth is too small | 451 | * This routine may be called many times when the bandwidth is too small |
405 | * (the bandwidth is checked on urb submit). | 452 | * (the bandwidth is checked on urb submit). |
406 | */ | 453 | */ |
407 | static struct usb_host_endpoint *get_isoc_ep(struct gspca_dev *gspca_dev) | 454 | static struct usb_host_endpoint *get_ep(struct gspca_dev *gspca_dev) |
408 | { | 455 | { |
409 | struct usb_interface *intf; | 456 | struct usb_interface *intf; |
410 | struct usb_host_endpoint *ep; | 457 | struct usb_host_endpoint *ep; |
@@ -413,28 +460,41 @@ static struct usb_host_endpoint *get_isoc_ep(struct gspca_dev *gspca_dev) | |||
413 | intf = usb_ifnum_to_if(gspca_dev->dev, gspca_dev->iface); | 460 | intf = usb_ifnum_to_if(gspca_dev->dev, gspca_dev->iface); |
414 | ep = NULL; | 461 | ep = NULL; |
415 | i = gspca_dev->alt; /* previous alt setting */ | 462 | i = gspca_dev->alt; /* previous alt setting */ |
463 | |||
464 | /* try isoc */ | ||
416 | while (--i > 0) { /* alt 0 is unusable */ | 465 | while (--i > 0) { /* alt 0 is unusable */ |
417 | ep = alt_isoc(&intf->altsetting[i], gspca_dev->cam.epaddr); | 466 | ep = alt_xfer(&intf->altsetting[i], |
467 | gspca_dev->cam.epaddr, | ||
468 | USB_ENDPOINT_XFER_ISOC); | ||
418 | if (ep) | 469 | if (ep) |
419 | break; | 470 | break; |
420 | } | 471 | } |
472 | |||
473 | /* if no isoc, try bulk */ | ||
421 | if (ep == NULL) { | 474 | if (ep == NULL) { |
422 | err("no ISOC endpoint found"); | 475 | ep = alt_xfer(&intf->altsetting[0], |
423 | return NULL; | 476 | gspca_dev->cam.epaddr, |
477 | USB_ENDPOINT_XFER_BULK); | ||
478 | if (ep == NULL) { | ||
479 | err("no transfer endpoint found"); | ||
480 | return NULL; | ||
481 | } | ||
424 | } | 482 | } |
425 | PDEBUG(D_STREAM, "use ISOC alt %d ep 0x%02x", | 483 | PDEBUG(D_STREAM, "use alt %d ep 0x%02x", |
426 | i, ep->desc.bEndpointAddress); | 484 | i, ep->desc.bEndpointAddress); |
427 | ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, i); | 485 | if (i > 0) { |
428 | if (ret < 0) { | 486 | ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, i); |
429 | err("set interface err %d", ret); | 487 | if (ret < 0) { |
430 | return NULL; | 488 | err("set interface err %d", ret); |
489 | return NULL; | ||
490 | } | ||
431 | } | 491 | } |
432 | gspca_dev->alt = i; /* memorize the current alt setting */ | 492 | gspca_dev->alt = i; /* memorize the current alt setting */ |
433 | return ep; | 493 | return ep; |
434 | } | 494 | } |
435 | 495 | ||
436 | /* | 496 | /* |
437 | * create the isochronous URBs | 497 | * create the URBs for image transfer |
438 | */ | 498 | */ |
439 | static int create_urbs(struct gspca_dev *gspca_dev, | 499 | static int create_urbs(struct gspca_dev *gspca_dev, |
440 | struct usb_host_endpoint *ep) | 500 | struct usb_host_endpoint *ep) |
@@ -445,15 +505,27 @@ static int create_urbs(struct gspca_dev *gspca_dev, | |||
445 | /* calculate the packet size and the number of packets */ | 505 | /* calculate the packet size and the number of packets */ |
446 | psize = le16_to_cpu(ep->desc.wMaxPacketSize); | 506 | psize = le16_to_cpu(ep->desc.wMaxPacketSize); |
447 | 507 | ||
448 | /* See paragraph 5.9 / table 5-11 of the usb 2.0 spec. */ | 508 | if (gspca_dev->alt != 0) { /* isoc */ |
449 | psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3)); | 509 | |
450 | npkt = ISO_MAX_SIZE / psize; | 510 | /* See paragraph 5.9 / table 5-11 of the usb 2.0 spec. */ |
451 | if (npkt > ISO_MAX_PKT) | 511 | psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3)); |
452 | npkt = ISO_MAX_PKT; | 512 | npkt = ISO_MAX_SIZE / psize; |
453 | bsize = psize * npkt; | 513 | if (npkt > ISO_MAX_PKT) |
454 | PDEBUG(D_STREAM, | 514 | npkt = ISO_MAX_PKT; |
455 | "isoc %d pkts size %d (bsize:%d)", npkt, psize, bsize); | 515 | bsize = psize * npkt; |
456 | nurbs = DEF_NURBS; | 516 | PDEBUG(D_STREAM, |
517 | "isoc %d pkts size %d = bsize:%d", | ||
518 | npkt, psize, bsize); | ||
519 | nurbs = DEF_NURBS; | ||
520 | } else { /* bulk */ | ||
521 | npkt = 0; | ||
522 | bsize = gspca_dev->cam. bulk_size; | ||
523 | if (bsize == 0) | ||
524 | bsize = psize; | ||
525 | PDEBUG(D_STREAM, "bulk bsize:%d", bsize); | ||
526 | nurbs = 1; | ||
527 | } | ||
528 | |||
457 | gspca_dev->nurbs = nurbs; | 529 | gspca_dev->nurbs = nurbs; |
458 | for (n = 0; n < nurbs; n++) { | 530 | for (n = 0; n < nurbs; n++) { |
459 | urb = usb_alloc_urb(npkt, GFP_KERNEL); | 531 | urb = usb_alloc_urb(npkt, GFP_KERNEL); |
@@ -476,17 +548,24 @@ static int create_urbs(struct gspca_dev *gspca_dev, | |||
476 | gspca_dev->urb[n] = urb; | 548 | gspca_dev->urb[n] = urb; |
477 | urb->dev = gspca_dev->dev; | 549 | urb->dev = gspca_dev->dev; |
478 | urb->context = gspca_dev; | 550 | urb->context = gspca_dev; |
479 | urb->pipe = usb_rcvisocpipe(gspca_dev->dev, | ||
480 | ep->desc.bEndpointAddress); | ||
481 | urb->transfer_flags = URB_ISO_ASAP | ||
482 | | URB_NO_TRANSFER_DMA_MAP; | ||
483 | urb->interval = ep->desc.bInterval; | ||
484 | urb->complete = isoc_irq; | ||
485 | urb->number_of_packets = npkt; | ||
486 | urb->transfer_buffer_length = bsize; | 551 | urb->transfer_buffer_length = bsize; |
487 | for (i = 0; i < npkt; i++) { | 552 | if (npkt != 0) { /* ISOC */ |
488 | urb->iso_frame_desc[i].length = psize; | 553 | urb->pipe = usb_rcvisocpipe(gspca_dev->dev, |
489 | urb->iso_frame_desc[i].offset = psize * i; | 554 | ep->desc.bEndpointAddress); |
555 | urb->transfer_flags = URB_ISO_ASAP | ||
556 | | URB_NO_TRANSFER_DMA_MAP; | ||
557 | urb->interval = ep->desc.bInterval; | ||
558 | urb->complete = isoc_irq; | ||
559 | urb->number_of_packets = npkt; | ||
560 | for (i = 0; i < npkt; i++) { | ||
561 | urb->iso_frame_desc[i].length = psize; | ||
562 | urb->iso_frame_desc[i].offset = psize * i; | ||
563 | } | ||
564 | } else { /* bulk */ | ||
565 | urb->pipe = usb_rcvbulkpipe(gspca_dev->dev, | ||
566 | ep->desc.bEndpointAddress), | ||
567 | urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP; | ||
568 | urb->complete = bulk_irq; | ||
490 | } | 569 | } |
491 | } | 570 | } |
492 | return 0; | 571 | return 0; |
@@ -508,7 +587,7 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev) | |||
508 | gspca_dev->alt = gspca_dev->nbalt; | 587 | gspca_dev->alt = gspca_dev->nbalt; |
509 | for (;;) { | 588 | for (;;) { |
510 | PDEBUG(D_STREAM, "init transfer alt %d", gspca_dev->alt); | 589 | PDEBUG(D_STREAM, "init transfer alt %d", gspca_dev->alt); |
511 | ep = get_isoc_ep(gspca_dev); | 590 | ep = get_ep(gspca_dev); |
512 | if (ep == NULL) { | 591 | if (ep == NULL) { |
513 | ret = -EIO; | 592 | ret = -EIO; |
514 | goto out; | 593 | goto out; |
@@ -518,10 +597,18 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev) | |||
518 | goto out; | 597 | goto out; |
519 | 598 | ||
520 | /* start the cam */ | 599 | /* start the cam */ |
521 | gspca_dev->sd_desc->start(gspca_dev); | 600 | ret = gspca_dev->sd_desc->start(gspca_dev); |
601 | if (ret < 0) { | ||
602 | destroy_urbs(gspca_dev); | ||
603 | goto out; | ||
604 | } | ||
522 | gspca_dev->streaming = 1; | 605 | gspca_dev->streaming = 1; |
523 | atomic_set(&gspca_dev->nevent, 0); | 606 | atomic_set(&gspca_dev->nevent, 0); |
524 | 607 | ||
608 | /* bulk transfers are started by the subdriver */ | ||
609 | if (gspca_dev->alt == 0) | ||
610 | break; | ||
611 | |||
525 | /* submit the URBs */ | 612 | /* submit the URBs */ |
526 | for (n = 0; n < gspca_dev->nurbs; n++) { | 613 | for (n = 0; n < gspca_dev->nurbs; n++) { |
527 | ret = usb_submit_urb(gspca_dev->urb[n], GFP_KERNEL); | 614 | ret = usb_submit_urb(gspca_dev->urb[n], GFP_KERNEL); |
@@ -553,7 +640,7 @@ static int gspca_set_alt0(struct gspca_dev *gspca_dev) | |||
553 | return ret; | 640 | return ret; |
554 | } | 641 | } |
555 | 642 | ||
556 | /* Note both the queue and the usb lock should be hold when calling this */ | 643 | /* Note: both the queue and the usb locks should be held when calling this */ |
557 | static void gspca_stream_off(struct gspca_dev *gspca_dev) | 644 | static void gspca_stream_off(struct gspca_dev *gspca_dev) |
558 | { | 645 | { |
559 | gspca_dev->streaming = 0; | 646 | gspca_dev->streaming = 0; |
@@ -759,6 +846,16 @@ out: | |||
759 | return ret; | 846 | return ret; |
760 | } | 847 | } |
761 | 848 | ||
849 | static void gspca_delete(struct kref *kref) | ||
850 | { | ||
851 | struct gspca_dev *gspca_dev = container_of(kref, struct gspca_dev, kref); | ||
852 | |||
853 | PDEBUG(D_STREAM, "device deleted"); | ||
854 | |||
855 | kfree(gspca_dev->usb_buf); | ||
856 | kfree(gspca_dev); | ||
857 | } | ||
858 | |||
762 | static int dev_open(struct inode *inode, struct file *file) | 859 | static int dev_open(struct inode *inode, struct file *file) |
763 | { | 860 | { |
764 | struct gspca_dev *gspca_dev; | 861 | struct gspca_dev *gspca_dev; |
@@ -778,13 +875,19 @@ static int dev_open(struct inode *inode, struct file *file) | |||
778 | goto out; | 875 | goto out; |
779 | } | 876 | } |
780 | gspca_dev->users++; | 877 | gspca_dev->users++; |
878 | |||
879 | /* one more user */ | ||
880 | kref_get(&gspca_dev->kref); | ||
881 | |||
781 | file->private_data = gspca_dev; | 882 | file->private_data = gspca_dev; |
782 | #ifdef GSPCA_DEBUG | 883 | #ifdef GSPCA_DEBUG |
783 | /* activate the v4l2 debug */ | 884 | /* activate the v4l2 debug */ |
784 | if (gspca_debug & D_V4L2) | 885 | if (gspca_debug & D_V4L2) |
785 | gspca_dev->vdev.debug |= 3; | 886 | gspca_dev->vdev.debug |= V4L2_DEBUG_IOCTL |
887 | | V4L2_DEBUG_IOCTL_ARG; | ||
786 | else | 888 | else |
787 | gspca_dev->vdev.debug &= ~3; | 889 | gspca_dev->vdev.debug &= ~(V4L2_DEBUG_IOCTL |
890 | | V4L2_DEBUG_IOCTL_ARG); | ||
788 | #endif | 891 | #endif |
789 | ret = 0; | 892 | ret = 0; |
790 | out: | 893 | out: |
@@ -818,7 +921,11 @@ static int dev_close(struct inode *inode, struct file *file) | |||
818 | } | 921 | } |
819 | file->private_data = NULL; | 922 | file->private_data = NULL; |
820 | mutex_unlock(&gspca_dev->queue_lock); | 923 | mutex_unlock(&gspca_dev->queue_lock); |
924 | |||
821 | PDEBUG(D_STREAM, "close done"); | 925 | PDEBUG(D_STREAM, "close done"); |
926 | |||
927 | kref_put(&gspca_dev->kref, gspca_delete); | ||
928 | |||
822 | return 0; | 929 | return 0; |
823 | } | 930 | } |
824 | 931 | ||
@@ -829,7 +936,6 @@ static int vidioc_querycap(struct file *file, void *priv, | |||
829 | 936 | ||
830 | memset(cap, 0, sizeof *cap); | 937 | memset(cap, 0, sizeof *cap); |
831 | strncpy(cap->driver, gspca_dev->sd_desc->name, sizeof cap->driver); | 938 | strncpy(cap->driver, gspca_dev->sd_desc->name, sizeof cap->driver); |
832 | /* strncpy(cap->card, gspca_dev->cam.dev_name, sizeof cap->card); */ | ||
833 | if (gspca_dev->dev->product != NULL) { | 939 | if (gspca_dev->dev->product != NULL) { |
834 | strncpy(cap->card, gspca_dev->dev->product, | 940 | strncpy(cap->card, gspca_dev->dev->product, |
835 | sizeof cap->card); | 941 | sizeof cap->card); |
@@ -1463,7 +1569,6 @@ static int vidioc_qbuf(struct file *file, void *priv, | |||
1463 | } | 1569 | } |
1464 | 1570 | ||
1465 | frame->v4l2_buf.flags |= V4L2_BUF_FLAG_QUEUED; | 1571 | frame->v4l2_buf.flags |= V4L2_BUF_FLAG_QUEUED; |
1466 | /* frame->v4l2_buf.flags &= ~V4L2_BUF_FLAG_DONE; */ | ||
1467 | 1572 | ||
1468 | if (frame->v4l2_buf.memory == V4L2_MEMORY_USERPTR) { | 1573 | if (frame->v4l2_buf.memory == V4L2_MEMORY_USERPTR) { |
1469 | frame->v4l2_buf.m.userptr = v4l2_buf->m.userptr; | 1574 | frame->v4l2_buf.m.userptr = v4l2_buf->m.userptr; |
@@ -1610,7 +1715,7 @@ static ssize_t dev_read(struct file *file, char __user *data, | |||
1610 | } | 1715 | } |
1611 | 1716 | ||
1612 | /* if the process slept for more than 1 second, | 1717 | /* if the process slept for more than 1 second, |
1613 | * get anewer frame */ | 1718 | * get a newer frame */ |
1614 | frame = &gspca_dev->frame[v4l2_buf.index]; | 1719 | frame = &gspca_dev->frame[v4l2_buf.index]; |
1615 | if (--n < 0) | 1720 | if (--n < 0) |
1616 | break; /* avoid infinite loop */ | 1721 | break; /* avoid infinite loop */ |
@@ -1728,21 +1833,21 @@ int gspca_dev_probe(struct usb_interface *intf, | |||
1728 | if (dev_size < sizeof *gspca_dev) | 1833 | if (dev_size < sizeof *gspca_dev) |
1729 | dev_size = sizeof *gspca_dev; | 1834 | dev_size = sizeof *gspca_dev; |
1730 | gspca_dev = kzalloc(dev_size, GFP_KERNEL); | 1835 | gspca_dev = kzalloc(dev_size, GFP_KERNEL); |
1731 | if (gspca_dev == NULL) { | 1836 | if (!gspca_dev) { |
1732 | err("couldn't kzalloc gspca struct"); | 1837 | err("couldn't kzalloc gspca struct"); |
1733 | return -EIO; | 1838 | return -ENOMEM; |
1734 | } | 1839 | } |
1840 | kref_init(&gspca_dev->kref); | ||
1735 | gspca_dev->usb_buf = kmalloc(USB_BUF_SZ, GFP_KERNEL); | 1841 | gspca_dev->usb_buf = kmalloc(USB_BUF_SZ, GFP_KERNEL); |
1736 | if (!gspca_dev->usb_buf) { | 1842 | if (!gspca_dev->usb_buf) { |
1737 | err("out of memory"); | 1843 | err("out of memory"); |
1738 | ret = -EIO; | 1844 | ret = -ENOMEM; |
1739 | goto out; | 1845 | goto out; |
1740 | } | 1846 | } |
1741 | gspca_dev->dev = dev; | 1847 | gspca_dev->dev = dev; |
1742 | gspca_dev->iface = interface->bInterfaceNumber; | 1848 | gspca_dev->iface = interface->bInterfaceNumber; |
1743 | gspca_dev->nbalt = intf->num_altsetting; | 1849 | gspca_dev->nbalt = intf->num_altsetting; |
1744 | gspca_dev->sd_desc = sd_desc; | 1850 | gspca_dev->sd_desc = sd_desc; |
1745 | /* gspca_dev->users = 0; (done by kzalloc) */ | ||
1746 | gspca_dev->nbufread = 2; | 1851 | gspca_dev->nbufread = 2; |
1747 | 1852 | ||
1748 | /* configure the subdriver and initialize the USB device */ | 1853 | /* configure the subdriver and initialize the USB device */ |
@@ -1781,8 +1886,7 @@ int gspca_dev_probe(struct usb_interface *intf, | |||
1781 | PDEBUG(D_PROBE, "probe ok"); | 1886 | PDEBUG(D_PROBE, "probe ok"); |
1782 | return 0; | 1887 | return 0; |
1783 | out: | 1888 | out: |
1784 | kfree(gspca_dev->usb_buf); | 1889 | kref_put(&gspca_dev->kref, gspca_delete); |
1785 | kfree(gspca_dev); | ||
1786 | return ret; | 1890 | return ret; |
1787 | } | 1891 | } |
1788 | EXPORT_SYMBOL(gspca_dev_probe); | 1892 | EXPORT_SYMBOL(gspca_dev_probe); |
@@ -1797,25 +1901,16 @@ void gspca_disconnect(struct usb_interface *intf) | |||
1797 | { | 1901 | { |
1798 | struct gspca_dev *gspca_dev = usb_get_intfdata(intf); | 1902 | struct gspca_dev *gspca_dev = usb_get_intfdata(intf); |
1799 | 1903 | ||
1800 | if (!gspca_dev) | 1904 | usb_set_intfdata(intf, NULL); |
1801 | return; | 1905 | |
1802 | gspca_dev->present = 0; | ||
1803 | mutex_lock(&gspca_dev->queue_lock); | ||
1804 | mutex_lock(&gspca_dev->usb_lock); | ||
1805 | gspca_dev->streaming = 0; | ||
1806 | destroy_urbs(gspca_dev); | ||
1807 | mutex_unlock(&gspca_dev->usb_lock); | ||
1808 | mutex_unlock(&gspca_dev->queue_lock); | ||
1809 | while (gspca_dev->users != 0) { /* wait until fully closed */ | ||
1810 | atomic_inc(&gspca_dev->nevent); | ||
1811 | wake_up_interruptible(&gspca_dev->wq); /* wake processes */ | ||
1812 | schedule(); | ||
1813 | } | ||
1814 | /* We don't want people trying to open up the device */ | 1906 | /* We don't want people trying to open up the device */ |
1815 | video_unregister_device(&gspca_dev->vdev); | 1907 | video_unregister_device(&gspca_dev->vdev); |
1816 | /* Free the memory */ | 1908 | |
1817 | kfree(gspca_dev->usb_buf); | 1909 | gspca_dev->present = 0; |
1818 | kfree(gspca_dev); | 1910 | gspca_dev->streaming = 0; |
1911 | |||
1912 | kref_put(&gspca_dev->kref, gspca_delete); | ||
1913 | |||
1819 | PDEBUG(D_PROBE, "disconnect complete"); | 1914 | PDEBUG(D_PROBE, "disconnect complete"); |
1820 | } | 1915 | } |
1821 | EXPORT_SYMBOL(gspca_disconnect); | 1916 | EXPORT_SYMBOL(gspca_disconnect); |
diff --git a/drivers/media/video/gspca/gspca.h b/drivers/media/video/gspca/gspca.h index c17625cff9ba..4779dd0b06da 100644 --- a/drivers/media/video/gspca/gspca.h +++ b/drivers/media/video/gspca/gspca.h | |||
@@ -49,13 +49,14 @@ extern int gspca_debug; | |||
49 | } while (0) | 49 | } while (0) |
50 | 50 | ||
51 | #define GSPCA_MAX_FRAMES 16 /* maximum number of video frame buffers */ | 51 | #define GSPCA_MAX_FRAMES 16 /* maximum number of video frame buffers */ |
52 | /* ISOC transfers */ | 52 | /* image transfers */ |
53 | #define MAX_NURBS 16 /* max number of URBs */ | 53 | #define MAX_NURBS 4 /* max number of URBs */ |
54 | #define ISO_MAX_PKT 32 /* max number of packets in an ISOC transfer */ | 54 | #define ISO_MAX_PKT 32 /* max number of packets in an ISOC transfer */ |
55 | #define ISO_MAX_SIZE 0x8000 /* max size of one URB buffer (32 Kb) */ | 55 | #define ISO_MAX_SIZE 0x8000 /* max size of one URB buffer (32 Kb) */ |
56 | 56 | ||
57 | /* device information - set at probe time */ | 57 | /* device information - set at probe time */ |
58 | struct cam { | 58 | struct cam { |
59 | int bulk_size; /* buffer size when image transfer by bulk */ | ||
59 | struct v4l2_pix_format *cam_mode; /* size nmodes */ | 60 | struct v4l2_pix_format *cam_mode; /* size nmodes */ |
60 | char nmodes; | 61 | char nmodes; |
61 | __u8 epaddr; | 62 | __u8 epaddr; |
@@ -93,7 +94,7 @@ struct sd_desc { | |||
93 | /* mandatory operations */ | 94 | /* mandatory operations */ |
94 | cam_cf_op config; /* called on probe */ | 95 | cam_cf_op config; /* called on probe */ |
95 | cam_op init; /* called on probe and resume */ | 96 | cam_op init; /* called on probe and resume */ |
96 | cam_v_op start; /* called on stream on */ | 97 | cam_op start; /* called on stream on */ |
97 | cam_pkt_op pkt_scan; | 98 | cam_pkt_op pkt_scan; |
98 | /* optional operations */ | 99 | /* optional operations */ |
99 | cam_v_op stopN; /* called on stream off - main alt */ | 100 | cam_v_op stopN; /* called on stream off - main alt */ |
@@ -105,10 +106,12 @@ struct sd_desc { | |||
105 | }; | 106 | }; |
106 | 107 | ||
107 | /* packet types when moving from iso buf to frame buf */ | 108 | /* packet types when moving from iso buf to frame buf */ |
108 | #define DISCARD_PACKET 0 | 109 | enum gspca_packet_type { |
109 | #define FIRST_PACKET 1 | 110 | DISCARD_PACKET, |
110 | #define INTER_PACKET 2 | 111 | FIRST_PACKET, |
111 | #define LAST_PACKET 3 | 112 | INTER_PACKET, |
113 | LAST_PACKET | ||
114 | }; | ||
112 | 115 | ||
113 | struct gspca_frame { | 116 | struct gspca_frame { |
114 | __u8 *data; /* frame buffer */ | 117 | __u8 *data; /* frame buffer */ |
@@ -121,6 +124,7 @@ struct gspca_dev { | |||
121 | struct video_device vdev; /* !! must be the first item */ | 124 | struct video_device vdev; /* !! must be the first item */ |
122 | struct file_operations fops; | 125 | struct file_operations fops; |
123 | struct usb_device *dev; | 126 | struct usb_device *dev; |
127 | struct kref kref; | ||
124 | struct file *capt_file; /* file doing video capture */ | 128 | struct file *capt_file; /* file doing video capture */ |
125 | 129 | ||
126 | struct cam cam; /* device information */ | 130 | struct cam cam; /* device information */ |
@@ -173,10 +177,11 @@ int gspca_dev_probe(struct usb_interface *intf, | |||
173 | struct module *module); | 177 | struct module *module); |
174 | void gspca_disconnect(struct usb_interface *intf); | 178 | void gspca_disconnect(struct usb_interface *intf); |
175 | struct gspca_frame *gspca_frame_add(struct gspca_dev *gspca_dev, | 179 | struct gspca_frame *gspca_frame_add(struct gspca_dev *gspca_dev, |
176 | int packet_type, | 180 | enum gspca_packet_type packet_type, |
177 | struct gspca_frame *frame, | 181 | struct gspca_frame *frame, |
178 | const __u8 *data, | 182 | const __u8 *data, |
179 | int len); | 183 | int len); |
184 | struct gspca_frame *gspca_get_i_frame(struct gspca_dev *gspca_dev); | ||
180 | #ifdef CONFIG_PM | 185 | #ifdef CONFIG_PM |
181 | int gspca_suspend(struct usb_interface *intf, pm_message_t message); | 186 | int gspca_suspend(struct usb_interface *intf, pm_message_t message); |
182 | int gspca_resume(struct usb_interface *intf); | 187 | int gspca_resume(struct usb_interface *intf); |
diff --git a/drivers/media/video/gspca/m5602/Kconfig b/drivers/media/video/gspca/m5602/Kconfig new file mode 100644 index 000000000000..5a69016ed75f --- /dev/null +++ b/drivers/media/video/gspca/m5602/Kconfig | |||
@@ -0,0 +1,11 @@ | |||
1 | config USB_M5602 | ||
2 | tristate "ALi USB m5602 Camera Driver" | ||
3 | depends on VIDEO_V4L2 && USB_GSPCA | ||
4 | help | ||
5 | Say Y here if you want support for cameras based on the | ||
6 | ALi m5602 connected to various image sensors. | ||
7 | |||
8 | See <file:Documentation/video4linux/m5602.txt> for more info. | ||
9 | |||
10 | To compile this driver as a module, choose M here: the | ||
11 | module will be called gspca_m5602. | ||
diff --git a/drivers/media/video/gspca/m5602/Makefile b/drivers/media/video/gspca/m5602/Makefile new file mode 100644 index 000000000000..226ab4fc9d60 --- /dev/null +++ b/drivers/media/video/gspca/m5602/Makefile | |||
@@ -0,0 +1,11 @@ | |||
1 | obj-$(CONFIG_USB_M5602) += gspca_m5602.o | ||
2 | |||
3 | gspca_m5602-objs := m5602_core.o \ | ||
4 | m5602_ov9650.o \ | ||
5 | m5602_mt9m111.o \ | ||
6 | m5602_po1030.o \ | ||
7 | m5602_s5k83a.o \ | ||
8 | m5602_s5k4aa.o | ||
9 | |||
10 | EXTRA_CFLAGS += -Idrivers/media/video/gspca | ||
11 | |||
diff --git a/drivers/media/video/gspca/m5602/m5602_bridge.h b/drivers/media/video/gspca/m5602/m5602_bridge.h new file mode 100644 index 000000000000..c786d7d3d44a --- /dev/null +++ b/drivers/media/video/gspca/m5602/m5602_bridge.h | |||
@@ -0,0 +1,170 @@ | |||
1 | /* | ||
2 | * USB Driver for ALi m5602 based webcams | ||
3 | * | ||
4 | * Copyright (C) 2008 Erik Andren | ||
5 | * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project. | ||
6 | * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br> | ||
7 | * | ||
8 | * Portions of code to USB interface and ALi driver software, | ||
9 | * Copyright (c) 2006 Willem Duinker | ||
10 | * v4l2 interface modeled after the V4L2 driver | ||
11 | * for SN9C10x PC Camera Controllers | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or | ||
14 | * modify it under the terms of the GNU General Public License as | ||
15 | * published by the Free Software Foundation, version 2. | ||
16 | * | ||
17 | */ | ||
18 | |||
19 | #ifndef M5602_BRIDGE_H_ | ||
20 | #define M5602_BRIDGE_H_ | ||
21 | |||
22 | #include "gspca.h" | ||
23 | |||
24 | #define MODULE_NAME "ALi m5602" | ||
25 | |||
26 | /*****************************************************************************/ | ||
27 | |||
28 | #undef PDEBUG | ||
29 | #undef info | ||
30 | #undef err | ||
31 | |||
32 | #define err(format, arg...) printk(KERN_ERR KBUILD_MODNAME ": " \ | ||
33 | format "\n" , ## arg) | ||
34 | #define info(format, arg...) printk(KERN_INFO KBUILD_MODNAME ": " \ | ||
35 | format "\n" , ## arg) | ||
36 | |||
37 | /* Debug parameters */ | ||
38 | #define DBG_INIT 0x1 | ||
39 | #define DBG_PROBE 0x2 | ||
40 | #define DBG_V4L2 0x4 | ||
41 | #define DBG_TRACE 0x8 | ||
42 | #define DBG_DATA 0x10 | ||
43 | #define DBG_V4L2_CID 0x20 | ||
44 | #define DBG_GSPCA 0x40 | ||
45 | |||
46 | #define PDEBUG(level, fmt, args...) \ | ||
47 | do { \ | ||
48 | if (m5602_debug & level) \ | ||
49 | info("[%s:%d] " fmt, __func__, __LINE__ , \ | ||
50 | ## args); \ | ||
51 | } while (0) | ||
52 | |||
53 | /*****************************************************************************/ | ||
54 | |||
55 | #define M5602_XB_SENSOR_TYPE 0x00 | ||
56 | #define M5602_XB_SENSOR_CTRL 0x01 | ||
57 | #define M5602_XB_LINE_OF_FRAME_H 0x02 | ||
58 | #define M5602_XB_LINE_OF_FRAME_L 0x03 | ||
59 | #define M5602_XB_PIX_OF_LINE_H 0x04 | ||
60 | #define M5602_XB_PIX_OF_LINE_L 0x05 | ||
61 | #define M5602_XB_VSYNC_PARA 0x06 | ||
62 | #define M5602_XB_HSYNC_PARA 0x07 | ||
63 | #define M5602_XB_TEST_MODE_1 0x08 | ||
64 | #define M5602_XB_TEST_MODE_2 0x09 | ||
65 | #define M5602_XB_SIG_INI 0x0a | ||
66 | #define M5602_XB_DS_PARA 0x0e | ||
67 | #define M5602_XB_TRIG_PARA 0x0f | ||
68 | #define M5602_XB_CLK_PD 0x10 | ||
69 | #define M5602_XB_MCU_CLK_CTRL 0x12 | ||
70 | #define M5602_XB_MCU_CLK_DIV 0x13 | ||
71 | #define M5602_XB_SEN_CLK_CTRL 0x14 | ||
72 | #define M5602_XB_SEN_CLK_DIV 0x15 | ||
73 | #define M5602_XB_AUD_CLK_CTRL 0x16 | ||
74 | #define M5602_XB_AUD_CLK_DIV 0x17 | ||
75 | #define M5602_XB_DEVCTR1 0x41 | ||
76 | #define M5602_XB_EPSETR0 0x42 | ||
77 | #define M5602_XB_EPAFCTR 0x47 | ||
78 | #define M5602_XB_EPBFCTR 0x49 | ||
79 | #define M5602_XB_EPEFCTR 0x4f | ||
80 | #define M5602_XB_TEST_REG 0x53 | ||
81 | #define M5602_XB_ALT2SIZE 0x54 | ||
82 | #define M5602_XB_ALT3SIZE 0x55 | ||
83 | #define M5602_XB_OBSFRAME 0x56 | ||
84 | #define M5602_XB_PWR_CTL 0x59 | ||
85 | #define M5602_XB_ADC_CTRL 0x60 | ||
86 | #define M5602_XB_ADC_DATA 0x61 | ||
87 | #define M5602_XB_MISC_CTRL 0x62 | ||
88 | #define M5602_XB_SNAPSHOT 0x63 | ||
89 | #define M5602_XB_SCRATCH_1 0x64 | ||
90 | #define M5602_XB_SCRATCH_2 0x65 | ||
91 | #define M5602_XB_SCRATCH_3 0x66 | ||
92 | #define M5602_XB_SCRATCH_4 0x67 | ||
93 | #define M5602_XB_I2C_CTRL 0x68 | ||
94 | #define M5602_XB_I2C_CLK_DIV 0x69 | ||
95 | #define M5602_XB_I2C_DEV_ADDR 0x6a | ||
96 | #define M5602_XB_I2C_REG_ADDR 0x6b | ||
97 | #define M5602_XB_I2C_DATA 0x6c | ||
98 | #define M5602_XB_I2C_STATUS 0x6d | ||
99 | #define M5602_XB_GPIO_DAT_H 0x70 | ||
100 | #define M5602_XB_GPIO_DAT_L 0x71 | ||
101 | #define M5602_XB_GPIO_DIR_H 0x72 | ||
102 | #define M5602_XB_GPIO_DIR_L 0x73 | ||
103 | #define M5602_XB_GPIO_EN_H 0x74 | ||
104 | #define M5602_XB_GPIO_EN_L 0x75 | ||
105 | #define M5602_XB_GPIO_DAT 0x76 | ||
106 | #define M5602_XB_GPIO_DIR 0x77 | ||
107 | #define M5602_XB_MISC_CTL 0x70 | ||
108 | |||
109 | #define I2C_BUSY 0x80 | ||
110 | |||
111 | /*****************************************************************************/ | ||
112 | |||
113 | /* Driver info */ | ||
114 | #define DRIVER_AUTHOR "ALi m5602 Linux Driver Project" | ||
115 | #define DRIVER_DESC "ALi m5602 webcam driver" | ||
116 | |||
117 | #define M5602_ISOC_ENDPOINT_ADDR 0x81 | ||
118 | #define M5602_INTR_ENDPOINT_ADDR 0x82 | ||
119 | |||
120 | #define M5602_MAX_FRAMES 32 | ||
121 | #define M5602_URBS 2 | ||
122 | #define M5602_ISOC_PACKETS 14 | ||
123 | |||
124 | #define M5602_URB_TIMEOUT msecs_to_jiffies(2 * M5602_ISOC_PACKETS) | ||
125 | #define M5602_URB_MSG_TIMEOUT 5000 | ||
126 | #define M5602_FRAME_TIMEOUT 2 | ||
127 | |||
128 | /*****************************************************************************/ | ||
129 | |||
130 | /* A skeleton used for sending messages to the m5602 bridge */ | ||
131 | static const unsigned char bridge_urb_skeleton[] = { | ||
132 | 0x13, 0x00, 0x81, 0x00 | ||
133 | }; | ||
134 | |||
135 | /* A skeleton used for sending messages to the sensor */ | ||
136 | static const unsigned char sensor_urb_skeleton[] = { | ||
137 | 0x23, M5602_XB_GPIO_EN_H, 0x81, 0x06, | ||
138 | 0x23, M5602_XB_MISC_CTRL, 0x81, 0x80, | ||
139 | 0x13, M5602_XB_I2C_DEV_ADDR, 0x81, 0x00, | ||
140 | 0x13, M5602_XB_I2C_REG_ADDR, 0x81, 0x00, | ||
141 | 0x13, M5602_XB_I2C_DATA, 0x81, 0x00, | ||
142 | 0x13, M5602_XB_I2C_CTRL, 0x81, 0x11 | ||
143 | }; | ||
144 | |||
145 | /* m5602 device descriptor, currently it just wraps the m5602_camera struct */ | ||
146 | struct sd { | ||
147 | struct gspca_dev gspca_dev; | ||
148 | |||
149 | /* The name of the m5602 camera */ | ||
150 | char *name; | ||
151 | |||
152 | /* A pointer to the currently connected sensor */ | ||
153 | struct m5602_sensor *sensor; | ||
154 | |||
155 | struct sd_desc *desc; | ||
156 | |||
157 | /* The current frame's id, used to detect frame boundaries */ | ||
158 | u8 frame_id; | ||
159 | |||
160 | /* The current frame count */ | ||
161 | u32 frame_count; | ||
162 | }; | ||
163 | |||
164 | int m5602_read_bridge( | ||
165 | struct sd *sd, u8 address, u8 *i2c_data); | ||
166 | |||
167 | int m5602_write_bridge( | ||
168 | struct sd *sd, u8 address, u8 i2c_data); | ||
169 | |||
170 | #endif | ||
diff --git a/drivers/media/video/gspca/m5602/m5602_core.c b/drivers/media/video/gspca/m5602/m5602_core.c new file mode 100644 index 000000000000..19d5e351ccc1 --- /dev/null +++ b/drivers/media/video/gspca/m5602/m5602_core.c | |||
@@ -0,0 +1,313 @@ | |||
1 | /* | ||
2 | * USB Driver for ALi m5602 based webcams | ||
3 | * | ||
4 | * Copyright (C) 2008 Erik Andren | ||
5 | * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project. | ||
6 | * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br> | ||
7 | * | ||
8 | * Portions of code to USB interface and ALi driver software, | ||
9 | * Copyright (c) 2006 Willem Duinker | ||
10 | * v4l2 interface modeled after the V4L2 driver | ||
11 | * for SN9C10x PC Camera Controllers | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or | ||
14 | * modify it under the terms of the GNU General Public License as | ||
15 | * published by the Free Software Foundation, version 2. | ||
16 | * | ||
17 | */ | ||
18 | |||
19 | #include "m5602_ov9650.h" | ||
20 | #include "m5602_mt9m111.h" | ||
21 | #include "m5602_po1030.h" | ||
22 | #include "m5602_s5k83a.h" | ||
23 | #include "m5602_s5k4aa.h" | ||
24 | |||
25 | /* Kernel module parameters */ | ||
26 | int force_sensor; | ||
27 | int dump_bridge; | ||
28 | int dump_sensor; | ||
29 | unsigned int m5602_debug; | ||
30 | |||
31 | static const __devinitdata struct usb_device_id m5602_table[] = { | ||
32 | {USB_DEVICE(0x0402, 0x5602)}, | ||
33 | {} | ||
34 | }; | ||
35 | |||
36 | MODULE_DEVICE_TABLE(usb, m5602_table); | ||
37 | |||
38 | /* Reads a byte from the m5602 */ | ||
39 | int m5602_read_bridge(struct sd *sd, u8 address, u8 *i2c_data) | ||
40 | { | ||
41 | int err; | ||
42 | struct usb_device *udev = sd->gspca_dev.dev; | ||
43 | __u8 *buf = sd->gspca_dev.usb_buf; | ||
44 | |||
45 | err = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), | ||
46 | 0x04, 0xc0, 0x14, | ||
47 | 0x8100 + address, buf, | ||
48 | 1, M5602_URB_MSG_TIMEOUT); | ||
49 | *i2c_data = buf[0]; | ||
50 | |||
51 | PDEBUG(DBG_TRACE, "Reading bridge register 0x%x containing 0x%x", | ||
52 | address, *i2c_data); | ||
53 | |||
54 | /* usb_control_msg(...) returns the number of bytes sent upon success, | ||
55 | mask that and return zero upon success instead*/ | ||
56 | return (err < 0) ? err : 0; | ||
57 | } | ||
58 | |||
59 | /* Writes a byte to to the m5602 */ | ||
60 | int m5602_write_bridge(struct sd *sd, u8 address, u8 i2c_data) | ||
61 | { | ||
62 | int err; | ||
63 | struct usb_device *udev = sd->gspca_dev.dev; | ||
64 | __u8 *buf = sd->gspca_dev.usb_buf; | ||
65 | |||
66 | PDEBUG(DBG_TRACE, "Writing bridge register 0x%x with 0x%x", | ||
67 | address, i2c_data); | ||
68 | |||
69 | memcpy(buf, bridge_urb_skeleton, | ||
70 | sizeof(bridge_urb_skeleton)); | ||
71 | buf[1] = address; | ||
72 | buf[3] = i2c_data; | ||
73 | |||
74 | err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), | ||
75 | 0x04, 0x40, 0x19, | ||
76 | 0x0000, buf, | ||
77 | 4, M5602_URB_MSG_TIMEOUT); | ||
78 | |||
79 | /* usb_control_msg(...) returns the number of bytes sent upon success, | ||
80 | mask that and return zero upon success instead */ | ||
81 | return (err < 0) ? err : 0; | ||
82 | } | ||
83 | |||
84 | /* Dump all the registers of the m5602 bridge, | ||
85 | unfortunately this breaks the camera until it's power cycled */ | ||
86 | static void m5602_dump_bridge(struct sd *sd) | ||
87 | { | ||
88 | int i; | ||
89 | for (i = 0; i < 0x80; i++) { | ||
90 | unsigned char val = 0; | ||
91 | m5602_read_bridge(sd, i, &val); | ||
92 | info("ALi m5602 address 0x%x contains 0x%x", i, val); | ||
93 | } | ||
94 | info("Warning: The camera probably won't work until it's power cycled"); | ||
95 | } | ||
96 | |||
97 | static int m5602_probe_sensor(struct sd *sd) | ||
98 | { | ||
99 | /* Try the po1030 */ | ||
100 | sd->sensor = &po1030; | ||
101 | if (!sd->sensor->probe(sd)) | ||
102 | return 0; | ||
103 | |||
104 | /* Try the mt9m111 sensor */ | ||
105 | sd->sensor = &mt9m111; | ||
106 | if (!sd->sensor->probe(sd)) | ||
107 | return 0; | ||
108 | |||
109 | /* Try the s5k4aa */ | ||
110 | sd->sensor = &s5k4aa; | ||
111 | if (!sd->sensor->probe(sd)) | ||
112 | return 0; | ||
113 | |||
114 | /* Try the ov9650 */ | ||
115 | sd->sensor = &ov9650; | ||
116 | if (!sd->sensor->probe(sd)) | ||
117 | return 0; | ||
118 | |||
119 | /* Try the s5k83a */ | ||
120 | sd->sensor = &s5k83a; | ||
121 | if (!sd->sensor->probe(sd)) | ||
122 | return 0; | ||
123 | |||
124 | /* More sensor probe function goes here */ | ||
125 | info("Failed to find a sensor"); | ||
126 | sd->sensor = NULL; | ||
127 | return -ENODEV; | ||
128 | } | ||
129 | |||
130 | static int m5602_configure(struct gspca_dev *gspca_dev, | ||
131 | const struct usb_device_id *id); | ||
132 | |||
133 | static int m5602_init(struct gspca_dev *gspca_dev) | ||
134 | { | ||
135 | struct sd *sd = (struct sd *) gspca_dev; | ||
136 | int err; | ||
137 | |||
138 | PDEBUG(DBG_TRACE, "Initializing ALi m5602 webcam"); | ||
139 | /* Run the init sequence */ | ||
140 | err = sd->sensor->init(sd); | ||
141 | |||
142 | return err; | ||
143 | } | ||
144 | |||
145 | static int m5602_start_transfer(struct gspca_dev *gspca_dev) | ||
146 | { | ||
147 | struct sd *sd = (struct sd *) gspca_dev; | ||
148 | __u8 *buf = sd->gspca_dev.usb_buf; | ||
149 | |||
150 | /* Send start command to the camera */ | ||
151 | const u8 buffer[4] = {0x13, 0xf9, 0x0f, 0x01}; | ||
152 | memcpy(buf, buffer, sizeof(buffer)); | ||
153 | usb_control_msg(gspca_dev->dev, usb_sndctrlpipe(gspca_dev->dev, 0), | ||
154 | 0x04, 0x40, 0x19, 0x0000, buf, | ||
155 | 4, M5602_URB_MSG_TIMEOUT); | ||
156 | |||
157 | PDEBUG(DBG_V4L2, "Transfer started"); | ||
158 | return 0; | ||
159 | } | ||
160 | |||
161 | static void m5602_urb_complete(struct gspca_dev *gspca_dev, | ||
162 | struct gspca_frame *frame, | ||
163 | __u8 *data, int len) | ||
164 | { | ||
165 | struct sd *sd = (struct sd *) gspca_dev; | ||
166 | |||
167 | if (len < 6) { | ||
168 | PDEBUG(DBG_DATA, "Packet is less than 6 bytes"); | ||
169 | return; | ||
170 | } | ||
171 | |||
172 | /* Frame delimiter: ff xx xx xx ff ff */ | ||
173 | if (data[0] == 0xff && data[4] == 0xff && data[5] == 0xff && | ||
174 | data[2] != sd->frame_id) { | ||
175 | PDEBUG(DBG_DATA, "Frame delimiter detected"); | ||
176 | sd->frame_id = data[2]; | ||
177 | |||
178 | /* Remove the extra fluff appended on each header */ | ||
179 | data += 6; | ||
180 | len -= 6; | ||
181 | |||
182 | /* Complete the last frame (if any) */ | ||
183 | frame = gspca_frame_add(gspca_dev, LAST_PACKET, | ||
184 | frame, data, 0); | ||
185 | sd->frame_count++; | ||
186 | |||
187 | /* Create a new frame */ | ||
188 | gspca_frame_add(gspca_dev, FIRST_PACKET, frame, data, len); | ||
189 | |||
190 | PDEBUG(DBG_V4L2, "Starting new frame %d", | ||
191 | sd->frame_count); | ||
192 | |||
193 | } else { | ||
194 | int cur_frame_len = frame->data_end - frame->data; | ||
195 | |||
196 | /* Remove urb header */ | ||
197 | data += 4; | ||
198 | len -= 4; | ||
199 | |||
200 | if (cur_frame_len + len <= frame->v4l2_buf.length) { | ||
201 | PDEBUG(DBG_DATA, "Continuing frame %d copying %d bytes", | ||
202 | sd->frame_count, len); | ||
203 | |||
204 | gspca_frame_add(gspca_dev, INTER_PACKET, frame, | ||
205 | data, len); | ||
206 | } else if (frame->v4l2_buf.length - cur_frame_len > 0) { | ||
207 | /* Add the remaining data up to frame size */ | ||
208 | gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, | ||
209 | frame->v4l2_buf.length - cur_frame_len); | ||
210 | } | ||
211 | } | ||
212 | } | ||
213 | |||
214 | static void m5602_stop_transfer(struct gspca_dev *gspca_dev) | ||
215 | { | ||
216 | /* Is there are a command to stop a data transfer? */ | ||
217 | } | ||
218 | |||
219 | /* sub-driver description, the ctrl and nctrl is filled at probe time */ | ||
220 | static struct sd_desc sd_desc = { | ||
221 | .name = MODULE_NAME, | ||
222 | .config = m5602_configure, | ||
223 | .init = m5602_init, | ||
224 | .start = m5602_start_transfer, | ||
225 | .stopN = m5602_stop_transfer, | ||
226 | .pkt_scan = m5602_urb_complete | ||
227 | }; | ||
228 | |||
229 | /* this function is called at probe time */ | ||
230 | static int m5602_configure(struct gspca_dev *gspca_dev, | ||
231 | const struct usb_device_id *id) | ||
232 | { | ||
233 | struct sd *sd = (struct sd *) gspca_dev; | ||
234 | struct cam *cam; | ||
235 | int err; | ||
236 | |||
237 | PDEBUG(DBG_GSPCA, "m5602_configure start"); | ||
238 | |||
239 | cam = &gspca_dev->cam; | ||
240 | cam->epaddr = M5602_ISOC_ENDPOINT_ADDR; | ||
241 | sd->desc = &sd_desc; | ||
242 | |||
243 | if (dump_bridge) | ||
244 | m5602_dump_bridge(sd); | ||
245 | |||
246 | /* Probe sensor */ | ||
247 | err = m5602_probe_sensor(sd); | ||
248 | if (err) | ||
249 | goto fail; | ||
250 | |||
251 | PDEBUG(DBG_GSPCA, "m5602_configure end"); | ||
252 | return 0; | ||
253 | |||
254 | fail: | ||
255 | PDEBUG(DBG_GSPCA, "m5602_configure failed"); | ||
256 | cam->cam_mode = NULL; | ||
257 | cam->nmodes = 0; | ||
258 | |||
259 | return err; | ||
260 | } | ||
261 | |||
262 | static int m5602_probe(struct usb_interface *intf, | ||
263 | const struct usb_device_id *id) | ||
264 | { | ||
265 | return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), | ||
266 | THIS_MODULE); | ||
267 | } | ||
268 | |||
269 | static struct usb_driver sd_driver = { | ||
270 | .name = MODULE_NAME, | ||
271 | .id_table = m5602_table, | ||
272 | .probe = m5602_probe, | ||
273 | #ifdef CONFIG_PM | ||
274 | .suspend = gspca_suspend, | ||
275 | .resume = gspca_resume, | ||
276 | #endif | ||
277 | .disconnect = gspca_disconnect | ||
278 | }; | ||
279 | |||
280 | /* -- module insert / remove -- */ | ||
281 | static int __init mod_m5602_init(void) | ||
282 | { | ||
283 | if (usb_register(&sd_driver) < 0) | ||
284 | return -1; | ||
285 | PDEBUG(D_PROBE, "m5602 module registered"); | ||
286 | return 0; | ||
287 | } | ||
288 | static void __exit mod_m5602_exit(void) | ||
289 | { | ||
290 | usb_deregister(&sd_driver); | ||
291 | PDEBUG(D_PROBE, "m5602 module deregistered"); | ||
292 | } | ||
293 | |||
294 | module_init(mod_m5602_init); | ||
295 | module_exit(mod_m5602_exit); | ||
296 | |||
297 | MODULE_AUTHOR(DRIVER_AUTHOR); | ||
298 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
299 | MODULE_LICENSE("GPL"); | ||
300 | module_param_named(debug, m5602_debug, int, S_IRUGO | S_IWUSR); | ||
301 | MODULE_PARM_DESC(debug, "toggles debug on/off"); | ||
302 | |||
303 | module_param(force_sensor, int, S_IRUGO | S_IWUSR); | ||
304 | MODULE_PARM_DESC(force_sensor, | ||
305 | "force detection of sensor, " | ||
306 | "1 = OV9650, 2 = S5K83A, 3 = S5K4AA, 4 = MT9M111, 5 = PO1030"); | ||
307 | |||
308 | module_param(dump_bridge, bool, S_IRUGO | S_IWUSR); | ||
309 | MODULE_PARM_DESC(dump_bridge, "Dumps all usb bridge registers at startup"); | ||
310 | |||
311 | module_param(dump_sensor, bool, S_IRUGO | S_IWUSR); | ||
312 | MODULE_PARM_DESC(dump_sensor, "Dumps all usb sensor registers " | ||
313 | "at startup providing a sensor is found"); | ||
diff --git a/drivers/media/video/gspca/m5602/m5602_mt9m111.c b/drivers/media/video/gspca/m5602/m5602_mt9m111.c new file mode 100644 index 000000000000..566d4925a0e8 --- /dev/null +++ b/drivers/media/video/gspca/m5602/m5602_mt9m111.c | |||
@@ -0,0 +1,345 @@ | |||
1 | /* | ||
2 | * Driver for the mt9m111 sensor | ||
3 | * | ||
4 | * Copyright (C) 2008 Erik Andren | ||
5 | * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project. | ||
6 | * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br> | ||
7 | * | ||
8 | * Portions of code to USB interface and ALi driver software, | ||
9 | * Copyright (c) 2006 Willem Duinker | ||
10 | * v4l2 interface modeled after the V4L2 driver | ||
11 | * for SN9C10x PC Camera Controllers | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or | ||
14 | * modify it under the terms of the GNU General Public License as | ||
15 | * published by the Free Software Foundation, version 2. | ||
16 | * | ||
17 | */ | ||
18 | |||
19 | #include "m5602_mt9m111.h" | ||
20 | |||
21 | int mt9m111_probe(struct sd *sd) | ||
22 | { | ||
23 | u8 data[2] = {0x00, 0x00}; | ||
24 | int i; | ||
25 | |||
26 | if (force_sensor) { | ||
27 | if (force_sensor == MT9M111_SENSOR) { | ||
28 | info("Forcing a %s sensor", mt9m111.name); | ||
29 | goto sensor_found; | ||
30 | } | ||
31 | /* If we want to force another sensor, don't try to probe this | ||
32 | * one */ | ||
33 | return -ENODEV; | ||
34 | } | ||
35 | |||
36 | info("Probing for a mt9m111 sensor"); | ||
37 | |||
38 | /* Do the preinit */ | ||
39 | for (i = 0; i < ARRAY_SIZE(preinit_mt9m111); i++) { | ||
40 | if (preinit_mt9m111[i][0] == BRIDGE) { | ||
41 | m5602_write_bridge(sd, | ||
42 | preinit_mt9m111[i][1], | ||
43 | preinit_mt9m111[i][2]); | ||
44 | } else { | ||
45 | data[0] = preinit_mt9m111[i][2]; | ||
46 | data[1] = preinit_mt9m111[i][3]; | ||
47 | mt9m111_write_sensor(sd, | ||
48 | preinit_mt9m111[i][1], data, 2); | ||
49 | } | ||
50 | } | ||
51 | |||
52 | if (mt9m111_read_sensor(sd, MT9M111_SC_CHIPVER, data, 2)) | ||
53 | return -ENODEV; | ||
54 | |||
55 | if ((data[0] == 0x14) && (data[1] == 0x3a)) { | ||
56 | info("Detected a mt9m111 sensor"); | ||
57 | goto sensor_found; | ||
58 | } | ||
59 | |||
60 | return -ENODEV; | ||
61 | |||
62 | sensor_found: | ||
63 | sd->gspca_dev.cam.cam_mode = mt9m111.modes; | ||
64 | sd->gspca_dev.cam.nmodes = mt9m111.nmodes; | ||
65 | sd->desc->ctrls = mt9m111.ctrls; | ||
66 | sd->desc->nctrls = mt9m111.nctrls; | ||
67 | return 0; | ||
68 | } | ||
69 | |||
70 | int mt9m111_init(struct sd *sd) | ||
71 | { | ||
72 | int i, err = 0; | ||
73 | |||
74 | /* Init the sensor */ | ||
75 | for (i = 0; i < ARRAY_SIZE(init_mt9m111); i++) { | ||
76 | u8 data[2]; | ||
77 | |||
78 | if (init_mt9m111[i][0] == BRIDGE) { | ||
79 | err = m5602_write_bridge(sd, | ||
80 | init_mt9m111[i][1], | ||
81 | init_mt9m111[i][2]); | ||
82 | } else { | ||
83 | data[0] = init_mt9m111[i][2]; | ||
84 | data[1] = init_mt9m111[i][3]; | ||
85 | err = mt9m111_write_sensor(sd, | ||
86 | init_mt9m111[i][1], data, 2); | ||
87 | } | ||
88 | } | ||
89 | |||
90 | if (dump_sensor) | ||
91 | mt9m111_dump_registers(sd); | ||
92 | |||
93 | return (err < 0) ? err : 0; | ||
94 | } | ||
95 | |||
96 | int mt9m111_power_down(struct sd *sd) | ||
97 | { | ||
98 | return 0; | ||
99 | } | ||
100 | |||
101 | int mt9m111_get_vflip(struct gspca_dev *gspca_dev, __s32 *val) | ||
102 | { | ||
103 | int err; | ||
104 | u8 data[2] = {0x00, 0x00}; | ||
105 | struct sd *sd = (struct sd *) gspca_dev; | ||
106 | |||
107 | err = mt9m111_read_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B, | ||
108 | data, 2); | ||
109 | *val = data[0] & MT9M111_RMB_MIRROR_ROWS; | ||
110 | PDEBUG(DBG_V4L2_CID, "Read vertical flip %d", *val); | ||
111 | |||
112 | return (err < 0) ? err : 0; | ||
113 | } | ||
114 | |||
115 | int mt9m111_set_vflip(struct gspca_dev *gspca_dev, __s32 val) | ||
116 | { | ||
117 | int err; | ||
118 | u8 data[2] = {0x00, 0x00}; | ||
119 | struct sd *sd = (struct sd *) gspca_dev; | ||
120 | |||
121 | PDEBUG(DBG_V4L2_CID, "Set vertical flip to %d", val); | ||
122 | |||
123 | /* Set the correct page map */ | ||
124 | err = mt9m111_write_sensor(sd, MT9M111_PAGE_MAP, data, 2); | ||
125 | if (err < 0) | ||
126 | goto out; | ||
127 | |||
128 | err = mt9m111_read_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B, data, 2); | ||
129 | if (err < 0) | ||
130 | goto out; | ||
131 | |||
132 | data[0] = (data[0] & 0xfe) | val; | ||
133 | err = mt9m111_write_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B, | ||
134 | data, 2); | ||
135 | out: | ||
136 | return (err < 0) ? err : 0; | ||
137 | } | ||
138 | |||
139 | int mt9m111_get_hflip(struct gspca_dev *gspca_dev, __s32 *val) | ||
140 | { | ||
141 | int err; | ||
142 | u8 data[2] = {0x00, 0x00}; | ||
143 | struct sd *sd = (struct sd *) gspca_dev; | ||
144 | |||
145 | err = mt9m111_read_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B, | ||
146 | data, 2); | ||
147 | *val = data[0] & MT9M111_RMB_MIRROR_COLS; | ||
148 | PDEBUG(DBG_V4L2_CID, "Read horizontal flip %d", *val); | ||
149 | |||
150 | return (err < 0) ? err : 0; | ||
151 | } | ||
152 | |||
153 | int mt9m111_set_hflip(struct gspca_dev *gspca_dev, __s32 val) | ||
154 | { | ||
155 | int err; | ||
156 | u8 data[2] = {0x00, 0x00}; | ||
157 | struct sd *sd = (struct sd *) gspca_dev; | ||
158 | |||
159 | PDEBUG(DBG_V4L2_CID, "Set horizontal flip to %d", val); | ||
160 | |||
161 | /* Set the correct page map */ | ||
162 | err = mt9m111_write_sensor(sd, MT9M111_PAGE_MAP, data, 2); | ||
163 | if (err < 0) | ||
164 | goto out; | ||
165 | |||
166 | err = mt9m111_read_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B, data, 2); | ||
167 | if (err < 0) | ||
168 | goto out; | ||
169 | |||
170 | data[0] = (data[0] & 0xfd) | ((val << 1) & 0x02); | ||
171 | err = mt9m111_write_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B, | ||
172 | data, 2); | ||
173 | out: | ||
174 | return (err < 0) ? err : 0; | ||
175 | } | ||
176 | |||
177 | int mt9m111_get_gain(struct gspca_dev *gspca_dev, __s32 *val) | ||
178 | { | ||
179 | int err, tmp; | ||
180 | u8 data[2] = {0x00, 0x00}; | ||
181 | struct sd *sd = (struct sd *) gspca_dev; | ||
182 | |||
183 | err = mt9m111_read_sensor(sd, MT9M111_SC_GLOBAL_GAIN, data, 2); | ||
184 | tmp = ((data[1] << 8) | data[0]); | ||
185 | |||
186 | *val = ((tmp & (1 << 10)) * 2) | | ||
187 | ((tmp & (1 << 9)) * 2) | | ||
188 | ((tmp & (1 << 8)) * 2) | | ||
189 | (tmp & 0x7f); | ||
190 | |||
191 | PDEBUG(DBG_V4L2_CID, "Read gain %d", *val); | ||
192 | |||
193 | return (err < 0) ? err : 0; | ||
194 | } | ||
195 | |||
196 | int mt9m111_set_gain(struct gspca_dev *gspca_dev, __s32 val) | ||
197 | { | ||
198 | int err, tmp; | ||
199 | u8 data[2] = {0x00, 0x00}; | ||
200 | struct sd *sd = (struct sd *) gspca_dev; | ||
201 | |||
202 | /* Set the correct page map */ | ||
203 | err = mt9m111_write_sensor(sd, MT9M111_PAGE_MAP, data, 2); | ||
204 | if (err < 0) | ||
205 | goto out; | ||
206 | |||
207 | if (val >= INITIAL_MAX_GAIN * 2 * 2 * 2) | ||
208 | return -EINVAL; | ||
209 | |||
210 | if ((val >= INITIAL_MAX_GAIN * 2 * 2) && | ||
211 | (val < (INITIAL_MAX_GAIN - 1) * 2 * 2 * 2)) | ||
212 | tmp = (1 << 10) | (val << 9) | | ||
213 | (val << 8) | (val / 8); | ||
214 | else if ((val >= INITIAL_MAX_GAIN * 2) && | ||
215 | (val < INITIAL_MAX_GAIN * 2 * 2)) | ||
216 | tmp = (1 << 9) | (1 << 8) | (val / 4); | ||
217 | else if ((val >= INITIAL_MAX_GAIN) && | ||
218 | (val < INITIAL_MAX_GAIN * 2)) | ||
219 | tmp = (1 << 8) | (val / 2); | ||
220 | else | ||
221 | tmp = val; | ||
222 | |||
223 | data[1] = (tmp & 0xff00) >> 8; | ||
224 | data[0] = (tmp & 0xff); | ||
225 | PDEBUG(DBG_V4L2_CID, "tmp=%d, data[1]=%d, data[0]=%d", tmp, | ||
226 | data[1], data[0]); | ||
227 | |||
228 | err = mt9m111_write_sensor(sd, MT9M111_SC_GLOBAL_GAIN, | ||
229 | data, 2); | ||
230 | out: | ||
231 | return (err < 0) ? err : 0; | ||
232 | } | ||
233 | |||
234 | int mt9m111_read_sensor(struct sd *sd, const u8 address, | ||
235 | u8 *i2c_data, const u8 len) { | ||
236 | int err, i; | ||
237 | |||
238 | do { | ||
239 | err = m5602_read_bridge(sd, M5602_XB_I2C_STATUS, i2c_data); | ||
240 | } while ((*i2c_data & I2C_BUSY) && !err); | ||
241 | if (err < 0) | ||
242 | goto out; | ||
243 | |||
244 | err = m5602_write_bridge(sd, M5602_XB_I2C_DEV_ADDR, | ||
245 | sd->sensor->i2c_slave_id); | ||
246 | if (err < 0) | ||
247 | goto out; | ||
248 | |||
249 | err = m5602_write_bridge(sd, M5602_XB_I2C_REG_ADDR, address); | ||
250 | if (err < 0) | ||
251 | goto out; | ||
252 | |||
253 | err = m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 0x1a); | ||
254 | if (err < 0) | ||
255 | goto out; | ||
256 | |||
257 | for (i = 0; i < len && !err; i++) { | ||
258 | err = m5602_read_bridge(sd, M5602_XB_I2C_DATA, &(i2c_data[i])); | ||
259 | |||
260 | PDEBUG(DBG_TRACE, "Reading sensor register " | ||
261 | "0x%x contains 0x%x ", address, *i2c_data); | ||
262 | } | ||
263 | out: | ||
264 | return (err < 0) ? err : 0; | ||
265 | } | ||
266 | |||
267 | int mt9m111_write_sensor(struct sd *sd, const u8 address, | ||
268 | u8 *i2c_data, const u8 len) | ||
269 | { | ||
270 | int err, i; | ||
271 | u8 *p; | ||
272 | struct usb_device *udev = sd->gspca_dev.dev; | ||
273 | __u8 *buf = sd->gspca_dev.usb_buf; | ||
274 | |||
275 | /* No sensor with a data width larger | ||
276 | than 16 bits has yet been seen, nor with 0 :p*/ | ||
277 | if (len > 2 || !len) | ||
278 | return -EINVAL; | ||
279 | |||
280 | memcpy(buf, sensor_urb_skeleton, | ||
281 | sizeof(sensor_urb_skeleton)); | ||
282 | |||
283 | buf[11] = sd->sensor->i2c_slave_id; | ||
284 | buf[15] = address; | ||
285 | |||
286 | p = buf + 16; | ||
287 | |||
288 | /* Copy a four byte write sequence for each byte to be written to */ | ||
289 | for (i = 0; i < len; i++) { | ||
290 | memcpy(p, sensor_urb_skeleton + 16, 4); | ||
291 | p[3] = i2c_data[i]; | ||
292 | p += 4; | ||
293 | PDEBUG(DBG_TRACE, "Writing sensor register 0x%x with 0x%x", | ||
294 | address, i2c_data[i]); | ||
295 | } | ||
296 | |||
297 | /* Copy the tailer */ | ||
298 | memcpy(p, sensor_urb_skeleton + 20, 4); | ||
299 | |||
300 | /* Set the total length */ | ||
301 | p[3] = 0x10 + len; | ||
302 | |||
303 | err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), | ||
304 | 0x04, 0x40, 0x19, | ||
305 | 0x0000, buf, | ||
306 | 20 + len * 4, M5602_URB_MSG_TIMEOUT); | ||
307 | |||
308 | return (err < 0) ? err : 0; | ||
309 | } | ||
310 | |||
311 | void mt9m111_dump_registers(struct sd *sd) | ||
312 | { | ||
313 | u8 address, value[2] = {0x00, 0x00}; | ||
314 | |||
315 | info("Dumping the mt9m111 register state"); | ||
316 | |||
317 | info("Dumping the mt9m111 sensor core registers"); | ||
318 | value[1] = MT9M111_SENSOR_CORE; | ||
319 | mt9m111_write_sensor(sd, MT9M111_PAGE_MAP, value, 2); | ||
320 | for (address = 0; address < 0xff; address++) { | ||
321 | mt9m111_read_sensor(sd, address, value, 2); | ||
322 | info("register 0x%x contains 0x%x%x", | ||
323 | address, value[0], value[1]); | ||
324 | } | ||
325 | |||
326 | info("Dumping the mt9m111 color pipeline registers"); | ||
327 | value[1] = MT9M111_COLORPIPE; | ||
328 | mt9m111_write_sensor(sd, MT9M111_PAGE_MAP, value, 2); | ||
329 | for (address = 0; address < 0xff; address++) { | ||
330 | mt9m111_read_sensor(sd, address, value, 2); | ||
331 | info("register 0x%x contains 0x%x%x", | ||
332 | address, value[0], value[1]); | ||
333 | } | ||
334 | |||
335 | info("Dumping the mt9m111 camera control registers"); | ||
336 | value[1] = MT9M111_CAMERA_CONTROL; | ||
337 | mt9m111_write_sensor(sd, MT9M111_PAGE_MAP, value, 2); | ||
338 | for (address = 0; address < 0xff; address++) { | ||
339 | mt9m111_read_sensor(sd, address, value, 2); | ||
340 | info("register 0x%x contains 0x%x%x", | ||
341 | address, value[0], value[1]); | ||
342 | } | ||
343 | |||
344 | info("mt9m111 register state dump complete"); | ||
345 | } | ||
diff --git a/drivers/media/video/gspca/m5602/m5602_mt9m111.h b/drivers/media/video/gspca/m5602/m5602_mt9m111.h new file mode 100644 index 000000000000..79a5d8878190 --- /dev/null +++ b/drivers/media/video/gspca/m5602/m5602_mt9m111.h | |||
@@ -0,0 +1,1020 @@ | |||
1 | /* | ||
2 | * Driver for the mt9m111 sensor | ||
3 | * | ||
4 | * Copyright (C) 2008 Erik Andren | ||
5 | * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project. | ||
6 | * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br> | ||
7 | * | ||
8 | * Portions of code to USB interface and ALi driver software, | ||
9 | * Copyright (c) 2006 Willem Duinker | ||
10 | * v4l2 interface modeled after the V4L2 driver | ||
11 | * for SN9C10x PC Camera Controllers | ||
12 | * | ||
13 | * Some defines taken from the mt9m111 sensor driver | ||
14 | * Copyright (C) 2008, Robert Jarzmik <robert.jarzmik@free.fr> | ||
15 | * | ||
16 | * This program is free software; you can redistribute it and/or | ||
17 | * modify it under the terms of the GNU General Public License as | ||
18 | * published by the Free Software Foundation, version 2. | ||
19 | * | ||
20 | */ | ||
21 | |||
22 | #ifndef M5602_MT9M111_H_ | ||
23 | #define M5602_MT9M111_H_ | ||
24 | |||
25 | #include "m5602_sensor.h" | ||
26 | |||
27 | /*****************************************************************************/ | ||
28 | |||
29 | #define MT9M111_SC_CHIPVER 0x00 | ||
30 | #define MT9M111_SC_ROWSTART 0x01 | ||
31 | #define MT9M111_SC_COLSTART 0x02 | ||
32 | #define MT9M111_SC_WINDOW_HEIGHT 0x03 | ||
33 | #define MT9M111_SC_WINDOW_WIDTH 0x04 | ||
34 | #define MT9M111_SC_HBLANK_CONTEXT_B 0x05 | ||
35 | #define MT9M111_SC_VBLANK_CONTEXT_B 0x06 | ||
36 | #define MT9M111_SC_HBLANK_CONTEXT_A 0x07 | ||
37 | #define MT9M111_SC_VBLANK_CONTEXT_A 0x08 | ||
38 | #define MT9M111_SC_SHUTTER_WIDTH 0x09 | ||
39 | #define MT9M111_SC_ROW_SPEED 0x0a | ||
40 | |||
41 | #define MT9M111_SC_EXTRA_DELAY 0x0b | ||
42 | #define MT9M111_SC_SHUTTER_DELAY 0x0c | ||
43 | #define MT9M111_SC_RESET 0x0d | ||
44 | #define MT9M111_SC_R_MODE_CONTEXT_B 0x20 | ||
45 | #define MT9M111_SC_R_MODE_CONTEXT_A 0x21 | ||
46 | #define MT9M111_SC_FLASH_CONTROL 0x23 | ||
47 | #define MT9M111_SC_GREEN_1_GAIN 0x2b | ||
48 | #define MT9M111_SC_BLUE_GAIN 0x2c | ||
49 | #define MT9M111_SC_RED_GAIN 0x2d | ||
50 | #define MT9M111_SC_GREEN_2_GAIN 0x2e | ||
51 | #define MT9M111_SC_GLOBAL_GAIN 0x2f | ||
52 | |||
53 | #define MT9M111_RMB_MIRROR_ROWS (1 << 0) | ||
54 | #define MT9M111_RMB_MIRROR_COLS (1 << 1) | ||
55 | |||
56 | #define MT9M111_CONTEXT_CONTROL 0xc8 | ||
57 | #define MT9M111_PAGE_MAP 0xf0 | ||
58 | #define MT9M111_BYTEWISE_ADDRESS 0xf1 | ||
59 | |||
60 | #define MT9M111_CP_OPERATING_MODE_CTL 0x06 | ||
61 | #define MT9M111_CP_LUMA_OFFSET 0x34 | ||
62 | #define MT9M111_CP_LUMA_CLIP 0x35 | ||
63 | #define MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_A 0x3a | ||
64 | #define MT9M111_CP_LENS_CORRECTION_1 0x3b | ||
65 | #define MT9M111_CP_DEFECT_CORR_CONTEXT_A 0x4c | ||
66 | #define MT9M111_CP_DEFECT_CORR_CONTEXT_B 0x4d | ||
67 | #define MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_B 0x9b | ||
68 | #define MT9M111_CP_GLOBAL_CLK_CONTROL 0xb3 | ||
69 | |||
70 | #define MT9M111_CC_AUTO_EXPOSURE_PARAMETER_18 0x65 | ||
71 | #define MT9M111_CC_AWB_PARAMETER_7 0x28 | ||
72 | |||
73 | #define MT9M111_SENSOR_CORE 0x00 | ||
74 | #define MT9M111_COLORPIPE 0x01 | ||
75 | #define MT9M111_CAMERA_CONTROL 0x02 | ||
76 | |||
77 | #define INITIAL_MAX_GAIN 64 | ||
78 | #define DEFAULT_GAIN 283 | ||
79 | |||
80 | /*****************************************************************************/ | ||
81 | |||
82 | /* Kernel module parameters */ | ||
83 | extern int force_sensor; | ||
84 | extern int dump_sensor; | ||
85 | extern unsigned int m5602_debug; | ||
86 | |||
87 | int mt9m111_probe(struct sd *sd); | ||
88 | int mt9m111_init(struct sd *sd); | ||
89 | int mt9m111_power_down(struct sd *sd); | ||
90 | |||
91 | int mt9m111_read_sensor(struct sd *sd, const u8 address, | ||
92 | u8 *i2c_data, const u8 len); | ||
93 | |||
94 | int mt9m111_write_sensor(struct sd *sd, const u8 address, | ||
95 | u8 *i2c_data, const u8 len); | ||
96 | |||
97 | void mt9m111_dump_registers(struct sd *sd); | ||
98 | |||
99 | int mt9m111_set_vflip(struct gspca_dev *gspca_dev, __s32 val); | ||
100 | int mt9m111_get_vflip(struct gspca_dev *gspca_dev, __s32 *val); | ||
101 | int mt9m111_get_hflip(struct gspca_dev *gspca_dev, __s32 *val); | ||
102 | int mt9m111_set_hflip(struct gspca_dev *gspca_dev, __s32 val); | ||
103 | int mt9m111_get_gain(struct gspca_dev *gspca_dev, __s32 *val); | ||
104 | int mt9m111_set_gain(struct gspca_dev *gspca_dev, __s32 val); | ||
105 | |||
106 | static struct m5602_sensor mt9m111 = { | ||
107 | .name = "MT9M111", | ||
108 | |||
109 | .i2c_slave_id = 0xba, | ||
110 | |||
111 | .probe = mt9m111_probe, | ||
112 | .init = mt9m111_init, | ||
113 | .power_down = mt9m111_power_down, | ||
114 | |||
115 | .read_sensor = mt9m111_read_sensor, | ||
116 | .write_sensor = mt9m111_write_sensor, | ||
117 | |||
118 | .nctrls = 3, | ||
119 | .ctrls = { | ||
120 | { | ||
121 | { | ||
122 | .id = V4L2_CID_VFLIP, | ||
123 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
124 | .name = "vertical flip", | ||
125 | .minimum = 0, | ||
126 | .maximum = 1, | ||
127 | .step = 1, | ||
128 | .default_value = 0 | ||
129 | }, | ||
130 | .set = mt9m111_set_vflip, | ||
131 | .get = mt9m111_get_vflip | ||
132 | }, { | ||
133 | { | ||
134 | .id = V4L2_CID_HFLIP, | ||
135 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
136 | .name = "horizontal flip", | ||
137 | .minimum = 0, | ||
138 | .maximum = 1, | ||
139 | .step = 1, | ||
140 | .default_value = 0 | ||
141 | }, | ||
142 | .set = mt9m111_set_hflip, | ||
143 | .get = mt9m111_get_hflip | ||
144 | }, { | ||
145 | { | ||
146 | .id = V4L2_CID_GAIN, | ||
147 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
148 | .name = "gain", | ||
149 | .minimum = 0, | ||
150 | .maximum = (INITIAL_MAX_GAIN - 1) * 2 * 2 * 2, | ||
151 | .step = 1, | ||
152 | .default_value = DEFAULT_GAIN, | ||
153 | .flags = V4L2_CTRL_FLAG_SLIDER | ||
154 | }, | ||
155 | .set = mt9m111_set_hflip, | ||
156 | .get = mt9m111_get_hflip | ||
157 | } | ||
158 | }, | ||
159 | |||
160 | .nmodes = 1, | ||
161 | .modes = { | ||
162 | { | ||
163 | M5602_DEFAULT_FRAME_WIDTH, | ||
164 | M5602_DEFAULT_FRAME_HEIGHT, | ||
165 | V4L2_PIX_FMT_SBGGR8, | ||
166 | V4L2_FIELD_NONE, | ||
167 | .sizeimage = | ||
168 | M5602_DEFAULT_FRAME_WIDTH * M5602_DEFAULT_FRAME_HEIGHT, | ||
169 | .bytesperline = M5602_DEFAULT_FRAME_WIDTH, | ||
170 | .colorspace = V4L2_COLORSPACE_SRGB, | ||
171 | .priv = 1 | ||
172 | } | ||
173 | } | ||
174 | }; | ||
175 | |||
176 | static const unsigned char preinit_mt9m111[][4] = | ||
177 | { | ||
178 | {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00}, | ||
179 | {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00}, | ||
180 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, | ||
181 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, | ||
182 | {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0d, 0x00}, | ||
183 | {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00, 0x00}, | ||
184 | {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, | ||
185 | {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00}, | ||
186 | |||
187 | {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, | ||
188 | {SENSOR, MT9M111_SC_RESET, 0xff, 0xf7}, | ||
189 | |||
190 | {BRIDGE, M5602_XB_GPIO_DIR, 0x05, 0x00}, | ||
191 | {BRIDGE, M5602_XB_GPIO_DAT, 0x04, 0x00}, | ||
192 | {BRIDGE, M5602_XB_GPIO_EN_H, 0x3e, 0x00}, | ||
193 | {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3e, 0x00}, | ||
194 | {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02, 0x00}, | ||
195 | {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00}, | ||
196 | {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00}, | ||
197 | {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00}, | ||
198 | |||
199 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, | ||
200 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, | ||
201 | {BRIDGE, M5602_XB_GPIO_DIR, 0x07, 0x00}, | ||
202 | {BRIDGE, M5602_XB_GPIO_DAT, 0x0b, 0x00}, | ||
203 | {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00}, | ||
204 | {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00}, | ||
205 | |||
206 | {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x0a, 0x00} | ||
207 | }; | ||
208 | |||
209 | static const unsigned char init_mt9m111[][4] = | ||
210 | { | ||
211 | {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00}, | ||
212 | {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00}, | ||
213 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, | ||
214 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, | ||
215 | {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, | ||
216 | {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0d, 0x00}, | ||
217 | {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00, 0x00}, | ||
218 | {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, | ||
219 | {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00}, | ||
220 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, | ||
221 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, | ||
222 | |||
223 | {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, | ||
224 | {SENSOR, MT9M111_SC_RESET, 0xff, 0xff}, | ||
225 | {SENSOR, MT9M111_SC_RESET, 0xff, 0xff}, | ||
226 | {SENSOR, MT9M111_SC_RESET, 0xff, 0xde}, | ||
227 | {SENSOR, MT9M111_SC_RESET, 0xff, 0xff}, | ||
228 | {SENSOR, MT9M111_SC_RESET, 0xff, 0xf7}, | ||
229 | {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01}, | ||
230 | |||
231 | {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xb3, 0x00}, | ||
232 | |||
233 | {SENSOR, MT9M111_CP_GLOBAL_CLK_CONTROL, 0xff, 0xff}, | ||
234 | |||
235 | {BRIDGE, M5602_XB_GPIO_DIR, 0x05, 0x00}, | ||
236 | {BRIDGE, M5602_XB_GPIO_DAT, 0x04, 0x00}, | ||
237 | {BRIDGE, M5602_XB_GPIO_EN_H, 0x3e, 0x00}, | ||
238 | {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3e, 0x00}, | ||
239 | {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02, 0x00}, | ||
240 | {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00}, | ||
241 | {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00}, | ||
242 | {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00}, | ||
243 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04, 0x00}, | ||
244 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, | ||
245 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, | ||
246 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, | ||
247 | {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, | ||
248 | {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00}, | ||
249 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, | ||
250 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, | ||
251 | {BRIDGE, M5602_XB_GPIO_DIR, 0x07, 0x00}, | ||
252 | {BRIDGE, M5602_XB_GPIO_DAT, 0x0b, 0x00}, | ||
253 | {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00}, | ||
254 | {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00}, | ||
255 | {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x0a, 0x00}, | ||
256 | |||
257 | {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, | ||
258 | {SENSOR, MT9M111_SC_RESET, 0x00, 0x05}, | ||
259 | {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, | ||
260 | {SENSOR, MT9M111_SC_RESET, 0x00, 0x29}, | ||
261 | {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, | ||
262 | {SENSOR, MT9M111_SC_RESET, 0x00, 0x08}, | ||
263 | {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01}, | ||
264 | {SENSOR, MT9M111_CP_OPERATING_MODE_CTL, 0x00, 0x10}, | ||
265 | {SENSOR, MT9M111_CP_LENS_CORRECTION_1, 0x04, 0x2a}, | ||
266 | {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_A, 0x00, 0x01}, | ||
267 | {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_B, 0x00, 0x01}, | ||
268 | {SENSOR, MT9M111_CP_LUMA_OFFSET, 0x00, 0x00}, | ||
269 | {SENSOR, MT9M111_CP_LUMA_CLIP, 0xff, 0x00}, | ||
270 | {SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_A, 0x14, 0x00}, | ||
271 | {SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_B, 0x14, 0x00}, | ||
272 | {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xcd, 0x00}, | ||
273 | |||
274 | {SENSOR, 0xcd, 0x00, 0x0e}, | ||
275 | {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xd0, 0x00}, | ||
276 | {SENSOR, 0xd0, 0x00, 0x40}, | ||
277 | {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x02}, | ||
278 | {SENSOR, MT9M111_CC_AUTO_EXPOSURE_PARAMETER_18, 0x00, 0x00}, | ||
279 | {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x28, 0x00}, | ||
280 | {SENSOR, MT9M111_CC_AWB_PARAMETER_7, 0xef, 0x07}, | ||
281 | {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x28, 0x00}, | ||
282 | {SENSOR, MT9M111_CC_AWB_PARAMETER_7, 0xef, 0x03}, | ||
283 | {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, | ||
284 | {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x33, 0x00}, | ||
285 | {SENSOR, 0x33, 0x03, 0x49}, | ||
286 | {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x33, 0x00}, | ||
287 | |||
288 | {SENSOR, 0x33, 0x03, 0x49}, | ||
289 | {SENSOR, 0x34, 0xc0, 0x19}, | ||
290 | {SENSOR, 0x3f, 0x20, 0x20}, | ||
291 | {SENSOR, 0x40, 0x20, 0x20}, | ||
292 | {SENSOR, 0x5a, 0xc0, 0x0a}, | ||
293 | {SENSOR, 0x70, 0x7b, 0x0a}, | ||
294 | {SENSOR, 0x71, 0xff, 0x00}, | ||
295 | {SENSOR, 0x72, 0x19, 0x0e}, | ||
296 | {SENSOR, 0x73, 0x18, 0x0f}, | ||
297 | {SENSOR, 0x74, 0x57, 0x32}, | ||
298 | {SENSOR, 0x75, 0x56, 0x34}, | ||
299 | {SENSOR, 0x76, 0x73, 0x35}, | ||
300 | {SENSOR, 0x77, 0x30, 0x12}, | ||
301 | {SENSOR, 0x78, 0x79, 0x02}, | ||
302 | {SENSOR, 0x79, 0x75, 0x06}, | ||
303 | {SENSOR, 0x7a, 0x77, 0x0a}, | ||
304 | {SENSOR, 0x7b, 0x78, 0x09}, | ||
305 | {SENSOR, 0x7c, 0x7d, 0x06}, | ||
306 | {SENSOR, 0x7d, 0x31, 0x10}, | ||
307 | {SENSOR, 0x7e, 0x00, 0x7e}, | ||
308 | {SENSOR, 0x80, 0x59, 0x04}, | ||
309 | {SENSOR, 0x81, 0x59, 0x04}, | ||
310 | {SENSOR, 0x82, 0x57, 0x0a}, | ||
311 | {SENSOR, 0x83, 0x58, 0x0b}, | ||
312 | {SENSOR, 0x84, 0x47, 0x0c}, | ||
313 | {SENSOR, 0x85, 0x48, 0x0e}, | ||
314 | {SENSOR, 0x86, 0x5b, 0x02}, | ||
315 | {SENSOR, 0x87, 0x00, 0x5c}, | ||
316 | {SENSOR, MT9M111_CONTEXT_CONTROL, 0x00, 0x08}, | ||
317 | {SENSOR, 0x60, 0x00, 0x80}, | ||
318 | {SENSOR, 0x61, 0x00, 0x00}, | ||
319 | {SENSOR, 0x62, 0x00, 0x00}, | ||
320 | {SENSOR, 0x63, 0x00, 0x00}, | ||
321 | {SENSOR, 0x64, 0x00, 0x00}, | ||
322 | |||
323 | {SENSOR, MT9M111_SC_ROWSTART, 0x00, 0x0d}, | ||
324 | {SENSOR, MT9M111_SC_COLSTART, 0x00, 0x18}, | ||
325 | {SENSOR, MT9M111_SC_WINDOW_HEIGHT, 0x04, 0x04}, | ||
326 | {SENSOR, MT9M111_SC_WINDOW_WIDTH, 0x05, 0x08}, | ||
327 | {SENSOR, MT9M111_SC_HBLANK_CONTEXT_B, 0x01, 0x38}, | ||
328 | {SENSOR, MT9M111_SC_VBLANK_CONTEXT_B, 0x00, 0x11}, | ||
329 | {SENSOR, MT9M111_SC_HBLANK_CONTEXT_A, 0x01, 0x38}, | ||
330 | {SENSOR, MT9M111_SC_VBLANK_CONTEXT_A, 0x00, 0x11}, | ||
331 | {SENSOR, MT9M111_SC_R_MODE_CONTEXT_B, 0x01, 0x03}, | ||
332 | {SENSOR, MT9M111_SC_R_MODE_CONTEXT_A, 0x01, 0x03}, | ||
333 | {SENSOR, 0x30, 0x04, 0x00}, | ||
334 | |||
335 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00}, | ||
336 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, | ||
337 | {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, | ||
338 | {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00}, | ||
339 | {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00}, | ||
340 | {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00}, | ||
341 | {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00}, | ||
342 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
343 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
344 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
345 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
346 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x04, 0x00}, | ||
347 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x04, 0x00}, | ||
348 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
349 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
350 | {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00}, | ||
351 | {BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00}, | ||
352 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, | ||
353 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, | ||
354 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x05, 0x00}, | ||
355 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x07, 0x00}, | ||
356 | {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00}, | ||
357 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, | ||
358 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xa0, 0x00}, | ||
359 | {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, | ||
360 | {SENSOR, MT9M111_SC_SHUTTER_WIDTH, 0x01, 0xf4}, | ||
361 | {SENSOR, MT9M111_SC_GLOBAL_GAIN, 0x00, 0xea}, | ||
362 | |||
363 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00}, | ||
364 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, | ||
365 | {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, | ||
366 | {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00}, | ||
367 | {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00}, | ||
368 | {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00}, | ||
369 | {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00}, | ||
370 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
371 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
372 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
373 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
374 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x04, 0x00}, | ||
375 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x04, 0x00}, | ||
376 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
377 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
378 | {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00}, | ||
379 | {BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00}, | ||
380 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, | ||
381 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, | ||
382 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x05, 0x00}, | ||
383 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x07, 0x00}, | ||
384 | {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00}, | ||
385 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, | ||
386 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, | ||
387 | |||
388 | {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, | ||
389 | {SENSOR, MT9M111_SC_RESET, 0x00, 0x09}, | ||
390 | {SENSOR, MT9M111_SC_RESET, 0x00, 0x29}, | ||
391 | {SENSOR, MT9M111_SC_RESET, 0x00, 0x08}, | ||
392 | {SENSOR, MT9M111_SC_RESET, 0x00, 0x0c}, | ||
393 | {SENSOR, MT9M111_SC_RESET, 0x00, 0x04}, | ||
394 | {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01}, | ||
395 | {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xb3, 0x00}, | ||
396 | {SENSOR, MT9M111_CP_GLOBAL_CLK_CONTROL, 0x00, 0x03}, | ||
397 | {BRIDGE, M5602_XB_GPIO_DIR, 0x05, 0x00}, | ||
398 | {BRIDGE, M5602_XB_GPIO_DAT, 0x04, 0x00}, | ||
399 | {BRIDGE, M5602_XB_GPIO_EN_H, 0x3e, 0x00}, | ||
400 | {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3e, 0x00}, | ||
401 | {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02, 0x00}, | ||
402 | {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00}, | ||
403 | {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00}, | ||
404 | {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00}, | ||
405 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04, 0x00}, | ||
406 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, | ||
407 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, | ||
408 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, | ||
409 | {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, | ||
410 | {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00}, | ||
411 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, | ||
412 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, | ||
413 | {BRIDGE, M5602_XB_GPIO_DIR, 0x07, 0x00}, | ||
414 | {BRIDGE, M5602_XB_GPIO_DAT, 0x0b, 0x00}, | ||
415 | {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00}, | ||
416 | {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00}, | ||
417 | {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x0a, 0x00}, | ||
418 | |||
419 | {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, | ||
420 | {SENSOR, MT9M111_SC_RESET, 0x00, 0x05}, | ||
421 | {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, | ||
422 | {SENSOR, MT9M111_SC_RESET, 0x00, 0x29}, | ||
423 | {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, | ||
424 | {SENSOR, MT9M111_SC_RESET, 0x00, 0x08}, | ||
425 | {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01}, | ||
426 | {SENSOR, MT9M111_CP_OPERATING_MODE_CTL, 0x00, 0x10}, | ||
427 | {SENSOR, MT9M111_CP_LENS_CORRECTION_1, 0x04, 0x2a}, | ||
428 | {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_A, 0x00, 0x01}, | ||
429 | {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_B, 0x00, 0x01}, | ||
430 | {SENSOR, MT9M111_CP_LUMA_OFFSET, 0x00, 0x00}, | ||
431 | {SENSOR, MT9M111_CP_LUMA_CLIP, 0xff, 0x00}, | ||
432 | {SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_A, 0x14, 0x00}, | ||
433 | {SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_B, 0x14, 0x00}, | ||
434 | |||
435 | {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xcd, 0x00}, | ||
436 | {SENSOR, 0xcd, 0x00, 0x0e}, | ||
437 | {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xd0, 0x00}, | ||
438 | {SENSOR, 0xd0, 0x00, 0x40}, | ||
439 | {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x02}, | ||
440 | {SENSOR, MT9M111_CC_AUTO_EXPOSURE_PARAMETER_18, 0x00, 0x00}, | ||
441 | {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x28, 0x00}, | ||
442 | {SENSOR, MT9M111_CC_AWB_PARAMETER_7, 0xef, 0x07}, | ||
443 | {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x28, 0x00}, | ||
444 | {SENSOR, MT9M111_CC_AWB_PARAMETER_7, 0xef, 0x03}, | ||
445 | {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, | ||
446 | {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x33, 0x00}, | ||
447 | {SENSOR, 0x33, 0x03, 0x49}, | ||
448 | {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x33, 0x00}, | ||
449 | |||
450 | {SENSOR, 0x33, 0x03, 0x49}, | ||
451 | {SENSOR, 0x34, 0xc0, 0x19}, | ||
452 | {SENSOR, 0x3f, 0x20, 0x20}, | ||
453 | {SENSOR, 0x40, 0x20, 0x20}, | ||
454 | {SENSOR, 0x5a, 0xc0, 0x0a}, | ||
455 | {SENSOR, 0x70, 0x7b, 0x0a}, | ||
456 | {SENSOR, 0x71, 0xff, 0x00}, | ||
457 | {SENSOR, 0x72, 0x19, 0x0e}, | ||
458 | {SENSOR, 0x73, 0x18, 0x0f}, | ||
459 | {SENSOR, 0x74, 0x57, 0x32}, | ||
460 | {SENSOR, 0x75, 0x56, 0x34}, | ||
461 | {SENSOR, 0x76, 0x73, 0x35}, | ||
462 | {SENSOR, 0x77, 0x30, 0x12}, | ||
463 | {SENSOR, 0x78, 0x79, 0x02}, | ||
464 | {SENSOR, 0x79, 0x75, 0x06}, | ||
465 | {SENSOR, 0x7a, 0x77, 0x0a}, | ||
466 | {SENSOR, 0x7b, 0x78, 0x09}, | ||
467 | {SENSOR, 0x7c, 0x7d, 0x06}, | ||
468 | {SENSOR, 0x7d, 0x31, 0x10}, | ||
469 | {SENSOR, 0x7e, 0x00, 0x7e}, | ||
470 | {SENSOR, 0x80, 0x59, 0x04}, | ||
471 | {SENSOR, 0x81, 0x59, 0x04}, | ||
472 | {SENSOR, 0x82, 0x57, 0x0a}, | ||
473 | {SENSOR, 0x83, 0x58, 0x0b}, | ||
474 | {SENSOR, 0x84, 0x47, 0x0c}, | ||
475 | {SENSOR, 0x85, 0x48, 0x0e}, | ||
476 | {SENSOR, 0x86, 0x5b, 0x02}, | ||
477 | {SENSOR, 0x87, 0x00, 0x5c}, | ||
478 | {SENSOR, MT9M111_CONTEXT_CONTROL, 0x00, 0x08}, | ||
479 | {SENSOR, 0x60, 0x00, 0x80}, | ||
480 | {SENSOR, 0x61, 0x00, 0x00}, | ||
481 | {SENSOR, 0x62, 0x00, 0x00}, | ||
482 | {SENSOR, 0x63, 0x00, 0x00}, | ||
483 | {SENSOR, 0x64, 0x00, 0x00}, | ||
484 | |||
485 | {SENSOR, MT9M111_SC_ROWSTART, 0x00, 0x0d}, | ||
486 | {SENSOR, MT9M111_SC_COLSTART, 0x00, 0x18}, | ||
487 | {SENSOR, MT9M111_SC_WINDOW_HEIGHT, 0x04, 0x04}, | ||
488 | {SENSOR, MT9M111_SC_WINDOW_WIDTH, 0x05, 0x08}, | ||
489 | {SENSOR, MT9M111_SC_HBLANK_CONTEXT_B, 0x01, 0x38}, | ||
490 | {SENSOR, MT9M111_SC_VBLANK_CONTEXT_B, 0x00, 0x11}, | ||
491 | {SENSOR, MT9M111_SC_HBLANK_CONTEXT_A, 0x01, 0x38}, | ||
492 | {SENSOR, MT9M111_SC_VBLANK_CONTEXT_A, 0x00, 0x11}, | ||
493 | {SENSOR, MT9M111_SC_R_MODE_CONTEXT_B, 0x01, 0x03}, | ||
494 | {SENSOR, MT9M111_SC_R_MODE_CONTEXT_A, 0x01, 0x03}, | ||
495 | {SENSOR, 0x30, 0x04, 0x00}, | ||
496 | |||
497 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00}, | ||
498 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, | ||
499 | {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, | ||
500 | {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00}, | ||
501 | {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00}, | ||
502 | {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00}, | ||
503 | {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00}, | ||
504 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
505 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
506 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
507 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
508 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x04, 0x00}, | ||
509 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x04, 0x00}, | ||
510 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
511 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
512 | {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00}, | ||
513 | {BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00}, | ||
514 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, | ||
515 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, | ||
516 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x05, 0x00}, | ||
517 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x07, 0x00}, | ||
518 | {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00}, | ||
519 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, | ||
520 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xa0, 0x00}, | ||
521 | {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, | ||
522 | {SENSOR, MT9M111_SC_SHUTTER_WIDTH, 0x01, 0xf4}, | ||
523 | {SENSOR, MT9M111_SC_GLOBAL_GAIN, 0x00, 0xea}, | ||
524 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, | ||
525 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, | ||
526 | |||
527 | {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, | ||
528 | {SENSOR, MT9M111_SC_RESET, 0x00, 0x09}, | ||
529 | {SENSOR, MT9M111_SC_RESET, 0x00, 0x29}, | ||
530 | {SENSOR, MT9M111_SC_RESET, 0x00, 0x08}, | ||
531 | {SENSOR, MT9M111_SC_RESET, 0x00, 0x0c}, | ||
532 | {SENSOR, MT9M111_SC_RESET, 0x00, 0x04}, | ||
533 | {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01}, | ||
534 | |||
535 | {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xb3, 0x00}, | ||
536 | {SENSOR, MT9M111_CP_GLOBAL_CLK_CONTROL, 0x00, 0x03}, | ||
537 | {BRIDGE, M5602_XB_GPIO_DIR, 0x05, 0x00}, | ||
538 | {BRIDGE, M5602_XB_GPIO_DAT, 0x04, 0x00}, | ||
539 | {BRIDGE, M5602_XB_GPIO_EN_H, 0x3e, 0x00}, | ||
540 | {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3e, 0x00}, | ||
541 | {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02, 0x00}, | ||
542 | {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00}, | ||
543 | {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00}, | ||
544 | {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00}, | ||
545 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04, 0x00}, | ||
546 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, | ||
547 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, | ||
548 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, | ||
549 | {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, | ||
550 | {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00}, | ||
551 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, | ||
552 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, | ||
553 | {BRIDGE, M5602_XB_GPIO_DIR, 0x07, 0x00}, | ||
554 | {BRIDGE, M5602_XB_GPIO_DAT, 0x0b, 0x00}, | ||
555 | {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00}, | ||
556 | {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00}, | ||
557 | {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x0a, 0x00}, | ||
558 | |||
559 | {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, | ||
560 | {SENSOR, MT9M111_SC_RESET, 0x00, 0x05}, | ||
561 | {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, | ||
562 | {SENSOR, MT9M111_SC_RESET, 0x00, 0x29}, | ||
563 | {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, | ||
564 | {SENSOR, MT9M111_SC_RESET, 0x00, 0x08}, | ||
565 | {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01}, | ||
566 | {SENSOR, MT9M111_CP_OPERATING_MODE_CTL, 0x00, 0x10}, | ||
567 | {SENSOR, MT9M111_CP_LENS_CORRECTION_1, 0x04, 0x2a}, | ||
568 | {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_A, 0x00, 0x01}, | ||
569 | {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_B, 0x00, 0x01}, | ||
570 | {SENSOR, MT9M111_CP_LUMA_OFFSET, 0x00, 0x00}, | ||
571 | {SENSOR, MT9M111_CP_LUMA_CLIP, 0xff, 0x00}, | ||
572 | {SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_A, 0x14, 0x00}, | ||
573 | {SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_B, 0x14, 0x00}, | ||
574 | |||
575 | {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xcd, 0x00}, | ||
576 | {SENSOR, 0xcd, 0x00, 0x0e}, | ||
577 | {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xd0, 0x00}, | ||
578 | {SENSOR, 0xd0, 0x00, 0x40}, | ||
579 | {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x02}, | ||
580 | {SENSOR, MT9M111_CC_AUTO_EXPOSURE_PARAMETER_18, 0x00, 0x00}, | ||
581 | {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x28, 0x00}, | ||
582 | {SENSOR, MT9M111_CC_AWB_PARAMETER_7, 0xef, 0x07}, | ||
583 | {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x28, 0x00}, | ||
584 | {SENSOR, MT9M111_CC_AWB_PARAMETER_7, 0xef, 0x03}, | ||
585 | {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, | ||
586 | {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x33, 0x00}, | ||
587 | {SENSOR, 0x33, 0x03, 0x49}, | ||
588 | {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x33, 0x00}, | ||
589 | |||
590 | {SENSOR, 0x33, 0x03, 0x49}, | ||
591 | {SENSOR, 0x34, 0xc0, 0x19}, | ||
592 | {SENSOR, 0x3f, 0x20, 0x20}, | ||
593 | {SENSOR, 0x40, 0x20, 0x20}, | ||
594 | {SENSOR, 0x5a, 0xc0, 0x0a}, | ||
595 | {SENSOR, 0x70, 0x7b, 0x0a}, | ||
596 | {SENSOR, 0x71, 0xff, 0x00}, | ||
597 | {SENSOR, 0x72, 0x19, 0x0e}, | ||
598 | {SENSOR, 0x73, 0x18, 0x0f}, | ||
599 | {SENSOR, 0x74, 0x57, 0x32}, | ||
600 | {SENSOR, 0x75, 0x56, 0x34}, | ||
601 | {SENSOR, 0x76, 0x73, 0x35}, | ||
602 | {SENSOR, 0x77, 0x30, 0x12}, | ||
603 | {SENSOR, 0x78, 0x79, 0x02}, | ||
604 | {SENSOR, 0x79, 0x75, 0x06}, | ||
605 | {SENSOR, 0x7a, 0x77, 0x0a}, | ||
606 | {SENSOR, 0x7b, 0x78, 0x09}, | ||
607 | {SENSOR, 0x7c, 0x7d, 0x06}, | ||
608 | {SENSOR, 0x7d, 0x31, 0x10}, | ||
609 | {SENSOR, 0x7e, 0x00, 0x7e}, | ||
610 | {SENSOR, 0x80, 0x59, 0x04}, | ||
611 | {SENSOR, 0x81, 0x59, 0x04}, | ||
612 | {SENSOR, 0x82, 0x57, 0x0a}, | ||
613 | {SENSOR, 0x83, 0x58, 0x0b}, | ||
614 | {SENSOR, 0x84, 0x47, 0x0c}, | ||
615 | {SENSOR, 0x85, 0x48, 0x0e}, | ||
616 | {SENSOR, 0x86, 0x5b, 0x02}, | ||
617 | {SENSOR, 0x87, 0x00, 0x5c}, | ||
618 | {SENSOR, MT9M111_CONTEXT_CONTROL, 0x00, 0x08}, | ||
619 | {SENSOR, 0x60, 0x00, 0x80}, | ||
620 | {SENSOR, 0x61, 0x00, 0x00}, | ||
621 | {SENSOR, 0x62, 0x00, 0x00}, | ||
622 | {SENSOR, 0x63, 0x00, 0x00}, | ||
623 | {SENSOR, 0x64, 0x00, 0x00}, | ||
624 | |||
625 | {SENSOR, MT9M111_SC_ROWSTART, 0x00, 0x0d}, | ||
626 | {SENSOR, MT9M111_SC_COLSTART, 0x00, 0x18}, | ||
627 | {SENSOR, MT9M111_SC_WINDOW_HEIGHT, 0x04, 0x04}, | ||
628 | {SENSOR, MT9M111_SC_WINDOW_WIDTH, 0x05, 0x08}, | ||
629 | {SENSOR, MT9M111_SC_HBLANK_CONTEXT_B, 0x01, 0x38}, | ||
630 | {SENSOR, MT9M111_SC_VBLANK_CONTEXT_B, 0x00, 0x11}, | ||
631 | {SENSOR, MT9M111_SC_HBLANK_CONTEXT_A, 0x01, 0x38}, | ||
632 | {SENSOR, MT9M111_SC_VBLANK_CONTEXT_A, 0x00, 0x11}, | ||
633 | {SENSOR, MT9M111_SC_R_MODE_CONTEXT_B, 0x01, 0x03}, | ||
634 | {SENSOR, MT9M111_SC_R_MODE_CONTEXT_A, 0x01, 0x03}, | ||
635 | {SENSOR, 0x30, 0x04, 0x00}, | ||
636 | |||
637 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00}, | ||
638 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, | ||
639 | {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, | ||
640 | {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00}, | ||
641 | {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00}, | ||
642 | {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00}, | ||
643 | {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00}, | ||
644 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
645 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
646 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
647 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
648 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x04, 0x00}, | ||
649 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x04, 0x00}, | ||
650 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
651 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
652 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, | ||
653 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, | ||
654 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x05, 0x00}, | ||
655 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x07, 0x00}, | ||
656 | {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00}, | ||
657 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, | ||
658 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xa0, 0x00}, | ||
659 | {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, | ||
660 | {SENSOR, MT9M111_SC_SHUTTER_WIDTH, 0x01, 0xf4}, | ||
661 | {SENSOR, MT9M111_SC_GLOBAL_GAIN, 0x00, 0xea}, | ||
662 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, | ||
663 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, | ||
664 | {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, | ||
665 | {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, | ||
666 | {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00}, | ||
667 | {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, | ||
668 | {SENSOR, MT9M111_SC_RESET, 0x00, 0x09}, | ||
669 | {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, | ||
670 | {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00}, | ||
671 | {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, | ||
672 | {SENSOR, MT9M111_SC_RESET, 0x00, 0x29}, | ||
673 | {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, | ||
674 | {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00}, | ||
675 | {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, | ||
676 | {SENSOR, MT9M111_SC_RESET, 0x00, 0x08}, | ||
677 | {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, | ||
678 | {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00}, | ||
679 | {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, | ||
680 | {SENSOR, MT9M111_SC_RESET, 0x00, 0x0c}, | ||
681 | {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, | ||
682 | {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00}, | ||
683 | {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, | ||
684 | {SENSOR, MT9M111_SC_RESET, 0x00, 0x04}, | ||
685 | {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01}, | ||
686 | {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, | ||
687 | {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xb3, 0x00}, | ||
688 | {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, | ||
689 | {SENSOR, MT9M111_CP_GLOBAL_CLK_CONTROL, 0x00, 0x03}, | ||
690 | {BRIDGE, M5602_XB_GPIO_DIR, 0x05, 0x00}, | ||
691 | {BRIDGE, M5602_XB_GPIO_DAT, 0x04, 0x00}, | ||
692 | {BRIDGE, M5602_XB_GPIO_EN_H, 0x3e, 0x00}, | ||
693 | {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3e, 0x00}, | ||
694 | {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02, 0x00}, | ||
695 | {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00}, | ||
696 | {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00}, | ||
697 | {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00}, | ||
698 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04, 0x00}, | ||
699 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, | ||
700 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, | ||
701 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, | ||
702 | {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, | ||
703 | {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00}, | ||
704 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, | ||
705 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, | ||
706 | {BRIDGE, M5602_XB_GPIO_DIR, 0x07, 0x00}, | ||
707 | {BRIDGE, M5602_XB_GPIO_DAT, 0x0b, 0x00}, | ||
708 | {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00}, | ||
709 | {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00}, | ||
710 | {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x0a, 0x00}, | ||
711 | {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, | ||
712 | {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, | ||
713 | {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00}, | ||
714 | {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, | ||
715 | {SENSOR, MT9M111_SC_RESET, 0x00, 0x05}, | ||
716 | {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, | ||
717 | {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, | ||
718 | {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00}, | ||
719 | {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, | ||
720 | {SENSOR, MT9M111_SC_RESET, 0x00, 0x29}, | ||
721 | {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, | ||
722 | {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, | ||
723 | {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00}, | ||
724 | {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, | ||
725 | |||
726 | {SENSOR, MT9M111_SC_RESET, 0x00, 0x08}, | ||
727 | {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01}, | ||
728 | {SENSOR, MT9M111_CP_OPERATING_MODE_CTL, 0x00, 0x10}, | ||
729 | {SENSOR, MT9M111_CP_LENS_CORRECTION_1, 0x04, 0x2a}, | ||
730 | {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_A, 0x00, 0x01}, | ||
731 | {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_B, 0x00, 0x01}, | ||
732 | {SENSOR, MT9M111_CP_LUMA_OFFSET, 0x00, 0x00}, | ||
733 | {SENSOR, MT9M111_CP_LUMA_CLIP, 0xff, 0x00}, | ||
734 | {SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_A, 0x14, 0x00}, | ||
735 | {SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_B, 0x14, 0x00}, | ||
736 | |||
737 | {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, | ||
738 | {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xcd, 0x00}, | ||
739 | {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, | ||
740 | {SENSOR, 0xcd, 0x00, 0x0e}, | ||
741 | {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, | ||
742 | {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xd0, 0x00}, | ||
743 | {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, | ||
744 | {SENSOR, 0xd0, 0x00, 0x40}, | ||
745 | {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x02}, | ||
746 | {SENSOR, MT9M111_CC_AUTO_EXPOSURE_PARAMETER_18, 0x00, 0x00}, | ||
747 | {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, | ||
748 | {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x28, 0x00}, | ||
749 | {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, | ||
750 | {SENSOR, MT9M111_CC_AWB_PARAMETER_7, 0xef, 0x07}, | ||
751 | {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, | ||
752 | {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x28, 0x00}, | ||
753 | {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, | ||
754 | {SENSOR, MT9M111_CC_AWB_PARAMETER_7, 0xef, 0x03}, | ||
755 | {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, | ||
756 | {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, | ||
757 | {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x33, 0x00}, | ||
758 | {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, | ||
759 | {SENSOR, 0x33, 0x03, 0x49}, | ||
760 | {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, | ||
761 | {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x33, 0x00}, | ||
762 | {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, | ||
763 | |||
764 | {SENSOR, 0x33, 0x03, 0x49}, | ||
765 | {SENSOR, 0x34, 0xc0, 0x19}, | ||
766 | {SENSOR, 0x3f, 0x20, 0x20}, | ||
767 | {SENSOR, 0x40, 0x20, 0x20}, | ||
768 | {SENSOR, 0x5a, 0xc0, 0x0a}, | ||
769 | {SENSOR, 0x70, 0x7b, 0x0a}, | ||
770 | {SENSOR, 0x71, 0xff, 0x00}, | ||
771 | {SENSOR, 0x72, 0x19, 0x0e}, | ||
772 | {SENSOR, 0x73, 0x18, 0x0f}, | ||
773 | {SENSOR, 0x74, 0x57, 0x32}, | ||
774 | {SENSOR, 0x75, 0x56, 0x34}, | ||
775 | {SENSOR, 0x76, 0x73, 0x35}, | ||
776 | {SENSOR, 0x77, 0x30, 0x12}, | ||
777 | {SENSOR, 0x78, 0x79, 0x02}, | ||
778 | {SENSOR, 0x79, 0x75, 0x06}, | ||
779 | {SENSOR, 0x7a, 0x77, 0x0a}, | ||
780 | {SENSOR, 0x7b, 0x78, 0x09}, | ||
781 | {SENSOR, 0x7c, 0x7d, 0x06}, | ||
782 | {SENSOR, 0x7d, 0x31, 0x10}, | ||
783 | {SENSOR, 0x7e, 0x00, 0x7e}, | ||
784 | {SENSOR, 0x80, 0x59, 0x04}, | ||
785 | {SENSOR, 0x81, 0x59, 0x04}, | ||
786 | {SENSOR, 0x82, 0x57, 0x0a}, | ||
787 | {SENSOR, 0x83, 0x58, 0x0b}, | ||
788 | {SENSOR, 0x84, 0x47, 0x0c}, | ||
789 | {SENSOR, 0x85, 0x48, 0x0e}, | ||
790 | {SENSOR, 0x86, 0x5b, 0x02}, | ||
791 | {SENSOR, 0x87, 0x00, 0x5c}, | ||
792 | {SENSOR, MT9M111_CONTEXT_CONTROL, 0x00, 0x08}, | ||
793 | {SENSOR, 0x60, 0x00, 0x80}, | ||
794 | {SENSOR, 0x61, 0x00, 0x00}, | ||
795 | {SENSOR, 0x62, 0x00, 0x00}, | ||
796 | {SENSOR, 0x63, 0x00, 0x00}, | ||
797 | {SENSOR, 0x64, 0x00, 0x00}, | ||
798 | {SENSOR, MT9M111_SC_ROWSTART, 0x00, 0x0d}, | ||
799 | {SENSOR, MT9M111_SC_COLSTART, 0x00, 0x12}, | ||
800 | {SENSOR, MT9M111_SC_WINDOW_HEIGHT, 0x04, 0x00}, | ||
801 | {SENSOR, MT9M111_SC_WINDOW_WIDTH, 0x05, 0x10}, | ||
802 | {SENSOR, MT9M111_SC_HBLANK_CONTEXT_B, 0x01, 0x60}, | ||
803 | {SENSOR, MT9M111_SC_VBLANK_CONTEXT_B, 0x00, 0x11}, | ||
804 | {SENSOR, MT9M111_SC_HBLANK_CONTEXT_A, 0x01, 0x60}, | ||
805 | {SENSOR, MT9M111_SC_VBLANK_CONTEXT_A, 0x00, 0x11}, | ||
806 | {SENSOR, MT9M111_SC_R_MODE_CONTEXT_B, 0x01, 0x0f}, | ||
807 | {SENSOR, MT9M111_SC_R_MODE_CONTEXT_A, 0x01, 0x0f}, | ||
808 | {SENSOR, 0x30, 0x04, 0x00}, | ||
809 | |||
810 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00}, | ||
811 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, | ||
812 | {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, | ||
813 | {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00}, | ||
814 | {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00}, | ||
815 | {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00}, | ||
816 | {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00}, | ||
817 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
818 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
819 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
820 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
821 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x01, 0x00}, | ||
822 | {BRIDGE, M5602_XB_VSYNC_PARA, 0xe3, 0x00}, | ||
823 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
824 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
825 | {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00}, | ||
826 | {BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00}, | ||
827 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, | ||
828 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, | ||
829 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x02, 0x00}, | ||
830 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x87, 0x00}, | ||
831 | {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00}, | ||
832 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, | ||
833 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, | ||
834 | |||
835 | {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, | ||
836 | {SENSOR, MT9M111_SC_SHUTTER_WIDTH, 0x01, 0x90}, | ||
837 | {SENSOR, MT9M111_SC_GLOBAL_GAIN, 0x00, 0xe6}, | ||
838 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, | ||
839 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, | ||
840 | {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, | ||
841 | {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, | ||
842 | {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00}, | ||
843 | {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, | ||
844 | {SENSOR, MT9M111_SC_RESET, 0x00, 0x09}, | ||
845 | {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, | ||
846 | {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00}, | ||
847 | {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, | ||
848 | {SENSOR, MT9M111_SC_RESET, 0x00, 0x29}, | ||
849 | {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, | ||
850 | {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00}, | ||
851 | {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, | ||
852 | {SENSOR, MT9M111_SC_RESET, 0x00, 0x08}, | ||
853 | {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, | ||
854 | {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00}, | ||
855 | {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, | ||
856 | {SENSOR, MT9M111_SC_RESET, 0x00, 0x0c}, | ||
857 | {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, | ||
858 | {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00}, | ||
859 | {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, | ||
860 | {SENSOR, MT9M111_SC_RESET, 0x00, 0x04}, | ||
861 | {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01}, | ||
862 | {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, | ||
863 | {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xb3, 0x00}, | ||
864 | {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, | ||
865 | {SENSOR, MT9M111_CP_GLOBAL_CLK_CONTROL, 0x00, 0x03}, | ||
866 | |||
867 | {BRIDGE, M5602_XB_GPIO_DIR, 0x05, 0x00}, | ||
868 | {BRIDGE, M5602_XB_GPIO_DAT, 0x04, 0x00}, | ||
869 | {BRIDGE, M5602_XB_GPIO_EN_H, 0x3e, 0x00}, | ||
870 | {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3e, 0x00}, | ||
871 | {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02, 0x00}, | ||
872 | {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00}, | ||
873 | {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00}, | ||
874 | {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00}, | ||
875 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04, 0x00}, | ||
876 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, | ||
877 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, | ||
878 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, | ||
879 | {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, | ||
880 | {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00}, | ||
881 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, | ||
882 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, | ||
883 | {BRIDGE, M5602_XB_GPIO_DIR, 0x07, 0x00}, | ||
884 | {BRIDGE, M5602_XB_GPIO_DAT, 0x0b, 0x00}, | ||
885 | {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00}, | ||
886 | {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00}, | ||
887 | {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x0a, 0x00}, | ||
888 | {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, | ||
889 | {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, | ||
890 | {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00}, | ||
891 | {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, | ||
892 | {SENSOR, MT9M111_SC_RESET, 0x00, 0x05}, | ||
893 | {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, | ||
894 | {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, | ||
895 | {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00}, | ||
896 | {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, | ||
897 | {SENSOR, MT9M111_SC_RESET, 0x00, 0x29}, | ||
898 | {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, | ||
899 | {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, | ||
900 | {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00}, | ||
901 | {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, | ||
902 | {SENSOR, MT9M111_SC_RESET, 0x00, 0x08}, | ||
903 | {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01}, | ||
904 | {SENSOR, MT9M111_CP_OPERATING_MODE_CTL, 0x00, 0x10}, | ||
905 | {SENSOR, MT9M111_CP_LENS_CORRECTION_1, 0x04, 0x2a}, | ||
906 | {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_A, 0x00, 0x01}, | ||
907 | {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_B, 0x00, 0x01}, | ||
908 | {SENSOR, MT9M111_CP_LUMA_OFFSET, 0x00, 0x00}, | ||
909 | {SENSOR, MT9M111_CP_LUMA_CLIP, 0xff, 0x00}, | ||
910 | {SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_A, 0x14, 0x00}, | ||
911 | {SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_B, 0x14, 0x00}, | ||
912 | |||
913 | {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, | ||
914 | {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xcd, 0x00}, | ||
915 | {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, | ||
916 | {SENSOR, 0xcd, 0x00, 0x0e}, | ||
917 | {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, | ||
918 | {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xd0, 0x00}, | ||
919 | {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, | ||
920 | {SENSOR, 0xd0, 0x00, 0x40}, | ||
921 | {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x02}, | ||
922 | {SENSOR, MT9M111_CC_AUTO_EXPOSURE_PARAMETER_18, 0x00, 0x00}, | ||
923 | {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, | ||
924 | {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x28, 0x00}, | ||
925 | {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, | ||
926 | {SENSOR, MT9M111_CC_AWB_PARAMETER_7, 0xef, 0x07}, | ||
927 | {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, | ||
928 | {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x28, 0x00}, | ||
929 | {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, | ||
930 | {SENSOR, MT9M111_CC_AWB_PARAMETER_7, 0xef, 0x03}, | ||
931 | {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, | ||
932 | |||
933 | {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, | ||
934 | {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x33, 0x00}, | ||
935 | {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, | ||
936 | {SENSOR, 0x33, 0x03, 0x49}, | ||
937 | {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, | ||
938 | {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x33, 0x00}, | ||
939 | {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, | ||
940 | |||
941 | {SENSOR, 0x33, 0x03, 0x49}, | ||
942 | {SENSOR, 0x34, 0xc0, 0x19}, | ||
943 | {SENSOR, 0x3f, 0x20, 0x20}, | ||
944 | {SENSOR, 0x40, 0x20, 0x20}, | ||
945 | {SENSOR, 0x5a, 0xc0, 0x0a}, | ||
946 | {SENSOR, 0x70, 0x7b, 0x0a}, | ||
947 | {SENSOR, 0x71, 0xff, 0x00}, | ||
948 | {SENSOR, 0x72, 0x19, 0x0e}, | ||
949 | {SENSOR, 0x73, 0x18, 0x0f}, | ||
950 | {SENSOR, 0x74, 0x57, 0x32}, | ||
951 | {SENSOR, 0x75, 0x56, 0x34}, | ||
952 | {SENSOR, 0x76, 0x73, 0x35}, | ||
953 | {SENSOR, 0x77, 0x30, 0x12}, | ||
954 | {SENSOR, 0x78, 0x79, 0x02}, | ||
955 | {SENSOR, 0x79, 0x75, 0x06}, | ||
956 | {SENSOR, 0x7a, 0x77, 0x0a}, | ||
957 | {SENSOR, 0x7b, 0x78, 0x09}, | ||
958 | {SENSOR, 0x7c, 0x7d, 0x06}, | ||
959 | {SENSOR, 0x7d, 0x31, 0x10}, | ||
960 | {SENSOR, 0x7e, 0x00, 0x7e}, | ||
961 | {SENSOR, 0x80, 0x59, 0x04}, | ||
962 | {SENSOR, 0x81, 0x59, 0x04}, | ||
963 | {SENSOR, 0x82, 0x57, 0x0a}, | ||
964 | {SENSOR, 0x83, 0x58, 0x0b}, | ||
965 | {SENSOR, 0x84, 0x47, 0x0c}, | ||
966 | {SENSOR, 0x85, 0x48, 0x0e}, | ||
967 | {SENSOR, 0x86, 0x5b, 0x02}, | ||
968 | {SENSOR, 0x87, 0x00, 0x5c}, | ||
969 | {SENSOR, MT9M111_CONTEXT_CONTROL, 0x00, 0x08}, | ||
970 | {SENSOR, 0x60, 0x00, 0x80}, | ||
971 | {SENSOR, 0x61, 0x00, 0x00}, | ||
972 | {SENSOR, 0x62, 0x00, 0x00}, | ||
973 | {SENSOR, 0x63, 0x00, 0x00}, | ||
974 | {SENSOR, 0x64, 0x00, 0x00}, | ||
975 | |||
976 | {SENSOR, MT9M111_SC_ROWSTART, 0x00, 0x0d}, | ||
977 | {SENSOR, MT9M111_SC_COLSTART, 0x00, 0x12}, | ||
978 | {SENSOR, MT9M111_SC_WINDOW_HEIGHT, 0x04, 0x00}, | ||
979 | {SENSOR, MT9M111_SC_WINDOW_WIDTH, 0x05, 0x10}, | ||
980 | {SENSOR, MT9M111_SC_HBLANK_CONTEXT_B, 0x01, 0x60}, | ||
981 | {SENSOR, MT9M111_SC_VBLANK_CONTEXT_B, 0x00, 0x11}, | ||
982 | {SENSOR, MT9M111_SC_HBLANK_CONTEXT_A, 0x01, 0x60}, | ||
983 | {SENSOR, MT9M111_SC_VBLANK_CONTEXT_A, 0x00, 0x11}, | ||
984 | {SENSOR, MT9M111_SC_R_MODE_CONTEXT_B, 0x01, 0x0f}, | ||
985 | {SENSOR, MT9M111_SC_R_MODE_CONTEXT_A, 0x01, 0x0f}, | ||
986 | {SENSOR, 0x30, 0x04, 0x00}, | ||
987 | |||
988 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00}, | ||
989 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, | ||
990 | {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, | ||
991 | {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00}, | ||
992 | {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00}, | ||
993 | {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00}, | ||
994 | {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00}, | ||
995 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
996 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
997 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
998 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
999 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x01, 0x00}, | ||
1000 | {BRIDGE, M5602_XB_VSYNC_PARA, 0xe0, 0x00}, | ||
1001 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
1002 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
1003 | {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00}, | ||
1004 | {BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00}, | ||
1005 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, | ||
1006 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, | ||
1007 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x02, 0x00}, | ||
1008 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x7f, 0x00}, | ||
1009 | {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00}, | ||
1010 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, | ||
1011 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, | ||
1012 | |||
1013 | {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, | ||
1014 | /* Set number of blank rows chosen to 400 */ | ||
1015 | {SENSOR, MT9M111_SC_SHUTTER_WIDTH, 0x01, 0x90}, | ||
1016 | /* Set the global gain to 283 (of 512) */ | ||
1017 | {SENSOR, MT9M111_SC_GLOBAL_GAIN, 0x03, 0x63} | ||
1018 | }; | ||
1019 | |||
1020 | #endif | ||
diff --git a/drivers/media/video/gspca/m5602/m5602_ov9650.c b/drivers/media/video/gspca/m5602/m5602_ov9650.c new file mode 100644 index 000000000000..31c5896250e7 --- /dev/null +++ b/drivers/media/video/gspca/m5602/m5602_ov9650.c | |||
@@ -0,0 +1,546 @@ | |||
1 | /* | ||
2 | * Driver for the ov9650 sensor | ||
3 | * | ||
4 | * Copyright (C) 2008 Erik Andren | ||
5 | * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project. | ||
6 | * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br> | ||
7 | * | ||
8 | * Portions of code to USB interface and ALi driver software, | ||
9 | * Copyright (c) 2006 Willem Duinker | ||
10 | * v4l2 interface modeled after the V4L2 driver | ||
11 | * for SN9C10x PC Camera Controllers | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or | ||
14 | * modify it under the terms of the GNU General Public License as | ||
15 | * published by the Free Software Foundation, version 2. | ||
16 | * | ||
17 | */ | ||
18 | |||
19 | #include "m5602_ov9650.h" | ||
20 | |||
21 | int ov9650_read_sensor(struct sd *sd, const u8 address, | ||
22 | u8 *i2c_data, const u8 len) | ||
23 | { | ||
24 | int err, i; | ||
25 | |||
26 | /* The ov9650 registers have a max depth of one byte */ | ||
27 | if (len > 1 || !len) | ||
28 | return -EINVAL; | ||
29 | |||
30 | do { | ||
31 | err = m5602_read_bridge(sd, M5602_XB_I2C_STATUS, i2c_data); | ||
32 | } while ((*i2c_data & I2C_BUSY) && !err); | ||
33 | |||
34 | m5602_write_bridge(sd, M5602_XB_I2C_DEV_ADDR, | ||
35 | ov9650.i2c_slave_id); | ||
36 | m5602_write_bridge(sd, M5602_XB_I2C_REG_ADDR, address); | ||
37 | m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 0x10 + len); | ||
38 | m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 0x08); | ||
39 | |||
40 | for (i = 0; i < len; i++) { | ||
41 | err = m5602_read_bridge(sd, M5602_XB_I2C_DATA, &(i2c_data[i])); | ||
42 | |||
43 | PDEBUG(DBG_TRACE, "Reading sensor register " | ||
44 | "0x%x containing 0x%x ", address, *i2c_data); | ||
45 | } | ||
46 | return (err < 0) ? err : 0; | ||
47 | } | ||
48 | |||
49 | int ov9650_write_sensor(struct sd *sd, const u8 address, | ||
50 | u8 *i2c_data, const u8 len) | ||
51 | { | ||
52 | int err, i; | ||
53 | u8 *p; | ||
54 | struct usb_device *udev = sd->gspca_dev.dev; | ||
55 | __u8 *buf = sd->gspca_dev.usb_buf; | ||
56 | |||
57 | /* The ov9650 only supports one byte writes */ | ||
58 | if (len > 1 || !len) | ||
59 | return -EINVAL; | ||
60 | |||
61 | memcpy(buf, sensor_urb_skeleton, | ||
62 | sizeof(sensor_urb_skeleton)); | ||
63 | |||
64 | buf[11] = sd->sensor->i2c_slave_id; | ||
65 | buf[15] = address; | ||
66 | |||
67 | /* Special case larger sensor writes */ | ||
68 | p = buf + 16; | ||
69 | |||
70 | /* Copy a four byte write sequence for each byte to be written to */ | ||
71 | for (i = 0; i < len; i++) { | ||
72 | memcpy(p, sensor_urb_skeleton + 16, 4); | ||
73 | p[3] = i2c_data[i]; | ||
74 | p += 4; | ||
75 | PDEBUG(DBG_TRACE, "Writing sensor register 0x%x with 0x%x", | ||
76 | address, i2c_data[i]); | ||
77 | } | ||
78 | |||
79 | /* Copy the tailer */ | ||
80 | memcpy(p, sensor_urb_skeleton + 20, 4); | ||
81 | |||
82 | /* Set the total length */ | ||
83 | p[3] = 0x10 + len; | ||
84 | |||
85 | err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), | ||
86 | 0x04, 0x40, 0x19, | ||
87 | 0x0000, buf, | ||
88 | 20 + len * 4, M5602_URB_MSG_TIMEOUT); | ||
89 | |||
90 | return (err < 0) ? err : 0; | ||
91 | } | ||
92 | |||
93 | int ov9650_probe(struct sd *sd) | ||
94 | { | ||
95 | u8 prod_id = 0, ver_id = 0, i; | ||
96 | |||
97 | if (force_sensor) { | ||
98 | if (force_sensor == OV9650_SENSOR) { | ||
99 | info("Forcing an %s sensor", ov9650.name); | ||
100 | goto sensor_found; | ||
101 | } | ||
102 | /* If we want to force another sensor, | ||
103 | don't try to probe this one */ | ||
104 | return -ENODEV; | ||
105 | } | ||
106 | |||
107 | info("Probing for an ov9650 sensor"); | ||
108 | |||
109 | /* Run the pre-init to actually probe the unit */ | ||
110 | for (i = 0; i < ARRAY_SIZE(preinit_ov9650); i++) { | ||
111 | u8 data = preinit_ov9650[i][2]; | ||
112 | if (preinit_ov9650[i][0] == SENSOR) | ||
113 | ov9650_write_sensor(sd, | ||
114 | preinit_ov9650[i][1], &data, 1); | ||
115 | else | ||
116 | m5602_write_bridge(sd, preinit_ov9650[i][1], data); | ||
117 | } | ||
118 | |||
119 | if (ov9650_read_sensor(sd, OV9650_PID, &prod_id, 1)) | ||
120 | return -ENODEV; | ||
121 | |||
122 | if (ov9650_read_sensor(sd, OV9650_VER, &ver_id, 1)) | ||
123 | return -ENODEV; | ||
124 | |||
125 | if ((prod_id == 0x96) && (ver_id == 0x52)) { | ||
126 | info("Detected an ov9650 sensor"); | ||
127 | goto sensor_found; | ||
128 | } | ||
129 | |||
130 | return -ENODEV; | ||
131 | |||
132 | sensor_found: | ||
133 | sd->gspca_dev.cam.cam_mode = ov9650.modes; | ||
134 | sd->gspca_dev.cam.nmodes = ov9650.nmodes; | ||
135 | sd->desc->ctrls = ov9650.ctrls; | ||
136 | sd->desc->nctrls = ov9650.nctrls; | ||
137 | return 0; | ||
138 | } | ||
139 | |||
140 | int ov9650_init(struct sd *sd) | ||
141 | { | ||
142 | int i, err = 0; | ||
143 | u8 data; | ||
144 | |||
145 | if (dump_sensor) | ||
146 | ov9650_dump_registers(sd); | ||
147 | |||
148 | for (i = 0; i < ARRAY_SIZE(init_ov9650) && !err; i++) { | ||
149 | data = init_ov9650[i][2]; | ||
150 | if (init_ov9650[i][0] == SENSOR) | ||
151 | err = ov9650_write_sensor(sd, init_ov9650[i][1], | ||
152 | &data, 1); | ||
153 | else | ||
154 | err = m5602_write_bridge(sd, init_ov9650[i][1], data); | ||
155 | } | ||
156 | |||
157 | if (!err && dmi_check_system(ov9650_flip_dmi_table)) { | ||
158 | info("vflip quirk active"); | ||
159 | data = 0x30; | ||
160 | err = ov9650_write_sensor(sd, OV9650_MVFP, &data, 1); | ||
161 | } | ||
162 | |||
163 | return (err < 0) ? err : 0; | ||
164 | } | ||
165 | |||
166 | int ov9650_power_down(struct sd *sd) | ||
167 | { | ||
168 | int i; | ||
169 | for (i = 0; i < ARRAY_SIZE(power_down_ov9650); i++) { | ||
170 | u8 data = power_down_ov9650[i][2]; | ||
171 | if (power_down_ov9650[i][0] == SENSOR) | ||
172 | ov9650_write_sensor(sd, | ||
173 | power_down_ov9650[i][1], &data, 1); | ||
174 | else | ||
175 | m5602_write_bridge(sd, power_down_ov9650[i][1], data); | ||
176 | } | ||
177 | |||
178 | return 0; | ||
179 | } | ||
180 | |||
181 | int ov9650_get_exposure(struct gspca_dev *gspca_dev, __s32 *val) | ||
182 | { | ||
183 | struct sd *sd = (struct sd *) gspca_dev; | ||
184 | u8 i2c_data; | ||
185 | int err; | ||
186 | |||
187 | err = ov9650_read_sensor(sd, OV9650_COM1, &i2c_data, 1); | ||
188 | if (err < 0) | ||
189 | goto out; | ||
190 | *val = i2c_data & 0x03; | ||
191 | |||
192 | err = ov9650_read_sensor(sd, OV9650_AECH, &i2c_data, 1); | ||
193 | if (err < 0) | ||
194 | goto out; | ||
195 | *val |= (i2c_data << 2); | ||
196 | |||
197 | err = ov9650_read_sensor(sd, OV9650_AECHM, &i2c_data, 1); | ||
198 | if (err < 0) | ||
199 | goto out; | ||
200 | *val |= (i2c_data & 0x3f) << 10; | ||
201 | |||
202 | PDEBUG(DBG_V4L2_CID, "Read exposure %d", *val); | ||
203 | out: | ||
204 | return (err < 0) ? err : 0; | ||
205 | } | ||
206 | |||
207 | int ov9650_set_exposure(struct gspca_dev *gspca_dev, __s32 val) | ||
208 | { | ||
209 | struct sd *sd = (struct sd *) gspca_dev; | ||
210 | u8 i2c_data; | ||
211 | int err; | ||
212 | |||
213 | PDEBUG(DBG_V4L2_CID, "Set exposure to %d", | ||
214 | val & 0xffff); | ||
215 | |||
216 | /* The 6 MSBs */ | ||
217 | i2c_data = (val >> 10) & 0x3f; | ||
218 | err = ov9650_write_sensor(sd, OV9650_AECHM, | ||
219 | &i2c_data, 1); | ||
220 | if (err < 0) | ||
221 | goto out; | ||
222 | |||
223 | /* The 8 middle bits */ | ||
224 | i2c_data = (val >> 2) & 0xff; | ||
225 | err = ov9650_write_sensor(sd, OV9650_AECH, | ||
226 | &i2c_data, 1); | ||
227 | if (err < 0) | ||
228 | goto out; | ||
229 | |||
230 | /* The 2 LSBs */ | ||
231 | i2c_data = val & 0x03; | ||
232 | err = ov9650_write_sensor(sd, OV9650_COM1, &i2c_data, 1); | ||
233 | |||
234 | out: | ||
235 | return (err < 0) ? err : 0; | ||
236 | } | ||
237 | |||
238 | int ov9650_get_gain(struct gspca_dev *gspca_dev, __s32 *val) | ||
239 | { | ||
240 | int err; | ||
241 | u8 i2c_data; | ||
242 | struct sd *sd = (struct sd *) gspca_dev; | ||
243 | |||
244 | ov9650_read_sensor(sd, OV9650_VREF, &i2c_data, 1); | ||
245 | *val = (i2c_data & 0x03) << 8; | ||
246 | |||
247 | err = ov9650_read_sensor(sd, OV9650_GAIN, &i2c_data, 1); | ||
248 | *val |= i2c_data; | ||
249 | PDEBUG(DBG_V4L2_CID, "Read gain %d", *val); | ||
250 | return (err < 0) ? err : 0; | ||
251 | } | ||
252 | |||
253 | int ov9650_set_gain(struct gspca_dev *gspca_dev, __s32 val) | ||
254 | { | ||
255 | int err; | ||
256 | u8 i2c_data; | ||
257 | struct sd *sd = (struct sd *) gspca_dev; | ||
258 | |||
259 | /* The 2 MSB */ | ||
260 | /* Read the OV9650_VREF register first to avoid | ||
261 | corrupting the VREF high and low bits */ | ||
262 | ov9650_read_sensor(sd, OV9650_VREF, &i2c_data, 1); | ||
263 | /* Mask away all uninteresting bits */ | ||
264 | i2c_data = ((val & 0x0300) >> 2) | | ||
265 | (i2c_data & 0x3F); | ||
266 | err = ov9650_write_sensor(sd, OV9650_VREF, &i2c_data, 1); | ||
267 | |||
268 | /* The 8 LSBs */ | ||
269 | i2c_data = val & 0xff; | ||
270 | err = ov9650_write_sensor(sd, OV9650_GAIN, &i2c_data, 1); | ||
271 | return (err < 0) ? err : 0; | ||
272 | } | ||
273 | |||
274 | int ov9650_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val) | ||
275 | { | ||
276 | int err; | ||
277 | u8 i2c_data; | ||
278 | struct sd *sd = (struct sd *) gspca_dev; | ||
279 | |||
280 | err = ov9650_read_sensor(sd, OV9650_RED, &i2c_data, 1); | ||
281 | *val = i2c_data; | ||
282 | |||
283 | PDEBUG(DBG_V4L2_CID, "Read red gain %d", *val); | ||
284 | |||
285 | return (err < 0) ? err : 0; | ||
286 | } | ||
287 | |||
288 | int ov9650_set_red_balance(struct gspca_dev *gspca_dev, __s32 val) | ||
289 | { | ||
290 | int err; | ||
291 | u8 i2c_data; | ||
292 | struct sd *sd = (struct sd *) gspca_dev; | ||
293 | |||
294 | PDEBUG(DBG_V4L2_CID, "Set red gain to %d", | ||
295 | val & 0xff); | ||
296 | |||
297 | i2c_data = val & 0xff; | ||
298 | err = ov9650_write_sensor(sd, OV9650_RED, &i2c_data, 1); | ||
299 | |||
300 | return (err < 0) ? err : 0; | ||
301 | } | ||
302 | |||
303 | int ov9650_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val) | ||
304 | { | ||
305 | int err; | ||
306 | u8 i2c_data; | ||
307 | struct sd *sd = (struct sd *) gspca_dev; | ||
308 | |||
309 | err = ov9650_read_sensor(sd, OV9650_BLUE, &i2c_data, 1); | ||
310 | *val = i2c_data; | ||
311 | |||
312 | PDEBUG(DBG_V4L2_CID, "Read blue gain %d", *val); | ||
313 | |||
314 | return (err < 0) ? err : 0; | ||
315 | } | ||
316 | |||
317 | int ov9650_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val) | ||
318 | { | ||
319 | int err; | ||
320 | u8 i2c_data; | ||
321 | struct sd *sd = (struct sd *) gspca_dev; | ||
322 | |||
323 | PDEBUG(DBG_V4L2_CID, "Set blue gain to %d", | ||
324 | val & 0xff); | ||
325 | |||
326 | i2c_data = val & 0xff; | ||
327 | err = ov9650_write_sensor(sd, OV9650_BLUE, &i2c_data, 1); | ||
328 | |||
329 | return (err < 0) ? err : 0; | ||
330 | } | ||
331 | |||
332 | int ov9650_get_hflip(struct gspca_dev *gspca_dev, __s32 *val) | ||
333 | { | ||
334 | int err; | ||
335 | u8 i2c_data; | ||
336 | struct sd *sd = (struct sd *) gspca_dev; | ||
337 | |||
338 | err = ov9650_read_sensor(sd, OV9650_MVFP, &i2c_data, 1); | ||
339 | if (dmi_check_system(ov9650_flip_dmi_table)) | ||
340 | *val = ((i2c_data & OV9650_HFLIP) >> 5) ? 0 : 1; | ||
341 | else | ||
342 | *val = (i2c_data & OV9650_HFLIP) >> 5; | ||
343 | PDEBUG(DBG_V4L2_CID, "Read horizontal flip %d", *val); | ||
344 | |||
345 | return (err < 0) ? err : 0; | ||
346 | } | ||
347 | |||
348 | int ov9650_set_hflip(struct gspca_dev *gspca_dev, __s32 val) | ||
349 | { | ||
350 | int err; | ||
351 | u8 i2c_data; | ||
352 | struct sd *sd = (struct sd *) gspca_dev; | ||
353 | |||
354 | PDEBUG(DBG_V4L2_CID, "Set horizontal flip to %d", val); | ||
355 | err = ov9650_read_sensor(sd, OV9650_MVFP, &i2c_data, 1); | ||
356 | if (err < 0) | ||
357 | goto out; | ||
358 | |||
359 | if (dmi_check_system(ov9650_flip_dmi_table)) | ||
360 | i2c_data = ((i2c_data & 0xdf) | | ||
361 | (((val ? 0 : 1) & 0x01) << 5)); | ||
362 | else | ||
363 | i2c_data = ((i2c_data & 0xdf) | | ||
364 | ((val & 0x01) << 5)); | ||
365 | |||
366 | err = ov9650_write_sensor(sd, OV9650_MVFP, &i2c_data, 1); | ||
367 | out: | ||
368 | return (err < 0) ? err : 0; | ||
369 | } | ||
370 | |||
371 | int ov9650_get_vflip(struct gspca_dev *gspca_dev, __s32 *val) | ||
372 | { | ||
373 | int err; | ||
374 | u8 i2c_data; | ||
375 | struct sd *sd = (struct sd *) gspca_dev; | ||
376 | |||
377 | err = ov9650_read_sensor(sd, OV9650_MVFP, &i2c_data, 1); | ||
378 | if (dmi_check_system(ov9650_flip_dmi_table)) | ||
379 | *val = ((i2c_data & 0x10) >> 4) ? 0 : 1; | ||
380 | else | ||
381 | *val = (i2c_data & 0x10) >> 4; | ||
382 | PDEBUG(DBG_V4L2_CID, "Read vertical flip %d", *val); | ||
383 | |||
384 | return (err < 0) ? err : 0; | ||
385 | } | ||
386 | |||
387 | int ov9650_set_vflip(struct gspca_dev *gspca_dev, __s32 val) | ||
388 | { | ||
389 | int err; | ||
390 | u8 i2c_data; | ||
391 | struct sd *sd = (struct sd *) gspca_dev; | ||
392 | |||
393 | PDEBUG(DBG_V4L2_CID, "Set vertical flip to %d", val); | ||
394 | err = ov9650_read_sensor(sd, OV9650_MVFP, &i2c_data, 1); | ||
395 | if (err < 0) | ||
396 | goto out; | ||
397 | |||
398 | if (dmi_check_system(ov9650_flip_dmi_table)) | ||
399 | i2c_data = ((i2c_data & 0xef) | | ||
400 | (((val ? 0 : 1) & 0x01) << 4)); | ||
401 | else | ||
402 | i2c_data = ((i2c_data & 0xef) | | ||
403 | ((val & 0x01) << 4)); | ||
404 | |||
405 | err = ov9650_write_sensor(sd, OV9650_MVFP, &i2c_data, 1); | ||
406 | out: | ||
407 | return (err < 0) ? err : 0; | ||
408 | } | ||
409 | |||
410 | int ov9650_get_brightness(struct gspca_dev *gspca_dev, __s32 *val) | ||
411 | { | ||
412 | int err; | ||
413 | u8 i2c_data; | ||
414 | struct sd *sd = (struct sd *) gspca_dev; | ||
415 | |||
416 | err = ov9650_read_sensor(sd, OV9650_VREF, &i2c_data, 1); | ||
417 | if (err < 0) | ||
418 | goto out; | ||
419 | *val = (i2c_data & 0x03) << 8; | ||
420 | |||
421 | err = ov9650_read_sensor(sd, OV9650_GAIN, &i2c_data, 1); | ||
422 | *val |= i2c_data; | ||
423 | PDEBUG(DBG_V4L2_CID, "Read gain %d", *val); | ||
424 | out: | ||
425 | return (err < 0) ? err : 0; | ||
426 | } | ||
427 | |||
428 | int ov9650_set_brightness(struct gspca_dev *gspca_dev, __s32 val) | ||
429 | { | ||
430 | int err; | ||
431 | u8 i2c_data; | ||
432 | struct sd *sd = (struct sd *) gspca_dev; | ||
433 | |||
434 | PDEBUG(DBG_V4L2_CID, "Set gain to %d", val & 0x3ff); | ||
435 | |||
436 | /* Read the OV9650_VREF register first to avoid | ||
437 | corrupting the VREF high and low bits */ | ||
438 | err = ov9650_read_sensor(sd, OV9650_VREF, &i2c_data, 1); | ||
439 | if (err < 0) | ||
440 | goto out; | ||
441 | |||
442 | /* Mask away all uninteresting bits */ | ||
443 | i2c_data = ((val & 0x0300) >> 2) | (i2c_data & 0x3F); | ||
444 | err = ov9650_write_sensor(sd, OV9650_VREF, &i2c_data, 1); | ||
445 | if (err < 0) | ||
446 | goto out; | ||
447 | |||
448 | /* The 8 LSBs */ | ||
449 | i2c_data = val & 0xff; | ||
450 | err = ov9650_write_sensor(sd, OV9650_GAIN, &i2c_data, 1); | ||
451 | |||
452 | out: | ||
453 | return (err < 0) ? err : 0; | ||
454 | } | ||
455 | |||
456 | int ov9650_get_auto_white_balance(struct gspca_dev *gspca_dev, __s32 *val) | ||
457 | { | ||
458 | int err; | ||
459 | u8 i2c_data; | ||
460 | struct sd *sd = (struct sd *) gspca_dev; | ||
461 | |||
462 | err = ov9650_read_sensor(sd, OV9650_COM8, &i2c_data, 1); | ||
463 | *val = (i2c_data & OV9650_AWB_EN) >> 1; | ||
464 | PDEBUG(DBG_V4L2_CID, "Read auto white balance %d", *val); | ||
465 | |||
466 | return (err < 0) ? err : 0; | ||
467 | } | ||
468 | |||
469 | int ov9650_set_auto_white_balance(struct gspca_dev *gspca_dev, __s32 val) | ||
470 | { | ||
471 | int err; | ||
472 | u8 i2c_data; | ||
473 | struct sd *sd = (struct sd *) gspca_dev; | ||
474 | |||
475 | PDEBUG(DBG_V4L2_CID, "Set auto white balance to %d", val); | ||
476 | err = ov9650_read_sensor(sd, OV9650_COM8, &i2c_data, 1); | ||
477 | if (err < 0) | ||
478 | goto out; | ||
479 | |||
480 | i2c_data = ((i2c_data & 0xfd) | ((val & 0x01) << 1)); | ||
481 | err = ov9650_write_sensor(sd, OV9650_COM8, &i2c_data, 1); | ||
482 | out: | ||
483 | return (err < 0) ? err : 0; | ||
484 | } | ||
485 | |||
486 | int ov9650_get_auto_gain(struct gspca_dev *gspca_dev, __s32 *val) | ||
487 | { | ||
488 | int err; | ||
489 | u8 i2c_data; | ||
490 | struct sd *sd = (struct sd *) gspca_dev; | ||
491 | |||
492 | err = ov9650_read_sensor(sd, OV9650_COM8, &i2c_data, 1); | ||
493 | *val = (i2c_data & OV9650_AGC_EN) >> 2; | ||
494 | PDEBUG(DBG_V4L2_CID, "Read auto gain control %d", *val); | ||
495 | |||
496 | return (err < 0) ? err : 0; | ||
497 | } | ||
498 | |||
499 | int ov9650_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val) | ||
500 | { | ||
501 | int err; | ||
502 | u8 i2c_data; | ||
503 | struct sd *sd = (struct sd *) gspca_dev; | ||
504 | |||
505 | PDEBUG(DBG_V4L2_CID, "Set auto gain control to %d", val); | ||
506 | err = ov9650_read_sensor(sd, OV9650_COM8, &i2c_data, 1); | ||
507 | if (err < 0) | ||
508 | goto out; | ||
509 | |||
510 | i2c_data = ((i2c_data & 0xfb) | ((val & 0x01) << 2)); | ||
511 | err = ov9650_write_sensor(sd, OV9650_COM8, &i2c_data, 1); | ||
512 | out: | ||
513 | return (err < 0) ? err : 0; | ||
514 | } | ||
515 | |||
516 | void ov9650_dump_registers(struct sd *sd) | ||
517 | { | ||
518 | int address; | ||
519 | info("Dumping the ov9650 register state"); | ||
520 | for (address = 0; address < 0xa9; address++) { | ||
521 | u8 value; | ||
522 | ov9650_read_sensor(sd, address, &value, 1); | ||
523 | info("register 0x%x contains 0x%x", | ||
524 | address, value); | ||
525 | } | ||
526 | |||
527 | info("ov9650 register state dump complete"); | ||
528 | |||
529 | info("Probing for which registers that are read/write"); | ||
530 | for (address = 0; address < 0xff; address++) { | ||
531 | u8 old_value, ctrl_value; | ||
532 | u8 test_value[2] = {0xff, 0xff}; | ||
533 | |||
534 | ov9650_read_sensor(sd, address, &old_value, 1); | ||
535 | ov9650_write_sensor(sd, address, test_value, 1); | ||
536 | ov9650_read_sensor(sd, address, &ctrl_value, 1); | ||
537 | |||
538 | if (ctrl_value == test_value[0]) | ||
539 | info("register 0x%x is writeable", address); | ||
540 | else | ||
541 | info("register 0x%x is read only", address); | ||
542 | |||
543 | /* Restore original value */ | ||
544 | ov9650_write_sensor(sd, address, &old_value, 1); | ||
545 | } | ||
546 | } | ||
diff --git a/drivers/media/video/gspca/m5602/m5602_ov9650.h b/drivers/media/video/gspca/m5602/m5602_ov9650.h new file mode 100644 index 000000000000..2f29cb056f30 --- /dev/null +++ b/drivers/media/video/gspca/m5602/m5602_ov9650.h | |||
@@ -0,0 +1,503 @@ | |||
1 | /* | ||
2 | * Driver for the ov9650 sensor | ||
3 | * | ||
4 | * Copyright (C) 2008 Erik Andren | ||
5 | * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project. | ||
6 | * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br> | ||
7 | * | ||
8 | * Portions of code to USB interface and ALi driver software, | ||
9 | * Copyright (c) 2006 Willem Duinker | ||
10 | * v4l2 interface modeled after the V4L2 driver | ||
11 | * for SN9C10x PC Camera Controllers | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or | ||
14 | * modify it under the terms of the GNU General Public License as | ||
15 | * published by the Free Software Foundation, version 2. | ||
16 | * | ||
17 | */ | ||
18 | |||
19 | #ifndef M5602_OV9650_H_ | ||
20 | #define M5602_OV9650_H_ | ||
21 | |||
22 | #include <linux/dmi.h> | ||
23 | |||
24 | #include "m5602_sensor.h" | ||
25 | |||
26 | /*****************************************************************************/ | ||
27 | |||
28 | #define OV9650_GAIN 0x00 | ||
29 | #define OV9650_BLUE 0x01 | ||
30 | #define OV9650_RED 0x02 | ||
31 | #define OV9650_VREF 0x03 | ||
32 | #define OV9650_COM1 0x04 | ||
33 | #define OV9650_BAVE 0x05 | ||
34 | #define OV9650_GEAVE 0x06 | ||
35 | #define OV9650_RSVD7 0x07 | ||
36 | #define OV9650_PID 0x0a | ||
37 | #define OV9650_VER 0x0b | ||
38 | #define OV9650_COM3 0x0c | ||
39 | #define OV9650_COM5 0x0e | ||
40 | #define OV9650_COM6 0x0f | ||
41 | #define OV9650_AECH 0x10 | ||
42 | #define OV9650_CLKRC 0x11 | ||
43 | #define OV9650_COM7 0x12 | ||
44 | #define OV9650_COM8 0x13 | ||
45 | #define OV9650_COM9 0x14 | ||
46 | #define OV9650_COM10 0x15 | ||
47 | #define OV9650_RSVD16 0x16 | ||
48 | #define OV9650_HSTART 0x17 | ||
49 | #define OV9650_HSTOP 0x18 | ||
50 | #define OV9650_VSTRT 0x19 | ||
51 | #define OV9650_VSTOP 0x1a | ||
52 | #define OV9650_PSHFT 0x1b | ||
53 | #define OV9650_MVFP 0x1e | ||
54 | #define OV9650_AEW 0x24 | ||
55 | #define OV9650_AEB 0x25 | ||
56 | #define OV9650_VPT 0x26 | ||
57 | #define OV9650_BBIAS 0x27 | ||
58 | #define OV9650_GbBIAS 0x28 | ||
59 | #define OV9650_Gr_COM 0x29 | ||
60 | #define OV9650_RBIAS 0x2c | ||
61 | #define OV9650_HREF 0x32 | ||
62 | #define OV9650_CHLF 0x33 | ||
63 | #define OV9650_ARBLM 0x34 | ||
64 | #define OV9650_RSVD35 0x35 | ||
65 | #define OV9650_RSVD36 0x36 | ||
66 | #define OV9650_ADC 0x37 | ||
67 | #define OV9650_ACOM38 0x38 | ||
68 | #define OV9650_OFON 0x39 | ||
69 | #define OV9650_TSLB 0x3a | ||
70 | #define OV9650_COM12 0x3c | ||
71 | #define OV9650_COM13 0x3d | ||
72 | #define OV9650_COM15 0x40 | ||
73 | #define OV9650_COM16 0x41 | ||
74 | #define OV9650_LCC1 0x62 | ||
75 | #define OV9650_LCC2 0x63 | ||
76 | #define OV9650_LCC3 0x64 | ||
77 | #define OV9650_LCC4 0x65 | ||
78 | #define OV9650_LCC5 0x66 | ||
79 | #define OV9650_HV 0x69 | ||
80 | #define OV9650_DBLV 0x6b | ||
81 | #define OV9650_COM21 0x8b | ||
82 | #define OV9650_COM22 0x8c | ||
83 | #define OV9650_COM24 0x8e | ||
84 | #define OV9650_DBLC1 0x8f | ||
85 | #define OV9650_RSVD94 0x94 | ||
86 | #define OV9650_RSVD95 0x95 | ||
87 | #define OV9650_RSVD96 0x96 | ||
88 | #define OV9650_LCCFB 0x9d | ||
89 | #define OV9650_LCCFR 0x9e | ||
90 | #define OV9650_AECHM 0xa1 | ||
91 | #define OV9650_COM26 0xa5 | ||
92 | #define OV9650_ACOMA8 0xa8 | ||
93 | #define OV9650_ACOMA9 0xa9 | ||
94 | |||
95 | #define OV9650_REGISTER_RESET (1 << 7) | ||
96 | #define OV9650_VGA_SELECT (1 << 6) | ||
97 | #define OV9650_RGB_SELECT (1 << 2) | ||
98 | #define OV9650_RAW_RGB_SELECT (1 << 0) | ||
99 | |||
100 | #define OV9650_FAST_AGC_AEC (1 << 7) | ||
101 | #define OV9650_AEC_UNLIM_STEP_SIZE (1 << 6) | ||
102 | #define OV9650_BANDING (1 << 5) | ||
103 | #define OV9650_AGC_EN (1 << 2) | ||
104 | #define OV9650_AWB_EN (1 << 1) | ||
105 | #define OV9650_AEC_EN (1 << 0) | ||
106 | |||
107 | #define OV9650_VARIOPIXEL (1 << 2) | ||
108 | #define OV9650_SYSTEM_CLK_SEL (1 << 7) | ||
109 | #define OV9650_SLAM_MODE (1 << 4) | ||
110 | |||
111 | #define OV9650_VFLIP (1 << 4) | ||
112 | #define OV9650_HFLIP (1 << 5) | ||
113 | |||
114 | #define GAIN_DEFAULT 0x14 | ||
115 | #define RED_GAIN_DEFAULT 0x70 | ||
116 | #define BLUE_GAIN_DEFAULT 0x20 | ||
117 | #define EXPOSURE_DEFAULT 0x5003 | ||
118 | |||
119 | /*****************************************************************************/ | ||
120 | |||
121 | /* Kernel module parameters */ | ||
122 | extern int force_sensor; | ||
123 | extern int dump_sensor; | ||
124 | extern unsigned int m5602_debug; | ||
125 | |||
126 | int ov9650_probe(struct sd *sd); | ||
127 | int ov9650_init(struct sd *sd); | ||
128 | int ov9650_power_down(struct sd *sd); | ||
129 | |||
130 | int ov9650_read_sensor(struct sd *sd, const u8 address, | ||
131 | u8 *i2c_data, const u8 len); | ||
132 | int ov9650_write_sensor(struct sd *sd, const u8 address, | ||
133 | u8 *i2c_data, const u8 len); | ||
134 | |||
135 | void ov9650_dump_registers(struct sd *sd); | ||
136 | |||
137 | int ov9650_set_exposure(struct gspca_dev *gspca_dev, __s32 val); | ||
138 | int ov9650_get_exposure(struct gspca_dev *gspca_dev, __s32 *val); | ||
139 | int ov9650_get_gain(struct gspca_dev *gspca_dev, __s32 *val); | ||
140 | int ov9650_set_gain(struct gspca_dev *gspca_dev, __s32 val); | ||
141 | int ov9650_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val); | ||
142 | int ov9650_set_red_balance(struct gspca_dev *gspca_dev, __s32 val); | ||
143 | int ov9650_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val); | ||
144 | int ov9650_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val); | ||
145 | int ov9650_get_hflip(struct gspca_dev *gspca_dev, __s32 *val); | ||
146 | int ov9650_set_hflip(struct gspca_dev *gspca_dev, __s32 val); | ||
147 | int ov9650_get_vflip(struct gspca_dev *gspca_dev, __s32 *val); | ||
148 | int ov9650_set_vflip(struct gspca_dev *gspca_dev, __s32 val); | ||
149 | int ov9650_get_brightness(struct gspca_dev *gspca_dev, __s32 *val); | ||
150 | int ov9650_set_brightness(struct gspca_dev *gspca_dev, __s32 val); | ||
151 | int ov9650_get_auto_white_balance(struct gspca_dev *gspca_dev, __s32 *val); | ||
152 | int ov9650_set_auto_white_balance(struct gspca_dev *gspca_dev, __s32 val); | ||
153 | int ov9650_get_auto_gain(struct gspca_dev *gspca_dev, __s32 *val); | ||
154 | int ov9650_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val); | ||
155 | |||
156 | static struct m5602_sensor ov9650 = { | ||
157 | .name = "OV9650", | ||
158 | .i2c_slave_id = 0x60, | ||
159 | .probe = ov9650_probe, | ||
160 | .init = ov9650_init, | ||
161 | .power_down = ov9650_power_down, | ||
162 | .read_sensor = ov9650_read_sensor, | ||
163 | .write_sensor = ov9650_write_sensor, | ||
164 | |||
165 | .nctrls = 8, | ||
166 | .ctrls = { | ||
167 | { | ||
168 | { | ||
169 | .id = V4L2_CID_EXPOSURE, | ||
170 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
171 | .name = "exposure", | ||
172 | .minimum = 0x00, | ||
173 | .maximum = 0xffff, | ||
174 | .step = 0x1, | ||
175 | .default_value = EXPOSURE_DEFAULT, | ||
176 | .flags = V4L2_CTRL_FLAG_SLIDER | ||
177 | }, | ||
178 | .set = ov9650_set_exposure, | ||
179 | .get = ov9650_get_exposure | ||
180 | }, { | ||
181 | { | ||
182 | .id = V4L2_CID_GAIN, | ||
183 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
184 | .name = "gain", | ||
185 | .minimum = 0x00, | ||
186 | .maximum = 0x3ff, | ||
187 | .step = 0x1, | ||
188 | .default_value = GAIN_DEFAULT, | ||
189 | .flags = V4L2_CTRL_FLAG_SLIDER | ||
190 | }, | ||
191 | .set = ov9650_set_gain, | ||
192 | .get = ov9650_get_gain | ||
193 | }, { | ||
194 | { | ||
195 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
196 | .name = "red balance", | ||
197 | .minimum = 0x00, | ||
198 | .maximum = 0xff, | ||
199 | .step = 0x1, | ||
200 | .default_value = RED_GAIN_DEFAULT, | ||
201 | .flags = V4L2_CTRL_FLAG_SLIDER | ||
202 | }, | ||
203 | .set = ov9650_set_red_balance, | ||
204 | .get = ov9650_get_red_balance | ||
205 | }, { | ||
206 | { | ||
207 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
208 | .name = "blue balance", | ||
209 | .minimum = 0x00, | ||
210 | .maximum = 0xff, | ||
211 | .step = 0x1, | ||
212 | .default_value = BLUE_GAIN_DEFAULT, | ||
213 | .flags = V4L2_CTRL_FLAG_SLIDER | ||
214 | }, | ||
215 | .set = ov9650_set_blue_balance, | ||
216 | .get = ov9650_get_blue_balance | ||
217 | }, { | ||
218 | { | ||
219 | .id = V4L2_CID_HFLIP, | ||
220 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
221 | .name = "horizontal flip", | ||
222 | .minimum = 0, | ||
223 | .maximum = 1, | ||
224 | .step = 1, | ||
225 | .default_value = 0 | ||
226 | }, | ||
227 | .set = ov9650_set_hflip, | ||
228 | .get = ov9650_get_hflip | ||
229 | }, { | ||
230 | { | ||
231 | .id = V4L2_CID_VFLIP, | ||
232 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
233 | .name = "vertical flip", | ||
234 | .minimum = 0, | ||
235 | .maximum = 1, | ||
236 | .step = 1, | ||
237 | .default_value = 0 | ||
238 | }, | ||
239 | .set = ov9650_set_vflip, | ||
240 | .get = ov9650_get_vflip | ||
241 | }, { | ||
242 | { | ||
243 | .id = V4L2_CID_AUTO_WHITE_BALANCE, | ||
244 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
245 | .name = "auto white balance", | ||
246 | .minimum = 0, | ||
247 | .maximum = 1, | ||
248 | .step = 1, | ||
249 | .default_value = 0 | ||
250 | }, | ||
251 | .set = ov9650_set_auto_white_balance, | ||
252 | .get = ov9650_get_auto_white_balance | ||
253 | }, { | ||
254 | { | ||
255 | .id = V4L2_CID_AUTOGAIN, | ||
256 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
257 | .name = "auto gain control", | ||
258 | .minimum = 0, | ||
259 | .maximum = 1, | ||
260 | .step = 1, | ||
261 | .default_value = 0 | ||
262 | }, | ||
263 | .set = ov9650_set_auto_gain, | ||
264 | .get = ov9650_get_auto_gain | ||
265 | } | ||
266 | }, | ||
267 | |||
268 | .nmodes = 1, | ||
269 | .modes = { | ||
270 | { | ||
271 | M5602_DEFAULT_FRAME_WIDTH, | ||
272 | M5602_DEFAULT_FRAME_HEIGHT, | ||
273 | V4L2_PIX_FMT_SBGGR8, | ||
274 | V4L2_FIELD_NONE, | ||
275 | .sizeimage = | ||
276 | M5602_DEFAULT_FRAME_WIDTH * M5602_DEFAULT_FRAME_HEIGHT, | ||
277 | .bytesperline = M5602_DEFAULT_FRAME_WIDTH, | ||
278 | .colorspace = V4L2_COLORSPACE_SRGB, | ||
279 | .priv = 1 | ||
280 | } | ||
281 | } | ||
282 | }; | ||
283 | |||
284 | static const unsigned char preinit_ov9650[][3] = | ||
285 | { | ||
286 | /* [INITCAM] */ | ||
287 | {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02}, | ||
288 | {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0}, | ||
289 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00}, | ||
290 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, | ||
291 | {BRIDGE, M5602_XB_ADC_CTRL, 0xc0}, | ||
292 | {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00}, | ||
293 | |||
294 | {BRIDGE, M5602_XB_SENSOR_TYPE, 0x08}, | ||
295 | {BRIDGE, M5602_XB_GPIO_DIR, 0x05}, | ||
296 | {BRIDGE, M5602_XB_GPIO_DAT, 0x04}, | ||
297 | {BRIDGE, M5602_XB_GPIO_EN_H, 0x06}, | ||
298 | {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06}, | ||
299 | {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00}, | ||
300 | {BRIDGE, M5602_XB_GPIO_DAT, 0x00}, | ||
301 | {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x0a}, | ||
302 | /* Reset chip */ | ||
303 | {SENSOR, OV9650_COM7, OV9650_REGISTER_RESET}, | ||
304 | /* Enable double clock */ | ||
305 | {SENSOR, OV9650_CLKRC, 0x80}, | ||
306 | /* Do something out of spec with the power */ | ||
307 | {SENSOR, OV9650_OFON, 0x40} | ||
308 | }; | ||
309 | |||
310 | static const unsigned char init_ov9650[][3] = | ||
311 | { | ||
312 | /* [INITCAM] */ | ||
313 | {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02}, | ||
314 | {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0}, | ||
315 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00}, | ||
316 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, | ||
317 | {BRIDGE, M5602_XB_ADC_CTRL, 0xc0}, | ||
318 | {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00}, | ||
319 | |||
320 | {BRIDGE, M5602_XB_SENSOR_TYPE, 0x08}, | ||
321 | {BRIDGE, M5602_XB_GPIO_DIR, 0x05}, | ||
322 | {BRIDGE, M5602_XB_GPIO_DAT, 0x04}, | ||
323 | {BRIDGE, M5602_XB_GPIO_EN_H, 0x06}, | ||
324 | {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06}, | ||
325 | {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00}, | ||
326 | {BRIDGE, M5602_XB_GPIO_DAT, 0x00}, | ||
327 | {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x0a}, | ||
328 | /* Reset chip */ | ||
329 | {SENSOR, OV9650_COM7, OV9650_REGISTER_RESET}, | ||
330 | /* Enable double clock */ | ||
331 | {SENSOR, OV9650_CLKRC, 0x80}, | ||
332 | /* Do something out of spec with the power */ | ||
333 | {SENSOR, OV9650_OFON, 0x40}, | ||
334 | |||
335 | /* Set QQVGA */ | ||
336 | {SENSOR, OV9650_COM1, 0x20}, | ||
337 | /* Set fast AGC/AEC algorithm with unlimited step size */ | ||
338 | {SENSOR, OV9650_COM8, OV9650_FAST_AGC_AEC | | ||
339 | OV9650_AEC_UNLIM_STEP_SIZE | | ||
340 | OV9650_AWB_EN | OV9650_AGC_EN}, | ||
341 | |||
342 | {SENSOR, OV9650_CHLF, 0x10}, | ||
343 | {SENSOR, OV9650_ARBLM, 0xbf}, | ||
344 | {SENSOR, OV9650_ACOM38, 0x81}, | ||
345 | /* Turn off color matrix coefficient double option */ | ||
346 | {SENSOR, OV9650_COM16, 0x00}, | ||
347 | /* Enable color matrix for RGB/YUV, Delay Y channel, | ||
348 | set output Y/UV delay to 1 */ | ||
349 | {SENSOR, OV9650_COM13, 0x19}, | ||
350 | /* Enable digital BLC, Set output mode to U Y V Y */ | ||
351 | {SENSOR, OV9650_TSLB, 0x0c}, | ||
352 | /* Limit the AGC/AEC stable upper region */ | ||
353 | {SENSOR, OV9650_COM24, 0x00}, | ||
354 | /* Enable HREF and some out of spec things */ | ||
355 | {SENSOR, OV9650_COM12, 0x73}, | ||
356 | /* Set all DBLC offset signs to positive and | ||
357 | do some out of spec stuff */ | ||
358 | {SENSOR, OV9650_DBLC1, 0xdf}, | ||
359 | {SENSOR, OV9650_COM21, 0x06}, | ||
360 | {SENSOR, OV9650_RSVD35, 0x91}, | ||
361 | /* Necessary, no camera stream without it */ | ||
362 | {SENSOR, OV9650_RSVD16, 0x06}, | ||
363 | {SENSOR, OV9650_RSVD94, 0x99}, | ||
364 | {SENSOR, OV9650_RSVD95, 0x99}, | ||
365 | {SENSOR, OV9650_RSVD96, 0x04}, | ||
366 | /* Enable full range output */ | ||
367 | {SENSOR, OV9650_COM15, 0x0}, | ||
368 | /* Enable HREF at optical black, enable ADBLC bias, | ||
369 | enable ADBLC, reset timings at format change */ | ||
370 | {SENSOR, OV9650_COM6, 0x4b}, | ||
371 | /* Subtract 32 from the B channel bias */ | ||
372 | {SENSOR, OV9650_BBIAS, 0xa0}, | ||
373 | /* Subtract 32 from the Gb channel bias */ | ||
374 | {SENSOR, OV9650_GbBIAS, 0xa0}, | ||
375 | /* Do not bypass the analog BLC and to some out of spec stuff */ | ||
376 | {SENSOR, OV9650_Gr_COM, 0x00}, | ||
377 | /* Subtract 32 from the R channel bias */ | ||
378 | {SENSOR, OV9650_RBIAS, 0xa0}, | ||
379 | /* Subtract 32 from the R channel bias */ | ||
380 | {SENSOR, OV9650_RBIAS, 0x0}, | ||
381 | {SENSOR, OV9650_COM26, 0x80}, | ||
382 | {SENSOR, OV9650_ACOMA9, 0x98}, | ||
383 | /* Set the AGC/AEC stable region upper limit */ | ||
384 | {SENSOR, OV9650_AEW, 0x68}, | ||
385 | /* Set the AGC/AEC stable region lower limit */ | ||
386 | {SENSOR, OV9650_AEB, 0x5c}, | ||
387 | /* Set the high and low limit nibbles to 3 */ | ||
388 | {SENSOR, OV9650_VPT, 0xc3}, | ||
389 | /* Set the Automatic Gain Ceiling (AGC) to 128x, | ||
390 | drop VSYNC at frame drop, | ||
391 | limit exposure timing, | ||
392 | drop frame when the AEC step is larger than the exposure gap */ | ||
393 | {SENSOR, OV9650_COM9, 0x6e}, | ||
394 | /* Set VSYNC negative, Set RESET to SLHS (slave mode horizontal sync) | ||
395 | and set PWDN to SLVS (slave mode vertical sync) */ | ||
396 | {SENSOR, OV9650_COM10, 0x42}, | ||
397 | /* Set horizontal column start high to default value */ | ||
398 | {SENSOR, OV9650_HSTART, 0x1a}, | ||
399 | /* Set horizontal column end */ | ||
400 | {SENSOR, OV9650_HSTOP, 0xbf}, | ||
401 | /* Complementing register to the two writes above */ | ||
402 | {SENSOR, OV9650_HREF, 0xb2}, | ||
403 | /* Set vertical row start high bits */ | ||
404 | {SENSOR, OV9650_VSTRT, 0x02}, | ||
405 | /* Set vertical row end low bits */ | ||
406 | {SENSOR, OV9650_VSTOP, 0x7e}, | ||
407 | /* Set complementing vertical frame control */ | ||
408 | {SENSOR, OV9650_VREF, 0x10}, | ||
409 | /* Set raw RGB output format with VGA resolution */ | ||
410 | {SENSOR, OV9650_COM7, OV9650_VGA_SELECT | | ||
411 | OV9650_RGB_SELECT | | ||
412 | OV9650_RAW_RGB_SELECT}, | ||
413 | {SENSOR, OV9650_ADC, 0x04}, | ||
414 | {SENSOR, OV9650_HV, 0x40}, | ||
415 | /* Enable denoise, and white-pixel erase */ | ||
416 | {SENSOR, OV9650_COM22, 0x23}, | ||
417 | |||
418 | /* Set the high bits of the exposure value */ | ||
419 | {SENSOR, OV9650_AECH, ((EXPOSURE_DEFAULT & 0xff00) >> 8)}, | ||
420 | |||
421 | /* Set the low bits of the exposure value */ | ||
422 | {SENSOR, OV9650_COM1, (EXPOSURE_DEFAULT & 0xff)}, | ||
423 | {SENSOR, OV9650_GAIN, GAIN_DEFAULT}, | ||
424 | {SENSOR, OV9650_BLUE, BLUE_GAIN_DEFAULT}, | ||
425 | {SENSOR, OV9650_RED, RED_GAIN_DEFAULT}, | ||
426 | |||
427 | {SENSOR, OV9650_COM3, OV9650_VARIOPIXEL}, | ||
428 | {SENSOR, OV9650_COM5, OV9650_SYSTEM_CLK_SEL}, | ||
429 | |||
430 | {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x82}, | ||
431 | {BRIDGE, M5602_XB_LINE_OF_FRAME_L, 0x00}, | ||
432 | {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82}, | ||
433 | {BRIDGE, M5602_XB_PIX_OF_LINE_L, 0x00}, | ||
434 | {BRIDGE, M5602_XB_SIG_INI, 0x01}, | ||
435 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, | ||
436 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x09}, | ||
437 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, | ||
438 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x01}, | ||
439 | {BRIDGE, M5602_XB_VSYNC_PARA, 0xe0}, | ||
440 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, | ||
441 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x00}, | ||
442 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x5e}, | ||
443 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x02}, | ||
444 | {BRIDGE, M5602_XB_HSYNC_PARA, 0xde} | ||
445 | }; | ||
446 | |||
447 | static const unsigned char power_down_ov9650[][3] = | ||
448 | { | ||
449 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04}, | ||
450 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, | ||
451 | {SENSOR, OV9650_COM7, 0x80}, | ||
452 | {SENSOR, OV9650_OFON, 0xf4}, | ||
453 | {SENSOR, OV9650_MVFP, 0x80}, | ||
454 | {SENSOR, OV9650_DBLV, 0x3f}, | ||
455 | {SENSOR, OV9650_RSVD36, 0x49}, | ||
456 | {SENSOR, OV9650_COM7, 0x05}, | ||
457 | |||
458 | {BRIDGE, M5602_XB_GPIO_DIR, 0x05}, | ||
459 | {BRIDGE, M5602_XB_GPIO_DAT, 0x04}, | ||
460 | {BRIDGE, M5602_XB_GPIO_EN_H, 0x06}, | ||
461 | {BRIDGE, M5602_XB_GPIO_EN_L, 0x06}, | ||
462 | {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02}, | ||
463 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04}, | ||
464 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0} | ||
465 | }; | ||
466 | |||
467 | /* Vertically and horizontally flips the image if matched, needed for machines | ||
468 | where the sensor is mounted upside down */ | ||
469 | static | ||
470 | const | ||
471 | struct dmi_system_id ov9650_flip_dmi_table[] = { | ||
472 | { | ||
473 | .ident = "ASUS A6VC", | ||
474 | .matches = { | ||
475 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."), | ||
476 | DMI_MATCH(DMI_PRODUCT_NAME, "A6VC") | ||
477 | } | ||
478 | }, | ||
479 | { | ||
480 | .ident = "ASUS A6VM", | ||
481 | .matches = { | ||
482 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."), | ||
483 | DMI_MATCH(DMI_PRODUCT_NAME, "A6VM") | ||
484 | } | ||
485 | }, | ||
486 | { | ||
487 | .ident = "ASUS A6JC", | ||
488 | .matches = { | ||
489 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."), | ||
490 | DMI_MATCH(DMI_PRODUCT_NAME, "A6JC") | ||
491 | } | ||
492 | }, | ||
493 | { | ||
494 | .ident = "ASUS A6Kt", | ||
495 | .matches = { | ||
496 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."), | ||
497 | DMI_MATCH(DMI_PRODUCT_NAME, "A6Kt") | ||
498 | } | ||
499 | }, | ||
500 | { } | ||
501 | }; | ||
502 | |||
503 | #endif | ||
diff --git a/drivers/media/video/gspca/m5602/m5602_po1030.c b/drivers/media/video/gspca/m5602/m5602_po1030.c new file mode 100644 index 000000000000..08c015bde115 --- /dev/null +++ b/drivers/media/video/gspca/m5602/m5602_po1030.c | |||
@@ -0,0 +1,336 @@ | |||
1 | /* | ||
2 | * Driver for the po1030 sensor | ||
3 | * | ||
4 | * Copyright (c) 2008 Erik Andren | ||
5 | * Copyright (c) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project. | ||
6 | * Copyright (c) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br> | ||
7 | * | ||
8 | * Portions of code to USB interface and ALi driver software, | ||
9 | * Copyright (c) 2006 Willem Duinker | ||
10 | * v4l2 interface modeled after the V4L2 driver | ||
11 | * for SN9C10x PC Camera Controllers | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or | ||
14 | * modify it under the terms of the GNU General Public License as | ||
15 | * published by the Free Software Foundation, version 2. | ||
16 | * | ||
17 | */ | ||
18 | |||
19 | #include "m5602_po1030.h" | ||
20 | |||
21 | int po1030_probe(struct sd *sd) | ||
22 | { | ||
23 | u8 prod_id = 0, ver_id = 0, i; | ||
24 | |||
25 | if (force_sensor) { | ||
26 | if (force_sensor == PO1030_SENSOR) { | ||
27 | info("Forcing a %s sensor", po1030.name); | ||
28 | goto sensor_found; | ||
29 | } | ||
30 | /* If we want to force another sensor, don't try to probe this | ||
31 | * one */ | ||
32 | return -ENODEV; | ||
33 | } | ||
34 | |||
35 | info("Probing for a po1030 sensor"); | ||
36 | |||
37 | /* Run the pre-init to actually probe the unit */ | ||
38 | for (i = 0; i < ARRAY_SIZE(preinit_po1030); i++) { | ||
39 | u8 data = preinit_po1030[i][2]; | ||
40 | if (preinit_po1030[i][0] == SENSOR) | ||
41 | po1030_write_sensor(sd, | ||
42 | preinit_po1030[i][1], &data, 1); | ||
43 | else | ||
44 | m5602_write_bridge(sd, preinit_po1030[i][1], data); | ||
45 | } | ||
46 | |||
47 | if (po1030_read_sensor(sd, 0x3, &prod_id, 1)) | ||
48 | return -ENODEV; | ||
49 | |||
50 | if (po1030_read_sensor(sd, 0x4, &ver_id, 1)) | ||
51 | return -ENODEV; | ||
52 | |||
53 | if ((prod_id == 0x02) && (ver_id == 0xef)) { | ||
54 | info("Detected a po1030 sensor"); | ||
55 | goto sensor_found; | ||
56 | } | ||
57 | return -ENODEV; | ||
58 | |||
59 | sensor_found: | ||
60 | sd->gspca_dev.cam.cam_mode = po1030.modes; | ||
61 | sd->gspca_dev.cam.nmodes = po1030.nmodes; | ||
62 | sd->desc->ctrls = po1030.ctrls; | ||
63 | sd->desc->nctrls = po1030.nctrls; | ||
64 | return 0; | ||
65 | } | ||
66 | |||
67 | int po1030_read_sensor(struct sd *sd, const u8 address, | ||
68 | u8 *i2c_data, const u8 len) | ||
69 | { | ||
70 | int err, i; | ||
71 | |||
72 | do { | ||
73 | err = m5602_read_bridge(sd, M5602_XB_I2C_STATUS, i2c_data); | ||
74 | } while ((*i2c_data & I2C_BUSY) && !err); | ||
75 | |||
76 | m5602_write_bridge(sd, M5602_XB_I2C_DEV_ADDR, | ||
77 | sd->sensor->i2c_slave_id); | ||
78 | m5602_write_bridge(sd, M5602_XB_I2C_REG_ADDR, address); | ||
79 | m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 0x10 + len); | ||
80 | m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 0x08); | ||
81 | |||
82 | for (i = 0; i < len; i++) { | ||
83 | err = m5602_read_bridge(sd, M5602_XB_I2C_DATA, &(i2c_data[i])); | ||
84 | |||
85 | PDEBUG(DBG_TRACE, "Reading sensor register " | ||
86 | "0x%x containing 0x%x ", address, *i2c_data); | ||
87 | } | ||
88 | return (err < 0) ? err : 0; | ||
89 | } | ||
90 | |||
91 | int po1030_write_sensor(struct sd *sd, const u8 address, | ||
92 | u8 *i2c_data, const u8 len) | ||
93 | { | ||
94 | int err, i; | ||
95 | u8 *p; | ||
96 | struct usb_device *udev = sd->gspca_dev.dev; | ||
97 | __u8 *buf = sd->gspca_dev.usb_buf; | ||
98 | |||
99 | /* The po1030 only supports one byte writes */ | ||
100 | if (len > 1 || !len) | ||
101 | return -EINVAL; | ||
102 | |||
103 | memcpy(buf, sensor_urb_skeleton, sizeof(sensor_urb_skeleton)); | ||
104 | |||
105 | buf[11] = sd->sensor->i2c_slave_id; | ||
106 | buf[15] = address; | ||
107 | |||
108 | p = buf + 16; | ||
109 | |||
110 | /* Copy a four byte write sequence for each byte to be written to */ | ||
111 | for (i = 0; i < len; i++) { | ||
112 | memcpy(p, sensor_urb_skeleton + 16, 4); | ||
113 | p[3] = i2c_data[i]; | ||
114 | p += 4; | ||
115 | PDEBUG(DBG_TRACE, "Writing sensor register 0x%x with 0x%x", | ||
116 | address, i2c_data[i]); | ||
117 | } | ||
118 | |||
119 | /* Copy the footer */ | ||
120 | memcpy(p, sensor_urb_skeleton + 20, 4); | ||
121 | |||
122 | /* Set the total length */ | ||
123 | p[3] = 0x10 + len; | ||
124 | |||
125 | err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), | ||
126 | 0x04, 0x40, 0x19, | ||
127 | 0x0000, buf, | ||
128 | 20 + len * 4, M5602_URB_MSG_TIMEOUT); | ||
129 | |||
130 | return (err < 0) ? err : 0; | ||
131 | } | ||
132 | |||
133 | int po1030_init(struct sd *sd) | ||
134 | { | ||
135 | int i, err = 0; | ||
136 | |||
137 | /* Init the sensor */ | ||
138 | for (i = 0; i < ARRAY_SIZE(init_po1030); i++) { | ||
139 | u8 data[2] = {0x00, 0x00}; | ||
140 | |||
141 | switch (init_po1030[i][0]) { | ||
142 | case BRIDGE: | ||
143 | err = m5602_write_bridge(sd, | ||
144 | init_po1030[i][1], | ||
145 | init_po1030[i][2]); | ||
146 | break; | ||
147 | |||
148 | case SENSOR: | ||
149 | data[0] = init_po1030[i][2]; | ||
150 | err = po1030_write_sensor(sd, | ||
151 | init_po1030[i][1], data, 1); | ||
152 | break; | ||
153 | |||
154 | case SENSOR_LONG: | ||
155 | data[0] = init_po1030[i][2]; | ||
156 | data[1] = init_po1030[i][3]; | ||
157 | err = po1030_write_sensor(sd, | ||
158 | init_po1030[i][1], data, 2); | ||
159 | break; | ||
160 | default: | ||
161 | info("Invalid stream command, exiting init"); | ||
162 | return -EINVAL; | ||
163 | } | ||
164 | } | ||
165 | |||
166 | if (dump_sensor) | ||
167 | po1030_dump_registers(sd); | ||
168 | |||
169 | return (err < 0) ? err : 0; | ||
170 | } | ||
171 | |||
172 | int po1030_get_exposure(struct gspca_dev *gspca_dev, __s32 *val) | ||
173 | { | ||
174 | struct sd *sd = (struct sd *) gspca_dev; | ||
175 | u8 i2c_data; | ||
176 | int err; | ||
177 | |||
178 | err = po1030_read_sensor(sd, PO1030_REG_INTEGLINES_H, | ||
179 | &i2c_data, 1); | ||
180 | if (err < 0) | ||
181 | goto out; | ||
182 | *val = (i2c_data << 8); | ||
183 | |||
184 | err = po1030_read_sensor(sd, PO1030_REG_INTEGLINES_M, | ||
185 | &i2c_data, 1); | ||
186 | *val |= i2c_data; | ||
187 | |||
188 | PDEBUG(DBG_V4L2_CID, "Exposure read as %d", *val); | ||
189 | out: | ||
190 | return (err < 0) ? err : 0; | ||
191 | } | ||
192 | |||
193 | int po1030_set_exposure(struct gspca_dev *gspca_dev, __s32 val) | ||
194 | { | ||
195 | struct sd *sd = (struct sd *) gspca_dev; | ||
196 | u8 i2c_data; | ||
197 | int err; | ||
198 | |||
199 | PDEBUG(DBG_V4L2, "Set exposure to %d", val & 0xffff); | ||
200 | |||
201 | i2c_data = ((val & 0xff00) >> 8); | ||
202 | PDEBUG(DBG_V4L2, "Set exposure to high byte to 0x%x", | ||
203 | i2c_data); | ||
204 | |||
205 | err = po1030_write_sensor(sd, PO1030_REG_INTEGLINES_H, | ||
206 | &i2c_data, 1); | ||
207 | if (err < 0) | ||
208 | goto out; | ||
209 | |||
210 | i2c_data = (val & 0xff); | ||
211 | PDEBUG(DBG_V4L2, "Set exposure to low byte to 0x%x", | ||
212 | i2c_data); | ||
213 | err = po1030_write_sensor(sd, PO1030_REG_INTEGLINES_M, | ||
214 | &i2c_data, 1); | ||
215 | |||
216 | out: | ||
217 | return (err < 0) ? err : 0; | ||
218 | } | ||
219 | |||
220 | int po1030_get_gain(struct gspca_dev *gspca_dev, __s32 *val) | ||
221 | { | ||
222 | struct sd *sd = (struct sd *) gspca_dev; | ||
223 | u8 i2c_data; | ||
224 | int err; | ||
225 | |||
226 | err = po1030_read_sensor(sd, PO1030_REG_GLOBALGAIN, | ||
227 | &i2c_data, 1); | ||
228 | *val = i2c_data; | ||
229 | PDEBUG(DBG_V4L2_CID, "Read global gain %d", *val); | ||
230 | |||
231 | return (err < 0) ? err : 0; | ||
232 | } | ||
233 | |||
234 | int po1030_set_gain(struct gspca_dev *gspca_dev, __s32 val) | ||
235 | { | ||
236 | struct sd *sd = (struct sd *) gspca_dev; | ||
237 | u8 i2c_data; | ||
238 | int err; | ||
239 | |||
240 | i2c_data = val & 0xff; | ||
241 | PDEBUG(DBG_V4L2, "Set global gain to %d", i2c_data); | ||
242 | err = po1030_write_sensor(sd, PO1030_REG_GLOBALGAIN, | ||
243 | &i2c_data, 1); | ||
244 | return (err < 0) ? err : 0; | ||
245 | } | ||
246 | |||
247 | int po1030_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val) | ||
248 | { | ||
249 | struct sd *sd = (struct sd *) gspca_dev; | ||
250 | u8 i2c_data; | ||
251 | int err; | ||
252 | |||
253 | err = po1030_read_sensor(sd, PO1030_REG_RED_GAIN, | ||
254 | &i2c_data, 1); | ||
255 | *val = i2c_data; | ||
256 | PDEBUG(DBG_V4L2_CID, "Read red gain %d", *val); | ||
257 | return (err < 0) ? err : 0; | ||
258 | } | ||
259 | |||
260 | int po1030_set_red_balance(struct gspca_dev *gspca_dev, __s32 val) | ||
261 | { | ||
262 | struct sd *sd = (struct sd *) gspca_dev; | ||
263 | u8 i2c_data; | ||
264 | int err; | ||
265 | |||
266 | i2c_data = val & 0xff; | ||
267 | PDEBUG(DBG_V4L2, "Set red gain to %d", i2c_data); | ||
268 | err = po1030_write_sensor(sd, PO1030_REG_RED_GAIN, | ||
269 | &i2c_data, 1); | ||
270 | return (err < 0) ? err : 0; | ||
271 | } | ||
272 | |||
273 | int po1030_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val) | ||
274 | { | ||
275 | struct sd *sd = (struct sd *) gspca_dev; | ||
276 | u8 i2c_data; | ||
277 | int err; | ||
278 | |||
279 | err = po1030_read_sensor(sd, PO1030_REG_BLUE_GAIN, | ||
280 | &i2c_data, 1); | ||
281 | *val = i2c_data; | ||
282 | PDEBUG(DBG_V4L2_CID, "Read blue gain %d", *val); | ||
283 | |||
284 | return (err < 0) ? err : 0; | ||
285 | } | ||
286 | |||
287 | int po1030_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val) | ||
288 | { | ||
289 | struct sd *sd = (struct sd *) gspca_dev; | ||
290 | u8 i2c_data; | ||
291 | int err; | ||
292 | i2c_data = val & 0xff; | ||
293 | PDEBUG(DBG_V4L2, "Set blue gain to %d", i2c_data); | ||
294 | err = po1030_write_sensor(sd, PO1030_REG_BLUE_GAIN, | ||
295 | &i2c_data, 1); | ||
296 | |||
297 | return (err < 0) ? err : 0; | ||
298 | } | ||
299 | |||
300 | int po1030_power_down(struct sd *sd) | ||
301 | { | ||
302 | return 0; | ||
303 | } | ||
304 | |||
305 | void po1030_dump_registers(struct sd *sd) | ||
306 | { | ||
307 | int address; | ||
308 | u8 value = 0; | ||
309 | |||
310 | info("Dumping the po1030 sensor core registers"); | ||
311 | for (address = 0; address < 0x7f; address++) { | ||
312 | po1030_read_sensor(sd, address, &value, 1); | ||
313 | info("register 0x%x contains 0x%x", | ||
314 | address, value); | ||
315 | } | ||
316 | |||
317 | info("po1030 register state dump complete"); | ||
318 | |||
319 | info("Probing for which registers that are read/write"); | ||
320 | for (address = 0; address < 0xff; address++) { | ||
321 | u8 old_value, ctrl_value; | ||
322 | u8 test_value[2] = {0xff, 0xff}; | ||
323 | |||
324 | po1030_read_sensor(sd, address, &old_value, 1); | ||
325 | po1030_write_sensor(sd, address, test_value, 1); | ||
326 | po1030_read_sensor(sd, address, &ctrl_value, 1); | ||
327 | |||
328 | if (ctrl_value == test_value[0]) | ||
329 | info("register 0x%x is writeable", address); | ||
330 | else | ||
331 | info("register 0x%x is read only", address); | ||
332 | |||
333 | /* Restore original value */ | ||
334 | po1030_write_sensor(sd, address, &old_value, 1); | ||
335 | } | ||
336 | } | ||
diff --git a/drivers/media/video/gspca/m5602/m5602_po1030.h b/drivers/media/video/gspca/m5602/m5602_po1030.h new file mode 100644 index 000000000000..68f34c97bf44 --- /dev/null +++ b/drivers/media/video/gspca/m5602/m5602_po1030.h | |||
@@ -0,0 +1,478 @@ | |||
1 | /* | ||
2 | * Driver for the po1030 sensor. | ||
3 | * This is probably a pixel plus sensor but we haven't identified it yet | ||
4 | * | ||
5 | * Copyright (c) 2008 Erik Andren | ||
6 | * Copyright (c) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project. | ||
7 | * Copyright (c) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br> | ||
8 | * | ||
9 | * Portions of code to USB interface and ALi driver software, | ||
10 | * Copyright (c) 2006 Willem Duinker | ||
11 | * v4l2 interface modeled after the V4L2 driver | ||
12 | * for SN9C10x PC Camera Controllers | ||
13 | * | ||
14 | * Register defines taken from Pascal Stangs Proxycon Armlib | ||
15 | * | ||
16 | * This program is free software; you can redistribute it and/or | ||
17 | * modify it under the terms of the GNU General Public License as | ||
18 | * published by the Free Software Foundation, version 2. | ||
19 | * | ||
20 | */ | ||
21 | |||
22 | #ifndef M5602_PO1030_H_ | ||
23 | #define M5602_PO1030_H_ | ||
24 | |||
25 | #include "m5602_sensor.h" | ||
26 | |||
27 | /*****************************************************************************/ | ||
28 | |||
29 | #define PO1030_REG_DEVID_H 0x00 | ||
30 | #define PO1030_REG_DEVID_L 0x01 | ||
31 | #define PO1030_REG_FRAMEWIDTH_H 0x04 | ||
32 | #define PO1030_REG_FRAMEWIDTH_L 0x05 | ||
33 | #define PO1030_REG_FRAMEHEIGHT_H 0x06 | ||
34 | #define PO1030_REG_FRAMEHEIGHT_L 0x07 | ||
35 | #define PO1030_REG_WINDOWX_H 0x08 | ||
36 | #define PO1030_REG_WINDOWX_L 0x09 | ||
37 | #define PO1030_REG_WINDOWY_H 0x0a | ||
38 | #define PO1030_REG_WINDOWY_L 0x0b | ||
39 | #define PO1030_REG_WINDOWWIDTH_H 0x0c | ||
40 | #define PO1030_REG_WINDOWWIDTH_L 0x0d | ||
41 | #define PO1030_REG_WINDOWHEIGHT_H 0x0e | ||
42 | #define PO1030_REG_WINDOWHEIGHT_L 0x0f | ||
43 | |||
44 | #define PO1030_REG_GLOBALIBIAS 0x12 | ||
45 | #define PO1030_REG_PIXELIBIAS 0x13 | ||
46 | |||
47 | #define PO1030_REG_GLOBALGAIN 0x15 | ||
48 | #define PO1030_REG_RED_GAIN 0x16 | ||
49 | #define PO1030_REG_GREEN_1_GAIN 0x17 | ||
50 | #define PO1030_REG_BLUE_GAIN 0x18 | ||
51 | #define PO1030_REG_GREEN_2_GAIN 0x19 | ||
52 | |||
53 | #define PO1030_REG_INTEGLINES_H 0x1a | ||
54 | #define PO1030_REG_INTEGLINES_M 0x1b | ||
55 | #define PO1030_REG_INTEGLINES_L 0x1c | ||
56 | |||
57 | #define PO1030_REG_CONTROL1 0x1d | ||
58 | #define PO1030_REG_CONTROL2 0x1e | ||
59 | #define PO1030_REG_CONTROL3 0x1f | ||
60 | #define PO1030_REG_CONTROL4 0x20 | ||
61 | |||
62 | #define PO1030_REG_PERIOD50_H 0x23 | ||
63 | #define PO1030_REG_PERIOD50_L 0x24 | ||
64 | #define PO1030_REG_PERIOD60_H 0x25 | ||
65 | #define PO1030_REG_PERIOD60_L 0x26 | ||
66 | #define PO1030_REG_REGCLK167 0x27 | ||
67 | #define PO1030_REG_DELTA50 0x28 | ||
68 | #define PO1030_REG_DELTA60 0x29 | ||
69 | |||
70 | #define PO1030_REG_ADCOFFSET 0x2c | ||
71 | |||
72 | /* Gamma Correction Coeffs */ | ||
73 | #define PO1030_REG_GC0 0x2d | ||
74 | #define PO1030_REG_GC1 0x2e | ||
75 | #define PO1030_REG_GC2 0x2f | ||
76 | #define PO1030_REG_GC3 0x30 | ||
77 | #define PO1030_REG_GC4 0x31 | ||
78 | #define PO1030_REG_GC5 0x32 | ||
79 | #define PO1030_REG_GC6 0x33 | ||
80 | #define PO1030_REG_GC7 0x34 | ||
81 | |||
82 | /* Color Transform Matrix */ | ||
83 | #define PO1030_REG_CT0 0x35 | ||
84 | #define PO1030_REG_CT1 0x36 | ||
85 | #define PO1030_REG_CT2 0x37 | ||
86 | #define PO1030_REG_CT3 0x38 | ||
87 | #define PO1030_REG_CT4 0x39 | ||
88 | #define PO1030_REG_CT5 0x3a | ||
89 | #define PO1030_REG_CT6 0x3b | ||
90 | #define PO1030_REG_CT7 0x3c | ||
91 | #define PO1030_REG_CT8 0x3d | ||
92 | |||
93 | #define PO1030_REG_AUTOCTRL1 0x3e | ||
94 | #define PO1030_REG_AUTOCTRL2 0x3f | ||
95 | |||
96 | #define PO1030_REG_YTARGET 0x40 | ||
97 | #define PO1030_REG_GLOBALGAINMIN 0x41 | ||
98 | #define PO1030_REG_GLOBALGAINMAX 0x42 | ||
99 | |||
100 | /* Output format control */ | ||
101 | #define PO1030_REG_OUTFORMCTRL1 0x5a | ||
102 | #define PO1030_REG_OUTFORMCTRL2 0x5b | ||
103 | #define PO1030_REG_OUTFORMCTRL3 0x5c | ||
104 | #define PO1030_REG_OUTFORMCTRL4 0x5d | ||
105 | #define PO1030_REG_OUTFORMCTRL5 0x5e | ||
106 | |||
107 | /* Imaging coefficients */ | ||
108 | #define PO1030_REG_YBRIGHT 0x73 | ||
109 | #define PO1030_REG_YCONTRAST 0x74 | ||
110 | #define PO1030_REG_YSATURATION 0x75 | ||
111 | |||
112 | /*****************************************************************************/ | ||
113 | |||
114 | #define PO1030_GLOBAL_GAIN_DEFAULT 0x12 | ||
115 | #define PO1030_EXPOSURE_DEFAULT 0xf0ff | ||
116 | #define PO1030_BLUE_GAIN_DEFAULT 0x40 | ||
117 | #define PO1030_RED_GAIN_DEFAULT 0x40 | ||
118 | |||
119 | /*****************************************************************************/ | ||
120 | |||
121 | /* Kernel module parameters */ | ||
122 | extern int force_sensor; | ||
123 | extern int dump_sensor; | ||
124 | extern unsigned int m5602_debug; | ||
125 | |||
126 | int po1030_probe(struct sd *sd); | ||
127 | int po1030_init(struct sd *sd); | ||
128 | int po1030_power_down(struct sd *sd); | ||
129 | |||
130 | void po1030_dump_registers(struct sd *sd); | ||
131 | |||
132 | int po1030_read_sensor(struct sd *sd, const u8 address, | ||
133 | u8 *i2c_data, const u8 len); | ||
134 | int po1030_write_sensor(struct sd *sd, const u8 address, | ||
135 | u8 *i2c_data, const u8 len); | ||
136 | |||
137 | int po1030_get_exposure(struct gspca_dev *gspca_dev, __s32 *val); | ||
138 | int po1030_set_exposure(struct gspca_dev *gspca_dev, __s32 val); | ||
139 | int po1030_get_gain(struct gspca_dev *gspca_dev, __s32 *val); | ||
140 | int po1030_set_gain(struct gspca_dev *gspca_dev, __s32 val); | ||
141 | int po1030_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val); | ||
142 | int po1030_set_red_balance(struct gspca_dev *gspca_dev, __s32 val); | ||
143 | int po1030_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val); | ||
144 | int po1030_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val); | ||
145 | |||
146 | static struct m5602_sensor po1030 = { | ||
147 | .name = "PO1030", | ||
148 | |||
149 | .i2c_slave_id = 0xdc, | ||
150 | |||
151 | .probe = po1030_probe, | ||
152 | .init = po1030_init, | ||
153 | .power_down = po1030_power_down, | ||
154 | |||
155 | .nctrls = 4, | ||
156 | .ctrls = { | ||
157 | { | ||
158 | { | ||
159 | .id = V4L2_CID_GAIN, | ||
160 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
161 | .name = "gain", | ||
162 | .minimum = 0x00, | ||
163 | .maximum = 0xff, | ||
164 | .step = 0x1, | ||
165 | .default_value = PO1030_GLOBAL_GAIN_DEFAULT, | ||
166 | .flags = V4L2_CTRL_FLAG_SLIDER | ||
167 | }, | ||
168 | .set = po1030_set_gain, | ||
169 | .get = po1030_get_gain | ||
170 | }, { | ||
171 | { | ||
172 | .id = V4L2_CID_EXPOSURE, | ||
173 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
174 | .name = "exposure", | ||
175 | .minimum = 0x00, | ||
176 | .maximum = 0xffff, | ||
177 | .step = 0x1, | ||
178 | .default_value = PO1030_EXPOSURE_DEFAULT, | ||
179 | .flags = V4L2_CTRL_FLAG_SLIDER | ||
180 | }, | ||
181 | .set = po1030_set_exposure, | ||
182 | .get = po1030_get_exposure | ||
183 | }, { | ||
184 | { | ||
185 | .id = V4L2_CID_RED_BALANCE, | ||
186 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
187 | .name = "red balance", | ||
188 | .minimum = 0x00, | ||
189 | .maximum = 0xff, | ||
190 | .step = 0x1, | ||
191 | .default_value = PO1030_RED_GAIN_DEFAULT, | ||
192 | .flags = V4L2_CTRL_FLAG_SLIDER | ||
193 | }, | ||
194 | .set = po1030_set_red_balance, | ||
195 | .get = po1030_get_red_balance | ||
196 | }, { | ||
197 | { | ||
198 | .id = V4L2_CID_BLUE_BALANCE, | ||
199 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
200 | .name = "blue balance", | ||
201 | .minimum = 0x00, | ||
202 | .maximum = 0xff, | ||
203 | .step = 0x1, | ||
204 | .default_value = PO1030_BLUE_GAIN_DEFAULT, | ||
205 | .flags = V4L2_CTRL_FLAG_SLIDER | ||
206 | }, | ||
207 | .set = po1030_set_blue_balance, | ||
208 | .get = po1030_get_blue_balance | ||
209 | } | ||
210 | }, | ||
211 | .nmodes = 1, | ||
212 | .modes = { | ||
213 | { | ||
214 | M5602_DEFAULT_FRAME_WIDTH, | ||
215 | M5602_DEFAULT_FRAME_HEIGHT, | ||
216 | V4L2_PIX_FMT_SBGGR8, | ||
217 | V4L2_FIELD_NONE, | ||
218 | .sizeimage = | ||
219 | M5602_DEFAULT_FRAME_WIDTH * M5602_DEFAULT_FRAME_HEIGHT, | ||
220 | .bytesperline = M5602_DEFAULT_FRAME_WIDTH, | ||
221 | .colorspace = V4L2_COLORSPACE_SRGB, | ||
222 | .priv = 1 | ||
223 | } | ||
224 | } | ||
225 | }; | ||
226 | |||
227 | static const unsigned char preinit_po1030[][3] = | ||
228 | { | ||
229 | {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02}, | ||
230 | {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0}, | ||
231 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00}, | ||
232 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, | ||
233 | {BRIDGE, M5602_XB_ADC_CTRL, 0xc0}, | ||
234 | {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0d}, | ||
235 | {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00}, | ||
236 | {BRIDGE, M5602_XB_ADC_CTRL, 0xc0}, | ||
237 | {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c}, | ||
238 | |||
239 | {SENSOR, PO1030_REG_AUTOCTRL2, 0x24}, | ||
240 | |||
241 | {BRIDGE, M5602_XB_GPIO_DIR, 0x05}, | ||
242 | {BRIDGE, M5602_XB_GPIO_DAT, 0x04}, | ||
243 | {BRIDGE, M5602_XB_GPIO_EN_H, 0x06}, | ||
244 | {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06}, | ||
245 | {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02}, | ||
246 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04}, | ||
247 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, | ||
248 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06}, | ||
249 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, | ||
250 | {BRIDGE, M5602_XB_ADC_CTRL, 0xc0}, | ||
251 | {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c}, | ||
252 | {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81}, | ||
253 | {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82}, | ||
254 | {BRIDGE, M5602_XB_SIG_INI, 0x01}, | ||
255 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, | ||
256 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x02}, | ||
257 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, | ||
258 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, | ||
259 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x01}, | ||
260 | {BRIDGE, M5602_XB_VSYNC_PARA, 0xec}, | ||
261 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, | ||
262 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, | ||
263 | {BRIDGE, M5602_XB_SIG_INI, 0x00}, | ||
264 | {BRIDGE, M5602_XB_SIG_INI, 0x02}, | ||
265 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x00}, | ||
266 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x00}, | ||
267 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x02}, | ||
268 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x87}, | ||
269 | {BRIDGE, M5602_XB_SIG_INI, 0x00}, | ||
270 | |||
271 | {SENSOR, PO1030_REG_AUTOCTRL2, 0x24}, | ||
272 | |||
273 | {BRIDGE, M5602_XB_GPIO_DIR, 0x05}, | ||
274 | {BRIDGE, M5602_XB_GPIO_DAT, 0x04}, | ||
275 | {BRIDGE, M5602_XB_GPIO_EN_H, 0x06}, | ||
276 | {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06}, | ||
277 | {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02}, | ||
278 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04}, | ||
279 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, | ||
280 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00}, | ||
281 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, | ||
282 | {BRIDGE, M5602_XB_ADC_CTRL, 0xc0}, | ||
283 | {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c}, | ||
284 | {BRIDGE, M5602_XB_GPIO_DIR, 0x05}, | ||
285 | {BRIDGE, M5602_XB_GPIO_DAT, 0x00} | ||
286 | }; | ||
287 | |||
288 | static const unsigned char init_po1030[][4] = | ||
289 | { | ||
290 | {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02}, | ||
291 | {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0}, | ||
292 | /*sequence 1*/ | ||
293 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00}, | ||
294 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, | ||
295 | {BRIDGE, M5602_XB_ADC_CTRL, 0xc0}, | ||
296 | {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0d}, | ||
297 | |||
298 | {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00}, | ||
299 | {BRIDGE, M5602_XB_ADC_CTRL, 0xc0}, | ||
300 | {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c}, | ||
301 | /*end of sequence 1*/ | ||
302 | |||
303 | /*sequence 2 (same as stop sequence)*/ | ||
304 | {SENSOR, PO1030_REG_AUTOCTRL2, 0x24}, | ||
305 | {BRIDGE, M5602_XB_GPIO_DIR, 0x05}, | ||
306 | {BRIDGE, M5602_XB_GPIO_DAT, 0x04}, | ||
307 | {BRIDGE, M5602_XB_GPIO_EN_H, 0x06}, | ||
308 | {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06}, | ||
309 | {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02}, | ||
310 | |||
311 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04}, | ||
312 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, | ||
313 | /*end of sequence 2*/ | ||
314 | |||
315 | /*sequence 5*/ | ||
316 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06}, | ||
317 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, | ||
318 | {BRIDGE, M5602_XB_ADC_CTRL, 0xc0}, | ||
319 | {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c}, | ||
320 | {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81}, | ||
321 | {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82}, | ||
322 | {BRIDGE, M5602_XB_SIG_INI, 0x01}, | ||
323 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, | ||
324 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x02}, | ||
325 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, | ||
326 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, | ||
327 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x01}, | ||
328 | {BRIDGE, M5602_XB_VSYNC_PARA, 0xec}, | ||
329 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, | ||
330 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, | ||
331 | {BRIDGE, M5602_XB_SIG_INI, 0x00}, | ||
332 | {BRIDGE, M5602_XB_SIG_INI, 0x02}, | ||
333 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x00}, | ||
334 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x00}, | ||
335 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x02}, | ||
336 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x87}, | ||
337 | {BRIDGE, M5602_XB_SIG_INI, 0x00}, | ||
338 | /*end of sequence 5*/ | ||
339 | |||
340 | /*sequence 2 stop */ | ||
341 | {SENSOR, PO1030_REG_AUTOCTRL2, 0x24}, | ||
342 | |||
343 | {BRIDGE, M5602_XB_GPIO_DIR, 0x05}, | ||
344 | {BRIDGE, M5602_XB_GPIO_DAT, 0x04}, | ||
345 | {BRIDGE, M5602_XB_GPIO_EN_H, 0x06}, | ||
346 | {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06}, | ||
347 | {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02}, | ||
348 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04}, | ||
349 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, | ||
350 | /*end of sequence 2 stop */ | ||
351 | |||
352 | /* --------------------------------- | ||
353 | * end of init - begin of start | ||
354 | * --------------------------------- */ | ||
355 | |||
356 | /*sequence 3*/ | ||
357 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00}, | ||
358 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, | ||
359 | {BRIDGE, M5602_XB_ADC_CTRL, 0xc0}, | ||
360 | {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c}, | ||
361 | /*end of sequence 3*/ | ||
362 | /*sequence 4*/ | ||
363 | {BRIDGE, M5602_XB_GPIO_DIR, 0x05}, | ||
364 | {BRIDGE, M5602_XB_GPIO_DAT, 0x00}, | ||
365 | {BRIDGE, M5602_XB_GPIO_EN_H, 0x06}, | ||
366 | {BRIDGE, M5602_XB_GPIO_EN_L, 0x00}, | ||
367 | |||
368 | {SENSOR, PO1030_REG_AUTOCTRL2, 0x04}, | ||
369 | |||
370 | /* Set the width to 751 */ | ||
371 | {SENSOR, PO1030_REG_FRAMEWIDTH_H, 0x02}, | ||
372 | {SENSOR, PO1030_REG_FRAMEWIDTH_L, 0xef}, | ||
373 | |||
374 | /* Set the height to 540 */ | ||
375 | {SENSOR, PO1030_REG_FRAMEHEIGHT_H, 0x02}, | ||
376 | {SENSOR, PO1030_REG_FRAMEHEIGHT_L, 0x1c}, | ||
377 | |||
378 | /* Set the x window to 1 */ | ||
379 | {SENSOR, PO1030_REG_WINDOWX_H, 0x00}, | ||
380 | {SENSOR, PO1030_REG_WINDOWX_L, 0x01}, | ||
381 | |||
382 | /* Set the y window to 1 */ | ||
383 | {SENSOR, PO1030_REG_WINDOWY_H, 0x00}, | ||
384 | {SENSOR, PO1030_REG_WINDOWX_L, 0x01}, | ||
385 | |||
386 | {SENSOR, PO1030_REG_WINDOWWIDTH_H, 0x02}, | ||
387 | {SENSOR, PO1030_REG_WINDOWWIDTH_L, 0x87}, | ||
388 | {SENSOR, PO1030_REG_WINDOWHEIGHT_H, 0x01}, | ||
389 | {SENSOR, PO1030_REG_WINDOWHEIGHT_L, 0xe3}, | ||
390 | |||
391 | {SENSOR, PO1030_REG_OUTFORMCTRL2, 0x04}, | ||
392 | {SENSOR, PO1030_REG_OUTFORMCTRL2, 0x04}, | ||
393 | {SENSOR, PO1030_REG_AUTOCTRL1, 0x08}, | ||
394 | {SENSOR, PO1030_REG_CONTROL2, 0x03}, | ||
395 | {SENSOR, 0x21, 0x90}, | ||
396 | {SENSOR, PO1030_REG_YTARGET, 0x60}, | ||
397 | {SENSOR, 0x59, 0x13}, | ||
398 | {SENSOR, PO1030_REG_OUTFORMCTRL1, 0x40}, | ||
399 | {SENSOR, 0x5f, 0x00}, | ||
400 | {SENSOR, 0x60, 0x80}, | ||
401 | {SENSOR, 0x78, 0x14}, | ||
402 | {SENSOR, 0x6f, 0x01}, | ||
403 | {SENSOR, PO1030_REG_CONTROL1, 0x18}, | ||
404 | {SENSOR, PO1030_REG_GLOBALGAINMAX, 0x14}, | ||
405 | {SENSOR, 0x63, 0x38}, | ||
406 | {SENSOR, 0x64, 0x38}, | ||
407 | {SENSOR, PO1030_REG_CONTROL1, 0x58}, | ||
408 | {SENSOR, PO1030_REG_RED_GAIN, 0x30}, | ||
409 | {SENSOR, PO1030_REG_GREEN_1_GAIN, 0x30}, | ||
410 | {SENSOR, PO1030_REG_BLUE_GAIN, 0x30}, | ||
411 | {SENSOR, PO1030_REG_GREEN_2_GAIN, 0x30}, | ||
412 | {SENSOR, PO1030_REG_GC0, 0x10}, | ||
413 | {SENSOR, PO1030_REG_GC1, 0x20}, | ||
414 | {SENSOR, PO1030_REG_GC2, 0x40}, | ||
415 | {SENSOR, PO1030_REG_GC3, 0x60}, | ||
416 | {SENSOR, PO1030_REG_GC4, 0x80}, | ||
417 | {SENSOR, PO1030_REG_GC5, 0xa0}, | ||
418 | {SENSOR, PO1030_REG_GC6, 0xc0}, | ||
419 | {SENSOR, PO1030_REG_GC7, 0xff}, | ||
420 | /*end of sequence 4*/ | ||
421 | /*sequence 5*/ | ||
422 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06}, | ||
423 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, | ||
424 | {BRIDGE, M5602_XB_ADC_CTRL, 0xc0}, | ||
425 | {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c}, | ||
426 | {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81}, | ||
427 | {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82}, | ||
428 | {BRIDGE, M5602_XB_SIG_INI, 0x01}, | ||
429 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, | ||
430 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x02}, | ||
431 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, | ||
432 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, | ||
433 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x01}, | ||
434 | {BRIDGE, M5602_XB_VSYNC_PARA, 0xec}, | ||
435 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, | ||
436 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, | ||
437 | {BRIDGE, M5602_XB_SIG_INI, 0x00}, | ||
438 | {BRIDGE, M5602_XB_SIG_INI, 0x00}, | ||
439 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x00}, | ||
440 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x00}, | ||
441 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x02}, | ||
442 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x7e}, | ||
443 | {BRIDGE, M5602_XB_SIG_INI, 0x00}, | ||
444 | /*end of sequence 5*/ | ||
445 | |||
446 | /*sequence 6*/ | ||
447 | /* Changing 40 in f0 the image becomes green in bayer mode and red in | ||
448 | * rgb mode */ | ||
449 | {SENSOR, PO1030_REG_RED_GAIN, PO1030_RED_GAIN_DEFAULT}, | ||
450 | /* in changing 40 in f0 the image becomes green in bayer mode and red in | ||
451 | * rgb mode */ | ||
452 | {SENSOR, PO1030_REG_BLUE_GAIN, PO1030_BLUE_GAIN_DEFAULT}, | ||
453 | |||
454 | /* with a very low lighted environment increase the exposure but | ||
455 | * decrease the FPS (Frame Per Second) */ | ||
456 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00}, | ||
457 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, | ||
458 | |||
459 | /* Controls high exposure more than SENSOR_LOW_EXPOSURE, use only in | ||
460 | * low lighted environment (f0 is more than ff ?)*/ | ||
461 | {SENSOR, PO1030_REG_INTEGLINES_H, ((PO1030_EXPOSURE_DEFAULT >> 2) | ||
462 | & 0xff)}, | ||
463 | |||
464 | /* Controls middle exposure, use only in high lighted environment */ | ||
465 | {SENSOR, PO1030_REG_INTEGLINES_M, PO1030_EXPOSURE_DEFAULT & 0xff}, | ||
466 | |||
467 | /* Controls clarity (not sure) */ | ||
468 | {SENSOR, PO1030_REG_INTEGLINES_L, 0x00}, | ||
469 | /* Controls gain (the image is more lighted) */ | ||
470 | {SENSOR, PO1030_REG_GLOBALGAIN, PO1030_GLOBAL_GAIN_DEFAULT}, | ||
471 | |||
472 | /* Sets the width */ | ||
473 | {SENSOR, PO1030_REG_FRAMEWIDTH_H, 0x02}, | ||
474 | {SENSOR, PO1030_REG_FRAMEWIDTH_L, 0xef} | ||
475 | /*end of sequence 6*/ | ||
476 | }; | ||
477 | |||
478 | #endif | ||
diff --git a/drivers/media/video/gspca/m5602/m5602_s5k4aa.c b/drivers/media/video/gspca/m5602/m5602_s5k4aa.c new file mode 100644 index 000000000000..68202565325d --- /dev/null +++ b/drivers/media/video/gspca/m5602/m5602_s5k4aa.c | |||
@@ -0,0 +1,463 @@ | |||
1 | /* | ||
2 | * Driver for the s5k4aa sensor | ||
3 | * | ||
4 | * Copyright (C) 2008 Erik Andren | ||
5 | * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project. | ||
6 | * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br> | ||
7 | * | ||
8 | * Portions of code to USB interface and ALi driver software, | ||
9 | * Copyright (c) 2006 Willem Duinker | ||
10 | * v4l2 interface modeled after the V4L2 driver | ||
11 | * for SN9C10x PC Camera Controllers | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or | ||
14 | * modify it under the terms of the GNU General Public License as | ||
15 | * published by the Free Software Foundation, version 2. | ||
16 | * | ||
17 | */ | ||
18 | |||
19 | #include "m5602_s5k4aa.h" | ||
20 | |||
21 | int s5k4aa_probe(struct sd *sd) | ||
22 | { | ||
23 | u8 prod_id[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; | ||
24 | const u8 expected_prod_id[6] = {0x00, 0x10, 0x00, 0x4b, 0x33, 0x75}; | ||
25 | int i, err = 0; | ||
26 | |||
27 | if (force_sensor) { | ||
28 | if (force_sensor == S5K4AA_SENSOR) { | ||
29 | info("Forcing a %s sensor", s5k4aa.name); | ||
30 | goto sensor_found; | ||
31 | } | ||
32 | /* If we want to force another sensor, don't try to probe this | ||
33 | * one */ | ||
34 | return -ENODEV; | ||
35 | } | ||
36 | |||
37 | info("Probing for a s5k4aa sensor"); | ||
38 | |||
39 | /* Preinit the sensor */ | ||
40 | for (i = 0; i < ARRAY_SIZE(preinit_s5k4aa) && !err; i++) { | ||
41 | u8 data[2] = {0x00, 0x00}; | ||
42 | |||
43 | switch (preinit_s5k4aa[i][0]) { | ||
44 | case BRIDGE: | ||
45 | err = m5602_write_bridge(sd, | ||
46 | preinit_s5k4aa[i][1], | ||
47 | preinit_s5k4aa[i][2]); | ||
48 | break; | ||
49 | |||
50 | case SENSOR: | ||
51 | data[0] = preinit_s5k4aa[i][2]; | ||
52 | err = s5k4aa_write_sensor(sd, | ||
53 | preinit_s5k4aa[i][1], | ||
54 | data, 1); | ||
55 | break; | ||
56 | |||
57 | case SENSOR_LONG: | ||
58 | data[0] = preinit_s5k4aa[i][2]; | ||
59 | data[1] = preinit_s5k4aa[i][3]; | ||
60 | err = s5k4aa_write_sensor(sd, | ||
61 | preinit_s5k4aa[i][1], | ||
62 | data, 2); | ||
63 | break; | ||
64 | default: | ||
65 | info("Invalid stream command, exiting init"); | ||
66 | return -EINVAL; | ||
67 | } | ||
68 | } | ||
69 | |||
70 | /* Test some registers, but we don't know their exact meaning yet */ | ||
71 | if (s5k4aa_read_sensor(sd, 0x00, prod_id, sizeof(prod_id))) | ||
72 | return -ENODEV; | ||
73 | |||
74 | if (memcmp(prod_id, expected_prod_id, sizeof(prod_id))) | ||
75 | return -ENODEV; | ||
76 | else | ||
77 | info("Detected a s5k4aa sensor"); | ||
78 | sensor_found: | ||
79 | sd->gspca_dev.cam.cam_mode = s5k4aa.modes; | ||
80 | sd->gspca_dev.cam.nmodes = s5k4aa.nmodes; | ||
81 | sd->desc->ctrls = s5k4aa.ctrls; | ||
82 | sd->desc->nctrls = s5k4aa.nctrls; | ||
83 | |||
84 | return 0; | ||
85 | } | ||
86 | |||
87 | int s5k4aa_read_sensor(struct sd *sd, const u8 address, | ||
88 | u8 *i2c_data, const u8 len) | ||
89 | { | ||
90 | int err, i; | ||
91 | |||
92 | do { | ||
93 | err = m5602_read_bridge(sd, M5602_XB_I2C_STATUS, i2c_data); | ||
94 | } while ((*i2c_data & I2C_BUSY) && !err); | ||
95 | if (err < 0) | ||
96 | goto out; | ||
97 | |||
98 | err = m5602_write_bridge(sd, M5602_XB_I2C_DEV_ADDR, | ||
99 | sd->sensor->i2c_slave_id); | ||
100 | if (err < 0) | ||
101 | goto out; | ||
102 | |||
103 | err = m5602_write_bridge(sd, M5602_XB_I2C_REG_ADDR, address); | ||
104 | if (err < 0) | ||
105 | goto out; | ||
106 | |||
107 | err = m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 0x18 + len); | ||
108 | if (err < 0) | ||
109 | goto out; | ||
110 | |||
111 | do { | ||
112 | err = m5602_read_bridge(sd, M5602_XB_I2C_STATUS, i2c_data); | ||
113 | } while ((*i2c_data & I2C_BUSY) && !err); | ||
114 | if (err < 0) | ||
115 | goto out; | ||
116 | |||
117 | for (i = 0; (i < len) & !err; i++) { | ||
118 | err = m5602_read_bridge(sd, M5602_XB_I2C_DATA, &(i2c_data[i])); | ||
119 | |||
120 | PDEBUG(DBG_TRACE, "Reading sensor register " | ||
121 | "0x%x containing 0x%x ", address, *i2c_data); | ||
122 | } | ||
123 | out: | ||
124 | return (err < 0) ? err : 0; | ||
125 | } | ||
126 | |||
127 | int s5k4aa_write_sensor(struct sd *sd, const u8 address, | ||
128 | u8 *i2c_data, const u8 len) | ||
129 | { | ||
130 | int err, i; | ||
131 | u8 *p; | ||
132 | struct usb_device *udev = sd->gspca_dev.dev; | ||
133 | __u8 *buf = sd->gspca_dev.usb_buf; | ||
134 | |||
135 | /* No sensor with a data width larger than 16 bits has yet been seen */ | ||
136 | if (len > 2 || !len) | ||
137 | return -EINVAL; | ||
138 | |||
139 | memcpy(buf, sensor_urb_skeleton, | ||
140 | sizeof(sensor_urb_skeleton)); | ||
141 | |||
142 | buf[11] = sd->sensor->i2c_slave_id; | ||
143 | buf[15] = address; | ||
144 | |||
145 | /* Special case larger sensor writes */ | ||
146 | p = buf + 16; | ||
147 | |||
148 | /* Copy a four byte write sequence for each byte to be written to */ | ||
149 | for (i = 0; i < len; i++) { | ||
150 | memcpy(p, sensor_urb_skeleton + 16, 4); | ||
151 | p[3] = i2c_data[i]; | ||
152 | p += 4; | ||
153 | PDEBUG(DBG_TRACE, "Writing sensor register 0x%x with 0x%x", | ||
154 | address, i2c_data[i]); | ||
155 | } | ||
156 | |||
157 | /* Copy the tailer */ | ||
158 | memcpy(p, sensor_urb_skeleton + 20, 4); | ||
159 | |||
160 | /* Set the total length */ | ||
161 | p[3] = 0x10 + len; | ||
162 | |||
163 | err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), | ||
164 | 0x04, 0x40, 0x19, | ||
165 | 0x0000, buf, | ||
166 | 20 + len * 4, M5602_URB_MSG_TIMEOUT); | ||
167 | |||
168 | return (err < 0) ? err : 0; | ||
169 | } | ||
170 | |||
171 | int s5k4aa_init(struct sd *sd) | ||
172 | { | ||
173 | int i, err = 0; | ||
174 | |||
175 | for (i = 0; i < ARRAY_SIZE(init_s5k4aa) && !err; i++) { | ||
176 | u8 data[2] = {0x00, 0x00}; | ||
177 | |||
178 | switch (init_s5k4aa[i][0]) { | ||
179 | case BRIDGE: | ||
180 | err = m5602_write_bridge(sd, | ||
181 | init_s5k4aa[i][1], | ||
182 | init_s5k4aa[i][2]); | ||
183 | break; | ||
184 | |||
185 | case SENSOR: | ||
186 | data[0] = init_s5k4aa[i][2]; | ||
187 | err = s5k4aa_write_sensor(sd, | ||
188 | init_s5k4aa[i][1], data, 1); | ||
189 | break; | ||
190 | |||
191 | case SENSOR_LONG: | ||
192 | data[0] = init_s5k4aa[i][2]; | ||
193 | data[1] = init_s5k4aa[i][3]; | ||
194 | err = s5k4aa_write_sensor(sd, | ||
195 | init_s5k4aa[i][1], data, 2); | ||
196 | break; | ||
197 | default: | ||
198 | info("Invalid stream command, exiting init"); | ||
199 | return -EINVAL; | ||
200 | } | ||
201 | } | ||
202 | |||
203 | if (dump_sensor) | ||
204 | s5k4aa_dump_registers(sd); | ||
205 | |||
206 | if (!err && dmi_check_system(s5k4aa_vflip_dmi_table)) { | ||
207 | u8 data = 0x02; | ||
208 | info("vertical flip quirk active"); | ||
209 | s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); | ||
210 | s5k4aa_read_sensor(sd, S5K4AA_READ_MODE, &data, 1); | ||
211 | data |= S5K4AA_RM_V_FLIP; | ||
212 | data &= ~S5K4AA_RM_H_FLIP; | ||
213 | s5k4aa_write_sensor(sd, S5K4AA_READ_MODE, &data, 1); | ||
214 | |||
215 | /* Decrement COLSTART to preserve color order (BGGR) */ | ||
216 | s5k4aa_read_sensor(sd, S5K4AA_COLSTART_LO, &data, 1); | ||
217 | data--; | ||
218 | s5k4aa_write_sensor(sd, S5K4AA_COLSTART_LO, &data, 1); | ||
219 | |||
220 | /* Increment ROWSTART to preserve color order (BGGR) */ | ||
221 | s5k4aa_read_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1); | ||
222 | data++; | ||
223 | s5k4aa_write_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1); | ||
224 | } | ||
225 | |||
226 | return (err < 0) ? err : 0; | ||
227 | } | ||
228 | |||
229 | int s5k4aa_power_down(struct sd *sd) | ||
230 | { | ||
231 | return 0; | ||
232 | } | ||
233 | |||
234 | int s5k4aa_get_exposure(struct gspca_dev *gspca_dev, __s32 *val) | ||
235 | { | ||
236 | struct sd *sd = (struct sd *) gspca_dev; | ||
237 | u8 data = S5K4AA_PAGE_MAP_2; | ||
238 | int err; | ||
239 | |||
240 | err = s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); | ||
241 | if (err < 0) | ||
242 | goto out; | ||
243 | |||
244 | err = s5k4aa_read_sensor(sd, S5K4AA_EXPOSURE_HI, &data, 1); | ||
245 | if (err < 0) | ||
246 | goto out; | ||
247 | |||
248 | *val = data << 8; | ||
249 | err = s5k4aa_read_sensor(sd, S5K4AA_EXPOSURE_LO, &data, 1); | ||
250 | *val |= data; | ||
251 | PDEBUG(DBG_V4L2_CID, "Read exposure %d", *val); | ||
252 | out: | ||
253 | return (err < 0) ? err : 0; | ||
254 | } | ||
255 | |||
256 | int s5k4aa_set_exposure(struct gspca_dev *gspca_dev, __s32 val) | ||
257 | { | ||
258 | struct sd *sd = (struct sd *) gspca_dev; | ||
259 | u8 data = S5K4AA_PAGE_MAP_2; | ||
260 | int err; | ||
261 | |||
262 | PDEBUG(DBG_V4L2_CID, "Set exposure to %d", val); | ||
263 | err = s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); | ||
264 | if (err < 0) | ||
265 | goto out; | ||
266 | data = (val >> 8) & 0xff; | ||
267 | err = s5k4aa_write_sensor(sd, S5K4AA_EXPOSURE_HI, &data, 1); | ||
268 | if (err < 0) | ||
269 | goto out; | ||
270 | data = val & 0xff; | ||
271 | err = s5k4aa_write_sensor(sd, S5K4AA_EXPOSURE_LO, &data, 1); | ||
272 | out: | ||
273 | return (err < 0) ? err : 0; | ||
274 | } | ||
275 | |||
276 | int s5k4aa_get_vflip(struct gspca_dev *gspca_dev, __s32 *val) | ||
277 | { | ||
278 | struct sd *sd = (struct sd *) gspca_dev; | ||
279 | u8 data = S5K4AA_PAGE_MAP_2; | ||
280 | int err; | ||
281 | |||
282 | err = s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); | ||
283 | if (err < 0) | ||
284 | goto out; | ||
285 | |||
286 | err = s5k4aa_read_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); | ||
287 | *val = (data & S5K4AA_RM_V_FLIP) >> 7; | ||
288 | PDEBUG(DBG_V4L2_CID, "Read vertical flip %d", *val); | ||
289 | |||
290 | out: | ||
291 | return (err < 0) ? err : 0; | ||
292 | } | ||
293 | |||
294 | int s5k4aa_set_vflip(struct gspca_dev *gspca_dev, __s32 val) | ||
295 | { | ||
296 | struct sd *sd = (struct sd *) gspca_dev; | ||
297 | u8 data = S5K4AA_PAGE_MAP_2; | ||
298 | int err; | ||
299 | |||
300 | PDEBUG(DBG_V4L2_CID, "Set vertical flip to %d", val); | ||
301 | err = s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); | ||
302 | if (err < 0) | ||
303 | goto out; | ||
304 | err = s5k4aa_write_sensor(sd, S5K4AA_READ_MODE, &data, 1); | ||
305 | if (err < 0) | ||
306 | goto out; | ||
307 | data = ((data & ~S5K4AA_RM_V_FLIP) | ||
308 | | ((val & 0x01) << 7)); | ||
309 | err = s5k4aa_write_sensor(sd, S5K4AA_READ_MODE, &data, 1); | ||
310 | if (err < 0) | ||
311 | goto out; | ||
312 | |||
313 | if (val) { | ||
314 | err = s5k4aa_read_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1); | ||
315 | if (err < 0) | ||
316 | goto out; | ||
317 | |||
318 | data++; | ||
319 | err = s5k4aa_write_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1); | ||
320 | } else { | ||
321 | err = s5k4aa_read_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1); | ||
322 | if (err < 0) | ||
323 | goto out; | ||
324 | |||
325 | data--; | ||
326 | err = s5k4aa_write_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1); | ||
327 | } | ||
328 | out: | ||
329 | return (err < 0) ? err : 0; | ||
330 | } | ||
331 | |||
332 | int s5k4aa_get_hflip(struct gspca_dev *gspca_dev, __s32 *val) | ||
333 | { | ||
334 | struct sd *sd = (struct sd *) gspca_dev; | ||
335 | u8 data = S5K4AA_PAGE_MAP_2; | ||
336 | int err; | ||
337 | |||
338 | err = s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); | ||
339 | if (err < 0) | ||
340 | goto out; | ||
341 | |||
342 | err = s5k4aa_read_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); | ||
343 | *val = (data & S5K4AA_RM_H_FLIP) >> 6; | ||
344 | PDEBUG(DBG_V4L2_CID, "Read horizontal flip %d", *val); | ||
345 | out: | ||
346 | return (err < 0) ? err : 0; | ||
347 | } | ||
348 | |||
349 | int s5k4aa_set_hflip(struct gspca_dev *gspca_dev, __s32 val) | ||
350 | { | ||
351 | struct sd *sd = (struct sd *) gspca_dev; | ||
352 | u8 data = S5K4AA_PAGE_MAP_2; | ||
353 | int err; | ||
354 | |||
355 | PDEBUG(DBG_V4L2_CID, "Set horizontal flip to %d", | ||
356 | val); | ||
357 | err = s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); | ||
358 | if (err < 0) | ||
359 | goto out; | ||
360 | err = s5k4aa_write_sensor(sd, S5K4AA_READ_MODE, &data, 1); | ||
361 | if (err < 0) | ||
362 | goto out; | ||
363 | |||
364 | data = ((data & ~S5K4AA_RM_H_FLIP) | ((val & 0x01) << 6)); | ||
365 | err = s5k4aa_write_sensor(sd, S5K4AA_READ_MODE, &data, 1); | ||
366 | if (err < 0) | ||
367 | goto out; | ||
368 | |||
369 | if (val) { | ||
370 | err = s5k4aa_read_sensor(sd, S5K4AA_COLSTART_LO, &data, 1); | ||
371 | if (err < 0) | ||
372 | goto out; | ||
373 | data++; | ||
374 | err = s5k4aa_write_sensor(sd, S5K4AA_COLSTART_LO, &data, 1); | ||
375 | if (err < 0) | ||
376 | goto out; | ||
377 | } else { | ||
378 | err = s5k4aa_read_sensor(sd, S5K4AA_COLSTART_LO, &data, 1); | ||
379 | if (err < 0) | ||
380 | goto out; | ||
381 | data--; | ||
382 | err = s5k4aa_write_sensor(sd, S5K4AA_COLSTART_LO, &data, 1); | ||
383 | } | ||
384 | out: | ||
385 | return (err < 0) ? err : 0; | ||
386 | } | ||
387 | |||
388 | int s5k4aa_get_gain(struct gspca_dev *gspca_dev, __s32 *val) | ||
389 | { | ||
390 | struct sd *sd = (struct sd *) gspca_dev; | ||
391 | u8 data = S5K4AA_PAGE_MAP_2; | ||
392 | int err; | ||
393 | |||
394 | err = s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); | ||
395 | if (err < 0) | ||
396 | goto out; | ||
397 | |||
398 | err = s5k4aa_read_sensor(sd, S5K4AA_GAIN_2, &data, 1); | ||
399 | *val = data; | ||
400 | PDEBUG(DBG_V4L2_CID, "Read gain %d", *val); | ||
401 | |||
402 | out: | ||
403 | return (err < 0) ? err : 0; | ||
404 | } | ||
405 | |||
406 | int s5k4aa_set_gain(struct gspca_dev *gspca_dev, __s32 val) | ||
407 | { | ||
408 | struct sd *sd = (struct sd *) gspca_dev; | ||
409 | u8 data = S5K4AA_PAGE_MAP_2; | ||
410 | int err; | ||
411 | |||
412 | PDEBUG(DBG_V4L2_CID, "Set gain to %d", val); | ||
413 | err = s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); | ||
414 | if (err < 0) | ||
415 | goto out; | ||
416 | |||
417 | data = val & 0xff; | ||
418 | err = s5k4aa_write_sensor(sd, S5K4AA_GAIN_2, &data, 1); | ||
419 | |||
420 | out: | ||
421 | return (err < 0) ? err : 0; | ||
422 | } | ||
423 | |||
424 | void s5k4aa_dump_registers(struct sd *sd) | ||
425 | { | ||
426 | int address; | ||
427 | u8 page, old_page; | ||
428 | s5k4aa_read_sensor(sd, S5K4AA_PAGE_MAP, &old_page, 1); | ||
429 | for (page = 0; page < 16; page++) { | ||
430 | s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &page, 1); | ||
431 | info("Dumping the s5k4aa register state for page 0x%x", page); | ||
432 | for (address = 0; address <= 0xff; address++) { | ||
433 | u8 value = 0; | ||
434 | s5k4aa_read_sensor(sd, address, &value, 1); | ||
435 | info("register 0x%x contains 0x%x", | ||
436 | address, value); | ||
437 | } | ||
438 | } | ||
439 | info("s5k4aa register state dump complete"); | ||
440 | |||
441 | for (page = 0; page < 16; page++) { | ||
442 | s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &page, 1); | ||
443 | info("Probing for which registers that are " | ||
444 | "read/write for page 0x%x", page); | ||
445 | for (address = 0; address <= 0xff; address++) { | ||
446 | u8 old_value, ctrl_value, test_value = 0xff; | ||
447 | |||
448 | s5k4aa_read_sensor(sd, address, &old_value, 1); | ||
449 | s5k4aa_write_sensor(sd, address, &test_value, 1); | ||
450 | s5k4aa_read_sensor(sd, address, &ctrl_value, 1); | ||
451 | |||
452 | if (ctrl_value == test_value) | ||
453 | info("register 0x%x is writeable", address); | ||
454 | else | ||
455 | info("register 0x%x is read only", address); | ||
456 | |||
457 | /* Restore original value */ | ||
458 | s5k4aa_write_sensor(sd, address, &old_value, 1); | ||
459 | } | ||
460 | } | ||
461 | info("Read/write register probing complete"); | ||
462 | s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &old_page, 1); | ||
463 | } | ||
diff --git a/drivers/media/video/gspca/m5602/m5602_s5k4aa.h b/drivers/media/video/gspca/m5602/m5602_s5k4aa.h new file mode 100644 index 000000000000..bb7f7e3e90af --- /dev/null +++ b/drivers/media/video/gspca/m5602/m5602_s5k4aa.h | |||
@@ -0,0 +1,370 @@ | |||
1 | /* | ||
2 | * Driver for the s5k4aa sensor | ||
3 | * | ||
4 | * Copyright (C) 2008 Erik Andren | ||
5 | * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project. | ||
6 | * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br> | ||
7 | * | ||
8 | * Portions of code to USB interface and ALi driver software, | ||
9 | * Copyright (c) 2006 Willem Duinker | ||
10 | * v4l2 interface modeled after the V4L2 driver | ||
11 | * for SN9C10x PC Camera Controllers | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or | ||
14 | * modify it under the terms of the GNU General Public License as | ||
15 | * published by the Free Software Foundation, version 2. | ||
16 | * | ||
17 | */ | ||
18 | |||
19 | #ifndef M5602_S5K4AA_H_ | ||
20 | #define M5602_S5K4AA_H_ | ||
21 | |||
22 | #include <linux/dmi.h> | ||
23 | |||
24 | #include "m5602_sensor.h" | ||
25 | |||
26 | /*****************************************************************************/ | ||
27 | |||
28 | #define S5K4AA_PAGE_MAP 0xec | ||
29 | |||
30 | #define S5K4AA_PAGE_MAP_0 0x00 | ||
31 | #define S5K4AA_PAGE_MAP_1 0x01 | ||
32 | #define S5K4AA_PAGE_MAP_2 0x02 | ||
33 | |||
34 | /* Sensor register definitions for page 0x02 */ | ||
35 | #define S5K4AA_READ_MODE 0x03 | ||
36 | #define S5K4AA_ROWSTART_HI 0x04 | ||
37 | #define S5K4AA_ROWSTART_LO 0x05 | ||
38 | #define S5K4AA_COLSTART_HI 0x06 | ||
39 | #define S5K4AA_COLSTART_LO 0x07 | ||
40 | #define S5K4AA_WINDOW_HEIGHT_HI 0x08 | ||
41 | #define S5K4AA_WINDOW_HEIGHT_LO 0x09 | ||
42 | #define S5K4AA_WINDOW_WIDTH_HI 0x0a | ||
43 | #define S5K4AA_WINDOW_WIDTH_LO 0x0b | ||
44 | #define S5K4AA_GLOBAL_GAIN__ 0x0f /* Only a guess ATM !!! */ | ||
45 | #define S5K4AA_H_BLANK_HI__ 0x1d /* Only a guess ATM !!! sync lost | ||
46 | if too low, reduces frame rate | ||
47 | if too high */ | ||
48 | #define S5K4AA_H_BLANK_LO__ 0x1e /* Only a guess ATM !!! */ | ||
49 | #define S5K4AA_EXPOSURE_HI 0x17 | ||
50 | #define S5K4AA_EXPOSURE_LO 0x18 | ||
51 | #define S5K4AA_GAIN_1 0x1f /* (digital?) gain : 5 bits */ | ||
52 | #define S5K4AA_GAIN_2 0x20 /* (analogue?) gain : 7 bits */ | ||
53 | |||
54 | #define S5K4AA_RM_ROW_SKIP_4X 0x08 | ||
55 | #define S5K4AA_RM_ROW_SKIP_2X 0x04 | ||
56 | #define S5K4AA_RM_COL_SKIP_4X 0x02 | ||
57 | #define S5K4AA_RM_COL_SKIP_2X 0x01 | ||
58 | #define S5K4AA_RM_H_FLIP 0x40 | ||
59 | #define S5K4AA_RM_V_FLIP 0x80 | ||
60 | |||
61 | /*****************************************************************************/ | ||
62 | |||
63 | /* Kernel module parameters */ | ||
64 | extern int force_sensor; | ||
65 | extern int dump_sensor; | ||
66 | extern unsigned int m5602_debug; | ||
67 | |||
68 | int s5k4aa_probe(struct sd *sd); | ||
69 | int s5k4aa_init(struct sd *sd); | ||
70 | int s5k4aa_power_down(struct sd *sd); | ||
71 | |||
72 | void s5k4aa_dump_registers(struct sd *sd); | ||
73 | |||
74 | int s5k4aa_read_sensor(struct sd *sd, const u8 address, | ||
75 | u8 *i2c_data, const u8 len); | ||
76 | int s5k4aa_write_sensor(struct sd *sd, const u8 address, | ||
77 | u8 *i2c_data, const u8 len); | ||
78 | |||
79 | int s5k4aa_get_exposure(struct gspca_dev *gspca_dev, __s32 *val); | ||
80 | int s5k4aa_set_exposure(struct gspca_dev *gspca_dev, __s32 val); | ||
81 | int s5k4aa_get_vflip(struct gspca_dev *gspca_dev, __s32 *val); | ||
82 | int s5k4aa_set_vflip(struct gspca_dev *gspca_dev, __s32 val); | ||
83 | int s5k4aa_get_hflip(struct gspca_dev *gspca_dev, __s32 *val); | ||
84 | int s5k4aa_set_hflip(struct gspca_dev *gspca_dev, __s32 val); | ||
85 | int s5k4aa_get_gain(struct gspca_dev *gspca_dev, __s32 *val); | ||
86 | int s5k4aa_set_gain(struct gspca_dev *gspca_dev, __s32 val); | ||
87 | |||
88 | static struct m5602_sensor s5k4aa = { | ||
89 | .name = "S5K4AA", | ||
90 | .probe = s5k4aa_probe, | ||
91 | .init = s5k4aa_init, | ||
92 | .power_down = s5k4aa_power_down, | ||
93 | .read_sensor = s5k4aa_read_sensor, | ||
94 | .write_sensor = s5k4aa_write_sensor, | ||
95 | .i2c_slave_id = 0x5a, | ||
96 | .nctrls = 4, | ||
97 | .ctrls = { | ||
98 | { | ||
99 | { | ||
100 | .id = V4L2_CID_VFLIP, | ||
101 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
102 | .name = "vertical flip", | ||
103 | .minimum = 0, | ||
104 | .maximum = 1, | ||
105 | .step = 1, | ||
106 | .default_value = 0 | ||
107 | }, | ||
108 | .set = s5k4aa_set_vflip, | ||
109 | .get = s5k4aa_get_vflip | ||
110 | |||
111 | }, { | ||
112 | { | ||
113 | .id = V4L2_CID_HFLIP, | ||
114 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
115 | .name = "horizontal flip", | ||
116 | .minimum = 0, | ||
117 | .maximum = 1, | ||
118 | .step = 1, | ||
119 | .default_value = 0 | ||
120 | }, | ||
121 | .set = s5k4aa_set_hflip, | ||
122 | .get = s5k4aa_get_hflip | ||
123 | |||
124 | }, { | ||
125 | { | ||
126 | .id = V4L2_CID_GAIN, | ||
127 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
128 | .name = "Gain", | ||
129 | .minimum = 0, | ||
130 | .maximum = 127, | ||
131 | .step = 1, | ||
132 | .default_value = 0xa0, | ||
133 | .flags = V4L2_CTRL_FLAG_SLIDER | ||
134 | }, | ||
135 | .set = s5k4aa_set_gain, | ||
136 | .get = s5k4aa_get_gain | ||
137 | }, { | ||
138 | { | ||
139 | .id = V4L2_CID_EXPOSURE, | ||
140 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
141 | .name = "Exposure", | ||
142 | .minimum = 13, | ||
143 | .maximum = 0xfff, | ||
144 | .step = 1, | ||
145 | .default_value = 0x100, | ||
146 | .flags = V4L2_CTRL_FLAG_SLIDER | ||
147 | }, | ||
148 | .set = s5k4aa_set_exposure, | ||
149 | .get = s5k4aa_get_exposure | ||
150 | } | ||
151 | }, | ||
152 | |||
153 | .nmodes = 1, | ||
154 | .modes = { | ||
155 | { | ||
156 | M5602_DEFAULT_FRAME_WIDTH, | ||
157 | M5602_DEFAULT_FRAME_HEIGHT, | ||
158 | V4L2_PIX_FMT_SBGGR8, | ||
159 | V4L2_FIELD_NONE, | ||
160 | .sizeimage = | ||
161 | M5602_DEFAULT_FRAME_WIDTH * M5602_DEFAULT_FRAME_HEIGHT, | ||
162 | .bytesperline = M5602_DEFAULT_FRAME_WIDTH, | ||
163 | .colorspace = V4L2_COLORSPACE_SRGB, | ||
164 | .priv = 1 | ||
165 | } | ||
166 | } | ||
167 | }; | ||
168 | |||
169 | static const unsigned char preinit_s5k4aa[][4] = | ||
170 | { | ||
171 | {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00}, | ||
172 | {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00}, | ||
173 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, | ||
174 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, | ||
175 | {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, | ||
176 | {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0d, 0x00}, | ||
177 | {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00, 0x00}, | ||
178 | |||
179 | {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00}, | ||
180 | {BRIDGE, M5602_XB_GPIO_DAT, 0x08, 0x00}, | ||
181 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0xb0, 0x00}, | ||
182 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0x80, 0x00}, | ||
183 | {BRIDGE, M5602_XB_GPIO_EN_H, 0x3f, 0x00}, | ||
184 | {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3f, 0x00}, | ||
185 | {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00}, | ||
186 | {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00}, | ||
187 | {BRIDGE, M5602_XB_GPIO_DAT, 0x00, 0x00}, | ||
188 | {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00}, | ||
189 | {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00}, | ||
190 | {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00}, | ||
191 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, | ||
192 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, | ||
193 | {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, | ||
194 | {BRIDGE, M5602_XB_SENSOR_TYPE, 0x08, 0x00}, | ||
195 | |||
196 | {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00}, | ||
197 | {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00}, | ||
198 | {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00}, | ||
199 | {BRIDGE, M5602_XB_GPIO_DAT, 0x14, 0x00}, | ||
200 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, | ||
201 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xf0, 0x00}, | ||
202 | {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00}, | ||
203 | {BRIDGE, M5602_XB_GPIO_DAT, 0x1c, 0x00}, | ||
204 | {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00}, | ||
205 | {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06, 0x00}, | ||
206 | {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00}, | ||
207 | {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00}, | ||
208 | {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x20, 0x00}, | ||
209 | |||
210 | {SENSOR, S5K4AA_PAGE_MAP, 0x00, 0x00} | ||
211 | }; | ||
212 | |||
213 | static const unsigned char init_s5k4aa[][4] = | ||
214 | { | ||
215 | {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00}, | ||
216 | {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00}, | ||
217 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, | ||
218 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, | ||
219 | {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, | ||
220 | {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0d, 0x00}, | ||
221 | {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00, 0x00}, | ||
222 | |||
223 | {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00}, | ||
224 | {BRIDGE, M5602_XB_GPIO_DAT, 0x08, 0x00}, | ||
225 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0xb0, 0x00}, | ||
226 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0x80, 0x00}, | ||
227 | {BRIDGE, M5602_XB_GPIO_EN_H, 0x3f, 0x00}, | ||
228 | {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3f, 0x00}, | ||
229 | {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00}, | ||
230 | {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00}, | ||
231 | {BRIDGE, M5602_XB_GPIO_DAT, 0x00, 0x00}, | ||
232 | {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00}, | ||
233 | {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00}, | ||
234 | {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00}, | ||
235 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, | ||
236 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, | ||
237 | {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, | ||
238 | {BRIDGE, M5602_XB_SENSOR_TYPE, 0x08, 0x00}, | ||
239 | |||
240 | {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00}, | ||
241 | {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00}, | ||
242 | {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00}, | ||
243 | {BRIDGE, M5602_XB_GPIO_DAT, 0x14, 0x00}, | ||
244 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, | ||
245 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xf0, 0x00}, | ||
246 | {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00}, | ||
247 | {BRIDGE, M5602_XB_GPIO_DAT, 0x1c, 0x00}, | ||
248 | {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00}, | ||
249 | {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06, 0x00}, | ||
250 | {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00}, | ||
251 | {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00}, | ||
252 | {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x20, 0x00}, | ||
253 | |||
254 | {SENSOR, S5K4AA_PAGE_MAP, 0x07, 0x00}, | ||
255 | {SENSOR, 0x36, 0x01, 0x00}, | ||
256 | {SENSOR, S5K4AA_PAGE_MAP, 0x00, 0x00}, | ||
257 | {SENSOR, 0x7b, 0xff, 0x00}, | ||
258 | {SENSOR, S5K4AA_PAGE_MAP, 0x02, 0x00}, | ||
259 | {SENSOR, 0x0c, 0x05, 0x00}, | ||
260 | {SENSOR, 0x02, 0x0e, 0x00}, | ||
261 | {SENSOR, S5K4AA_GAIN_1, 0x0f, 0x00}, | ||
262 | {SENSOR, S5K4AA_GAIN_2, 0x00, 0x00}, | ||
263 | {SENSOR, S5K4AA_GLOBAL_GAIN__, 0x01, 0x00}, | ||
264 | {SENSOR, 0x11, 0x00, 0x00}, | ||
265 | {SENSOR, 0x12, 0x00, 0x00}, | ||
266 | {SENSOR, S5K4AA_PAGE_MAP, 0x02, 0x00}, | ||
267 | {SENSOR, S5K4AA_READ_MODE, 0xa0, 0x00}, | ||
268 | {SENSOR, 0x37, 0x00, 0x00}, | ||
269 | {SENSOR, S5K4AA_ROWSTART_HI, 0x00, 0x00}, | ||
270 | {SENSOR, S5K4AA_ROWSTART_LO, 0x2a, 0x00}, | ||
271 | {SENSOR, S5K4AA_COLSTART_HI, 0x00, 0x00}, | ||
272 | {SENSOR, S5K4AA_COLSTART_LO, 0x0b, 0x00}, | ||
273 | {SENSOR, S5K4AA_WINDOW_HEIGHT_HI, 0x03, 0x00}, | ||
274 | {SENSOR, S5K4AA_WINDOW_HEIGHT_LO, 0xc4, 0x00}, | ||
275 | {SENSOR, S5K4AA_WINDOW_WIDTH_HI, 0x05, 0x00}, | ||
276 | {SENSOR, S5K4AA_WINDOW_WIDTH_LO, 0x08, 0x00}, | ||
277 | {SENSOR, S5K4AA_H_BLANK_HI__, 0x00, 0x00}, | ||
278 | {SENSOR, S5K4AA_H_BLANK_LO__, 0x48, 0x00}, | ||
279 | {SENSOR, S5K4AA_EXPOSURE_HI, 0x00, 0x00}, | ||
280 | {SENSOR, S5K4AA_EXPOSURE_LO, 0x43, 0x00}, | ||
281 | {SENSOR, 0x11, 0x04, 0x00}, | ||
282 | {SENSOR, 0x12, 0xc3, 0x00}, | ||
283 | {SENSOR, S5K4AA_PAGE_MAP, 0x02, 0x00}, | ||
284 | |||
285 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00}, | ||
286 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, | ||
287 | {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, | ||
288 | {BRIDGE, M5602_XB_SENSOR_TYPE, 0x08, 0x00}, | ||
289 | {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00}, | ||
290 | {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00}, | ||
291 | {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00}, | ||
292 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
293 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
294 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
295 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
296 | /* VSYNC_PARA, VSYNC_PARA : img height 480 = 0x01e0 */ | ||
297 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x01, 0x00}, | ||
298 | {BRIDGE, M5602_XB_VSYNC_PARA, 0xe0, 0x00}, | ||
299 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
300 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
301 | {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00}, | ||
302 | {BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00}, | ||
303 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, | ||
304 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, | ||
305 | /* HSYNC_PARA, HSYNC_PARA : img width 640 = 0x0280 */ | ||
306 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x02, 0x00}, | ||
307 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x80, 0x00}, | ||
308 | {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00}, | ||
309 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, | ||
310 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xa0, 0x00}, /* 48 MHz */ | ||
311 | |||
312 | {SENSOR, S5K4AA_PAGE_MAP, 0x02, 0x00}, | ||
313 | {SENSOR, S5K4AA_READ_MODE, S5K4AA_RM_H_FLIP | S5K4AA_RM_ROW_SKIP_2X | ||
314 | | S5K4AA_RM_COL_SKIP_2X, 0x00}, | ||
315 | /* 0x37 : Fix image stability when light is too bright and improves | ||
316 | * image quality in 640x480, but worsens it in 1280x1024 */ | ||
317 | {SENSOR, 0x37, 0x01, 0x00}, | ||
318 | /* ROWSTART_HI, ROWSTART_LO : 10 + (1024-960)/2 = 42 = 0x002a */ | ||
319 | {SENSOR, S5K4AA_ROWSTART_HI, 0x00, 0x00}, | ||
320 | {SENSOR, S5K4AA_ROWSTART_LO, 0x2a, 0x00}, | ||
321 | {SENSOR, S5K4AA_COLSTART_HI, 0x00, 0x00}, | ||
322 | {SENSOR, S5K4AA_COLSTART_LO, 0x0c, 0x00}, | ||
323 | /* window_height_hi, window_height_lo : 960 = 0x03c0 */ | ||
324 | {SENSOR, S5K4AA_WINDOW_HEIGHT_HI, 0x03, 0x00}, | ||
325 | {SENSOR, S5K4AA_WINDOW_HEIGHT_LO, 0xc0, 0x00}, | ||
326 | /* window_width_hi, window_width_lo : 1280 = 0x0500 */ | ||
327 | {SENSOR, S5K4AA_WINDOW_WIDTH_HI, 0x05, 0x00}, | ||
328 | {SENSOR, S5K4AA_WINDOW_WIDTH_LO, 0x00, 0x00}, | ||
329 | {SENSOR, S5K4AA_H_BLANK_HI__, 0x00, 0x00}, | ||
330 | {SENSOR, S5K4AA_H_BLANK_LO__, 0xa8, 0x00}, /* helps to sync... */ | ||
331 | {SENSOR, S5K4AA_EXPOSURE_HI, 0x01, 0x00}, | ||
332 | {SENSOR, S5K4AA_EXPOSURE_LO, 0x00, 0x00}, | ||
333 | {SENSOR, 0x11, 0x04, 0x00}, | ||
334 | {SENSOR, 0x12, 0xc3, 0x00}, | ||
335 | {SENSOR, S5K4AA_PAGE_MAP, 0x02, 0x00}, | ||
336 | {SENSOR, 0x02, 0x0e, 0x00}, | ||
337 | {SENSOR_LONG, S5K4AA_GLOBAL_GAIN__, 0x0f, 0x00}, | ||
338 | {SENSOR, S5K4AA_GAIN_1, 0x0b, 0x00}, | ||
339 | {SENSOR, S5K4AA_GAIN_2, 0xa0, 0x00} | ||
340 | }; | ||
341 | |||
342 | static | ||
343 | const | ||
344 | struct dmi_system_id s5k4aa_vflip_dmi_table[] = { | ||
345 | { | ||
346 | .ident = "Fujitsu-Siemens Amilo Xa 2528", | ||
347 | .matches = { | ||
348 | DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), | ||
349 | DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Xa 2528") | ||
350 | } | ||
351 | }, | ||
352 | { | ||
353 | .ident = "Fujitsu-Siemens Amilo Xi 2550", | ||
354 | .matches = { | ||
355 | DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), | ||
356 | DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Xi 2550") | ||
357 | } | ||
358 | }, | ||
359 | { | ||
360 | .ident = "MSI GX700", | ||
361 | .matches = { | ||
362 | DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"), | ||
363 | DMI_MATCH(DMI_PRODUCT_NAME, "GX700"), | ||
364 | DMI_MATCH(DMI_BIOS_DATE, "07/26/2007") | ||
365 | } | ||
366 | }, | ||
367 | { } | ||
368 | }; | ||
369 | |||
370 | #endif | ||
diff --git a/drivers/media/video/gspca/m5602/m5602_s5k83a.c b/drivers/media/video/gspca/m5602/m5602_s5k83a.c new file mode 100644 index 000000000000..b4b33c2d0499 --- /dev/null +++ b/drivers/media/video/gspca/m5602/m5602_s5k83a.c | |||
@@ -0,0 +1,423 @@ | |||
1 | /* | ||
2 | * Driver for the s5k83a sensor | ||
3 | * | ||
4 | * Copyright (C) 2008 Erik Andren | ||
5 | * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project. | ||
6 | * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br> | ||
7 | * | ||
8 | * Portions of code to USB interface and ALi driver software, | ||
9 | * Copyright (c) 2006 Willem Duinker | ||
10 | * v4l2 interface modeled after the V4L2 driver | ||
11 | * for SN9C10x PC Camera Controllers | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or | ||
14 | * modify it under the terms of the GNU General Public License as | ||
15 | * published by the Free Software Foundation, version 2. | ||
16 | * | ||
17 | */ | ||
18 | |||
19 | #include "m5602_s5k83a.h" | ||
20 | |||
21 | int s5k83a_probe(struct sd *sd) | ||
22 | { | ||
23 | u8 prod_id = 0, ver_id = 0; | ||
24 | int i, err = 0; | ||
25 | |||
26 | if (force_sensor) { | ||
27 | if (force_sensor == S5K83A_SENSOR) { | ||
28 | info("Forcing a %s sensor", s5k83a.name); | ||
29 | goto sensor_found; | ||
30 | } | ||
31 | /* If we want to force another sensor, don't try to probe this | ||
32 | * one */ | ||
33 | return -ENODEV; | ||
34 | } | ||
35 | |||
36 | info("Probing for a s5k83a sensor"); | ||
37 | |||
38 | /* Preinit the sensor */ | ||
39 | for (i = 0; i < ARRAY_SIZE(preinit_s5k83a) && !err; i++) { | ||
40 | u8 data[2] = {preinit_s5k83a[i][2], preinit_s5k83a[i][3]}; | ||
41 | if (preinit_s5k83a[i][0] == SENSOR) | ||
42 | err = s5k83a_write_sensor(sd, preinit_s5k83a[i][1], | ||
43 | data, 2); | ||
44 | else | ||
45 | err = m5602_write_bridge(sd, preinit_s5k83a[i][1], | ||
46 | data[0]); | ||
47 | } | ||
48 | |||
49 | /* We don't know what register (if any) that contain the product id | ||
50 | * Just pick the first addresses that seem to produce the same results | ||
51 | * on multiple machines */ | ||
52 | if (s5k83a_read_sensor(sd, 0x00, &prod_id, 1)) | ||
53 | return -ENODEV; | ||
54 | |||
55 | if (s5k83a_read_sensor(sd, 0x01, &ver_id, 1)) | ||
56 | return -ENODEV; | ||
57 | |||
58 | if ((prod_id == 0xff) || (ver_id == 0xff)) | ||
59 | return -ENODEV; | ||
60 | else | ||
61 | info("Detected a s5k83a sensor"); | ||
62 | |||
63 | sensor_found: | ||
64 | sd->gspca_dev.cam.cam_mode = s5k83a.modes; | ||
65 | sd->gspca_dev.cam.nmodes = s5k83a.nmodes; | ||
66 | sd->desc->ctrls = s5k83a.ctrls; | ||
67 | sd->desc->nctrls = s5k83a.nctrls; | ||
68 | return 0; | ||
69 | } | ||
70 | |||
71 | int s5k83a_read_sensor(struct sd *sd, const u8 address, | ||
72 | u8 *i2c_data, const u8 len) | ||
73 | { | ||
74 | int err, i; | ||
75 | |||
76 | do { | ||
77 | err = m5602_read_bridge(sd, M5602_XB_I2C_STATUS, i2c_data); | ||
78 | } while ((*i2c_data & I2C_BUSY) && !err); | ||
79 | if (err < 0) | ||
80 | goto out; | ||
81 | |||
82 | err = m5602_write_bridge(sd, M5602_XB_I2C_DEV_ADDR, | ||
83 | sd->sensor->i2c_slave_id); | ||
84 | if (err < 0) | ||
85 | goto out; | ||
86 | |||
87 | err = m5602_write_bridge(sd, M5602_XB_I2C_REG_ADDR, address); | ||
88 | if (err < 0) | ||
89 | goto out; | ||
90 | |||
91 | err = m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 0x18 + len); | ||
92 | if (err < 0) | ||
93 | goto out; | ||
94 | |||
95 | do { | ||
96 | err = m5602_read_bridge(sd, M5602_XB_I2C_STATUS, i2c_data); | ||
97 | } while ((*i2c_data & I2C_BUSY) && !err); | ||
98 | |||
99 | if (err < 0) | ||
100 | goto out; | ||
101 | for (i = 0; i < len && !len; i++) { | ||
102 | err = m5602_read_bridge(sd, M5602_XB_I2C_DATA, &(i2c_data[i])); | ||
103 | |||
104 | PDEBUG(DBG_TRACE, "Reading sensor register " | ||
105 | "0x%x containing 0x%x ", address, *i2c_data); | ||
106 | } | ||
107 | |||
108 | out: | ||
109 | return (err < 0) ? err : 0; | ||
110 | } | ||
111 | |||
112 | int s5k83a_write_sensor(struct sd *sd, const u8 address, | ||
113 | u8 *i2c_data, const u8 len) | ||
114 | { | ||
115 | int err, i; | ||
116 | u8 *p; | ||
117 | struct usb_device *udev = sd->gspca_dev.dev; | ||
118 | __u8 *buf = sd->gspca_dev.usb_buf; | ||
119 | |||
120 | /* No sensor with a data width larger than 16 bits has yet been seen */ | ||
121 | if (len > 2 || !len) | ||
122 | return -EINVAL; | ||
123 | |||
124 | memcpy(buf, sensor_urb_skeleton, | ||
125 | sizeof(sensor_urb_skeleton)); | ||
126 | |||
127 | buf[11] = sd->sensor->i2c_slave_id; | ||
128 | buf[15] = address; | ||
129 | |||
130 | /* Special case larger sensor writes */ | ||
131 | p = buf + 16; | ||
132 | |||
133 | /* Copy a four byte write sequence for each byte to be written to */ | ||
134 | for (i = 0; i < len; i++) { | ||
135 | memcpy(p, sensor_urb_skeleton + 16, 4); | ||
136 | p[3] = i2c_data[i]; | ||
137 | p += 4; | ||
138 | PDEBUG(DBG_TRACE, "Writing sensor register 0x%x with 0x%x", | ||
139 | address, i2c_data[i]); | ||
140 | } | ||
141 | |||
142 | /* Copy the tailer */ | ||
143 | memcpy(p, sensor_urb_skeleton + 20, 4); | ||
144 | |||
145 | /* Set the total length */ | ||
146 | p[3] = 0x10 + len; | ||
147 | |||
148 | err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), | ||
149 | 0x04, 0x40, 0x19, | ||
150 | 0x0000, buf, | ||
151 | 20 + len * 4, M5602_URB_MSG_TIMEOUT); | ||
152 | |||
153 | return (err < 0) ? err : 0; | ||
154 | } | ||
155 | |||
156 | int s5k83a_init(struct sd *sd) | ||
157 | { | ||
158 | int i, err = 0; | ||
159 | |||
160 | for (i = 0; i < ARRAY_SIZE(init_s5k83a) && !err; i++) { | ||
161 | u8 data[2] = {0x00, 0x00}; | ||
162 | |||
163 | switch (init_s5k83a[i][0]) { | ||
164 | case BRIDGE: | ||
165 | err = m5602_write_bridge(sd, | ||
166 | init_s5k83a[i][1], | ||
167 | init_s5k83a[i][2]); | ||
168 | break; | ||
169 | |||
170 | case SENSOR: | ||
171 | data[0] = init_s5k83a[i][2]; | ||
172 | err = s5k83a_write_sensor(sd, | ||
173 | init_s5k83a[i][1], data, 1); | ||
174 | break; | ||
175 | |||
176 | case SENSOR_LONG: | ||
177 | data[0] = init_s5k83a[i][2]; | ||
178 | data[1] = init_s5k83a[i][3]; | ||
179 | err = s5k83a_write_sensor(sd, | ||
180 | init_s5k83a[i][1], data, 2); | ||
181 | break; | ||
182 | default: | ||
183 | info("Invalid stream command, exiting init"); | ||
184 | return -EINVAL; | ||
185 | } | ||
186 | } | ||
187 | |||
188 | if (dump_sensor) | ||
189 | s5k83a_dump_registers(sd); | ||
190 | |||
191 | return (err < 0) ? err : 0; | ||
192 | } | ||
193 | |||
194 | int s5k83a_power_down(struct sd *sd) | ||
195 | { | ||
196 | return 0; | ||
197 | } | ||
198 | |||
199 | void s5k83a_dump_registers(struct sd *sd) | ||
200 | { | ||
201 | int address; | ||
202 | u8 page, old_page; | ||
203 | s5k83a_read_sensor(sd, S5K83A_PAGE_MAP, &old_page, 1); | ||
204 | |||
205 | for (page = 0; page < 16; page++) { | ||
206 | s5k83a_write_sensor(sd, S5K83A_PAGE_MAP, &page, 1); | ||
207 | info("Dumping the s5k83a register state for page 0x%x", page); | ||
208 | for (address = 0; address <= 0xff; address++) { | ||
209 | u8 val = 0; | ||
210 | s5k83a_read_sensor(sd, address, &val, 1); | ||
211 | info("register 0x%x contains 0x%x", | ||
212 | address, val); | ||
213 | } | ||
214 | } | ||
215 | info("s5k83a register state dump complete"); | ||
216 | |||
217 | for (page = 0; page < 16; page++) { | ||
218 | s5k83a_write_sensor(sd, S5K83A_PAGE_MAP, &page, 1); | ||
219 | info("Probing for which registers that are read/write " | ||
220 | "for page 0x%x", page); | ||
221 | for (address = 0; address <= 0xff; address++) { | ||
222 | u8 old_val, ctrl_val, test_val = 0xff; | ||
223 | |||
224 | s5k83a_read_sensor(sd, address, &old_val, 1); | ||
225 | s5k83a_write_sensor(sd, address, &test_val, 1); | ||
226 | s5k83a_read_sensor(sd, address, &ctrl_val, 1); | ||
227 | |||
228 | if (ctrl_val == test_val) | ||
229 | info("register 0x%x is writeable", address); | ||
230 | else | ||
231 | info("register 0x%x is read only", address); | ||
232 | |||
233 | /* Restore original val */ | ||
234 | s5k83a_write_sensor(sd, address, &old_val, 1); | ||
235 | } | ||
236 | } | ||
237 | info("Read/write register probing complete"); | ||
238 | s5k83a_write_sensor(sd, S5K83A_PAGE_MAP, &old_page, 1); | ||
239 | } | ||
240 | |||
241 | int s5k83a_get_brightness(struct gspca_dev *gspca_dev, __s32 *val) | ||
242 | { | ||
243 | int err; | ||
244 | u8 data[2]; | ||
245 | struct sd *sd = (struct sd *) gspca_dev; | ||
246 | |||
247 | err = s5k83a_read_sensor(sd, S5K83A_BRIGHTNESS, data, 2); | ||
248 | data[1] = data[1] << 1; | ||
249 | *val = data[1]; | ||
250 | |||
251 | return (err < 0) ? err : 0; | ||
252 | } | ||
253 | |||
254 | int s5k83a_set_brightness(struct gspca_dev *gspca_dev, __s32 val) | ||
255 | { | ||
256 | int err; | ||
257 | u8 data[2]; | ||
258 | struct sd *sd = (struct sd *) gspca_dev; | ||
259 | |||
260 | data[0] = 0x00; | ||
261 | data[1] = 0x20; | ||
262 | err = s5k83a_write_sensor(sd, 0x14, data, 2); | ||
263 | if (err < 0) | ||
264 | return err; | ||
265 | |||
266 | data[0] = 0x01; | ||
267 | data[1] = 0x00; | ||
268 | err = s5k83a_write_sensor(sd, 0x0d, data, 2); | ||
269 | if (err < 0) | ||
270 | return err; | ||
271 | |||
272 | /* FIXME: This is not sane, we need to figure out the composition | ||
273 | of these registers */ | ||
274 | data[0] = val >> 3; /* brightness, high 5 bits */ | ||
275 | data[1] = val >> 1; /* brightness, high 7 bits */ | ||
276 | err = s5k83a_write_sensor(sd, S5K83A_BRIGHTNESS, data, 2); | ||
277 | |||
278 | return (err < 0) ? err : 0; | ||
279 | } | ||
280 | |||
281 | int s5k83a_get_whiteness(struct gspca_dev *gspca_dev, __s32 *val) | ||
282 | { | ||
283 | int err; | ||
284 | u8 data; | ||
285 | struct sd *sd = (struct sd *) gspca_dev; | ||
286 | |||
287 | err = s5k83a_read_sensor(sd, S5K83A_WHITENESS, &data, 1); | ||
288 | |||
289 | *val = data; | ||
290 | return (err < 0) ? err : 0; | ||
291 | } | ||
292 | |||
293 | int s5k83a_set_whiteness(struct gspca_dev *gspca_dev, __s32 val) | ||
294 | { | ||
295 | int err; | ||
296 | u8 data[1]; | ||
297 | struct sd *sd = (struct sd *) gspca_dev; | ||
298 | |||
299 | data[0] = val; | ||
300 | err = s5k83a_write_sensor(sd, S5K83A_WHITENESS, data, 1); | ||
301 | |||
302 | return (err < 0) ? err : 0; | ||
303 | } | ||
304 | |||
305 | int s5k83a_get_gain(struct gspca_dev *gspca_dev, __s32 *val) | ||
306 | { | ||
307 | int err; | ||
308 | u8 data[2]; | ||
309 | struct sd *sd = (struct sd *) gspca_dev; | ||
310 | |||
311 | err = s5k83a_read_sensor(sd, S5K83A_GAIN, data, 2); | ||
312 | |||
313 | data[1] = data[1] & 0x3f; | ||
314 | if (data[1] > S5K83A_MAXIMUM_GAIN) | ||
315 | data[1] = S5K83A_MAXIMUM_GAIN; | ||
316 | |||
317 | *val = data[1]; | ||
318 | |||
319 | return (err < 0) ? err : 0; | ||
320 | } | ||
321 | |||
322 | int s5k83a_set_gain(struct gspca_dev *gspca_dev, __s32 val) | ||
323 | { | ||
324 | int err; | ||
325 | u8 data[2]; | ||
326 | struct sd *sd = (struct sd *) gspca_dev; | ||
327 | |||
328 | data[0] = 0; | ||
329 | data[1] = val; | ||
330 | err = s5k83a_write_sensor(sd, S5K83A_GAIN, data, 2); | ||
331 | |||
332 | return (err < 0) ? err : 0; | ||
333 | } | ||
334 | |||
335 | int s5k83a_get_vflip(struct gspca_dev *gspca_dev, __s32 *val) | ||
336 | { | ||
337 | int err; | ||
338 | u8 data[1]; | ||
339 | struct sd *sd = (struct sd *) gspca_dev; | ||
340 | |||
341 | data[0] = 0x05; | ||
342 | err = s5k83a_write_sensor(sd, S5K83A_PAGE_MAP, data, 1); | ||
343 | if (err < 0) | ||
344 | return err; | ||
345 | |||
346 | err = s5k83a_read_sensor(sd, S5K83A_FLIP, data, 1); | ||
347 | *val = (data[0] | 0x40) ? 1 : 0; | ||
348 | |||
349 | return (err < 0) ? err : 0; | ||
350 | } | ||
351 | |||
352 | int s5k83a_set_vflip(struct gspca_dev *gspca_dev, __s32 val) | ||
353 | { | ||
354 | int err; | ||
355 | u8 data[1]; | ||
356 | struct sd *sd = (struct sd *) gspca_dev; | ||
357 | |||
358 | data[0] = 0x05; | ||
359 | err = s5k83a_write_sensor(sd, S5K83A_PAGE_MAP, data, 1); | ||
360 | if (err < 0) | ||
361 | return err; | ||
362 | |||
363 | err = s5k83a_read_sensor(sd, S5K83A_FLIP, data, 1); | ||
364 | if (err < 0) | ||
365 | return err; | ||
366 | |||
367 | /* set or zero six bit, seven is hflip */ | ||
368 | data[0] = (val) ? (data[0] & 0x80) | 0x40 | S5K83A_FLIP_MASK | ||
369 | : (data[0] & 0x80) | S5K83A_FLIP_MASK; | ||
370 | err = s5k83a_write_sensor(sd, S5K83A_FLIP, data, 1); | ||
371 | if (err < 0) | ||
372 | return err; | ||
373 | |||
374 | data[0] = (val) ? 0x0b : 0x0a; | ||
375 | err = s5k83a_write_sensor(sd, S5K83A_VFLIP_TUNE, data, 1); | ||
376 | |||
377 | return (err < 0) ? err : 0; | ||
378 | } | ||
379 | |||
380 | int s5k83a_get_hflip(struct gspca_dev *gspca_dev, __s32 *val) | ||
381 | { | ||
382 | int err; | ||
383 | u8 data[1]; | ||
384 | struct sd *sd = (struct sd *) gspca_dev; | ||
385 | |||
386 | data[0] = 0x05; | ||
387 | err = s5k83a_write_sensor(sd, S5K83A_PAGE_MAP, data, 1); | ||
388 | if (err < 0) | ||
389 | return err; | ||
390 | |||
391 | err = s5k83a_read_sensor(sd, S5K83A_FLIP, data, 1); | ||
392 | *val = (data[0] | 0x80) ? 1 : 0; | ||
393 | |||
394 | return (err < 0) ? err : 0; | ||
395 | } | ||
396 | |||
397 | int s5k83a_set_hflip(struct gspca_dev *gspca_dev, __s32 val) | ||
398 | { | ||
399 | int err; | ||
400 | u8 data[1]; | ||
401 | struct sd *sd = (struct sd *) gspca_dev; | ||
402 | |||
403 | data[0] = 0x05; | ||
404 | err = s5k83a_write_sensor(sd, S5K83A_PAGE_MAP, data, 1); | ||
405 | if (err < 0) | ||
406 | return err; | ||
407 | |||
408 | err = s5k83a_read_sensor(sd, S5K83A_FLIP, data, 1); | ||
409 | if (err < 0) | ||
410 | return err; | ||
411 | |||
412 | /* set or zero seven bit, six is vflip */ | ||
413 | data[0] = (val) ? (data[0] & 0x40) | 0x80 | S5K83A_FLIP_MASK | ||
414 | : (data[0] & 0x40) | S5K83A_FLIP_MASK; | ||
415 | err = s5k83a_write_sensor(sd, S5K83A_FLIP, data, 1); | ||
416 | if (err < 0) | ||
417 | return err; | ||
418 | |||
419 | data[0] = (val) ? 0x0a : 0x0b; | ||
420 | err = s5k83a_write_sensor(sd, S5K83A_HFLIP_TUNE, data, 1); | ||
421 | |||
422 | return (err < 0) ? err : 0; | ||
423 | } | ||
diff --git a/drivers/media/video/gspca/m5602/m5602_s5k83a.h b/drivers/media/video/gspca/m5602/m5602_s5k83a.h new file mode 100644 index 000000000000..833708eb5a42 --- /dev/null +++ b/drivers/media/video/gspca/m5602/m5602_s5k83a.h | |||
@@ -0,0 +1,484 @@ | |||
1 | /* | ||
2 | * Driver for the s5k83a sensor | ||
3 | * | ||
4 | * Copyright (C) 2008 Erik Andren | ||
5 | * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project. | ||
6 | * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br> | ||
7 | * | ||
8 | * Portions of code to USB interface and ALi driver software, | ||
9 | * Copyright (c) 2006 Willem Duinker | ||
10 | * v4l2 interface modeled after the V4L2 driver | ||
11 | * for SN9C10x PC Camera Controllers | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or | ||
14 | * modify it under the terms of the GNU General Public License as | ||
15 | * published by the Free Software Foundation, version 2. | ||
16 | * | ||
17 | */ | ||
18 | |||
19 | #ifndef M5602_S5K83A_H_ | ||
20 | #define M5602_S5K83A_H_ | ||
21 | |||
22 | #include "m5602_sensor.h" | ||
23 | |||
24 | #define S5K83A_FLIP 0x01 | ||
25 | #define S5K83A_HFLIP_TUNE 0x03 | ||
26 | #define S5K83A_VFLIP_TUNE 0x05 | ||
27 | #define S5K83A_WHITENESS 0x0a | ||
28 | #define S5K83A_GAIN 0x18 | ||
29 | #define S5K83A_BRIGHTNESS 0x1b | ||
30 | #define S5K83A_PAGE_MAP 0xec | ||
31 | |||
32 | #define S5K83A_DEFAULT_BRIGHTNESS 0x71 | ||
33 | #define S5K83A_DEFAULT_WHITENESS 0x7e | ||
34 | #define S5K83A_DEFAULT_GAIN 0x00 | ||
35 | #define S5K83A_MAXIMUM_GAIN 0x3c | ||
36 | #define S5K83A_FLIP_MASK 0x10 | ||
37 | |||
38 | |||
39 | /*****************************************************************************/ | ||
40 | |||
41 | /* Kernel module parameters */ | ||
42 | extern int force_sensor; | ||
43 | extern int dump_sensor; | ||
44 | extern unsigned int m5602_debug; | ||
45 | |||
46 | |||
47 | int s5k83a_probe(struct sd *sd); | ||
48 | int s5k83a_init(struct sd *sd); | ||
49 | int s5k83a_power_down(struct sd *sd); | ||
50 | |||
51 | void s5k83a_dump_registers(struct sd *sd); | ||
52 | |||
53 | int s5k83a_read_sensor(struct sd *sd, const u8 address, | ||
54 | u8 *i2c_data, const u8 len); | ||
55 | int s5k83a_write_sensor(struct sd *sd, const u8 address, | ||
56 | u8 *i2c_data, const u8 len); | ||
57 | |||
58 | int s5k83a_set_brightness(struct gspca_dev *gspca_dev, __s32 val); | ||
59 | int s5k83a_get_brightness(struct gspca_dev *gspca_dev, __s32 *val); | ||
60 | int s5k83a_set_whiteness(struct gspca_dev *gspca_dev, __s32 val); | ||
61 | int s5k83a_get_whiteness(struct gspca_dev *gspca_dev, __s32 *val); | ||
62 | int s5k83a_set_gain(struct gspca_dev *gspca_dev, __s32 val); | ||
63 | int s5k83a_get_gain(struct gspca_dev *gspca_dev, __s32 *val); | ||
64 | int s5k83a_get_vflip(struct gspca_dev *gspca_dev, __s32 *val); | ||
65 | int s5k83a_set_vflip(struct gspca_dev *gspca_dev, __s32 val); | ||
66 | int s5k83a_get_hflip(struct gspca_dev *gspca_dev, __s32 *val); | ||
67 | int s5k83a_set_hflip(struct gspca_dev *gspca_dev, __s32 val); | ||
68 | |||
69 | |||
70 | static struct m5602_sensor s5k83a = { | ||
71 | .name = "S5K83A", | ||
72 | .probe = s5k83a_probe, | ||
73 | .init = s5k83a_init, | ||
74 | .power_down = s5k83a_power_down, | ||
75 | .read_sensor = s5k83a_read_sensor, | ||
76 | .write_sensor = s5k83a_write_sensor, | ||
77 | .i2c_slave_id = 0x5a, | ||
78 | .nctrls = 5, | ||
79 | .ctrls = { | ||
80 | { | ||
81 | { | ||
82 | .id = V4L2_CID_BRIGHTNESS, | ||
83 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
84 | .name = "brightness", | ||
85 | .minimum = 0x00, | ||
86 | .maximum = 0xff, | ||
87 | .step = 0x01, | ||
88 | .default_value = S5K83A_DEFAULT_BRIGHTNESS, | ||
89 | .flags = V4L2_CTRL_FLAG_SLIDER | ||
90 | }, | ||
91 | .set = s5k83a_set_brightness, | ||
92 | .get = s5k83a_get_brightness | ||
93 | |||
94 | }, { | ||
95 | { | ||
96 | .id = V4L2_CID_WHITENESS, | ||
97 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
98 | .name = "whiteness", | ||
99 | .minimum = 0x00, | ||
100 | .maximum = 0xff, | ||
101 | .step = 0x01, | ||
102 | .default_value = S5K83A_DEFAULT_WHITENESS, | ||
103 | .flags = V4L2_CTRL_FLAG_SLIDER | ||
104 | }, | ||
105 | .set = s5k83a_set_whiteness, | ||
106 | .get = s5k83a_get_whiteness, | ||
107 | }, { | ||
108 | { | ||
109 | .id = V4L2_CID_GAIN, | ||
110 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
111 | .name = "gain", | ||
112 | .minimum = 0x00, | ||
113 | .maximum = S5K83A_MAXIMUM_GAIN, | ||
114 | .step = 0x01, | ||
115 | .default_value = S5K83A_DEFAULT_GAIN, | ||
116 | .flags = V4L2_CTRL_FLAG_SLIDER | ||
117 | }, | ||
118 | .set = s5k83a_set_gain, | ||
119 | .get = s5k83a_get_gain | ||
120 | }, { | ||
121 | { | ||
122 | .id = V4L2_CID_HFLIP, | ||
123 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
124 | .name = "horizontal flip", | ||
125 | .minimum = 0, | ||
126 | .maximum = 1, | ||
127 | .step = 1, | ||
128 | .default_value = 0 | ||
129 | }, | ||
130 | .set = s5k83a_set_hflip, | ||
131 | .get = s5k83a_get_hflip | ||
132 | }, { | ||
133 | { | ||
134 | .id = V4L2_CID_VFLIP, | ||
135 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
136 | .name = "vertical flip", | ||
137 | .minimum = 0, | ||
138 | .maximum = 1, | ||
139 | .step = 1, | ||
140 | .default_value = 0 | ||
141 | }, | ||
142 | .set = s5k83a_set_vflip, | ||
143 | .get = s5k83a_get_vflip | ||
144 | } | ||
145 | }, | ||
146 | .nmodes = 1, | ||
147 | .modes = { | ||
148 | { | ||
149 | M5602_DEFAULT_FRAME_WIDTH, | ||
150 | M5602_DEFAULT_FRAME_HEIGHT, | ||
151 | V4L2_PIX_FMT_SBGGR8, | ||
152 | V4L2_FIELD_NONE, | ||
153 | .sizeimage = | ||
154 | M5602_DEFAULT_FRAME_WIDTH * M5602_DEFAULT_FRAME_HEIGHT, | ||
155 | .bytesperline = M5602_DEFAULT_FRAME_WIDTH, | ||
156 | .colorspace = V4L2_COLORSPACE_SRGB, | ||
157 | .priv = 1 | ||
158 | } | ||
159 | } | ||
160 | }; | ||
161 | |||
162 | static const unsigned char preinit_s5k83a[][4] = | ||
163 | { | ||
164 | {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00}, | ||
165 | {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00}, | ||
166 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, | ||
167 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, | ||
168 | {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, | ||
169 | {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0d, 0x00}, | ||
170 | {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00, 0x00}, | ||
171 | |||
172 | {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00}, | ||
173 | {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00}, | ||
174 | {BRIDGE, M5602_XB_GPIO_DAT, 0x08, 0x00}, | ||
175 | {BRIDGE, M5602_XB_GPIO_EN_H, 0x3f, 0x00}, | ||
176 | {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3f, 0x00}, | ||
177 | {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00}, | ||
178 | {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00}, | ||
179 | {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00}, | ||
180 | {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00}, | ||
181 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0xb0, 0x00}, | ||
182 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0x80, 0x00}, | ||
183 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, | ||
184 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, | ||
185 | {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, | ||
186 | {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00}, | ||
187 | {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00}, | ||
188 | {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00}, | ||
189 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, | ||
190 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xf0, 0x00}, | ||
191 | {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00}, | ||
192 | {BRIDGE, M5602_XB_GPIO_DAT, 0x1c, 0x00}, | ||
193 | {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00}, | ||
194 | {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06, 0x00}, | ||
195 | {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00}, | ||
196 | {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00}, | ||
197 | {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x20, 0x00}, | ||
198 | |||
199 | {SENSOR, S5K83A_PAGE_MAP, 0x00, 0x00} | ||
200 | }; | ||
201 | |||
202 | /* This could probably be considerably shortened. | ||
203 | I don't have the hardware to experiment with it, patches welcome | ||
204 | */ | ||
205 | static const unsigned char init_s5k83a[][4] = | ||
206 | { | ||
207 | {SENSOR, S5K83A_PAGE_MAP, 0x04, 0x00}, | ||
208 | {SENSOR, 0xaf, 0x01, 0x00}, | ||
209 | {SENSOR, S5K83A_PAGE_MAP, 0x00, 0x00}, | ||
210 | {SENSOR, 0x7b, 0xff, 0x00}, | ||
211 | {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00}, | ||
212 | {SENSOR, 0x01, 0x50, 0x00}, | ||
213 | {SENSOR, 0x12, 0x20, 0x00}, | ||
214 | {SENSOR, 0x17, 0x40, 0x00}, | ||
215 | {SENSOR, S5K83A_BRIGHTNESS, 0x0f, 0x00}, | ||
216 | {SENSOR, 0x1c, 0x00, 0x00}, | ||
217 | {SENSOR, 0x02, 0x70, 0x00}, | ||
218 | {SENSOR, 0x03, 0x0b, 0x00}, | ||
219 | {SENSOR, 0x04, 0xf0, 0x00}, | ||
220 | {SENSOR, 0x05, 0x0b, 0x00}, | ||
221 | {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00}, | ||
222 | |||
223 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00}, | ||
224 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, | ||
225 | {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, | ||
226 | {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00}, | ||
227 | {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00}, | ||
228 | {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00}, | ||
229 | {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00}, | ||
230 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
231 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
232 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
233 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
234 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x01, 0x00}, | ||
235 | {BRIDGE, M5602_XB_VSYNC_PARA, 0xe4, 0x00}, | ||
236 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
237 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
238 | {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00}, | ||
239 | {BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00}, | ||
240 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, | ||
241 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, | ||
242 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x02, 0x00}, | ||
243 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x87, 0x00}, | ||
244 | {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00}, | ||
245 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, | ||
246 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, | ||
247 | |||
248 | {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00}, | ||
249 | {SENSOR, 0x06, 0x71, 0x00}, | ||
250 | {SENSOR, 0x07, 0xe8, 0x00}, | ||
251 | {SENSOR, 0x08, 0x02, 0x00}, | ||
252 | {SENSOR, 0x09, 0x88, 0x00}, | ||
253 | {SENSOR, 0x14, 0x00, 0x00}, | ||
254 | {SENSOR, 0x15, 0x20, 0x00}, | ||
255 | {SENSOR, 0x19, 0x00, 0x00}, | ||
256 | {SENSOR, 0x1a, 0x98, 0x00}, | ||
257 | {SENSOR, 0x0f, 0x02, 0x00}, | ||
258 | {SENSOR, 0x10, 0xe5, 0x00}, | ||
259 | {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00}, | ||
260 | {SENSOR_LONG, 0x14, 0x00, 0x20}, | ||
261 | {SENSOR_LONG, 0x0d, 0x00, 0x7d}, | ||
262 | {SENSOR_LONG, 0x1b, 0x0d, 0x05}, | ||
263 | |||
264 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00}, | ||
265 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, | ||
266 | {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, | ||
267 | {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00}, | ||
268 | {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00}, | ||
269 | {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00}, | ||
270 | {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00}, | ||
271 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
272 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
273 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
274 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
275 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x01, 0x00}, | ||
276 | {BRIDGE, M5602_XB_VSYNC_PARA, 0xe4, 0x00}, | ||
277 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
278 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
279 | {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00}, | ||
280 | {BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00}, | ||
281 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, | ||
282 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, | ||
283 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x02, 0x00}, | ||
284 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x87, 0x00}, | ||
285 | |||
286 | {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00}, | ||
287 | {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00}, | ||
288 | {BRIDGE, M5602_XB_GPIO_DAT, 0x08, 0x00}, | ||
289 | {BRIDGE, M5602_XB_GPIO_EN_H, 0x3f, 0x00}, | ||
290 | {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3f, 0x00}, | ||
291 | {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00}, | ||
292 | {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00}, | ||
293 | {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00}, | ||
294 | {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00}, | ||
295 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0xb0, 0x00}, | ||
296 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0x80, 0x00}, | ||
297 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, | ||
298 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, | ||
299 | {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, | ||
300 | {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00}, | ||
301 | {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00}, | ||
302 | {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00}, | ||
303 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, | ||
304 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xf0, 0x00}, | ||
305 | {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00}, | ||
306 | {BRIDGE, M5602_XB_GPIO_DAT, 0x1c, 0x00}, | ||
307 | {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00}, | ||
308 | {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06, 0x00}, | ||
309 | {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00}, | ||
310 | {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00}, | ||
311 | {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x20, 0x00}, | ||
312 | |||
313 | {SENSOR, S5K83A_PAGE_MAP, 0x04, 0x00}, | ||
314 | {SENSOR, 0xaf, 0x01, 0x00}, | ||
315 | {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00}, | ||
316 | /* ff ( init value )is very dark) || 71 and f0 better */ | ||
317 | {SENSOR, 0x7b, 0xff, 0x00}, | ||
318 | {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00}, | ||
319 | {SENSOR, 0x01, 0x50, 0x00}, | ||
320 | {SENSOR, 0x12, 0x20, 0x00}, | ||
321 | {SENSOR, 0x17, 0x40, 0x00}, | ||
322 | {SENSOR, S5K83A_BRIGHTNESS, 0x0f, 0x00}, | ||
323 | {SENSOR, 0x1c, 0x00, 0x00}, | ||
324 | {SENSOR, 0x02, 0x70, 0x00}, | ||
325 | /* some values like 0x10 give a blue-purple image */ | ||
326 | {SENSOR, 0x03, 0x0b, 0x00}, | ||
327 | {SENSOR, 0x04, 0xf0, 0x00}, | ||
328 | {SENSOR, 0x05, 0x0b, 0x00}, | ||
329 | {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00}, | ||
330 | |||
331 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00}, | ||
332 | /* under 80 don't work, highter depend on value */ | ||
333 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, | ||
334 | |||
335 | {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, | ||
336 | {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00}, | ||
337 | {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00}, | ||
338 | {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00}, | ||
339 | {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00}, | ||
340 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
341 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
342 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
343 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
344 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x01, 0x00}, | ||
345 | {BRIDGE, M5602_XB_VSYNC_PARA, 0xe4, 0x00}, | ||
346 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
347 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
348 | {BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00}, | ||
349 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, | ||
350 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, | ||
351 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x02, 0x00}, | ||
352 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x7f, 0x00}, | ||
353 | |||
354 | {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00}, | ||
355 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, | ||
356 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, | ||
357 | |||
358 | {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00}, | ||
359 | {SENSOR, 0x06, 0x71, 0x00}, | ||
360 | {SENSOR, 0x07, 0xe8, 0x00}, | ||
361 | {SENSOR, 0x08, 0x02, 0x00}, | ||
362 | {SENSOR, 0x09, 0x88, 0x00}, | ||
363 | {SENSOR, 0x14, 0x00, 0x00}, | ||
364 | {SENSOR, 0x15, 0x20, 0x00}, | ||
365 | {SENSOR, 0x19, 0x00, 0x00}, | ||
366 | {SENSOR, 0x1a, 0x98, 0x00}, | ||
367 | {SENSOR, 0x0f, 0x02, 0x00}, | ||
368 | {SENSOR, 0x10, 0xe5, 0x00}, | ||
369 | {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00}, | ||
370 | {SENSOR_LONG, 0x14, 0x00, 0x20}, | ||
371 | {SENSOR_LONG, 0x0d, 0x00, 0x7d}, | ||
372 | {SENSOR_LONG, 0x1b, 0x0d, 0x05}, | ||
373 | |||
374 | /* The following sequence is useless after a clean boot | ||
375 | but is necessary after resume from suspend */ | ||
376 | {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00}, | ||
377 | {BRIDGE, M5602_XB_GPIO_DAT, 0x08, 0x00}, | ||
378 | {BRIDGE, M5602_XB_GPIO_EN_H, 0x3f, 0x00}, | ||
379 | {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3f, 0x00}, | ||
380 | {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00}, | ||
381 | {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00}, | ||
382 | {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00}, | ||
383 | {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00}, | ||
384 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0xb0, 0x00}, | ||
385 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0x80, 0x00}, | ||
386 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, | ||
387 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, | ||
388 | {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, | ||
389 | {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00}, | ||
390 | {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00}, | ||
391 | {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00}, | ||
392 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, | ||
393 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xf0, 0x00}, | ||
394 | {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00}, | ||
395 | {BRIDGE, M5602_XB_GPIO_DAT, 0x1c, 0x00}, | ||
396 | {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00}, | ||
397 | {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06, 0x00}, | ||
398 | {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00}, | ||
399 | {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00}, | ||
400 | {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x20, 0x00}, | ||
401 | |||
402 | {SENSOR, S5K83A_PAGE_MAP, 0x04, 0x00}, | ||
403 | {SENSOR, 0xaf, 0x01, 0x00}, | ||
404 | {SENSOR, S5K83A_PAGE_MAP, 0x00, 0x00}, | ||
405 | {SENSOR, 0x7b, 0xff, 0x00}, | ||
406 | {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00}, | ||
407 | {SENSOR, 0x01, 0x50, 0x00}, | ||
408 | {SENSOR, 0x12, 0x20, 0x00}, | ||
409 | {SENSOR, 0x17, 0x40, 0x00}, | ||
410 | {SENSOR, S5K83A_BRIGHTNESS, 0x0f, 0x00}, | ||
411 | {SENSOR, 0x1c, 0x00, 0x00}, | ||
412 | {SENSOR, 0x02, 0x70, 0x00}, | ||
413 | {SENSOR, 0x03, 0x0b, 0x00}, | ||
414 | {SENSOR, 0x04, 0xf0, 0x00}, | ||
415 | {SENSOR, 0x05, 0x0b, 0x00}, | ||
416 | {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00}, | ||
417 | |||
418 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00}, | ||
419 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, | ||
420 | {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, | ||
421 | {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00}, | ||
422 | {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00}, | ||
423 | {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00}, | ||
424 | {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00}, | ||
425 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
426 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
427 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
428 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
429 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x01, 0x00}, | ||
430 | {BRIDGE, M5602_XB_VSYNC_PARA, 0xe4, 0x00}, | ||
431 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
432 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
433 | {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00}, | ||
434 | {BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00}, | ||
435 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, | ||
436 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, | ||
437 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x02, 0x00}, | ||
438 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x7f, 0x00}, | ||
439 | {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00}, | ||
440 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, | ||
441 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, | ||
442 | |||
443 | {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00}, | ||
444 | {SENSOR, 0x06, 0x71, 0x00}, | ||
445 | {SENSOR, 0x07, 0xe8, 0x00}, | ||
446 | {SENSOR, 0x08, 0x02, 0x00}, | ||
447 | {SENSOR, 0x09, 0x88, 0x00}, | ||
448 | {SENSOR, 0x14, 0x00, 0x00}, | ||
449 | {SENSOR, 0x15, 0x20, 0x00}, | ||
450 | {SENSOR, 0x19, 0x00, 0x00}, | ||
451 | {SENSOR, 0x1a, 0x98, 0x00}, | ||
452 | {SENSOR, 0x0f, 0x02, 0x00}, | ||
453 | |||
454 | {SENSOR, 0x10, 0xe5, 0x00}, | ||
455 | {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00}, | ||
456 | {SENSOR_LONG, 0x14, 0x00, 0x20}, | ||
457 | {SENSOR_LONG, 0x0d, 0x00, 0x7d}, | ||
458 | {SENSOR_LONG, 0x1b, 0x0d, 0x05}, | ||
459 | |||
460 | /* normal colors | ||
461 | (this is value after boot, but after tries can be different) */ | ||
462 | {SENSOR, 0x00, 0x06, 0x00}, | ||
463 | |||
464 | /* set default brightness */ | ||
465 | {SENSOR_LONG, 0x14, 0x00, 0x20}, | ||
466 | {SENSOR_LONG, 0x0d, 0x01, 0x00}, | ||
467 | {SENSOR_LONG, 0x1b, S5K83A_DEFAULT_BRIGHTNESS >> 3, | ||
468 | S5K83A_DEFAULT_BRIGHTNESS >> 1}, | ||
469 | |||
470 | /* set default whiteness */ | ||
471 | {SENSOR, S5K83A_WHITENESS, S5K83A_DEFAULT_WHITENESS, 0x00}, | ||
472 | |||
473 | /* set default gain */ | ||
474 | {SENSOR_LONG, 0x18, 0x00, S5K83A_DEFAULT_GAIN}, | ||
475 | |||
476 | /* set default flip */ | ||
477 | {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00}, | ||
478 | {SENSOR, S5K83A_FLIP, 0x00 | S5K83A_FLIP_MASK, 0x00}, | ||
479 | {SENSOR, S5K83A_HFLIP_TUNE, 0x0b, 0x00}, | ||
480 | {SENSOR, S5K83A_VFLIP_TUNE, 0x0a, 0x00} | ||
481 | |||
482 | }; | ||
483 | |||
484 | #endif | ||
diff --git a/drivers/media/video/gspca/m5602/m5602_sensor.h b/drivers/media/video/gspca/m5602/m5602_sensor.h new file mode 100644 index 000000000000..930fcaab4416 --- /dev/null +++ b/drivers/media/video/gspca/m5602/m5602_sensor.h | |||
@@ -0,0 +1,76 @@ | |||
1 | /* | ||
2 | * USB Driver for ALi m5602 based webcams | ||
3 | * | ||
4 | * Copyright (C) 2008 Erik Andren | ||
5 | * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project. | ||
6 | * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br> | ||
7 | * | ||
8 | * Portions of code to USB interface and ALi driver software, | ||
9 | * Copyright (c) 2006 Willem Duinker | ||
10 | * v4l2 interface modeled after the V4L2 driver | ||
11 | * for SN9C10x PC Camera Controllers | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or | ||
14 | * modify it under the terms of the GNU General Public License as | ||
15 | * published by the Free Software Foundation, version 2. | ||
16 | * | ||
17 | */ | ||
18 | |||
19 | #ifndef M5602_SENSOR_H_ | ||
20 | #define M5602_SENSOR_H_ | ||
21 | |||
22 | #include "m5602_bridge.h" | ||
23 | |||
24 | #define M5602_DEFAULT_FRAME_WIDTH 640 | ||
25 | #define M5602_DEFAULT_FRAME_HEIGHT 480 | ||
26 | |||
27 | #define M5602_MAX_CTRLS (V4L2_CID_LASTP1 - V4L2_CID_BASE + 10) | ||
28 | |||
29 | /* Enumerates all supported sensors */ | ||
30 | enum sensors { | ||
31 | OV9650_SENSOR = 1, | ||
32 | S5K83A_SENSOR = 2, | ||
33 | S5K4AA_SENSOR = 3, | ||
34 | MT9M111_SENSOR = 4, | ||
35 | PO1030_SENSOR = 5 | ||
36 | }; | ||
37 | |||
38 | /* Enumerates all possible instruction types */ | ||
39 | enum instruction { | ||
40 | BRIDGE, | ||
41 | SENSOR, | ||
42 | SENSOR_LONG | ||
43 | }; | ||
44 | |||
45 | struct m5602_sensor { | ||
46 | /* Defines the name of a sensor */ | ||
47 | char name[32]; | ||
48 | |||
49 | /* What i2c address the sensor is connected to */ | ||
50 | u8 i2c_slave_id; | ||
51 | |||
52 | /* Probes if the sensor is connected */ | ||
53 | int (*probe)(struct sd *sd); | ||
54 | |||
55 | /* Performs a initialization sequence */ | ||
56 | int (*init)(struct sd *sd); | ||
57 | |||
58 | /* Performs a power down sequence */ | ||
59 | int (*power_down)(struct sd *sd); | ||
60 | |||
61 | /* Reads a sensor register */ | ||
62 | int (*read_sensor)(struct sd *sd, const u8 address, | ||
63 | u8 *i2c_data, const u8 len); | ||
64 | |||
65 | /* Writes to a sensor register */ | ||
66 | int (*write_sensor)(struct sd *sd, const u8 address, | ||
67 | u8 *i2c_data, const u8 len); | ||
68 | |||
69 | int nctrls; | ||
70 | struct ctrl ctrls[M5602_MAX_CTRLS]; | ||
71 | |||
72 | char nmodes; | ||
73 | struct v4l2_pix_format modes[]; | ||
74 | }; | ||
75 | |||
76 | #endif | ||
diff --git a/drivers/media/video/gspca/mars.c b/drivers/media/video/gspca/mars.c index 4d5db47ba8cb..277ca34a8817 100644 --- a/drivers/media/video/gspca/mars.c +++ b/drivers/media/video/gspca/mars.c | |||
@@ -134,7 +134,7 @@ static int sd_init(struct gspca_dev *gspca_dev) | |||
134 | return 0; | 134 | return 0; |
135 | } | 135 | } |
136 | 136 | ||
137 | static void sd_start(struct gspca_dev *gspca_dev) | 137 | static int sd_start(struct gspca_dev *gspca_dev) |
138 | { | 138 | { |
139 | int err_code; | 139 | int err_code; |
140 | __u8 *data; | 140 | __u8 *data; |
@@ -143,9 +143,10 @@ static void sd_start(struct gspca_dev *gspca_dev) | |||
143 | int intpipe; | 143 | int intpipe; |
144 | 144 | ||
145 | PDEBUG(D_STREAM, "camera start, iface %d, alt 8", gspca_dev->iface); | 145 | PDEBUG(D_STREAM, "camera start, iface %d, alt 8", gspca_dev->iface); |
146 | if (usb_set_interface(gspca_dev->dev, gspca_dev->iface, 8) < 0) { | 146 | err_code = usb_set_interface(gspca_dev->dev, gspca_dev->iface, 8); |
147 | if (err_code < 0) { | ||
147 | PDEBUG(D_ERR|D_STREAM, "Set packet size: set interface error"); | 148 | PDEBUG(D_ERR|D_STREAM, "Set packet size: set interface error"); |
148 | return; | 149 | return err_code; |
149 | } | 150 | } |
150 | 151 | ||
151 | data = gspca_dev->usb_buf; | 152 | data = gspca_dev->usb_buf; |
@@ -154,7 +155,7 @@ static void sd_start(struct gspca_dev *gspca_dev) | |||
154 | 155 | ||
155 | err_code = reg_w(gspca_dev, data[0], 2); | 156 | err_code = reg_w(gspca_dev, data[0], 2); |
156 | if (err_code < 0) | 157 | if (err_code < 0) |
157 | return; | 158 | return err_code; |
158 | 159 | ||
159 | /* | 160 | /* |
160 | Initialize the MR97113 chip register | 161 | Initialize the MR97113 chip register |
@@ -180,14 +181,14 @@ static void sd_start(struct gspca_dev *gspca_dev) | |||
180 | 181 | ||
181 | err_code = reg_w(gspca_dev, data[0], 11); | 182 | err_code = reg_w(gspca_dev, data[0], 11); |
182 | if (err_code < 0) | 183 | if (err_code < 0) |
183 | return; | 184 | return err_code; |
184 | 185 | ||
185 | data[0] = 0x23; /* address */ | 186 | data[0] = 0x23; /* address */ |
186 | data[1] = 0x09; /* reg 35, append frame header */ | 187 | data[1] = 0x09; /* reg 35, append frame header */ |
187 | 188 | ||
188 | err_code = reg_w(gspca_dev, data[0], 2); | 189 | err_code = reg_w(gspca_dev, data[0], 2); |
189 | if (err_code < 0) | 190 | if (err_code < 0) |
190 | return; | 191 | return err_code; |
191 | 192 | ||
192 | data[0] = 0x3c; /* address */ | 193 | data[0] = 0x3c; /* address */ |
193 | /* if (gspca_dev->width == 1280) */ | 194 | /* if (gspca_dev->width == 1280) */ |
@@ -198,7 +199,7 @@ static void sd_start(struct gspca_dev *gspca_dev) | |||
198 | * (unit: 4KB) 200KB */ | 199 | * (unit: 4KB) 200KB */ |
199 | err_code = reg_w(gspca_dev, data[0], 2); | 200 | err_code = reg_w(gspca_dev, data[0], 2); |
200 | if (err_code < 0) | 201 | if (err_code < 0) |
201 | return; | 202 | return err_code; |
202 | 203 | ||
203 | if (0) { /* fixed dark-gain */ | 204 | if (0) { /* fixed dark-gain */ |
204 | data[1] = 0; /* reg 94, Y Gain (1.75) */ | 205 | data[1] = 0; /* reg 94, Y Gain (1.75) */ |
@@ -240,13 +241,13 @@ static void sd_start(struct gspca_dev *gspca_dev) | |||
240 | 241 | ||
241 | err_code = reg_w(gspca_dev, data[0], 6); | 242 | err_code = reg_w(gspca_dev, data[0], 6); |
242 | if (err_code < 0) | 243 | if (err_code < 0) |
243 | return; | 244 | return err_code; |
244 | 245 | ||
245 | data[0] = 0x67; | 246 | data[0] = 0x67; |
246 | data[1] = 0x13; /* reg 103, first pixel B, disable sharpness */ | 247 | data[1] = 0x13; /* reg 103, first pixel B, disable sharpness */ |
247 | err_code = reg_w(gspca_dev, data[0], 2); | 248 | err_code = reg_w(gspca_dev, data[0], 2); |
248 | if (err_code < 0) | 249 | if (err_code < 0) |
249 | return; | 250 | return err_code; |
250 | 251 | ||
251 | /* | 252 | /* |
252 | * initialize the value of MI sensor... | 253 | * initialize the value of MI sensor... |
@@ -326,6 +327,7 @@ static void sd_start(struct gspca_dev *gspca_dev) | |||
326 | data[0] = 0x00; | 327 | data[0] = 0x00; |
327 | data[1] = 0x4d; /* ISOC transfering enable... */ | 328 | data[1] = 0x4d; /* ISOC transfering enable... */ |
328 | reg_w(gspca_dev, data[0], 2); | 329 | reg_w(gspca_dev, data[0], 2); |
330 | return err_code; | ||
329 | } | 331 | } |
330 | 332 | ||
331 | static void sd_stopN(struct gspca_dev *gspca_dev) | 333 | static void sd_stopN(struct gspca_dev *gspca_dev) |
diff --git a/drivers/media/video/gspca/ov519.c b/drivers/media/video/gspca/ov519.c index 4df4eec9f7e7..ca671194679e 100644 --- a/drivers/media/video/gspca/ov519.c +++ b/drivers/media/video/gspca/ov519.c | |||
@@ -1854,7 +1854,7 @@ static int set_ov_sensor_window(struct sd *sd) | |||
1854 | } | 1854 | } |
1855 | 1855 | ||
1856 | /* -- start the camera -- */ | 1856 | /* -- start the camera -- */ |
1857 | static void sd_start(struct gspca_dev *gspca_dev) | 1857 | static int sd_start(struct gspca_dev *gspca_dev) |
1858 | { | 1858 | { |
1859 | struct sd *sd = (struct sd *) gspca_dev; | 1859 | struct sd *sd = (struct sd *) gspca_dev; |
1860 | int ret; | 1860 | int ret; |
@@ -1871,9 +1871,10 @@ static void sd_start(struct gspca_dev *gspca_dev) | |||
1871 | goto out; | 1871 | goto out; |
1872 | PDEBUG(D_STREAM, "camera started alt: 0x%02x", gspca_dev->alt); | 1872 | PDEBUG(D_STREAM, "camera started alt: 0x%02x", gspca_dev->alt); |
1873 | ov51x_led_control(sd, 1); | 1873 | ov51x_led_control(sd, 1); |
1874 | return; | 1874 | return 0; |
1875 | out: | 1875 | out: |
1876 | PDEBUG(D_ERR, "camera start error:%d", ret); | 1876 | PDEBUG(D_ERR, "camera start error:%d", ret); |
1877 | return ret; | ||
1877 | } | 1878 | } |
1878 | 1879 | ||
1879 | static void sd_stopN(struct gspca_dev *gspca_dev) | 1880 | static void sd_stopN(struct gspca_dev *gspca_dev) |
diff --git a/drivers/media/video/gspca/pac207.c b/drivers/media/video/gspca/pac207.c index 83b5f740c947..0b0c573d06da 100644 --- a/drivers/media/video/gspca/pac207.c +++ b/drivers/media/video/gspca/pac207.c | |||
@@ -281,7 +281,7 @@ static int sd_init(struct gspca_dev *gspca_dev) | |||
281 | } | 281 | } |
282 | 282 | ||
283 | /* -- start the camera -- */ | 283 | /* -- start the camera -- */ |
284 | static void sd_start(struct gspca_dev *gspca_dev) | 284 | static int sd_start(struct gspca_dev *gspca_dev) |
285 | { | 285 | { |
286 | struct sd *sd = (struct sd *) gspca_dev; | 286 | struct sd *sd = (struct sd *) gspca_dev; |
287 | __u8 mode; | 287 | __u8 mode; |
@@ -323,6 +323,7 @@ static void sd_start(struct gspca_dev *gspca_dev) | |||
323 | sd->sof_read = 0; | 323 | sd->sof_read = 0; |
324 | sd->autogain_ignore_frames = 0; | 324 | sd->autogain_ignore_frames = 0; |
325 | atomic_set(&sd->avg_lum, -1); | 325 | atomic_set(&sd->avg_lum, -1); |
326 | return 0; | ||
326 | } | 327 | } |
327 | 328 | ||
328 | static void sd_stopN(struct gspca_dev *gspca_dev) | 329 | static void sd_stopN(struct gspca_dev *gspca_dev) |
@@ -534,6 +535,7 @@ static const __devinitdata struct usb_device_id device_table[] = { | |||
534 | {USB_DEVICE(0x093a, 0x2470)}, | 535 | {USB_DEVICE(0x093a, 0x2470)}, |
535 | {USB_DEVICE(0x093a, 0x2471)}, | 536 | {USB_DEVICE(0x093a, 0x2471)}, |
536 | {USB_DEVICE(0x093a, 0x2472)}, | 537 | {USB_DEVICE(0x093a, 0x2472)}, |
538 | {USB_DEVICE(0x093a, 0x2476)}, | ||
537 | {USB_DEVICE(0x2001, 0xf115)}, | 539 | {USB_DEVICE(0x2001, 0xf115)}, |
538 | {} | 540 | {} |
539 | }; | 541 | }; |
diff --git a/drivers/media/video/gspca/pac7311.c b/drivers/media/video/gspca/pac7311.c index ba865b7f1ed8..e5ff9a6199ef 100644 --- a/drivers/media/video/gspca/pac7311.c +++ b/drivers/media/video/gspca/pac7311.c | |||
@@ -675,7 +675,7 @@ static int sd_init(struct gspca_dev *gspca_dev) | |||
675 | return 0; | 675 | return 0; |
676 | } | 676 | } |
677 | 677 | ||
678 | static void sd_start(struct gspca_dev *gspca_dev) | 678 | static int sd_start(struct gspca_dev *gspca_dev) |
679 | { | 679 | { |
680 | struct sd *sd = (struct sd *) gspca_dev; | 680 | struct sd *sd = (struct sd *) gspca_dev; |
681 | 681 | ||
@@ -724,6 +724,7 @@ static void sd_start(struct gspca_dev *gspca_dev) | |||
724 | reg_w(gspca_dev, 0x78, 0x01); | 724 | reg_w(gspca_dev, 0x78, 0x01); |
725 | else | 725 | else |
726 | reg_w(gspca_dev, 0x78, 0x05); | 726 | reg_w(gspca_dev, 0x78, 0x05); |
727 | return 0; | ||
727 | } | 728 | } |
728 | 729 | ||
729 | static void sd_stopN(struct gspca_dev *gspca_dev) | 730 | static void sd_stopN(struct gspca_dev *gspca_dev) |
diff --git a/drivers/media/video/gspca/sonixb.c b/drivers/media/video/gspca/sonixb.c index 12b81ae526b7..6c69bc7778fc 100644 --- a/drivers/media/video/gspca/sonixb.c +++ b/drivers/media/video/gspca/sonixb.c | |||
@@ -490,7 +490,7 @@ static const __u8 tas5130_sensor_init[][8] = { | |||
490 | {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10}, | 490 | {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10}, |
491 | }; | 491 | }; |
492 | 492 | ||
493 | struct sensor_data sensor_data[] = { | 493 | static struct sensor_data sensor_data[] = { |
494 | SENS(initHv7131, NULL, hv7131_sensor_init, NULL, NULL, 0, NO_EXPO|NO_FREQ, 0), | 494 | SENS(initHv7131, NULL, hv7131_sensor_init, NULL, NULL, 0, NO_EXPO|NO_FREQ, 0), |
495 | SENS(initOv6650, NULL, ov6650_sensor_init, NULL, NULL, F_GAIN|F_SIF, 0, 0x60), | 495 | SENS(initOv6650, NULL, ov6650_sensor_init, NULL, NULL, F_GAIN|F_SIF, 0, 0x60), |
496 | SENS(initOv7630, initOv7630_3, ov7630_sensor_init, NULL, ov7630_sensor_init_3, | 496 | SENS(initOv7630, initOv7630_3, ov7630_sensor_init, NULL, ov7630_sensor_init_3, |
@@ -892,7 +892,7 @@ static int sd_init(struct gspca_dev *gspca_dev) | |||
892 | } | 892 | } |
893 | 893 | ||
894 | /* -- start the camera -- */ | 894 | /* -- start the camera -- */ |
895 | static void sd_start(struct gspca_dev *gspca_dev) | 895 | static int sd_start(struct gspca_dev *gspca_dev) |
896 | { | 896 | { |
897 | struct sd *sd = (struct sd *) gspca_dev; | 897 | struct sd *sd = (struct sd *) gspca_dev; |
898 | struct cam *cam = &gspca_dev->cam; | 898 | struct cam *cam = &gspca_dev->cam; |
@@ -976,6 +976,7 @@ static void sd_start(struct gspca_dev *gspca_dev) | |||
976 | sd->frames_to_drop = 0; | 976 | sd->frames_to_drop = 0; |
977 | sd->autogain_ignore_frames = 0; | 977 | sd->autogain_ignore_frames = 0; |
978 | atomic_set(&sd->avg_lum, -1); | 978 | atomic_set(&sd->avg_lum, -1); |
979 | return 0; | ||
979 | } | 980 | } |
980 | 981 | ||
981 | static void sd_stopN(struct gspca_dev *gspca_dev) | 982 | static void sd_stopN(struct gspca_dev *gspca_dev) |
diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c index 572b0f363b64..53cb82d9e7c6 100644 --- a/drivers/media/video/gspca/sonixj.c +++ b/drivers/media/video/gspca/sonixj.c | |||
@@ -39,6 +39,7 @@ struct sd { | |||
39 | unsigned char contrast; | 39 | unsigned char contrast; |
40 | unsigned char colors; | 40 | unsigned char colors; |
41 | unsigned char autogain; | 41 | unsigned char autogain; |
42 | __u8 vflip; /* ov7630 only */ | ||
42 | 43 | ||
43 | signed char ag_cnt; | 44 | signed char ag_cnt; |
44 | #define AG_CNT_START 13 | 45 | #define AG_CNT_START 13 |
@@ -70,6 +71,8 @@ static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val); | |||
70 | static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val); | 71 | static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val); |
71 | static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val); | 72 | static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val); |
72 | static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val); | 73 | static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val); |
74 | static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val); | ||
75 | static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val); | ||
73 | 76 | ||
74 | static struct ctrl sd_ctrls[] = { | 77 | static struct ctrl sd_ctrls[] = { |
75 | { | 78 | { |
@@ -131,6 +134,22 @@ static struct ctrl sd_ctrls[] = { | |||
131 | .set = sd_setautogain, | 134 | .set = sd_setautogain, |
132 | .get = sd_getautogain, | 135 | .get = sd_getautogain, |
133 | }, | 136 | }, |
137 | /* ov7630 only */ | ||
138 | #define VFLIP_IDX 4 | ||
139 | { | ||
140 | { | ||
141 | .id = V4L2_CID_VFLIP, | ||
142 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
143 | .name = "Vflip", | ||
144 | .minimum = 0, | ||
145 | .maximum = 1, | ||
146 | .step = 1, | ||
147 | #define VFLIP_DEF 1 | ||
148 | .default_value = VFLIP_DEF, | ||
149 | }, | ||
150 | .set = sd_setvflip, | ||
151 | .get = sd_getvflip, | ||
152 | }, | ||
134 | }; | 153 | }; |
135 | 154 | ||
136 | static struct v4l2_pix_format vga_mode[] = { | 155 | static struct v4l2_pix_format vga_mode[] = { |
@@ -248,10 +267,12 @@ static const __u8 gamma_def[] = { | |||
248 | 0xa6, 0xb2, 0xbf, 0xca, 0xd5, 0xe0, 0xeb, 0xf5, 0xff | 267 | 0xa6, 0xb2, 0xbf, 0xca, 0xd5, 0xe0, 0xeb, 0xf5, 0xff |
249 | }; | 268 | }; |
250 | 269 | ||
270 | /* color matrix and offsets */ | ||
251 | static const __u8 reg84[] = { | 271 | static const __u8 reg84[] = { |
252 | 0x14, 0x00, 0x27, 0x00, 0x07, 0x00, 0xe5, 0x0f, | 272 | 0x14, 0x00, 0x27, 0x00, 0x07, 0x00, /* YR YG YB gains */ |
253 | 0xe4, 0x0f, 0x38, 0x00, 0x3e, 0x00, 0xc3, 0x0f, | 273 | 0xe8, 0x0f, 0xda, 0x0f, 0x40, 0x00, /* UR UG UB */ |
254 | 0xf7, 0x0f, 0x00, 0x00, 0x00 | 274 | 0x3e, 0x00, 0xcd, 0x0f, 0xf7, 0x0f, /* VR VG VB */ |
275 | 0x00, 0x00, 0x00 /* YUV offsets */ | ||
255 | }; | 276 | }; |
256 | static const __u8 hv7131r_sensor_init[][8] = { | 277 | static const __u8 hv7131r_sensor_init[][8] = { |
257 | {0xC1, 0x11, 0x01, 0x08, 0x01, 0x00, 0x00, 0x10}, | 278 | {0xC1, 0x11, 0x01, 0x08, 0x01, 0x00, 0x00, 0x10}, |
@@ -434,7 +455,8 @@ static const __u8 ov7630_sensor_init[][8] = { | |||
434 | {0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10}, | 455 | {0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10}, |
435 | {0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10}, | 456 | {0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10}, |
436 | /*fixme: + 0x12, 0x04*/ | 457 | /*fixme: + 0x12, 0x04*/ |
437 | {0xa1, 0x21, 0x75, 0x82, 0x00, 0x00, 0x00, 0x10}, | 458 | /* {0xa1, 0x21, 0x75, 0x82, 0x00, 0x00, 0x00, 0x10}, * COMN |
459 | * set by setvflip */ | ||
438 | {0xa1, 0x21, 0x10, 0x32, 0x00, 0x00, 0x00, 0x10}, | 460 | {0xa1, 0x21, 0x10, 0x32, 0x00, 0x00, 0x00, 0x10}, |
439 | {0xa1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10}, | 461 | {0xa1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10}, |
440 | {0xb1, 0x21, 0x01, 0x80, 0x80, 0x00, 0x00, 0x10}, | 462 | {0xb1, 0x21, 0x01, 0x80, 0x80, 0x00, 0x00, 0x10}, |
@@ -949,6 +971,8 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
949 | gspca_dev->ctrl_dis = (1 << AUTOGAIN_IDX); | 971 | gspca_dev->ctrl_dis = (1 << AUTOGAIN_IDX); |
950 | break; | 972 | break; |
951 | } | 973 | } |
974 | if (sd->sensor != SENSOR_OV7630) | ||
975 | gspca_dev->ctrl_dis |= (1 << VFLIP_IDX); | ||
952 | 976 | ||
953 | return 0; | 977 | return 0; |
954 | } | 978 | } |
@@ -1080,20 +1104,17 @@ static unsigned int setexposure(struct gspca_dev *gspca_dev, | |||
1080 | static void setbrightcont(struct gspca_dev *gspca_dev) | 1104 | static void setbrightcont(struct gspca_dev *gspca_dev) |
1081 | { | 1105 | { |
1082 | struct sd *sd = (struct sd *) gspca_dev; | 1106 | struct sd *sd = (struct sd *) gspca_dev; |
1083 | unsigned val; | 1107 | int val; |
1084 | __u8 reg84_full[0x15]; | 1108 | __u8 reg84_full[0x15]; |
1085 | 1109 | ||
1086 | memset(reg84_full, 0, sizeof reg84_full); | 1110 | memcpy(reg84_full, reg84, sizeof reg84_full); |
1087 | val = sd->contrast * 0x20 / CONTRAST_MAX + 0x10; /* 10..30 */ | 1111 | val = sd->contrast * 0x30 / CONTRAST_MAX + 0x10; /* 10..40 */ |
1088 | reg84_full[2] = val; | 1112 | reg84_full[0] = (val + 1) / 2; /* red */ |
1089 | reg84_full[0] = (val + 1) / 2; | 1113 | reg84_full[2] = val; /* green */ |
1090 | reg84_full[4] = (val + 1) / 5; | 1114 | reg84_full[4] = (val + 1) / 5; /* blue */ |
1091 | if (val > BRIGHTNESS_DEF) | 1115 | val = (sd->brightness - BRIGHTNESS_DEF) * 0x10 |
1092 | val = (sd->brightness - BRIGHTNESS_DEF) * 0x20 | ||
1093 | / BRIGHTNESS_MAX; | 1116 | / BRIGHTNESS_MAX; |
1094 | else | 1117 | reg84_full[0x12] = val & 0x1f; /* 5:0 signed value */ |
1095 | val = 0; | ||
1096 | reg84_full[0x12] = val; /* 00..1f */ | ||
1097 | reg_w(gspca_dev, 0x84, reg84_full, sizeof reg84_full); | 1118 | reg_w(gspca_dev, 0x84, reg84_full, sizeof reg84_full); |
1098 | } | 1119 | } |
1099 | 1120 | ||
@@ -1172,8 +1193,16 @@ static void setautogain(struct gspca_dev *gspca_dev) | |||
1172 | sd->ag_cnt = -1; | 1193 | sd->ag_cnt = -1; |
1173 | } | 1194 | } |
1174 | 1195 | ||
1196 | static void setvflip(struct sd *sd) | ||
1197 | { | ||
1198 | if (sd->sensor != SENSOR_OV7630) | ||
1199 | return; | ||
1200 | i2c_w1(&sd->gspca_dev, 0x75, /* COMN */ | ||
1201 | sd->vflip ? 0x82 : 0x02); | ||
1202 | } | ||
1203 | |||
1175 | /* -- start the camera -- */ | 1204 | /* -- start the camera -- */ |
1176 | static void sd_start(struct gspca_dev *gspca_dev) | 1205 | static int sd_start(struct gspca_dev *gspca_dev) |
1177 | { | 1206 | { |
1178 | struct sd *sd = (struct sd *) gspca_dev; | 1207 | struct sd *sd = (struct sd *) gspca_dev; |
1179 | int i; | 1208 | int i; |
@@ -1263,6 +1292,7 @@ static void sd_start(struct gspca_dev *gspca_dev) | |||
1263 | break; | 1292 | break; |
1264 | case SENSOR_OV7630: | 1293 | case SENSOR_OV7630: |
1265 | ov7630_InitSensor(gspca_dev); | 1294 | ov7630_InitSensor(gspca_dev); |
1295 | setvflip(sd); | ||
1266 | reg17 = 0xe2; | 1296 | reg17 = 0xe2; |
1267 | reg1 = 0x44; | 1297 | reg1 = 0x44; |
1268 | break; | 1298 | break; |
@@ -1320,12 +1350,16 @@ static void sd_start(struct gspca_dev *gspca_dev) | |||
1320 | setbrightness(gspca_dev); | 1350 | setbrightness(gspca_dev); |
1321 | setcontrast(gspca_dev); | 1351 | setcontrast(gspca_dev); |
1322 | break; | 1352 | break; |
1353 | case SENSOR_OV7630: | ||
1354 | setvflip(sd); | ||
1355 | /* fall thru */ | ||
1323 | default: /* OV76xx */ | 1356 | default: /* OV76xx */ |
1324 | setbrightcont(gspca_dev); | 1357 | setbrightcont(gspca_dev); |
1325 | break; | 1358 | break; |
1326 | } | 1359 | } |
1327 | setautogain(gspca_dev); | 1360 | setautogain(gspca_dev); |
1328 | reg_w1(gspca_dev, 0x01, reg1); | 1361 | reg_w1(gspca_dev, 0x01, reg1); |
1362 | return 0; | ||
1329 | } | 1363 | } |
1330 | 1364 | ||
1331 | static void sd_stopN(struct gspca_dev *gspca_dev) | 1365 | static void sd_stopN(struct gspca_dev *gspca_dev) |
@@ -1546,6 +1580,24 @@ static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val) | |||
1546 | return 0; | 1580 | return 0; |
1547 | } | 1581 | } |
1548 | 1582 | ||
1583 | static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val) | ||
1584 | { | ||
1585 | struct sd *sd = (struct sd *) gspca_dev; | ||
1586 | |||
1587 | sd->vflip = val; | ||
1588 | if (gspca_dev->streaming) | ||
1589 | setvflip(sd); | ||
1590 | return 0; | ||
1591 | } | ||
1592 | |||
1593 | static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val) | ||
1594 | { | ||
1595 | struct sd *sd = (struct sd *) gspca_dev; | ||
1596 | |||
1597 | *val = sd->vflip; | ||
1598 | return 0; | ||
1599 | } | ||
1600 | |||
1549 | /* sub-driver description */ | 1601 | /* sub-driver description */ |
1550 | static const struct sd_desc sd_desc = { | 1602 | static const struct sd_desc sd_desc = { |
1551 | .name = MODULE_NAME, | 1603 | .name = MODULE_NAME, |
@@ -1567,6 +1619,7 @@ static const struct sd_desc sd_desc = { | |||
1567 | static const __devinitdata struct usb_device_id device_table[] = { | 1619 | static const __devinitdata struct usb_device_id device_table[] = { |
1568 | #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE | 1620 | #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE |
1569 | {USB_DEVICE(0x0458, 0x7025), BSI(SN9C120, MI0360, 0x5d)}, | 1621 | {USB_DEVICE(0x0458, 0x7025), BSI(SN9C120, MI0360, 0x5d)}, |
1622 | {USB_DEVICE(0x0458, 0x702e), BSI(SN9C120, OV7660, 0x21)}, | ||
1570 | {USB_DEVICE(0x045e, 0x00f5), BSI(SN9C105, OV7660, 0x21)}, | 1623 | {USB_DEVICE(0x045e, 0x00f5), BSI(SN9C105, OV7660, 0x21)}, |
1571 | {USB_DEVICE(0x045e, 0x00f7), BSI(SN9C105, OV7660, 0x21)}, | 1624 | {USB_DEVICE(0x045e, 0x00f7), BSI(SN9C105, OV7660, 0x21)}, |
1572 | {USB_DEVICE(0x0471, 0x0327), BSI(SN9C105, MI0360, 0x5d)}, | 1625 | {USB_DEVICE(0x0471, 0x0327), BSI(SN9C105, MI0360, 0x5d)}, |
@@ -1588,7 +1641,9 @@ static const __devinitdata struct usb_device_id device_table[] = { | |||
1588 | /* {USB_DEVICE(0x0c45, 0x60fa), BSI(SN9C105, OV7648, 0x??)}, */ | 1641 | /* {USB_DEVICE(0x0c45, 0x60fa), BSI(SN9C105, OV7648, 0x??)}, */ |
1589 | {USB_DEVICE(0x0c45, 0x60fb), BSI(SN9C105, OV7660, 0x21)}, | 1642 | {USB_DEVICE(0x0c45, 0x60fb), BSI(SN9C105, OV7660, 0x21)}, |
1590 | {USB_DEVICE(0x0c45, 0x60fc), BSI(SN9C105, HV7131R, 0x11)}, | 1643 | {USB_DEVICE(0x0c45, 0x60fc), BSI(SN9C105, HV7131R, 0x11)}, |
1591 | /* {USB_DEVICE(0x0c45, 0x60fe), BSI(SN9C105, OV7630, 0x??)}, */ | 1644 | #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE |
1645 | {USB_DEVICE(0x0c45, 0x60fe), BSI(SN9C105, OV7630, 0x21)}, | ||
1646 | #endif | ||
1592 | /* {USB_DEVICE(0x0c45, 0x6108), BSI(SN9C120, OM6801, 0x??)}, */ | 1647 | /* {USB_DEVICE(0x0c45, 0x6108), BSI(SN9C120, OM6801, 0x??)}, */ |
1593 | /* {USB_DEVICE(0x0c45, 0x6122), BSI(SN9C110, ICM105C, 0x??)}, */ | 1648 | /* {USB_DEVICE(0x0c45, 0x6122), BSI(SN9C110, ICM105C, 0x??)}, */ |
1594 | /* {USB_DEVICE(0x0c45, 0x6123), BSI(SN9C110, SanyoCCD, 0x??)}, */ | 1649 | /* {USB_DEVICE(0x0c45, 0x6123), BSI(SN9C110, SanyoCCD, 0x??)}, */ |
diff --git a/drivers/media/video/gspca/spca500.c b/drivers/media/video/gspca/spca500.c index 6e733901fcca..bca106c153fa 100644 --- a/drivers/media/video/gspca/spca500.c +++ b/drivers/media/video/gspca/spca500.c | |||
@@ -660,7 +660,7 @@ static int sd_init(struct gspca_dev *gspca_dev) | |||
660 | return 0; | 660 | return 0; |
661 | } | 661 | } |
662 | 662 | ||
663 | static void sd_start(struct gspca_dev *gspca_dev) | 663 | static int sd_start(struct gspca_dev *gspca_dev) |
664 | { | 664 | { |
665 | struct sd *sd = (struct sd *) gspca_dev; | 665 | struct sd *sd = (struct sd *) gspca_dev; |
666 | int err; | 666 | int err; |
@@ -867,6 +867,7 @@ static void sd_start(struct gspca_dev *gspca_dev) | |||
867 | write_vector(gspca_dev, Clicksmart510_defaults); | 867 | write_vector(gspca_dev, Clicksmart510_defaults); |
868 | break; | 868 | break; |
869 | } | 869 | } |
870 | return 0; | ||
870 | } | 871 | } |
871 | 872 | ||
872 | static void sd_stopN(struct gspca_dev *gspca_dev) | 873 | static void sd_stopN(struct gspca_dev *gspca_dev) |
diff --git a/drivers/media/video/gspca/spca501.c b/drivers/media/video/gspca/spca501.c index e9eb59bae4fb..b742f260c7ca 100644 --- a/drivers/media/video/gspca/spca501.c +++ b/drivers/media/video/gspca/spca501.c | |||
@@ -1980,7 +1980,7 @@ static int sd_init(struct gspca_dev *gspca_dev) | |||
1980 | return 0; | 1980 | return 0; |
1981 | } | 1981 | } |
1982 | 1982 | ||
1983 | static void sd_start(struct gspca_dev *gspca_dev) | 1983 | static int sd_start(struct gspca_dev *gspca_dev) |
1984 | { | 1984 | { |
1985 | struct usb_device *dev = gspca_dev->dev; | 1985 | struct usb_device *dev = gspca_dev->dev; |
1986 | int mode; | 1986 | int mode; |
@@ -2012,6 +2012,7 @@ static void sd_start(struct gspca_dev *gspca_dev) | |||
2012 | setbrightness(gspca_dev); | 2012 | setbrightness(gspca_dev); |
2013 | setcontrast(gspca_dev); | 2013 | setcontrast(gspca_dev); |
2014 | setcolors(gspca_dev); | 2014 | setcolors(gspca_dev); |
2015 | return 0; | ||
2015 | } | 2016 | } |
2016 | 2017 | ||
2017 | static void sd_stopN(struct gspca_dev *gspca_dev) | 2018 | static void sd_stopN(struct gspca_dev *gspca_dev) |
diff --git a/drivers/media/video/gspca/spca505.c b/drivers/media/video/gspca/spca505.c index f601daf19ebe..b345749213cf 100644 --- a/drivers/media/video/gspca/spca505.c +++ b/drivers/media/video/gspca/spca505.c | |||
@@ -688,7 +688,7 @@ static int sd_init(struct gspca_dev *gspca_dev) | |||
688 | return 0; | 688 | return 0; |
689 | } | 689 | } |
690 | 690 | ||
691 | static void sd_start(struct gspca_dev *gspca_dev) | 691 | static int sd_start(struct gspca_dev *gspca_dev) |
692 | { | 692 | { |
693 | struct usb_device *dev = gspca_dev->dev; | 693 | struct usb_device *dev = gspca_dev->dev; |
694 | int ret; | 694 | int ret; |
@@ -733,6 +733,7 @@ static void sd_start(struct gspca_dev *gspca_dev) | |||
733 | /* reg_write(dev, 0x5, 0x0, 0x0); */ | 733 | /* reg_write(dev, 0x5, 0x0, 0x0); */ |
734 | /* reg_write(dev, 0x5, 0x0, 0x1); */ | 734 | /* reg_write(dev, 0x5, 0x0, 0x1); */ |
735 | /* reg_write(dev, 0x5, 0x11, 0x2); */ | 735 | /* reg_write(dev, 0x5, 0x11, 0x2); */ |
736 | return ret; | ||
736 | } | 737 | } |
737 | 738 | ||
738 | static void sd_stopN(struct gspca_dev *gspca_dev) | 739 | static void sd_stopN(struct gspca_dev *gspca_dev) |
diff --git a/drivers/media/video/gspca/spca506.c b/drivers/media/video/gspca/spca506.c index 195dce96ef06..645ee9d44d02 100644 --- a/drivers/media/video/gspca/spca506.c +++ b/drivers/media/video/gspca/spca506.c | |||
@@ -422,7 +422,7 @@ static int sd_init(struct gspca_dev *gspca_dev) | |||
422 | return 0; | 422 | return 0; |
423 | } | 423 | } |
424 | 424 | ||
425 | static void sd_start(struct gspca_dev *gspca_dev) | 425 | static int sd_start(struct gspca_dev *gspca_dev) |
426 | { | 426 | { |
427 | struct usb_device *dev = gspca_dev->dev; | 427 | struct usb_device *dev = gspca_dev->dev; |
428 | __u16 norme; | 428 | __u16 norme; |
@@ -549,6 +549,7 @@ static void sd_start(struct gspca_dev *gspca_dev) | |||
549 | PDEBUG(D_STREAM, "webcam started"); | 549 | PDEBUG(D_STREAM, "webcam started"); |
550 | spca506_GetNormeInput(gspca_dev, &norme, &channel); | 550 | spca506_GetNormeInput(gspca_dev, &norme, &channel); |
551 | spca506_SetNormeInput(gspca_dev, norme, channel); | 551 | spca506_SetNormeInput(gspca_dev, norme, channel); |
552 | return 0; | ||
552 | } | 553 | } |
553 | 554 | ||
554 | static void sd_stopN(struct gspca_dev *gspca_dev) | 555 | static void sd_stopN(struct gspca_dev *gspca_dev) |
diff --git a/drivers/media/video/gspca/spca508.c b/drivers/media/video/gspca/spca508.c index 281ce02103a3..63ec902c895d 100644 --- a/drivers/media/video/gspca/spca508.c +++ b/drivers/media/video/gspca/spca508.c | |||
@@ -1528,7 +1528,7 @@ static int sd_init(struct gspca_dev *gspca_dev) | |||
1528 | return 0; | 1528 | return 0; |
1529 | } | 1529 | } |
1530 | 1530 | ||
1531 | static void sd_start(struct gspca_dev *gspca_dev) | 1531 | static int sd_start(struct gspca_dev *gspca_dev) |
1532 | { | 1532 | { |
1533 | int mode; | 1533 | int mode; |
1534 | 1534 | ||
@@ -1546,6 +1546,7 @@ static void sd_start(struct gspca_dev *gspca_dev) | |||
1546 | break; | 1546 | break; |
1547 | } | 1547 | } |
1548 | reg_write(gspca_dev->dev, 0x8112, 0x10 | 0x20); | 1548 | reg_write(gspca_dev->dev, 0x8112, 0x10 | 0x20); |
1549 | return 0; | ||
1549 | } | 1550 | } |
1550 | 1551 | ||
1551 | static void sd_stopN(struct gspca_dev *gspca_dev) | 1552 | static void sd_stopN(struct gspca_dev *gspca_dev) |
diff --git a/drivers/media/video/gspca/spca561.c b/drivers/media/video/gspca/spca561.c index 95fcfcb9e31b..020a03c466c1 100644 --- a/drivers/media/video/gspca/spca561.c +++ b/drivers/media/video/gspca/spca561.c | |||
@@ -152,7 +152,7 @@ static void reg_w_val(struct usb_device *dev, __u16 index, __u8 value) | |||
152 | 152 | ||
153 | ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), | 153 | ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), |
154 | 0, /* request */ | 154 | 0, /* request */ |
155 | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | 155 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
156 | value, index, NULL, 0, 500); | 156 | value, index, NULL, 0, 500); |
157 | PDEBUG(D_USBO, "reg write: 0x%02x:0x%02x", index, value); | 157 | PDEBUG(D_USBO, "reg write: 0x%02x:0x%02x", index, value); |
158 | if (ret < 0) | 158 | if (ret < 0) |
@@ -699,7 +699,7 @@ static void setautogain(struct gspca_dev *gspca_dev) | |||
699 | sd->ag_cnt = -1; | 699 | sd->ag_cnt = -1; |
700 | } | 700 | } |
701 | 701 | ||
702 | static void sd_start_12a(struct gspca_dev *gspca_dev) | 702 | static int sd_start_12a(struct gspca_dev *gspca_dev) |
703 | { | 703 | { |
704 | struct usb_device *dev = gspca_dev->dev; | 704 | struct usb_device *dev = gspca_dev->dev; |
705 | int Clck = 0x8a; /* lower 0x8X values lead to fps > 30 */ | 705 | int Clck = 0x8a; /* lower 0x8X values lead to fps > 30 */ |
@@ -725,8 +725,9 @@ static void sd_start_12a(struct gspca_dev *gspca_dev) | |||
725 | setwhite(gspca_dev); | 725 | setwhite(gspca_dev); |
726 | setautogain(gspca_dev); | 726 | setautogain(gspca_dev); |
727 | setexposure(gspca_dev); | 727 | setexposure(gspca_dev); |
728 | return 0; | ||
728 | } | 729 | } |
729 | static void sd_start_72a(struct gspca_dev *gspca_dev) | 730 | static int sd_start_72a(struct gspca_dev *gspca_dev) |
730 | { | 731 | { |
731 | struct usb_device *dev = gspca_dev->dev; | 732 | struct usb_device *dev = gspca_dev->dev; |
732 | int Clck; | 733 | int Clck; |
@@ -750,6 +751,7 @@ static void sd_start_72a(struct gspca_dev *gspca_dev) | |||
750 | reg_w_val(dev, 0x8700, Clck); /* 0x27 clock */ | 751 | reg_w_val(dev, 0x8700, Clck); /* 0x27 clock */ |
751 | reg_w_val(dev, 0x8112, 0x10 | 0x20); | 752 | reg_w_val(dev, 0x8112, 0x10 | 0x20); |
752 | setautogain(gspca_dev); | 753 | setautogain(gspca_dev); |
754 | return 0; | ||
753 | } | 755 | } |
754 | 756 | ||
755 | static void sd_stopN(struct gspca_dev *gspca_dev) | 757 | static void sd_stopN(struct gspca_dev *gspca_dev) |
@@ -1064,7 +1066,7 @@ static struct ctrl sd_ctrls_12a[] = { | |||
1064 | { | 1066 | { |
1065 | .id = V4L2_CID_DO_WHITE_BALANCE, | 1067 | .id = V4L2_CID_DO_WHITE_BALANCE, |
1066 | .type = V4L2_CTRL_TYPE_INTEGER, | 1068 | .type = V4L2_CTRL_TYPE_INTEGER, |
1067 | .name = "While Balance", | 1069 | .name = "White Balance", |
1068 | .minimum = WHITE_MIN, | 1070 | .minimum = WHITE_MIN, |
1069 | .maximum = WHITE_MAX, | 1071 | .maximum = WHITE_MAX, |
1070 | .step = 1, | 1072 | .step = 1, |
diff --git a/drivers/media/video/gspca/stk014.c b/drivers/media/video/gspca/stk014.c index 2f2de429e273..d9d64911f22a 100644 --- a/drivers/media/video/gspca/stk014.c +++ b/drivers/media/video/gspca/stk014.c | |||
@@ -324,7 +324,7 @@ static int sd_init(struct gspca_dev *gspca_dev) | |||
324 | } | 324 | } |
325 | 325 | ||
326 | /* -- start the camera -- */ | 326 | /* -- start the camera -- */ |
327 | static void sd_start(struct gspca_dev *gspca_dev) | 327 | static int sd_start(struct gspca_dev *gspca_dev) |
328 | { | 328 | { |
329 | int ret, value; | 329 | int ret, value; |
330 | 330 | ||
@@ -374,9 +374,10 @@ static void sd_start(struct gspca_dev *gspca_dev) | |||
374 | set_par(gspca_dev, 0x01000000); | 374 | set_par(gspca_dev, 0x01000000); |
375 | set_par(gspca_dev, 0x01000000); | 375 | set_par(gspca_dev, 0x01000000); |
376 | PDEBUG(D_STREAM, "camera started alt: 0x%02x", gspca_dev->alt); | 376 | PDEBUG(D_STREAM, "camera started alt: 0x%02x", gspca_dev->alt); |
377 | return; | 377 | return 0; |
378 | out: | 378 | out: |
379 | PDEBUG(D_ERR|D_STREAM, "camera start err %d", ret); | 379 | PDEBUG(D_ERR|D_STREAM, "camera start err %d", ret); |
380 | return ret; | ||
380 | } | 381 | } |
381 | 382 | ||
382 | static void sd_stopN(struct gspca_dev *gspca_dev) | 383 | static void sd_stopN(struct gspca_dev *gspca_dev) |
diff --git a/drivers/media/video/gspca/sunplus.c b/drivers/media/video/gspca/sunplus.c index 1cfcc6c49558..bd9288665a80 100644 --- a/drivers/media/video/gspca/sunplus.c +++ b/drivers/media/video/gspca/sunplus.c | |||
@@ -961,7 +961,7 @@ static int sd_init(struct gspca_dev *gspca_dev) | |||
961 | return 0; | 961 | return 0; |
962 | } | 962 | } |
963 | 963 | ||
964 | static void sd_start(struct gspca_dev *gspca_dev) | 964 | static int sd_start(struct gspca_dev *gspca_dev) |
965 | { | 965 | { |
966 | struct sd *sd = (struct sd *) gspca_dev; | 966 | struct sd *sd = (struct sd *) gspca_dev; |
967 | struct usb_device *dev = gspca_dev->dev; | 967 | struct usb_device *dev = gspca_dev->dev; |
@@ -1042,6 +1042,7 @@ static void sd_start(struct gspca_dev *gspca_dev) | |||
1042 | break; | 1042 | break; |
1043 | } | 1043 | } |
1044 | sp5xx_initContBrigHueRegisters(gspca_dev); | 1044 | sp5xx_initContBrigHueRegisters(gspca_dev); |
1045 | return 0; | ||
1045 | } | 1046 | } |
1046 | 1047 | ||
1047 | static void sd_stopN(struct gspca_dev *gspca_dev) | 1048 | static void sd_stopN(struct gspca_dev *gspca_dev) |
diff --git a/drivers/media/video/gspca/t613.c b/drivers/media/video/gspca/t613.c index f034c748fc7e..b561f7c4f066 100644 --- a/drivers/media/video/gspca/t613.c +++ b/drivers/media/video/gspca/t613.c | |||
@@ -28,8 +28,6 @@ | |||
28 | 28 | ||
29 | #include "gspca.h" | 29 | #include "gspca.h" |
30 | 30 | ||
31 | #define MAX_GAMMA 0x10 /* 0 to 15 */ | ||
32 | |||
33 | #define V4L2_CID_EFFECTS (V4L2_CID_PRIVATE_BASE + 0) | 31 | #define V4L2_CID_EFFECTS (V4L2_CID_PRIVATE_BASE + 0) |
34 | 32 | ||
35 | MODULE_AUTHOR("Leandro Costantino <le_costantino@pixartargentina.com.ar>"); | 33 | MODULE_AUTHOR("Leandro Costantino <le_costantino@pixartargentina.com.ar>"); |
@@ -49,6 +47,10 @@ struct sd { | |||
49 | unsigned char whitebalance; | 47 | unsigned char whitebalance; |
50 | unsigned char mirror; | 48 | unsigned char mirror; |
51 | unsigned char effect; | 49 | unsigned char effect; |
50 | |||
51 | __u8 sensor; | ||
52 | #define SENSOR_TAS5130A 0 | ||
53 | #define SENSOR_OTHER 1 | ||
52 | }; | 54 | }; |
53 | 55 | ||
54 | /* V4L2 controls supported by the driver */ | 56 | /* V4L2 controls supported by the driver */ |
@@ -83,9 +85,9 @@ static struct ctrl sd_ctrls[] = { | |||
83 | .type = V4L2_CTRL_TYPE_INTEGER, | 85 | .type = V4L2_CTRL_TYPE_INTEGER, |
84 | .name = "Brightness", | 86 | .name = "Brightness", |
85 | .minimum = 0, | 87 | .minimum = 0, |
86 | .maximum = 0x0f, | 88 | .maximum = 14, |
87 | .step = 1, | 89 | .step = 1, |
88 | .default_value = 0x09, | 90 | .default_value = 8, |
89 | }, | 91 | }, |
90 | .set = sd_setbrightness, | 92 | .set = sd_setbrightness, |
91 | .get = sd_getbrightness, | 93 | .get = sd_getbrightness, |
@@ -118,16 +120,17 @@ static struct ctrl sd_ctrls[] = { | |||
118 | .set = sd_setcolors, | 120 | .set = sd_setcolors, |
119 | .get = sd_getcolors, | 121 | .get = sd_getcolors, |
120 | }, | 122 | }, |
121 | #define SD_GAMMA 3 | 123 | #define GAMMA_MAX 16 |
124 | #define GAMMA_DEF 10 | ||
122 | { | 125 | { |
123 | { | 126 | { |
124 | .id = V4L2_CID_GAMMA, /* (gamma on win) */ | 127 | .id = V4L2_CID_GAMMA, /* (gamma on win) */ |
125 | .type = V4L2_CTRL_TYPE_INTEGER, | 128 | .type = V4L2_CTRL_TYPE_INTEGER, |
126 | .name = "Gamma (Untested)", | 129 | .name = "Gamma", |
127 | .minimum = 0, | 130 | .minimum = 0, |
128 | .maximum = MAX_GAMMA, | 131 | .maximum = GAMMA_MAX - 1, |
129 | .step = 1, | 132 | .step = 1, |
130 | .default_value = 0x09, | 133 | .default_value = GAMMA_DEF, |
131 | }, | 134 | }, |
132 | .set = sd_setgamma, | 135 | .set = sd_setgamma, |
133 | .get = sd_getgamma, | 136 | .get = sd_getgamma, |
@@ -197,7 +200,7 @@ static struct ctrl sd_ctrls[] = { | |||
197 | .type = V4L2_CTRL_TYPE_INTEGER, | 200 | .type = V4L2_CTRL_TYPE_INTEGER, |
198 | .name = "Sharpness", | 201 | .name = "Sharpness", |
199 | .minimum = 0, | 202 | .minimum = 0, |
200 | .maximum = MAX_GAMMA, /* 0 to 16 */ | 203 | .maximum = 15, |
201 | .step = 1, | 204 | .step = 1, |
202 | .default_value = 0x06, | 205 | .default_value = 0x06, |
203 | }, | 206 | }, |
@@ -258,7 +261,6 @@ static struct v4l2_pix_format vga_mode_t16[] = { | |||
258 | .priv = 0}, | 261 | .priv = 0}, |
259 | }; | 262 | }; |
260 | 263 | ||
261 | #define T16_OFFSET_DATA 631 | ||
262 | #define MAX_EFFECTS 7 | 264 | #define MAX_EFFECTS 7 |
263 | /* easily done by soft, this table could be removed, | 265 | /* easily done by soft, this table could be removed, |
264 | * i keep it here just in case */ | 266 | * i keep it here just in case */ |
@@ -272,87 +274,87 @@ static const __u8 effects_table[MAX_EFFECTS][6] = { | |||
272 | {0xa8, 0xc8, 0xc6, 0xd2, 0xc0, 0x40}, /* Negative */ | 274 | {0xa8, 0xc8, 0xc6, 0xd2, 0xc0, 0x40}, /* Negative */ |
273 | }; | 275 | }; |
274 | 276 | ||
275 | static const __u8 gamma_table[MAX_GAMMA][34] = { | 277 | static const __u8 gamma_table[GAMMA_MAX][34] = { |
276 | {0x90, 0x00, 0x91, 0x3e, 0x92, 0x69, 0x93, 0x85, | 278 | {0x90, 0x00, 0x91, 0x3e, 0x92, 0x69, 0x93, 0x85, /* 0 */ |
277 | 0x94, 0x95, 0x95, 0xa1, 0x96, 0xae, 0x97, 0xb9, | 279 | 0x94, 0x95, 0x95, 0xa1, 0x96, 0xae, 0x97, 0xb9, |
278 | 0x98, 0xc2, 0x99, 0xcb, 0x9a, 0xd4, 0x9b, 0xdb, | 280 | 0x98, 0xc2, 0x99, 0xcb, 0x9a, 0xd4, 0x9b, 0xdb, |
279 | 0x9c, 0xe3, 0x9d, 0xea, 0x9e, 0xf1, 0x9f, 0xf8, | 281 | 0x9c, 0xe3, 0x9d, 0xea, 0x9e, 0xf1, 0x9f, 0xf8, |
280 | 0xa0, 0xff}, | 282 | 0xa0, 0xff}, |
281 | {0x90, 0x00, 0x91, 0x33, 0x92, 0x5A, 0x93, 0x75, | 283 | {0x90, 0x00, 0x91, 0x33, 0x92, 0x5a, 0x93, 0x75, /* 1 */ |
282 | 0x94, 0x85, 0x95, 0x93, 0x96, 0xA1, 0x97, 0xAD, | 284 | 0x94, 0x85, 0x95, 0x93, 0x96, 0xa1, 0x97, 0xad, |
283 | 0x98, 0xB7, 0x99, 0xC2, 0x9A, 0xCB, 0x9B, 0xD4, | 285 | 0x98, 0xb7, 0x99, 0xc2, 0x9a, 0xcb, 0x9b, 0xd4, |
284 | 0x9C, 0xDE, 0x9D, 0xE7, 0x9E, 0xF0, 0x9F, 0xF7, | 286 | 0x9c, 0xde, 0x9D, 0xe7, 0x9e, 0xf0, 0x9f, 0xf7, |
285 | 0xa0, 0xff}, | 287 | 0xa0, 0xff}, |
286 | {0x90, 0x00, 0x91, 0x2F, 0x92, 0x51, 0x93, 0x6B, | 288 | {0x90, 0x00, 0x91, 0x2f, 0x92, 0x51, 0x93, 0x6b, /* 2 */ |
287 | 0x94, 0x7C, 0x95, 0x8A, 0x96, 0x99, 0x97, 0xA6, | 289 | 0x94, 0x7c, 0x95, 0x8a, 0x96, 0x99, 0x97, 0xa6, |
288 | 0x98, 0xB1, 0x99, 0xBC, 0x9A, 0xC6, 0x9B, 0xD0, | 290 | 0x98, 0xb1, 0x99, 0xbc, 0x9a, 0xc6, 0x9b, 0xd0, |
289 | 0x9C, 0xDB, 0x9D, 0xE4, 0x9E, 0xED, 0x9F, 0xF6, | 291 | 0x9c, 0xdb, 0x9d, 0xe4, 0x9e, 0xed, 0x9f, 0xf6, |
290 | 0xa0, 0xff}, | 292 | 0xa0, 0xff}, |
291 | {0x90, 0x00, 0x91, 0x29, 0x92, 0x48, 0x93, 0x60, | 293 | {0x90, 0x00, 0x91, 0x29, 0x92, 0x48, 0x93, 0x60, /* 3 */ |
292 | 0x94, 0x72, 0x95, 0x81, 0x96, 0x90, 0x97, 0x9E, | 294 | 0x94, 0x72, 0x95, 0x81, 0x96, 0x90, 0x97, 0x9e, |
293 | 0x98, 0xAA, 0x99, 0xB5, 0x9A, 0xBF, 0x9B, 0xCB, | 295 | 0x98, 0xaa, 0x99, 0xb5, 0x9a, 0xbf, 0x9b, 0xcb, |
294 | 0x9C, 0xD6, 0x9D, 0xE1, 0x9E, 0xEB, 0x9F, 0xF5, | 296 | 0x9c, 0xd6, 0x9d, 0xe1, 0x9e, 0xeb, 0x9f, 0xf5, |
295 | 0xa0, 0xff}, | 297 | 0xa0, 0xff}, |
296 | {0x90, 0x00, 0x91, 0x23, 0x92, 0x3F, 0x93, 0x55, | 298 | {0x90, 0x00, 0x91, 0x23, 0x92, 0x3f, 0x93, 0x55, /* 4 */ |
297 | 0x94, 0x68, 0x95, 0x77, 0x96, 0x86, 0x97, 0x95, | 299 | 0x94, 0x68, 0x95, 0x77, 0x96, 0x86, 0x97, 0x95, |
298 | 0x98, 0xA2, 0x99, 0xAD, 0x9A, 0xB9, 0x9B, 0xC6, | 300 | 0x98, 0xa2, 0x99, 0xad, 0x9a, 0xb9, 0x9b, 0xc6, |
299 | 0x9C, 0xD2, 0x9D, 0xDE, 0x9E, 0xE9, 0x9F, 0xF4, | 301 | 0x9c, 0xd2, 0x9d, 0xde, 0x9e, 0xe9, 0x9f, 0xf4, |
300 | 0xa0, 0xff}, | 302 | 0xa0, 0xff}, |
301 | {0x90, 0x00, 0x91, 0x1B, 0x92, 0x33, 0x93, 0x48, | 303 | {0x90, 0x00, 0x91, 0x1b, 0x92, 0x33, 0x93, 0x48, /* 5 */ |
302 | 0x94, 0x59, 0x95, 0x69, 0x96, 0x79, 0x97, 0x87, | 304 | 0x94, 0x59, 0x95, 0x69, 0x96, 0x79, 0x97, 0x87, |
303 | 0x98, 0x96, 0x99, 0xA3, 0x9A, 0xB1, 0x9B, 0xBE, | 305 | 0x98, 0x96, 0x99, 0xa3, 0x9a, 0xb1, 0x9b, 0xbe, |
304 | 0x9C, 0xCC, 0x9D, 0xDA, 0x9E, 0xE7, 0x9F, 0xF3, | 306 | 0x9c, 0xcc, 0x9d, 0xda, 0x9e, 0xe7, 0x9f, 0xf3, |
305 | 0xa0, 0xff}, | 307 | 0xa0, 0xff}, |
306 | {0x90, 0x00, 0x91, 0x02, 0x92, 0x10, 0x93, 0x20, | 308 | {0x90, 0x00, 0x91, 0x02, 0x92, 0x10, 0x93, 0x20, /* 6 */ |
307 | 0x94, 0x32, 0x95, 0x40, 0x96, 0x57, 0x97, 0x67, | 309 | 0x94, 0x32, 0x95, 0x40, 0x96, 0x57, 0x97, 0x67, |
308 | 0x98, 0x77, 0x99, 0x88, 0x9a, 0x99, 0x9b, 0xaa, | 310 | 0x98, 0x77, 0x99, 0x88, 0x9a, 0x99, 0x9b, 0xaa, |
309 | 0x9c, 0xbb, 0x9d, 0xcc, 0x9e, 0xdd, 0x9f, 0xee, | 311 | 0x9c, 0xbb, 0x9d, 0xcc, 0x9e, 0xdd, 0x9f, 0xee, |
310 | 0xa0, 0xff}, | 312 | 0xa0, 0xff}, |
311 | {0x90, 0x00, 0x91, 0x02, 0x92, 0x14, 0x93, 0x26, | 313 | {0x90, 0x00, 0x91, 0x02, 0x92, 0x14, 0x93, 0x26, /* 7 */ |
312 | 0x94, 0x38, 0x95, 0x4A, 0x96, 0x60, 0x97, 0x70, | 314 | 0x94, 0x38, 0x95, 0x4a, 0x96, 0x60, 0x97, 0x70, |
313 | 0x98, 0x80, 0x99, 0x90, 0x9A, 0xA0, 0x9B, 0xB0, | 315 | 0x98, 0x80, 0x99, 0x90, 0x9a, 0xa0, 0x9b, 0xb0, |
314 | 0x9C, 0xC0, 0x9D, 0xD0, 0x9E, 0xE0, 0x9F, 0xF0, | 316 | 0x9c, 0xc0, 0x9D, 0xd0, 0x9e, 0xe0, 0x9f, 0xf0, |
315 | 0xa0, 0xff}, | 317 | 0xa0, 0xff}, |
316 | {0x90, 0x00, 0x91, 0x10, 0x92, 0x22, 0x93, 0x35, | 318 | {0x90, 0x00, 0x91, 0x10, 0x92, 0x22, 0x93, 0x35, /* 8 */ |
317 | 0x94, 0x47, 0x95, 0x5A, 0x96, 0x69, 0x97, 0x79, | 319 | 0x94, 0x47, 0x95, 0x5a, 0x96, 0x69, 0x97, 0x79, |
318 | 0x98, 0x88, 0x99, 0x97, 0x9A, 0xA7, 0x9B, 0xB6, | 320 | 0x98, 0x88, 0x99, 0x97, 0x9a, 0xa7, 0x9b, 0xb6, |
319 | 0x9C, 0xC4, 0x9D, 0xD3, 0x9E, 0xE0, 0x9F, 0xF0, | 321 | 0x9c, 0xc4, 0x9d, 0xd3, 0x9e, 0xe0, 0x9f, 0xf0, |
320 | 0xa0, 0xff}, | 322 | 0xa0, 0xff}, |
321 | {0x90, 0x00, 0x91, 0x10, 0x92, 0x26, 0x93, 0x40, | 323 | {0x90, 0x00, 0x91, 0x10, 0x92, 0x26, 0x93, 0x40, /* 9 */ |
322 | 0x94, 0x54, 0x95, 0x65, 0x96, 0x75, 0x97, 0x84, | 324 | 0x94, 0x54, 0x95, 0x65, 0x96, 0x75, 0x97, 0x84, |
323 | 0x98, 0x93, 0x99, 0xa1, 0x9a, 0xb0, 0x9b, 0xbd, | 325 | 0x98, 0x93, 0x99, 0xa1, 0x9a, 0xb0, 0x9b, 0xbd, |
324 | 0x9c, 0xca, 0x9d, 0xd6, 0x9e, 0xe0, 0x9f, 0xf0, | 326 | 0x9c, 0xca, 0x9d, 0xd6, 0x9e, 0xe0, 0x9f, 0xf0, |
325 | 0xa0, 0xff}, | 327 | 0xa0, 0xff}, |
326 | {0x90, 0x00, 0x91, 0x18, 0x92, 0x2B, 0x93, 0x44, | 328 | {0x90, 0x00, 0x91, 0x18, 0x92, 0x2b, 0x93, 0x44, /* 10 */ |
327 | 0x94, 0x60, 0x95, 0x70, 0x96, 0x80, 0x97, 0x8E, | 329 | 0x94, 0x60, 0x95, 0x70, 0x96, 0x80, 0x97, 0x8e, |
328 | 0x98, 0x9C, 0x99, 0xAA, 0x9A, 0xB7, 0x9B, 0xC4, | 330 | 0x98, 0x9c, 0x99, 0xaa, 0x9a, 0xb7, 0x9b, 0xc4, |
329 | 0x9C, 0xD0, 0x9D, 0xD8, 0x9E, 0xE2, 0x9F, 0xF0, | 331 | 0x9c, 0xd0, 0x9d, 0xd8, 0x9e, 0xe2, 0x9f, 0xf0, |
330 | 0xa0, 0xff}, | 332 | 0xa0, 0xff}, |
331 | {0x90, 0x00, 0x91, 0x1A, 0x92, 0x34, 0x93, 0x52, | 333 | {0x90, 0x00, 0x91, 0x1a, 0x92, 0x34, 0x93, 0x52, /* 11 */ |
332 | 0x94, 0x66, 0x95, 0x7E, 0x96, 0x8D, 0x97, 0x9B, | 334 | 0x94, 0x66, 0x95, 0x7e, 0x96, 0x8D, 0x97, 0x9B, |
333 | 0x98, 0xA8, 0x99, 0xB4, 0x9A, 0xC0, 0x9B, 0xCB, | 335 | 0x98, 0xa8, 0x99, 0xb4, 0x9a, 0xc0, 0x9b, 0xcb, |
334 | 0x9C, 0xD6, 0x9D, 0xE1, 0x9E, 0xEB, 0x9F, 0xF5, | 336 | 0x9c, 0xd6, 0x9d, 0xe1, 0x9e, 0xeb, 0x9f, 0xf5, |
335 | 0xa0, 0xff}, | 337 | 0xa0, 0xff}, |
336 | {0x90, 0x00, 0x91, 0x3F, 0x92, 0x5A, 0x93, 0x6E, | 338 | {0x90, 0x00, 0x91, 0x3f, 0x92, 0x5a, 0x93, 0x6e, /* 12 */ |
337 | 0x94, 0x7F, 0x95, 0x8E, 0x96, 0x9C, 0x97, 0xA8, | 339 | 0x94, 0x7f, 0x95, 0x8e, 0x96, 0x9c, 0x97, 0xa8, |
338 | 0x98, 0xB4, 0x99, 0xBF, 0x9A, 0xC9, 0x9B, 0xD3, | 340 | 0x98, 0xb4, 0x99, 0xbf, 0x9a, 0xc9, 0x9b, 0xd3, |
339 | 0x9C, 0xDC, 0x9D, 0xE5, 0x9E, 0xEE, 0x9F, 0xF6, | 341 | 0x9c, 0xdc, 0x9d, 0xe5, 0x9e, 0xee, 0x9f, 0xf6, |
340 | 0xA0, 0xFF}, | ||
341 | {0x90, 0x00, 0x91, 0x54, 0x92, 0x6F, 0x93, 0x83, | ||
342 | 0x94, 0x93, 0x95, 0xA0, 0x96, 0xAD, 0x97, 0xB7, | ||
343 | 0x98, 0xC2, 0x99, 0xCB, 0x9A, 0xD4, 0x9B, 0xDC, | ||
344 | 0x9C, 0xE4, 0x9D, 0xEB, 0x9E, 0xF2, 0x9F, 0xF9, | ||
345 | 0xa0, 0xff}, | 342 | 0xa0, 0xff}, |
346 | {0x90, 0x00, 0x91, 0x6E, 0x92, 0x88, 0x93, 0x9A, | 343 | {0x90, 0x00, 0x91, 0x54, 0x92, 0x6f, 0x93, 0x83, /* 13 */ |
347 | 0x94, 0xA8, 0x95, 0xB3, 0x96, 0xBD, 0x97, 0xC6, | 344 | 0x94, 0x93, 0x95, 0xa0, 0x96, 0xad, 0x97, 0xb7, |
348 | 0x98, 0xCF, 0x99, 0xD6, 0x9A, 0xDD, 0x9B, 0xE3, | 345 | 0x98, 0xc2, 0x99, 0xcb, 0x9a, 0xd4, 0x9b, 0xdc, |
349 | 0x9C, 0xE9, 0x9D, 0xEF, 0x9E, 0xF4, 0x9F, 0xFA, | 346 | 0x9c, 0xe4, 0x9d, 0xeb, 0x9e, 0xf2, 0x9f, 0xf9, |
350 | 0xa0, 0xff}, | 347 | 0xa0, 0xff}, |
351 | {0x90, 0x00, 0x91, 0x93, 0x92, 0xA8, 0x93, 0xB7, | 348 | {0x90, 0x00, 0x91, 0x6e, 0x92, 0x88, 0x93, 0x9a, /* 14 */ |
352 | 0x94, 0xC1, 0x95, 0xCA, 0x96, 0xD2, 0x97, 0xD8, | 349 | 0x94, 0xa8, 0x95, 0xb3, 0x96, 0xbd, 0x97, 0xc6, |
353 | 0x98, 0xDE, 0x99, 0xE3, 0x9A, 0xE8, 0x9B, 0xED, | 350 | 0x98, 0xcf, 0x99, 0xd6, 0x9a, 0xdd, 0x9b, 0xe3, |
354 | 0x9C, 0xF1, 0x9D, 0xF5, 0x9E, 0xF8, 0x9F, 0xFC, | 351 | 0x9c, 0xe9, 0x9d, 0xef, 0x9e, 0xf4, 0x9f, 0xfa, |
355 | 0xA0, 0xFF} | 352 | 0xa0, 0xff}, |
353 | {0x90, 0x00, 0x91, 0x93, 0x92, 0xa8, 0x93, 0xb7, /* 15 */ | ||
354 | 0x94, 0xc1, 0x95, 0xca, 0x96, 0xd2, 0x97, 0xd8, | ||
355 | 0x98, 0xde, 0x99, 0xe3, 0x9a, 0xe8, 0x9b, 0xed, | ||
356 | 0x9c, 0xf1, 0x9d, 0xf5, 0x9e, 0xf8, 0x9f, 0xfc, | ||
357 | 0xa0, 0xff} | ||
356 | }; | 358 | }; |
357 | 359 | ||
358 | static const __u8 tas5130a_sensor_init[][8] = { | 360 | static const __u8 tas5130a_sensor_init[][8] = { |
@@ -364,7 +366,7 @@ static const __u8 tas5130a_sensor_init[][8] = { | |||
364 | }; | 366 | }; |
365 | 367 | ||
366 | /* read 1 byte */ | 368 | /* read 1 byte */ |
367 | static int reg_r_1(struct gspca_dev *gspca_dev, | 369 | static int reg_r(struct gspca_dev *gspca_dev, |
368 | __u16 index) | 370 | __u16 index) |
369 | { | 371 | { |
370 | usb_control_msg(gspca_dev->dev, | 372 | usb_control_msg(gspca_dev->dev, |
@@ -378,26 +380,26 @@ static int reg_r_1(struct gspca_dev *gspca_dev, | |||
378 | } | 380 | } |
379 | 381 | ||
380 | static void reg_w(struct gspca_dev *gspca_dev, | 382 | static void reg_w(struct gspca_dev *gspca_dev, |
381 | __u16 value, | 383 | __u16 index) |
382 | __u16 index, | 384 | { |
383 | const __u8 *buffer, __u16 len) | 385 | usb_control_msg(gspca_dev->dev, |
386 | usb_sndctrlpipe(gspca_dev->dev, 0), | ||
387 | 0, | ||
388 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, | ||
389 | 0, index, | ||
390 | NULL, 0, 500); | ||
391 | } | ||
392 | |||
393 | static void i2c_w(struct gspca_dev *gspca_dev, | ||
394 | const __u8 *buffer, __u16 len) | ||
384 | { | 395 | { |
385 | if (buffer == NULL) { | ||
386 | usb_control_msg(gspca_dev->dev, | ||
387 | usb_sndctrlpipe(gspca_dev->dev, 0), | ||
388 | 0, | ||
389 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, | ||
390 | value, index, | ||
391 | NULL, 0, 500); | ||
392 | return; | ||
393 | } | ||
394 | if (len <= USB_BUF_SZ) { | 396 | if (len <= USB_BUF_SZ) { |
395 | memcpy(gspca_dev->usb_buf, buffer, len); | 397 | memcpy(gspca_dev->usb_buf, buffer, len); |
396 | usb_control_msg(gspca_dev->dev, | 398 | usb_control_msg(gspca_dev->dev, |
397 | usb_sndctrlpipe(gspca_dev->dev, 0), | 399 | usb_sndctrlpipe(gspca_dev->dev, 0), |
398 | 0, | 400 | 0, |
399 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, | 401 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, |
400 | value, index, | 402 | 0x01, 0, |
401 | gspca_dev->usb_buf, len, 500); | 403 | gspca_dev->usb_buf, len, 500); |
402 | } else { | 404 | } else { |
403 | __u8 *tmpbuf; | 405 | __u8 *tmpbuf; |
@@ -408,12 +410,56 @@ static void reg_w(struct gspca_dev *gspca_dev, | |||
408 | usb_sndctrlpipe(gspca_dev->dev, 0), | 410 | usb_sndctrlpipe(gspca_dev->dev, 0), |
409 | 0, | 411 | 0, |
410 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, | 412 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, |
411 | value, index, | 413 | 0x01, 0, |
412 | tmpbuf, len, 500); | 414 | tmpbuf, len, 500); |
413 | kfree(tmpbuf); | 415 | kfree(tmpbuf); |
414 | } | 416 | } |
415 | } | 417 | } |
416 | 418 | ||
419 | static void other_sensor_init(struct gspca_dev *gspca_dev) | ||
420 | { | ||
421 | int i; | ||
422 | const __u8 *p; | ||
423 | __u8 byte; | ||
424 | __u8 val[6] = {0x62, 0, 0x64, 0, 0x60, 0x05}; | ||
425 | static const __u8 sensor_init[] = { | ||
426 | 0xdf, 0x6d, | ||
427 | 0xdd, 0x18, | ||
428 | 0x5a, 0xe0, | ||
429 | 0x5c, 0x07, | ||
430 | 0x5d, 0xb0, | ||
431 | 0x5e, 0x1e, | ||
432 | 0x60, 0x71, | ||
433 | 0xef, 0x00, | ||
434 | 0xe9, 0x00, | ||
435 | 0xea, 0x00, | ||
436 | 0x90, 0x24, | ||
437 | 0x91, 0xb2, | ||
438 | 0x82, 0x32, | ||
439 | 0xfd, 0x00, | ||
440 | 0xfd, 0x01, | ||
441 | 0xfd, 0x41, | ||
442 | 0x00 /* table end */ | ||
443 | }; | ||
444 | |||
445 | p = sensor_init; | ||
446 | while (*p != 0) { | ||
447 | val[1] = *p++; | ||
448 | val[3] = *p++; | ||
449 | if (*p == 0) | ||
450 | reg_w(gspca_dev, 0x3c80); | ||
451 | i2c_w(gspca_dev, val, sizeof val); | ||
452 | i = 4; | ||
453 | while (--i >= 0) { | ||
454 | msleep(15); | ||
455 | byte = reg_r(gspca_dev, 0x60); | ||
456 | if (!(byte & 0x01)) | ||
457 | break; | ||
458 | } | ||
459 | } | ||
460 | reg_w(gspca_dev, 0x3c80); | ||
461 | } | ||
462 | |||
417 | /* this function is called at probe time */ | 463 | /* this function is called at probe time */ |
418 | static int sd_config(struct gspca_dev *gspca_dev, | 464 | static int sd_config(struct gspca_dev *gspca_dev, |
419 | const struct usb_device_id *id) | 465 | const struct usb_device_id *id) |
@@ -430,7 +476,7 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
430 | sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value; | 476 | sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value; |
431 | sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value; | 477 | sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value; |
432 | sd->colors = sd_ctrls[SD_COLOR].qctrl.default_value; | 478 | sd->colors = sd_ctrls[SD_COLOR].qctrl.default_value; |
433 | sd->gamma = sd_ctrls[SD_GAMMA].qctrl.default_value; | 479 | sd->gamma = GAMMA_DEF; |
434 | sd->mirror = sd_ctrls[SD_MIRROR].qctrl.default_value; | 480 | sd->mirror = sd_ctrls[SD_MIRROR].qctrl.default_value; |
435 | sd->freq = sd_ctrls[SD_LIGHTFREQ].qctrl.default_value; | 481 | sd->freq = sd_ctrls[SD_LIGHTFREQ].qctrl.default_value; |
436 | sd->whitebalance = sd_ctrls[SD_WHITE_BALANCE].qctrl.default_value; | 482 | sd->whitebalance = sd_ctrls[SD_WHITE_BALANCE].qctrl.default_value; |
@@ -439,27 +485,37 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
439 | return 0; | 485 | return 0; |
440 | } | 486 | } |
441 | 487 | ||
442 | static int init_default_parameters(struct gspca_dev *gspca_dev) | 488 | static void setgamma(struct gspca_dev *gspca_dev) |
489 | { | ||
490 | struct sd *sd = (struct sd *) gspca_dev; | ||
491 | |||
492 | PDEBUG(D_CONF, "Gamma: %d", sd->gamma); | ||
493 | i2c_w(gspca_dev, gamma_table[sd->gamma], sizeof gamma_table[0]); | ||
494 | } | ||
495 | |||
496 | /* this function is called at probe and resume time */ | ||
497 | static int sd_init(struct gspca_dev *gspca_dev) | ||
443 | { | 498 | { |
444 | /* some of this registers are not really neded, because | 499 | /* some of this registers are not really neded, because |
445 | * they are overriden by setbrigthness, setcontrast, etc, | 500 | * they are overriden by setbrigthness, setcontrast, etc, |
446 | * but wont hurt anyway, and can help someone with similar webcam | 501 | * but wont hurt anyway, and can help someone with similar webcam |
447 | * to see the initial parameters.*/ | 502 | * to see the initial parameters.*/ |
448 | int i = 0; | 503 | struct sd *sd = (struct sd *) gspca_dev; |
449 | __u8 test_byte; | 504 | int i; |
505 | __u8 byte, test_byte; | ||
450 | 506 | ||
451 | static const __u8 read_indexs[] = | 507 | static const __u8 read_indexs[] = |
452 | { 0x06, 0x07, 0x0a, 0x0b, 0x66, 0x80, 0x81, 0x8e, 0x8f, 0xa5, | 508 | { 0x06, 0x07, 0x0a, 0x0b, 0x66, 0x80, 0x81, 0x8e, 0x8f, 0xa5, |
453 | 0xa6, 0xa8, 0xbb, 0xbc, 0xc6, 0x00, 0x00 }; | 509 | 0xa6, 0xa8, 0xbb, 0xbc, 0xc6, 0x00, 0x00 }; |
454 | static const __u8 n1[6] = | 510 | static const __u8 n1[] = |
455 | {0x08, 0x03, 0x09, 0x03, 0x12, 0x04}; | 511 | {0x08, 0x03, 0x09, 0x03, 0x12, 0x04}; |
456 | static const __u8 n2[2] = | 512 | static const __u8 n2[] = |
457 | {0x08, 0x00}; | 513 | {0x08, 0x00}; |
458 | static const __u8 nset[6] = | 514 | static const __u8 nset[] = |
459 | { 0x61, 0x68, 0x62, 0xff, 0x60, 0x07 }; | 515 | { 0x61, 0x68, 0x62, 0xff, 0x60, 0x07 }; |
460 | static const __u8 n3[6] = | 516 | static const __u8 n3[] = |
461 | {0x61, 0x68, 0x65, 0x0a, 0x60, 0x04}; | 517 | {0x61, 0x68, 0x65, 0x0a, 0x60, 0x04}; |
462 | static const __u8 n4[0x46] = | 518 | static const __u8 n4[] = |
463 | {0x09, 0x01, 0x12, 0x04, 0x66, 0x8a, 0x80, 0x3c, | 519 | {0x09, 0x01, 0x12, 0x04, 0x66, 0x8a, 0x80, 0x3c, |
464 | 0x81, 0x22, 0x84, 0x50, 0x8a, 0x78, 0x8b, 0x68, | 520 | 0x81, 0x22, 0x84, 0x50, 0x8a, 0x78, 0x8b, 0x68, |
465 | 0x8c, 0x88, 0x8e, 0x33, 0x8f, 0x24, 0xaa, 0xb1, | 521 | 0x8c, 0x88, 0x8e, 0x33, 0x8f, 0x24, 0xaa, 0xb1, |
@@ -469,33 +525,26 @@ static int init_default_parameters(struct gspca_dev *gspca_dev) | |||
469 | 0x65, 0x0a, 0xbb, 0x86, 0xaf, 0x58, 0xb0, 0x68, | 525 | 0x65, 0x0a, 0xbb, 0x86, 0xaf, 0x58, 0xb0, 0x68, |
470 | 0x87, 0x40, 0x89, 0x2b, 0x8d, 0xff, 0x83, 0x40, | 526 | 0x87, 0x40, 0x89, 0x2b, 0x8d, 0xff, 0x83, 0x40, |
471 | 0xac, 0x84, 0xad, 0x86, 0xaf, 0x46}; | 527 | 0xac, 0x84, 0xad, 0x86, 0xaf, 0x46}; |
472 | static const __u8 nset4[18] = { | 528 | static const __u8 nset4[] = { |
473 | 0xe0, 0x60, 0xe1, 0xa8, 0xe2, 0xe0, 0xe3, 0x60, 0xe4, 0xa8, | 529 | 0xe0, 0x60, 0xe1, 0xa8, 0xe2, 0xe0, 0xe3, 0x60, 0xe4, 0xa8, |
474 | 0xe5, 0xe0, 0xe6, 0x60, 0xe7, 0xa8, | 530 | 0xe5, 0xe0, 0xe6, 0x60, 0xe7, 0xa8, |
475 | 0xe8, 0xe0 | 531 | 0xe8, 0xe0 |
476 | }; | 532 | }; |
477 | /* ojo puede ser 0xe6 en vez de 0xe9 */ | 533 | /* ojo puede ser 0xe6 en vez de 0xe9 */ |
478 | static const __u8 nset2[20] = { | 534 | static const __u8 nset2[] = { |
479 | 0xd0, 0xbb, 0xd1, 0x28, 0xd2, 0x10, 0xd3, 0x10, 0xd4, 0xbb, | 535 | 0xd0, 0xbb, 0xd1, 0x28, 0xd2, 0x10, 0xd3, 0x10, 0xd4, 0xbb, |
480 | 0xd5, 0x28, 0xd6, 0x1e, 0xd7, 0x27, | 536 | 0xd5, 0x28, 0xd6, 0x1e, 0xd7, 0x27, |
481 | 0xd8, 0xc8, 0xd9, 0xfc | 537 | 0xd8, 0xc8, 0xd9, 0xfc |
482 | }; | 538 | }; |
483 | static const __u8 missing[8] = | 539 | static const __u8 missing[] = |
484 | { 0x87, 0x20, 0x88, 0x20, 0x89, 0x20, 0x80, 0x38 }; | 540 | { 0x87, 0x20, 0x88, 0x20, 0x89, 0x20, 0x80, 0x38 }; |
485 | static const __u8 nset3[18] = { | 541 | static const __u8 nset3[] = { |
486 | 0xc7, 0x60, 0xc8, 0xa8, 0xc9, 0xe0, 0xca, 0x60, 0xcb, 0xa8, | 542 | 0xc7, 0x60, 0xc8, 0xa8, 0xc9, 0xe0, 0xca, 0x60, 0xcb, 0xa8, |
487 | 0xcc, 0xe0, 0xcd, 0x60, 0xce, 0xa8, | 543 | 0xcc, 0xe0, 0xcd, 0x60, 0xce, 0xa8, |
488 | 0xcf, 0xe0 | 544 | 0xcf, 0xe0 |
489 | }; | 545 | }; |
490 | static const __u8 nset5[4] = | 546 | static const __u8 nset5[] = |
491 | { 0x8f, 0x24, 0xc3, 0x00 }; /* bright */ | 547 | { 0x8f, 0x24, 0xc3, 0x00 }; /* bright */ |
492 | static const __u8 nset6[34] = { | ||
493 | 0x90, 0x00, 0x91, 0x1c, 0x92, 0x30, 0x93, 0x43, 0x94, 0x54, | ||
494 | 0x95, 0x65, 0x96, 0x75, 0x97, 0x84, | ||
495 | 0x98, 0x93, 0x99, 0xa1, 0x9a, 0xb0, 0x9b, 0xbd, 0x9c, 0xca, | ||
496 | 0x9d, 0xd8, 0x9e, 0xe5, 0x9f, 0xf2, | ||
497 | 0xa0, 0xff | ||
498 | }; /* Gamma */ | ||
499 | static const __u8 nset7[4] = | 548 | static const __u8 nset7[4] = |
500 | { 0x66, 0xca, 0xa8, 0xf8 }; /* 50/60 Hz */ | 549 | { 0x66, 0xca, 0xa8, 0xf8 }; /* 50/60 Hz */ |
501 | static const __u8 nset9[4] = | 550 | static const __u8 nset9[4] = |
@@ -505,95 +554,111 @@ static int init_default_parameters(struct gspca_dev *gspca_dev) | |||
505 | static const __u8 nset10[6] = | 554 | static const __u8 nset10[6] = |
506 | { 0x0c, 0x03, 0xab, 0x10, 0x81, 0x20 }; | 555 | { 0x0c, 0x03, 0xab, 0x10, 0x81, 0x20 }; |
507 | 556 | ||
508 | reg_w(gspca_dev, 0x01, 0x0000, n1, 0x06); | 557 | byte = reg_r(gspca_dev, 0x06); |
509 | reg_w(gspca_dev, 0x01, 0x0000, nset, 0x06); | 558 | test_byte = reg_r(gspca_dev, 0x07); |
510 | reg_r_1(gspca_dev, 0x0063); | 559 | if (byte == 0x08 && test_byte == 0x07) { |
511 | reg_w(gspca_dev, 0x01, 0x0000, n2, 0x02); | 560 | PDEBUG(D_CONF, "other sensor"); |
561 | sd->sensor = SENSOR_OTHER; | ||
562 | } else { | ||
563 | PDEBUG(D_CONF, "sensor %02x %02x", byte, test_byte); | ||
564 | sd->sensor = SENSOR_TAS5130A; | ||
565 | } | ||
566 | |||
567 | i2c_w(gspca_dev, n1, sizeof n1); | ||
568 | test_byte = 0; | ||
569 | i = 5; | ||
570 | while (--i >= 0) { | ||
571 | i2c_w(gspca_dev, nset, sizeof nset); | ||
572 | msleep(5); | ||
573 | test_byte = reg_r(gspca_dev, 0x0063); | ||
574 | msleep(100); | ||
575 | if (test_byte == 0x17) | ||
576 | break; /* OK */ | ||
577 | } | ||
578 | if (i < 0) { | ||
579 | err("Bad sensor reset %02x", test_byte); | ||
580 | /* return -EIO; */ | ||
581 | /*fixme: test - continue */ | ||
582 | } | ||
583 | i2c_w(gspca_dev, n2, sizeof n2); | ||
512 | 584 | ||
585 | i = 0; | ||
513 | while (read_indexs[i] != 0x00) { | 586 | while (read_indexs[i] != 0x00) { |
514 | test_byte = reg_r_1(gspca_dev, read_indexs[i]); | 587 | test_byte = reg_r(gspca_dev, read_indexs[i]); |
515 | PDEBUG(D_CONF, "Reg 0x%02x => 0x%02x", read_indexs[i], | 588 | PDEBUG(D_STREAM, "Reg 0x%02x = 0x%02x", read_indexs[i], |
516 | test_byte); | 589 | test_byte); |
517 | i++; | 590 | i++; |
518 | } | 591 | } |
519 | 592 | ||
520 | reg_w(gspca_dev, 0x01, 0x0000, n3, 0x06); | 593 | i2c_w(gspca_dev, n3, sizeof n3); |
521 | reg_w(gspca_dev, 0x01, 0x0000, n4, 0x46); | 594 | i2c_w(gspca_dev, n4, sizeof n4); |
522 | reg_r_1(gspca_dev, 0x0080); | 595 | reg_r(gspca_dev, 0x0080); |
523 | reg_w(gspca_dev, 0x00, 0x2c80, NULL, 0); | 596 | reg_w(gspca_dev, 0x2c80); |
524 | reg_w(gspca_dev, 0x01, 0x0000, nset2, 0x14); | 597 | i2c_w(gspca_dev, nset2, sizeof nset2); |
525 | reg_w(gspca_dev, 0x01, 0x0000, nset3, 0x12); | 598 | i2c_w(gspca_dev, nset3, sizeof nset3); |
526 | reg_w(gspca_dev, 0x01, 0x0000, nset4, 0x12); | 599 | i2c_w(gspca_dev, nset4, sizeof nset4); |
527 | reg_w(gspca_dev, 0x00, 0x3880, NULL, 0); | 600 | reg_w(gspca_dev, 0x3880); |
528 | reg_w(gspca_dev, 0x00, 0x3880, NULL, 0); | 601 | reg_w(gspca_dev, 0x3880); |
529 | reg_w(gspca_dev, 0x00, 0x338e, NULL, 0); | 602 | reg_w(gspca_dev, 0x338e); |
530 | reg_w(gspca_dev, 0x01, 0x0000, nset5, 0x04); | 603 | i2c_w(gspca_dev, nset5, sizeof nset5); |
531 | reg_w(gspca_dev, 0x00, 0x00a9, NULL, 0); | 604 | reg_w(gspca_dev, 0x00a9); |
532 | reg_w(gspca_dev, 0x01, 0x0000, nset6, 0x22); | 605 | setgamma(gspca_dev); |
533 | reg_w(gspca_dev, 0x00, 0x86bb, NULL, 0); | 606 | reg_w(gspca_dev, 0x86bb); |
534 | reg_w(gspca_dev, 0x00, 0x4aa6, NULL, 0); | 607 | reg_w(gspca_dev, 0x4aa6); |
535 | 608 | ||
536 | reg_w(gspca_dev, 0x01, 0x0000, missing, 0x08); | 609 | i2c_w(gspca_dev, missing, sizeof missing); |
537 | 610 | ||
538 | reg_w(gspca_dev, 0x00, 0x2087, NULL, 0); | 611 | reg_w(gspca_dev, 0x2087); |
539 | reg_w(gspca_dev, 0x00, 0x2088, NULL, 0); | 612 | reg_w(gspca_dev, 0x2088); |
540 | reg_w(gspca_dev, 0x00, 0x2089, NULL, 0); | 613 | reg_w(gspca_dev, 0x2089); |
541 | 614 | ||
542 | reg_w(gspca_dev, 0x01, 0x0000, nset7, 0x04); | 615 | i2c_w(gspca_dev, nset7, sizeof nset7); |
543 | reg_w(gspca_dev, 0x01, 0x0000, nset10, 0x06); | 616 | i2c_w(gspca_dev, nset10, sizeof nset10); |
544 | reg_w(gspca_dev, 0x01, 0x0000, nset8, 0x06); | 617 | i2c_w(gspca_dev, nset8, sizeof nset8); |
545 | reg_w(gspca_dev, 0x01, 0x0000, nset9, 0x04); | 618 | i2c_w(gspca_dev, nset9, sizeof nset9); |
546 | 619 | ||
547 | reg_w(gspca_dev, 0x00, 0x2880, NULL, 0); | 620 | reg_w(gspca_dev, 0x2880); |
548 | reg_w(gspca_dev, 0x01, 0x0000, nset2, 0x14); | 621 | i2c_w(gspca_dev, nset2, sizeof nset2); |
549 | reg_w(gspca_dev, 0x01, 0x0000, nset3, 0x12); | 622 | i2c_w(gspca_dev, nset3, sizeof nset3); |
550 | reg_w(gspca_dev, 0x01, 0x0000, nset4, 0x12); | 623 | i2c_w(gspca_dev, nset4, sizeof nset4); |
551 | 624 | ||
552 | return 0; | 625 | return 0; |
553 | } | 626 | } |
554 | 627 | ||
555 | /* this function is called at probe and resume time */ | ||
556 | static int sd_init(struct gspca_dev *gspca_dev) | ||
557 | { | ||
558 | init_default_parameters(gspca_dev); | ||
559 | return 0; | ||
560 | } | ||
561 | |||
562 | static void setbrightness(struct gspca_dev *gspca_dev) | 628 | static void setbrightness(struct gspca_dev *gspca_dev) |
563 | { | 629 | { |
564 | struct sd *sd = (struct sd *) gspca_dev; | 630 | struct sd *sd = (struct sd *) gspca_dev; |
565 | unsigned int brightness; | 631 | unsigned int brightness; |
566 | __u8 set6[4] = { 0x8f, 0x26, 0xc3, 0x80 }; | 632 | __u8 set6[4] = { 0x8f, 0x26, 0xc3, 0x00 }; |
567 | brightness = sd->brightness; | ||
568 | 633 | ||
634 | brightness = sd->brightness; | ||
569 | if (brightness < 7) { | 635 | if (brightness < 7) { |
570 | set6[3] = 0x70 - (brightness * 0xa); | 636 | set6[3] = 0x70 - brightness * 0x10; |
571 | } else { | 637 | } else { |
572 | set6[1] = 0x24; | 638 | set6[1] = 0x24; |
573 | set6[3] = 0x00 + ((brightness - 7) * 0xa); | 639 | set6[3] = 0x00 + ((brightness - 7) * 0x10); |
574 | } | 640 | } |
575 | 641 | ||
576 | reg_w(gspca_dev, 0x01, 0x0000, set6, 4); | 642 | i2c_w(gspca_dev, set6, sizeof set6); |
577 | } | 643 | } |
578 | 644 | ||
579 | static void setflip(struct gspca_dev *gspca_dev) | 645 | static void setflip(struct gspca_dev *gspca_dev) |
580 | { | 646 | { |
581 | struct sd *sd = (struct sd *) gspca_dev; | 647 | struct sd *sd = (struct sd *) gspca_dev; |
582 | |||
583 | __u8 flipcmd[8] = | 648 | __u8 flipcmd[8] = |
584 | { 0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09 }; | 649 | {0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09}; |
585 | 650 | ||
586 | if (sd->mirror == 1) | 651 | if (sd->mirror) |
587 | flipcmd[3] = 0x01; | 652 | flipcmd[3] = 0x01; |
588 | 653 | ||
589 | reg_w(gspca_dev, 0x01, 0x0000, flipcmd, 8); | 654 | i2c_w(gspca_dev, flipcmd, sizeof flipcmd); |
590 | } | 655 | } |
591 | 656 | ||
592 | static void seteffect(struct gspca_dev *gspca_dev) | 657 | static void seteffect(struct gspca_dev *gspca_dev) |
593 | { | 658 | { |
594 | struct sd *sd = (struct sd *) gspca_dev; | 659 | struct sd *sd = (struct sd *) gspca_dev; |
595 | 660 | ||
596 | reg_w(gspca_dev, 0x01, 0x0000, effects_table[sd->effect], 0x06); | 661 | i2c_w(gspca_dev, effects_table[sd->effect], sizeof effects_table[0]); |
597 | if (sd->effect == 1 || sd->effect == 5) { | 662 | if (sd->effect == 1 || sd->effect == 5) { |
598 | PDEBUG(D_CONF, | 663 | PDEBUG(D_CONF, |
599 | "This effect have been disabled for webcam \"safety\""); | 664 | "This effect have been disabled for webcam \"safety\""); |
@@ -601,9 +666,9 @@ static void seteffect(struct gspca_dev *gspca_dev) | |||
601 | } | 666 | } |
602 | 667 | ||
603 | if (sd->effect == 1 || sd->effect == 4) | 668 | if (sd->effect == 1 || sd->effect == 4) |
604 | reg_w(gspca_dev, 0x00, 0x4aa6, NULL, 0); | 669 | reg_w(gspca_dev, 0x4aa6); |
605 | else | 670 | else |
606 | reg_w(gspca_dev, 0x00, 0xfaa6, NULL, 0); | 671 | reg_w(gspca_dev, 0xfaa6); |
607 | } | 672 | } |
608 | 673 | ||
609 | static void setwhitebalance(struct gspca_dev *gspca_dev) | 674 | static void setwhitebalance(struct gspca_dev *gspca_dev) |
@@ -616,7 +681,7 @@ static void setwhitebalance(struct gspca_dev *gspca_dev) | |||
616 | if (sd->whitebalance == 1) | 681 | if (sd->whitebalance == 1) |
617 | white_balance[7] = 0x3c; | 682 | white_balance[7] = 0x3c; |
618 | 683 | ||
619 | reg_w(gspca_dev, 0x01, 0x0000, white_balance, 8); | 684 | i2c_w(gspca_dev, white_balance, sizeof white_balance); |
620 | } | 685 | } |
621 | 686 | ||
622 | static void setlightfreq(struct gspca_dev *gspca_dev) | 687 | static void setlightfreq(struct gspca_dev *gspca_dev) |
@@ -627,21 +692,21 @@ static void setlightfreq(struct gspca_dev *gspca_dev) | |||
627 | if (sd->freq == 2) /* 60hz */ | 692 | if (sd->freq == 2) /* 60hz */ |
628 | freq[1] = 0x00; | 693 | freq[1] = 0x00; |
629 | 694 | ||
630 | reg_w(gspca_dev, 0x1, 0x0000, freq, 0x4); | 695 | i2c_w(gspca_dev, freq, sizeof freq); |
631 | } | 696 | } |
632 | 697 | ||
633 | static void setcontrast(struct gspca_dev *gspca_dev) | 698 | static void setcontrast(struct gspca_dev *gspca_dev) |
634 | { | 699 | { |
635 | struct sd *sd = (struct sd *) gspca_dev; | 700 | struct sd *sd = (struct sd *) gspca_dev; |
636 | unsigned int contrast = sd->contrast; | 701 | unsigned int contrast = sd->contrast; |
637 | __u16 reg_to_write = 0x00; | 702 | __u16 reg_to_write; |
638 | 703 | ||
639 | if (contrast < 7) | 704 | if (contrast < 7) |
640 | reg_to_write = 0x8ea9 - (0x200 * contrast); | 705 | reg_to_write = 0x8ea9 - (0x200 * contrast); |
641 | else | 706 | else |
642 | reg_to_write = (0x00a9 + ((contrast - 7) * 0x200)); | 707 | reg_to_write = (0x00a9 + ((contrast - 7) * 0x200)); |
643 | 708 | ||
644 | reg_w(gspca_dev, 0x00, reg_to_write, NULL, 0); | 709 | reg_w(gspca_dev, reg_to_write); |
645 | } | 710 | } |
646 | 711 | ||
647 | static void setcolors(struct gspca_dev *gspca_dev) | 712 | static void setcolors(struct gspca_dev *gspca_dev) |
@@ -650,11 +715,7 @@ static void setcolors(struct gspca_dev *gspca_dev) | |||
650 | __u16 reg_to_write; | 715 | __u16 reg_to_write; |
651 | 716 | ||
652 | reg_to_write = 0xc0bb + sd->colors * 0x100; | 717 | reg_to_write = 0xc0bb + sd->colors * 0x100; |
653 | reg_w(gspca_dev, 0x00, reg_to_write, NULL, 0); | 718 | reg_w(gspca_dev, reg_to_write); |
654 | } | ||
655 | |||
656 | static void setgamma(struct gspca_dev *gspca_dev) | ||
657 | { | ||
658 | } | 719 | } |
659 | 720 | ||
660 | static void setsharpness(struct gspca_dev *gspca_dev) | 721 | static void setsharpness(struct gspca_dev *gspca_dev) |
@@ -664,7 +725,99 @@ static void setsharpness(struct gspca_dev *gspca_dev) | |||
664 | 725 | ||
665 | reg_to_write = 0x0aa6 + 0x1000 * sd->sharpness; | 726 | reg_to_write = 0x0aa6 + 0x1000 * sd->sharpness; |
666 | 727 | ||
667 | reg_w(gspca_dev, 0x00, reg_to_write, NULL, 0); | 728 | reg_w(gspca_dev, reg_to_write); |
729 | } | ||
730 | |||
731 | static int sd_start(struct gspca_dev *gspca_dev) | ||
732 | { | ||
733 | struct sd *sd = (struct sd *) gspca_dev; | ||
734 | int i, mode; | ||
735 | static const __u8 t1[] = { 0x66, 0x00, 0xa8, 0xe8 }; | ||
736 | __u8 t2[] = { 0x07, 0x00, 0x0d, 0x60, 0x0e, 0x80 }; | ||
737 | static const __u8 t3[] = | ||
738 | { 0xb3, 0x07, 0xb4, 0x00, 0xb5, 0x88, 0xb6, 0x02, 0xb7, 0x06, | ||
739 | 0xb8, 0x00, 0xb9, 0xe7, 0xba, 0x01 }; | ||
740 | static const __u8 t4[] = { 0x0b, 0x04, 0x0a, 0x40 }; | ||
741 | |||
742 | mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode]. priv; | ||
743 | switch (mode) { | ||
744 | case 1: /* 352x288 */ | ||
745 | t2[1] = 0x40; | ||
746 | break; | ||
747 | case 2: /* 320x240 */ | ||
748 | t2[1] = 0x10; | ||
749 | break; | ||
750 | case 3: /* 176x144 */ | ||
751 | t2[1] = 0x50; | ||
752 | break; | ||
753 | case 4: /* 160x120 */ | ||
754 | t2[1] = 0x20; | ||
755 | break; | ||
756 | default: /* 640x480 (0x00) */ | ||
757 | break; | ||
758 | } | ||
759 | |||
760 | if (sd->sensor == SENSOR_TAS5130A) { | ||
761 | i = 0; | ||
762 | while (tas5130a_sensor_init[i][0] != 0) { | ||
763 | i2c_w(gspca_dev, tas5130a_sensor_init[i], | ||
764 | sizeof tas5130a_sensor_init[0]); | ||
765 | i++; | ||
766 | } | ||
767 | reg_w(gspca_dev, 0x3c80); | ||
768 | /* just in case and to keep sync with logs (for mine) */ | ||
769 | i2c_w(gspca_dev, tas5130a_sensor_init[3], | ||
770 | sizeof tas5130a_sensor_init[0]); | ||
771 | reg_w(gspca_dev, 0x3c80); | ||
772 | } else { | ||
773 | other_sensor_init(gspca_dev); | ||
774 | } | ||
775 | /* just in case and to keep sync with logs (for mine) */ | ||
776 | i2c_w(gspca_dev, t1, sizeof t1); | ||
777 | i2c_w(gspca_dev, t2, sizeof t2); | ||
778 | reg_r(gspca_dev, 0x0012); | ||
779 | i2c_w(gspca_dev, t3, sizeof t3); | ||
780 | reg_w(gspca_dev, 0x0013); | ||
781 | i2c_w(gspca_dev, t4, sizeof t4); | ||
782 | /* restart on each start, just in case, sometimes regs goes wrong | ||
783 | * when using controls from app */ | ||
784 | setbrightness(gspca_dev); | ||
785 | setcontrast(gspca_dev); | ||
786 | setcolors(gspca_dev); | ||
787 | return 0; | ||
788 | } | ||
789 | |||
790 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, | ||
791 | struct gspca_frame *frame, /* target */ | ||
792 | __u8 *data, /* isoc packet */ | ||
793 | int len) /* iso packet length */ | ||
794 | { | ||
795 | static __u8 ffd9[] = { 0xff, 0xd9 }; | ||
796 | |||
797 | if (data[0] == 0x5a) { | ||
798 | /* Control Packet, after this came the header again, | ||
799 | * but extra bytes came in the packet before this, | ||
800 | * sometimes an EOF arrives, sometimes not... */ | ||
801 | return; | ||
802 | } | ||
803 | data += 2; | ||
804 | len -= 2; | ||
805 | if (data[0] == 0xff && data[1] == 0xd8) { | ||
806 | /* extra bytes....., could be processed too but would be | ||
807 | * a waste of time, right now leave the application and | ||
808 | * libjpeg do it for ourserlves.. */ | ||
809 | frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, | ||
810 | ffd9, 2); | ||
811 | gspca_frame_add(gspca_dev, FIRST_PACKET, frame, data, len); | ||
812 | return; | ||
813 | } | ||
814 | |||
815 | if (data[len - 2] == 0xff && data[len - 1] == 0xd9) { | ||
816 | /* Just in case, i have seen packets with the marker, | ||
817 | * other's do not include it... */ | ||
818 | len -= 2; | ||
819 | } | ||
820 | gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len); | ||
668 | } | 821 | } |
669 | 822 | ||
670 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) | 823 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) |
@@ -788,6 +941,7 @@ static int sd_setgamma(struct gspca_dev *gspca_dev, __s32 val) | |||
788 | static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val) | 941 | static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val) |
789 | { | 942 | { |
790 | struct sd *sd = (struct sd *) gspca_dev; | 943 | struct sd *sd = (struct sd *) gspca_dev; |
944 | |||
791 | *val = sd->gamma; | 945 | *val = sd->gamma; |
792 | return 0; | 946 | return 0; |
793 | } | 947 | } |
@@ -835,9 +989,9 @@ static int sd_setlowlight(struct gspca_dev *gspca_dev, __s32 val) | |||
835 | 989 | ||
836 | sd->autogain = val; | 990 | sd->autogain = val; |
837 | if (val != 0) | 991 | if (val != 0) |
838 | reg_w(gspca_dev, 0x00, 0xf48e, NULL, 0); | 992 | reg_w(gspca_dev, 0xf48e); |
839 | else | 993 | else |
840 | reg_w(gspca_dev, 0x00, 0xb48e, NULL, 0); | 994 | reg_w(gspca_dev, 0xb48e); |
841 | return 0; | 995 | return 0; |
842 | } | 996 | } |
843 | 997 | ||
@@ -849,99 +1003,6 @@ static int sd_getlowlight(struct gspca_dev *gspca_dev, __s32 *val) | |||
849 | return 0; | 1003 | return 0; |
850 | } | 1004 | } |
851 | 1005 | ||
852 | static void sd_start(struct gspca_dev *gspca_dev) | ||
853 | { | ||
854 | int mode; | ||
855 | |||
856 | static const __u8 t1[] = { 0x66, 0x00, 0xa8, 0xe8 }; | ||
857 | __u8 t2[] = { 0x07, 0x00, 0x0d, 0x60, 0x0e, 0x80 }; | ||
858 | static const __u8 t3[] = | ||
859 | { 0xb3, 0x07, 0xb4, 0x00, 0xb5, 0x88, 0xb6, 0x02, 0xb7, 0x06, | ||
860 | 0xb8, 0x00, 0xb9, 0xe7, 0xba, 0x01 }; | ||
861 | static const __u8 t4[] = { 0x0b, 0x04, 0x0a, 0x40 }; | ||
862 | |||
863 | mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode]. priv; | ||
864 | switch (mode) { | ||
865 | case 1: /* 352x288 */ | ||
866 | t2[1] = 0x40; | ||
867 | break; | ||
868 | case 2: /* 320x240 */ | ||
869 | t2[1] = 0x10; | ||
870 | break; | ||
871 | case 3: /* 176x144 */ | ||
872 | t2[1] = 0x50; | ||
873 | break; | ||
874 | case 4: /* 160x120 */ | ||
875 | t2[1] = 0x20; | ||
876 | break; | ||
877 | default: /* 640x480 (0x00) */ | ||
878 | break; | ||
879 | } | ||
880 | |||
881 | reg_w(gspca_dev, 0x01, 0x0000, tas5130a_sensor_init[0], 0x8); | ||
882 | reg_w(gspca_dev, 0x01, 0x0000, tas5130a_sensor_init[1], 0x8); | ||
883 | reg_w(gspca_dev, 0x01, 0x0000, tas5130a_sensor_init[2], 0x8); | ||
884 | reg_w(gspca_dev, 0x01, 0x0000, tas5130a_sensor_init[3], 0x8); | ||
885 | reg_w(gspca_dev, 0x00, 0x3c80, NULL, 0); | ||
886 | /* just in case and to keep sync with logs (for mine) */ | ||
887 | reg_w(gspca_dev, 0x01, 0x0000, tas5130a_sensor_init[3], 0x8); | ||
888 | reg_w(gspca_dev, 0x00, 0x3c80, NULL, 0); | ||
889 | /* just in case and to keep sync with logs (for mine) */ | ||
890 | reg_w(gspca_dev, 0x01, 0x0000, t1, 4); | ||
891 | reg_w(gspca_dev, 0x01, 0x0000, t2, 6); | ||
892 | reg_r_1(gspca_dev, 0x0012); | ||
893 | reg_w(gspca_dev, 0x01, 0x0000, t3, 0x10); | ||
894 | reg_w(gspca_dev, 0x00, 0x0013, NULL, 0); | ||
895 | reg_w(gspca_dev, 0x01, 0x0000, t4, 0x4); | ||
896 | /* restart on each start, just in case, sometimes regs goes wrong | ||
897 | * when using controls from app */ | ||
898 | setbrightness(gspca_dev); | ||
899 | setcontrast(gspca_dev); | ||
900 | setcolors(gspca_dev); | ||
901 | } | ||
902 | |||
903 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, | ||
904 | struct gspca_frame *frame, /* target */ | ||
905 | __u8 *data, /* isoc packet */ | ||
906 | int len) /* iso packet length */ | ||
907 | { | ||
908 | int sof = 0; | ||
909 | static __u8 ffd9[] = { 0xff, 0xd9 }; | ||
910 | |||
911 | if (data[0] == 0x5a) { | ||
912 | /* Control Packet, after this came the header again, | ||
913 | * but extra bytes came in the packet before this, | ||
914 | * sometimes an EOF arrives, sometimes not... */ | ||
915 | return; | ||
916 | } | ||
917 | |||
918 | if (data[len - 1] == 0xff && data[len] == 0xd9) { | ||
919 | /* Just in case, i have seen packets with the marker, | ||
920 | * other's do not include it... */ | ||
921 | data += 2; | ||
922 | len -= 4; | ||
923 | } else if (data[2] == 0xff && data[3] == 0xd8) { | ||
924 | sof = 1; | ||
925 | data += 2; | ||
926 | len -= 2; | ||
927 | } else { | ||
928 | data += 2; | ||
929 | len -= 2; | ||
930 | } | ||
931 | |||
932 | if (sof) { | ||
933 | /* extra bytes....., could be processed too but would be | ||
934 | * a waste of time, right now leave the application and | ||
935 | * libjpeg do it for ourserlves.. */ | ||
936 | frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, | ||
937 | ffd9, 2); | ||
938 | gspca_frame_add(gspca_dev, FIRST_PACKET, frame, data, len); | ||
939 | return; | ||
940 | } | ||
941 | |||
942 | gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len); | ||
943 | } | ||
944 | |||
945 | static int sd_querymenu(struct gspca_dev *gspca_dev, | 1006 | static int sd_querymenu(struct gspca_dev *gspca_dev, |
946 | struct v4l2_querymenu *menu) | 1007 | struct v4l2_querymenu *menu) |
947 | { | 1008 | { |
diff --git a/drivers/media/video/gspca/tv8532.c b/drivers/media/video/gspca/tv8532.c index 084af05302a0..968a5911704f 100644 --- a/drivers/media/video/gspca/tv8532.c +++ b/drivers/media/video/gspca/tv8532.c | |||
@@ -390,7 +390,7 @@ static void setbrightness(struct gspca_dev *gspca_dev) | |||
390 | } | 390 | } |
391 | 391 | ||
392 | /* -- start the camera -- */ | 392 | /* -- start the camera -- */ |
393 | static void sd_start(struct gspca_dev *gspca_dev) | 393 | static int sd_start(struct gspca_dev *gspca_dev) |
394 | { | 394 | { |
395 | reg_w_1(gspca_dev, TV8532_AD_SLOPE, 0x32); | 395 | reg_w_1(gspca_dev, TV8532_AD_SLOPE, 0x32); |
396 | reg_w_1(gspca_dev, TV8532_AD_BITCTRL, 0x00); | 396 | reg_w_1(gspca_dev, TV8532_AD_BITCTRL, 0x00); |
@@ -443,6 +443,7 @@ static void sd_start(struct gspca_dev *gspca_dev) | |||
443 | /************************************************/ | 443 | /************************************************/ |
444 | tv_8532_PollReg(gspca_dev); | 444 | tv_8532_PollReg(gspca_dev); |
445 | reg_w_1(gspca_dev, TV8532_UDP_UPDATE, 0x00); /* 0x31 */ | 445 | reg_w_1(gspca_dev, TV8532_UDP_UPDATE, 0x00); /* 0x31 */ |
446 | return 0; | ||
446 | } | 447 | } |
447 | 448 | ||
448 | static void sd_stopN(struct gspca_dev *gspca_dev) | 449 | static void sd_stopN(struct gspca_dev *gspca_dev) |
diff --git a/drivers/media/video/gspca/vc032x.c b/drivers/media/video/gspca/vc032x.c index bd4c226c9a07..be46d9232540 100644 --- a/drivers/media/video/gspca/vc032x.c +++ b/drivers/media/video/gspca/vc032x.c | |||
@@ -80,7 +80,6 @@ static struct ctrl sd_ctrls[] = { | |||
80 | .step = 1, | 80 | .step = 1, |
81 | #define FREQ_DEF 1 | 81 | #define FREQ_DEF 1 |
82 | .default_value = FREQ_DEF, | 82 | .default_value = FREQ_DEF, |
83 | .default_value = 1, | ||
84 | }, | 83 | }, |
85 | .set = sd_setfreq, | 84 | .set = sd_setfreq, |
86 | .get = sd_getfreq, | 85 | .get = sd_getfreq, |
@@ -1502,7 +1501,7 @@ static void setlightfreq(struct gspca_dev *gspca_dev) | |||
1502 | usb_exchange(gspca_dev, ov7660_freq_tb[sd->lightfreq]); | 1501 | usb_exchange(gspca_dev, ov7660_freq_tb[sd->lightfreq]); |
1503 | } | 1502 | } |
1504 | 1503 | ||
1505 | static void sd_start(struct gspca_dev *gspca_dev) | 1504 | static int sd_start(struct gspca_dev *gspca_dev) |
1506 | { | 1505 | { |
1507 | struct sd *sd = (struct sd *) gspca_dev; | 1506 | struct sd *sd = (struct sd *) gspca_dev; |
1508 | const __u8 *GammaT = NULL; | 1507 | const __u8 *GammaT = NULL; |
@@ -1586,7 +1585,7 @@ static void sd_start(struct gspca_dev *gspca_dev) | |||
1586 | break; | 1585 | break; |
1587 | default: | 1586 | default: |
1588 | PDEBUG(D_PROBE, "Damned !! no sensor found Bye"); | 1587 | PDEBUG(D_PROBE, "Damned !! no sensor found Bye"); |
1589 | return; | 1588 | return -EMEDIUMTYPE; |
1590 | } | 1589 | } |
1591 | if (GammaT && MatrixT) { | 1590 | if (GammaT && MatrixT) { |
1592 | put_tab_to_reg(gspca_dev, GammaT, 17, 0xb84a); | 1591 | put_tab_to_reg(gspca_dev, GammaT, 17, 0xb84a); |
@@ -1622,6 +1621,7 @@ static void sd_start(struct gspca_dev *gspca_dev) | |||
1622 | setautogain(gspca_dev); | 1621 | setautogain(gspca_dev); |
1623 | setlightfreq(gspca_dev); | 1622 | setlightfreq(gspca_dev); |
1624 | } | 1623 | } |
1624 | return 0; | ||
1625 | } | 1625 | } |
1626 | 1626 | ||
1627 | static void sd_stopN(struct gspca_dev *gspca_dev) | 1627 | static void sd_stopN(struct gspca_dev *gspca_dev) |
diff --git a/drivers/media/video/gspca/zc3xx.c b/drivers/media/video/gspca/zc3xx.c index d61ef727e0c2..d0a4451dc46f 100644 --- a/drivers/media/video/gspca/zc3xx.c +++ b/drivers/media/video/gspca/zc3xx.c | |||
@@ -7178,7 +7178,7 @@ static int sd_init(struct gspca_dev *gspca_dev) | |||
7178 | return 0; | 7178 | return 0; |
7179 | } | 7179 | } |
7180 | 7180 | ||
7181 | static void sd_start(struct gspca_dev *gspca_dev) | 7181 | static int sd_start(struct gspca_dev *gspca_dev) |
7182 | { | 7182 | { |
7183 | struct sd *sd = (struct sd *) gspca_dev; | 7183 | struct sd *sd = (struct sd *) gspca_dev; |
7184 | struct usb_device *dev = gspca_dev->dev; | 7184 | struct usb_device *dev = gspca_dev->dev; |
@@ -7331,6 +7331,7 @@ static void sd_start(struct gspca_dev *gspca_dev) | |||
7331 | reg_w(dev, 0x02, 0x0008); | 7331 | reg_w(dev, 0x02, 0x0008); |
7332 | break; | 7332 | break; |
7333 | } | 7333 | } |
7334 | return 0; | ||
7334 | } | 7335 | } |
7335 | 7336 | ||
7336 | static void sd_stop0(struct gspca_dev *gspca_dev) | 7337 | static void sd_stop0(struct gspca_dev *gspca_dev) |
diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c index a30254bed311..efe849981ab7 100644 --- a/drivers/media/video/ir-kbd-i2c.c +++ b/drivers/media/video/ir-kbd-i2c.c | |||
@@ -12,6 +12,10 @@ | |||
12 | * Markus Rechberger <mrechberger@gmail.com> | 12 | * Markus Rechberger <mrechberger@gmail.com> |
13 | * modified for DViCO Fusion HDTV 5 RT GOLD by | 13 | * modified for DViCO Fusion HDTV 5 RT GOLD by |
14 | * Chaogui Zhang <czhang1974@gmail.com> | 14 | * Chaogui Zhang <czhang1974@gmail.com> |
15 | * modified for MSI TV@nywhere Plus by | ||
16 | * Henry Wong <henry@stuffedcow.net> | ||
17 | * Mark Schultz <n9xmj@yahoo.com> | ||
18 | * Brian Rogers <brian_rogers@comcast.net> | ||
15 | * | 19 | * |
16 | * This program is free software; you can redistribute it and/or modify | 20 | * This program is free software; you can redistribute it and/or modify |
17 | * it under the terms of the GNU General Public License as published by | 21 | * it under the terms of the GNU General Public License as published by |
@@ -65,7 +69,7 @@ static int get_key_haup_common(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw, | |||
65 | int size, int offset) | 69 | int size, int offset) |
66 | { | 70 | { |
67 | unsigned char buf[6]; | 71 | unsigned char buf[6]; |
68 | int start, range, toggle, dev, code; | 72 | int start, range, toggle, dev, code, ircode; |
69 | 73 | ||
70 | /* poll IR chip */ | 74 | /* poll IR chip */ |
71 | if (size != i2c_master_recv(&ir->c,buf,size)) | 75 | if (size != i2c_master_recv(&ir->c,buf,size)) |
@@ -85,6 +89,24 @@ static int get_key_haup_common(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw, | |||
85 | if (!start) | 89 | if (!start) |
86 | /* no key pressed */ | 90 | /* no key pressed */ |
87 | return 0; | 91 | return 0; |
92 | /* | ||
93 | * Hauppauge remotes (black/silver) always use | ||
94 | * specific device ids. If we do not filter the | ||
95 | * device ids then messages destined for devices | ||
96 | * such as TVs (id=0) will get through causing | ||
97 | * mis-fired events. | ||
98 | * | ||
99 | * We also filter out invalid key presses which | ||
100 | * produce annoying debug log entries. | ||
101 | */ | ||
102 | ircode= (start << 12) | (toggle << 11) | (dev << 6) | code; | ||
103 | if ((ircode & 0x1fff)==0x1fff) | ||
104 | /* invalid key press */ | ||
105 | return 0; | ||
106 | |||
107 | if (dev!=0x1e && dev!=0x1f) | ||
108 | /* not a hauppauge remote */ | ||
109 | return 0; | ||
88 | 110 | ||
89 | if (!range) | 111 | if (!range) |
90 | code += 64; | 112 | code += 64; |
@@ -94,7 +116,7 @@ static int get_key_haup_common(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw, | |||
94 | 116 | ||
95 | /* return key */ | 117 | /* return key */ |
96 | *ir_key = code; | 118 | *ir_key = code; |
97 | *ir_raw = (start << 12) | (toggle << 11) | (dev << 6) | code; | 119 | *ir_raw = ircode; |
98 | return 1; | 120 | return 1; |
99 | } | 121 | } |
100 | 122 | ||
@@ -224,9 +246,15 @@ static void ir_timer(unsigned long data) | |||
224 | static void ir_work(struct work_struct *work) | 246 | static void ir_work(struct work_struct *work) |
225 | { | 247 | { |
226 | struct IR_i2c *ir = container_of(work, struct IR_i2c, work); | 248 | struct IR_i2c *ir = container_of(work, struct IR_i2c, work); |
249 | int polling_interval = 100; | ||
250 | |||
251 | /* MSI TV@nywhere Plus requires more frequent polling | ||
252 | otherwise it will miss some keypresses */ | ||
253 | if (ir->c.adapter->id == I2C_HW_SAA7134 && ir->c.addr == 0x30) | ||
254 | polling_interval = 50; | ||
227 | 255 | ||
228 | ir_key_poll(ir); | 256 | ir_key_poll(ir); |
229 | mod_timer(&ir->timer, jiffies + msecs_to_jiffies(100)); | 257 | mod_timer(&ir->timer, jiffies + msecs_to_jiffies(polling_interval)); |
230 | } | 258 | } |
231 | 259 | ||
232 | /* ----------------------------------------------------------------------- */ | 260 | /* ----------------------------------------------------------------------- */ |
@@ -465,9 +493,37 @@ static int ir_probe(struct i2c_adapter *adap) | |||
465 | (1 == rc) ? "yes" : "no"); | 493 | (1 == rc) ? "yes" : "no"); |
466 | if (1 == rc) { | 494 | if (1 == rc) { |
467 | ir_attach(adap, probe[i], 0, 0); | 495 | ir_attach(adap, probe[i], 0, 0); |
468 | break; | 496 | return 0; |
469 | } | 497 | } |
470 | } | 498 | } |
499 | |||
500 | /* Special case for MSI TV@nywhere Plus remote */ | ||
501 | if (adap->id == I2C_HW_SAA7134) { | ||
502 | u8 temp; | ||
503 | |||
504 | /* MSI TV@nywhere Plus controller doesn't seem to | ||
505 | respond to probes unless we read something from | ||
506 | an existing device. Weird... */ | ||
507 | |||
508 | msg.addr = 0x50; | ||
509 | rc = i2c_transfer(adap, &msg, 1); | ||
510 | dprintk(1, "probe 0x%02x @ %s: %s\n", | ||
511 | msg.addr, adap->name, | ||
512 | (1 == rc) ? "yes" : "no"); | ||
513 | |||
514 | /* Now do the probe. The controller does not respond | ||
515 | to 0-byte reads, so we use a 1-byte read instead. */ | ||
516 | msg.addr = 0x30; | ||
517 | msg.len = 1; | ||
518 | msg.buf = &temp; | ||
519 | rc = i2c_transfer(adap, &msg, 1); | ||
520 | dprintk(1, "probe 0x%02x @ %s: %s\n", | ||
521 | msg.addr, adap->name, | ||
522 | (1 == rc) ? "yes" : "no"); | ||
523 | if (1 == rc) | ||
524 | ir_attach(adap, msg.addr, 0, 0); | ||
525 | } | ||
526 | |||
471 | return 0; | 527 | return 0; |
472 | } | 528 | } |
473 | 529 | ||
diff --git a/drivers/media/video/ivtv/ivtv-cards.h b/drivers/media/video/ivtv/ivtv-cards.h index 381af1bceef8..0b8fe85fb697 100644 --- a/drivers/media/video/ivtv/ivtv-cards.h +++ b/drivers/media/video/ivtv/ivtv-cards.h | |||
@@ -154,7 +154,7 @@ | |||
154 | #define IVTV_CAP_ENCODER (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_TUNER | \ | 154 | #define IVTV_CAP_ENCODER (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_TUNER | \ |
155 | V4L2_CAP_AUDIO | V4L2_CAP_READWRITE | V4L2_CAP_VBI_CAPTURE | \ | 155 | V4L2_CAP_AUDIO | V4L2_CAP_READWRITE | V4L2_CAP_VBI_CAPTURE | \ |
156 | V4L2_CAP_SLICED_VBI_CAPTURE) | 156 | V4L2_CAP_SLICED_VBI_CAPTURE) |
157 | #define IVTV_CAP_DECODER (V4L2_CAP_VBI_OUTPUT | V4L2_CAP_VIDEO_OUTPUT | \ | 157 | #define IVTV_CAP_DECODER (V4L2_CAP_VIDEO_OUTPUT | \ |
158 | V4L2_CAP_SLICED_VBI_OUTPUT | V4L2_CAP_VIDEO_OUTPUT_OVERLAY) | 158 | V4L2_CAP_SLICED_VBI_OUTPUT | V4L2_CAP_VIDEO_OUTPUT_OVERLAY) |
159 | 159 | ||
160 | struct ivtv_card_video_input { | 160 | struct ivtv_card_video_input { |
diff --git a/drivers/media/video/ivtv/ivtv-driver.c b/drivers/media/video/ivtv/ivtv-driver.c index 4afc7ea07e86..aeaa13f6cb36 100644 --- a/drivers/media/video/ivtv/ivtv-driver.c +++ b/drivers/media/video/ivtv/ivtv-driver.c | |||
@@ -61,14 +61,14 @@ | |||
61 | #include "tuner-xc2028.h" | 61 | #include "tuner-xc2028.h" |
62 | 62 | ||
63 | /* var to keep track of the number of array elements in use */ | 63 | /* var to keep track of the number of array elements in use */ |
64 | int ivtv_cards_active = 0; | 64 | int ivtv_cards_active; |
65 | 65 | ||
66 | /* If you have already X v4l cards, then set this to X. This way | 66 | /* If you have already X v4l cards, then set this to X. This way |
67 | the device numbers stay matched. Example: you have a WinTV card | 67 | the device numbers stay matched. Example: you have a WinTV card |
68 | without radio and a PVR-350 with. Normally this would give a | 68 | without radio and a PVR-350 with. Normally this would give a |
69 | video1 device together with a radio0 device for the PVR. By | 69 | video1 device together with a radio0 device for the PVR. By |
70 | setting this to 1 you ensure that radio0 is now also radio1. */ | 70 | setting this to 1 you ensure that radio0 is now also radio1. */ |
71 | int ivtv_first_minor = 0; | 71 | int ivtv_first_minor; |
72 | 72 | ||
73 | /* Master variable for all ivtv info */ | 73 | /* Master variable for all ivtv info */ |
74 | struct ivtv *ivtv_cards[IVTV_MAX_CARDS]; | 74 | struct ivtv *ivtv_cards[IVTV_MAX_CARDS]; |
@@ -251,7 +251,7 @@ MODULE_PARM_DESC(newi2c, | |||
251 | "\t\t\t-1 is autodetect, 0 is off, 1 is on\n" | 251 | "\t\t\t-1 is autodetect, 0 is off, 1 is on\n" |
252 | "\t\t\tDefault is autodetect"); | 252 | "\t\t\tDefault is autodetect"); |
253 | 253 | ||
254 | MODULE_PARM_DESC(ivtv_first_minor, "Set minor assigned to first card"); | 254 | MODULE_PARM_DESC(ivtv_first_minor, "Set kernel number assigned to first card"); |
255 | 255 | ||
256 | MODULE_AUTHOR("Kevin Thayer, Chris Kennedy, Hans Verkuil"); | 256 | MODULE_AUTHOR("Kevin Thayer, Chris Kennedy, Hans Verkuil"); |
257 | MODULE_DESCRIPTION("CX23415/CX23416 driver"); | 257 | MODULE_DESCRIPTION("CX23415/CX23416 driver"); |
@@ -655,9 +655,9 @@ done: | |||
655 | 655 | ||
656 | if (itv->card == NULL) { | 656 | if (itv->card == NULL) { |
657 | itv->card = ivtv_get_card(IVTV_CARD_PVR_150); | 657 | itv->card = ivtv_get_card(IVTV_CARD_PVR_150); |
658 | IVTV_ERR("Unknown card: vendor/device: %04x/%04x\n", | 658 | IVTV_ERR("Unknown card: vendor/device: [%04x:%04x]\n", |
659 | itv->dev->vendor, itv->dev->device); | 659 | itv->dev->vendor, itv->dev->device); |
660 | IVTV_ERR(" subsystem vendor/device: %04x/%04x\n", | 660 | IVTV_ERR(" subsystem vendor/device: [%04x:%04x]\n", |
661 | itv->dev->subsystem_vendor, itv->dev->subsystem_device); | 661 | itv->dev->subsystem_vendor, itv->dev->subsystem_device); |
662 | IVTV_ERR(" %s based\n", chipname); | 662 | IVTV_ERR(" %s based\n", chipname); |
663 | IVTV_ERR("Defaulting to %s card\n", itv->card->name); | 663 | IVTV_ERR("Defaulting to %s card\n", itv->card->name); |
@@ -720,7 +720,7 @@ static int __devinit ivtv_init_struct1(struct ivtv *itv) | |||
720 | itv->speed = 1000; | 720 | itv->speed = 1000; |
721 | 721 | ||
722 | /* VBI */ | 722 | /* VBI */ |
723 | itv->vbi.in.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE; | 723 | itv->vbi.in.type = V4L2_BUF_TYPE_VBI_CAPTURE; |
724 | itv->vbi.sliced_in = &itv->vbi.in.fmt.sliced; | 724 | itv->vbi.sliced_in = &itv->vbi.in.fmt.sliced; |
725 | 725 | ||
726 | /* Init the sg table for osd/yuv output */ | 726 | /* Init the sg table for osd/yuv output */ |
diff --git a/drivers/media/video/ivtv/ivtv-driver.h b/drivers/media/video/ivtv/ivtv-driver.h index 2ceb5227637c..bc29436e8a3c 100644 --- a/drivers/media/video/ivtv/ivtv-driver.h +++ b/drivers/media/video/ivtv/ivtv-driver.h | |||
@@ -49,7 +49,6 @@ | |||
49 | #include <linux/i2c-algo-bit.h> | 49 | #include <linux/i2c-algo-bit.h> |
50 | #include <linux/list.h> | 50 | #include <linux/list.h> |
51 | #include <linux/unistd.h> | 51 | #include <linux/unistd.h> |
52 | #include <linux/byteorder/swab.h> | ||
53 | #include <linux/pagemap.h> | 52 | #include <linux/pagemap.h> |
54 | #include <linux/scatterlist.h> | 53 | #include <linux/scatterlist.h> |
55 | #include <linux/workqueue.h> | 54 | #include <linux/workqueue.h> |
@@ -507,6 +506,8 @@ struct yuv_playback_info | |||
507 | struct v4l2_rect main_rect; | 506 | struct v4l2_rect main_rect; |
508 | u32 v4l2_src_w; | 507 | u32 v4l2_src_w; |
509 | u32 v4l2_src_h; | 508 | u32 v4l2_src_h; |
509 | |||
510 | u8 running; /* Have any frames been displayed */ | ||
510 | }; | 511 | }; |
511 | 512 | ||
512 | #define IVTV_VBI_FRAMES 32 | 513 | #define IVTV_VBI_FRAMES 32 |
@@ -751,6 +752,12 @@ void ivtv_read_eeprom(struct ivtv *itv, struct tveeprom *tv); | |||
751 | /* First-open initialization: load firmware, init cx25840, etc. */ | 752 | /* First-open initialization: load firmware, init cx25840, etc. */ |
752 | int ivtv_init_on_first_open(struct ivtv *itv); | 753 | int ivtv_init_on_first_open(struct ivtv *itv); |
753 | 754 | ||
755 | /* Test if the current VBI mode is raw (1) or sliced (0) */ | ||
756 | static inline int ivtv_raw_vbi(const struct ivtv *itv) | ||
757 | { | ||
758 | return itv->vbi.in.type == V4L2_BUF_TYPE_VBI_CAPTURE; | ||
759 | } | ||
760 | |||
754 | /* This is a PCI post thing, where if the pci register is not read, then | 761 | /* This is a PCI post thing, where if the pci register is not read, then |
755 | the write doesn't always take effect right away. By reading back the | 762 | the write doesn't always take effect right away. By reading back the |
756 | register any pending PCI writes will be performed (in order), and so | 763 | register any pending PCI writes will be performed (in order), and so |
diff --git a/drivers/media/video/ivtv/ivtv-fileops.c b/drivers/media/video/ivtv/ivtv-fileops.c index 7ec5c99f9ad1..b7457fc60ba5 100644 --- a/drivers/media/video/ivtv/ivtv-fileops.c +++ b/drivers/media/video/ivtv/ivtv-fileops.c | |||
@@ -39,7 +39,7 @@ | |||
39 | associated VBI streams are also automatically claimed. | 39 | associated VBI streams are also automatically claimed. |
40 | Possible error returns: -EBUSY if someone else has claimed | 40 | Possible error returns: -EBUSY if someone else has claimed |
41 | the stream or 0 on success. */ | 41 | the stream or 0 on success. */ |
42 | int ivtv_claim_stream(struct ivtv_open_id *id, int type) | 42 | static int ivtv_claim_stream(struct ivtv_open_id *id, int type) |
43 | { | 43 | { |
44 | struct ivtv *itv = id->itv; | 44 | struct ivtv *itv = id->itv; |
45 | struct ivtv_stream *s = &itv->streams[type]; | 45 | struct ivtv_stream *s = &itv->streams[type]; |
@@ -78,7 +78,7 @@ int ivtv_claim_stream(struct ivtv_open_id *id, int type) | |||
78 | if (type == IVTV_DEC_STREAM_TYPE_MPG) { | 78 | if (type == IVTV_DEC_STREAM_TYPE_MPG) { |
79 | vbi_type = IVTV_DEC_STREAM_TYPE_VBI; | 79 | vbi_type = IVTV_DEC_STREAM_TYPE_VBI; |
80 | } else if (type == IVTV_ENC_STREAM_TYPE_MPG && | 80 | } else if (type == IVTV_ENC_STREAM_TYPE_MPG && |
81 | itv->vbi.insert_mpeg && itv->vbi.sliced_in->service_set) { | 81 | itv->vbi.insert_mpeg && !ivtv_raw_vbi(itv)) { |
82 | vbi_type = IVTV_ENC_STREAM_TYPE_VBI; | 82 | vbi_type = IVTV_ENC_STREAM_TYPE_VBI; |
83 | } else { | 83 | } else { |
84 | return 0; | 84 | return 0; |
@@ -305,7 +305,7 @@ static size_t ivtv_copy_buf_to_user(struct ivtv_stream *s, struct ivtv_buffer *b | |||
305 | 305 | ||
306 | if (len > ucount) len = ucount; | 306 | if (len > ucount) len = ucount; |
307 | if (itv->vbi.insert_mpeg && s->type == IVTV_ENC_STREAM_TYPE_MPG && | 307 | if (itv->vbi.insert_mpeg && s->type == IVTV_ENC_STREAM_TYPE_MPG && |
308 | itv->vbi.sliced_in->service_set && buf != &itv->vbi.sliced_mpeg_buf) { | 308 | !ivtv_raw_vbi(itv) && buf != &itv->vbi.sliced_mpeg_buf) { |
309 | const char *start = buf->buf + buf->readpos; | 309 | const char *start = buf->buf + buf->readpos; |
310 | const char *p = start + 1; | 310 | const char *p = start + 1; |
311 | const u8 *q; | 311 | const u8 *q; |
@@ -372,7 +372,7 @@ static ssize_t ivtv_read(struct ivtv_stream *s, char __user *ubuf, size_t tot_co | |||
372 | /* Each VBI buffer is one frame, the v4l2 API says that for VBI the frames should | 372 | /* Each VBI buffer is one frame, the v4l2 API says that for VBI the frames should |
373 | arrive one-by-one, so make sure we never output more than one VBI frame at a time */ | 373 | arrive one-by-one, so make sure we never output more than one VBI frame at a time */ |
374 | if (s->type == IVTV_DEC_STREAM_TYPE_VBI || | 374 | if (s->type == IVTV_DEC_STREAM_TYPE_VBI || |
375 | (s->type == IVTV_ENC_STREAM_TYPE_VBI && itv->vbi.sliced_in->service_set)) | 375 | (s->type == IVTV_ENC_STREAM_TYPE_VBI && !ivtv_raw_vbi(itv))) |
376 | single_frame = 1; | 376 | single_frame = 1; |
377 | 377 | ||
378 | for (;;) { | 378 | for (;;) { |
diff --git a/drivers/media/video/ivtv/ivtv-fileops.h b/drivers/media/video/ivtv/ivtv-fileops.h index 2c8d5186c9c3..df81e790147f 100644 --- a/drivers/media/video/ivtv/ivtv-fileops.h +++ b/drivers/media/video/ivtv/ivtv-fileops.h | |||
@@ -38,11 +38,6 @@ void ivtv_unmute(struct ivtv *itv); | |||
38 | 38 | ||
39 | /* Utilities */ | 39 | /* Utilities */ |
40 | 40 | ||
41 | /* Try to claim a stream for the filehandle. Return 0 on success, | ||
42 | -EBUSY if stream already claimed. Once a stream is claimed, it | ||
43 | remains claimed until the associated filehandle is closed. */ | ||
44 | int ivtv_claim_stream(struct ivtv_open_id *id, int type); | ||
45 | |||
46 | /* Release a previously claimed stream. */ | 41 | /* Release a previously claimed stream. */ |
47 | void ivtv_release_stream(struct ivtv_stream *s); | 42 | void ivtv_release_stream(struct ivtv_stream *s); |
48 | 43 | ||
diff --git a/drivers/media/video/ivtv/ivtv-gpio.c b/drivers/media/video/ivtv/ivtv-gpio.c index bc22905ea20f..74a44844ccaf 100644 --- a/drivers/media/video/ivtv/ivtv-gpio.c +++ b/drivers/media/video/ivtv/ivtv-gpio.c | |||
@@ -124,7 +124,7 @@ void ivtv_reset_ir_gpio(struct ivtv *itv) | |||
124 | } | 124 | } |
125 | 125 | ||
126 | /* Xceive tuner reset function */ | 126 | /* Xceive tuner reset function */ |
127 | int ivtv_reset_tuner_gpio(void *dev, int cmd, int value) | 127 | int ivtv_reset_tuner_gpio(void *dev, int component, int cmd, int value) |
128 | { | 128 | { |
129 | struct i2c_algo_bit_data *algo = dev; | 129 | struct i2c_algo_bit_data *algo = dev; |
130 | struct ivtv *itv = algo->data; | 130 | struct ivtv *itv = algo->data; |
diff --git a/drivers/media/video/ivtv/ivtv-gpio.h b/drivers/media/video/ivtv/ivtv-gpio.h index 964a265d91a9..48b6291613a2 100644 --- a/drivers/media/video/ivtv/ivtv-gpio.h +++ b/drivers/media/video/ivtv/ivtv-gpio.h | |||
@@ -24,7 +24,7 @@ | |||
24 | /* GPIO stuff */ | 24 | /* GPIO stuff */ |
25 | void ivtv_gpio_init(struct ivtv *itv); | 25 | void ivtv_gpio_init(struct ivtv *itv); |
26 | void ivtv_reset_ir_gpio(struct ivtv *itv); | 26 | void ivtv_reset_ir_gpio(struct ivtv *itv); |
27 | int ivtv_reset_tuner_gpio(void *dev, int cmd, int value); | 27 | int ivtv_reset_tuner_gpio(void *dev, int component, int cmd, int value); |
28 | int ivtv_gpio(struct ivtv *itv, unsigned int command, void *arg); | 28 | int ivtv_gpio(struct ivtv *itv, unsigned int command, void *arg); |
29 | 29 | ||
30 | #endif | 30 | #endif |
diff --git a/drivers/media/video/ivtv/ivtv-i2c.c b/drivers/media/video/ivtv/ivtv-i2c.c index af154238fb9a..24700c211d52 100644 --- a/drivers/media/video/ivtv/ivtv-i2c.c +++ b/drivers/media/video/ivtv/ivtv-i2c.c | |||
@@ -64,8 +64,6 @@ | |||
64 | #include "ivtv-gpio.h" | 64 | #include "ivtv-gpio.h" |
65 | #include "ivtv-i2c.h" | 65 | #include "ivtv-i2c.h" |
66 | 66 | ||
67 | #include <media/ir-kbd-i2c.h> | ||
68 | |||
69 | /* i2c implementation for cx23415/6 chip, ivtv project. | 67 | /* i2c implementation for cx23415/6 chip, ivtv project. |
70 | * Author: Kevin Thayer (nufan_wfk at yahoo.com) | 68 | * Author: Kevin Thayer (nufan_wfk at yahoo.com) |
71 | */ | 69 | */ |
diff --git a/drivers/media/video/ivtv/ivtv-ioctl.c b/drivers/media/video/ivtv/ivtv-ioctl.c index 61030309d0ad..8696527ab134 100644 --- a/drivers/media/video/ivtv/ivtv-ioctl.c +++ b/drivers/media/video/ivtv/ivtv-ioctl.c | |||
@@ -101,18 +101,15 @@ void ivtv_expand_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal) | |||
101 | } | 101 | } |
102 | } | 102 | } |
103 | 103 | ||
104 | static int check_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal) | 104 | static void check_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal) |
105 | { | 105 | { |
106 | int f, l; | 106 | int f, l; |
107 | u16 set = 0; | ||
108 | 107 | ||
109 | for (f = 0; f < 2; f++) { | 108 | for (f = 0; f < 2; f++) { |
110 | for (l = 0; l < 24; l++) { | 109 | for (l = 0; l < 24; l++) { |
111 | fmt->service_lines[f][l] = select_service_from_set(f, l, fmt->service_lines[f][l], is_pal); | 110 | fmt->service_lines[f][l] = select_service_from_set(f, l, fmt->service_lines[f][l], is_pal); |
112 | set |= fmt->service_lines[f][l]; | ||
113 | } | 111 | } |
114 | } | 112 | } |
115 | return set != 0; | ||
116 | } | 113 | } |
117 | 114 | ||
118 | u16 ivtv_get_service_set(struct v4l2_sliced_vbi_format *fmt) | 115 | u16 ivtv_get_service_set(struct v4l2_sliced_vbi_format *fmt) |
@@ -474,7 +471,7 @@ static int ivtv_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format | |||
474 | int h = fmt->fmt.pix.height; | 471 | int h = fmt->fmt.pix.height; |
475 | 472 | ||
476 | w = min(w, 720); | 473 | w = min(w, 720); |
477 | w = max(w, 1); | 474 | w = max(w, 2); |
478 | h = min(h, itv->is_50hz ? 576 : 480); | 475 | h = min(h, itv->is_50hz ? 576 : 480); |
479 | h = max(h, 2); | 476 | h = max(h, 2); |
480 | ivtv_g_fmt_vid_cap(file, fh, fmt); | 477 | ivtv_g_fmt_vid_cap(file, fh, fmt); |
@@ -512,27 +509,20 @@ static int ivtv_try_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_ | |||
512 | static int ivtv_try_fmt_vid_out(struct file *file, void *fh, struct v4l2_format *fmt) | 509 | static int ivtv_try_fmt_vid_out(struct file *file, void *fh, struct v4l2_format *fmt) |
513 | { | 510 | { |
514 | struct ivtv_open_id *id = fh; | 511 | struct ivtv_open_id *id = fh; |
515 | s32 w, h; | 512 | struct ivtv *itv = id->itv; |
516 | int field; | 513 | s32 w = fmt->fmt.pix.width; |
517 | int ret; | 514 | s32 h = fmt->fmt.pix.height; |
515 | int field = fmt->fmt.pix.field; | ||
516 | int ret = ivtv_g_fmt_vid_out(file, fh, fmt); | ||
518 | 517 | ||
519 | w = fmt->fmt.pix.width; | 518 | w = min(w, 720); |
520 | h = fmt->fmt.pix.height; | 519 | w = max(w, 2); |
521 | field = fmt->fmt.pix.field; | 520 | h = min(h, itv->is_out_50hz ? 576 : 480); |
522 | ret = ivtv_g_fmt_vid_out(file, fh, fmt); | 521 | h = max(h, 2); |
522 | if (id->type == IVTV_DEC_STREAM_TYPE_YUV) | ||
523 | fmt->fmt.pix.field = field; | ||
523 | fmt->fmt.pix.width = w; | 524 | fmt->fmt.pix.width = w; |
524 | fmt->fmt.pix.height = h; | 525 | fmt->fmt.pix.height = h; |
525 | if (!ret && id->type == IVTV_DEC_STREAM_TYPE_YUV) { | ||
526 | fmt->fmt.pix.field = field; | ||
527 | if (fmt->fmt.pix.width < 2) | ||
528 | fmt->fmt.pix.width = 2; | ||
529 | if (fmt->fmt.pix.width > 720) | ||
530 | fmt->fmt.pix.width = 720; | ||
531 | if (fmt->fmt.pix.height < 2) | ||
532 | fmt->fmt.pix.height = 2; | ||
533 | if (fmt->fmt.pix.height > 576) | ||
534 | fmt->fmt.pix.height = 576; | ||
535 | } | ||
536 | return ret; | 526 | return ret; |
537 | } | 527 | } |
538 | 528 | ||
@@ -560,9 +550,9 @@ static int ivtv_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f | |||
560 | struct ivtv_open_id *id = fh; | 550 | struct ivtv_open_id *id = fh; |
561 | struct ivtv *itv = id->itv; | 551 | struct ivtv *itv = id->itv; |
562 | struct cx2341x_mpeg_params *p = &itv->params; | 552 | struct cx2341x_mpeg_params *p = &itv->params; |
553 | int ret = ivtv_try_fmt_vid_cap(file, fh, fmt); | ||
563 | int w = fmt->fmt.pix.width; | 554 | int w = fmt->fmt.pix.width; |
564 | int h = fmt->fmt.pix.height; | 555 | int h = fmt->fmt.pix.height; |
565 | int ret = ivtv_try_fmt_vid_cap(file, fh, fmt); | ||
566 | 556 | ||
567 | if (ret) | 557 | if (ret) |
568 | return ret; | 558 | return ret; |
@@ -585,8 +575,11 @@ static int ivtv_s_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *f | |||
585 | { | 575 | { |
586 | struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv; | 576 | struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv; |
587 | 577 | ||
578 | if (!ivtv_raw_vbi(itv) && atomic_read(&itv->capturing) > 0) | ||
579 | return -EBUSY; | ||
588 | itv->vbi.sliced_in->service_set = 0; | 580 | itv->vbi.sliced_in->service_set = 0; |
589 | itv->video_dec_func(itv, VIDIOC_S_FMT, &itv->vbi.in); | 581 | itv->vbi.in.type = V4L2_BUF_TYPE_VBI_CAPTURE; |
582 | itv->video_dec_func(itv, VIDIOC_S_FMT, fmt); | ||
590 | return ivtv_g_fmt_vbi_cap(file, fh, fmt); | 583 | return ivtv_g_fmt_vbi_cap(file, fh, fmt); |
591 | } | 584 | } |
592 | 585 | ||
@@ -600,10 +593,10 @@ static int ivtv_s_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_fo | |||
600 | if (ret || id->type == IVTV_DEC_STREAM_TYPE_VBI) | 593 | if (ret || id->type == IVTV_DEC_STREAM_TYPE_VBI) |
601 | return ret; | 594 | return ret; |
602 | 595 | ||
603 | if (check_service_set(vbifmt, itv->is_50hz) == 0) | 596 | check_service_set(vbifmt, itv->is_50hz); |
604 | return -EINVAL; | 597 | if (ivtv_raw_vbi(itv) && atomic_read(&itv->capturing) > 0) |
605 | if (atomic_read(&itv->capturing) > 0) | ||
606 | return -EBUSY; | 598 | return -EBUSY; |
599 | itv->vbi.in.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE; | ||
607 | itv->video_dec_func(itv, VIDIOC_S_FMT, fmt); | 600 | itv->video_dec_func(itv, VIDIOC_S_FMT, fmt); |
608 | memcpy(itv->vbi.sliced_in, vbifmt, sizeof(*itv->vbi.sliced_in)); | 601 | memcpy(itv->vbi.sliced_in, vbifmt, sizeof(*itv->vbi.sliced_in)); |
609 | return 0; | 602 | return 0; |
@@ -651,8 +644,6 @@ static int ivtv_s_fmt_vid_out(struct file *file, void *fh, struct v4l2_format *f | |||
651 | itv->dma_data_req_size = | 644 | itv->dma_data_req_size = |
652 | 1080 * ((yi->v4l2_src_h + 31) & ~31); | 645 | 1080 * ((yi->v4l2_src_h + 31) & ~31); |
653 | 646 | ||
654 | /* Force update of yuv registers */ | ||
655 | yi->yuv_forced_update = 1; | ||
656 | return 0; | 647 | return 0; |
657 | } | 648 | } |
658 | 649 | ||
@@ -761,7 +752,7 @@ static int ivtv_querycap(struct file *file, void *fh, struct v4l2_capability *vc | |||
761 | 752 | ||
762 | strlcpy(vcap->driver, IVTV_DRIVER_NAME, sizeof(vcap->driver)); | 753 | strlcpy(vcap->driver, IVTV_DRIVER_NAME, sizeof(vcap->driver)); |
763 | strlcpy(vcap->card, itv->card_name, sizeof(vcap->card)); | 754 | strlcpy(vcap->card, itv->card_name, sizeof(vcap->card)); |
764 | strlcpy(vcap->bus_info, pci_name(itv->dev), sizeof(vcap->bus_info)); | 755 | snprintf(vcap->bus_info, sizeof(vcap->bus_info), "PCI:%s", pci_name(itv->dev)); |
765 | vcap->version = IVTV_DRIVER_VERSION; /* version */ | 756 | vcap->version = IVTV_DRIVER_VERSION; /* version */ |
766 | vcap->capabilities = itv->v4l2_cap; /* capabilities */ | 757 | vcap->capabilities = itv->v4l2_cap; /* capabilities */ |
767 | return 0; | 758 | return 0; |
@@ -1370,6 +1361,9 @@ static int ivtv_g_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *fb) | |||
1370 | if (itv->osd_global_alpha_state) | 1361 | if (itv->osd_global_alpha_state) |
1371 | fb->flags |= V4L2_FBUF_FLAG_GLOBAL_ALPHA; | 1362 | fb->flags |= V4L2_FBUF_FLAG_GLOBAL_ALPHA; |
1372 | 1363 | ||
1364 | if (yi->track_osd) | ||
1365 | fb->flags |= V4L2_FBUF_FLAG_OVERLAY; | ||
1366 | |||
1373 | pixfmt &= 7; | 1367 | pixfmt &= 7; |
1374 | 1368 | ||
1375 | /* no local alpha for RGB565 or unknown formats */ | 1369 | /* no local alpha for RGB565 or unknown formats */ |
@@ -1389,8 +1383,6 @@ static int ivtv_g_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *fb) | |||
1389 | else | 1383 | else |
1390 | fb->flags |= V4L2_FBUF_FLAG_LOCAL_ALPHA; | 1384 | fb->flags |= V4L2_FBUF_FLAG_LOCAL_ALPHA; |
1391 | } | 1385 | } |
1392 | if (yi->track_osd) | ||
1393 | fb->flags |= V4L2_FBUF_FLAG_OVERLAY; | ||
1394 | 1386 | ||
1395 | return 0; | 1387 | return 0; |
1396 | } | 1388 | } |
diff --git a/drivers/media/video/ivtv/ivtv-irq.c b/drivers/media/video/ivtv/ivtv-irq.c index 34f3ab827858..f5d00ec5da73 100644 --- a/drivers/media/video/ivtv/ivtv-irq.c +++ b/drivers/media/video/ivtv/ivtv-irq.c | |||
@@ -753,7 +753,7 @@ static void ivtv_irq_vsync(struct ivtv *itv) | |||
753 | */ | 753 | */ |
754 | unsigned int frame = read_reg(0x28c0) & 1; | 754 | unsigned int frame = read_reg(0x28c0) & 1; |
755 | struct yuv_playback_info *yi = &itv->yuv_info; | 755 | struct yuv_playback_info *yi = &itv->yuv_info; |
756 | int last_dma_frame = atomic_read(&itv->yuv_info.next_dma_frame); | 756 | int last_dma_frame = atomic_read(&yi->next_dma_frame); |
757 | struct yuv_frame_info *f = &yi->new_frame_info[last_dma_frame]; | 757 | struct yuv_frame_info *f = &yi->new_frame_info[last_dma_frame]; |
758 | 758 | ||
759 | if (0) IVTV_DEBUG_IRQ("DEC VSYNC\n"); | 759 | if (0) IVTV_DEBUG_IRQ("DEC VSYNC\n"); |
@@ -772,6 +772,7 @@ static void ivtv_irq_vsync(struct ivtv *itv) | |||
772 | next_dma_frame = (next_dma_frame + 1) % IVTV_YUV_BUFFERS; | 772 | next_dma_frame = (next_dma_frame + 1) % IVTV_YUV_BUFFERS; |
773 | atomic_set(&yi->next_dma_frame, next_dma_frame); | 773 | atomic_set(&yi->next_dma_frame, next_dma_frame); |
774 | yi->fields_lapsed = -1; | 774 | yi->fields_lapsed = -1; |
775 | yi->running = 1; | ||
775 | } | 776 | } |
776 | } | 777 | } |
777 | } | 778 | } |
@@ -804,9 +805,11 @@ static void ivtv_irq_vsync(struct ivtv *itv) | |||
804 | } | 805 | } |
805 | 806 | ||
806 | /* Check if we need to update the yuv registers */ | 807 | /* Check if we need to update the yuv registers */ |
807 | if ((yi->yuv_forced_update || f->update) && last_dma_frame != -1) { | 808 | if (yi->running && (yi->yuv_forced_update || f->update)) { |
808 | if (!f->update) { | 809 | if (!f->update) { |
809 | last_dma_frame = (u8)(last_dma_frame - 1) % IVTV_YUV_BUFFERS; | 810 | last_dma_frame = |
811 | (u8)(atomic_read(&yi->next_dma_frame) - | ||
812 | 1) % IVTV_YUV_BUFFERS; | ||
810 | f = &yi->new_frame_info[last_dma_frame]; | 813 | f = &yi->new_frame_info[last_dma_frame]; |
811 | } | 814 | } |
812 | 815 | ||
diff --git a/drivers/media/video/ivtv/ivtv-streams.c b/drivers/media/video/ivtv/ivtv-streams.c index 730e85d86fc8..5bbf31e39304 100644 --- a/drivers/media/video/ivtv/ivtv-streams.c +++ b/drivers/media/video/ivtv/ivtv-streams.c | |||
@@ -75,7 +75,7 @@ static const struct file_operations ivtv_v4l2_dec_fops = { | |||
75 | static struct { | 75 | static struct { |
76 | const char *name; | 76 | const char *name; |
77 | int vfl_type; | 77 | int vfl_type; |
78 | int minor_offset; | 78 | int num_offset; |
79 | int dma, pio; | 79 | int dma, pio; |
80 | enum v4l2_buf_type buf_type; | 80 | enum v4l2_buf_type buf_type; |
81 | const struct file_operations *fops; | 81 | const struct file_operations *fops; |
@@ -171,8 +171,8 @@ static void ivtv_stream_init(struct ivtv *itv, int type) | |||
171 | static int ivtv_prep_dev(struct ivtv *itv, int type) | 171 | static int ivtv_prep_dev(struct ivtv *itv, int type) |
172 | { | 172 | { |
173 | struct ivtv_stream *s = &itv->streams[type]; | 173 | struct ivtv_stream *s = &itv->streams[type]; |
174 | int minor_offset = ivtv_stream_info[type].minor_offset; | 174 | int num_offset = ivtv_stream_info[type].num_offset; |
175 | int minor; | 175 | int num = itv->num + ivtv_first_minor + num_offset; |
176 | 176 | ||
177 | /* These four fields are always initialized. If v4l2dev == NULL, then | 177 | /* These four fields are always initialized. If v4l2dev == NULL, then |
178 | this stream is not in use. In that case no other fields but these | 178 | this stream is not in use. In that case no other fields but these |
@@ -188,9 +188,6 @@ static int ivtv_prep_dev(struct ivtv *itv, int type) | |||
188 | if (type >= IVTV_DEC_STREAM_TYPE_MPG && !(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) | 188 | if (type >= IVTV_DEC_STREAM_TYPE_MPG && !(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) |
189 | return 0; | 189 | return 0; |
190 | 190 | ||
191 | /* card number + user defined offset + device offset */ | ||
192 | minor = itv->num + ivtv_first_minor + minor_offset; | ||
193 | |||
194 | /* User explicitly selected 0 buffers for these streams, so don't | 191 | /* User explicitly selected 0 buffers for these streams, so don't |
195 | create them. */ | 192 | create them. */ |
196 | if (ivtv_stream_info[type].dma != PCI_DMA_NONE && | 193 | if (ivtv_stream_info[type].dma != PCI_DMA_NONE && |
@@ -211,7 +208,7 @@ static int ivtv_prep_dev(struct ivtv *itv, int type) | |||
211 | snprintf(s->v4l2dev->name, sizeof(s->v4l2dev->name), "ivtv%d %s", | 208 | snprintf(s->v4l2dev->name, sizeof(s->v4l2dev->name), "ivtv%d %s", |
212 | itv->num, s->name); | 209 | itv->num, s->name); |
213 | 210 | ||
214 | s->v4l2dev->minor = minor; | 211 | s->v4l2dev->num = num; |
215 | s->v4l2dev->parent = &itv->dev->dev; | 212 | s->v4l2dev->parent = &itv->dev->dev; |
216 | s->v4l2dev->fops = ivtv_stream_info[type].fops; | 213 | s->v4l2dev->fops = ivtv_stream_info[type].fops; |
217 | s->v4l2dev->release = video_device_release; | 214 | s->v4l2dev->release = video_device_release; |
@@ -250,39 +247,46 @@ static int ivtv_reg_dev(struct ivtv *itv, int type) | |||
250 | { | 247 | { |
251 | struct ivtv_stream *s = &itv->streams[type]; | 248 | struct ivtv_stream *s = &itv->streams[type]; |
252 | int vfl_type = ivtv_stream_info[type].vfl_type; | 249 | int vfl_type = ivtv_stream_info[type].vfl_type; |
253 | int minor; | 250 | int num; |
254 | 251 | ||
255 | if (s->v4l2dev == NULL) | 252 | if (s->v4l2dev == NULL) |
256 | return 0; | 253 | return 0; |
257 | 254 | ||
258 | minor = s->v4l2dev->minor; | 255 | num = s->v4l2dev->num; |
256 | /* card number + user defined offset + device offset */ | ||
257 | if (type != IVTV_ENC_STREAM_TYPE_MPG) { | ||
258 | struct ivtv_stream *s_mpg = &itv->streams[IVTV_ENC_STREAM_TYPE_MPG]; | ||
259 | |||
260 | if (s_mpg->v4l2dev) | ||
261 | num = s_mpg->v4l2dev->num + ivtv_stream_info[type].num_offset; | ||
262 | } | ||
263 | |||
259 | /* Register device. First try the desired minor, then any free one. */ | 264 | /* Register device. First try the desired minor, then any free one. */ |
260 | if (video_register_device(s->v4l2dev, vfl_type, minor) && | 265 | if (video_register_device(s->v4l2dev, vfl_type, num)) { |
261 | video_register_device(s->v4l2dev, vfl_type, -1)) { | 266 | IVTV_ERR("Couldn't register v4l2 device for %s kernel number %d\n", |
262 | IVTV_ERR("Couldn't register v4l2 device for %s minor %d\n", | 267 | s->name, num); |
263 | s->name, minor); | ||
264 | video_device_release(s->v4l2dev); | 268 | video_device_release(s->v4l2dev); |
265 | s->v4l2dev = NULL; | 269 | s->v4l2dev = NULL; |
266 | return -ENOMEM; | 270 | return -ENOMEM; |
267 | } | 271 | } |
272 | num = s->v4l2dev->num; | ||
268 | 273 | ||
269 | switch (vfl_type) { | 274 | switch (vfl_type) { |
270 | case VFL_TYPE_GRABBER: | 275 | case VFL_TYPE_GRABBER: |
271 | IVTV_INFO("Registered device video%d for %s (%d kB)\n", | 276 | IVTV_INFO("Registered device video%d for %s (%d kB)\n", |
272 | s->v4l2dev->minor, s->name, itv->options.kilobytes[type]); | 277 | num, s->name, itv->options.kilobytes[type]); |
273 | break; | 278 | break; |
274 | case VFL_TYPE_RADIO: | 279 | case VFL_TYPE_RADIO: |
275 | IVTV_INFO("Registered device radio%d for %s\n", | 280 | IVTV_INFO("Registered device radio%d for %s\n", |
276 | s->v4l2dev->minor - MINOR_VFL_TYPE_RADIO_MIN, s->name); | 281 | num, s->name); |
277 | break; | 282 | break; |
278 | case VFL_TYPE_VBI: | 283 | case VFL_TYPE_VBI: |
279 | if (itv->options.kilobytes[type]) | 284 | if (itv->options.kilobytes[type]) |
280 | IVTV_INFO("Registered device vbi%d for %s (%d kB)\n", | 285 | IVTV_INFO("Registered device vbi%d for %s (%d kB)\n", |
281 | s->v4l2dev->minor - MINOR_VFL_TYPE_VBI_MIN, | 286 | num, s->name, itv->options.kilobytes[type]); |
282 | s->name, itv->options.kilobytes[type]); | ||
283 | else | 287 | else |
284 | IVTV_INFO("Registered device vbi%d for %s\n", | 288 | IVTV_INFO("Registered device vbi%d for %s\n", |
285 | s->v4l2dev->minor - MINOR_VFL_TYPE_VBI_MIN, s->name); | 289 | num, s->name); |
286 | break; | 290 | break; |
287 | } | 291 | } |
288 | return 0; | 292 | return 0; |
@@ -330,7 +334,7 @@ void ivtv_streams_cleanup(struct ivtv *itv, int unregister) | |||
330 | 334 | ||
331 | static void ivtv_vbi_setup(struct ivtv *itv) | 335 | static void ivtv_vbi_setup(struct ivtv *itv) |
332 | { | 336 | { |
333 | int raw = itv->vbi.sliced_in->service_set == 0; | 337 | int raw = ivtv_raw_vbi(itv); |
334 | u32 data[CX2341X_MBOX_MAX_DATA]; | 338 | u32 data[CX2341X_MBOX_MAX_DATA]; |
335 | int lines; | 339 | int lines; |
336 | int i; | 340 | int i; |
diff --git a/drivers/media/video/ivtv/ivtv-vbi.c b/drivers/media/video/ivtv/ivtv-vbi.c index 1ce9deb1104f..4a37a7d2e69d 100644 --- a/drivers/media/video/ivtv/ivtv-vbi.c +++ b/drivers/media/video/ivtv/ivtv-vbi.c | |||
@@ -334,7 +334,7 @@ void ivtv_process_vbi_data(struct ivtv *itv, struct ivtv_buffer *buf, | |||
334 | int y; | 334 | int y; |
335 | 335 | ||
336 | /* Raw VBI data */ | 336 | /* Raw VBI data */ |
337 | if (streamtype == IVTV_ENC_STREAM_TYPE_VBI && itv->vbi.sliced_in->service_set == 0) { | 337 | if (streamtype == IVTV_ENC_STREAM_TYPE_VBI && ivtv_raw_vbi(itv)) { |
338 | u8 type; | 338 | u8 type; |
339 | 339 | ||
340 | ivtv_buf_swap(buf); | 340 | ivtv_buf_swap(buf); |
diff --git a/drivers/media/video/ivtv/ivtv-yuv.c b/drivers/media/video/ivtv/ivtv-yuv.c index 3092ff1d00a0..ee91107376c7 100644 --- a/drivers/media/video/ivtv/ivtv-yuv.c +++ b/drivers/media/video/ivtv/ivtv-yuv.c | |||
@@ -1147,6 +1147,7 @@ void ivtv_yuv_close(struct ivtv *itv) | |||
1147 | IVTV_DEBUG_YUV("ivtv_yuv_close\n"); | 1147 | IVTV_DEBUG_YUV("ivtv_yuv_close\n"); |
1148 | ivtv_waitq(&itv->vsync_waitq); | 1148 | ivtv_waitq(&itv->vsync_waitq); |
1149 | 1149 | ||
1150 | yi->running = 0; | ||
1150 | atomic_set(&yi->next_dma_frame, -1); | 1151 | atomic_set(&yi->next_dma_frame, -1); |
1151 | atomic_set(&yi->next_fill_frame, 0); | 1152 | atomic_set(&yi->next_fill_frame, 0); |
1152 | 1153 | ||
diff --git a/drivers/media/video/ivtv/ivtvfb.c b/drivers/media/video/ivtv/ivtvfb.c index bdfda48e56bf..8a4a150b12fb 100644 --- a/drivers/media/video/ivtv/ivtvfb.c +++ b/drivers/media/video/ivtv/ivtvfb.c | |||
@@ -275,7 +275,6 @@ static int ivtvfb_prep_dec_dma_to_device(struct ivtv *itv, | |||
275 | int size_in_bytes) | 275 | int size_in_bytes) |
276 | { | 276 | { |
277 | DEFINE_WAIT(wait); | 277 | DEFINE_WAIT(wait); |
278 | int ret = 0; | ||
279 | int got_sig = 0; | 278 | int got_sig = 0; |
280 | 279 | ||
281 | mutex_lock(&itv->udma.lock); | 280 | mutex_lock(&itv->udma.lock); |
@@ -316,7 +315,7 @@ static int ivtvfb_prep_dec_dma_to_device(struct ivtv *itv, | |||
316 | return -EINTR; | 315 | return -EINTR; |
317 | } | 316 | } |
318 | 317 | ||
319 | return ret; | 318 | return 0; |
320 | } | 319 | } |
321 | 320 | ||
322 | static int ivtvfb_prep_frame(struct ivtv *itv, int cmd, void __user *source, | 321 | static int ivtvfb_prep_frame(struct ivtv *itv, int cmd, void __user *source, |
@@ -368,11 +367,12 @@ static int ivtvfb_prep_frame(struct ivtv *itv, int cmd, void __user *source, | |||
368 | } | 367 | } |
369 | 368 | ||
370 | static ssize_t ivtvfb_write(struct fb_info *info, const char __user *buf, | 369 | static ssize_t ivtvfb_write(struct fb_info *info, const char __user *buf, |
371 | size_t count, loff_t *ppos) | 370 | size_t count, loff_t *ppos) |
372 | { | 371 | { |
373 | unsigned long p = *ppos; | 372 | unsigned long p = *ppos; |
374 | void *dst; | 373 | void *dst; |
375 | int err = 0; | 374 | int err = 0; |
375 | int dma_err; | ||
376 | unsigned long total_size; | 376 | unsigned long total_size; |
377 | struct ivtv *itv = (struct ivtv *) info->par; | 377 | struct ivtv *itv = (struct ivtv *) info->par; |
378 | unsigned long dma_offset = | 378 | unsigned long dma_offset = |
@@ -399,7 +399,6 @@ static ssize_t ivtvfb_write(struct fb_info *info, const char __user *buf, | |||
399 | if (count + p > total_size) { | 399 | if (count + p > total_size) { |
400 | if (!err) | 400 | if (!err) |
401 | err = -ENOSPC; | 401 | err = -ENOSPC; |
402 | |||
403 | count = total_size - p; | 402 | count = total_size - p; |
404 | } | 403 | } |
405 | 404 | ||
@@ -408,39 +407,34 @@ static ssize_t ivtvfb_write(struct fb_info *info, const char __user *buf, | |||
408 | if (info->fbops->fb_sync) | 407 | if (info->fbops->fb_sync) |
409 | info->fbops->fb_sync(info); | 408 | info->fbops->fb_sync(info); |
410 | 409 | ||
411 | if (!access_ok(VERIFY_READ, buf, count)) { | 410 | /* If transfer size > threshold and both src/dst |
412 | IVTVFB_WARN("Invalid userspace pointer 0x%08lx\n", | 411 | addresses are aligned, use DMA */ |
413 | (unsigned long)buf); | 412 | if (count >= 4096 && |
414 | err = -EFAULT; | 413 | ((unsigned long)buf & 3) == ((unsigned long)dst & 3)) { |
415 | } | 414 | /* Odd address = can't DMA. Align */ |
416 | 415 | if ((unsigned long)dst & 3) { | |
417 | if (!err) { | 416 | lead = 4 - ((unsigned long)dst & 3); |
418 | /* If transfer size > threshold and both src/dst | 417 | if (copy_from_user(dst, buf, lead)) |
419 | addresses are aligned, use DMA */ | 418 | return -EFAULT; |
420 | if (count >= 4096 && | 419 | buf += lead; |
421 | ((unsigned long)buf & 3) == ((unsigned long)dst & 3)) { | 420 | dst += lead; |
422 | /* Odd address = can't DMA. Align */ | ||
423 | if ((unsigned long)dst & 3) { | ||
424 | lead = 4 - ((unsigned long)dst & 3); | ||
425 | memcpy(dst, buf, lead); | ||
426 | buf += lead; | ||
427 | dst += lead; | ||
428 | } | ||
429 | /* DMA resolution is 32 bits */ | ||
430 | if ((count - lead) & 3) | ||
431 | tail = (count - lead) & 3; | ||
432 | /* DMA the data */ | ||
433 | dma_size = count - lead - tail; | ||
434 | err = ivtvfb_prep_dec_dma_to_device(itv, | ||
435 | p + lead + dma_offset, (void *)buf, dma_size); | ||
436 | dst += dma_size; | ||
437 | buf += dma_size; | ||
438 | /* Copy any leftover data */ | ||
439 | if (tail) | ||
440 | memcpy(dst, buf, tail); | ||
441 | } else { | ||
442 | memcpy(dst, buf, count); | ||
443 | } | 421 | } |
422 | /* DMA resolution is 32 bits */ | ||
423 | if ((count - lead) & 3) | ||
424 | tail = (count - lead) & 3; | ||
425 | /* DMA the data */ | ||
426 | dma_size = count - lead - tail; | ||
427 | dma_err = ivtvfb_prep_dec_dma_to_device(itv, | ||
428 | p + lead + dma_offset, (void __user *)buf, dma_size); | ||
429 | if (dma_err) | ||
430 | return dma_err; | ||
431 | dst += dma_size; | ||
432 | buf += dma_size; | ||
433 | /* Copy any leftover data */ | ||
434 | if (tail && copy_from_user(dst, buf, tail)) | ||
435 | return -EFAULT; | ||
436 | } else if (copy_from_user(dst, buf, count)) { | ||
437 | return -EFAULT; | ||
444 | } | 438 | } |
445 | 439 | ||
446 | if (!err) | 440 | if (!err) |
@@ -463,9 +457,12 @@ static int ivtvfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long ar | |||
463 | vblank.flags = FB_VBLANK_HAVE_COUNT |FB_VBLANK_HAVE_VCOUNT | | 457 | vblank.flags = FB_VBLANK_HAVE_COUNT |FB_VBLANK_HAVE_VCOUNT | |
464 | FB_VBLANK_HAVE_VSYNC; | 458 | FB_VBLANK_HAVE_VSYNC; |
465 | trace = read_reg(0x028c0) >> 16; | 459 | trace = read_reg(0x028c0) >> 16; |
466 | if (itv->is_50hz && trace > 312) trace -= 312; | 460 | if (itv->is_50hz && trace > 312) |
467 | else if (itv->is_60hz && trace > 262) trace -= 262; | 461 | trace -= 312; |
468 | if (trace == 1) vblank.flags |= FB_VBLANK_VSYNCING; | 462 | else if (itv->is_60hz && trace > 262) |
463 | trace -= 262; | ||
464 | if (trace == 1) | ||
465 | vblank.flags |= FB_VBLANK_VSYNCING; | ||
469 | vblank.count = itv->last_vsync_field; | 466 | vblank.count = itv->last_vsync_field; |
470 | vblank.vcount = trace; | 467 | vblank.vcount = trace; |
471 | vblank.hcount = 0; | 468 | vblank.hcount = 0; |
@@ -476,7 +473,8 @@ static int ivtvfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long ar | |||
476 | 473 | ||
477 | case FBIO_WAITFORVSYNC: | 474 | case FBIO_WAITFORVSYNC: |
478 | prepare_to_wait(&itv->vsync_waitq, &wait, TASK_INTERRUPTIBLE); | 475 | prepare_to_wait(&itv->vsync_waitq, &wait, TASK_INTERRUPTIBLE); |
479 | if (!schedule_timeout(msecs_to_jiffies(50))) rc = -ETIMEDOUT; | 476 | if (!schedule_timeout(msecs_to_jiffies(50))) |
477 | rc = -ETIMEDOUT; | ||
480 | finish_wait(&itv->vsync_waitq, &wait); | 478 | finish_wait(&itv->vsync_waitq, &wait); |
481 | return rc; | 479 | return rc; |
482 | 480 | ||
diff --git a/drivers/media/video/meye.c b/drivers/media/video/meye.c index a9ef7802eb5f..6418f4a78f2a 100644 --- a/drivers/media/video/meye.c +++ b/drivers/media/video/meye.c | |||
@@ -843,17 +843,16 @@ again: | |||
843 | 843 | ||
844 | static int meye_open(struct inode *inode, struct file *file) | 844 | static int meye_open(struct inode *inode, struct file *file) |
845 | { | 845 | { |
846 | int i, err; | 846 | int i; |
847 | 847 | ||
848 | err = video_exclusive_open(inode, file); | 848 | if (test_and_set_bit(0, &meye.in_use)) |
849 | if (err < 0) | 849 | return -EBUSY; |
850 | return err; | ||
851 | 850 | ||
852 | mchip_hic_stop(); | 851 | mchip_hic_stop(); |
853 | 852 | ||
854 | if (mchip_dma_alloc()) { | 853 | if (mchip_dma_alloc()) { |
855 | printk(KERN_ERR "meye: mchip framebuffer allocation failed\n"); | 854 | printk(KERN_ERR "meye: mchip framebuffer allocation failed\n"); |
856 | video_exclusive_release(inode, file); | 855 | clear_bit(0, &meye.in_use); |
857 | return -ENOBUFS; | 856 | return -ENOBUFS; |
858 | } | 857 | } |
859 | 858 | ||
@@ -868,7 +867,7 @@ static int meye_release(struct inode *inode, struct file *file) | |||
868 | { | 867 | { |
869 | mchip_hic_stop(); | 868 | mchip_hic_stop(); |
870 | mchip_dma_free(); | 869 | mchip_dma_free(); |
871 | video_exclusive_release(inode, file); | 870 | clear_bit(0, &meye.in_use); |
872 | return 0; | 871 | return 0; |
873 | } | 872 | } |
874 | 873 | ||
@@ -1774,6 +1773,7 @@ static int __devinit meye_probe(struct pci_dev *pcidev, | |||
1774 | goto outnotdev; | 1773 | goto outnotdev; |
1775 | } | 1774 | } |
1776 | 1775 | ||
1776 | ret = -ENOMEM; | ||
1777 | meye.mchip_dev = pcidev; | 1777 | meye.mchip_dev = pcidev; |
1778 | meye.video_dev = video_device_alloc(); | 1778 | meye.video_dev = video_device_alloc(); |
1779 | if (!meye.video_dev) { | 1779 | if (!meye.video_dev) { |
@@ -1781,7 +1781,6 @@ static int __devinit meye_probe(struct pci_dev *pcidev, | |||
1781 | goto outnotdev; | 1781 | goto outnotdev; |
1782 | } | 1782 | } |
1783 | 1783 | ||
1784 | ret = -ENOMEM; | ||
1785 | meye.grab_temp = vmalloc(MCHIP_NB_PAGES_MJPEG * PAGE_SIZE); | 1784 | meye.grab_temp = vmalloc(MCHIP_NB_PAGES_MJPEG * PAGE_SIZE); |
1786 | if (!meye.grab_temp) { | 1785 | if (!meye.grab_temp) { |
1787 | printk(KERN_ERR "meye: grab buffer allocation failed\n"); | 1786 | printk(KERN_ERR "meye: grab buffer allocation failed\n"); |
diff --git a/drivers/media/video/meye.h b/drivers/media/video/meye.h index d535748df445..5f70a106ba2b 100644 --- a/drivers/media/video/meye.h +++ b/drivers/media/video/meye.h | |||
@@ -311,6 +311,7 @@ struct meye { | |||
311 | struct video_device *video_dev; /* video device parameters */ | 311 | struct video_device *video_dev; /* video device parameters */ |
312 | struct video_picture picture; /* video picture parameters */ | 312 | struct video_picture picture; /* video picture parameters */ |
313 | struct meye_params params; /* additional parameters */ | 313 | struct meye_params params; /* additional parameters */ |
314 | unsigned long in_use; /* set to 1 if the device is in use */ | ||
314 | #ifdef CONFIG_PM | 315 | #ifdef CONFIG_PM |
315 | u8 pm_mchip_mode; /* old mchip mode */ | 316 | u8 pm_mchip_mode; /* old mchip mode */ |
316 | #endif | 317 | #endif |
diff --git a/drivers/media/video/mt9m001.c b/drivers/media/video/mt9m001.c index 554d2295484e..0c524376b67e 100644 --- a/drivers/media/video/mt9m001.c +++ b/drivers/media/video/mt9m001.c | |||
@@ -117,24 +117,51 @@ static int reg_clear(struct soc_camera_device *icd, const u8 reg, | |||
117 | 117 | ||
118 | static int mt9m001_init(struct soc_camera_device *icd) | 118 | static int mt9m001_init(struct soc_camera_device *icd) |
119 | { | 119 | { |
120 | struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); | ||
121 | struct soc_camera_link *icl = mt9m001->client->dev.platform_data; | ||
120 | int ret; | 122 | int ret; |
121 | 123 | ||
122 | /* Disable chip, synchronous option update */ | ||
123 | dev_dbg(icd->vdev->parent, "%s\n", __func__); | 124 | dev_dbg(icd->vdev->parent, "%s\n", __func__); |
124 | 125 | ||
125 | ret = reg_write(icd, MT9M001_RESET, 1); | 126 | if (icl->power) { |
126 | if (ret >= 0) | 127 | ret = icl->power(&mt9m001->client->dev, 1); |
127 | ret = reg_write(icd, MT9M001_RESET, 0); | 128 | if (ret < 0) { |
128 | if (ret >= 0) | 129 | dev_err(icd->vdev->parent, |
130 | "Platform failed to power-on the camera.\n"); | ||
131 | return ret; | ||
132 | } | ||
133 | } | ||
134 | |||
135 | /* The camera could have been already on, we reset it additionally */ | ||
136 | if (icl->reset) | ||
137 | ret = icl->reset(&mt9m001->client->dev); | ||
138 | else | ||
139 | ret = -ENODEV; | ||
140 | |||
141 | if (ret < 0) { | ||
142 | /* Either no platform reset, or platform reset failed */ | ||
143 | ret = reg_write(icd, MT9M001_RESET, 1); | ||
144 | if (!ret) | ||
145 | ret = reg_write(icd, MT9M001_RESET, 0); | ||
146 | } | ||
147 | /* Disable chip, synchronous option update */ | ||
148 | if (!ret) | ||
129 | ret = reg_write(icd, MT9M001_OUTPUT_CONTROL, 0); | 149 | ret = reg_write(icd, MT9M001_OUTPUT_CONTROL, 0); |
130 | 150 | ||
131 | return ret >= 0 ? 0 : -EIO; | 151 | return ret; |
132 | } | 152 | } |
133 | 153 | ||
134 | static int mt9m001_release(struct soc_camera_device *icd) | 154 | static int mt9m001_release(struct soc_camera_device *icd) |
135 | { | 155 | { |
156 | struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); | ||
157 | struct soc_camera_link *icl = mt9m001->client->dev.platform_data; | ||
158 | |||
136 | /* Disable the chip */ | 159 | /* Disable the chip */ |
137 | reg_write(icd, MT9M001_OUTPUT_CONTROL, 0); | 160 | reg_write(icd, MT9M001_OUTPUT_CONTROL, 0); |
161 | |||
162 | if (icl->power) | ||
163 | icl->power(&mt9m001->client->dev, 0); | ||
164 | |||
138 | return 0; | 165 | return 0; |
139 | } | 166 | } |
140 | 167 | ||
@@ -267,24 +294,24 @@ static int mt9m001_set_fmt_cap(struct soc_camera_device *icd, | |||
267 | 294 | ||
268 | /* Blanking and start values - default... */ | 295 | /* Blanking and start values - default... */ |
269 | ret = reg_write(icd, MT9M001_HORIZONTAL_BLANKING, hblank); | 296 | ret = reg_write(icd, MT9M001_HORIZONTAL_BLANKING, hblank); |
270 | if (ret >= 0) | 297 | if (!ret) |
271 | ret = reg_write(icd, MT9M001_VERTICAL_BLANKING, vblank); | 298 | ret = reg_write(icd, MT9M001_VERTICAL_BLANKING, vblank); |
272 | 299 | ||
273 | /* The caller provides a supported format, as verified per | 300 | /* The caller provides a supported format, as verified per |
274 | * call to icd->try_fmt_cap() */ | 301 | * call to icd->try_fmt_cap() */ |
275 | if (ret >= 0) | 302 | if (!ret) |
276 | ret = reg_write(icd, MT9M001_COLUMN_START, rect->left); | 303 | ret = reg_write(icd, MT9M001_COLUMN_START, rect->left); |
277 | if (ret >= 0) | 304 | if (!ret) |
278 | ret = reg_write(icd, MT9M001_ROW_START, rect->top); | 305 | ret = reg_write(icd, MT9M001_ROW_START, rect->top); |
279 | if (ret >= 0) | 306 | if (!ret) |
280 | ret = reg_write(icd, MT9M001_WINDOW_WIDTH, rect->width - 1); | 307 | ret = reg_write(icd, MT9M001_WINDOW_WIDTH, rect->width - 1); |
281 | if (ret >= 0) | 308 | if (!ret) |
282 | ret = reg_write(icd, MT9M001_WINDOW_HEIGHT, | 309 | ret = reg_write(icd, MT9M001_WINDOW_HEIGHT, |
283 | rect->height + icd->y_skip_top - 1); | 310 | rect->height + icd->y_skip_top - 1); |
284 | if (ret >= 0 && mt9m001->autoexposure) { | 311 | if (!ret && mt9m001->autoexposure) { |
285 | ret = reg_write(icd, MT9M001_SHUTTER_WIDTH, | 312 | ret = reg_write(icd, MT9M001_SHUTTER_WIDTH, |
286 | rect->height + icd->y_skip_top + vblank); | 313 | rect->height + icd->y_skip_top + vblank); |
287 | if (ret >= 0) { | 314 | if (!ret) { |
288 | const struct v4l2_queryctrl *qctrl = | 315 | const struct v4l2_queryctrl *qctrl = |
289 | soc_camera_find_qctrl(icd->ops, | 316 | soc_camera_find_qctrl(icd->ops, |
290 | V4L2_CID_EXPOSURE); | 317 | V4L2_CID_EXPOSURE); |
@@ -295,7 +322,7 @@ static int mt9m001_set_fmt_cap(struct soc_camera_device *icd, | |||
295 | } | 322 | } |
296 | } | 323 | } |
297 | 324 | ||
298 | return ret < 0 ? ret : 0; | 325 | return ret; |
299 | } | 326 | } |
300 | 327 | ||
301 | static int mt9m001_try_fmt_cap(struct soc_camera_device *icd, | 328 | static int mt9m001_try_fmt_cap(struct soc_camera_device *icd, |
diff --git a/drivers/media/video/mt9m111.c b/drivers/media/video/mt9m111.c new file mode 100644 index 000000000000..da0b2d553fd0 --- /dev/null +++ b/drivers/media/video/mt9m111.c | |||
@@ -0,0 +1,973 @@ | |||
1 | /* | ||
2 | * Driver for MT9M111 CMOS Image Sensor from Micron | ||
3 | * | ||
4 | * Copyright (C) 2008, Robert Jarzmik <robert.jarzmik@free.fr> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | #include <linux/videodev2.h> | ||
11 | #include <linux/slab.h> | ||
12 | #include <linux/i2c.h> | ||
13 | #include <linux/log2.h> | ||
14 | #include <linux/gpio.h> | ||
15 | #include <linux/delay.h> | ||
16 | |||
17 | #include <media/v4l2-common.h> | ||
18 | #include <media/v4l2-chip-ident.h> | ||
19 | #include <media/soc_camera.h> | ||
20 | |||
21 | /* | ||
22 | * mt9m111 i2c address is 0x5d or 0x48 (depending on SAddr pin) | ||
23 | * The platform has to define i2c_board_info and call i2c_register_board_info() | ||
24 | */ | ||
25 | |||
26 | /* mt9m111: Sensor register addresses */ | ||
27 | #define MT9M111_CHIP_VERSION 0x000 | ||
28 | #define MT9M111_ROW_START 0x001 | ||
29 | #define MT9M111_COLUMN_START 0x002 | ||
30 | #define MT9M111_WINDOW_HEIGHT 0x003 | ||
31 | #define MT9M111_WINDOW_WIDTH 0x004 | ||
32 | #define MT9M111_HORIZONTAL_BLANKING_B 0x005 | ||
33 | #define MT9M111_VERTICAL_BLANKING_B 0x006 | ||
34 | #define MT9M111_HORIZONTAL_BLANKING_A 0x007 | ||
35 | #define MT9M111_VERTICAL_BLANKING_A 0x008 | ||
36 | #define MT9M111_SHUTTER_WIDTH 0x009 | ||
37 | #define MT9M111_ROW_SPEED 0x00a | ||
38 | #define MT9M111_EXTRA_DELAY 0x00b | ||
39 | #define MT9M111_SHUTTER_DELAY 0x00c | ||
40 | #define MT9M111_RESET 0x00d | ||
41 | #define MT9M111_READ_MODE_B 0x020 | ||
42 | #define MT9M111_READ_MODE_A 0x021 | ||
43 | #define MT9M111_FLASH_CONTROL 0x023 | ||
44 | #define MT9M111_GREEN1_GAIN 0x02b | ||
45 | #define MT9M111_BLUE_GAIN 0x02c | ||
46 | #define MT9M111_RED_GAIN 0x02d | ||
47 | #define MT9M111_GREEN2_GAIN 0x02e | ||
48 | #define MT9M111_GLOBAL_GAIN 0x02f | ||
49 | #define MT9M111_CONTEXT_CONTROL 0x0c8 | ||
50 | #define MT9M111_PAGE_MAP 0x0f0 | ||
51 | #define MT9M111_BYTE_WISE_ADDR 0x0f1 | ||
52 | |||
53 | #define MT9M111_RESET_SYNC_CHANGES (1 << 15) | ||
54 | #define MT9M111_RESET_RESTART_BAD_FRAME (1 << 9) | ||
55 | #define MT9M111_RESET_SHOW_BAD_FRAMES (1 << 8) | ||
56 | #define MT9M111_RESET_RESET_SOC (1 << 5) | ||
57 | #define MT9M111_RESET_OUTPUT_DISABLE (1 << 4) | ||
58 | #define MT9M111_RESET_CHIP_ENABLE (1 << 3) | ||
59 | #define MT9M111_RESET_ANALOG_STANDBY (1 << 2) | ||
60 | #define MT9M111_RESET_RESTART_FRAME (1 << 1) | ||
61 | #define MT9M111_RESET_RESET_MODE (1 << 0) | ||
62 | |||
63 | #define MT9M111_RMB_MIRROR_COLS (1 << 1) | ||
64 | #define MT9M111_RMB_MIRROR_ROWS (1 << 0) | ||
65 | #define MT9M111_CTXT_CTRL_RESTART (1 << 15) | ||
66 | #define MT9M111_CTXT_CTRL_DEFECTCOR_B (1 << 12) | ||
67 | #define MT9M111_CTXT_CTRL_RESIZE_B (1 << 10) | ||
68 | #define MT9M111_CTXT_CTRL_CTRL2_B (1 << 9) | ||
69 | #define MT9M111_CTXT_CTRL_GAMMA_B (1 << 8) | ||
70 | #define MT9M111_CTXT_CTRL_XENON_EN (1 << 7) | ||
71 | #define MT9M111_CTXT_CTRL_READ_MODE_B (1 << 3) | ||
72 | #define MT9M111_CTXT_CTRL_LED_FLASH_EN (1 << 2) | ||
73 | #define MT9M111_CTXT_CTRL_VBLANK_SEL_B (1 << 1) | ||
74 | #define MT9M111_CTXT_CTRL_HBLANK_SEL_B (1 << 0) | ||
75 | /* | ||
76 | * mt9m111: Colorpipe register addresses (0x100..0x1ff) | ||
77 | */ | ||
78 | #define MT9M111_OPER_MODE_CTRL 0x106 | ||
79 | #define MT9M111_OUTPUT_FORMAT_CTRL 0x108 | ||
80 | #define MT9M111_REDUCER_XZOOM_B 0x1a0 | ||
81 | #define MT9M111_REDUCER_XSIZE_B 0x1a1 | ||
82 | #define MT9M111_REDUCER_YZOOM_B 0x1a3 | ||
83 | #define MT9M111_REDUCER_YSIZE_B 0x1a4 | ||
84 | #define MT9M111_REDUCER_XZOOM_A 0x1a6 | ||
85 | #define MT9M111_REDUCER_XSIZE_A 0x1a7 | ||
86 | #define MT9M111_REDUCER_YZOOM_A 0x1a9 | ||
87 | #define MT9M111_REDUCER_YSIZE_A 0x1aa | ||
88 | |||
89 | #define MT9M111_OUTPUT_FORMAT_CTRL2_A 0x13a | ||
90 | #define MT9M111_OUTPUT_FORMAT_CTRL2_B 0x19b | ||
91 | |||
92 | #define MT9M111_OPMODE_AUTOEXPO_EN (1 << 14) | ||
93 | |||
94 | |||
95 | #define MT9M111_OUTFMT_PROCESSED_BAYER (1 << 14) | ||
96 | #define MT9M111_OUTFMT_BYPASS_IFP (1 << 10) | ||
97 | #define MT9M111_OUTFMT_INV_PIX_CLOCK (1 << 9) | ||
98 | #define MT9M111_OUTFMT_RGB (1 << 8) | ||
99 | #define MT9M111_OUTFMT_RGB565 (0x0 << 6) | ||
100 | #define MT9M111_OUTFMT_RGB555 (0x1 << 6) | ||
101 | #define MT9M111_OUTFMT_RGB444x (0x2 << 6) | ||
102 | #define MT9M111_OUTFMT_RGBx444 (0x3 << 6) | ||
103 | #define MT9M111_OUTFMT_TST_RAMP_OFF (0x0 << 4) | ||
104 | #define MT9M111_OUTFMT_TST_RAMP_COL (0x1 << 4) | ||
105 | #define MT9M111_OUTFMT_TST_RAMP_ROW (0x2 << 4) | ||
106 | #define MT9M111_OUTFMT_TST_RAMP_FRAME (0x3 << 4) | ||
107 | #define MT9M111_OUTFMT_SHIFT_3_UP (1 << 3) | ||
108 | #define MT9M111_OUTFMT_AVG_CHROMA (1 << 2) | ||
109 | #define MT9M111_OUTFMT_SWAP_YCbCr_C_Y (1 << 1) | ||
110 | #define MT9M111_OUTFMT_SWAP_RGB_EVEN (1 << 1) | ||
111 | #define MT9M111_OUTFMT_SWAP_YCbCr_Cb_Cr (1 << 0) | ||
112 | /* | ||
113 | * mt9m111: Camera control register addresses (0x200..0x2ff not implemented) | ||
114 | */ | ||
115 | |||
116 | #define reg_read(reg) mt9m111_reg_read(icd, MT9M111_##reg) | ||
117 | #define reg_write(reg, val) mt9m111_reg_write(icd, MT9M111_##reg, (val)) | ||
118 | #define reg_set(reg, val) mt9m111_reg_set(icd, MT9M111_##reg, (val)) | ||
119 | #define reg_clear(reg, val) mt9m111_reg_clear(icd, MT9M111_##reg, (val)) | ||
120 | |||
121 | #define MT9M111_MIN_DARK_ROWS 8 | ||
122 | #define MT9M111_MIN_DARK_COLS 24 | ||
123 | #define MT9M111_MAX_HEIGHT 1024 | ||
124 | #define MT9M111_MAX_WIDTH 1280 | ||
125 | |||
126 | #define COL_FMT(_name, _depth, _fourcc, _colorspace) \ | ||
127 | { .name = _name, .depth = _depth, .fourcc = _fourcc, \ | ||
128 | .colorspace = _colorspace } | ||
129 | #define RGB_FMT(_name, _depth, _fourcc) \ | ||
130 | COL_FMT(_name, _depth, _fourcc, V4L2_COLORSPACE_SRGB) | ||
131 | |||
132 | static const struct soc_camera_data_format mt9m111_colour_formats[] = { | ||
133 | COL_FMT("YCrYCb 8 bit", 8, V4L2_PIX_FMT_YUYV, V4L2_COLORSPACE_JPEG), | ||
134 | RGB_FMT("RGB 565", 16, V4L2_PIX_FMT_RGB565), | ||
135 | RGB_FMT("RGB 555", 16, V4L2_PIX_FMT_RGB555), | ||
136 | RGB_FMT("Bayer (sRGB) 10 bit", 10, V4L2_PIX_FMT_SBGGR16), | ||
137 | RGB_FMT("Bayer (sRGB) 8 bit", 8, V4L2_PIX_FMT_SBGGR8), | ||
138 | }; | ||
139 | |||
140 | enum mt9m111_context { | ||
141 | HIGHPOWER = 0, | ||
142 | LOWPOWER, | ||
143 | }; | ||
144 | |||
145 | struct mt9m111 { | ||
146 | struct i2c_client *client; | ||
147 | struct soc_camera_device icd; | ||
148 | int model; /* V4L2_IDENT_MT9M111* codes from v4l2-chip-ident.h */ | ||
149 | enum mt9m111_context context; | ||
150 | unsigned int left, top, width, height; | ||
151 | u32 pixfmt; | ||
152 | unsigned char autoexposure; | ||
153 | unsigned char datawidth; | ||
154 | unsigned int powered:1; | ||
155 | unsigned int hflip:1; | ||
156 | unsigned int vflip:1; | ||
157 | unsigned int swap_rgb_even_odd:1; | ||
158 | unsigned int swap_rgb_red_blue:1; | ||
159 | unsigned int swap_yuv_y_chromas:1; | ||
160 | unsigned int swap_yuv_cb_cr:1; | ||
161 | }; | ||
162 | |||
163 | static int reg_page_map_set(struct i2c_client *client, const u16 reg) | ||
164 | { | ||
165 | int ret; | ||
166 | u16 page; | ||
167 | static int lastpage = -1; /* PageMap cache value */ | ||
168 | |||
169 | page = (reg >> 8); | ||
170 | if (page == lastpage) | ||
171 | return 0; | ||
172 | if (page > 2) | ||
173 | return -EINVAL; | ||
174 | |||
175 | ret = i2c_smbus_write_word_data(client, MT9M111_PAGE_MAP, swab16(page)); | ||
176 | if (!ret) | ||
177 | lastpage = page; | ||
178 | return ret; | ||
179 | } | ||
180 | |||
181 | static int mt9m111_reg_read(struct soc_camera_device *icd, const u16 reg) | ||
182 | { | ||
183 | struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); | ||
184 | struct i2c_client *client = mt9m111->client; | ||
185 | int ret; | ||
186 | |||
187 | ret = reg_page_map_set(client, reg); | ||
188 | if (!ret) | ||
189 | ret = swab16(i2c_smbus_read_word_data(client, (reg & 0xff))); | ||
190 | |||
191 | dev_dbg(&icd->dev, "read reg.%03x -> %04x\n", reg, ret); | ||
192 | return ret; | ||
193 | } | ||
194 | |||
195 | static int mt9m111_reg_write(struct soc_camera_device *icd, const u16 reg, | ||
196 | const u16 data) | ||
197 | { | ||
198 | struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); | ||
199 | struct i2c_client *client = mt9m111->client; | ||
200 | int ret; | ||
201 | |||
202 | ret = reg_page_map_set(client, reg); | ||
203 | if (!ret) | ||
204 | ret = i2c_smbus_write_word_data(mt9m111->client, (reg & 0xff), | ||
205 | swab16(data)); | ||
206 | dev_dbg(&icd->dev, "write reg.%03x = %04x -> %d\n", reg, data, ret); | ||
207 | return ret; | ||
208 | } | ||
209 | |||
210 | static int mt9m111_reg_set(struct soc_camera_device *icd, const u16 reg, | ||
211 | const u16 data) | ||
212 | { | ||
213 | int ret; | ||
214 | |||
215 | ret = mt9m111_reg_read(icd, reg); | ||
216 | if (ret >= 0) | ||
217 | ret = mt9m111_reg_write(icd, reg, ret | data); | ||
218 | return ret; | ||
219 | } | ||
220 | |||
221 | static int mt9m111_reg_clear(struct soc_camera_device *icd, const u16 reg, | ||
222 | const u16 data) | ||
223 | { | ||
224 | int ret; | ||
225 | |||
226 | ret = mt9m111_reg_read(icd, reg); | ||
227 | return mt9m111_reg_write(icd, reg, ret & ~data); | ||
228 | } | ||
229 | |||
230 | static int mt9m111_set_context(struct soc_camera_device *icd, | ||
231 | enum mt9m111_context ctxt) | ||
232 | { | ||
233 | int valB = MT9M111_CTXT_CTRL_RESTART | MT9M111_CTXT_CTRL_DEFECTCOR_B | ||
234 | | MT9M111_CTXT_CTRL_RESIZE_B | MT9M111_CTXT_CTRL_CTRL2_B | ||
235 | | MT9M111_CTXT_CTRL_GAMMA_B | MT9M111_CTXT_CTRL_READ_MODE_B | ||
236 | | MT9M111_CTXT_CTRL_VBLANK_SEL_B | ||
237 | | MT9M111_CTXT_CTRL_HBLANK_SEL_B; | ||
238 | int valA = MT9M111_CTXT_CTRL_RESTART; | ||
239 | |||
240 | if (ctxt == HIGHPOWER) | ||
241 | return reg_write(CONTEXT_CONTROL, valB); | ||
242 | else | ||
243 | return reg_write(CONTEXT_CONTROL, valA); | ||
244 | } | ||
245 | |||
246 | static int mt9m111_setup_rect(struct soc_camera_device *icd) | ||
247 | { | ||
248 | struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); | ||
249 | int ret, is_raw_format; | ||
250 | int width = mt9m111->width; | ||
251 | int height = mt9m111->height; | ||
252 | |||
253 | if ((mt9m111->pixfmt == V4L2_PIX_FMT_SBGGR8) | ||
254 | || (mt9m111->pixfmt == V4L2_PIX_FMT_SBGGR16)) | ||
255 | is_raw_format = 1; | ||
256 | else | ||
257 | is_raw_format = 0; | ||
258 | |||
259 | ret = reg_write(COLUMN_START, mt9m111->left); | ||
260 | if (!ret) | ||
261 | ret = reg_write(ROW_START, mt9m111->top); | ||
262 | |||
263 | if (is_raw_format) { | ||
264 | if (!ret) | ||
265 | ret = reg_write(WINDOW_WIDTH, width); | ||
266 | if (!ret) | ||
267 | ret = reg_write(WINDOW_HEIGHT, height); | ||
268 | } else { | ||
269 | if (!ret) | ||
270 | ret = reg_write(REDUCER_XZOOM_B, MT9M111_MAX_WIDTH); | ||
271 | if (!ret) | ||
272 | ret = reg_write(REDUCER_YZOOM_B, MT9M111_MAX_HEIGHT); | ||
273 | if (!ret) | ||
274 | ret = reg_write(REDUCER_XSIZE_B, width); | ||
275 | if (!ret) | ||
276 | ret = reg_write(REDUCER_YSIZE_B, height); | ||
277 | if (!ret) | ||
278 | ret = reg_write(REDUCER_XZOOM_A, MT9M111_MAX_WIDTH); | ||
279 | if (!ret) | ||
280 | ret = reg_write(REDUCER_YZOOM_A, MT9M111_MAX_HEIGHT); | ||
281 | if (!ret) | ||
282 | ret = reg_write(REDUCER_XSIZE_A, width); | ||
283 | if (!ret) | ||
284 | ret = reg_write(REDUCER_YSIZE_A, height); | ||
285 | } | ||
286 | |||
287 | return ret; | ||
288 | } | ||
289 | |||
290 | static int mt9m111_setup_pixfmt(struct soc_camera_device *icd, u16 outfmt) | ||
291 | { | ||
292 | int ret; | ||
293 | |||
294 | ret = reg_write(OUTPUT_FORMAT_CTRL2_A, outfmt); | ||
295 | if (!ret) | ||
296 | ret = reg_write(OUTPUT_FORMAT_CTRL2_B, outfmt); | ||
297 | return ret; | ||
298 | } | ||
299 | |||
300 | static int mt9m111_setfmt_bayer8(struct soc_camera_device *icd) | ||
301 | { | ||
302 | return mt9m111_setup_pixfmt(icd, MT9M111_OUTFMT_PROCESSED_BAYER); | ||
303 | } | ||
304 | |||
305 | static int mt9m111_setfmt_bayer10(struct soc_camera_device *icd) | ||
306 | { | ||
307 | return mt9m111_setup_pixfmt(icd, MT9M111_OUTFMT_BYPASS_IFP); | ||
308 | } | ||
309 | |||
310 | static int mt9m111_setfmt_rgb565(struct soc_camera_device *icd) | ||
311 | { | ||
312 | struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); | ||
313 | int val = 0; | ||
314 | |||
315 | if (mt9m111->swap_rgb_red_blue) | ||
316 | val |= MT9M111_OUTFMT_SWAP_YCbCr_Cb_Cr; | ||
317 | if (mt9m111->swap_rgb_even_odd) | ||
318 | val |= MT9M111_OUTFMT_SWAP_RGB_EVEN; | ||
319 | val |= MT9M111_OUTFMT_RGB | MT9M111_OUTFMT_RGB565; | ||
320 | |||
321 | return mt9m111_setup_pixfmt(icd, val); | ||
322 | } | ||
323 | |||
324 | static int mt9m111_setfmt_rgb555(struct soc_camera_device *icd) | ||
325 | { | ||
326 | struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); | ||
327 | int val = 0; | ||
328 | |||
329 | if (mt9m111->swap_rgb_red_blue) | ||
330 | val |= MT9M111_OUTFMT_SWAP_YCbCr_Cb_Cr; | ||
331 | if (mt9m111->swap_rgb_even_odd) | ||
332 | val |= MT9M111_OUTFMT_SWAP_RGB_EVEN; | ||
333 | val |= MT9M111_OUTFMT_RGB | MT9M111_OUTFMT_RGB555; | ||
334 | |||
335 | return mt9m111_setup_pixfmt(icd, val); | ||
336 | } | ||
337 | |||
338 | static int mt9m111_setfmt_yuv(struct soc_camera_device *icd) | ||
339 | { | ||
340 | struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); | ||
341 | int val = 0; | ||
342 | |||
343 | if (mt9m111->swap_yuv_cb_cr) | ||
344 | val |= MT9M111_OUTFMT_SWAP_YCbCr_Cb_Cr; | ||
345 | if (mt9m111->swap_yuv_y_chromas) | ||
346 | val |= MT9M111_OUTFMT_SWAP_YCbCr_C_Y; | ||
347 | |||
348 | return mt9m111_setup_pixfmt(icd, val); | ||
349 | } | ||
350 | |||
351 | static int mt9m111_enable(struct soc_camera_device *icd) | ||
352 | { | ||
353 | struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); | ||
354 | struct soc_camera_link *icl = mt9m111->client->dev.platform_data; | ||
355 | int ret; | ||
356 | |||
357 | if (icl->power) { | ||
358 | ret = icl->power(&mt9m111->client->dev, 1); | ||
359 | if (ret < 0) { | ||
360 | dev_err(icd->vdev->parent, | ||
361 | "Platform failed to power-on the camera.\n"); | ||
362 | return ret; | ||
363 | } | ||
364 | } | ||
365 | |||
366 | ret = reg_set(RESET, MT9M111_RESET_CHIP_ENABLE); | ||
367 | if (!ret) | ||
368 | mt9m111->powered = 1; | ||
369 | return ret; | ||
370 | } | ||
371 | |||
372 | static int mt9m111_disable(struct soc_camera_device *icd) | ||
373 | { | ||
374 | struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); | ||
375 | struct soc_camera_link *icl = mt9m111->client->dev.platform_data; | ||
376 | int ret; | ||
377 | |||
378 | ret = reg_clear(RESET, MT9M111_RESET_CHIP_ENABLE); | ||
379 | if (!ret) | ||
380 | mt9m111->powered = 0; | ||
381 | |||
382 | if (icl->power) | ||
383 | icl->power(&mt9m111->client->dev, 0); | ||
384 | |||
385 | return ret; | ||
386 | } | ||
387 | |||
388 | static int mt9m111_reset(struct soc_camera_device *icd) | ||
389 | { | ||
390 | int ret; | ||
391 | |||
392 | ret = reg_set(RESET, MT9M111_RESET_RESET_MODE); | ||
393 | if (!ret) | ||
394 | ret = reg_set(RESET, MT9M111_RESET_RESET_SOC); | ||
395 | if (!ret) | ||
396 | ret = reg_clear(RESET, MT9M111_RESET_RESET_MODE | ||
397 | | MT9M111_RESET_RESET_SOC); | ||
398 | return ret; | ||
399 | } | ||
400 | |||
401 | static int mt9m111_start_capture(struct soc_camera_device *icd) | ||
402 | { | ||
403 | return 0; | ||
404 | } | ||
405 | |||
406 | static int mt9m111_stop_capture(struct soc_camera_device *icd) | ||
407 | { | ||
408 | return 0; | ||
409 | } | ||
410 | |||
411 | static unsigned long mt9m111_query_bus_param(struct soc_camera_device *icd) | ||
412 | { | ||
413 | return SOCAM_MASTER | SOCAM_PCLK_SAMPLE_RISING | | ||
414 | SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_HIGH | | ||
415 | SOCAM_DATAWIDTH_8; | ||
416 | } | ||
417 | |||
418 | static int mt9m111_set_bus_param(struct soc_camera_device *icd, unsigned long f) | ||
419 | { | ||
420 | return 0; | ||
421 | } | ||
422 | |||
423 | static int mt9m111_set_pixfmt(struct soc_camera_device *icd, u32 pixfmt) | ||
424 | { | ||
425 | struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); | ||
426 | int ret; | ||
427 | |||
428 | switch (pixfmt) { | ||
429 | case V4L2_PIX_FMT_SBGGR8: | ||
430 | ret = mt9m111_setfmt_bayer8(icd); | ||
431 | break; | ||
432 | case V4L2_PIX_FMT_SBGGR16: | ||
433 | ret = mt9m111_setfmt_bayer10(icd); | ||
434 | break; | ||
435 | case V4L2_PIX_FMT_RGB555: | ||
436 | ret = mt9m111_setfmt_rgb555(icd); | ||
437 | break; | ||
438 | case V4L2_PIX_FMT_RGB565: | ||
439 | ret = mt9m111_setfmt_rgb565(icd); | ||
440 | break; | ||
441 | case V4L2_PIX_FMT_YUYV: | ||
442 | ret = mt9m111_setfmt_yuv(icd); | ||
443 | break; | ||
444 | default: | ||
445 | dev_err(&icd->dev, "Pixel format not handled : %x\n", pixfmt); | ||
446 | ret = -EINVAL; | ||
447 | } | ||
448 | |||
449 | if (!ret) | ||
450 | mt9m111->pixfmt = pixfmt; | ||
451 | |||
452 | return ret; | ||
453 | } | ||
454 | |||
455 | static int mt9m111_set_fmt_cap(struct soc_camera_device *icd, | ||
456 | __u32 pixfmt, struct v4l2_rect *rect) | ||
457 | { | ||
458 | struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); | ||
459 | int ret; | ||
460 | |||
461 | mt9m111->left = rect->left; | ||
462 | mt9m111->top = rect->top; | ||
463 | mt9m111->width = rect->width; | ||
464 | mt9m111->height = rect->height; | ||
465 | |||
466 | dev_dbg(&icd->dev, "%s fmt=%x left=%d, top=%d, width=%d, height=%d\n", | ||
467 | __func__, pixfmt, mt9m111->left, mt9m111->top, mt9m111->width, | ||
468 | mt9m111->height); | ||
469 | |||
470 | ret = mt9m111_setup_rect(icd); | ||
471 | if (!ret) | ||
472 | ret = mt9m111_set_pixfmt(icd, pixfmt); | ||
473 | return ret; | ||
474 | } | ||
475 | |||
476 | static int mt9m111_try_fmt_cap(struct soc_camera_device *icd, | ||
477 | struct v4l2_format *f) | ||
478 | { | ||
479 | if (f->fmt.pix.height > MT9M111_MAX_HEIGHT) | ||
480 | f->fmt.pix.height = MT9M111_MAX_HEIGHT; | ||
481 | if (f->fmt.pix.width > MT9M111_MAX_WIDTH) | ||
482 | f->fmt.pix.width = MT9M111_MAX_WIDTH; | ||
483 | |||
484 | return 0; | ||
485 | } | ||
486 | |||
487 | static int mt9m111_get_chip_id(struct soc_camera_device *icd, | ||
488 | struct v4l2_chip_ident *id) | ||
489 | { | ||
490 | struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); | ||
491 | |||
492 | if (id->match_type != V4L2_CHIP_MATCH_I2C_ADDR) | ||
493 | return -EINVAL; | ||
494 | |||
495 | if (id->match_chip != mt9m111->client->addr) | ||
496 | return -ENODEV; | ||
497 | |||
498 | id->ident = mt9m111->model; | ||
499 | id->revision = 0; | ||
500 | |||
501 | return 0; | ||
502 | } | ||
503 | |||
504 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
505 | static int mt9m111_get_register(struct soc_camera_device *icd, | ||
506 | struct v4l2_register *reg) | ||
507 | { | ||
508 | int val; | ||
509 | |||
510 | struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); | ||
511 | |||
512 | if (reg->match_type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0x2ff) | ||
513 | return -EINVAL; | ||
514 | if (reg->match_chip != mt9m111->client->addr) | ||
515 | return -ENODEV; | ||
516 | |||
517 | val = mt9m111_reg_read(icd, reg->reg); | ||
518 | reg->val = (u64)val; | ||
519 | |||
520 | if (reg->val > 0xffff) | ||
521 | return -EIO; | ||
522 | |||
523 | return 0; | ||
524 | } | ||
525 | |||
526 | static int mt9m111_set_register(struct soc_camera_device *icd, | ||
527 | struct v4l2_register *reg) | ||
528 | { | ||
529 | struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); | ||
530 | |||
531 | if (reg->match_type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0x2ff) | ||
532 | return -EINVAL; | ||
533 | |||
534 | if (reg->match_chip != mt9m111->client->addr) | ||
535 | return -ENODEV; | ||
536 | |||
537 | if (mt9m111_reg_write(icd, reg->reg, reg->val) < 0) | ||
538 | return -EIO; | ||
539 | |||
540 | return 0; | ||
541 | } | ||
542 | #endif | ||
543 | |||
544 | static const struct v4l2_queryctrl mt9m111_controls[] = { | ||
545 | { | ||
546 | .id = V4L2_CID_VFLIP, | ||
547 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
548 | .name = "Flip Verticaly", | ||
549 | .minimum = 0, | ||
550 | .maximum = 1, | ||
551 | .step = 1, | ||
552 | .default_value = 0, | ||
553 | }, { | ||
554 | .id = V4L2_CID_HFLIP, | ||
555 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
556 | .name = "Flip Horizontaly", | ||
557 | .minimum = 0, | ||
558 | .maximum = 1, | ||
559 | .step = 1, | ||
560 | .default_value = 0, | ||
561 | }, { /* gain = 1/32*val (=>gain=1 if val==32) */ | ||
562 | .id = V4L2_CID_GAIN, | ||
563 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
564 | .name = "Gain", | ||
565 | .minimum = 0, | ||
566 | .maximum = 63 * 2 * 2, | ||
567 | .step = 1, | ||
568 | .default_value = 32, | ||
569 | .flags = V4L2_CTRL_FLAG_SLIDER, | ||
570 | }, { | ||
571 | .id = V4L2_CID_EXPOSURE_AUTO, | ||
572 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
573 | .name = "Auto Exposure", | ||
574 | .minimum = 0, | ||
575 | .maximum = 1, | ||
576 | .step = 1, | ||
577 | .default_value = 1, | ||
578 | } | ||
579 | }; | ||
580 | |||
581 | static int mt9m111_video_probe(struct soc_camera_device *); | ||
582 | static void mt9m111_video_remove(struct soc_camera_device *); | ||
583 | static int mt9m111_get_control(struct soc_camera_device *, | ||
584 | struct v4l2_control *); | ||
585 | static int mt9m111_set_control(struct soc_camera_device *, | ||
586 | struct v4l2_control *); | ||
587 | static int mt9m111_resume(struct soc_camera_device *icd); | ||
588 | static int mt9m111_init(struct soc_camera_device *icd); | ||
589 | static int mt9m111_release(struct soc_camera_device *icd); | ||
590 | |||
591 | static struct soc_camera_ops mt9m111_ops = { | ||
592 | .owner = THIS_MODULE, | ||
593 | .probe = mt9m111_video_probe, | ||
594 | .remove = mt9m111_video_remove, | ||
595 | .init = mt9m111_init, | ||
596 | .resume = mt9m111_resume, | ||
597 | .release = mt9m111_release, | ||
598 | .start_capture = mt9m111_start_capture, | ||
599 | .stop_capture = mt9m111_stop_capture, | ||
600 | .set_fmt_cap = mt9m111_set_fmt_cap, | ||
601 | .try_fmt_cap = mt9m111_try_fmt_cap, | ||
602 | .query_bus_param = mt9m111_query_bus_param, | ||
603 | .set_bus_param = mt9m111_set_bus_param, | ||
604 | .controls = mt9m111_controls, | ||
605 | .num_controls = ARRAY_SIZE(mt9m111_controls), | ||
606 | .get_control = mt9m111_get_control, | ||
607 | .set_control = mt9m111_set_control, | ||
608 | .get_chip_id = mt9m111_get_chip_id, | ||
609 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
610 | .get_register = mt9m111_get_register, | ||
611 | .set_register = mt9m111_set_register, | ||
612 | #endif | ||
613 | }; | ||
614 | |||
615 | static int mt9m111_set_flip(struct soc_camera_device *icd, int flip, int mask) | ||
616 | { | ||
617 | struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); | ||
618 | int ret; | ||
619 | |||
620 | if (mt9m111->context == HIGHPOWER) { | ||
621 | if (flip) | ||
622 | ret = reg_set(READ_MODE_B, mask); | ||
623 | else | ||
624 | ret = reg_clear(READ_MODE_B, mask); | ||
625 | } else { | ||
626 | if (flip) | ||
627 | ret = reg_set(READ_MODE_A, mask); | ||
628 | else | ||
629 | ret = reg_clear(READ_MODE_A, mask); | ||
630 | } | ||
631 | |||
632 | return ret; | ||
633 | } | ||
634 | |||
635 | static int mt9m111_get_global_gain(struct soc_camera_device *icd) | ||
636 | { | ||
637 | unsigned int data, gain; | ||
638 | |||
639 | data = reg_read(GLOBAL_GAIN); | ||
640 | if (data >= 0) | ||
641 | gain = ((data & (1 << 10)) * 2) | ||
642 | | ((data & (1 << 9)) * 2) | ||
643 | | (data & 0x2f); | ||
644 | else | ||
645 | gain = data; | ||
646 | |||
647 | return gain; | ||
648 | } | ||
649 | static int mt9m111_set_global_gain(struct soc_camera_device *icd, int gain) | ||
650 | { | ||
651 | u16 val; | ||
652 | |||
653 | if (gain > 63 * 2 * 2) | ||
654 | return -EINVAL; | ||
655 | |||
656 | icd->gain = gain; | ||
657 | if ((gain >= 64 * 2) && (gain < 63 * 2 * 2)) | ||
658 | val = (1 << 10) | (1 << 9) | (gain / 4); | ||
659 | else if ((gain >= 64) && (gain < 64 * 2)) | ||
660 | val = (1 << 9) | (gain / 2); | ||
661 | else | ||
662 | val = gain; | ||
663 | |||
664 | return reg_write(GLOBAL_GAIN, val); | ||
665 | } | ||
666 | |||
667 | static int mt9m111_set_autoexposure(struct soc_camera_device *icd, int on) | ||
668 | { | ||
669 | struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); | ||
670 | int ret; | ||
671 | |||
672 | if (on) | ||
673 | ret = reg_set(OPER_MODE_CTRL, MT9M111_OPMODE_AUTOEXPO_EN); | ||
674 | else | ||
675 | ret = reg_clear(OPER_MODE_CTRL, MT9M111_OPMODE_AUTOEXPO_EN); | ||
676 | |||
677 | if (!ret) | ||
678 | mt9m111->autoexposure = on; | ||
679 | |||
680 | return ret; | ||
681 | } | ||
682 | static int mt9m111_get_control(struct soc_camera_device *icd, | ||
683 | struct v4l2_control *ctrl) | ||
684 | { | ||
685 | struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); | ||
686 | int data; | ||
687 | |||
688 | switch (ctrl->id) { | ||
689 | case V4L2_CID_VFLIP: | ||
690 | if (mt9m111->context == HIGHPOWER) | ||
691 | data = reg_read(READ_MODE_B); | ||
692 | else | ||
693 | data = reg_read(READ_MODE_A); | ||
694 | |||
695 | if (data < 0) | ||
696 | return -EIO; | ||
697 | ctrl->value = !!(data & MT9M111_RMB_MIRROR_ROWS); | ||
698 | break; | ||
699 | case V4L2_CID_HFLIP: | ||
700 | if (mt9m111->context == HIGHPOWER) | ||
701 | data = reg_read(READ_MODE_B); | ||
702 | else | ||
703 | data = reg_read(READ_MODE_A); | ||
704 | |||
705 | if (data < 0) | ||
706 | return -EIO; | ||
707 | ctrl->value = !!(data & MT9M111_RMB_MIRROR_COLS); | ||
708 | break; | ||
709 | case V4L2_CID_GAIN: | ||
710 | data = mt9m111_get_global_gain(icd); | ||
711 | if (data < 0) | ||
712 | return data; | ||
713 | ctrl->value = data; | ||
714 | break; | ||
715 | case V4L2_CID_EXPOSURE_AUTO: | ||
716 | ctrl->value = mt9m111->autoexposure; | ||
717 | break; | ||
718 | } | ||
719 | return 0; | ||
720 | } | ||
721 | |||
722 | static int mt9m111_set_control(struct soc_camera_device *icd, | ||
723 | struct v4l2_control *ctrl) | ||
724 | { | ||
725 | struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); | ||
726 | const struct v4l2_queryctrl *qctrl; | ||
727 | int ret; | ||
728 | |||
729 | qctrl = soc_camera_find_qctrl(&mt9m111_ops, ctrl->id); | ||
730 | |||
731 | if (!qctrl) | ||
732 | return -EINVAL; | ||
733 | |||
734 | switch (ctrl->id) { | ||
735 | case V4L2_CID_VFLIP: | ||
736 | mt9m111->vflip = ctrl->value; | ||
737 | ret = mt9m111_set_flip(icd, ctrl->value, | ||
738 | MT9M111_RMB_MIRROR_ROWS); | ||
739 | break; | ||
740 | case V4L2_CID_HFLIP: | ||
741 | mt9m111->hflip = ctrl->value; | ||
742 | ret = mt9m111_set_flip(icd, ctrl->value, | ||
743 | MT9M111_RMB_MIRROR_COLS); | ||
744 | break; | ||
745 | case V4L2_CID_GAIN: | ||
746 | ret = mt9m111_set_global_gain(icd, ctrl->value); | ||
747 | break; | ||
748 | case V4L2_CID_EXPOSURE_AUTO: | ||
749 | ret = mt9m111_set_autoexposure(icd, ctrl->value); | ||
750 | break; | ||
751 | default: | ||
752 | ret = -EINVAL; | ||
753 | } | ||
754 | |||
755 | return ret; | ||
756 | } | ||
757 | |||
758 | static int mt9m111_restore_state(struct soc_camera_device *icd) | ||
759 | { | ||
760 | struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); | ||
761 | |||
762 | mt9m111_set_context(icd, mt9m111->context); | ||
763 | mt9m111_set_pixfmt(icd, mt9m111->pixfmt); | ||
764 | mt9m111_setup_rect(icd); | ||
765 | mt9m111_set_flip(icd, mt9m111->hflip, MT9M111_RMB_MIRROR_COLS); | ||
766 | mt9m111_set_flip(icd, mt9m111->vflip, MT9M111_RMB_MIRROR_ROWS); | ||
767 | mt9m111_set_global_gain(icd, icd->gain); | ||
768 | mt9m111_set_autoexposure(icd, mt9m111->autoexposure); | ||
769 | return 0; | ||
770 | } | ||
771 | |||
772 | static int mt9m111_resume(struct soc_camera_device *icd) | ||
773 | { | ||
774 | struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); | ||
775 | int ret = 0; | ||
776 | |||
777 | if (mt9m111->powered) { | ||
778 | ret = mt9m111_enable(icd); | ||
779 | if (!ret) | ||
780 | ret = mt9m111_reset(icd); | ||
781 | if (!ret) | ||
782 | ret = mt9m111_restore_state(icd); | ||
783 | } | ||
784 | return ret; | ||
785 | } | ||
786 | |||
787 | static int mt9m111_init(struct soc_camera_device *icd) | ||
788 | { | ||
789 | struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); | ||
790 | int ret; | ||
791 | |||
792 | mt9m111->context = HIGHPOWER; | ||
793 | ret = mt9m111_enable(icd); | ||
794 | if (!ret) | ||
795 | ret = mt9m111_reset(icd); | ||
796 | if (!ret) | ||
797 | ret = mt9m111_set_context(icd, mt9m111->context); | ||
798 | if (!ret) | ||
799 | ret = mt9m111_set_autoexposure(icd, mt9m111->autoexposure); | ||
800 | if (ret) | ||
801 | dev_err(&icd->dev, "mt9m111 init failed: %d\n", ret); | ||
802 | return ret; | ||
803 | } | ||
804 | |||
805 | static int mt9m111_release(struct soc_camera_device *icd) | ||
806 | { | ||
807 | int ret; | ||
808 | |||
809 | ret = mt9m111_disable(icd); | ||
810 | if (ret < 0) | ||
811 | dev_err(&icd->dev, "mt9m111 release failed: %d\n", ret); | ||
812 | |||
813 | return ret; | ||
814 | } | ||
815 | |||
816 | /* | ||
817 | * Interface active, can use i2c. If it fails, it can indeed mean, that | ||
818 | * this wasn't our capture interface, so, we wait for the right one | ||
819 | */ | ||
820 | static int mt9m111_video_probe(struct soc_camera_device *icd) | ||
821 | { | ||
822 | struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); | ||
823 | s32 data; | ||
824 | int ret; | ||
825 | |||
826 | /* | ||
827 | * We must have a parent by now. And it cannot be a wrong one. | ||
828 | * So this entire test is completely redundant. | ||
829 | */ | ||
830 | if (!icd->dev.parent || | ||
831 | to_soc_camera_host(icd->dev.parent)->nr != icd->iface) | ||
832 | return -ENODEV; | ||
833 | |||
834 | ret = mt9m111_enable(icd); | ||
835 | if (ret) | ||
836 | goto ei2c; | ||
837 | ret = mt9m111_reset(icd); | ||
838 | if (ret) | ||
839 | goto ei2c; | ||
840 | |||
841 | data = reg_read(CHIP_VERSION); | ||
842 | |||
843 | switch (data) { | ||
844 | case 0x143a: | ||
845 | mt9m111->model = V4L2_IDENT_MT9M111; | ||
846 | icd->formats = mt9m111_colour_formats; | ||
847 | icd->num_formats = ARRAY_SIZE(mt9m111_colour_formats); | ||
848 | break; | ||
849 | default: | ||
850 | ret = -ENODEV; | ||
851 | dev_err(&icd->dev, | ||
852 | "No MT9M111 chip detected, register read %x\n", data); | ||
853 | goto ei2c; | ||
854 | } | ||
855 | |||
856 | dev_info(&icd->dev, "Detected a MT9M111 chip ID 0x143a\n"); | ||
857 | |||
858 | ret = soc_camera_video_start(icd); | ||
859 | if (ret) | ||
860 | goto eisis; | ||
861 | |||
862 | mt9m111->autoexposure = 1; | ||
863 | |||
864 | mt9m111->swap_rgb_even_odd = 1; | ||
865 | mt9m111->swap_rgb_red_blue = 1; | ||
866 | |||
867 | return 0; | ||
868 | eisis: | ||
869 | ei2c: | ||
870 | return ret; | ||
871 | } | ||
872 | |||
873 | static void mt9m111_video_remove(struct soc_camera_device *icd) | ||
874 | { | ||
875 | struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); | ||
876 | |||
877 | dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", mt9m111->client->addr, | ||
878 | mt9m111->icd.dev.parent, mt9m111->icd.vdev); | ||
879 | soc_camera_video_stop(&mt9m111->icd); | ||
880 | } | ||
881 | |||
882 | static int mt9m111_probe(struct i2c_client *client, | ||
883 | const struct i2c_device_id *did) | ||
884 | { | ||
885 | struct mt9m111 *mt9m111; | ||
886 | struct soc_camera_device *icd; | ||
887 | struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); | ||
888 | struct soc_camera_link *icl = client->dev.platform_data; | ||
889 | int ret; | ||
890 | |||
891 | if (!icl) { | ||
892 | dev_err(&client->dev, "MT9M111 driver needs platform data\n"); | ||
893 | return -EINVAL; | ||
894 | } | ||
895 | |||
896 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA)) { | ||
897 | dev_warn(&adapter->dev, | ||
898 | "I2C-Adapter doesn't support I2C_FUNC_SMBUS_WORD\n"); | ||
899 | return -EIO; | ||
900 | } | ||
901 | |||
902 | mt9m111 = kzalloc(sizeof(struct mt9m111), GFP_KERNEL); | ||
903 | if (!mt9m111) | ||
904 | return -ENOMEM; | ||
905 | |||
906 | mt9m111->client = client; | ||
907 | i2c_set_clientdata(client, mt9m111); | ||
908 | |||
909 | /* Second stage probe - when a capture adapter is there */ | ||
910 | icd = &mt9m111->icd; | ||
911 | icd->ops = &mt9m111_ops; | ||
912 | icd->control = &client->dev; | ||
913 | icd->x_min = MT9M111_MIN_DARK_COLS; | ||
914 | icd->y_min = MT9M111_MIN_DARK_ROWS; | ||
915 | icd->x_current = icd->x_min; | ||
916 | icd->y_current = icd->y_min; | ||
917 | icd->width_min = MT9M111_MIN_DARK_ROWS; | ||
918 | icd->width_max = MT9M111_MAX_WIDTH; | ||
919 | icd->height_min = MT9M111_MIN_DARK_COLS; | ||
920 | icd->height_max = MT9M111_MAX_HEIGHT; | ||
921 | icd->y_skip_top = 0; | ||
922 | icd->iface = icl->bus_id; | ||
923 | |||
924 | ret = soc_camera_device_register(icd); | ||
925 | if (ret) | ||
926 | goto eisdr; | ||
927 | return 0; | ||
928 | |||
929 | eisdr: | ||
930 | kfree(mt9m111); | ||
931 | return ret; | ||
932 | } | ||
933 | |||
934 | static int mt9m111_remove(struct i2c_client *client) | ||
935 | { | ||
936 | struct mt9m111 *mt9m111 = i2c_get_clientdata(client); | ||
937 | soc_camera_device_unregister(&mt9m111->icd); | ||
938 | kfree(mt9m111); | ||
939 | |||
940 | return 0; | ||
941 | } | ||
942 | |||
943 | static const struct i2c_device_id mt9m111_id[] = { | ||
944 | { "mt9m111", 0 }, | ||
945 | { } | ||
946 | }; | ||
947 | MODULE_DEVICE_TABLE(i2c, mt9m111_id); | ||
948 | |||
949 | static struct i2c_driver mt9m111_i2c_driver = { | ||
950 | .driver = { | ||
951 | .name = "mt9m111", | ||
952 | }, | ||
953 | .probe = mt9m111_probe, | ||
954 | .remove = mt9m111_remove, | ||
955 | .id_table = mt9m111_id, | ||
956 | }; | ||
957 | |||
958 | static int __init mt9m111_mod_init(void) | ||
959 | { | ||
960 | return i2c_add_driver(&mt9m111_i2c_driver); | ||
961 | } | ||
962 | |||
963 | static void __exit mt9m111_mod_exit(void) | ||
964 | { | ||
965 | i2c_del_driver(&mt9m111_i2c_driver); | ||
966 | } | ||
967 | |||
968 | module_init(mt9m111_mod_init); | ||
969 | module_exit(mt9m111_mod_exit); | ||
970 | |||
971 | MODULE_DESCRIPTION("Micron MT9M111 Camera driver"); | ||
972 | MODULE_AUTHOR("Robert Jarzmik"); | ||
973 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/video/mt9v022.c b/drivers/media/video/mt9v022.c index 56808cd2f8a9..2584201059d8 100644 --- a/drivers/media/video/mt9v022.c +++ b/drivers/media/video/mt9v022.c | |||
@@ -134,34 +134,56 @@ static int reg_clear(struct soc_camera_device *icd, const u8 reg, | |||
134 | static int mt9v022_init(struct soc_camera_device *icd) | 134 | static int mt9v022_init(struct soc_camera_device *icd) |
135 | { | 135 | { |
136 | struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); | 136 | struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); |
137 | struct soc_camera_link *icl = mt9v022->client->dev.platform_data; | ||
137 | int ret; | 138 | int ret; |
138 | 139 | ||
140 | if (icl->power) { | ||
141 | ret = icl->power(&mt9v022->client->dev, 1); | ||
142 | if (ret < 0) { | ||
143 | dev_err(icd->vdev->parent, | ||
144 | "Platform failed to power-on the camera.\n"); | ||
145 | return ret; | ||
146 | } | ||
147 | } | ||
148 | |||
149 | /* | ||
150 | * The camera could have been already on, we hard-reset it additionally, | ||
151 | * if available. Soft reset is done in video_probe(). | ||
152 | */ | ||
153 | if (icl->reset) | ||
154 | icl->reset(&mt9v022->client->dev); | ||
155 | |||
139 | /* Almost the default mode: master, parallel, simultaneous, and an | 156 | /* Almost the default mode: master, parallel, simultaneous, and an |
140 | * undocumented bit 0x200, which is present in table 7, but not in 8, | 157 | * undocumented bit 0x200, which is present in table 7, but not in 8, |
141 | * plus snapshot mode to disable scan for now */ | 158 | * plus snapshot mode to disable scan for now */ |
142 | mt9v022->chip_control |= 0x10; | 159 | mt9v022->chip_control |= 0x10; |
143 | ret = reg_write(icd, MT9V022_CHIP_CONTROL, mt9v022->chip_control); | 160 | ret = reg_write(icd, MT9V022_CHIP_CONTROL, mt9v022->chip_control); |
144 | if (ret >= 0) | 161 | if (!ret) |
145 | reg_write(icd, MT9V022_READ_MODE, 0x300); | 162 | ret = reg_write(icd, MT9V022_READ_MODE, 0x300); |
146 | 163 | ||
147 | /* All defaults */ | 164 | /* All defaults */ |
148 | if (ret >= 0) | 165 | if (!ret) |
149 | /* AEC, AGC on */ | 166 | /* AEC, AGC on */ |
150 | ret = reg_set(icd, MT9V022_AEC_AGC_ENABLE, 0x3); | 167 | ret = reg_set(icd, MT9V022_AEC_AGC_ENABLE, 0x3); |
151 | if (ret >= 0) | 168 | if (!ret) |
152 | ret = reg_write(icd, MT9V022_MAX_TOTAL_SHUTTER_WIDTH, 480); | 169 | ret = reg_write(icd, MT9V022_MAX_TOTAL_SHUTTER_WIDTH, 480); |
153 | if (ret >= 0) | 170 | if (!ret) |
154 | /* default - auto */ | 171 | /* default - auto */ |
155 | ret = reg_clear(icd, MT9V022_BLACK_LEVEL_CALIB_CTRL, 1); | 172 | ret = reg_clear(icd, MT9V022_BLACK_LEVEL_CALIB_CTRL, 1); |
156 | if (ret >= 0) | 173 | if (!ret) |
157 | ret = reg_write(icd, MT9V022_DIGITAL_TEST_PATTERN, 0); | 174 | ret = reg_write(icd, MT9V022_DIGITAL_TEST_PATTERN, 0); |
158 | 175 | ||
159 | return ret >= 0 ? 0 : -EIO; | 176 | return ret; |
160 | } | 177 | } |
161 | 178 | ||
162 | static int mt9v022_release(struct soc_camera_device *icd) | 179 | static int mt9v022_release(struct soc_camera_device *icd) |
163 | { | 180 | { |
164 | /* Nothing? */ | 181 | struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); |
182 | struct soc_camera_link *icl = mt9v022->client->dev.platform_data; | ||
183 | |||
184 | if (icl->power) | ||
185 | icl->power(&mt9v022->client->dev, 0); | ||
186 | |||
165 | return 0; | 187 | return 0; |
166 | } | 188 | } |
167 | 189 | ||
@@ -352,21 +374,21 @@ static int mt9v022_set_fmt_cap(struct soc_camera_device *icd, | |||
352 | rect->height + icd->y_skip_top + 43); | 374 | rect->height + icd->y_skip_top + 43); |
353 | } | 375 | } |
354 | /* Setup frame format: defaults apart from width and height */ | 376 | /* Setup frame format: defaults apart from width and height */ |
355 | if (ret >= 0) | 377 | if (!ret) |
356 | ret = reg_write(icd, MT9V022_COLUMN_START, rect->left); | 378 | ret = reg_write(icd, MT9V022_COLUMN_START, rect->left); |
357 | if (ret >= 0) | 379 | if (!ret) |
358 | ret = reg_write(icd, MT9V022_ROW_START, rect->top); | 380 | ret = reg_write(icd, MT9V022_ROW_START, rect->top); |
359 | if (ret >= 0) | 381 | if (!ret) |
360 | /* Default 94, Phytec driver says: | 382 | /* Default 94, Phytec driver says: |
361 | * "width + horizontal blank >= 660" */ | 383 | * "width + horizontal blank >= 660" */ |
362 | ret = reg_write(icd, MT9V022_HORIZONTAL_BLANKING, | 384 | ret = reg_write(icd, MT9V022_HORIZONTAL_BLANKING, |
363 | rect->width > 660 - 43 ? 43 : | 385 | rect->width > 660 - 43 ? 43 : |
364 | 660 - rect->width); | 386 | 660 - rect->width); |
365 | if (ret >= 0) | 387 | if (!ret) |
366 | ret = reg_write(icd, MT9V022_VERTICAL_BLANKING, 45); | 388 | ret = reg_write(icd, MT9V022_VERTICAL_BLANKING, 45); |
367 | if (ret >= 0) | 389 | if (!ret) |
368 | ret = reg_write(icd, MT9V022_WINDOW_WIDTH, rect->width); | 390 | ret = reg_write(icd, MT9V022_WINDOW_WIDTH, rect->width); |
369 | if (ret >= 0) | 391 | if (!ret) |
370 | ret = reg_write(icd, MT9V022_WINDOW_HEIGHT, | 392 | ret = reg_write(icd, MT9V022_WINDOW_HEIGHT, |
371 | rect->height + icd->y_skip_top); | 393 | rect->height + icd->y_skip_top); |
372 | 394 | ||
@@ -717,7 +739,7 @@ static int mt9v022_video_probe(struct soc_camera_device *icd) | |||
717 | icd->num_formats = 1; | 739 | icd->num_formats = 1; |
718 | } | 740 | } |
719 | 741 | ||
720 | if (ret >= 0) | 742 | if (!ret) |
721 | ret = soc_camera_video_start(icd); | 743 | ret = soc_camera_video_start(icd); |
722 | if (ret < 0) | 744 | if (ret < 0) |
723 | goto eisis; | 745 | goto eisis; |
diff --git a/drivers/media/video/mxb.c b/drivers/media/video/mxb.c index 8ef578caba3b..7f130284b5c7 100644 --- a/drivers/media/video/mxb.c +++ b/drivers/media/video/mxb.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <media/tuner.h> | 27 | #include <media/tuner.h> |
28 | #include <linux/video_decoder.h> | 28 | #include <linux/video_decoder.h> |
29 | #include <media/v4l2-common.h> | 29 | #include <media/v4l2-common.h> |
30 | #include <media/saa7115.h> | ||
30 | 31 | ||
31 | #include "mxb.h" | 32 | #include "mxb.h" |
32 | #include "tea6415c.h" | 33 | #include "tea6415c.h" |
@@ -122,6 +123,8 @@ static struct saa7146_extension_ioctls ioctls[] = { | |||
122 | { VIDIOC_S_FREQUENCY, SAA7146_EXCLUSIVE }, | 123 | { VIDIOC_S_FREQUENCY, SAA7146_EXCLUSIVE }, |
123 | { VIDIOC_G_AUDIO, SAA7146_EXCLUSIVE }, | 124 | { VIDIOC_G_AUDIO, SAA7146_EXCLUSIVE }, |
124 | { VIDIOC_S_AUDIO, SAA7146_EXCLUSIVE }, | 125 | { VIDIOC_S_AUDIO, SAA7146_EXCLUSIVE }, |
126 | { VIDIOC_DBG_G_REGISTER, SAA7146_EXCLUSIVE }, | ||
127 | { VIDIOC_DBG_S_REGISTER, SAA7146_EXCLUSIVE }, | ||
125 | { MXB_S_AUDIO_CD, SAA7146_EXCLUSIVE }, /* custom control */ | 128 | { MXB_S_AUDIO_CD, SAA7146_EXCLUSIVE }, /* custom control */ |
126 | { MXB_S_AUDIO_LINE, SAA7146_EXCLUSIVE }, /* custom control */ | 129 | { MXB_S_AUDIO_LINE, SAA7146_EXCLUSIVE }, /* custom control */ |
127 | { 0, 0 } | 130 | { 0, 0 } |
@@ -134,12 +137,12 @@ struct mxb | |||
134 | 137 | ||
135 | struct i2c_adapter i2c_adapter; | 138 | struct i2c_adapter i2c_adapter; |
136 | 139 | ||
137 | struct i2c_client* saa7111a; | 140 | struct i2c_client *saa7111a; |
138 | struct i2c_client* tda9840; | 141 | struct i2c_client *tda9840; |
139 | struct i2c_client* tea6415c; | 142 | struct i2c_client *tea6415c; |
140 | struct i2c_client* tuner; | 143 | struct i2c_client *tuner; |
141 | struct i2c_client* tea6420_1; | 144 | struct i2c_client *tea6420_1; |
142 | struct i2c_client* tea6420_2; | 145 | struct i2c_client *tea6420_2; |
143 | 146 | ||
144 | int cur_mode; /* current audio mode (mono, stereo, ...) */ | 147 | int cur_mode; /* current audio mode (mono, stereo, ...) */ |
145 | int cur_input; /* current input */ | 148 | int cur_input; /* current input */ |
@@ -151,23 +154,23 @@ static struct saa7146_extension extension; | |||
151 | 154 | ||
152 | static int mxb_check_clients(struct device *dev, void *data) | 155 | static int mxb_check_clients(struct device *dev, void *data) |
153 | { | 156 | { |
154 | struct mxb* mxb = data; | 157 | struct mxb *mxb = data; |
155 | struct i2c_client *client = i2c_verify_client(dev); | 158 | struct i2c_client *client = i2c_verify_client(dev); |
156 | 159 | ||
157 | if( !client ) | 160 | if (!client) |
158 | return 0; | 161 | return 0; |
159 | 162 | ||
160 | if( I2C_ADDR_TEA6420_1 == client->addr ) | 163 | if (I2C_ADDR_TEA6420_1 == client->addr) |
161 | mxb->tea6420_1 = client; | 164 | mxb->tea6420_1 = client; |
162 | if( I2C_ADDR_TEA6420_2 == client->addr ) | 165 | if (I2C_ADDR_TEA6420_2 == client->addr) |
163 | mxb->tea6420_2 = client; | 166 | mxb->tea6420_2 = client; |
164 | if( I2C_TEA6415C_2 == client->addr ) | 167 | if (I2C_TEA6415C_2 == client->addr) |
165 | mxb->tea6415c = client; | 168 | mxb->tea6415c = client; |
166 | if( I2C_ADDR_TDA9840 == client->addr ) | 169 | if (I2C_ADDR_TDA9840 == client->addr) |
167 | mxb->tda9840 = client; | 170 | mxb->tda9840 = client; |
168 | if( I2C_SAA7111 == client->addr ) | 171 | if (I2C_SAA7111 == client->addr) |
169 | mxb->saa7111a = client; | 172 | mxb->saa7111a = client; |
170 | if( 0x60 == client->addr ) | 173 | if (0x60 == client->addr) |
171 | mxb->tuner = client; | 174 | mxb->tuner = client; |
172 | 175 | ||
173 | return 0; | 176 | return 0; |
@@ -178,23 +181,28 @@ static int mxb_probe(struct saa7146_dev* dev) | |||
178 | struct mxb* mxb = NULL; | 181 | struct mxb* mxb = NULL; |
179 | int result; | 182 | int result; |
180 | 183 | ||
181 | if ((result = request_module("saa7111")) < 0) { | 184 | result = request_module("saa7115"); |
185 | if (result < 0) { | ||
182 | printk("mxb: saa7111 i2c module not available.\n"); | 186 | printk("mxb: saa7111 i2c module not available.\n"); |
183 | return -ENODEV; | 187 | return -ENODEV; |
184 | } | 188 | } |
185 | if ((result = request_module("tea6420")) < 0) { | 189 | result = request_module("tea6420"); |
190 | if (result < 0) { | ||
186 | printk("mxb: tea6420 i2c module not available.\n"); | 191 | printk("mxb: tea6420 i2c module not available.\n"); |
187 | return -ENODEV; | 192 | return -ENODEV; |
188 | } | 193 | } |
189 | if ((result = request_module("tea6415c")) < 0) { | 194 | result = request_module("tea6415c"); |
195 | if (result < 0) { | ||
190 | printk("mxb: tea6415c i2c module not available.\n"); | 196 | printk("mxb: tea6415c i2c module not available.\n"); |
191 | return -ENODEV; | 197 | return -ENODEV; |
192 | } | 198 | } |
193 | if ((result = request_module("tda9840")) < 0) { | 199 | result = request_module("tda9840"); |
200 | if (result < 0) { | ||
194 | printk("mxb: tda9840 i2c module not available.\n"); | 201 | printk("mxb: tda9840 i2c module not available.\n"); |
195 | return -ENODEV; | 202 | return -ENODEV; |
196 | } | 203 | } |
197 | if ((result = request_module("tuner")) < 0) { | 204 | result = request_module("tuner"); |
205 | if (result < 0) { | ||
198 | printk("mxb: tuner i2c module not available.\n"); | 206 | printk("mxb: tuner i2c module not available.\n"); |
199 | return -ENODEV; | 207 | return -ENODEV; |
200 | } | 208 | } |
@@ -207,9 +215,10 @@ static int mxb_probe(struct saa7146_dev* dev) | |||
207 | 215 | ||
208 | mxb->i2c_adapter = (struct i2c_adapter) { | 216 | mxb->i2c_adapter = (struct i2c_adapter) { |
209 | .class = I2C_CLASS_TV_ANALOG, | 217 | .class = I2C_CLASS_TV_ANALOG, |
210 | .name = "mxb", | ||
211 | }; | 218 | }; |
212 | 219 | ||
220 | snprintf(mxb->i2c_adapter.name, sizeof(mxb->i2c_adapter.name), "mxb%d", mxb_num); | ||
221 | |||
213 | saa7146_i2c_adapter_prepare(dev, &mxb->i2c_adapter, SAA7146_I2C_BUS_BIT_RATE_480); | 222 | saa7146_i2c_adapter_prepare(dev, &mxb->i2c_adapter, SAA7146_I2C_BUS_BIT_RATE_480); |
214 | if(i2c_add_adapter(&mxb->i2c_adapter) < 0) { | 223 | if(i2c_add_adapter(&mxb->i2c_adapter) < 0) { |
215 | DEB_S(("cannot register i2c-device. skipping.\n")); | 224 | DEB_S(("cannot register i2c-device. skipping.\n")); |
@@ -290,38 +299,7 @@ static struct { | |||
290 | { 9, { 0x1d, 0xed, 0xd0, 0x68, 0x29, 0xb4, 0xe1, 0x00, 0xb8 } }, | 299 | { 9, { 0x1d, 0xed, 0xd0, 0x68, 0x29, 0xb4, 0xe1, 0x00, 0xb8 } }, |
291 | { 9, { 0x3d, 0xed, 0xd0, 0x68, 0x29, 0xb4, 0xe1, 0x00, 0xb8 } }, | 300 | { 9, { 0x3d, 0xed, 0xd0, 0x68, 0x29, 0xb4, 0xe1, 0x00, 0xb8 } }, |
292 | { 3, { 0x80, 0xb3, 0x0a } }, | 301 | { 3, { 0x80, 0xb3, 0x0a } }, |
293 | {-1, { 0} } | 302 | {-1, { 0 } } |
294 | }; | ||
295 | |||
296 | static const unsigned char mxb_saa7111_init[] = { | ||
297 | 0x00, 0x00, /* 00 - ID byte */ | ||
298 | 0x01, 0x00, /* 01 - reserved */ | ||
299 | |||
300 | /*front end */ | ||
301 | 0x02, 0xd8, /* 02 - FUSE=x, GUDL=x, MODE=x */ | ||
302 | 0x03, 0x23, /* 03 - HLNRS=0, VBSL=1, WPOFF=0, HOLDG=0, GAFIX=0, GAI1=256, GAI2=256 */ | ||
303 | 0x04, 0x00, /* 04 - GAI1=256 */ | ||
304 | 0x05, 0x00, /* 05 - GAI2=256 */ | ||
305 | |||
306 | /* decoder */ | ||
307 | 0x06, 0xf0, /* 06 - HSB at xx(50Hz) / xx(60Hz) pixels after end of last line */ | ||
308 | 0x07, 0x30, /* 07 - HSS at xx(50Hz) / xx(60Hz) pixels after end of last line */ | ||
309 | 0x08, 0xa8, /* 08 - AUFD=x, FSEL=x, EXFIL=x, VTRC=x, HPLL=x, VNOI=x */ | ||
310 | 0x09, 0x02, /* 09 - BYPS=x, PREF=x, BPSS=x, VBLB=x, UPTCV=x, APER=x */ | ||
311 | 0x0a, 0x80, /* 0a - BRIG=128 */ | ||
312 | 0x0b, 0x47, /* 0b - CONT=1.109 */ | ||
313 | 0x0c, 0x40, /* 0c - SATN=1.0 */ | ||
314 | 0x0d, 0x00, /* 0d - HUE=0 */ | ||
315 | 0x0e, 0x01, /* 0e - CDTO=0, CSTD=0, DCCF=0, FCTC=0, CHBW=1 */ | ||
316 | 0x0f, 0x00, /* 0f - reserved */ | ||
317 | 0x10, 0xd0, /* 10 - OFTS=x, HDEL=x, VRLN=x, YDEL=x */ | ||
318 | 0x11, 0x8c, /* 11 - GPSW=x, CM99=x, FECO=x, COMPO=x, OEYC=1, OEHV=1, VIPB=0, COLO=0 */ | ||
319 | 0x12, 0x80, /* 12 - xx output control 2 */ | ||
320 | 0x13, 0x30, /* 13 - xx output control 3 */ | ||
321 | 0x14, 0x00, /* 14 - reserved */ | ||
322 | 0x15, 0x15, /* 15 - VBI */ | ||
323 | 0x16, 0x04, /* 16 - VBI */ | ||
324 | 0x17, 0x00, /* 17 - VBI */ | ||
325 | }; | 303 | }; |
326 | 304 | ||
327 | /* bring hardware to a sane state. this has to be done, just in case someone | 305 | /* bring hardware to a sane state. this has to be done, just in case someone |
@@ -331,37 +309,28 @@ static const unsigned char mxb_saa7111_init[] = { | |||
331 | static int mxb_init_done(struct saa7146_dev* dev) | 309 | static int mxb_init_done(struct saa7146_dev* dev) |
332 | { | 310 | { |
333 | struct mxb* mxb = (struct mxb*)dev->ext_priv; | 311 | struct mxb* mxb = (struct mxb*)dev->ext_priv; |
334 | struct video_decoder_init init; | ||
335 | struct i2c_msg msg; | 312 | struct i2c_msg msg; |
336 | struct tuner_setup tun_setup; | 313 | struct tuner_setup tun_setup; |
337 | v4l2_std_id std = V4L2_STD_PAL_BG; | 314 | v4l2_std_id std = V4L2_STD_PAL_BG; |
315 | struct v4l2_routing route; | ||
338 | 316 | ||
339 | int i = 0, err = 0; | 317 | int i = 0, err = 0; |
340 | struct tea6415c_multiplex vm; | 318 | struct tea6415c_multiplex vm; |
341 | 319 | ||
342 | /* select video mode in saa7111a */ | 320 | /* select video mode in saa7111a */ |
343 | i = VIDEO_MODE_PAL; | 321 | mxb->saa7111a->driver->command(mxb->saa7111a, VIDIOC_S_STD, &std); |
344 | /* fixme: currently pointless: gets overwritten by configuration below */ | ||
345 | mxb->saa7111a->driver->command(mxb->saa7111a,DECODER_SET_NORM, &i); | ||
346 | |||
347 | /* write configuration to saa7111a */ | ||
348 | init.data = mxb_saa7111_init; | ||
349 | init.len = sizeof(mxb_saa7111_init); | ||
350 | mxb->saa7111a->driver->command(mxb->saa7111a,DECODER_INIT, &init); | ||
351 | 322 | ||
352 | /* select tuner-output on saa7111a */ | 323 | /* select tuner-output on saa7111a */ |
353 | i = 0; | 324 | i = 0; |
354 | mxb->saa7111a->driver->command(mxb->saa7111a,DECODER_SET_INPUT, &i); | 325 | route.input = SAA7115_COMPOSITE0; |
355 | 326 | route.output = SAA7111_FMT_CCIR | SAA7111_VBI_BYPASS; | |
356 | /* enable vbi bypass */ | 327 | mxb->saa7111a->driver->command(mxb->saa7111a, VIDIOC_INT_S_VIDEO_ROUTING, &route); |
357 | i = 1; | ||
358 | mxb->saa7111a->driver->command(mxb->saa7111a,DECODER_SET_VBI_BYPASS, &i); | ||
359 | 328 | ||
360 | /* select a tuner type */ | 329 | /* select a tuner type */ |
361 | tun_setup.mode_mask = T_ANALOG_TV; | 330 | tun_setup.mode_mask = T_ANALOG_TV; |
362 | tun_setup.addr = ADDR_UNSET; | 331 | tun_setup.addr = ADDR_UNSET; |
363 | tun_setup.type = TUNER_PHILIPS_PAL; | 332 | tun_setup.type = TUNER_PHILIPS_PAL; |
364 | mxb->tuner->driver->command(mxb->tuner,TUNER_SET_TYPE_ADDR, &tun_setup); | 333 | mxb->tuner->driver->command(mxb->tuner, TUNER_SET_TYPE_ADDR, &tun_setup); |
365 | /* tune in some frequency on tuner */ | 334 | /* tune in some frequency on tuner */ |
366 | mxb->cur_freq.tuner = 0; | 335 | mxb->cur_freq.tuner = 0; |
367 | mxb->cur_freq.type = V4L2_TUNER_ANALOG_TV; | 336 | mxb->cur_freq.type = V4L2_TUNER_ANALOG_TV; |
@@ -373,27 +342,26 @@ static int mxb_init_done(struct saa7146_dev* dev) | |||
373 | mxb->tuner->driver->command(mxb->tuner, VIDIOC_S_STD, &std); | 342 | mxb->tuner->driver->command(mxb->tuner, VIDIOC_S_STD, &std); |
374 | 343 | ||
375 | /* mute audio on tea6420s */ | 344 | /* mute audio on tea6420s */ |
376 | mxb->tea6420_1->driver->command(mxb->tea6420_1,TEA6420_SWITCH, &TEA6420_line[6][0]); | 345 | mxb->tea6420_1->driver->command(mxb->tea6420_1, TEA6420_SWITCH, &TEA6420_line[6][0]); |
377 | mxb->tea6420_2->driver->command(mxb->tea6420_2,TEA6420_SWITCH, &TEA6420_line[6][1]); | 346 | mxb->tea6420_2->driver->command(mxb->tea6420_2, TEA6420_SWITCH, &TEA6420_line[6][1]); |
378 | mxb->tea6420_1->driver->command(mxb->tea6420_1,TEA6420_SWITCH, &TEA6420_cd[6][0]); | 347 | mxb->tea6420_1->driver->command(mxb->tea6420_1, TEA6420_SWITCH, &TEA6420_cd[6][0]); |
379 | mxb->tea6420_2->driver->command(mxb->tea6420_2,TEA6420_SWITCH, &TEA6420_cd[6][1]); | 348 | mxb->tea6420_2->driver->command(mxb->tea6420_2, TEA6420_SWITCH, &TEA6420_cd[6][1]); |
380 | 349 | ||
381 | /* switch to tuner-channel on tea6415c*/ | 350 | /* switch to tuner-channel on tea6415c*/ |
382 | vm.out = 17; | 351 | vm.out = 17; |
383 | vm.in = 3; | 352 | vm.in = 3; |
384 | mxb->tea6415c->driver->command(mxb->tea6415c,TEA6415C_SWITCH, &vm); | 353 | mxb->tea6415c->driver->command(mxb->tea6415c, TEA6415C_SWITCH, &vm); |
385 | 354 | ||
386 | /* select tuner-output on multicable on tea6415c*/ | 355 | /* select tuner-output on multicable on tea6415c*/ |
387 | vm.in = 3; | 356 | vm.in = 3; |
388 | vm.out = 13; | 357 | vm.out = 13; |
389 | mxb->tea6415c->driver->command(mxb->tea6415c,TEA6415C_SWITCH, &vm); | 358 | mxb->tea6415c->driver->command(mxb->tea6415c, TEA6415C_SWITCH, &vm); |
390 | 359 | ||
391 | /* the rest for mxb */ | 360 | /* the rest for mxb */ |
392 | mxb->cur_input = 0; | 361 | mxb->cur_input = 0; |
393 | mxb->cur_mute = 1; | 362 | mxb->cur_mute = 1; |
394 | 363 | ||
395 | mxb->cur_mode = V4L2_TUNER_MODE_STEREO; | 364 | mxb->cur_mode = V4L2_TUNER_MODE_STEREO; |
396 | mxb->tda9840->driver->command(mxb->tda9840, TDA9840_SWITCH, &mxb->cur_mode); | ||
397 | 365 | ||
398 | /* check if the saa7740 (aka 'sound arena module') is present | 366 | /* check if the saa7740 (aka 'sound arena module') is present |
399 | on the mxb. if so, we must initialize it. due to lack of | 367 | on the mxb. if so, we must initialize it. due to lack of |
@@ -404,21 +372,22 @@ static int mxb_init_done(struct saa7146_dev* dev) | |||
404 | msg.len = mxb_saa7740_init[0].length; | 372 | msg.len = mxb_saa7740_init[0].length; |
405 | msg.buf = &mxb_saa7740_init[0].data[0]; | 373 | msg.buf = &mxb_saa7740_init[0].data[0]; |
406 | 374 | ||
407 | if( 1 == (err = i2c_transfer(&mxb->i2c_adapter, &msg, 1))) { | 375 | err = i2c_transfer(&mxb->i2c_adapter, &msg, 1); |
376 | if (err == 1) { | ||
408 | /* the sound arena module is a pos, that's probably the reason | 377 | /* the sound arena module is a pos, that's probably the reason |
409 | philips refuses to hand out a datasheet for the saa7740... | 378 | philips refuses to hand out a datasheet for the saa7740... |
410 | it seems to screw up the i2c bus, so we disable fast irq | 379 | it seems to screw up the i2c bus, so we disable fast irq |
411 | based i2c transactions here and rely on the slow and safe | 380 | based i2c transactions here and rely on the slow and safe |
412 | polling method ... */ | 381 | polling method ... */ |
413 | extension.flags &= ~SAA7146_USE_I2C_IRQ; | 382 | extension.flags &= ~SAA7146_USE_I2C_IRQ; |
414 | for(i = 1;;i++) { | 383 | for (i = 1; ; i++) { |
415 | if( -1 == mxb_saa7740_init[i].length ) { | 384 | if (-1 == mxb_saa7740_init[i].length) |
416 | break; | 385 | break; |
417 | } | ||
418 | 386 | ||
419 | msg.len = mxb_saa7740_init[i].length; | 387 | msg.len = mxb_saa7740_init[i].length; |
420 | msg.buf = &mxb_saa7740_init[i].data[0]; | 388 | msg.buf = &mxb_saa7740_init[i].data[0]; |
421 | if( 1 != (err = i2c_transfer(&mxb->i2c_adapter, &msg, 1))) { | 389 | err = i2c_transfer(&mxb->i2c_adapter, &msg, 1); |
390 | if (err != 1) { | ||
422 | DEB_D(("failed to initialize 'sound arena module'.\n")); | 391 | DEB_D(("failed to initialize 'sound arena module'.\n")); |
423 | goto err; | 392 | goto err; |
424 | } | 393 | } |
@@ -432,7 +401,8 @@ err: | |||
432 | /* ext->saa has been filled by the core driver */ | 401 | /* ext->saa has been filled by the core driver */ |
433 | 402 | ||
434 | /* some stuff is done via variables */ | 403 | /* some stuff is done via variables */ |
435 | saa7146_set_hps_source_and_sync(dev, input_port_selection[mxb->cur_input].hps_source, input_port_selection[mxb->cur_input].hps_sync); | 404 | saa7146_set_hps_source_and_sync(dev, input_port_selection[mxb->cur_input].hps_source, |
405 | input_port_selection[mxb->cur_input].hps_sync); | ||
436 | 406 | ||
437 | /* some stuff is done via direct write to the registers */ | 407 | /* some stuff is done via direct write to the registers */ |
438 | 408 | ||
@@ -457,24 +427,24 @@ void mxb_irq_bh(struct saa7146_dev* dev, u32* irq_mask) | |||
457 | static struct saa7146_ext_vv vv_data; | 427 | static struct saa7146_ext_vv vv_data; |
458 | 428 | ||
459 | /* this function only gets called when the probing was successful */ | 429 | /* this function only gets called when the probing was successful */ |
460 | static int mxb_attach(struct saa7146_dev* dev, struct saa7146_pci_extension_data *info) | 430 | static int mxb_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data *info) |
461 | { | 431 | { |
462 | struct mxb* mxb = (struct mxb*)dev->ext_priv; | 432 | struct mxb *mxb = (struct mxb *)dev->ext_priv; |
463 | 433 | ||
464 | DEB_EE(("dev:%p\n",dev)); | 434 | DEB_EE(("dev:%p\n", dev)); |
465 | 435 | ||
466 | /* checking for i2c-devices can be omitted here, because we | 436 | /* checking for i2c-devices can be omitted here, because we |
467 | already did this in "mxb_vl42_probe" */ | 437 | already did this in "mxb_vl42_probe" */ |
468 | 438 | ||
469 | saa7146_vv_init(dev,&vv_data); | 439 | saa7146_vv_init(dev, &vv_data); |
470 | if( 0 != saa7146_register_device(&mxb->video_dev, dev, "mxb", VFL_TYPE_GRABBER)) { | 440 | if (saa7146_register_device(&mxb->video_dev, dev, "mxb", VFL_TYPE_GRABBER)) { |
471 | ERR(("cannot register capture v4l2 device. skipping.\n")); | 441 | ERR(("cannot register capture v4l2 device. skipping.\n")); |
472 | return -1; | 442 | return -1; |
473 | } | 443 | } |
474 | 444 | ||
475 | /* initialization stuff (vbi) (only for revision > 0 and for extensions which want it)*/ | 445 | /* initialization stuff (vbi) (only for revision > 0 and for extensions which want it)*/ |
476 | if( 0 != MXB_BOARD_CAN_DO_VBI(dev)) { | 446 | if (MXB_BOARD_CAN_DO_VBI(dev)) { |
477 | if( 0 != saa7146_register_device(&mxb->vbi_dev, dev, "mxb", VFL_TYPE_VBI)) { | 447 | if (saa7146_register_device(&mxb->vbi_dev, dev, "mxb", VFL_TYPE_VBI)) { |
478 | ERR(("cannot register vbi v4l2 device. skipping.\n")); | 448 | ERR(("cannot register vbi v4l2 device. skipping.\n")); |
479 | } | 449 | } |
480 | } | 450 | } |
@@ -486,18 +456,18 @@ static int mxb_attach(struct saa7146_dev* dev, struct saa7146_pci_extension_data | |||
486 | i2c_use_client(mxb->saa7111a); | 456 | i2c_use_client(mxb->saa7111a); |
487 | i2c_use_client(mxb->tuner); | 457 | i2c_use_client(mxb->tuner); |
488 | 458 | ||
489 | printk("mxb: found 'Multimedia eXtension Board'-%d.\n",mxb_num); | 459 | printk("mxb: found Multimedia eXtension Board #%d.\n", mxb_num); |
490 | 460 | ||
491 | mxb_num++; | 461 | mxb_num++; |
492 | mxb_init_done(dev); | 462 | mxb_init_done(dev); |
493 | return 0; | 463 | return 0; |
494 | } | 464 | } |
495 | 465 | ||
496 | static int mxb_detach(struct saa7146_dev* dev) | 466 | static int mxb_detach(struct saa7146_dev *dev) |
497 | { | 467 | { |
498 | struct mxb* mxb = (struct mxb*)dev->ext_priv; | 468 | struct mxb *mxb = (struct mxb *)dev->ext_priv; |
499 | 469 | ||
500 | DEB_EE(("dev:%p\n",dev)); | 470 | DEB_EE(("dev:%p\n", dev)); |
501 | 471 | ||
502 | i2c_release_client(mxb->tea6420_1); | 472 | i2c_release_client(mxb->tea6420_1); |
503 | i2c_release_client(mxb->tea6420_2); | 473 | i2c_release_client(mxb->tea6420_2); |
@@ -507,9 +477,8 @@ static int mxb_detach(struct saa7146_dev* dev) | |||
507 | i2c_release_client(mxb->tuner); | 477 | i2c_release_client(mxb->tuner); |
508 | 478 | ||
509 | saa7146_unregister_device(&mxb->video_dev,dev); | 479 | saa7146_unregister_device(&mxb->video_dev,dev); |
510 | if( 0 != MXB_BOARD_CAN_DO_VBI(dev)) { | 480 | if (MXB_BOARD_CAN_DO_VBI(dev)) |
511 | saa7146_unregister_device(&mxb->vbi_dev,dev); | 481 | saa7146_unregister_device(&mxb->vbi_dev, dev); |
512 | } | ||
513 | saa7146_vv_release(dev); | 482 | saa7146_vv_release(dev); |
514 | 483 | ||
515 | mxb_num--; | 484 | mxb_num--; |
@@ -523,7 +492,7 @@ static int mxb_detach(struct saa7146_dev* dev) | |||
523 | static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) | 492 | static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) |
524 | { | 493 | { |
525 | struct saa7146_dev *dev = fh->dev; | 494 | struct saa7146_dev *dev = fh->dev; |
526 | struct mxb* mxb = (struct mxb*)dev->ext_priv; | 495 | struct mxb *mxb = (struct mxb *)dev->ext_priv; |
527 | struct saa7146_vv *vv = dev->vv_data; | 496 | struct saa7146_vv *vv = dev->vv_data; |
528 | 497 | ||
529 | switch(cmd) { | 498 | switch(cmd) { |
@@ -532,11 +501,9 @@ static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) | |||
532 | struct v4l2_input *i = arg; | 501 | struct v4l2_input *i = arg; |
533 | 502 | ||
534 | DEB_EE(("VIDIOC_ENUMINPUT %d.\n",i->index)); | 503 | DEB_EE(("VIDIOC_ENUMINPUT %d.\n",i->index)); |
535 | if( i->index < 0 || i->index >= MXB_INPUTS) { | 504 | if (i->index < 0 || i->index >= MXB_INPUTS) |
536 | return -EINVAL; | 505 | return -EINVAL; |
537 | } | ||
538 | memcpy(i, &mxb_inputs[i->index], sizeof(struct v4l2_input)); | 506 | memcpy(i, &mxb_inputs[i->index], sizeof(struct v4l2_input)); |
539 | |||
540 | return 0; | 507 | return 0; |
541 | } | 508 | } |
542 | /* the saa7146 provides some controls (brightness, contrast, saturation) | 509 | /* the saa7146 provides some controls (brightness, contrast, saturation) |
@@ -550,7 +517,7 @@ static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) | |||
550 | for (i = MAXCONTROLS - 1; i >= 0; i--) { | 517 | for (i = MAXCONTROLS - 1; i >= 0; i--) { |
551 | if (mxb_controls[i].id == qc->id) { | 518 | if (mxb_controls[i].id == qc->id) { |
552 | *qc = mxb_controls[i]; | 519 | *qc = mxb_controls[i]; |
553 | DEB_D(("VIDIOC_QUERYCTRL %d.\n",qc->id)); | 520 | DEB_D(("VIDIOC_QUERYCTRL %d.\n", qc->id)); |
554 | return 0; | 521 | return 0; |
555 | } | 522 | } |
556 | } | 523 | } |
@@ -562,56 +529,51 @@ static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) | |||
562 | int i; | 529 | int i; |
563 | 530 | ||
564 | for (i = MAXCONTROLS - 1; i >= 0; i--) { | 531 | for (i = MAXCONTROLS - 1; i >= 0; i--) { |
565 | if (mxb_controls[i].id == vc->id) { | 532 | if (mxb_controls[i].id == vc->id) |
566 | break; | 533 | break; |
567 | } | ||
568 | } | 534 | } |
569 | 535 | ||
570 | if( i < 0 ) { | 536 | if (i < 0) |
571 | return -EAGAIN; | 537 | return -EAGAIN; |
572 | } | ||
573 | 538 | ||
574 | switch (vc->id ) { | 539 | if (vc->id == V4L2_CID_AUDIO_MUTE) { |
575 | case V4L2_CID_AUDIO_MUTE: { | 540 | vc->value = mxb->cur_mute; |
576 | vc->value = mxb->cur_mute; | 541 | DEB_D(("VIDIOC_G_CTRL V4L2_CID_AUDIO_MUTE:%d.\n", vc->value)); |
577 | DEB_D(("VIDIOC_G_CTRL V4L2_CID_AUDIO_MUTE:%d.\n",vc->value)); | 542 | return 0; |
578 | return 0; | ||
579 | } | ||
580 | } | 543 | } |
581 | 544 | ||
582 | DEB_EE(("VIDIOC_G_CTRL V4L2_CID_AUDIO_MUTE:%d.\n",vc->value)); | 545 | DEB_EE(("VIDIOC_G_CTRL V4L2_CID_AUDIO_MUTE:%d.\n", vc->value)); |
583 | return 0; | 546 | return 0; |
584 | } | 547 | } |
585 | 548 | ||
586 | case VIDIOC_S_CTRL: | 549 | case VIDIOC_S_CTRL: |
587 | { | 550 | { |
588 | struct v4l2_control *vc = arg; | 551 | struct v4l2_control *vc = arg; |
589 | int i = 0; | 552 | int i = 0; |
590 | 553 | ||
591 | for (i = MAXCONTROLS - 1; i >= 0; i--) { | 554 | for (i = MAXCONTROLS - 1; i >= 0; i--) { |
592 | if (mxb_controls[i].id == vc->id) { | 555 | if (mxb_controls[i].id == vc->id) |
593 | break; | 556 | break; |
594 | } | ||
595 | } | 557 | } |
596 | 558 | ||
597 | if( i < 0 ) { | 559 | if (i < 0) |
598 | return -EAGAIN; | 560 | return -EAGAIN; |
599 | } | ||
600 | 561 | ||
601 | switch (vc->id ) { | 562 | if (vc->id == V4L2_CID_AUDIO_MUTE) { |
602 | case V4L2_CID_AUDIO_MUTE: { | 563 | mxb->cur_mute = vc->value; |
603 | mxb->cur_mute = vc->value; | 564 | if (!vc->value) { |
604 | if( 0 == vc->value ) { | 565 | /* switch the audio-source */ |
605 | /* switch the audio-source */ | 566 | mxb->tea6420_1->driver->command(mxb->tea6420_1, TEA6420_SWITCH, |
606 | mxb->tea6420_1->driver->command(mxb->tea6420_1,TEA6420_SWITCH, &TEA6420_line[video_audio_connect[mxb->cur_input]][0]); | 567 | &TEA6420_line[video_audio_connect[mxb->cur_input]][0]); |
607 | mxb->tea6420_2->driver->command(mxb->tea6420_2,TEA6420_SWITCH, &TEA6420_line[video_audio_connect[mxb->cur_input]][1]); | 568 | mxb->tea6420_2->driver->command(mxb->tea6420_2, TEA6420_SWITCH, |
608 | } else { | 569 | &TEA6420_line[video_audio_connect[mxb->cur_input]][1]); |
609 | mxb->tea6420_1->driver->command(mxb->tea6420_1,TEA6420_SWITCH, &TEA6420_line[6][0]); | 570 | } else { |
610 | mxb->tea6420_2->driver->command(mxb->tea6420_2,TEA6420_SWITCH, &TEA6420_line[6][1]); | 571 | mxb->tea6420_1->driver->command(mxb->tea6420_1, TEA6420_SWITCH, |
611 | } | 572 | &TEA6420_line[6][0]); |
612 | DEB_EE(("VIDIOC_S_CTRL, V4L2_CID_AUDIO_MUTE: %d.\n",vc->value)); | 573 | mxb->tea6420_2->driver->command(mxb->tea6420_2, TEA6420_SWITCH, |
613 | break; | 574 | &TEA6420_line[6][1]); |
614 | } | 575 | } |
576 | DEB_EE(("VIDIOC_S_CTRL, V4L2_CID_AUDIO_MUTE: %d.\n", vc->value)); | ||
615 | } | 577 | } |
616 | return 0; | 578 | return 0; |
617 | } | 579 | } |
@@ -620,106 +582,84 @@ static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) | |||
620 | int *input = (int *)arg; | 582 | int *input = (int *)arg; |
621 | *input = mxb->cur_input; | 583 | *input = mxb->cur_input; |
622 | 584 | ||
623 | DEB_EE(("VIDIOC_G_INPUT %d.\n",*input)); | 585 | DEB_EE(("VIDIOC_G_INPUT %d.\n", *input)); |
624 | return 0; | 586 | return 0; |
625 | } | 587 | } |
626 | case VIDIOC_S_INPUT: | 588 | case VIDIOC_S_INPUT: |
627 | { | 589 | { |
628 | int input = *(int *)arg; | 590 | int input = *(int *)arg; |
629 | struct tea6415c_multiplex vm; | 591 | struct tea6415c_multiplex vm; |
592 | struct v4l2_routing route; | ||
630 | int i = 0; | 593 | int i = 0; |
631 | 594 | ||
632 | DEB_EE(("VIDIOC_S_INPUT %d.\n",input)); | 595 | DEB_EE(("VIDIOC_S_INPUT %d.\n", input)); |
633 | 596 | ||
634 | if (input < 0 || input >= MXB_INPUTS) { | 597 | if (input < 0 || input >= MXB_INPUTS) |
635 | return -EINVAL; | 598 | return -EINVAL; |
636 | } | ||
637 | |||
638 | /* fixme: locke das setzen des inputs mit hilfe des mutexes | ||
639 | mutex_lock(&dev->lock); | ||
640 | video_mux(dev,*i); | ||
641 | mutex_unlock(&dev->lock); | ||
642 | */ | ||
643 | |||
644 | /* fixme: check if streaming capture | ||
645 | if ( 0 != dev->streaming ) { | ||
646 | DEB_D(("VIDIOC_S_INPUT illegal while streaming.\n")); | ||
647 | return -EPERM; | ||
648 | } | ||
649 | */ | ||
650 | 599 | ||
651 | mxb->cur_input = input; | 600 | mxb->cur_input = input; |
652 | 601 | ||
653 | saa7146_set_hps_source_and_sync(dev, input_port_selection[input].hps_source, input_port_selection[input].hps_sync); | 602 | saa7146_set_hps_source_and_sync(dev, input_port_selection[input].hps_source, |
603 | input_port_selection[input].hps_sync); | ||
654 | 604 | ||
655 | /* prepare switching of tea6415c and saa7111a; | 605 | /* prepare switching of tea6415c and saa7111a; |
656 | have a look at the 'background'-file for further informations */ | 606 | have a look at the 'background'-file for further informations */ |
657 | switch( input ) { | 607 | switch (input) { |
658 | 608 | case TUNER: | |
659 | case TUNER: | 609 | i = SAA7115_COMPOSITE0; |
660 | { | 610 | vm.in = 3; |
661 | i = 0; | 611 | vm.out = 17; |
662 | vm.in = 3; | 612 | |
663 | vm.out = 17; | 613 | if (mxb->tea6415c->driver->command(mxb->tea6415c, TEA6415C_SWITCH, &vm)) { |
664 | 614 | printk(KERN_ERR "VIDIOC_S_INPUT: could not address tea6415c #1\n"); | |
665 | if ( 0 != mxb->tea6415c->driver->command(mxb->tea6415c,TEA6415C_SWITCH, &vm)) { | 615 | return -EFAULT; |
666 | printk("VIDIOC_S_INPUT: could not address tea6415c #1\n"); | ||
667 | return -EFAULT; | ||
668 | } | ||
669 | /* connect tuner-output always to multicable */ | ||
670 | vm.in = 3; | ||
671 | vm.out = 13; | ||
672 | break; | ||
673 | } | ||
674 | case AUX3_YC: | ||
675 | { | ||
676 | /* nothing to be done here. aux3_yc is | ||
677 | directly connected to the saa711a */ | ||
678 | i = 5; | ||
679 | break; | ||
680 | } | ||
681 | case AUX3: | ||
682 | { | ||
683 | /* nothing to be done here. aux3 is | ||
684 | directly connected to the saa711a */ | ||
685 | i = 1; | ||
686 | break; | ||
687 | } | ||
688 | case AUX1: | ||
689 | { | ||
690 | i = 0; | ||
691 | vm.in = 1; | ||
692 | vm.out = 17; | ||
693 | break; | ||
694 | } | 616 | } |
617 | /* connect tuner-output always to multicable */ | ||
618 | vm.in = 3; | ||
619 | vm.out = 13; | ||
620 | break; | ||
621 | case AUX3_YC: | ||
622 | /* nothing to be done here. aux3_yc is | ||
623 | directly connected to the saa711a */ | ||
624 | i = SAA7115_SVIDEO1; | ||
625 | break; | ||
626 | case AUX3: | ||
627 | /* nothing to be done here. aux3 is | ||
628 | directly connected to the saa711a */ | ||
629 | i = SAA7115_COMPOSITE1; | ||
630 | break; | ||
631 | case AUX1: | ||
632 | i = SAA7115_COMPOSITE0; | ||
633 | vm.in = 1; | ||
634 | vm.out = 17; | ||
635 | break; | ||
695 | } | 636 | } |
696 | 637 | ||
697 | /* switch video in tea6415c only if necessary */ | 638 | /* switch video in tea6415c only if necessary */ |
698 | switch( input ) { | 639 | switch (input) { |
699 | case TUNER: | 640 | case TUNER: |
700 | case AUX1: | 641 | case AUX1: |
701 | { | 642 | if (mxb->tea6415c->driver->command(mxb->tea6415c, TEA6415C_SWITCH, &vm)) { |
702 | if ( 0 != mxb->tea6415c->driver->command(mxb->tea6415c,TEA6415C_SWITCH, &vm)) { | 643 | printk(KERN_ERR "VIDIOC_S_INPUT: could not address tea6415c #3\n"); |
703 | printk("VIDIOC_S_INPUT: could not address tea6415c #3\n"); | 644 | return -EFAULT; |
704 | return -EFAULT; | ||
705 | } | ||
706 | break; | ||
707 | } | ||
708 | default: | ||
709 | { | ||
710 | break; | ||
711 | } | 645 | } |
646 | break; | ||
647 | default: | ||
648 | break; | ||
712 | } | 649 | } |
713 | 650 | ||
714 | /* switch video in saa7111a */ | 651 | /* switch video in saa7111a */ |
715 | if ( 0 != mxb->saa7111a->driver->command(mxb->saa7111a,DECODER_SET_INPUT, &i)) { | 652 | route.input = i; |
653 | route.output = 0; | ||
654 | if (mxb->saa7111a->driver->command(mxb->saa7111a, VIDIOC_INT_S_VIDEO_ROUTING, &route)) | ||
716 | printk("VIDIOC_S_INPUT: could not address saa7111a #1.\n"); | 655 | printk("VIDIOC_S_INPUT: could not address saa7111a #1.\n"); |
717 | } | ||
718 | 656 | ||
719 | /* switch the audio-source only if necessary */ | 657 | /* switch the audio-source only if necessary */ |
720 | if( 0 == mxb->cur_mute ) { | 658 | if( 0 == mxb->cur_mute ) { |
721 | mxb->tea6420_1->driver->command(mxb->tea6420_1,TEA6420_SWITCH, &TEA6420_line[video_audio_connect[input]][0]); | 659 | mxb->tea6420_1->driver->command(mxb->tea6420_1, TEA6420_SWITCH, |
722 | mxb->tea6420_2->driver->command(mxb->tea6420_2,TEA6420_SWITCH, &TEA6420_line[video_audio_connect[input]][1]); | 660 | &TEA6420_line[video_audio_connect[input]][0]); |
661 | mxb->tea6420_2->driver->command(mxb->tea6420_2, TEA6420_SWITCH, | ||
662 | &TEA6420_line[video_audio_connect[input]][1]); | ||
723 | } | 663 | } |
724 | 664 | ||
725 | return 0; | 665 | return 0; |
@@ -727,114 +667,44 @@ static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) | |||
727 | case VIDIOC_G_TUNER: | 667 | case VIDIOC_G_TUNER: |
728 | { | 668 | { |
729 | struct v4l2_tuner *t = arg; | 669 | struct v4l2_tuner *t = arg; |
730 | int byte = 0; | ||
731 | 670 | ||
732 | if( 0 != t->index ) { | 671 | if (t->index) { |
733 | DEB_D(("VIDIOC_G_TUNER: channel %d does not have a tuner attached.\n", t->index)); | 672 | DEB_D(("VIDIOC_G_TUNER: channel %d does not have a tuner attached.\n", t->index)); |
734 | return -EINVAL; | 673 | return -EINVAL; |
735 | } | 674 | } |
736 | 675 | ||
737 | DEB_EE(("VIDIOC_G_TUNER: %d\n", t->index)); | 676 | DEB_EE(("VIDIOC_G_TUNER: %d\n", t->index)); |
738 | 677 | ||
739 | memset(t,0,sizeof(*t)); | 678 | memset(t, 0, sizeof(*t)); |
740 | strcpy(t->name, "Television"); | 679 | i2c_clients_command(&mxb->i2c_adapter, cmd, arg); |
741 | 680 | ||
681 | strlcpy(t->name, "TV Tuner", sizeof(t->name)); | ||
742 | t->type = V4L2_TUNER_ANALOG_TV; | 682 | t->type = V4L2_TUNER_ANALOG_TV; |
743 | t->capability = V4L2_TUNER_CAP_NORM | V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP; | 683 | t->capability = V4L2_TUNER_CAP_NORM | V4L2_TUNER_CAP_STEREO | \ |
744 | t->rangelow = 772; /* 48.25 MHZ / 62.5 kHz = 772, see fi1216mk2-specs, page 2 */ | 684 | V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP; |
745 | t->rangehigh = 13684; /* 855.25 MHz / 62.5 kHz = 13684 */ | ||
746 | /* FIXME: add the real signal strength here */ | ||
747 | t->signal = 0xffff; | ||
748 | t->afc = 0; | ||
749 | |||
750 | mxb->tda9840->driver->command(mxb->tda9840,TDA9840_DETECT, &byte); | ||
751 | t->audmode = mxb->cur_mode; | 685 | t->audmode = mxb->cur_mode; |
752 | |||
753 | if( byte < 0 ) { | ||
754 | t->rxsubchans = V4L2_TUNER_SUB_MONO; | ||
755 | } else { | ||
756 | switch(byte) { | ||
757 | case TDA9840_MONO_DETECT: { | ||
758 | t->rxsubchans = V4L2_TUNER_SUB_MONO; | ||
759 | DEB_D(("VIDIOC_G_TUNER: V4L2_TUNER_MODE_MONO.\n")); | ||
760 | break; | ||
761 | } | ||
762 | case TDA9840_DUAL_DETECT: { | ||
763 | t->rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2; | ||
764 | DEB_D(("VIDIOC_G_TUNER: V4L2_TUNER_MODE_LANG1.\n")); | ||
765 | break; | ||
766 | } | ||
767 | case TDA9840_STEREO_DETECT: { | ||
768 | t->rxsubchans = V4L2_TUNER_SUB_STEREO | V4L2_TUNER_SUB_MONO; | ||
769 | DEB_D(("VIDIOC_G_TUNER: V4L2_TUNER_MODE_STEREO.\n")); | ||
770 | break; | ||
771 | } | ||
772 | default: { /* TDA9840_INCORRECT_DETECT */ | ||
773 | t->rxsubchans = V4L2_TUNER_MODE_MONO; | ||
774 | DEB_D(("VIDIOC_G_TUNER: TDA9840_INCORRECT_DETECT => V4L2_TUNER_MODE_MONO\n")); | ||
775 | break; | ||
776 | } | ||
777 | } | ||
778 | } | ||
779 | |||
780 | return 0; | 686 | return 0; |
781 | } | 687 | } |
782 | case VIDIOC_S_TUNER: | 688 | case VIDIOC_S_TUNER: |
783 | { | 689 | { |
784 | struct v4l2_tuner *t = arg; | 690 | struct v4l2_tuner *t = arg; |
785 | int result = 0; | ||
786 | int byte = 0; | ||
787 | 691 | ||
788 | if( 0 != t->index ) { | 692 | if (t->index) { |
789 | DEB_D(("VIDIOC_S_TUNER: channel %d does not have a tuner attached.\n",t->index)); | 693 | DEB_D(("VIDIOC_S_TUNER: channel %d does not have a tuner attached.\n",t->index)); |
790 | return -EINVAL; | 694 | return -EINVAL; |
791 | } | 695 | } |
792 | 696 | ||
793 | switch(t->audmode) { | 697 | mxb->cur_mode = t->audmode; |
794 | case V4L2_TUNER_MODE_STEREO: { | 698 | i2c_clients_command(&mxb->i2c_adapter, cmd, arg); |
795 | mxb->cur_mode = V4L2_TUNER_MODE_STEREO; | ||
796 | byte = TDA9840_SET_STEREO; | ||
797 | DEB_D(("VIDIOC_S_TUNER: V4L2_TUNER_MODE_STEREO\n")); | ||
798 | break; | ||
799 | } | ||
800 | case V4L2_TUNER_MODE_LANG1_LANG2: { | ||
801 | mxb->cur_mode = V4L2_TUNER_MODE_LANG1_LANG2; | ||
802 | byte = TDA9840_SET_BOTH; | ||
803 | DEB_D(("VIDIOC_S_TUNER: V4L2_TUNER_MODE_LANG1_LANG2\n")); | ||
804 | break; | ||
805 | } | ||
806 | case V4L2_TUNER_MODE_LANG1: { | ||
807 | mxb->cur_mode = V4L2_TUNER_MODE_LANG1; | ||
808 | byte = TDA9840_SET_LANG1; | ||
809 | DEB_D(("VIDIOC_S_TUNER: V4L2_TUNER_MODE_LANG1\n")); | ||
810 | break; | ||
811 | } | ||
812 | case V4L2_TUNER_MODE_LANG2: { | ||
813 | mxb->cur_mode = V4L2_TUNER_MODE_LANG2; | ||
814 | byte = TDA9840_SET_LANG2; | ||
815 | DEB_D(("VIDIOC_S_TUNER: V4L2_TUNER_MODE_LANG2\n")); | ||
816 | break; | ||
817 | } | ||
818 | default: { /* case V4L2_TUNER_MODE_MONO: {*/ | ||
819 | mxb->cur_mode = V4L2_TUNER_MODE_MONO; | ||
820 | byte = TDA9840_SET_MONO; | ||
821 | DEB_D(("VIDIOC_S_TUNER: TDA9840_SET_MONO\n")); | ||
822 | break; | ||
823 | } | ||
824 | } | ||
825 | |||
826 | if( 0 != (result = mxb->tda9840->driver->command(mxb->tda9840, TDA9840_SWITCH, &byte))) { | ||
827 | printk("VIDIOC_S_TUNER error. result:%d, byte:%d\n",result,byte); | ||
828 | } | ||
829 | |||
830 | return 0; | 699 | return 0; |
831 | } | 700 | } |
832 | case VIDIOC_G_FREQUENCY: | 701 | case VIDIOC_G_FREQUENCY: |
833 | { | 702 | { |
834 | struct v4l2_frequency *f = arg; | 703 | struct v4l2_frequency *f = arg; |
835 | 704 | ||
836 | if(0 != mxb->cur_input) { | 705 | if (mxb->cur_input) { |
837 | DEB_D(("VIDIOC_G_FREQ: channel %d does not have a tuner!\n",mxb->cur_input)); | 706 | DEB_D(("VIDIOC_G_FREQ: channel %d does not have a tuner!\n", |
707 | mxb->cur_input)); | ||
838 | return -EINVAL; | 708 | return -EINVAL; |
839 | } | 709 | } |
840 | 710 | ||
@@ -847,14 +717,14 @@ static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) | |||
847 | { | 717 | { |
848 | struct v4l2_frequency *f = arg; | 718 | struct v4l2_frequency *f = arg; |
849 | 719 | ||
850 | if (0 != f->tuner) | 720 | if (f->tuner) |
851 | return -EINVAL; | 721 | return -EINVAL; |
852 | 722 | ||
853 | if (V4L2_TUNER_ANALOG_TV != f->type) | 723 | if (V4L2_TUNER_ANALOG_TV != f->type) |
854 | return -EINVAL; | 724 | return -EINVAL; |
855 | 725 | ||
856 | if(0 != mxb->cur_input) { | 726 | if (mxb->cur_input) { |
857 | DEB_D(("VIDIOC_S_FREQ: channel %d does not have a tuner!\n",mxb->cur_input)); | 727 | DEB_D(("VIDIOC_S_FREQ: channel %d does not have a tuner!\n", mxb->cur_input)); |
858 | return -EINVAL; | 728 | return -EINVAL; |
859 | } | 729 | } |
860 | 730 | ||
@@ -875,7 +745,7 @@ static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) | |||
875 | { | 745 | { |
876 | int i = *(int*)arg; | 746 | int i = *(int*)arg; |
877 | 747 | ||
878 | if( i < 0 || i >= MXB_AUDIOS ) { | 748 | if (i < 0 || i >= MXB_AUDIOS) { |
879 | DEB_D(("illegal argument to MXB_S_AUDIO_CD: i:%d.\n",i)); | 749 | DEB_D(("illegal argument to MXB_S_AUDIO_CD: i:%d.\n",i)); |
880 | return -EINVAL; | 750 | return -EINVAL; |
881 | } | 751 | } |
@@ -891,7 +761,7 @@ static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) | |||
891 | { | 761 | { |
892 | int i = *(int*)arg; | 762 | int i = *(int*)arg; |
893 | 763 | ||
894 | if( i < 0 || i >= MXB_AUDIOS ) { | 764 | if (i < 0 || i >= MXB_AUDIOS) { |
895 | DEB_D(("illegal argument to MXB_S_AUDIO_LINE: i:%d.\n",i)); | 765 | DEB_D(("illegal argument to MXB_S_AUDIO_LINE: i:%d.\n",i)); |
896 | return -EINVAL; | 766 | return -EINVAL; |
897 | } | 767 | } |
@@ -906,12 +776,12 @@ static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) | |||
906 | { | 776 | { |
907 | struct v4l2_audio *a = arg; | 777 | struct v4l2_audio *a = arg; |
908 | 778 | ||
909 | if( a->index < 0 || a->index > MXB_INPUTS ) { | 779 | if (a->index < 0 || a->index > MXB_INPUTS) { |
910 | DEB_D(("VIDIOC_G_AUDIO %d out of range.\n",a->index)); | 780 | DEB_D(("VIDIOC_G_AUDIO %d out of range.\n", a->index)); |
911 | return -EINVAL; | 781 | return -EINVAL; |
912 | } | 782 | } |
913 | 783 | ||
914 | DEB_EE(("VIDIOC_G_AUDIO %d.\n",a->index)); | 784 | DEB_EE(("VIDIOC_G_AUDIO %d.\n", a->index)); |
915 | memcpy(a, &mxb_audios[video_audio_connect[mxb->cur_input]], sizeof(struct v4l2_audio)); | 785 | memcpy(a, &mxb_audios[video_audio_connect[mxb->cur_input]], sizeof(struct v4l2_audio)); |
916 | 786 | ||
917 | return 0; | 787 | return 0; |
@@ -919,9 +789,16 @@ static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) | |||
919 | case VIDIOC_S_AUDIO: | 789 | case VIDIOC_S_AUDIO: |
920 | { | 790 | { |
921 | struct v4l2_audio *a = arg; | 791 | struct v4l2_audio *a = arg; |
922 | DEB_D(("VIDIOC_S_AUDIO %d.\n",a->index)); | 792 | |
793 | DEB_D(("VIDIOC_S_AUDIO %d.\n", a->index)); | ||
923 | return 0; | 794 | return 0; |
924 | } | 795 | } |
796 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
797 | case VIDIOC_DBG_S_REGISTER: | ||
798 | case VIDIOC_DBG_G_REGISTER: | ||
799 | i2c_clients_command(&mxb->i2c_adapter, cmd, arg); | ||
800 | return 0; | ||
801 | #endif | ||
925 | default: | 802 | default: |
926 | /* | 803 | /* |
927 | DEB2(printk("does not handle this ioctl.\n")); | 804 | DEB2(printk("does not handle this ioctl.\n")); |
@@ -944,7 +821,7 @@ static int std_callback(struct saa7146_dev *dev, struct saa7146_standard *standa | |||
944 | /* set the 7146 gpio register -- I don't know what this does exactly */ | 821 | /* set the 7146 gpio register -- I don't know what this does exactly */ |
945 | saa7146_write(dev, GPIO_CTRL, 0x00404050); | 822 | saa7146_write(dev, GPIO_CTRL, 0x00404050); |
946 | /* unset the 7111 gpio register -- I don't know what this does exactly */ | 823 | /* unset the 7111 gpio register -- I don't know what this does exactly */ |
947 | mxb->saa7111a->driver->command(mxb->saa7111a, DECODER_SET_GPIO, &zero); | 824 | mxb->saa7111a->driver->command(mxb->saa7111a, VIDIOC_INT_S_GPIO, &zero); |
948 | mxb->tuner->driver->command(mxb->tuner, VIDIOC_S_STD, &std); | 825 | mxb->tuner->driver->command(mxb->tuner, VIDIOC_S_STD, &std); |
949 | } else { | 826 | } else { |
950 | v4l2_std_id std = V4L2_STD_PAL_BG; | 827 | v4l2_std_id std = V4L2_STD_PAL_BG; |
@@ -953,7 +830,7 @@ static int std_callback(struct saa7146_dev *dev, struct saa7146_standard *standa | |||
953 | /* set the 7146 gpio register -- I don't know what this does exactly */ | 830 | /* set the 7146 gpio register -- I don't know what this does exactly */ |
954 | saa7146_write(dev, GPIO_CTRL, 0x00404050); | 831 | saa7146_write(dev, GPIO_CTRL, 0x00404050); |
955 | /* set the 7111 gpio register -- I don't know what this does exactly */ | 832 | /* set the 7111 gpio register -- I don't know what this does exactly */ |
956 | mxb->saa7111a->driver->command(mxb->saa7111a, DECODER_SET_GPIO, &one); | 833 | mxb->saa7111a->driver->command(mxb->saa7111a, VIDIOC_INT_S_GPIO, &one); |
957 | mxb->tuner->driver->command(mxb->tuner, VIDIOC_S_STD, &std); | 834 | mxb->tuner->driver->command(mxb->tuner, VIDIOC_S_STD, &std); |
958 | } | 835 | } |
959 | return 0; | 836 | return 0; |
@@ -1029,7 +906,7 @@ static struct saa7146_extension extension = { | |||
1029 | 906 | ||
1030 | static int __init mxb_init_module(void) | 907 | static int __init mxb_init_module(void) |
1031 | { | 908 | { |
1032 | if( 0 != saa7146_register_extension(&extension)) { | 909 | if (saa7146_register_extension(&extension)) { |
1033 | DEB_S(("failed to register extension.\n")); | 910 | DEB_S(("failed to register extension.\n")); |
1034 | return -ENODEV; | 911 | return -ENODEV; |
1035 | } | 912 | } |
diff --git a/drivers/media/video/ov511.c b/drivers/media/video/ov511.c index c6852402c5e9..935d73de57bd 100644 --- a/drivers/media/video/ov511.c +++ b/drivers/media/video/ov511.c | |||
@@ -974,14 +974,14 @@ dump_i2c_range(struct usb_ov511 *ov, int reg1, int regn) | |||
974 | 974 | ||
975 | for (i = reg1; i <= regn; i++) { | 975 | for (i = reg1; i <= regn; i++) { |
976 | rc = i2c_r(ov, i); | 976 | rc = i2c_r(ov, i); |
977 | info("Sensor[0x%02X] = 0x%02X", i, rc); | 977 | dev_info(&ov->dev->dev, "Sensor[0x%02X] = 0x%02X\n", i, rc); |
978 | } | 978 | } |
979 | } | 979 | } |
980 | 980 | ||
981 | static void | 981 | static void |
982 | dump_i2c_regs(struct usb_ov511 *ov) | 982 | dump_i2c_regs(struct usb_ov511 *ov) |
983 | { | 983 | { |
984 | info("I2C REGS"); | 984 | dev_info(&ov->dev->dev, "I2C REGS\n"); |
985 | dump_i2c_range(ov, 0x00, 0x7C); | 985 | dump_i2c_range(ov, 0x00, 0x7C); |
986 | } | 986 | } |
987 | 987 | ||
@@ -992,28 +992,28 @@ dump_reg_range(struct usb_ov511 *ov, int reg1, int regn) | |||
992 | 992 | ||
993 | for (i = reg1; i <= regn; i++) { | 993 | for (i = reg1; i <= regn; i++) { |
994 | rc = reg_r(ov, i); | 994 | rc = reg_r(ov, i); |
995 | info("OV511[0x%02X] = 0x%02X", i, rc); | 995 | dev_info(&ov->dev->dev, "OV511[0x%02X] = 0x%02X\n", i, rc); |
996 | } | 996 | } |
997 | } | 997 | } |
998 | 998 | ||
999 | static void | 999 | static void |
1000 | ov511_dump_regs(struct usb_ov511 *ov) | 1000 | ov511_dump_regs(struct usb_ov511 *ov) |
1001 | { | 1001 | { |
1002 | info("CAMERA INTERFACE REGS"); | 1002 | dev_info(&ov->dev->dev, "CAMERA INTERFACE REGS\n"); |
1003 | dump_reg_range(ov, 0x10, 0x1f); | 1003 | dump_reg_range(ov, 0x10, 0x1f); |
1004 | info("DRAM INTERFACE REGS"); | 1004 | dev_info(&ov->dev->dev, "DRAM INTERFACE REGS\n"); |
1005 | dump_reg_range(ov, 0x20, 0x23); | 1005 | dump_reg_range(ov, 0x20, 0x23); |
1006 | info("ISO FIFO REGS"); | 1006 | dev_info(&ov->dev->dev, "ISO FIFO REGS\n"); |
1007 | dump_reg_range(ov, 0x30, 0x31); | 1007 | dump_reg_range(ov, 0x30, 0x31); |
1008 | info("PIO REGS"); | 1008 | dev_info(&ov->dev->dev, "PIO REGS\n"); |
1009 | dump_reg_range(ov, 0x38, 0x39); | 1009 | dump_reg_range(ov, 0x38, 0x39); |
1010 | dump_reg_range(ov, 0x3e, 0x3e); | 1010 | dump_reg_range(ov, 0x3e, 0x3e); |
1011 | info("I2C REGS"); | 1011 | dev_info(&ov->dev->dev, "I2C REGS\n"); |
1012 | dump_reg_range(ov, 0x40, 0x49); | 1012 | dump_reg_range(ov, 0x40, 0x49); |
1013 | info("SYSTEM CONTROL REGS"); | 1013 | dev_info(&ov->dev->dev, "SYSTEM CONTROL REGS\n"); |
1014 | dump_reg_range(ov, 0x50, 0x55); | 1014 | dump_reg_range(ov, 0x50, 0x55); |
1015 | dump_reg_range(ov, 0x5e, 0x5f); | 1015 | dump_reg_range(ov, 0x5e, 0x5f); |
1016 | info("OmniCE REGS"); | 1016 | dev_info(&ov->dev->dev, "OmniCE REGS\n"); |
1017 | dump_reg_range(ov, 0x70, 0x79); | 1017 | dump_reg_range(ov, 0x70, 0x79); |
1018 | /* NOTE: Quantization tables are not readable. You will get the value | 1018 | /* NOTE: Quantization tables are not readable. You will get the value |
1019 | * in reg. 0x79 for every table register */ | 1019 | * in reg. 0x79 for every table register */ |
@@ -1025,25 +1025,25 @@ ov511_dump_regs(struct usb_ov511 *ov) | |||
1025 | static void | 1025 | static void |
1026 | ov518_dump_regs(struct usb_ov511 *ov) | 1026 | ov518_dump_regs(struct usb_ov511 *ov) |
1027 | { | 1027 | { |
1028 | info("VIDEO MODE REGS"); | 1028 | dev_info(&ov->dev->dev, "VIDEO MODE REGS\n"); |
1029 | dump_reg_range(ov, 0x20, 0x2f); | 1029 | dump_reg_range(ov, 0x20, 0x2f); |
1030 | info("DATA PUMP AND SNAPSHOT REGS"); | 1030 | dev_info(&ov->dev->dev, "DATA PUMP AND SNAPSHOT REGS\n"); |
1031 | dump_reg_range(ov, 0x30, 0x3f); | 1031 | dump_reg_range(ov, 0x30, 0x3f); |
1032 | info("I2C REGS"); | 1032 | dev_info(&ov->dev->dev, "I2C REGS\n"); |
1033 | dump_reg_range(ov, 0x40, 0x4f); | 1033 | dump_reg_range(ov, 0x40, 0x4f); |
1034 | info("SYSTEM CONTROL AND VENDOR REGS"); | 1034 | dev_info(&ov->dev->dev, "SYSTEM CONTROL AND VENDOR REGS\n"); |
1035 | dump_reg_range(ov, 0x50, 0x5f); | 1035 | dump_reg_range(ov, 0x50, 0x5f); |
1036 | info("60 - 6F"); | 1036 | dev_info(&ov->dev->dev, "60 - 6F\n"); |
1037 | dump_reg_range(ov, 0x60, 0x6f); | 1037 | dump_reg_range(ov, 0x60, 0x6f); |
1038 | info("70 - 7F"); | 1038 | dev_info(&ov->dev->dev, "70 - 7F\n"); |
1039 | dump_reg_range(ov, 0x70, 0x7f); | 1039 | dump_reg_range(ov, 0x70, 0x7f); |
1040 | info("Y QUANTIZATION TABLE"); | 1040 | dev_info(&ov->dev->dev, "Y QUANTIZATION TABLE\n"); |
1041 | dump_reg_range(ov, 0x80, 0x8f); | 1041 | dump_reg_range(ov, 0x80, 0x8f); |
1042 | info("UV QUANTIZATION TABLE"); | 1042 | dev_info(&ov->dev->dev, "UV QUANTIZATION TABLE\n"); |
1043 | dump_reg_range(ov, 0x90, 0x9f); | 1043 | dump_reg_range(ov, 0x90, 0x9f); |
1044 | info("A0 - BF"); | 1044 | dev_info(&ov->dev->dev, "A0 - BF\n"); |
1045 | dump_reg_range(ov, 0xa0, 0xbf); | 1045 | dump_reg_range(ov, 0xa0, 0xbf); |
1046 | info("CBR"); | 1046 | dev_info(&ov->dev->dev, "CBR\n"); |
1047 | dump_reg_range(ov, 0xc0, 0xcf); | 1047 | dump_reg_range(ov, 0xc0, 0xcf); |
1048 | } | 1048 | } |
1049 | #endif | 1049 | #endif |
@@ -3205,9 +3205,10 @@ ov511_move_data(struct usb_ov511 *ov, unsigned char *in, int n) | |||
3205 | */ | 3205 | */ |
3206 | 3206 | ||
3207 | if (printph) { | 3207 | if (printph) { |
3208 | info("ph(%3d): %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x", | 3208 | dev_info(&ov->dev->dev, |
3209 | pnum, in[0], in[1], in[2], in[3], in[4], in[5], in[6], | 3209 | "ph(%3d): %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x\n", |
3210 | in[7], in[8], in[9], in[10], in[11]); | 3210 | pnum, in[0], in[1], in[2], in[3], in[4], in[5], in[6], |
3211 | in[7], in[8], in[9], in[10], in[11]); | ||
3211 | } | 3212 | } |
3212 | 3213 | ||
3213 | /* Check for SOF/EOF packet */ | 3214 | /* Check for SOF/EOF packet */ |
@@ -3366,8 +3367,10 @@ ov518_move_data(struct usb_ov511 *ov, unsigned char *in, int n) | |||
3366 | * the definitive SOF/EOF format */ | 3367 | * the definitive SOF/EOF format */ |
3367 | if ((!(in[0] | in[1] | in[2] | in[3] | in[5])) && in[6]) { | 3368 | if ((!(in[0] | in[1] | in[2] | in[3] | in[5])) && in[6]) { |
3368 | if (printph) { | 3369 | if (printph) { |
3369 | info("ph: %2x %2x %2x %2x %2x %2x %2x %2x", in[0], | 3370 | dev_info(&ov->dev->dev, |
3370 | in[1], in[2], in[3], in[4], in[5], in[6], in[7]); | 3371 | "ph: %2x %2x %2x %2x %2x %2x %2x %2x\n", |
3372 | in[0], in[1], in[2], in[3], in[4], in[5], | ||
3373 | in[6], in[7]); | ||
3371 | } | 3374 | } |
3372 | 3375 | ||
3373 | if (frame->scanstate == STATE_LINES) { | 3376 | if (frame->scanstate == STATE_LINES) { |
@@ -3646,14 +3649,16 @@ ov51x_init_isoc(struct usb_ov511 *ov) | |||
3646 | if (packetsize == -1) { | 3649 | if (packetsize == -1) { |
3647 | ov518_set_packet_size(ov, 640); | 3650 | ov518_set_packet_size(ov, 640); |
3648 | } else { | 3651 | } else { |
3649 | info("Forcing packet size to %d", packetsize); | 3652 | dev_info(&ov->dev->dev, "Forcing packet size to %d\n", |
3653 | packetsize); | ||
3650 | ov518_set_packet_size(ov, packetsize); | 3654 | ov518_set_packet_size(ov, packetsize); |
3651 | } | 3655 | } |
3652 | } else { | 3656 | } else { |
3653 | if (packetsize == -1) { | 3657 | if (packetsize == -1) { |
3654 | ov511_set_packet_size(ov, size); | 3658 | ov511_set_packet_size(ov, size); |
3655 | } else { | 3659 | } else { |
3656 | info("Forcing packet size to %d", packetsize); | 3660 | dev_info(&ov->dev->dev, "Forcing packet size to %d\n", |
3661 | packetsize); | ||
3657 | ov511_set_packet_size(ov, packetsize); | 3662 | ov511_set_packet_size(ov, packetsize); |
3658 | } | 3663 | } |
3659 | } | 3664 | } |
@@ -4121,7 +4126,7 @@ ov51x_v4l1_ioctl_internal(struct inode *inode, struct file *file, | |||
4121 | return -EIO; | 4126 | return -EIO; |
4122 | 4127 | ||
4123 | if (force_palette && p->palette != force_palette) { | 4128 | if (force_palette && p->palette != force_palette) { |
4124 | info("Palette rejected (%s)", | 4129 | dev_info(&ov->dev->dev, "Palette rejected (%s)\n", |
4125 | symbolic(v4l1_plist, p->palette)); | 4130 | symbolic(v4l1_plist, p->palette)); |
4126 | return -EINVAL; | 4131 | return -EINVAL; |
4127 | } | 4132 | } |
@@ -4849,26 +4854,27 @@ ov7xx0_configure(struct usb_ov511 *ov) | |||
4849 | err("Error detecting sensor type"); | 4854 | err("Error detecting sensor type"); |
4850 | return -1; | 4855 | return -1; |
4851 | } else if ((rc & 3) == 3) { | 4856 | } else if ((rc & 3) == 3) { |
4852 | info("Sensor is an OV7610"); | 4857 | dev_info(&ov->dev->dev, "Sensor is an OV7610\n"); |
4853 | ov->sensor = SEN_OV7610; | 4858 | ov->sensor = SEN_OV7610; |
4854 | } else if ((rc & 3) == 1) { | 4859 | } else if ((rc & 3) == 1) { |
4855 | /* I don't know what's different about the 76BE yet. */ | 4860 | /* I don't know what's different about the 76BE yet. */ |
4856 | if (i2c_r(ov, 0x15) & 1) | 4861 | if (i2c_r(ov, 0x15) & 1) |
4857 | info("Sensor is an OV7620AE"); | 4862 | dev_info(&ov->dev->dev, "Sensor is an OV7620AE\n"); |
4858 | else | 4863 | else |
4859 | info("Sensor is an OV76BE"); | 4864 | dev_info(&ov->dev->dev, "Sensor is an OV76BE\n"); |
4860 | 4865 | ||
4861 | /* OV511+ will return all zero isoc data unless we | 4866 | /* OV511+ will return all zero isoc data unless we |
4862 | * configure the sensor as a 7620. Someone needs to | 4867 | * configure the sensor as a 7620. Someone needs to |
4863 | * find the exact reg. setting that causes this. */ | 4868 | * find the exact reg. setting that causes this. */ |
4864 | if (ov->bridge == BRG_OV511PLUS) { | 4869 | if (ov->bridge == BRG_OV511PLUS) { |
4865 | info("Enabling 511+/7620AE workaround"); | 4870 | dev_info(&ov->dev->dev, |
4871 | "Enabling 511+/7620AE workaround\n"); | ||
4866 | ov->sensor = SEN_OV7620; | 4872 | ov->sensor = SEN_OV7620; |
4867 | } else { | 4873 | } else { |
4868 | ov->sensor = SEN_OV76BE; | 4874 | ov->sensor = SEN_OV76BE; |
4869 | } | 4875 | } |
4870 | } else if ((rc & 3) == 0) { | 4876 | } else if ((rc & 3) == 0) { |
4871 | info("Sensor is an OV7620"); | 4877 | dev_info(&ov->dev->dev, "Sensor is an OV7620\n"); |
4872 | ov->sensor = SEN_OV7620; | 4878 | ov->sensor = SEN_OV7620; |
4873 | } else { | 4879 | } else { |
4874 | err("Unknown image sensor version: %d", rc & 3); | 4880 | err("Unknown image sensor version: %d", rc & 3); |
@@ -5024,16 +5030,16 @@ ov6xx0_configure(struct usb_ov511 *ov) | |||
5024 | 5030 | ||
5025 | if ((rc & 3) == 0) { | 5031 | if ((rc & 3) == 0) { |
5026 | ov->sensor = SEN_OV6630; | 5032 | ov->sensor = SEN_OV6630; |
5027 | info("Sensor is an OV6630"); | 5033 | dev_info(&ov->dev->dev, "Sensor is an OV6630\n"); |
5028 | } else if ((rc & 3) == 1) { | 5034 | } else if ((rc & 3) == 1) { |
5029 | ov->sensor = SEN_OV6620; | 5035 | ov->sensor = SEN_OV6620; |
5030 | info("Sensor is an OV6620"); | 5036 | dev_info(&ov->dev->dev, "Sensor is an OV6620\n"); |
5031 | } else if ((rc & 3) == 2) { | 5037 | } else if ((rc & 3) == 2) { |
5032 | ov->sensor = SEN_OV6630; | 5038 | ov->sensor = SEN_OV6630; |
5033 | info("Sensor is an OV6630AE"); | 5039 | dev_info(&ov->dev->dev, "Sensor is an OV6630AE\n"); |
5034 | } else if ((rc & 3) == 3) { | 5040 | } else if ((rc & 3) == 3) { |
5035 | ov->sensor = SEN_OV6630; | 5041 | ov->sensor = SEN_OV6630; |
5036 | info("Sensor is an OV6630AF"); | 5042 | dev_info(&ov->dev->dev, "Sensor is an OV6630AF\n"); |
5037 | } | 5043 | } |
5038 | 5044 | ||
5039 | /* Set sensor-specific vars */ | 5045 | /* Set sensor-specific vars */ |
@@ -5088,10 +5094,10 @@ ks0127_configure(struct usb_ov511 *ov) | |||
5088 | err("Error detecting sensor type"); | 5094 | err("Error detecting sensor type"); |
5089 | return -1; | 5095 | return -1; |
5090 | } else if ((rc & 0x0f) == 0) { | 5096 | } else if ((rc & 0x0f) == 0) { |
5091 | info("Sensor is a KS0127"); | 5097 | dev_info(&ov->dev->dev, "Sensor is a KS0127\n"); |
5092 | ov->sensor = SEN_KS0127; | 5098 | ov->sensor = SEN_KS0127; |
5093 | } else if ((rc & 0x0f) == 9) { | 5099 | } else if ((rc & 0x0f) == 9) { |
5094 | info("Sensor is a KS0127B Rev. A"); | 5100 | dev_info(&ov->dev->dev, "Sensor is a KS0127B Rev. A\n"); |
5095 | ov->sensor = SEN_KS0127B; | 5101 | ov->sensor = SEN_KS0127B; |
5096 | } | 5102 | } |
5097 | } else { | 5103 | } else { |
@@ -5200,7 +5206,8 @@ saa7111a_configure(struct usb_ov511 *ov) | |||
5200 | err("Error detecting sensor version"); | 5206 | err("Error detecting sensor version"); |
5201 | return -1; | 5207 | return -1; |
5202 | } else { | 5208 | } else { |
5203 | info("Sensor is an SAA7111A (version 0x%x)", rc); | 5209 | dev_info(&ov->dev->dev, |
5210 | "Sensor is an SAA7111A (version 0x%x)\n", rc); | ||
5204 | ov->sensor = SEN_SAA7111A; | 5211 | ov->sensor = SEN_SAA7111A; |
5205 | } | 5212 | } |
5206 | 5213 | ||
@@ -5262,7 +5269,7 @@ ov511_configure(struct usb_ov511 *ov) | |||
5262 | 5269 | ||
5263 | PDEBUG (1, "CustomID = %d", ov->customid); | 5270 | PDEBUG (1, "CustomID = %d", ov->customid); |
5264 | ov->desc = symbolic(camlist, ov->customid); | 5271 | ov->desc = symbolic(camlist, ov->customid); |
5265 | info("model: %s", ov->desc); | 5272 | dev_info(&ov->dev->dev, "model: %s\n", ov->desc); |
5266 | 5273 | ||
5267 | if (0 == strcmp(ov->desc, NOT_DEFINED_STR)) { | 5274 | if (0 == strcmp(ov->desc, NOT_DEFINED_STR)) { |
5268 | err("Camera type (%d) not recognized", ov->customid); | 5275 | err("Camera type (%d) not recognized", ov->customid); |
@@ -5426,7 +5433,8 @@ ov518_configure(struct usb_ov511 *ov) | |||
5426 | PDEBUG(4, ""); | 5433 | PDEBUG(4, ""); |
5427 | 5434 | ||
5428 | /* First 5 bits of custom ID reg are a revision ID on OV518 */ | 5435 | /* First 5 bits of custom ID reg are a revision ID on OV518 */ |
5429 | info("Device revision %d", 0x1F & reg_r(ov, R511_SYS_CUST_ID)); | 5436 | dev_info(&ov->dev->dev, "Device revision %d\n", |
5437 | 0x1F & reg_r(ov, R511_SYS_CUST_ID)); | ||
5430 | 5438 | ||
5431 | /* Give it the default description */ | 5439 | /* Give it the default description */ |
5432 | ov->desc = symbolic(camlist, 0); | 5440 | ov->desc = symbolic(camlist, 0); |
@@ -5773,7 +5781,8 @@ ov51x_probe(struct usb_interface *intf, const struct usb_device_id *id) | |||
5773 | goto error; | 5781 | goto error; |
5774 | } | 5782 | } |
5775 | 5783 | ||
5776 | info("USB %s video device found", symbolic(brglist, ov->bridge)); | 5784 | dev_info(&intf->dev, "USB %s video device found\n", |
5785 | symbolic(brglist, ov->bridge)); | ||
5777 | 5786 | ||
5778 | init_waitqueue_head(&ov->wq); | 5787 | init_waitqueue_head(&ov->wq); |
5779 | 5788 | ||
@@ -5854,8 +5863,8 @@ ov51x_probe(struct usb_interface *intf, const struct usb_device_id *id) | |||
5854 | goto error; | 5863 | goto error; |
5855 | } | 5864 | } |
5856 | 5865 | ||
5857 | info("Device at %s registered to minor %d", ov->usb_path, | 5866 | dev_info(&intf->dev, "Device at %s registered to minor %d\n", |
5858 | ov->vdev->minor); | 5867 | ov->usb_path, ov->vdev->minor); |
5859 | 5868 | ||
5860 | usb_set_intfdata(intf, ov); | 5869 | usb_set_intfdata(intf, ov); |
5861 | if (ov_create_sysfs(ov->vdev)) { | 5870 | if (ov_create_sysfs(ov->vdev)) { |
@@ -5958,7 +5967,8 @@ usb_ov511_init(void) | |||
5958 | if (retval) | 5967 | if (retval) |
5959 | goto out; | 5968 | goto out; |
5960 | 5969 | ||
5961 | info(DRIVER_VERSION " : " DRIVER_DESC); | 5970 | printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" |
5971 | DRIVER_DESC "\n"); | ||
5962 | 5972 | ||
5963 | out: | 5973 | out: |
5964 | return retval; | 5974 | return retval; |
@@ -5968,8 +5978,7 @@ static void __exit | |||
5968 | usb_ov511_exit(void) | 5978 | usb_ov511_exit(void) |
5969 | { | 5979 | { |
5970 | usb_deregister(&ov511_driver); | 5980 | usb_deregister(&ov511_driver); |
5971 | info("driver deregistered"); | 5981 | printk(KERN_INFO KBUILD_MODNAME ": driver deregistered\n"); |
5972 | |||
5973 | } | 5982 | } |
5974 | 5983 | ||
5975 | module_init(usb_ov511_init); | 5984 | module_init(usb_ov511_init); |
diff --git a/drivers/media/video/ov511.h b/drivers/media/video/ov511.h index baded1262ca9..70d99e52329d 100644 --- a/drivers/media/video/ov511.h +++ b/drivers/media/video/ov511.h | |||
@@ -12,7 +12,8 @@ | |||
12 | 12 | ||
13 | #ifdef OV511_DEBUG | 13 | #ifdef OV511_DEBUG |
14 | #define PDEBUG(level, fmt, args...) \ | 14 | #define PDEBUG(level, fmt, args...) \ |
15 | if (debug >= (level)) info("[%s:%d] " fmt, \ | 15 | if (debug >= (level)) \ |
16 | printk(KERN_INFO KBUILD_MODNAME "[%s:%d] \n" fmt, \ | ||
16 | __func__, __LINE__ , ## args) | 17 | __func__, __LINE__ , ## args) |
17 | #else | 18 | #else |
18 | #define PDEBUG(level, fmt, args...) do {} while(0) | 19 | #define PDEBUG(level, fmt, args...) do {} while(0) |
diff --git a/drivers/media/video/ovcamchip/ovcamchip_core.c b/drivers/media/video/ovcamchip/ovcamchip_core.c index 065c2454113e..2c4acbf5a4fe 100644 --- a/drivers/media/video/ovcamchip/ovcamchip_core.c +++ b/drivers/media/video/ovcamchip/ovcamchip_core.c | |||
@@ -49,12 +49,6 @@ MODULE_LICENSE("GPL"); | |||
49 | #define GENERIC_REG_ID_LOW 0x1D /* manufacturer ID LSB */ | 49 | #define GENERIC_REG_ID_LOW 0x1D /* manufacturer ID LSB */ |
50 | #define GENERIC_REG_COM_I 0x29 /* misc ID bits */ | 50 | #define GENERIC_REG_COM_I 0x29 /* misc ID bits */ |
51 | 51 | ||
52 | extern struct ovcamchip_ops ov6x20_ops; | ||
53 | extern struct ovcamchip_ops ov6x30_ops; | ||
54 | extern struct ovcamchip_ops ov7x10_ops; | ||
55 | extern struct ovcamchip_ops ov7x20_ops; | ||
56 | extern struct ovcamchip_ops ov76be_ops; | ||
57 | |||
58 | static char *chip_names[NUM_CC_TYPES] = { | 52 | static char *chip_names[NUM_CC_TYPES] = { |
59 | [CC_UNKNOWN] = "Unknown chip", | 53 | [CC_UNKNOWN] = "Unknown chip", |
60 | [CC_OV76BE] = "OV76BE", | 54 | [CC_OV76BE] = "OV76BE", |
diff --git a/drivers/media/video/ovcamchip/ovcamchip_priv.h b/drivers/media/video/ovcamchip/ovcamchip_priv.h index 9afa4fe47726..a05650faedda 100644 --- a/drivers/media/video/ovcamchip/ovcamchip_priv.h +++ b/drivers/media/video/ovcamchip/ovcamchip_priv.h | |||
@@ -53,6 +53,12 @@ struct ovcamchip { | |||
53 | int initialized; /* OVCAMCHIP_CMD_INITIALIZE was successful */ | 53 | int initialized; /* OVCAMCHIP_CMD_INITIALIZE was successful */ |
54 | }; | 54 | }; |
55 | 55 | ||
56 | extern struct ovcamchip_ops ov6x20_ops; | ||
57 | extern struct ovcamchip_ops ov6x30_ops; | ||
58 | extern struct ovcamchip_ops ov7x10_ops; | ||
59 | extern struct ovcamchip_ops ov7x20_ops; | ||
60 | extern struct ovcamchip_ops ov76be_ops; | ||
61 | |||
56 | /* --------------------------------- */ | 62 | /* --------------------------------- */ |
57 | /* I2C I/O */ | 63 | /* I2C I/O */ |
58 | /* --------------------------------- */ | 64 | /* --------------------------------- */ |
diff --git a/drivers/media/video/pms.c b/drivers/media/video/pms.c index 7c84f795db54..994807818aa2 100644 --- a/drivers/media/video/pms.c +++ b/drivers/media/video/pms.c | |||
@@ -47,6 +47,7 @@ struct pms_device | |||
47 | struct video_picture picture; | 47 | struct video_picture picture; |
48 | int height; | 48 | int height; |
49 | int width; | 49 | int width; |
50 | unsigned long in_use; | ||
50 | struct mutex lock; | 51 | struct mutex lock; |
51 | }; | 52 | }; |
52 | 53 | ||
@@ -881,10 +882,27 @@ static ssize_t pms_read(struct file *file, char __user *buf, | |||
881 | return len; | 882 | return len; |
882 | } | 883 | } |
883 | 884 | ||
885 | static int pms_exclusive_open(struct inode *inode, struct file *file) | ||
886 | { | ||
887 | struct video_device *v = video_devdata(file); | ||
888 | struct pms_device *pd = (struct pms_device *)v; | ||
889 | |||
890 | return test_and_set_bit(0, &pd->in_use) ? -EBUSY : 0; | ||
891 | } | ||
892 | |||
893 | static int pms_exclusive_release(struct inode *inode, struct file *file) | ||
894 | { | ||
895 | struct video_device *v = video_devdata(file); | ||
896 | struct pms_device *pd = (struct pms_device *)v; | ||
897 | |||
898 | clear_bit(0, &pd->in_use); | ||
899 | return 0; | ||
900 | } | ||
901 | |||
884 | static const struct file_operations pms_fops = { | 902 | static const struct file_operations pms_fops = { |
885 | .owner = THIS_MODULE, | 903 | .owner = THIS_MODULE, |
886 | .open = video_exclusive_open, | 904 | .open = pms_exclusive_open, |
887 | .release = video_exclusive_release, | 905 | .release = pms_exclusive_release, |
888 | .ioctl = pms_ioctl, | 906 | .ioctl = pms_ioctl, |
889 | #ifdef CONFIG_COMPAT | 907 | #ifdef CONFIG_COMPAT |
890 | .compat_ioctl = v4l_compat_ioctl32, | 908 | .compat_ioctl = v4l_compat_ioctl32, |
@@ -897,6 +915,7 @@ static struct video_device pms_template= | |||
897 | { | 915 | { |
898 | .name = "Mediavision PMS", | 916 | .name = "Mediavision PMS", |
899 | .fops = &pms_fops, | 917 | .fops = &pms_fops, |
918 | .release = video_device_release_empty, | ||
900 | }; | 919 | }; |
901 | 920 | ||
902 | static struct pms_device pms_device; | 921 | static struct pms_device pms_device; |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-ctrl.c b/drivers/media/video/pvrusb2/pvrusb2-ctrl.c index 0764fbfffb73..203f54cd18a1 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-ctrl.c +++ b/drivers/media/video/pvrusb2/pvrusb2-ctrl.c | |||
@@ -134,13 +134,17 @@ int pvr2_ctrl_get_min(struct pvr2_ctrl *cptr) | |||
134 | 134 | ||
135 | 135 | ||
136 | /* Retrieve control's default value (any type) */ | 136 | /* Retrieve control's default value (any type) */ |
137 | int pvr2_ctrl_get_def(struct pvr2_ctrl *cptr) | 137 | int pvr2_ctrl_get_def(struct pvr2_ctrl *cptr, int *valptr) |
138 | { | 138 | { |
139 | int ret = 0; | 139 | int ret = 0; |
140 | if (!cptr) return 0; | 140 | if (!cptr) return 0; |
141 | LOCK_TAKE(cptr->hdw->big_lock); do { | 141 | LOCK_TAKE(cptr->hdw->big_lock); do { |
142 | if (cptr->info->type == pvr2_ctl_int) { | 142 | if (cptr->info->type == pvr2_ctl_int) { |
143 | ret = cptr->info->default_value; | 143 | if (cptr->info->get_def_value) { |
144 | ret = cptr->info->get_def_value(cptr, valptr); | ||
145 | } else { | ||
146 | *valptr = cptr->info->default_value; | ||
147 | } | ||
144 | } | 148 | } |
145 | } while(0); LOCK_GIVE(cptr->hdw->big_lock); | 149 | } while(0); LOCK_GIVE(cptr->hdw->big_lock); |
146 | return ret; | 150 | return ret; |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-ctrl.h b/drivers/media/video/pvrusb2/pvrusb2-ctrl.h index 0371ae6e6e4e..794ff90121c7 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-ctrl.h +++ b/drivers/media/video/pvrusb2/pvrusb2-ctrl.h | |||
@@ -49,7 +49,7 @@ int pvr2_ctrl_get_max(struct pvr2_ctrl *); | |||
49 | int pvr2_ctrl_get_min(struct pvr2_ctrl *); | 49 | int pvr2_ctrl_get_min(struct pvr2_ctrl *); |
50 | 50 | ||
51 | /* Retrieve control's default value (any type) */ | 51 | /* Retrieve control's default value (any type) */ |
52 | int pvr2_ctrl_get_def(struct pvr2_ctrl *); | 52 | int pvr2_ctrl_get_def(struct pvr2_ctrl *, int *valptr); |
53 | 53 | ||
54 | /* Retrieve control's enumeration count (enum only) */ | 54 | /* Retrieve control's enumeration count (enum only) */ |
55 | int pvr2_ctrl_get_cnt(struct pvr2_ctrl *); | 55 | int pvr2_ctrl_get_cnt(struct pvr2_ctrl *); |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h index 657f861593b3..de7ee7264be6 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h | |||
@@ -82,6 +82,7 @@ struct pvr2_ctl_info { | |||
82 | 82 | ||
83 | /* Control's implementation */ | 83 | /* Control's implementation */ |
84 | pvr2_ctlf_get_value get_value; /* Get its value */ | 84 | pvr2_ctlf_get_value get_value; /* Get its value */ |
85 | pvr2_ctlf_get_value get_def_value; /* Get its default value */ | ||
85 | pvr2_ctlf_get_value get_min_value; /* Get minimum allowed value */ | 86 | pvr2_ctlf_get_value get_min_value; /* Get minimum allowed value */ |
86 | pvr2_ctlf_get_value get_max_value; /* Get maximum allowed value */ | 87 | pvr2_ctlf_get_value get_max_value; /* Get maximum allowed value */ |
87 | pvr2_ctlf_set_value set_value; /* Set its value */ | 88 | pvr2_ctlf_set_value set_value; /* Set its value */ |
@@ -307,6 +308,10 @@ struct pvr2_hdw { | |||
307 | struct v4l2_tuner tuner_signal_info; | 308 | struct v4l2_tuner tuner_signal_info; |
308 | int tuner_signal_stale; | 309 | int tuner_signal_stale; |
309 | 310 | ||
311 | /* Cropping capability info */ | ||
312 | struct v4l2_cropcap cropcap_info; | ||
313 | int cropcap_stale; | ||
314 | |||
310 | /* Video standard handling */ | 315 | /* Video standard handling */ |
311 | v4l2_std_id std_mask_eeprom; // Hardware supported selections | 316 | v4l2_std_id std_mask_eeprom; // Hardware supported selections |
312 | v4l2_std_id std_mask_avail; // Which standards we may select from | 317 | v4l2_std_id std_mask_avail; // Which standards we may select from |
@@ -367,6 +372,10 @@ struct pvr2_hdw { | |||
367 | VCREATE_DATA(bass); | 372 | VCREATE_DATA(bass); |
368 | VCREATE_DATA(treble); | 373 | VCREATE_DATA(treble); |
369 | VCREATE_DATA(mute); | 374 | VCREATE_DATA(mute); |
375 | VCREATE_DATA(cropl); | ||
376 | VCREATE_DATA(cropt); | ||
377 | VCREATE_DATA(cropw); | ||
378 | VCREATE_DATA(croph); | ||
370 | VCREATE_DATA(input); | 379 | VCREATE_DATA(input); |
371 | VCREATE_DATA(audiomode); | 380 | VCREATE_DATA(audiomode); |
372 | VCREATE_DATA(res_hor); | 381 | VCREATE_DATA(res_hor); |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index f051c6aa7f1f..94265bd3d926 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c | |||
@@ -298,6 +298,7 @@ static int pvr2_send_request_ex(struct pvr2_hdw *hdw, | |||
298 | unsigned int timeout,int probe_fl, | 298 | unsigned int timeout,int probe_fl, |
299 | void *write_data,unsigned int write_len, | 299 | void *write_data,unsigned int write_len, |
300 | void *read_data,unsigned int read_len); | 300 | void *read_data,unsigned int read_len); |
301 | static int pvr2_hdw_check_cropcap(struct pvr2_hdw *hdw); | ||
301 | 302 | ||
302 | 303 | ||
303 | static void trace_stbit(const char *name,int val) | 304 | static void trace_stbit(const char *name,int val) |
@@ -402,6 +403,194 @@ static int ctrl_freq_set(struct pvr2_ctrl *cptr,int m,int v) | |||
402 | return 0; | 403 | return 0; |
403 | } | 404 | } |
404 | 405 | ||
406 | static int ctrl_cropl_min_get(struct pvr2_ctrl *cptr, int *left) | ||
407 | { | ||
408 | struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; | ||
409 | int stat = pvr2_hdw_check_cropcap(cptr->hdw); | ||
410 | if (stat != 0) { | ||
411 | return stat; | ||
412 | } | ||
413 | *left = cap->bounds.left; | ||
414 | return 0; | ||
415 | } | ||
416 | |||
417 | static int ctrl_cropl_max_get(struct pvr2_ctrl *cptr, int *left) | ||
418 | { | ||
419 | struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; | ||
420 | int stat = pvr2_hdw_check_cropcap(cptr->hdw); | ||
421 | if (stat != 0) { | ||
422 | return stat; | ||
423 | } | ||
424 | *left = cap->bounds.left; | ||
425 | if (cap->bounds.width > cptr->hdw->cropw_val) { | ||
426 | *left += cap->bounds.width - cptr->hdw->cropw_val; | ||
427 | } | ||
428 | return 0; | ||
429 | } | ||
430 | |||
431 | static int ctrl_cropt_min_get(struct pvr2_ctrl *cptr, int *top) | ||
432 | { | ||
433 | struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; | ||
434 | int stat = pvr2_hdw_check_cropcap(cptr->hdw); | ||
435 | if (stat != 0) { | ||
436 | return stat; | ||
437 | } | ||
438 | *top = cap->bounds.top; | ||
439 | return 0; | ||
440 | } | ||
441 | |||
442 | static int ctrl_cropt_max_get(struct pvr2_ctrl *cptr, int *top) | ||
443 | { | ||
444 | struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; | ||
445 | int stat = pvr2_hdw_check_cropcap(cptr->hdw); | ||
446 | if (stat != 0) { | ||
447 | return stat; | ||
448 | } | ||
449 | *top = cap->bounds.top; | ||
450 | if (cap->bounds.height > cptr->hdw->croph_val) { | ||
451 | *top += cap->bounds.height - cptr->hdw->croph_val; | ||
452 | } | ||
453 | return 0; | ||
454 | } | ||
455 | |||
456 | static int ctrl_cropw_max_get(struct pvr2_ctrl *cptr, int *val) | ||
457 | { | ||
458 | struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; | ||
459 | int stat = pvr2_hdw_check_cropcap(cptr->hdw); | ||
460 | if (stat != 0) { | ||
461 | return stat; | ||
462 | } | ||
463 | *val = 0; | ||
464 | if (cap->bounds.width > cptr->hdw->cropl_val) { | ||
465 | *val = cap->bounds.width - cptr->hdw->cropl_val; | ||
466 | } | ||
467 | return 0; | ||
468 | } | ||
469 | |||
470 | static int ctrl_croph_max_get(struct pvr2_ctrl *cptr, int *val) | ||
471 | { | ||
472 | struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; | ||
473 | int stat = pvr2_hdw_check_cropcap(cptr->hdw); | ||
474 | if (stat != 0) { | ||
475 | return stat; | ||
476 | } | ||
477 | *val = 0; | ||
478 | if (cap->bounds.height > cptr->hdw->cropt_val) { | ||
479 | *val = cap->bounds.height - cptr->hdw->cropt_val; | ||
480 | } | ||
481 | return 0; | ||
482 | } | ||
483 | |||
484 | static int ctrl_get_cropcapbl(struct pvr2_ctrl *cptr, int *val) | ||
485 | { | ||
486 | struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; | ||
487 | int stat = pvr2_hdw_check_cropcap(cptr->hdw); | ||
488 | if (stat != 0) { | ||
489 | return stat; | ||
490 | } | ||
491 | *val = cap->bounds.left; | ||
492 | return 0; | ||
493 | } | ||
494 | |||
495 | static int ctrl_get_cropcapbt(struct pvr2_ctrl *cptr, int *val) | ||
496 | { | ||
497 | struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; | ||
498 | int stat = pvr2_hdw_check_cropcap(cptr->hdw); | ||
499 | if (stat != 0) { | ||
500 | return stat; | ||
501 | } | ||
502 | *val = cap->bounds.top; | ||
503 | return 0; | ||
504 | } | ||
505 | |||
506 | static int ctrl_get_cropcapbw(struct pvr2_ctrl *cptr, int *val) | ||
507 | { | ||
508 | struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; | ||
509 | int stat = pvr2_hdw_check_cropcap(cptr->hdw); | ||
510 | if (stat != 0) { | ||
511 | return stat; | ||
512 | } | ||
513 | *val = cap->bounds.width; | ||
514 | return 0; | ||
515 | } | ||
516 | |||
517 | static int ctrl_get_cropcapbh(struct pvr2_ctrl *cptr, int *val) | ||
518 | { | ||
519 | struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; | ||
520 | int stat = pvr2_hdw_check_cropcap(cptr->hdw); | ||
521 | if (stat != 0) { | ||
522 | return stat; | ||
523 | } | ||
524 | *val = cap->bounds.height; | ||
525 | return 0; | ||
526 | } | ||
527 | |||
528 | static int ctrl_get_cropcapdl(struct pvr2_ctrl *cptr, int *val) | ||
529 | { | ||
530 | struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; | ||
531 | int stat = pvr2_hdw_check_cropcap(cptr->hdw); | ||
532 | if (stat != 0) { | ||
533 | return stat; | ||
534 | } | ||
535 | *val = cap->defrect.left; | ||
536 | return 0; | ||
537 | } | ||
538 | |||
539 | static int ctrl_get_cropcapdt(struct pvr2_ctrl *cptr, int *val) | ||
540 | { | ||
541 | struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; | ||
542 | int stat = pvr2_hdw_check_cropcap(cptr->hdw); | ||
543 | if (stat != 0) { | ||
544 | return stat; | ||
545 | } | ||
546 | *val = cap->defrect.top; | ||
547 | return 0; | ||
548 | } | ||
549 | |||
550 | static int ctrl_get_cropcapdw(struct pvr2_ctrl *cptr, int *val) | ||
551 | { | ||
552 | struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; | ||
553 | int stat = pvr2_hdw_check_cropcap(cptr->hdw); | ||
554 | if (stat != 0) { | ||
555 | return stat; | ||
556 | } | ||
557 | *val = cap->defrect.width; | ||
558 | return 0; | ||
559 | } | ||
560 | |||
561 | static int ctrl_get_cropcapdh(struct pvr2_ctrl *cptr, int *val) | ||
562 | { | ||
563 | struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; | ||
564 | int stat = pvr2_hdw_check_cropcap(cptr->hdw); | ||
565 | if (stat != 0) { | ||
566 | return stat; | ||
567 | } | ||
568 | *val = cap->defrect.height; | ||
569 | return 0; | ||
570 | } | ||
571 | |||
572 | static int ctrl_get_cropcappan(struct pvr2_ctrl *cptr, int *val) | ||
573 | { | ||
574 | struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; | ||
575 | int stat = pvr2_hdw_check_cropcap(cptr->hdw); | ||
576 | if (stat != 0) { | ||
577 | return stat; | ||
578 | } | ||
579 | *val = cap->pixelaspect.numerator; | ||
580 | return 0; | ||
581 | } | ||
582 | |||
583 | static int ctrl_get_cropcappad(struct pvr2_ctrl *cptr, int *val) | ||
584 | { | ||
585 | struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; | ||
586 | int stat = pvr2_hdw_check_cropcap(cptr->hdw); | ||
587 | if (stat != 0) { | ||
588 | return stat; | ||
589 | } | ||
590 | *val = cap->pixelaspect.denominator; | ||
591 | return 0; | ||
592 | } | ||
593 | |||
405 | static int ctrl_vres_max_get(struct pvr2_ctrl *cptr,int *vp) | 594 | static int ctrl_vres_max_get(struct pvr2_ctrl *cptr,int *vp) |
406 | { | 595 | { |
407 | /* Actual maximum depends on the video standard in effect. */ | 596 | /* Actual maximum depends on the video standard in effect. */ |
@@ -779,6 +968,10 @@ VCREATE_FUNCS(balance) | |||
779 | VCREATE_FUNCS(bass) | 968 | VCREATE_FUNCS(bass) |
780 | VCREATE_FUNCS(treble) | 969 | VCREATE_FUNCS(treble) |
781 | VCREATE_FUNCS(mute) | 970 | VCREATE_FUNCS(mute) |
971 | VCREATE_FUNCS(cropl) | ||
972 | VCREATE_FUNCS(cropt) | ||
973 | VCREATE_FUNCS(cropw) | ||
974 | VCREATE_FUNCS(croph) | ||
782 | VCREATE_FUNCS(audiomode) | 975 | VCREATE_FUNCS(audiomode) |
783 | VCREATE_FUNCS(res_hor) | 976 | VCREATE_FUNCS(res_hor) |
784 | VCREATE_FUNCS(res_ver) | 977 | VCREATE_FUNCS(res_ver) |
@@ -849,6 +1042,72 @@ static const struct pvr2_ctl_info control_defs[] = { | |||
849 | .default_value = 0, | 1042 | .default_value = 0, |
850 | DEFREF(mute), | 1043 | DEFREF(mute), |
851 | DEFBOOL, | 1044 | DEFBOOL, |
1045 | }, { | ||
1046 | .desc = "Capture crop left margin", | ||
1047 | .name = "crop_left", | ||
1048 | .internal_id = PVR2_CID_CROPL, | ||
1049 | .default_value = 0, | ||
1050 | DEFREF(cropl), | ||
1051 | DEFINT(-129, 340), | ||
1052 | .get_min_value = ctrl_cropl_min_get, | ||
1053 | .get_max_value = ctrl_cropl_max_get, | ||
1054 | .get_def_value = ctrl_get_cropcapdl, | ||
1055 | }, { | ||
1056 | .desc = "Capture crop top margin", | ||
1057 | .name = "crop_top", | ||
1058 | .internal_id = PVR2_CID_CROPT, | ||
1059 | .default_value = 0, | ||
1060 | DEFREF(cropt), | ||
1061 | DEFINT(-35, 544), | ||
1062 | .get_min_value = ctrl_cropt_min_get, | ||
1063 | .get_max_value = ctrl_cropt_max_get, | ||
1064 | .get_def_value = ctrl_get_cropcapdt, | ||
1065 | }, { | ||
1066 | .desc = "Capture crop width", | ||
1067 | .name = "crop_width", | ||
1068 | .internal_id = PVR2_CID_CROPW, | ||
1069 | .default_value = 720, | ||
1070 | DEFREF(cropw), | ||
1071 | .get_max_value = ctrl_cropw_max_get, | ||
1072 | .get_def_value = ctrl_get_cropcapdw, | ||
1073 | }, { | ||
1074 | .desc = "Capture crop height", | ||
1075 | .name = "crop_height", | ||
1076 | .internal_id = PVR2_CID_CROPH, | ||
1077 | .default_value = 480, | ||
1078 | DEFREF(croph), | ||
1079 | .get_max_value = ctrl_croph_max_get, | ||
1080 | .get_def_value = ctrl_get_cropcapdh, | ||
1081 | }, { | ||
1082 | .desc = "Capture capability pixel aspect numerator", | ||
1083 | .name = "cropcap_pixel_numerator", | ||
1084 | .internal_id = PVR2_CID_CROPCAPPAN, | ||
1085 | .get_value = ctrl_get_cropcappan, | ||
1086 | }, { | ||
1087 | .desc = "Capture capability pixel aspect denominator", | ||
1088 | .name = "cropcap_pixel_denominator", | ||
1089 | .internal_id = PVR2_CID_CROPCAPPAD, | ||
1090 | .get_value = ctrl_get_cropcappad, | ||
1091 | }, { | ||
1092 | .desc = "Capture capability bounds top", | ||
1093 | .name = "cropcap_bounds_top", | ||
1094 | .internal_id = PVR2_CID_CROPCAPBT, | ||
1095 | .get_value = ctrl_get_cropcapbt, | ||
1096 | }, { | ||
1097 | .desc = "Capture capability bounds left", | ||
1098 | .name = "cropcap_bounds_left", | ||
1099 | .internal_id = PVR2_CID_CROPCAPBL, | ||
1100 | .get_value = ctrl_get_cropcapbl, | ||
1101 | }, { | ||
1102 | .desc = "Capture capability bounds width", | ||
1103 | .name = "cropcap_bounds_width", | ||
1104 | .internal_id = PVR2_CID_CROPCAPBW, | ||
1105 | .get_value = ctrl_get_cropcapbw, | ||
1106 | }, { | ||
1107 | .desc = "Capture capability bounds height", | ||
1108 | .name = "cropcap_bounds_height", | ||
1109 | .internal_id = PVR2_CID_CROPCAPBH, | ||
1110 | .get_value = ctrl_get_cropcapbh, | ||
852 | },{ | 1111 | },{ |
853 | .desc = "Video Source", | 1112 | .desc = "Video Source", |
854 | .name = "input", | 1113 | .name = "input", |
@@ -1313,9 +1572,19 @@ int pvr2_upload_firmware2(struct pvr2_hdw *hdw) | |||
1313 | if (bcnt > FIRMWARE_CHUNK_SIZE) bcnt = FIRMWARE_CHUNK_SIZE; | 1572 | if (bcnt > FIRMWARE_CHUNK_SIZE) bcnt = FIRMWARE_CHUNK_SIZE; |
1314 | memcpy(fw_ptr, fw_entry->data + fw_done, bcnt); | 1573 | memcpy(fw_ptr, fw_entry->data + fw_done, bcnt); |
1315 | /* Usbsnoop log shows that we must swap bytes... */ | 1574 | /* Usbsnoop log shows that we must swap bytes... */ |
1575 | /* Some background info: The data being swapped here is a | ||
1576 | firmware image destined for the mpeg encoder chip that | ||
1577 | lives at the other end of a USB endpoint. The encoder | ||
1578 | chip always talks in 32 bit chunks and its storage is | ||
1579 | organized into 32 bit words. However from the file | ||
1580 | system to the encoder chip everything is purely a byte | ||
1581 | stream. The firmware file's contents are always 32 bit | ||
1582 | swapped from what the encoder expects. Thus the need | ||
1583 | always exists to swap the bytes regardless of the endian | ||
1584 | type of the host processor and therefore swab32() makes | ||
1585 | the most sense. */ | ||
1316 | for (icnt = 0; icnt < bcnt/4 ; icnt++) | 1586 | for (icnt = 0; icnt < bcnt/4 ; icnt++) |
1317 | ((u32 *)fw_ptr)[icnt] = | 1587 | ((u32 *)fw_ptr)[icnt] = swab32(((u32 *)fw_ptr)[icnt]); |
1318 | ___swab32(((u32 *)fw_ptr)[icnt]); | ||
1319 | 1588 | ||
1320 | ret |= usb_bulk_msg(hdw->usb_dev, pipe, fw_ptr,bcnt, | 1589 | ret |= usb_bulk_msg(hdw->usb_dev, pipe, fw_ptr,bcnt, |
1321 | &actual_length, HZ); | 1590 | &actual_length, HZ); |
@@ -1905,7 +2174,7 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf, | |||
1905 | const struct usb_device_id *devid) | 2174 | const struct usb_device_id *devid) |
1906 | { | 2175 | { |
1907 | unsigned int idx,cnt1,cnt2,m; | 2176 | unsigned int idx,cnt1,cnt2,m; |
1908 | struct pvr2_hdw *hdw; | 2177 | struct pvr2_hdw *hdw = NULL; |
1909 | int valid_std_mask; | 2178 | int valid_std_mask; |
1910 | struct pvr2_ctrl *cptr; | 2179 | struct pvr2_ctrl *cptr; |
1911 | const struct pvr2_device_desc *hdw_desc; | 2180 | const struct pvr2_device_desc *hdw_desc; |
@@ -1915,6 +2184,16 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf, | |||
1915 | 2184 | ||
1916 | hdw_desc = (const struct pvr2_device_desc *)(devid->driver_info); | 2185 | hdw_desc = (const struct pvr2_device_desc *)(devid->driver_info); |
1917 | 2186 | ||
2187 | if (hdw_desc == NULL) { | ||
2188 | pvr2_trace(PVR2_TRACE_INIT, "pvr2_hdw_create:" | ||
2189 | " No device description pointer," | ||
2190 | " unable to continue."); | ||
2191 | pvr2_trace(PVR2_TRACE_INIT, "If you have a new device type," | ||
2192 | " please contact Mike Isely <isely@pobox.com>" | ||
2193 | " to get it included in the driver\n"); | ||
2194 | goto fail; | ||
2195 | } | ||
2196 | |||
1918 | hdw = kzalloc(sizeof(*hdw),GFP_KERNEL); | 2197 | hdw = kzalloc(sizeof(*hdw),GFP_KERNEL); |
1919 | pvr2_trace(PVR2_TRACE_INIT,"pvr2_hdw_create: hdw=%p, type \"%s\"", | 2198 | pvr2_trace(PVR2_TRACE_INIT,"pvr2_hdw_create: hdw=%p, type \"%s\"", |
1920 | hdw,hdw_desc->description); | 2199 | hdw,hdw_desc->description); |
@@ -2072,6 +2351,7 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf, | |||
2072 | valid_std_mask; | 2351 | valid_std_mask; |
2073 | } | 2352 | } |
2074 | 2353 | ||
2354 | hdw->cropcap_stale = !0; | ||
2075 | hdw->eeprom_addr = -1; | 2355 | hdw->eeprom_addr = -1; |
2076 | hdw->unit_number = -1; | 2356 | hdw->unit_number = -1; |
2077 | hdw->v4l_minor_number_video = -1; | 2357 | hdw->v4l_minor_number_video = -1; |
@@ -2508,6 +2788,28 @@ static int pvr2_hdw_commit_execute(struct pvr2_hdw *hdw) | |||
2508 | /* Can't commit anything until pathway is ok. */ | 2788 | /* Can't commit anything until pathway is ok. */ |
2509 | return 0; | 2789 | return 0; |
2510 | } | 2790 | } |
2791 | /* The broadcast decoder can only scale down, so if | ||
2792 | * res_*_dirty && crop window < output format ==> enlarge crop. | ||
2793 | * | ||
2794 | * The mpeg encoder receives fields of res_hor_val dots and | ||
2795 | * res_ver_val halflines. Limits: hor<=720, ver<=576. | ||
2796 | */ | ||
2797 | if (hdw->res_hor_dirty && hdw->cropw_val < hdw->res_hor_val) { | ||
2798 | hdw->cropw_val = hdw->res_hor_val; | ||
2799 | hdw->cropw_dirty = !0; | ||
2800 | } else if (hdw->cropw_dirty) { | ||
2801 | hdw->res_hor_dirty = !0; /* must rescale */ | ||
2802 | hdw->res_hor_val = min(720, hdw->cropw_val); | ||
2803 | } | ||
2804 | if (hdw->res_ver_dirty && hdw->croph_val < hdw->res_ver_val) { | ||
2805 | hdw->croph_val = hdw->res_ver_val; | ||
2806 | hdw->croph_dirty = !0; | ||
2807 | } else if (hdw->croph_dirty) { | ||
2808 | int nvres = hdw->std_mask_cur & V4L2_STD_525_60 ? 480 : 576; | ||
2809 | hdw->res_ver_dirty = !0; | ||
2810 | hdw->res_ver_val = min(nvres, hdw->croph_val); | ||
2811 | } | ||
2812 | |||
2511 | /* If any of the below has changed, then we can't do the update | 2813 | /* If any of the below has changed, then we can't do the update |
2512 | while the pipeline is running. Pipeline must be paused first | 2814 | while the pipeline is running. Pipeline must be paused first |
2513 | and decoder -> encoder connection be made quiescent before we | 2815 | and decoder -> encoder connection be made quiescent before we |
@@ -2518,6 +2820,8 @@ static int pvr2_hdw_commit_execute(struct pvr2_hdw *hdw) | |||
2518 | hdw->srate_dirty || | 2820 | hdw->srate_dirty || |
2519 | hdw->res_ver_dirty || | 2821 | hdw->res_ver_dirty || |
2520 | hdw->res_hor_dirty || | 2822 | hdw->res_hor_dirty || |
2823 | hdw->cropw_dirty || | ||
2824 | hdw->croph_dirty || | ||
2521 | hdw->input_dirty || | 2825 | hdw->input_dirty || |
2522 | (hdw->active_stream_type != hdw->desired_stream_type)); | 2826 | (hdw->active_stream_type != hdw->desired_stream_type)); |
2523 | if (disruptive_change && !hdw->state_pipeline_idle) { | 2827 | if (disruptive_change && !hdw->state_pipeline_idle) { |
@@ -2587,6 +2891,9 @@ static int pvr2_hdw_commit_execute(struct pvr2_hdw *hdw) | |||
2587 | } | 2891 | } |
2588 | 2892 | ||
2589 | hdw->state_pipeline_config = !0; | 2893 | hdw->state_pipeline_config = !0; |
2894 | /* Hardware state may have changed in a way to cause the cropping | ||
2895 | capabilities to have changed. So mark it stale, which will | ||
2896 | cause a later re-fetch. */ | ||
2590 | trace_stbit("state_pipeline_config",hdw->state_pipeline_config); | 2897 | trace_stbit("state_pipeline_config",hdw->state_pipeline_config); |
2591 | return !0; | 2898 | return !0; |
2592 | } | 2899 | } |
@@ -2677,6 +2984,33 @@ void pvr2_hdw_execute_tuner_poll(struct pvr2_hdw *hdw) | |||
2677 | } | 2984 | } |
2678 | 2985 | ||
2679 | 2986 | ||
2987 | static int pvr2_hdw_check_cropcap(struct pvr2_hdw *hdw) | ||
2988 | { | ||
2989 | if (!hdw->cropcap_stale) { | ||
2990 | return 0; | ||
2991 | } | ||
2992 | pvr2_i2c_core_status_poll(hdw); | ||
2993 | if (hdw->cropcap_stale) { | ||
2994 | return -EIO; | ||
2995 | } | ||
2996 | return 0; | ||
2997 | } | ||
2998 | |||
2999 | |||
3000 | /* Return information about cropping capabilities */ | ||
3001 | int pvr2_hdw_get_cropcap(struct pvr2_hdw *hdw, struct v4l2_cropcap *pp) | ||
3002 | { | ||
3003 | int stat = 0; | ||
3004 | LOCK_TAKE(hdw->big_lock); | ||
3005 | stat = pvr2_hdw_check_cropcap(hdw); | ||
3006 | if (!stat) { | ||
3007 | memcpy(pp, &hdw->cropcap_info, sizeof(hdw->cropcap_info)); | ||
3008 | } | ||
3009 | LOCK_GIVE(hdw->big_lock); | ||
3010 | return stat; | ||
3011 | } | ||
3012 | |||
3013 | |||
2680 | /* Return information about the tuner */ | 3014 | /* Return information about the tuner */ |
2681 | int pvr2_hdw_get_tuner_status(struct pvr2_hdw *hdw,struct v4l2_tuner *vtp) | 3015 | int pvr2_hdw_get_tuner_status(struct pvr2_hdw *hdw,struct v4l2_tuner *vtp) |
2682 | { | 3016 | { |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.h b/drivers/media/video/pvrusb2/pvrusb2-hdw.h index c04956d304a7..49482d1f2b28 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.h +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.h | |||
@@ -36,6 +36,16 @@ | |||
36 | #define PVR2_CID_FREQUENCY 6 | 36 | #define PVR2_CID_FREQUENCY 6 |
37 | #define PVR2_CID_HRES 7 | 37 | #define PVR2_CID_HRES 7 |
38 | #define PVR2_CID_VRES 8 | 38 | #define PVR2_CID_VRES 8 |
39 | #define PVR2_CID_CROPL 9 | ||
40 | #define PVR2_CID_CROPT 10 | ||
41 | #define PVR2_CID_CROPW 11 | ||
42 | #define PVR2_CID_CROPH 12 | ||
43 | #define PVR2_CID_CROPCAPPAN 13 | ||
44 | #define PVR2_CID_CROPCAPPAD 14 | ||
45 | #define PVR2_CID_CROPCAPBL 15 | ||
46 | #define PVR2_CID_CROPCAPBT 16 | ||
47 | #define PVR2_CID_CROPCAPBW 17 | ||
48 | #define PVR2_CID_CROPCAPBH 18 | ||
39 | 49 | ||
40 | /* Legal values for the INPUT state variable */ | 50 | /* Legal values for the INPUT state variable */ |
41 | #define PVR2_CVAL_INPUT_TV 0 | 51 | #define PVR2_CVAL_INPUT_TV 0 |
@@ -170,6 +180,9 @@ void pvr2_hdw_execute_tuner_poll(struct pvr2_hdw *); | |||
170 | /* Return information about the tuner */ | 180 | /* Return information about the tuner */ |
171 | int pvr2_hdw_get_tuner_status(struct pvr2_hdw *,struct v4l2_tuner *); | 181 | int pvr2_hdw_get_tuner_status(struct pvr2_hdw *,struct v4l2_tuner *); |
172 | 182 | ||
183 | /* Return information about cropping capabilities */ | ||
184 | int pvr2_hdw_get_cropcap(struct pvr2_hdw *, struct v4l2_cropcap *); | ||
185 | |||
173 | /* Query device and see if it thinks it is on a high-speed USB link */ | 186 | /* Query device and see if it thinks it is on a high-speed USB link */ |
174 | int pvr2_hdw_is_hsm(struct pvr2_hdw *); | 187 | int pvr2_hdw_is_hsm(struct pvr2_hdw *); |
175 | 188 | ||
diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c index ccdb429fc7af..94a47718e88e 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c +++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c | |||
@@ -37,8 +37,9 @@ | |||
37 | #define OP_VOLUME 3 | 37 | #define OP_VOLUME 3 |
38 | #define OP_FREQ 4 | 38 | #define OP_FREQ 4 |
39 | #define OP_AUDIORATE 5 | 39 | #define OP_AUDIORATE 5 |
40 | #define OP_SIZE 6 | 40 | #define OP_CROP 6 |
41 | #define OP_LOG 7 | 41 | #define OP_SIZE 7 |
42 | #define OP_LOG 8 | ||
42 | 43 | ||
43 | static const struct pvr2_i2c_op * const ops[] = { | 44 | static const struct pvr2_i2c_op * const ops[] = { |
44 | [OP_STANDARD] = &pvr2_i2c_op_v4l2_standard, | 45 | [OP_STANDARD] = &pvr2_i2c_op_v4l2_standard, |
@@ -46,6 +47,7 @@ static const struct pvr2_i2c_op * const ops[] = { | |||
46 | [OP_BCSH] = &pvr2_i2c_op_v4l2_bcsh, | 47 | [OP_BCSH] = &pvr2_i2c_op_v4l2_bcsh, |
47 | [OP_VOLUME] = &pvr2_i2c_op_v4l2_volume, | 48 | [OP_VOLUME] = &pvr2_i2c_op_v4l2_volume, |
48 | [OP_FREQ] = &pvr2_i2c_op_v4l2_frequency, | 49 | [OP_FREQ] = &pvr2_i2c_op_v4l2_frequency, |
50 | [OP_CROP] = &pvr2_i2c_op_v4l2_crop, | ||
49 | [OP_SIZE] = &pvr2_i2c_op_v4l2_size, | 51 | [OP_SIZE] = &pvr2_i2c_op_v4l2_size, |
50 | [OP_LOG] = &pvr2_i2c_op_v4l2_log, | 52 | [OP_LOG] = &pvr2_i2c_op_v4l2_log, |
51 | }; | 53 | }; |
@@ -59,6 +61,7 @@ void pvr2_i2c_probe(struct pvr2_hdw *hdw,struct pvr2_i2c_client *cp) | |||
59 | (1 << OP_BCSH) | | 61 | (1 << OP_BCSH) | |
60 | (1 << OP_VOLUME) | | 62 | (1 << OP_VOLUME) | |
61 | (1 << OP_FREQ) | | 63 | (1 << OP_FREQ) | |
64 | (1 << OP_CROP) | | ||
62 | (1 << OP_SIZE) | | 65 | (1 << OP_SIZE) | |
63 | (1 << OP_LOG)); | 66 | (1 << OP_LOG)); |
64 | cp->status_poll = pvr2_v4l2_cmd_status_poll; | 67 | cp->status_poll = pvr2_v4l2_cmd_status_poll; |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c index 55f04a0b2047..16bb11902a52 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c +++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c | |||
@@ -37,6 +37,7 @@ static void set_standard(struct pvr2_hdw *hdw) | |||
37 | pvr2_i2c_core_cmd(hdw,VIDIOC_S_STD,&vs); | 37 | pvr2_i2c_core_cmd(hdw,VIDIOC_S_STD,&vs); |
38 | } | 38 | } |
39 | hdw->tuner_signal_stale = !0; | 39 | hdw->tuner_signal_stale = !0; |
40 | hdw->cropcap_stale = !0; | ||
40 | } | 41 | } |
41 | 42 | ||
42 | 43 | ||
@@ -233,6 +234,37 @@ const struct pvr2_i2c_op pvr2_i2c_op_v4l2_size = { | |||
233 | }; | 234 | }; |
234 | 235 | ||
235 | 236 | ||
237 | static void set_crop(struct pvr2_hdw *hdw) | ||
238 | { | ||
239 | struct v4l2_crop crop; | ||
240 | |||
241 | memset(&crop, 0, sizeof crop); | ||
242 | crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
243 | crop.c.left = hdw->cropl_val; | ||
244 | crop.c.top = hdw->cropt_val; | ||
245 | crop.c.height = hdw->croph_val; | ||
246 | crop.c.width = hdw->cropw_val; | ||
247 | |||
248 | pvr2_trace(PVR2_TRACE_CHIPS, | ||
249 | "i2c v4l2 set_crop crop=%d:%d:%d:%d", | ||
250 | crop.c.width, crop.c.height, crop.c.left, crop.c.top); | ||
251 | |||
252 | pvr2_i2c_core_cmd(hdw, VIDIOC_S_CROP, &crop); | ||
253 | } | ||
254 | |||
255 | static int check_crop(struct pvr2_hdw *hdw) | ||
256 | { | ||
257 | return (hdw->cropl_dirty || hdw->cropt_dirty || | ||
258 | hdw->cropw_dirty || hdw->croph_dirty); | ||
259 | } | ||
260 | |||
261 | const struct pvr2_i2c_op pvr2_i2c_op_v4l2_crop = { | ||
262 | .check = check_crop, | ||
263 | .update = set_crop, | ||
264 | .name = "v4l2_crop", | ||
265 | }; | ||
266 | |||
267 | |||
236 | static void do_log(struct pvr2_hdw *hdw) | 268 | static void do_log(struct pvr2_hdw *hdw) |
237 | { | 269 | { |
238 | pvr2_trace(PVR2_TRACE_CHIPS,"i2c v4l2 do_log()"); | 270 | pvr2_trace(PVR2_TRACE_CHIPS,"i2c v4l2 do_log()"); |
@@ -263,7 +295,19 @@ void pvr2_v4l2_cmd_stream(struct pvr2_i2c_client *cp,int fl) | |||
263 | 295 | ||
264 | void pvr2_v4l2_cmd_status_poll(struct pvr2_i2c_client *cp) | 296 | void pvr2_v4l2_cmd_status_poll(struct pvr2_i2c_client *cp) |
265 | { | 297 | { |
266 | pvr2_i2c_client_cmd(cp,VIDIOC_G_TUNER,&cp->hdw->tuner_signal_info); | 298 | int stat; |
299 | struct pvr2_hdw *hdw = cp->hdw; | ||
300 | if (hdw->cropcap_stale) { | ||
301 | hdw->cropcap_info.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
302 | stat = pvr2_i2c_client_cmd(cp, VIDIOC_CROPCAP, | ||
303 | &hdw->cropcap_info); | ||
304 | if (stat == 0) { | ||
305 | /* Check was successful, so the data is no | ||
306 | longer considered stale. */ | ||
307 | hdw->cropcap_stale = 0; | ||
308 | } | ||
309 | } | ||
310 | pvr2_i2c_client_cmd(cp, VIDIOC_G_TUNER, &hdw->tuner_signal_info); | ||
267 | } | 311 | } |
268 | 312 | ||
269 | 313 | ||
diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h b/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h index 7fa38683b3b1..eb744a20610d 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h +++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h | |||
@@ -29,6 +29,7 @@ extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_radio; | |||
29 | extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_bcsh; | 29 | extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_bcsh; |
30 | extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_volume; | 30 | extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_volume; |
31 | extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_frequency; | 31 | extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_frequency; |
32 | extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_crop; | ||
32 | extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_size; | 33 | extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_size; |
33 | extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_audiomode; | 34 | extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_audiomode; |
34 | extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_log; | 35 | extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_log; |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c index e600576a6c4b..d6a35401fefb 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c +++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c | |||
@@ -827,7 +827,7 @@ static unsigned int pvr2_i2c_client_describe(struct pvr2_i2c_client *cp, | |||
827 | if ((detail & PVR2_I2C_DETAIL_CTLMASK) && cp->ctl_mask) { | 827 | if ((detail & PVR2_I2C_DETAIL_CTLMASK) && cp->ctl_mask) { |
828 | unsigned int idx; | 828 | unsigned int idx; |
829 | unsigned long msk,sm; | 829 | unsigned long msk,sm; |
830 | int spcfl; | 830 | |
831 | bcnt = scnprintf(buf,maxlen," ["); | 831 | bcnt = scnprintf(buf,maxlen," ["); |
832 | ccnt += bcnt; buf += bcnt; maxlen -= bcnt; | 832 | ccnt += bcnt; buf += bcnt; maxlen -= bcnt; |
833 | sm = 0; | 833 | sm = 0; |
@@ -891,6 +891,7 @@ static int pvr2_i2c_attach_inform(struct i2c_client *client) | |||
891 | INIT_LIST_HEAD(&cp->list); | 891 | INIT_LIST_HEAD(&cp->list); |
892 | cp->client = client; | 892 | cp->client = client; |
893 | mutex_lock(&hdw->i2c_list_lock); do { | 893 | mutex_lock(&hdw->i2c_list_lock); do { |
894 | hdw->cropcap_stale = !0; | ||
894 | list_add_tail(&cp->list,&hdw->i2c_clients); | 895 | list_add_tail(&cp->list,&hdw->i2c_clients); |
895 | hdw->i2c_pend_types |= PVR2_I2C_PEND_DETECT; | 896 | hdw->i2c_pend_types |= PVR2_I2C_PEND_DETECT; |
896 | } while (0); mutex_unlock(&hdw->i2c_list_lock); | 897 | } while (0); mutex_unlock(&hdw->i2c_list_lock); |
@@ -905,6 +906,7 @@ static int pvr2_i2c_detach_inform(struct i2c_client *client) | |||
905 | unsigned long amask = 0; | 906 | unsigned long amask = 0; |
906 | int foundfl = 0; | 907 | int foundfl = 0; |
907 | mutex_lock(&hdw->i2c_list_lock); do { | 908 | mutex_lock(&hdw->i2c_list_lock); do { |
909 | hdw->cropcap_stale = !0; | ||
908 | list_for_each_entry_safe(cp, ncp, &hdw->i2c_clients, list) { | 910 | list_for_each_entry_safe(cp, ncp, &hdw->i2c_clients, list) { |
909 | if (cp->client == client) { | 911 | if (cp->client == client) { |
910 | trace_i2c("pvr2_i2c_detach" | 912 | trace_i2c("pvr2_i2c_detach" |
@@ -946,22 +948,32 @@ static struct i2c_adapter pvr2_i2c_adap_template = { | |||
946 | .client_unregister = pvr2_i2c_detach_inform, | 948 | .client_unregister = pvr2_i2c_detach_inform, |
947 | }; | 949 | }; |
948 | 950 | ||
949 | static void do_i2c_scan(struct pvr2_hdw *hdw) | 951 | |
952 | /* Return true if device exists at given address */ | ||
953 | static int do_i2c_probe(struct pvr2_hdw *hdw, int addr) | ||
950 | { | 954 | { |
951 | struct i2c_msg msg[1]; | 955 | struct i2c_msg msg[1]; |
952 | int i,rc; | 956 | int rc; |
953 | msg[0].addr = 0; | 957 | msg[0].addr = 0; |
954 | msg[0].flags = I2C_M_RD; | 958 | msg[0].flags = I2C_M_RD; |
955 | msg[0].len = 0; | 959 | msg[0].len = 0; |
956 | msg[0].buf = NULL; | 960 | msg[0].buf = NULL; |
957 | printk("%s: i2c scan beginning\n",hdw->name); | 961 | msg[0].addr = addr; |
962 | rc = i2c_transfer(&hdw->i2c_adap, msg, ARRAY_SIZE(msg)); | ||
963 | return rc == 1; | ||
964 | } | ||
965 | |||
966 | static void do_i2c_scan(struct pvr2_hdw *hdw) | ||
967 | { | ||
968 | int i; | ||
969 | printk(KERN_INFO "%s: i2c scan beginning\n", hdw->name); | ||
958 | for (i = 0; i < 128; i++) { | 970 | for (i = 0; i < 128; i++) { |
959 | msg[0].addr = i; | 971 | if (do_i2c_probe(hdw, i)) { |
960 | rc = i2c_transfer(&hdw->i2c_adap,msg, ARRAY_SIZE(msg)); | 972 | printk(KERN_INFO "%s: i2c scan: found device @ 0x%x\n", |
961 | if (rc != 1) continue; | 973 | hdw->name, i); |
962 | printk("%s: i2c scan: found device @ 0x%x\n",hdw->name,i); | 974 | } |
963 | } | 975 | } |
964 | printk("%s: i2c scan done.\n",hdw->name); | 976 | printk(KERN_INFO "%s: i2c scan done.\n", hdw->name); |
965 | } | 977 | } |
966 | 978 | ||
967 | void pvr2_i2c_core_init(struct pvr2_hdw *hdw) | 979 | void pvr2_i2c_core_init(struct pvr2_hdw *hdw) |
@@ -980,8 +992,6 @@ void pvr2_i2c_core_init(struct pvr2_hdw *hdw) | |||
980 | hdw->i2c_func[0x18] = i2c_black_hole; | 992 | hdw->i2c_func[0x18] = i2c_black_hole; |
981 | } else if (ir_mode[hdw->unit_number] == 1) { | 993 | } else if (ir_mode[hdw->unit_number] == 1) { |
982 | if (hdw->hdw_desc->ir_scheme == PVR2_IR_SCHEME_24XXX) { | 994 | if (hdw->hdw_desc->ir_scheme == PVR2_IR_SCHEME_24XXX) { |
983 | /* This comment is present PURELY to get | ||
984 | checkpatch.pl to STFU. Lovely, eh? */ | ||
985 | hdw->i2c_func[0x18] = i2c_24xxx_ir; | 995 | hdw->i2c_func[0x18] = i2c_24xxx_ir; |
986 | } | 996 | } |
987 | } | 997 | } |
@@ -1006,6 +1016,16 @@ void pvr2_i2c_core_init(struct pvr2_hdw *hdw) | |||
1006 | mutex_init(&hdw->i2c_list_lock); | 1016 | mutex_init(&hdw->i2c_list_lock); |
1007 | hdw->i2c_linked = !0; | 1017 | hdw->i2c_linked = !0; |
1008 | i2c_add_adapter(&hdw->i2c_adap); | 1018 | i2c_add_adapter(&hdw->i2c_adap); |
1019 | if (hdw->i2c_func[0x18] == i2c_24xxx_ir) { | ||
1020 | /* Probe for a different type of IR receiver on this | ||
1021 | device. If present, disable the emulated IR receiver. */ | ||
1022 | if (do_i2c_probe(hdw, 0x71)) { | ||
1023 | pvr2_trace(PVR2_TRACE_INFO, | ||
1024 | "Device has newer IR hardware;" | ||
1025 | " disabling unneeded virtual IR device"); | ||
1026 | hdw->i2c_func[0x18] = NULL; | ||
1027 | } | ||
1028 | } | ||
1009 | if (i2c_scan) do_i2c_scan(hdw); | 1029 | if (i2c_scan) do_i2c_scan(hdw); |
1010 | } | 1030 | } |
1011 | 1031 | ||
diff --git a/drivers/media/video/pvrusb2/pvrusb2-main.c b/drivers/media/video/pvrusb2/pvrusb2-main.c index ad0d98c2ebb4..9b3c874d96d6 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-main.c +++ b/drivers/media/video/pvrusb2/pvrusb2-main.c | |||
@@ -137,9 +137,11 @@ static int __init pvr_init(void) | |||
137 | ret = usb_register(&pvr_driver); | 137 | ret = usb_register(&pvr_driver); |
138 | 138 | ||
139 | if (ret == 0) | 139 | if (ret == 0) |
140 | info(DRIVER_DESC " : " DRIVER_VERSION); | 140 | printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" |
141 | if (pvrusb2_debug) info("Debug mask is %d (0x%x)", | 141 | DRIVER_DESC "\n"); |
142 | pvrusb2_debug,pvrusb2_debug); | 142 | if (pvrusb2_debug) |
143 | printk(KERN_INFO KBUILD_MODNAME ": Debug mask is %d (0x%x)\n", | ||
144 | pvrusb2_debug,pvrusb2_debug); | ||
143 | 145 | ||
144 | pvr2_trace(PVR2_TRACE_INIT,"pvr_init complete"); | 146 | pvr2_trace(PVR2_TRACE_INIT,"pvr_init complete"); |
145 | 147 | ||
diff --git a/drivers/media/video/pvrusb2/pvrusb2-sysfs.c b/drivers/media/video/pvrusb2/pvrusb2-sysfs.c index 46a8c39ba030..733680f21317 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-sysfs.c +++ b/drivers/media/video/pvrusb2/pvrusb2-sysfs.c | |||
@@ -65,6 +65,7 @@ struct pvr2_sysfs_ctl_item { | |||
65 | struct device_attribute attr_type; | 65 | struct device_attribute attr_type; |
66 | struct device_attribute attr_min; | 66 | struct device_attribute attr_min; |
67 | struct device_attribute attr_max; | 67 | struct device_attribute attr_max; |
68 | struct device_attribute attr_def; | ||
68 | struct device_attribute attr_enum; | 69 | struct device_attribute attr_enum; |
69 | struct device_attribute attr_bits; | 70 | struct device_attribute attr_bits; |
70 | struct device_attribute attr_val; | 71 | struct device_attribute attr_val; |
@@ -145,6 +146,23 @@ static ssize_t show_max(struct device *class_dev, | |||
145 | return scnprintf(buf, PAGE_SIZE, "%ld\n", val); | 146 | return scnprintf(buf, PAGE_SIZE, "%ld\n", val); |
146 | } | 147 | } |
147 | 148 | ||
149 | static ssize_t show_def(struct device *class_dev, | ||
150 | struct device_attribute *attr, | ||
151 | char *buf) | ||
152 | { | ||
153 | struct pvr2_sysfs_ctl_item *cip; | ||
154 | int val; | ||
155 | int ret; | ||
156 | cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_def); | ||
157 | ret = pvr2_ctrl_get_def(cip->cptr, &val); | ||
158 | pvr2_sysfs_trace("pvr2_sysfs(%p) show_def(cid=%d) is %d, stat=%d", | ||
159 | cip->chptr, cip->ctl_id, val, ret); | ||
160 | if (ret < 0) { | ||
161 | return ret; | ||
162 | } | ||
163 | return scnprintf(buf, PAGE_SIZE, "%d\n", val); | ||
164 | } | ||
165 | |||
148 | static ssize_t show_val_norm(struct device *class_dev, | 166 | static ssize_t show_val_norm(struct device *class_dev, |
149 | struct device_attribute *attr, | 167 | struct device_attribute *attr, |
150 | char *buf) | 168 | char *buf) |
@@ -320,6 +338,10 @@ static void pvr2_sysfs_add_control(struct pvr2_sysfs *sfp,int ctl_id) | |||
320 | cip->attr_max.attr.mode = S_IRUGO; | 338 | cip->attr_max.attr.mode = S_IRUGO; |
321 | cip->attr_max.show = show_max; | 339 | cip->attr_max.show = show_max; |
322 | 340 | ||
341 | cip->attr_def.attr.name = "def_val"; | ||
342 | cip->attr_def.attr.mode = S_IRUGO; | ||
343 | cip->attr_def.show = show_def; | ||
344 | |||
323 | cip->attr_val.attr.name = "cur_val"; | 345 | cip->attr_val.attr.name = "cur_val"; |
324 | cip->attr_val.attr.mode = S_IRUGO; | 346 | cip->attr_val.attr.mode = S_IRUGO; |
325 | 347 | ||
@@ -343,6 +365,7 @@ static void pvr2_sysfs_add_control(struct pvr2_sysfs *sfp,int ctl_id) | |||
343 | cip->attr_gen[acnt++] = &cip->attr_name.attr; | 365 | cip->attr_gen[acnt++] = &cip->attr_name.attr; |
344 | cip->attr_gen[acnt++] = &cip->attr_type.attr; | 366 | cip->attr_gen[acnt++] = &cip->attr_type.attr; |
345 | cip->attr_gen[acnt++] = &cip->attr_val.attr; | 367 | cip->attr_gen[acnt++] = &cip->attr_val.attr; |
368 | cip->attr_gen[acnt++] = &cip->attr_def.attr; | ||
346 | cip->attr_val.show = show_val_norm; | 369 | cip->attr_val.show = show_val_norm; |
347 | cip->attr_val.store = store_val_norm; | 370 | cip->attr_val.store = store_val_norm; |
348 | if (pvr2_ctrl_has_custom_symbols(cptr)) { | 371 | if (pvr2_ctrl_has_custom_symbols(cptr)) { |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c index 00306faeac01..f048d80b77e5 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c +++ b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c | |||
@@ -533,7 +533,7 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file, | |||
533 | 533 | ||
534 | lmin = pvr2_ctrl_get_min(hcp); | 534 | lmin = pvr2_ctrl_get_min(hcp); |
535 | lmax = pvr2_ctrl_get_max(hcp); | 535 | lmax = pvr2_ctrl_get_max(hcp); |
536 | ldef = pvr2_ctrl_get_def(hcp); | 536 | pvr2_ctrl_get_def(hcp, &ldef); |
537 | if (w == -1) { | 537 | if (w == -1) { |
538 | w = ldef; | 538 | w = ldef; |
539 | } else if (w < lmin) { | 539 | } else if (w < lmin) { |
@@ -543,7 +543,7 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file, | |||
543 | } | 543 | } |
544 | lmin = pvr2_ctrl_get_min(vcp); | 544 | lmin = pvr2_ctrl_get_min(vcp); |
545 | lmax = pvr2_ctrl_get_max(vcp); | 545 | lmax = pvr2_ctrl_get_max(vcp); |
546 | ldef = pvr2_ctrl_get_def(vcp); | 546 | pvr2_ctrl_get_def(vcp, &ldef); |
547 | if (h == -1) { | 547 | if (h == -1) { |
548 | h = ldef; | 548 | h = ldef; |
549 | } else if (h < lmin) { | 549 | } else if (h < lmin) { |
@@ -604,6 +604,7 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file, | |||
604 | case VIDIOC_QUERYCTRL: | 604 | case VIDIOC_QUERYCTRL: |
605 | { | 605 | { |
606 | struct pvr2_ctrl *cptr; | 606 | struct pvr2_ctrl *cptr; |
607 | int val; | ||
607 | struct v4l2_queryctrl *vc = (struct v4l2_queryctrl *)arg; | 608 | struct v4l2_queryctrl *vc = (struct v4l2_queryctrl *)arg; |
608 | ret = 0; | 609 | ret = 0; |
609 | if (vc->id & V4L2_CTRL_FLAG_NEXT_CTRL) { | 610 | if (vc->id & V4L2_CTRL_FLAG_NEXT_CTRL) { |
@@ -627,7 +628,8 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file, | |||
627 | pvr2_ctrl_get_desc(cptr)); | 628 | pvr2_ctrl_get_desc(cptr)); |
628 | strlcpy(vc->name,pvr2_ctrl_get_desc(cptr),sizeof(vc->name)); | 629 | strlcpy(vc->name,pvr2_ctrl_get_desc(cptr),sizeof(vc->name)); |
629 | vc->flags = pvr2_ctrl_get_v4lflags(cptr); | 630 | vc->flags = pvr2_ctrl_get_v4lflags(cptr); |
630 | vc->default_value = pvr2_ctrl_get_def(cptr); | 631 | pvr2_ctrl_get_def(cptr, &val); |
632 | vc->default_value = val; | ||
631 | switch (pvr2_ctrl_get_type(cptr)) { | 633 | switch (pvr2_ctrl_get_type(cptr)) { |
632 | case pvr2_ctl_enum: | 634 | case pvr2_ctl_enum: |
633 | vc->type = V4L2_CTRL_TYPE_MENU; | 635 | vc->type = V4L2_CTRL_TYPE_MENU; |
@@ -753,6 +755,92 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file, | |||
753 | break; | 755 | break; |
754 | } | 756 | } |
755 | 757 | ||
758 | case VIDIOC_CROPCAP: | ||
759 | { | ||
760 | struct v4l2_cropcap *cap = (struct v4l2_cropcap *)arg; | ||
761 | if (cap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { | ||
762 | ret = -EINVAL; | ||
763 | break; | ||
764 | } | ||
765 | ret = pvr2_hdw_get_cropcap(hdw, cap); | ||
766 | cap->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; /* paranoia */ | ||
767 | break; | ||
768 | } | ||
769 | case VIDIOC_G_CROP: | ||
770 | { | ||
771 | struct v4l2_crop *crop = (struct v4l2_crop *)arg; | ||
772 | int val = 0; | ||
773 | if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { | ||
774 | ret = -EINVAL; | ||
775 | break; | ||
776 | } | ||
777 | ret = pvr2_ctrl_get_value( | ||
778 | pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPL), &val); | ||
779 | if (ret != 0) { | ||
780 | ret = -EINVAL; | ||
781 | break; | ||
782 | } | ||
783 | crop->c.left = val; | ||
784 | ret = pvr2_ctrl_get_value( | ||
785 | pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPT), &val); | ||
786 | if (ret != 0) { | ||
787 | ret = -EINVAL; | ||
788 | break; | ||
789 | } | ||
790 | crop->c.top = val; | ||
791 | ret = pvr2_ctrl_get_value( | ||
792 | pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPW), &val); | ||
793 | if (ret != 0) { | ||
794 | ret = -EINVAL; | ||
795 | break; | ||
796 | } | ||
797 | crop->c.width = val; | ||
798 | ret = pvr2_ctrl_get_value( | ||
799 | pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPH), &val); | ||
800 | if (ret != 0) { | ||
801 | ret = -EINVAL; | ||
802 | break; | ||
803 | } | ||
804 | crop->c.height = val; | ||
805 | } | ||
806 | case VIDIOC_S_CROP: | ||
807 | { | ||
808 | struct v4l2_crop *crop = (struct v4l2_crop *)arg; | ||
809 | struct v4l2_cropcap cap; | ||
810 | if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { | ||
811 | ret = -EINVAL; | ||
812 | break; | ||
813 | } | ||
814 | cap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
815 | ret = pvr2_ctrl_set_value( | ||
816 | pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPL), | ||
817 | crop->c.left); | ||
818 | if (ret != 0) { | ||
819 | ret = -EINVAL; | ||
820 | break; | ||
821 | } | ||
822 | ret = pvr2_ctrl_set_value( | ||
823 | pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPT), | ||
824 | crop->c.top); | ||
825 | if (ret != 0) { | ||
826 | ret = -EINVAL; | ||
827 | break; | ||
828 | } | ||
829 | ret = pvr2_ctrl_set_value( | ||
830 | pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPW), | ||
831 | crop->c.width); | ||
832 | if (ret != 0) { | ||
833 | ret = -EINVAL; | ||
834 | break; | ||
835 | } | ||
836 | ret = pvr2_ctrl_set_value( | ||
837 | pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPH), | ||
838 | crop->c.height); | ||
839 | if (ret != 0) { | ||
840 | ret = -EINVAL; | ||
841 | break; | ||
842 | } | ||
843 | } | ||
756 | case VIDIOC_LOG_STATUS: | 844 | case VIDIOC_LOG_STATUS: |
757 | { | 845 | { |
758 | pvr2_hdw_trigger_module_log(hdw); | 846 | pvr2_hdw_trigger_module_log(hdw); |
diff --git a/drivers/media/video/pwc/pwc-ctrl.c b/drivers/media/video/pwc/pwc-ctrl.c index dbc560742553..c66530210192 100644 --- a/drivers/media/video/pwc/pwc-ctrl.c +++ b/drivers/media/video/pwc/pwc-ctrl.c | |||
@@ -41,7 +41,6 @@ | |||
41 | #include <asm/uaccess.h> | 41 | #include <asm/uaccess.h> |
42 | #endif | 42 | #endif |
43 | #include <asm/errno.h> | 43 | #include <asm/errno.h> |
44 | #include <linux/version.h> | ||
45 | 44 | ||
46 | #include "pwc.h" | 45 | #include "pwc.h" |
47 | #include "pwc-uncompress.h" | 46 | #include "pwc-uncompress.h" |
diff --git a/drivers/media/video/pwc/pwc-if.c b/drivers/media/video/pwc/pwc-if.c index 9aee7cb6f79a..ab28389b4cda 100644 --- a/drivers/media/video/pwc/pwc-if.c +++ b/drivers/media/video/pwc/pwc-if.c | |||
@@ -1112,7 +1112,7 @@ static int pwc_video_open(struct inode *inode, struct file *file) | |||
1112 | 1112 | ||
1113 | PWC_DEBUG_OPEN(">> video_open called(vdev = 0x%p).\n", vdev); | 1113 | PWC_DEBUG_OPEN(">> video_open called(vdev = 0x%p).\n", vdev); |
1114 | 1114 | ||
1115 | pdev = (struct pwc_device *)vdev->priv; | 1115 | pdev = video_get_drvdata(vdev); |
1116 | BUG_ON(!pdev); | 1116 | BUG_ON(!pdev); |
1117 | if (pdev->vopen) { | 1117 | if (pdev->vopen) { |
1118 | PWC_DEBUG_OPEN("I'm busy, someone is using the device.\n"); | 1118 | PWC_DEBUG_OPEN("I'm busy, someone is using the device.\n"); |
@@ -1233,7 +1233,7 @@ static int pwc_video_close(struct inode *inode, struct file *file) | |||
1233 | PWC_DEBUG_OPEN(">> video_close called(vdev = 0x%p).\n", vdev); | 1233 | PWC_DEBUG_OPEN(">> video_close called(vdev = 0x%p).\n", vdev); |
1234 | 1234 | ||
1235 | lock_kernel(); | 1235 | lock_kernel(); |
1236 | pdev = (struct pwc_device *)vdev->priv; | 1236 | pdev = video_get_drvdata(vdev); |
1237 | if (pdev->vopen == 0) | 1237 | if (pdev->vopen == 0) |
1238 | PWC_DEBUG_MODULE("video_close() called on closed device?\n"); | 1238 | PWC_DEBUG_MODULE("video_close() called on closed device?\n"); |
1239 | 1239 | ||
@@ -1304,7 +1304,7 @@ static ssize_t pwc_video_read(struct file *file, char __user *buf, | |||
1304 | vdev, buf, count); | 1304 | vdev, buf, count); |
1305 | if (vdev == NULL) | 1305 | if (vdev == NULL) |
1306 | return -EFAULT; | 1306 | return -EFAULT; |
1307 | pdev = vdev->priv; | 1307 | pdev = video_get_drvdata(vdev); |
1308 | if (pdev == NULL) | 1308 | if (pdev == NULL) |
1309 | return -EFAULT; | 1309 | return -EFAULT; |
1310 | 1310 | ||
@@ -1386,7 +1386,7 @@ static unsigned int pwc_video_poll(struct file *file, poll_table *wait) | |||
1386 | 1386 | ||
1387 | if (vdev == NULL) | 1387 | if (vdev == NULL) |
1388 | return -EFAULT; | 1388 | return -EFAULT; |
1389 | pdev = vdev->priv; | 1389 | pdev = video_get_drvdata(vdev); |
1390 | if (pdev == NULL) | 1390 | if (pdev == NULL) |
1391 | return -EFAULT; | 1391 | return -EFAULT; |
1392 | 1392 | ||
@@ -1408,7 +1408,7 @@ static int pwc_video_ioctl(struct inode *inode, struct file *file, | |||
1408 | 1408 | ||
1409 | if (!vdev) | 1409 | if (!vdev) |
1410 | goto out; | 1410 | goto out; |
1411 | pdev = vdev->priv; | 1411 | pdev = video_get_drvdata(vdev); |
1412 | 1412 | ||
1413 | mutex_lock(&pdev->modlock); | 1413 | mutex_lock(&pdev->modlock); |
1414 | if (!pdev->unplugged) | 1414 | if (!pdev->unplugged) |
@@ -1428,7 +1428,7 @@ static int pwc_video_mmap(struct file *file, struct vm_area_struct *vma) | |||
1428 | int index; | 1428 | int index; |
1429 | 1429 | ||
1430 | PWC_DEBUG_MEMORY(">> %s\n", __func__); | 1430 | PWC_DEBUG_MEMORY(">> %s\n", __func__); |
1431 | pdev = vdev->priv; | 1431 | pdev = video_get_drvdata(vdev); |
1432 | size = vma->vm_end - vma->vm_start; | 1432 | size = vma->vm_end - vma->vm_start; |
1433 | start = vma->vm_start; | 1433 | start = vma->vm_start; |
1434 | 1434 | ||
diff --git a/drivers/media/video/pwc/pwc-v4l.c b/drivers/media/video/pwc/pwc-v4l.c index 1742889874df..76a1376c9751 100644 --- a/drivers/media/video/pwc/pwc-v4l.c +++ b/drivers/media/video/pwc/pwc-v4l.c | |||
@@ -346,7 +346,7 @@ int pwc_video_do_ioctl(struct inode *inode, struct file *file, | |||
346 | 346 | ||
347 | if (vdev == NULL) | 347 | if (vdev == NULL) |
348 | return -EFAULT; | 348 | return -EFAULT; |
349 | pdev = vdev->priv; | 349 | pdev = video_get_drvdata(vdev); |
350 | if (pdev == NULL) | 350 | if (pdev == NULL) |
351 | return -EFAULT; | 351 | return -EFAULT; |
352 | 352 | ||
diff --git a/drivers/media/video/pxa_camera.c b/drivers/media/video/pxa_camera.c index cf96b2cc4f1c..eb6be5802928 100644 --- a/drivers/media/video/pxa_camera.c +++ b/drivers/media/video/pxa_camera.c | |||
@@ -629,17 +629,6 @@ static void pxa_camera_activate(struct pxa_camera_dev *pcdev) | |||
629 | pdata->init(pcdev->dev); | 629 | pdata->init(pcdev->dev); |
630 | } | 630 | } |
631 | 631 | ||
632 | if (pdata && pdata->power) { | ||
633 | dev_dbg(pcdev->dev, "%s: Power on camera\n", __func__); | ||
634 | pdata->power(pcdev->dev, 1); | ||
635 | } | ||
636 | |||
637 | if (pdata && pdata->reset) { | ||
638 | dev_dbg(pcdev->dev, "%s: Releasing camera reset\n", | ||
639 | __func__); | ||
640 | pdata->reset(pcdev->dev, 1); | ||
641 | } | ||
642 | |||
643 | CICR0 = 0x3FF; /* disable all interrupts */ | 632 | CICR0 = 0x3FF; /* disable all interrupts */ |
644 | 633 | ||
645 | if (pcdev->platform_flags & PXA_CAMERA_PCLK_EN) | 634 | if (pcdev->platform_flags & PXA_CAMERA_PCLK_EN) |
@@ -660,20 +649,7 @@ static void pxa_camera_activate(struct pxa_camera_dev *pcdev) | |||
660 | 649 | ||
661 | static void pxa_camera_deactivate(struct pxa_camera_dev *pcdev) | 650 | static void pxa_camera_deactivate(struct pxa_camera_dev *pcdev) |
662 | { | 651 | { |
663 | struct pxacamera_platform_data *board = pcdev->pdata; | ||
664 | |||
665 | clk_disable(pcdev->clk); | 652 | clk_disable(pcdev->clk); |
666 | |||
667 | if (board && board->reset) { | ||
668 | dev_dbg(pcdev->dev, "%s: Asserting camera reset\n", | ||
669 | __func__); | ||
670 | board->reset(pcdev->dev, 0); | ||
671 | } | ||
672 | |||
673 | if (board && board->power) { | ||
674 | dev_dbg(pcdev->dev, "%s: Power off camera\n", __func__); | ||
675 | board->power(pcdev->dev, 0); | ||
676 | } | ||
677 | } | 653 | } |
678 | 654 | ||
679 | static irqreturn_t pxa_camera_irq(int irq, void *data) | 655 | static irqreturn_t pxa_camera_irq(int irq, void *data) |
@@ -1144,31 +1120,31 @@ static int pxa_camera_probe(struct platform_device *pdev) | |||
1144 | pcdev->dev = &pdev->dev; | 1120 | pcdev->dev = &pdev->dev; |
1145 | 1121 | ||
1146 | /* request dma */ | 1122 | /* request dma */ |
1147 | pcdev->dma_chans[0] = pxa_request_dma("CI_Y", DMA_PRIO_HIGH, | 1123 | err = pxa_request_dma("CI_Y", DMA_PRIO_HIGH, |
1148 | pxa_camera_dma_irq_y, pcdev); | 1124 | pxa_camera_dma_irq_y, pcdev); |
1149 | if (pcdev->dma_chans[0] < 0) { | 1125 | if (err < 0) { |
1150 | dev_err(pcdev->dev, "Can't request DMA for Y\n"); | 1126 | dev_err(pcdev->dev, "Can't request DMA for Y\n"); |
1151 | err = -ENOMEM; | ||
1152 | goto exit_iounmap; | 1127 | goto exit_iounmap; |
1153 | } | 1128 | } |
1129 | pcdev->dma_chans[0] = err; | ||
1154 | dev_dbg(pcdev->dev, "got DMA channel %d\n", pcdev->dma_chans[0]); | 1130 | dev_dbg(pcdev->dev, "got DMA channel %d\n", pcdev->dma_chans[0]); |
1155 | 1131 | ||
1156 | pcdev->dma_chans[1] = pxa_request_dma("CI_U", DMA_PRIO_HIGH, | 1132 | err = pxa_request_dma("CI_U", DMA_PRIO_HIGH, |
1157 | pxa_camera_dma_irq_u, pcdev); | 1133 | pxa_camera_dma_irq_u, pcdev); |
1158 | if (pcdev->dma_chans[1] < 0) { | 1134 | if (err < 0) { |
1159 | dev_err(pcdev->dev, "Can't request DMA for U\n"); | 1135 | dev_err(pcdev->dev, "Can't request DMA for U\n"); |
1160 | err = -ENOMEM; | ||
1161 | goto exit_free_dma_y; | 1136 | goto exit_free_dma_y; |
1162 | } | 1137 | } |
1138 | pcdev->dma_chans[1] = err; | ||
1163 | dev_dbg(pcdev->dev, "got DMA channel (U) %d\n", pcdev->dma_chans[1]); | 1139 | dev_dbg(pcdev->dev, "got DMA channel (U) %d\n", pcdev->dma_chans[1]); |
1164 | 1140 | ||
1165 | pcdev->dma_chans[2] = pxa_request_dma("CI_V", DMA_PRIO_HIGH, | 1141 | err = pxa_request_dma("CI_V", DMA_PRIO_HIGH, |
1166 | pxa_camera_dma_irq_v, pcdev); | 1142 | pxa_camera_dma_irq_v, pcdev); |
1167 | if (pcdev->dma_chans[0] < 0) { | 1143 | if (err < 0) { |
1168 | dev_err(pcdev->dev, "Can't request DMA for V\n"); | 1144 | dev_err(pcdev->dev, "Can't request DMA for V\n"); |
1169 | err = -ENOMEM; | ||
1170 | goto exit_free_dma_u; | 1145 | goto exit_free_dma_u; |
1171 | } | 1146 | } |
1147 | pcdev->dma_chans[2] = err; | ||
1172 | dev_dbg(pcdev->dev, "got DMA channel (V) %d\n", pcdev->dma_chans[2]); | 1148 | dev_dbg(pcdev->dev, "got DMA channel (V) %d\n", pcdev->dma_chans[2]); |
1173 | 1149 | ||
1174 | DRCMR(68) = pcdev->dma_chans[0] | DRCMR_MAPVLD; | 1150 | DRCMR(68) = pcdev->dma_chans[0] | DRCMR_MAPVLD; |
diff --git a/drivers/media/video/s2255drv.c b/drivers/media/video/s2255drv.c index 92b83feae366..5272926db73e 100644 --- a/drivers/media/video/s2255drv.c +++ b/drivers/media/video/s2255drv.c | |||
@@ -58,6 +58,8 @@ | |||
58 | 58 | ||
59 | 59 | ||
60 | 60 | ||
61 | /* default JPEG quality */ | ||
62 | #define S2255_DEF_JPEG_QUAL 50 | ||
61 | /* vendor request in */ | 63 | /* vendor request in */ |
62 | #define S2255_VR_IN 0 | 64 | #define S2255_VR_IN 0 |
63 | /* vendor request out */ | 65 | /* vendor request out */ |
@@ -67,20 +69,21 @@ | |||
67 | /* USB endpoint number for configuring the device */ | 69 | /* USB endpoint number for configuring the device */ |
68 | #define S2255_CONFIG_EP 2 | 70 | #define S2255_CONFIG_EP 2 |
69 | /* maximum time for DSP to start responding after last FW word loaded(ms) */ | 71 | /* maximum time for DSP to start responding after last FW word loaded(ms) */ |
70 | #define S2255_DSP_BOOTTIME 400 | 72 | #define S2255_DSP_BOOTTIME 800 |
71 | /* maximum time to wait for firmware to load (ms) */ | 73 | /* maximum time to wait for firmware to load (ms) */ |
72 | #define S2255_LOAD_TIMEOUT (5000 + S2255_DSP_BOOTTIME) | 74 | #define S2255_LOAD_TIMEOUT (5000 + S2255_DSP_BOOTTIME) |
73 | #define S2255_DEF_BUFS 16 | 75 | #define S2255_DEF_BUFS 16 |
76 | #define S2255_SETMODE_TIMEOUT 500 | ||
74 | #define MAX_CHANNELS 4 | 77 | #define MAX_CHANNELS 4 |
75 | #define FRAME_MARKER 0x2255DA4AL | 78 | #define S2255_MARKER_FRAME 0x2255DA4AL |
76 | #define MAX_PIPE_USBBLOCK (40 * 1024) | 79 | #define S2255_MARKER_RESPONSE 0x2255ACACL |
77 | #define DEFAULT_PIPE_USBBLOCK (16 * 1024) | 80 | #define S2255_USB_XFER_SIZE (16 * 1024) |
78 | #define MAX_CHANNELS 4 | 81 | #define MAX_CHANNELS 4 |
79 | #define MAX_PIPE_BUFFERS 1 | 82 | #define MAX_PIPE_BUFFERS 1 |
80 | #define SYS_FRAMES 4 | 83 | #define SYS_FRAMES 4 |
81 | /* maximum size is PAL full size plus room for the marker header(s) */ | 84 | /* maximum size is PAL full size plus room for the marker header(s) */ |
82 | #define SYS_FRAMES_MAXSIZE (720 * 288 * 2 * 2 + 4096) | 85 | #define SYS_FRAMES_MAXSIZE (720*288*2*2 + 4096) |
83 | #define DEF_USB_BLOCK (4096) | 86 | #define DEF_USB_BLOCK S2255_USB_XFER_SIZE |
84 | #define LINE_SZ_4CIFS_NTSC 640 | 87 | #define LINE_SZ_4CIFS_NTSC 640 |
85 | #define LINE_SZ_2CIFS_NTSC 640 | 88 | #define LINE_SZ_2CIFS_NTSC 640 |
86 | #define LINE_SZ_1CIFS_NTSC 320 | 89 | #define LINE_SZ_1CIFS_NTSC 320 |
@@ -108,6 +111,9 @@ | |||
108 | #define COLOR_YUVPL 1 /* YUV planar */ | 111 | #define COLOR_YUVPL 1 /* YUV planar */ |
109 | #define COLOR_YUVPK 2 /* YUV packed */ | 112 | #define COLOR_YUVPK 2 /* YUV packed */ |
110 | #define COLOR_Y8 4 /* monochrome */ | 113 | #define COLOR_Y8 4 /* monochrome */ |
114 | #define COLOR_JPG 5 /* JPEG */ | ||
115 | #define MASK_COLOR 0xff | ||
116 | #define MASK_JPG_QUALITY 0xff00 | ||
111 | 117 | ||
112 | /* frame decimation. Not implemented by V4L yet(experimental in V4L) */ | 118 | /* frame decimation. Not implemented by V4L yet(experimental in V4L) */ |
113 | #define FDEC_1 1 /* capture every frame. default */ | 119 | #define FDEC_1 1 /* capture every frame. default */ |
@@ -148,16 +154,14 @@ struct s2255_mode { | |||
148 | u32 restart; /* if DSP requires restart */ | 154 | u32 restart; /* if DSP requires restart */ |
149 | }; | 155 | }; |
150 | 156 | ||
151 | /* frame structure */ | ||
152 | #define FRAME_STATE_UNUSED 0 | ||
153 | #define FRAME_STATE_FILLING 1 | ||
154 | #define FRAME_STATE_FULL 2 | ||
155 | 157 | ||
158 | #define S2255_READ_IDLE 0 | ||
159 | #define S2255_READ_FRAME 1 | ||
156 | 160 | ||
161 | /* frame structure */ | ||
157 | struct s2255_framei { | 162 | struct s2255_framei { |
158 | unsigned long size; | 163 | unsigned long size; |
159 | 164 | unsigned long ulState; /* ulState:S2255_READ_IDLE, S2255_READ_FRAME*/ | |
160 | unsigned long ulState; /* ulState ==0 unused, 1 being filled, 2 full */ | ||
161 | void *lpvbits; /* image data */ | 165 | void *lpvbits; /* image data */ |
162 | unsigned long cur_size; /* current data copied to it */ | 166 | unsigned long cur_size; /* current data copied to it */ |
163 | }; | 167 | }; |
@@ -188,6 +192,10 @@ struct s2255_dmaqueue { | |||
188 | #define S2255_FW_FAILED 3 | 192 | #define S2255_FW_FAILED 3 |
189 | #define S2255_FW_DISCONNECTING 4 | 193 | #define S2255_FW_DISCONNECTING 4 |
190 | 194 | ||
195 | #define S2255_FW_MARKER 0x22552f2f | ||
196 | /* 2255 read states */ | ||
197 | #define S2255_READ_IDLE 0 | ||
198 | #define S2255_READ_FRAME 1 | ||
191 | struct s2255_fw { | 199 | struct s2255_fw { |
192 | int fw_loaded; | 200 | int fw_loaded; |
193 | int fw_size; | 201 | int fw_size; |
@@ -195,7 +203,6 @@ struct s2255_fw { | |||
195 | atomic_t fw_state; | 203 | atomic_t fw_state; |
196 | void *pfw_data; | 204 | void *pfw_data; |
197 | wait_queue_head_t wait_fw; | 205 | wait_queue_head_t wait_fw; |
198 | struct timer_list dsp_wait; | ||
199 | const struct firmware *fw; | 206 | const struct firmware *fw; |
200 | }; | 207 | }; |
201 | 208 | ||
@@ -237,15 +244,27 @@ struct s2255_dev { | |||
237 | struct s2255_pipeinfo pipes[MAX_PIPE_BUFFERS]; | 244 | struct s2255_pipeinfo pipes[MAX_PIPE_BUFFERS]; |
238 | struct s2255_bufferi buffer[MAX_CHANNELS]; | 245 | struct s2255_bufferi buffer[MAX_CHANNELS]; |
239 | struct s2255_mode mode[MAX_CHANNELS]; | 246 | struct s2255_mode mode[MAX_CHANNELS]; |
247 | /* jpeg compression */ | ||
248 | struct v4l2_jpegcompression jc[MAX_CHANNELS]; | ||
240 | const struct s2255_fmt *cur_fmt[MAX_CHANNELS]; | 249 | const struct s2255_fmt *cur_fmt[MAX_CHANNELS]; |
241 | int cur_frame[MAX_CHANNELS]; | 250 | int cur_frame[MAX_CHANNELS]; |
242 | int last_frame[MAX_CHANNELS]; | 251 | int last_frame[MAX_CHANNELS]; |
243 | u32 cc; /* current channel */ | 252 | u32 cc; /* current channel */ |
244 | int b_acquire[MAX_CHANNELS]; | 253 | int b_acquire[MAX_CHANNELS]; |
254 | /* allocated image size */ | ||
245 | unsigned long req_image_size[MAX_CHANNELS]; | 255 | unsigned long req_image_size[MAX_CHANNELS]; |
256 | /* received packet size */ | ||
257 | unsigned long pkt_size[MAX_CHANNELS]; | ||
246 | int bad_payload[MAX_CHANNELS]; | 258 | int bad_payload[MAX_CHANNELS]; |
247 | unsigned long frame_count[MAX_CHANNELS]; | 259 | unsigned long frame_count[MAX_CHANNELS]; |
248 | int frame_ready; | 260 | int frame_ready; |
261 | /* if JPEG image */ | ||
262 | int jpg_size[MAX_CHANNELS]; | ||
263 | /* if channel configured to default state */ | ||
264 | int chn_configured[MAX_CHANNELS]; | ||
265 | wait_queue_head_t wait_setmode[MAX_CHANNELS]; | ||
266 | int setmode_ready[MAX_CHANNELS]; | ||
267 | int chn_ready; | ||
249 | struct kref kref; | 268 | struct kref kref; |
250 | spinlock_t slock; | 269 | spinlock_t slock; |
251 | }; | 270 | }; |
@@ -306,12 +325,16 @@ static void s2255_stop_readpipe(struct s2255_dev *dev); | |||
306 | static int s2255_start_acquire(struct s2255_dev *dev, unsigned long chn); | 325 | static int s2255_start_acquire(struct s2255_dev *dev, unsigned long chn); |
307 | static int s2255_stop_acquire(struct s2255_dev *dev, unsigned long chn); | 326 | static int s2255_stop_acquire(struct s2255_dev *dev, unsigned long chn); |
308 | static void s2255_fillbuff(struct s2255_dev *dev, struct s2255_buffer *buf, | 327 | static void s2255_fillbuff(struct s2255_dev *dev, struct s2255_buffer *buf, |
309 | int chn); | 328 | int chn, int jpgsize); |
310 | static int s2255_set_mode(struct s2255_dev *dev, unsigned long chn, | 329 | static int s2255_set_mode(struct s2255_dev *dev, unsigned long chn, |
311 | struct s2255_mode *mode); | 330 | struct s2255_mode *mode); |
312 | static int s2255_board_shutdown(struct s2255_dev *dev); | 331 | static int s2255_board_shutdown(struct s2255_dev *dev); |
313 | static void s2255_exit_v4l(struct s2255_dev *dev); | 332 | static void s2255_exit_v4l(struct s2255_dev *dev); |
314 | static void s2255_fwload_start(struct s2255_dev *dev); | 333 | static void s2255_fwload_start(struct s2255_dev *dev, int reset); |
334 | static void s2255_destroy(struct kref *kref); | ||
335 | static long s2255_vendor_req(struct s2255_dev *dev, unsigned char req, | ||
336 | u16 index, u16 value, void *buf, | ||
337 | s32 buf_len, int bOut); | ||
315 | 338 | ||
316 | #define dprintk(level, fmt, arg...) \ | 339 | #define dprintk(level, fmt, arg...) \ |
317 | do { \ | 340 | do { \ |
@@ -407,6 +430,10 @@ static const struct s2255_fmt formats[] = { | |||
407 | .fourcc = V4L2_PIX_FMT_UYVY, | 430 | .fourcc = V4L2_PIX_FMT_UYVY, |
408 | .depth = 16 | 431 | .depth = 16 |
409 | }, { | 432 | }, { |
433 | .name = "JPG", | ||
434 | .fourcc = V4L2_PIX_FMT_JPEG, | ||
435 | .depth = 24 | ||
436 | }, { | ||
410 | .name = "8bpp GREY", | 437 | .name = "8bpp GREY", |
411 | .fourcc = V4L2_PIX_FMT_GREY, | 438 | .fourcc = V4L2_PIX_FMT_GREY, |
412 | .depth = 8 | 439 | .depth = 8 |
@@ -464,6 +491,13 @@ static void planar422p_to_yuv_packed(const unsigned char *in, | |||
464 | return; | 491 | return; |
465 | } | 492 | } |
466 | 493 | ||
494 | static void s2255_reset_dsppower(struct s2255_dev *dev) | ||
495 | { | ||
496 | s2255_vendor_req(dev, 0x40, 0x0b0b, 0x0b0b, NULL, 0, 1); | ||
497 | msleep(10); | ||
498 | s2255_vendor_req(dev, 0x50, 0x0000, 0x0000, NULL, 0, 1); | ||
499 | return; | ||
500 | } | ||
467 | 501 | ||
468 | /* kickstarts the firmware loading. from probe | 502 | /* kickstarts the firmware loading. from probe |
469 | */ | 503 | */ |
@@ -480,18 +514,6 @@ static void s2255_timer(unsigned long user_data) | |||
480 | } | 514 | } |
481 | } | 515 | } |
482 | 516 | ||
483 | /* called when DSP is up and running. DSP is guaranteed to | ||
484 | be running after S2255_DSP_BOOTTIME */ | ||
485 | static void s2255_dsp_running(unsigned long user_data) | ||
486 | { | ||
487 | struct s2255_fw *data = (struct s2255_fw *)user_data; | ||
488 | dprintk(1, "dsp running\n"); | ||
489 | atomic_set(&data->fw_state, S2255_FW_SUCCESS); | ||
490 | wake_up(&data->wait_fw); | ||
491 | printk(KERN_INFO "s2255: firmware loaded successfully\n"); | ||
492 | return; | ||
493 | } | ||
494 | |||
495 | 517 | ||
496 | /* this loads the firmware asynchronously. | 518 | /* this loads the firmware asynchronously. |
497 | Originally this was done synchroously in probe. | 519 | Originally this was done synchroously in probe. |
@@ -549,19 +571,14 @@ static void s2255_fwchunk_complete(struct urb *urb) | |||
549 | } | 571 | } |
550 | data->fw_loaded += len; | 572 | data->fw_loaded += len; |
551 | } else { | 573 | } else { |
552 | init_timer(&data->dsp_wait); | ||
553 | data->dsp_wait.function = s2255_dsp_running; | ||
554 | data->dsp_wait.data = (unsigned long)data; | ||
555 | atomic_set(&data->fw_state, S2255_FW_LOADED_DSPWAIT); | 574 | atomic_set(&data->fw_state, S2255_FW_LOADED_DSPWAIT); |
556 | mod_timer(&data->dsp_wait, msecs_to_jiffies(S2255_DSP_BOOTTIME) | ||
557 | + jiffies); | ||
558 | } | 575 | } |
559 | dprintk(100, "2255 complete done\n"); | 576 | dprintk(100, "2255 complete done\n"); |
560 | return; | 577 | return; |
561 | 578 | ||
562 | } | 579 | } |
563 | 580 | ||
564 | static int s2255_got_frame(struct s2255_dev *dev, int chn) | 581 | static int s2255_got_frame(struct s2255_dev *dev, int chn, int jpgsize) |
565 | { | 582 | { |
566 | struct s2255_dmaqueue *dma_q = &dev->vidq[chn]; | 583 | struct s2255_dmaqueue *dma_q = &dev->vidq[chn]; |
567 | struct s2255_buffer *buf; | 584 | struct s2255_buffer *buf; |
@@ -586,8 +603,7 @@ static int s2255_got_frame(struct s2255_dev *dev, int chn) | |||
586 | list_del(&buf->vb.queue); | 603 | list_del(&buf->vb.queue); |
587 | do_gettimeofday(&buf->vb.ts); | 604 | do_gettimeofday(&buf->vb.ts); |
588 | dprintk(100, "[%p/%d] wakeup\n", buf, buf->vb.i); | 605 | dprintk(100, "[%p/%d] wakeup\n", buf, buf->vb.i); |
589 | 606 | s2255_fillbuff(dev, buf, dma_q->channel, jpgsize); | |
590 | s2255_fillbuff(dev, buf, dma_q->channel); | ||
591 | wake_up(&buf->vb.done); | 607 | wake_up(&buf->vb.done); |
592 | dprintk(2, "wakeup [buf/i] [%p/%d]\n", buf, buf->vb.i); | 608 | dprintk(2, "wakeup [buf/i] [%p/%d]\n", buf, buf->vb.i); |
593 | unlock: | 609 | unlock: |
@@ -621,7 +637,7 @@ static const struct s2255_fmt *format_by_fourcc(int fourcc) | |||
621 | * | 637 | * |
622 | */ | 638 | */ |
623 | static void s2255_fillbuff(struct s2255_dev *dev, struct s2255_buffer *buf, | 639 | static void s2255_fillbuff(struct s2255_dev *dev, struct s2255_buffer *buf, |
624 | int chn) | 640 | int chn, int jpgsize) |
625 | { | 641 | { |
626 | int pos = 0; | 642 | int pos = 0; |
627 | struct timeval ts; | 643 | struct timeval ts; |
@@ -649,6 +665,10 @@ static void s2255_fillbuff(struct s2255_dev *dev, struct s2255_buffer *buf, | |||
649 | case V4L2_PIX_FMT_GREY: | 665 | case V4L2_PIX_FMT_GREY: |
650 | memcpy(vbuf, tmpbuf, buf->vb.width * buf->vb.height); | 666 | memcpy(vbuf, tmpbuf, buf->vb.width * buf->vb.height); |
651 | break; | 667 | break; |
668 | case V4L2_PIX_FMT_JPEG: | ||
669 | buf->vb.size = jpgsize; | ||
670 | memcpy(vbuf, tmpbuf, buf->vb.size); | ||
671 | break; | ||
652 | case V4L2_PIX_FMT_YUV422P: | 672 | case V4L2_PIX_FMT_YUV422P: |
653 | memcpy(vbuf, tmpbuf, | 673 | memcpy(vbuf, tmpbuf, |
654 | buf->vb.width * buf->vb.height * 2); | 674 | buf->vb.width * buf->vb.height * 2); |
@@ -657,9 +677,6 @@ static void s2255_fillbuff(struct s2255_dev *dev, struct s2255_buffer *buf, | |||
657 | printk(KERN_DEBUG "s2255: unknown format?\n"); | 677 | printk(KERN_DEBUG "s2255: unknown format?\n"); |
658 | } | 678 | } |
659 | dev->last_frame[chn] = -1; | 679 | dev->last_frame[chn] = -1; |
660 | /* done with the frame, free it */ | ||
661 | frm->ulState = 0; | ||
662 | dprintk(4, "freeing buffer\n"); | ||
663 | } else { | 680 | } else { |
664 | printk(KERN_ERR "s2255: =======no frame\n"); | 681 | printk(KERN_ERR "s2255: =======no frame\n"); |
665 | return; | 682 | return; |
@@ -1021,6 +1038,10 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, | |||
1021 | case V4L2_PIX_FMT_GREY: | 1038 | case V4L2_PIX_FMT_GREY: |
1022 | fh->mode.color = COLOR_Y8; | 1039 | fh->mode.color = COLOR_Y8; |
1023 | break; | 1040 | break; |
1041 | case V4L2_PIX_FMT_JPEG: | ||
1042 | fh->mode.color = COLOR_JPG | | ||
1043 | (fh->dev->jc[fh->channel].quality << 8); | ||
1044 | break; | ||
1024 | case V4L2_PIX_FMT_YUV422P: | 1045 | case V4L2_PIX_FMT_YUV422P: |
1025 | fh->mode.color = COLOR_YUVPL; | 1046 | fh->mode.color = COLOR_YUVPL; |
1026 | break; | 1047 | break; |
@@ -1139,7 +1160,7 @@ static u32 get_transfer_size(struct s2255_mode *mode) | |||
1139 | } | 1160 | } |
1140 | } | 1161 | } |
1141 | outImageSize = linesPerFrame * pixelsPerLine; | 1162 | outImageSize = linesPerFrame * pixelsPerLine; |
1142 | if (mode->color != COLOR_Y8) { | 1163 | if ((mode->color & MASK_COLOR) != COLOR_Y8) { |
1143 | /* 2 bytes/pixel if not monochrome */ | 1164 | /* 2 bytes/pixel if not monochrome */ |
1144 | outImageSize *= 2; | 1165 | outImageSize *= 2; |
1145 | } | 1166 | } |
@@ -1185,12 +1206,17 @@ static int s2255_set_mode(struct s2255_dev *dev, unsigned long chn, | |||
1185 | u32 *buffer; | 1206 | u32 *buffer; |
1186 | unsigned long chn_rev; | 1207 | unsigned long chn_rev; |
1187 | 1208 | ||
1209 | mutex_lock(&dev->lock); | ||
1188 | chn_rev = G_chnmap[chn]; | 1210 | chn_rev = G_chnmap[chn]; |
1189 | dprintk(3, "mode scale [%ld] %p %d\n", chn, mode, mode->scale); | 1211 | dprintk(3, "mode scale [%ld] %p %d\n", chn, mode, mode->scale); |
1190 | dprintk(3, "mode scale [%ld] %p %d\n", chn, &dev->mode[chn], | 1212 | dprintk(3, "mode scale [%ld] %p %d\n", chn, &dev->mode[chn], |
1191 | dev->mode[chn].scale); | 1213 | dev->mode[chn].scale); |
1192 | dprintk(2, "mode contrast %x\n", mode->contrast); | 1214 | dprintk(2, "mode contrast %x\n", mode->contrast); |
1193 | 1215 | ||
1216 | /* if JPEG, set the quality */ | ||
1217 | if ((mode->color & MASK_COLOR) == COLOR_JPG) | ||
1218 | mode->color = (dev->jc[chn].quality << 8) | COLOR_JPG; | ||
1219 | |||
1194 | /* save the mode */ | 1220 | /* save the mode */ |
1195 | dev->mode[chn] = *mode; | 1221 | dev->mode[chn] = *mode; |
1196 | dev->req_image_size[chn] = get_transfer_size(mode); | 1222 | dev->req_image_size[chn] = get_transfer_size(mode); |
@@ -1199,6 +1225,7 @@ static int s2255_set_mode(struct s2255_dev *dev, unsigned long chn, | |||
1199 | buffer = kzalloc(512, GFP_KERNEL); | 1225 | buffer = kzalloc(512, GFP_KERNEL); |
1200 | if (buffer == NULL) { | 1226 | if (buffer == NULL) { |
1201 | dev_err(&dev->udev->dev, "out of mem\n"); | 1227 | dev_err(&dev->udev->dev, "out of mem\n"); |
1228 | mutex_unlock(&dev->lock); | ||
1202 | return -ENOMEM; | 1229 | return -ENOMEM; |
1203 | } | 1230 | } |
1204 | 1231 | ||
@@ -1214,12 +1241,20 @@ static int s2255_set_mode(struct s2255_dev *dev, unsigned long chn, | |||
1214 | dprintk(1, "set mode done chn %lu, %d\n", chn, res); | 1241 | dprintk(1, "set mode done chn %lu, %d\n", chn, res); |
1215 | 1242 | ||
1216 | /* wait at least 3 frames before continuing */ | 1243 | /* wait at least 3 frames before continuing */ |
1217 | if (mode->restart) | 1244 | if (mode->restart) { |
1218 | msleep(125); | 1245 | dev->setmode_ready[chn] = 0; |
1246 | wait_event_timeout(dev->wait_setmode[chn], | ||
1247 | (dev->setmode_ready[chn] != 0), | ||
1248 | msecs_to_jiffies(S2255_SETMODE_TIMEOUT)); | ||
1249 | if (dev->setmode_ready[chn] != 1) { | ||
1250 | printk(KERN_DEBUG "s2255: no set mode response\n"); | ||
1251 | res = -EFAULT; | ||
1252 | } | ||
1253 | } | ||
1219 | 1254 | ||
1220 | /* clear the restart flag */ | 1255 | /* clear the restart flag */ |
1221 | dev->mode[chn].restart = 0; | 1256 | dev->mode[chn].restart = 0; |
1222 | 1257 | mutex_unlock(&dev->lock); | |
1223 | return res; | 1258 | return res; |
1224 | } | 1259 | } |
1225 | 1260 | ||
@@ -1270,7 +1305,7 @@ static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) | |||
1270 | dev->cur_frame[chn] = 0; | 1305 | dev->cur_frame[chn] = 0; |
1271 | dev->frame_count[chn] = 0; | 1306 | dev->frame_count[chn] = 0; |
1272 | for (j = 0; j < SYS_FRAMES; j++) { | 1307 | for (j = 0; j < SYS_FRAMES; j++) { |
1273 | dev->buffer[chn].frame[j].ulState = 0; | 1308 | dev->buffer[chn].frame[j].ulState = S2255_READ_IDLE; |
1274 | dev->buffer[chn].frame[j].cur_size = 0; | 1309 | dev->buffer[chn].frame[j].cur_size = 0; |
1275 | } | 1310 | } |
1276 | res = videobuf_streamon(&fh->vb_vidq); | 1311 | res = videobuf_streamon(&fh->vb_vidq); |
@@ -1446,6 +1481,27 @@ static int vidioc_s_ctrl(struct file *file, void *priv, | |||
1446 | return -EINVAL; | 1481 | return -EINVAL; |
1447 | } | 1482 | } |
1448 | 1483 | ||
1484 | static int vidioc_g_jpegcomp(struct file *file, void *priv, | ||
1485 | struct v4l2_jpegcompression *jc) | ||
1486 | { | ||
1487 | struct s2255_fh *fh = priv; | ||
1488 | struct s2255_dev *dev = fh->dev; | ||
1489 | *jc = dev->jc[fh->channel]; | ||
1490 | dprintk(2, "getting jpegcompression, quality %d\n", jc->quality); | ||
1491 | return 0; | ||
1492 | } | ||
1493 | |||
1494 | static int vidioc_s_jpegcomp(struct file *file, void *priv, | ||
1495 | struct v4l2_jpegcompression *jc) | ||
1496 | { | ||
1497 | struct s2255_fh *fh = priv; | ||
1498 | struct s2255_dev *dev = fh->dev; | ||
1499 | if (jc->quality < 0 || jc->quality > 100) | ||
1500 | return -EINVAL; | ||
1501 | dev->jc[fh->channel].quality = jc->quality; | ||
1502 | dprintk(2, "setting jpeg quality %d\n", jc->quality); | ||
1503 | return 0; | ||
1504 | } | ||
1449 | static int s2255_open(struct inode *inode, struct file *file) | 1505 | static int s2255_open(struct inode *inode, struct file *file) |
1450 | { | 1506 | { |
1451 | int minor = iminor(inode); | 1507 | int minor = iminor(inode); |
@@ -1455,8 +1511,10 @@ static int s2255_open(struct inode *inode, struct file *file) | |||
1455 | enum v4l2_buf_type type = 0; | 1511 | enum v4l2_buf_type type = 0; |
1456 | int i = 0; | 1512 | int i = 0; |
1457 | int cur_channel = -1; | 1513 | int cur_channel = -1; |
1514 | int state; | ||
1458 | dprintk(1, "s2255: open called (minor=%d)\n", minor); | 1515 | dprintk(1, "s2255: open called (minor=%d)\n", minor); |
1459 | 1516 | ||
1517 | lock_kernel(); | ||
1460 | list_for_each(list, &s2255_devlist) { | 1518 | list_for_each(list, &s2255_devlist) { |
1461 | h = list_entry(list, struct s2255_dev, s2255_devlist); | 1519 | h = list_entry(list, struct s2255_dev, s2255_devlist); |
1462 | for (i = 0; i < MAX_CHANNELS; i++) { | 1520 | for (i = 0; i < MAX_CHANNELS; i++) { |
@@ -1469,45 +1527,78 @@ static int s2255_open(struct inode *inode, struct file *file) | |||
1469 | } | 1527 | } |
1470 | 1528 | ||
1471 | if ((NULL == dev) || (cur_channel == -1)) { | 1529 | if ((NULL == dev) || (cur_channel == -1)) { |
1472 | dprintk(1, "s2255: openv4l no dev\n"); | 1530 | unlock_kernel(); |
1531 | printk(KERN_INFO "s2255: openv4l no dev\n"); | ||
1473 | return -ENODEV; | 1532 | return -ENODEV; |
1474 | } | 1533 | } |
1475 | 1534 | ||
1535 | if (atomic_read(&dev->fw_data->fw_state) == S2255_FW_DISCONNECTING) { | ||
1536 | unlock_kernel(); | ||
1537 | printk(KERN_INFO "disconnecting\n"); | ||
1538 | return -ENODEV; | ||
1539 | } | ||
1540 | kref_get(&dev->kref); | ||
1476 | mutex_lock(&dev->open_lock); | 1541 | mutex_lock(&dev->open_lock); |
1477 | 1542 | ||
1478 | dev->users[cur_channel]++; | 1543 | dev->users[cur_channel]++; |
1479 | dprintk(4, "s2255: open_handles %d\n", dev->users[cur_channel]); | 1544 | dprintk(4, "s2255: open_handles %d\n", dev->users[cur_channel]); |
1480 | 1545 | ||
1481 | if (atomic_read(&dev->fw_data->fw_state) == S2255_FW_FAILED) { | 1546 | switch (atomic_read(&dev->fw_data->fw_state)) { |
1547 | case S2255_FW_FAILED: | ||
1482 | err("2255 firmware load failed. retrying.\n"); | 1548 | err("2255 firmware load failed. retrying.\n"); |
1483 | s2255_fwload_start(dev); | 1549 | s2255_fwload_start(dev, 1); |
1484 | wait_event_timeout(dev->fw_data->wait_fw, | 1550 | wait_event_timeout(dev->fw_data->wait_fw, |
1485 | (atomic_read(&dev->fw_data->fw_state) | 1551 | ((atomic_read(&dev->fw_data->fw_state) |
1486 | != S2255_FW_NOTLOADED), | 1552 | == S2255_FW_SUCCESS) || |
1553 | (atomic_read(&dev->fw_data->fw_state) | ||
1554 | == S2255_FW_DISCONNECTING)), | ||
1487 | msecs_to_jiffies(S2255_LOAD_TIMEOUT)); | 1555 | msecs_to_jiffies(S2255_LOAD_TIMEOUT)); |
1488 | if (atomic_read(&dev->fw_data->fw_state) | 1556 | break; |
1489 | != S2255_FW_SUCCESS) { | 1557 | case S2255_FW_NOTLOADED: |
1490 | printk(KERN_INFO "2255 FW load failed.\n"); | 1558 | case S2255_FW_LOADED_DSPWAIT: |
1491 | dev->users[cur_channel]--; | ||
1492 | mutex_unlock(&dev->open_lock); | ||
1493 | return -EFAULT; | ||
1494 | } | ||
1495 | } else if (atomic_read(&dev->fw_data->fw_state) == S2255_FW_NOTLOADED) { | ||
1496 | /* give S2255_LOAD_TIMEOUT time for firmware to load in case | 1559 | /* give S2255_LOAD_TIMEOUT time for firmware to load in case |
1497 | driver loaded and then device immediately opened */ | 1560 | driver loaded and then device immediately opened */ |
1498 | printk(KERN_INFO "%s waiting for firmware load\n", __func__); | 1561 | printk(KERN_INFO "%s waiting for firmware load\n", __func__); |
1499 | wait_event_timeout(dev->fw_data->wait_fw, | 1562 | wait_event_timeout(dev->fw_data->wait_fw, |
1500 | (atomic_read(&dev->fw_data->fw_state) | 1563 | ((atomic_read(&dev->fw_data->fw_state) |
1501 | != S2255_FW_NOTLOADED), | 1564 | == S2255_FW_SUCCESS) || |
1502 | msecs_to_jiffies(S2255_LOAD_TIMEOUT)); | 1565 | (atomic_read(&dev->fw_data->fw_state) |
1503 | if (atomic_read(&dev->fw_data->fw_state) | 1566 | == S2255_FW_DISCONNECTING)), |
1504 | != S2255_FW_SUCCESS) { | 1567 | msecs_to_jiffies(S2255_LOAD_TIMEOUT)); |
1505 | printk(KERN_INFO "2255 firmware not loaded" | 1568 | break; |
1506 | "try again\n"); | 1569 | case S2255_FW_SUCCESS: |
1507 | dev->users[cur_channel]--; | 1570 | default: |
1508 | mutex_unlock(&dev->open_lock); | 1571 | break; |
1509 | return -EBUSY; | 1572 | } |
1573 | state = atomic_read(&dev->fw_data->fw_state); | ||
1574 | if (state != S2255_FW_SUCCESS) { | ||
1575 | int rc; | ||
1576 | switch (state) { | ||
1577 | case S2255_FW_FAILED: | ||
1578 | printk(KERN_INFO "2255 FW load failed. %d\n", state); | ||
1579 | rc = -ENODEV; | ||
1580 | break; | ||
1581 | case S2255_FW_DISCONNECTING: | ||
1582 | printk(KERN_INFO "%s: disconnecting\n", __func__); | ||
1583 | rc = -ENODEV; | ||
1584 | break; | ||
1585 | case S2255_FW_LOADED_DSPWAIT: | ||
1586 | case S2255_FW_NOTLOADED: | ||
1587 | printk(KERN_INFO "%s: firmware not loaded yet" | ||
1588 | "please try again later\n", | ||
1589 | __func__); | ||
1590 | rc = -EAGAIN; | ||
1591 | break; | ||
1592 | default: | ||
1593 | printk(KERN_INFO "%s: unknown state\n", __func__); | ||
1594 | rc = -EFAULT; | ||
1595 | break; | ||
1510 | } | 1596 | } |
1597 | dev->users[cur_channel]--; | ||
1598 | mutex_unlock(&dev->open_lock); | ||
1599 | kref_put(&dev->kref, s2255_destroy); | ||
1600 | unlock_kernel(); | ||
1601 | return rc; | ||
1511 | } | 1602 | } |
1512 | 1603 | ||
1513 | /* allocate + initialize per filehandle data */ | 1604 | /* allocate + initialize per filehandle data */ |
@@ -1515,6 +1606,8 @@ static int s2255_open(struct inode *inode, struct file *file) | |||
1515 | if (NULL == fh) { | 1606 | if (NULL == fh) { |
1516 | dev->users[cur_channel]--; | 1607 | dev->users[cur_channel]--; |
1517 | mutex_unlock(&dev->open_lock); | 1608 | mutex_unlock(&dev->open_lock); |
1609 | kref_put(&dev->kref, s2255_destroy); | ||
1610 | unlock_kernel(); | ||
1518 | return -ENOMEM; | 1611 | return -ENOMEM; |
1519 | } | 1612 | } |
1520 | 1613 | ||
@@ -1528,6 +1621,13 @@ static int s2255_open(struct inode *inode, struct file *file) | |||
1528 | fh->height = NUM_LINES_4CIFS_NTSC * 2; | 1621 | fh->height = NUM_LINES_4CIFS_NTSC * 2; |
1529 | fh->channel = cur_channel; | 1622 | fh->channel = cur_channel; |
1530 | 1623 | ||
1624 | /* configure channel to default state */ | ||
1625 | if (!dev->chn_configured[cur_channel]) { | ||
1626 | s2255_set_mode(dev, cur_channel, &fh->mode); | ||
1627 | dev->chn_configured[cur_channel] = 1; | ||
1628 | } | ||
1629 | |||
1630 | |||
1531 | /* Put all controls at a sane state */ | 1631 | /* Put all controls at a sane state */ |
1532 | for (i = 0; i < ARRAY_SIZE(s2255_qctrl); i++) | 1632 | for (i = 0; i < ARRAY_SIZE(s2255_qctrl); i++) |
1533 | qctl_regs[i] = s2255_qctrl[i].default_value; | 1633 | qctl_regs[i] = s2255_qctrl[i].default_value; |
@@ -1546,8 +1646,8 @@ static int s2255_open(struct inode *inode, struct file *file) | |||
1546 | V4L2_FIELD_INTERLACED, | 1646 | V4L2_FIELD_INTERLACED, |
1547 | sizeof(struct s2255_buffer), fh); | 1647 | sizeof(struct s2255_buffer), fh); |
1548 | 1648 | ||
1549 | kref_get(&dev->kref); | ||
1550 | mutex_unlock(&dev->open_lock); | 1649 | mutex_unlock(&dev->open_lock); |
1650 | unlock_kernel(); | ||
1551 | return 0; | 1651 | return 0; |
1552 | } | 1652 | } |
1553 | 1653 | ||
@@ -1569,30 +1669,24 @@ static unsigned int s2255_poll(struct file *file, | |||
1569 | static void s2255_destroy(struct kref *kref) | 1669 | static void s2255_destroy(struct kref *kref) |
1570 | { | 1670 | { |
1571 | struct s2255_dev *dev = to_s2255_dev(kref); | 1671 | struct s2255_dev *dev = to_s2255_dev(kref); |
1672 | struct list_head *list; | ||
1673 | int i; | ||
1572 | if (!dev) { | 1674 | if (!dev) { |
1573 | printk(KERN_ERR "s2255drv: kref problem\n"); | 1675 | printk(KERN_ERR "s2255drv: kref problem\n"); |
1574 | return; | 1676 | return; |
1575 | } | 1677 | } |
1576 | |||
1577 | /* | ||
1578 | * Wake up any firmware load waiting (only done in .open, | ||
1579 | * which holds the open_lock mutex) | ||
1580 | */ | ||
1581 | atomic_set(&dev->fw_data->fw_state, S2255_FW_DISCONNECTING); | 1678 | atomic_set(&dev->fw_data->fw_state, S2255_FW_DISCONNECTING); |
1582 | wake_up(&dev->fw_data->wait_fw); | 1679 | wake_up(&dev->fw_data->wait_fw); |
1583 | 1680 | for (i = 0; i < MAX_CHANNELS; i++) { | |
1584 | /* prevent s2255_disconnect from racing s2255_open */ | 1681 | dev->setmode_ready[i] = 1; |
1682 | wake_up(&dev->wait_setmode[i]); | ||
1683 | } | ||
1585 | mutex_lock(&dev->open_lock); | 1684 | mutex_lock(&dev->open_lock); |
1685 | /* reset the DSP so firmware can be reload next time */ | ||
1686 | s2255_reset_dsppower(dev); | ||
1586 | s2255_exit_v4l(dev); | 1687 | s2255_exit_v4l(dev); |
1587 | /* | ||
1588 | * device unregistered so no longer possible to open. open_mutex | ||
1589 | * can be unlocked and timers deleted afterwards. | ||
1590 | */ | ||
1591 | mutex_unlock(&dev->open_lock); | ||
1592 | |||
1593 | /* board shutdown stops the read pipe if it is running */ | 1688 | /* board shutdown stops the read pipe if it is running */ |
1594 | s2255_board_shutdown(dev); | 1689 | s2255_board_shutdown(dev); |
1595 | |||
1596 | /* make sure firmware still not trying to load */ | 1690 | /* make sure firmware still not trying to load */ |
1597 | del_timer(&dev->timer); /* only started in .probe and .open */ | 1691 | del_timer(&dev->timer); /* only started in .probe and .open */ |
1598 | 1692 | ||
@@ -1602,23 +1696,19 @@ static void s2255_destroy(struct kref *kref) | |||
1602 | usb_free_urb(dev->fw_data->fw_urb); | 1696 | usb_free_urb(dev->fw_data->fw_urb); |
1603 | dev->fw_data->fw_urb = NULL; | 1697 | dev->fw_data->fw_urb = NULL; |
1604 | } | 1698 | } |
1605 | |||
1606 | /* | ||
1607 | * delete the dsp_wait timer, which sets the firmware | ||
1608 | * state on completion. This is done before fw_data | ||
1609 | * is freed below. | ||
1610 | */ | ||
1611 | |||
1612 | del_timer(&dev->fw_data->dsp_wait); /* only started in .open */ | ||
1613 | |||
1614 | if (dev->fw_data->fw) | 1699 | if (dev->fw_data->fw) |
1615 | release_firmware(dev->fw_data->fw); | 1700 | release_firmware(dev->fw_data->fw); |
1616 | kfree(dev->fw_data->pfw_data); | 1701 | kfree(dev->fw_data->pfw_data); |
1617 | kfree(dev->fw_data); | 1702 | kfree(dev->fw_data); |
1618 | |||
1619 | usb_put_dev(dev->udev); | 1703 | usb_put_dev(dev->udev); |
1620 | dprintk(1, "%s", __func__); | 1704 | dprintk(1, "%s", __func__); |
1621 | kfree(dev); | 1705 | kfree(dev); |
1706 | |||
1707 | while (!list_empty(&s2255_devlist)) { | ||
1708 | list = s2255_devlist.next; | ||
1709 | list_del(list); | ||
1710 | } | ||
1711 | mutex_unlock(&dev->open_lock); | ||
1622 | } | 1712 | } |
1623 | 1713 | ||
1624 | static int s2255_close(struct inode *inode, struct file *file) | 1714 | static int s2255_close(struct inode *inode, struct file *file) |
@@ -1702,6 +1792,8 @@ static const struct v4l2_ioctl_ops s2255_ioctl_ops = { | |||
1702 | #ifdef CONFIG_VIDEO_V4L1_COMPAT | 1792 | #ifdef CONFIG_VIDEO_V4L1_COMPAT |
1703 | .vidiocgmbuf = vidioc_cgmbuf, | 1793 | .vidiocgmbuf = vidioc_cgmbuf, |
1704 | #endif | 1794 | #endif |
1795 | .vidioc_s_jpegcomp = vidioc_s_jpegcomp, | ||
1796 | .vidioc_g_jpegcomp = vidioc_g_jpegcomp, | ||
1705 | }; | 1797 | }; |
1706 | 1798 | ||
1707 | static struct video_device template = { | 1799 | static struct video_device template = { |
@@ -1740,7 +1832,7 @@ static int s2255_probe_v4l(struct s2255_dev *dev) | |||
1740 | ret = video_register_device(dev->vdev[i], | 1832 | ret = video_register_device(dev->vdev[i], |
1741 | VFL_TYPE_GRABBER, | 1833 | VFL_TYPE_GRABBER, |
1742 | cur_nr + i); | 1834 | cur_nr + i); |
1743 | dev->vdev[i]->priv = dev; | 1835 | video_set_drvdata(dev->vdev[i], dev); |
1744 | 1836 | ||
1745 | if (ret != 0) { | 1837 | if (ret != 0) { |
1746 | dev_err(&dev->udev->dev, | 1838 | dev_err(&dev->udev->dev, |
@@ -1754,18 +1846,16 @@ static int s2255_probe_v4l(struct s2255_dev *dev) | |||
1754 | 1846 | ||
1755 | static void s2255_exit_v4l(struct s2255_dev *dev) | 1847 | static void s2255_exit_v4l(struct s2255_dev *dev) |
1756 | { | 1848 | { |
1757 | struct list_head *list; | 1849 | |
1758 | int i; | 1850 | int i; |
1759 | /* unregister the video devices */ | ||
1760 | while (!list_empty(&s2255_devlist)) { | ||
1761 | list = s2255_devlist.next; | ||
1762 | list_del(list); | ||
1763 | } | ||
1764 | for (i = 0; i < MAX_CHANNELS; i++) { | 1851 | for (i = 0; i < MAX_CHANNELS; i++) { |
1765 | if (-1 != dev->vdev[i]->minor) | 1852 | if (-1 != dev->vdev[i]->minor) { |
1766 | video_unregister_device(dev->vdev[i]); | 1853 | video_unregister_device(dev->vdev[i]); |
1767 | else | 1854 | printk(KERN_INFO "s2255 unregistered\n"); |
1855 | } else { | ||
1768 | video_device_release(dev->vdev[i]); | 1856 | video_device_release(dev->vdev[i]); |
1857 | printk(KERN_INFO "s2255 released\n"); | ||
1858 | } | ||
1769 | } | 1859 | } |
1770 | } | 1860 | } |
1771 | 1861 | ||
@@ -1775,134 +1865,123 @@ static void s2255_exit_v4l(struct s2255_dev *dev) | |||
1775 | * function again). | 1865 | * function again). |
1776 | * | 1866 | * |
1777 | * Received frame structure: | 1867 | * Received frame structure: |
1778 | * bytes 0-3: marker : 0x2255DA4AL (FRAME_MARKER) | 1868 | * bytes 0-3: marker : 0x2255DA4AL (S2255_MARKER_FRAME) |
1779 | * bytes 4-7: channel: 0-3 | 1869 | * bytes 4-7: channel: 0-3 |
1780 | * bytes 8-11: payload size: size of the frame | 1870 | * bytes 8-11: payload size: size of the frame |
1781 | * bytes 12-payloadsize+12: frame data | 1871 | * bytes 12-payloadsize+12: frame data |
1782 | */ | 1872 | */ |
1783 | static int save_frame(struct s2255_dev *dev, struct s2255_pipeinfo *pipe_info) | 1873 | static int save_frame(struct s2255_dev *dev, struct s2255_pipeinfo *pipe_info) |
1784 | { | 1874 | { |
1785 | static int dbgsync; /* = 0; */ | ||
1786 | char *pdest; | 1875 | char *pdest; |
1787 | u32 offset = 0; | 1876 | u32 offset = 0; |
1788 | int bsync = 0; | 1877 | int bframe = 0; |
1789 | int btrunc = 0; | ||
1790 | char *psrc; | 1878 | char *psrc; |
1791 | unsigned long copy_size; | 1879 | unsigned long copy_size; |
1792 | unsigned long size; | 1880 | unsigned long size; |
1793 | s32 idx = -1; | 1881 | s32 idx = -1; |
1794 | struct s2255_framei *frm; | 1882 | struct s2255_framei *frm; |
1795 | unsigned char *pdata; | 1883 | unsigned char *pdata; |
1796 | unsigned long cur_size; | 1884 | |
1797 | int bsearch = 0; | ||
1798 | struct s2255_bufferi *buf; | ||
1799 | dprintk(100, "buffer to user\n"); | 1885 | dprintk(100, "buffer to user\n"); |
1800 | 1886 | ||
1801 | idx = dev->cur_frame[dev->cc]; | 1887 | idx = dev->cur_frame[dev->cc]; |
1802 | buf = &dev->buffer[dev->cc]; | 1888 | frm = &dev->buffer[dev->cc].frame[idx]; |
1803 | frm = &buf->frame[idx]; | ||
1804 | |||
1805 | if (frm->ulState == 0) { | ||
1806 | frm->ulState = 1; | ||
1807 | frm->cur_size = 0; | ||
1808 | bsearch = 1; | ||
1809 | } else if (frm->ulState == 2) { | ||
1810 | /* system frame was not freed */ | ||
1811 | dprintk(2, "sys frame not free. overrun ringbuf\n"); | ||
1812 | bsearch = 1; | ||
1813 | frm->ulState = 1; | ||
1814 | frm->cur_size = 0; | ||
1815 | } | ||
1816 | |||
1817 | if (bsearch) { | ||
1818 | if (*(s32 *) pipe_info->transfer_buffer != FRAME_MARKER) { | ||
1819 | u32 jj; | ||
1820 | if (dbgsync == 0) { | ||
1821 | dprintk(3, "not synched, discarding all packets" | ||
1822 | "until marker\n"); | ||
1823 | 1889 | ||
1824 | dbgsync++; | 1890 | if (frm->ulState == S2255_READ_IDLE) { |
1825 | } | 1891 | int jj; |
1826 | pdata = (unsigned char *)pipe_info->transfer_buffer; | 1892 | unsigned int cc; |
1827 | for (jj = 0; jj < (pipe_info->cur_transfer_size - 12); | 1893 | s32 *pdword; |
1828 | jj++) { | 1894 | int payload; |
1829 | if (*(s32 *) pdata == FRAME_MARKER) { | 1895 | /* search for marker codes */ |
1830 | int cc; | 1896 | pdata = (unsigned char *)pipe_info->transfer_buffer; |
1831 | dprintk(3, | 1897 | for (jj = 0; jj < (pipe_info->cur_transfer_size - 12); jj++) { |
1832 | "found frame marker at offset:" | 1898 | switch (*(s32 *) pdata) { |
1833 | " %d [%x %x]\n", jj, pdata[0], | 1899 | case S2255_MARKER_FRAME: |
1834 | pdata[1]); | 1900 | pdword = (s32 *)pdata; |
1835 | offset = jj; | 1901 | dprintk(4, "found frame marker at offset:" |
1836 | bsync = 1; | 1902 | " %d [%x %x]\n", jj, pdata[0], |
1837 | cc = *(u32 *) (pdata + sizeof(u32)); | 1903 | pdata[1]); |
1838 | if (cc >= MAX_CHANNELS) { | 1904 | offset = jj + PREFIX_SIZE; |
1839 | printk(KERN_ERR | 1905 | bframe = 1; |
1840 | "bad channel\n"); | 1906 | cc = pdword[1]; |
1841 | return -EINVAL; | 1907 | if (cc >= MAX_CHANNELS) { |
1842 | } | 1908 | printk(KERN_ERR |
1843 | /* reverse it */ | 1909 | "bad channel\n"); |
1844 | dev->cc = G_chnmap[cc]; | 1910 | return -EINVAL; |
1911 | } | ||
1912 | /* reverse it */ | ||
1913 | dev->cc = G_chnmap[cc]; | ||
1914 | payload = pdword[3]; | ||
1915 | if (payload > dev->req_image_size[dev->cc]) { | ||
1916 | dev->bad_payload[dev->cc]++; | ||
1917 | /* discard the bad frame */ | ||
1918 | return -EINVAL; | ||
1919 | } | ||
1920 | dev->pkt_size[dev->cc] = payload; | ||
1921 | dev->jpg_size[dev->cc] = pdword[4]; | ||
1922 | break; | ||
1923 | case S2255_MARKER_RESPONSE: | ||
1924 | pdword = (s32 *)pdata; | ||
1925 | pdata += DEF_USB_BLOCK; | ||
1926 | jj += DEF_USB_BLOCK; | ||
1927 | if (pdword[1] >= MAX_CHANNELS) | ||
1928 | break; | ||
1929 | cc = G_chnmap[pdword[1]]; | ||
1930 | if (!(cc >= 0 && cc < MAX_CHANNELS)) | ||
1931 | break; | ||
1932 | switch (pdword[2]) { | ||
1933 | case 0x01: | ||
1934 | /* check if channel valid */ | ||
1935 | /* set mode ready */ | ||
1936 | dev->setmode_ready[cc] = 1; | ||
1937 | wake_up(&dev->wait_setmode[cc]); | ||
1938 | dprintk(5, "setmode ready %d\n", cc); | ||
1845 | break; | 1939 | break; |
1940 | case 0x10: | ||
1941 | |||
1942 | dev->chn_ready |= (1 << cc); | ||
1943 | if ((dev->chn_ready & 0x0f) != 0x0f) | ||
1944 | break; | ||
1945 | /* all channels ready */ | ||
1946 | printk(KERN_INFO "s2255: fw loaded\n"); | ||
1947 | atomic_set(&dev->fw_data->fw_state, | ||
1948 | S2255_FW_SUCCESS); | ||
1949 | wake_up(&dev->fw_data->wait_fw); | ||
1950 | break; | ||
1951 | default: | ||
1952 | printk(KERN_INFO "s2255 unknwn resp\n"); | ||
1846 | } | 1953 | } |
1954 | default: | ||
1847 | pdata++; | 1955 | pdata++; |
1956 | break; | ||
1848 | } | 1957 | } |
1849 | if (bsync == 0) | 1958 | if (bframe) |
1850 | return -EINVAL; | 1959 | break; |
1851 | } else { | 1960 | } /* for */ |
1852 | u32 *pword; | 1961 | if (!bframe) |
1853 | u32 payload; | 1962 | return -EINVAL; |
1854 | int cc; | ||
1855 | dbgsync = 0; | ||
1856 | bsync = 1; | ||
1857 | pword = (u32 *) pipe_info->transfer_buffer; | ||
1858 | cc = pword[1]; | ||
1859 | |||
1860 | if (cc >= MAX_CHANNELS) { | ||
1861 | printk("invalid channel found. " | ||
1862 | "throwing out data!\n"); | ||
1863 | return -EINVAL; | ||
1864 | } | ||
1865 | dev->cc = G_chnmap[cc]; | ||
1866 | payload = pword[2]; | ||
1867 | if (payload != dev->req_image_size[dev->cc]) { | ||
1868 | dprintk(1, "[%d][%d]unexpected payload: %d" | ||
1869 | "required: %lu \n", cc, dev->cc, | ||
1870 | payload, dev->req_image_size[dev->cc]); | ||
1871 | dev->bad_payload[dev->cc]++; | ||
1872 | /* discard the bad frame */ | ||
1873 | return -EINVAL; | ||
1874 | } | ||
1875 | |||
1876 | } | ||
1877 | } | ||
1878 | /* search done. now find out if should be acquiring | ||
1879 | on this channel */ | ||
1880 | if (!dev->b_acquire[dev->cc]) { | ||
1881 | frm->ulState = 0; | ||
1882 | return -EINVAL; | ||
1883 | } | 1963 | } |
1884 | 1964 | ||
1965 | |||
1885 | idx = dev->cur_frame[dev->cc]; | 1966 | idx = dev->cur_frame[dev->cc]; |
1886 | frm = &dev->buffer[dev->cc].frame[idx]; | 1967 | frm = &dev->buffer[dev->cc].frame[idx]; |
1887 | 1968 | ||
1888 | if (frm->ulState == 0) { | 1969 | /* search done. now find out if should be acquiring on this channel */ |
1889 | frm->ulState = 1; | 1970 | if (!dev->b_acquire[dev->cc]) { |
1890 | frm->cur_size = 0; | 1971 | /* we found a frame, but this channel is turned off */ |
1891 | } else if (frm->ulState == 2) { | 1972 | frm->ulState = S2255_READ_IDLE; |
1892 | /* system frame ring buffer overrun */ | 1973 | return -EINVAL; |
1893 | dprintk(2, "sys frame overrun. overwriting frame %d %d\n", | ||
1894 | dev->cc, idx); | ||
1895 | frm->ulState = 1; | ||
1896 | frm->cur_size = 0; | ||
1897 | } | 1974 | } |
1898 | 1975 | ||
1899 | if (bsync) { | 1976 | if (frm->ulState == S2255_READ_IDLE) { |
1900 | /* skip the marker 512 bytes (and offset if out of sync) */ | 1977 | frm->ulState = S2255_READ_FRAME; |
1901 | psrc = (u8 *)pipe_info->transfer_buffer + offset + PREFIX_SIZE; | 1978 | frm->cur_size = 0; |
1902 | } else { | ||
1903 | psrc = (u8 *)pipe_info->transfer_buffer; | ||
1904 | } | 1979 | } |
1905 | 1980 | ||
1981 | /* skip the marker 512 bytes (and offset if out of sync) */ | ||
1982 | psrc = (u8 *)pipe_info->transfer_buffer + offset; | ||
1983 | |||
1984 | |||
1906 | if (frm->lpvbits == NULL) { | 1985 | if (frm->lpvbits == NULL) { |
1907 | dprintk(1, "s2255 frame buffer == NULL.%p %p %d %d", | 1986 | dprintk(1, "s2255 frame buffer == NULL.%p %p %d %d", |
1908 | frm, dev, dev->cc, idx); | 1987 | frm, dev, dev->cc, idx); |
@@ -1911,33 +1990,20 @@ static int save_frame(struct s2255_dev *dev, struct s2255_pipeinfo *pipe_info) | |||
1911 | 1990 | ||
1912 | pdest = frm->lpvbits + frm->cur_size; | 1991 | pdest = frm->lpvbits + frm->cur_size; |
1913 | 1992 | ||
1914 | if (bsync) { | 1993 | copy_size = (pipe_info->cur_transfer_size - offset); |
1915 | copy_size = | ||
1916 | (pipe_info->cur_transfer_size - offset) - PREFIX_SIZE; | ||
1917 | if (copy_size > pipe_info->cur_transfer_size) { | ||
1918 | printk("invalid copy size, overflow!\n"); | ||
1919 | return -ENOMEM; | ||
1920 | } | ||
1921 | } else { | ||
1922 | copy_size = pipe_info->cur_transfer_size; | ||
1923 | } | ||
1924 | 1994 | ||
1925 | cur_size = frm->cur_size; | 1995 | size = dev->pkt_size[dev->cc] - PREFIX_SIZE; |
1926 | size = dev->req_image_size[dev->cc]; | ||
1927 | 1996 | ||
1928 | if ((copy_size + cur_size) > size) { | 1997 | /* sanity check on pdest */ |
1929 | copy_size = size - cur_size; | 1998 | if ((copy_size + frm->cur_size) < dev->req_image_size[dev->cc]) |
1930 | btrunc = 1; | 1999 | memcpy(pdest, psrc, copy_size); |
1931 | } | ||
1932 | 2000 | ||
1933 | memcpy(pdest, psrc, copy_size); | ||
1934 | cur_size += copy_size; | ||
1935 | frm->cur_size += copy_size; | 2001 | frm->cur_size += copy_size; |
1936 | dprintk(50, "cur_size size %lu size %lu \n", cur_size, size); | 2002 | dprintk(4, "cur_size size %lu size %lu \n", frm->cur_size, size); |
2003 | |||
2004 | if (frm->cur_size >= size) { | ||
1937 | 2005 | ||
1938 | if (cur_size >= (size - PREFIX_SIZE)) { | ||
1939 | u32 cc = dev->cc; | 2006 | u32 cc = dev->cc; |
1940 | frm->ulState = 2; | ||
1941 | dprintk(2, "****************[%d]Buffer[%d]full*************\n", | 2007 | dprintk(2, "****************[%d]Buffer[%d]full*************\n", |
1942 | cc, idx); | 2008 | cc, idx); |
1943 | dev->last_frame[cc] = dev->cur_frame[cc]; | 2009 | dev->last_frame[cc] = dev->cur_frame[cc]; |
@@ -1946,16 +2012,13 @@ static int save_frame(struct s2255_dev *dev, struct s2255_pipeinfo *pipe_info) | |||
1946 | if ((dev->cur_frame[cc] == SYS_FRAMES) || | 2012 | if ((dev->cur_frame[cc] == SYS_FRAMES) || |
1947 | (dev->cur_frame[cc] == dev->buffer[cc].dwFrames)) | 2013 | (dev->cur_frame[cc] == dev->buffer[cc].dwFrames)) |
1948 | dev->cur_frame[cc] = 0; | 2014 | dev->cur_frame[cc] = 0; |
1949 | 2015 | /* frame ready */ | |
1950 | /* signal the semaphore for this channel */ | ||
1951 | if (dev->b_acquire[cc]) | 2016 | if (dev->b_acquire[cc]) |
1952 | s2255_got_frame(dev, cc); | 2017 | s2255_got_frame(dev, cc, dev->jpg_size[cc]); |
1953 | dev->frame_count[cc]++; | 2018 | dev->frame_count[cc]++; |
1954 | } | 2019 | frm->ulState = S2255_READ_IDLE; |
1955 | /* frame was truncated */ | 2020 | frm->cur_size = 0; |
1956 | if (btrunc) { | 2021 | |
1957 | /* return more data to process */ | ||
1958 | return EAGAIN; | ||
1959 | } | 2022 | } |
1960 | /* done successfully */ | 2023 | /* done successfully */ |
1961 | return 0; | 2024 | return 0; |
@@ -1974,8 +2037,8 @@ static void s2255_read_video_callback(struct s2255_dev *dev, | |||
1974 | } | 2037 | } |
1975 | /* otherwise copy to the system buffers */ | 2038 | /* otherwise copy to the system buffers */ |
1976 | res = save_frame(dev, pipe_info); | 2039 | res = save_frame(dev, pipe_info); |
1977 | if (res == EAGAIN) | 2040 | if (res != 0) |
1978 | save_frame(dev, pipe_info); | 2041 | dprintk(4, "s2255: read callback failed\n"); |
1979 | 2042 | ||
1980 | dprintk(50, "callback read video done\n"); | 2043 | dprintk(50, "callback read video done\n"); |
1981 | return; | 2044 | return; |
@@ -2095,11 +2158,9 @@ static int s2255_board_init(struct s2255_dev *dev) | |||
2095 | 2158 | ||
2096 | memset(pipe, 0, sizeof(*pipe)); | 2159 | memset(pipe, 0, sizeof(*pipe)); |
2097 | pipe->dev = dev; | 2160 | pipe->dev = dev; |
2098 | pipe->cur_transfer_size = DEFAULT_PIPE_USBBLOCK; | 2161 | pipe->cur_transfer_size = S2255_USB_XFER_SIZE; |
2099 | pipe->max_transfer_size = MAX_PIPE_USBBLOCK; | 2162 | pipe->max_transfer_size = S2255_USB_XFER_SIZE; |
2100 | 2163 | ||
2101 | if (pipe->cur_transfer_size > pipe->max_transfer_size) | ||
2102 | pipe->cur_transfer_size = pipe->max_transfer_size; | ||
2103 | pipe->transfer_buffer = kzalloc(pipe->max_transfer_size, | 2164 | pipe->transfer_buffer = kzalloc(pipe->max_transfer_size, |
2104 | GFP_KERNEL); | 2165 | GFP_KERNEL); |
2105 | if (pipe->transfer_buffer == NULL) { | 2166 | if (pipe->transfer_buffer == NULL) { |
@@ -2119,6 +2180,7 @@ static int s2255_board_init(struct s2255_dev *dev) | |||
2119 | for (j = 0; j < MAX_CHANNELS; j++) { | 2180 | for (j = 0; j < MAX_CHANNELS; j++) { |
2120 | dev->b_acquire[j] = 0; | 2181 | dev->b_acquire[j] = 0; |
2121 | dev->mode[j] = mode_def; | 2182 | dev->mode[j] = mode_def; |
2183 | dev->jc[j].quality = S2255_DEF_JPEG_QUAL; | ||
2122 | dev->cur_fmt[j] = &formats[0]; | 2184 | dev->cur_fmt[j] = &formats[0]; |
2123 | dev->mode[j].restart = 1; | 2185 | dev->mode[j].restart = 1; |
2124 | dev->req_image_size[j] = get_transfer_size(&mode_def); | 2186 | dev->req_image_size[j] = get_transfer_size(&mode_def); |
@@ -2323,7 +2385,7 @@ static int s2255_stop_acquire(struct s2255_dev *dev, unsigned long chn) | |||
2323 | kfree(buffer); | 2385 | kfree(buffer); |
2324 | dev->b_acquire[chn] = 0; | 2386 | dev->b_acquire[chn] = 0; |
2325 | 2387 | ||
2326 | return 0; | 2388 | return res; |
2327 | } | 2389 | } |
2328 | 2390 | ||
2329 | static void s2255_stop_readpipe(struct s2255_dev *dev) | 2391 | static void s2255_stop_readpipe(struct s2255_dev *dev) |
@@ -2359,8 +2421,10 @@ static void s2255_stop_readpipe(struct s2255_dev *dev) | |||
2359 | return; | 2421 | return; |
2360 | } | 2422 | } |
2361 | 2423 | ||
2362 | static void s2255_fwload_start(struct s2255_dev *dev) | 2424 | static void s2255_fwload_start(struct s2255_dev *dev, int reset) |
2363 | { | 2425 | { |
2426 | if (reset) | ||
2427 | s2255_reset_dsppower(dev); | ||
2364 | dev->fw_data->fw_size = dev->fw_data->fw->size; | 2428 | dev->fw_data->fw_size = dev->fw_data->fw->size; |
2365 | atomic_set(&dev->fw_data->fw_state, S2255_FW_NOTLOADED); | 2429 | atomic_set(&dev->fw_data->fw_state, S2255_FW_NOTLOADED); |
2366 | memcpy(dev->fw_data->pfw_data, | 2430 | memcpy(dev->fw_data->pfw_data, |
@@ -2383,6 +2447,8 @@ static int s2255_probe(struct usb_interface *interface, | |||
2383 | struct usb_endpoint_descriptor *endpoint; | 2447 | struct usb_endpoint_descriptor *endpoint; |
2384 | int i; | 2448 | int i; |
2385 | int retval = -ENOMEM; | 2449 | int retval = -ENOMEM; |
2450 | __le32 *pdata; | ||
2451 | int fw_size; | ||
2386 | 2452 | ||
2387 | dprintk(2, "s2255: probe\n"); | 2453 | dprintk(2, "s2255: probe\n"); |
2388 | 2454 | ||
@@ -2437,6 +2503,8 @@ static int s2255_probe(struct usb_interface *interface, | |||
2437 | dev->timer.data = (unsigned long)dev->fw_data; | 2503 | dev->timer.data = (unsigned long)dev->fw_data; |
2438 | 2504 | ||
2439 | init_waitqueue_head(&dev->fw_data->wait_fw); | 2505 | init_waitqueue_head(&dev->fw_data->wait_fw); |
2506 | for (i = 0; i < MAX_CHANNELS; i++) | ||
2507 | init_waitqueue_head(&dev->wait_setmode[i]); | ||
2440 | 2508 | ||
2441 | 2509 | ||
2442 | dev->fw_data->fw_urb = usb_alloc_urb(0, GFP_KERNEL); | 2510 | dev->fw_data->fw_urb = usb_alloc_urb(0, GFP_KERNEL); |
@@ -2456,16 +2524,30 @@ static int s2255_probe(struct usb_interface *interface, | |||
2456 | printk(KERN_ERR "sensoray 2255 failed to get firmware\n"); | 2524 | printk(KERN_ERR "sensoray 2255 failed to get firmware\n"); |
2457 | goto error; | 2525 | goto error; |
2458 | } | 2526 | } |
2527 | /* check the firmware is valid */ | ||
2528 | fw_size = dev->fw_data->fw->size; | ||
2529 | pdata = (__le32 *) &dev->fw_data->fw->data[fw_size - 8]; | ||
2459 | 2530 | ||
2531 | if (*pdata != S2255_FW_MARKER) { | ||
2532 | printk(KERN_INFO "Firmware invalid.\n"); | ||
2533 | retval = -ENODEV; | ||
2534 | goto error; | ||
2535 | } else { | ||
2536 | /* make sure firmware is the latest */ | ||
2537 | __le32 *pRel; | ||
2538 | pRel = (__le32 *) &dev->fw_data->fw->data[fw_size - 4]; | ||
2539 | printk(KERN_INFO "s2255 dsp fw version %x\n", *pRel); | ||
2540 | } | ||
2460 | /* loads v4l specific */ | 2541 | /* loads v4l specific */ |
2461 | s2255_probe_v4l(dev); | 2542 | s2255_probe_v4l(dev); |
2543 | usb_reset_device(dev->udev); | ||
2462 | /* load 2255 board specific */ | 2544 | /* load 2255 board specific */ |
2463 | s2255_board_init(dev); | 2545 | s2255_board_init(dev); |
2464 | 2546 | ||
2465 | dprintk(4, "before probe done %p\n", dev); | 2547 | dprintk(4, "before probe done %p\n", dev); |
2466 | spin_lock_init(&dev->slock); | 2548 | spin_lock_init(&dev->slock); |
2467 | 2549 | ||
2468 | s2255_fwload_start(dev); | 2550 | s2255_fwload_start(dev, 0); |
2469 | dev_info(&interface->dev, "Sensoray 2255 detected\n"); | 2551 | dev_info(&interface->dev, "Sensoray 2255 detected\n"); |
2470 | return 0; | 2552 | return 0; |
2471 | error: | 2553 | error: |
@@ -2476,14 +2558,30 @@ error: | |||
2476 | static void s2255_disconnect(struct usb_interface *interface) | 2558 | static void s2255_disconnect(struct usb_interface *interface) |
2477 | { | 2559 | { |
2478 | struct s2255_dev *dev = NULL; | 2560 | struct s2255_dev *dev = NULL; |
2561 | int i; | ||
2479 | dprintk(1, "s2255: disconnect interface %p\n", interface); | 2562 | dprintk(1, "s2255: disconnect interface %p\n", interface); |
2480 | dev = usb_get_intfdata(interface); | 2563 | dev = usb_get_intfdata(interface); |
2564 | |||
2565 | /* | ||
2566 | * wake up any of the timers to allow open_lock to be | ||
2567 | * acquired sooner | ||
2568 | */ | ||
2569 | atomic_set(&dev->fw_data->fw_state, S2255_FW_DISCONNECTING); | ||
2570 | wake_up(&dev->fw_data->wait_fw); | ||
2571 | for (i = 0; i < MAX_CHANNELS; i++) { | ||
2572 | dev->setmode_ready[i] = 1; | ||
2573 | wake_up(&dev->wait_setmode[i]); | ||
2574 | } | ||
2575 | |||
2576 | mutex_lock(&dev->open_lock); | ||
2577 | usb_set_intfdata(interface, NULL); | ||
2578 | mutex_unlock(&dev->open_lock); | ||
2579 | |||
2481 | if (dev) { | 2580 | if (dev) { |
2482 | kref_put(&dev->kref, s2255_destroy); | 2581 | kref_put(&dev->kref, s2255_destroy); |
2483 | dprintk(1, "s2255drv: disconnect\n"); | 2582 | dprintk(1, "s2255drv: disconnect\n"); |
2484 | dev_info(&interface->dev, "s2255usb now disconnected\n"); | 2583 | dev_info(&interface->dev, "s2255usb now disconnected\n"); |
2485 | } | 2584 | } |
2486 | usb_set_intfdata(interface, NULL); | ||
2487 | } | 2585 | } |
2488 | 2586 | ||
2489 | static struct usb_driver s2255_driver = { | 2587 | static struct usb_driver s2255_driver = { |
diff --git a/drivers/media/video/saa5246a.c b/drivers/media/video/saa5246a.c index 6ee63e69b36c..4a21b8a6a709 100644 --- a/drivers/media/video/saa5246a.c +++ b/drivers/media/video/saa5246a.c | |||
@@ -43,135 +43,363 @@ | |||
43 | #include <linux/mm.h> | 43 | #include <linux/mm.h> |
44 | #include <linux/init.h> | 44 | #include <linux/init.h> |
45 | #include <linux/i2c.h> | 45 | #include <linux/i2c.h> |
46 | #include <linux/smp_lock.h> | ||
47 | #include <linux/mutex.h> | ||
46 | #include <linux/videotext.h> | 48 | #include <linux/videotext.h> |
47 | #include <linux/videodev.h> | 49 | #include <linux/videodev.h> |
48 | #include <media/v4l2-common.h> | 50 | #include <media/v4l2-common.h> |
49 | #include <media/v4l2-ioctl.h> | 51 | #include <media/v4l2-ioctl.h> |
50 | #include <linux/mutex.h> | 52 | #include <media/v4l2-i2c-drv-legacy.h> |
51 | |||
52 | #include "saa5246a.h" | ||
53 | 53 | ||
54 | MODULE_AUTHOR("Michael Geng <linux@MichaelGeng.de>"); | 54 | MODULE_AUTHOR("Michael Geng <linux@MichaelGeng.de>"); |
55 | MODULE_DESCRIPTION("Philips SAA5246A, SAA5281 Teletext decoder driver"); | 55 | MODULE_DESCRIPTION("Philips SAA5246A, SAA5281 Teletext decoder driver"); |
56 | MODULE_LICENSE("GPL"); | 56 | MODULE_LICENSE("GPL"); |
57 | 57 | ||
58 | struct saa5246a_device | 58 | #define MAJOR_VERSION 1 /* driver major version number */ |
59 | { | 59 | #define MINOR_VERSION 8 /* driver minor version number */ |
60 | u8 pgbuf[NUM_DAUS][VTX_VIRTUALSIZE]; | 60 | |
61 | int is_searching[NUM_DAUS]; | 61 | /* Number of DAUs = number of pages that can be searched at the same time. */ |
62 | struct i2c_client *client; | 62 | #define NUM_DAUS 4 |
63 | struct mutex lock; | 63 | |
64 | }; | 64 | #define NUM_ROWS_PER_PAGE 40 |
65 | |||
66 | /* first column is 0 (not 1) */ | ||
67 | #define POS_TIME_START 32 | ||
68 | #define POS_TIME_END 39 | ||
69 | |||
70 | #define POS_HEADER_START 7 | ||
71 | #define POS_HEADER_END 31 | ||
72 | |||
73 | /* Returns 'true' if the part of the videotext page described with req contains | ||
74 | (at least parts of) the time field */ | ||
75 | #define REQ_CONTAINS_TIME(p_req) \ | ||
76 | ((p_req)->start <= POS_TIME_END && \ | ||
77 | (p_req)->end >= POS_TIME_START) | ||
78 | |||
79 | /* Returns 'true' if the part of the videotext page described with req contains | ||
80 | (at least parts of) the page header */ | ||
81 | #define REQ_CONTAINS_HEADER(p_req) \ | ||
82 | ((p_req)->start <= POS_HEADER_END && \ | ||
83 | (p_req)->end >= POS_HEADER_START) | ||
84 | |||
85 | /*****************************************************************************/ | ||
86 | /* Mode register numbers of the SAA5246A */ | ||
87 | /*****************************************************************************/ | ||
88 | #define SAA5246A_REGISTER_R0 0 | ||
89 | #define SAA5246A_REGISTER_R1 1 | ||
90 | #define SAA5246A_REGISTER_R2 2 | ||
91 | #define SAA5246A_REGISTER_R3 3 | ||
92 | #define SAA5246A_REGISTER_R4 4 | ||
93 | #define SAA5246A_REGISTER_R5 5 | ||
94 | #define SAA5246A_REGISTER_R6 6 | ||
95 | #define SAA5246A_REGISTER_R7 7 | ||
96 | #define SAA5246A_REGISTER_R8 8 | ||
97 | #define SAA5246A_REGISTER_R9 9 | ||
98 | #define SAA5246A_REGISTER_R10 10 | ||
99 | #define SAA5246A_REGISTER_R11 11 | ||
100 | #define SAA5246A_REGISTER_R11B 11 | ||
101 | |||
102 | /* SAA5246A mode registers often autoincrement to the next register. | ||
103 | Therefore we use variable argument lists. The following macro indicates | ||
104 | the end of a command list. */ | ||
105 | #define COMMAND_END (-1) | ||
106 | |||
107 | /*****************************************************************************/ | ||
108 | /* Contents of the mode registers of the SAA5246A */ | ||
109 | /*****************************************************************************/ | ||
110 | /* Register R0 (Advanced Control) */ | ||
111 | #define R0_SELECT_R11 0x00 | ||
112 | #define R0_SELECT_R11B 0x01 | ||
113 | |||
114 | #define R0_PLL_TIME_CONSTANT_LONG 0x00 | ||
115 | #define R0_PLL_TIME_CONSTANT_SHORT 0x02 | ||
116 | |||
117 | #define R0_ENABLE_nODD_EVEN_OUTPUT 0x00 | ||
118 | #define R0_DISABLE_nODD_EVEN_OUTPUT 0x04 | ||
119 | |||
120 | #define R0_ENABLE_HDR_POLL 0x00 | ||
121 | #define R0_DISABLE_HDR_POLL 0x10 | ||
122 | |||
123 | #define R0_DO_NOT_FORCE_nODD_EVEN_LOW_IF_PICTURE_DISPLAYED 0x00 | ||
124 | #define R0_FORCE_nODD_EVEN_LOW_IF_PICTURE_DISPLAYED 0x20 | ||
125 | |||
126 | #define R0_NO_FREE_RUN_PLL 0x00 | ||
127 | #define R0_FREE_RUN_PLL 0x40 | ||
128 | |||
129 | #define R0_NO_AUTOMATIC_FASTEXT_PROMPT 0x00 | ||
130 | #define R0_AUTOMATIC_FASTEXT_PROMPT 0x80 | ||
131 | |||
132 | /* Register R1 (Mode) */ | ||
133 | #define R1_INTERLACED_312_AND_HALF_312_AND_HALF_LINES 0x00 | ||
134 | #define R1_NON_INTERLACED_312_313_LINES 0x01 | ||
135 | #define R1_NON_INTERLACED_312_312_LINES 0x02 | ||
136 | #define R1_FFB_LEADING_EDGE_IN_FIRST_BROAD_PULSE 0x03 | ||
137 | #define R1_FFB_LEADING_EDGE_IN_SECOND_BROAD_PULSE 0x07 | ||
138 | |||
139 | #define R1_DEW 0x00 | ||
140 | #define R1_FULL_FIELD 0x08 | ||
141 | |||
142 | #define R1_EXTENDED_PACKET_DISABLE 0x00 | ||
143 | #define R1_EXTENDED_PACKET_ENABLE 0x10 | ||
144 | |||
145 | #define R1_DAUS_ALL_ON 0x00 | ||
146 | #define R1_DAUS_ALL_OFF 0x20 | ||
147 | |||
148 | #define R1_7_BITS_PLUS_PARITY 0x00 | ||
149 | #define R1_8_BITS_NO_PARITY 0x40 | ||
150 | |||
151 | #define R1_VCS_TO_SCS 0x00 | ||
152 | #define R1_NO_VCS_TO_SCS 0x80 | ||
153 | |||
154 | /* Register R2 (Page request address) */ | ||
155 | #define R2_IN_R3_SELECT_PAGE_HUNDREDS 0x00 | ||
156 | #define R2_IN_R3_SELECT_PAGE_TENS 0x01 | ||
157 | #define R2_IN_R3_SELECT_PAGE_UNITS 0x02 | ||
158 | #define R2_IN_R3_SELECT_HOURS_TENS 0x03 | ||
159 | #define R2_IN_R3_SELECT_HOURS_UNITS 0x04 | ||
160 | #define R2_IN_R3_SELECT_MINUTES_TENS 0x05 | ||
161 | #define R2_IN_R3_SELECT_MINUTES_UNITS 0x06 | ||
162 | |||
163 | #define R2_DAU_0 0x00 | ||
164 | #define R2_DAU_1 0x10 | ||
165 | #define R2_DAU_2 0x20 | ||
166 | #define R2_DAU_3 0x30 | ||
167 | |||
168 | #define R2_BANK_0 0x00 | ||
169 | #define R2_BANK 1 0x40 | ||
170 | |||
171 | #define R2_HAMMING_CHECK_ON 0x80 | ||
172 | #define R2_HAMMING_CHECK_OFF 0x00 | ||
173 | |||
174 | /* Register R3 (Page request data) */ | ||
175 | #define R3_PAGE_HUNDREDS_0 0x00 | ||
176 | #define R3_PAGE_HUNDREDS_1 0x01 | ||
177 | #define R3_PAGE_HUNDREDS_2 0x02 | ||
178 | #define R3_PAGE_HUNDREDS_3 0x03 | ||
179 | #define R3_PAGE_HUNDREDS_4 0x04 | ||
180 | #define R3_PAGE_HUNDREDS_5 0x05 | ||
181 | #define R3_PAGE_HUNDREDS_6 0x06 | ||
182 | #define R3_PAGE_HUNDREDS_7 0x07 | ||
65 | 183 | ||
66 | static struct video_device saa_template; /* Declared near bottom */ | 184 | #define R3_HOLD_PAGE 0x00 |
185 | #define R3_UPDATE_PAGE 0x08 | ||
67 | 186 | ||
68 | /* Addresses to scan */ | 187 | #define R3_PAGE_HUNDREDS_DO_NOT_CARE 0x00 |
69 | static unsigned short normal_i2c[] = { I2C_ADDRESS, I2C_CLIENT_END }; | 188 | #define R3_PAGE_HUNDREDS_DO_CARE 0x10 |
70 | 189 | ||
71 | I2C_CLIENT_INSMOD; | 190 | #define R3_PAGE_TENS_DO_NOT_CARE 0x00 |
191 | #define R3_PAGE_TENS_DO_CARE 0x10 | ||
72 | 192 | ||
73 | static struct i2c_client client_template; | 193 | #define R3_PAGE_UNITS_DO_NOT_CARE 0x00 |
194 | #define R3_PAGE_UNITS_DO_CARE 0x10 | ||
74 | 195 | ||
75 | static int saa5246a_attach(struct i2c_adapter *adap, int addr, int kind) | 196 | #define R3_HOURS_TENS_DO_NOT_CARE 0x00 |
76 | { | 197 | #define R3_HOURS_TENS_DO_CARE 0x10 |
77 | int pgbuf; | ||
78 | int err; | ||
79 | struct i2c_client *client; | ||
80 | struct video_device *vd; | ||
81 | struct saa5246a_device *t; | ||
82 | 198 | ||
83 | printk(KERN_INFO "saa5246a: teletext chip found.\n"); | 199 | #define R3_HOURS_UNITS_DO_NOT_CARE 0x00 |
84 | client=kmalloc(sizeof(*client), GFP_KERNEL); | 200 | #define R3_HOURS_UNITS_DO_CARE 0x10 |
85 | if(client==NULL) | ||
86 | return -ENOMEM; | ||
87 | client_template.adapter = adap; | ||
88 | client_template.addr = addr; | ||
89 | memcpy(client, &client_template, sizeof(*client)); | ||
90 | t = kzalloc(sizeof(*t), GFP_KERNEL); | ||
91 | if(t==NULL) | ||
92 | { | ||
93 | kfree(client); | ||
94 | return -ENOMEM; | ||
95 | } | ||
96 | strlcpy(client->name, IF_NAME, I2C_NAME_SIZE); | ||
97 | mutex_init(&t->lock); | ||
98 | 201 | ||
99 | /* | 202 | #define R3_MINUTES_TENS_DO_NOT_CARE 0x00 |
100 | * Now create a video4linux device | 203 | #define R3_MINUTES_TENS_DO_CARE 0x10 |
101 | */ | ||
102 | 204 | ||
103 | vd = video_device_alloc(); | 205 | #define R3_MINUTES_UNITS_DO_NOT_CARE 0x00 |
104 | if(vd==NULL) | 206 | #define R3_MINUTES_UNITS_DO_CARE 0x10 |
105 | { | ||
106 | kfree(t); | ||
107 | kfree(client); | ||
108 | return -ENOMEM; | ||
109 | } | ||
110 | i2c_set_clientdata(client, vd); | ||
111 | memcpy(vd, &saa_template, sizeof(*vd)); | ||
112 | 207 | ||
113 | for (pgbuf = 0; pgbuf < NUM_DAUS; pgbuf++) | 208 | /* Register R4 (Display chapter) */ |
114 | { | 209 | #define R4_DISPLAY_PAGE_0 0x00 |
115 | memset(t->pgbuf[pgbuf], ' ', sizeof(t->pgbuf[0])); | 210 | #define R4_DISPLAY_PAGE_1 0x01 |
116 | t->is_searching[pgbuf] = false; | 211 | #define R4_DISPLAY_PAGE_2 0x02 |
117 | } | 212 | #define R4_DISPLAY_PAGE_3 0x03 |
118 | vd->priv=t; | 213 | #define R4_DISPLAY_PAGE_4 0x04 |
214 | #define R4_DISPLAY_PAGE_5 0x05 | ||
215 | #define R4_DISPLAY_PAGE_6 0x06 | ||
216 | #define R4_DISPLAY_PAGE_7 0x07 | ||
119 | 217 | ||
218 | /* Register R5 (Normal display control) */ | ||
219 | #define R5_PICTURE_INSIDE_BOXING_OFF 0x00 | ||
220 | #define R5_PICTURE_INSIDE_BOXING_ON 0x01 | ||
120 | 221 | ||
121 | /* | 222 | #define R5_PICTURE_OUTSIDE_BOXING_OFF 0x00 |
122 | * Register it | 223 | #define R5_PICTURE_OUTSIDE_BOXING_ON 0x02 |
123 | */ | ||
124 | 224 | ||
125 | if((err=video_register_device(vd, VFL_TYPE_VTX,-1))<0) | 225 | #define R5_TEXT_INSIDE_BOXING_OFF 0x00 |
126 | { | 226 | #define R5_TEXT_INSIDE_BOXING_ON 0x04 |
127 | kfree(t); | ||
128 | kfree(client); | ||
129 | video_device_release(vd); | ||
130 | return err; | ||
131 | } | ||
132 | t->client = client; | ||
133 | i2c_attach_client(client); | ||
134 | return 0; | ||
135 | } | ||
136 | 227 | ||
137 | /* | 228 | #define R5_TEXT_OUTSIDE_BOXING_OFF 0x00 |
138 | * We do most of the hard work when we become a device on the i2c. | 229 | #define R5_TEXT_OUTSIDE_BOXING_ON 0x08 |
139 | */ | ||
140 | static int saa5246a_probe(struct i2c_adapter *adap) | ||
141 | { | ||
142 | if (adap->class & I2C_CLASS_TV_ANALOG) | ||
143 | return i2c_probe(adap, &addr_data, saa5246a_attach); | ||
144 | return 0; | ||
145 | } | ||
146 | 230 | ||
147 | static int saa5246a_detach(struct i2c_client *client) | 231 | #define R5_CONTRAST_REDUCTION_INSIDE_BOXING_OFF 0x00 |
148 | { | 232 | #define R5_CONTRAST_REDUCTION_INSIDE_BOXING_ON 0x10 |
149 | struct video_device *vd = i2c_get_clientdata(client); | ||
150 | i2c_detach_client(client); | ||
151 | video_unregister_device(vd); | ||
152 | kfree(vd->priv); | ||
153 | kfree(client); | ||
154 | return 0; | ||
155 | } | ||
156 | 233 | ||
157 | /* | 234 | #define R5_CONTRAST_REDUCTION_OUTSIDE_BOXING_OFF 0x00 |
158 | * I2C interfaces | 235 | #define R5_CONTRAST_REDUCTION_OUTSIDE_BOXING_ON 0x20 |
159 | */ | 236 | |
237 | #define R5_BACKGROUND_COLOR_INSIDE_BOXING_OFF 0x00 | ||
238 | #define R5_BACKGROUND_COLOR_INSIDE_BOXING_ON 0x40 | ||
239 | |||
240 | #define R5_BACKGROUND_COLOR_OUTSIDE_BOXING_OFF 0x00 | ||
241 | #define R5_BACKGROUND_COLOR_OUTSIDE_BOXING_ON 0x80 | ||
242 | |||
243 | /* Register R6 (Newsflash display) */ | ||
244 | #define R6_NEWSFLASH_PICTURE_INSIDE_BOXING_OFF 0x00 | ||
245 | #define R6_NEWSFLASH_PICTURE_INSIDE_BOXING_ON 0x01 | ||
246 | |||
247 | #define R6_NEWSFLASH_PICTURE_OUTSIDE_BOXING_OFF 0x00 | ||
248 | #define R6_NEWSFLASH_PICTURE_OUTSIDE_BOXING_ON 0x02 | ||
249 | |||
250 | #define R6_NEWSFLASH_TEXT_INSIDE_BOXING_OFF 0x00 | ||
251 | #define R6_NEWSFLASH_TEXT_INSIDE_BOXING_ON 0x04 | ||
252 | |||
253 | #define R6_NEWSFLASH_TEXT_OUTSIDE_BOXING_OFF 0x00 | ||
254 | #define R6_NEWSFLASH_TEXT_OUTSIDE_BOXING_ON 0x08 | ||
255 | |||
256 | #define R6_NEWSFLASH_CONTRAST_REDUCTION_INSIDE_BOXING_OFF 0x00 | ||
257 | #define R6_NEWSFLASH_CONTRAST_REDUCTION_INSIDE_BOXING_ON 0x10 | ||
258 | |||
259 | #define R6_NEWSFLASH_CONTRAST_REDUCTION_OUTSIDE_BOXING_OFF 0x00 | ||
260 | #define R6_NEWSFLASH_CONTRAST_REDUCTION_OUTSIDE_BOXING_ON 0x20 | ||
261 | |||
262 | #define R6_NEWSFLASH_BACKGROUND_COLOR_INSIDE_BOXING_OFF 0x00 | ||
263 | #define R6_NEWSFLASH_BACKGROUND_COLOR_INSIDE_BOXING_ON 0x40 | ||
264 | |||
265 | #define R6_NEWSFLASH_BACKGROUND_COLOR_OUTSIDE_BOXING_OFF 0x00 | ||
266 | #define R6_NEWSFLASH_BACKGROUND_COLOR_OUTSIDE_BOXING_ON 0x80 | ||
267 | |||
268 | /* Register R7 (Display mode) */ | ||
269 | #define R7_BOX_OFF_ROW_0 0x00 | ||
270 | #define R7_BOX_ON_ROW_0 0x01 | ||
271 | |||
272 | #define R7_BOX_OFF_ROW_1_TO_23 0x00 | ||
273 | #define R7_BOX_ON_ROW_1_TO_23 0x02 | ||
274 | |||
275 | #define R7_BOX_OFF_ROW_24 0x00 | ||
276 | #define R7_BOX_ON_ROW_24 0x04 | ||
277 | |||
278 | #define R7_SINGLE_HEIGHT 0x00 | ||
279 | #define R7_DOUBLE_HEIGHT 0x08 | ||
280 | |||
281 | #define R7_TOP_HALF 0x00 | ||
282 | #define R7_BOTTOM_HALF 0x10 | ||
283 | |||
284 | #define R7_REVEAL_OFF 0x00 | ||
285 | #define R7_REVEAL_ON 0x20 | ||
286 | |||
287 | #define R7_CURSER_OFF 0x00 | ||
288 | #define R7_CURSER_ON 0x40 | ||
289 | |||
290 | #define R7_STATUS_BOTTOM 0x00 | ||
291 | #define R7_STATUS_TOP 0x80 | ||
292 | |||
293 | /* Register R8 (Active chapter) */ | ||
294 | #define R8_ACTIVE_CHAPTER_0 0x00 | ||
295 | #define R8_ACTIVE_CHAPTER_1 0x01 | ||
296 | #define R8_ACTIVE_CHAPTER_2 0x02 | ||
297 | #define R8_ACTIVE_CHAPTER_3 0x03 | ||
298 | #define R8_ACTIVE_CHAPTER_4 0x04 | ||
299 | #define R8_ACTIVE_CHAPTER_5 0x05 | ||
300 | #define R8_ACTIVE_CHAPTER_6 0x06 | ||
301 | #define R8_ACTIVE_CHAPTER_7 0x07 | ||
302 | |||
303 | #define R8_CLEAR_MEMORY 0x08 | ||
304 | #define R8_DO_NOT_CLEAR_MEMORY 0x00 | ||
305 | |||
306 | /* Register R9 (Curser row) */ | ||
307 | #define R9_CURSER_ROW_0 0x00 | ||
308 | #define R9_CURSER_ROW_1 0x01 | ||
309 | #define R9_CURSER_ROW_2 0x02 | ||
310 | #define R9_CURSER_ROW_25 0x19 | ||
311 | |||
312 | /* Register R10 (Curser column) */ | ||
313 | #define R10_CURSER_COLUMN_0 0x00 | ||
314 | #define R10_CURSER_COLUMN_6 0x06 | ||
315 | #define R10_CURSER_COLUMN_8 0x08 | ||
316 | |||
317 | /*****************************************************************************/ | ||
318 | /* Row 25 control data in column 0 to 9 */ | ||
319 | /*****************************************************************************/ | ||
320 | #define ROW25_COLUMN0_PAGE_UNITS 0x0F | ||
321 | |||
322 | #define ROW25_COLUMN1_PAGE_TENS 0x0F | ||
323 | |||
324 | #define ROW25_COLUMN2_MINUTES_UNITS 0x0F | ||
160 | 325 | ||
161 | static struct i2c_driver i2c_driver_videotext = | 326 | #define ROW25_COLUMN3_MINUTES_TENS 0x07 |
327 | #define ROW25_COLUMN3_DELETE_PAGE 0x08 | ||
328 | |||
329 | #define ROW25_COLUMN4_HOUR_UNITS 0x0F | ||
330 | |||
331 | #define ROW25_COLUMN5_HOUR_TENS 0x03 | ||
332 | #define ROW25_COLUMN5_INSERT_HEADLINE 0x04 | ||
333 | #define ROW25_COLUMN5_INSERT_SUBTITLE 0x08 | ||
334 | |||
335 | #define ROW25_COLUMN6_SUPPRESS_HEADER 0x01 | ||
336 | #define ROW25_COLUMN6_UPDATE_PAGE 0x02 | ||
337 | #define ROW25_COLUMN6_INTERRUPTED_SEQUENCE 0x04 | ||
338 | #define ROW25_COLUMN6_SUPPRESS_DISPLAY 0x08 | ||
339 | |||
340 | #define ROW25_COLUMN7_SERIAL_MODE 0x01 | ||
341 | #define ROW25_COLUMN7_CHARACTER_SET 0x0E | ||
342 | |||
343 | #define ROW25_COLUMN8_PAGE_HUNDREDS 0x07 | ||
344 | #define ROW25_COLUMN8_PAGE_NOT_FOUND 0x10 | ||
345 | |||
346 | #define ROW25_COLUMN9_PAGE_BEING_LOOKED_FOR 0x20 | ||
347 | |||
348 | #define ROW25_COLUMN0_TO_7_HAMMING_ERROR 0x10 | ||
349 | |||
350 | /*****************************************************************************/ | ||
351 | /* Helper macros for extracting page, hour and minute digits */ | ||
352 | /*****************************************************************************/ | ||
353 | /* BYTE_POS 0 is at row 0, column 0, | ||
354 | BYTE_POS 1 is at row 0, column 1, | ||
355 | BYTE_POS 40 is at row 1, column 0, (with NUM_ROWS_PER_PAGE = 40) | ||
356 | BYTE_POS 41 is at row 1, column 1, (with NUM_ROWS_PER_PAGE = 40), | ||
357 | ... */ | ||
358 | #define ROW(BYTE_POS) (BYTE_POS / NUM_ROWS_PER_PAGE) | ||
359 | #define COLUMN(BYTE_POS) (BYTE_POS % NUM_ROWS_PER_PAGE) | ||
360 | |||
361 | /*****************************************************************************/ | ||
362 | /* Helper macros for extracting page, hour and minute digits */ | ||
363 | /*****************************************************************************/ | ||
364 | /* Macros for extracting hundreds, tens and units of a page number which | ||
365 | must be in the range 0 ... 0x799. | ||
366 | Note that page is coded in hexadecimal, i.e. 0x123 means page 123. | ||
367 | page 0x.. means page 8.. */ | ||
368 | #define HUNDREDS_OF_PAGE(page) (((page) / 0x100) & 0x7) | ||
369 | #define TENS_OF_PAGE(page) (((page) / 0x10) & 0xF) | ||
370 | #define UNITS_OF_PAGE(page) ((page) & 0xF) | ||
371 | |||
372 | /* Macros for extracting tens and units of a hour information which | ||
373 | must be in the range 0 ... 0x24. | ||
374 | Note that hour is coded in hexadecimal, i.e. 0x12 means 12 hours */ | ||
375 | #define TENS_OF_HOUR(hour) ((hour) / 0x10) | ||
376 | #define UNITS_OF_HOUR(hour) ((hour) & 0xF) | ||
377 | |||
378 | /* Macros for extracting tens and units of a minute information which | ||
379 | must be in the range 0 ... 0x59. | ||
380 | Note that minute is coded in hexadecimal, i.e. 0x12 means 12 minutes */ | ||
381 | #define TENS_OF_MINUTE(minute) ((minute) / 0x10) | ||
382 | #define UNITS_OF_MINUTE(minute) ((minute) & 0xF) | ||
383 | |||
384 | #define HOUR_MAX 0x23 | ||
385 | #define MINUTE_MAX 0x59 | ||
386 | #define PAGE_MAX 0x8FF | ||
387 | |||
388 | |||
389 | struct saa5246a_device | ||
162 | { | 390 | { |
163 | .driver = { | 391 | u8 pgbuf[NUM_DAUS][VTX_VIRTUALSIZE]; |
164 | .name = IF_NAME, /* name */ | 392 | int is_searching[NUM_DAUS]; |
165 | }, | 393 | struct i2c_client *client; |
166 | .id = I2C_DRIVERID_SAA5249, /* in i2c.h */ | 394 | unsigned long in_use; |
167 | .attach_adapter = saa5246a_probe, | 395 | struct mutex lock; |
168 | .detach_client = saa5246a_detach, | ||
169 | }; | 396 | }; |
170 | 397 | ||
171 | static struct i2c_client client_template = { | 398 | static struct video_device saa_template; /* Declared near bottom */ |
172 | .driver = &i2c_driver_videotext, | 399 | |
173 | .name = "(unset)", | 400 | /* |
174 | }; | 401 | * I2C interfaces |
402 | */ | ||
175 | 403 | ||
176 | static int i2c_sendbuf(struct saa5246a_device *t, int reg, int count, u8 *data) | 404 | static int i2c_sendbuf(struct saa5246a_device *t, int reg, int count, u8 *data) |
177 | { | 405 | { |
@@ -579,8 +807,8 @@ static inline int saa5246a_stop_dau(struct saa5246a_device *t, | |||
579 | static int do_saa5246a_ioctl(struct inode *inode, struct file *file, | 807 | static int do_saa5246a_ioctl(struct inode *inode, struct file *file, |
580 | unsigned int cmd, void *arg) | 808 | unsigned int cmd, void *arg) |
581 | { | 809 | { |
582 | struct video_device *vd = video_devdata(file); | 810 | struct saa5246a_device *t = video_drvdata(file); |
583 | struct saa5246a_device *t=vd->priv; | 811 | |
584 | switch(cmd) | 812 | switch(cmd) |
585 | { | 813 | { |
586 | case VTXIOCGETINFO: | 814 | case VTXIOCGETINFO: |
@@ -720,8 +948,7 @@ static inline unsigned int vtx_fix_command(unsigned int cmd) | |||
720 | static int saa5246a_ioctl(struct inode *inode, struct file *file, | 948 | static int saa5246a_ioctl(struct inode *inode, struct file *file, |
721 | unsigned int cmd, unsigned long arg) | 949 | unsigned int cmd, unsigned long arg) |
722 | { | 950 | { |
723 | struct video_device *vd = video_devdata(file); | 951 | struct saa5246a_device *t = video_drvdata(file); |
724 | struct saa5246a_device *t = vd->priv; | ||
725 | int err; | 952 | int err; |
726 | 953 | ||
727 | cmd = vtx_fix_command(cmd); | 954 | cmd = vtx_fix_command(cmd); |
@@ -733,21 +960,15 @@ static int saa5246a_ioctl(struct inode *inode, struct file *file, | |||
733 | 960 | ||
734 | static int saa5246a_open(struct inode *inode, struct file *file) | 961 | static int saa5246a_open(struct inode *inode, struct file *file) |
735 | { | 962 | { |
736 | struct video_device *vd = video_devdata(file); | 963 | struct saa5246a_device *t = video_drvdata(file); |
737 | struct saa5246a_device *t = vd->priv; | ||
738 | int err; | ||
739 | 964 | ||
740 | err = video_exclusive_open(inode,file); | 965 | if (t->client == NULL) |
741 | if (err < 0) | 966 | return -ENODEV; |
742 | return err; | ||
743 | 967 | ||
744 | if (t->client==NULL) { | 968 | if (test_and_set_bit(0, &t->in_use)) |
745 | err = -ENODEV; | 969 | return -EBUSY; |
746 | goto fail; | ||
747 | } | ||
748 | 970 | ||
749 | if (i2c_senddata(t, SAA5246A_REGISTER_R0, | 971 | if (i2c_senddata(t, SAA5246A_REGISTER_R0, |
750 | |||
751 | R0_SELECT_R11 | | 972 | R0_SELECT_R11 | |
752 | R0_PLL_TIME_CONSTANT_LONG | | 973 | R0_PLL_TIME_CONSTANT_LONG | |
753 | R0_ENABLE_nODD_EVEN_OUTPUT | | 974 | R0_ENABLE_nODD_EVEN_OUTPUT | |
@@ -773,21 +994,15 @@ static int saa5246a_open(struct inode *inode, struct file *file) | |||
773 | 994 | ||
774 | COMMAND_END)) | 995 | COMMAND_END)) |
775 | { | 996 | { |
776 | err = -EIO; | 997 | clear_bit(0, &t->in_use); |
777 | goto fail; | 998 | return -EIO; |
778 | } | 999 | } |
779 | |||
780 | return 0; | 1000 | return 0; |
781 | |||
782 | fail: | ||
783 | video_exclusive_release(inode,file); | ||
784 | return err; | ||
785 | } | 1001 | } |
786 | 1002 | ||
787 | static int saa5246a_release(struct inode *inode, struct file *file) | 1003 | static int saa5246a_release(struct inode *inode, struct file *file) |
788 | { | 1004 | { |
789 | struct video_device *vd = video_devdata(file); | 1005 | struct saa5246a_device *t = video_drvdata(file); |
790 | struct saa5246a_device *t = vd->priv; | ||
791 | 1006 | ||
792 | /* Stop all acquisition circuits. */ | 1007 | /* Stop all acquisition circuits. */ |
793 | i2c_senddata(t, SAA5246A_REGISTER_R1, | 1008 | i2c_senddata(t, SAA5246A_REGISTER_R1, |
@@ -800,26 +1015,10 @@ static int saa5246a_release(struct inode *inode, struct file *file) | |||
800 | R1_VCS_TO_SCS, | 1015 | R1_VCS_TO_SCS, |
801 | 1016 | ||
802 | COMMAND_END); | 1017 | COMMAND_END); |
803 | video_exclusive_release(inode,file); | 1018 | clear_bit(0, &t->in_use); |
804 | return 0; | 1019 | return 0; |
805 | } | 1020 | } |
806 | 1021 | ||
807 | static int __init init_saa_5246a (void) | ||
808 | { | ||
809 | printk(KERN_INFO | ||
810 | "SAA5246A (or compatible) Teletext decoder driver version %d.%d\n", | ||
811 | MAJOR_VERSION, MINOR_VERSION); | ||
812 | return i2c_add_driver(&i2c_driver_videotext); | ||
813 | } | ||
814 | |||
815 | static void __exit cleanup_saa_5246a (void) | ||
816 | { | ||
817 | i2c_del_driver(&i2c_driver_videotext); | ||
818 | } | ||
819 | |||
820 | module_init(init_saa_5246a); | ||
821 | module_exit(cleanup_saa_5246a); | ||
822 | |||
823 | static const struct file_operations saa_fops = { | 1022 | static const struct file_operations saa_fops = { |
824 | .owner = THIS_MODULE, | 1023 | .owner = THIS_MODULE, |
825 | .open = saa5246a_open, | 1024 | .open = saa5246a_open, |
@@ -830,8 +1029,79 @@ static const struct file_operations saa_fops = { | |||
830 | 1029 | ||
831 | static struct video_device saa_template = | 1030 | static struct video_device saa_template = |
832 | { | 1031 | { |
833 | .name = IF_NAME, | 1032 | .name = "saa5246a", |
834 | .fops = &saa_fops, | 1033 | .fops = &saa_fops, |
835 | .release = video_device_release, | 1034 | .release = video_device_release, |
836 | .minor = -1, | 1035 | .minor = -1, |
837 | }; | 1036 | }; |
1037 | |||
1038 | /* Addresses to scan */ | ||
1039 | static unsigned short normal_i2c[] = { 0x22 >> 1, I2C_CLIENT_END }; | ||
1040 | |||
1041 | I2C_CLIENT_INSMOD; | ||
1042 | |||
1043 | static int saa5246a_probe(struct i2c_client *client, | ||
1044 | const struct i2c_device_id *id) | ||
1045 | { | ||
1046 | int pgbuf; | ||
1047 | int err; | ||
1048 | struct video_device *vd; | ||
1049 | struct saa5246a_device *t; | ||
1050 | |||
1051 | v4l_info(client, "chip found @ 0x%x (%s)\n", | ||
1052 | client->addr << 1, client->adapter->name); | ||
1053 | v4l_info(client, "VideoText version %d.%d\n", | ||
1054 | MAJOR_VERSION, MINOR_VERSION); | ||
1055 | t = kzalloc(sizeof(*t), GFP_KERNEL); | ||
1056 | if (t == NULL) | ||
1057 | return -ENOMEM; | ||
1058 | mutex_init(&t->lock); | ||
1059 | |||
1060 | /* Now create a video4linux device */ | ||
1061 | vd = video_device_alloc(); | ||
1062 | if (vd == NULL) { | ||
1063 | kfree(t); | ||
1064 | return -ENOMEM; | ||
1065 | } | ||
1066 | i2c_set_clientdata(client, vd); | ||
1067 | memcpy(vd, &saa_template, sizeof(*vd)); | ||
1068 | |||
1069 | for (pgbuf = 0; pgbuf < NUM_DAUS; pgbuf++) { | ||
1070 | memset(t->pgbuf[pgbuf], ' ', sizeof(t->pgbuf[0])); | ||
1071 | t->is_searching[pgbuf] = false; | ||
1072 | } | ||
1073 | video_set_drvdata(vd, t); | ||
1074 | |||
1075 | /* Register it */ | ||
1076 | err = video_register_device(vd, VFL_TYPE_VTX, -1); | ||
1077 | if (err < 0) { | ||
1078 | kfree(t); | ||
1079 | video_device_release(vd); | ||
1080 | return err; | ||
1081 | } | ||
1082 | t->client = client; | ||
1083 | return 0; | ||
1084 | } | ||
1085 | |||
1086 | static int saa5246a_remove(struct i2c_client *client) | ||
1087 | { | ||
1088 | struct video_device *vd = i2c_get_clientdata(client); | ||
1089 | |||
1090 | video_unregister_device(vd); | ||
1091 | kfree(video_get_drvdata(vd)); | ||
1092 | return 0; | ||
1093 | } | ||
1094 | |||
1095 | static const struct i2c_device_id saa5246a_id[] = { | ||
1096 | { "saa5246a", 0 }, | ||
1097 | { } | ||
1098 | }; | ||
1099 | MODULE_DEVICE_TABLE(i2c, saa5246a_id); | ||
1100 | |||
1101 | static struct v4l2_i2c_driver_data v4l2_i2c_data = { | ||
1102 | .name = "saa5246a", | ||
1103 | .driverid = I2C_DRIVERID_SAA5249, | ||
1104 | .probe = saa5246a_probe, | ||
1105 | .remove = saa5246a_remove, | ||
1106 | .id_table = saa5246a_id, | ||
1107 | }; | ||
diff --git a/drivers/media/video/saa5246a.h b/drivers/media/video/saa5246a.h deleted file mode 100644 index 64394c036c60..000000000000 --- a/drivers/media/video/saa5246a.h +++ /dev/null | |||
@@ -1,359 +0,0 @@ | |||
1 | /* | ||
2 | Driver for the SAA5246A or SAA5281 Teletext (=Videotext) decoder chips from | ||
3 | Philips. | ||
4 | |||
5 | Copyright (C) 2004 Michael Geng (linux@MichaelGeng.de) | ||
6 | |||
7 | This program is free software; you can redistribute it and/or modify | ||
8 | it under the terms of the GNU General Public License as published by | ||
9 | the Free Software Foundation; either version 2 of the License, or | ||
10 | (at your option) any later version. | ||
11 | |||
12 | This program is distributed in the hope that it will be useful, | ||
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | GNU General Public License for more details. | ||
16 | |||
17 | You should have received a copy of the GNU General Public License | ||
18 | along with this program; if not, write to the Free Software | ||
19 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
20 | |||
21 | */ | ||
22 | #ifndef __SAA5246A_H__ | ||
23 | #define __SAA5246A_H__ | ||
24 | |||
25 | #define MAJOR_VERSION 1 /* driver major version number */ | ||
26 | #define MINOR_VERSION 8 /* driver minor version number */ | ||
27 | |||
28 | #define IF_NAME "SAA5246A" | ||
29 | |||
30 | #define I2C_ADDRESS 17 | ||
31 | |||
32 | /* Number of DAUs = number of pages that can be searched at the same time. */ | ||
33 | #define NUM_DAUS 4 | ||
34 | |||
35 | #define NUM_ROWS_PER_PAGE 40 | ||
36 | |||
37 | /* first column is 0 (not 1) */ | ||
38 | #define POS_TIME_START 32 | ||
39 | #define POS_TIME_END 39 | ||
40 | |||
41 | #define POS_HEADER_START 7 | ||
42 | #define POS_HEADER_END 31 | ||
43 | |||
44 | /* Returns 'true' if the part of the videotext page described with req contains | ||
45 | (at least parts of) the time field */ | ||
46 | #define REQ_CONTAINS_TIME(p_req) \ | ||
47 | ((p_req)->start <= POS_TIME_END && \ | ||
48 | (p_req)->end >= POS_TIME_START) | ||
49 | |||
50 | /* Returns 'true' if the part of the videotext page described with req contains | ||
51 | (at least parts of) the page header */ | ||
52 | #define REQ_CONTAINS_HEADER(p_req) \ | ||
53 | ((p_req)->start <= POS_HEADER_END && \ | ||
54 | (p_req)->end >= POS_HEADER_START) | ||
55 | |||
56 | /*****************************************************************************/ | ||
57 | /* Mode register numbers of the SAA5246A */ | ||
58 | /*****************************************************************************/ | ||
59 | #define SAA5246A_REGISTER_R0 0 | ||
60 | #define SAA5246A_REGISTER_R1 1 | ||
61 | #define SAA5246A_REGISTER_R2 2 | ||
62 | #define SAA5246A_REGISTER_R3 3 | ||
63 | #define SAA5246A_REGISTER_R4 4 | ||
64 | #define SAA5246A_REGISTER_R5 5 | ||
65 | #define SAA5246A_REGISTER_R6 6 | ||
66 | #define SAA5246A_REGISTER_R7 7 | ||
67 | #define SAA5246A_REGISTER_R8 8 | ||
68 | #define SAA5246A_REGISTER_R9 9 | ||
69 | #define SAA5246A_REGISTER_R10 10 | ||
70 | #define SAA5246A_REGISTER_R11 11 | ||
71 | #define SAA5246A_REGISTER_R11B 11 | ||
72 | |||
73 | /* SAA5246A mode registers often autoincrement to the next register. | ||
74 | Therefore we use variable argument lists. The following macro indicates | ||
75 | the end of a command list. */ | ||
76 | #define COMMAND_END (- 1) | ||
77 | |||
78 | /*****************************************************************************/ | ||
79 | /* Contents of the mode registers of the SAA5246A */ | ||
80 | /*****************************************************************************/ | ||
81 | /* Register R0 (Advanced Control) */ | ||
82 | #define R0_SELECT_R11 0x00 | ||
83 | #define R0_SELECT_R11B 0x01 | ||
84 | |||
85 | #define R0_PLL_TIME_CONSTANT_LONG 0x00 | ||
86 | #define R0_PLL_TIME_CONSTANT_SHORT 0x02 | ||
87 | |||
88 | #define R0_ENABLE_nODD_EVEN_OUTPUT 0x00 | ||
89 | #define R0_DISABLE_nODD_EVEN_OUTPUT 0x04 | ||
90 | |||
91 | #define R0_ENABLE_HDR_POLL 0x00 | ||
92 | #define R0_DISABLE_HDR_POLL 0x10 | ||
93 | |||
94 | #define R0_DO_NOT_FORCE_nODD_EVEN_LOW_IF_PICTURE_DISPLAYED 0x00 | ||
95 | #define R0_FORCE_nODD_EVEN_LOW_IF_PICTURE_DISPLAYED 0x20 | ||
96 | |||
97 | #define R0_NO_FREE_RUN_PLL 0x00 | ||
98 | #define R0_FREE_RUN_PLL 0x40 | ||
99 | |||
100 | #define R0_NO_AUTOMATIC_FASTEXT_PROMPT 0x00 | ||
101 | #define R0_AUTOMATIC_FASTEXT_PROMPT 0x80 | ||
102 | |||
103 | /* Register R1 (Mode) */ | ||
104 | #define R1_INTERLACED_312_AND_HALF_312_AND_HALF_LINES 0x00 | ||
105 | #define R1_NON_INTERLACED_312_313_LINES 0x01 | ||
106 | #define R1_NON_INTERLACED_312_312_LINES 0x02 | ||
107 | #define R1_FFB_LEADING_EDGE_IN_FIRST_BROAD_PULSE 0x03 | ||
108 | #define R1_FFB_LEADING_EDGE_IN_SECOND_BROAD_PULSE 0x07 | ||
109 | |||
110 | #define R1_DEW 0x00 | ||
111 | #define R1_FULL_FIELD 0x08 | ||
112 | |||
113 | #define R1_EXTENDED_PACKET_DISABLE 0x00 | ||
114 | #define R1_EXTENDED_PACKET_ENABLE 0x10 | ||
115 | |||
116 | #define R1_DAUS_ALL_ON 0x00 | ||
117 | #define R1_DAUS_ALL_OFF 0x20 | ||
118 | |||
119 | #define R1_7_BITS_PLUS_PARITY 0x00 | ||
120 | #define R1_8_BITS_NO_PARITY 0x40 | ||
121 | |||
122 | #define R1_VCS_TO_SCS 0x00 | ||
123 | #define R1_NO_VCS_TO_SCS 0x80 | ||
124 | |||
125 | /* Register R2 (Page request address) */ | ||
126 | #define R2_IN_R3_SELECT_PAGE_HUNDREDS 0x00 | ||
127 | #define R2_IN_R3_SELECT_PAGE_TENS 0x01 | ||
128 | #define R2_IN_R3_SELECT_PAGE_UNITS 0x02 | ||
129 | #define R2_IN_R3_SELECT_HOURS_TENS 0x03 | ||
130 | #define R2_IN_R3_SELECT_HOURS_UNITS 0x04 | ||
131 | #define R2_IN_R3_SELECT_MINUTES_TENS 0x05 | ||
132 | #define R2_IN_R3_SELECT_MINUTES_UNITS 0x06 | ||
133 | |||
134 | #define R2_DAU_0 0x00 | ||
135 | #define R2_DAU_1 0x10 | ||
136 | #define R2_DAU_2 0x20 | ||
137 | #define R2_DAU_3 0x30 | ||
138 | |||
139 | #define R2_BANK_0 0x00 | ||
140 | #define R2_BANK 1 0x40 | ||
141 | |||
142 | #define R2_HAMMING_CHECK_ON 0x80 | ||
143 | #define R2_HAMMING_CHECK_OFF 0x00 | ||
144 | |||
145 | /* Register R3 (Page request data) */ | ||
146 | #define R3_PAGE_HUNDREDS_0 0x00 | ||
147 | #define R3_PAGE_HUNDREDS_1 0x01 | ||
148 | #define R3_PAGE_HUNDREDS_2 0x02 | ||
149 | #define R3_PAGE_HUNDREDS_3 0x03 | ||
150 | #define R3_PAGE_HUNDREDS_4 0x04 | ||
151 | #define R3_PAGE_HUNDREDS_5 0x05 | ||
152 | #define R3_PAGE_HUNDREDS_6 0x06 | ||
153 | #define R3_PAGE_HUNDREDS_7 0x07 | ||
154 | |||
155 | #define R3_HOLD_PAGE 0x00 | ||
156 | #define R3_UPDATE_PAGE 0x08 | ||
157 | |||
158 | #define R3_PAGE_HUNDREDS_DO_NOT_CARE 0x00 | ||
159 | #define R3_PAGE_HUNDREDS_DO_CARE 0x10 | ||
160 | |||
161 | #define R3_PAGE_TENS_DO_NOT_CARE 0x00 | ||
162 | #define R3_PAGE_TENS_DO_CARE 0x10 | ||
163 | |||
164 | #define R3_PAGE_UNITS_DO_NOT_CARE 0x00 | ||
165 | #define R3_PAGE_UNITS_DO_CARE 0x10 | ||
166 | |||
167 | #define R3_HOURS_TENS_DO_NOT_CARE 0x00 | ||
168 | #define R3_HOURS_TENS_DO_CARE 0x10 | ||
169 | |||
170 | #define R3_HOURS_UNITS_DO_NOT_CARE 0x00 | ||
171 | #define R3_HOURS_UNITS_DO_CARE 0x10 | ||
172 | |||
173 | #define R3_MINUTES_TENS_DO_NOT_CARE 0x00 | ||
174 | #define R3_MINUTES_TENS_DO_CARE 0x10 | ||
175 | |||
176 | #define R3_MINUTES_UNITS_DO_NOT_CARE 0x00 | ||
177 | #define R3_MINUTES_UNITS_DO_CARE 0x10 | ||
178 | |||
179 | /* Register R4 (Display chapter) */ | ||
180 | #define R4_DISPLAY_PAGE_0 0x00 | ||
181 | #define R4_DISPLAY_PAGE_1 0x01 | ||
182 | #define R4_DISPLAY_PAGE_2 0x02 | ||
183 | #define R4_DISPLAY_PAGE_3 0x03 | ||
184 | #define R4_DISPLAY_PAGE_4 0x04 | ||
185 | #define R4_DISPLAY_PAGE_5 0x05 | ||
186 | #define R4_DISPLAY_PAGE_6 0x06 | ||
187 | #define R4_DISPLAY_PAGE_7 0x07 | ||
188 | |||
189 | /* Register R5 (Normal display control) */ | ||
190 | #define R5_PICTURE_INSIDE_BOXING_OFF 0x00 | ||
191 | #define R5_PICTURE_INSIDE_BOXING_ON 0x01 | ||
192 | |||
193 | #define R5_PICTURE_OUTSIDE_BOXING_OFF 0x00 | ||
194 | #define R5_PICTURE_OUTSIDE_BOXING_ON 0x02 | ||
195 | |||
196 | #define R5_TEXT_INSIDE_BOXING_OFF 0x00 | ||
197 | #define R5_TEXT_INSIDE_BOXING_ON 0x04 | ||
198 | |||
199 | #define R5_TEXT_OUTSIDE_BOXING_OFF 0x00 | ||
200 | #define R5_TEXT_OUTSIDE_BOXING_ON 0x08 | ||
201 | |||
202 | #define R5_CONTRAST_REDUCTION_INSIDE_BOXING_OFF 0x00 | ||
203 | #define R5_CONTRAST_REDUCTION_INSIDE_BOXING_ON 0x10 | ||
204 | |||
205 | #define R5_CONTRAST_REDUCTION_OUTSIDE_BOXING_OFF 0x00 | ||
206 | #define R5_CONTRAST_REDUCTION_OUTSIDE_BOXING_ON 0x20 | ||
207 | |||
208 | #define R5_BACKGROUND_COLOR_INSIDE_BOXING_OFF 0x00 | ||
209 | #define R5_BACKGROUND_COLOR_INSIDE_BOXING_ON 0x40 | ||
210 | |||
211 | #define R5_BACKGROUND_COLOR_OUTSIDE_BOXING_OFF 0x00 | ||
212 | #define R5_BACKGROUND_COLOR_OUTSIDE_BOXING_ON 0x80 | ||
213 | |||
214 | /* Register R6 (Newsflash display) */ | ||
215 | #define R6_NEWSFLASH_PICTURE_INSIDE_BOXING_OFF 0x00 | ||
216 | #define R6_NEWSFLASH_PICTURE_INSIDE_BOXING_ON 0x01 | ||
217 | |||
218 | #define R6_NEWSFLASH_PICTURE_OUTSIDE_BOXING_OFF 0x00 | ||
219 | #define R6_NEWSFLASH_PICTURE_OUTSIDE_BOXING_ON 0x02 | ||
220 | |||
221 | #define R6_NEWSFLASH_TEXT_INSIDE_BOXING_OFF 0x00 | ||
222 | #define R6_NEWSFLASH_TEXT_INSIDE_BOXING_ON 0x04 | ||
223 | |||
224 | #define R6_NEWSFLASH_TEXT_OUTSIDE_BOXING_OFF 0x00 | ||
225 | #define R6_NEWSFLASH_TEXT_OUTSIDE_BOXING_ON 0x08 | ||
226 | |||
227 | #define R6_NEWSFLASH_CONTRAST_REDUCTION_INSIDE_BOXING_OFF 0x00 | ||
228 | #define R6_NEWSFLASH_CONTRAST_REDUCTION_INSIDE_BOXING_ON 0x10 | ||
229 | |||
230 | #define R6_NEWSFLASH_CONTRAST_REDUCTION_OUTSIDE_BOXING_OFF 0x00 | ||
231 | #define R6_NEWSFLASH_CONTRAST_REDUCTION_OUTSIDE_BOXING_ON 0x20 | ||
232 | |||
233 | #define R6_NEWSFLASH_BACKGROUND_COLOR_INSIDE_BOXING_OFF 0x00 | ||
234 | #define R6_NEWSFLASH_BACKGROUND_COLOR_INSIDE_BOXING_ON 0x40 | ||
235 | |||
236 | #define R6_NEWSFLASH_BACKGROUND_COLOR_OUTSIDE_BOXING_OFF 0x00 | ||
237 | #define R6_NEWSFLASH_BACKGROUND_COLOR_OUTSIDE_BOXING_ON 0x80 | ||
238 | |||
239 | /* Register R7 (Display mode) */ | ||
240 | #define R7_BOX_OFF_ROW_0 0x00 | ||
241 | #define R7_BOX_ON_ROW_0 0x01 | ||
242 | |||
243 | #define R7_BOX_OFF_ROW_1_TO_23 0x00 | ||
244 | #define R7_BOX_ON_ROW_1_TO_23 0x02 | ||
245 | |||
246 | #define R7_BOX_OFF_ROW_24 0x00 | ||
247 | #define R7_BOX_ON_ROW_24 0x04 | ||
248 | |||
249 | #define R7_SINGLE_HEIGHT 0x00 | ||
250 | #define R7_DOUBLE_HEIGHT 0x08 | ||
251 | |||
252 | #define R7_TOP_HALF 0x00 | ||
253 | #define R7_BOTTOM_HALF 0x10 | ||
254 | |||
255 | #define R7_REVEAL_OFF 0x00 | ||
256 | #define R7_REVEAL_ON 0x20 | ||
257 | |||
258 | #define R7_CURSER_OFF 0x00 | ||
259 | #define R7_CURSER_ON 0x40 | ||
260 | |||
261 | #define R7_STATUS_BOTTOM 0x00 | ||
262 | #define R7_STATUS_TOP 0x80 | ||
263 | |||
264 | /* Register R8 (Active chapter) */ | ||
265 | #define R8_ACTIVE_CHAPTER_0 0x00 | ||
266 | #define R8_ACTIVE_CHAPTER_1 0x01 | ||
267 | #define R8_ACTIVE_CHAPTER_2 0x02 | ||
268 | #define R8_ACTIVE_CHAPTER_3 0x03 | ||
269 | #define R8_ACTIVE_CHAPTER_4 0x04 | ||
270 | #define R8_ACTIVE_CHAPTER_5 0x05 | ||
271 | #define R8_ACTIVE_CHAPTER_6 0x06 | ||
272 | #define R8_ACTIVE_CHAPTER_7 0x07 | ||
273 | |||
274 | #define R8_CLEAR_MEMORY 0x08 | ||
275 | #define R8_DO_NOT_CLEAR_MEMORY 0x00 | ||
276 | |||
277 | /* Register R9 (Curser row) */ | ||
278 | #define R9_CURSER_ROW_0 0x00 | ||
279 | #define R9_CURSER_ROW_1 0x01 | ||
280 | #define R9_CURSER_ROW_2 0x02 | ||
281 | #define R9_CURSER_ROW_25 0x19 | ||
282 | |||
283 | /* Register R10 (Curser column) */ | ||
284 | #define R10_CURSER_COLUMN_0 0x00 | ||
285 | #define R10_CURSER_COLUMN_6 0x06 | ||
286 | #define R10_CURSER_COLUMN_8 0x08 | ||
287 | |||
288 | /*****************************************************************************/ | ||
289 | /* Row 25 control data in column 0 to 9 */ | ||
290 | /*****************************************************************************/ | ||
291 | #define ROW25_COLUMN0_PAGE_UNITS 0x0F | ||
292 | |||
293 | #define ROW25_COLUMN1_PAGE_TENS 0x0F | ||
294 | |||
295 | #define ROW25_COLUMN2_MINUTES_UNITS 0x0F | ||
296 | |||
297 | #define ROW25_COLUMN3_MINUTES_TENS 0x07 | ||
298 | #define ROW25_COLUMN3_DELETE_PAGE 0x08 | ||
299 | |||
300 | #define ROW25_COLUMN4_HOUR_UNITS 0x0F | ||
301 | |||
302 | #define ROW25_COLUMN5_HOUR_TENS 0x03 | ||
303 | #define ROW25_COLUMN5_INSERT_HEADLINE 0x04 | ||
304 | #define ROW25_COLUMN5_INSERT_SUBTITLE 0x08 | ||
305 | |||
306 | #define ROW25_COLUMN6_SUPPRESS_HEADER 0x01 | ||
307 | #define ROW25_COLUMN6_UPDATE_PAGE 0x02 | ||
308 | #define ROW25_COLUMN6_INTERRUPTED_SEQUENCE 0x04 | ||
309 | #define ROW25_COLUMN6_SUPPRESS_DISPLAY 0x08 | ||
310 | |||
311 | #define ROW25_COLUMN7_SERIAL_MODE 0x01 | ||
312 | #define ROW25_COLUMN7_CHARACTER_SET 0x0E | ||
313 | |||
314 | #define ROW25_COLUMN8_PAGE_HUNDREDS 0x07 | ||
315 | #define ROW25_COLUMN8_PAGE_NOT_FOUND 0x10 | ||
316 | |||
317 | #define ROW25_COLUMN9_PAGE_BEING_LOOKED_FOR 0x20 | ||
318 | |||
319 | #define ROW25_COLUMN0_TO_7_HAMMING_ERROR 0x10 | ||
320 | |||
321 | /*****************************************************************************/ | ||
322 | /* Helper macros for extracting page, hour and minute digits */ | ||
323 | /*****************************************************************************/ | ||
324 | /* BYTE_POS 0 is at row 0, column 0, | ||
325 | BYTE_POS 1 is at row 0, column 1, | ||
326 | BYTE_POS 40 is at row 1, column 0, (with NUM_ROWS_PER_PAGE = 40) | ||
327 | BYTE_POS 41 is at row 1, column 1, (with NUM_ROWS_PER_PAGE = 40), | ||
328 | ... */ | ||
329 | #define ROW(BYTE_POS) (BYTE_POS / NUM_ROWS_PER_PAGE) | ||
330 | #define COLUMN(BYTE_POS) (BYTE_POS % NUM_ROWS_PER_PAGE) | ||
331 | |||
332 | /*****************************************************************************/ | ||
333 | /* Helper macros for extracting page, hour and minute digits */ | ||
334 | /*****************************************************************************/ | ||
335 | /* Macros for extracting hundreds, tens and units of a page number which | ||
336 | must be in the range 0 ... 0x799. | ||
337 | Note that page is coded in hexadecimal, i.e. 0x123 means page 123. | ||
338 | page 0x.. means page 8.. */ | ||
339 | #define HUNDREDS_OF_PAGE(page) (((page) / 0x100) & 0x7) | ||
340 | #define TENS_OF_PAGE(page) (((page) / 0x10) & 0xF) | ||
341 | #define UNITS_OF_PAGE(page) ((page) & 0xF) | ||
342 | |||
343 | /* Macros for extracting tens and units of a hour information which | ||
344 | must be in the range 0 ... 0x24. | ||
345 | Note that hour is coded in hexadecimal, i.e. 0x12 means 12 hours */ | ||
346 | #define TENS_OF_HOUR(hour) ((hour) / 0x10) | ||
347 | #define UNITS_OF_HOUR(hour) ((hour) & 0xF) | ||
348 | |||
349 | /* Macros for extracting tens and units of a minute information which | ||
350 | must be in the range 0 ... 0x59. | ||
351 | Note that minute is coded in hexadecimal, i.e. 0x12 means 12 minutes */ | ||
352 | #define TENS_OF_MINUTE(minute) ((minute) / 0x10) | ||
353 | #define UNITS_OF_MINUTE(minute) ((minute) & 0xF) | ||
354 | |||
355 | #define HOUR_MAX 0x23 | ||
356 | #define MINUTE_MAX 0x59 | ||
357 | #define PAGE_MAX 0x8FF | ||
358 | |||
359 | #endif /* __SAA5246A_H__ */ | ||
diff --git a/drivers/media/video/saa5249.c b/drivers/media/video/saa5249.c index 0d639738d4e6..3bb959c25d9d 100644 --- a/drivers/media/video/saa5249.c +++ b/drivers/media/video/saa5249.c | |||
@@ -15,8 +15,6 @@ | |||
15 | * | 15 | * |
16 | * Copyright (c) 1998 Richard Guenther <richard.guenther@student.uni-tuebingen.de> | 16 | * Copyright (c) 1998 Richard Guenther <richard.guenther@student.uni-tuebingen.de> |
17 | * | 17 | * |
18 | * $Id: saa5249.c,v 1.1 1998/03/30 22:23:23 alan Exp $ | ||
19 | * | ||
20 | * Derived From | 18 | * Derived From |
21 | * | 19 | * |
22 | * vtx.c: | 20 | * vtx.c: |
@@ -45,33 +43,28 @@ | |||
45 | 43 | ||
46 | #include <linux/module.h> | 44 | #include <linux/module.h> |
47 | #include <linux/kernel.h> | 45 | #include <linux/kernel.h> |
48 | #include <linux/sched.h> | ||
49 | #include <linux/mm.h> | 46 | #include <linux/mm.h> |
50 | #include <linux/errno.h> | ||
51 | #include <linux/delay.h> | ||
52 | #include <linux/ioport.h> | ||
53 | #include <linux/slab.h> | ||
54 | #include <linux/init.h> | 47 | #include <linux/init.h> |
55 | #include <stdarg.h> | ||
56 | #include <linux/i2c.h> | 48 | #include <linux/i2c.h> |
49 | #include <linux/smp_lock.h> | ||
50 | #include <linux/mutex.h> | ||
51 | #include <linux/delay.h> | ||
57 | #include <linux/videotext.h> | 52 | #include <linux/videotext.h> |
58 | #include <linux/videodev.h> | 53 | #include <linux/videodev.h> |
59 | #include <media/v4l2-common.h> | 54 | #include <media/v4l2-common.h> |
60 | #include <media/v4l2-ioctl.h> | 55 | #include <media/v4l2-ioctl.h> |
61 | #include <linux/mutex.h> | 56 | #include <media/v4l2-i2c-drv-legacy.h> |
62 | |||
63 | 57 | ||
64 | #include <asm/io.h> | 58 | MODULE_AUTHOR("Michael Geng <linux@MichaelGeng.de>"); |
65 | #include <asm/uaccess.h> | 59 | MODULE_DESCRIPTION("Philips SAA5249 Teletext decoder driver"); |
60 | MODULE_LICENSE("GPL"); | ||
66 | 61 | ||
67 | #define VTX_VER_MAJ 1 | 62 | #define VTX_VER_MAJ 1 |
68 | #define VTX_VER_MIN 8 | 63 | #define VTX_VER_MIN 8 |
69 | 64 | ||
70 | 65 | ||
71 | |||
72 | #define NUM_DAUS 4 | 66 | #define NUM_DAUS 4 |
73 | #define NUM_BUFS 8 | 67 | #define NUM_BUFS 8 |
74 | #define IF_NAME "SAA5249" | ||
75 | 68 | ||
76 | static const int disp_modes[8][3] = | 69 | static const int disp_modes[8][3] = |
77 | { | 70 | { |
@@ -109,6 +102,7 @@ struct saa5249_device | |||
109 | int disp_mode; | 102 | int disp_mode; |
110 | int virtual_mode; | 103 | int virtual_mode; |
111 | struct i2c_client *client; | 104 | struct i2c_client *client; |
105 | unsigned long in_use; | ||
112 | struct mutex lock; | 106 | struct mutex lock; |
113 | }; | 107 | }; |
114 | 108 | ||
@@ -123,125 +117,8 @@ struct saa5249_device | |||
123 | 117 | ||
124 | #define VTX_DEV_MINOR 0 | 118 | #define VTX_DEV_MINOR 0 |
125 | 119 | ||
126 | /* General defines and debugging support */ | ||
127 | |||
128 | #define RESCHED do { cond_resched(); } while(0) | ||
129 | |||
130 | static struct video_device saa_template; /* Declared near bottom */ | 120 | static struct video_device saa_template; /* Declared near bottom */ |
131 | 121 | ||
132 | /* Addresses to scan */ | ||
133 | static unsigned short normal_i2c[] = {34>>1,I2C_CLIENT_END}; | ||
134 | |||
135 | I2C_CLIENT_INSMOD; | ||
136 | |||
137 | static struct i2c_client client_template; | ||
138 | |||
139 | static int saa5249_attach(struct i2c_adapter *adap, int addr, int kind) | ||
140 | { | ||
141 | int pgbuf; | ||
142 | int err; | ||
143 | struct i2c_client *client; | ||
144 | struct video_device *vd; | ||
145 | struct saa5249_device *t; | ||
146 | |||
147 | printk(KERN_INFO "saa5249: teletext chip found.\n"); | ||
148 | client=kmalloc(sizeof(*client), GFP_KERNEL); | ||
149 | if(client==NULL) | ||
150 | return -ENOMEM; | ||
151 | client_template.adapter = adap; | ||
152 | client_template.addr = addr; | ||
153 | memcpy(client, &client_template, sizeof(*client)); | ||
154 | t = kzalloc(sizeof(*t), GFP_KERNEL); | ||
155 | if(t==NULL) | ||
156 | { | ||
157 | kfree(client); | ||
158 | return -ENOMEM; | ||
159 | } | ||
160 | strlcpy(client->name, IF_NAME, I2C_NAME_SIZE); | ||
161 | mutex_init(&t->lock); | ||
162 | |||
163 | /* | ||
164 | * Now create a video4linux device | ||
165 | */ | ||
166 | |||
167 | vd = kmalloc(sizeof(struct video_device), GFP_KERNEL); | ||
168 | if(vd==NULL) | ||
169 | { | ||
170 | kfree(t); | ||
171 | kfree(client); | ||
172 | return -ENOMEM; | ||
173 | } | ||
174 | i2c_set_clientdata(client, vd); | ||
175 | memcpy(vd, &saa_template, sizeof(*vd)); | ||
176 | |||
177 | for (pgbuf = 0; pgbuf < NUM_DAUS; pgbuf++) | ||
178 | { | ||
179 | memset(t->vdau[pgbuf].pgbuf, ' ', sizeof(t->vdau[0].pgbuf)); | ||
180 | memset(t->vdau[pgbuf].sregs, 0, sizeof(t->vdau[0].sregs)); | ||
181 | memset(t->vdau[pgbuf].laststat, 0, sizeof(t->vdau[0].laststat)); | ||
182 | t->vdau[pgbuf].expire = 0; | ||
183 | t->vdau[pgbuf].clrfound = true; | ||
184 | t->vdau[pgbuf].stopped = true; | ||
185 | t->is_searching[pgbuf] = false; | ||
186 | } | ||
187 | vd->priv=t; | ||
188 | |||
189 | |||
190 | /* | ||
191 | * Register it | ||
192 | */ | ||
193 | |||
194 | if((err=video_register_device(vd, VFL_TYPE_VTX,-1))<0) | ||
195 | { | ||
196 | kfree(t); | ||
197 | kfree(vd); | ||
198 | kfree(client); | ||
199 | return err; | ||
200 | } | ||
201 | t->client = client; | ||
202 | i2c_attach_client(client); | ||
203 | return 0; | ||
204 | } | ||
205 | |||
206 | /* | ||
207 | * We do most of the hard work when we become a device on the i2c. | ||
208 | */ | ||
209 | |||
210 | static int saa5249_probe(struct i2c_adapter *adap) | ||
211 | { | ||
212 | if (adap->class & I2C_CLASS_TV_ANALOG) | ||
213 | return i2c_probe(adap, &addr_data, saa5249_attach); | ||
214 | return 0; | ||
215 | } | ||
216 | |||
217 | static int saa5249_detach(struct i2c_client *client) | ||
218 | { | ||
219 | struct video_device *vd = i2c_get_clientdata(client); | ||
220 | i2c_detach_client(client); | ||
221 | video_unregister_device(vd); | ||
222 | kfree(vd->priv); | ||
223 | kfree(vd); | ||
224 | kfree(client); | ||
225 | return 0; | ||
226 | } | ||
227 | |||
228 | /* new I2C driver support */ | ||
229 | |||
230 | static struct i2c_driver i2c_driver_videotext = | ||
231 | { | ||
232 | .driver = { | ||
233 | .name = IF_NAME, /* name */ | ||
234 | }, | ||
235 | .id = I2C_DRIVERID_SAA5249, /* in i2c.h */ | ||
236 | .attach_adapter = saa5249_probe, | ||
237 | .detach_client = saa5249_detach, | ||
238 | }; | ||
239 | |||
240 | static struct i2c_client client_template = { | ||
241 | .driver = &i2c_driver_videotext, | ||
242 | .name = "(unset)", | ||
243 | }; | ||
244 | |||
245 | /* | 122 | /* |
246 | * Wait the given number of jiffies (10ms). This calls the scheduler, so the actual | 123 | * Wait the given number of jiffies (10ms). This calls the scheduler, so the actual |
247 | * delay may be longer. | 124 | * delay may be longer. |
@@ -275,7 +152,7 @@ static int i2c_sendbuf(struct saa5249_device *t, int reg, int count, u8 *data) | |||
275 | buf[0] = reg; | 152 | buf[0] = reg; |
276 | memcpy(buf+1, data, count); | 153 | memcpy(buf+1, data, count); |
277 | 154 | ||
278 | if(i2c_master_send(t->client, buf, count+1)==count+1) | 155 | if (i2c_master_send(t->client, buf, count + 1) == count + 1) |
279 | return 0; | 156 | return 0; |
280 | return -1; | 157 | return -1; |
281 | } | 158 | } |
@@ -317,246 +194,236 @@ static int do_saa5249_ioctl(struct inode *inode, struct file *file, | |||
317 | unsigned int cmd, void *arg) | 194 | unsigned int cmd, void *arg) |
318 | { | 195 | { |
319 | static int virtual_mode = false; | 196 | static int virtual_mode = false; |
320 | struct video_device *vd = video_devdata(file); | 197 | struct saa5249_device *t = video_drvdata(file); |
321 | struct saa5249_device *t=vd->priv; | ||
322 | 198 | ||
323 | switch(cmd) | 199 | switch (cmd) { |
200 | case VTXIOCGETINFO: | ||
324 | { | 201 | { |
325 | case VTXIOCGETINFO: | 202 | vtx_info_t *info = arg; |
326 | { | 203 | info->version_major = VTX_VER_MAJ; |
327 | vtx_info_t *info = arg; | 204 | info->version_minor = VTX_VER_MIN; |
328 | info->version_major = VTX_VER_MAJ; | 205 | info->numpages = NUM_DAUS; |
329 | info->version_minor = VTX_VER_MIN; | 206 | /*info->cct_type = CCT_TYPE;*/ |
330 | info->numpages = NUM_DAUS; | 207 | return 0; |
331 | /*info->cct_type = CCT_TYPE;*/ | 208 | } |
332 | return 0; | ||
333 | } | ||
334 | 209 | ||
335 | case VTXIOCCLRPAGE: | 210 | case VTXIOCCLRPAGE: |
336 | { | 211 | { |
337 | vtx_pagereq_t *req = arg; | 212 | vtx_pagereq_t *req = arg; |
338 | 213 | ||
339 | if (req->pgbuf < 0 || req->pgbuf >= NUM_DAUS) | 214 | if (req->pgbuf < 0 || req->pgbuf >= NUM_DAUS) |
340 | return -EINVAL; | 215 | return -EINVAL; |
341 | memset(t->vdau[req->pgbuf].pgbuf, ' ', sizeof(t->vdau[0].pgbuf)); | 216 | memset(t->vdau[req->pgbuf].pgbuf, ' ', sizeof(t->vdau[0].pgbuf)); |
342 | t->vdau[req->pgbuf].clrfound = true; | 217 | t->vdau[req->pgbuf].clrfound = true; |
343 | return 0; | 218 | return 0; |
344 | } | 219 | } |
345 | 220 | ||
346 | case VTXIOCCLRFOUND: | 221 | case VTXIOCCLRFOUND: |
347 | { | 222 | { |
348 | vtx_pagereq_t *req = arg; | 223 | vtx_pagereq_t *req = arg; |
349 | 224 | ||
350 | if (req->pgbuf < 0 || req->pgbuf >= NUM_DAUS) | 225 | if (req->pgbuf < 0 || req->pgbuf >= NUM_DAUS) |
351 | return -EINVAL; | 226 | return -EINVAL; |
352 | t->vdau[req->pgbuf].clrfound = true; | 227 | t->vdau[req->pgbuf].clrfound = true; |
353 | return 0; | 228 | return 0; |
354 | } | 229 | } |
355 | 230 | ||
356 | case VTXIOCPAGEREQ: | 231 | case VTXIOCPAGEREQ: |
357 | { | 232 | { |
358 | vtx_pagereq_t *req = arg; | 233 | vtx_pagereq_t *req = arg; |
359 | if (!(req->pagemask & PGMASK_PAGE)) | 234 | if (!(req->pagemask & PGMASK_PAGE)) |
360 | req->page = 0; | 235 | req->page = 0; |
361 | if (!(req->pagemask & PGMASK_HOUR)) | 236 | if (!(req->pagemask & PGMASK_HOUR)) |
362 | req->hour = 0; | 237 | req->hour = 0; |
363 | if (!(req->pagemask & PGMASK_MINUTE)) | 238 | if (!(req->pagemask & PGMASK_MINUTE)) |
364 | req->minute = 0; | 239 | req->minute = 0; |
365 | if (req->page < 0 || req->page > 0x8ff) /* 7FF ?? */ | 240 | if (req->page < 0 || req->page > 0x8ff) /* 7FF ?? */ |
366 | return -EINVAL; | 241 | return -EINVAL; |
367 | req->page &= 0x7ff; | 242 | req->page &= 0x7ff; |
368 | if (req->hour < 0 || req->hour > 0x3f || req->minute < 0 || req->minute > 0x7f || | 243 | if (req->hour < 0 || req->hour > 0x3f || req->minute < 0 || req->minute > 0x7f || |
369 | req->pagemask < 0 || req->pagemask >= PGMASK_MAX || req->pgbuf < 0 || req->pgbuf >= NUM_DAUS) | 244 | req->pagemask < 0 || req->pagemask >= PGMASK_MAX || req->pgbuf < 0 || req->pgbuf >= NUM_DAUS) |
370 | return -EINVAL; | 245 | return -EINVAL; |
371 | t->vdau[req->pgbuf].sregs[0] = (req->pagemask & PG_HUND ? 0x10 : 0) | (req->page / 0x100); | 246 | t->vdau[req->pgbuf].sregs[0] = (req->pagemask & PG_HUND ? 0x10 : 0) | (req->page / 0x100); |
372 | t->vdau[req->pgbuf].sregs[1] = (req->pagemask & PG_TEN ? 0x10 : 0) | ((req->page / 0x10) & 0xf); | 247 | t->vdau[req->pgbuf].sregs[1] = (req->pagemask & PG_TEN ? 0x10 : 0) | ((req->page / 0x10) & 0xf); |
373 | t->vdau[req->pgbuf].sregs[2] = (req->pagemask & PG_UNIT ? 0x10 : 0) | (req->page & 0xf); | 248 | t->vdau[req->pgbuf].sregs[2] = (req->pagemask & PG_UNIT ? 0x10 : 0) | (req->page & 0xf); |
374 | t->vdau[req->pgbuf].sregs[3] = (req->pagemask & HR_TEN ? 0x10 : 0) | (req->hour / 0x10); | 249 | t->vdau[req->pgbuf].sregs[3] = (req->pagemask & HR_TEN ? 0x10 : 0) | (req->hour / 0x10); |
375 | t->vdau[req->pgbuf].sregs[4] = (req->pagemask & HR_UNIT ? 0x10 : 0) | (req->hour & 0xf); | 250 | t->vdau[req->pgbuf].sregs[4] = (req->pagemask & HR_UNIT ? 0x10 : 0) | (req->hour & 0xf); |
376 | t->vdau[req->pgbuf].sregs[5] = (req->pagemask & MIN_TEN ? 0x10 : 0) | (req->minute / 0x10); | 251 | t->vdau[req->pgbuf].sregs[5] = (req->pagemask & MIN_TEN ? 0x10 : 0) | (req->minute / 0x10); |
377 | t->vdau[req->pgbuf].sregs[6] = (req->pagemask & MIN_UNIT ? 0x10 : 0) | (req->minute & 0xf); | 252 | t->vdau[req->pgbuf].sregs[6] = (req->pagemask & MIN_UNIT ? 0x10 : 0) | (req->minute & 0xf); |
378 | t->vdau[req->pgbuf].stopped = false; | 253 | t->vdau[req->pgbuf].stopped = false; |
379 | t->vdau[req->pgbuf].clrfound = true; | 254 | t->vdau[req->pgbuf].clrfound = true; |
380 | t->is_searching[req->pgbuf] = true; | 255 | t->is_searching[req->pgbuf] = true; |
381 | return 0; | 256 | return 0; |
382 | } | 257 | } |
383 | 258 | ||
384 | case VTXIOCGETSTAT: | 259 | case VTXIOCGETSTAT: |
385 | { | 260 | { |
386 | vtx_pagereq_t *req = arg; | 261 | vtx_pagereq_t *req = arg; |
387 | u8 infobits[10]; | 262 | u8 infobits[10]; |
388 | vtx_pageinfo_t info; | 263 | vtx_pageinfo_t info; |
389 | int a; | 264 | int a; |
390 | 265 | ||
391 | if (req->pgbuf < 0 || req->pgbuf >= NUM_DAUS) | 266 | if (req->pgbuf < 0 || req->pgbuf >= NUM_DAUS) |
392 | return -EINVAL; | 267 | return -EINVAL; |
393 | if (!t->vdau[req->pgbuf].stopped) | 268 | if (!t->vdau[req->pgbuf].stopped) { |
394 | { | 269 | if (i2c_senddata(t, 2, 0, -1) || |
395 | if (i2c_senddata(t, 2, 0, -1) || | 270 | i2c_sendbuf(t, 3, sizeof(t->vdau[0].sregs), t->vdau[req->pgbuf].sregs) || |
396 | i2c_sendbuf(t, 3, sizeof(t->vdau[0].sregs), t->vdau[req->pgbuf].sregs) || | 271 | i2c_senddata(t, 8, 0, 25, 0, ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', -1) || |
397 | i2c_senddata(t, 8, 0, 25, 0, ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', -1) || | 272 | i2c_senddata(t, 2, 0, t->vdau[req->pgbuf].sregs[0] | 8, -1) || |
398 | i2c_senddata(t, 2, 0, t->vdau[req->pgbuf].sregs[0] | 8, -1) || | 273 | i2c_senddata(t, 8, 0, 25, 0, -1)) |
399 | i2c_senddata(t, 8, 0, 25, 0, -1)) | 274 | return -EIO; |
400 | return -EIO; | 275 | jdelay(PAGE_WAIT); |
401 | jdelay(PAGE_WAIT); | 276 | if (i2c_getdata(t, 10, infobits)) |
402 | if (i2c_getdata(t, 10, infobits)) | 277 | return -EIO; |
403 | return -EIO; | ||
404 | 278 | ||
405 | if (!(infobits[8] & 0x10) && !(infobits[7] & 0xf0) && /* check FOUND-bit */ | 279 | if (!(infobits[8] & 0x10) && !(infobits[7] & 0xf0) && /* check FOUND-bit */ |
406 | (memcmp(infobits, t->vdau[req->pgbuf].laststat, sizeof(infobits)) || | 280 | (memcmp(infobits, t->vdau[req->pgbuf].laststat, sizeof(infobits)) || |
407 | time_after_eq(jiffies, t->vdau[req->pgbuf].expire))) | 281 | time_after_eq(jiffies, t->vdau[req->pgbuf].expire))) |
408 | { /* check if new page arrived */ | 282 | { /* check if new page arrived */ |
409 | if (i2c_senddata(t, 8, 0, 0, 0, -1) || | 283 | if (i2c_senddata(t, 8, 0, 0, 0, -1) || |
410 | i2c_getdata(t, VTX_PAGESIZE, t->vdau[req->pgbuf].pgbuf)) | 284 | i2c_getdata(t, VTX_PAGESIZE, t->vdau[req->pgbuf].pgbuf)) |
285 | return -EIO; | ||
286 | t->vdau[req->pgbuf].expire = jiffies + PGBUF_EXPIRE; | ||
287 | memset(t->vdau[req->pgbuf].pgbuf + VTX_PAGESIZE, ' ', VTX_VIRTUALSIZE - VTX_PAGESIZE); | ||
288 | if (t->virtual_mode) { | ||
289 | /* Packet X/24 */ | ||
290 | if (i2c_senddata(t, 8, 0, 0x20, 0, -1) || | ||
291 | i2c_getdata(t, 40, t->vdau[req->pgbuf].pgbuf + VTX_PAGESIZE + 20 * 40)) | ||
292 | return -EIO; | ||
293 | /* Packet X/27/0 */ | ||
294 | if (i2c_senddata(t, 8, 0, 0x21, 0, -1) || | ||
295 | i2c_getdata(t, 40, t->vdau[req->pgbuf].pgbuf + VTX_PAGESIZE + 16 * 40)) | ||
296 | return -EIO; | ||
297 | /* Packet 8/30/0...8/30/15 | ||
298 | * FIXME: AFAIK, the 5249 does hamming-decoding for some bytes in packet 8/30, | ||
299 | * so we should undo this here. | ||
300 | */ | ||
301 | if (i2c_senddata(t, 8, 0, 0x22, 0, -1) || | ||
302 | i2c_getdata(t, 40, t->vdau[req->pgbuf].pgbuf + VTX_PAGESIZE + 23 * 40)) | ||
411 | return -EIO; | 303 | return -EIO; |
412 | t->vdau[req->pgbuf].expire = jiffies + PGBUF_EXPIRE; | ||
413 | memset(t->vdau[req->pgbuf].pgbuf + VTX_PAGESIZE, ' ', VTX_VIRTUALSIZE - VTX_PAGESIZE); | ||
414 | if (t->virtual_mode) | ||
415 | { | ||
416 | /* Packet X/24 */ | ||
417 | if (i2c_senddata(t, 8, 0, 0x20, 0, -1) || | ||
418 | i2c_getdata(t, 40, t->vdau[req->pgbuf].pgbuf + VTX_PAGESIZE + 20 * 40)) | ||
419 | return -EIO; | ||
420 | /* Packet X/27/0 */ | ||
421 | if (i2c_senddata(t, 8, 0, 0x21, 0, -1) || | ||
422 | i2c_getdata(t, 40, t->vdau[req->pgbuf].pgbuf + VTX_PAGESIZE + 16 * 40)) | ||
423 | return -EIO; | ||
424 | /* Packet 8/30/0...8/30/15 | ||
425 | * FIXME: AFAIK, the 5249 does hamming-decoding for some bytes in packet 8/30, | ||
426 | * so we should undo this here. | ||
427 | */ | ||
428 | if (i2c_senddata(t, 8, 0, 0x22, 0, -1) || | ||
429 | i2c_getdata(t, 40, t->vdau[req->pgbuf].pgbuf + VTX_PAGESIZE + 23 * 40)) | ||
430 | return -EIO; | ||
431 | } | ||
432 | t->vdau[req->pgbuf].clrfound = false; | ||
433 | memcpy(t->vdau[req->pgbuf].laststat, infobits, sizeof(infobits)); | ||
434 | } | ||
435 | else | ||
436 | { | ||
437 | memcpy(infobits, t->vdau[req->pgbuf].laststat, sizeof(infobits)); | ||
438 | } | 304 | } |
439 | } | 305 | t->vdau[req->pgbuf].clrfound = false; |
440 | else | 306 | memcpy(t->vdau[req->pgbuf].laststat, infobits, sizeof(infobits)); |
441 | { | 307 | } else { |
442 | memcpy(infobits, t->vdau[req->pgbuf].laststat, sizeof(infobits)); | 308 | memcpy(infobits, t->vdau[req->pgbuf].laststat, sizeof(infobits)); |
443 | } | 309 | } |
310 | } else { | ||
311 | memcpy(infobits, t->vdau[req->pgbuf].laststat, sizeof(infobits)); | ||
312 | } | ||
444 | 313 | ||
445 | info.pagenum = ((infobits[8] << 8) & 0x700) | ((infobits[1] << 4) & 0xf0) | (infobits[0] & 0x0f); | 314 | info.pagenum = ((infobits[8] << 8) & 0x700) | ((infobits[1] << 4) & 0xf0) | (infobits[0] & 0x0f); |
446 | if (info.pagenum < 0x100) | 315 | if (info.pagenum < 0x100) |
447 | info.pagenum += 0x800; | 316 | info.pagenum += 0x800; |
448 | info.hour = ((infobits[5] << 4) & 0x30) | (infobits[4] & 0x0f); | 317 | info.hour = ((infobits[5] << 4) & 0x30) | (infobits[4] & 0x0f); |
449 | info.minute = ((infobits[3] << 4) & 0x70) | (infobits[2] & 0x0f); | 318 | info.minute = ((infobits[3] << 4) & 0x70) | (infobits[2] & 0x0f); |
450 | info.charset = ((infobits[7] >> 1) & 7); | 319 | info.charset = ((infobits[7] >> 1) & 7); |
451 | info.delete = !!(infobits[3] & 8); | 320 | info.delete = !!(infobits[3] & 8); |
452 | info.headline = !!(infobits[5] & 4); | 321 | info.headline = !!(infobits[5] & 4); |
453 | info.subtitle = !!(infobits[5] & 8); | 322 | info.subtitle = !!(infobits[5] & 8); |
454 | info.supp_header = !!(infobits[6] & 1); | 323 | info.supp_header = !!(infobits[6] & 1); |
455 | info.update = !!(infobits[6] & 2); | 324 | info.update = !!(infobits[6] & 2); |
456 | info.inter_seq = !!(infobits[6] & 4); | 325 | info.inter_seq = !!(infobits[6] & 4); |
457 | info.dis_disp = !!(infobits[6] & 8); | 326 | info.dis_disp = !!(infobits[6] & 8); |
458 | info.serial = !!(infobits[7] & 1); | 327 | info.serial = !!(infobits[7] & 1); |
459 | info.notfound = !!(infobits[8] & 0x10); | 328 | info.notfound = !!(infobits[8] & 0x10); |
460 | info.pblf = !!(infobits[9] & 0x20); | 329 | info.pblf = !!(infobits[9] & 0x20); |
461 | info.hamming = 0; | 330 | info.hamming = 0; |
462 | for (a = 0; a <= 7; a++) | 331 | for (a = 0; a <= 7; a++) { |
463 | { | 332 | if (infobits[a] & 0xf0) { |
464 | if (infobits[a] & 0xf0) | 333 | info.hamming = 1; |
465 | { | 334 | break; |
466 | info.hamming = 1; | ||
467 | break; | ||
468 | } | ||
469 | } | ||
470 | if (t->vdau[req->pgbuf].clrfound) | ||
471 | info.notfound = 1; | ||
472 | if(copy_to_user(req->buffer, &info, sizeof(vtx_pageinfo_t))) | ||
473 | return -EFAULT; | ||
474 | if (!info.hamming && !info.notfound) | ||
475 | { | ||
476 | t->is_searching[req->pgbuf] = false; | ||
477 | } | 335 | } |
478 | return 0; | ||
479 | } | 336 | } |
337 | if (t->vdau[req->pgbuf].clrfound) | ||
338 | info.notfound = 1; | ||
339 | if (copy_to_user(req->buffer, &info, sizeof(vtx_pageinfo_t))) | ||
340 | return -EFAULT; | ||
341 | if (!info.hamming && !info.notfound) | ||
342 | t->is_searching[req->pgbuf] = false; | ||
343 | return 0; | ||
344 | } | ||
480 | 345 | ||
481 | case VTXIOCGETPAGE: | 346 | case VTXIOCGETPAGE: |
482 | { | 347 | { |
483 | vtx_pagereq_t *req = arg; | 348 | vtx_pagereq_t *req = arg; |
484 | int start, end; | 349 | int start, end; |
485 | 350 | ||
486 | if (req->pgbuf < 0 || req->pgbuf >= NUM_DAUS || req->start < 0 || | 351 | if (req->pgbuf < 0 || req->pgbuf >= NUM_DAUS || req->start < 0 || |
487 | req->start > req->end || req->end >= (virtual_mode ? VTX_VIRTUALSIZE : VTX_PAGESIZE)) | 352 | req->start > req->end || req->end >= (virtual_mode ? VTX_VIRTUALSIZE : VTX_PAGESIZE)) |
488 | return -EINVAL; | 353 | return -EINVAL; |
489 | if(copy_to_user(req->buffer, &t->vdau[req->pgbuf].pgbuf[req->start], req->end - req->start + 1)) | 354 | if (copy_to_user(req->buffer, &t->vdau[req->pgbuf].pgbuf[req->start], req->end - req->start + 1)) |
355 | return -EFAULT; | ||
356 | |||
357 | /* | ||
358 | * Always read the time directly from SAA5249 | ||
359 | */ | ||
360 | |||
361 | if (req->start <= 39 && req->end >= 32) { | ||
362 | int len; | ||
363 | char buf[16]; | ||
364 | start = max(req->start, 32); | ||
365 | end = min(req->end, 39); | ||
366 | len = end - start + 1; | ||
367 | if (i2c_senddata(t, 8, 0, 0, start, -1) || | ||
368 | i2c_getdata(t, len, buf)) | ||
369 | return -EIO; | ||
370 | if (copy_to_user(req->buffer + start - req->start, buf, len)) | ||
371 | return -EFAULT; | ||
372 | } | ||
373 | /* Insert the current header if DAU is still searching for a page */ | ||
374 | if (req->start <= 31 && req->end >= 7 && t->is_searching[req->pgbuf]) { | ||
375 | char buf[32]; | ||
376 | int len; | ||
377 | |||
378 | start = max(req->start, 7); | ||
379 | end = min(req->end, 31); | ||
380 | len = end - start + 1; | ||
381 | if (i2c_senddata(t, 8, 0, 0, start, -1) || | ||
382 | i2c_getdata(t, len, buf)) | ||
383 | return -EIO; | ||
384 | if (copy_to_user(req->buffer + start - req->start, buf, len)) | ||
490 | return -EFAULT; | 385 | return -EFAULT; |
491 | |||
492 | /* | ||
493 | * Always read the time directly from SAA5249 | ||
494 | */ | ||
495 | |||
496 | if (req->start <= 39 && req->end >= 32) | ||
497 | { | ||
498 | int len; | ||
499 | char buf[16]; | ||
500 | start = max(req->start, 32); | ||
501 | end = min(req->end, 39); | ||
502 | len=end-start+1; | ||
503 | if (i2c_senddata(t, 8, 0, 0, start, -1) || | ||
504 | i2c_getdata(t, len, buf)) | ||
505 | return -EIO; | ||
506 | if(copy_to_user(req->buffer+start-req->start, buf, len)) | ||
507 | return -EFAULT; | ||
508 | } | ||
509 | /* Insert the current header if DAU is still searching for a page */ | ||
510 | if (req->start <= 31 && req->end >= 7 && t->is_searching[req->pgbuf]) | ||
511 | { | ||
512 | char buf[32]; | ||
513 | int len; | ||
514 | start = max(req->start, 7); | ||
515 | end = min(req->end, 31); | ||
516 | len=end-start+1; | ||
517 | if (i2c_senddata(t, 8, 0, 0, start, -1) || | ||
518 | i2c_getdata(t, len, buf)) | ||
519 | return -EIO; | ||
520 | if(copy_to_user(req->buffer+start-req->start, buf, len)) | ||
521 | return -EFAULT; | ||
522 | } | ||
523 | return 0; | ||
524 | } | 386 | } |
387 | return 0; | ||
388 | } | ||
525 | 389 | ||
526 | case VTXIOCSTOPDAU: | 390 | case VTXIOCSTOPDAU: |
527 | { | 391 | { |
528 | vtx_pagereq_t *req = arg; | 392 | vtx_pagereq_t *req = arg; |
529 | 393 | ||
530 | if (req->pgbuf < 0 || req->pgbuf >= NUM_DAUS) | 394 | if (req->pgbuf < 0 || req->pgbuf >= NUM_DAUS) |
531 | return -EINVAL; | 395 | return -EINVAL; |
532 | t->vdau[req->pgbuf].stopped = true; | 396 | t->vdau[req->pgbuf].stopped = true; |
533 | t->is_searching[req->pgbuf] = false; | 397 | t->is_searching[req->pgbuf] = false; |
534 | return 0; | 398 | return 0; |
535 | } | 399 | } |
536 | 400 | ||
537 | case VTXIOCPUTPAGE: | 401 | case VTXIOCPUTPAGE: |
538 | case VTXIOCSETDISP: | 402 | case VTXIOCSETDISP: |
539 | case VTXIOCPUTSTAT: | 403 | case VTXIOCPUTSTAT: |
540 | return 0; | 404 | return 0; |
541 | 405 | ||
542 | case VTXIOCCLRCACHE: | 406 | case VTXIOCCLRCACHE: |
543 | { | 407 | { |
544 | if (i2c_senddata(t, 0, NUM_DAUS, 0, 8, -1) || i2c_senddata(t, 11, | 408 | if (i2c_senddata(t, 0, NUM_DAUS, 0, 8, -1) || i2c_senddata(t, 11, |
545 | ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ', | 409 | ' ', ' ', ' ', ' ', ' ', ' ', |
546 | ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ', -1)) | 410 | ' ', ' ', ' ', ' ', ' ', ' ', |
547 | return -EIO; | 411 | ' ', ' ', ' ', ' ', ' ', ' ', |
548 | if (i2c_senddata(t, 3, 0x20, -1)) | 412 | ' ', ' ', ' ', ' ', ' ', ' ', |
549 | return -EIO; | 413 | -1)) |
550 | jdelay(10 * CLEAR_DELAY); /* I have no idea how long we have to wait here */ | 414 | return -EIO; |
551 | return 0; | 415 | if (i2c_senddata(t, 3, 0x20, -1)) |
552 | } | 416 | return -EIO; |
417 | jdelay(10 * CLEAR_DELAY); /* I have no idea how long we have to wait here */ | ||
418 | return 0; | ||
419 | } | ||
553 | 420 | ||
554 | case VTXIOCSETVIRT: | 421 | case VTXIOCSETVIRT: |
555 | { | 422 | { |
556 | /* The SAA5249 has virtual-row reception turned on always */ | 423 | /* The SAA5249 has virtual-row reception turned on always */ |
557 | t->virtual_mode = (int)(long)arg; | 424 | t->virtual_mode = (int)(long)arg; |
558 | return 0; | 425 | return 0; |
559 | } | 426 | } |
560 | } | 427 | } |
561 | return -EINVAL; | 428 | return -EINVAL; |
562 | } | 429 | } |
@@ -616,8 +483,7 @@ static inline unsigned int vtx_fix_command(unsigned int cmd) | |||
616 | static int saa5249_ioctl(struct inode *inode, struct file *file, | 483 | static int saa5249_ioctl(struct inode *inode, struct file *file, |
617 | unsigned int cmd, unsigned long arg) | 484 | unsigned int cmd, unsigned long arg) |
618 | { | 485 | { |
619 | struct video_device *vd = video_devdata(file); | 486 | struct saa5249_device *t = video_drvdata(file); |
620 | struct saa5249_device *t=vd->priv; | ||
621 | int err; | 487 | int err; |
622 | 488 | ||
623 | cmd = vtx_fix_command(cmd); | 489 | cmd = vtx_fix_command(cmd); |
@@ -629,32 +495,27 @@ static int saa5249_ioctl(struct inode *inode, struct file *file, | |||
629 | 495 | ||
630 | static int saa5249_open(struct inode *inode, struct file *file) | 496 | static int saa5249_open(struct inode *inode, struct file *file) |
631 | { | 497 | { |
632 | struct video_device *vd = video_devdata(file); | 498 | struct saa5249_device *t = video_drvdata(file); |
633 | struct saa5249_device *t=vd->priv; | 499 | int pgbuf; |
634 | int err,pgbuf; | ||
635 | 500 | ||
636 | err = video_exclusive_open(inode,file); | 501 | if (t->client == NULL) |
637 | if (err < 0) | 502 | return -ENODEV; |
638 | return err; | ||
639 | 503 | ||
640 | if (t->client==NULL) { | 504 | if (test_and_set_bit(0, &t->in_use)) |
641 | err = -ENODEV; | 505 | return -EBUSY; |
642 | goto fail; | ||
643 | } | ||
644 | 506 | ||
645 | if (i2c_senddata(t, 0, 0, -1) || /* Select R11 */ | 507 | if (i2c_senddata(t, 0, 0, -1) || /* Select R11 */ |
646 | /* Turn off parity checks (we do this ourselves) */ | 508 | /* Turn off parity checks (we do this ourselves) */ |
647 | i2c_senddata(t, 1, disp_modes[t->disp_mode][0], 0, -1) || | 509 | i2c_senddata(t, 1, disp_modes[t->disp_mode][0], 0, -1) || |
648 | /* Display TV-picture, no virtual rows */ | 510 | /* Display TV-picture, no virtual rows */ |
649 | i2c_senddata(t, 4, NUM_DAUS, disp_modes[t->disp_mode][1], disp_modes[t->disp_mode][2], 7, -1)) /* Set display to page 4 */ | 511 | i2c_senddata(t, 4, NUM_DAUS, disp_modes[t->disp_mode][1], disp_modes[t->disp_mode][2], 7, -1)) |
650 | 512 | /* Set display to page 4 */ | |
651 | { | 513 | { |
652 | err = -EIO; | 514 | clear_bit(0, &t->in_use); |
653 | goto fail; | 515 | return -EIO; |
654 | } | 516 | } |
655 | 517 | ||
656 | for (pgbuf = 0; pgbuf < NUM_DAUS; pgbuf++) | 518 | for (pgbuf = 0; pgbuf < NUM_DAUS; pgbuf++) { |
657 | { | ||
658 | memset(t->vdau[pgbuf].pgbuf, ' ', sizeof(t->vdau[0].pgbuf)); | 519 | memset(t->vdau[pgbuf].pgbuf, ' ', sizeof(t->vdau[0].pgbuf)); |
659 | memset(t->vdau[pgbuf].sregs, 0, sizeof(t->vdau[0].sregs)); | 520 | memset(t->vdau[pgbuf].sregs, 0, sizeof(t->vdau[0].sregs)); |
660 | memset(t->vdau[pgbuf].laststat, 0, sizeof(t->vdau[0].laststat)); | 521 | memset(t->vdau[pgbuf].laststat, 0, sizeof(t->vdau[0].laststat)); |
@@ -665,39 +526,20 @@ static int saa5249_open(struct inode *inode, struct file *file) | |||
665 | } | 526 | } |
666 | t->virtual_mode = false; | 527 | t->virtual_mode = false; |
667 | return 0; | 528 | return 0; |
668 | |||
669 | fail: | ||
670 | video_exclusive_release(inode,file); | ||
671 | return err; | ||
672 | } | 529 | } |
673 | 530 | ||
674 | 531 | ||
675 | 532 | ||
676 | static int saa5249_release(struct inode *inode, struct file *file) | 533 | static int saa5249_release(struct inode *inode, struct file *file) |
677 | { | 534 | { |
678 | struct video_device *vd = video_devdata(file); | 535 | struct saa5249_device *t = video_drvdata(file); |
679 | struct saa5249_device *t=vd->priv; | 536 | |
680 | i2c_senddata(t, 1, 0x20, -1); /* Turn off CCT */ | 537 | i2c_senddata(t, 1, 0x20, -1); /* Turn off CCT */ |
681 | i2c_senddata(t, 5, 3, 3, -1); /* Turn off TV-display */ | 538 | i2c_senddata(t, 5, 3, 3, -1); /* Turn off TV-display */ |
682 | video_exclusive_release(inode,file); | 539 | clear_bit(0, &t->in_use); |
683 | return 0; | 540 | return 0; |
684 | } | 541 | } |
685 | 542 | ||
686 | static int __init init_saa_5249 (void) | ||
687 | { | ||
688 | printk(KERN_INFO "SAA5249 driver (" IF_NAME " interface) for VideoText version %d.%d\n", | ||
689 | VTX_VER_MAJ, VTX_VER_MIN); | ||
690 | return i2c_add_driver(&i2c_driver_videotext); | ||
691 | } | ||
692 | |||
693 | static void __exit cleanup_saa_5249 (void) | ||
694 | { | ||
695 | i2c_del_driver(&i2c_driver_videotext); | ||
696 | } | ||
697 | |||
698 | module_init(init_saa_5249); | ||
699 | module_exit(cleanup_saa_5249); | ||
700 | |||
701 | static const struct file_operations saa_fops = { | 543 | static const struct file_operations saa_fops = { |
702 | .owner = THIS_MODULE, | 544 | .owner = THIS_MODULE, |
703 | .open = saa5249_open, | 545 | .open = saa5249_open, |
@@ -711,8 +553,84 @@ static const struct file_operations saa_fops = { | |||
711 | 553 | ||
712 | static struct video_device saa_template = | 554 | static struct video_device saa_template = |
713 | { | 555 | { |
714 | .name = IF_NAME, | 556 | .name = "saa5249", |
715 | .fops = &saa_fops, | 557 | .fops = &saa_fops, |
558 | .release = video_device_release, | ||
716 | }; | 559 | }; |
717 | 560 | ||
718 | MODULE_LICENSE("GPL"); | 561 | /* Addresses to scan */ |
562 | static unsigned short normal_i2c[] = { 0x22 >> 1, I2C_CLIENT_END }; | ||
563 | |||
564 | I2C_CLIENT_INSMOD; | ||
565 | |||
566 | static int saa5249_probe(struct i2c_client *client, | ||
567 | const struct i2c_device_id *id) | ||
568 | { | ||
569 | int pgbuf; | ||
570 | int err; | ||
571 | struct video_device *vd; | ||
572 | struct saa5249_device *t; | ||
573 | |||
574 | v4l_info(client, "chip found @ 0x%x (%s)\n", | ||
575 | client->addr << 1, client->adapter->name); | ||
576 | v4l_info(client, "VideoText version %d.%d\n", | ||
577 | VTX_VER_MAJ, VTX_VER_MIN); | ||
578 | t = kzalloc(sizeof(*t), GFP_KERNEL); | ||
579 | if (t == NULL) | ||
580 | return -ENOMEM; | ||
581 | mutex_init(&t->lock); | ||
582 | |||
583 | /* Now create a video4linux device */ | ||
584 | vd = kmalloc(sizeof(struct video_device), GFP_KERNEL); | ||
585 | if (vd == NULL) { | ||
586 | kfree(client); | ||
587 | return -ENOMEM; | ||
588 | } | ||
589 | i2c_set_clientdata(client, vd); | ||
590 | memcpy(vd, &saa_template, sizeof(*vd)); | ||
591 | |||
592 | for (pgbuf = 0; pgbuf < NUM_DAUS; pgbuf++) { | ||
593 | memset(t->vdau[pgbuf].pgbuf, ' ', sizeof(t->vdau[0].pgbuf)); | ||
594 | memset(t->vdau[pgbuf].sregs, 0, sizeof(t->vdau[0].sregs)); | ||
595 | memset(t->vdau[pgbuf].laststat, 0, sizeof(t->vdau[0].laststat)); | ||
596 | t->vdau[pgbuf].expire = 0; | ||
597 | t->vdau[pgbuf].clrfound = true; | ||
598 | t->vdau[pgbuf].stopped = true; | ||
599 | t->is_searching[pgbuf] = false; | ||
600 | } | ||
601 | video_set_drvdata(vd, t); | ||
602 | |||
603 | /* Register it */ | ||
604 | err = video_register_device(vd, VFL_TYPE_VTX, -1); | ||
605 | if (err < 0) { | ||
606 | kfree(t); | ||
607 | kfree(vd); | ||
608 | return err; | ||
609 | } | ||
610 | t->client = client; | ||
611 | return 0; | ||
612 | } | ||
613 | |||
614 | static int saa5249_remove(struct i2c_client *client) | ||
615 | { | ||
616 | struct video_device *vd = i2c_get_clientdata(client); | ||
617 | |||
618 | video_unregister_device(vd); | ||
619 | kfree(video_get_drvdata(vd)); | ||
620 | kfree(vd); | ||
621 | return 0; | ||
622 | } | ||
623 | |||
624 | static const struct i2c_device_id saa5249_id[] = { | ||
625 | { "saa5249", 0 }, | ||
626 | { } | ||
627 | }; | ||
628 | MODULE_DEVICE_TABLE(i2c, saa5249_id); | ||
629 | |||
630 | static struct v4l2_i2c_driver_data v4l2_i2c_data = { | ||
631 | .name = "saa5249", | ||
632 | .driverid = I2C_DRIVERID_SAA5249, | ||
633 | .probe = saa5249_probe, | ||
634 | .remove = saa5249_remove, | ||
635 | .id_table = saa5249_id, | ||
636 | }; | ||
diff --git a/drivers/media/video/saa7115.c b/drivers/media/video/saa7115.c index ad733caec720..c8e9cb3db30a 100644 --- a/drivers/media/video/saa7115.c +++ b/drivers/media/video/saa7115.c | |||
@@ -1057,7 +1057,7 @@ static void saa711x_set_lcr(struct i2c_client *client, struct v4l2_sliced_vbi_fo | |||
1057 | for (i = 0; i <= 23; i++) | 1057 | for (i = 0; i <= 23; i++) |
1058 | lcr[i] = 0xff; | 1058 | lcr[i] = 0xff; |
1059 | 1059 | ||
1060 | if (fmt->service_set == 0) { | 1060 | if (fmt == NULL) { |
1061 | /* raw VBI */ | 1061 | /* raw VBI */ |
1062 | if (is_50hz) | 1062 | if (is_50hz) |
1063 | for (i = 6; i <= 23; i++) | 1063 | for (i = 6; i <= 23; i++) |
@@ -1113,7 +1113,7 @@ static void saa711x_set_lcr(struct i2c_client *client, struct v4l2_sliced_vbi_fo | |||
1113 | } | 1113 | } |
1114 | 1114 | ||
1115 | /* enable/disable raw VBI capturing */ | 1115 | /* enable/disable raw VBI capturing */ |
1116 | saa711x_writeregs(client, fmt->service_set == 0 ? | 1116 | saa711x_writeregs(client, fmt == NULL ? |
1117 | saa7115_cfg_vbi_on : | 1117 | saa7115_cfg_vbi_on : |
1118 | saa7115_cfg_vbi_off); | 1118 | saa7115_cfg_vbi_off); |
1119 | } | 1119 | } |
@@ -1153,6 +1153,10 @@ static int saa711x_set_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt | |||
1153 | saa711x_set_lcr(client, &fmt->fmt.sliced); | 1153 | saa711x_set_lcr(client, &fmt->fmt.sliced); |
1154 | return 0; | 1154 | return 0; |
1155 | } | 1155 | } |
1156 | if (fmt->type == V4L2_BUF_TYPE_VBI_CAPTURE) { | ||
1157 | saa711x_set_lcr(client, NULL); | ||
1158 | return 0; | ||
1159 | } | ||
1156 | if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | 1160 | if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) |
1157 | return -EINVAL; | 1161 | return -EINVAL; |
1158 | 1162 | ||
@@ -1309,10 +1313,13 @@ static int saa7115_command(struct i2c_client *client, unsigned int cmd, void *ar | |||
1309 | case VIDIOC_INT_S_VIDEO_ROUTING: | 1313 | case VIDIOC_INT_S_VIDEO_ROUTING: |
1310 | { | 1314 | { |
1311 | struct v4l2_routing *route = arg; | 1315 | struct v4l2_routing *route = arg; |
1316 | u32 input = route->input; | ||
1317 | u8 mask = (state->ident == V4L2_IDENT_SAA7111) ? 0xf8 : 0xf0; | ||
1312 | 1318 | ||
1313 | v4l_dbg(1, debug, client, "decoder set input %d output %d\n", route->input, route->output); | 1319 | v4l_dbg(1, debug, client, "decoder set input %d output %d\n", route->input, route->output); |
1314 | /* saa7113 does not have these inputs */ | 1320 | /* saa7111/3 does not have these inputs */ |
1315 | if (state->ident == V4L2_IDENT_SAA7113 && | 1321 | if ((state->ident == V4L2_IDENT_SAA7113 || |
1322 | state->ident == V4L2_IDENT_SAA7111) && | ||
1316 | (route->input == SAA7115_COMPOSITE4 || | 1323 | (route->input == SAA7115_COMPOSITE4 || |
1317 | route->input == SAA7115_COMPOSITE5)) { | 1324 | route->input == SAA7115_COMPOSITE5)) { |
1318 | return -EINVAL; | 1325 | return -EINVAL; |
@@ -1327,10 +1334,23 @@ static int saa7115_command(struct i2c_client *client, unsigned int cmd, void *ar | |||
1327 | (route->input >= SAA7115_SVIDEO0) ? "S-Video" : "Composite", (route->output == SAA7115_IPORT_ON) ? "iport on" : "iport off"); | 1334 | (route->input >= SAA7115_SVIDEO0) ? "S-Video" : "Composite", (route->output == SAA7115_IPORT_ON) ? "iport on" : "iport off"); |
1328 | state->input = route->input; | 1335 | state->input = route->input; |
1329 | 1336 | ||
1337 | /* saa7111 has slightly different input numbering */ | ||
1338 | if (state->ident == V4L2_IDENT_SAA7111) { | ||
1339 | if (input >= SAA7115_COMPOSITE4) | ||
1340 | input -= 2; | ||
1341 | /* saa7111 specific */ | ||
1342 | saa711x_write(client, R_10_CHROMA_CNTL_2, | ||
1343 | (saa711x_read(client, R_10_CHROMA_CNTL_2) & 0x3f) | | ||
1344 | ((route->output & 0xc0) ^ 0x40)); | ||
1345 | saa711x_write(client, R_13_RT_X_PORT_OUT_CNTL, | ||
1346 | (saa711x_read(client, R_13_RT_X_PORT_OUT_CNTL) & 0xf0) | | ||
1347 | ((route->output & 2) ? 0x0a : 0)); | ||
1348 | } | ||
1349 | |||
1330 | /* select mode */ | 1350 | /* select mode */ |
1331 | saa711x_write(client, R_02_INPUT_CNTL_1, | 1351 | saa711x_write(client, R_02_INPUT_CNTL_1, |
1332 | (saa711x_read(client, R_02_INPUT_CNTL_1) & 0xf0) | | 1352 | (saa711x_read(client, R_02_INPUT_CNTL_1) & mask) | |
1333 | state->input); | 1353 | input); |
1334 | 1354 | ||
1335 | /* bypass chrominance trap for S-Video modes */ | 1355 | /* bypass chrominance trap for S-Video modes */ |
1336 | saa711x_write(client, R_09_LUMA_CNTL, | 1356 | saa711x_write(client, R_09_LUMA_CNTL, |
@@ -1384,6 +1404,13 @@ static int saa7115_command(struct i2c_client *client, unsigned int cmd, void *ar | |||
1384 | saa711x_writeregs(client, saa7115_cfg_reset_scaler); | 1404 | saa711x_writeregs(client, saa7115_cfg_reset_scaler); |
1385 | break; | 1405 | break; |
1386 | 1406 | ||
1407 | case VIDIOC_INT_S_GPIO: | ||
1408 | if (state->ident != V4L2_IDENT_SAA7111) | ||
1409 | return -EINVAL; | ||
1410 | saa711x_write(client, 0x11, (saa711x_read(client, 0x11) & 0x7f) | | ||
1411 | (*(u32 *)arg ? 0x80 : 0)); | ||
1412 | break; | ||
1413 | |||
1387 | case VIDIOC_INT_G_VBI_DATA: | 1414 | case VIDIOC_INT_G_VBI_DATA: |
1388 | { | 1415 | { |
1389 | struct v4l2_sliced_vbi_data *data = arg; | 1416 | struct v4l2_sliced_vbi_data *data = arg; |
@@ -1539,7 +1566,8 @@ static int saa7115_probe(struct i2c_client *client, | |||
1539 | state->crystal_freq = SAA7115_FREQ_32_11_MHZ; | 1566 | state->crystal_freq = SAA7115_FREQ_32_11_MHZ; |
1540 | saa711x_writeregs(client, saa7115_init_auto_input); | 1567 | saa711x_writeregs(client, saa7115_init_auto_input); |
1541 | } | 1568 | } |
1542 | saa711x_writeregs(client, saa7115_init_misc); | 1569 | if (state->ident != V4L2_IDENT_SAA7111) |
1570 | saa711x_writeregs(client, saa7115_init_misc); | ||
1543 | saa711x_set_v4lstd(client, V4L2_STD_NTSC); | 1571 | saa711x_set_v4lstd(client, V4L2_STD_NTSC); |
1544 | 1572 | ||
1545 | v4l_dbg(1, debug, client, "status: (1E) 0x%02x, (1F) 0x%02x\n", | 1573 | v4l_dbg(1, debug, client, "status: (1E) 0x%02x, (1F) 0x%02x\n", |
diff --git a/drivers/media/video/saa7134/saa6752hs.c b/drivers/media/video/saa7134/saa6752hs.c index 707be175509d..1fb6eccdade3 100644 --- a/drivers/media/video/saa7134/saa6752hs.c +++ b/drivers/media/video/saa7134/saa6752hs.c | |||
@@ -1,3 +1,27 @@ | |||
1 | /* | ||
2 | saa6752hs - i2c-driver for the saa6752hs by Philips | ||
3 | |||
4 | Copyright (C) 2004 Andrew de Quincey | ||
5 | |||
6 | AC-3 support: | ||
7 | |||
8 | Copyright (C) 2008 Hans Verkuil <hverkuil@xs4all.nl> | ||
9 | |||
10 | This program is free software; you can redistribute it and/or modify | ||
11 | it under the terms of the GNU General Public License vs published by | ||
12 | the Free Software Foundation; either version 2 of the License, or | ||
13 | (at your option) any later version. | ||
14 | |||
15 | This program is distributed in the hope that it will be useful, | ||
16 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | GNU General Public License for more details. | ||
19 | |||
20 | You should have received a copy of the GNU General Public License | ||
21 | along with this program; if not, write to the Free Software | ||
22 | Foundation, Inc., 675 Mvss Ave, Cambridge, MA 02139, USA. | ||
23 | */ | ||
24 | |||
1 | #include <linux/module.h> | 25 | #include <linux/module.h> |
2 | #include <linux/kernel.h> | 26 | #include <linux/kernel.h> |
3 | #include <linux/string.h> | 27 | #include <linux/string.h> |
@@ -10,6 +34,8 @@ | |||
10 | #include <linux/types.h> | 34 | #include <linux/types.h> |
11 | #include <linux/videodev2.h> | 35 | #include <linux/videodev2.h> |
12 | #include <media/v4l2-common.h> | 36 | #include <media/v4l2-common.h> |
37 | #include <media/v4l2-chip-ident.h> | ||
38 | #include <media/v4l2-i2c-drv-legacy.h> | ||
13 | #include <linux/init.h> | 39 | #include <linux/init.h> |
14 | #include <linux/crc32.h> | 40 | #include <linux/crc32.h> |
15 | 41 | ||
@@ -27,9 +53,6 @@ MODULE_DESCRIPTION("device driver for saa6752hs MPEG2 encoder"); | |||
27 | MODULE_AUTHOR("Andrew de Quincey"); | 53 | MODULE_AUTHOR("Andrew de Quincey"); |
28 | MODULE_LICENSE("GPL"); | 54 | MODULE_LICENSE("GPL"); |
29 | 55 | ||
30 | static struct i2c_driver driver; | ||
31 | static struct i2c_client client_template; | ||
32 | |||
33 | enum saa6752hs_videoformat { | 56 | enum saa6752hs_videoformat { |
34 | SAA6752HS_VF_D1 = 0, /* standard D1 video format: 720x576 */ | 57 | SAA6752HS_VF_D1 = 0, /* standard D1 video format: 720x576 */ |
35 | SAA6752HS_VF_2_3_D1 = 1,/* 2/3D1 video format: 480x576 */ | 58 | SAA6752HS_VF_2_3_D1 = 1,/* 2/3D1 video format: 480x576 */ |
@@ -46,7 +69,9 @@ struct saa6752hs_mpeg_params { | |||
46 | __u16 ts_pid_pcr; | 69 | __u16 ts_pid_pcr; |
47 | 70 | ||
48 | /* audio */ | 71 | /* audio */ |
49 | enum v4l2_mpeg_audio_l2_bitrate au_l2_bitrate; | 72 | enum v4l2_mpeg_audio_encoding au_encoding; |
73 | enum v4l2_mpeg_audio_l2_bitrate au_l2_bitrate; | ||
74 | enum v4l2_mpeg_audio_ac3_bitrate au_ac3_bitrate; | ||
50 | 75 | ||
51 | /* video */ | 76 | /* video */ |
52 | enum v4l2_mpeg_video_aspect vi_aspect; | 77 | enum v4l2_mpeg_video_aspect vi_aspect; |
@@ -70,7 +95,9 @@ static const struct v4l2_format v4l2_format_table[] = | |||
70 | }; | 95 | }; |
71 | 96 | ||
72 | struct saa6752hs_state { | 97 | struct saa6752hs_state { |
73 | struct i2c_client client; | 98 | int chip; |
99 | u32 revision; | ||
100 | int has_ac3; | ||
74 | struct saa6752hs_mpeg_params params; | 101 | struct saa6752hs_mpeg_params params; |
75 | enum saa6752hs_videoformat video_format; | 102 | enum saa6752hs_videoformat video_format; |
76 | v4l2_std_id standard; | 103 | v4l2_std_id standard; |
@@ -145,6 +172,39 @@ static u8 PMT[] = { | |||
145 | 0x00, 0x00, 0x00, 0x00 /* CRC32 */ | 172 | 0x00, 0x00, 0x00, 0x00 /* CRC32 */ |
146 | }; | 173 | }; |
147 | 174 | ||
175 | static u8 PMT_AC3[] = { | ||
176 | 0xc2, /* i2c register */ | ||
177 | 0x01, /* table number for encoder(1) */ | ||
178 | 0x47, /* sync */ | ||
179 | |||
180 | 0x40, /* transport_error_indicator(0), payload_unit_start(1), transport_priority(0) */ | ||
181 | 0x10, /* PMT PID (0x0010) */ | ||
182 | 0x10, /* transport_scrambling_control(00), adaptation_field_control(01), continuity_counter(0) */ | ||
183 | |||
184 | 0x00, /* PSI pointer to start of table */ | ||
185 | |||
186 | 0x02, /* TID (2) */ | ||
187 | 0xb0, 0x1a, /* section_syntax_indicator(1), section_length(26) */ | ||
188 | |||
189 | 0x00, 0x01, /* program_number(1) */ | ||
190 | |||
191 | 0xc1, /* version_number(0), current_next_indicator(1) */ | ||
192 | |||
193 | 0x00, 0x00, /* section_number(0), last_section_number(0) */ | ||
194 | |||
195 | 0xe1, 0x04, /* PCR_PID (0x0104) */ | ||
196 | |||
197 | 0xf0, 0x00, /* program_info_length(0) */ | ||
198 | |||
199 | 0x02, 0xe1, 0x00, 0xf0, 0x00, /* video stream type(2), pid */ | ||
200 | 0x06, 0xe1, 0x03, 0xf0, 0x03, /* audio stream type(6), pid */ | ||
201 | 0x6a, /* AC3 */ | ||
202 | 0x01, /* Descriptor_length(1) */ | ||
203 | 0x00, /* component_type_flag(0), bsid_flag(0), mainid_flag(0), asvc_flag(0), reserved flags(0) */ | ||
204 | |||
205 | 0xED, 0xDE, 0x2D, 0xF3 /* CRC32 BE */ | ||
206 | }; | ||
207 | |||
148 | static struct saa6752hs_mpeg_params param_defaults = | 208 | static struct saa6752hs_mpeg_params param_defaults = |
149 | { | 209 | { |
150 | .ts_pid_pmt = 16, | 210 | .ts_pid_pmt = 16, |
@@ -157,12 +217,14 @@ static struct saa6752hs_mpeg_params param_defaults = | |||
157 | .vi_bitrate_peak = 6000, | 217 | .vi_bitrate_peak = 6000, |
158 | .vi_bitrate_mode = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR, | 218 | .vi_bitrate_mode = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR, |
159 | 219 | ||
220 | .au_encoding = V4L2_MPEG_AUDIO_ENCODING_LAYER_2, | ||
160 | .au_l2_bitrate = V4L2_MPEG_AUDIO_L2_BITRATE_256K, | 221 | .au_l2_bitrate = V4L2_MPEG_AUDIO_L2_BITRATE_256K, |
222 | .au_ac3_bitrate = V4L2_MPEG_AUDIO_AC3_BITRATE_256K, | ||
161 | }; | 223 | }; |
162 | 224 | ||
163 | /* ---------------------------------------------------------------------- */ | 225 | /* ---------------------------------------------------------------------- */ |
164 | 226 | ||
165 | static int saa6752hs_chip_command(struct i2c_client* client, | 227 | static int saa6752hs_chip_command(struct i2c_client *client, |
166 | enum saa6752hs_command command) | 228 | enum saa6752hs_command command) |
167 | { | 229 | { |
168 | unsigned char buf[3]; | 230 | unsigned char buf[3]; |
@@ -229,45 +291,61 @@ static int saa6752hs_chip_command(struct i2c_client* client, | |||
229 | } | 291 | } |
230 | 292 | ||
231 | 293 | ||
232 | static int saa6752hs_set_bitrate(struct i2c_client* client, | 294 | static inline void set_reg8(struct i2c_client *client, uint8_t reg, uint8_t val) |
233 | struct saa6752hs_mpeg_params* params) | 295 | { |
296 | u8 buf[2]; | ||
297 | |||
298 | buf[0] = reg; | ||
299 | buf[1] = val; | ||
300 | i2c_master_send(client, buf, 2); | ||
301 | } | ||
302 | |||
303 | static inline void set_reg16(struct i2c_client *client, uint8_t reg, uint16_t val) | ||
234 | { | 304 | { |
235 | u8 buf[3]; | 305 | u8 buf[3]; |
306 | |||
307 | buf[0] = reg; | ||
308 | buf[1] = val >> 8; | ||
309 | buf[2] = val & 0xff; | ||
310 | i2c_master_send(client, buf, 3); | ||
311 | } | ||
312 | |||
313 | static int saa6752hs_set_bitrate(struct i2c_client *client, | ||
314 | struct saa6752hs_state *h) | ||
315 | { | ||
316 | struct saa6752hs_mpeg_params *params = &h->params; | ||
236 | int tot_bitrate; | 317 | int tot_bitrate; |
318 | int is_384k; | ||
237 | 319 | ||
238 | /* set the bitrate mode */ | 320 | /* set the bitrate mode */ |
239 | buf[0] = 0x71; | 321 | set_reg8(client, 0x71, |
240 | buf[1] = (params->vi_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) ? 0 : 1; | 322 | params->vi_bitrate_mode != V4L2_MPEG_VIDEO_BITRATE_MODE_VBR); |
241 | i2c_master_send(client, buf, 2); | ||
242 | 323 | ||
243 | /* set the video bitrate */ | 324 | /* set the video bitrate */ |
244 | if (params->vi_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) { | 325 | if (params->vi_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) { |
245 | /* set the target bitrate */ | 326 | /* set the target bitrate */ |
246 | buf[0] = 0x80; | 327 | set_reg16(client, 0x80, params->vi_bitrate); |
247 | buf[1] = params->vi_bitrate >> 8; | ||
248 | buf[2] = params->vi_bitrate & 0xff; | ||
249 | i2c_master_send(client, buf, 3); | ||
250 | 328 | ||
251 | /* set the max bitrate */ | 329 | /* set the max bitrate */ |
252 | buf[0] = 0x81; | 330 | set_reg16(client, 0x81, params->vi_bitrate_peak); |
253 | buf[1] = params->vi_bitrate_peak >> 8; | ||
254 | buf[2] = params->vi_bitrate_peak & 0xff; | ||
255 | i2c_master_send(client, buf, 3); | ||
256 | tot_bitrate = params->vi_bitrate_peak; | 331 | tot_bitrate = params->vi_bitrate_peak; |
257 | } else { | 332 | } else { |
258 | /* set the target bitrate (no max bitrate for CBR) */ | 333 | /* set the target bitrate (no max bitrate for CBR) */ |
259 | buf[0] = 0x81; | 334 | set_reg16(client, 0x81, params->vi_bitrate); |
260 | buf[1] = params->vi_bitrate >> 8; | ||
261 | buf[2] = params->vi_bitrate & 0xff; | ||
262 | i2c_master_send(client, buf, 3); | ||
263 | tot_bitrate = params->vi_bitrate; | 335 | tot_bitrate = params->vi_bitrate; |
264 | } | 336 | } |
265 | 337 | ||
338 | /* set the audio encoding */ | ||
339 | set_reg8(client, 0x93, | ||
340 | params->au_encoding == V4L2_MPEG_AUDIO_ENCODING_AC3); | ||
341 | |||
266 | /* set the audio bitrate */ | 342 | /* set the audio bitrate */ |
267 | buf[0] = 0x94; | 343 | if (params->au_encoding == V4L2_MPEG_AUDIO_ENCODING_AC3) |
268 | buf[1] = (V4L2_MPEG_AUDIO_L2_BITRATE_256K == params->au_l2_bitrate) ? 0 : 1; | 344 | is_384k = V4L2_MPEG_AUDIO_AC3_BITRATE_384K == params->au_ac3_bitrate; |
269 | i2c_master_send(client, buf, 2); | 345 | else |
270 | tot_bitrate += (V4L2_MPEG_AUDIO_L2_BITRATE_256K == params->au_l2_bitrate) ? 256 : 384; | 346 | is_384k = V4L2_MPEG_AUDIO_L2_BITRATE_384K == params->au_l2_bitrate; |
347 | set_reg8(client, 0x94, is_384k); | ||
348 | tot_bitrate += is_384k ? 384 : 256; | ||
271 | 349 | ||
272 | /* Note: the total max bitrate is determined by adding the video and audio | 350 | /* Note: the total max bitrate is determined by adding the video and audio |
273 | bitrates together and also adding an extra 768kbit/s to stay on the | 351 | bitrates together and also adding an extra 768kbit/s to stay on the |
@@ -278,16 +356,12 @@ static int saa6752hs_set_bitrate(struct i2c_client* client, | |||
278 | tot_bitrate = MPEG_TOTAL_TARGET_BITRATE_MAX; | 356 | tot_bitrate = MPEG_TOTAL_TARGET_BITRATE_MAX; |
279 | 357 | ||
280 | /* set the total bitrate */ | 358 | /* set the total bitrate */ |
281 | buf[0] = 0xb1; | 359 | set_reg16(client, 0xb1, tot_bitrate); |
282 | buf[1] = tot_bitrate >> 8; | ||
283 | buf[2] = tot_bitrate & 0xff; | ||
284 | i2c_master_send(client, buf, 3); | ||
285 | |||
286 | return 0; | 360 | return 0; |
287 | } | 361 | } |
288 | 362 | ||
289 | static void saa6752hs_set_subsampling(struct i2c_client* client, | 363 | static void saa6752hs_set_subsampling(struct i2c_client *client, |
290 | struct v4l2_format* f) | 364 | struct v4l2_format *f) |
291 | { | 365 | { |
292 | struct saa6752hs_state *h = i2c_get_clientdata(client); | 366 | struct saa6752hs_state *h = i2c_get_clientdata(client); |
293 | int dist_352, dist_480, dist_720; | 367 | int dist_352, dist_480, dist_720; |
@@ -332,7 +406,7 @@ static void saa6752hs_set_subsampling(struct i2c_client* client, | |||
332 | } | 406 | } |
333 | 407 | ||
334 | 408 | ||
335 | static int handle_ctrl(struct saa6752hs_mpeg_params *params, | 409 | static int handle_ctrl(int has_ac3, struct saa6752hs_mpeg_params *params, |
336 | struct v4l2_ext_control *ctrl, unsigned int cmd) | 410 | struct v4l2_ext_control *ctrl, unsigned int cmd) |
337 | { | 411 | { |
338 | int old = 0, new; | 412 | int old = 0, new; |
@@ -379,8 +453,9 @@ static int handle_ctrl(struct saa6752hs_mpeg_params *params, | |||
379 | params->ts_pid_pcr = new; | 453 | params->ts_pid_pcr = new; |
380 | break; | 454 | break; |
381 | case V4L2_CID_MPEG_AUDIO_ENCODING: | 455 | case V4L2_CID_MPEG_AUDIO_ENCODING: |
382 | old = V4L2_MPEG_AUDIO_ENCODING_LAYER_2; | 456 | old = params->au_encoding; |
383 | if (set && new != old) | 457 | if (set && new != V4L2_MPEG_AUDIO_ENCODING_LAYER_2 && |
458 | (!has_ac3 || new != V4L2_MPEG_AUDIO_ENCODING_AC3)) | ||
384 | return -ERANGE; | 459 | return -ERANGE; |
385 | new = old; | 460 | new = old; |
386 | break; | 461 | break; |
@@ -395,6 +470,19 @@ static int handle_ctrl(struct saa6752hs_mpeg_params *params, | |||
395 | new = V4L2_MPEG_AUDIO_L2_BITRATE_384K; | 470 | new = V4L2_MPEG_AUDIO_L2_BITRATE_384K; |
396 | params->au_l2_bitrate = new; | 471 | params->au_l2_bitrate = new; |
397 | break; | 472 | break; |
473 | case V4L2_CID_MPEG_AUDIO_AC3_BITRATE: | ||
474 | if (!has_ac3) | ||
475 | return -EINVAL; | ||
476 | old = params->au_ac3_bitrate; | ||
477 | if (set && new != V4L2_MPEG_AUDIO_AC3_BITRATE_256K && | ||
478 | new != V4L2_MPEG_AUDIO_AC3_BITRATE_384K) | ||
479 | return -ERANGE; | ||
480 | if (new <= V4L2_MPEG_AUDIO_AC3_BITRATE_256K) | ||
481 | new = V4L2_MPEG_AUDIO_AC3_BITRATE_256K; | ||
482 | else | ||
483 | new = V4L2_MPEG_AUDIO_AC3_BITRATE_384K; | ||
484 | params->au_ac3_bitrate = new; | ||
485 | break; | ||
398 | case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: | 486 | case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: |
399 | old = V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000; | 487 | old = V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000; |
400 | if (set && new != old) | 488 | if (set && new != old) |
@@ -448,17 +536,19 @@ static int handle_ctrl(struct saa6752hs_mpeg_params *params, | |||
448 | return 0; | 536 | return 0; |
449 | } | 537 | } |
450 | 538 | ||
451 | static int saa6752hs_qctrl(struct saa6752hs_mpeg_params *params, | 539 | static int saa6752hs_qctrl(struct saa6752hs_state *h, |
452 | struct v4l2_queryctrl *qctrl) | 540 | struct v4l2_queryctrl *qctrl) |
453 | { | 541 | { |
542 | struct saa6752hs_mpeg_params *params = &h->params; | ||
454 | int err; | 543 | int err; |
455 | 544 | ||
456 | switch (qctrl->id) { | 545 | switch (qctrl->id) { |
457 | case V4L2_CID_MPEG_AUDIO_ENCODING: | 546 | case V4L2_CID_MPEG_AUDIO_ENCODING: |
458 | return v4l2_ctrl_query_fill(qctrl, | 547 | return v4l2_ctrl_query_fill(qctrl, |
459 | V4L2_MPEG_AUDIO_ENCODING_LAYER_2, | 548 | V4L2_MPEG_AUDIO_ENCODING_LAYER_2, |
460 | V4L2_MPEG_AUDIO_ENCODING_LAYER_2, 1, | 549 | h->has_ac3 ? V4L2_MPEG_AUDIO_ENCODING_AC3 : |
461 | V4L2_MPEG_AUDIO_ENCODING_LAYER_2); | 550 | V4L2_MPEG_AUDIO_ENCODING_LAYER_2, |
551 | 1, V4L2_MPEG_AUDIO_ENCODING_LAYER_2); | ||
462 | 552 | ||
463 | case V4L2_CID_MPEG_AUDIO_L2_BITRATE: | 553 | case V4L2_CID_MPEG_AUDIO_L2_BITRATE: |
464 | return v4l2_ctrl_query_fill(qctrl, | 554 | return v4l2_ctrl_query_fill(qctrl, |
@@ -466,6 +556,14 @@ static int saa6752hs_qctrl(struct saa6752hs_mpeg_params *params, | |||
466 | V4L2_MPEG_AUDIO_L2_BITRATE_384K, 1, | 556 | V4L2_MPEG_AUDIO_L2_BITRATE_384K, 1, |
467 | V4L2_MPEG_AUDIO_L2_BITRATE_256K); | 557 | V4L2_MPEG_AUDIO_L2_BITRATE_256K); |
468 | 558 | ||
559 | case V4L2_CID_MPEG_AUDIO_AC3_BITRATE: | ||
560 | if (!h->has_ac3) | ||
561 | return -EINVAL; | ||
562 | return v4l2_ctrl_query_fill(qctrl, | ||
563 | V4L2_MPEG_AUDIO_AC3_BITRATE_256K, | ||
564 | V4L2_MPEG_AUDIO_AC3_BITRATE_384K, 1, | ||
565 | V4L2_MPEG_AUDIO_AC3_BITRATE_256K); | ||
566 | |||
469 | case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: | 567 | case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: |
470 | return v4l2_ctrl_query_fill(qctrl, | 568 | return v4l2_ctrl_query_fill(qctrl, |
471 | V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000, | 569 | V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000, |
@@ -512,44 +610,57 @@ static int saa6752hs_qctrl(struct saa6752hs_mpeg_params *params, | |||
512 | return -EINVAL; | 610 | return -EINVAL; |
513 | } | 611 | } |
514 | 612 | ||
515 | static int saa6752hs_qmenu(struct saa6752hs_mpeg_params *params, | 613 | static int saa6752hs_qmenu(struct saa6752hs_state *h, |
516 | struct v4l2_querymenu *qmenu) | 614 | struct v4l2_querymenu *qmenu) |
517 | { | 615 | { |
518 | static const char *mpeg_audio_l2_bitrate[] = { | 616 | static const u32 mpeg_audio_encoding[] = { |
519 | "", | 617 | V4L2_MPEG_AUDIO_ENCODING_LAYER_2, |
520 | "", | 618 | V4L2_CTRL_MENU_IDS_END |
521 | "", | 619 | }; |
522 | "", | 620 | static const u32 mpeg_audio_ac3_encoding[] = { |
523 | "", | 621 | V4L2_MPEG_AUDIO_ENCODING_LAYER_2, |
524 | "", | 622 | V4L2_MPEG_AUDIO_ENCODING_AC3, |
525 | "", | 623 | V4L2_CTRL_MENU_IDS_END |
526 | "", | 624 | }; |
527 | "", | 625 | static u32 mpeg_audio_l2_bitrate[] = { |
528 | "", | 626 | V4L2_MPEG_AUDIO_L2_BITRATE_256K, |
529 | "", | 627 | V4L2_MPEG_AUDIO_L2_BITRATE_384K, |
530 | "256 kbps", | 628 | V4L2_CTRL_MENU_IDS_END |
531 | "", | 629 | }; |
532 | "384 kbps", | 630 | static u32 mpeg_audio_ac3_bitrate[] = { |
533 | NULL | 631 | V4L2_MPEG_AUDIO_AC3_BITRATE_256K, |
632 | V4L2_MPEG_AUDIO_AC3_BITRATE_384K, | ||
633 | V4L2_CTRL_MENU_IDS_END | ||
534 | }; | 634 | }; |
535 | struct v4l2_queryctrl qctrl; | 635 | struct v4l2_queryctrl qctrl; |
536 | int err; | 636 | int err; |
537 | 637 | ||
538 | qctrl.id = qmenu->id; | 638 | qctrl.id = qmenu->id; |
539 | err = saa6752hs_qctrl(params, &qctrl); | 639 | err = saa6752hs_qctrl(h, &qctrl); |
540 | if (err) | 640 | if (err) |
541 | return err; | 641 | return err; |
542 | if (qmenu->id == V4L2_CID_MPEG_AUDIO_L2_BITRATE) | 642 | switch (qmenu->id) { |
543 | return v4l2_ctrl_query_menu(qmenu, &qctrl, | 643 | case V4L2_CID_MPEG_AUDIO_L2_BITRATE: |
644 | return v4l2_ctrl_query_menu_valid_items(qmenu, | ||
544 | mpeg_audio_l2_bitrate); | 645 | mpeg_audio_l2_bitrate); |
545 | return v4l2_ctrl_query_menu(qmenu, &qctrl, | 646 | case V4L2_CID_MPEG_AUDIO_AC3_BITRATE: |
546 | v4l2_ctrl_get_menu(qmenu->id)); | 647 | if (!h->has_ac3) |
648 | return -EINVAL; | ||
649 | return v4l2_ctrl_query_menu_valid_items(qmenu, | ||
650 | mpeg_audio_ac3_bitrate); | ||
651 | case V4L2_CID_MPEG_AUDIO_ENCODING: | ||
652 | return v4l2_ctrl_query_menu_valid_items(qmenu, | ||
653 | h->has_ac3 ? mpeg_audio_ac3_encoding : | ||
654 | mpeg_audio_encoding); | ||
655 | } | ||
656 | return v4l2_ctrl_query_menu(qmenu, &qctrl, NULL); | ||
547 | } | 657 | } |
548 | 658 | ||
549 | static int saa6752hs_init(struct i2c_client* client) | 659 | static int saa6752hs_init(struct i2c_client *client, u32 leading_null_bytes) |
550 | { | 660 | { |
551 | unsigned char buf[9], buf2[4]; | 661 | unsigned char buf[9], buf2[4]; |
552 | struct saa6752hs_state *h; | 662 | struct saa6752hs_state *h; |
663 | unsigned size; | ||
553 | u32 crc; | 664 | u32 crc; |
554 | unsigned char localPAT[256]; | 665 | unsigned char localPAT[256]; |
555 | unsigned char localPMT[256]; | 666 | unsigned char localPMT[256]; |
@@ -557,45 +668,31 @@ static int saa6752hs_init(struct i2c_client* client) | |||
557 | h = i2c_get_clientdata(client); | 668 | h = i2c_get_clientdata(client); |
558 | 669 | ||
559 | /* Set video format - must be done first as it resets other settings */ | 670 | /* Set video format - must be done first as it resets other settings */ |
560 | buf[0] = 0x41; | 671 | set_reg8(client, 0x41, h->video_format); |
561 | buf[1] = h->video_format; | ||
562 | i2c_master_send(client, buf, 2); | ||
563 | 672 | ||
564 | /* Set number of lines in input signal */ | 673 | /* Set number of lines in input signal */ |
565 | buf[0] = 0x40; | 674 | set_reg8(client, 0x40, (h->standard & V4L2_STD_525_60) ? 1 : 0); |
566 | buf[1] = 0x00; | ||
567 | if (h->standard & V4L2_STD_525_60) | ||
568 | buf[1] = 0x01; | ||
569 | i2c_master_send(client, buf, 2); | ||
570 | 675 | ||
571 | /* set bitrate */ | 676 | /* set bitrate */ |
572 | saa6752hs_set_bitrate(client, &h->params); | 677 | saa6752hs_set_bitrate(client, h); |
573 | 678 | ||
574 | /* Set GOP structure {3, 13} */ | 679 | /* Set GOP structure {3, 13} */ |
575 | buf[0] = 0x72; | 680 | set_reg16(client, 0x72, 0x030d); |
576 | buf[1] = 0x03; | ||
577 | buf[2] = 0x0D; | ||
578 | i2c_master_send(client,buf,3); | ||
579 | 681 | ||
580 | /* Set minimum Q-scale {4} */ | 682 | /* Set minimum Q-scale {4} */ |
581 | buf[0] = 0x82; | 683 | set_reg8(client, 0x82, 0x04); |
582 | buf[1] = 0x04; | ||
583 | i2c_master_send(client,buf,2); | ||
584 | 684 | ||
585 | /* Set maximum Q-scale {12} */ | 685 | /* Set maximum Q-scale {12} */ |
586 | buf[0] = 0x83; | 686 | set_reg8(client, 0x83, 0x0c); |
587 | buf[1] = 0x0C; | ||
588 | i2c_master_send(client,buf,2); | ||
589 | 687 | ||
590 | /* Set Output Protocol */ | 688 | /* Set Output Protocol */ |
591 | buf[0] = 0xD0; | 689 | set_reg8(client, 0xd0, 0x81); |
592 | buf[1] = 0x81; | ||
593 | i2c_master_send(client,buf,2); | ||
594 | 690 | ||
595 | /* Set video output stream format {TS} */ | 691 | /* Set video output stream format {TS} */ |
596 | buf[0] = 0xB0; | 692 | set_reg8(client, 0xb0, 0x05); |
597 | buf[1] = 0x05; | 693 | |
598 | i2c_master_send(client,buf,2); | 694 | /* Set leading null byte for TS */ |
695 | set_reg16(client, 0xf6, leading_null_bytes); | ||
599 | 696 | ||
600 | /* compute PAT */ | 697 | /* compute PAT */ |
601 | memcpy(localPAT, PAT, sizeof(PAT)); | 698 | memcpy(localPAT, PAT, sizeof(PAT)); |
@@ -608,7 +705,13 @@ static int saa6752hs_init(struct i2c_client* client) | |||
608 | localPAT[sizeof(PAT) - 1] = crc & 0xFF; | 705 | localPAT[sizeof(PAT) - 1] = crc & 0xFF; |
609 | 706 | ||
610 | /* compute PMT */ | 707 | /* compute PMT */ |
611 | memcpy(localPMT, PMT, sizeof(PMT)); | 708 | if (h->params.au_encoding == V4L2_MPEG_AUDIO_ENCODING_AC3) { |
709 | size = sizeof(PMT_AC3); | ||
710 | memcpy(localPMT, PMT_AC3, size); | ||
711 | } else { | ||
712 | size = sizeof(PMT); | ||
713 | memcpy(localPMT, PMT, size); | ||
714 | } | ||
612 | localPMT[3] = 0x40 | ((h->params.ts_pid_pmt >> 8) & 0x0f); | 715 | localPMT[3] = 0x40 | ((h->params.ts_pid_pmt >> 8) & 0x0f); |
613 | localPMT[4] = h->params.ts_pid_pmt & 0xff; | 716 | localPMT[4] = h->params.ts_pid_pmt & 0xff; |
614 | localPMT[15] = 0xE0 | ((h->params.ts_pid_pcr >> 8) & 0x0F); | 717 | localPMT[15] = 0xE0 | ((h->params.ts_pid_pcr >> 8) & 0x0F); |
@@ -617,40 +720,28 @@ static int saa6752hs_init(struct i2c_client* client) | |||
617 | localPMT[21] = h->params.ts_pid_video & 0xFF; | 720 | localPMT[21] = h->params.ts_pid_video & 0xFF; |
618 | localPMT[25] = 0xE0 | ((h->params.ts_pid_audio >> 8) & 0x0F); | 721 | localPMT[25] = 0xE0 | ((h->params.ts_pid_audio >> 8) & 0x0F); |
619 | localPMT[26] = h->params.ts_pid_audio & 0xFF; | 722 | localPMT[26] = h->params.ts_pid_audio & 0xFF; |
620 | crc = crc32_be(~0, &localPMT[7], sizeof(PMT) - 7 - 4); | 723 | crc = crc32_be(~0, &localPMT[7], size - 7 - 4); |
621 | localPMT[sizeof(PMT) - 4] = (crc >> 24) & 0xFF; | 724 | localPMT[size - 4] = (crc >> 24) & 0xFF; |
622 | localPMT[sizeof(PMT) - 3] = (crc >> 16) & 0xFF; | 725 | localPMT[size - 3] = (crc >> 16) & 0xFF; |
623 | localPMT[sizeof(PMT) - 2] = (crc >> 8) & 0xFF; | 726 | localPMT[size - 2] = (crc >> 8) & 0xFF; |
624 | localPMT[sizeof(PMT) - 1] = crc & 0xFF; | 727 | localPMT[size - 1] = crc & 0xFF; |
625 | 728 | ||
626 | /* Set Audio PID */ | 729 | /* Set Audio PID */ |
627 | buf[0] = 0xC1; | 730 | set_reg16(client, 0xc1, h->params.ts_pid_audio); |
628 | buf[1] = (h->params.ts_pid_audio >> 8) & 0xFF; | ||
629 | buf[2] = h->params.ts_pid_audio & 0xFF; | ||
630 | i2c_master_send(client,buf,3); | ||
631 | 731 | ||
632 | /* Set Video PID */ | 732 | /* Set Video PID */ |
633 | buf[0] = 0xC0; | 733 | set_reg16(client, 0xc0, h->params.ts_pid_video); |
634 | buf[1] = (h->params.ts_pid_video >> 8) & 0xFF; | ||
635 | buf[2] = h->params.ts_pid_video & 0xFF; | ||
636 | i2c_master_send(client,buf,3); | ||
637 | 734 | ||
638 | /* Set PCR PID */ | 735 | /* Set PCR PID */ |
639 | buf[0] = 0xC4; | 736 | set_reg16(client, 0xc4, h->params.ts_pid_pcr); |
640 | buf[1] = (h->params.ts_pid_pcr >> 8) & 0xFF; | ||
641 | buf[2] = h->params.ts_pid_pcr & 0xFF; | ||
642 | i2c_master_send(client,buf,3); | ||
643 | 737 | ||
644 | /* Send SI tables */ | 738 | /* Send SI tables */ |
645 | i2c_master_send(client,localPAT,sizeof(PAT)); | 739 | i2c_master_send(client, localPAT, sizeof(PAT)); |
646 | i2c_master_send(client,localPMT,sizeof(PMT)); | 740 | i2c_master_send(client, localPMT, size); |
647 | 741 | ||
648 | /* mute then unmute audio. This removes buzzing artefacts */ | 742 | /* mute then unmute audio. This removes buzzing artefacts */ |
649 | buf[0] = 0xa4; | 743 | set_reg8(client, 0xa4, 1); |
650 | buf[1] = 1; | 744 | set_reg8(client, 0xa4, 0); |
651 | i2c_master_send(client, buf, 2); | ||
652 | buf[1] = 0; | ||
653 | i2c_master_send(client, buf, 2); | ||
654 | 745 | ||
655 | /* start it going */ | 746 | /* start it going */ |
656 | saa6752hs_chip_command(client, SAA6752HS_COMMAND_START); | 747 | saa6752hs_chip_command(client, SAA6752HS_COMMAND_START); |
@@ -688,45 +779,6 @@ static int saa6752hs_init(struct i2c_client* client) | |||
688 | return 0; | 779 | return 0; |
689 | } | 780 | } |
690 | 781 | ||
691 | static int saa6752hs_attach(struct i2c_adapter *adap, int addr, int kind) | ||
692 | { | ||
693 | struct saa6752hs_state *h; | ||
694 | |||
695 | |||
696 | if (NULL == (h = kzalloc(sizeof(*h), GFP_KERNEL))) | ||
697 | return -ENOMEM; | ||
698 | h->client = client_template; | ||
699 | h->params = param_defaults; | ||
700 | h->client.adapter = adap; | ||
701 | h->client.addr = addr; | ||
702 | |||
703 | /* Assume 625 input lines */ | ||
704 | h->standard = 0; | ||
705 | |||
706 | i2c_set_clientdata(&h->client, h); | ||
707 | i2c_attach_client(&h->client); | ||
708 | |||
709 | v4l_info(&h->client,"saa6752hs: chip found @ 0x%x\n", addr<<1); | ||
710 | return 0; | ||
711 | } | ||
712 | |||
713 | static int saa6752hs_probe(struct i2c_adapter *adap) | ||
714 | { | ||
715 | if (adap->class & I2C_CLASS_TV_ANALOG) | ||
716 | return i2c_probe(adap, &addr_data, saa6752hs_attach); | ||
717 | return 0; | ||
718 | } | ||
719 | |||
720 | static int saa6752hs_detach(struct i2c_client *client) | ||
721 | { | ||
722 | struct saa6752hs_state *h; | ||
723 | |||
724 | h = i2c_get_clientdata(client); | ||
725 | i2c_detach_client(client); | ||
726 | kfree(h); | ||
727 | return 0; | ||
728 | } | ||
729 | |||
730 | static int | 782 | static int |
731 | saa6752hs_command(struct i2c_client *client, unsigned int cmd, void *arg) | 783 | saa6752hs_command(struct i2c_client *client, unsigned int cmd, void *arg) |
732 | { | 784 | { |
@@ -737,14 +789,13 @@ saa6752hs_command(struct i2c_client *client, unsigned int cmd, void *arg) | |||
737 | int i; | 789 | int i; |
738 | 790 | ||
739 | switch (cmd) { | 791 | switch (cmd) { |
792 | case VIDIOC_INT_INIT: | ||
793 | /* apply settings and start encoder */ | ||
794 | saa6752hs_init(client, *(u32 *)arg); | ||
795 | break; | ||
740 | case VIDIOC_S_EXT_CTRLS: | 796 | case VIDIOC_S_EXT_CTRLS: |
741 | if (ctrls->ctrl_class != V4L2_CTRL_CLASS_MPEG) | 797 | if (ctrls->ctrl_class != V4L2_CTRL_CLASS_MPEG) |
742 | return -EINVAL; | 798 | return -EINVAL; |
743 | if (ctrls->count == 0) { | ||
744 | /* apply settings and start encoder */ | ||
745 | saa6752hs_init(client); | ||
746 | break; | ||
747 | } | ||
748 | /* fall through */ | 799 | /* fall through */ |
749 | case VIDIOC_TRY_EXT_CTRLS: | 800 | case VIDIOC_TRY_EXT_CTRLS: |
750 | case VIDIOC_G_EXT_CTRLS: | 801 | case VIDIOC_G_EXT_CTRLS: |
@@ -752,7 +803,8 @@ saa6752hs_command(struct i2c_client *client, unsigned int cmd, void *arg) | |||
752 | return -EINVAL; | 803 | return -EINVAL; |
753 | params = h->params; | 804 | params = h->params; |
754 | for (i = 0; i < ctrls->count; i++) { | 805 | for (i = 0; i < ctrls->count; i++) { |
755 | if ((err = handle_ctrl(¶ms, ctrls->controls + i, cmd))) { | 806 | err = handle_ctrl(h->has_ac3, ¶ms, ctrls->controls + i, cmd); |
807 | if (err) { | ||
756 | ctrls->error_idx = i; | 808 | ctrls->error_idx = i; |
757 | return err; | 809 | return err; |
758 | } | 810 | } |
@@ -760,9 +812,9 @@ saa6752hs_command(struct i2c_client *client, unsigned int cmd, void *arg) | |||
760 | h->params = params; | 812 | h->params = params; |
761 | break; | 813 | break; |
762 | case VIDIOC_QUERYCTRL: | 814 | case VIDIOC_QUERYCTRL: |
763 | return saa6752hs_qctrl(&h->params, arg); | 815 | return saa6752hs_qctrl(h, arg); |
764 | case VIDIOC_QUERYMENU: | 816 | case VIDIOC_QUERYMENU: |
765 | return saa6752hs_qmenu(&h->params, arg); | 817 | return saa6752hs_qmenu(h, arg); |
766 | case VIDIOC_G_FMT: | 818 | case VIDIOC_G_FMT: |
767 | { | 819 | { |
768 | struct v4l2_format *f = arg; | 820 | struct v4l2_format *f = arg; |
@@ -785,6 +837,11 @@ saa6752hs_command(struct i2c_client *client, unsigned int cmd, void *arg) | |||
785 | case VIDIOC_S_STD: | 837 | case VIDIOC_S_STD: |
786 | h->standard = *((v4l2_std_id *) arg); | 838 | h->standard = *((v4l2_std_id *) arg); |
787 | break; | 839 | break; |
840 | |||
841 | case VIDIOC_G_CHIP_IDENT: | ||
842 | return v4l2_chip_ident_i2c_client(client, | ||
843 | arg, h->chip, h->revision); | ||
844 | |||
788 | default: | 845 | default: |
789 | /* nothing */ | 846 | /* nothing */ |
790 | break; | 847 | break; |
@@ -793,36 +850,55 @@ saa6752hs_command(struct i2c_client *client, unsigned int cmd, void *arg) | |||
793 | return err; | 850 | return err; |
794 | } | 851 | } |
795 | 852 | ||
796 | /* ----------------------------------------------------------------------- */ | 853 | static int saa6752hs_probe(struct i2c_client *client, |
854 | const struct i2c_device_id *id) | ||
855 | { | ||
856 | struct saa6752hs_state *h = kzalloc(sizeof(*h), GFP_KERNEL); | ||
857 | u8 addr = 0x13; | ||
858 | u8 data[12]; | ||
797 | 859 | ||
798 | static struct i2c_driver driver = { | 860 | v4l_info(client, "chip found @ 0x%x (%s)\n", |
799 | .driver = { | 861 | client->addr << 1, client->adapter->name); |
800 | .name = "saa6752hs", | 862 | if (h == NULL) |
801 | }, | 863 | return -ENOMEM; |
802 | .id = I2C_DRIVERID_SAA6752HS, | ||
803 | .attach_adapter = saa6752hs_probe, | ||
804 | .detach_client = saa6752hs_detach, | ||
805 | .command = saa6752hs_command, | ||
806 | }; | ||
807 | 864 | ||
808 | static struct i2c_client client_template = | 865 | i2c_master_send(client, &addr, 1); |
809 | { | 866 | i2c_master_recv(client, data, sizeof(data)); |
810 | .name = "saa6752hs", | 867 | h->chip = V4L2_IDENT_SAA6752HS; |
811 | .driver = &driver, | 868 | h->revision = (data[8] << 8) | data[9]; |
812 | }; | 869 | h->has_ac3 = 0; |
870 | if (h->revision == 0x0206) { | ||
871 | h->chip = V4L2_IDENT_SAA6752HS_AC3; | ||
872 | h->has_ac3 = 1; | ||
873 | v4l_info(client, "support AC-3\n"); | ||
874 | } | ||
875 | h->params = param_defaults; | ||
876 | h->standard = 0; /* Assume 625 input lines */ | ||
813 | 877 | ||
814 | static int __init saa6752hs_init_module(void) | 878 | i2c_set_clientdata(client, h); |
815 | { | 879 | return 0; |
816 | return i2c_add_driver(&driver); | ||
817 | } | 880 | } |
818 | 881 | ||
819 | static void __exit saa6752hs_cleanup_module(void) | 882 | static int saa6752hs_remove(struct i2c_client *client) |
820 | { | 883 | { |
821 | i2c_del_driver(&driver); | 884 | kfree(i2c_get_clientdata(client)); |
885 | return 0; | ||
822 | } | 886 | } |
823 | 887 | ||
824 | module_init(saa6752hs_init_module); | 888 | static const struct i2c_device_id saa6752hs_id[] = { |
825 | module_exit(saa6752hs_cleanup_module); | 889 | { "saa6752hs", 0 }, |
890 | { } | ||
891 | }; | ||
892 | MODULE_DEVICE_TABLE(i2c, saa6752hs_id); | ||
893 | |||
894 | static struct v4l2_i2c_driver_data v4l2_i2c_data = { | ||
895 | .name = "saa6752hs", | ||
896 | .driverid = I2C_DRIVERID_SAA6752HS, | ||
897 | .command = saa6752hs_command, | ||
898 | .probe = saa6752hs_probe, | ||
899 | .remove = saa6752hs_remove, | ||
900 | .id_table = saa6752hs_id, | ||
901 | }; | ||
826 | 902 | ||
827 | /* | 903 | /* |
828 | * Overrides for Emacs so that we follow Linus's tabbing style. | 904 | * Overrides for Emacs so that we follow Linus's tabbing style. |
diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 98364d171def..ddc5402c5fb0 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c | |||
@@ -3260,6 +3260,7 @@ struct saa7134_board saa7134_boards[] = { | |||
3260 | }, | 3260 | }, |
3261 | [SAA7134_BOARD_HAUPPAUGE_HVR1110] = { | 3261 | [SAA7134_BOARD_HAUPPAUGE_HVR1110] = { |
3262 | /* Thomas Genty <tomlohave@gmail.com> */ | 3262 | /* Thomas Genty <tomlohave@gmail.com> */ |
3263 | /* David Bentham <db260179@hotmail.com> */ | ||
3263 | .name = "Hauppauge WinTV-HVR1110 DVB-T/Hybrid", | 3264 | .name = "Hauppauge WinTV-HVR1110 DVB-T/Hybrid", |
3264 | .audio_clock = 0x00187de7, | 3265 | .audio_clock = 0x00187de7, |
3265 | .tuner_type = TUNER_PHILIPS_TDA8290, | 3266 | .tuner_type = TUNER_PHILIPS_TDA8290, |
@@ -3268,23 +3269,26 @@ struct saa7134_board saa7134_boards[] = { | |||
3268 | .radio_addr = ADDR_UNSET, | 3269 | .radio_addr = ADDR_UNSET, |
3269 | .tuner_config = 1, | 3270 | .tuner_config = 1, |
3270 | .mpeg = SAA7134_MPEG_DVB, | 3271 | .mpeg = SAA7134_MPEG_DVB, |
3272 | .gpiomask = 0x0200100, | ||
3271 | .inputs = {{ | 3273 | .inputs = {{ |
3272 | .name = name_tv, | 3274 | .name = name_tv, |
3273 | .vmux = 1, | 3275 | .vmux = 1, |
3274 | .amux = TV, | 3276 | .amux = TV, |
3275 | .tv = 1, | 3277 | .tv = 1, |
3276 | },{ | 3278 | .gpio = 0x0000100, |
3277 | .name = name_comp1, | 3279 | }, { |
3278 | .vmux = 3, | 3280 | .name = name_comp1, |
3279 | .amux = LINE2, /* FIXME: audio doesn't work on svideo/composite */ | 3281 | .vmux = 3, |
3280 | },{ | 3282 | .amux = LINE1, |
3281 | .name = name_svideo, | 3283 | }, { |
3282 | .vmux = 8, | 3284 | .name = name_svideo, |
3283 | .amux = LINE2, /* FIXME: audio doesn't work on svideo/composite */ | 3285 | .vmux = 8, |
3284 | }}, | 3286 | .amux = LINE1, |
3287 | } }, | ||
3285 | .radio = { | 3288 | .radio = { |
3286 | .name = name_radio, | 3289 | .name = name_radio, |
3287 | .amux = TV, | 3290 | .amux = TV, |
3291 | .gpio = 0x0200100, | ||
3288 | }, | 3292 | }, |
3289 | }, | 3293 | }, |
3290 | [SAA7134_BOARD_CINERGY_HT_PCMCIA] = { | 3294 | [SAA7134_BOARD_CINERGY_HT_PCMCIA] = { |
@@ -3388,6 +3392,42 @@ struct saa7134_board saa7134_boards[] = { | |||
3388 | .amux = 0, | 3392 | .amux = 0, |
3389 | }, | 3393 | }, |
3390 | }, | 3394 | }, |
3395 | [SAA7134_BOARD_ENCORE_ENLTV_FM53] = { | ||
3396 | .name = "Encore ENLTV-FM v5.3", | ||
3397 | .audio_clock = 0x00200000, | ||
3398 | .tuner_type = TUNER_TNF_5335MF, | ||
3399 | .radio_type = UNSET, | ||
3400 | .tuner_addr = ADDR_UNSET, | ||
3401 | .radio_addr = ADDR_UNSET, | ||
3402 | .gpiomask = 0x7000, | ||
3403 | .inputs = { { | ||
3404 | .name = name_tv, | ||
3405 | .vmux = 1, | ||
3406 | .amux = 1, | ||
3407 | .tv = 1, | ||
3408 | .gpio = 0x50000, | ||
3409 | }, { | ||
3410 | .name = name_comp1, | ||
3411 | .vmux = 3, | ||
3412 | .amux = 2, | ||
3413 | .gpio = 0x2000, | ||
3414 | }, { | ||
3415 | .name = name_svideo, | ||
3416 | .vmux = 8, | ||
3417 | .amux = 2, | ||
3418 | .gpio = 0x2000, | ||
3419 | } }, | ||
3420 | .radio = { | ||
3421 | .name = name_radio, | ||
3422 | .vmux = 1, | ||
3423 | .amux = 1, | ||
3424 | }, | ||
3425 | .mute = { | ||
3426 | .name = name_mute, | ||
3427 | .gpio = 0xf000, | ||
3428 | .amux = 0, | ||
3429 | }, | ||
3430 | }, | ||
3391 | [SAA7134_BOARD_CINERGY_HT_PCI] = { | 3431 | [SAA7134_BOARD_CINERGY_HT_PCI] = { |
3392 | .name = "Terratec Cinergy HT PCI", | 3432 | .name = "Terratec Cinergy HT PCI", |
3393 | .audio_clock = 0x00187de7, | 3433 | .audio_clock = 0x00187de7, |
@@ -3631,6 +3671,40 @@ struct saa7134_board saa7134_boards[] = { | |||
3631 | .tv = 1, | 3671 | .tv = 1, |
3632 | }}, | 3672 | }}, |
3633 | }, | 3673 | }, |
3674 | [SAA7134_BOARD_AVERMEDIA_M135A] = { | ||
3675 | .name = "Avermedia PCI pure analog (M135A)", | ||
3676 | .audio_clock = 0x00187de7, | ||
3677 | .tuner_type = TUNER_PHILIPS_TDA8290, | ||
3678 | .radio_type = UNSET, | ||
3679 | .tuner_addr = ADDR_UNSET, | ||
3680 | .radio_addr = ADDR_UNSET, | ||
3681 | .tuner_config = 2, | ||
3682 | .gpiomask = 0x020200000, | ||
3683 | .inputs = {{ | ||
3684 | .name = name_tv, | ||
3685 | .vmux = 1, | ||
3686 | .amux = TV, | ||
3687 | .tv = 1, | ||
3688 | }, { | ||
3689 | .name = name_comp1, | ||
3690 | .vmux = 3, | ||
3691 | .amux = LINE1, | ||
3692 | }, { | ||
3693 | .name = name_svideo, | ||
3694 | .vmux = 8, | ||
3695 | .amux = LINE1, | ||
3696 | } }, | ||
3697 | .radio = { | ||
3698 | .name = name_radio, | ||
3699 | .amux = TV, | ||
3700 | .gpio = 0x00200000, | ||
3701 | }, | ||
3702 | .mute = { | ||
3703 | .name = name_mute, | ||
3704 | .amux = TV, | ||
3705 | .gpio = 0x01, | ||
3706 | }, | ||
3707 | }, | ||
3634 | [SAA7134_BOARD_BEHOLD_401] = { | 3708 | [SAA7134_BOARD_BEHOLD_401] = { |
3635 | /* Beholder Intl. Ltd. 2008 */ | 3709 | /* Beholder Intl. Ltd. 2008 */ |
3636 | /*Dmitry Belimov <d.belimov@gmail.com> */ | 3710 | /*Dmitry Belimov <d.belimov@gmail.com> */ |
@@ -4409,6 +4483,129 @@ struct saa7134_board saa7134_boards[] = { | |||
4409 | /* no DVB support for now */ | 4483 | /* no DVB support for now */ |
4410 | /* .mpeg = SAA7134_MPEG_DVB, */ | 4484 | /* .mpeg = SAA7134_MPEG_DVB, */ |
4411 | }, | 4485 | }, |
4486 | [SAA7134_BOARD_ASUSTeK_TIGER_3IN1] = { | ||
4487 | .name = "Asus Tiger 3in1", | ||
4488 | .audio_clock = 0x00187de7, | ||
4489 | .tuner_type = TUNER_PHILIPS_TDA8290, | ||
4490 | .radio_type = UNSET, | ||
4491 | .tuner_addr = ADDR_UNSET, | ||
4492 | .radio_addr = ADDR_UNSET, | ||
4493 | .tuner_config = 2, | ||
4494 | .gpiomask = 1 << 21, | ||
4495 | .mpeg = SAA7134_MPEG_DVB, | ||
4496 | .inputs = {{ | ||
4497 | .name = name_tv, | ||
4498 | .vmux = 1, | ||
4499 | .amux = TV, | ||
4500 | .tv = 1, | ||
4501 | }, { | ||
4502 | .name = name_comp, | ||
4503 | .vmux = 0, | ||
4504 | .amux = LINE2, | ||
4505 | }, { | ||
4506 | .name = name_svideo, | ||
4507 | .vmux = 8, | ||
4508 | .amux = LINE2, | ||
4509 | } }, | ||
4510 | .radio = { | ||
4511 | .name = name_radio, | ||
4512 | .amux = TV, | ||
4513 | .gpio = 0x0200000, | ||
4514 | }, | ||
4515 | }, | ||
4516 | [SAA7134_BOARD_REAL_ANGEL_220] = { | ||
4517 | .name = "Zogis Real Angel 220", | ||
4518 | .audio_clock = 0x00187de7, | ||
4519 | .tuner_type = TUNER_TNF_5335MF, | ||
4520 | .radio_type = UNSET, | ||
4521 | .tuner_addr = ADDR_UNSET, | ||
4522 | .radio_addr = ADDR_UNSET, | ||
4523 | .gpiomask = 0x801a8087, | ||
4524 | .inputs = { { | ||
4525 | .name = name_tv, | ||
4526 | .vmux = 3, | ||
4527 | .amux = LINE2, | ||
4528 | .tv = 1, | ||
4529 | .gpio = 0x624000, | ||
4530 | }, { | ||
4531 | .name = name_comp1, | ||
4532 | .vmux = 1, | ||
4533 | .amux = LINE1, | ||
4534 | .gpio = 0x624000, | ||
4535 | }, { | ||
4536 | .name = name_svideo, | ||
4537 | .vmux = 1, | ||
4538 | .amux = LINE1, | ||
4539 | .gpio = 0x624000, | ||
4540 | } }, | ||
4541 | .radio = { | ||
4542 | .name = name_radio, | ||
4543 | .amux = LINE2, | ||
4544 | .gpio = 0x624001, | ||
4545 | }, | ||
4546 | .mute = { | ||
4547 | .name = name_mute, | ||
4548 | .amux = TV, | ||
4549 | }, | ||
4550 | }, | ||
4551 | [SAA7134_BOARD_ADS_INSTANT_HDTV_PCI] = { | ||
4552 | .name = "ADS Tech Instant HDTV", | ||
4553 | .audio_clock = 0x00187de7, | ||
4554 | .tuner_type = TUNER_PHILIPS_TUV1236D, | ||
4555 | .radio_type = UNSET, | ||
4556 | .tuner_addr = ADDR_UNSET, | ||
4557 | .radio_addr = ADDR_UNSET, | ||
4558 | .tda9887_conf = TDA9887_PRESENT, | ||
4559 | .mpeg = SAA7134_MPEG_DVB, | ||
4560 | .inputs = { { | ||
4561 | .name = name_tv, | ||
4562 | .vmux = 1, | ||
4563 | .amux = TV, | ||
4564 | .tv = 1, | ||
4565 | }, { | ||
4566 | .name = name_comp, | ||
4567 | .vmux = 4, | ||
4568 | .amux = LINE1, | ||
4569 | }, { | ||
4570 | .name = name_svideo, | ||
4571 | .vmux = 8, | ||
4572 | .amux = LINE1, | ||
4573 | } }, | ||
4574 | }, | ||
4575 | [SAA7134_BOARD_ASUSTeK_TIGER] = { | ||
4576 | .name = "Asus Tiger Rev:1.00", | ||
4577 | .audio_clock = 0x00187de7, | ||
4578 | .tuner_type = TUNER_PHILIPS_TDA8290, | ||
4579 | .radio_type = UNSET, | ||
4580 | .tuner_addr = ADDR_UNSET, | ||
4581 | .radio_addr = ADDR_UNSET, | ||
4582 | .tuner_config = 0, | ||
4583 | .mpeg = SAA7134_MPEG_DVB, | ||
4584 | .gpiomask = 0x0200000, | ||
4585 | .inputs = { { | ||
4586 | .name = name_tv, | ||
4587 | .vmux = 1, | ||
4588 | .amux = TV, | ||
4589 | .tv = 1, | ||
4590 | }, { | ||
4591 | .name = name_comp1, | ||
4592 | .vmux = 3, | ||
4593 | .amux = LINE2, | ||
4594 | }, { | ||
4595 | .name = name_comp2, | ||
4596 | .vmux = 0, | ||
4597 | .amux = LINE2, | ||
4598 | }, { | ||
4599 | .name = name_svideo, | ||
4600 | .vmux = 8, | ||
4601 | .amux = LINE2, | ||
4602 | } }, | ||
4603 | .radio = { | ||
4604 | .name = name_radio, | ||
4605 | .amux = TV, | ||
4606 | .gpio = 0x0200000, | ||
4607 | }, | ||
4608 | }, | ||
4412 | }; | 4609 | }; |
4413 | 4610 | ||
4414 | const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards); | 4611 | const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards); |
@@ -4777,6 +4974,12 @@ struct pci_device_id saa7134_pci_tbl[] = { | |||
4777 | 4974 | ||
4778 | },{ | 4975 | },{ |
4779 | .vendor = PCI_VENDOR_ID_PHILIPS, | 4976 | .vendor = PCI_VENDOR_ID_PHILIPS, |
4977 | .device = PCI_DEVICE_ID_PHILIPS_SAA7133, | ||
4978 | .subvendor = 0x1461, /* Avermedia Technologies Inc */ | ||
4979 | .subdevice = 0xf11d, | ||
4980 | .driver_data = SAA7134_BOARD_AVERMEDIA_M135A, | ||
4981 | }, { | ||
4982 | .vendor = PCI_VENDOR_ID_PHILIPS, | ||
4780 | .device = PCI_DEVICE_ID_PHILIPS_SAA7130, | 4983 | .device = PCI_DEVICE_ID_PHILIPS_SAA7130, |
4781 | .subvendor = PCI_VENDOR_ID_PHILIPS, | 4984 | .subvendor = PCI_VENDOR_ID_PHILIPS, |
4782 | .subdevice = 0x2004, | 4985 | .subdevice = 0x2004, |
@@ -5157,6 +5360,12 @@ struct pci_device_id saa7134_pci_tbl[] = { | |||
5157 | .driver_data = SAA7134_BOARD_ENCORE_ENLTV_FM, | 5360 | .driver_data = SAA7134_BOARD_ENCORE_ENLTV_FM, |
5158 | },{ | 5361 | },{ |
5159 | .vendor = PCI_VENDOR_ID_PHILIPS, | 5362 | .vendor = PCI_VENDOR_ID_PHILIPS, |
5363 | .device = PCI_DEVICE_ID_PHILIPS_SAA7130, | ||
5364 | .subvendor = 0x1a7f, | ||
5365 | .subdevice = 0x2008, | ||
5366 | .driver_data = SAA7134_BOARD_ENCORE_ENLTV_FM53, | ||
5367 | }, { | ||
5368 | .vendor = PCI_VENDOR_ID_PHILIPS, | ||
5160 | .device = PCI_DEVICE_ID_PHILIPS_SAA7133, | 5369 | .device = PCI_DEVICE_ID_PHILIPS_SAA7133, |
5161 | .subvendor = 0x153b, | 5370 | .subvendor = 0x153b, |
5162 | .subdevice = 0x1175, | 5371 | .subdevice = 0x1175, |
@@ -5183,8 +5392,8 @@ struct pci_device_id saa7134_pci_tbl[] = { | |||
5183 | .vendor = PCI_VENDOR_ID_PHILIPS, | 5392 | .vendor = PCI_VENDOR_ID_PHILIPS, |
5184 | .device = PCI_DEVICE_ID_PHILIPS_SAA7133, | 5393 | .device = PCI_DEVICE_ID_PHILIPS_SAA7133, |
5185 | .subvendor = 0x1043, | 5394 | .subvendor = 0x1043, |
5186 | .subdevice = 0x4857, | 5395 | .subdevice = 0x4857, /* REV:1.00 */ |
5187 | .driver_data = SAA7134_BOARD_ASUSTeK_P7131_DUAL, | 5396 | .driver_data = SAA7134_BOARD_ASUSTeK_TIGER, |
5188 | },{ | 5397 | },{ |
5189 | .vendor = PCI_VENDOR_ID_PHILIPS, | 5398 | .vendor = PCI_VENDOR_ID_PHILIPS, |
5190 | .device = PCI_DEVICE_ID_PHILIPS_SAA7134, | 5399 | .device = PCI_DEVICE_ID_PHILIPS_SAA7134, |
@@ -5415,6 +5624,12 @@ struct pci_device_id saa7134_pci_tbl[] = { | |||
5415 | .driver_data = SAA7134_BOARD_VIDEOMATE_T750, | 5624 | .driver_data = SAA7134_BOARD_VIDEOMATE_T750, |
5416 | }, { | 5625 | }, { |
5417 | .vendor = PCI_VENDOR_ID_PHILIPS, | 5626 | .vendor = PCI_VENDOR_ID_PHILIPS, |
5627 | .device = PCI_DEVICE_ID_PHILIPS_SAA7133, /* SAA7135HL */ | ||
5628 | .subvendor = 0x1421, | ||
5629 | .subdevice = 0x0380, | ||
5630 | .driver_data = SAA7134_BOARD_ADS_INSTANT_HDTV_PCI, | ||
5631 | }, { | ||
5632 | .vendor = PCI_VENDOR_ID_PHILIPS, | ||
5418 | .device = PCI_DEVICE_ID_PHILIPS_SAA7133, | 5633 | .device = PCI_DEVICE_ID_PHILIPS_SAA7133, |
5419 | .subvendor = 0x5169, | 5634 | .subvendor = 0x5169, |
5420 | .subdevice = 0x1502, | 5635 | .subdevice = 0x1502, |
@@ -5432,6 +5647,12 @@ struct pci_device_id saa7134_pci_tbl[] = { | |||
5432 | .subdevice = 0xf636, | 5647 | .subdevice = 0xf636, |
5433 | .driver_data = SAA7134_BOARD_AVERMEDIA_M103, | 5648 | .driver_data = SAA7134_BOARD_AVERMEDIA_M103, |
5434 | }, { | 5649 | }, { |
5650 | .vendor = PCI_VENDOR_ID_PHILIPS, | ||
5651 | .device = PCI_DEVICE_ID_PHILIPS_SAA7133, | ||
5652 | .subvendor = 0x1043, | ||
5653 | .subdevice = 0x4878, /* REV:1.02G */ | ||
5654 | .driver_data = SAA7134_BOARD_ASUSTeK_TIGER_3IN1, | ||
5655 | }, { | ||
5435 | /* --- boards without eeprom + subsystem ID --- */ | 5656 | /* --- boards without eeprom + subsystem ID --- */ |
5436 | .vendor = PCI_VENDOR_ID_PHILIPS, | 5657 | .vendor = PCI_VENDOR_ID_PHILIPS, |
5437 | .device = PCI_DEVICE_ID_PHILIPS_SAA7134, | 5658 | .device = PCI_DEVICE_ID_PHILIPS_SAA7134, |
@@ -5540,7 +5761,7 @@ static int saa7134_tda8290_callback(struct saa7134_dev *dev, | |||
5540 | return 0; | 5761 | return 0; |
5541 | } | 5762 | } |
5542 | 5763 | ||
5543 | int saa7134_tuner_callback(void *priv, int command, int arg) | 5764 | int saa7134_tuner_callback(void *priv, int component, int command, int arg) |
5544 | { | 5765 | { |
5545 | struct saa7134_dev *dev = priv; | 5766 | struct saa7134_dev *dev = priv; |
5546 | if (dev != NULL) { | 5767 | if (dev != NULL) { |
@@ -5620,6 +5841,7 @@ int saa7134_board_init1(struct saa7134_dev *dev) | |||
5620 | case SAA7134_BOARD_AVERMEDIA_STUDIO_507: | 5841 | case SAA7134_BOARD_AVERMEDIA_STUDIO_507: |
5621 | case SAA7134_BOARD_AVERMEDIA_GO_007_FM: | 5842 | case SAA7134_BOARD_AVERMEDIA_GO_007_FM: |
5622 | case SAA7134_BOARD_AVERMEDIA_777: | 5843 | case SAA7134_BOARD_AVERMEDIA_777: |
5844 | case SAA7134_BOARD_AVERMEDIA_M135A: | ||
5623 | /* case SAA7134_BOARD_SABRENT_SBTTVFM: */ /* not finished yet */ | 5845 | /* case SAA7134_BOARD_SABRENT_SBTTVFM: */ /* not finished yet */ |
5624 | case SAA7134_BOARD_VIDEOMATE_TV_PVR: | 5846 | case SAA7134_BOARD_VIDEOMATE_TV_PVR: |
5625 | case SAA7134_BOARD_VIDEOMATE_GOLD_PLUS: | 5847 | case SAA7134_BOARD_VIDEOMATE_GOLD_PLUS: |
@@ -5644,6 +5866,7 @@ int saa7134_board_init1(struct saa7134_dev *dev) | |||
5644 | case SAA7134_BOARD_AVERMEDIA_A16AR: | 5866 | case SAA7134_BOARD_AVERMEDIA_A16AR: |
5645 | case SAA7134_BOARD_ENCORE_ENLTV: | 5867 | case SAA7134_BOARD_ENCORE_ENLTV: |
5646 | case SAA7134_BOARD_ENCORE_ENLTV_FM: | 5868 | case SAA7134_BOARD_ENCORE_ENLTV_FM: |
5869 | case SAA7134_BOARD_ENCORE_ENLTV_FM53: | ||
5647 | case SAA7134_BOARD_10MOONSTVMASTER3: | 5870 | case SAA7134_BOARD_10MOONSTVMASTER3: |
5648 | case SAA7134_BOARD_BEHOLD_401: | 5871 | case SAA7134_BOARD_BEHOLD_401: |
5649 | case SAA7134_BOARD_BEHOLD_403: | 5872 | case SAA7134_BOARD_BEHOLD_403: |
@@ -5656,6 +5879,7 @@ int saa7134_board_init1(struct saa7134_dev *dev) | |||
5656 | case SAA7134_BOARD_BEHOLD_505FM: | 5879 | case SAA7134_BOARD_BEHOLD_505FM: |
5657 | case SAA7134_BOARD_BEHOLD_507_9FM: | 5880 | case SAA7134_BOARD_BEHOLD_507_9FM: |
5658 | case SAA7134_BOARD_GENIUS_TVGO_A11MCE: | 5881 | case SAA7134_BOARD_GENIUS_TVGO_A11MCE: |
5882 | case SAA7134_BOARD_REAL_ANGEL_220: | ||
5659 | dev->has_remote = SAA7134_REMOTE_GPIO; | 5883 | dev->has_remote = SAA7134_REMOTE_GPIO; |
5660 | break; | 5884 | break; |
5661 | case SAA7134_BOARD_FLYDVBS_LR300: | 5885 | case SAA7134_BOARD_FLYDVBS_LR300: |
@@ -5745,6 +5969,7 @@ int saa7134_board_init1(struct saa7134_dev *dev) | |||
5745 | case SAA7134_BOARD_PINNACLE_PCTV_110i: | 5969 | case SAA7134_BOARD_PINNACLE_PCTV_110i: |
5746 | case SAA7134_BOARD_PINNACLE_PCTV_310i: | 5970 | case SAA7134_BOARD_PINNACLE_PCTV_310i: |
5747 | case SAA7134_BOARD_UPMOST_PURPLE_TV: | 5971 | case SAA7134_BOARD_UPMOST_PURPLE_TV: |
5972 | case SAA7134_BOARD_MSI_TVATANYWHERE_PLUS: | ||
5748 | case SAA7134_BOARD_HAUPPAUGE_HVR1110: | 5973 | case SAA7134_BOARD_HAUPPAUGE_HVR1110: |
5749 | case SAA7134_BOARD_BEHOLD_607_9FM: | 5974 | case SAA7134_BOARD_BEHOLD_607_9FM: |
5750 | case SAA7134_BOARD_BEHOLD_M6: | 5975 | case SAA7134_BOARD_BEHOLD_M6: |
@@ -5987,6 +6212,7 @@ int saa7134_board_init2(struct saa7134_dev *dev) | |||
5987 | case SAA7134_BOARD_PINNACLE_PCTV_310i: | 6212 | case SAA7134_BOARD_PINNACLE_PCTV_310i: |
5988 | case SAA7134_BOARD_KWORLD_DVBT_210: | 6213 | case SAA7134_BOARD_KWORLD_DVBT_210: |
5989 | case SAA7134_BOARD_TEVION_DVBT_220RF: | 6214 | case SAA7134_BOARD_TEVION_DVBT_220RF: |
6215 | case SAA7134_BOARD_ASUSTeK_TIGER: | ||
5990 | case SAA7134_BOARD_ASUSTeK_P7131_DUAL: | 6216 | case SAA7134_BOARD_ASUSTeK_P7131_DUAL: |
5991 | case SAA7134_BOARD_ASUSTeK_P7131_HYBRID_LNA: | 6217 | case SAA7134_BOARD_ASUSTeK_P7131_HYBRID_LNA: |
5992 | case SAA7134_BOARD_MEDION_MD8800_QUADRO: | 6218 | case SAA7134_BOARD_MEDION_MD8800_QUADRO: |
@@ -6002,6 +6228,14 @@ int saa7134_board_init2(struct saa7134_dev *dev) | |||
6002 | i2c_transfer(&dev->i2c_adap, &msg, 1); | 6228 | i2c_transfer(&dev->i2c_adap, &msg, 1); |
6003 | break; | 6229 | break; |
6004 | } | 6230 | } |
6231 | case SAA7134_BOARD_ASUSTeK_TIGER_3IN1: | ||
6232 | { | ||
6233 | u8 data[] = { 0x3c, 0x33, 0x60}; | ||
6234 | struct i2c_msg msg = {.addr = 0x0b, .flags = 0, .buf = data, | ||
6235 | .len = sizeof(data)}; | ||
6236 | i2c_transfer(&dev->i2c_adap, &msg, 1); | ||
6237 | break; | ||
6238 | } | ||
6005 | case SAA7134_BOARD_FLYDVB_TRIO: | 6239 | case SAA7134_BOARD_FLYDVB_TRIO: |
6006 | { | 6240 | { |
6007 | u8 data[] = { 0x3c, 0x33, 0x62}; | 6241 | u8 data[] = { 0x3c, 0x33, 0x62}; |
@@ -6027,6 +6261,7 @@ int saa7134_board_init2(struct saa7134_dev *dev) | |||
6027 | i2c_transfer(&dev->i2c_adap, &msg, 1); | 6261 | i2c_transfer(&dev->i2c_adap, &msg, 1); |
6028 | break; | 6262 | break; |
6029 | } | 6263 | } |
6264 | case SAA7134_BOARD_ADS_INSTANT_HDTV_PCI: | ||
6030 | case SAA7134_BOARD_KWORLD_ATSC110: | 6265 | case SAA7134_BOARD_KWORLD_ATSC110: |
6031 | { | 6266 | { |
6032 | /* enable tuner */ | 6267 | /* enable tuner */ |
diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c index 75d618415f4f..b686bfabbde0 100644 --- a/drivers/media/video/saa7134/saa7134-core.c +++ b/drivers/media/video/saa7134/saa7134-core.c | |||
@@ -215,7 +215,7 @@ unsigned long saa7134_buffer_base(struct saa7134_buf *buf) | |||
215 | int saa7134_pgtable_alloc(struct pci_dev *pci, struct saa7134_pgtable *pt) | 215 | int saa7134_pgtable_alloc(struct pci_dev *pci, struct saa7134_pgtable *pt) |
216 | { | 216 | { |
217 | __le32 *cpu; | 217 | __le32 *cpu; |
218 | dma_addr_t dma_addr; | 218 | dma_addr_t dma_addr = 0; |
219 | 219 | ||
220 | cpu = pci_alloc_consistent(pci, SAA7134_PGTABLE_SIZE, &dma_addr); | 220 | cpu = pci_alloc_consistent(pci, SAA7134_PGTABLE_SIZE, &dma_addr); |
221 | if (NULL == cpu) | 221 | if (NULL == cpu) |
@@ -359,32 +359,6 @@ void saa7134_buffer_timeout(unsigned long data) | |||
359 | spin_unlock_irqrestore(&dev->slock,flags); | 359 | spin_unlock_irqrestore(&dev->slock,flags); |
360 | } | 360 | } |
361 | 361 | ||
362 | /* resends a current buffer in queue after resume */ | ||
363 | |||
364 | static int saa7134_buffer_requeue(struct saa7134_dev *dev, | ||
365 | struct saa7134_dmaqueue *q) | ||
366 | { | ||
367 | struct saa7134_buf *buf, *next; | ||
368 | |||
369 | assert_spin_locked(&dev->slock); | ||
370 | |||
371 | buf = q->curr; | ||
372 | next = buf; | ||
373 | dprintk("buffer_requeue\n"); | ||
374 | |||
375 | if (!buf) | ||
376 | return 0; | ||
377 | |||
378 | dprintk("buffer_requeue : resending active buffers \n"); | ||
379 | |||
380 | if (!list_empty(&q->queue)) | ||
381 | next = list_entry(q->queue.next, struct saa7134_buf, | ||
382 | vb.queue); | ||
383 | buf->activate(dev, buf, next); | ||
384 | |||
385 | return 0; | ||
386 | } | ||
387 | |||
388 | /* ------------------------------------------------------------------ */ | 362 | /* ------------------------------------------------------------------ */ |
389 | 363 | ||
390 | int saa7134_set_dmabits(struct saa7134_dev *dev) | 364 | int saa7134_set_dmabits(struct saa7134_dev *dev) |
@@ -442,9 +416,7 @@ int saa7134_set_dmabits(struct saa7134_dev *dev) | |||
442 | /* TS capture -- dma 5 */ | 416 | /* TS capture -- dma 5 */ |
443 | if (dev->ts_q.curr) { | 417 | if (dev->ts_q.curr) { |
444 | ctrl |= SAA7134_MAIN_CTRL_TE5; | 418 | ctrl |= SAA7134_MAIN_CTRL_TE5; |
445 | irq |= SAA7134_IRQ1_INTE_RA2_3 | | 419 | irq |= SAA7134_IRQ1_INTE_RA2_1 | |
446 | SAA7134_IRQ1_INTE_RA2_2 | | ||
447 | SAA7134_IRQ1_INTE_RA2_1 | | ||
448 | SAA7134_IRQ1_INTE_RA2_0; | 420 | SAA7134_IRQ1_INTE_RA2_0; |
449 | } | 421 | } |
450 | 422 | ||
@@ -727,6 +699,10 @@ static int saa7134_hw_enable2(struct saa7134_dev *dev) | |||
727 | irq2_mask |= SAA7134_IRQ2_INTE_GPIO18A; | 699 | irq2_mask |= SAA7134_IRQ2_INTE_GPIO18A; |
728 | } | 700 | } |
729 | 701 | ||
702 | if (dev->has_remote == SAA7134_REMOTE_I2C) { | ||
703 | request_module("ir-kbd-i2c"); | ||
704 | } | ||
705 | |||
730 | saa_writel(SAA7134_IRQ1, 0); | 706 | saa_writel(SAA7134_IRQ1, 0); |
731 | saa_writel(SAA7134_IRQ2, irq2_mask); | 707 | saa_writel(SAA7134_IRQ2, irq2_mask); |
732 | 708 | ||
@@ -1139,6 +1115,32 @@ static void __devexit saa7134_finidev(struct pci_dev *pci_dev) | |||
1139 | } | 1115 | } |
1140 | 1116 | ||
1141 | #ifdef CONFIG_PM | 1117 | #ifdef CONFIG_PM |
1118 | |||
1119 | /* resends a current buffer in queue after resume */ | ||
1120 | static int saa7134_buffer_requeue(struct saa7134_dev *dev, | ||
1121 | struct saa7134_dmaqueue *q) | ||
1122 | { | ||
1123 | struct saa7134_buf *buf, *next; | ||
1124 | |||
1125 | assert_spin_locked(&dev->slock); | ||
1126 | |||
1127 | buf = q->curr; | ||
1128 | next = buf; | ||
1129 | dprintk("buffer_requeue\n"); | ||
1130 | |||
1131 | if (!buf) | ||
1132 | return 0; | ||
1133 | |||
1134 | dprintk("buffer_requeue : resending active buffers \n"); | ||
1135 | |||
1136 | if (!list_empty(&q->queue)) | ||
1137 | next = list_entry(q->queue.next, struct saa7134_buf, | ||
1138 | vb.queue); | ||
1139 | buf->activate(dev, buf, next); | ||
1140 | |||
1141 | return 0; | ||
1142 | } | ||
1143 | |||
1142 | static int saa7134_suspend(struct pci_dev *pci_dev , pm_message_t state) | 1144 | static int saa7134_suspend(struct pci_dev *pci_dev , pm_message_t state) |
1143 | { | 1145 | { |
1144 | 1146 | ||
diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index be48b9b66a67..87c10983266f 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c | |||
@@ -553,7 +553,6 @@ static int configure_tda827x_fe(struct saa7134_dev *dev, | |||
553 | /* ------------------------------------------------------------------ */ | 553 | /* ------------------------------------------------------------------ */ |
554 | 554 | ||
555 | static struct tda827x_config tda827x_cfg_0 = { | 555 | static struct tda827x_config tda827x_cfg_0 = { |
556 | .tuner_callback = saa7134_tuner_callback, | ||
557 | .init = philips_tda827x_tuner_init, | 556 | .init = philips_tda827x_tuner_init, |
558 | .sleep = philips_tda827x_tuner_sleep, | 557 | .sleep = philips_tda827x_tuner_sleep, |
559 | .config = 0, | 558 | .config = 0, |
@@ -561,7 +560,6 @@ static struct tda827x_config tda827x_cfg_0 = { | |||
561 | }; | 560 | }; |
562 | 561 | ||
563 | static struct tda827x_config tda827x_cfg_1 = { | 562 | static struct tda827x_config tda827x_cfg_1 = { |
564 | .tuner_callback = saa7134_tuner_callback, | ||
565 | .init = philips_tda827x_tuner_init, | 563 | .init = philips_tda827x_tuner_init, |
566 | .sleep = philips_tda827x_tuner_sleep, | 564 | .sleep = philips_tda827x_tuner_sleep, |
567 | .config = 1, | 565 | .config = 1, |
@@ -569,7 +567,6 @@ static struct tda827x_config tda827x_cfg_1 = { | |||
569 | }; | 567 | }; |
570 | 568 | ||
571 | static struct tda827x_config tda827x_cfg_2 = { | 569 | static struct tda827x_config tda827x_cfg_2 = { |
572 | .tuner_callback = saa7134_tuner_callback, | ||
573 | .init = philips_tda827x_tuner_init, | 570 | .init = philips_tda827x_tuner_init, |
574 | .sleep = philips_tda827x_tuner_sleep, | 571 | .sleep = philips_tda827x_tuner_sleep, |
575 | .config = 2, | 572 | .config = 2, |
@@ -577,7 +574,6 @@ static struct tda827x_config tda827x_cfg_2 = { | |||
577 | }; | 574 | }; |
578 | 575 | ||
579 | static struct tda827x_config tda827x_cfg_2_sw42 = { | 576 | static struct tda827x_config tda827x_cfg_2_sw42 = { |
580 | .tuner_callback = saa7134_tuner_callback, | ||
581 | .init = philips_tda827x_tuner_init, | 577 | .init = philips_tda827x_tuner_init, |
582 | .sleep = philips_tda827x_tuner_sleep, | 578 | .sleep = philips_tda827x_tuner_sleep, |
583 | .config = 2, | 579 | .config = 2, |
@@ -799,6 +795,20 @@ static struct tda1004x_config twinhan_dtv_dvb_3056_config = { | |||
799 | .request_firmware = philips_tda1004x_request_firmware | 795 | .request_firmware = philips_tda1004x_request_firmware |
800 | }; | 796 | }; |
801 | 797 | ||
798 | static struct tda1004x_config asus_tiger_3in1_config = { | ||
799 | .demod_address = 0x0b, | ||
800 | .invert = 1, | ||
801 | .invert_oclk = 0, | ||
802 | .xtal_freq = TDA10046_XTAL_16M, | ||
803 | .agc_config = TDA10046_AGC_TDA827X, | ||
804 | .gpio_config = TDA10046_GP11_I, | ||
805 | .if_freq = TDA10046_FREQ_045, | ||
806 | .i2c_gate = 0x4b, | ||
807 | .tuner_address = 0x61, | ||
808 | .antenna_switch = 1, | ||
809 | .request_firmware = philips_tda1004x_request_firmware | ||
810 | }; | ||
811 | |||
802 | /* ------------------------------------------------------------------ | 812 | /* ------------------------------------------------------------------ |
803 | * special case: this card uses saa713x GPIO22 for the mode switch | 813 | * special case: this card uses saa713x GPIO22 for the mode switch |
804 | */ | 814 | */ |
@@ -822,7 +832,6 @@ static int ads_duo_tuner_sleep(struct dvb_frontend *fe) | |||
822 | } | 832 | } |
823 | 833 | ||
824 | static struct tda827x_config ads_duo_cfg = { | 834 | static struct tda827x_config ads_duo_cfg = { |
825 | .tuner_callback = saa7134_tuner_callback, | ||
826 | .init = ads_duo_tuner_init, | 835 | .init = ads_duo_tuner_init, |
827 | .sleep = ads_duo_tuner_sleep, | 836 | .sleep = ads_duo_tuner_sleep, |
828 | .config = 0 | 837 | .config = 0 |
@@ -1147,6 +1156,7 @@ static int dvb_init(struct saa7134_dev *dev) | |||
1147 | dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, | 1156 | dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, |
1148 | NULL, DVB_PLL_TDHU2); | 1157 | NULL, DVB_PLL_TDHU2); |
1149 | break; | 1158 | break; |
1159 | case SAA7134_BOARD_ADS_INSTANT_HDTV_PCI: | ||
1150 | case SAA7134_BOARD_KWORLD_ATSC110: | 1160 | case SAA7134_BOARD_KWORLD_ATSC110: |
1151 | dev->dvb.frontend = dvb_attach(nxt200x_attach, &kworldatsc110, | 1161 | dev->dvb.frontend = dvb_attach(nxt200x_attach, &kworldatsc110, |
1152 | &dev->i2c_adap); | 1162 | &dev->i2c_adap); |
@@ -1300,6 +1310,36 @@ static int dvb_init(struct saa7134_dev *dev) | |||
1300 | &dev->i2c_adap); | 1310 | &dev->i2c_adap); |
1301 | attach_xc3028 = 1; | 1311 | attach_xc3028 = 1; |
1302 | break; | 1312 | break; |
1313 | case SAA7134_BOARD_ASUSTeK_TIGER_3IN1: | ||
1314 | if (!use_frontend) { /* terrestrial */ | ||
1315 | if (configure_tda827x_fe(dev, &asus_tiger_3in1_config, | ||
1316 | &tda827x_cfg_2) < 0) | ||
1317 | goto dettach_frontend; | ||
1318 | } else { /* satellite */ | ||
1319 | dev->dvb.frontend = dvb_attach(tda10086_attach, | ||
1320 | &flydvbs, &dev->i2c_adap); | ||
1321 | if (dev->dvb.frontend) { | ||
1322 | if (dvb_attach(tda826x_attach, | ||
1323 | dev->dvb.frontend, 0x60, | ||
1324 | &dev->i2c_adap, 0) == NULL) { | ||
1325 | wprintk("%s: Asus Tiger 3in1, no " | ||
1326 | "tda826x found!\n", __func__); | ||
1327 | goto dettach_frontend; | ||
1328 | } | ||
1329 | if (dvb_attach(lnbp21_attach, dev->dvb.frontend, | ||
1330 | &dev->i2c_adap, 0, 0) == NULL) { | ||
1331 | wprintk("%s: Asus Tiger 3in1, no lnbp21" | ||
1332 | " found!\n", __func__); | ||
1333 | goto dettach_frontend; | ||
1334 | } | ||
1335 | } | ||
1336 | } | ||
1337 | break; | ||
1338 | case SAA7134_BOARD_ASUSTeK_TIGER: | ||
1339 | if (configure_tda827x_fe(dev, &philips_tiger_config, | ||
1340 | &tda827x_cfg_0) < 0) | ||
1341 | goto dettach_frontend; | ||
1342 | break; | ||
1303 | default: | 1343 | default: |
1304 | wprintk("Huh? unknown DVB card?\n"); | 1344 | wprintk("Huh? unknown DVB card?\n"); |
1305 | break; | 1345 | break; |
@@ -1327,6 +1367,8 @@ static int dvb_init(struct saa7134_dev *dev) | |||
1327 | printk(KERN_ERR "%s/dvb: frontend initialization failed\n", dev->name); | 1367 | printk(KERN_ERR "%s/dvb: frontend initialization failed\n", dev->name); |
1328 | return -1; | 1368 | return -1; |
1329 | } | 1369 | } |
1370 | /* define general-purpose callback pointer */ | ||
1371 | dev->dvb.frontend->callback = saa7134_tuner_callback; | ||
1330 | 1372 | ||
1331 | /* register everything else */ | 1373 | /* register everything else */ |
1332 | ret = videobuf_dvb_register(&dev->dvb, THIS_MODULE, dev, &dev->pci->dev, | 1374 | ret = videobuf_dvb_register(&dev->dvb, THIS_MODULE, dev, &dev->pci->dev, |
diff --git a/drivers/media/video/saa7134/saa7134-empress.c b/drivers/media/video/saa7134/saa7134-empress.c index c0c5d7509c25..9a8766a78a0c 100644 --- a/drivers/media/video/saa7134/saa7134-empress.c +++ b/drivers/media/video/saa7134/saa7134-empress.c | |||
@@ -29,6 +29,7 @@ | |||
29 | 29 | ||
30 | #include <media/saa6752hs.h> | 30 | #include <media/saa6752hs.h> |
31 | #include <media/v4l2-common.h> | 31 | #include <media/v4l2-common.h> |
32 | #include <media/v4l2-chip-ident.h> | ||
32 | 33 | ||
33 | /* ------------------------------------------------------------------ */ | 34 | /* ------------------------------------------------------------------ */ |
34 | 35 | ||
@@ -63,10 +64,19 @@ static void ts_reset_encoder(struct saa7134_dev* dev) | |||
63 | 64 | ||
64 | static int ts_init_encoder(struct saa7134_dev* dev) | 65 | static int ts_init_encoder(struct saa7134_dev* dev) |
65 | { | 66 | { |
66 | struct v4l2_ext_controls ctrls = { V4L2_CTRL_CLASS_MPEG, 0 }; | 67 | u32 leading_null_bytes = 0; |
67 | 68 | ||
69 | /* If more cards start to need this, then this | ||
70 | should probably be added to the card definitions. */ | ||
71 | switch (dev->board) { | ||
72 | case SAA7134_BOARD_BEHOLD_M6: | ||
73 | case SAA7134_BOARD_BEHOLD_M63: | ||
74 | case SAA7134_BOARD_BEHOLD_M6_EXTRA: | ||
75 | leading_null_bytes = 1; | ||
76 | break; | ||
77 | } | ||
68 | ts_reset_encoder(dev); | 78 | ts_reset_encoder(dev); |
69 | saa7134_i2c_call_clients(dev, VIDIOC_S_EXT_CTRLS, &ctrls); | 79 | saa7134_i2c_call_clients(dev, VIDIOC_INT_INIT, &leading_null_bytes); |
70 | dev->empress_started = 1; | 80 | dev->empress_started = 1; |
71 | return 0; | 81 | return 0; |
72 | } | 82 | } |
@@ -79,9 +89,11 @@ static int ts_open(struct inode *inode, struct file *file) | |||
79 | struct saa7134_dev *dev; | 89 | struct saa7134_dev *dev; |
80 | int err; | 90 | int err; |
81 | 91 | ||
92 | lock_kernel(); | ||
82 | list_for_each_entry(dev, &saa7134_devlist, devlist) | 93 | list_for_each_entry(dev, &saa7134_devlist, devlist) |
83 | if (dev->empress_dev && dev->empress_dev->minor == minor) | 94 | if (dev->empress_dev && dev->empress_dev->minor == minor) |
84 | goto found; | 95 | goto found; |
96 | unlock_kernel(); | ||
85 | return -ENODEV; | 97 | return -ENODEV; |
86 | found: | 98 | found: |
87 | 99 | ||
@@ -103,6 +115,7 @@ static int ts_open(struct inode *inode, struct file *file) | |||
103 | done_up: | 115 | done_up: |
104 | mutex_unlock(&dev->empress_tsq.vb_lock); | 116 | mutex_unlock(&dev->empress_tsq.vb_lock); |
105 | done: | 117 | done: |
118 | unlock_kernel(); | ||
106 | return err; | 119 | return err; |
107 | } | 120 | } |
108 | 121 | ||
@@ -290,15 +303,6 @@ static int empress_streamoff(struct file *file, void *priv, | |||
290 | return videobuf_streamoff(&dev->empress_tsq); | 303 | return videobuf_streamoff(&dev->empress_tsq); |
291 | } | 304 | } |
292 | 305 | ||
293 | static int saa7134_i2c_call_saa6752(struct saa7134_dev *dev, | ||
294 | unsigned int cmd, void *arg) | ||
295 | { | ||
296 | if (dev->mpeg_i2c_client == NULL) | ||
297 | return -EINVAL; | ||
298 | return dev->mpeg_i2c_client->driver->command(dev->mpeg_i2c_client, | ||
299 | cmd, arg); | ||
300 | } | ||
301 | |||
302 | static int empress_s_ext_ctrls(struct file *file, void *priv, | 306 | static int empress_s_ext_ctrls(struct file *file, void *priv, |
303 | struct v4l2_ext_controls *ctrls) | 307 | struct v4l2_ext_controls *ctrls) |
304 | { | 308 | { |
@@ -400,6 +404,39 @@ static int empress_querymenu(struct file *file, void *priv, | |||
400 | return saa7134_i2c_call_saa6752(dev, VIDIOC_QUERYMENU, c); | 404 | return saa7134_i2c_call_saa6752(dev, VIDIOC_QUERYMENU, c); |
401 | } | 405 | } |
402 | 406 | ||
407 | static int empress_g_chip_ident(struct file *file, void *fh, | ||
408 | struct v4l2_chip_ident *chip) | ||
409 | { | ||
410 | struct saa7134_dev *dev = file->private_data; | ||
411 | |||
412 | chip->ident = V4L2_IDENT_NONE; | ||
413 | chip->revision = 0; | ||
414 | if (dev->mpeg_i2c_client == NULL) | ||
415 | return -EINVAL; | ||
416 | if (chip->match_type == V4L2_CHIP_MATCH_I2C_DRIVER && | ||
417 | chip->match_chip == I2C_DRIVERID_SAA6752HS) | ||
418 | return saa7134_i2c_call_saa6752(dev, VIDIOC_G_CHIP_IDENT, chip); | ||
419 | if (chip->match_type == V4L2_CHIP_MATCH_I2C_ADDR && | ||
420 | chip->match_chip == dev->mpeg_i2c_client->addr) | ||
421 | return saa7134_i2c_call_saa6752(dev, VIDIOC_G_CHIP_IDENT, chip); | ||
422 | return -EINVAL; | ||
423 | } | ||
424 | |||
425 | static int empress_s_std(struct file *file, void *priv, v4l2_std_id *id) | ||
426 | { | ||
427 | struct saa7134_dev *dev = file->private_data; | ||
428 | |||
429 | return saa7134_s_std_internal(dev, NULL, id); | ||
430 | } | ||
431 | |||
432 | static int empress_g_std(struct file *file, void *priv, v4l2_std_id *id) | ||
433 | { | ||
434 | struct saa7134_dev *dev = file->private_data; | ||
435 | |||
436 | *id = dev->tvnorm->id; | ||
437 | return 0; | ||
438 | } | ||
439 | |||
403 | static const struct file_operations ts_fops = | 440 | static const struct file_operations ts_fops = |
404 | { | 441 | { |
405 | .owner = THIS_MODULE, | 442 | .owner = THIS_MODULE, |
@@ -428,11 +465,13 @@ static const struct v4l2_ioctl_ops ts_ioctl_ops = { | |||
428 | .vidioc_enum_input = empress_enum_input, | 465 | .vidioc_enum_input = empress_enum_input, |
429 | .vidioc_g_input = empress_g_input, | 466 | .vidioc_g_input = empress_g_input, |
430 | .vidioc_s_input = empress_s_input, | 467 | .vidioc_s_input = empress_s_input, |
431 | |||
432 | .vidioc_queryctrl = empress_queryctrl, | 468 | .vidioc_queryctrl = empress_queryctrl, |
433 | .vidioc_querymenu = empress_querymenu, | 469 | .vidioc_querymenu = empress_querymenu, |
434 | .vidioc_g_ctrl = empress_g_ctrl, | 470 | .vidioc_g_ctrl = empress_g_ctrl, |
435 | .vidioc_s_ctrl = empress_s_ctrl, | 471 | .vidioc_s_ctrl = empress_s_ctrl, |
472 | .vidioc_g_chip_ident = empress_g_chip_ident, | ||
473 | .vidioc_s_std = empress_s_std, | ||
474 | .vidioc_g_std = empress_g_std, | ||
436 | }; | 475 | }; |
437 | 476 | ||
438 | /* ----------------------------------------------------------- */ | 477 | /* ----------------------------------------------------------- */ |
diff --git a/drivers/media/video/saa7134/saa7134-i2c.c b/drivers/media/video/saa7134/saa7134-i2c.c index 5f713e637683..20c1b33caf7b 100644 --- a/drivers/media/video/saa7134/saa7134-i2c.c +++ b/drivers/media/video/saa7134/saa7134-i2c.c | |||
@@ -337,6 +337,7 @@ static int attach_inform(struct i2c_client *client) | |||
337 | case 0x47: | 337 | case 0x47: |
338 | case 0x71: | 338 | case 0x71: |
339 | case 0x2d: | 339 | case 0x2d: |
340 | case 0x30: | ||
340 | { | 341 | { |
341 | struct IR_i2c *ir = i2c_get_clientdata(client); | 342 | struct IR_i2c *ir = i2c_get_clientdata(client); |
342 | d1printk("%s i2c IR detected (%s).\n", | 343 | d1printk("%s i2c IR detected (%s).\n", |
@@ -427,6 +428,16 @@ void saa7134_i2c_call_clients(struct saa7134_dev *dev, | |||
427 | i2c_clients_command(&dev->i2c_adap, cmd, arg); | 428 | i2c_clients_command(&dev->i2c_adap, cmd, arg); |
428 | } | 429 | } |
429 | 430 | ||
431 | int saa7134_i2c_call_saa6752(struct saa7134_dev *dev, | ||
432 | unsigned int cmd, void *arg) | ||
433 | { | ||
434 | if (dev->mpeg_i2c_client == NULL) | ||
435 | return -EINVAL; | ||
436 | return dev->mpeg_i2c_client->driver->command(dev->mpeg_i2c_client, | ||
437 | cmd, arg); | ||
438 | } | ||
439 | EXPORT_SYMBOL_GPL(saa7134_i2c_call_saa6752); | ||
440 | |||
430 | int saa7134_i2c_register(struct saa7134_dev *dev) | 441 | int saa7134_i2c_register(struct saa7134_dev *dev) |
431 | { | 442 | { |
432 | dev->i2c_adap = saa7134_adap_template; | 443 | dev->i2c_adap = saa7134_adap_template; |
diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index ad08d13dffdd..c53fd5f9f6b5 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c | |||
@@ -62,8 +62,11 @@ MODULE_PARM_DESC(disable_other_ir, "disable full codes of " | |||
62 | #define i2cdprintk(fmt, arg...) if (ir_debug) \ | 62 | #define i2cdprintk(fmt, arg...) if (ir_debug) \ |
63 | printk(KERN_DEBUG "%s/ir: " fmt, ir->c.name , ## arg) | 63 | printk(KERN_DEBUG "%s/ir: " fmt, ir->c.name , ## arg) |
64 | 64 | ||
65 | /** rc5 functions */ | 65 | /* Helper functions for RC5 and NEC decoding at GPIO16 or GPIO18 */ |
66 | static int saa7134_rc5_irq(struct saa7134_dev *dev); | 66 | static int saa7134_rc5_irq(struct saa7134_dev *dev); |
67 | static int saa7134_nec_irq(struct saa7134_dev *dev); | ||
68 | static void nec_task(unsigned long data); | ||
69 | static void saa7134_nec_timer(unsigned long data); | ||
67 | 70 | ||
68 | /* -------------------- GPIO generic keycode builder -------------------- */ | 71 | /* -------------------- GPIO generic keycode builder -------------------- */ |
69 | 72 | ||
@@ -115,6 +118,53 @@ static int build_key(struct saa7134_dev *dev) | |||
115 | 118 | ||
116 | /* --------------------- Chip specific I2C key builders ----------------- */ | 119 | /* --------------------- Chip specific I2C key builders ----------------- */ |
117 | 120 | ||
121 | static int get_key_msi_tvanywhere_plus(struct IR_i2c *ir, u32 *ir_key, | ||
122 | u32 *ir_raw) | ||
123 | { | ||
124 | unsigned char b; | ||
125 | int gpio; | ||
126 | |||
127 | /* <dev> is needed to access GPIO. Used by the saa_readl macro. */ | ||
128 | struct saa7134_dev *dev = ir->c.adapter->algo_data; | ||
129 | if (dev == NULL) { | ||
130 | dprintk("get_key_msi_tvanywhere_plus: " | ||
131 | "gir->c.adapter->algo_data is NULL!\n"); | ||
132 | return -EIO; | ||
133 | } | ||
134 | |||
135 | /* rising SAA7134_GPIO_GPRESCAN reads the status */ | ||
136 | |||
137 | saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); | ||
138 | saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); | ||
139 | |||
140 | gpio = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2); | ||
141 | |||
142 | /* GPIO&0x40 is pulsed low when a button is pressed. Don't do | ||
143 | I2C receive if gpio&0x40 is not low. */ | ||
144 | |||
145 | if (gpio & 0x40) | ||
146 | return 0; /* No button press */ | ||
147 | |||
148 | /* GPIO says there is a button press. Get it. */ | ||
149 | |||
150 | if (1 != i2c_master_recv(&ir->c, &b, 1)) { | ||
151 | i2cdprintk("read error\n"); | ||
152 | return -EIO; | ||
153 | } | ||
154 | |||
155 | /* No button press */ | ||
156 | |||
157 | if (b == 0xff) | ||
158 | return 0; | ||
159 | |||
160 | /* Button pressed */ | ||
161 | |||
162 | dprintk("get_key_msi_tvanywhere_plus: Key = 0x%02X\n", b); | ||
163 | *ir_key = b; | ||
164 | *ir_raw = b; | ||
165 | return 1; | ||
166 | } | ||
167 | |||
118 | static int get_key_purpletv(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) | 168 | static int get_key_purpletv(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) |
119 | { | 169 | { |
120 | unsigned char b; | 170 | unsigned char b; |
@@ -280,7 +330,9 @@ void saa7134_input_irq(struct saa7134_dev *dev) | |||
280 | { | 330 | { |
281 | struct card_ir *ir = dev->remote; | 331 | struct card_ir *ir = dev->remote; |
282 | 332 | ||
283 | if (!ir->polling && !ir->rc5_gpio) { | 333 | if (ir->nec_gpio) { |
334 | saa7134_nec_irq(dev); | ||
335 | } else if (!ir->polling && !ir->rc5_gpio) { | ||
284 | build_key(dev); | 336 | build_key(dev); |
285 | } else if (ir->rc5_gpio) { | 337 | } else if (ir->rc5_gpio) { |
286 | saa7134_rc5_irq(dev); | 338 | saa7134_rc5_irq(dev); |
@@ -316,6 +368,10 @@ void saa7134_ir_start(struct saa7134_dev *dev, struct card_ir *ir) | |||
316 | ir->addr = 0x17; | 368 | ir->addr = 0x17; |
317 | ir->rc5_key_timeout = ir_rc5_key_timeout; | 369 | ir->rc5_key_timeout = ir_rc5_key_timeout; |
318 | ir->rc5_remote_gap = ir_rc5_remote_gap; | 370 | ir->rc5_remote_gap = ir_rc5_remote_gap; |
371 | } else if (ir->nec_gpio) { | ||
372 | setup_timer(&ir->timer_keyup, saa7134_nec_timer, | ||
373 | (unsigned long)dev); | ||
374 | tasklet_init(&ir->tlet, nec_task, (unsigned long)dev); | ||
319 | } | 375 | } |
320 | } | 376 | } |
321 | 377 | ||
@@ -335,6 +391,7 @@ int saa7134_input_init1(struct saa7134_dev *dev) | |||
335 | u32 mask_keyup = 0; | 391 | u32 mask_keyup = 0; |
336 | int polling = 0; | 392 | int polling = 0; |
337 | int rc5_gpio = 0; | 393 | int rc5_gpio = 0; |
394 | int nec_gpio = 0; | ||
338 | int ir_type = IR_TYPE_OTHER; | 395 | int ir_type = IR_TYPE_OTHER; |
339 | int err; | 396 | int err; |
340 | 397 | ||
@@ -391,6 +448,12 @@ int saa7134_input_init1(struct saa7134_dev *dev) | |||
391 | saa_setb(SAA7134_GPIO_GPMODE0, 0x4); | 448 | saa_setb(SAA7134_GPIO_GPMODE0, 0x4); |
392 | saa_setb(SAA7134_GPIO_GPSTATUS0, 0x4); | 449 | saa_setb(SAA7134_GPIO_GPSTATUS0, 0x4); |
393 | break; | 450 | break; |
451 | case SAA7134_BOARD_AVERMEDIA_M135A: | ||
452 | ir_codes = ir_codes_avermedia_m135a; | ||
453 | mask_keydown = 0x0040000; | ||
454 | mask_keycode = 0x00013f; | ||
455 | nec_gpio = 1; | ||
456 | break; | ||
394 | case SAA7134_BOARD_AVERMEDIA_777: | 457 | case SAA7134_BOARD_AVERMEDIA_777: |
395 | case SAA7134_BOARD_AVERMEDIA_A16AR: | 458 | case SAA7134_BOARD_AVERMEDIA_A16AR: |
396 | ir_codes = ir_codes_avermedia; | 459 | ir_codes = ir_codes_avermedia; |
@@ -499,6 +562,12 @@ int saa7134_input_init1(struct saa7134_dev *dev) | |||
499 | mask_keyup = 0x040000; | 562 | mask_keyup = 0x040000; |
500 | polling = 50; // ms | 563 | polling = 50; // ms |
501 | break; | 564 | break; |
565 | case SAA7134_BOARD_ENCORE_ENLTV_FM53: | ||
566 | ir_codes = ir_codes_encore_enltv_fm53; | ||
567 | mask_keydown = 0x0040000; | ||
568 | mask_keycode = 0x00007f; | ||
569 | nec_gpio = 1; | ||
570 | break; | ||
502 | case SAA7134_BOARD_10MOONSTVMASTER3: | 571 | case SAA7134_BOARD_10MOONSTVMASTER3: |
503 | ir_codes = ir_codes_encore_enltv; | 572 | ir_codes = ir_codes_encore_enltv; |
504 | mask_keycode = 0x5f80000; | 573 | mask_keycode = 0x5f80000; |
@@ -511,6 +580,12 @@ int saa7134_input_init1(struct saa7134_dev *dev) | |||
511 | mask_keydown = 0xf00000; | 580 | mask_keydown = 0xf00000; |
512 | polling = 50; /* ms */ | 581 | polling = 50; /* ms */ |
513 | break; | 582 | break; |
583 | case SAA7134_BOARD_REAL_ANGEL_220: | ||
584 | ir_codes = ir_codes_real_audio_220_32_keys; | ||
585 | mask_keycode = 0x3f00; | ||
586 | mask_keyup = 0x4000; | ||
587 | polling = 50; /* ms */ | ||
588 | break; | ||
514 | } | 589 | } |
515 | if (NULL == ir_codes) { | 590 | if (NULL == ir_codes) { |
516 | printk("%s: Oops: IR config error [card=%d]\n", | 591 | printk("%s: Oops: IR config error [card=%d]\n", |
@@ -533,6 +608,7 @@ int saa7134_input_init1(struct saa7134_dev *dev) | |||
533 | ir->mask_keyup = mask_keyup; | 608 | ir->mask_keyup = mask_keyup; |
534 | ir->polling = polling; | 609 | ir->polling = polling; |
535 | ir->rc5_gpio = rc5_gpio; | 610 | ir->rc5_gpio = rc5_gpio; |
611 | ir->nec_gpio = nec_gpio; | ||
536 | 612 | ||
537 | /* init input device */ | 613 | /* init input device */ |
538 | snprintf(ir->name, sizeof(ir->name), "saa7134 IR (%s)", | 614 | snprintf(ir->name, sizeof(ir->name), "saa7134 IR (%s)", |
@@ -612,6 +688,11 @@ void saa7134_set_i2c_ir(struct saa7134_dev *dev, struct IR_i2c *ir) | |||
612 | ir->get_key = get_key_purpletv; | 688 | ir->get_key = get_key_purpletv; |
613 | ir->ir_codes = ir_codes_purpletv; | 689 | ir->ir_codes = ir_codes_purpletv; |
614 | break; | 690 | break; |
691 | case SAA7134_BOARD_MSI_TVATANYWHERE_PLUS: | ||
692 | snprintf(ir->c.name, sizeof(ir->c.name), "MSI TV@nywhere Plus"); | ||
693 | ir->get_key = get_key_msi_tvanywhere_plus; | ||
694 | ir->ir_codes = ir_codes_msi_tvanywhere_plus; | ||
695 | break; | ||
615 | case SAA7134_BOARD_HAUPPAUGE_HVR1110: | 696 | case SAA7134_BOARD_HAUPPAUGE_HVR1110: |
616 | snprintf(ir->c.name, sizeof(ir->c.name), "HVR 1110"); | 697 | snprintf(ir->c.name, sizeof(ir->c.name), "HVR 1110"); |
617 | ir->get_key = get_key_hvr1110; | 698 | ir->get_key = get_key_hvr1110; |
@@ -675,8 +756,125 @@ static int saa7134_rc5_irq(struct saa7134_dev *dev) | |||
675 | return 1; | 756 | return 1; |
676 | } | 757 | } |
677 | 758 | ||
678 | /* ---------------------------------------------------------------------- | 759 | |
679 | * Local variables: | 760 | /* On NEC protocol, One has 2.25 ms, and zero has 1.125 ms |
680 | * c-basic-offset: 8 | 761 | The first pulse (start) has 9 + 4.5 ms |
681 | * End: | ||
682 | */ | 762 | */ |
763 | |||
764 | static void saa7134_nec_timer(unsigned long data) | ||
765 | { | ||
766 | struct saa7134_dev *dev = (struct saa7134_dev *) data; | ||
767 | struct card_ir *ir = dev->remote; | ||
768 | |||
769 | dprintk("Cancel key repeat\n"); | ||
770 | |||
771 | ir_input_nokey(ir->dev, &ir->ir); | ||
772 | } | ||
773 | |||
774 | static void nec_task(unsigned long data) | ||
775 | { | ||
776 | struct saa7134_dev *dev = (struct saa7134_dev *) data; | ||
777 | struct card_ir *ir; | ||
778 | struct timeval tv; | ||
779 | int count, pulse, oldpulse, gap; | ||
780 | u32 ircode = 0, not_code = 0; | ||
781 | int ngap = 0; | ||
782 | |||
783 | if (!data) { | ||
784 | printk(KERN_ERR "saa713x/ir: Can't recover dev struct\n"); | ||
785 | /* GPIO will be kept disabled */ | ||
786 | return; | ||
787 | } | ||
788 | |||
789 | ir = dev->remote; | ||
790 | |||
791 | /* rising SAA7134_GPIO_GPRESCAN reads the status */ | ||
792 | saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); | ||
793 | saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); | ||
794 | |||
795 | oldpulse = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2) & ir->mask_keydown; | ||
796 | pulse = oldpulse; | ||
797 | |||
798 | do_gettimeofday(&tv); | ||
799 | ir->base_time = tv; | ||
800 | |||
801 | /* Decode NEC pulsecode. This code can take up to 76.5 ms to run. | ||
802 | Unfortunately, using IRQ to decode pulse didn't work, since it uses | ||
803 | a pulse train of 38KHz. This means one pulse on each 52 us | ||
804 | */ | ||
805 | do { | ||
806 | /* Wait until the end of pulse/space or 5 ms */ | ||
807 | for (count = 0; count < 500; count++) { | ||
808 | udelay(10); | ||
809 | /* rising SAA7134_GPIO_GPRESCAN reads the status */ | ||
810 | saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); | ||
811 | saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); | ||
812 | pulse = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2) | ||
813 | & ir->mask_keydown; | ||
814 | if (pulse != oldpulse) | ||
815 | break; | ||
816 | } | ||
817 | |||
818 | do_gettimeofday(&tv); | ||
819 | gap = 1000000 * (tv.tv_sec - ir->base_time.tv_sec) + | ||
820 | tv.tv_usec - ir->base_time.tv_usec; | ||
821 | |||
822 | if (!pulse) { | ||
823 | /* Bit 0 has 560 us, while bit 1 has 1120 us. | ||
824 | Do something only if bit == 1 | ||
825 | */ | ||
826 | if (ngap && (gap > 560 + 280)) { | ||
827 | unsigned int shift = ngap - 1; | ||
828 | |||
829 | /* Address first, then command */ | ||
830 | if (shift < 8) { | ||
831 | shift += 8; | ||
832 | ircode |= 1 << shift; | ||
833 | } else if (shift < 16) { | ||
834 | not_code |= 1 << shift; | ||
835 | } else if (shift < 24) { | ||
836 | shift -= 16; | ||
837 | ircode |= 1 << shift; | ||
838 | } else { | ||
839 | shift -= 24; | ||
840 | not_code |= 1 << shift; | ||
841 | } | ||
842 | } | ||
843 | ngap++; | ||
844 | } | ||
845 | |||
846 | |||
847 | ir->base_time = tv; | ||
848 | |||
849 | /* TIMEOUT - Long pulse */ | ||
850 | if (gap >= 5000) | ||
851 | break; | ||
852 | oldpulse = pulse; | ||
853 | } while (ngap < 32); | ||
854 | |||
855 | if (ngap == 32) { | ||
856 | /* FIXME: should check if not_code == ~ircode */ | ||
857 | ir->code = ir_extract_bits(ircode, ir->mask_keycode); | ||
858 | |||
859 | dprintk("scancode = 0x%02x (code = 0x%02x, notcode= 0x%02x)\n", | ||
860 | ir->code, ircode, not_code); | ||
861 | |||
862 | ir_input_keydown(ir->dev, &ir->ir, ir->code, ir->code); | ||
863 | } else | ||
864 | dprintk("Repeat last key\n"); | ||
865 | |||
866 | /* Keep repeating the last key */ | ||
867 | mod_timer(&ir->timer_keyup, jiffies + msecs_to_jiffies(150)); | ||
868 | |||
869 | saa_setl(SAA7134_IRQ2, SAA7134_IRQ2_INTE_GPIO18); | ||
870 | } | ||
871 | |||
872 | static int saa7134_nec_irq(struct saa7134_dev *dev) | ||
873 | { | ||
874 | struct card_ir *ir = dev->remote; | ||
875 | |||
876 | saa_clearl(SAA7134_IRQ2, SAA7134_IRQ2_INTE_GPIO18); | ||
877 | tasklet_schedule(&ir->tlet); | ||
878 | |||
879 | return 1; | ||
880 | } | ||
diff --git a/drivers/media/video/saa7134/saa7134-ts.c b/drivers/media/video/saa7134/saa7134-ts.c index eae72fd60cec..ef55a59f0cda 100644 --- a/drivers/media/video/saa7134/saa7134-ts.c +++ b/drivers/media/video/saa7134/saa7134-ts.c | |||
@@ -66,11 +66,29 @@ static int buffer_activate(struct saa7134_dev *dev, | |||
66 | saa7134_set_dmabits(dev); | 66 | saa7134_set_dmabits(dev); |
67 | 67 | ||
68 | mod_timer(&dev->ts_q.timeout, jiffies+BUFFER_TIMEOUT); | 68 | mod_timer(&dev->ts_q.timeout, jiffies+BUFFER_TIMEOUT); |
69 | |||
70 | if (dev->ts_state == SAA7134_TS_BUFF_DONE) { | ||
71 | /* Clear TS cache */ | ||
72 | dev->buff_cnt = 0; | ||
73 | saa_writeb(SAA7134_TS_SERIAL1, 0x00); | ||
74 | saa_writeb(SAA7134_TS_SERIAL1, 0x03); | ||
75 | saa_writeb(SAA7134_TS_SERIAL1, 0x00); | ||
76 | saa_writeb(SAA7134_TS_SERIAL1, 0x01); | ||
77 | |||
78 | /* TS clock non-inverted */ | ||
79 | saa_writeb(SAA7134_TS_SERIAL1, 0x00); | ||
80 | |||
81 | /* Start TS stream */ | ||
82 | saa_writeb(SAA7134_TS_SERIAL0, 0x40); | ||
83 | saa_writeb(SAA7134_TS_PARALLEL, 0xEC); | ||
84 | dev->ts_state = SAA7134_TS_STARTED; | ||
85 | } | ||
86 | |||
69 | return 0; | 87 | return 0; |
70 | } | 88 | } |
71 | 89 | ||
72 | static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, | 90 | static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, |
73 | enum v4l2_field field) | 91 | enum v4l2_field field) |
74 | { | 92 | { |
75 | struct saa7134_dev *dev = q->priv_data; | 93 | struct saa7134_dev *dev = q->priv_data; |
76 | struct saa7134_buf *buf = container_of(vb,struct saa7134_buf,vb); | 94 | struct saa7134_buf *buf = container_of(vb,struct saa7134_buf,vb); |
@@ -110,16 +128,22 @@ static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, | |||
110 | goto oops; | 128 | goto oops; |
111 | } | 129 | } |
112 | 130 | ||
113 | /* dma: setup channel 5 (= TS) */ | 131 | dev->buff_cnt++; |
114 | control = SAA7134_RS_CONTROL_BURST_16 | | 132 | |
115 | SAA7134_RS_CONTROL_ME | | 133 | if (dev->buff_cnt == dev->ts.nr_bufs) { |
116 | (buf->pt->dma >> 12); | 134 | dev->ts_state = SAA7134_TS_BUFF_DONE; |
117 | 135 | /* dma: setup channel 5 (= TS) */ | |
118 | saa_writeb(SAA7134_TS_DMA0, ((lines-1)&0xff)); | 136 | control = SAA7134_RS_CONTROL_BURST_16 | |
119 | saa_writeb(SAA7134_TS_DMA1, (((lines-1)>>8)&0xff)); | 137 | SAA7134_RS_CONTROL_ME | |
120 | saa_writeb(SAA7134_TS_DMA2, ((((lines-1)>>16)&0x3f) | 0x00)); /* TSNOPIT=0, TSCOLAP=0 */ | 138 | (buf->pt->dma >> 12); |
121 | saa_writel(SAA7134_RS_PITCH(5),TS_PACKET_SIZE); | 139 | |
122 | saa_writel(SAA7134_RS_CONTROL(5),control); | 140 | saa_writeb(SAA7134_TS_DMA0, (lines - 1) & 0xff); |
141 | saa_writeb(SAA7134_TS_DMA1, ((lines - 1) >> 8) & 0xff); | ||
142 | /* TSNOPIT=0, TSCOLAP=0 */ | ||
143 | saa_writeb(SAA7134_TS_DMA2, (((lines - 1) >> 16) & 0x3f) | 0x00); | ||
144 | saa_writel(SAA7134_RS_PITCH(5), TS_PACKET_SIZE); | ||
145 | saa_writel(SAA7134_RS_CONTROL(5), control); | ||
146 | } | ||
123 | 147 | ||
124 | buf->vb.state = VIDEOBUF_PREPARED; | 148 | buf->vb.state = VIDEOBUF_PREPARED; |
125 | buf->activate = buffer_activate; | 149 | buf->activate = buffer_activate; |
@@ -140,6 +164,8 @@ buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size) | |||
140 | if (0 == *count) | 164 | if (0 == *count) |
141 | *count = dev->ts.nr_bufs; | 165 | *count = dev->ts.nr_bufs; |
142 | *count = saa7134_buffer_count(*size,*count); | 166 | *count = saa7134_buffer_count(*size,*count); |
167 | dev->buff_cnt = 0; | ||
168 | dev->ts_state = SAA7134_TS_STOPPED; | ||
143 | return 0; | 169 | return 0; |
144 | } | 170 | } |
145 | 171 | ||
@@ -154,7 +180,13 @@ static void buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb) | |||
154 | static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb) | 180 | static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb) |
155 | { | 181 | { |
156 | struct saa7134_buf *buf = container_of(vb,struct saa7134_buf,vb); | 182 | struct saa7134_buf *buf = container_of(vb,struct saa7134_buf,vb); |
183 | struct saa7134_dev *dev = q->priv_data; | ||
157 | 184 | ||
185 | if (dev->ts_state == SAA7134_TS_STARTED) { | ||
186 | /* Stop TS transport */ | ||
187 | saa_writeb(SAA7134_TS_PARALLEL, 0x6c); | ||
188 | dev->ts_state = SAA7134_TS_STOPPED; | ||
189 | } | ||
158 | saa7134_dma_free(q,buf); | 190 | saa7134_dma_free(q,buf); |
159 | } | 191 | } |
160 | 192 | ||
@@ -182,7 +214,7 @@ int saa7134_ts_init_hw(struct saa7134_dev *dev) | |||
182 | /* deactivate TS softreset */ | 214 | /* deactivate TS softreset */ |
183 | saa_writeb(SAA7134_TS_SERIAL1, 0x00); | 215 | saa_writeb(SAA7134_TS_SERIAL1, 0x00); |
184 | /* TSSOP high active, TSVAL high active, TSLOCK ignored */ | 216 | /* TSSOP high active, TSVAL high active, TSLOCK ignored */ |
185 | saa_writeb(SAA7134_TS_PARALLEL, 0xec); | 217 | saa_writeb(SAA7134_TS_PARALLEL, 0x6c); |
186 | saa_writeb(SAA7134_TS_PARALLEL_SERIAL, (TS_PACKET_SIZE-1)); | 218 | saa_writeb(SAA7134_TS_PARALLEL_SERIAL, (TS_PACKET_SIZE-1)); |
187 | saa_writeb(SAA7134_TS_DMA0, ((dev->ts.nr_packets-1)&0xff)); | 219 | saa_writeb(SAA7134_TS_DMA0, ((dev->ts.nr_packets-1)&0xff)); |
188 | saa_writeb(SAA7134_TS_DMA1, (((dev->ts.nr_packets-1)>>8)&0xff)); | 220 | saa_writeb(SAA7134_TS_DMA1, (((dev->ts.nr_packets-1)>>8)&0xff)); |
diff --git a/drivers/media/video/saa7134/saa7134-video.c b/drivers/media/video/saa7134/saa7134-video.c index 68c268981861..02bb6747a39c 100644 --- a/drivers/media/video/saa7134/saa7134-video.c +++ b/drivers/media/video/saa7134/saa7134-video.c | |||
@@ -628,6 +628,9 @@ void saa7134_set_tvnorm_hw(struct saa7134_dev *dev) | |||
628 | 628 | ||
629 | if (card_in(dev, dev->ctl_input).tv) | 629 | if (card_in(dev, dev->ctl_input).tv) |
630 | saa7134_i2c_call_clients(dev, VIDIOC_S_STD, &dev->tvnorm->id); | 630 | saa7134_i2c_call_clients(dev, VIDIOC_S_STD, &dev->tvnorm->id); |
631 | /* Set the correct norm for the saa6752hs. This function | ||
632 | does nothing if there is no saa6752hs. */ | ||
633 | saa7134_i2c_call_saa6752(dev, VIDIOC_S_STD, &dev->tvnorm->id); | ||
631 | } | 634 | } |
632 | 635 | ||
633 | static void set_h_prescale(struct saa7134_dev *dev, int task, int prescale) | 636 | static void set_h_prescale(struct saa7134_dev *dev, int task, int prescale) |
@@ -1330,6 +1333,8 @@ static int video_open(struct inode *inode, struct file *file) | |||
1330 | struct saa7134_fh *fh; | 1333 | struct saa7134_fh *fh; |
1331 | enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | 1334 | enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
1332 | int radio = 0; | 1335 | int radio = 0; |
1336 | |||
1337 | lock_kernel(); | ||
1333 | list_for_each_entry(dev, &saa7134_devlist, devlist) { | 1338 | list_for_each_entry(dev, &saa7134_devlist, devlist) { |
1334 | if (dev->video_dev && (dev->video_dev->minor == minor)) | 1339 | if (dev->video_dev && (dev->video_dev->minor == minor)) |
1335 | goto found; | 1340 | goto found; |
@@ -1342,6 +1347,7 @@ static int video_open(struct inode *inode, struct file *file) | |||
1342 | goto found; | 1347 | goto found; |
1343 | } | 1348 | } |
1344 | } | 1349 | } |
1350 | unlock_kernel(); | ||
1345 | return -ENODEV; | 1351 | return -ENODEV; |
1346 | found: | 1352 | found: |
1347 | 1353 | ||
@@ -1350,8 +1356,10 @@ static int video_open(struct inode *inode, struct file *file) | |||
1350 | 1356 | ||
1351 | /* allocate + initialize per filehandle data */ | 1357 | /* allocate + initialize per filehandle data */ |
1352 | fh = kzalloc(sizeof(*fh),GFP_KERNEL); | 1358 | fh = kzalloc(sizeof(*fh),GFP_KERNEL); |
1353 | if (NULL == fh) | 1359 | if (NULL == fh) { |
1360 | unlock_kernel(); | ||
1354 | return -ENOMEM; | 1361 | return -ENOMEM; |
1362 | } | ||
1355 | file->private_data = fh; | 1363 | file->private_data = fh; |
1356 | fh->dev = dev; | 1364 | fh->dev = dev; |
1357 | fh->radio = radio; | 1365 | fh->radio = radio; |
@@ -1384,6 +1392,7 @@ static int video_open(struct inode *inode, struct file *file) | |||
1384 | /* switch to video/vbi mode */ | 1392 | /* switch to video/vbi mode */ |
1385 | video_mux(dev,dev->ctl_input); | 1393 | video_mux(dev,dev->ctl_input); |
1386 | } | 1394 | } |
1395 | unlock_kernel(); | ||
1387 | return 0; | 1396 | return 0; |
1388 | } | 1397 | } |
1389 | 1398 | ||
@@ -1790,18 +1799,25 @@ static int saa7134_querycap(struct file *file, void *priv, | |||
1790 | return 0; | 1799 | return 0; |
1791 | } | 1800 | } |
1792 | 1801 | ||
1793 | static int saa7134_s_std(struct file *file, void *priv, v4l2_std_id *id) | 1802 | int saa7134_s_std_internal(struct saa7134_dev *dev, struct saa7134_fh *fh, v4l2_std_id *id) |
1794 | { | 1803 | { |
1795 | struct saa7134_fh *fh = priv; | ||
1796 | struct saa7134_dev *dev = fh->dev; | ||
1797 | unsigned long flags; | 1804 | unsigned long flags; |
1798 | unsigned int i; | 1805 | unsigned int i; |
1799 | v4l2_std_id fixup; | 1806 | v4l2_std_id fixup; |
1800 | int err; | 1807 | int err; |
1801 | 1808 | ||
1802 | err = v4l2_prio_check(&dev->prio, &fh->prio); | 1809 | /* When called from the empress code fh == NULL. |
1803 | if (0 != err) | 1810 | That needs to be fixed somehow, but for now this is |
1804 | return err; | 1811 | good enough. */ |
1812 | if (fh) { | ||
1813 | err = v4l2_prio_check(&dev->prio, &fh->prio); | ||
1814 | if (0 != err) | ||
1815 | return err; | ||
1816 | } else if (res_locked(dev, RESOURCE_OVERLAY)) { | ||
1817 | /* Don't change the std from the mpeg device | ||
1818 | if overlay is active. */ | ||
1819 | return -EBUSY; | ||
1820 | } | ||
1805 | 1821 | ||
1806 | for (i = 0; i < TVNORMS; i++) | 1822 | for (i = 0; i < TVNORMS; i++) |
1807 | if (*id == tvnorms[i].id) | 1823 | if (*id == tvnorms[i].id) |
@@ -1834,7 +1850,7 @@ static int saa7134_s_std(struct file *file, void *priv, v4l2_std_id *id) | |||
1834 | *id = tvnorms[i].id; | 1850 | *id = tvnorms[i].id; |
1835 | 1851 | ||
1836 | mutex_lock(&dev->lock); | 1852 | mutex_lock(&dev->lock); |
1837 | if (res_check(fh, RESOURCE_OVERLAY)) { | 1853 | if (fh && res_check(fh, RESOURCE_OVERLAY)) { |
1838 | spin_lock_irqsave(&dev->slock, flags); | 1854 | spin_lock_irqsave(&dev->slock, flags); |
1839 | stop_preview(dev, fh); | 1855 | stop_preview(dev, fh); |
1840 | spin_unlock_irqrestore(&dev->slock, flags); | 1856 | spin_unlock_irqrestore(&dev->slock, flags); |
@@ -1851,6 +1867,23 @@ static int saa7134_s_std(struct file *file, void *priv, v4l2_std_id *id) | |||
1851 | mutex_unlock(&dev->lock); | 1867 | mutex_unlock(&dev->lock); |
1852 | return 0; | 1868 | return 0; |
1853 | } | 1869 | } |
1870 | EXPORT_SYMBOL_GPL(saa7134_s_std_internal); | ||
1871 | |||
1872 | static int saa7134_s_std(struct file *file, void *priv, v4l2_std_id *id) | ||
1873 | { | ||
1874 | struct saa7134_fh *fh = priv; | ||
1875 | |||
1876 | return saa7134_s_std_internal(fh->dev, fh, id); | ||
1877 | } | ||
1878 | |||
1879 | static int saa7134_g_std(struct file *file, void *priv, v4l2_std_id *id) | ||
1880 | { | ||
1881 | struct saa7134_fh *fh = priv; | ||
1882 | struct saa7134_dev *dev = fh->dev; | ||
1883 | |||
1884 | *id = dev->tvnorm->id; | ||
1885 | return 0; | ||
1886 | } | ||
1854 | 1887 | ||
1855 | static int saa7134_cropcap(struct file *file, void *priv, | 1888 | static int saa7134_cropcap(struct file *file, void *priv, |
1856 | struct v4l2_cropcap *cap) | 1889 | struct v4l2_cropcap *cap) |
@@ -2077,18 +2110,6 @@ static int saa7134_enum_fmt_vid_overlay(struct file *file, void *priv, | |||
2077 | return 0; | 2110 | return 0; |
2078 | } | 2111 | } |
2079 | 2112 | ||
2080 | static int saa7134_enum_fmt_vbi_cap(struct file *file, void *priv, | ||
2081 | struct v4l2_fmtdesc *f) | ||
2082 | { | ||
2083 | if (0 != f->index) | ||
2084 | return -EINVAL; | ||
2085 | |||
2086 | f->pixelformat = V4L2_PIX_FMT_GREY; | ||
2087 | strcpy(f->description, "vbi data"); | ||
2088 | |||
2089 | return 0; | ||
2090 | } | ||
2091 | |||
2092 | static int saa7134_g_fbuf(struct file *file, void *f, | 2113 | static int saa7134_g_fbuf(struct file *file, void *f, |
2093 | struct v4l2_framebuffer *fb) | 2114 | struct v4l2_framebuffer *fb) |
2094 | { | 2115 | { |
@@ -2379,7 +2400,6 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = { | |||
2379 | .vidioc_g_fmt_vid_overlay = saa7134_g_fmt_vid_overlay, | 2400 | .vidioc_g_fmt_vid_overlay = saa7134_g_fmt_vid_overlay, |
2380 | .vidioc_try_fmt_vid_overlay = saa7134_try_fmt_vid_overlay, | 2401 | .vidioc_try_fmt_vid_overlay = saa7134_try_fmt_vid_overlay, |
2381 | .vidioc_s_fmt_vid_overlay = saa7134_s_fmt_vid_overlay, | 2402 | .vidioc_s_fmt_vid_overlay = saa7134_s_fmt_vid_overlay, |
2382 | .vidioc_enum_fmt_vbi_cap = saa7134_enum_fmt_vbi_cap, | ||
2383 | .vidioc_g_fmt_vbi_cap = saa7134_try_get_set_fmt_vbi_cap, | 2403 | .vidioc_g_fmt_vbi_cap = saa7134_try_get_set_fmt_vbi_cap, |
2384 | .vidioc_try_fmt_vbi_cap = saa7134_try_get_set_fmt_vbi_cap, | 2404 | .vidioc_try_fmt_vbi_cap = saa7134_try_get_set_fmt_vbi_cap, |
2385 | .vidioc_s_fmt_vbi_cap = saa7134_try_get_set_fmt_vbi_cap, | 2405 | .vidioc_s_fmt_vbi_cap = saa7134_try_get_set_fmt_vbi_cap, |
@@ -2391,6 +2411,7 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = { | |||
2391 | .vidioc_qbuf = saa7134_qbuf, | 2411 | .vidioc_qbuf = saa7134_qbuf, |
2392 | .vidioc_dqbuf = saa7134_dqbuf, | 2412 | .vidioc_dqbuf = saa7134_dqbuf, |
2393 | .vidioc_s_std = saa7134_s_std, | 2413 | .vidioc_s_std = saa7134_s_std, |
2414 | .vidioc_g_std = saa7134_g_std, | ||
2394 | .vidioc_enum_input = saa7134_enum_input, | 2415 | .vidioc_enum_input = saa7134_enum_input, |
2395 | .vidioc_g_input = saa7134_g_input, | 2416 | .vidioc_g_input = saa7134_g_input, |
2396 | .vidioc_s_input = saa7134_s_input, | 2417 | .vidioc_s_input = saa7134_s_input, |
diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index a0884f639f65..491ab1f8fdd3 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h | |||
@@ -269,6 +269,12 @@ struct saa7134_format { | |||
269 | #define SAA7134_BOARD_BEHOLD_M6_EXTRA 144 | 269 | #define SAA7134_BOARD_BEHOLD_M6_EXTRA 144 |
270 | #define SAA7134_BOARD_AVERMEDIA_M103 145 | 270 | #define SAA7134_BOARD_AVERMEDIA_M103 145 |
271 | #define SAA7134_BOARD_ASUSTeK_P7131_ANALOG 146 | 271 | #define SAA7134_BOARD_ASUSTeK_P7131_ANALOG 146 |
272 | #define SAA7134_BOARD_ASUSTeK_TIGER_3IN1 147 | ||
273 | #define SAA7134_BOARD_ENCORE_ENLTV_FM53 148 | ||
274 | #define SAA7134_BOARD_AVERMEDIA_M135A 149 | ||
275 | #define SAA7134_BOARD_REAL_ANGEL_220 150 | ||
276 | #define SAA7134_BOARD_ADS_INSTANT_HDTV_PCI 151 | ||
277 | #define SAA7134_BOARD_ASUSTeK_TIGER 152 | ||
272 | 278 | ||
273 | #define SAA7134_MAXBOARDS 8 | 279 | #define SAA7134_MAXBOARDS 8 |
274 | #define SAA7134_INPUT_MAX 8 | 280 | #define SAA7134_INPUT_MAX 8 |
@@ -462,6 +468,12 @@ struct saa7134_mpeg_ops { | |||
462 | void (*signal_change)(struct saa7134_dev *dev); | 468 | void (*signal_change)(struct saa7134_dev *dev); |
463 | }; | 469 | }; |
464 | 470 | ||
471 | enum saa7134_ts_status { | ||
472 | SAA7134_TS_STOPPED, | ||
473 | SAA7134_TS_BUFF_DONE, | ||
474 | SAA7134_TS_STARTED, | ||
475 | }; | ||
476 | |||
465 | /* global device status */ | 477 | /* global device status */ |
466 | struct saa7134_dev { | 478 | struct saa7134_dev { |
467 | struct list_head devlist; | 479 | struct list_head devlist; |
@@ -555,6 +567,8 @@ struct saa7134_dev { | |||
555 | /* SAA7134_MPEG_* */ | 567 | /* SAA7134_MPEG_* */ |
556 | struct saa7134_ts ts; | 568 | struct saa7134_ts ts; |
557 | struct saa7134_dmaqueue ts_q; | 569 | struct saa7134_dmaqueue ts_q; |
570 | enum saa7134_ts_status ts_state; | ||
571 | unsigned int buff_cnt; | ||
558 | struct saa7134_mpeg_ops *mops; | 572 | struct saa7134_mpeg_ops *mops; |
559 | struct i2c_client *mpeg_i2c_client; | 573 | struct i2c_client *mpeg_i2c_client; |
560 | 574 | ||
@@ -644,7 +658,7 @@ extern struct pci_device_id __devinitdata saa7134_pci_tbl[]; | |||
644 | 658 | ||
645 | extern int saa7134_board_init1(struct saa7134_dev *dev); | 659 | extern int saa7134_board_init1(struct saa7134_dev *dev); |
646 | extern int saa7134_board_init2(struct saa7134_dev *dev); | 660 | extern int saa7134_board_init2(struct saa7134_dev *dev); |
647 | int saa7134_tuner_callback(void *priv, int command, int arg); | 661 | int saa7134_tuner_callback(void *priv, int component, int command, int arg); |
648 | 662 | ||
649 | 663 | ||
650 | /* ----------------------------------------------------------- */ | 664 | /* ----------------------------------------------------------- */ |
@@ -654,6 +668,8 @@ int saa7134_i2c_register(struct saa7134_dev *dev); | |||
654 | int saa7134_i2c_unregister(struct saa7134_dev *dev); | 668 | int saa7134_i2c_unregister(struct saa7134_dev *dev); |
655 | void saa7134_i2c_call_clients(struct saa7134_dev *dev, | 669 | void saa7134_i2c_call_clients(struct saa7134_dev *dev, |
656 | unsigned int cmd, void *arg); | 670 | unsigned int cmd, void *arg); |
671 | int saa7134_i2c_call_saa6752(struct saa7134_dev *dev, | ||
672 | unsigned int cmd, void *arg); | ||
657 | 673 | ||
658 | 674 | ||
659 | /* ----------------------------------------------------------- */ | 675 | /* ----------------------------------------------------------- */ |
@@ -666,6 +682,7 @@ extern struct video_device saa7134_radio_template; | |||
666 | int saa7134_s_ctrl_internal(struct saa7134_dev *dev, struct saa7134_fh *fh, struct v4l2_control *c); | 682 | int saa7134_s_ctrl_internal(struct saa7134_dev *dev, struct saa7134_fh *fh, struct v4l2_control *c); |
667 | int saa7134_g_ctrl_internal(struct saa7134_dev *dev, struct saa7134_fh *fh, struct v4l2_control *c); | 683 | int saa7134_g_ctrl_internal(struct saa7134_dev *dev, struct saa7134_fh *fh, struct v4l2_control *c); |
668 | int saa7134_queryctrl(struct file *file, void *priv, struct v4l2_queryctrl *c); | 684 | int saa7134_queryctrl(struct file *file, void *priv, struct v4l2_queryctrl *c); |
685 | int saa7134_s_std_internal(struct saa7134_dev *dev, struct saa7134_fh *fh, v4l2_std_id *id); | ||
669 | 686 | ||
670 | int saa7134_videoport_init(struct saa7134_dev *dev); | 687 | int saa7134_videoport_init(struct saa7134_dev *dev); |
671 | void saa7134_set_tvnorm_hw(struct saa7134_dev *dev); | 688 | void saa7134_set_tvnorm_hw(struct saa7134_dev *dev); |
diff --git a/drivers/media/video/se401.c b/drivers/media/video/se401.c index acceed5d04ae..ae3949180c4e 100644 --- a/drivers/media/video/se401.c +++ b/drivers/media/video/se401.c | |||
@@ -288,7 +288,7 @@ static void se401_button_irq(struct urb *urb) | |||
288 | int status; | 288 | int status; |
289 | 289 | ||
290 | if (!se401->dev) { | 290 | if (!se401->dev) { |
291 | info("ohoh: device vapourished"); | 291 | dev_info(&urb->dev->dev, "device vapourished\n"); |
292 | return; | 292 | return; |
293 | } | 293 | } |
294 | 294 | ||
@@ -328,7 +328,7 @@ static void se401_video_irq(struct urb *urb) | |||
328 | return; | 328 | return; |
329 | 329 | ||
330 | if (!se401->dev) { | 330 | if (!se401->dev) { |
331 | info ("ohoh: device vapourished"); | 331 | dev_info(&urb->dev->dev, "device vapourished\n"); |
332 | return; | 332 | return; |
333 | } | 333 | } |
334 | 334 | ||
@@ -375,7 +375,7 @@ static void se401_video_irq(struct urb *urb) | |||
375 | urb->status=0; | 375 | urb->status=0; |
376 | urb->dev=se401->dev; | 376 | urb->dev=se401->dev; |
377 | if(usb_submit_urb(urb, GFP_KERNEL)) | 377 | if(usb_submit_urb(urb, GFP_KERNEL)) |
378 | info("urb burned down"); | 378 | dev_info(&urb->dev->dev, "urb burned down\n"); |
379 | return; | 379 | return; |
380 | } | 380 | } |
381 | 381 | ||
@@ -860,7 +860,8 @@ static int se401_newframe(struct usb_se401 *se401, int framenr) | |||
860 | ); | 860 | ); |
861 | if (se401->nullpackets > SE401_MAX_NULLPACKETS) { | 861 | if (se401->nullpackets > SE401_MAX_NULLPACKETS) { |
862 | se401->nullpackets=0; | 862 | se401->nullpackets=0; |
863 | info("to many null length packets, restarting capture"); | 863 | dev_info(&se401->dev->dev, |
864 | "too many null length packets, restarting capture\n"); | ||
864 | se401_stop_stream(se401); | 865 | se401_stop_stream(se401); |
865 | se401_start_stream(se401); | 866 | se401_start_stream(se401); |
866 | } else { | 867 | } else { |
@@ -880,7 +881,8 @@ static int se401_newframe(struct usb_se401 *se401, int framenr) | |||
880 | se401->scratch_use=0; | 881 | se401->scratch_use=0; |
881 | if (errors > SE401_MAX_ERRORS) { | 882 | if (errors > SE401_MAX_ERRORS) { |
882 | errors=0; | 883 | errors=0; |
883 | info("to much errors, restarting capture"); | 884 | dev_info(&se401->dev->dev, |
885 | "too many errors, restarting capture\n"); | ||
884 | se401_stop_stream(se401); | 886 | se401_stop_stream(se401); |
885 | se401_start_stream(se401); | 887 | se401_start_stream(se401); |
886 | } | 888 | } |
@@ -913,7 +915,7 @@ static void usb_se401_remove_disconnected (struct usb_se401 *se401) | |||
913 | usb_kill_urb(se401->inturb); | 915 | usb_kill_urb(se401->inturb); |
914 | usb_free_urb(se401->inturb); | 916 | usb_free_urb(se401->inturb); |
915 | } | 917 | } |
916 | info("%s disconnected", se401->camera_name); | 918 | dev_info(&se401->dev->dev, "%s disconnected", se401->camera_name); |
917 | 919 | ||
918 | /* Free the memory */ | 920 | /* Free the memory */ |
919 | kfree(se401->width); | 921 | kfree(se401->width); |
@@ -936,14 +938,18 @@ static int se401_open(struct inode *inode, struct file *file) | |||
936 | struct usb_se401 *se401 = (struct usb_se401 *)dev; | 938 | struct usb_se401 *se401 = (struct usb_se401 *)dev; |
937 | int err = 0; | 939 | int err = 0; |
938 | 940 | ||
939 | if (se401->user) | 941 | lock_kernel(); |
942 | if (se401->user) { | ||
943 | unlock_kernel(); | ||
940 | return -EBUSY; | 944 | return -EBUSY; |
945 | } | ||
941 | se401->fbuf = rvmalloc(se401->maxframesize * SE401_NUMFRAMES); | 946 | se401->fbuf = rvmalloc(se401->maxframesize * SE401_NUMFRAMES); |
942 | if (se401->fbuf) | 947 | if (se401->fbuf) |
943 | file->private_data = dev; | 948 | file->private_data = dev; |
944 | else | 949 | else |
945 | err = -ENOMEM; | 950 | err = -ENOMEM; |
946 | se401->user = !err; | 951 | se401->user = !err; |
952 | unlock_kernel(); | ||
947 | 953 | ||
948 | return err; | 954 | return err; |
949 | } | 955 | } |
@@ -956,8 +962,8 @@ static int se401_close(struct inode *inode, struct file *file) | |||
956 | 962 | ||
957 | rvfree(se401->fbuf, se401->maxframesize * SE401_NUMFRAMES); | 963 | rvfree(se401->fbuf, se401->maxframesize * SE401_NUMFRAMES); |
958 | if (se401->removed) { | 964 | if (se401->removed) { |
965 | dev_info(&se401->dev->dev, "device unregistered\n"); | ||
959 | usb_se401_remove_disconnected(se401); | 966 | usb_se401_remove_disconnected(se401); |
960 | info("device unregistered"); | ||
961 | } else { | 967 | } else { |
962 | for (i=0; i<SE401_NUMFRAMES; i++) | 968 | for (i=0; i<SE401_NUMFRAMES; i++) |
963 | se401->frame[i].grabstate=FRAME_UNUSED; | 969 | se401->frame[i].grabstate=FRAME_UNUSED; |
@@ -1232,6 +1238,7 @@ static const struct file_operations se401_fops = { | |||
1232 | static struct video_device se401_template = { | 1238 | static struct video_device se401_template = { |
1233 | .name = "se401 USB camera", | 1239 | .name = "se401 USB camera", |
1234 | .fops = &se401_fops, | 1240 | .fops = &se401_fops, |
1241 | .release = video_device_release_empty, | ||
1235 | }; | 1242 | }; |
1236 | 1243 | ||
1237 | 1244 | ||
@@ -1271,7 +1278,7 @@ static int se401_init(struct usb_se401 *se401, int button) | |||
1271 | for (i=0; i<se401->sizes; i++) { | 1278 | for (i=0; i<se401->sizes; i++) { |
1272 | sprintf(temp, "%s %dx%d", temp, se401->width[i], se401->height[i]); | 1279 | sprintf(temp, "%s %dx%d", temp, se401->width[i], se401->height[i]); |
1273 | } | 1280 | } |
1274 | info("%s", temp); | 1281 | dev_info(&se401->dev->dev, "%s\n", temp); |
1275 | se401->maxframesize=se401->width[se401->sizes-1]*se401->height[se401->sizes-1]*3; | 1282 | se401->maxframesize=se401->width[se401->sizes-1]*se401->height[se401->sizes-1]*3; |
1276 | 1283 | ||
1277 | rc=se401_sndctrl(0, se401, SE401_REQ_GET_WIDTH, 0, cp, sizeof(cp)); | 1284 | rc=se401_sndctrl(0, se401, SE401_REQ_GET_WIDTH, 0, cp, sizeof(cp)); |
@@ -1305,7 +1312,8 @@ static int se401_init(struct usb_se401 *se401, int button) | |||
1305 | if (button) { | 1312 | if (button) { |
1306 | se401->inturb=usb_alloc_urb(0, GFP_KERNEL); | 1313 | se401->inturb=usb_alloc_urb(0, GFP_KERNEL); |
1307 | if (!se401->inturb) { | 1314 | if (!se401->inturb) { |
1308 | info("Allocation of inturb failed"); | 1315 | dev_info(&se401->dev->dev, |
1316 | "Allocation of inturb failed\n"); | ||
1309 | return 1; | 1317 | return 1; |
1310 | } | 1318 | } |
1311 | usb_fill_int_urb(se401->inturb, se401->dev, | 1319 | usb_fill_int_urb(se401->inturb, se401->dev, |
@@ -1316,7 +1324,7 @@ static int se401_init(struct usb_se401 *se401, int button) | |||
1316 | 8 | 1324 | 8 |
1317 | ); | 1325 | ); |
1318 | if (usb_submit_urb(se401->inturb, GFP_KERNEL)) { | 1326 | if (usb_submit_urb(se401->inturb, GFP_KERNEL)) { |
1319 | info("int urb burned down"); | 1327 | dev_info(&se401->dev->dev, "int urb burned down\n"); |
1320 | return 1; | 1328 | return 1; |
1321 | } | 1329 | } |
1322 | } else | 1330 | } else |
@@ -1373,7 +1381,7 @@ static int se401_probe(struct usb_interface *intf, | |||
1373 | return -ENODEV; | 1381 | return -ENODEV; |
1374 | 1382 | ||
1375 | /* We found one */ | 1383 | /* We found one */ |
1376 | info("SE401 camera found: %s", camera_name); | 1384 | dev_info(&intf->dev, "SE401 camera found: %s\n", camera_name); |
1377 | 1385 | ||
1378 | if ((se401 = kzalloc(sizeof(*se401), GFP_KERNEL)) == NULL) { | 1386 | if ((se401 = kzalloc(sizeof(*se401), GFP_KERNEL)) == NULL) { |
1379 | err("couldn't kmalloc se401 struct"); | 1387 | err("couldn't kmalloc se401 struct"); |
@@ -1384,7 +1392,8 @@ static int se401_probe(struct usb_interface *intf, | |||
1384 | se401->iface = interface->bInterfaceNumber; | 1392 | se401->iface = interface->bInterfaceNumber; |
1385 | se401->camera_name = camera_name; | 1393 | se401->camera_name = camera_name; |
1386 | 1394 | ||
1387 | info("firmware version: %02x", le16_to_cpu(dev->descriptor.bcdDevice) & 255); | 1395 | dev_info(&intf->dev, "firmware version: %02x\n", |
1396 | le16_to_cpu(dev->descriptor.bcdDevice) & 255); | ||
1388 | 1397 | ||
1389 | if (se401_init(se401, button)) { | 1398 | if (se401_init(se401, button)) { |
1390 | kfree(se401); | 1399 | kfree(se401); |
@@ -1402,7 +1411,8 @@ static int se401_probe(struct usb_interface *intf, | |||
1402 | err("video_register_device failed"); | 1411 | err("video_register_device failed"); |
1403 | return -EIO; | 1412 | return -EIO; |
1404 | } | 1413 | } |
1405 | info("registered new video device: video%d", se401->vdev.minor); | 1414 | dev_info(&intf->dev, "registered new video device: video%d\n", |
1415 | se401->vdev.minor); | ||
1406 | 1416 | ||
1407 | usb_set_intfdata (intf, se401); | 1417 | usb_set_intfdata (intf, se401); |
1408 | return 0; | 1418 | return 0; |
@@ -1446,10 +1456,10 @@ static struct usb_driver se401_driver = { | |||
1446 | 1456 | ||
1447 | static int __init usb_se401_init(void) | 1457 | static int __init usb_se401_init(void) |
1448 | { | 1458 | { |
1449 | info("SE401 usb camera driver version %s registering", version); | 1459 | printk(KERN_INFO "SE401 usb camera driver version %s registering\n", version); |
1450 | if (flickerless) | 1460 | if (flickerless) |
1451 | if (flickerless!=50 && flickerless!=60) { | 1461 | if (flickerless!=50 && flickerless!=60) { |
1452 | info("Invallid flickerless value, use 0, 50 or 60."); | 1462 | printk(KERN_ERR "Invallid flickerless value, use 0, 50 or 60.\n"); |
1453 | return -1; | 1463 | return -1; |
1454 | } | 1464 | } |
1455 | return usb_register(&se401_driver); | 1465 | return usb_register(&se401_driver); |
@@ -1458,7 +1468,7 @@ static int __init usb_se401_init(void) | |||
1458 | static void __exit usb_se401_exit(void) | 1468 | static void __exit usb_se401_exit(void) |
1459 | { | 1469 | { |
1460 | usb_deregister(&se401_driver); | 1470 | usb_deregister(&se401_driver); |
1461 | info("SE401 driver deregistered"); | 1471 | printk(KERN_INFO "SE401 driver deregistered\frame"); |
1462 | } | 1472 | } |
1463 | 1473 | ||
1464 | module_init(usb_se401_init); | 1474 | module_init(usb_se401_init); |
diff --git a/drivers/media/video/sh_mobile_ceu_camera.c b/drivers/media/video/sh_mobile_ceu_camera.c index 318754e73132..76838091dc66 100644 --- a/drivers/media/video/sh_mobile_ceu_camera.c +++ b/drivers/media/video/sh_mobile_ceu_camera.c | |||
@@ -304,9 +304,6 @@ static int sh_mobile_ceu_add_device(struct soc_camera_device *icd) | |||
304 | "SuperH Mobile CEU driver attached to camera %d\n", | 304 | "SuperH Mobile CEU driver attached to camera %d\n", |
305 | icd->devnum); | 305 | icd->devnum); |
306 | 306 | ||
307 | if (pcdev->pdata->enable_camera) | ||
308 | pcdev->pdata->enable_camera(); | ||
309 | |||
310 | ret = icd->ops->init(icd); | 307 | ret = icd->ops->init(icd); |
311 | if (ret) | 308 | if (ret) |
312 | goto err; | 309 | goto err; |
@@ -333,8 +330,6 @@ static void sh_mobile_ceu_remove_device(struct soc_camera_device *icd) | |||
333 | ceu_write(pcdev, CEIER, 0); | 330 | ceu_write(pcdev, CEIER, 0); |
334 | ceu_write(pcdev, CAPSR, 1 << 16); /* reset */ | 331 | ceu_write(pcdev, CAPSR, 1 << 16); /* reset */ |
335 | icd->ops->release(icd); | 332 | icd->ops->release(icd); |
336 | if (pcdev->pdata->disable_camera) | ||
337 | pcdev->pdata->disable_camera(); | ||
338 | 333 | ||
339 | dev_info(&icd->dev, | 334 | dev_info(&icd->dev, |
340 | "SuperH Mobile CEU driver detached from camera %d\n", | 335 | "SuperH Mobile CEU driver detached from camera %d\n", |
diff --git a/drivers/media/video/sn9c102/sn9c102_core.c b/drivers/media/video/sn9c102/sn9c102_core.c index 2da6938718f2..20e30bd9364b 100644 --- a/drivers/media/video/sn9c102/sn9c102_core.c +++ b/drivers/media/video/sn9c102/sn9c102_core.c | |||
@@ -116,6 +116,26 @@ MODULE_PARM_DESC(debug, | |||
116 | "\n"); | 116 | "\n"); |
117 | #endif | 117 | #endif |
118 | 118 | ||
119 | /* | ||
120 | Add the probe entries to this table. Be sure to add the entry in the right | ||
121 | place, since, on failure, the next probing routine is called according to | ||
122 | the order of the list below, from top to bottom. | ||
123 | */ | ||
124 | static int (*sn9c102_sensor_table[])(struct sn9c102_device *) = { | ||
125 | &sn9c102_probe_hv7131d, /* strong detection based on SENSOR ids */ | ||
126 | &sn9c102_probe_hv7131r, /* strong detection based on SENSOR ids */ | ||
127 | &sn9c102_probe_mi0343, /* strong detection based on SENSOR ids */ | ||
128 | &sn9c102_probe_mi0360, /* strong detection based on SENSOR ids */ | ||
129 | &sn9c102_probe_mt9v111, /* strong detection based on SENSOR ids */ | ||
130 | &sn9c102_probe_pas106b, /* strong detection based on SENSOR ids */ | ||
131 | &sn9c102_probe_pas202bcb, /* strong detection based on SENSOR ids */ | ||
132 | &sn9c102_probe_ov7630, /* strong detection based on SENSOR ids */ | ||
133 | &sn9c102_probe_ov7660, /* strong detection based on SENSOR ids */ | ||
134 | &sn9c102_probe_tas5110c1b, /* detection based on USB pid/vid */ | ||
135 | &sn9c102_probe_tas5110d, /* detection based on USB pid/vid */ | ||
136 | &sn9c102_probe_tas5130d1b, /* detection based on USB pid/vid */ | ||
137 | }; | ||
138 | |||
119 | /*****************************************************************************/ | 139 | /*****************************************************************************/ |
120 | 140 | ||
121 | static u32 | 141 | static u32 |
@@ -1746,7 +1766,7 @@ static int sn9c102_open(struct inode* inode, struct file* filp) | |||
1746 | if (!down_read_trylock(&sn9c102_dev_lock)) | 1766 | if (!down_read_trylock(&sn9c102_dev_lock)) |
1747 | return -ERESTARTSYS; | 1767 | return -ERESTARTSYS; |
1748 | 1768 | ||
1749 | cam = video_get_drvdata(video_devdata(filp)); | 1769 | cam = video_drvdata(filp); |
1750 | 1770 | ||
1751 | if (wait_for_completion_interruptible(&cam->probe)) { | 1771 | if (wait_for_completion_interruptible(&cam->probe)) { |
1752 | up_read(&sn9c102_dev_lock); | 1772 | up_read(&sn9c102_dev_lock); |
@@ -1843,7 +1863,7 @@ static int sn9c102_release(struct inode* inode, struct file* filp) | |||
1843 | 1863 | ||
1844 | down_write(&sn9c102_dev_lock); | 1864 | down_write(&sn9c102_dev_lock); |
1845 | 1865 | ||
1846 | cam = video_get_drvdata(video_devdata(filp)); | 1866 | cam = video_drvdata(filp); |
1847 | 1867 | ||
1848 | sn9c102_stop_transfer(cam); | 1868 | sn9c102_stop_transfer(cam); |
1849 | sn9c102_release_buffers(cam); | 1869 | sn9c102_release_buffers(cam); |
@@ -1863,7 +1883,7 @@ static int sn9c102_release(struct inode* inode, struct file* filp) | |||
1863 | static ssize_t | 1883 | static ssize_t |
1864 | sn9c102_read(struct file* filp, char __user * buf, size_t count, loff_t* f_pos) | 1884 | sn9c102_read(struct file* filp, char __user * buf, size_t count, loff_t* f_pos) |
1865 | { | 1885 | { |
1866 | struct sn9c102_device* cam = video_get_drvdata(video_devdata(filp)); | 1886 | struct sn9c102_device *cam = video_drvdata(filp); |
1867 | struct sn9c102_frame_t* f, * i; | 1887 | struct sn9c102_frame_t* f, * i; |
1868 | unsigned long lock_flags; | 1888 | unsigned long lock_flags; |
1869 | long timeout; | 1889 | long timeout; |
@@ -1987,7 +2007,7 @@ exit: | |||
1987 | 2007 | ||
1988 | static unsigned int sn9c102_poll(struct file *filp, poll_table *wait) | 2008 | static unsigned int sn9c102_poll(struct file *filp, poll_table *wait) |
1989 | { | 2009 | { |
1990 | struct sn9c102_device* cam = video_get_drvdata(video_devdata(filp)); | 2010 | struct sn9c102_device *cam = video_drvdata(filp); |
1991 | struct sn9c102_frame_t* f; | 2011 | struct sn9c102_frame_t* f; |
1992 | unsigned long lock_flags; | 2012 | unsigned long lock_flags; |
1993 | unsigned int mask = 0; | 2013 | unsigned int mask = 0; |
@@ -2063,7 +2083,7 @@ static struct vm_operations_struct sn9c102_vm_ops = { | |||
2063 | 2083 | ||
2064 | static int sn9c102_mmap(struct file* filp, struct vm_area_struct *vma) | 2084 | static int sn9c102_mmap(struct file* filp, struct vm_area_struct *vma) |
2065 | { | 2085 | { |
2066 | struct sn9c102_device* cam = video_get_drvdata(video_devdata(filp)); | 2086 | struct sn9c102_device *cam = video_drvdata(filp); |
2067 | unsigned long size = vma->vm_end - vma->vm_start, | 2087 | unsigned long size = vma->vm_end - vma->vm_start, |
2068 | start = vma->vm_start; | 2088 | start = vma->vm_start; |
2069 | void *pos; | 2089 | void *pos; |
@@ -3075,7 +3095,7 @@ sn9c102_vidioc_s_audio(struct sn9c102_device* cam, void __user * arg) | |||
3075 | static int sn9c102_ioctl_v4l2(struct inode* inode, struct file* filp, | 3095 | static int sn9c102_ioctl_v4l2(struct inode* inode, struct file* filp, |
3076 | unsigned int cmd, void __user * arg) | 3096 | unsigned int cmd, void __user * arg) |
3077 | { | 3097 | { |
3078 | struct sn9c102_device* cam = video_get_drvdata(video_devdata(filp)); | 3098 | struct sn9c102_device *cam = video_drvdata(filp); |
3079 | 3099 | ||
3080 | switch (cmd) { | 3100 | switch (cmd) { |
3081 | 3101 | ||
@@ -3179,7 +3199,7 @@ static int sn9c102_ioctl_v4l2(struct inode* inode, struct file* filp, | |||
3179 | static int sn9c102_ioctl(struct inode* inode, struct file* filp, | 3199 | static int sn9c102_ioctl(struct inode* inode, struct file* filp, |
3180 | unsigned int cmd, unsigned long arg) | 3200 | unsigned int cmd, unsigned long arg) |
3181 | { | 3201 | { |
3182 | struct sn9c102_device* cam = video_get_drvdata(video_devdata(filp)); | 3202 | struct sn9c102_device *cam = video_drvdata(filp); |
3183 | int err = 0; | 3203 | int err = 0; |
3184 | 3204 | ||
3185 | if (mutex_lock_interruptible(&cam->fileop_mutex)) | 3205 | if (mutex_lock_interruptible(&cam->fileop_mutex)) |
diff --git a/drivers/media/video/sn9c102/sn9c102_devtable.h b/drivers/media/video/sn9c102/sn9c102_devtable.h index 90a401dc3884..e23734f6d6e2 100644 --- a/drivers/media/video/sn9c102/sn9c102_devtable.h +++ b/drivers/media/video/sn9c102/sn9c102_devtable.h | |||
@@ -140,24 +140,4 @@ extern int sn9c102_probe_tas5110c1b(struct sn9c102_device* cam); | |||
140 | extern int sn9c102_probe_tas5110d(struct sn9c102_device* cam); | 140 | extern int sn9c102_probe_tas5110d(struct sn9c102_device* cam); |
141 | extern int sn9c102_probe_tas5130d1b(struct sn9c102_device* cam); | 141 | extern int sn9c102_probe_tas5130d1b(struct sn9c102_device* cam); |
142 | 142 | ||
143 | /* | ||
144 | Add the above entries to this table. Be sure to add the entry in the right | ||
145 | place, since, on failure, the next probing routine is called according to | ||
146 | the order of the list below, from top to bottom. | ||
147 | */ | ||
148 | static int (*sn9c102_sensor_table[])(struct sn9c102_device*) = { | ||
149 | &sn9c102_probe_hv7131d, /* strong detection based on SENSOR ids */ | ||
150 | &sn9c102_probe_hv7131r, /* strong detection based on SENSOR ids */ | ||
151 | &sn9c102_probe_mi0343, /* strong detection based on SENSOR ids */ | ||
152 | &sn9c102_probe_mi0360, /* strong detection based on SENSOR ids */ | ||
153 | &sn9c102_probe_mt9v111, /* strong detection based on SENSOR ids */ | ||
154 | &sn9c102_probe_pas106b, /* strong detection based on SENSOR ids */ | ||
155 | &sn9c102_probe_pas202bcb, /* strong detection based on SENSOR ids */ | ||
156 | &sn9c102_probe_ov7630, /* strong detection based on SENSOR ids */ | ||
157 | &sn9c102_probe_ov7660, /* strong detection based on SENSOR ids */ | ||
158 | &sn9c102_probe_tas5110c1b, /* detection based on USB pid/vid */ | ||
159 | &sn9c102_probe_tas5110d, /* detection based on USB pid/vid */ | ||
160 | &sn9c102_probe_tas5130d1b, /* detection based on USB pid/vid */ | ||
161 | }; | ||
162 | |||
163 | #endif /* _SN9C102_DEVTABLE_H_ */ | 143 | #endif /* _SN9C102_DEVTABLE_H_ */ |
diff --git a/drivers/media/video/sn9c102/sn9c102_hv7131d.c b/drivers/media/video/sn9c102/sn9c102_hv7131d.c index eaf9ad0dc8a6..db2434948939 100644 --- a/drivers/media/video/sn9c102/sn9c102_hv7131d.c +++ b/drivers/media/video/sn9c102/sn9c102_hv7131d.c | |||
@@ -20,6 +20,7 @@ | |||
20 | ***************************************************************************/ | 20 | ***************************************************************************/ |
21 | 21 | ||
22 | #include "sn9c102_sensor.h" | 22 | #include "sn9c102_sensor.h" |
23 | #include "sn9c102_devtable.h" | ||
23 | 24 | ||
24 | 25 | ||
25 | static int hv7131d_init(struct sn9c102_device* cam) | 26 | static int hv7131d_init(struct sn9c102_device* cam) |
diff --git a/drivers/media/video/sn9c102/sn9c102_hv7131r.c b/drivers/media/video/sn9c102/sn9c102_hv7131r.c index 0fc401223cfc..4295887ff609 100644 --- a/drivers/media/video/sn9c102/sn9c102_hv7131r.c +++ b/drivers/media/video/sn9c102/sn9c102_hv7131r.c | |||
@@ -20,6 +20,7 @@ | |||
20 | ***************************************************************************/ | 20 | ***************************************************************************/ |
21 | 21 | ||
22 | #include "sn9c102_sensor.h" | 22 | #include "sn9c102_sensor.h" |
23 | #include "sn9c102_devtable.h" | ||
23 | 24 | ||
24 | 25 | ||
25 | static int hv7131r_init(struct sn9c102_device* cam) | 26 | static int hv7131r_init(struct sn9c102_device* cam) |
diff --git a/drivers/media/video/sn9c102/sn9c102_mi0343.c b/drivers/media/video/sn9c102/sn9c102_mi0343.c index 00b134ca0a3d..1f5b09bec89c 100644 --- a/drivers/media/video/sn9c102/sn9c102_mi0343.c +++ b/drivers/media/video/sn9c102/sn9c102_mi0343.c | |||
@@ -20,6 +20,7 @@ | |||
20 | ***************************************************************************/ | 20 | ***************************************************************************/ |
21 | 21 | ||
22 | #include "sn9c102_sensor.h" | 22 | #include "sn9c102_sensor.h" |
23 | #include "sn9c102_devtable.h" | ||
23 | 24 | ||
24 | 25 | ||
25 | static int mi0343_init(struct sn9c102_device* cam) | 26 | static int mi0343_init(struct sn9c102_device* cam) |
diff --git a/drivers/media/video/sn9c102/sn9c102_mi0360.c b/drivers/media/video/sn9c102/sn9c102_mi0360.c index f8d81d82e8d5..d973fc1973d9 100644 --- a/drivers/media/video/sn9c102/sn9c102_mi0360.c +++ b/drivers/media/video/sn9c102/sn9c102_mi0360.c | |||
@@ -20,6 +20,7 @@ | |||
20 | ***************************************************************************/ | 20 | ***************************************************************************/ |
21 | 21 | ||
22 | #include "sn9c102_sensor.h" | 22 | #include "sn9c102_sensor.h" |
23 | #include "sn9c102_devtable.h" | ||
23 | 24 | ||
24 | 25 | ||
25 | static int mi0360_init(struct sn9c102_device* cam) | 26 | static int mi0360_init(struct sn9c102_device* cam) |
diff --git a/drivers/media/video/sn9c102/sn9c102_mt9v111.c b/drivers/media/video/sn9c102/sn9c102_mt9v111.c index 3b98ac3bbc38..95986eb492e4 100644 --- a/drivers/media/video/sn9c102/sn9c102_mt9v111.c +++ b/drivers/media/video/sn9c102/sn9c102_mt9v111.c | |||
@@ -20,6 +20,7 @@ | |||
20 | ***************************************************************************/ | 20 | ***************************************************************************/ |
21 | 21 | ||
22 | #include "sn9c102_sensor.h" | 22 | #include "sn9c102_sensor.h" |
23 | #include "sn9c102_devtable.h" | ||
23 | 24 | ||
24 | 25 | ||
25 | static int mt9v111_init(struct sn9c102_device *cam) | 26 | static int mt9v111_init(struct sn9c102_device *cam) |
diff --git a/drivers/media/video/sn9c102/sn9c102_ov7630.c b/drivers/media/video/sn9c102/sn9c102_ov7630.c index e4856fd77982..803712c29f02 100644 --- a/drivers/media/video/sn9c102/sn9c102_ov7630.c +++ b/drivers/media/video/sn9c102/sn9c102_ov7630.c | |||
@@ -20,6 +20,7 @@ | |||
20 | ***************************************************************************/ | 20 | ***************************************************************************/ |
21 | 21 | ||
22 | #include "sn9c102_sensor.h" | 22 | #include "sn9c102_sensor.h" |
23 | #include "sn9c102_devtable.h" | ||
23 | 24 | ||
24 | 25 | ||
25 | static int ov7630_init(struct sn9c102_device* cam) | 26 | static int ov7630_init(struct sn9c102_device* cam) |
diff --git a/drivers/media/video/sn9c102/sn9c102_ov7660.c b/drivers/media/video/sn9c102/sn9c102_ov7660.c index 8aae416ba8ec..7977795d342b 100644 --- a/drivers/media/video/sn9c102/sn9c102_ov7660.c +++ b/drivers/media/video/sn9c102/sn9c102_ov7660.c | |||
@@ -20,6 +20,7 @@ | |||
20 | ***************************************************************************/ | 20 | ***************************************************************************/ |
21 | 21 | ||
22 | #include "sn9c102_sensor.h" | 22 | #include "sn9c102_sensor.h" |
23 | #include "sn9c102_devtable.h" | ||
23 | 24 | ||
24 | 25 | ||
25 | static int ov7660_init(struct sn9c102_device* cam) | 26 | static int ov7660_init(struct sn9c102_device* cam) |
diff --git a/drivers/media/video/sn9c102/sn9c102_pas106b.c b/drivers/media/video/sn9c102/sn9c102_pas106b.c index 360f2a848bc0..81cd969c1b7b 100644 --- a/drivers/media/video/sn9c102/sn9c102_pas106b.c +++ b/drivers/media/video/sn9c102/sn9c102_pas106b.c | |||
@@ -21,6 +21,7 @@ | |||
21 | 21 | ||
22 | #include <linux/delay.h> | 22 | #include <linux/delay.h> |
23 | #include "sn9c102_sensor.h" | 23 | #include "sn9c102_sensor.h" |
24 | #include "sn9c102_devtable.h" | ||
24 | 25 | ||
25 | 26 | ||
26 | static int pas106b_init(struct sn9c102_device* cam) | 27 | static int pas106b_init(struct sn9c102_device* cam) |
diff --git a/drivers/media/video/sn9c102/sn9c102_pas202bcb.c b/drivers/media/video/sn9c102/sn9c102_pas202bcb.c index ca4a1506ed3d..2782f94cf6f8 100644 --- a/drivers/media/video/sn9c102/sn9c102_pas202bcb.c +++ b/drivers/media/video/sn9c102/sn9c102_pas202bcb.c | |||
@@ -26,6 +26,7 @@ | |||
26 | 26 | ||
27 | #include <linux/delay.h> | 27 | #include <linux/delay.h> |
28 | #include "sn9c102_sensor.h" | 28 | #include "sn9c102_sensor.h" |
29 | #include "sn9c102_devtable.h" | ||
29 | 30 | ||
30 | 31 | ||
31 | static int pas202bcb_init(struct sn9c102_device* cam) | 32 | static int pas202bcb_init(struct sn9c102_device* cam) |
diff --git a/drivers/media/video/sn9c102/sn9c102_tas5110c1b.c b/drivers/media/video/sn9c102/sn9c102_tas5110c1b.c index e7d2de2bace1..04cdfdde8564 100644 --- a/drivers/media/video/sn9c102/sn9c102_tas5110c1b.c +++ b/drivers/media/video/sn9c102/sn9c102_tas5110c1b.c | |||
@@ -20,6 +20,7 @@ | |||
20 | ***************************************************************************/ | 20 | ***************************************************************************/ |
21 | 21 | ||
22 | #include "sn9c102_sensor.h" | 22 | #include "sn9c102_sensor.h" |
23 | #include "sn9c102_devtable.h" | ||
23 | 24 | ||
24 | 25 | ||
25 | static int tas5110c1b_init(struct sn9c102_device* cam) | 26 | static int tas5110c1b_init(struct sn9c102_device* cam) |
diff --git a/drivers/media/video/sn9c102/sn9c102_tas5110d.c b/drivers/media/video/sn9c102/sn9c102_tas5110d.c index d32fdbccdc5e..9372e6f9fcff 100644 --- a/drivers/media/video/sn9c102/sn9c102_tas5110d.c +++ b/drivers/media/video/sn9c102/sn9c102_tas5110d.c | |||
@@ -20,6 +20,7 @@ | |||
20 | ***************************************************************************/ | 20 | ***************************************************************************/ |
21 | 21 | ||
22 | #include "sn9c102_sensor.h" | 22 | #include "sn9c102_sensor.h" |
23 | #include "sn9c102_devtable.h" | ||
23 | 24 | ||
24 | 25 | ||
25 | static int tas5110d_init(struct sn9c102_device* cam) | 26 | static int tas5110d_init(struct sn9c102_device* cam) |
diff --git a/drivers/media/video/sn9c102/sn9c102_tas5130d1b.c b/drivers/media/video/sn9c102/sn9c102_tas5130d1b.c index 56fb1d575a8a..a30bbc4389f5 100644 --- a/drivers/media/video/sn9c102/sn9c102_tas5130d1b.c +++ b/drivers/media/video/sn9c102/sn9c102_tas5130d1b.c | |||
@@ -20,6 +20,7 @@ | |||
20 | ***************************************************************************/ | 20 | ***************************************************************************/ |
21 | 21 | ||
22 | #include "sn9c102_sensor.h" | 22 | #include "sn9c102_sensor.h" |
23 | #include "sn9c102_devtable.h" | ||
23 | 24 | ||
24 | 25 | ||
25 | static int tas5130d1b_init(struct sn9c102_device* cam) | 26 | static int tas5130d1b_init(struct sn9c102_device* cam) |
diff --git a/drivers/media/video/stk-webcam.c b/drivers/media/video/stk-webcam.c index ad36af30e099..db69bc5556d6 100644 --- a/drivers/media/video/stk-webcam.c +++ b/drivers/media/video/stk-webcam.c | |||
@@ -65,22 +65,6 @@ static struct usb_device_id stkwebcam_table[] = { | |||
65 | }; | 65 | }; |
66 | MODULE_DEVICE_TABLE(usb, stkwebcam_table); | 66 | MODULE_DEVICE_TABLE(usb, stkwebcam_table); |
67 | 67 | ||
68 | static void stk_camera_cleanup(struct kref *kref) | ||
69 | { | ||
70 | struct stk_camera *dev = to_stk_camera(kref); | ||
71 | |||
72 | STK_INFO("Syntek USB2.0 Camera release resources" | ||
73 | " video device /dev/video%d\n", dev->vdev.minor); | ||
74 | video_unregister_device(&dev->vdev); | ||
75 | dev->vdev.priv = NULL; | ||
76 | |||
77 | if (dev->sio_bufs != NULL || dev->isobufs != NULL) | ||
78 | STK_ERROR("We are leaking memory\n"); | ||
79 | usb_put_intf(dev->interface); | ||
80 | kfree(dev); | ||
81 | } | ||
82 | |||
83 | |||
84 | /* | 68 | /* |
85 | * Basic stuff | 69 | * Basic stuff |
86 | */ | 70 | */ |
@@ -689,34 +673,24 @@ static int v4l_stk_open(struct inode *inode, struct file *fp) | |||
689 | vdev = video_devdata(fp); | 673 | vdev = video_devdata(fp); |
690 | dev = vdev_to_camera(vdev); | 674 | dev = vdev_to_camera(vdev); |
691 | 675 | ||
692 | if (dev == NULL || !is_present(dev)) | 676 | lock_kernel(); |
677 | if (dev == NULL || !is_present(dev)) { | ||
678 | unlock_kernel(); | ||
693 | return -ENXIO; | 679 | return -ENXIO; |
694 | fp->private_data = vdev; | 680 | } |
695 | kref_get(&dev->kref); | 681 | fp->private_data = dev; |
696 | usb_autopm_get_interface(dev->interface); | 682 | usb_autopm_get_interface(dev->interface); |
683 | unlock_kernel(); | ||
697 | 684 | ||
698 | return 0; | 685 | return 0; |
699 | } | 686 | } |
700 | 687 | ||
701 | static int v4l_stk_release(struct inode *inode, struct file *fp) | 688 | static int v4l_stk_release(struct inode *inode, struct file *fp) |
702 | { | 689 | { |
703 | struct stk_camera *dev; | 690 | struct stk_camera *dev = fp->private_data; |
704 | struct video_device *vdev; | ||
705 | |||
706 | vdev = video_devdata(fp); | ||
707 | if (vdev == NULL) { | ||
708 | STK_ERROR("v4l_release called w/o video devdata\n"); | ||
709 | return -EFAULT; | ||
710 | } | ||
711 | dev = vdev_to_camera(vdev); | ||
712 | if (dev == NULL) { | ||
713 | STK_ERROR("v4l_release called on removed device\n"); | ||
714 | return -ENODEV; | ||
715 | } | ||
716 | 691 | ||
717 | if (dev->owner != fp) { | 692 | if (dev->owner != fp) { |
718 | usb_autopm_put_interface(dev->interface); | 693 | usb_autopm_put_interface(dev->interface); |
719 | kref_put(&dev->kref, stk_camera_cleanup); | ||
720 | return 0; | 694 | return 0; |
721 | } | 695 | } |
722 | 696 | ||
@@ -727,7 +701,6 @@ static int v4l_stk_release(struct inode *inode, struct file *fp) | |||
727 | dev->owner = NULL; | 701 | dev->owner = NULL; |
728 | 702 | ||
729 | usb_autopm_put_interface(dev->interface); | 703 | usb_autopm_put_interface(dev->interface); |
730 | kref_put(&dev->kref, stk_camera_cleanup); | ||
731 | 704 | ||
732 | return 0; | 705 | return 0; |
733 | } | 706 | } |
@@ -738,14 +711,8 @@ static ssize_t v4l_stk_read(struct file *fp, char __user *buf, | |||
738 | int i; | 711 | int i; |
739 | int ret; | 712 | int ret; |
740 | unsigned long flags; | 713 | unsigned long flags; |
741 | struct stk_camera *dev; | ||
742 | struct video_device *vdev; | ||
743 | struct stk_sio_buffer *sbuf; | 714 | struct stk_sio_buffer *sbuf; |
744 | 715 | struct stk_camera *dev = fp->private_data; | |
745 | vdev = video_devdata(fp); | ||
746 | if (vdev == NULL) | ||
747 | return -EFAULT; | ||
748 | dev = vdev_to_camera(vdev); | ||
749 | 716 | ||
750 | if (dev == NULL) | 717 | if (dev == NULL) |
751 | return -EIO; | 718 | return -EIO; |
@@ -804,15 +771,8 @@ static ssize_t v4l_stk_read(struct file *fp, char __user *buf, | |||
804 | 771 | ||
805 | static unsigned int v4l_stk_poll(struct file *fp, poll_table *wait) | 772 | static unsigned int v4l_stk_poll(struct file *fp, poll_table *wait) |
806 | { | 773 | { |
807 | struct stk_camera *dev; | 774 | struct stk_camera *dev = fp->private_data; |
808 | struct video_device *vdev; | ||
809 | |||
810 | vdev = video_devdata(fp); | ||
811 | |||
812 | if (vdev == NULL) | ||
813 | return -EFAULT; | ||
814 | 775 | ||
815 | dev = vdev_to_camera(vdev); | ||
816 | if (dev == NULL) | 776 | if (dev == NULL) |
817 | return -ENODEV; | 777 | return -ENODEV; |
818 | 778 | ||
@@ -850,16 +810,12 @@ static int v4l_stk_mmap(struct file *fp, struct vm_area_struct *vma) | |||
850 | unsigned int i; | 810 | unsigned int i; |
851 | int ret; | 811 | int ret; |
852 | unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; | 812 | unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; |
853 | struct stk_camera *dev; | 813 | struct stk_camera *dev = fp->private_data; |
854 | struct video_device *vdev; | ||
855 | struct stk_sio_buffer *sbuf = NULL; | 814 | struct stk_sio_buffer *sbuf = NULL; |
856 | 815 | ||
857 | if (!(vma->vm_flags & VM_WRITE) || !(vma->vm_flags & VM_SHARED)) | 816 | if (!(vma->vm_flags & VM_WRITE) || !(vma->vm_flags & VM_SHARED)) |
858 | return -EINVAL; | 817 | return -EINVAL; |
859 | 818 | ||
860 | vdev = video_devdata(fp); | ||
861 | dev = vdev_to_camera(vdev); | ||
862 | |||
863 | for (i = 0; i < dev->n_sbufs; i++) { | 819 | for (i = 0; i < dev->n_sbufs; i++) { |
864 | if (dev->sio_bufs[i].v4lbuf.m.offset == offset) { | 820 | if (dev->sio_bufs[i].v4lbuf.m.offset == offset) { |
865 | sbuf = dev->sio_bufs + i; | 821 | sbuf = dev->sio_bufs + i; |
@@ -1355,6 +1311,12 @@ static const struct v4l2_ioctl_ops v4l_stk_ioctl_ops = { | |||
1355 | 1311 | ||
1356 | static void stk_v4l_dev_release(struct video_device *vd) | 1312 | static void stk_v4l_dev_release(struct video_device *vd) |
1357 | { | 1313 | { |
1314 | struct stk_camera *dev = vdev_to_camera(vd); | ||
1315 | |||
1316 | if (dev->sio_bufs != NULL || dev->isobufs != NULL) | ||
1317 | STK_ERROR("We are leaking memory\n"); | ||
1318 | usb_put_intf(dev->interface); | ||
1319 | kfree(dev); | ||
1358 | } | 1320 | } |
1359 | 1321 | ||
1360 | static struct video_device stk_v4l_data = { | 1322 | static struct video_device stk_v4l_data = { |
@@ -1375,7 +1337,6 @@ static int stk_register_video_device(struct stk_camera *dev) | |||
1375 | dev->vdev = stk_v4l_data; | 1337 | dev->vdev = stk_v4l_data; |
1376 | dev->vdev.debug = debug; | 1338 | dev->vdev.debug = debug; |
1377 | dev->vdev.parent = &dev->interface->dev; | 1339 | dev->vdev.parent = &dev->interface->dev; |
1378 | dev->vdev.priv = dev; | ||
1379 | err = video_register_device(&dev->vdev, VFL_TYPE_GRABBER, -1); | 1340 | err = video_register_device(&dev->vdev, VFL_TYPE_GRABBER, -1); |
1380 | if (err) | 1341 | if (err) |
1381 | STK_ERROR("v4l registration failed\n"); | 1342 | STK_ERROR("v4l registration failed\n"); |
@@ -1392,7 +1353,7 @@ static int stk_camera_probe(struct usb_interface *interface, | |||
1392 | const struct usb_device_id *id) | 1353 | const struct usb_device_id *id) |
1393 | { | 1354 | { |
1394 | int i; | 1355 | int i; |
1395 | int err; | 1356 | int err = 0; |
1396 | 1357 | ||
1397 | struct stk_camera *dev = NULL; | 1358 | struct stk_camera *dev = NULL; |
1398 | struct usb_device *udev = interface_to_usbdev(interface); | 1359 | struct usb_device *udev = interface_to_usbdev(interface); |
@@ -1405,7 +1366,6 @@ static int stk_camera_probe(struct usb_interface *interface, | |||
1405 | return -ENOMEM; | 1366 | return -ENOMEM; |
1406 | } | 1367 | } |
1407 | 1368 | ||
1408 | kref_init(&dev->kref); | ||
1409 | spin_lock_init(&dev->spinlock); | 1369 | spin_lock_init(&dev->spinlock); |
1410 | init_waitqueue_head(&dev->wait_frame); | 1370 | init_waitqueue_head(&dev->wait_frame); |
1411 | 1371 | ||
@@ -1438,8 +1398,8 @@ static int stk_camera_probe(struct usb_interface *interface, | |||
1438 | } | 1398 | } |
1439 | if (!dev->isoc_ep) { | 1399 | if (!dev->isoc_ep) { |
1440 | STK_ERROR("Could not find isoc-in endpoint"); | 1400 | STK_ERROR("Could not find isoc-in endpoint"); |
1441 | kref_put(&dev->kref, stk_camera_cleanup); | 1401 | err = -ENODEV; |
1442 | return -ENODEV; | 1402 | goto error; |
1443 | } | 1403 | } |
1444 | dev->vsettings.brightness = 0x7fff; | 1404 | dev->vsettings.brightness = 0x7fff; |
1445 | dev->vsettings.palette = V4L2_PIX_FMT_RGB565; | 1405 | dev->vsettings.palette = V4L2_PIX_FMT_RGB565; |
@@ -1453,14 +1413,17 @@ static int stk_camera_probe(struct usb_interface *interface, | |||
1453 | 1413 | ||
1454 | err = stk_register_video_device(dev); | 1414 | err = stk_register_video_device(dev); |
1455 | if (err) { | 1415 | if (err) { |
1456 | kref_put(&dev->kref, stk_camera_cleanup); | 1416 | goto error; |
1457 | return err; | ||
1458 | } | 1417 | } |
1459 | 1418 | ||
1460 | stk_create_sysfs_files(&dev->vdev); | 1419 | stk_create_sysfs_files(&dev->vdev); |
1461 | usb_autopm_enable(dev->interface); | 1420 | usb_autopm_enable(dev->interface); |
1462 | 1421 | ||
1463 | return 0; | 1422 | return 0; |
1423 | |||
1424 | error: | ||
1425 | kfree(dev); | ||
1426 | return err; | ||
1464 | } | 1427 | } |
1465 | 1428 | ||
1466 | static void stk_camera_disconnect(struct usb_interface *interface) | 1429 | static void stk_camera_disconnect(struct usb_interface *interface) |
@@ -1473,7 +1436,10 @@ static void stk_camera_disconnect(struct usb_interface *interface) | |||
1473 | wake_up_interruptible(&dev->wait_frame); | 1436 | wake_up_interruptible(&dev->wait_frame); |
1474 | stk_remove_sysfs_files(&dev->vdev); | 1437 | stk_remove_sysfs_files(&dev->vdev); |
1475 | 1438 | ||
1476 | kref_put(&dev->kref, stk_camera_cleanup); | 1439 | STK_INFO("Syntek USB2.0 Camera release resources" |
1440 | "video device /dev/video%d\n", dev->vdev.minor); | ||
1441 | |||
1442 | video_unregister_device(&dev->vdev); | ||
1477 | } | 1443 | } |
1478 | 1444 | ||
1479 | #ifdef CONFIG_PM | 1445 | #ifdef CONFIG_PM |
diff --git a/drivers/media/video/stk-webcam.h b/drivers/media/video/stk-webcam.h index df4dfefc5327..084a85bdd16e 100644 --- a/drivers/media/video/stk-webcam.h +++ b/drivers/media/video/stk-webcam.h | |||
@@ -99,7 +99,6 @@ struct stk_camera { | |||
99 | 99 | ||
100 | u8 isoc_ep; | 100 | u8 isoc_ep; |
101 | 101 | ||
102 | struct kref kref; | ||
103 | /* Not sure if this is right */ | 102 | /* Not sure if this is right */ |
104 | atomic_t urbs_used; | 103 | atomic_t urbs_used; |
105 | 104 | ||
@@ -121,7 +120,6 @@ struct stk_camera { | |||
121 | unsigned sequence; | 120 | unsigned sequence; |
122 | }; | 121 | }; |
123 | 122 | ||
124 | #define to_stk_camera(d) container_of(d, struct stk_camera, kref) | ||
125 | #define vdev_to_camera(d) container_of(d, struct stk_camera, vdev) | 123 | #define vdev_to_camera(d) container_of(d, struct stk_camera, vdev) |
126 | 124 | ||
127 | void stk_camera_delete(struct kref *); | 125 | void stk_camera_delete(struct kref *); |
diff --git a/drivers/media/video/stradis.c b/drivers/media/video/stradis.c index 276bded06ab3..bbad54f85c83 100644 --- a/drivers/media/video/stradis.c +++ b/drivers/media/video/stradis.c | |||
@@ -1882,12 +1882,16 @@ static int saa_open(struct inode *inode, struct file *file) | |||
1882 | struct video_device *vdev = video_devdata(file); | 1882 | struct video_device *vdev = video_devdata(file); |
1883 | struct saa7146 *saa = container_of(vdev, struct saa7146, video_dev); | 1883 | struct saa7146 *saa = container_of(vdev, struct saa7146, video_dev); |
1884 | 1884 | ||
1885 | lock_kernel(); | ||
1885 | file->private_data = saa; | 1886 | file->private_data = saa; |
1886 | 1887 | ||
1887 | saa->user++; | 1888 | saa->user++; |
1888 | if (saa->user > 1) | 1889 | if (saa->user > 1) { |
1890 | unlock_kernel(); | ||
1889 | return 0; /* device open already, don't reset */ | 1891 | return 0; /* device open already, don't reset */ |
1892 | } | ||
1890 | saa->writemode = VID_WRITE_MPEG_VID; /* default to video */ | 1893 | saa->writemode = VID_WRITE_MPEG_VID; /* default to video */ |
1894 | unlock_kernel(); | ||
1891 | return 0; | 1895 | return 0; |
1892 | } | 1896 | } |
1893 | 1897 | ||
@@ -1921,6 +1925,7 @@ static struct video_device saa_template = { | |||
1921 | .name = "SAA7146A", | 1925 | .name = "SAA7146A", |
1922 | .fops = &saa_fops, | 1926 | .fops = &saa_fops, |
1923 | .minor = -1, | 1927 | .minor = -1, |
1928 | .release = video_device_release_empty, | ||
1924 | }; | 1929 | }; |
1925 | 1930 | ||
1926 | static int __devinit configure_saa7146(struct pci_dev *pdev, int num) | 1931 | static int __devinit configure_saa7146(struct pci_dev *pdev, int num) |
diff --git a/drivers/media/video/stv680.c b/drivers/media/video/stv680.c index dce947439459..9c549d935994 100644 --- a/drivers/media/video/stv680.c +++ b/drivers/media/video/stv680.c | |||
@@ -84,7 +84,8 @@ static unsigned int debug; | |||
84 | #define PDEBUG(level, fmt, args...) \ | 84 | #define PDEBUG(level, fmt, args...) \ |
85 | do { \ | 85 | do { \ |
86 | if (debug >= level) \ | 86 | if (debug >= level) \ |
87 | info("[%s:%d] " fmt, __func__, __LINE__ , ## args); \ | 87 | printk(KERN_INFO KBUILD_MODNAME " [%s:%d] \n" fmt, \ |
88 | __func__, __LINE__ , ## args); \ | ||
88 | } while (0) | 89 | } while (0) |
89 | 90 | ||
90 | 91 | ||
@@ -1086,6 +1087,7 @@ static int stv_open (struct inode *inode, struct file *file) | |||
1086 | int err = 0; | 1087 | int err = 0; |
1087 | 1088 | ||
1088 | /* we are called with the BKL held */ | 1089 | /* we are called with the BKL held */ |
1090 | lock_kernel(); | ||
1089 | stv680->user = 1; | 1091 | stv680->user = 1; |
1090 | err = stv_init (stv680); /* main initialization routine for camera */ | 1092 | err = stv_init (stv680); /* main initialization routine for camera */ |
1091 | 1093 | ||
@@ -1099,6 +1101,7 @@ static int stv_open (struct inode *inode, struct file *file) | |||
1099 | } | 1101 | } |
1100 | if (err) | 1102 | if (err) |
1101 | stv680->user = 0; | 1103 | stv680->user = 0; |
1104 | unlock_kernel(); | ||
1102 | 1105 | ||
1103 | return err; | 1106 | return err; |
1104 | } | 1107 | } |
@@ -1550,7 +1553,8 @@ static int __init usb_stv680_init (void) | |||
1550 | } | 1553 | } |
1551 | PDEBUG (0, "STV(i): usb camera driver version %s registering", DRIVER_VERSION); | 1554 | PDEBUG (0, "STV(i): usb camera driver version %s registering", DRIVER_VERSION); |
1552 | 1555 | ||
1553 | info(DRIVER_DESC " " DRIVER_VERSION); | 1556 | printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" |
1557 | DRIVER_DESC "\n"); | ||
1554 | return 0; | 1558 | return 0; |
1555 | } | 1559 | } |
1556 | 1560 | ||
diff --git a/drivers/media/video/tda9840.c b/drivers/media/video/tda9840.c index 2437c1a269c5..1c391f0328fd 100644 --- a/drivers/media/video/tda9840.c +++ b/drivers/media/video/tda9840.c | |||
@@ -2,6 +2,7 @@ | |||
2 | tda9840 - i2c-driver for the tda9840 by SGS Thomson | 2 | tda9840 - i2c-driver for the tda9840 by SGS Thomson |
3 | 3 | ||
4 | Copyright (C) 1998-2003 Michael Hunold <michael@mihu.de> | 4 | Copyright (C) 1998-2003 Michael Hunold <michael@mihu.de> |
5 | Copyright (C) 2008 Hans Verkuil <hverkuil@xs4all.nl> | ||
5 | 6 | ||
6 | The tda9840 is a stereo/dual sound processor with digital | 7 | The tda9840 is a stereo/dual sound processor with digital |
7 | identification. It can be found at address 0x84 on the i2c-bus. | 8 | identification. It can be found at address 0x84 on the i2c-bus. |
@@ -28,59 +29,118 @@ | |||
28 | #include <linux/module.h> | 29 | #include <linux/module.h> |
29 | #include <linux/ioctl.h> | 30 | #include <linux/ioctl.h> |
30 | #include <linux/i2c.h> | 31 | #include <linux/i2c.h> |
31 | 32 | #include <media/v4l2-common.h> | |
33 | #include <media/v4l2-i2c-drv-legacy.h> | ||
32 | #include "tda9840.h" | 34 | #include "tda9840.h" |
33 | 35 | ||
34 | static int debug; /* insmod parameter */ | 36 | MODULE_AUTHOR("Michael Hunold <michael@mihu.de>"); |
37 | MODULE_DESCRIPTION("tda9840 driver"); | ||
38 | MODULE_LICENSE("GPL"); | ||
39 | |||
40 | static int debug; | ||
35 | module_param(debug, int, 0644); | 41 | module_param(debug, int, 0644); |
36 | MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off)."); | ||
37 | 42 | ||
38 | #define dprintk(args...) \ | 43 | MODULE_PARM_DESC(debug, "Debug level (0-1)"); |
39 | do { if (debug) { printk("%s: %s()[%d]: ", KBUILD_MODNAME, __func__, __LINE__); printk(args); } } while (0) | ||
40 | 44 | ||
41 | #define SWITCH 0x00 | 45 | #define SWITCH 0x00 |
42 | #define LEVEL_ADJUST 0x02 | 46 | #define LEVEL_ADJUST 0x02 |
43 | #define STEREO_ADJUST 0x03 | 47 | #define STEREO_ADJUST 0x03 |
44 | #define TEST 0x04 | 48 | #define TEST 0x04 |
45 | 49 | ||
50 | #define TDA9840_SET_MUTE 0x00 | ||
51 | #define TDA9840_SET_MONO 0x10 | ||
52 | #define TDA9840_SET_STEREO 0x2a | ||
53 | #define TDA9840_SET_LANG1 0x12 | ||
54 | #define TDA9840_SET_LANG2 0x1e | ||
55 | #define TDA9840_SET_BOTH 0x1a | ||
56 | #define TDA9840_SET_BOTH_R 0x16 | ||
57 | #define TDA9840_SET_EXTERNAL 0x7a | ||
58 | |||
46 | /* addresses to scan, found only at 0x42 (7-Bit) */ | 59 | /* addresses to scan, found only at 0x42 (7-Bit) */ |
47 | static unsigned short normal_i2c[] = { I2C_ADDR_TDA9840, I2C_CLIENT_END }; | 60 | static unsigned short normal_i2c[] = { I2C_ADDR_TDA9840, I2C_CLIENT_END }; |
48 | 61 | ||
49 | /* magic definition of all other variables and things */ | 62 | /* magic definition of all other variables and things */ |
50 | I2C_CLIENT_INSMOD; | 63 | I2C_CLIENT_INSMOD; |
51 | 64 | ||
52 | static struct i2c_driver driver; | 65 | static void tda9840_write(struct i2c_client *client, u8 reg, u8 val) |
53 | static struct i2c_client client_template; | 66 | { |
67 | if (i2c_smbus_write_byte_data(client, reg, val)) | ||
68 | v4l_dbg(1, debug, client, "error writing %02x to %02x\n", | ||
69 | val, reg); | ||
70 | } | ||
54 | 71 | ||
55 | static int command(struct i2c_client *client, unsigned int cmd, void *arg) | 72 | static int tda9840_command(struct i2c_client *client, unsigned cmd, void *arg) |
56 | { | 73 | { |
57 | int result; | ||
58 | int byte = *(int *)arg; | 74 | int byte = *(int *)arg; |
59 | 75 | ||
60 | switch (cmd) { | 76 | switch (cmd) { |
61 | case TDA9840_SWITCH: | 77 | case VIDIOC_S_TUNER: { |
62 | 78 | struct v4l2_tuner *t = arg; | |
63 | dprintk("TDA9840_SWITCH: 0x%02x\n", byte); | 79 | int byte; |
64 | 80 | ||
65 | if (byte != TDA9840_SET_MONO | 81 | if (t->index) |
66 | && byte != TDA9840_SET_MUTE | ||
67 | && byte != TDA9840_SET_STEREO | ||
68 | && byte != TDA9840_SET_LANG1 | ||
69 | && byte != TDA9840_SET_LANG2 | ||
70 | && byte != TDA9840_SET_BOTH | ||
71 | && byte != TDA9840_SET_BOTH_R | ||
72 | && byte != TDA9840_SET_EXTERNAL) { | ||
73 | return -EINVAL; | 82 | return -EINVAL; |
83 | |||
84 | switch (t->audmode) { | ||
85 | case V4L2_TUNER_MODE_STEREO: | ||
86 | byte = TDA9840_SET_STEREO; | ||
87 | break; | ||
88 | case V4L2_TUNER_MODE_LANG1_LANG2: | ||
89 | byte = TDA9840_SET_BOTH; | ||
90 | break; | ||
91 | case V4L2_TUNER_MODE_LANG1: | ||
92 | byte = TDA9840_SET_LANG1; | ||
93 | break; | ||
94 | case V4L2_TUNER_MODE_LANG2: | ||
95 | byte = TDA9840_SET_LANG2; | ||
96 | break; | ||
97 | default: | ||
98 | byte = TDA9840_SET_MONO; | ||
99 | break; | ||
100 | } | ||
101 | v4l_dbg(1, debug, client, "TDA9840_SWITCH: 0x%02x\n", byte); | ||
102 | tda9840_write(client, SWITCH, byte); | ||
103 | break; | ||
104 | } | ||
105 | |||
106 | case VIDIOC_G_TUNER: { | ||
107 | struct v4l2_tuner *t = arg; | ||
108 | u8 byte; | ||
109 | |||
110 | t->rxsubchans = V4L2_TUNER_SUB_MONO; | ||
111 | if (1 != i2c_master_recv(client, &byte, 1)) { | ||
112 | v4l_dbg(1, debug, client, | ||
113 | "i2c_master_recv() failed\n"); | ||
114 | return -EIO; | ||
74 | } | 115 | } |
75 | 116 | ||
76 | result = i2c_smbus_write_byte_data(client, SWITCH, byte); | 117 | if (byte & 0x80) { |
77 | if (result) | 118 | v4l_dbg(1, debug, client, |
78 | dprintk("i2c_smbus_write_byte() failed, ret:%d\n", result); | 119 | "TDA9840_DETECT: register contents invalid\n"); |
120 | return -EINVAL; | ||
121 | } | ||
122 | |||
123 | v4l_dbg(1, debug, client, "TDA9840_DETECT: byte: 0x%02x\n", byte); | ||
124 | |||
125 | switch (byte & 0x60) { | ||
126 | case 0x00: | ||
127 | t->rxsubchans = V4L2_TUNER_SUB_MONO; | ||
128 | break; | ||
129 | case 0x20: | ||
130 | t->rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2; | ||
131 | break; | ||
132 | case 0x40: | ||
133 | t->rxsubchans = V4L2_TUNER_SUB_STEREO | V4L2_TUNER_SUB_MONO; | ||
134 | break; | ||
135 | default: /* Incorrect detect */ | ||
136 | t->rxsubchans = V4L2_TUNER_MODE_MONO; | ||
137 | break; | ||
138 | } | ||
79 | break; | 139 | break; |
140 | } | ||
80 | 141 | ||
81 | case TDA9840_LEVEL_ADJUST: | 142 | case TDA9840_LEVEL_ADJUST: |
82 | 143 | v4l_dbg(1, debug, client, "TDA9840_LEVEL_ADJUST: %d\n", byte); | |
83 | dprintk("TDA9840_LEVEL_ADJUST: %d\n", byte); | ||
84 | 144 | ||
85 | /* check for correct range */ | 145 | /* check for correct range */ |
86 | if (byte > 25 || byte < -20) | 146 | if (byte > 25 || byte < -20) |
@@ -92,15 +152,11 @@ static int command(struct i2c_client *client, unsigned int cmd, void *arg) | |||
92 | byte += 0x8; | 152 | byte += 0x8; |
93 | else | 153 | else |
94 | byte = -byte; | 154 | byte = -byte; |
95 | 155 | tda9840_write(client, LEVEL_ADJUST, byte); | |
96 | result = i2c_smbus_write_byte_data(client, LEVEL_ADJUST, byte); | ||
97 | if (result) | ||
98 | dprintk("i2c_smbus_write_byte() failed, ret:%d\n", result); | ||
99 | break; | 156 | break; |
100 | 157 | ||
101 | case TDA9840_STEREO_ADJUST: | 158 | case TDA9840_STEREO_ADJUST: |
102 | 159 | v4l_dbg(1, debug, client, "TDA9840_STEREO_ADJUST: %d\n", byte); | |
103 | dprintk("TDA9840_STEREO_ADJUST: %d\n", byte); | ||
104 | 160 | ||
105 | /* check for correct range */ | 161 | /* check for correct range */ |
106 | if (byte > 25 || byte < -24) | 162 | if (byte > 25 || byte < -24) |
@@ -113,143 +169,59 @@ static int command(struct i2c_client *client, unsigned int cmd, void *arg) | |||
113 | else | 169 | else |
114 | byte = -byte; | 170 | byte = -byte; |
115 | 171 | ||
116 | result = i2c_smbus_write_byte_data(client, STEREO_ADJUST, byte); | 172 | tda9840_write(client, STEREO_ADJUST, byte); |
117 | if (result) | ||
118 | dprintk("i2c_smbus_write_byte() failed, ret:%d\n", result); | ||
119 | break; | ||
120 | |||
121 | case TDA9840_DETECT: { | ||
122 | int *ret = (int *)arg; | ||
123 | |||
124 | byte = i2c_smbus_read_byte_data(client, STEREO_ADJUST); | ||
125 | if (byte == -1) { | ||
126 | dprintk("i2c_smbus_read_byte_data() failed\n"); | ||
127 | return -EIO; | ||
128 | } | ||
129 | |||
130 | if (0 != (byte & 0x80)) { | ||
131 | dprintk("TDA9840_DETECT: register contents invalid\n"); | ||
132 | return -EINVAL; | ||
133 | } | ||
134 | |||
135 | dprintk("TDA9840_DETECT: byte: 0x%02x\n", byte); | ||
136 | *ret = ((byte & 0x60) >> 5); | ||
137 | result = 0; | ||
138 | break; | ||
139 | } | ||
140 | case TDA9840_TEST: | ||
141 | dprintk("TDA9840_TEST: 0x%02x\n", byte); | ||
142 | |||
143 | /* mask out irrelevant bits */ | ||
144 | byte &= 0x3; | ||
145 | |||
146 | result = i2c_smbus_write_byte_data(client, TEST, byte); | ||
147 | if (result) | ||
148 | dprintk("i2c_smbus_write_byte() failed, ret:%d\n", result); | ||
149 | break; | 173 | break; |
150 | default: | 174 | default: |
151 | return -ENOIOCTLCMD; | 175 | return -ENOIOCTLCMD; |
152 | } | 176 | } |
153 | 177 | ||
154 | if (result) | ||
155 | return -EIO; | ||
156 | |||
157 | return 0; | 178 | return 0; |
158 | } | 179 | } |
159 | 180 | ||
160 | static int detect(struct i2c_adapter *adapter, int address, int kind) | 181 | static int tda9840_probe(struct i2c_client *client, |
182 | const struct i2c_device_id *id) | ||
161 | { | 183 | { |
162 | struct i2c_client *client; | 184 | int result; |
163 | int result = 0; | 185 | int byte; |
164 | |||
165 | int byte = 0x0; | ||
166 | 186 | ||
167 | /* let's see whether this adapter can support what we need */ | 187 | /* let's see whether this adapter can support what we need */ |
168 | if (0 == i2c_check_functionality(adapter, | 188 | if (!i2c_check_functionality(client->adapter, |
169 | I2C_FUNC_SMBUS_READ_BYTE_DATA | | 189 | I2C_FUNC_SMBUS_READ_BYTE_DATA | |
170 | I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) { | 190 | I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) |
171 | return 0; | 191 | return 0; |
172 | } | ||
173 | |||
174 | /* allocate memory for client structure */ | ||
175 | client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL); | ||
176 | if (!client) { | ||
177 | printk("not enough kernel memory\n"); | ||
178 | return -ENOMEM; | ||
179 | } | ||
180 | |||
181 | /* fill client structure */ | ||
182 | memcpy(client, &client_template, sizeof(struct i2c_client)); | ||
183 | client->addr = address; | ||
184 | client->adapter = adapter; | ||
185 | 192 | ||
186 | /* tell the i2c layer a new client has arrived */ | 193 | v4l_info(client, "chip found @ 0x%x (%s)\n", |
187 | if (0 != (result = i2c_attach_client(client))) { | 194 | client->addr << 1, client->adapter->name); |
188 | kfree(client); | ||
189 | return result; | ||
190 | } | ||
191 | 195 | ||
192 | /* set initial values for level & stereo - adjustment, mode */ | 196 | /* set initial values for level & stereo - adjustment, mode */ |
193 | byte = 0; | 197 | byte = 0; |
194 | result = command(client, TDA9840_LEVEL_ADJUST, &byte); | 198 | result = tda9840_command(client, TDA9840_LEVEL_ADJUST, &byte); |
195 | result += command(client, TDA9840_STEREO_ADJUST, &byte); | 199 | result += tda9840_command(client, TDA9840_STEREO_ADJUST, &byte); |
196 | byte = TDA9840_SET_MONO; | 200 | tda9840_write(client, SWITCH, TDA9840_SET_STEREO); |
197 | result = command(client, TDA9840_SWITCH, &byte); | ||
198 | if (result) { | 201 | if (result) { |
199 | dprintk("could not initialize tda9840\n"); | 202 | v4l_dbg(1, debug, client, "could not initialize tda9840\n"); |
200 | return -ENODEV; | 203 | return -ENODEV; |
201 | } | 204 | } |
202 | |||
203 | printk("tda9840: detected @ 0x%02x on adapter %s\n", address, &client->adapter->name[0]); | ||
204 | return 0; | 205 | return 0; |
205 | } | 206 | } |
206 | 207 | ||
207 | static int attach(struct i2c_adapter *adapter) | 208 | static int tda9840_legacy_probe(struct i2c_adapter *adapter) |
208 | { | ||
209 | /* let's see whether this is a know adapter we can attach to */ | ||
210 | if (adapter->id != I2C_HW_SAA7146) { | ||
211 | dprintk("refusing to probe on unknown adapter [name='%s',id=0x%x]\n", adapter->name, adapter->id); | ||
212 | return -ENODEV; | ||
213 | } | ||
214 | |||
215 | return i2c_probe(adapter, &addr_data, &detect); | ||
216 | } | ||
217 | |||
218 | static int detach(struct i2c_client *client) | ||
219 | { | 209 | { |
220 | int ret = i2c_detach_client(client); | 210 | /* Let's see whether this is a known adapter we can attach to. |
221 | kfree(client); | 211 | Prevents conflicts with tvaudio.c. */ |
222 | return ret; | 212 | return adapter->id == I2C_HW_SAA7146; |
223 | } | 213 | } |
224 | 214 | static const struct i2c_device_id tda9840_id[] = { | |
225 | static struct i2c_driver driver = { | 215 | { "tda9840", 0 }, |
226 | .driver = { | 216 | { } |
227 | .name = "tda9840", | ||
228 | }, | ||
229 | .id = I2C_DRIVERID_TDA9840, | ||
230 | .attach_adapter = attach, | ||
231 | .detach_client = detach, | ||
232 | .command = command, | ||
233 | }; | 217 | }; |
218 | MODULE_DEVICE_TABLE(i2c, tda9840_id); | ||
234 | 219 | ||
235 | static struct i2c_client client_template = { | 220 | static struct v4l2_i2c_driver_data v4l2_i2c_data = { |
236 | .name = "tda9840", | 221 | .name = "tda9840", |
237 | .driver = &driver, | 222 | .driverid = I2C_DRIVERID_TDA9840, |
223 | .command = tda9840_command, | ||
224 | .probe = tda9840_probe, | ||
225 | .legacy_probe = tda9840_legacy_probe, | ||
226 | .id_table = tda9840_id, | ||
238 | }; | 227 | }; |
239 | |||
240 | static int __init this_module_init(void) | ||
241 | { | ||
242 | return i2c_add_driver(&driver); | ||
243 | } | ||
244 | |||
245 | static void __exit this_module_exit(void) | ||
246 | { | ||
247 | i2c_del_driver(&driver); | ||
248 | } | ||
249 | |||
250 | module_init(this_module_init); | ||
251 | module_exit(this_module_exit); | ||
252 | |||
253 | MODULE_AUTHOR("Michael Hunold <michael@mihu.de>"); | ||
254 | MODULE_DESCRIPTION("tda9840 driver"); | ||
255 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/video/tda9840.h b/drivers/media/video/tda9840.h index 7da8432cdca7..dc12ae7caf6f 100644 --- a/drivers/media/video/tda9840.h +++ b/drivers/media/video/tda9840.h | |||
@@ -3,24 +3,6 @@ | |||
3 | 3 | ||
4 | #define I2C_ADDR_TDA9840 0x42 | 4 | #define I2C_ADDR_TDA9840 0x42 |
5 | 5 | ||
6 | #define TDA9840_DETECT _IOR('v',1,int) | ||
7 | /* return values for TDA9840_DETCT */ | ||
8 | #define TDA9840_MONO_DETECT 0x0 | ||
9 | #define TDA9840_DUAL_DETECT 0x1 | ||
10 | #define TDA9840_STEREO_DETECT 0x2 | ||
11 | #define TDA9840_INCORRECT_DETECT 0x3 | ||
12 | |||
13 | #define TDA9840_SWITCH _IOW('v',2,int) | ||
14 | /* modes than can be set with TDA9840_SWITCH */ | ||
15 | #define TDA9840_SET_MUTE 0x00 | ||
16 | #define TDA9840_SET_MONO 0x10 | ||
17 | #define TDA9840_SET_STEREO 0x2a | ||
18 | #define TDA9840_SET_LANG1 0x12 | ||
19 | #define TDA9840_SET_LANG2 0x1e | ||
20 | #define TDA9840_SET_BOTH 0x1a | ||
21 | #define TDA9840_SET_BOTH_R 0x16 | ||
22 | #define TDA9840_SET_EXTERNAL 0x7a | ||
23 | |||
24 | /* values may range between +2.5 and -2.0; | 6 | /* values may range between +2.5 and -2.0; |
25 | the value has to be multiplied with 10 */ | 7 | the value has to be multiplied with 10 */ |
26 | #define TDA9840_LEVEL_ADJUST _IOW('v',3,int) | 8 | #define TDA9840_LEVEL_ADJUST _IOW('v',3,int) |
@@ -29,7 +11,4 @@ | |||
29 | the value has to be multiplied with 10 */ | 11 | the value has to be multiplied with 10 */ |
30 | #define TDA9840_STEREO_ADJUST _IOW('v',4,int) | 12 | #define TDA9840_STEREO_ADJUST _IOW('v',4,int) |
31 | 13 | ||
32 | /* currently not implemented */ | ||
33 | #define TDA9840_TEST _IOW('v',5,int) | ||
34 | |||
35 | #endif | 14 | #endif |
diff --git a/drivers/media/video/tea6415c.c b/drivers/media/video/tea6415c.c index 421c1445e96c..cde092adbb5a 100644 --- a/drivers/media/video/tea6415c.c +++ b/drivers/media/video/tea6415c.c | |||
@@ -2,6 +2,7 @@ | |||
2 | tea6415c - i2c-driver for the tea6415c by SGS Thomson | 2 | tea6415c - i2c-driver for the tea6415c by SGS Thomson |
3 | 3 | ||
4 | Copyright (C) 1998-2003 Michael Hunold <michael@mihu.de> | 4 | Copyright (C) 1998-2003 Michael Hunold <michael@mihu.de> |
5 | Copyright (C) 2008 Hans Verkuil <hverkuil@xs4all.nl> | ||
5 | 6 | ||
6 | The tea6415c is a bus controlled video-matrix-switch | 7 | The tea6415c is a bus controlled video-matrix-switch |
7 | with 8 inputs and 6 outputs. | 8 | with 8 inputs and 6 outputs. |
@@ -30,18 +31,18 @@ | |||
30 | #include <linux/module.h> | 31 | #include <linux/module.h> |
31 | #include <linux/ioctl.h> | 32 | #include <linux/ioctl.h> |
32 | #include <linux/i2c.h> | 33 | #include <linux/i2c.h> |
33 | 34 | #include <media/v4l2-common.h> | |
35 | #include <media/v4l2-i2c-drv-legacy.h> | ||
34 | #include "tea6415c.h" | 36 | #include "tea6415c.h" |
35 | 37 | ||
36 | static int debug; /* insmod parameter */ | 38 | MODULE_AUTHOR("Michael Hunold <michael@mihu.de>"); |
37 | module_param(debug, int, 0644); | 39 | MODULE_DESCRIPTION("tea6415c driver"); |
38 | MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off)."); | 40 | MODULE_LICENSE("GPL"); |
39 | 41 | ||
40 | #define dprintk(args...) \ | 42 | static int debug; |
41 | do { if (debug) { printk("%s: %s()[%d]: ", KBUILD_MODNAME, __func__, __LINE__); printk(args); } } while (0) | 43 | module_param(debug, int, 0644); |
42 | 44 | ||
43 | #define TEA6415C_NUM_INPUTS 8 | 45 | MODULE_PARM_DESC(debug, "Debug level (0-1)"); |
44 | #define TEA6415C_NUM_OUTPUTS 6 | ||
45 | 46 | ||
46 | /* addresses to scan, found only at 0x03 and/or 0x43 (7-bit) */ | 47 | /* addresses to scan, found only at 0x03 and/or 0x43 (7-bit) */ |
47 | static unsigned short normal_i2c[] = { I2C_TEA6415C_1, I2C_TEA6415C_2, I2C_CLIENT_END }; | 48 | static unsigned short normal_i2c[] = { I2C_TEA6415C_1, I2C_TEA6415C_2, I2C_CLIENT_END }; |
@@ -49,60 +50,6 @@ static unsigned short normal_i2c[] = { I2C_TEA6415C_1, I2C_TEA6415C_2, I2C_CLIEN | |||
49 | /* magic definition of all other variables and things */ | 50 | /* magic definition of all other variables and things */ |
50 | I2C_CLIENT_INSMOD; | 51 | I2C_CLIENT_INSMOD; |
51 | 52 | ||
52 | static struct i2c_driver driver; | ||
53 | static struct i2c_client client_template; | ||
54 | |||
55 | /* this function is called by i2c_probe */ | ||
56 | static int detect(struct i2c_adapter *adapter, int address, int kind) | ||
57 | { | ||
58 | struct i2c_client *client = NULL; | ||
59 | int err = 0; | ||
60 | |||
61 | /* let's see whether this adapter can support what we need */ | ||
62 | if (0 == i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WRITE_BYTE)) { | ||
63 | return 0; | ||
64 | } | ||
65 | |||
66 | /* allocate memory for client structure */ | ||
67 | client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL); | ||
68 | if (!client) { | ||
69 | return -ENOMEM; | ||
70 | } | ||
71 | |||
72 | /* fill client structure */ | ||
73 | memcpy(client, &client_template, sizeof(struct i2c_client)); | ||
74 | client->addr = address; | ||
75 | client->adapter = adapter; | ||
76 | |||
77 | /* tell the i2c layer a new client has arrived */ | ||
78 | if (0 != (err = i2c_attach_client(client))) { | ||
79 | kfree(client); | ||
80 | return err; | ||
81 | } | ||
82 | |||
83 | printk("tea6415c: detected @ 0x%02x on adapter %s\n", address, &client->adapter->name[0]); | ||
84 | |||
85 | return 0; | ||
86 | } | ||
87 | |||
88 | static int attach(struct i2c_adapter *adapter) | ||
89 | { | ||
90 | /* let's see whether this is a know adapter we can attach to */ | ||
91 | if (adapter->id != I2C_HW_SAA7146) { | ||
92 | dprintk("refusing to probe on unknown adapter [name='%s',id=0x%x]\n", adapter->name, adapter->id); | ||
93 | return -ENODEV; | ||
94 | } | ||
95 | |||
96 | return i2c_probe(adapter, &addr_data, &detect); | ||
97 | } | ||
98 | |||
99 | static int detach(struct i2c_client *client) | ||
100 | { | ||
101 | int ret = i2c_detach_client(client); | ||
102 | kfree(client); | ||
103 | return ret; | ||
104 | } | ||
105 | |||
106 | /* makes a connection between the input-pin 'i' and the output-pin 'o' | 53 | /* makes a connection between the input-pin 'i' and the output-pin 'o' |
107 | for the tea6415c-client 'client' */ | 54 | for the tea6415c-client 'client' */ |
108 | static int switch_matrix(struct i2c_client *client, int i, int o) | 55 | static int switch_matrix(struct i2c_client *client, int i, int o) |
@@ -110,7 +57,7 @@ static int switch_matrix(struct i2c_client *client, int i, int o) | |||
110 | u8 byte = 0; | 57 | u8 byte = 0; |
111 | int ret; | 58 | int ret; |
112 | 59 | ||
113 | dprintk("adr:0x%02x, i:%d, o:%d\n", client->addr, i, o); | 60 | v4l_dbg(1, debug, client, "i=%d, o=%d\n", i, o); |
114 | 61 | ||
115 | /* check if the pins are valid */ | 62 | /* check if the pins are valid */ |
116 | if (0 == ((1 == i || 3 == i || 5 == i || 6 == i || 8 == i || 10 == i || 20 == i || 11 == i) | 63 | if (0 == ((1 == i || 3 == i || 5 == i || 6 == i || 8 == i || 10 == i || 20 == i || 11 == i) |
@@ -168,14 +115,14 @@ static int switch_matrix(struct i2c_client *client, int i, int o) | |||
168 | 115 | ||
169 | ret = i2c_smbus_write_byte(client, byte); | 116 | ret = i2c_smbus_write_byte(client, byte); |
170 | if (ret) { | 117 | if (ret) { |
171 | dprintk("i2c_smbus_write_byte() failed, ret:%d\n", ret); | 118 | v4l_dbg(1, debug, client, |
119 | "i2c_smbus_write_byte() failed, ret:%d\n", ret); | ||
172 | return -EIO; | 120 | return -EIO; |
173 | } | 121 | } |
174 | |||
175 | return ret; | 122 | return ret; |
176 | } | 123 | } |
177 | 124 | ||
178 | static int command(struct i2c_client *client, unsigned int cmd, void *arg) | 125 | static int tea6415c_command(struct i2c_client *client, unsigned cmd, void *arg) |
179 | { | 126 | { |
180 | struct tea6415c_multiplex *v = (struct tea6415c_multiplex *)arg; | 127 | struct tea6415c_multiplex *v = (struct tea6415c_multiplex *)arg; |
181 | int result = 0; | 128 | int result = 0; |
@@ -187,38 +134,40 @@ static int command(struct i2c_client *client, unsigned int cmd, void *arg) | |||
187 | default: | 134 | default: |
188 | return -ENOIOCTLCMD; | 135 | return -ENOIOCTLCMD; |
189 | } | 136 | } |
190 | |||
191 | return result; | 137 | return result; |
192 | } | 138 | } |
193 | 139 | ||
194 | static struct i2c_driver driver = { | 140 | /* this function is called by i2c_probe */ |
195 | .driver = { | 141 | static int tea6415c_probe(struct i2c_client *client, |
196 | .name = "tea6415c", | 142 | const struct i2c_device_id *id) |
197 | }, | ||
198 | .id = I2C_DRIVERID_TEA6415C, | ||
199 | .attach_adapter = attach, | ||
200 | .detach_client = detach, | ||
201 | .command = command, | ||
202 | }; | ||
203 | |||
204 | static struct i2c_client client_template = { | ||
205 | .name = "tea6415c", | ||
206 | .driver = &driver, | ||
207 | }; | ||
208 | |||
209 | static int __init this_module_init(void) | ||
210 | { | 143 | { |
211 | return i2c_add_driver(&driver); | 144 | /* let's see whether this adapter can support what we need */ |
145 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WRITE_BYTE)) | ||
146 | return 0; | ||
147 | |||
148 | v4l_info(client, "chip found @ 0x%x (%s)\n", | ||
149 | client->addr << 1, client->adapter->name); | ||
150 | return 0; | ||
212 | } | 151 | } |
213 | 152 | ||
214 | static void __exit this_module_exit(void) | 153 | static int tea6415c_legacy_probe(struct i2c_adapter *adapter) |
215 | { | 154 | { |
216 | i2c_del_driver(&driver); | 155 | /* Let's see whether this is a known adapter we can attach to. |
156 | Prevents conflicts with tvaudio.c. */ | ||
157 | return adapter->id == I2C_HW_SAA7146; | ||
217 | } | 158 | } |
218 | 159 | ||
219 | module_init(this_module_init); | 160 | static const struct i2c_device_id tea6415c_id[] = { |
220 | module_exit(this_module_exit); | 161 | { "tea6415c", 0 }, |
162 | { } | ||
163 | }; | ||
164 | MODULE_DEVICE_TABLE(i2c, tea6415c_id); | ||
221 | 165 | ||
222 | MODULE_AUTHOR("Michael Hunold <michael@mihu.de>"); | 166 | static struct v4l2_i2c_driver_data v4l2_i2c_data = { |
223 | MODULE_DESCRIPTION("tea6415c driver"); | 167 | .name = "tea6415c", |
224 | MODULE_LICENSE("GPL"); | 168 | .driverid = I2C_DRIVERID_TEA6415C, |
169 | .command = tea6415c_command, | ||
170 | .probe = tea6415c_probe, | ||
171 | .legacy_probe = tea6415c_legacy_probe, | ||
172 | .id_table = tea6415c_id, | ||
173 | }; | ||
diff --git a/drivers/media/video/tea6420.c b/drivers/media/video/tea6420.c index b5c8957d130e..e50820969e64 100644 --- a/drivers/media/video/tea6420.c +++ b/drivers/media/video/tea6420.c | |||
@@ -2,6 +2,7 @@ | |||
2 | tea6420 - i2c-driver for the tea6420 by SGS Thomson | 2 | tea6420 - i2c-driver for the tea6420 by SGS Thomson |
3 | 3 | ||
4 | Copyright (C) 1998-2003 Michael Hunold <michael@mihu.de> | 4 | Copyright (C) 1998-2003 Michael Hunold <michael@mihu.de> |
5 | Copyright (C) 2008 Hans Verkuil <hverkuil@xs4all.nl> | ||
5 | 6 | ||
6 | The tea6420 is a bus controlled audio-matrix with 5 stereo inputs, | 7 | The tea6420 is a bus controlled audio-matrix with 5 stereo inputs, |
7 | 4 stereo outputs and gain control for each output. | 8 | 4 stereo outputs and gain control for each output. |
@@ -30,15 +31,18 @@ | |||
30 | #include <linux/module.h> | 31 | #include <linux/module.h> |
31 | #include <linux/ioctl.h> | 32 | #include <linux/ioctl.h> |
32 | #include <linux/i2c.h> | 33 | #include <linux/i2c.h> |
33 | 34 | #include <media/v4l2-common.h> | |
35 | #include <media/v4l2-i2c-drv-legacy.h> | ||
34 | #include "tea6420.h" | 36 | #include "tea6420.h" |
35 | 37 | ||
36 | static int debug; /* insmod parameter */ | 38 | MODULE_AUTHOR("Michael Hunold <michael@mihu.de>"); |
39 | MODULE_DESCRIPTION("tea6420 driver"); | ||
40 | MODULE_LICENSE("GPL"); | ||
41 | |||
42 | static int debug; | ||
37 | module_param(debug, int, 0644); | 43 | module_param(debug, int, 0644); |
38 | MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off)."); | ||
39 | 44 | ||
40 | #define dprintk(args...) \ | 45 | MODULE_PARM_DESC(debug, "Debug level (0-1)"); |
41 | do { if (debug) { printk("%s: %s()[%d]: ", KBUILD_MODNAME, __func__, __LINE__); printk(args); } } while (0) | ||
42 | 46 | ||
43 | /* addresses to scan, found only at 0x4c and/or 0x4d (7-Bit) */ | 47 | /* addresses to scan, found only at 0x4c and/or 0x4d (7-Bit) */ |
44 | static unsigned short normal_i2c[] = { I2C_ADDR_TEA6420_1, I2C_ADDR_TEA6420_2, I2C_CLIENT_END }; | 48 | static unsigned short normal_i2c[] = { I2C_ADDR_TEA6420_1, I2C_ADDR_TEA6420_2, I2C_CLIENT_END }; |
@@ -46,23 +50,20 @@ static unsigned short normal_i2c[] = { I2C_ADDR_TEA6420_1, I2C_ADDR_TEA6420_2, I | |||
46 | /* magic definition of all other variables and things */ | 50 | /* magic definition of all other variables and things */ |
47 | I2C_CLIENT_INSMOD; | 51 | I2C_CLIENT_INSMOD; |
48 | 52 | ||
49 | static struct i2c_driver driver; | ||
50 | static struct i2c_client client_template; | ||
51 | |||
52 | /* make a connection between the input 'i' and the output 'o' | 53 | /* make a connection between the input 'i' and the output 'o' |
53 | with gain 'g' for the tea6420-client 'client' (note: i = 6 means 'mute') */ | 54 | with gain 'g' for the tea6420-client 'client' (note: i = 6 means 'mute') */ |
54 | static int tea6420_switch(struct i2c_client *client, int i, int o, int g) | 55 | static int tea6420_switch(struct i2c_client *client, int i, int o, int g) |
55 | { | 56 | { |
56 | u8 byte = 0; | 57 | u8 byte; |
57 | int ret; | 58 | int ret; |
58 | 59 | ||
59 | dprintk("adr:0x%02x, i:%d, o:%d, g:%d\n", client->addr, i, o, g); | 60 | v4l_dbg(1, debug, client, "i=%d, o=%d, g=%d\n", i, o, g); |
60 | 61 | ||
61 | /* check if the parameters are valid */ | 62 | /* check if the parameters are valid */ |
62 | if (i < 1 || i > 6 || o < 1 || o > 4 || g < 0 || g > 6 || g % 2 != 0) | 63 | if (i < 1 || i > 6 || o < 1 || o > 4 || g < 0 || g > 6 || g % 2 != 0) |
63 | return -1; | 64 | return -1; |
64 | 65 | ||
65 | byte = ((o - 1) << 5); | 66 | byte = ((o - 1) << 5); |
66 | byte |= (i - 1); | 67 | byte |= (i - 1); |
67 | 68 | ||
68 | /* to understand this, have a look at the tea6420-specs (p.5) */ | 69 | /* to understand this, have a look at the tea6420-specs (p.5) */ |
@@ -82,40 +83,41 @@ static int tea6420_switch(struct i2c_client *client, int i, int o, int g) | |||
82 | 83 | ||
83 | ret = i2c_smbus_write_byte(client, byte); | 84 | ret = i2c_smbus_write_byte(client, byte); |
84 | if (ret) { | 85 | if (ret) { |
85 | dprintk("i2c_smbus_write_byte() failed, ret:%d\n", ret); | 86 | v4l_dbg(1, debug, client, |
87 | "i2c_smbus_write_byte() failed, ret:%d\n", ret); | ||
86 | return -EIO; | 88 | return -EIO; |
87 | } | 89 | } |
88 | |||
89 | return 0; | 90 | return 0; |
90 | } | 91 | } |
91 | 92 | ||
92 | /* this function is called by i2c_probe */ | 93 | static int tea6420_command(struct i2c_client *client, unsigned cmd, void *arg) |
93 | static int tea6420_detect(struct i2c_adapter *adapter, int address, int kind) | ||
94 | { | 94 | { |
95 | struct i2c_client *client; | 95 | struct tea6420_multiplex *a = (struct tea6420_multiplex *)arg; |
96 | int err = 0, i = 0; | 96 | int result = 0; |
97 | 97 | ||
98 | /* let's see whether this adapter can support what we need */ | 98 | switch (cmd) { |
99 | if (0 == i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WRITE_BYTE)) { | 99 | case TEA6420_SWITCH: |
100 | return 0; | 100 | result = tea6420_switch(client, a->in, a->out, a->gain); |
101 | break; | ||
102 | default: | ||
103 | return -ENOIOCTLCMD; | ||
101 | } | 104 | } |
102 | 105 | ||
103 | /* allocate memory for client structure */ | 106 | return result; |
104 | client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL); | 107 | } |
105 | if (!client) { | ||
106 | return -ENOMEM; | ||
107 | } | ||
108 | 108 | ||
109 | /* fill client structure */ | 109 | /* this function is called by i2c_probe */ |
110 | memcpy(client, &client_template, sizeof(struct i2c_client)); | 110 | static int tea6420_probe(struct i2c_client *client, |
111 | client->addr = address; | 111 | const struct i2c_device_id *id) |
112 | client->adapter = adapter; | 112 | { |
113 | int err, i; | ||
113 | 114 | ||
114 | /* tell the i2c layer a new client has arrived */ | 115 | /* let's see whether this adapter can support what we need */ |
115 | if (0 != (err = i2c_attach_client(client))) { | 116 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WRITE_BYTE)) |
116 | kfree(client); | 117 | return -EIO; |
117 | return err; | 118 | |
118 | } | 119 | v4l_info(client, "chip found @ 0x%x (%s)\n", |
120 | client->addr << 1, client->adapter->name); | ||
119 | 121 | ||
120 | /* set initial values: set "mute"-input to all outputs at gain 0 */ | 122 | /* set initial values: set "mute"-input to all outputs at gain 0 */ |
121 | err = 0; | 123 | err = 0; |
@@ -123,78 +125,31 @@ static int tea6420_detect(struct i2c_adapter *adapter, int address, int kind) | |||
123 | err += tea6420_switch(client, 6, i, 0); | 125 | err += tea6420_switch(client, 6, i, 0); |
124 | } | 126 | } |
125 | if (err) { | 127 | if (err) { |
126 | dprintk("could not initialize tea6420\n"); | 128 | v4l_dbg(1, debug, client, "could not initialize tea6420\n"); |
127 | kfree(client); | 129 | kfree(client); |
128 | return -ENODEV; | 130 | return -ENODEV; |
129 | } | 131 | } |
130 | |||
131 | printk("tea6420: detected @ 0x%02x on adapter %s\n", address, &client->adapter->name[0]); | ||
132 | |||
133 | return 0; | 132 | return 0; |
134 | } | 133 | } |
135 | 134 | ||
136 | static int attach(struct i2c_adapter *adapter) | 135 | static int tea6420_legacy_probe(struct i2c_adapter *adapter) |
137 | { | 136 | { |
138 | /* let's see whether this is a know adapter we can attach to */ | 137 | /* Let's see whether this is a known adapter we can attach to. |
139 | if (adapter->id != I2C_HW_SAA7146) { | 138 | Prevents conflicts with tvaudio.c. */ |
140 | dprintk("refusing to probe on unknown adapter [name='%s',id=0x%x]\n", adapter->name, adapter->id); | 139 | return adapter->id == I2C_HW_SAA7146; |
141 | return -ENODEV; | ||
142 | } | ||
143 | |||
144 | return i2c_probe(adapter, &addr_data, &tea6420_detect); | ||
145 | } | ||
146 | |||
147 | static int detach(struct i2c_client *client) | ||
148 | { | ||
149 | int ret = i2c_detach_client(client); | ||
150 | kfree(client); | ||
151 | return ret; | ||
152 | } | ||
153 | |||
154 | static int command(struct i2c_client *client, unsigned int cmd, void *arg) | ||
155 | { | ||
156 | struct tea6420_multiplex *a = (struct tea6420_multiplex *)arg; | ||
157 | int result = 0; | ||
158 | |||
159 | switch (cmd) { | ||
160 | case TEA6420_SWITCH: | ||
161 | result = tea6420_switch(client, a->in, a->out, a->gain); | ||
162 | break; | ||
163 | default: | ||
164 | return -ENOIOCTLCMD; | ||
165 | } | ||
166 | |||
167 | return result; | ||
168 | } | 140 | } |
169 | 141 | ||
170 | static struct i2c_driver driver = { | 142 | static const struct i2c_device_id tea6420_id[] = { |
171 | .driver = { | 143 | { "tea6420", 0 }, |
172 | .name = "tea6420", | 144 | { } |
173 | }, | ||
174 | .id = I2C_DRIVERID_TEA6420, | ||
175 | .attach_adapter = attach, | ||
176 | .detach_client = detach, | ||
177 | .command = command, | ||
178 | }; | 145 | }; |
146 | MODULE_DEVICE_TABLE(i2c, tea6420_id); | ||
179 | 147 | ||
180 | static struct i2c_client client_template = { | 148 | static struct v4l2_i2c_driver_data v4l2_i2c_data = { |
181 | .name = "tea6420", | 149 | .name = "tea6420", |
182 | .driver = &driver, | 150 | .driverid = I2C_DRIVERID_TEA6420, |
151 | .command = tea6420_command, | ||
152 | .probe = tea6420_probe, | ||
153 | .legacy_probe = tea6420_legacy_probe, | ||
154 | .id_table = tea6420_id, | ||
183 | }; | 155 | }; |
184 | |||
185 | static int __init this_module_init(void) | ||
186 | { | ||
187 | return i2c_add_driver(&driver); | ||
188 | } | ||
189 | |||
190 | static void __exit this_module_exit(void) | ||
191 | { | ||
192 | i2c_del_driver(&driver); | ||
193 | } | ||
194 | |||
195 | module_init(this_module_init); | ||
196 | module_exit(this_module_exit); | ||
197 | |||
198 | MODULE_AUTHOR("Michael Hunold <michael@mihu.de>"); | ||
199 | MODULE_DESCRIPTION("tea6420 driver"); | ||
200 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/video/tuner-3036.c b/drivers/media/video/tuner-3036.c deleted file mode 100644 index bdf506e6ae27..000000000000 --- a/drivers/media/video/tuner-3036.c +++ /dev/null | |||
@@ -1,214 +0,0 @@ | |||
1 | /* | ||
2 | * Driver for Philips SAB3036 "CITAC" tuner control chip. | ||
3 | * | ||
4 | * Author: Phil Blundell <philb@gnu.org> | ||
5 | * | ||
6 | * The SAB3036 is just about different enough from the chips that | ||
7 | * tuner.c copes with to make it not worth the effort to crowbar | ||
8 | * the support into that file. So instead we have a separate driver. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or | ||
11 | * modify it under the terms of the GNU General Public License | ||
12 | * as published by the Free Software Foundation; either version | ||
13 | * 2 of the License, or (at your option) any later version. | ||
14 | */ | ||
15 | |||
16 | #include <linux/module.h> | ||
17 | #include <linux/kernel.h> | ||
18 | #include <linux/sched.h> | ||
19 | #include <linux/string.h> | ||
20 | #include <linux/timer.h> | ||
21 | #include <linux/delay.h> | ||
22 | #include <linux/errno.h> | ||
23 | #include <linux/slab.h> | ||
24 | #include <linux/init.h> | ||
25 | |||
26 | #include <linux/i2c.h> | ||
27 | #include <linux/videodev.h> | ||
28 | #include <media/v4l2-common.h> | ||
29 | |||
30 | #include <media/tuner.h> | ||
31 | |||
32 | static int debug; /* insmod parameter */ | ||
33 | static int this_adap; | ||
34 | |||
35 | static struct i2c_client client_template; | ||
36 | |||
37 | /* Addresses to scan */ | ||
38 | static unsigned short normal_i2c[] = { 0x60, 0x61, I2C_CLIENT_END }; | ||
39 | static unsigned short ignore = I2C_CLIENT_END; | ||
40 | |||
41 | static struct i2c_client_address_data addr_data = { | ||
42 | .normal_i2c = normal_i2c, | ||
43 | .probe = &ignore, | ||
44 | .ignore = &ignore, | ||
45 | }; | ||
46 | |||
47 | /* ---------------------------------------------------------------------- */ | ||
48 | |||
49 | static unsigned char | ||
50 | tuner_getstatus (struct i2c_client *c) | ||
51 | { | ||
52 | unsigned char byte; | ||
53 | if (i2c_master_recv(c, &byte, 1) != 1) | ||
54 | printk(KERN_ERR "tuner-3036: I/O error.\n"); | ||
55 | return byte; | ||
56 | } | ||
57 | |||
58 | #define TUNER_FL 0x80 | ||
59 | |||
60 | static int | ||
61 | tuner_islocked (struct i2c_client *c) | ||
62 | { | ||
63 | return (tuner_getstatus(c) & TUNER_FL); | ||
64 | } | ||
65 | |||
66 | /* ---------------------------------------------------------------------- */ | ||
67 | |||
68 | static void | ||
69 | set_tv_freq(struct i2c_client *c, int freq) | ||
70 | { | ||
71 | u16 div = ((freq * 20) / 16); | ||
72 | unsigned long give_up = jiffies + HZ; | ||
73 | unsigned char buffer[2]; | ||
74 | |||
75 | if (debug) | ||
76 | printk(KERN_DEBUG "tuner: setting frequency %dMHz, divisor %x\n", freq / 16, div); | ||
77 | |||
78 | /* Select high tuning current */ | ||
79 | buffer[0] = 0x29; | ||
80 | buffer[1] = 0x3e; | ||
81 | |||
82 | if (i2c_master_send(c, buffer, 2) != 2) | ||
83 | printk("tuner: i2c i/o error 1\n"); | ||
84 | |||
85 | buffer[0] = 0x80 | ((div>>8) & 0x7f); | ||
86 | buffer[1] = div & 0xff; | ||
87 | |||
88 | if (i2c_master_send(c, buffer, 2) != 2) | ||
89 | printk("tuner: i2c i/o error 2\n"); | ||
90 | |||
91 | while (!tuner_islocked(c) && time_before(jiffies, give_up)) | ||
92 | schedule(); | ||
93 | |||
94 | if (!tuner_islocked(c)) | ||
95 | printk(KERN_WARNING "tuner: failed to achieve PLL lock\n"); | ||
96 | |||
97 | /* Select low tuning current and engage AFC */ | ||
98 | buffer[0] = 0x29; | ||
99 | buffer[1] = 0xb2; | ||
100 | |||
101 | if (i2c_master_send(c, buffer, 2) != 2) | ||
102 | printk("tuner: i2c i/o error 3\n"); | ||
103 | |||
104 | if (debug) | ||
105 | printk(KERN_DEBUG "tuner: status %02x\n", tuner_getstatus(c)); | ||
106 | } | ||
107 | |||
108 | /* ---------------------------------------------------------------------- */ | ||
109 | |||
110 | static int | ||
111 | tuner_attach(struct i2c_adapter *adap, int addr, int kind) | ||
112 | { | ||
113 | static unsigned char buffer[] = { 0x29, 0x32, 0x2a, 0, 0x2b, 0 }; | ||
114 | |||
115 | struct i2c_client *client; | ||
116 | |||
117 | if (this_adap > 0) | ||
118 | return -1; | ||
119 | this_adap++; | ||
120 | |||
121 | client_template.adapter = adap; | ||
122 | client_template.addr = addr; | ||
123 | |||
124 | client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL); | ||
125 | if (client == NULL) | ||
126 | return -ENOMEM; | ||
127 | memcpy(client, &client_template, sizeof(struct i2c_client)); | ||
128 | |||
129 | printk("tuner: SAB3036 found, status %02x\n", tuner_getstatus(client)); | ||
130 | |||
131 | i2c_attach_client(client); | ||
132 | |||
133 | if (i2c_master_send(client, buffer, 2) != 2) | ||
134 | printk("tuner: i2c i/o error 1\n"); | ||
135 | if (i2c_master_send(client, buffer+2, 2) != 2) | ||
136 | printk("tuner: i2c i/o error 2\n"); | ||
137 | if (i2c_master_send(client, buffer+4, 2) != 2) | ||
138 | printk("tuner: i2c i/o error 3\n"); | ||
139 | return 0; | ||
140 | } | ||
141 | |||
142 | static int | ||
143 | tuner_detach(struct i2c_client *c) | ||
144 | { | ||
145 | return 0; | ||
146 | } | ||
147 | |||
148 | static int | ||
149 | tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) | ||
150 | { | ||
151 | int *iarg = (int*)arg; | ||
152 | |||
153 | switch (cmd) | ||
154 | { | ||
155 | case VIDIOCSFREQ: | ||
156 | set_tv_freq(client, *iarg); | ||
157 | break; | ||
158 | |||
159 | default: | ||
160 | return -EINVAL; | ||
161 | } | ||
162 | return 0; | ||
163 | } | ||
164 | |||
165 | static int | ||
166 | tuner_probe(struct i2c_adapter *adap) | ||
167 | { | ||
168 | this_adap = 0; | ||
169 | if (adap->id == I2C_HW_B_LP) | ||
170 | return i2c_probe(adap, &addr_data, tuner_attach); | ||
171 | return 0; | ||
172 | } | ||
173 | |||
174 | /* ----------------------------------------------------------------------- */ | ||
175 | |||
176 | static struct i2c_driver | ||
177 | i2c_driver_tuner = | ||
178 | { | ||
179 | .driver = { | ||
180 | .name = "sab3036", | ||
181 | }, | ||
182 | .id = I2C_DRIVERID_SAB3036, | ||
183 | .attach_adapter = tuner_probe, | ||
184 | .detach_client = tuner_detach, | ||
185 | .command = tuner_command | ||
186 | }; | ||
187 | |||
188 | static struct i2c_client client_template = | ||
189 | { | ||
190 | .driver = &i2c_driver_tuner, | ||
191 | .name = "SAB3036", | ||
192 | }; | ||
193 | |||
194 | static int __init | ||
195 | tuner3036_init(void) | ||
196 | { | ||
197 | return i2c_add_driver(&i2c_driver_tuner); | ||
198 | } | ||
199 | |||
200 | static void __exit | ||
201 | tuner3036_exit(void) | ||
202 | { | ||
203 | i2c_del_driver(&i2c_driver_tuner); | ||
204 | } | ||
205 | |||
206 | MODULE_DESCRIPTION("SAB3036 tuner driver"); | ||
207 | MODULE_AUTHOR("Philip Blundell <philb@gnu.org>"); | ||
208 | MODULE_LICENSE("GPL"); | ||
209 | |||
210 | module_param(debug, int, 0); | ||
211 | MODULE_PARM_DESC(debug,"Enable debugging output"); | ||
212 | |||
213 | module_init(tuner3036_init); | ||
214 | module_exit(tuner3036_exit); | ||
diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index d806a3556eed..4a7735c6c1a6 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c | |||
@@ -92,7 +92,6 @@ struct tuner { | |||
92 | 92 | ||
93 | unsigned int type; /* chip type id */ | 93 | unsigned int type; /* chip type id */ |
94 | unsigned int config; | 94 | unsigned int config; |
95 | int (*tuner_callback) (void *dev, int command, int arg); | ||
96 | const char *name; | 95 | const char *name; |
97 | }; | 96 | }; |
98 | 97 | ||
@@ -346,7 +345,7 @@ static struct xc5000_config xc5000_cfg; | |||
346 | 345 | ||
347 | static void set_type(struct i2c_client *c, unsigned int type, | 346 | static void set_type(struct i2c_client *c, unsigned int type, |
348 | unsigned int new_mode_mask, unsigned int new_config, | 347 | unsigned int new_mode_mask, unsigned int new_config, |
349 | int (*tuner_callback) (void *dev, int command,int arg)) | 348 | int (*tuner_callback) (void *dev, int component, int cmd, int arg)) |
350 | { | 349 | { |
351 | struct tuner *t = i2c_get_clientdata(c); | 350 | struct tuner *t = i2c_get_clientdata(c); |
352 | struct dvb_tuner_ops *fe_tuner_ops = &t->fe.ops.tuner_ops; | 351 | struct dvb_tuner_ops *fe_tuner_ops = &t->fe.ops.tuner_ops; |
@@ -362,7 +361,7 @@ static void set_type(struct i2c_client *c, unsigned int type, | |||
362 | t->config = new_config; | 361 | t->config = new_config; |
363 | if (tuner_callback != NULL) { | 362 | if (tuner_callback != NULL) { |
364 | tuner_dbg("defining GPIO callback\n"); | 363 | tuner_dbg("defining GPIO callback\n"); |
365 | t->tuner_callback = tuner_callback; | 364 | t->fe.callback = tuner_callback; |
366 | } | 365 | } |
367 | 366 | ||
368 | if (t->mode == T_UNINITIALIZED) { | 367 | if (t->mode == T_UNINITIALIZED) { |
@@ -385,7 +384,6 @@ static void set_type(struct i2c_client *c, unsigned int type, | |||
385 | { | 384 | { |
386 | struct tda829x_config cfg = { | 385 | struct tda829x_config cfg = { |
387 | .lna_cfg = t->config, | 386 | .lna_cfg = t->config, |
388 | .tuner_callback = t->tuner_callback, | ||
389 | }; | 387 | }; |
390 | if (!dvb_attach(tda829x_attach, &t->fe, t->i2c->adapter, | 388 | if (!dvb_attach(tda829x_attach, &t->fe, t->i2c->adapter, |
391 | t->i2c->addr, &cfg)) | 389 | t->i2c->addr, &cfg)) |
@@ -433,7 +431,6 @@ static void set_type(struct i2c_client *c, unsigned int type, | |||
433 | struct xc2028_config cfg = { | 431 | struct xc2028_config cfg = { |
434 | .i2c_adap = t->i2c->adapter, | 432 | .i2c_adap = t->i2c->adapter, |
435 | .i2c_addr = t->i2c->addr, | 433 | .i2c_addr = t->i2c->addr, |
436 | .callback = t->tuner_callback, | ||
437 | }; | 434 | }; |
438 | if (!dvb_attach(xc2028_attach, &t->fe, &cfg)) | 435 | if (!dvb_attach(xc2028_attach, &t->fe, &cfg)) |
439 | goto attach_failed; | 436 | goto attach_failed; |
@@ -450,10 +447,8 @@ static void set_type(struct i2c_client *c, unsigned int type, | |||
450 | 447 | ||
451 | xc5000_cfg.i2c_address = t->i2c->addr; | 448 | xc5000_cfg.i2c_address = t->i2c->addr; |
452 | xc5000_cfg.if_khz = 5380; | 449 | xc5000_cfg.if_khz = 5380; |
453 | xc5000_cfg.tuner_callback = t->tuner_callback; | ||
454 | if (!dvb_attach(xc5000_attach, | 450 | if (!dvb_attach(xc5000_attach, |
455 | &t->fe, t->i2c->adapter, &xc5000_cfg, | 451 | &t->fe, t->i2c->adapter, &xc5000_cfg)) |
456 | c->adapter->algo_data)) | ||
457 | goto attach_failed; | 452 | goto attach_failed; |
458 | 453 | ||
459 | xc_tuner_ops = &t->fe.ops.tuner_ops; | 454 | xc_tuner_ops = &t->fe.ops.tuner_ops; |
@@ -1225,7 +1220,7 @@ register_client: | |||
1225 | } else { | 1220 | } else { |
1226 | t->mode = V4L2_TUNER_DIGITAL_TV; | 1221 | t->mode = V4L2_TUNER_DIGITAL_TV; |
1227 | } | 1222 | } |
1228 | set_type(client, t->type, t->mode_mask, t->config, t->tuner_callback); | 1223 | set_type(client, t->type, t->mode_mask, t->config, t->fe.callback); |
1229 | list_add_tail(&t->list, &tuner_list); | 1224 | list_add_tail(&t->list, &tuner_list); |
1230 | return 0; | 1225 | return 0; |
1231 | } | 1226 | } |
diff --git a/drivers/media/video/usbvideo/ibmcam.c b/drivers/media/video/usbvideo/ibmcam.c index cc27efe121dd..28421d386f1e 100644 --- a/drivers/media/video/usbvideo/ibmcam.c +++ b/drivers/media/video/usbvideo/ibmcam.c | |||
@@ -258,7 +258,9 @@ static enum ParseState ibmcam_find_header(struct uvd *uvd) /* FIXME: Add frame h | |||
258 | (RING_QUEUE_PEEK(&uvd->dp, 2) == 0x00)) | 258 | (RING_QUEUE_PEEK(&uvd->dp, 2) == 0x00)) |
259 | { | 259 | { |
260 | #if 0 /* This code helps to detect new frame markers */ | 260 | #if 0 /* This code helps to detect new frame markers */ |
261 | info("Header sig: 00 FF 00 %02X", RING_QUEUE_PEEK(&uvd->dp, 3)); | 261 | dev_info(&uvd->dev->dev, |
262 | "Header sig: 00 FF 00 %02X\n", | ||
263 | RING_QUEUE_PEEK(&uvd->dp, 3)); | ||
262 | #endif | 264 | #endif |
263 | frame->header = RING_QUEUE_PEEK(&uvd->dp, 3); | 265 | frame->header = RING_QUEUE_PEEK(&uvd->dp, 3); |
264 | if ((frame->header == HDRSIG_MODEL1_128x96) || | 266 | if ((frame->header == HDRSIG_MODEL1_128x96) || |
@@ -266,7 +268,8 @@ static enum ParseState ibmcam_find_header(struct uvd *uvd) /* FIXME: Add frame h | |||
266 | (frame->header == HDRSIG_MODEL1_352x288)) | 268 | (frame->header == HDRSIG_MODEL1_352x288)) |
267 | { | 269 | { |
268 | #if 0 | 270 | #if 0 |
269 | info("Header found."); | 271 | dev_info(&uvd->dev->dev, |
272 | "Header found.\n"); | ||
270 | #endif | 273 | #endif |
271 | RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, marker_len); | 274 | RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, marker_len); |
272 | icam->has_hdr = 1; | 275 | icam->has_hdr = 1; |
@@ -295,7 +298,7 @@ case IBMCAM_MODEL_4: | |||
295 | (RING_QUEUE_PEEK(&uvd->dp, 1) == 0xFF)) | 298 | (RING_QUEUE_PEEK(&uvd->dp, 1) == 0xFF)) |
296 | { | 299 | { |
297 | #if 0 | 300 | #if 0 |
298 | info("Header found."); | 301 | dev_info(&uvd->dev->dev, "Header found.\n"); |
299 | #endif | 302 | #endif |
300 | RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, marker_len); | 303 | RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, marker_len); |
301 | icam->has_hdr = 1; | 304 | icam->has_hdr = 1; |
@@ -338,7 +341,7 @@ case IBMCAM_MODEL_4: | |||
338 | byte4 = RING_QUEUE_PEEK(&uvd->dp, 3); | 341 | byte4 = RING_QUEUE_PEEK(&uvd->dp, 3); |
339 | frame->header = (byte3 << 8) | byte4; | 342 | frame->header = (byte3 << 8) | byte4; |
340 | #if 0 | 343 | #if 0 |
341 | info("Header found."); | 344 | dev_info(&uvd->dev->dev, "Header found.\n"); |
342 | #endif | 345 | #endif |
343 | RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, marker_len); | 346 | RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, marker_len); |
344 | icam->has_hdr = 1; | 347 | icam->has_hdr = 1; |
@@ -354,7 +357,8 @@ case IBMCAM_MODEL_4: | |||
354 | } | 357 | } |
355 | if (!icam->has_hdr) { | 358 | if (!icam->has_hdr) { |
356 | if (uvd->debug > 2) | 359 | if (uvd->debug > 2) |
357 | info("Skipping frame, no header"); | 360 | dev_info(&uvd->dev->dev, |
361 | "Skipping frame, no header\n"); | ||
358 | return scan_EndParse; | 362 | return scan_EndParse; |
359 | } | 363 | } |
360 | 364 | ||
@@ -881,7 +885,9 @@ static enum ParseState ibmcam_model3_parse_lines( | |||
881 | */ | 885 | */ |
882 | if ((frame->curline + 1) >= data_h) { | 886 | if ((frame->curline + 1) >= data_h) { |
883 | if (uvd->debug >= 3) | 887 | if (uvd->debug >= 3) |
884 | info("Reached line %d. (frame is done)", frame->curline); | 888 | dev_info(&uvd->dev->dev, |
889 | "Reached line %d. (frame is done)\n", | ||
890 | frame->curline); | ||
885 | return scan_NextFrame; | 891 | return scan_NextFrame; |
886 | } | 892 | } |
887 | 893 | ||
@@ -954,8 +960,9 @@ static enum ParseState ibmcam_model3_parse_lines( | |||
954 | 960 | ||
955 | if (frame->curline >= VIDEOSIZE_Y(frame->request)) { | 961 | if (frame->curline >= VIDEOSIZE_Y(frame->request)) { |
956 | if (uvd->debug >= 3) { | 962 | if (uvd->debug >= 3) { |
957 | info("All requested lines (%ld.) done.", | 963 | dev_info(&uvd->dev->dev, |
958 | VIDEOSIZE_Y(frame->request)); | 964 | "All requested lines (%ld.) done.\n", |
965 | VIDEOSIZE_Y(frame->request)); | ||
959 | } | 966 | } |
960 | return scan_NextFrame; | 967 | return scan_NextFrame; |
961 | } else | 968 | } else |
@@ -1000,7 +1007,9 @@ static enum ParseState ibmcam_model4_128x96_parse_lines( | |||
1000 | */ | 1007 | */ |
1001 | if ((frame->curline + 1) >= data_h) { | 1008 | if ((frame->curline + 1) >= data_h) { |
1002 | if (uvd->debug >= 3) | 1009 | if (uvd->debug >= 3) |
1003 | info("Reached line %d. (frame is done)", frame->curline); | 1010 | dev_info(&uvd->dev->dev, |
1011 | "Reached line %d. (frame is done)\n", | ||
1012 | frame->curline); | ||
1004 | return scan_NextFrame; | 1013 | return scan_NextFrame; |
1005 | } | 1014 | } |
1006 | 1015 | ||
@@ -1049,8 +1058,9 @@ static enum ParseState ibmcam_model4_128x96_parse_lines( | |||
1049 | 1058 | ||
1050 | if (frame->curline >= VIDEOSIZE_Y(frame->request)) { | 1059 | if (frame->curline >= VIDEOSIZE_Y(frame->request)) { |
1051 | if (uvd->debug >= 3) { | 1060 | if (uvd->debug >= 3) { |
1052 | info("All requested lines (%ld.) done.", | 1061 | dev_info(&uvd->dev->dev, |
1053 | VIDEOSIZE_Y(frame->request)); | 1062 | "All requested lines (%ld.) done.\n", |
1063 | VIDEOSIZE_Y(frame->request)); | ||
1054 | } | 1064 | } |
1055 | return scan_NextFrame; | 1065 | return scan_NextFrame; |
1056 | } else | 1066 | } else |
@@ -1171,10 +1181,11 @@ static int ibmcam_veio( | |||
1171 | sizeof(cp), | 1181 | sizeof(cp), |
1172 | 1000); | 1182 | 1000); |
1173 | #if 0 | 1183 | #if 0 |
1174 | info("USB => %02x%02x%02x%02x%02x%02x%02x%02x " | 1184 | dev_info(&uvd->dev->dev, |
1175 | "(req=$%02x val=$%04x ind=$%04x)", | 1185 | "USB => %02x%02x%02x%02x%02x%02x%02x%02x " |
1176 | cp[0],cp[1],cp[2],cp[3],cp[4],cp[5],cp[6],cp[7], | 1186 | "(req=$%02x val=$%04x ind=$%04x)\n", |
1177 | req, value, index); | 1187 | cp[0],cp[1],cp[2],cp[3],cp[4],cp[5],cp[6],cp[7], |
1188 | req, value, index); | ||
1178 | #endif | 1189 | #endif |
1179 | } else { | 1190 | } else { |
1180 | i = usb_control_msg( | 1191 | i = usb_control_msg( |
@@ -1449,10 +1460,9 @@ static void ibmcam_adjust_contrast(struct uvd *uvd) | |||
1449 | */ | 1460 | */ |
1450 | static void ibmcam_change_lighting_conditions(struct uvd *uvd) | 1461 | static void ibmcam_change_lighting_conditions(struct uvd *uvd) |
1451 | { | 1462 | { |
1452 | static const char proc[] = "ibmcam_change_lighting_conditions"; | ||
1453 | |||
1454 | if (debug > 0) | 1463 | if (debug > 0) |
1455 | info("%s: Set lighting to %hu.", proc, lighting); | 1464 | dev_info(&uvd->dev->dev, |
1465 | "%s: Set lighting to %hu.\n", __func__, lighting); | ||
1456 | 1466 | ||
1457 | switch (IBMCAM_T(uvd)->camera_model) { | 1467 | switch (IBMCAM_T(uvd)->camera_model) { |
1458 | case IBMCAM_MODEL_1: | 1468 | case IBMCAM_MODEL_1: |
@@ -1495,8 +1505,6 @@ static void ibmcam_change_lighting_conditions(struct uvd *uvd) | |||
1495 | */ | 1505 | */ |
1496 | static void ibmcam_set_sharpness(struct uvd *uvd) | 1506 | static void ibmcam_set_sharpness(struct uvd *uvd) |
1497 | { | 1507 | { |
1498 | static const char proc[] = "ibmcam_set_sharpness"; | ||
1499 | |||
1500 | switch (IBMCAM_T(uvd)->camera_model) { | 1508 | switch (IBMCAM_T(uvd)->camera_model) { |
1501 | case IBMCAM_MODEL_1: | 1509 | case IBMCAM_MODEL_1: |
1502 | { | 1510 | { |
@@ -1505,7 +1513,8 @@ static void ibmcam_set_sharpness(struct uvd *uvd) | |||
1505 | 1513 | ||
1506 | RESTRICT_TO_RANGE(sharpness, SHARPNESS_MIN, SHARPNESS_MAX); | 1514 | RESTRICT_TO_RANGE(sharpness, SHARPNESS_MIN, SHARPNESS_MAX); |
1507 | if (debug > 0) | 1515 | if (debug > 0) |
1508 | info("%s: Set sharpness to %hu.", proc, sharpness); | 1516 | dev_info(&uvd->dev->dev, "%s: Set sharpness to %hu.\n", |
1517 | __func__, sharpness); | ||
1509 | 1518 | ||
1510 | sv = sa[sharpness - SHARPNESS_MIN]; | 1519 | sv = sa[sharpness - SHARPNESS_MIN]; |
1511 | for (i=0; i < 2; i++) { | 1520 | for (i=0; i < 2; i++) { |
@@ -1564,11 +1573,11 @@ static void ibmcam_set_sharpness(struct uvd *uvd) | |||
1564 | */ | 1573 | */ |
1565 | static void ibmcam_set_brightness(struct uvd *uvd) | 1574 | static void ibmcam_set_brightness(struct uvd *uvd) |
1566 | { | 1575 | { |
1567 | static const char proc[] = "ibmcam_set_brightness"; | ||
1568 | static const unsigned short n = 1; | 1576 | static const unsigned short n = 1; |
1569 | 1577 | ||
1570 | if (debug > 0) | 1578 | if (debug > 0) |
1571 | info("%s: Set brightness to %hu.", proc, uvd->vpic.brightness); | 1579 | dev_info(&uvd->dev->dev, "%s: Set brightness to %hu.\n", |
1580 | __func__, uvd->vpic.brightness); | ||
1572 | 1581 | ||
1573 | switch (IBMCAM_T(uvd)->camera_model) { | 1582 | switch (IBMCAM_T(uvd)->camera_model) { |
1574 | case IBMCAM_MODEL_1: | 1583 | case IBMCAM_MODEL_1: |
@@ -2115,7 +2124,8 @@ static void ibmcam_model2_setup_after_video_if(struct uvd *uvd) | |||
2115 | break; | 2124 | break; |
2116 | } | 2125 | } |
2117 | if (uvd->debug > 0) | 2126 | if (uvd->debug > 0) |
2118 | info("Framerate (hardware): %hd.", hw_fps); | 2127 | dev_info(&uvd->dev->dev, "Framerate (hardware): %hd.\n", |
2128 | hw_fps); | ||
2119 | RESTRICT_TO_RANGE(hw_fps, 0, 31); | 2129 | RESTRICT_TO_RANGE(hw_fps, 0, 31); |
2120 | ibmcam_model2_Packet1(uvd, mod2_set_framerate, hw_fps); | 2130 | ibmcam_model2_Packet1(uvd, mod2_set_framerate, hw_fps); |
2121 | } | 2131 | } |
@@ -3487,7 +3497,7 @@ static void ibmcam_model3_setup_after_video_if(struct uvd *uvd) | |||
3487 | /* 01.01.08 - Added for RCA video in support -LO */ | 3497 | /* 01.01.08 - Added for RCA video in support -LO */ |
3488 | if(init_model3_input) { | 3498 | if(init_model3_input) { |
3489 | if (debug > 0) | 3499 | if (debug > 0) |
3490 | info("Setting input to RCA."); | 3500 | dev_info(&uvd->dev->dev, "Setting input to RCA.\n"); |
3491 | for (i=0; i < ARRAY_SIZE(initData); i++) { | 3501 | for (i=0; i < ARRAY_SIZE(initData); i++) { |
3492 | ibmcam_veio(uvd, initData[i].req, initData[i].value, initData[i].index); | 3502 | ibmcam_veio(uvd, initData[i].req, initData[i].value, initData[i].index); |
3493 | } | 3503 | } |
@@ -3685,7 +3695,7 @@ static int ibmcam_probe(struct usb_interface *intf, const struct usb_device_id * | |||
3685 | unsigned char video_ep = 0; | 3695 | unsigned char video_ep = 0; |
3686 | 3696 | ||
3687 | if (debug >= 1) | 3697 | if (debug >= 1) |
3688 | info("ibmcam_probe(%p,%u.)", intf, ifnum); | 3698 | dev_info(&uvd->dev->dev, "ibmcam_probe(%p,%u.)\n", intf, ifnum); |
3689 | 3699 | ||
3690 | /* We don't handle multi-config cameras */ | 3700 | /* We don't handle multi-config cameras */ |
3691 | if (dev->descriptor.bNumConfigurations != 1) | 3701 | if (dev->descriptor.bNumConfigurations != 1) |
@@ -3736,14 +3746,16 @@ static int ibmcam_probe(struct usb_interface *intf, const struct usb_device_id * | |||
3736 | brand = "IBM PC Camera"; /* a.k.a. Xirlink C-It */ | 3746 | brand = "IBM PC Camera"; /* a.k.a. Xirlink C-It */ |
3737 | break; | 3747 | break; |
3738 | } | 3748 | } |
3739 | info("%s USB camera found (model %d, rev. 0x%04x)", | 3749 | dev_info(&uvd->dev->dev, |
3740 | brand, model, le16_to_cpu(dev->descriptor.bcdDevice)); | 3750 | "%s USB camera found (model %d, rev. 0x%04x)\n", |
3751 | brand, model, le16_to_cpu(dev->descriptor.bcdDevice)); | ||
3741 | } while (0); | 3752 | } while (0); |
3742 | 3753 | ||
3743 | /* Validate found interface: must have one ISO endpoint */ | 3754 | /* Validate found interface: must have one ISO endpoint */ |
3744 | nas = intf->num_altsetting; | 3755 | nas = intf->num_altsetting; |
3745 | if (debug > 0) | 3756 | if (debug > 0) |
3746 | info("Number of alternate settings=%d.", nas); | 3757 | dev_info(&uvd->dev->dev, "Number of alternate settings=%d.\n", |
3758 | nas); | ||
3747 | if (nas < 2) { | 3759 | if (nas < 2) { |
3748 | err("Too few alternate settings for this camera!"); | 3760 | err("Too few alternate settings for this camera!"); |
3749 | return -ENODEV; | 3761 | return -ENODEV; |
@@ -3787,7 +3799,9 @@ static int ibmcam_probe(struct usb_interface *intf, const struct usb_device_id * | |||
3787 | actInterface = i; | 3799 | actInterface = i; |
3788 | maxPS = le16_to_cpu(endpoint->wMaxPacketSize); | 3800 | maxPS = le16_to_cpu(endpoint->wMaxPacketSize); |
3789 | if (debug > 0) | 3801 | if (debug > 0) |
3790 | info("Active setting=%d. maxPS=%d.", i, maxPS); | 3802 | dev_info(&uvd->dev->dev, |
3803 | "Active setting=%d. " | ||
3804 | "maxPS=%d.\n", i, maxPS); | ||
3791 | } else | 3805 | } else |
3792 | err("More than one active alt. setting! Ignoring #%d.", i); | 3806 | err("More than one active alt. setting! Ignoring #%d.", i); |
3793 | } | 3807 | } |
@@ -3826,7 +3840,7 @@ static int ibmcam_probe(struct usb_interface *intf, const struct usb_device_id * | |||
3826 | RESTRICT_TO_RANGE(framerate, 0, 5); | 3840 | RESTRICT_TO_RANGE(framerate, 0, 5); |
3827 | break; | 3841 | break; |
3828 | default: | 3842 | default: |
3829 | info("IBM camera: using 320x240"); | 3843 | dev_info(&uvd->dev->dev, "IBM camera: using 320x240\n"); |
3830 | size = SIZE_320x240; | 3844 | size = SIZE_320x240; |
3831 | /* No break here */ | 3845 | /* No break here */ |
3832 | case SIZE_320x240: | 3846 | case SIZE_320x240: |
@@ -3855,7 +3869,7 @@ static int ibmcam_probe(struct usb_interface *intf, const struct usb_device_id * | |||
3855 | canvasY = 120; | 3869 | canvasY = 120; |
3856 | break; | 3870 | break; |
3857 | default: | 3871 | default: |
3858 | info("IBM NetCamera: using 176x144"); | 3872 | dev_info(&uvd->dev->dev, "IBM NetCamera: using 176x144\n"); |
3859 | size = SIZE_176x144; | 3873 | size = SIZE_176x144; |
3860 | /* No break here */ | 3874 | /* No break here */ |
3861 | case SIZE_176x144: | 3875 | case SIZE_176x144: |
diff --git a/drivers/media/video/usbvideo/konicawc.c b/drivers/media/video/usbvideo/konicawc.c index 1c180284ec6c..e986c28b7bb0 100644 --- a/drivers/media/video/usbvideo/konicawc.c +++ b/drivers/media/video/usbvideo/konicawc.c | |||
@@ -337,7 +337,8 @@ static int konicawc_compress_iso(struct uvd *uvd, struct urb *dataurb, struct ur | |||
337 | } | 337 | } |
338 | 338 | ||
339 | if((sts > 0x01) && (sts < 0x80)) { | 339 | if((sts > 0x01) && (sts < 0x80)) { |
340 | info("unknown status %2.2x", sts); | 340 | dev_info(&uvd->dev->dev, "unknown status %2.2x\n", |
341 | sts); | ||
341 | bad++; | 342 | bad++; |
342 | continue; | 343 | continue; |
343 | } | 344 | } |
@@ -568,8 +569,12 @@ static void konicawc_process_isoc(struct uvd *uvd, struct usbvideo_frame *frame) | |||
568 | fdrops = (0x80 + curframe - cam->lastframe) & 0x7F; | 569 | fdrops = (0x80 + curframe - cam->lastframe) & 0x7F; |
569 | fdrops--; | 570 | fdrops--; |
570 | if(fdrops) { | 571 | if(fdrops) { |
571 | info("Dropped %d frames (%d -> %d)", fdrops, | 572 | dev_info(&uvd->dev->dev, |
572 | cam->lastframe, curframe); | 573 | "Dropped %d frames " |
574 | "(%d -> %d)\n", | ||
575 | fdrops, | ||
576 | cam->lastframe, | ||
577 | curframe); | ||
573 | } | 578 | } |
574 | } | 579 | } |
575 | cam->lastframe = curframe; | 580 | cam->lastframe = curframe; |
@@ -784,7 +789,8 @@ static int konicawc_probe(struct usb_interface *intf, const struct usb_device_id | |||
784 | if (dev->descriptor.bNumConfigurations != 1) | 789 | if (dev->descriptor.bNumConfigurations != 1) |
785 | return -ENODEV; | 790 | return -ENODEV; |
786 | 791 | ||
787 | info("Konica Webcam (rev. 0x%04x)", le16_to_cpu(dev->descriptor.bcdDevice)); | 792 | dev_info(&intf->dev, "Konica Webcam (rev. 0x%04x)\n", |
793 | le16_to_cpu(dev->descriptor.bcdDevice)); | ||
788 | RESTRICT_TO_RANGE(speed, 0, MAX_SPEED); | 794 | RESTRICT_TO_RANGE(speed, 0, MAX_SPEED); |
789 | 795 | ||
790 | /* Validate found interface: must have one ISO endpoint */ | 796 | /* Validate found interface: must have one ISO endpoint */ |
@@ -925,7 +931,8 @@ static struct usb_device_id id_table[] = { | |||
925 | static int __init konicawc_init(void) | 931 | static int __init konicawc_init(void) |
926 | { | 932 | { |
927 | struct usbvideo_cb cbTbl; | 933 | struct usbvideo_cb cbTbl; |
928 | info(DRIVER_DESC " " DRIVER_VERSION); | 934 | printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" |
935 | DRIVER_DESC "\n"); | ||
929 | memset(&cbTbl, 0, sizeof(cbTbl)); | 936 | memset(&cbTbl, 0, sizeof(cbTbl)); |
930 | cbTbl.probe = konicawc_probe; | 937 | cbTbl.probe = konicawc_probe; |
931 | cbTbl.setupOnOpen = konicawc_setup_on_open; | 938 | cbTbl.setupOnOpen = konicawc_setup_on_open; |
diff --git a/drivers/media/video/usbvideo/quickcam_messenger.c b/drivers/media/video/usbvideo/quickcam_messenger.c index 3d26a30abe1e..05c61b523115 100644 --- a/drivers/media/video/usbvideo/quickcam_messenger.c +++ b/drivers/media/video/usbvideo/quickcam_messenger.c | |||
@@ -1080,7 +1080,8 @@ static struct usbvideo_cb qcm_driver = { | |||
1080 | 1080 | ||
1081 | static int __init qcm_init(void) | 1081 | static int __init qcm_init(void) |
1082 | { | 1082 | { |
1083 | info(DRIVER_DESC " " DRIVER_VERSION); | 1083 | printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" |
1084 | DRIVER_DESC "\n"); | ||
1084 | 1085 | ||
1085 | return usbvideo_register( | 1086 | return usbvideo_register( |
1086 | &cams, | 1087 | &cams, |
diff --git a/drivers/media/video/usbvideo/ultracam.c b/drivers/media/video/usbvideo/ultracam.c index 9544e644bf0d..9714baab7833 100644 --- a/drivers/media/video/usbvideo/ultracam.c +++ b/drivers/media/video/usbvideo/ultracam.c | |||
@@ -156,10 +156,11 @@ static int ultracam_veio( | |||
156 | sizeof(cp), | 156 | sizeof(cp), |
157 | 1000); | 157 | 1000); |
158 | #if 1 | 158 | #if 1 |
159 | info("USB => %02x%02x%02x%02x%02x%02x%02x%02x " | 159 | dev_info(&uvd->dev->dev, |
160 | "(req=$%02x val=$%04x ind=$%04x)", | 160 | "USB => %02x%02x%02x%02x%02x%02x%02x%02x " |
161 | cp[0],cp[1],cp[2],cp[3],cp[4],cp[5],cp[6],cp[7], | 161 | "(req=$%02x val=$%04x ind=$%04x)\n", |
162 | req, value, index); | 162 | cp[0],cp[1],cp[2],cp[3],cp[4],cp[5],cp[6],cp[7], |
163 | req, value, index); | ||
163 | #endif | 164 | #endif |
164 | } else { | 165 | } else { |
165 | i = usb_control_msg( | 166 | i = usb_control_msg( |
@@ -517,19 +518,20 @@ static int ultracam_probe(struct usb_interface *intf, const struct usb_device_id | |||
517 | unsigned char video_ep = 0; | 518 | unsigned char video_ep = 0; |
518 | 519 | ||
519 | if (debug >= 1) | 520 | if (debug >= 1) |
520 | info("ultracam_probe(%p)", intf); | 521 | dev_info(&intf->dev, "ultracam_probe\n"); |
521 | 522 | ||
522 | /* We don't handle multi-config cameras */ | 523 | /* We don't handle multi-config cameras */ |
523 | if (dev->descriptor.bNumConfigurations != 1) | 524 | if (dev->descriptor.bNumConfigurations != 1) |
524 | return -ENODEV; | 525 | return -ENODEV; |
525 | 526 | ||
526 | info("IBM Ultra camera found (rev. 0x%04x)", | 527 | dev_info(&intf->dev, "IBM Ultra camera found (rev. 0x%04x)\n", |
527 | le16_to_cpu(dev->descriptor.bcdDevice)); | 528 | le16_to_cpu(dev->descriptor.bcdDevice)); |
528 | 529 | ||
529 | /* Validate found interface: must have one ISO endpoint */ | 530 | /* Validate found interface: must have one ISO endpoint */ |
530 | nas = intf->num_altsetting; | 531 | nas = intf->num_altsetting; |
531 | if (debug > 0) | 532 | if (debug > 0) |
532 | info("Number of alternate settings=%d.", nas); | 533 | dev_info(&intf->dev, "Number of alternate settings=%d.\n", |
534 | nas); | ||
533 | if (nas < 8) { | 535 | if (nas < 8) { |
534 | err("Too few alternate settings for this camera!"); | 536 | err("Too few alternate settings for this camera!"); |
535 | return -ENODEV; | 537 | return -ENODEV; |
@@ -576,7 +578,9 @@ static int ultracam_probe(struct usb_interface *intf, const struct usb_device_id | |||
576 | actInterface = i; | 578 | actInterface = i; |
577 | maxPS = le16_to_cpu(endpoint->wMaxPacketSize); | 579 | maxPS = le16_to_cpu(endpoint->wMaxPacketSize); |
578 | if (debug > 0) | 580 | if (debug > 0) |
579 | info("Active setting=%d. maxPS=%d.", i, maxPS); | 581 | dev_info(&intf->dev, |
582 | "Active setting=%d. " | ||
583 | "maxPS=%d.\n", i, maxPS); | ||
580 | } else { | 584 | } else { |
581 | /* Got another active alt. setting */ | 585 | /* Got another active alt. setting */ |
582 | if (maxPS < le16_to_cpu(endpoint->wMaxPacketSize)) { | 586 | if (maxPS < le16_to_cpu(endpoint->wMaxPacketSize)) { |
@@ -584,8 +588,11 @@ static int ultracam_probe(struct usb_interface *intf, const struct usb_device_id | |||
584 | actInterface = i; | 588 | actInterface = i; |
585 | maxPS = le16_to_cpu(endpoint->wMaxPacketSize); | 589 | maxPS = le16_to_cpu(endpoint->wMaxPacketSize); |
586 | if (debug > 0) { | 590 | if (debug > 0) { |
587 | info("Even better ctive setting=%d. maxPS=%d.", | 591 | dev_info(&intf->dev, |
588 | i, maxPS); | 592 | "Even better ctive " |
593 | "setting=%d. " | ||
594 | "maxPS=%d.\n", | ||
595 | i, maxPS); | ||
589 | } | 596 | } |
590 | } | 597 | } |
591 | } | 598 | } |
diff --git a/drivers/media/video/usbvideo/usbvideo.c b/drivers/media/video/usbvideo/usbvideo.c index bf1bc2f69b02..07cd87d16f69 100644 --- a/drivers/media/video/usbvideo/usbvideo.c +++ b/drivers/media/video/usbvideo/usbvideo.c | |||
@@ -468,8 +468,9 @@ static void usbvideo_ReportStatistics(const struct uvd *uvd) | |||
468 | percent = (100 * goodPackets) / allPackets; | 468 | percent = (100 * goodPackets) / allPackets; |
469 | else | 469 | else |
470 | percent = goodPackets / (allPackets / 100); | 470 | percent = goodPackets / (allPackets / 100); |
471 | info("Packet Statistics: Total=%lu. Empty=%lu. Usage=%lu%%", | 471 | dev_info(&uvd->dev->dev, |
472 | allPackets, badPackets, percent); | 472 | "Packet Statistics: Total=%lu. Empty=%lu. Usage=%lu%%\n", |
473 | allPackets, badPackets, percent); | ||
473 | if (uvd->iso_packet_len > 0) { | 474 | if (uvd->iso_packet_len > 0) { |
474 | unsigned long allBytes, xferBytes; | 475 | unsigned long allBytes, xferBytes; |
475 | char multiplier = ' '; | 476 | char multiplier = ' '; |
@@ -497,8 +498,9 @@ static void usbvideo_ReportStatistics(const struct uvd *uvd) | |||
497 | } | 498 | } |
498 | } | 499 | } |
499 | } | 500 | } |
500 | info("Transfer Statistics: Transferred=%lu%cB Usage=%lu%%", | 501 | dev_info(&uvd->dev->dev, |
501 | xferBytes, multiplier, percent); | 502 | "Transfer Statistics: Transferred=%lu%cB Usage=%lu%%\n", |
503 | xferBytes, multiplier, percent); | ||
502 | } | 504 | } |
503 | } | 505 | } |
504 | } | 506 | } |
@@ -545,7 +547,7 @@ void usbvideo_TestPattern(struct uvd *uvd, int fullframe, int pmode) | |||
545 | { /* For debugging purposes only */ | 547 | { /* For debugging purposes only */ |
546 | char tmp[20]; | 548 | char tmp[20]; |
547 | usbvideo_VideosizeToString(tmp, sizeof(tmp), frame->request); | 549 | usbvideo_VideosizeToString(tmp, sizeof(tmp), frame->request); |
548 | info("testpattern: frame=%s", tmp); | 550 | dev_info(&uvd->dev->dev, "testpattern: frame=%s\n", tmp); |
549 | } | 551 | } |
550 | #endif | 552 | #endif |
551 | /* Form every scan line */ | 553 | /* Form every scan line */ |
@@ -854,7 +856,7 @@ static void usbvideo_Disconnect(struct usb_interface *intf) | |||
854 | 856 | ||
855 | usbvideo_ClientIncModCount(uvd); | 857 | usbvideo_ClientIncModCount(uvd); |
856 | if (uvd->debug > 0) | 858 | if (uvd->debug > 0) |
857 | info("%s(%p.)", __func__, intf); | 859 | dev_info(&intf->dev, "%s(%p.)\n", __func__, intf); |
858 | 860 | ||
859 | mutex_lock(&uvd->lock); | 861 | mutex_lock(&uvd->lock); |
860 | uvd->remove_pending = 1; /* Now all ISO data will be ignored */ | 862 | uvd->remove_pending = 1; /* Now all ISO data will be ignored */ |
@@ -870,14 +872,15 @@ static void usbvideo_Disconnect(struct usb_interface *intf) | |||
870 | 872 | ||
871 | video_unregister_device(&uvd->vdev); | 873 | video_unregister_device(&uvd->vdev); |
872 | if (uvd->debug > 0) | 874 | if (uvd->debug > 0) |
873 | info("%s: Video unregistered.", __func__); | 875 | dev_info(&intf->dev, "%s: Video unregistered.\n", __func__); |
874 | 876 | ||
875 | if (uvd->user) | 877 | if (uvd->user) |
876 | info("%s: In use, disconnect pending.", __func__); | 878 | dev_info(&intf->dev, "%s: In use, disconnect pending.\n", |
879 | __func__); | ||
877 | else | 880 | else |
878 | usbvideo_CameraRelease(uvd); | 881 | usbvideo_CameraRelease(uvd); |
879 | mutex_unlock(&uvd->lock); | 882 | mutex_unlock(&uvd->lock); |
880 | info("USB camera disconnected."); | 883 | dev_info(&intf->dev, "USB camera disconnected.\n"); |
881 | 884 | ||
882 | usbvideo_ClientDecModCount(uvd); | 885 | usbvideo_ClientDecModCount(uvd); |
883 | } | 886 | } |
@@ -1015,14 +1018,17 @@ int usbvideo_RegisterVideoDevice(struct uvd *uvd) | |||
1015 | return -EINVAL; | 1018 | return -EINVAL; |
1016 | } | 1019 | } |
1017 | if (uvd->video_endp == 0) { | 1020 | if (uvd->video_endp == 0) { |
1018 | info("%s: No video endpoint specified; data pump disabled.", __func__); | 1021 | dev_info(&uvd->dev->dev, |
1022 | "%s: No video endpoint specified; data pump disabled.\n", | ||
1023 | __func__); | ||
1019 | } | 1024 | } |
1020 | if (uvd->paletteBits == 0) { | 1025 | if (uvd->paletteBits == 0) { |
1021 | err("%s: No palettes specified!", __func__); | 1026 | err("%s: No palettes specified!", __func__); |
1022 | return -EINVAL; | 1027 | return -EINVAL; |
1023 | } | 1028 | } |
1024 | if (uvd->defaultPalette == 0) { | 1029 | if (uvd->defaultPalette == 0) { |
1025 | info("%s: No default palette!", __func__); | 1030 | dev_info(&uvd->dev->dev, "%s: No default palette!\n", |
1031 | __func__); | ||
1026 | } | 1032 | } |
1027 | 1033 | ||
1028 | uvd->max_frame_size = VIDEOSIZE_X(uvd->canvas) * | 1034 | uvd->max_frame_size = VIDEOSIZE_X(uvd->canvas) * |
@@ -1031,25 +1037,29 @@ int usbvideo_RegisterVideoDevice(struct uvd *uvd) | |||
1031 | usbvideo_VideosizeToString(tmp2, sizeof(tmp2), uvd->canvas); | 1037 | usbvideo_VideosizeToString(tmp2, sizeof(tmp2), uvd->canvas); |
1032 | 1038 | ||
1033 | if (uvd->debug > 0) { | 1039 | if (uvd->debug > 0) { |
1034 | info("%s: iface=%d. endpoint=$%02x paletteBits=$%08lx", | 1040 | dev_info(&uvd->dev->dev, |
1035 | __func__, uvd->iface, uvd->video_endp, uvd->paletteBits); | 1041 | "%s: iface=%d. endpoint=$%02x paletteBits=$%08lx\n", |
1042 | __func__, uvd->iface, uvd->video_endp, | ||
1043 | uvd->paletteBits); | ||
1036 | } | 1044 | } |
1037 | if (uvd->dev == NULL) { | 1045 | if (uvd->dev == NULL) { |
1038 | err("%s: uvd->dev == NULL", __func__); | 1046 | err("%s: uvd->dev == NULL", __func__); |
1039 | return -EINVAL; | 1047 | return -EINVAL; |
1040 | } | 1048 | } |
1041 | uvd->vdev.parent = &uvd->dev->dev; | 1049 | uvd->vdev.parent = &uvd->dev->dev; |
1042 | if (video_register_device(&uvd->vdev, VFL_TYPE_GRABBER, video_nr) == -1) { | 1050 | uvd->vdev.release = video_device_release_empty; |
1051 | if (video_register_device(&uvd->vdev, VFL_TYPE_GRABBER, video_nr) < 0) { | ||
1043 | err("%s: video_register_device failed", __func__); | 1052 | err("%s: video_register_device failed", __func__); |
1044 | return -EPIPE; | 1053 | return -EPIPE; |
1045 | } | 1054 | } |
1046 | if (uvd->debug > 1) { | 1055 | if (uvd->debug > 1) { |
1047 | info("%s: video_register_device() successful", __func__); | 1056 | dev_info(&uvd->dev->dev, |
1057 | "%s: video_register_device() successful\n", __func__); | ||
1048 | } | 1058 | } |
1049 | 1059 | ||
1050 | info("%s on /dev/video%d: canvas=%s videosize=%s", | 1060 | dev_info(&uvd->dev->dev, "%s on /dev/video%d: canvas=%s videosize=%s\n", |
1051 | (uvd->handle != NULL) ? uvd->handle->drvName : "???", | 1061 | (uvd->handle != NULL) ? uvd->handle->drvName : "???", |
1052 | uvd->vdev.minor, tmp2, tmp1); | 1062 | uvd->vdev.minor, tmp2, tmp1); |
1053 | 1063 | ||
1054 | usb_get_dev(uvd->dev); | 1064 | usb_get_dev(uvd->dev); |
1055 | return 0; | 1065 | return 0; |
@@ -1111,7 +1121,7 @@ static int usbvideo_v4l_open(struct inode *inode, struct file *file) | |||
1111 | int i, errCode = 0; | 1121 | int i, errCode = 0; |
1112 | 1122 | ||
1113 | if (uvd->debug > 1) | 1123 | if (uvd->debug > 1) |
1114 | info("%s($%p)", __func__, dev); | 1124 | dev_info(&uvd->dev->dev, "%s($%p)\n", __func__, dev); |
1115 | 1125 | ||
1116 | if (0 < usbvideo_ClientIncModCount(uvd)) | 1126 | if (0 < usbvideo_ClientIncModCount(uvd)) |
1117 | return -ENODEV; | 1127 | return -ENODEV; |
@@ -1178,19 +1188,25 @@ static int usbvideo_v4l_open(struct inode *inode, struct file *file) | |||
1178 | if (errCode == 0) { | 1188 | if (errCode == 0) { |
1179 | if (VALID_CALLBACK(uvd, setupOnOpen)) { | 1189 | if (VALID_CALLBACK(uvd, setupOnOpen)) { |
1180 | if (uvd->debug > 1) | 1190 | if (uvd->debug > 1) |
1181 | info("%s: setupOnOpen callback", __func__); | 1191 | dev_info(&uvd->dev->dev, |
1192 | "%s: setupOnOpen callback\n", | ||
1193 | __func__); | ||
1182 | errCode = GET_CALLBACK(uvd, setupOnOpen)(uvd); | 1194 | errCode = GET_CALLBACK(uvd, setupOnOpen)(uvd); |
1183 | if (errCode < 0) { | 1195 | if (errCode < 0) { |
1184 | err("%s: setupOnOpen callback failed (%d.).", | 1196 | err("%s: setupOnOpen callback failed (%d.).", |
1185 | __func__, errCode); | 1197 | __func__, errCode); |
1186 | } else if (uvd->debug > 1) { | 1198 | } else if (uvd->debug > 1) { |
1187 | info("%s: setupOnOpen callback successful", __func__); | 1199 | dev_info(&uvd->dev->dev, |
1200 | "%s: setupOnOpen callback successful\n", | ||
1201 | __func__); | ||
1188 | } | 1202 | } |
1189 | } | 1203 | } |
1190 | if (errCode == 0) { | 1204 | if (errCode == 0) { |
1191 | uvd->settingsAdjusted = 0; | 1205 | uvd->settingsAdjusted = 0; |
1192 | if (uvd->debug > 1) | 1206 | if (uvd->debug > 1) |
1193 | info("%s: Open succeeded.", __func__); | 1207 | dev_info(&uvd->dev->dev, |
1208 | "%s: Open succeeded.\n", | ||
1209 | __func__); | ||
1194 | uvd->user++; | 1210 | uvd->user++; |
1195 | file->private_data = uvd; | 1211 | file->private_data = uvd; |
1196 | } | 1212 | } |
@@ -1200,7 +1216,8 @@ static int usbvideo_v4l_open(struct inode *inode, struct file *file) | |||
1200 | if (errCode != 0) | 1216 | if (errCode != 0) |
1201 | usbvideo_ClientDecModCount(uvd); | 1217 | usbvideo_ClientDecModCount(uvd); |
1202 | if (uvd->debug > 0) | 1218 | if (uvd->debug > 0) |
1203 | info("%s: Returning %d.", __func__, errCode); | 1219 | dev_info(&uvd->dev->dev, "%s: Returning %d.\n", __func__, |
1220 | errCode); | ||
1204 | return errCode; | 1221 | return errCode; |
1205 | } | 1222 | } |
1206 | 1223 | ||
@@ -1223,7 +1240,7 @@ static int usbvideo_v4l_close(struct inode *inode, struct file *file) | |||
1223 | int i; | 1240 | int i; |
1224 | 1241 | ||
1225 | if (uvd->debug > 1) | 1242 | if (uvd->debug > 1) |
1226 | info("%s($%p)", __func__, dev); | 1243 | dev_info(&uvd->dev->dev, "%s($%p)\n", __func__, dev); |
1227 | 1244 | ||
1228 | mutex_lock(&uvd->lock); | 1245 | mutex_lock(&uvd->lock); |
1229 | GET_CALLBACK(uvd, stopDataPump)(uvd); | 1246 | GET_CALLBACK(uvd, stopDataPump)(uvd); |
@@ -1243,14 +1260,15 @@ static int usbvideo_v4l_close(struct inode *inode, struct file *file) | |||
1243 | uvd->user--; | 1260 | uvd->user--; |
1244 | if (uvd->remove_pending) { | 1261 | if (uvd->remove_pending) { |
1245 | if (uvd->debug > 0) | 1262 | if (uvd->debug > 0) |
1246 | info("usbvideo_v4l_close: Final disconnect."); | 1263 | dev_info(&uvd->dev->dev, "%s: Final disconnect.\n", |
1264 | __func__); | ||
1247 | usbvideo_CameraRelease(uvd); | 1265 | usbvideo_CameraRelease(uvd); |
1248 | } | 1266 | } |
1249 | mutex_unlock(&uvd->lock); | 1267 | mutex_unlock(&uvd->lock); |
1250 | usbvideo_ClientDecModCount(uvd); | 1268 | usbvideo_ClientDecModCount(uvd); |
1251 | 1269 | ||
1252 | if (uvd->debug > 1) | 1270 | if (uvd->debug > 1) |
1253 | info("%s: Completed.", __func__); | 1271 | dev_info(&uvd->dev->dev, "%s: Completed.\n", __func__); |
1254 | file->private_data = NULL; | 1272 | file->private_data = NULL; |
1255 | return 0; | 1273 | return 0; |
1256 | } | 1274 | } |
@@ -1364,8 +1382,9 @@ static int usbvideo_v4l_do_ioctl(struct inode *inode, struct file *file, | |||
1364 | struct video_mmap *vm = arg; | 1382 | struct video_mmap *vm = arg; |
1365 | 1383 | ||
1366 | if (uvd->debug >= 1) { | 1384 | if (uvd->debug >= 1) { |
1367 | info("VIDIOCMCAPTURE: frame=%d. size=%dx%d, format=%d.", | 1385 | dev_info(&uvd->dev->dev, |
1368 | vm->frame, vm->width, vm->height, vm->format); | 1386 | "VIDIOCMCAPTURE: frame=%d. size=%dx%d, format=%d.\n", |
1387 | vm->frame, vm->width, vm->height, vm->format); | ||
1369 | } | 1388 | } |
1370 | /* | 1389 | /* |
1371 | * Check if the requested size is supported. If the requestor | 1390 | * Check if the requested size is supported. If the requestor |
@@ -1383,18 +1402,24 @@ static int usbvideo_v4l_do_ioctl(struct inode *inode, struct file *file, | |||
1383 | if ((vm->width > VIDEOSIZE_X(uvd->canvas)) || | 1402 | if ((vm->width > VIDEOSIZE_X(uvd->canvas)) || |
1384 | (vm->height > VIDEOSIZE_Y(uvd->canvas))) { | 1403 | (vm->height > VIDEOSIZE_Y(uvd->canvas))) { |
1385 | if (uvd->debug > 0) { | 1404 | if (uvd->debug > 0) { |
1386 | info("VIDIOCMCAPTURE: Size=%dx%d too large; " | 1405 | dev_info(&uvd->dev->dev, |
1387 | "allowed only up to %ldx%ld", vm->width, vm->height, | 1406 | "VIDIOCMCAPTURE: Size=%dx%d " |
1388 | VIDEOSIZE_X(uvd->canvas), VIDEOSIZE_Y(uvd->canvas)); | 1407 | "too large; allowed only up " |
1408 | "to %ldx%ld\n", vm->width, | ||
1409 | vm->height, | ||
1410 | VIDEOSIZE_X(uvd->canvas), | ||
1411 | VIDEOSIZE_Y(uvd->canvas)); | ||
1389 | } | 1412 | } |
1390 | return -EINVAL; | 1413 | return -EINVAL; |
1391 | } | 1414 | } |
1392 | /* Check if the palette is supported */ | 1415 | /* Check if the palette is supported */ |
1393 | if (((1L << vm->format) & uvd->paletteBits) == 0) { | 1416 | if (((1L << vm->format) & uvd->paletteBits) == 0) { |
1394 | if (uvd->debug > 0) { | 1417 | if (uvd->debug > 0) { |
1395 | info("VIDIOCMCAPTURE: format=%d. not supported" | 1418 | dev_info(&uvd->dev->dev, |
1396 | " (paletteBits=$%08lx)", | 1419 | "VIDIOCMCAPTURE: format=%d. " |
1397 | vm->format, uvd->paletteBits); | 1420 | "not supported " |
1421 | "(paletteBits=$%08lx)\n", | ||
1422 | vm->format, uvd->paletteBits); | ||
1398 | } | 1423 | } |
1399 | return -EINVAL; | 1424 | return -EINVAL; |
1400 | } | 1425 | } |
@@ -1422,7 +1447,9 @@ static int usbvideo_v4l_do_ioctl(struct inode *inode, struct file *file, | |||
1422 | return -EINVAL; | 1447 | return -EINVAL; |
1423 | 1448 | ||
1424 | if (uvd->debug >= 1) | 1449 | if (uvd->debug >= 1) |
1425 | info("VIDIOCSYNC: syncing to frame %d.", *frameNum); | 1450 | dev_info(&uvd->dev->dev, |
1451 | "VIDIOCSYNC: syncing to frame %d.\n", | ||
1452 | *frameNum); | ||
1426 | if (uvd->flags & FLAGS_NO_DECODING) | 1453 | if (uvd->flags & FLAGS_NO_DECODING) |
1427 | ret = usbvideo_GetFrame(uvd, *frameNum); | 1454 | ret = usbvideo_GetFrame(uvd, *frameNum); |
1428 | else if (VALID_CALLBACK(uvd, getFrame)) { | 1455 | else if (VALID_CALLBACK(uvd, getFrame)) { |
@@ -1504,7 +1531,9 @@ static ssize_t usbvideo_v4l_read(struct file *file, char __user *buf, | |||
1504 | return -EFAULT; | 1531 | return -EFAULT; |
1505 | 1532 | ||
1506 | if (uvd->debug >= 1) | 1533 | if (uvd->debug >= 1) |
1507 | info("%s: %Zd. bytes, noblock=%d.", __func__, count, noblock); | 1534 | dev_info(&uvd->dev->dev, |
1535 | "%s: %Zd. bytes, noblock=%d.\n", | ||
1536 | __func__, count, noblock); | ||
1508 | 1537 | ||
1509 | mutex_lock(&uvd->lock); | 1538 | mutex_lock(&uvd->lock); |
1510 | 1539 | ||
@@ -1685,18 +1714,21 @@ static void usbvideo_IsocIrq(struct urb *urb) | |||
1685 | return; | 1714 | return; |
1686 | #if 0 | 1715 | #if 0 |
1687 | if (urb->actual_length > 0) { | 1716 | if (urb->actual_length > 0) { |
1688 | info("urb=$%p status=%d. errcount=%d. length=%d.", | 1717 | dev_info(&uvd->dev->dev, |
1689 | urb, urb->status, urb->error_count, urb->actual_length); | 1718 | "urb=$%p status=%d. errcount=%d. length=%d.\n", |
1719 | urb, urb->status, urb->error_count, | ||
1720 | urb->actual_length); | ||
1690 | } else { | 1721 | } else { |
1691 | static int c = 0; | 1722 | static int c = 0; |
1692 | if (c++ % 100 == 0) | 1723 | if (c++ % 100 == 0) |
1693 | info("No Isoc data"); | 1724 | dev_info(&uvd->dev->dev, "No Isoc data\n"); |
1694 | } | 1725 | } |
1695 | #endif | 1726 | #endif |
1696 | 1727 | ||
1697 | if (!uvd->streaming) { | 1728 | if (!uvd->streaming) { |
1698 | if (uvd->debug >= 1) | 1729 | if (uvd->debug >= 1) |
1699 | info("Not streaming, but interrupt!"); | 1730 | dev_info(&uvd->dev->dev, |
1731 | "Not streaming, but interrupt!\n"); | ||
1700 | return; | 1732 | return; |
1701 | } | 1733 | } |
1702 | 1734 | ||
@@ -1741,7 +1773,7 @@ static int usbvideo_StartDataPump(struct uvd *uvd) | |||
1741 | int i, errFlag; | 1773 | int i, errFlag; |
1742 | 1774 | ||
1743 | if (uvd->debug > 1) | 1775 | if (uvd->debug > 1) |
1744 | info("%s($%p)", __func__, uvd); | 1776 | dev_info(&uvd->dev->dev, "%s($%p)\n", __func__, uvd); |
1745 | 1777 | ||
1746 | if (!CAMERA_IS_OPERATIONAL(uvd)) { | 1778 | if (!CAMERA_IS_OPERATIONAL(uvd)) { |
1747 | err("%s: Camera is not operational", __func__); | 1779 | err("%s: Camera is not operational", __func__); |
@@ -1789,7 +1821,9 @@ static int usbvideo_StartDataPump(struct uvd *uvd) | |||
1789 | 1821 | ||
1790 | uvd->streaming = 1; | 1822 | uvd->streaming = 1; |
1791 | if (uvd->debug > 1) | 1823 | if (uvd->debug > 1) |
1792 | info("%s: streaming=1 video_endp=$%02x", __func__, uvd->video_endp); | 1824 | dev_info(&uvd->dev->dev, |
1825 | "%s: streaming=1 video_endp=$%02x\n", __func__, | ||
1826 | uvd->video_endp); | ||
1793 | return 0; | 1827 | return 0; |
1794 | } | 1828 | } |
1795 | 1829 | ||
@@ -1811,14 +1845,14 @@ static void usbvideo_StopDataPump(struct uvd *uvd) | |||
1811 | return; | 1845 | return; |
1812 | 1846 | ||
1813 | if (uvd->debug > 1) | 1847 | if (uvd->debug > 1) |
1814 | info("%s($%p)", __func__, uvd); | 1848 | dev_info(&uvd->dev->dev, "%s($%p)\n", __func__, uvd); |
1815 | 1849 | ||
1816 | /* Unschedule all of the iso td's */ | 1850 | /* Unschedule all of the iso td's */ |
1817 | for (i=0; i < USBVIDEO_NUMSBUF; i++) { | 1851 | for (i=0; i < USBVIDEO_NUMSBUF; i++) { |
1818 | usb_kill_urb(uvd->sbuf[i].urb); | 1852 | usb_kill_urb(uvd->sbuf[i].urb); |
1819 | } | 1853 | } |
1820 | if (uvd->debug > 1) | 1854 | if (uvd->debug > 1) |
1821 | info("%s: streaming=0", __func__); | 1855 | dev_info(&uvd->dev->dev, "%s: streaming=0\n", __func__); |
1822 | uvd->streaming = 0; | 1856 | uvd->streaming = 0; |
1823 | 1857 | ||
1824 | if (!uvd->remove_pending) { | 1858 | if (!uvd->remove_pending) { |
@@ -1850,7 +1884,8 @@ static int usbvideo_NewFrame(struct uvd *uvd, int framenum) | |||
1850 | int n; | 1884 | int n; |
1851 | 1885 | ||
1852 | if (uvd->debug > 1) | 1886 | if (uvd->debug > 1) |
1853 | info("usbvideo_NewFrame($%p,%d.)", uvd, framenum); | 1887 | dev_info(&uvd->dev->dev, "usbvideo_NewFrame($%p,%d.)\n", uvd, |
1888 | framenum); | ||
1854 | 1889 | ||
1855 | /* If we're not grabbing a frame right now and the other frame is */ | 1890 | /* If we're not grabbing a frame right now and the other frame is */ |
1856 | /* ready to be grabbed into, then use it instead */ | 1891 | /* ready to be grabbed into, then use it instead */ |
@@ -1955,12 +1990,14 @@ static int usbvideo_GetFrame(struct uvd *uvd, int frameNum) | |||
1955 | struct usbvideo_frame *frame = &uvd->frame[frameNum]; | 1990 | struct usbvideo_frame *frame = &uvd->frame[frameNum]; |
1956 | 1991 | ||
1957 | if (uvd->debug >= 2) | 1992 | if (uvd->debug >= 2) |
1958 | info("%s($%p,%d.)", __func__, uvd, frameNum); | 1993 | dev_info(&uvd->dev->dev, "%s($%p,%d.)\n", __func__, uvd, |
1994 | frameNum); | ||
1959 | 1995 | ||
1960 | switch (frame->frameState) { | 1996 | switch (frame->frameState) { |
1961 | case FrameState_Unused: | 1997 | case FrameState_Unused: |
1962 | if (uvd->debug >= 2) | 1998 | if (uvd->debug >= 2) |
1963 | info("%s: FrameState_Unused", __func__); | 1999 | dev_info(&uvd->dev->dev, "%s: FrameState_Unused\n", |
2000 | __func__); | ||
1964 | return -EINVAL; | 2001 | return -EINVAL; |
1965 | case FrameState_Ready: | 2002 | case FrameState_Ready: |
1966 | case FrameState_Grabbing: | 2003 | case FrameState_Grabbing: |
@@ -1970,7 +2007,9 @@ static int usbvideo_GetFrame(struct uvd *uvd, int frameNum) | |||
1970 | redo: | 2007 | redo: |
1971 | if (!CAMERA_IS_OPERATIONAL(uvd)) { | 2008 | if (!CAMERA_IS_OPERATIONAL(uvd)) { |
1972 | if (uvd->debug >= 2) | 2009 | if (uvd->debug >= 2) |
1973 | info("%s: Camera is not operational (1)", __func__); | 2010 | dev_info(&uvd->dev->dev, |
2011 | "%s: Camera is not operational (1)\n", | ||
2012 | __func__); | ||
1974 | return -EIO; | 2013 | return -EIO; |
1975 | } | 2014 | } |
1976 | ntries = 0; | 2015 | ntries = 0; |
@@ -1979,24 +2018,33 @@ static int usbvideo_GetFrame(struct uvd *uvd, int frameNum) | |||
1979 | signalPending = signal_pending(current); | 2018 | signalPending = signal_pending(current); |
1980 | if (!CAMERA_IS_OPERATIONAL(uvd)) { | 2019 | if (!CAMERA_IS_OPERATIONAL(uvd)) { |
1981 | if (uvd->debug >= 2) | 2020 | if (uvd->debug >= 2) |
1982 | info("%s: Camera is not operational (2)", __func__); | 2021 | dev_info(&uvd->dev->dev, |
2022 | "%s: Camera is not " | ||
2023 | "operational (2)\n", __func__); | ||
1983 | return -EIO; | 2024 | return -EIO; |
1984 | } | 2025 | } |
1985 | assert(uvd->fbuf != NULL); | 2026 | assert(uvd->fbuf != NULL); |
1986 | if (signalPending) { | 2027 | if (signalPending) { |
1987 | if (uvd->debug >= 2) | 2028 | if (uvd->debug >= 2) |
1988 | info("%s: Signal=$%08x", __func__, signalPending); | 2029 | dev_info(&uvd->dev->dev, |
2030 | "%s: Signal=$%08x\n", __func__, | ||
2031 | signalPending); | ||
1989 | if (uvd->flags & FLAGS_RETRY_VIDIOCSYNC) { | 2032 | if (uvd->flags & FLAGS_RETRY_VIDIOCSYNC) { |
1990 | usbvideo_TestPattern(uvd, 1, 0); | 2033 | usbvideo_TestPattern(uvd, 1, 0); |
1991 | uvd->curframe = -1; | 2034 | uvd->curframe = -1; |
1992 | uvd->stats.frame_num++; | 2035 | uvd->stats.frame_num++; |
1993 | if (uvd->debug >= 2) | 2036 | if (uvd->debug >= 2) |
1994 | info("%s: Forced test pattern screen", __func__); | 2037 | dev_info(&uvd->dev->dev, |
2038 | "%s: Forced test " | ||
2039 | "pattern screen\n", | ||
2040 | __func__); | ||
1995 | return 0; | 2041 | return 0; |
1996 | } else { | 2042 | } else { |
1997 | /* Standard answer: Interrupted! */ | 2043 | /* Standard answer: Interrupted! */ |
1998 | if (uvd->debug >= 2) | 2044 | if (uvd->debug >= 2) |
1999 | info("%s: Interrupted!", __func__); | 2045 | dev_info(&uvd->dev->dev, |
2046 | "%s: Interrupted!\n", | ||
2047 | __func__); | ||
2000 | return -EINTR; | 2048 | return -EINTR; |
2001 | } | 2049 | } |
2002 | } else { | 2050 | } else { |
@@ -2010,8 +2058,10 @@ static int usbvideo_GetFrame(struct uvd *uvd, int frameNum) | |||
2010 | } | 2058 | } |
2011 | } while (frame->frameState == FrameState_Grabbing); | 2059 | } while (frame->frameState == FrameState_Grabbing); |
2012 | if (uvd->debug >= 2) { | 2060 | if (uvd->debug >= 2) { |
2013 | info("%s: Grabbing done; state=%d. (%lu. bytes)", | 2061 | dev_info(&uvd->dev->dev, |
2014 | __func__, frame->frameState, frame->seqRead_Length); | 2062 | "%s: Grabbing done; state=%d. (%lu. bytes)\n", |
2063 | __func__, frame->frameState, | ||
2064 | frame->seqRead_Length); | ||
2015 | } | 2065 | } |
2016 | if (frame->frameState == FrameState_Error) { | 2066 | if (frame->frameState == FrameState_Error) { |
2017 | int ret = usbvideo_NewFrame(uvd, frameNum); | 2067 | int ret = usbvideo_NewFrame(uvd, frameNum); |
@@ -2048,7 +2098,9 @@ static int usbvideo_GetFrame(struct uvd *uvd, int frameNum) | |||
2048 | } | 2098 | } |
2049 | frame->frameState = FrameState_Done_Hold; | 2099 | frame->frameState = FrameState_Done_Hold; |
2050 | if (uvd->debug >= 2) | 2100 | if (uvd->debug >= 2) |
2051 | info("%s: Entered FrameState_Done_Hold state.", __func__); | 2101 | dev_info(&uvd->dev->dev, |
2102 | "%s: Entered FrameState_Done_Hold state.\n", | ||
2103 | __func__); | ||
2052 | return 0; | 2104 | return 0; |
2053 | 2105 | ||
2054 | case FrameState_Done_Hold: | 2106 | case FrameState_Done_Hold: |
@@ -2059,7 +2111,9 @@ static int usbvideo_GetFrame(struct uvd *uvd, int frameNum) | |||
2059 | * it will be released back into the wild to roam freely. | 2111 | * it will be released back into the wild to roam freely. |
2060 | */ | 2112 | */ |
2061 | if (uvd->debug >= 2) | 2113 | if (uvd->debug >= 2) |
2062 | info("%s: FrameState_Done_Hold state.", __func__); | 2114 | dev_info(&uvd->dev->dev, |
2115 | "%s: FrameState_Done_Hold state.\n", | ||
2116 | __func__); | ||
2063 | return 0; | 2117 | return 0; |
2064 | } | 2118 | } |
2065 | 2119 | ||
diff --git a/drivers/media/video/usbvideo/vicam.c b/drivers/media/video/usbvideo/vicam.c index 2eb45829791c..7a127d6bfdee 100644 --- a/drivers/media/video/usbvideo/vicam.c +++ b/drivers/media/video/usbvideo/vicam.c | |||
@@ -472,9 +472,8 @@ vicam_ioctl(struct inode *inode, struct file *file, unsigned int ioctlnr, unsign | |||
472 | static int | 472 | static int |
473 | vicam_open(struct inode *inode, struct file *file) | 473 | vicam_open(struct inode *inode, struct file *file) |
474 | { | 474 | { |
475 | struct video_device *dev = video_devdata(file); | 475 | struct vicam_camera *cam = video_drvdata(file); |
476 | struct vicam_camera *cam = | 476 | |
477 | (struct vicam_camera *) dev->priv; | ||
478 | DBG("open\n"); | 477 | DBG("open\n"); |
479 | 478 | ||
480 | if (!cam) { | 479 | if (!cam) { |
@@ -488,20 +487,24 @@ vicam_open(struct inode *inode, struct file *file) | |||
488 | * rely on this fact forever. | 487 | * rely on this fact forever. |
489 | */ | 488 | */ |
490 | 489 | ||
490 | lock_kernel(); | ||
491 | if (cam->open_count > 0) { | 491 | if (cam->open_count > 0) { |
492 | printk(KERN_INFO | 492 | printk(KERN_INFO |
493 | "vicam_open called on already opened camera"); | 493 | "vicam_open called on already opened camera"); |
494 | unlock_kernel(); | ||
494 | return -EBUSY; | 495 | return -EBUSY; |
495 | } | 496 | } |
496 | 497 | ||
497 | cam->raw_image = kmalloc(VICAM_MAX_READ_SIZE, GFP_KERNEL); | 498 | cam->raw_image = kmalloc(VICAM_MAX_READ_SIZE, GFP_KERNEL); |
498 | if (!cam->raw_image) { | 499 | if (!cam->raw_image) { |
500 | unlock_kernel(); | ||
499 | return -ENOMEM; | 501 | return -ENOMEM; |
500 | } | 502 | } |
501 | 503 | ||
502 | cam->framebuf = rvmalloc(VICAM_MAX_FRAME_SIZE * VICAM_FRAMES); | 504 | cam->framebuf = rvmalloc(VICAM_MAX_FRAME_SIZE * VICAM_FRAMES); |
503 | if (!cam->framebuf) { | 505 | if (!cam->framebuf) { |
504 | kfree(cam->raw_image); | 506 | kfree(cam->raw_image); |
507 | unlock_kernel(); | ||
505 | return -ENOMEM; | 508 | return -ENOMEM; |
506 | } | 509 | } |
507 | 510 | ||
@@ -509,6 +512,7 @@ vicam_open(struct inode *inode, struct file *file) | |||
509 | if (!cam->cntrlbuf) { | 512 | if (!cam->cntrlbuf) { |
510 | kfree(cam->raw_image); | 513 | kfree(cam->raw_image); |
511 | rvfree(cam->framebuf, VICAM_MAX_FRAME_SIZE * VICAM_FRAMES); | 514 | rvfree(cam->framebuf, VICAM_MAX_FRAME_SIZE * VICAM_FRAMES); |
515 | unlock_kernel(); | ||
512 | return -ENOMEM; | 516 | return -ENOMEM; |
513 | } | 517 | } |
514 | 518 | ||
@@ -526,6 +530,7 @@ vicam_open(struct inode *inode, struct file *file) | |||
526 | cam->open_count++; | 530 | cam->open_count++; |
527 | 531 | ||
528 | file->private_data = cam; | 532 | file->private_data = cam; |
533 | unlock_kernel(); | ||
529 | 534 | ||
530 | return 0; | 535 | return 0; |
531 | } | 536 | } |
@@ -795,6 +800,7 @@ static struct video_device vicam_template = { | |||
795 | .name = "ViCam-based USB Camera", | 800 | .name = "ViCam-based USB Camera", |
796 | .fops = &vicam_fops, | 801 | .fops = &vicam_fops, |
797 | .minor = -1, | 802 | .minor = -1, |
803 | .release = video_device_release_empty, | ||
798 | }; | 804 | }; |
799 | 805 | ||
800 | /* table of devices that work with this driver */ | 806 | /* table of devices that work with this driver */ |
@@ -859,9 +865,8 @@ vicam_probe( struct usb_interface *intf, const struct usb_device_id *id) | |||
859 | 865 | ||
860 | mutex_init(&cam->cam_lock); | 866 | mutex_init(&cam->cam_lock); |
861 | 867 | ||
862 | memcpy(&cam->vdev, &vicam_template, | 868 | memcpy(&cam->vdev, &vicam_template, sizeof(vicam_template)); |
863 | sizeof (vicam_template)); | 869 | video_set_drvdata(&cam->vdev, cam); |
864 | cam->vdev.priv = cam; // sort of a reverse mapping for those functions that get vdev only | ||
865 | 870 | ||
866 | cam->udev = dev; | 871 | cam->udev = dev; |
867 | cam->bulkEndpoint = bulkEndpoint; | 872 | cam->bulkEndpoint = bulkEndpoint; |
diff --git a/drivers/media/video/usbvision/usbvision-core.c b/drivers/media/video/usbvision/usbvision-core.c index c317ed7a8482..b26b563a0b0a 100644 --- a/drivers/media/video/usbvision/usbvision-core.c +++ b/drivers/media/video/usbvision/usbvision-core.c | |||
@@ -84,7 +84,8 @@ MODULE_PARM_DESC(adjust_Y_Offset, "adjust Y offset display [core]"); | |||
84 | #ifdef USBVISION_DEBUG | 84 | #ifdef USBVISION_DEBUG |
85 | #define PDEBUG(level, fmt, args...) { \ | 85 | #define PDEBUG(level, fmt, args...) { \ |
86 | if (core_debug & (level)) \ | 86 | if (core_debug & (level)) \ |
87 | info("[%s:%d] " fmt, __func__, __LINE__ , ## args); \ | 87 | printk(KERN_INFO KBUILD_MODNAME ":[%s:%d] " fmt, \ |
88 | __func__, __LINE__ , ## args); \ | ||
88 | } | 89 | } |
89 | #else | 90 | #else |
90 | #define PDEBUG(level, fmt, args...) do {} while(0) | 91 | #define PDEBUG(level, fmt, args...) do {} while(0) |
diff --git a/drivers/media/video/usbvision/usbvision-i2c.c b/drivers/media/video/usbvision/usbvision-i2c.c index a6d00858b07e..92427fdc1459 100644 --- a/drivers/media/video/usbvision/usbvision-i2c.c +++ b/drivers/media/video/usbvision/usbvision-i2c.c | |||
@@ -47,7 +47,8 @@ MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]"); | |||
47 | 47 | ||
48 | #define PDEBUG(level, fmt, args...) { \ | 48 | #define PDEBUG(level, fmt, args...) { \ |
49 | if (i2c_debug & (level)) \ | 49 | if (i2c_debug & (level)) \ |
50 | info("[%s:%d] " fmt, __func__, __LINE__ , ## args); \ | 50 | printk(KERN_INFO KBUILD_MODNAME ":[%s:%d] " fmt, \ |
51 | __func__, __LINE__ , ## args); \ | ||
51 | } | 52 | } |
52 | 53 | ||
53 | static int usbvision_i2c_write(struct usb_usbvision *usbvision, unsigned char addr, char *buf, | 54 | static int usbvision_i2c_write(struct usb_usbvision *usbvision, unsigned char addr, char *buf, |
diff --git a/drivers/media/video/usbvision/usbvision-video.c b/drivers/media/video/usbvision/usbvision-video.c index b977116a0dd9..e10b256aeba4 100644 --- a/drivers/media/video/usbvision/usbvision-video.c +++ b/drivers/media/video/usbvision/usbvision-video.c | |||
@@ -98,7 +98,8 @@ USBVISION_DRIVER_VERSION_PATCHLEVEL) | |||
98 | #ifdef USBVISION_DEBUG | 98 | #ifdef USBVISION_DEBUG |
99 | #define PDEBUG(level, fmt, args...) { \ | 99 | #define PDEBUG(level, fmt, args...) { \ |
100 | if (video_debug & (level)) \ | 100 | if (video_debug & (level)) \ |
101 | info("[%s:%d] " fmt, __func__, __LINE__ , ## args); \ | 101 | printk(KERN_INFO KBUILD_MODNAME ":[%s:%d] " fmt, \ |
102 | __func__, __LINE__ , ## args); \ | ||
102 | } | 103 | } |
103 | #else | 104 | #else |
104 | #define PDEBUG(level, fmt, args...) do {} while(0) | 105 | #define PDEBUG(level, fmt, args...) do {} while(0) |
@@ -360,13 +361,12 @@ static void usbvision_remove_sysfs(struct video_device *vdev) | |||
360 | */ | 361 | */ |
361 | static int usbvision_v4l2_open(struct inode *inode, struct file *file) | 362 | static int usbvision_v4l2_open(struct inode *inode, struct file *file) |
362 | { | 363 | { |
363 | struct video_device *dev = video_devdata(file); | 364 | struct usb_usbvision *usbvision = video_drvdata(file); |
364 | struct usb_usbvision *usbvision = | ||
365 | (struct usb_usbvision *) video_get_drvdata(dev); | ||
366 | int errCode = 0; | 365 | int errCode = 0; |
367 | 366 | ||
368 | PDEBUG(DBG_IO, "open"); | 367 | PDEBUG(DBG_IO, "open"); |
369 | 368 | ||
369 | lock_kernel(); | ||
370 | usbvision_reset_powerOffTimer(usbvision); | 370 | usbvision_reset_powerOffTimer(usbvision); |
371 | 371 | ||
372 | if (usbvision->user) | 372 | if (usbvision->user) |
@@ -424,6 +424,7 @@ static int usbvision_v4l2_open(struct inode *inode, struct file *file) | |||
424 | usbvision_empty_framequeues(usbvision); | 424 | usbvision_empty_framequeues(usbvision); |
425 | 425 | ||
426 | PDEBUG(DBG_IO, "success"); | 426 | PDEBUG(DBG_IO, "success"); |
427 | unlock_kernel(); | ||
427 | return errCode; | 428 | return errCode; |
428 | } | 429 | } |
429 | 430 | ||
@@ -437,9 +438,7 @@ static int usbvision_v4l2_open(struct inode *inode, struct file *file) | |||
437 | */ | 438 | */ |
438 | static int usbvision_v4l2_close(struct inode *inode, struct file *file) | 439 | static int usbvision_v4l2_close(struct inode *inode, struct file *file) |
439 | { | 440 | { |
440 | struct video_device *dev = video_devdata(file); | 441 | struct usb_usbvision *usbvision = video_drvdata(file); |
441 | struct usb_usbvision *usbvision = | ||
442 | (struct usb_usbvision *) video_get_drvdata(dev); | ||
443 | 442 | ||
444 | PDEBUG(DBG_IO, "close"); | 443 | PDEBUG(DBG_IO, "close"); |
445 | mutex_lock(&usbvision->lock); | 444 | mutex_lock(&usbvision->lock); |
@@ -484,9 +483,7 @@ static int usbvision_v4l2_close(struct inode *inode, struct file *file) | |||
484 | static int vidioc_g_register (struct file *file, void *priv, | 483 | static int vidioc_g_register (struct file *file, void *priv, |
485 | struct v4l2_register *reg) | 484 | struct v4l2_register *reg) |
486 | { | 485 | { |
487 | struct video_device *dev = video_devdata(file); | 486 | struct usb_usbvision *usbvision = video_drvdata(file); |
488 | struct usb_usbvision *usbvision = | ||
489 | (struct usb_usbvision *) video_get_drvdata(dev); | ||
490 | int errCode; | 487 | int errCode; |
491 | 488 | ||
492 | if (!v4l2_chip_match_host(reg->match_type, reg->match_chip)) | 489 | if (!v4l2_chip_match_host(reg->match_type, reg->match_chip)) |
@@ -505,9 +502,7 @@ static int vidioc_g_register (struct file *file, void *priv, | |||
505 | static int vidioc_s_register (struct file *file, void *priv, | 502 | static int vidioc_s_register (struct file *file, void *priv, |
506 | struct v4l2_register *reg) | 503 | struct v4l2_register *reg) |
507 | { | 504 | { |
508 | struct video_device *dev = video_devdata(file); | 505 | struct usb_usbvision *usbvision = video_drvdata(file); |
509 | struct usb_usbvision *usbvision = | ||
510 | (struct usb_usbvision *) video_get_drvdata(dev); | ||
511 | int errCode; | 506 | int errCode; |
512 | 507 | ||
513 | if (!v4l2_chip_match_host(reg->match_type, reg->match_chip)) | 508 | if (!v4l2_chip_match_host(reg->match_type, reg->match_chip)) |
@@ -526,9 +521,7 @@ static int vidioc_s_register (struct file *file, void *priv, | |||
526 | static int vidioc_querycap (struct file *file, void *priv, | 521 | static int vidioc_querycap (struct file *file, void *priv, |
527 | struct v4l2_capability *vc) | 522 | struct v4l2_capability *vc) |
528 | { | 523 | { |
529 | struct video_device *dev = video_devdata(file); | 524 | struct usb_usbvision *usbvision = video_drvdata(file); |
530 | struct usb_usbvision *usbvision = | ||
531 | (struct usb_usbvision *) video_get_drvdata(dev); | ||
532 | 525 | ||
533 | strlcpy(vc->driver, "USBVision", sizeof(vc->driver)); | 526 | strlcpy(vc->driver, "USBVision", sizeof(vc->driver)); |
534 | strlcpy(vc->card, | 527 | strlcpy(vc->card, |
@@ -548,9 +541,7 @@ static int vidioc_querycap (struct file *file, void *priv, | |||
548 | static int vidioc_enum_input (struct file *file, void *priv, | 541 | static int vidioc_enum_input (struct file *file, void *priv, |
549 | struct v4l2_input *vi) | 542 | struct v4l2_input *vi) |
550 | { | 543 | { |
551 | struct video_device *dev = video_devdata(file); | 544 | struct usb_usbvision *usbvision = video_drvdata(file); |
552 | struct usb_usbvision *usbvision = | ||
553 | (struct usb_usbvision *) video_get_drvdata(dev); | ||
554 | int chan; | 545 | int chan; |
555 | 546 | ||
556 | if ((vi->index >= usbvision->video_inputs) || (vi->index < 0) ) | 547 | if ((vi->index >= usbvision->video_inputs) || (vi->index < 0) ) |
@@ -603,9 +594,7 @@ static int vidioc_enum_input (struct file *file, void *priv, | |||
603 | 594 | ||
604 | static int vidioc_g_input (struct file *file, void *priv, unsigned int *input) | 595 | static int vidioc_g_input (struct file *file, void *priv, unsigned int *input) |
605 | { | 596 | { |
606 | struct video_device *dev = video_devdata(file); | 597 | struct usb_usbvision *usbvision = video_drvdata(file); |
607 | struct usb_usbvision *usbvision = | ||
608 | (struct usb_usbvision *) video_get_drvdata(dev); | ||
609 | 598 | ||
610 | *input = usbvision->ctl_input; | 599 | *input = usbvision->ctl_input; |
611 | return 0; | 600 | return 0; |
@@ -613,9 +602,7 @@ static int vidioc_g_input (struct file *file, void *priv, unsigned int *input) | |||
613 | 602 | ||
614 | static int vidioc_s_input (struct file *file, void *priv, unsigned int input) | 603 | static int vidioc_s_input (struct file *file, void *priv, unsigned int input) |
615 | { | 604 | { |
616 | struct video_device *dev = video_devdata(file); | 605 | struct usb_usbvision *usbvision = video_drvdata(file); |
617 | struct usb_usbvision *usbvision = | ||
618 | (struct usb_usbvision *) video_get_drvdata(dev); | ||
619 | 606 | ||
620 | if ((input >= usbvision->video_inputs) || (input < 0) ) | 607 | if ((input >= usbvision->video_inputs) || (input < 0) ) |
621 | return -EINVAL; | 608 | return -EINVAL; |
@@ -632,9 +619,8 @@ static int vidioc_s_input (struct file *file, void *priv, unsigned int input) | |||
632 | 619 | ||
633 | static int vidioc_s_std (struct file *file, void *priv, v4l2_std_id *id) | 620 | static int vidioc_s_std (struct file *file, void *priv, v4l2_std_id *id) |
634 | { | 621 | { |
635 | struct video_device *dev = video_devdata(file); | 622 | struct usb_usbvision *usbvision = video_drvdata(file); |
636 | struct usb_usbvision *usbvision = | 623 | |
637 | (struct usb_usbvision *) video_get_drvdata(dev); | ||
638 | usbvision->tvnormId=*id; | 624 | usbvision->tvnormId=*id; |
639 | 625 | ||
640 | mutex_lock(&usbvision->lock); | 626 | mutex_lock(&usbvision->lock); |
@@ -650,9 +636,7 @@ static int vidioc_s_std (struct file *file, void *priv, v4l2_std_id *id) | |||
650 | static int vidioc_g_tuner (struct file *file, void *priv, | 636 | static int vidioc_g_tuner (struct file *file, void *priv, |
651 | struct v4l2_tuner *vt) | 637 | struct v4l2_tuner *vt) |
652 | { | 638 | { |
653 | struct video_device *dev = video_devdata(file); | 639 | struct usb_usbvision *usbvision = video_drvdata(file); |
654 | struct usb_usbvision *usbvision = | ||
655 | (struct usb_usbvision *) video_get_drvdata(dev); | ||
656 | 640 | ||
657 | if (!usbvision->have_tuner || vt->index) // Only tuner 0 | 641 | if (!usbvision->have_tuner || vt->index) // Only tuner 0 |
658 | return -EINVAL; | 642 | return -EINVAL; |
@@ -671,9 +655,7 @@ static int vidioc_g_tuner (struct file *file, void *priv, | |||
671 | static int vidioc_s_tuner (struct file *file, void *priv, | 655 | static int vidioc_s_tuner (struct file *file, void *priv, |
672 | struct v4l2_tuner *vt) | 656 | struct v4l2_tuner *vt) |
673 | { | 657 | { |
674 | struct video_device *dev = video_devdata(file); | 658 | struct usb_usbvision *usbvision = video_drvdata(file); |
675 | struct usb_usbvision *usbvision = | ||
676 | (struct usb_usbvision *) video_get_drvdata(dev); | ||
677 | 659 | ||
678 | // Only no or one tuner for now | 660 | // Only no or one tuner for now |
679 | if (!usbvision->have_tuner || vt->index) | 661 | if (!usbvision->have_tuner || vt->index) |
@@ -687,9 +669,7 @@ static int vidioc_s_tuner (struct file *file, void *priv, | |||
687 | static int vidioc_g_frequency (struct file *file, void *priv, | 669 | static int vidioc_g_frequency (struct file *file, void *priv, |
688 | struct v4l2_frequency *freq) | 670 | struct v4l2_frequency *freq) |
689 | { | 671 | { |
690 | struct video_device *dev = video_devdata(file); | 672 | struct usb_usbvision *usbvision = video_drvdata(file); |
691 | struct usb_usbvision *usbvision = | ||
692 | (struct usb_usbvision *) video_get_drvdata(dev); | ||
693 | 673 | ||
694 | freq->tuner = 0; // Only one tuner | 674 | freq->tuner = 0; // Only one tuner |
695 | if(usbvision->radio) { | 675 | if(usbvision->radio) { |
@@ -705,9 +685,7 @@ static int vidioc_g_frequency (struct file *file, void *priv, | |||
705 | static int vidioc_s_frequency (struct file *file, void *priv, | 685 | static int vidioc_s_frequency (struct file *file, void *priv, |
706 | struct v4l2_frequency *freq) | 686 | struct v4l2_frequency *freq) |
707 | { | 687 | { |
708 | struct video_device *dev = video_devdata(file); | 688 | struct usb_usbvision *usbvision = video_drvdata(file); |
709 | struct usb_usbvision *usbvision = | ||
710 | (struct usb_usbvision *) video_get_drvdata(dev); | ||
711 | 689 | ||
712 | // Only no or one tuner for now | 690 | // Only no or one tuner for now |
713 | if (!usbvision->have_tuner || freq->tuner) | 691 | if (!usbvision->have_tuner || freq->tuner) |
@@ -721,9 +699,7 @@ static int vidioc_s_frequency (struct file *file, void *priv, | |||
721 | 699 | ||
722 | static int vidioc_g_audio (struct file *file, void *priv, struct v4l2_audio *a) | 700 | static int vidioc_g_audio (struct file *file, void *priv, struct v4l2_audio *a) |
723 | { | 701 | { |
724 | struct video_device *dev = video_devdata(file); | 702 | struct usb_usbvision *usbvision = video_drvdata(file); |
725 | struct usb_usbvision *usbvision = | ||
726 | (struct usb_usbvision *) video_get_drvdata(dev); | ||
727 | 703 | ||
728 | memset(a,0,sizeof(*a)); | 704 | memset(a,0,sizeof(*a)); |
729 | if(usbvision->radio) { | 705 | if(usbvision->radio) { |
@@ -748,9 +724,7 @@ static int vidioc_s_audio (struct file *file, void *fh, | |||
748 | static int vidioc_queryctrl (struct file *file, void *priv, | 724 | static int vidioc_queryctrl (struct file *file, void *priv, |
749 | struct v4l2_queryctrl *ctrl) | 725 | struct v4l2_queryctrl *ctrl) |
750 | { | 726 | { |
751 | struct video_device *dev = video_devdata(file); | 727 | struct usb_usbvision *usbvision = video_drvdata(file); |
752 | struct usb_usbvision *usbvision = | ||
753 | (struct usb_usbvision *) video_get_drvdata(dev); | ||
754 | int id=ctrl->id; | 728 | int id=ctrl->id; |
755 | 729 | ||
756 | memset(ctrl,0,sizeof(*ctrl)); | 730 | memset(ctrl,0,sizeof(*ctrl)); |
@@ -767,9 +741,7 @@ static int vidioc_queryctrl (struct file *file, void *priv, | |||
767 | static int vidioc_g_ctrl (struct file *file, void *priv, | 741 | static int vidioc_g_ctrl (struct file *file, void *priv, |
768 | struct v4l2_control *ctrl) | 742 | struct v4l2_control *ctrl) |
769 | { | 743 | { |
770 | struct video_device *dev = video_devdata(file); | 744 | struct usb_usbvision *usbvision = video_drvdata(file); |
771 | struct usb_usbvision *usbvision = | ||
772 | (struct usb_usbvision *) video_get_drvdata(dev); | ||
773 | call_i2c_clients(usbvision, VIDIOC_G_CTRL, ctrl); | 745 | call_i2c_clients(usbvision, VIDIOC_G_CTRL, ctrl); |
774 | 746 | ||
775 | return 0; | 747 | return 0; |
@@ -778,9 +750,7 @@ static int vidioc_g_ctrl (struct file *file, void *priv, | |||
778 | static int vidioc_s_ctrl (struct file *file, void *priv, | 750 | static int vidioc_s_ctrl (struct file *file, void *priv, |
779 | struct v4l2_control *ctrl) | 751 | struct v4l2_control *ctrl) |
780 | { | 752 | { |
781 | struct video_device *dev = video_devdata(file); | 753 | struct usb_usbvision *usbvision = video_drvdata(file); |
782 | struct usb_usbvision *usbvision = | ||
783 | (struct usb_usbvision *) video_get_drvdata(dev); | ||
784 | call_i2c_clients(usbvision, VIDIOC_S_CTRL, ctrl); | 754 | call_i2c_clients(usbvision, VIDIOC_S_CTRL, ctrl); |
785 | 755 | ||
786 | return 0; | 756 | return 0; |
@@ -789,9 +759,7 @@ static int vidioc_s_ctrl (struct file *file, void *priv, | |||
789 | static int vidioc_reqbufs (struct file *file, | 759 | static int vidioc_reqbufs (struct file *file, |
790 | void *priv, struct v4l2_requestbuffers *vr) | 760 | void *priv, struct v4l2_requestbuffers *vr) |
791 | { | 761 | { |
792 | struct video_device *dev = video_devdata(file); | 762 | struct usb_usbvision *usbvision = video_drvdata(file); |
793 | struct usb_usbvision *usbvision = | ||
794 | (struct usb_usbvision *) video_get_drvdata(dev); | ||
795 | int ret; | 763 | int ret; |
796 | 764 | ||
797 | RESTRICT_TO_RANGE(vr->count,1,USBVISION_NUMFRAMES); | 765 | RESTRICT_TO_RANGE(vr->count,1,USBVISION_NUMFRAMES); |
@@ -819,9 +787,7 @@ static int vidioc_reqbufs (struct file *file, | |||
819 | static int vidioc_querybuf (struct file *file, | 787 | static int vidioc_querybuf (struct file *file, |
820 | void *priv, struct v4l2_buffer *vb) | 788 | void *priv, struct v4l2_buffer *vb) |
821 | { | 789 | { |
822 | struct video_device *dev = video_devdata(file); | 790 | struct usb_usbvision *usbvision = video_drvdata(file); |
823 | struct usb_usbvision *usbvision = | ||
824 | (struct usb_usbvision *) video_get_drvdata(dev); | ||
825 | struct usbvision_frame *frame; | 791 | struct usbvision_frame *frame; |
826 | 792 | ||
827 | /* FIXME : must control | 793 | /* FIXME : must control |
@@ -857,9 +823,7 @@ static int vidioc_querybuf (struct file *file, | |||
857 | 823 | ||
858 | static int vidioc_qbuf (struct file *file, void *priv, struct v4l2_buffer *vb) | 824 | static int vidioc_qbuf (struct file *file, void *priv, struct v4l2_buffer *vb) |
859 | { | 825 | { |
860 | struct video_device *dev = video_devdata(file); | 826 | struct usb_usbvision *usbvision = video_drvdata(file); |
861 | struct usb_usbvision *usbvision = | ||
862 | (struct usb_usbvision *) video_get_drvdata(dev); | ||
863 | struct usbvision_frame *frame; | 827 | struct usbvision_frame *frame; |
864 | unsigned long lock_flags; | 828 | unsigned long lock_flags; |
865 | 829 | ||
@@ -896,9 +860,7 @@ static int vidioc_qbuf (struct file *file, void *priv, struct v4l2_buffer *vb) | |||
896 | 860 | ||
897 | static int vidioc_dqbuf (struct file *file, void *priv, struct v4l2_buffer *vb) | 861 | static int vidioc_dqbuf (struct file *file, void *priv, struct v4l2_buffer *vb) |
898 | { | 862 | { |
899 | struct video_device *dev = video_devdata(file); | 863 | struct usb_usbvision *usbvision = video_drvdata(file); |
900 | struct usb_usbvision *usbvision = | ||
901 | (struct usb_usbvision *) video_get_drvdata(dev); | ||
902 | int ret; | 864 | int ret; |
903 | struct usbvision_frame *f; | 865 | struct usbvision_frame *f; |
904 | unsigned long lock_flags; | 866 | unsigned long lock_flags; |
@@ -939,9 +901,7 @@ static int vidioc_dqbuf (struct file *file, void *priv, struct v4l2_buffer *vb) | |||
939 | 901 | ||
940 | static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) | 902 | static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) |
941 | { | 903 | { |
942 | struct video_device *dev = video_devdata(file); | 904 | struct usb_usbvision *usbvision = video_drvdata(file); |
943 | struct usb_usbvision *usbvision = | ||
944 | (struct usb_usbvision *) video_get_drvdata(dev); | ||
945 | int b=V4L2_BUF_TYPE_VIDEO_CAPTURE; | 905 | int b=V4L2_BUF_TYPE_VIDEO_CAPTURE; |
946 | 906 | ||
947 | usbvision->streaming = Stream_On; | 907 | usbvision->streaming = Stream_On; |
@@ -953,9 +913,7 @@ static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) | |||
953 | static int vidioc_streamoff(struct file *file, | 913 | static int vidioc_streamoff(struct file *file, |
954 | void *priv, enum v4l2_buf_type type) | 914 | void *priv, enum v4l2_buf_type type) |
955 | { | 915 | { |
956 | struct video_device *dev = video_devdata(file); | 916 | struct usb_usbvision *usbvision = video_drvdata(file); |
957 | struct usb_usbvision *usbvision = | ||
958 | (struct usb_usbvision *) video_get_drvdata(dev); | ||
959 | int b=V4L2_BUF_TYPE_VIDEO_CAPTURE; | 917 | int b=V4L2_BUF_TYPE_VIDEO_CAPTURE; |
960 | 918 | ||
961 | if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | 919 | if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE) |
@@ -988,9 +946,7 @@ static int vidioc_enum_fmt_vid_cap (struct file *file, void *priv, | |||
988 | static int vidioc_g_fmt_vid_cap (struct file *file, void *priv, | 946 | static int vidioc_g_fmt_vid_cap (struct file *file, void *priv, |
989 | struct v4l2_format *vf) | 947 | struct v4l2_format *vf) |
990 | { | 948 | { |
991 | struct video_device *dev = video_devdata(file); | 949 | struct usb_usbvision *usbvision = video_drvdata(file); |
992 | struct usb_usbvision *usbvision = | ||
993 | (struct usb_usbvision *) video_get_drvdata(dev); | ||
994 | vf->fmt.pix.width = usbvision->curwidth; | 950 | vf->fmt.pix.width = usbvision->curwidth; |
995 | vf->fmt.pix.height = usbvision->curheight; | 951 | vf->fmt.pix.height = usbvision->curheight; |
996 | vf->fmt.pix.pixelformat = usbvision->palette.format; | 952 | vf->fmt.pix.pixelformat = usbvision->palette.format; |
@@ -1006,9 +962,7 @@ static int vidioc_g_fmt_vid_cap (struct file *file, void *priv, | |||
1006 | static int vidioc_try_fmt_vid_cap (struct file *file, void *priv, | 962 | static int vidioc_try_fmt_vid_cap (struct file *file, void *priv, |
1007 | struct v4l2_format *vf) | 963 | struct v4l2_format *vf) |
1008 | { | 964 | { |
1009 | struct video_device *dev = video_devdata(file); | 965 | struct usb_usbvision *usbvision = video_drvdata(file); |
1010 | struct usb_usbvision *usbvision = | ||
1011 | (struct usb_usbvision *) video_get_drvdata(dev); | ||
1012 | int formatIdx; | 966 | int formatIdx; |
1013 | 967 | ||
1014 | /* Find requested format in available ones */ | 968 | /* Find requested format in available ones */ |
@@ -1036,9 +990,7 @@ static int vidioc_try_fmt_vid_cap (struct file *file, void *priv, | |||
1036 | static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, | 990 | static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, |
1037 | struct v4l2_format *vf) | 991 | struct v4l2_format *vf) |
1038 | { | 992 | { |
1039 | struct video_device *dev = video_devdata(file); | 993 | struct usb_usbvision *usbvision = video_drvdata(file); |
1040 | struct usb_usbvision *usbvision = | ||
1041 | (struct usb_usbvision *) video_get_drvdata(dev); | ||
1042 | int ret; | 994 | int ret; |
1043 | 995 | ||
1044 | if( 0 != (ret=vidioc_try_fmt_vid_cap (file, priv, vf)) ) { | 996 | if( 0 != (ret=vidioc_try_fmt_vid_cap (file, priv, vf)) ) { |
@@ -1066,9 +1018,7 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, | |||
1066 | static ssize_t usbvision_v4l2_read(struct file *file, char __user *buf, | 1018 | static ssize_t usbvision_v4l2_read(struct file *file, char __user *buf, |
1067 | size_t count, loff_t *ppos) | 1019 | size_t count, loff_t *ppos) |
1068 | { | 1020 | { |
1069 | struct video_device *dev = video_devdata(file); | 1021 | struct usb_usbvision *usbvision = video_drvdata(file); |
1070 | struct usb_usbvision *usbvision = | ||
1071 | (struct usb_usbvision *) video_get_drvdata(dev); | ||
1072 | int noblock = file->f_flags & O_NONBLOCK; | 1022 | int noblock = file->f_flags & O_NONBLOCK; |
1073 | unsigned long lock_flags; | 1023 | unsigned long lock_flags; |
1074 | 1024 | ||
@@ -1177,10 +1127,7 @@ static int usbvision_v4l2_mmap(struct file *file, struct vm_area_struct *vma) | |||
1177 | start = vma->vm_start; | 1127 | start = vma->vm_start; |
1178 | void *pos; | 1128 | void *pos; |
1179 | u32 i; | 1129 | u32 i; |
1180 | 1130 | struct usb_usbvision *usbvision = video_drvdata(file); | |
1181 | struct video_device *dev = video_devdata(file); | ||
1182 | struct usb_usbvision *usbvision = | ||
1183 | (struct usb_usbvision *) video_get_drvdata(dev); | ||
1184 | 1131 | ||
1185 | PDEBUG(DBG_MMAP, "mmap"); | 1132 | PDEBUG(DBG_MMAP, "mmap"); |
1186 | 1133 | ||
@@ -1237,9 +1184,7 @@ static int usbvision_v4l2_mmap(struct file *file, struct vm_area_struct *vma) | |||
1237 | */ | 1184 | */ |
1238 | static int usbvision_radio_open(struct inode *inode, struct file *file) | 1185 | static int usbvision_radio_open(struct inode *inode, struct file *file) |
1239 | { | 1186 | { |
1240 | struct video_device *dev = video_devdata(file); | 1187 | struct usb_usbvision *usbvision = video_drvdata(file); |
1241 | struct usb_usbvision *usbvision = | ||
1242 | (struct usb_usbvision *) video_get_drvdata(dev); | ||
1243 | int errCode = 0; | 1188 | int errCode = 0; |
1244 | 1189 | ||
1245 | PDEBUG(DBG_IO, "%s:", __func__); | 1190 | PDEBUG(DBG_IO, "%s:", __func__); |
@@ -1289,9 +1234,7 @@ out: | |||
1289 | 1234 | ||
1290 | static int usbvision_radio_close(struct inode *inode, struct file *file) | 1235 | static int usbvision_radio_close(struct inode *inode, struct file *file) |
1291 | { | 1236 | { |
1292 | struct video_device *dev = video_devdata(file); | 1237 | struct usb_usbvision *usbvision = video_drvdata(file); |
1293 | struct usb_usbvision *usbvision = | ||
1294 | (struct usb_usbvision *) video_get_drvdata(dev); | ||
1295 | int errCode = 0; | 1238 | int errCode = 0; |
1296 | 1239 | ||
1297 | PDEBUG(DBG_IO, ""); | 1240 | PDEBUG(DBG_IO, ""); |
diff --git a/drivers/media/video/uvc/uvc_ctrl.c b/drivers/media/video/uvc/uvc_ctrl.c index feab12aa2c7b..f16aafe9cf14 100644 --- a/drivers/media/video/uvc/uvc_ctrl.c +++ b/drivers/media/video/uvc/uvc_ctrl.c | |||
@@ -83,6 +83,22 @@ static struct uvc_control_info uvc_ctrls[] = { | |||
83 | }, | 83 | }, |
84 | { | 84 | { |
85 | .entity = UVC_GUID_UVC_PROCESSING, | 85 | .entity = UVC_GUID_UVC_PROCESSING, |
86 | .selector = PU_WHITE_BALANCE_TEMPERATURE_CONTROL, | ||
87 | .index = 6, | ||
88 | .size = 2, | ||
89 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE | ||
90 | | UVC_CONTROL_RESTORE | UVC_CONTROL_AUTO_UPDATE, | ||
91 | }, | ||
92 | { | ||
93 | .entity = UVC_GUID_UVC_PROCESSING, | ||
94 | .selector = PU_WHITE_BALANCE_COMPONENT_CONTROL, | ||
95 | .index = 7, | ||
96 | .size = 4, | ||
97 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE | ||
98 | | UVC_CONTROL_RESTORE | UVC_CONTROL_AUTO_UPDATE, | ||
99 | }, | ||
100 | { | ||
101 | .entity = UVC_GUID_UVC_PROCESSING, | ||
86 | .selector = PU_BACKLIGHT_COMPENSATION_CONTROL, | 102 | .selector = PU_BACKLIGHT_COMPENSATION_CONTROL, |
87 | .index = 8, | 103 | .index = 8, |
88 | .size = 2, | 104 | .size = 2, |
@@ -114,6 +130,60 @@ static struct uvc_control_info uvc_ctrls[] = { | |||
114 | | UVC_CONTROL_GET_DEF | UVC_CONTROL_RESTORE, | 130 | | UVC_CONTROL_GET_DEF | UVC_CONTROL_RESTORE, |
115 | }, | 131 | }, |
116 | { | 132 | { |
133 | .entity = UVC_GUID_UVC_PROCESSING, | ||
134 | .selector = PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL, | ||
135 | .index = 12, | ||
136 | .size = 1, | ||
137 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR | ||
138 | | UVC_CONTROL_GET_DEF | UVC_CONTROL_RESTORE, | ||
139 | }, | ||
140 | { | ||
141 | .entity = UVC_GUID_UVC_PROCESSING, | ||
142 | .selector = PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL, | ||
143 | .index = 13, | ||
144 | .size = 1, | ||
145 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR | ||
146 | | UVC_CONTROL_GET_DEF | UVC_CONTROL_RESTORE, | ||
147 | }, | ||
148 | { | ||
149 | .entity = UVC_GUID_UVC_PROCESSING, | ||
150 | .selector = PU_DIGITAL_MULTIPLIER_CONTROL, | ||
151 | .index = 14, | ||
152 | .size = 2, | ||
153 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE | ||
154 | | UVC_CONTROL_RESTORE, | ||
155 | }, | ||
156 | { | ||
157 | .entity = UVC_GUID_UVC_PROCESSING, | ||
158 | .selector = PU_DIGITAL_MULTIPLIER_LIMIT_CONTROL, | ||
159 | .index = 15, | ||
160 | .size = 2, | ||
161 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE | ||
162 | | UVC_CONTROL_RESTORE, | ||
163 | }, | ||
164 | { | ||
165 | .entity = UVC_GUID_UVC_PROCESSING, | ||
166 | .selector = PU_ANALOG_VIDEO_STANDARD_CONTROL, | ||
167 | .index = 16, | ||
168 | .size = 1, | ||
169 | .flags = UVC_CONTROL_GET_CUR, | ||
170 | }, | ||
171 | { | ||
172 | .entity = UVC_GUID_UVC_PROCESSING, | ||
173 | .selector = PU_ANALOG_LOCK_STATUS_CONTROL, | ||
174 | .index = 17, | ||
175 | .size = 1, | ||
176 | .flags = UVC_CONTROL_GET_CUR, | ||
177 | }, | ||
178 | { | ||
179 | .entity = UVC_GUID_UVC_CAMERA, | ||
180 | .selector = CT_SCANNING_MODE_CONTROL, | ||
181 | .index = 0, | ||
182 | .size = 1, | ||
183 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR | ||
184 | | UVC_CONTROL_RESTORE, | ||
185 | }, | ||
186 | { | ||
117 | .entity = UVC_GUID_UVC_CAMERA, | 187 | .entity = UVC_GUID_UVC_CAMERA, |
118 | .selector = CT_AE_MODE_CONTROL, | 188 | .selector = CT_AE_MODE_CONTROL, |
119 | .index = 1, | 189 | .index = 1, |
@@ -140,6 +210,14 @@ static struct uvc_control_info uvc_ctrls[] = { | |||
140 | }, | 210 | }, |
141 | { | 211 | { |
142 | .entity = UVC_GUID_UVC_CAMERA, | 212 | .entity = UVC_GUID_UVC_CAMERA, |
213 | .selector = CT_EXPOSURE_TIME_RELATIVE_CONTROL, | ||
214 | .index = 4, | ||
215 | .size = 1, | ||
216 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR | ||
217 | | UVC_CONTROL_RESTORE, | ||
218 | }, | ||
219 | { | ||
220 | .entity = UVC_GUID_UVC_CAMERA, | ||
143 | .selector = CT_FOCUS_ABSOLUTE_CONTROL, | 221 | .selector = CT_FOCUS_ABSOLUTE_CONTROL, |
144 | .index = 5, | 222 | .index = 5, |
145 | .size = 2, | 223 | .size = 2, |
@@ -148,42 +226,90 @@ static struct uvc_control_info uvc_ctrls[] = { | |||
148 | }, | 226 | }, |
149 | { | 227 | { |
150 | .entity = UVC_GUID_UVC_CAMERA, | 228 | .entity = UVC_GUID_UVC_CAMERA, |
151 | .selector = CT_FOCUS_AUTO_CONTROL, | 229 | .selector = CT_FOCUS_RELATIVE_CONTROL, |
152 | .index = 17, | 230 | .index = 6, |
153 | .size = 1, | 231 | .size = 2, |
154 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR | 232 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE |
155 | | UVC_CONTROL_GET_DEF | UVC_CONTROL_RESTORE, | 233 | | UVC_CONTROL_AUTO_UPDATE, |
156 | }, | 234 | }, |
157 | { | 235 | { |
158 | .entity = UVC_GUID_UVC_PROCESSING, | 236 | .entity = UVC_GUID_UVC_CAMERA, |
159 | .selector = PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL, | 237 | .selector = CT_IRIS_ABSOLUTE_CONTROL, |
160 | .index = 12, | 238 | .index = 7, |
239 | .size = 2, | ||
240 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE | ||
241 | | UVC_CONTROL_RESTORE | UVC_CONTROL_AUTO_UPDATE, | ||
242 | }, | ||
243 | { | ||
244 | .entity = UVC_GUID_UVC_CAMERA, | ||
245 | .selector = CT_IRIS_RELATIVE_CONTROL, | ||
246 | .index = 8, | ||
161 | .size = 1, | 247 | .size = 1, |
162 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR | 248 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR |
163 | | UVC_CONTROL_GET_DEF | UVC_CONTROL_RESTORE, | 249 | | UVC_CONTROL_AUTO_UPDATE, |
164 | }, | 250 | }, |
165 | { | 251 | { |
166 | .entity = UVC_GUID_UVC_PROCESSING, | 252 | .entity = UVC_GUID_UVC_CAMERA, |
167 | .selector = PU_WHITE_BALANCE_TEMPERATURE_CONTROL, | 253 | .selector = CT_ZOOM_ABSOLUTE_CONTROL, |
168 | .index = 6, | 254 | .index = 9, |
169 | .size = 2, | 255 | .size = 2, |
170 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE | 256 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE |
171 | | UVC_CONTROL_RESTORE | UVC_CONTROL_AUTO_UPDATE, | 257 | | UVC_CONTROL_RESTORE | UVC_CONTROL_AUTO_UPDATE, |
172 | }, | 258 | }, |
173 | { | 259 | { |
174 | .entity = UVC_GUID_UVC_PROCESSING, | 260 | .entity = UVC_GUID_UVC_CAMERA, |
175 | .selector = PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL, | 261 | .selector = CT_ZOOM_RELATIVE_CONTROL, |
262 | .index = 10, | ||
263 | .size = 3, | ||
264 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE | ||
265 | | UVC_CONTROL_AUTO_UPDATE, | ||
266 | }, | ||
267 | { | ||
268 | .entity = UVC_GUID_UVC_CAMERA, | ||
269 | .selector = CT_PANTILT_ABSOLUTE_CONTROL, | ||
270 | .index = 11, | ||
271 | .size = 8, | ||
272 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE | ||
273 | | UVC_CONTROL_RESTORE | UVC_CONTROL_AUTO_UPDATE, | ||
274 | }, | ||
275 | { | ||
276 | .entity = UVC_GUID_UVC_CAMERA, | ||
277 | .selector = CT_PANTILT_RELATIVE_CONTROL, | ||
278 | .index = 12, | ||
279 | .size = 4, | ||
280 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE | ||
281 | | UVC_CONTROL_AUTO_UPDATE, | ||
282 | }, | ||
283 | { | ||
284 | .entity = UVC_GUID_UVC_CAMERA, | ||
285 | .selector = CT_ROLL_ABSOLUTE_CONTROL, | ||
176 | .index = 13, | 286 | .index = 13, |
287 | .size = 2, | ||
288 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE | ||
289 | | UVC_CONTROL_RESTORE | UVC_CONTROL_AUTO_UPDATE, | ||
290 | }, | ||
291 | { | ||
292 | .entity = UVC_GUID_UVC_CAMERA, | ||
293 | .selector = CT_ROLL_RELATIVE_CONTROL, | ||
294 | .index = 14, | ||
295 | .size = 2, | ||
296 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE | ||
297 | | UVC_CONTROL_AUTO_UPDATE, | ||
298 | }, | ||
299 | { | ||
300 | .entity = UVC_GUID_UVC_CAMERA, | ||
301 | .selector = CT_FOCUS_AUTO_CONTROL, | ||
302 | .index = 17, | ||
177 | .size = 1, | 303 | .size = 1, |
178 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR | 304 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR |
179 | | UVC_CONTROL_GET_DEF | UVC_CONTROL_RESTORE, | 305 | | UVC_CONTROL_GET_DEF | UVC_CONTROL_RESTORE, |
180 | }, | 306 | }, |
181 | { | 307 | { |
182 | .entity = UVC_GUID_UVC_PROCESSING, | 308 | .entity = UVC_GUID_UVC_CAMERA, |
183 | .selector = PU_WHITE_BALANCE_COMPONENT_CONTROL, | 309 | .selector = CT_PRIVACY_CONTROL, |
184 | .index = 7, | 310 | .index = 18, |
185 | .size = 4, | 311 | .size = 1, |
186 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE | 312 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR |
187 | | UVC_CONTROL_RESTORE | UVC_CONTROL_AUTO_UPDATE, | 313 | | UVC_CONTROL_RESTORE | UVC_CONTROL_AUTO_UPDATE, |
188 | }, | 314 | }, |
189 | }; | 315 | }; |
@@ -711,7 +837,17 @@ static int uvc_ctrl_commit_entity(struct uvc_device *dev, | |||
711 | 837 | ||
712 | for (i = 0; i < entity->ncontrols; ++i) { | 838 | for (i = 0; i < entity->ncontrols; ++i) { |
713 | ctrl = &entity->controls[i]; | 839 | ctrl = &entity->controls[i]; |
714 | if (ctrl->info == NULL || !ctrl->dirty) | 840 | if (ctrl->info == NULL) |
841 | continue; | ||
842 | |||
843 | /* Reset the loaded flag for auto-update controls that were | ||
844 | * marked as loaded in uvc_ctrl_get/uvc_ctrl_set to prevent | ||
845 | * uvc_ctrl_get from using the cached value. | ||
846 | */ | ||
847 | if (ctrl->info->flags & UVC_CONTROL_AUTO_UPDATE) | ||
848 | ctrl->loaded = 0; | ||
849 | |||
850 | if (!ctrl->dirty) | ||
715 | continue; | 851 | continue; |
716 | 852 | ||
717 | if (!rollback) | 853 | if (!rollback) |
@@ -727,9 +863,6 @@ static int uvc_ctrl_commit_entity(struct uvc_device *dev, | |||
727 | uvc_ctrl_data(ctrl, UVC_CTRL_DATA_BACKUP), | 863 | uvc_ctrl_data(ctrl, UVC_CTRL_DATA_BACKUP), |
728 | ctrl->info->size); | 864 | ctrl->info->size); |
729 | 865 | ||
730 | if ((ctrl->info->flags & UVC_CONTROL_GET_CUR) == 0) | ||
731 | ctrl->loaded = 0; | ||
732 | |||
733 | ctrl->dirty = 0; | 866 | ctrl->dirty = 0; |
734 | 867 | ||
735 | if (ret < 0) | 868 | if (ret < 0) |
@@ -787,8 +920,7 @@ int uvc_ctrl_get(struct uvc_video_device *video, | |||
787 | if (ret < 0) | 920 | if (ret < 0) |
788 | return ret; | 921 | return ret; |
789 | 922 | ||
790 | if ((ctrl->info->flags & UVC_CONTROL_AUTO_UPDATE) == 0) | 923 | ctrl->loaded = 1; |
791 | ctrl->loaded = 1; | ||
792 | } | 924 | } |
793 | 925 | ||
794 | xctrl->value = uvc_get_le_value( | 926 | xctrl->value = uvc_get_le_value( |
@@ -839,8 +971,7 @@ int uvc_ctrl_set(struct uvc_video_device *video, | |||
839 | return ret; | 971 | return ret; |
840 | } | 972 | } |
841 | 973 | ||
842 | if ((ctrl->info->flags & UVC_CONTROL_AUTO_UPDATE) == 0) | 974 | ctrl->loaded = 1; |
843 | ctrl->loaded = 1; | ||
844 | } | 975 | } |
845 | 976 | ||
846 | if (!ctrl->dirty) { | 977 | if (!ctrl->dirty) { |
diff --git a/drivers/media/video/uvc/uvc_driver.c b/drivers/media/video/uvc/uvc_driver.c index 7e102034d38d..d7ad060640bc 100644 --- a/drivers/media/video/uvc/uvc_driver.c +++ b/drivers/media/video/uvc/uvc_driver.c | |||
@@ -1663,7 +1663,7 @@ static int uvc_suspend(struct usb_interface *intf, pm_message_t message) | |||
1663 | return uvc_video_suspend(&dev->video); | 1663 | return uvc_video_suspend(&dev->video); |
1664 | } | 1664 | } |
1665 | 1665 | ||
1666 | static int uvc_resume(struct usb_interface *intf) | 1666 | static int __uvc_resume(struct usb_interface *intf, int reset) |
1667 | { | 1667 | { |
1668 | struct uvc_device *dev = usb_get_intfdata(intf); | 1668 | struct uvc_device *dev = usb_get_intfdata(intf); |
1669 | int ret; | 1669 | int ret; |
@@ -1672,7 +1672,7 @@ static int uvc_resume(struct usb_interface *intf) | |||
1672 | intf->cur_altsetting->desc.bInterfaceNumber); | 1672 | intf->cur_altsetting->desc.bInterfaceNumber); |
1673 | 1673 | ||
1674 | if (intf->cur_altsetting->desc.bInterfaceSubClass == SC_VIDEOCONTROL) { | 1674 | if (intf->cur_altsetting->desc.bInterfaceSubClass == SC_VIDEOCONTROL) { |
1675 | if ((ret = uvc_ctrl_resume_device(dev)) < 0) | 1675 | if (reset && (ret = uvc_ctrl_resume_device(dev)) < 0) |
1676 | return ret; | 1676 | return ret; |
1677 | 1677 | ||
1678 | return uvc_status_resume(dev); | 1678 | return uvc_status_resume(dev); |
@@ -1687,6 +1687,16 @@ static int uvc_resume(struct usb_interface *intf) | |||
1687 | return uvc_video_resume(&dev->video); | 1687 | return uvc_video_resume(&dev->video); |
1688 | } | 1688 | } |
1689 | 1689 | ||
1690 | static int uvc_resume(struct usb_interface *intf) | ||
1691 | { | ||
1692 | return __uvc_resume(intf, 0); | ||
1693 | } | ||
1694 | |||
1695 | static int uvc_reset_resume(struct usb_interface *intf) | ||
1696 | { | ||
1697 | return __uvc_resume(intf, 1); | ||
1698 | } | ||
1699 | |||
1690 | /* ------------------------------------------------------------------------ | 1700 | /* ------------------------------------------------------------------------ |
1691 | * Driver initialization and cleanup | 1701 | * Driver initialization and cleanup |
1692 | */ | 1702 | */ |
@@ -1902,6 +1912,24 @@ static struct usb_device_id uvc_ids[] = { | |||
1902 | .bInterfaceSubClass = 1, | 1912 | .bInterfaceSubClass = 1, |
1903 | .bInterfaceProtocol = 0, | 1913 | .bInterfaceProtocol = 0, |
1904 | .driver_info = UVC_QUIRK_PROBE_MINMAX }, | 1914 | .driver_info = UVC_QUIRK_PROBE_MINMAX }, |
1915 | /* Compaq Presario B1200 - Bison Electronics */ | ||
1916 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | ||
1917 | | USB_DEVICE_ID_MATCH_INT_INFO, | ||
1918 | .idVendor = 0x5986, | ||
1919 | .idProduct = 0x0104, | ||
1920 | .bInterfaceClass = USB_CLASS_VIDEO, | ||
1921 | .bInterfaceSubClass = 1, | ||
1922 | .bInterfaceProtocol = 0, | ||
1923 | .driver_info = UVC_QUIRK_PROBE_MINMAX }, | ||
1924 | /* Acer Travelmate 7720 - Bison Electronics */ | ||
1925 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | ||
1926 | | USB_DEVICE_ID_MATCH_INT_INFO, | ||
1927 | .idVendor = 0x5986, | ||
1928 | .idProduct = 0x0105, | ||
1929 | .bInterfaceClass = USB_CLASS_VIDEO, | ||
1930 | .bInterfaceSubClass = 1, | ||
1931 | .bInterfaceProtocol = 0, | ||
1932 | .driver_info = UVC_QUIRK_PROBE_MINMAX }, | ||
1905 | /* Medion Akoya Mini E1210 - Bison Electronics */ | 1933 | /* Medion Akoya Mini E1210 - Bison Electronics */ |
1906 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | 1934 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE |
1907 | | USB_DEVICE_ID_MATCH_INT_INFO, | 1935 | | USB_DEVICE_ID_MATCH_INT_INFO, |
@@ -1920,6 +1948,24 @@ static struct usb_device_id uvc_ids[] = { | |||
1920 | .bInterfaceSubClass = 1, | 1948 | .bInterfaceSubClass = 1, |
1921 | .bInterfaceProtocol = 0, | 1949 | .bInterfaceProtocol = 0, |
1922 | .driver_info = UVC_QUIRK_PROBE_MINMAX }, | 1950 | .driver_info = UVC_QUIRK_PROBE_MINMAX }, |
1951 | /* Fujitsu Amilo SI2636 - Bison Electronics */ | ||
1952 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | ||
1953 | | USB_DEVICE_ID_MATCH_INT_INFO, | ||
1954 | .idVendor = 0x5986, | ||
1955 | .idProduct = 0x0202, | ||
1956 | .bInterfaceClass = USB_CLASS_VIDEO, | ||
1957 | .bInterfaceSubClass = 1, | ||
1958 | .bInterfaceProtocol = 0, | ||
1959 | .driver_info = UVC_QUIRK_PROBE_MINMAX }, | ||
1960 | /* Advent 4211 - Bison Electronics */ | ||
1961 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | ||
1962 | | USB_DEVICE_ID_MATCH_INT_INFO, | ||
1963 | .idVendor = 0x5986, | ||
1964 | .idProduct = 0x0203, | ||
1965 | .bInterfaceClass = USB_CLASS_VIDEO, | ||
1966 | .bInterfaceSubClass = 1, | ||
1967 | .bInterfaceProtocol = 0, | ||
1968 | .driver_info = UVC_QUIRK_PROBE_MINMAX }, | ||
1923 | /* Bison Electronics */ | 1969 | /* Bison Electronics */ |
1924 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | 1970 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE |
1925 | | USB_DEVICE_ID_MATCH_INT_INFO, | 1971 | | USB_DEVICE_ID_MATCH_INT_INFO, |
@@ -1952,6 +1998,7 @@ struct uvc_driver uvc_driver = { | |||
1952 | .disconnect = uvc_disconnect, | 1998 | .disconnect = uvc_disconnect, |
1953 | .suspend = uvc_suspend, | 1999 | .suspend = uvc_suspend, |
1954 | .resume = uvc_resume, | 2000 | .resume = uvc_resume, |
2001 | .reset_resume = uvc_reset_resume, | ||
1955 | .id_table = uvc_ids, | 2002 | .id_table = uvc_ids, |
1956 | .supports_autosuspend = 1, | 2003 | .supports_autosuspend = 1, |
1957 | }, | 2004 | }, |
diff --git a/drivers/media/video/uvc/uvc_status.c b/drivers/media/video/uvc/uvc_status.c index 75e678ac54eb..5d60b264d59a 100644 --- a/drivers/media/video/uvc/uvc_status.c +++ b/drivers/media/video/uvc/uvc_status.c | |||
@@ -177,9 +177,15 @@ int uvc_status_init(struct uvc_device *dev) | |||
177 | 177 | ||
178 | uvc_input_init(dev); | 178 | uvc_input_init(dev); |
179 | 179 | ||
180 | dev->status = kzalloc(UVC_MAX_STATUS_SIZE, GFP_KERNEL); | ||
181 | if (dev->status == NULL) | ||
182 | return -ENOMEM; | ||
183 | |||
180 | dev->int_urb = usb_alloc_urb(0, GFP_KERNEL); | 184 | dev->int_urb = usb_alloc_urb(0, GFP_KERNEL); |
181 | if (dev->int_urb == NULL) | 185 | if (dev->int_urb == NULL) { |
186 | kfree(dev->status); | ||
182 | return -ENOMEM; | 187 | return -ENOMEM; |
188 | } | ||
183 | 189 | ||
184 | pipe = usb_rcvintpipe(dev->udev, ep->desc.bEndpointAddress); | 190 | pipe = usb_rcvintpipe(dev->udev, ep->desc.bEndpointAddress); |
185 | 191 | ||
@@ -192,7 +198,7 @@ int uvc_status_init(struct uvc_device *dev) | |||
192 | interval = fls(interval) - 1; | 198 | interval = fls(interval) - 1; |
193 | 199 | ||
194 | usb_fill_int_urb(dev->int_urb, dev->udev, pipe, | 200 | usb_fill_int_urb(dev->int_urb, dev->udev, pipe, |
195 | dev->status, sizeof dev->status, uvc_status_complete, | 201 | dev->status, UVC_MAX_STATUS_SIZE, uvc_status_complete, |
196 | dev, interval); | 202 | dev, interval); |
197 | 203 | ||
198 | return usb_submit_urb(dev->int_urb, GFP_KERNEL); | 204 | return usb_submit_urb(dev->int_urb, GFP_KERNEL); |
@@ -202,6 +208,7 @@ void uvc_status_cleanup(struct uvc_device *dev) | |||
202 | { | 208 | { |
203 | usb_kill_urb(dev->int_urb); | 209 | usb_kill_urb(dev->int_urb); |
204 | usb_free_urb(dev->int_urb); | 210 | usb_free_urb(dev->int_urb); |
211 | kfree(dev->status); | ||
205 | uvc_input_cleanup(dev); | 212 | uvc_input_cleanup(dev); |
206 | } | 213 | } |
207 | 214 | ||
diff --git a/drivers/media/video/uvc/uvc_v4l2.c b/drivers/media/video/uvc/uvc_v4l2.c index d7bd71be40a9..78e4c4e09d89 100644 --- a/drivers/media/video/uvc/uvc_v4l2.c +++ b/drivers/media/video/uvc/uvc_v4l2.c | |||
@@ -400,15 +400,13 @@ static int uvc_has_privileges(struct uvc_fh *handle) | |||
400 | 400 | ||
401 | static int uvc_v4l2_open(struct inode *inode, struct file *file) | 401 | static int uvc_v4l2_open(struct inode *inode, struct file *file) |
402 | { | 402 | { |
403 | struct video_device *vdev; | ||
404 | struct uvc_video_device *video; | 403 | struct uvc_video_device *video; |
405 | struct uvc_fh *handle; | 404 | struct uvc_fh *handle; |
406 | int ret = 0; | 405 | int ret = 0; |
407 | 406 | ||
408 | uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_open\n"); | 407 | uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_open\n"); |
409 | mutex_lock(&uvc_driver.open_mutex); | 408 | mutex_lock(&uvc_driver.open_mutex); |
410 | vdev = video_devdata(file); | 409 | video = video_drvdata(file); |
411 | video = video_get_drvdata(vdev); | ||
412 | 410 | ||
413 | if (video->dev->state & UVC_DEV_DISCONNECTED) { | 411 | if (video->dev->state & UVC_DEV_DISCONNECTED) { |
414 | ret = -ENODEV; | 412 | ret = -ENODEV; |
@@ -440,8 +438,7 @@ done: | |||
440 | 438 | ||
441 | static int uvc_v4l2_release(struct inode *inode, struct file *file) | 439 | static int uvc_v4l2_release(struct inode *inode, struct file *file) |
442 | { | 440 | { |
443 | struct video_device *vdev = video_devdata(file); | 441 | struct uvc_video_device *video = video_drvdata(file); |
444 | struct uvc_video_device *video = video_get_drvdata(vdev); | ||
445 | struct uvc_fh *handle = (struct uvc_fh *)file->private_data; | 442 | struct uvc_fh *handle = (struct uvc_fh *)file->private_data; |
446 | 443 | ||
447 | uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_release\n"); | 444 | uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_release\n"); |
@@ -845,10 +842,6 @@ static int uvc_v4l2_do_ioctl(struct inode *inode, struct file *file, | |||
845 | if (ret < 0) | 842 | if (ret < 0) |
846 | return ret; | 843 | return ret; |
847 | 844 | ||
848 | if (!(video->streaming->cur_format->flags & | ||
849 | UVC_FMT_FLAG_COMPRESSED)) | ||
850 | video->queue.flags |= UVC_QUEUE_DROP_INCOMPLETE; | ||
851 | |||
852 | rb->count = ret; | 845 | rb->count = ret; |
853 | ret = 0; | 846 | ret = 0; |
854 | break; | 847 | break; |
@@ -1031,8 +1024,7 @@ static struct vm_operations_struct uvc_vm_ops = { | |||
1031 | 1024 | ||
1032 | static int uvc_v4l2_mmap(struct file *file, struct vm_area_struct *vma) | 1025 | static int uvc_v4l2_mmap(struct file *file, struct vm_area_struct *vma) |
1033 | { | 1026 | { |
1034 | struct video_device *vdev = video_devdata(file); | 1027 | struct uvc_video_device *video = video_drvdata(file); |
1035 | struct uvc_video_device *video = video_get_drvdata(vdev); | ||
1036 | struct uvc_buffer *uninitialized_var(buffer); | 1028 | struct uvc_buffer *uninitialized_var(buffer); |
1037 | struct page *page; | 1029 | struct page *page; |
1038 | unsigned long addr, start, size; | 1030 | unsigned long addr, start, size; |
@@ -1085,8 +1077,7 @@ done: | |||
1085 | 1077 | ||
1086 | static unsigned int uvc_v4l2_poll(struct file *file, poll_table *wait) | 1078 | static unsigned int uvc_v4l2_poll(struct file *file, poll_table *wait) |
1087 | { | 1079 | { |
1088 | struct video_device *vdev = video_devdata(file); | 1080 | struct uvc_video_device *video = video_drvdata(file); |
1089 | struct uvc_video_device *video = video_get_drvdata(vdev); | ||
1090 | 1081 | ||
1091 | uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_poll\n"); | 1082 | uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_poll\n"); |
1092 | 1083 | ||
diff --git a/drivers/media/video/uvc/uvc_video.c b/drivers/media/video/uvc/uvc_video.c index 6854ac78a161..b7bb23820d80 100644 --- a/drivers/media/video/uvc/uvc_video.c +++ b/drivers/media/video/uvc/uvc_video.c | |||
@@ -455,7 +455,8 @@ static void uvc_video_decode_isoc(struct urb *urb, | |||
455 | urb->iso_frame_desc[i].actual_length - ret); | 455 | urb->iso_frame_desc[i].actual_length - ret); |
456 | 456 | ||
457 | /* Process the header again. */ | 457 | /* Process the header again. */ |
458 | uvc_video_decode_end(video, buf, mem, ret); | 458 | uvc_video_decode_end(video, buf, mem, |
459 | urb->iso_frame_desc[i].actual_length); | ||
459 | 460 | ||
460 | if (buf->state == UVC_BUF_STATE_DONE || | 461 | if (buf->state == UVC_BUF_STATE_DONE || |
461 | buf->state == UVC_BUF_STATE_ERROR) | 462 | buf->state == UVC_BUF_STATE_ERROR) |
@@ -512,7 +513,7 @@ static void uvc_video_decode_bulk(struct urb *urb, | |||
512 | video->bulk.payload_size >= video->bulk.max_payload_size) { | 513 | video->bulk.payload_size >= video->bulk.max_payload_size) { |
513 | if (!video->bulk.skip_payload && buf != NULL) { | 514 | if (!video->bulk.skip_payload && buf != NULL) { |
514 | uvc_video_decode_end(video, buf, video->bulk.header, | 515 | uvc_video_decode_end(video, buf, video->bulk.header, |
515 | video->bulk.header_size); | 516 | video->bulk.payload_size); |
516 | if (buf->state == UVC_BUF_STATE_DONE || | 517 | if (buf->state == UVC_BUF_STATE_DONE || |
517 | buf->state == UVC_BUF_STATE_ERROR) | 518 | buf->state == UVC_BUF_STATE_ERROR) |
518 | buf = uvc_queue_next_buffer(&video->queue, buf); | 519 | buf = uvc_queue_next_buffer(&video->queue, buf); |
@@ -655,7 +656,7 @@ static int uvc_init_video_isoc(struct uvc_video_device *video, | |||
655 | if (size > UVC_MAX_FRAME_SIZE) | 656 | if (size > UVC_MAX_FRAME_SIZE) |
656 | return -EINVAL; | 657 | return -EINVAL; |
657 | 658 | ||
658 | npackets = (size + psize - 1) / psize; | 659 | npackets = DIV_ROUND_UP(size, psize); |
659 | if (npackets > UVC_MAX_ISO_PACKETS) | 660 | if (npackets > UVC_MAX_ISO_PACKETS) |
660 | npackets = UVC_MAX_ISO_PACKETS; | 661 | npackets = UVC_MAX_ISO_PACKETS; |
661 | 662 | ||
@@ -970,6 +971,11 @@ int uvc_video_enable(struct uvc_video_device *video, int enable) | |||
970 | return 0; | 971 | return 0; |
971 | } | 972 | } |
972 | 973 | ||
974 | if (video->streaming->cur_format->flags & UVC_FMT_FLAG_COMPRESSED) | ||
975 | video->queue.flags &= ~UVC_QUEUE_DROP_INCOMPLETE; | ||
976 | else | ||
977 | video->queue.flags |= UVC_QUEUE_DROP_INCOMPLETE; | ||
978 | |||
973 | if ((ret = uvc_queue_enable(&video->queue, 1)) < 0) | 979 | if ((ret = uvc_queue_enable(&video->queue, 1)) < 0) |
974 | return ret; | 980 | return ret; |
975 | 981 | ||
diff --git a/drivers/media/video/uvc/uvcvideo.h b/drivers/media/video/uvc/uvcvideo.h index bafe3406e305..9a6bc1aafb16 100644 --- a/drivers/media/video/uvc/uvcvideo.h +++ b/drivers/media/video/uvc/uvcvideo.h | |||
@@ -303,6 +303,8 @@ struct uvc_xu_control { | |||
303 | #define UVC_MAX_FRAME_SIZE (16*1024*1024) | 303 | #define UVC_MAX_FRAME_SIZE (16*1024*1024) |
304 | /* Maximum number of video buffers. */ | 304 | /* Maximum number of video buffers. */ |
305 | #define UVC_MAX_VIDEO_BUFFERS 32 | 305 | #define UVC_MAX_VIDEO_BUFFERS 32 |
306 | /* Maximum status buffer size in bytes of interrupt URB. */ | ||
307 | #define UVC_MAX_STATUS_SIZE 16 | ||
306 | 308 | ||
307 | #define UVC_CTRL_CONTROL_TIMEOUT 300 | 309 | #define UVC_CTRL_CONTROL_TIMEOUT 300 |
308 | #define UVC_CTRL_STREAMING_TIMEOUT 1000 | 310 | #define UVC_CTRL_STREAMING_TIMEOUT 1000 |
@@ -634,7 +636,7 @@ struct uvc_device { | |||
634 | /* Status Interrupt Endpoint */ | 636 | /* Status Interrupt Endpoint */ |
635 | struct usb_host_endpoint *int_ep; | 637 | struct usb_host_endpoint *int_ep; |
636 | struct urb *int_urb; | 638 | struct urb *int_urb; |
637 | __u8 status[16]; | 639 | __u8 *status; |
638 | struct input_dev *input; | 640 | struct input_dev *input; |
639 | 641 | ||
640 | /* Video Streaming interfaces */ | 642 | /* Video Streaming interfaces */ |
diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c index 88ca13104417..20c3be8617ea 100644 --- a/drivers/media/video/v4l2-common.c +++ b/drivers/media/video/v4l2-common.c | |||
@@ -187,9 +187,11 @@ const char **v4l2_ctrl_get_menu(u32 id) | |||
187 | NULL | 187 | NULL |
188 | }; | 188 | }; |
189 | static const char *mpeg_audio_encoding[] = { | 189 | static const char *mpeg_audio_encoding[] = { |
190 | "Layer I", | 190 | "MPEG-1/2 Layer I", |
191 | "Layer II", | 191 | "MPEG-1/2 Layer II", |
192 | "Layer III", | 192 | "MPEG-1/2 Layer III", |
193 | "MPEG-2/4 AAC", | ||
194 | "AC-3", | ||
193 | NULL | 195 | NULL |
194 | }; | 196 | }; |
195 | static const char *mpeg_audio_l1_bitrate[] = { | 197 | static const char *mpeg_audio_l1_bitrate[] = { |
@@ -243,6 +245,28 @@ const char **v4l2_ctrl_get_menu(u32 id) | |||
243 | "320 kbps", | 245 | "320 kbps", |
244 | NULL | 246 | NULL |
245 | }; | 247 | }; |
248 | static const char *mpeg_audio_ac3_bitrate[] = { | ||
249 | "32 kbps", | ||
250 | "40 kbps", | ||
251 | "48 kbps", | ||
252 | "56 kbps", | ||
253 | "64 kbps", | ||
254 | "80 kbps", | ||
255 | "96 kbps", | ||
256 | "112 kbps", | ||
257 | "128 kbps", | ||
258 | "160 kbps", | ||
259 | "192 kbps", | ||
260 | "224 kbps", | ||
261 | "256 kbps", | ||
262 | "320 kbps", | ||
263 | "384 kbps", | ||
264 | "448 kbps", | ||
265 | "512 kbps", | ||
266 | "576 kbps", | ||
267 | "640 kbps", | ||
268 | NULL | ||
269 | }; | ||
246 | static const char *mpeg_audio_mode[] = { | 270 | static const char *mpeg_audio_mode[] = { |
247 | "Stereo", | 271 | "Stereo", |
248 | "Joint Stereo", | 272 | "Joint Stereo", |
@@ -271,6 +295,7 @@ const char **v4l2_ctrl_get_menu(u32 id) | |||
271 | static const char *mpeg_video_encoding[] = { | 295 | static const char *mpeg_video_encoding[] = { |
272 | "MPEG-1", | 296 | "MPEG-1", |
273 | "MPEG-2", | 297 | "MPEG-2", |
298 | "MPEG-4 AVC", | ||
274 | NULL | 299 | NULL |
275 | }; | 300 | }; |
276 | static const char *mpeg_video_aspect[] = { | 301 | static const char *mpeg_video_aspect[] = { |
@@ -311,6 +336,8 @@ const char **v4l2_ctrl_get_menu(u32 id) | |||
311 | return mpeg_audio_l2_bitrate; | 336 | return mpeg_audio_l2_bitrate; |
312 | case V4L2_CID_MPEG_AUDIO_L3_BITRATE: | 337 | case V4L2_CID_MPEG_AUDIO_L3_BITRATE: |
313 | return mpeg_audio_l3_bitrate; | 338 | return mpeg_audio_l3_bitrate; |
339 | case V4L2_CID_MPEG_AUDIO_AC3_BITRATE: | ||
340 | return mpeg_audio_ac3_bitrate; | ||
314 | case V4L2_CID_MPEG_AUDIO_MODE: | 341 | case V4L2_CID_MPEG_AUDIO_MODE: |
315 | return mpeg_audio_mode; | 342 | return mpeg_audio_mode; |
316 | case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION: | 343 | case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION: |
@@ -335,62 +362,73 @@ const char **v4l2_ctrl_get_menu(u32 id) | |||
335 | } | 362 | } |
336 | EXPORT_SYMBOL(v4l2_ctrl_get_menu); | 363 | EXPORT_SYMBOL(v4l2_ctrl_get_menu); |
337 | 364 | ||
338 | /* Fill in a struct v4l2_queryctrl */ | 365 | /* Return the control name. */ |
339 | int v4l2_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 min, s32 max, s32 step, s32 def) | 366 | const char *v4l2_ctrl_get_name(u32 id) |
340 | { | 367 | { |
341 | const char *name; | 368 | switch (id) { |
342 | |||
343 | qctrl->flags = 0; | ||
344 | switch (qctrl->id) { | ||
345 | /* USER controls */ | 369 | /* USER controls */ |
346 | case V4L2_CID_USER_CLASS: name = "User Controls"; break; | 370 | case V4L2_CID_USER_CLASS: return "User Controls"; |
347 | case V4L2_CID_AUDIO_VOLUME: name = "Volume"; break; | 371 | case V4L2_CID_AUDIO_VOLUME: return "Volume"; |
348 | case V4L2_CID_AUDIO_MUTE: name = "Mute"; break; | 372 | case V4L2_CID_AUDIO_MUTE: return "Mute"; |
349 | case V4L2_CID_AUDIO_BALANCE: name = "Balance"; break; | 373 | case V4L2_CID_AUDIO_BALANCE: return "Balance"; |
350 | case V4L2_CID_AUDIO_BASS: name = "Bass"; break; | 374 | case V4L2_CID_AUDIO_BASS: return "Bass"; |
351 | case V4L2_CID_AUDIO_TREBLE: name = "Treble"; break; | 375 | case V4L2_CID_AUDIO_TREBLE: return "Treble"; |
352 | case V4L2_CID_AUDIO_LOUDNESS: name = "Loudness"; break; | 376 | case V4L2_CID_AUDIO_LOUDNESS: return "Loudness"; |
353 | case V4L2_CID_BRIGHTNESS: name = "Brightness"; break; | 377 | case V4L2_CID_BRIGHTNESS: return "Brightness"; |
354 | case V4L2_CID_CONTRAST: name = "Contrast"; break; | 378 | case V4L2_CID_CONTRAST: return "Contrast"; |
355 | case V4L2_CID_SATURATION: name = "Saturation"; break; | 379 | case V4L2_CID_SATURATION: return "Saturation"; |
356 | case V4L2_CID_HUE: name = "Hue"; break; | 380 | case V4L2_CID_HUE: return "Hue"; |
357 | 381 | ||
358 | /* MPEG controls */ | 382 | /* MPEG controls */ |
359 | case V4L2_CID_MPEG_CLASS: name = "MPEG Encoder Controls"; break; | 383 | case V4L2_CID_MPEG_CLASS: return "MPEG Encoder Controls"; |
360 | case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: name = "Audio Sampling Frequency"; break; | 384 | case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: return "Audio Sampling Frequency"; |
361 | case V4L2_CID_MPEG_AUDIO_ENCODING: name = "Audio Encoding Layer"; break; | 385 | case V4L2_CID_MPEG_AUDIO_ENCODING: return "Audio Encoding"; |
362 | case V4L2_CID_MPEG_AUDIO_L1_BITRATE: name = "Audio Layer I Bitrate"; break; | 386 | case V4L2_CID_MPEG_AUDIO_L1_BITRATE: return "Audio Layer I Bitrate"; |
363 | case V4L2_CID_MPEG_AUDIO_L2_BITRATE: name = "Audio Layer II Bitrate"; break; | 387 | case V4L2_CID_MPEG_AUDIO_L2_BITRATE: return "Audio Layer II Bitrate"; |
364 | case V4L2_CID_MPEG_AUDIO_L3_BITRATE: name = "Audio Layer III Bitrate"; break; | 388 | case V4L2_CID_MPEG_AUDIO_L3_BITRATE: return "Audio Layer III Bitrate"; |
365 | case V4L2_CID_MPEG_AUDIO_MODE: name = "Audio Stereo Mode"; break; | 389 | case V4L2_CID_MPEG_AUDIO_AAC_BITRATE: return "Audio AAC Bitrate"; |
366 | case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION: name = "Audio Stereo Mode Extension"; break; | 390 | case V4L2_CID_MPEG_AUDIO_AC3_BITRATE: return "Audio AC-3 Bitrate"; |
367 | case V4L2_CID_MPEG_AUDIO_EMPHASIS: name = "Audio Emphasis"; break; | 391 | case V4L2_CID_MPEG_AUDIO_MODE: return "Audio Stereo Mode"; |
368 | case V4L2_CID_MPEG_AUDIO_CRC: name = "Audio CRC"; break; | 392 | case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION: return "Audio Stereo Mode Extension"; |
369 | case V4L2_CID_MPEG_AUDIO_MUTE: name = "Audio Mute"; break; | 393 | case V4L2_CID_MPEG_AUDIO_EMPHASIS: return "Audio Emphasis"; |
370 | case V4L2_CID_MPEG_VIDEO_ENCODING: name = "Video Encoding"; break; | 394 | case V4L2_CID_MPEG_AUDIO_CRC: return "Audio CRC"; |
371 | case V4L2_CID_MPEG_VIDEO_ASPECT: name = "Video Aspect"; break; | 395 | case V4L2_CID_MPEG_AUDIO_MUTE: return "Audio Mute"; |
372 | case V4L2_CID_MPEG_VIDEO_B_FRAMES: name = "Video B Frames"; break; | 396 | case V4L2_CID_MPEG_VIDEO_ENCODING: return "Video Encoding"; |
373 | case V4L2_CID_MPEG_VIDEO_GOP_SIZE: name = "Video GOP Size"; break; | 397 | case V4L2_CID_MPEG_VIDEO_ASPECT: return "Video Aspect"; |
374 | case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE: name = "Video GOP Closure"; break; | 398 | case V4L2_CID_MPEG_VIDEO_B_FRAMES: return "Video B Frames"; |
375 | case V4L2_CID_MPEG_VIDEO_PULLDOWN: name = "Video Pulldown"; break; | 399 | case V4L2_CID_MPEG_VIDEO_GOP_SIZE: return "Video GOP Size"; |
376 | case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: name = "Video Bitrate Mode"; break; | 400 | case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE: return "Video GOP Closure"; |
377 | case V4L2_CID_MPEG_VIDEO_BITRATE: name = "Video Bitrate"; break; | 401 | case V4L2_CID_MPEG_VIDEO_PULLDOWN: return "Video Pulldown"; |
378 | case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: name = "Video Peak Bitrate"; break; | 402 | case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: return "Video Bitrate Mode"; |
379 | case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION: name = "Video Temporal Decimation"; break; | 403 | case V4L2_CID_MPEG_VIDEO_BITRATE: return "Video Bitrate"; |
380 | case V4L2_CID_MPEG_VIDEO_MUTE: name = "Video Mute"; break; | 404 | case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: return "Video Peak Bitrate"; |
381 | case V4L2_CID_MPEG_VIDEO_MUTE_YUV: name = "Video Mute YUV"; break; | 405 | case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION: return "Video Temporal Decimation"; |
382 | case V4L2_CID_MPEG_STREAM_TYPE: name = "Stream Type"; break; | 406 | case V4L2_CID_MPEG_VIDEO_MUTE: return "Video Mute"; |
383 | case V4L2_CID_MPEG_STREAM_PID_PMT: name = "Stream PMT Program ID"; break; | 407 | case V4L2_CID_MPEG_VIDEO_MUTE_YUV: return "Video Mute YUV"; |
384 | case V4L2_CID_MPEG_STREAM_PID_AUDIO: name = "Stream Audio Program ID"; break; | 408 | case V4L2_CID_MPEG_STREAM_TYPE: return "Stream Type"; |
385 | case V4L2_CID_MPEG_STREAM_PID_VIDEO: name = "Stream Video Program ID"; break; | 409 | case V4L2_CID_MPEG_STREAM_PID_PMT: return "Stream PMT Program ID"; |
386 | case V4L2_CID_MPEG_STREAM_PID_PCR: name = "Stream PCR Program ID"; break; | 410 | case V4L2_CID_MPEG_STREAM_PID_AUDIO: return "Stream Audio Program ID"; |
387 | case V4L2_CID_MPEG_STREAM_PES_ID_AUDIO: name = "Stream PES Audio ID"; break; | 411 | case V4L2_CID_MPEG_STREAM_PID_VIDEO: return "Stream Video Program ID"; |
388 | case V4L2_CID_MPEG_STREAM_PES_ID_VIDEO: name = "Stream PES Video ID"; break; | 412 | case V4L2_CID_MPEG_STREAM_PID_PCR: return "Stream PCR Program ID"; |
389 | case V4L2_CID_MPEG_STREAM_VBI_FMT: name = "Stream VBI Format"; break; | 413 | case V4L2_CID_MPEG_STREAM_PES_ID_AUDIO: return "Stream PES Audio ID"; |
414 | case V4L2_CID_MPEG_STREAM_PES_ID_VIDEO: return "Stream PES Video ID"; | ||
415 | case V4L2_CID_MPEG_STREAM_VBI_FMT: return "Stream VBI Format"; | ||
390 | 416 | ||
391 | default: | 417 | default: |
392 | return -EINVAL; | 418 | return NULL; |
393 | } | 419 | } |
420 | } | ||
421 | EXPORT_SYMBOL(v4l2_ctrl_get_name); | ||
422 | |||
423 | /* Fill in a struct v4l2_queryctrl */ | ||
424 | int v4l2_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 min, s32 max, s32 step, s32 def) | ||
425 | { | ||
426 | const char *name = v4l2_ctrl_get_name(qctrl->id); | ||
427 | |||
428 | qctrl->flags = 0; | ||
429 | if (name == NULL) | ||
430 | return -EINVAL; | ||
431 | |||
394 | switch (qctrl->id) { | 432 | switch (qctrl->id) { |
395 | case V4L2_CID_AUDIO_MUTE: | 433 | case V4L2_CID_AUDIO_MUTE: |
396 | case V4L2_CID_AUDIO_LOUDNESS: | 434 | case V4L2_CID_AUDIO_LOUDNESS: |
@@ -407,6 +445,7 @@ int v4l2_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 min, s32 max, s32 ste | |||
407 | case V4L2_CID_MPEG_AUDIO_L1_BITRATE: | 445 | case V4L2_CID_MPEG_AUDIO_L1_BITRATE: |
408 | case V4L2_CID_MPEG_AUDIO_L2_BITRATE: | 446 | case V4L2_CID_MPEG_AUDIO_L2_BITRATE: |
409 | case V4L2_CID_MPEG_AUDIO_L3_BITRATE: | 447 | case V4L2_CID_MPEG_AUDIO_L3_BITRATE: |
448 | case V4L2_CID_MPEG_AUDIO_AC3_BITRATE: | ||
410 | case V4L2_CID_MPEG_AUDIO_MODE: | 449 | case V4L2_CID_MPEG_AUDIO_MODE: |
411 | case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION: | 450 | case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION: |
412 | case V4L2_CID_MPEG_AUDIO_EMPHASIS: | 451 | case V4L2_CID_MPEG_AUDIO_EMPHASIS: |
@@ -493,7 +532,7 @@ int v4l2_ctrl_query_fill_std(struct v4l2_queryctrl *qctrl) | |||
493 | case V4L2_CID_MPEG_AUDIO_ENCODING: | 532 | case V4L2_CID_MPEG_AUDIO_ENCODING: |
494 | return v4l2_ctrl_query_fill(qctrl, | 533 | return v4l2_ctrl_query_fill(qctrl, |
495 | V4L2_MPEG_AUDIO_ENCODING_LAYER_1, | 534 | V4L2_MPEG_AUDIO_ENCODING_LAYER_1, |
496 | V4L2_MPEG_AUDIO_ENCODING_LAYER_3, 1, | 535 | V4L2_MPEG_AUDIO_ENCODING_AC3, 1, |
497 | V4L2_MPEG_AUDIO_ENCODING_LAYER_2); | 536 | V4L2_MPEG_AUDIO_ENCODING_LAYER_2); |
498 | case V4L2_CID_MPEG_AUDIO_L1_BITRATE: | 537 | case V4L2_CID_MPEG_AUDIO_L1_BITRATE: |
499 | return v4l2_ctrl_query_fill(qctrl, | 538 | return v4l2_ctrl_query_fill(qctrl, |
@@ -510,6 +549,13 @@ int v4l2_ctrl_query_fill_std(struct v4l2_queryctrl *qctrl) | |||
510 | V4L2_MPEG_AUDIO_L3_BITRATE_32K, | 549 | V4L2_MPEG_AUDIO_L3_BITRATE_32K, |
511 | V4L2_MPEG_AUDIO_L3_BITRATE_320K, 1, | 550 | V4L2_MPEG_AUDIO_L3_BITRATE_320K, 1, |
512 | V4L2_MPEG_AUDIO_L3_BITRATE_192K); | 551 | V4L2_MPEG_AUDIO_L3_BITRATE_192K); |
552 | case V4L2_CID_MPEG_AUDIO_AAC_BITRATE: | ||
553 | return v4l2_ctrl_query_fill(qctrl, 0, 6400, 1, 3200000); | ||
554 | case V4L2_CID_MPEG_AUDIO_AC3_BITRATE: | ||
555 | return v4l2_ctrl_query_fill(qctrl, | ||
556 | V4L2_MPEG_AUDIO_AC3_BITRATE_32K, | ||
557 | V4L2_MPEG_AUDIO_AC3_BITRATE_640K, 1, | ||
558 | V4L2_MPEG_AUDIO_AC3_BITRATE_384K); | ||
513 | case V4L2_CID_MPEG_AUDIO_MODE: | 559 | case V4L2_CID_MPEG_AUDIO_MODE: |
514 | return v4l2_ctrl_query_fill(qctrl, | 560 | return v4l2_ctrl_query_fill(qctrl, |
515 | V4L2_MPEG_AUDIO_MODE_STEREO, | 561 | V4L2_MPEG_AUDIO_MODE_STEREO, |
@@ -535,7 +581,7 @@ int v4l2_ctrl_query_fill_std(struct v4l2_queryctrl *qctrl) | |||
535 | case V4L2_CID_MPEG_VIDEO_ENCODING: | 581 | case V4L2_CID_MPEG_VIDEO_ENCODING: |
536 | return v4l2_ctrl_query_fill(qctrl, | 582 | return v4l2_ctrl_query_fill(qctrl, |
537 | V4L2_MPEG_VIDEO_ENCODING_MPEG_1, | 583 | V4L2_MPEG_VIDEO_ENCODING_MPEG_1, |
538 | V4L2_MPEG_VIDEO_ENCODING_MPEG_2, 1, | 584 | V4L2_MPEG_VIDEO_ENCODING_MPEG_4_AVC, 1, |
539 | V4L2_MPEG_VIDEO_ENCODING_MPEG_2); | 585 | V4L2_MPEG_VIDEO_ENCODING_MPEG_2); |
540 | case V4L2_CID_MPEG_VIDEO_ASPECT: | 586 | case V4L2_CID_MPEG_VIDEO_ASPECT: |
541 | return v4l2_ctrl_query_fill(qctrl, | 587 | return v4l2_ctrl_query_fill(qctrl, |
@@ -594,12 +640,17 @@ int v4l2_ctrl_query_fill_std(struct v4l2_queryctrl *qctrl) | |||
594 | EXPORT_SYMBOL(v4l2_ctrl_query_fill_std); | 640 | EXPORT_SYMBOL(v4l2_ctrl_query_fill_std); |
595 | 641 | ||
596 | /* Fill in a struct v4l2_querymenu based on the struct v4l2_queryctrl and | 642 | /* Fill in a struct v4l2_querymenu based on the struct v4l2_queryctrl and |
597 | the menu. The qctrl pointer may be NULL, in which case it is ignored. */ | 643 | the menu. The qctrl pointer may be NULL, in which case it is ignored. |
644 | If menu_items is NULL, then the menu items are retrieved using | ||
645 | v4l2_ctrl_get_menu. */ | ||
598 | int v4l2_ctrl_query_menu(struct v4l2_querymenu *qmenu, struct v4l2_queryctrl *qctrl, | 646 | int v4l2_ctrl_query_menu(struct v4l2_querymenu *qmenu, struct v4l2_queryctrl *qctrl, |
599 | const char **menu_items) | 647 | const char **menu_items) |
600 | { | 648 | { |
601 | int i; | 649 | int i; |
602 | 650 | ||
651 | qmenu->reserved = 0; | ||
652 | if (menu_items == NULL) | ||
653 | menu_items = v4l2_ctrl_get_menu(qmenu->id); | ||
603 | if (menu_items == NULL || | 654 | if (menu_items == NULL || |
604 | (qctrl && (qmenu->index < qctrl->minimum || qmenu->index > qctrl->maximum))) | 655 | (qctrl && (qmenu->index < qctrl->minimum || qmenu->index > qctrl->maximum))) |
605 | return -EINVAL; | 656 | return -EINVAL; |
@@ -607,11 +658,31 @@ int v4l2_ctrl_query_menu(struct v4l2_querymenu *qmenu, struct v4l2_queryctrl *qc | |||
607 | if (menu_items[i] == NULL || menu_items[i][0] == '\0') | 658 | if (menu_items[i] == NULL || menu_items[i][0] == '\0') |
608 | return -EINVAL; | 659 | return -EINVAL; |
609 | snprintf(qmenu->name, sizeof(qmenu->name), menu_items[qmenu->index]); | 660 | snprintf(qmenu->name, sizeof(qmenu->name), menu_items[qmenu->index]); |
610 | qmenu->reserved = 0; | ||
611 | return 0; | 661 | return 0; |
612 | } | 662 | } |
613 | EXPORT_SYMBOL(v4l2_ctrl_query_menu); | 663 | EXPORT_SYMBOL(v4l2_ctrl_query_menu); |
614 | 664 | ||
665 | /* Fill in a struct v4l2_querymenu based on the specified array of valid | ||
666 | menu items (terminated by V4L2_CTRL_MENU_IDS_END). | ||
667 | Use this if there are 'holes' in the list of valid menu items. */ | ||
668 | int v4l2_ctrl_query_menu_valid_items(struct v4l2_querymenu *qmenu, const u32 *ids) | ||
669 | { | ||
670 | const char **menu_items = v4l2_ctrl_get_menu(qmenu->id); | ||
671 | |||
672 | qmenu->reserved = 0; | ||
673 | if (menu_items == NULL || ids == NULL) | ||
674 | return -EINVAL; | ||
675 | while (*ids != V4L2_CTRL_MENU_IDS_END) { | ||
676 | if (*ids++ == qmenu->index) { | ||
677 | snprintf(qmenu->name, sizeof(qmenu->name), | ||
678 | menu_items[qmenu->index]); | ||
679 | return 0; | ||
680 | } | ||
681 | } | ||
682 | return -EINVAL; | ||
683 | } | ||
684 | EXPORT_SYMBOL(v4l2_ctrl_query_menu_valid_items); | ||
685 | |||
615 | /* ctrl_classes points to an array of u32 pointers, the last element is | 686 | /* ctrl_classes points to an array of u32 pointers, the last element is |
616 | a NULL pointer. Each u32 array is a 0-terminated array of control IDs. | 687 | a NULL pointer. Each u32 array is a 0-terminated array of control IDs. |
617 | Each array must be sorted low to high and belong to the same control | 688 | Each array must be sorted low to high and belong to the same control |
diff --git a/drivers/media/video/v4l2-dev.c b/drivers/media/video/v4l2-dev.c index 155fdec9ac7d..ccd6566a515e 100644 --- a/drivers/media/video/v4l2-dev.c +++ b/drivers/media/video/v4l2-dev.c | |||
@@ -42,6 +42,7 @@ static ssize_t show_index(struct device *cd, | |||
42 | struct device_attribute *attr, char *buf) | 42 | struct device_attribute *attr, char *buf) |
43 | { | 43 | { |
44 | struct video_device *vfd = container_of(cd, struct video_device, dev); | 44 | struct video_device *vfd = container_of(cd, struct video_device, dev); |
45 | |||
45 | return sprintf(buf, "%i\n", vfd->index); | 46 | return sprintf(buf, "%i\n", vfd->index); |
46 | } | 47 | } |
47 | 48 | ||
@@ -49,6 +50,7 @@ static ssize_t show_name(struct device *cd, | |||
49 | struct device_attribute *attr, char *buf) | 50 | struct device_attribute *attr, char *buf) |
50 | { | 51 | { |
51 | struct video_device *vfd = container_of(cd, struct video_device, dev); | 52 | struct video_device *vfd = container_of(cd, struct video_device, dev); |
53 | |||
52 | return sprintf(buf, "%.*s\n", (int)sizeof(vfd->name), vfd->name); | 54 | return sprintf(buf, "%.*s\n", (int)sizeof(vfd->name), vfd->name); |
53 | } | 55 | } |
54 | 56 | ||
@@ -58,12 +60,16 @@ static struct device_attribute video_device_attrs[] = { | |||
58 | __ATTR_NULL | 60 | __ATTR_NULL |
59 | }; | 61 | }; |
60 | 62 | ||
63 | /* | ||
64 | * Active devices | ||
65 | */ | ||
66 | static struct video_device *video_device[VIDEO_NUM_DEVICES]; | ||
67 | static DEFINE_MUTEX(videodev_lock); | ||
68 | static DECLARE_BITMAP(video_nums[VFL_TYPE_MAX], VIDEO_NUM_DEVICES); | ||
69 | |||
61 | struct video_device *video_device_alloc(void) | 70 | struct video_device *video_device_alloc(void) |
62 | { | 71 | { |
63 | struct video_device *vfd; | 72 | return kzalloc(sizeof(struct video_device), GFP_KERNEL); |
64 | |||
65 | vfd = kzalloc(sizeof(*vfd), GFP_KERNEL); | ||
66 | return vfd; | ||
67 | } | 73 | } |
68 | EXPORT_SYMBOL(video_device_alloc); | 74 | EXPORT_SYMBOL(video_device_alloc); |
69 | 75 | ||
@@ -73,16 +79,52 @@ void video_device_release(struct video_device *vfd) | |||
73 | } | 79 | } |
74 | EXPORT_SYMBOL(video_device_release); | 80 | EXPORT_SYMBOL(video_device_release); |
75 | 81 | ||
82 | void video_device_release_empty(struct video_device *vfd) | ||
83 | { | ||
84 | /* Do nothing */ | ||
85 | /* Only valid when the video_device struct is a static. */ | ||
86 | } | ||
87 | EXPORT_SYMBOL(video_device_release_empty); | ||
88 | |||
89 | /* Called when the last user of the character device is gone. */ | ||
90 | static void v4l2_chardev_release(struct kobject *kobj) | ||
91 | { | ||
92 | struct video_device *vfd = container_of(kobj, struct video_device, cdev.kobj); | ||
93 | |||
94 | mutex_lock(&videodev_lock); | ||
95 | if (video_device[vfd->minor] != vfd) { | ||
96 | mutex_unlock(&videodev_lock); | ||
97 | BUG(); | ||
98 | return; | ||
99 | } | ||
100 | |||
101 | /* Free up this device for reuse */ | ||
102 | video_device[vfd->minor] = NULL; | ||
103 | clear_bit(vfd->num, video_nums[vfd->vfl_type]); | ||
104 | mutex_unlock(&videodev_lock); | ||
105 | |||
106 | /* Release the character device */ | ||
107 | vfd->cdev_release(kobj); | ||
108 | /* Release video_device and perform other | ||
109 | cleanups as needed. */ | ||
110 | if (vfd->release) | ||
111 | vfd->release(vfd); | ||
112 | } | ||
113 | |||
114 | /* The new kobj_type for the character device */ | ||
115 | static struct kobj_type v4l2_ktype_cdev_default = { | ||
116 | .release = v4l2_chardev_release, | ||
117 | }; | ||
118 | |||
76 | static void video_release(struct device *cd) | 119 | static void video_release(struct device *cd) |
77 | { | 120 | { |
78 | struct video_device *vfd = container_of(cd, struct video_device, dev); | 121 | struct video_device *vfd = container_of(cd, struct video_device, dev); |
79 | 122 | ||
80 | #if 1 | 123 | /* It's now safe to delete the char device. |
81 | /* needed until all drivers are fixed */ | 124 | This will either trigger the v4l2_chardev_release immediately (if |
82 | if (!vfd->release) | 125 | the refcount goes to 0) or later when the last user of the |
83 | return; | 126 | character device closes it. */ |
84 | #endif | 127 | cdev_del(&vfd->cdev); |
85 | vfd->release(vfd); | ||
86 | } | 128 | } |
87 | 129 | ||
88 | static struct class video_class = { | 130 | static struct class video_class = { |
@@ -91,87 +133,12 @@ static struct class video_class = { | |||
91 | .dev_release = video_release, | 133 | .dev_release = video_release, |
92 | }; | 134 | }; |
93 | 135 | ||
94 | /* | ||
95 | * Active devices | ||
96 | */ | ||
97 | |||
98 | static struct video_device *video_device[VIDEO_NUM_DEVICES]; | ||
99 | static DEFINE_MUTEX(videodev_lock); | ||
100 | |||
101 | struct video_device *video_devdata(struct file *file) | 136 | struct video_device *video_devdata(struct file *file) |
102 | { | 137 | { |
103 | return video_device[iminor(file->f_path.dentry->d_inode)]; | 138 | return video_device[iminor(file->f_path.dentry->d_inode)]; |
104 | } | 139 | } |
105 | EXPORT_SYMBOL(video_devdata); | 140 | EXPORT_SYMBOL(video_devdata); |
106 | 141 | ||
107 | /* | ||
108 | * Open a video device - FIXME: Obsoleted | ||
109 | */ | ||
110 | static int video_open(struct inode *inode, struct file *file) | ||
111 | { | ||
112 | unsigned int minor = iminor(inode); | ||
113 | int err = 0; | ||
114 | struct video_device *vfl; | ||
115 | const struct file_operations *old_fops; | ||
116 | |||
117 | if (minor >= VIDEO_NUM_DEVICES) | ||
118 | return -ENODEV; | ||
119 | lock_kernel(); | ||
120 | mutex_lock(&videodev_lock); | ||
121 | vfl = video_device[minor]; | ||
122 | if (vfl == NULL) { | ||
123 | mutex_unlock(&videodev_lock); | ||
124 | request_module("char-major-%d-%d", VIDEO_MAJOR, minor); | ||
125 | mutex_lock(&videodev_lock); | ||
126 | vfl = video_device[minor]; | ||
127 | if (vfl == NULL) { | ||
128 | mutex_unlock(&videodev_lock); | ||
129 | unlock_kernel(); | ||
130 | return -ENODEV; | ||
131 | } | ||
132 | } | ||
133 | old_fops = file->f_op; | ||
134 | file->f_op = fops_get(vfl->fops); | ||
135 | if (file->f_op->open) | ||
136 | err = file->f_op->open(inode, file); | ||
137 | if (err) { | ||
138 | fops_put(file->f_op); | ||
139 | file->f_op = fops_get(old_fops); | ||
140 | } | ||
141 | fops_put(old_fops); | ||
142 | mutex_unlock(&videodev_lock); | ||
143 | unlock_kernel(); | ||
144 | return err; | ||
145 | } | ||
146 | |||
147 | /* | ||
148 | * open/release helper functions -- handle exclusive opens | ||
149 | * Should be removed soon | ||
150 | */ | ||
151 | int video_exclusive_open(struct inode *inode, struct file *file) | ||
152 | { | ||
153 | struct video_device *vfl = video_devdata(file); | ||
154 | int retval = 0; | ||
155 | |||
156 | mutex_lock(&vfl->lock); | ||
157 | if (vfl->users) | ||
158 | retval = -EBUSY; | ||
159 | else | ||
160 | vfl->users++; | ||
161 | mutex_unlock(&vfl->lock); | ||
162 | return retval; | ||
163 | } | ||
164 | EXPORT_SYMBOL(video_exclusive_open); | ||
165 | |||
166 | int video_exclusive_release(struct inode *inode, struct file *file) | ||
167 | { | ||
168 | struct video_device *vfl = video_devdata(file); | ||
169 | |||
170 | vfl->users--; | ||
171 | return 0; | ||
172 | } | ||
173 | EXPORT_SYMBOL(video_exclusive_release); | ||
174 | |||
175 | /** | 142 | /** |
176 | * get_index - assign stream number based on parent device | 143 | * get_index - assign stream number based on parent device |
177 | * @vdev: video_device to assign index number to, vdev->dev should be assigned | 144 | * @vdev: video_device to assign index number to, vdev->dev should be assigned |
@@ -252,33 +219,29 @@ int video_register_device_index(struct video_device *vfd, int type, int nr, | |||
252 | int index) | 219 | int index) |
253 | { | 220 | { |
254 | int i = 0; | 221 | int i = 0; |
255 | int base; | ||
256 | int end; | ||
257 | int ret; | 222 | int ret; |
258 | char *name_base; | 223 | int minor_offset = 0; |
224 | int minor_cnt = VIDEO_NUM_DEVICES; | ||
225 | const char *name_base; | ||
226 | void *priv = video_get_drvdata(vfd); | ||
227 | |||
228 | /* the release callback MUST be present */ | ||
229 | BUG_ON(!vfd->release); | ||
259 | 230 | ||
260 | if (vfd == NULL) | 231 | if (vfd == NULL) |
261 | return -EINVAL; | 232 | return -EINVAL; |
262 | 233 | ||
263 | switch (type) { | 234 | switch (type) { |
264 | case VFL_TYPE_GRABBER: | 235 | case VFL_TYPE_GRABBER: |
265 | base = MINOR_VFL_TYPE_GRABBER_MIN; | ||
266 | end = MINOR_VFL_TYPE_GRABBER_MAX+1; | ||
267 | name_base = "video"; | 236 | name_base = "video"; |
268 | break; | 237 | break; |
269 | case VFL_TYPE_VTX: | 238 | case VFL_TYPE_VTX: |
270 | base = MINOR_VFL_TYPE_VTX_MIN; | ||
271 | end = MINOR_VFL_TYPE_VTX_MAX+1; | ||
272 | name_base = "vtx"; | 239 | name_base = "vtx"; |
273 | break; | 240 | break; |
274 | case VFL_TYPE_VBI: | 241 | case VFL_TYPE_VBI: |
275 | base = MINOR_VFL_TYPE_VBI_MIN; | ||
276 | end = MINOR_VFL_TYPE_VBI_MAX+1; | ||
277 | name_base = "vbi"; | 242 | name_base = "vbi"; |
278 | break; | 243 | break; |
279 | case VFL_TYPE_RADIO: | 244 | case VFL_TYPE_RADIO: |
280 | base = MINOR_VFL_TYPE_RADIO_MIN; | ||
281 | end = MINOR_VFL_TYPE_RADIO_MAX+1; | ||
282 | name_base = "radio"; | 245 | name_base = "radio"; |
283 | break; | 246 | break; |
284 | default: | 247 | default: |
@@ -287,28 +250,70 @@ int video_register_device_index(struct video_device *vfd, int type, int nr, | |||
287 | return -EINVAL; | 250 | return -EINVAL; |
288 | } | 251 | } |
289 | 252 | ||
253 | vfd->vfl_type = type; | ||
254 | |||
255 | #ifdef CONFIG_VIDEO_FIXED_MINOR_RANGES | ||
256 | /* Keep the ranges for the first four types for historical | ||
257 | * reasons. | ||
258 | * Newer devices (not yet in place) should use the range | ||
259 | * of 128-191 and just pick the first free minor there | ||
260 | * (new style). */ | ||
261 | switch (type) { | ||
262 | case VFL_TYPE_GRABBER: | ||
263 | minor_offset = 0; | ||
264 | minor_cnt = 64; | ||
265 | break; | ||
266 | case VFL_TYPE_RADIO: | ||
267 | minor_offset = 64; | ||
268 | minor_cnt = 64; | ||
269 | break; | ||
270 | case VFL_TYPE_VTX: | ||
271 | minor_offset = 192; | ||
272 | minor_cnt = 32; | ||
273 | break; | ||
274 | case VFL_TYPE_VBI: | ||
275 | minor_offset = 224; | ||
276 | minor_cnt = 32; | ||
277 | break; | ||
278 | default: | ||
279 | minor_offset = 128; | ||
280 | minor_cnt = 64; | ||
281 | break; | ||
282 | } | ||
283 | #endif | ||
284 | |||
285 | /* Initialize the character device */ | ||
286 | cdev_init(&vfd->cdev, vfd->fops); | ||
287 | vfd->cdev.owner = vfd->fops->owner; | ||
290 | /* pick a minor number */ | 288 | /* pick a minor number */ |
291 | mutex_lock(&videodev_lock); | 289 | mutex_lock(&videodev_lock); |
292 | if (nr >= 0 && nr < end-base) { | 290 | nr = find_next_zero_bit(video_nums[type], minor_cnt, nr == -1 ? 0 : nr); |
293 | /* use the one the driver asked for */ | 291 | if (nr == minor_cnt) |
294 | i = base + nr; | 292 | nr = find_first_zero_bit(video_nums[type], minor_cnt); |
295 | if (NULL != video_device[i]) { | 293 | if (nr == minor_cnt) { |
296 | mutex_unlock(&videodev_lock); | 294 | printk(KERN_ERR "could not get a free kernel number\n"); |
297 | return -ENFILE; | 295 | mutex_unlock(&videodev_lock); |
298 | } | 296 | return -ENFILE; |
299 | } else { | ||
300 | /* use first free */ | ||
301 | for (i = base; i < end; i++) | ||
302 | if (NULL == video_device[i]) | ||
303 | break; | ||
304 | if (i == end) { | ||
305 | mutex_unlock(&videodev_lock); | ||
306 | return -ENFILE; | ||
307 | } | ||
308 | } | 297 | } |
309 | video_device[i] = vfd; | 298 | #ifdef CONFIG_VIDEO_FIXED_MINOR_RANGES |
310 | vfd->vfl_type = type; | 299 | /* 1-on-1 mapping of kernel number to minor number */ |
311 | vfd->minor = i; | 300 | i = nr; |
301 | #else | ||
302 | /* The kernel number and minor numbers are independent */ | ||
303 | for (i = 0; i < VIDEO_NUM_DEVICES; i++) | ||
304 | if (video_device[i] == NULL) | ||
305 | break; | ||
306 | if (i == VIDEO_NUM_DEVICES) { | ||
307 | mutex_unlock(&videodev_lock); | ||
308 | printk(KERN_ERR "could not get a free minor\n"); | ||
309 | return -ENFILE; | ||
310 | } | ||
311 | #endif | ||
312 | vfd->minor = i + minor_offset; | ||
313 | vfd->num = nr; | ||
314 | set_bit(nr, video_nums[type]); | ||
315 | BUG_ON(video_device[vfd->minor]); | ||
316 | video_device[vfd->minor] = vfd; | ||
312 | 317 | ||
313 | ret = get_index(vfd, index); | 318 | ret = get_index(vfd, index); |
314 | vfd->index = ret; | 319 | vfd->index = ret; |
@@ -320,35 +325,41 @@ int video_register_device_index(struct video_device *vfd, int type, int nr, | |||
320 | goto fail_minor; | 325 | goto fail_minor; |
321 | } | 326 | } |
322 | 327 | ||
323 | mutex_init(&vfd->lock); | 328 | ret = cdev_add(&vfd->cdev, MKDEV(VIDEO_MAJOR, vfd->minor), 1); |
324 | 329 | if (ret < 0) { | |
330 | printk(KERN_ERR "%s: cdev_add failed\n", __func__); | ||
331 | goto fail_minor; | ||
332 | } | ||
325 | /* sysfs class */ | 333 | /* sysfs class */ |
326 | memset(&vfd->dev, 0x00, sizeof(vfd->dev)); | 334 | memset(&vfd->dev, 0, sizeof(vfd->dev)); |
335 | /* The memset above cleared the device's drvdata, so | ||
336 | put back the copy we made earlier. */ | ||
337 | video_set_drvdata(vfd, priv); | ||
327 | vfd->dev.class = &video_class; | 338 | vfd->dev.class = &video_class; |
328 | vfd->dev.devt = MKDEV(VIDEO_MAJOR, vfd->minor); | 339 | vfd->dev.devt = MKDEV(VIDEO_MAJOR, vfd->minor); |
329 | if (vfd->parent) | 340 | if (vfd->parent) |
330 | vfd->dev.parent = vfd->parent; | 341 | vfd->dev.parent = vfd->parent; |
331 | sprintf(vfd->dev.bus_id, "%s%d", name_base, i - base); | 342 | sprintf(vfd->dev.bus_id, "%s%d", name_base, nr); |
332 | ret = device_register(&vfd->dev); | 343 | ret = device_register(&vfd->dev); |
333 | if (ret < 0) { | 344 | if (ret < 0) { |
334 | printk(KERN_ERR "%s: device_register failed\n", __func__); | 345 | printk(KERN_ERR "%s: device_register failed\n", __func__); |
335 | goto fail_minor; | 346 | goto del_cdev; |
336 | } | 347 | } |
337 | 348 | /* Remember the cdev's release function */ | |
338 | #if 1 | 349 | vfd->cdev_release = vfd->cdev.kobj.ktype->release; |
339 | /* needed until all drivers are fixed */ | 350 | /* Install our own */ |
340 | if (!vfd->release) | 351 | vfd->cdev.kobj.ktype = &v4l2_ktype_cdev_default; |
341 | printk(KERN_WARNING "videodev: \"%s\" has no release callback. " | ||
342 | "Please fix your driver for proper sysfs support, see " | ||
343 | "http://lwn.net/Articles/36850/\n", vfd->name); | ||
344 | #endif | ||
345 | return 0; | 352 | return 0; |
346 | 353 | ||
354 | del_cdev: | ||
355 | cdev_del(&vfd->cdev); | ||
356 | |||
347 | fail_minor: | 357 | fail_minor: |
348 | mutex_lock(&videodev_lock); | 358 | mutex_lock(&videodev_lock); |
349 | video_device[vfd->minor] = NULL; | 359 | video_device[vfd->minor] = NULL; |
350 | vfd->minor = -1; | 360 | clear_bit(vfd->num, video_nums[type]); |
351 | mutex_unlock(&videodev_lock); | 361 | mutex_unlock(&videodev_lock); |
362 | vfd->minor = -1; | ||
352 | return ret; | 363 | return ret; |
353 | } | 364 | } |
354 | EXPORT_SYMBOL(video_register_device_index); | 365 | EXPORT_SYMBOL(video_register_device_index); |
@@ -363,42 +374,29 @@ EXPORT_SYMBOL(video_register_device_index); | |||
363 | 374 | ||
364 | void video_unregister_device(struct video_device *vfd) | 375 | void video_unregister_device(struct video_device *vfd) |
365 | { | 376 | { |
366 | mutex_lock(&videodev_lock); | ||
367 | if (video_device[vfd->minor] != vfd) | ||
368 | panic("videodev: bad unregister"); | ||
369 | |||
370 | video_device[vfd->minor] = NULL; | ||
371 | device_unregister(&vfd->dev); | 377 | device_unregister(&vfd->dev); |
372 | mutex_unlock(&videodev_lock); | ||
373 | } | 378 | } |
374 | EXPORT_SYMBOL(video_unregister_device); | 379 | EXPORT_SYMBOL(video_unregister_device); |
375 | 380 | ||
376 | /* | 381 | /* |
377 | * Video fs operations | ||
378 | */ | ||
379 | static const struct file_operations video_fops = { | ||
380 | .owner = THIS_MODULE, | ||
381 | .llseek = no_llseek, | ||
382 | .open = video_open, | ||
383 | }; | ||
384 | |||
385 | /* | ||
386 | * Initialise video for linux | 382 | * Initialise video for linux |
387 | */ | 383 | */ |
388 | |||
389 | static int __init videodev_init(void) | 384 | static int __init videodev_init(void) |
390 | { | 385 | { |
386 | dev_t dev = MKDEV(VIDEO_MAJOR, 0); | ||
391 | int ret; | 387 | int ret; |
392 | 388 | ||
393 | printk(KERN_INFO "Linux video capture interface: v2.00\n"); | 389 | printk(KERN_INFO "Linux video capture interface: v2.00\n"); |
394 | if (register_chrdev(VIDEO_MAJOR, VIDEO_NAME, &video_fops)) { | 390 | ret = register_chrdev_region(dev, VIDEO_NUM_DEVICES, VIDEO_NAME); |
395 | printk(KERN_WARNING "video_dev: unable to get major %d\n", VIDEO_MAJOR); | 391 | if (ret < 0) { |
396 | return -EIO; | 392 | printk(KERN_WARNING "videodev: unable to get major %d\n", |
393 | VIDEO_MAJOR); | ||
394 | return ret; | ||
397 | } | 395 | } |
398 | 396 | ||
399 | ret = class_register(&video_class); | 397 | ret = class_register(&video_class); |
400 | if (ret < 0) { | 398 | if (ret < 0) { |
401 | unregister_chrdev(VIDEO_MAJOR, VIDEO_NAME); | 399 | unregister_chrdev_region(dev, VIDEO_NUM_DEVICES); |
402 | printk(KERN_WARNING "video_dev: class_register failed\n"); | 400 | printk(KERN_WARNING "video_dev: class_register failed\n"); |
403 | return -EIO; | 401 | return -EIO; |
404 | } | 402 | } |
@@ -408,8 +406,10 @@ static int __init videodev_init(void) | |||
408 | 406 | ||
409 | static void __exit videodev_exit(void) | 407 | static void __exit videodev_exit(void) |
410 | { | 408 | { |
409 | dev_t dev = MKDEV(VIDEO_MAJOR, 0); | ||
410 | |||
411 | class_unregister(&video_class); | 411 | class_unregister(&video_class); |
412 | unregister_chrdev(VIDEO_MAJOR, VIDEO_NAME); | 412 | unregister_chrdev_region(dev, VIDEO_NUM_DEVICES); |
413 | } | 413 | } |
414 | 414 | ||
415 | module_init(videodev_init) | 415 | module_init(videodev_init) |
diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c index 140ef92c19c1..155c9d77a463 100644 --- a/drivers/media/video/v4l2-ioctl.c +++ b/drivers/media/video/v4l2-ioctl.c | |||
@@ -746,18 +746,6 @@ static int __video_do_ioctl(struct inode *inode, struct file *file, | |||
746 | ret = ops->vidioc_enum_fmt_vid_overlay(file, | 746 | ret = ops->vidioc_enum_fmt_vid_overlay(file, |
747 | fh, f); | 747 | fh, f); |
748 | break; | 748 | break; |
749 | #if 1 | ||
750 | /* V4L2_BUF_TYPE_VBI_CAPTURE should not support VIDIOC_ENUM_FMT | ||
751 | * according to the spec. The bttv and saa7134 drivers support | ||
752 | * it though, so just warn that this is deprecated and will be | ||
753 | * removed in the near future. */ | ||
754 | case V4L2_BUF_TYPE_VBI_CAPTURE: | ||
755 | if (ops->vidioc_enum_fmt_vbi_cap) { | ||
756 | printk(KERN_WARNING "vidioc_enum_fmt_vbi_cap will be removed in 2.6.28!\n"); | ||
757 | ret = ops->vidioc_enum_fmt_vbi_cap(file, fh, f); | ||
758 | } | ||
759 | break; | ||
760 | #endif | ||
761 | case V4L2_BUF_TYPE_VIDEO_OUTPUT: | 749 | case V4L2_BUF_TYPE_VIDEO_OUTPUT: |
762 | if (ops->vidioc_enum_fmt_vid_out) | 750 | if (ops->vidioc_enum_fmt_vid_out) |
763 | ret = ops->vidioc_enum_fmt_vid_out(file, fh, f); | 751 | ret = ops->vidioc_enum_fmt_vid_out(file, fh, f); |
diff --git a/drivers/media/video/vino.c b/drivers/media/video/vino.c index 1edda456fc64..8ec57df1904f 100644 --- a/drivers/media/video/vino.c +++ b/drivers/media/video/vino.c | |||
@@ -39,7 +39,6 @@ | |||
39 | #include <linux/i2c-algo-sgi.h> | 39 | #include <linux/i2c-algo-sgi.h> |
40 | 40 | ||
41 | #include <linux/videodev2.h> | 41 | #include <linux/videodev2.h> |
42 | #include <media/v4l2-ioctl.h> | ||
43 | #include <media/v4l2-common.h> | 42 | #include <media/v4l2-common.h> |
44 | #include <media/v4l2-ioctl.h> | 43 | #include <media/v4l2-ioctl.h> |
45 | #include <linux/video_decoder.h> | 44 | #include <linux/video_decoder.h> |
@@ -810,7 +809,7 @@ static void vino_free_buffer_with_count(struct vino_framebuffer *fb, | |||
810 | dprintk("vino_free_buffer_with_count(): count = %d\n", count); | 809 | dprintk("vino_free_buffer_with_count(): count = %d\n", count); |
811 | 810 | ||
812 | for (i = 0; i < count; i++) { | 811 | for (i = 0; i < count; i++) { |
813 | ClearPageReserved(virt_to_page(fb->desc_table.virtual[i])); | 812 | ClearPageReserved(virt_to_page((void *)fb->desc_table.virtual[i])); |
814 | dma_unmap_single(NULL, | 813 | dma_unmap_single(NULL, |
815 | fb->desc_table.dma_cpu[VINO_PAGE_RATIO * i], | 814 | fb->desc_table.dma_cpu[VINO_PAGE_RATIO * i], |
816 | PAGE_SIZE, DMA_FROM_DEVICE); | 815 | PAGE_SIZE, DMA_FROM_DEVICE); |
@@ -888,7 +887,7 @@ static int vino_allocate_buffer(struct vino_framebuffer *fb, | |||
888 | dma_data_addr + VINO_PAGE_SIZE * j; | 887 | dma_data_addr + VINO_PAGE_SIZE * j; |
889 | } | 888 | } |
890 | 889 | ||
891 | SetPageReserved(virt_to_page(fb->desc_table.virtual[i])); | 890 | SetPageReserved(virt_to_page((void *)fb->desc_table.virtual[i])); |
892 | } | 891 | } |
893 | 892 | ||
894 | /* page_count needs to be set anyway, because the descriptor table has | 893 | /* page_count needs to be set anyway, because the descriptor table has |
@@ -975,7 +974,7 @@ static int vino_prepare_user_buffer(struct vino_framebuffer *fb, | |||
975 | dma_data_addr + VINO_PAGE_SIZE * j; | 974 | dma_data_addr + VINO_PAGE_SIZE * j; |
976 | } | 975 | } |
977 | 976 | ||
978 | SetPageReserved(virt_to_page(fb->desc_table.virtual[i])); | 977 | SetPageReserved(virt_to_page((void *)fb->desc_table.virtual[i])); |
979 | } | 978 | } |
980 | 979 | ||
981 | /* page_count needs to be set anyway, because the descriptor table has | 980 | /* page_count needs to be set anyway, because the descriptor table has |
@@ -4025,8 +4024,7 @@ out: | |||
4025 | 4024 | ||
4026 | static int vino_open(struct inode *inode, struct file *file) | 4025 | static int vino_open(struct inode *inode, struct file *file) |
4027 | { | 4026 | { |
4028 | struct video_device *dev = video_devdata(file); | 4027 | struct vino_channel_settings *vcs = video_drvdata(file); |
4029 | struct vino_channel_settings *vcs = video_get_drvdata(dev); | ||
4030 | int ret = 0; | 4028 | int ret = 0; |
4031 | dprintk("open(): channel = %c\n", | 4029 | dprintk("open(): channel = %c\n", |
4032 | (vcs->channel == VINO_CHANNEL_A) ? 'A' : 'B'); | 4030 | (vcs->channel == VINO_CHANNEL_A) ? 'A' : 'B'); |
@@ -4057,8 +4055,7 @@ static int vino_open(struct inode *inode, struct file *file) | |||
4057 | 4055 | ||
4058 | static int vino_close(struct inode *inode, struct file *file) | 4056 | static int vino_close(struct inode *inode, struct file *file) |
4059 | { | 4057 | { |
4060 | struct video_device *dev = video_devdata(file); | 4058 | struct vino_channel_settings *vcs = video_drvdata(file); |
4061 | struct vino_channel_settings *vcs = video_get_drvdata(dev); | ||
4062 | dprintk("close():\n"); | 4059 | dprintk("close():\n"); |
4063 | 4060 | ||
4064 | mutex_lock(&vcs->mutex); | 4061 | mutex_lock(&vcs->mutex); |
@@ -4101,8 +4098,7 @@ static struct vm_operations_struct vino_vm_ops = { | |||
4101 | 4098 | ||
4102 | static int vino_mmap(struct file *file, struct vm_area_struct *vma) | 4099 | static int vino_mmap(struct file *file, struct vm_area_struct *vma) |
4103 | { | 4100 | { |
4104 | struct video_device *dev = video_devdata(file); | 4101 | struct vino_channel_settings *vcs = video_drvdata(file); |
4105 | struct vino_channel_settings *vcs = video_get_drvdata(dev); | ||
4106 | 4102 | ||
4107 | unsigned long start = vma->vm_start; | 4103 | unsigned long start = vma->vm_start; |
4108 | unsigned long size = vma->vm_end - vma->vm_start; | 4104 | unsigned long size = vma->vm_end - vma->vm_start; |
@@ -4207,8 +4203,7 @@ out: | |||
4207 | 4203 | ||
4208 | static unsigned int vino_poll(struct file *file, poll_table *pt) | 4204 | static unsigned int vino_poll(struct file *file, poll_table *pt) |
4209 | { | 4205 | { |
4210 | struct video_device *dev = video_devdata(file); | 4206 | struct vino_channel_settings *vcs = video_drvdata(file); |
4211 | struct vino_channel_settings *vcs = video_get_drvdata(dev); | ||
4212 | unsigned int outgoing; | 4207 | unsigned int outgoing; |
4213 | unsigned int ret = 0; | 4208 | unsigned int ret = 0; |
4214 | 4209 | ||
@@ -4248,8 +4243,7 @@ error: | |||
4248 | static int vino_do_ioctl(struct inode *inode, struct file *file, | 4243 | static int vino_do_ioctl(struct inode *inode, struct file *file, |
4249 | unsigned int cmd, void *arg) | 4244 | unsigned int cmd, void *arg) |
4250 | { | 4245 | { |
4251 | struct video_device *dev = video_devdata(file); | 4246 | struct vino_channel_settings *vcs = video_drvdata(file); |
4252 | struct vino_channel_settings *vcs = video_get_drvdata(dev); | ||
4253 | 4247 | ||
4254 | #ifdef VINO_DEBUG | 4248 | #ifdef VINO_DEBUG |
4255 | switch (_IOC_TYPE(cmd)) { | 4249 | switch (_IOC_TYPE(cmd)) { |
@@ -4356,8 +4350,7 @@ static int vino_do_ioctl(struct inode *inode, struct file *file, | |||
4356 | static int vino_ioctl(struct inode *inode, struct file *file, | 4350 | static int vino_ioctl(struct inode *inode, struct file *file, |
4357 | unsigned int cmd, unsigned long arg) | 4351 | unsigned int cmd, unsigned long arg) |
4358 | { | 4352 | { |
4359 | struct video_device *dev = video_devdata(file); | 4353 | struct vino_channel_settings *vcs = video_drvdata(file); |
4360 | struct vino_channel_settings *vcs = video_get_drvdata(dev); | ||
4361 | int ret; | 4354 | int ret; |
4362 | 4355 | ||
4363 | if (mutex_lock_interruptible(&vcs->mutex)) | 4356 | if (mutex_lock_interruptible(&vcs->mutex)) |
diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c index 8ba8daafd7ea..65c8af18e767 100644 --- a/drivers/media/video/vivi.c +++ b/drivers/media/video/vivi.c | |||
@@ -898,9 +898,11 @@ static int vivi_open(struct inode *inode, struct file *file) | |||
898 | 898 | ||
899 | printk(KERN_DEBUG "vivi: open called (minor=%d)\n", minor); | 899 | printk(KERN_DEBUG "vivi: open called (minor=%d)\n", minor); |
900 | 900 | ||
901 | lock_kernel(); | ||
901 | list_for_each_entry(dev, &vivi_devlist, vivi_devlist) | 902 | list_for_each_entry(dev, &vivi_devlist, vivi_devlist) |
902 | if (dev->vfd->minor == minor) | 903 | if (dev->vfd->minor == minor) |
903 | goto found; | 904 | goto found; |
905 | unlock_kernel(); | ||
904 | return -ENODEV; | 906 | return -ENODEV; |
905 | 907 | ||
906 | found: | 908 | found: |
@@ -925,8 +927,10 @@ found: | |||
925 | } | 927 | } |
926 | unlock: | 928 | unlock: |
927 | mutex_unlock(&dev->mutex); | 929 | mutex_unlock(&dev->mutex); |
928 | if (retval) | 930 | if (retval) { |
931 | unlock_kernel(); | ||
929 | return retval; | 932 | return retval; |
933 | } | ||
930 | 934 | ||
931 | file->private_data = fh; | 935 | file->private_data = fh; |
932 | fh->dev = dev; | 936 | fh->dev = dev; |
@@ -955,6 +959,7 @@ unlock: | |||
955 | sizeof(struct vivi_buffer), fh); | 959 | sizeof(struct vivi_buffer), fh); |
956 | 960 | ||
957 | vivi_start_thread(fh); | 961 | vivi_start_thread(fh); |
962 | unlock_kernel(); | ||
958 | 963 | ||
959 | return 0; | 964 | return 0; |
960 | } | 965 | } |
diff --git a/drivers/media/video/vpx3220.c b/drivers/media/video/vpx3220.c index 35293029da02..45be9ec8edc4 100644 --- a/drivers/media/video/vpx3220.c +++ b/drivers/media/video/vpx3220.c | |||
@@ -24,8 +24,6 @@ | |||
24 | #include <linux/types.h> | 24 | #include <linux/types.h> |
25 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
26 | 26 | ||
27 | #include <linux/byteorder/swab.h> | ||
28 | |||
29 | #include <asm/io.h> | 27 | #include <asm/io.h> |
30 | #include <asm/uaccess.h> | 28 | #include <asm/uaccess.h> |
31 | 29 | ||
diff --git a/drivers/media/video/w9966.c b/drivers/media/video/w9966.c index 2ff00bc5ad64..b2dbe48a92bb 100644 --- a/drivers/media/video/w9966.c +++ b/drivers/media/video/w9966.c | |||
@@ -113,6 +113,7 @@ struct w9966_dev { | |||
113 | signed char contrast; | 113 | signed char contrast; |
114 | signed char color; | 114 | signed char color; |
115 | signed char hue; | 115 | signed char hue; |
116 | unsigned long in_use; | ||
116 | }; | 117 | }; |
117 | 118 | ||
118 | /* | 119 | /* |
@@ -184,10 +185,25 @@ static int w9966_v4l_ioctl(struct inode *inode, struct file *file, | |||
184 | static ssize_t w9966_v4l_read(struct file *file, char __user *buf, | 185 | static ssize_t w9966_v4l_read(struct file *file, char __user *buf, |
185 | size_t count, loff_t *ppos); | 186 | size_t count, loff_t *ppos); |
186 | 187 | ||
188 | static int w9966_exclusive_open(struct inode *inode, struct file *file) | ||
189 | { | ||
190 | struct w9966_dev *cam = video_drvdata(file); | ||
191 | |||
192 | return test_and_set_bit(0, &cam->in_use) ? -EBUSY : 0; | ||
193 | } | ||
194 | |||
195 | static int w9966_exclusive_release(struct inode *inode, struct file *file) | ||
196 | { | ||
197 | struct w9966_dev *cam = video_drvdata(file); | ||
198 | |||
199 | clear_bit(0, &cam->in_use); | ||
200 | return 0; | ||
201 | } | ||
202 | |||
187 | static const struct file_operations w9966_fops = { | 203 | static const struct file_operations w9966_fops = { |
188 | .owner = THIS_MODULE, | 204 | .owner = THIS_MODULE, |
189 | .open = video_exclusive_open, | 205 | .open = w9966_exclusive_open, |
190 | .release = video_exclusive_release, | 206 | .release = w9966_exclusive_release, |
191 | .ioctl = w9966_v4l_ioctl, | 207 | .ioctl = w9966_v4l_ioctl, |
192 | #ifdef CONFIG_COMPAT | 208 | #ifdef CONFIG_COMPAT |
193 | .compat_ioctl = v4l_compat_ioctl32, | 209 | .compat_ioctl = v4l_compat_ioctl32, |
@@ -198,6 +214,7 @@ static const struct file_operations w9966_fops = { | |||
198 | static struct video_device w9966_template = { | 214 | static struct video_device w9966_template = { |
199 | .name = W9966_DRIVERNAME, | 215 | .name = W9966_DRIVERNAME, |
200 | .fops = &w9966_fops, | 216 | .fops = &w9966_fops, |
217 | .release = video_device_release_empty, | ||
201 | }; | 218 | }; |
202 | 219 | ||
203 | /* | 220 | /* |
@@ -332,7 +349,7 @@ static int w9966_init(struct w9966_dev* cam, struct parport* port) | |||
332 | 349 | ||
333 | // Fill in the video_device struct and register us to v4l | 350 | // Fill in the video_device struct and register us to v4l |
334 | memcpy(&cam->vdev, &w9966_template, sizeof(struct video_device)); | 351 | memcpy(&cam->vdev, &w9966_template, sizeof(struct video_device)); |
335 | cam->vdev.priv = cam; | 352 | video_set_drvdata(&cam->vdev, cam); |
336 | 353 | ||
337 | if (video_register_device(&cam->vdev, VFL_TYPE_GRABBER, video_nr) < 0) | 354 | if (video_register_device(&cam->vdev, VFL_TYPE_GRABBER, video_nr) < 0) |
338 | return -1; | 355 | return -1; |
@@ -713,8 +730,7 @@ static int w9966_wReg_i2c(struct w9966_dev* cam, int reg, int data) | |||
713 | static int w9966_v4l_do_ioctl(struct inode *inode, struct file *file, | 730 | static int w9966_v4l_do_ioctl(struct inode *inode, struct file *file, |
714 | unsigned int cmd, void *arg) | 731 | unsigned int cmd, void *arg) |
715 | { | 732 | { |
716 | struct video_device *vdev = video_devdata(file); | 733 | struct w9966_dev *cam = video_drvdata(file); |
717 | struct w9966_dev *cam = vdev->priv; | ||
718 | 734 | ||
719 | switch(cmd) | 735 | switch(cmd) |
720 | { | 736 | { |
@@ -872,8 +888,7 @@ static int w9966_v4l_ioctl(struct inode *inode, struct file *file, | |||
872 | static ssize_t w9966_v4l_read(struct file *file, char __user *buf, | 888 | static ssize_t w9966_v4l_read(struct file *file, char __user *buf, |
873 | size_t count, loff_t *ppos) | 889 | size_t count, loff_t *ppos) |
874 | { | 890 | { |
875 | struct video_device *vdev = video_devdata(file); | 891 | struct w9966_dev *cam = video_drvdata(file); |
876 | struct w9966_dev *cam = vdev->priv; | ||
877 | unsigned char addr = 0xa0; // ECP, read, CCD-transfer, 00000 | 892 | unsigned char addr = 0xa0; // ECP, read, CCD-transfer, 00000 |
878 | unsigned char __user *dest = (unsigned char __user *)buf; | 893 | unsigned char __user *dest = (unsigned char __user *)buf; |
879 | unsigned long dleft = count; | 894 | unsigned long dleft = count; |
diff --git a/drivers/media/video/zc0301/zc0301_core.c b/drivers/media/video/zc0301/zc0301_core.c index 0c3287734c93..6a0902bcba6b 100644 --- a/drivers/media/video/zc0301/zc0301_core.c +++ b/drivers/media/video/zc0301/zc0301_core.c | |||
@@ -657,7 +657,7 @@ static int zc0301_open(struct inode* inode, struct file* filp) | |||
657 | if (!down_read_trylock(&zc0301_dev_lock)) | 657 | if (!down_read_trylock(&zc0301_dev_lock)) |
658 | return -EAGAIN; | 658 | return -EAGAIN; |
659 | 659 | ||
660 | cam = video_get_drvdata(video_devdata(filp)); | 660 | cam = video_drvdata(filp); |
661 | 661 | ||
662 | if (wait_for_completion_interruptible(&cam->probe)) { | 662 | if (wait_for_completion_interruptible(&cam->probe)) { |
663 | up_read(&zc0301_dev_lock); | 663 | up_read(&zc0301_dev_lock); |
@@ -739,7 +739,7 @@ static int zc0301_release(struct inode* inode, struct file* filp) | |||
739 | 739 | ||
740 | down_write(&zc0301_dev_lock); | 740 | down_write(&zc0301_dev_lock); |
741 | 741 | ||
742 | cam = video_get_drvdata(video_devdata(filp)); | 742 | cam = video_drvdata(filp); |
743 | 743 | ||
744 | zc0301_stop_transfer(cam); | 744 | zc0301_stop_transfer(cam); |
745 | zc0301_release_buffers(cam); | 745 | zc0301_release_buffers(cam); |
@@ -759,7 +759,7 @@ static int zc0301_release(struct inode* inode, struct file* filp) | |||
759 | static ssize_t | 759 | static ssize_t |
760 | zc0301_read(struct file* filp, char __user * buf, size_t count, loff_t* f_pos) | 760 | zc0301_read(struct file* filp, char __user * buf, size_t count, loff_t* f_pos) |
761 | { | 761 | { |
762 | struct zc0301_device* cam = video_get_drvdata(video_devdata(filp)); | 762 | struct zc0301_device *cam = video_drvdata(filp); |
763 | struct zc0301_frame_t* f, * i; | 763 | struct zc0301_frame_t* f, * i; |
764 | unsigned long lock_flags; | 764 | unsigned long lock_flags; |
765 | long timeout; | 765 | long timeout; |
@@ -866,7 +866,7 @@ exit: | |||
866 | 866 | ||
867 | static unsigned int zc0301_poll(struct file *filp, poll_table *wait) | 867 | static unsigned int zc0301_poll(struct file *filp, poll_table *wait) |
868 | { | 868 | { |
869 | struct zc0301_device* cam = video_get_drvdata(video_devdata(filp)); | 869 | struct zc0301_device *cam = video_drvdata(filp); |
870 | struct zc0301_frame_t* f; | 870 | struct zc0301_frame_t* f; |
871 | unsigned long lock_flags; | 871 | unsigned long lock_flags; |
872 | unsigned int mask = 0; | 872 | unsigned int mask = 0; |
@@ -941,7 +941,7 @@ static struct vm_operations_struct zc0301_vm_ops = { | |||
941 | 941 | ||
942 | static int zc0301_mmap(struct file* filp, struct vm_area_struct *vma) | 942 | static int zc0301_mmap(struct file* filp, struct vm_area_struct *vma) |
943 | { | 943 | { |
944 | struct zc0301_device* cam = video_get_drvdata(video_devdata(filp)); | 944 | struct zc0301_device *cam = video_drvdata(filp); |
945 | unsigned long size = vma->vm_end - vma->vm_start, | 945 | unsigned long size = vma->vm_end - vma->vm_start, |
946 | start = vma->vm_start; | 946 | start = vma->vm_start; |
947 | void *pos; | 947 | void *pos; |
@@ -1796,7 +1796,7 @@ zc0301_vidioc_s_parm(struct zc0301_device* cam, void __user * arg) | |||
1796 | static int zc0301_ioctl_v4l2(struct inode* inode, struct file* filp, | 1796 | static int zc0301_ioctl_v4l2(struct inode* inode, struct file* filp, |
1797 | unsigned int cmd, void __user * arg) | 1797 | unsigned int cmd, void __user * arg) |
1798 | { | 1798 | { |
1799 | struct zc0301_device* cam = video_get_drvdata(video_devdata(filp)); | 1799 | struct zc0301_device *cam = video_drvdata(filp); |
1800 | 1800 | ||
1801 | switch (cmd) { | 1801 | switch (cmd) { |
1802 | 1802 | ||
@@ -1891,7 +1891,7 @@ static int zc0301_ioctl_v4l2(struct inode* inode, struct file* filp, | |||
1891 | static int zc0301_ioctl(struct inode* inode, struct file* filp, | 1891 | static int zc0301_ioctl(struct inode* inode, struct file* filp, |
1892 | unsigned int cmd, unsigned long arg) | 1892 | unsigned int cmd, unsigned long arg) |
1893 | { | 1893 | { |
1894 | struct zc0301_device* cam = video_get_drvdata(video_devdata(filp)); | 1894 | struct zc0301_device *cam = video_drvdata(filp); |
1895 | int err = 0; | 1895 | int err = 0; |
1896 | 1896 | ||
1897 | if (mutex_lock_interruptible(&cam->fileop_mutex)) | 1897 | if (mutex_lock_interruptible(&cam->fileop_mutex)) |
diff --git a/drivers/media/video/zoran/Kconfig b/drivers/media/video/zoran/Kconfig new file mode 100644 index 000000000000..4ea5fa71de89 --- /dev/null +++ b/drivers/media/video/zoran/Kconfig | |||
@@ -0,0 +1,73 @@ | |||
1 | config VIDEO_ZORAN | ||
2 | tristate "Zoran ZR36057/36067 Video For Linux" | ||
3 | depends on PCI && I2C_ALGOBIT && VIDEO_V4L1 && VIRT_TO_BUS | ||
4 | help | ||
5 | Say Y for support for MJPEG capture cards based on the Zoran | ||
6 | 36057/36067 PCI controller chipset. This includes the Iomega | ||
7 | Buz, Pinnacle DC10+ and the Linux Media Labs LML33. There is | ||
8 | a driver homepage at <http://mjpeg.sf.net/driver-zoran/>. For | ||
9 | more information, check <file:Documentation/video4linux/Zoran>. | ||
10 | |||
11 | To compile this driver as a module, choose M here: the | ||
12 | module will be called zr36067. | ||
13 | |||
14 | config VIDEO_ZORAN_DC30 | ||
15 | tristate "Pinnacle/Miro DC30(+) support" | ||
16 | depends on VIDEO_ZORAN | ||
17 | select VIDEO_ADV7175 if VIDEO_HELPER_CHIPS_AUTO | ||
18 | select VIDEO_VPX3220 if VIDEO_HELPER_CHIPS_AUTO | ||
19 | help | ||
20 | Support for the Pinnacle/Miro DC30(+) MJPEG capture/playback | ||
21 | card. This also supports really old DC10 cards based on the | ||
22 | zr36050 MJPEG codec and zr36016 VFE. | ||
23 | |||
24 | config VIDEO_ZORAN_ZR36060 | ||
25 | tristate "Zoran ZR36060" | ||
26 | depends on VIDEO_ZORAN | ||
27 | help | ||
28 | Say Y to support Zoran boards based on 36060 chips. | ||
29 | This includes Iomega Buz, Pinnacle DC10, Linux media Labs 33 | ||
30 | and 33 R10 and AverMedia 6 boards. | ||
31 | |||
32 | config VIDEO_ZORAN_BUZ | ||
33 | tristate "Iomega Buz support" | ||
34 | depends on VIDEO_ZORAN_ZR36060 | ||
35 | select VIDEO_SAA7111 if VIDEO_HELPER_CHIPS_AUTO | ||
36 | select VIDEO_SAA7185 if VIDEO_HELPER_CHIPS_AUTO | ||
37 | help | ||
38 | Support for the Iomega Buz MJPEG capture/playback card. | ||
39 | |||
40 | config VIDEO_ZORAN_DC10 | ||
41 | tristate "Pinnacle/Miro DC10(+) support" | ||
42 | depends on VIDEO_ZORAN_ZR36060 | ||
43 | select VIDEO_SAA7110 if VIDEO_HELPER_CHIPS_AUTO | ||
44 | select VIDEO_ADV7175 if VIDEO_HELPER_CHIPS_AUTO | ||
45 | help | ||
46 | Support for the Pinnacle/Miro DC10(+) MJPEG capture/playback | ||
47 | card. | ||
48 | |||
49 | config VIDEO_ZORAN_LML33 | ||
50 | tristate "Linux Media Labs LML33 support" | ||
51 | depends on VIDEO_ZORAN_ZR36060 | ||
52 | select VIDEO_BT819 if VIDEO_HELPER_CHIPS_AUTO | ||
53 | select VIDEO_BT856 if VIDEO_HELPER_CHIPS_AUTO | ||
54 | help | ||
55 | Support for the Linux Media Labs LML33 MJPEG capture/playback | ||
56 | card. | ||
57 | |||
58 | config VIDEO_ZORAN_LML33R10 | ||
59 | tristate "Linux Media Labs LML33R10 support" | ||
60 | depends on VIDEO_ZORAN_ZR36060 | ||
61 | select VIDEO_SAA7114 if VIDEO_HELPER_CHIPS_AUTO | ||
62 | select VIDEO_ADV7170 if VIDEO_HELPER_CHIPS_AUTO | ||
63 | help | ||
64 | support for the Linux Media Labs LML33R10 MJPEG capture/playback | ||
65 | card. | ||
66 | |||
67 | config VIDEO_ZORAN_AVS6EYES | ||
68 | tristate "AverMedia 6 Eyes support (EXPERIMENTAL)" | ||
69 | depends on VIDEO_ZORAN_ZR36060 && EXPERIMENTAL && VIDEO_V4L1 | ||
70 | select VIDEO_BT856 if VIDEO_HELPER_CHIPS_AUTO | ||
71 | select VIDEO_KS0127 if VIDEO_HELPER_CHIPS_AUTO | ||
72 | help | ||
73 | Support for the AverMedia 6 Eyes video surveillance card. | ||
diff --git a/drivers/media/video/zoran/Makefile b/drivers/media/video/zoran/Makefile new file mode 100644 index 000000000000..44cc13352c88 --- /dev/null +++ b/drivers/media/video/zoran/Makefile | |||
@@ -0,0 +1,6 @@ | |||
1 | zr36067-objs := zoran_procfs.o zoran_device.o \ | ||
2 | zoran_driver.o zoran_card.o | ||
3 | |||
4 | obj-$(CONFIG_VIDEO_ZORAN) += zr36067.o videocodec.o | ||
5 | obj-$(CONFIG_VIDEO_ZORAN_DC30) += zr36050.o zr36016.o | ||
6 | obj-$(CONFIG_VIDEO_ZORAN_ZR36060) += zr36060.o | ||
diff --git a/drivers/media/video/videocodec.c b/drivers/media/video/zoran/videocodec.c index cf24956f3204..cf24956f3204 100644 --- a/drivers/media/video/videocodec.c +++ b/drivers/media/video/zoran/videocodec.c | |||
diff --git a/drivers/media/video/videocodec.h b/drivers/media/video/zoran/videocodec.h index 97a3bbeda505..97a3bbeda505 100644 --- a/drivers/media/video/videocodec.h +++ b/drivers/media/video/zoran/videocodec.h | |||
diff --git a/drivers/media/video/zoran.h b/drivers/media/video/zoran/zoran.h index 46b7ad477ceb..46b7ad477ceb 100644 --- a/drivers/media/video/zoran.h +++ b/drivers/media/video/zoran/zoran.h | |||
diff --git a/drivers/media/video/zoran_card.c b/drivers/media/video/zoran/zoran_card.c index 3282be730298..3282be730298 100644 --- a/drivers/media/video/zoran_card.c +++ b/drivers/media/video/zoran/zoran_card.c | |||
diff --git a/drivers/media/video/zoran_card.h b/drivers/media/video/zoran/zoran_card.h index e4dc9d29b404..e4dc9d29b404 100644 --- a/drivers/media/video/zoran_card.h +++ b/drivers/media/video/zoran/zoran_card.h | |||
diff --git a/drivers/media/video/zoran_device.c b/drivers/media/video/zoran/zoran_device.c index 88d369708e4c..5d948ff7faf0 100644 --- a/drivers/media/video/zoran_device.c +++ b/drivers/media/video/zoran/zoran_device.c | |||
@@ -58,8 +58,6 @@ | |||
58 | ZR36057_ISR_GIRQ1 | \ | 58 | ZR36057_ISR_GIRQ1 | \ |
59 | ZR36057_ISR_JPEGRepIRQ ) | 59 | ZR36057_ISR_JPEGRepIRQ ) |
60 | 60 | ||
61 | extern const struct zoran_format zoran_formats[]; | ||
62 | |||
63 | static int lml33dpath; /* default = 0 | 61 | static int lml33dpath; /* default = 0 |
64 | * 1 will use digital path in capture | 62 | * 1 will use digital path in capture |
65 | * mode instead of analog. It can be | 63 | * mode instead of analog. It can be |
@@ -377,7 +375,7 @@ zr36057_set_vfe (struct zoran *zr, | |||
377 | 375 | ||
378 | /* horizontal */ | 376 | /* horizontal */ |
379 | VidWinWid = video_width; | 377 | VidWinWid = video_width; |
380 | X = (VidWinWid * 64 + tvn->Wa - 1) / tvn->Wa; | 378 | X = DIV_ROUND_UP(VidWinWid * 64, tvn->Wa); |
381 | We = (VidWinWid * 64) / X; | 379 | We = (VidWinWid * 64) / X; |
382 | HorDcm = 64 - X; | 380 | HorDcm = 64 - X; |
383 | hcrop1 = 2 * ((tvn->Wa - We) / 4); | 381 | hcrop1 = 2 * ((tvn->Wa - We) / 4); |
@@ -403,7 +401,7 @@ zr36057_set_vfe (struct zoran *zr, | |||
403 | /* Vertical */ | 401 | /* Vertical */ |
404 | DispMode = !(video_height > BUZ_MAX_HEIGHT / 2); | 402 | DispMode = !(video_height > BUZ_MAX_HEIGHT / 2); |
405 | VidWinHt = DispMode ? video_height : video_height / 2; | 403 | VidWinHt = DispMode ? video_height : video_height / 2; |
406 | Y = (VidWinHt * 64 * 2 + tvn->Ha - 1) / tvn->Ha; | 404 | Y = DIV_ROUND_UP(VidWinHt * 64 * 2, tvn->Ha); |
407 | He = (VidWinHt * 64) / Y; | 405 | He = (VidWinHt * 64) / Y; |
408 | VerDcm = 64 - Y; | 406 | VerDcm = 64 - Y; |
409 | vcrop1 = (tvn->Ha / 2 - He) / 2; | 407 | vcrop1 = (tvn->Ha / 2 - He) / 2; |
diff --git a/drivers/media/video/zoran_device.h b/drivers/media/video/zoran/zoran_device.h index 37fa86a34083..74c6c8edb7d0 100644 --- a/drivers/media/video/zoran_device.h +++ b/drivers/media/video/zoran/zoran_device.h | |||
@@ -78,6 +78,14 @@ extern void zoran_set_pci_master(struct zoran *zr, | |||
78 | extern void zoran_init_hardware(struct zoran *zr); | 78 | extern void zoran_init_hardware(struct zoran *zr); |
79 | extern void zr36057_restart(struct zoran *zr); | 79 | extern void zr36057_restart(struct zoran *zr); |
80 | 80 | ||
81 | extern const struct zoran_format zoran_formats[]; | ||
82 | |||
83 | extern int v4l_nbufs; | ||
84 | extern int v4l_bufsize; | ||
85 | extern int jpg_nbufs; | ||
86 | extern int jpg_bufsize; | ||
87 | extern int pass_through; | ||
88 | |||
81 | /* i2c */ | 89 | /* i2c */ |
82 | extern int decoder_command(struct zoran *zr, | 90 | extern int decoder_command(struct zoran *zr, |
83 | int cmd, | 91 | int cmd, |
diff --git a/drivers/media/video/zoran_driver.c b/drivers/media/video/zoran/zoran_driver.c index 2dab9eea4def..25de7631443e 100644 --- a/drivers/media/video/zoran_driver.c +++ b/drivers/media/video/zoran/zoran_driver.c | |||
@@ -194,12 +194,6 @@ const struct zoran_format zoran_formats[] = { | |||
194 | // RJ: Test only - want to test BUZ_USE_HIMEM even when CONFIG_BIGPHYS_AREA is defined | 194 | // RJ: Test only - want to test BUZ_USE_HIMEM even when CONFIG_BIGPHYS_AREA is defined |
195 | 195 | ||
196 | 196 | ||
197 | extern int v4l_nbufs; | ||
198 | extern int v4l_bufsize; | ||
199 | extern int jpg_nbufs; | ||
200 | extern int jpg_bufsize; | ||
201 | extern int pass_through; | ||
202 | |||
203 | static int lock_norm; /* 0 = default 1 = Don't change TV standard (norm) */ | 197 | static int lock_norm; /* 0 = default 1 = Don't change TV standard (norm) */ |
204 | module_param(lock_norm, int, 0644); | 198 | module_param(lock_norm, int, 0644); |
205 | MODULE_PARM_DESC(lock_norm, "Prevent norm changes (1 = ignore, >1 = fail)"); | 199 | MODULE_PARM_DESC(lock_norm, "Prevent norm changes (1 = ignore, >1 = fail)"); |
@@ -1211,6 +1205,7 @@ zoran_open (struct inode *inode, | |||
1211 | struct zoran_fh *fh; | 1205 | struct zoran_fh *fh; |
1212 | int i, res, first_open = 0, have_module_locks = 0; | 1206 | int i, res, first_open = 0, have_module_locks = 0; |
1213 | 1207 | ||
1208 | lock_kernel(); | ||
1214 | /* find the device */ | 1209 | /* find the device */ |
1215 | for (i = 0; i < zoran_num; i++) { | 1210 | for (i = 0; i < zoran_num; i++) { |
1216 | if (zoran[i]->video_dev->minor == minor) { | 1211 | if (zoran[i]->video_dev->minor == minor) { |
@@ -1321,6 +1316,7 @@ zoran_open (struct inode *inode, | |||
1321 | file->private_data = fh; | 1316 | file->private_data = fh; |
1322 | fh->zr = zr; | 1317 | fh->zr = zr; |
1323 | zoran_open_init_session(file); | 1318 | zoran_open_init_session(file); |
1319 | unlock_kernel(); | ||
1324 | 1320 | ||
1325 | return 0; | 1321 | return 0; |
1326 | 1322 | ||
@@ -1338,6 +1334,7 @@ open_unlock_and_return: | |||
1338 | if (zr) { | 1334 | if (zr) { |
1339 | /*mutex_unlock(&zr->resource_lock);*/ | 1335 | /*mutex_unlock(&zr->resource_lock);*/ |
1340 | } | 1336 | } |
1337 | unlock_kernel(); | ||
1341 | 1338 | ||
1342 | return res; | 1339 | return res; |
1343 | } | 1340 | } |
@@ -2920,6 +2917,8 @@ zoran_do_ioctl (struct inode *inode, | |||
2920 | fmt->fmt.pix.bytesperline = 0; | 2917 | fmt->fmt.pix.bytesperline = 0; |
2921 | fmt->fmt.pix.sizeimage = | 2918 | fmt->fmt.pix.sizeimage = |
2922 | fh->jpg_buffers.buffer_size; | 2919 | fh->jpg_buffers.buffer_size; |
2920 | fmt->fmt.pix.colorspace = | ||
2921 | V4L2_COLORSPACE_SMPTE170M; | ||
2923 | 2922 | ||
2924 | /* we hereby abuse this variable to show that | 2923 | /* we hereby abuse this variable to show that |
2925 | * we're gonna do mjpeg capture */ | 2924 | * we're gonna do mjpeg capture */ |
@@ -2979,6 +2978,8 @@ zoran_do_ioctl (struct inode *inode, | |||
2979 | fmt->fmt.pix.sizeimage = | 2978 | fmt->fmt.pix.sizeimage = |
2980 | fh->v4l_settings.height * | 2979 | fh->v4l_settings.height * |
2981 | fh->v4l_settings.bytesperline; | 2980 | fh->v4l_settings.bytesperline; |
2981 | fmt->fmt.pix.colorspace = | ||
2982 | fh->v4l_settings.format->colorspace; | ||
2982 | if (BUZ_MAX_HEIGHT < | 2983 | if (BUZ_MAX_HEIGHT < |
2983 | (fh->v4l_settings.height * 2)) | 2984 | (fh->v4l_settings.height * 2)) |
2984 | fmt->fmt.pix.field = | 2985 | fmt->fmt.pix.field = |
diff --git a/drivers/media/video/zoran_procfs.c b/drivers/media/video/zoran/zoran_procfs.c index 870bc5a70e3f..870bc5a70e3f 100644 --- a/drivers/media/video/zoran_procfs.c +++ b/drivers/media/video/zoran/zoran_procfs.c | |||
diff --git a/drivers/media/video/zoran_procfs.h b/drivers/media/video/zoran/zoran_procfs.h index f2d5b1ba448f..f2d5b1ba448f 100644 --- a/drivers/media/video/zoran_procfs.h +++ b/drivers/media/video/zoran/zoran_procfs.h | |||
diff --git a/drivers/media/video/zr36016.c b/drivers/media/video/zoran/zr36016.c index 00d132bcd1e4..00d132bcd1e4 100644 --- a/drivers/media/video/zr36016.c +++ b/drivers/media/video/zoran/zr36016.c | |||
diff --git a/drivers/media/video/zr36016.h b/drivers/media/video/zoran/zr36016.h index 8c79229f69d1..8c79229f69d1 100644 --- a/drivers/media/video/zr36016.h +++ b/drivers/media/video/zoran/zr36016.h | |||
diff --git a/drivers/media/video/zr36050.c b/drivers/media/video/zoran/zr36050.c index cf8b271a1c8f..cf8b271a1c8f 100644 --- a/drivers/media/video/zr36050.c +++ b/drivers/media/video/zoran/zr36050.c | |||
diff --git a/drivers/media/video/zr36050.h b/drivers/media/video/zoran/zr36050.h index 9f52f0cdde50..9f52f0cdde50 100644 --- a/drivers/media/video/zr36050.h +++ b/drivers/media/video/zoran/zr36050.h | |||
diff --git a/drivers/media/video/zr36057.h b/drivers/media/video/zoran/zr36057.h index 54c9362aa980..54c9362aa980 100644 --- a/drivers/media/video/zr36057.h +++ b/drivers/media/video/zoran/zr36057.h | |||
diff --git a/drivers/media/video/zr36060.c b/drivers/media/video/zoran/zr36060.c index 8e74054d5ef1..8e74054d5ef1 100644 --- a/drivers/media/video/zr36060.c +++ b/drivers/media/video/zoran/zr36060.c | |||
diff --git a/drivers/media/video/zr36060.h b/drivers/media/video/zoran/zr36060.h index 914ffa4ad8d3..914ffa4ad8d3 100644 --- a/drivers/media/video/zr36060.h +++ b/drivers/media/video/zoran/zr36060.h | |||
diff --git a/drivers/media/video/zr364xx.c b/drivers/media/video/zr364xx.c index 18d1c4ba79fb..7cdac99deea6 100644 --- a/drivers/media/video/zr364xx.c +++ b/drivers/media/video/zr364xx.c | |||
@@ -52,7 +52,7 @@ | |||
52 | 52 | ||
53 | 53 | ||
54 | /* Debug macro */ | 54 | /* Debug macro */ |
55 | #define DBG(x...) if (debug) info(x) | 55 | #define DBG(x...) if (debug) printk(KERN_INFO KBUILD_MODNAME x) |
56 | 56 | ||
57 | 57 | ||
58 | /* Init methods, need to find nicer names for these | 58 | /* Init methods, need to find nicer names for these |
@@ -116,6 +116,7 @@ struct zr364xx_camera { | |||
116 | int height; | 116 | int height; |
117 | int method; | 117 | int method; |
118 | struct mutex lock; | 118 | struct mutex lock; |
119 | int users; | ||
119 | }; | 120 | }; |
120 | 121 | ||
121 | 122 | ||
@@ -127,7 +128,7 @@ static int send_control_msg(struct usb_device *udev, u8 request, u16 value, | |||
127 | 128 | ||
128 | unsigned char *transfer_buffer = kmalloc(size, GFP_KERNEL); | 129 | unsigned char *transfer_buffer = kmalloc(size, GFP_KERNEL); |
129 | if (!transfer_buffer) { | 130 | if (!transfer_buffer) { |
130 | info("kmalloc(%d) failed", size); | 131 | dev_err(&udev->dev, "kmalloc(%d) failed\n", size); |
131 | return -ENOMEM; | 132 | return -ENOMEM; |
132 | } | 133 | } |
133 | 134 | ||
@@ -143,7 +144,8 @@ static int send_control_msg(struct usb_device *udev, u8 request, u16 value, | |||
143 | kfree(transfer_buffer); | 144 | kfree(transfer_buffer); |
144 | 145 | ||
145 | if (status < 0) | 146 | if (status < 0) |
146 | info("Failed sending control message, error %d.", status); | 147 | dev_err(&udev->dev, |
148 | "Failed sending control message, error %d.\n", status); | ||
147 | 149 | ||
148 | return status; | 150 | return status; |
149 | } | 151 | } |
@@ -303,11 +305,11 @@ static int read_frame(struct zr364xx_camera *cam, int framenum) | |||
303 | DBG("buffer : %d %d", cam->buffer[0], cam->buffer[1]); | 305 | DBG("buffer : %d %d", cam->buffer[0], cam->buffer[1]); |
304 | DBG("bulk : n=%d size=%d", n, actual_length); | 306 | DBG("bulk : n=%d size=%d", n, actual_length); |
305 | if (n < 0) { | 307 | if (n < 0) { |
306 | info("error reading bulk msg"); | 308 | dev_err(&cam->udev->dev, "error reading bulk msg\n"); |
307 | return 0; | 309 | return 0; |
308 | } | 310 | } |
309 | if (actual_length < 0 || actual_length > BUFFER_SIZE) { | 311 | if (actual_length < 0 || actual_length > BUFFER_SIZE) { |
310 | info("wrong number of bytes"); | 312 | dev_err(&cam->udev->dev, "wrong number of bytes\n"); |
311 | return 0; | 313 | return 0; |
312 | } | 314 | } |
313 | 315 | ||
@@ -641,42 +643,47 @@ static int zr364xx_open(struct inode *inode, struct file *file) | |||
641 | 643 | ||
642 | DBG("zr364xx_open"); | 644 | DBG("zr364xx_open"); |
643 | 645 | ||
644 | cam->skip = 2; | 646 | mutex_lock(&cam->lock); |
645 | 647 | ||
646 | err = video_exclusive_open(inode, file); | 648 | if (cam->users) { |
647 | if (err < 0) | 649 | err = -EBUSY; |
648 | return err; | 650 | goto out; |
651 | } | ||
649 | 652 | ||
650 | if (!cam->framebuf) { | 653 | if (!cam->framebuf) { |
651 | cam->framebuf = vmalloc_32(MAX_FRAME_SIZE * FRAMES); | 654 | cam->framebuf = vmalloc_32(MAX_FRAME_SIZE * FRAMES); |
652 | if (!cam->framebuf) { | 655 | if (!cam->framebuf) { |
653 | info("vmalloc_32 failed!"); | 656 | dev_err(&cam->udev->dev, "vmalloc_32 failed!\n"); |
654 | return -ENOMEM; | 657 | err = -ENOMEM; |
658 | goto out; | ||
655 | } | 659 | } |
656 | } | 660 | } |
657 | 661 | ||
658 | mutex_lock(&cam->lock); | ||
659 | for (i = 0; init[cam->method][i].size != -1; i++) { | 662 | for (i = 0; init[cam->method][i].size != -1; i++) { |
660 | err = | 663 | err = |
661 | send_control_msg(udev, 1, init[cam->method][i].value, | 664 | send_control_msg(udev, 1, init[cam->method][i].value, |
662 | 0, init[cam->method][i].bytes, | 665 | 0, init[cam->method][i].bytes, |
663 | init[cam->method][i].size); | 666 | init[cam->method][i].size); |
664 | if (err < 0) { | 667 | if (err < 0) { |
665 | info("error during open sequence: %d", i); | 668 | dev_err(&cam->udev->dev, |
666 | mutex_unlock(&cam->lock); | 669 | "error during open sequence: %d\n", i); |
667 | return err; | 670 | goto out; |
668 | } | 671 | } |
669 | } | 672 | } |
670 | 673 | ||
674 | cam->skip = 2; | ||
675 | cam->users++; | ||
671 | file->private_data = vdev; | 676 | file->private_data = vdev; |
672 | 677 | ||
673 | /* Added some delay here, since opening/closing the camera quickly, | 678 | /* Added some delay here, since opening/closing the camera quickly, |
674 | * like Ekiga does during its startup, can crash the webcam | 679 | * like Ekiga does during its startup, can crash the webcam |
675 | */ | 680 | */ |
676 | mdelay(100); | 681 | mdelay(100); |
682 | err = 0; | ||
677 | 683 | ||
684 | out: | ||
678 | mutex_unlock(&cam->lock); | 685 | mutex_unlock(&cam->lock); |
679 | return 0; | 686 | return err; |
680 | } | 687 | } |
681 | 688 | ||
682 | 689 | ||
@@ -697,28 +704,30 @@ static int zr364xx_release(struct inode *inode, struct file *file) | |||
697 | udev = cam->udev; | 704 | udev = cam->udev; |
698 | 705 | ||
699 | mutex_lock(&cam->lock); | 706 | mutex_lock(&cam->lock); |
707 | |||
708 | cam->users--; | ||
709 | file->private_data = NULL; | ||
710 | |||
700 | for (i = 0; i < 2; i++) { | 711 | for (i = 0; i < 2; i++) { |
701 | err = | 712 | err = |
702 | send_control_msg(udev, 1, init[cam->method][i].value, | 713 | send_control_msg(udev, 1, init[cam->method][i].value, |
703 | 0, init[i][cam->method].bytes, | 714 | 0, init[i][cam->method].bytes, |
704 | init[cam->method][i].size); | 715 | init[cam->method][i].size); |
705 | if (err < 0) { | 716 | if (err < 0) { |
706 | info("error during release sequence"); | 717 | dev_err(&udev->dev, "error during release sequence\n"); |
707 | mutex_unlock(&cam->lock); | 718 | goto out; |
708 | return err; | ||
709 | } | 719 | } |
710 | } | 720 | } |
711 | 721 | ||
712 | file->private_data = NULL; | ||
713 | video_exclusive_release(inode, file); | ||
714 | |||
715 | /* Added some delay here, since opening/closing the camera quickly, | 722 | /* Added some delay here, since opening/closing the camera quickly, |
716 | * like Ekiga does during its startup, can crash the webcam | 723 | * like Ekiga does during its startup, can crash the webcam |
717 | */ | 724 | */ |
718 | mdelay(100); | 725 | mdelay(100); |
726 | err = 0; | ||
719 | 727 | ||
728 | out: | ||
720 | mutex_unlock(&cam->lock); | 729 | mutex_unlock(&cam->lock); |
721 | return 0; | 730 | return err; |
722 | } | 731 | } |
723 | 732 | ||
724 | 733 | ||
@@ -801,13 +810,14 @@ static int zr364xx_probe(struct usb_interface *intf, | |||
801 | 810 | ||
802 | DBG("probing..."); | 811 | DBG("probing..."); |
803 | 812 | ||
804 | info(DRIVER_DESC " compatible webcam plugged"); | 813 | dev_info(&intf->dev, DRIVER_DESC " compatible webcam plugged\n"); |
805 | info("model %04x:%04x detected", udev->descriptor.idVendor, | 814 | dev_info(&intf->dev, "model %04x:%04x detected\n", |
806 | udev->descriptor.idProduct); | 815 | le16_to_cpu(udev->descriptor.idVendor), |
816 | le16_to_cpu(udev->descriptor.idProduct)); | ||
807 | 817 | ||
808 | cam = kzalloc(sizeof(struct zr364xx_camera), GFP_KERNEL); | 818 | cam = kzalloc(sizeof(struct zr364xx_camera), GFP_KERNEL); |
809 | if (cam == NULL) { | 819 | if (cam == NULL) { |
810 | info("cam: out of memory !"); | 820 | dev_err(&udev->dev, "cam: out of memory !\n"); |
811 | return -ENOMEM; | 821 | return -ENOMEM; |
812 | } | 822 | } |
813 | /* save the init method used by this camera */ | 823 | /* save the init method used by this camera */ |
@@ -815,7 +825,7 @@ static int zr364xx_probe(struct usb_interface *intf, | |||
815 | 825 | ||
816 | cam->vdev = video_device_alloc(); | 826 | cam->vdev = video_device_alloc(); |
817 | if (cam->vdev == NULL) { | 827 | if (cam->vdev == NULL) { |
818 | info("cam->vdev: out of memory !"); | 828 | dev_err(&udev->dev, "cam->vdev: out of memory !\n"); |
819 | kfree(cam); | 829 | kfree(cam); |
820 | return -ENOMEM; | 830 | return -ENOMEM; |
821 | } | 831 | } |
@@ -827,7 +837,7 @@ static int zr364xx_probe(struct usb_interface *intf, | |||
827 | cam->udev = udev; | 837 | cam->udev = udev; |
828 | 838 | ||
829 | if ((cam->buffer = kmalloc(BUFFER_SIZE, GFP_KERNEL)) == NULL) { | 839 | if ((cam->buffer = kmalloc(BUFFER_SIZE, GFP_KERNEL)) == NULL) { |
830 | info("cam->buffer: out of memory !"); | 840 | dev_info(&udev->dev, "cam->buffer: out of memory !\n"); |
831 | video_device_release(cam->vdev); | 841 | video_device_release(cam->vdev); |
832 | kfree(cam); | 842 | kfree(cam); |
833 | return -ENODEV; | 843 | return -ENODEV; |
@@ -835,17 +845,17 @@ static int zr364xx_probe(struct usb_interface *intf, | |||
835 | 845 | ||
836 | switch (mode) { | 846 | switch (mode) { |
837 | case 1: | 847 | case 1: |
838 | info("160x120 mode selected"); | 848 | dev_info(&udev->dev, "160x120 mode selected\n"); |
839 | cam->width = 160; | 849 | cam->width = 160; |
840 | cam->height = 120; | 850 | cam->height = 120; |
841 | break; | 851 | break; |
842 | case 2: | 852 | case 2: |
843 | info("640x480 mode selected"); | 853 | dev_info(&udev->dev, "640x480 mode selected\n"); |
844 | cam->width = 640; | 854 | cam->width = 640; |
845 | cam->height = 480; | 855 | cam->height = 480; |
846 | break; | 856 | break; |
847 | default: | 857 | default: |
848 | info("320x240 mode selected"); | 858 | dev_info(&udev->dev, "320x240 mode selected\n"); |
849 | cam->width = 320; | 859 | cam->width = 320; |
850 | cam->height = 240; | 860 | cam->height = 240; |
851 | break; | 861 | break; |
@@ -865,7 +875,7 @@ static int zr364xx_probe(struct usb_interface *intf, | |||
865 | 875 | ||
866 | err = video_register_device(cam->vdev, VFL_TYPE_GRABBER, -1); | 876 | err = video_register_device(cam->vdev, VFL_TYPE_GRABBER, -1); |
867 | if (err) { | 877 | if (err) { |
868 | info("video_register_device failed"); | 878 | dev_err(&udev->dev, "video_register_device failed\n"); |
869 | video_device_release(cam->vdev); | 879 | video_device_release(cam->vdev); |
870 | kfree(cam->buffer); | 880 | kfree(cam->buffer); |
871 | kfree(cam); | 881 | kfree(cam); |
@@ -874,7 +884,8 @@ static int zr364xx_probe(struct usb_interface *intf, | |||
874 | 884 | ||
875 | usb_set_intfdata(intf, cam); | 885 | usb_set_intfdata(intf, cam); |
876 | 886 | ||
877 | info(DRIVER_DESC " controlling video device %d", cam->vdev->minor); | 887 | dev_info(&udev->dev, DRIVER_DESC " controlling video device %d\n", |
888 | cam->vdev->minor); | ||
878 | return 0; | 889 | return 0; |
879 | } | 890 | } |
880 | 891 | ||
@@ -884,7 +895,7 @@ static void zr364xx_disconnect(struct usb_interface *intf) | |||
884 | struct zr364xx_camera *cam = usb_get_intfdata(intf); | 895 | struct zr364xx_camera *cam = usb_get_intfdata(intf); |
885 | usb_set_intfdata(intf, NULL); | 896 | usb_set_intfdata(intf, NULL); |
886 | dev_set_drvdata(&intf->dev, NULL); | 897 | dev_set_drvdata(&intf->dev, NULL); |
887 | info(DRIVER_DESC " webcam unplugged"); | 898 | dev_info(&intf->dev, DRIVER_DESC " webcam unplugged\n"); |
888 | if (cam->vdev) | 899 | if (cam->vdev) |
889 | video_unregister_device(cam->vdev); | 900 | video_unregister_device(cam->vdev); |
890 | cam->vdev = NULL; | 901 | cam->vdev = NULL; |
@@ -913,16 +924,16 @@ static int __init zr364xx_init(void) | |||
913 | int retval; | 924 | int retval; |
914 | retval = usb_register(&zr364xx_driver); | 925 | retval = usb_register(&zr364xx_driver); |
915 | if (retval) | 926 | if (retval) |
916 | info("usb_register failed!"); | 927 | printk(KERN_ERR KBUILD_MODNAME ": usb_register failed!\n"); |
917 | else | 928 | else |
918 | info(DRIVER_DESC " module loaded"); | 929 | printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_DESC "\n"); |
919 | return retval; | 930 | return retval; |
920 | } | 931 | } |
921 | 932 | ||
922 | 933 | ||
923 | static void __exit zr364xx_exit(void) | 934 | static void __exit zr364xx_exit(void) |
924 | { | 935 | { |
925 | info(DRIVER_DESC " module unloaded"); | 936 | printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_DESC " module unloaded\n"); |
926 | usb_deregister(&zr364xx_driver); | 937 | usb_deregister(&zr364xx_driver); |
927 | } | 938 | } |
928 | 939 | ||