diff options
Diffstat (limited to 'drivers/media/video/cx18')
-rw-r--r-- | drivers/media/video/cx18/Kconfig | 5 | ||||
-rw-r--r-- | drivers/media/video/cx18/cx18-av-core.c | 81 | ||||
-rw-r--r-- | drivers/media/video/cx18/cx18-cards.c | 27 | ||||
-rw-r--r-- | drivers/media/video/cx18/cx18-cards.h | 5 | ||||
-rw-r--r-- | drivers/media/video/cx18/cx18-controls.c | 6 | ||||
-rw-r--r-- | drivers/media/video/cx18/cx18-driver.c | 55 | ||||
-rw-r--r-- | drivers/media/video/cx18/cx18-driver.h | 12 | ||||
-rw-r--r-- | drivers/media/video/cx18/cx18-dvb.c | 40 | ||||
-rw-r--r-- | drivers/media/video/cx18/cx18-fileops.c | 19 | ||||
-rw-r--r-- | drivers/media/video/cx18/cx18-fileops.h | 9 | ||||
-rw-r--r-- | drivers/media/video/cx18/cx18-gpio.c | 48 | ||||
-rw-r--r-- | drivers/media/video/cx18/cx18-i2c.c | 10 | ||||
-rw-r--r-- | drivers/media/video/cx18/cx18-ioctl.c | 12 | ||||
-rw-r--r-- | drivers/media/video/cx18/cx18-irq.c | 12 | ||||
-rw-r--r-- | drivers/media/video/cx18/cx18-mailbox.c | 8 | ||||
-rw-r--r-- | drivers/media/video/cx18/cx18-queue.c | 22 | ||||
-rw-r--r-- | drivers/media/video/cx18/cx18-queue.h | 4 | ||||
-rw-r--r-- | drivers/media/video/cx18/cx18-streams.c | 50 | ||||
-rw-r--r-- | drivers/media/video/cx18/cx18-streams.h | 2 |
19 files changed, 225 insertions, 202 deletions
diff --git a/drivers/media/video/cx18/Kconfig b/drivers/media/video/cx18/Kconfig index acc4b47f1d1d..5f942690570c 100644 --- a/drivers/media/video/cx18/Kconfig +++ b/drivers/media/video/cx18/Kconfig | |||
@@ -1,14 +1,17 @@ | |||
1 | config VIDEO_CX18 | 1 | config VIDEO_CX18 |
2 | tristate "Conexant cx23418 MPEG encoder support" | 2 | tristate "Conexant cx23418 MPEG encoder support" |
3 | depends on VIDEO_V4L2 && DVB_CORE && PCI && I2C && EXPERIMENTAL | 3 | depends on VIDEO_V4L2 && DVB_CORE && PCI && I2C && EXPERIMENTAL |
4 | depends on INPUT # due to VIDEO_IR | ||
5 | depends on HOTPLUG # due to FW_LOADER | ||
4 | select I2C_ALGOBIT | 6 | select I2C_ALGOBIT |
5 | select FW_LOADER | 7 | select FW_LOADER |
6 | select VIDEO_IR | 8 | select VIDEO_IR |
7 | select MEDIA_TUNER | 9 | select VIDEO_TUNER |
8 | select VIDEO_TVEEPROM | 10 | select VIDEO_TVEEPROM |
9 | select VIDEO_CX2341X | 11 | select VIDEO_CX2341X |
10 | select VIDEO_CS5345 | 12 | select VIDEO_CS5345 |
11 | select DVB_S5H1409 | 13 | select DVB_S5H1409 |
14 | select MEDIA_TUNER_MXL5005S | ||
12 | ---help--- | 15 | ---help--- |
13 | This is a video4linux driver for Conexant cx23418 based | 16 | This is a video4linux driver for Conexant cx23418 based |
14 | PCI combo video recorder devices. | 17 | PCI combo video recorder devices. |
diff --git a/drivers/media/video/cx18/cx18-av-core.c b/drivers/media/video/cx18/cx18-av-core.c index 66864904c99b..9a26751615c6 100644 --- a/drivers/media/video/cx18/cx18-av-core.c +++ b/drivers/media/video/cx18/cx18-av-core.c | |||
@@ -182,14 +182,16 @@ static void input_change(struct cx18 *cx) | |||
182 | if (std == V4L2_STD_NTSC_M_JP) { | 182 | if (std == V4L2_STD_NTSC_M_JP) { |
183 | /* Japan uses EIAJ audio standard */ | 183 | /* Japan uses EIAJ audio standard */ |
184 | cx18_av_write(cx, 0x808, 0xf7); | 184 | cx18_av_write(cx, 0x808, 0xf7); |
185 | cx18_av_write(cx, 0x80b, 0x02); | ||
185 | } else if (std == V4L2_STD_NTSC_M_KR) { | 186 | } else if (std == V4L2_STD_NTSC_M_KR) { |
186 | /* South Korea uses A2 audio standard */ | 187 | /* South Korea uses A2 audio standard */ |
187 | cx18_av_write(cx, 0x808, 0xf8); | 188 | cx18_av_write(cx, 0x808, 0xf8); |
189 | cx18_av_write(cx, 0x80b, 0x03); | ||
188 | } else { | 190 | } else { |
189 | /* Others use the BTSC audio standard */ | 191 | /* Others use the BTSC audio standard */ |
190 | cx18_av_write(cx, 0x808, 0xf6); | 192 | cx18_av_write(cx, 0x808, 0xf6); |
193 | cx18_av_write(cx, 0x80b, 0x01); | ||
191 | } | 194 | } |
192 | cx18_av_write(cx, 0x80b, 0x00); | ||
193 | } else if (std & V4L2_STD_PAL) { | 195 | } else if (std & V4L2_STD_PAL) { |
194 | /* Follow tuner change procedure for PAL */ | 196 | /* Follow tuner change procedure for PAL */ |
195 | cx18_av_write(cx, 0x808, 0xff); | 197 | cx18_av_write(cx, 0x808, 0xff); |
@@ -741,8 +743,8 @@ static void log_audio_status(struct cx18 *cx) | |||
741 | { | 743 | { |
742 | struct cx18_av_state *state = &cx->av_state; | 744 | struct cx18_av_state *state = &cx->av_state; |
743 | u8 download_ctl = cx18_av_read(cx, 0x803); | 745 | u8 download_ctl = cx18_av_read(cx, 0x803); |
744 | u8 mod_det_stat0 = cx18_av_read(cx, 0x805); | 746 | u8 mod_det_stat0 = cx18_av_read(cx, 0x804); |
745 | u8 mod_det_stat1 = cx18_av_read(cx, 0x804); | 747 | u8 mod_det_stat1 = cx18_av_read(cx, 0x805); |
746 | u8 audio_config = cx18_av_read(cx, 0x808); | 748 | u8 audio_config = cx18_av_read(cx, 0x808); |
747 | u8 pref_mode = cx18_av_read(cx, 0x809); | 749 | u8 pref_mode = cx18_av_read(cx, 0x809); |
748 | u8 afc0 = cx18_av_read(cx, 0x80b); | 750 | u8 afc0 = cx18_av_read(cx, 0x80b); |
@@ -760,12 +762,12 @@ static void log_audio_status(struct cx18 *cx) | |||
760 | case 0x12: p = "dual with SAP"; break; | 762 | case 0x12: p = "dual with SAP"; break; |
761 | case 0x14: p = "tri with SAP"; break; | 763 | case 0x14: p = "tri with SAP"; break; |
762 | case 0xfe: p = "forced mode"; break; | 764 | case 0xfe: p = "forced mode"; break; |
763 | default: p = "not defined"; | 765 | default: p = "not defined"; break; |
764 | } | 766 | } |
765 | CX18_INFO("Detected audio mode: %s\n", p); | 767 | CX18_INFO("Detected audio mode: %s\n", p); |
766 | 768 | ||
767 | switch (mod_det_stat1) { | 769 | switch (mod_det_stat1) { |
768 | case 0x00: p = "BTSC"; break; | 770 | case 0x00: p = "not defined"; break; |
769 | case 0x01: p = "EIAJ"; break; | 771 | case 0x01: p = "EIAJ"; break; |
770 | case 0x02: p = "A2-M"; break; | 772 | case 0x02: p = "A2-M"; break; |
771 | case 0x03: p = "A2-BG"; break; | 773 | case 0x03: p = "A2-BG"; break; |
@@ -779,8 +781,13 @@ static void log_audio_status(struct cx18 *cx) | |||
779 | case 0x0b: p = "NICAM-I"; break; | 781 | case 0x0b: p = "NICAM-I"; break; |
780 | case 0x0c: p = "NICAM-L"; break; | 782 | case 0x0c: p = "NICAM-L"; break; |
781 | case 0x0d: p = "BTSC/EIAJ/A2-M Mono (4.5 MHz FMMono)"; break; | 783 | case 0x0d: p = "BTSC/EIAJ/A2-M Mono (4.5 MHz FMMono)"; break; |
784 | case 0x0e: p = "IF FM Radio"; break; | ||
785 | case 0x0f: p = "BTSC"; break; | ||
786 | case 0x10: p = "detected chrominance"; break; | ||
787 | case 0xfd: p = "unknown audio standard"; break; | ||
788 | case 0xfe: p = "forced audio standard"; break; | ||
782 | case 0xff: p = "no detected audio standard"; break; | 789 | case 0xff: p = "no detected audio standard"; break; |
783 | default: p = "not defined"; | 790 | default: p = "not defined"; break; |
784 | } | 791 | } |
785 | CX18_INFO("Detected audio standard: %s\n", p); | 792 | CX18_INFO("Detected audio standard: %s\n", p); |
786 | CX18_INFO("Audio muted: %s\n", | 793 | CX18_INFO("Audio muted: %s\n", |
@@ -789,22 +796,23 @@ static void log_audio_status(struct cx18 *cx) | |||
789 | (download_ctl & 0x10) ? "running" : "stopped"); | 796 | (download_ctl & 0x10) ? "running" : "stopped"); |
790 | 797 | ||
791 | switch (audio_config >> 4) { | 798 | switch (audio_config >> 4) { |
792 | case 0x00: p = "BTSC"; break; | 799 | case 0x00: p = "undefined"; break; |
793 | case 0x01: p = "EIAJ"; break; | 800 | case 0x01: p = "BTSC"; break; |
794 | case 0x02: p = "A2-M"; break; | 801 | case 0x02: p = "EIAJ"; break; |
795 | case 0x03: p = "A2-BG"; break; | 802 | case 0x03: p = "A2-M"; break; |
796 | case 0x04: p = "A2-DK1"; break; | 803 | case 0x04: p = "A2-BG"; break; |
797 | case 0x05: p = "A2-DK2"; break; | 804 | case 0x05: p = "A2-DK1"; break; |
798 | case 0x06: p = "A2-DK3"; break; | 805 | case 0x06: p = "A2-DK2"; break; |
799 | case 0x07: p = "A1 (6.0 MHz FM Mono)"; break; | 806 | case 0x07: p = "A2-DK3"; break; |
800 | case 0x08: p = "AM-L"; break; | 807 | case 0x08: p = "A1 (6.0 MHz FM Mono)"; break; |
801 | case 0x09: p = "NICAM-BG"; break; | 808 | case 0x09: p = "AM-L"; break; |
802 | case 0x0a: p = "NICAM-DK"; break; | 809 | case 0x0a: p = "NICAM-BG"; break; |
803 | case 0x0b: p = "NICAM-I"; break; | 810 | case 0x0b: p = "NICAM-DK"; break; |
804 | case 0x0c: p = "NICAM-L"; break; | 811 | case 0x0c: p = "NICAM-I"; break; |
805 | case 0x0d: p = "FM radio"; break; | 812 | case 0x0d: p = "NICAM-L"; break; |
813 | case 0x0e: p = "FM radio"; break; | ||
806 | case 0x0f: p = "automatic detection"; break; | 814 | case 0x0f: p = "automatic detection"; break; |
807 | default: p = "undefined"; | 815 | default: p = "undefined"; break; |
808 | } | 816 | } |
809 | CX18_INFO("Configured audio standard: %s\n", p); | 817 | CX18_INFO("Configured audio standard: %s\n", p); |
810 | 818 | ||
@@ -815,12 +823,9 @@ static void log_audio_status(struct cx18 *cx) | |||
815 | case 0x02: p = "MONO3 (STEREO forced MONO)"; break; | 823 | case 0x02: p = "MONO3 (STEREO forced MONO)"; break; |
816 | case 0x03: p = "MONO4 (NICAM ANALOG-Language C/Analog Fallback)"; break; | 824 | case 0x03: p = "MONO4 (NICAM ANALOG-Language C/Analog Fallback)"; break; |
817 | case 0x04: p = "STEREO"; break; | 825 | case 0x04: p = "STEREO"; break; |
818 | case 0x05: p = "DUAL1 (AB)"; break; | 826 | case 0x05: p = "DUAL1 (AC)"; break; |
819 | case 0x06: p = "DUAL2 (AC) (FM)"; break; | 827 | case 0x06: p = "DUAL2 (BC)"; break; |
820 | case 0x07: p = "DUAL3 (BC) (FM)"; break; | 828 | case 0x07: p = "DUAL3 (AB)"; break; |
821 | case 0x08: p = "DUAL4 (AC) (AM)"; break; | ||
822 | case 0x09: p = "DUAL5 (BC) (AM)"; break; | ||
823 | case 0x0a: p = "SAP"; break; | ||
824 | default: p = "undefined"; | 829 | default: p = "undefined"; |
825 | } | 830 | } |
826 | CX18_INFO("Configured audio mode: %s\n", p); | 831 | CX18_INFO("Configured audio mode: %s\n", p); |
@@ -835,9 +840,11 @@ static void log_audio_status(struct cx18 *cx) | |||
835 | case 0x06: p = "BTSC"; break; | 840 | case 0x06: p = "BTSC"; break; |
836 | case 0x07: p = "EIAJ"; break; | 841 | case 0x07: p = "EIAJ"; break; |
837 | case 0x08: p = "A2-M"; break; | 842 | case 0x08: p = "A2-M"; break; |
838 | case 0x09: p = "FM Radio"; break; | 843 | case 0x09: p = "FM Radio (4.5 MHz)"; break; |
844 | case 0x0a: p = "FM Radio (5.5 MHz)"; break; | ||
845 | case 0x0b: p = "S-Video"; break; | ||
839 | case 0x0f: p = "automatic standard and mode detection"; break; | 846 | case 0x0f: p = "automatic standard and mode detection"; break; |
840 | default: p = "undefined"; | 847 | default: p = "undefined"; break; |
841 | } | 848 | } |
842 | CX18_INFO("Configured audio system: %s\n", p); | 849 | CX18_INFO("Configured audio system: %s\n", p); |
843 | } | 850 | } |
@@ -857,22 +864,24 @@ static void log_audio_status(struct cx18 *cx) | |||
857 | case 5: p = "language AC"; break; | 864 | case 5: p = "language AC"; break; |
858 | case 6: p = "language BC"; break; | 865 | case 6: p = "language BC"; break; |
859 | case 7: p = "language AB"; break; | 866 | case 7: p = "language AB"; break; |
860 | default: p = "undefined"; | 867 | default: p = "undefined"; break; |
861 | } | 868 | } |
862 | CX18_INFO("Preferred audio mode: %s\n", p); | 869 | CX18_INFO("Preferred audio mode: %s\n", p); |
863 | 870 | ||
864 | if ((audio_config & 0xf) == 0xf) { | 871 | if ((audio_config & 0xf) == 0xf) { |
865 | switch ((afc0 >> 2) & 0x1) { | 872 | switch ((afc0 >> 3) & 0x1) { |
866 | case 0: p = "system DK"; break; | 873 | case 0: p = "system DK"; break; |
867 | case 1: p = "system L"; break; | 874 | case 1: p = "system L"; break; |
868 | } | 875 | } |
869 | CX18_INFO("Selected 65 MHz format: %s\n", p); | 876 | CX18_INFO("Selected 65 MHz format: %s\n", p); |
870 | 877 | ||
871 | switch (afc0 & 0x3) { | 878 | switch (afc0 & 0x7) { |
872 | case 0: p = "BTSC"; break; | 879 | case 0: p = "Chroma"; break; |
873 | case 1: p = "EIAJ"; break; | 880 | case 1: p = "BTSC"; break; |
874 | case 2: p = "A2-M"; break; | 881 | case 2: p = "EIAJ"; break; |
875 | default: p = "undefined"; | 882 | case 3: p = "A2-M"; break; |
883 | case 4: p = "autodetect"; break; | ||
884 | default: p = "undefined"; break; | ||
876 | } | 885 | } |
877 | CX18_INFO("Selected 45 MHz format: %s\n", p); | 886 | CX18_INFO("Selected 45 MHz format: %s\n", p); |
878 | } | 887 | } |
diff --git a/drivers/media/video/cx18/cx18-cards.c b/drivers/media/video/cx18/cx18-cards.c index f5e3ba1f5354..baccd079243d 100644 --- a/drivers/media/video/cx18/cx18-cards.c +++ b/drivers/media/video/cx18/cx18-cards.c | |||
@@ -47,11 +47,12 @@ static struct cx18_card_tuner_i2c cx18_i2c_std = { | |||
47 | static const struct cx18_card cx18_card_hvr1600_esmt = { | 47 | static const struct cx18_card cx18_card_hvr1600_esmt = { |
48 | .type = CX18_CARD_HVR_1600_ESMT, | 48 | .type = CX18_CARD_HVR_1600_ESMT, |
49 | .name = "Hauppauge HVR-1600", | 49 | .name = "Hauppauge HVR-1600", |
50 | .comment = "DVB & VBI are not yet supported\n", | 50 | .comment = "VBI is not yet supported\n", |
51 | .v4l2_capabilities = CX18_CAP_ENCODER, | 51 | .v4l2_capabilities = CX18_CAP_ENCODER, |
52 | .hw_audio_ctrl = CX18_HW_CX23418, | 52 | .hw_audio_ctrl = CX18_HW_CX23418, |
53 | .hw_muxer = CX18_HW_CS5345, | 53 | .hw_muxer = CX18_HW_CS5345, |
54 | .hw_all = CX18_HW_TVEEPROM | CX18_HW_TUNER | CX18_HW_CS5345, | 54 | .hw_all = CX18_HW_TVEEPROM | CX18_HW_TUNER | |
55 | CX18_HW_CS5345 | CX18_HW_DVB, | ||
55 | .video_inputs = { | 56 | .video_inputs = { |
56 | { CX18_CARD_INPUT_VID_TUNER, 0, CX23418_COMPOSITE7 }, | 57 | { CX18_CARD_INPUT_VID_TUNER, 0, CX23418_COMPOSITE7 }, |
57 | { CX18_CARD_INPUT_SVIDEO1, 1, CX23418_SVIDEO1 }, | 58 | { CX18_CARD_INPUT_SVIDEO1, 1, CX23418_SVIDEO1 }, |
@@ -86,11 +87,12 @@ static const struct cx18_card cx18_card_hvr1600_esmt = { | |||
86 | static const struct cx18_card cx18_card_hvr1600_samsung = { | 87 | static const struct cx18_card cx18_card_hvr1600_samsung = { |
87 | .type = CX18_CARD_HVR_1600_SAMSUNG, | 88 | .type = CX18_CARD_HVR_1600_SAMSUNG, |
88 | .name = "Hauppauge HVR-1600 (Preproduction)", | 89 | .name = "Hauppauge HVR-1600 (Preproduction)", |
89 | .comment = "DVB & VBI are not yet supported\n", | 90 | .comment = "VBI is not yet supported\n", |
90 | .v4l2_capabilities = CX18_CAP_ENCODER, | 91 | .v4l2_capabilities = CX18_CAP_ENCODER, |
91 | .hw_audio_ctrl = CX18_HW_CX23418, | 92 | .hw_audio_ctrl = CX18_HW_CX23418, |
92 | .hw_muxer = CX18_HW_CS5345, | 93 | .hw_muxer = CX18_HW_CS5345, |
93 | .hw_all = CX18_HW_TVEEPROM | CX18_HW_TUNER | CX18_HW_CS5345, | 94 | .hw_all = CX18_HW_TVEEPROM | CX18_HW_TUNER | |
95 | CX18_HW_CS5345 | CX18_HW_DVB, | ||
94 | .video_inputs = { | 96 | .video_inputs = { |
95 | { CX18_CARD_INPUT_VID_TUNER, 0, CX23418_COMPOSITE7 }, | 97 | { CX18_CARD_INPUT_VID_TUNER, 0, CX23418_COMPOSITE7 }, |
96 | { CX18_CARD_INPUT_SVIDEO1, 1, CX23418_SVIDEO1 }, | 98 | { CX18_CARD_INPUT_SVIDEO1, 1, CX23418_SVIDEO1 }, |
@@ -124,7 +126,7 @@ static const struct cx18_card cx18_card_hvr1600_samsung = { | |||
124 | 126 | ||
125 | /* ------------------------------------------------------------------------- */ | 127 | /* ------------------------------------------------------------------------- */ |
126 | 128 | ||
127 | /* Compro VideoMate H900: not working at the moment! */ | 129 | /* Compro VideoMate H900: note that this card is analog only! */ |
128 | 130 | ||
129 | static const struct cx18_card_pci_info cx18_pci_h900[] = { | 131 | static const struct cx18_card_pci_info cx18_pci_h900[] = { |
130 | { PCI_DEVICE_ID_CX23418, CX18_PCI_ID_COMPRO, 0xe100 }, | 132 | { PCI_DEVICE_ID_CX23418, CX18_PCI_ID_COMPRO, 0xe100 }, |
@@ -134,14 +136,15 @@ static const struct cx18_card_pci_info cx18_pci_h900[] = { | |||
134 | static const struct cx18_card cx18_card_h900 = { | 136 | static const struct cx18_card cx18_card_h900 = { |
135 | .type = CX18_CARD_COMPRO_H900, | 137 | .type = CX18_CARD_COMPRO_H900, |
136 | .name = "Compro VideoMate H900", | 138 | .name = "Compro VideoMate H900", |
137 | .comment = "Not yet supported!\n", | 139 | .comment = "VBI is not yet supported\n", |
138 | .v4l2_capabilities = 0, | 140 | .v4l2_capabilities = CX18_CAP_ENCODER, |
139 | .hw_audio_ctrl = CX18_HW_CX23418, | 141 | .hw_audio_ctrl = CX18_HW_CX23418, |
140 | .hw_all = CX18_HW_TUNER, | 142 | .hw_all = CX18_HW_TUNER, |
141 | .video_inputs = { | 143 | .video_inputs = { |
142 | { CX18_CARD_INPUT_VID_TUNER, 0, CX23418_COMPOSITE7 }, | 144 | { CX18_CARD_INPUT_VID_TUNER, 0, CX23418_COMPOSITE2 }, |
143 | { CX18_CARD_INPUT_SVIDEO1, 1, CX23418_SVIDEO1 }, | 145 | { CX18_CARD_INPUT_SVIDEO1, 1, |
144 | { CX18_CARD_INPUT_COMPOSITE1, 1, CX23418_COMPOSITE3 }, | 146 | CX23418_SVIDEO_LUMA3 | CX23418_SVIDEO_CHROMA4 }, |
147 | { CX18_CARD_INPUT_COMPOSITE1, 1, CX23418_COMPOSITE1 }, | ||
145 | }, | 148 | }, |
146 | .audio_inputs = { | 149 | .audio_inputs = { |
147 | { CX18_CARD_INPUT_AUD_TUNER, | 150 | { CX18_CARD_INPUT_AUD_TUNER, |
@@ -163,6 +166,7 @@ static const struct cx18_card cx18_card_h900 = { | |||
163 | .tune_lane = 0, | 166 | .tune_lane = 0, |
164 | .initial_emrs = 0, | 167 | .initial_emrs = 0, |
165 | }, | 168 | }, |
169 | .xceive_pin = 15, | ||
166 | .pci_list = cx18_pci_h900, | 170 | .pci_list = cx18_pci_h900, |
167 | .i2c = &cx18_i2c_std, | 171 | .i2c = &cx18_i2c_std, |
168 | }; | 172 | }; |
@@ -200,8 +204,6 @@ static const struct cx18_card cx18_card_mpc718 = { | |||
200 | /* XC3028 tuner */ | 204 | /* XC3028 tuner */ |
201 | { .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 }, | 205 | { .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 }, |
202 | }, | 206 | }, |
203 | /* tuner reset */ | ||
204 | .gpio_init = { .direction = 0x1000, .initial_value = 0x1000 }, | ||
205 | .ddr = { | 207 | .ddr = { |
206 | /* Probably Samsung K4D263238G-VC33 memory */ | 208 | /* Probably Samsung K4D263238G-VC33 memory */ |
207 | .chip_config = 0x003, | 209 | .chip_config = 0x003, |
@@ -211,6 +213,7 @@ static const struct cx18_card cx18_card_mpc718 = { | |||
211 | .tune_lane = 0, | 213 | .tune_lane = 0, |
212 | .initial_emrs = 2, | 214 | .initial_emrs = 2, |
213 | }, | 215 | }, |
216 | .xceive_pin = 15, | ||
214 | .pci_list = cx18_pci_mpc718, | 217 | .pci_list = cx18_pci_mpc718, |
215 | .i2c = &cx18_i2c_std, | 218 | .i2c = &cx18_i2c_std, |
216 | }; | 219 | }; |
diff --git a/drivers/media/video/cx18/cx18-cards.h b/drivers/media/video/cx18/cx18-cards.h index bca249bdd337..bccb67f0db16 100644 --- a/drivers/media/video/cx18/cx18-cards.h +++ b/drivers/media/video/cx18/cx18-cards.h | |||
@@ -114,8 +114,8 @@ struct cx18_card_pci_info { | |||
114 | /* The mask is the set of bits used by the operation */ | 114 | /* The mask is the set of bits used by the operation */ |
115 | 115 | ||
116 | struct cx18_gpio_init { /* set initial GPIO DIR and OUT values */ | 116 | struct cx18_gpio_init { /* set initial GPIO DIR and OUT values */ |
117 | u16 direction; /* DIR setting. Leave to 0 if no init is needed */ | 117 | u32 direction; /* DIR setting. Leave to 0 if no init is needed */ |
118 | u16 initial_value; | 118 | u32 initial_value; |
119 | }; | 119 | }; |
120 | 120 | ||
121 | struct cx18_card_tuner { | 121 | struct cx18_card_tuner { |
@@ -153,6 +153,7 @@ struct cx18_card { | |||
153 | struct cx18_card_audio_input radio_input; | 153 | struct cx18_card_audio_input radio_input; |
154 | 154 | ||
155 | /* GPIO card-specific settings */ | 155 | /* GPIO card-specific settings */ |
156 | u8 xceive_pin; /* XCeive tuner GPIO reset pin */ | ||
156 | struct cx18_gpio_init gpio_init; | 157 | struct cx18_gpio_init gpio_init; |
157 | 158 | ||
158 | struct cx18_card_tuner tuners[CX18_CARD_MAX_TUNERS]; | 159 | struct cx18_card_tuner tuners[CX18_CARD_MAX_TUNERS]; |
diff --git a/drivers/media/video/cx18/cx18-controls.c b/drivers/media/video/cx18/cx18-controls.c index 2bdac5ebbb0d..87cf41021665 100644 --- a/drivers/media/video/cx18/cx18-controls.c +++ b/drivers/media/video/cx18/cx18-controls.c | |||
@@ -159,7 +159,7 @@ static int cx18_setup_vbi_fmt(struct cx18 *cx, enum v4l2_mpeg_stream_vbi_fmt fmt | |||
159 | { | 159 | { |
160 | if (!(cx->v4l2_cap & V4L2_CAP_SLICED_VBI_CAPTURE)) | 160 | if (!(cx->v4l2_cap & V4L2_CAP_SLICED_VBI_CAPTURE)) |
161 | return -EINVAL; | 161 | return -EINVAL; |
162 | if (atomic_read(&cx->capturing) > 0) | 162 | if (atomic_read(&cx->ana_capturing) > 0) |
163 | return -EBUSY; | 163 | return -EBUSY; |
164 | 164 | ||
165 | /* First try to allocate sliced VBI buffers if needed. */ | 165 | /* First try to allocate sliced VBI buffers if needed. */ |
@@ -235,7 +235,7 @@ int cx18_control_ioctls(struct cx18 *cx, unsigned int cmd, void *arg) | |||
235 | CX18_DEBUG_IOCTL("VIDIOC_S_EXT_CTRLS\n"); | 235 | CX18_DEBUG_IOCTL("VIDIOC_S_EXT_CTRLS\n"); |
236 | if (c->ctrl_class == V4L2_CTRL_CLASS_MPEG) { | 236 | if (c->ctrl_class == V4L2_CTRL_CLASS_MPEG) { |
237 | struct cx2341x_mpeg_params p = cx->params; | 237 | struct cx2341x_mpeg_params p = cx->params; |
238 | int err = cx2341x_ext_ctrls(&p, atomic_read(&cx->capturing), arg, cmd); | 238 | int err = cx2341x_ext_ctrls(&p, atomic_read(&cx->ana_capturing), arg, cmd); |
239 | 239 | ||
240 | if (err) | 240 | if (err) |
241 | return err; | 241 | return err; |
@@ -295,7 +295,7 @@ int cx18_control_ioctls(struct cx18 *cx, unsigned int cmd, void *arg) | |||
295 | CX18_DEBUG_IOCTL("VIDIOC_TRY_EXT_CTRLS\n"); | 295 | CX18_DEBUG_IOCTL("VIDIOC_TRY_EXT_CTRLS\n"); |
296 | if (c->ctrl_class == V4L2_CTRL_CLASS_MPEG) | 296 | if (c->ctrl_class == V4L2_CTRL_CLASS_MPEG) |
297 | return cx2341x_ext_ctrls(&cx->params, | 297 | return cx2341x_ext_ctrls(&cx->params, |
298 | atomic_read(&cx->capturing), arg, cmd); | 298 | atomic_read(&cx->ana_capturing), arg, cmd); |
299 | return -EINVAL; | 299 | return -EINVAL; |
300 | } | 300 | } |
301 | 301 | ||
diff --git a/drivers/media/video/cx18/cx18-driver.c b/drivers/media/video/cx18/cx18-driver.c index 3f55d47bc4b9..2b810bb2a4c7 100644 --- a/drivers/media/video/cx18/cx18-driver.c +++ b/drivers/media/video/cx18/cx18-driver.c | |||
@@ -164,16 +164,6 @@ MODULE_LICENSE("GPL"); | |||
164 | 164 | ||
165 | MODULE_VERSION(CX18_VERSION); | 165 | MODULE_VERSION(CX18_VERSION); |
166 | 166 | ||
167 | int cx18_waitq(wait_queue_head_t *waitq) | ||
168 | { | ||
169 | DEFINE_WAIT(wait); | ||
170 | |||
171 | prepare_to_wait(waitq, &wait, TASK_INTERRUPTIBLE); | ||
172 | schedule(); | ||
173 | finish_wait(waitq, &wait); | ||
174 | return signal_pending(current) ? -EINTR : 0; | ||
175 | } | ||
176 | |||
177 | /* Generic utility functions */ | 167 | /* Generic utility functions */ |
178 | int cx18_msleep_timeout(unsigned int msecs, int intr) | 168 | int cx18_msleep_timeout(unsigned int msecs, int intr) |
179 | { | 169 | { |
@@ -220,13 +210,13 @@ static void cx18_process_eeprom(struct cx18 *cx) | |||
220 | 210 | ||
221 | /* Many thanks to Steven Toth from Hauppauge for providing the | 211 | /* Many thanks to Steven Toth from Hauppauge for providing the |
222 | model numbers */ | 212 | model numbers */ |
213 | /* Note: the Samsung memory models cannot be reliably determined | ||
214 | from the model number. Use the cardtype module option if you | ||
215 | have one of these preproduction models. */ | ||
223 | switch (tv.model) { | 216 | switch (tv.model) { |
224 | case 74000 ... 74099: | 217 | case 74000 ... 74999: |
225 | cx->card = cx18_get_card(CX18_CARD_HVR_1600_ESMT); | 218 | cx->card = cx18_get_card(CX18_CARD_HVR_1600_ESMT); |
226 | break; | 219 | break; |
227 | case 74700 ... 74799: | ||
228 | cx->card = cx18_get_card(CX18_CARD_HVR_1600_SAMSUNG); | ||
229 | break; | ||
230 | case 0: | 220 | case 0: |
231 | CX18_ERR("Invalid EEPROM\n"); | 221 | CX18_ERR("Invalid EEPROM\n"); |
232 | return; | 222 | return; |
@@ -548,6 +538,7 @@ static int cx18_setup_pci(struct cx18 *cx, struct pci_dev *dev, | |||
548 | return 0; | 538 | return 0; |
549 | } | 539 | } |
550 | 540 | ||
541 | #ifdef MODULE | ||
551 | static u32 cx18_request_module(struct cx18 *cx, u32 hw, | 542 | static u32 cx18_request_module(struct cx18 *cx, u32 hw, |
552 | const char *name, u32 id) | 543 | const char *name, u32 id) |
553 | { | 544 | { |
@@ -560,12 +551,14 @@ static u32 cx18_request_module(struct cx18 *cx, u32 hw, | |||
560 | CX18_DEBUG_INFO("Loaded module %s\n", name); | 551 | CX18_DEBUG_INFO("Loaded module %s\n", name); |
561 | return hw; | 552 | return hw; |
562 | } | 553 | } |
554 | #endif | ||
563 | 555 | ||
564 | static void cx18_load_and_init_modules(struct cx18 *cx) | 556 | static void cx18_load_and_init_modules(struct cx18 *cx) |
565 | { | 557 | { |
566 | u32 hw = cx->card->hw_all; | 558 | u32 hw = cx->card->hw_all; |
567 | int i; | 559 | int i; |
568 | 560 | ||
561 | #ifdef MODULE | ||
569 | /* load modules */ | 562 | /* load modules */ |
570 | #ifndef CONFIG_MEDIA_TUNER | 563 | #ifndef CONFIG_MEDIA_TUNER |
571 | hw = cx18_request_module(cx, hw, "tuner", CX18_HW_TUNER); | 564 | hw = cx18_request_module(cx, hw, "tuner", CX18_HW_TUNER); |
@@ -573,6 +566,7 @@ static void cx18_load_and_init_modules(struct cx18 *cx) | |||
573 | #ifndef CONFIG_VIDEO_CS5345 | 566 | #ifndef CONFIG_VIDEO_CS5345 |
574 | hw = cx18_request_module(cx, hw, "cs5345", CX18_HW_CS5345); | 567 | hw = cx18_request_module(cx, hw, "cs5345", CX18_HW_CS5345); |
575 | #endif | 568 | #endif |
569 | #endif | ||
576 | 570 | ||
577 | /* check which i2c devices are actually found */ | 571 | /* check which i2c devices are actually found */ |
578 | for (i = 0; i < 32; i++) { | 572 | for (i = 0; i < 32; i++) { |
@@ -676,7 +670,7 @@ static int __devinit cx18_probe(struct pci_dev *dev, | |||
676 | cx18_init_power(cx, 1); | 670 | cx18_init_power(cx, 1); |
677 | cx18_init_memory(cx); | 671 | cx18_init_memory(cx); |
678 | 672 | ||
679 | cx->scb = (struct cx18_scb *)(cx->enc_mem + SCB_OFFSET); | 673 | cx->scb = (struct cx18_scb __iomem *)(cx->enc_mem + SCB_OFFSET); |
680 | cx18_init_scb(cx); | 674 | cx18_init_scb(cx); |
681 | 675 | ||
682 | cx18_gpio_init(cx); | 676 | cx18_gpio_init(cx); |
@@ -757,17 +751,6 @@ static int __devinit cx18_probe(struct pci_dev *dev, | |||
757 | if (cx->options.radio > 0) | 751 | if (cx->options.radio > 0) |
758 | cx->v4l2_cap |= V4L2_CAP_RADIO; | 752 | cx->v4l2_cap |= V4L2_CAP_RADIO; |
759 | 753 | ||
760 | retval = cx18_streams_setup(cx); | ||
761 | if (retval) { | ||
762 | CX18_ERR("Error %d setting up streams\n", retval); | ||
763 | goto free_irq; | ||
764 | } | ||
765 | retval = cx18_streams_register(cx); | ||
766 | if (retval) { | ||
767 | CX18_ERR("Error %d registering devices\n", retval); | ||
768 | goto free_streams; | ||
769 | } | ||
770 | |||
771 | if (cx->options.tuner > -1) { | 754 | if (cx->options.tuner > -1) { |
772 | struct tuner_setup setup; | 755 | struct tuner_setup setup; |
773 | 756 | ||
@@ -794,14 +777,23 @@ static int __devinit cx18_probe(struct pci_dev *dev, | |||
794 | are not. */ | 777 | are not. */ |
795 | cx->tuner_std = cx->std; | 778 | cx->tuner_std = cx->std; |
796 | 779 | ||
797 | cx18_init_on_first_open(cx); | 780 | retval = cx18_streams_setup(cx); |
781 | if (retval) { | ||
782 | CX18_ERR("Error %d setting up streams\n", retval); | ||
783 | goto free_irq; | ||
784 | } | ||
785 | retval = cx18_streams_register(cx); | ||
786 | if (retval) { | ||
787 | CX18_ERR("Error %d registering devices\n", retval); | ||
788 | goto free_streams; | ||
789 | } | ||
798 | 790 | ||
799 | CX18_INFO("Initialized card #%d: %s\n", cx->num, cx->card_name); | 791 | CX18_INFO("Initialized card #%d: %s\n", cx->num, cx->card_name); |
800 | 792 | ||
801 | return 0; | 793 | return 0; |
802 | 794 | ||
803 | free_streams: | 795 | free_streams: |
804 | cx18_streams_cleanup(cx); | 796 | cx18_streams_cleanup(cx, 1); |
805 | free_irq: | 797 | free_irq: |
806 | free_irq(cx->dev->irq, (void *)cx); | 798 | free_irq(cx->dev->irq, (void *)cx); |
807 | free_i2c: | 799 | free_i2c: |
@@ -895,7 +887,7 @@ static void cx18_remove(struct pci_dev *pci_dev) | |||
895 | 887 | ||
896 | /* Stop all captures */ | 888 | /* Stop all captures */ |
897 | CX18_DEBUG_INFO("Stopping all streams\n"); | 889 | CX18_DEBUG_INFO("Stopping all streams\n"); |
898 | if (atomic_read(&cx->capturing) > 0) | 890 | if (atomic_read(&cx->tot_capturing) > 0) |
899 | cx18_stop_all_captures(cx); | 891 | cx18_stop_all_captures(cx); |
900 | 892 | ||
901 | /* Interrupts */ | 893 | /* Interrupts */ |
@@ -904,14 +896,13 @@ static void cx18_remove(struct pci_dev *pci_dev) | |||
904 | 896 | ||
905 | cx18_halt_firmware(cx); | 897 | cx18_halt_firmware(cx); |
906 | 898 | ||
907 | cx18_streams_cleanup(cx); | 899 | cx18_streams_cleanup(cx, 1); |
908 | 900 | ||
909 | exit_cx18_i2c(cx); | 901 | exit_cx18_i2c(cx); |
910 | 902 | ||
911 | free_irq(cx->dev->irq, (void *)cx); | 903 | free_irq(cx->dev->irq, (void *)cx); |
912 | 904 | ||
913 | if (cx->dev) | 905 | cx18_iounmap(cx); |
914 | cx18_iounmap(cx); | ||
915 | 906 | ||
916 | release_mem_region(cx->base_addr, CX18_MEM_SIZE); | 907 | release_mem_region(cx->base_addr, CX18_MEM_SIZE); |
917 | 908 | ||
diff --git a/drivers/media/video/cx18/cx18-driver.h b/drivers/media/video/cx18/cx18-driver.h index 2ee939193bb7..de14ab59a206 100644 --- a/drivers/media/video/cx18/cx18-driver.h +++ b/drivers/media/video/cx18/cx18-driver.h | |||
@@ -358,7 +358,7 @@ struct cx18 { | |||
358 | u32 v4l2_cap; /* V4L2 capabilities of card */ | 358 | u32 v4l2_cap; /* V4L2 capabilities of card */ |
359 | u32 hw_flags; /* Hardware description of the board */ | 359 | u32 hw_flags; /* Hardware description of the board */ |
360 | unsigned mdl_offset; | 360 | unsigned mdl_offset; |
361 | struct cx18_scb *scb; /* pointer to SCB */ | 361 | struct cx18_scb __iomem *scb; /* pointer to SCB */ |
362 | 362 | ||
363 | struct cx18_av_state av_state; | 363 | struct cx18_av_state av_state; |
364 | 364 | ||
@@ -380,7 +380,8 @@ struct cx18 { | |||
380 | int stream_buf_size[CX18_MAX_STREAMS]; /* Stream buffer size */ | 380 | int stream_buf_size[CX18_MAX_STREAMS]; /* Stream buffer size */ |
381 | struct cx18_stream streams[CX18_MAX_STREAMS]; /* Stream data */ | 381 | struct cx18_stream streams[CX18_MAX_STREAMS]; /* Stream data */ |
382 | unsigned long i_flags; /* global cx18 flags */ | 382 | unsigned long i_flags; /* global cx18 flags */ |
383 | atomic_t capturing; /* count number of active capture streams */ | 383 | atomic_t ana_capturing; /* count number of active analog capture streams */ |
384 | atomic_t tot_capturing; /* total count number of active capture streams */ | ||
384 | spinlock_t lock; /* lock access to this struct */ | 385 | spinlock_t lock; /* lock access to this struct */ |
385 | int search_pack_header; | 386 | int search_pack_header; |
386 | 387 | ||
@@ -423,6 +424,10 @@ struct cx18 { | |||
423 | struct mutex i2c_bus_lock[2]; | 424 | struct mutex i2c_bus_lock[2]; |
424 | struct i2c_client *i2c_clients[I2C_CLIENTS_MAX]; | 425 | struct i2c_client *i2c_clients[I2C_CLIENTS_MAX]; |
425 | 426 | ||
427 | /* gpio */ | ||
428 | u32 gpio_dir; | ||
429 | u32 gpio_val; | ||
430 | |||
426 | /* v4l2 and User settings */ | 431 | /* v4l2 and User settings */ |
427 | 432 | ||
428 | /* codec settings */ | 433 | /* codec settings */ |
@@ -444,9 +449,6 @@ extern spinlock_t cx18_cards_lock; | |||
444 | /* Return non-zero if a signal is pending */ | 449 | /* Return non-zero if a signal is pending */ |
445 | int cx18_msleep_timeout(unsigned int msecs, int intr); | 450 | int cx18_msleep_timeout(unsigned int msecs, int intr); |
446 | 451 | ||
447 | /* Wait on queue, returns -EINTR if interrupted */ | ||
448 | int cx18_waitq(wait_queue_head_t *waitq); | ||
449 | |||
450 | /* Read Hauppauge eeprom */ | 452 | /* Read Hauppauge eeprom */ |
451 | struct tveeprom; /* forward reference */ | 453 | struct tveeprom; /* forward reference */ |
452 | void cx18_read_eeprom(struct cx18 *cx, struct tveeprom *tv); | 454 | void cx18_read_eeprom(struct cx18 *cx, struct tveeprom *tv); |
diff --git a/drivers/media/video/cx18/cx18-dvb.c b/drivers/media/video/cx18/cx18-dvb.c index 65efe69d939a..c9744173f969 100644 --- a/drivers/media/video/cx18/cx18-dvb.c +++ b/drivers/media/video/cx18/cx18-dvb.c | |||
@@ -24,25 +24,27 @@ | |||
24 | #include "cx18-streams.h" | 24 | #include "cx18-streams.h" |
25 | #include "cx18-cards.h" | 25 | #include "cx18-cards.h" |
26 | #include "s5h1409.h" | 26 | #include "s5h1409.h" |
27 | 27 | #include "mxl5005s.h" | |
28 | /* Wait until the MXL500X driver is merged */ | ||
29 | #ifdef HAVE_MXL500X | ||
30 | #include "mxl500x.h" | ||
31 | #endif | ||
32 | 28 | ||
33 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | 29 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); |
34 | 30 | ||
35 | #define CX18_REG_DMUX_NUM_PORT_0_CONTROL 0xd5a000 | 31 | #define CX18_REG_DMUX_NUM_PORT_0_CONTROL 0xd5a000 |
36 | 32 | ||
37 | #ifdef HAVE_MXL500X | 33 | static struct mxl5005s_config hauppauge_hvr1600_tuner = { |
38 | static struct mxl500x_config hauppauge_hvr1600_tuner = { | 34 | .i2c_address = 0xC6 >> 1, |
39 | .delsys = MXL500x_MODE_ATSC, | 35 | .if_freq = IF_FREQ_5380000HZ, |
40 | .octf = MXL500x_OCTF_CH, | 36 | .xtal_freq = CRYSTAL_FREQ_16000000HZ, |
41 | .xtal_freq = 16000000, | 37 | .agc_mode = MXL_SINGLE_AGC, |
42 | .iflo_freq = 5380000, | 38 | .tracking_filter = MXL_TF_C_H, |
43 | .ref_freq = 322800000, | 39 | .rssi_enable = MXL_RSSI_ENABLE, |
44 | .rssi_ena = MXL_RSSI_ENABLE, | 40 | .cap_select = MXL_CAP_SEL_ENABLE, |
45 | .addr = 0xC6 >> 1, | 41 | .div_out = MXL_DIV_OUT_4, |
42 | .clock_out = MXL_CLOCK_OUT_DISABLE, | ||
43 | .output_load = MXL5005S_IF_OUTPUT_LOAD_200_OHM, | ||
44 | .top = MXL5005S_TOP_25P2, | ||
45 | .mod_mode = MXL_DIGITAL_MODE, | ||
46 | .if_mode = MXL_ZERO_IF, | ||
47 | .AgcMasterByte = 0x00, | ||
46 | }; | 48 | }; |
47 | 49 | ||
48 | static struct s5h1409_config hauppauge_hvr1600_config = { | 50 | static struct s5h1409_config hauppauge_hvr1600_config = { |
@@ -55,7 +57,6 @@ static struct s5h1409_config hauppauge_hvr1600_config = { | |||
55 | .mpeg_timing = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK | 57 | .mpeg_timing = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK |
56 | 58 | ||
57 | }; | 59 | }; |
58 | #endif | ||
59 | 60 | ||
60 | static int dvb_register(struct cx18_stream *stream); | 61 | static int dvb_register(struct cx18_stream *stream); |
61 | 62 | ||
@@ -252,21 +253,18 @@ static int dvb_register(struct cx18_stream *stream) | |||
252 | int ret = 0; | 253 | int ret = 0; |
253 | 254 | ||
254 | switch (cx->card->type) { | 255 | switch (cx->card->type) { |
255 | /* Wait until the MXL500X driver is merged */ | ||
256 | #ifdef HAVE_MXL500X | ||
257 | case CX18_CARD_HVR_1600_ESMT: | 256 | case CX18_CARD_HVR_1600_ESMT: |
258 | case CX18_CARD_HVR_1600_SAMSUNG: | 257 | case CX18_CARD_HVR_1600_SAMSUNG: |
259 | dvb->fe = dvb_attach(s5h1409_attach, | 258 | dvb->fe = dvb_attach(s5h1409_attach, |
260 | &hauppauge_hvr1600_config, | 259 | &hauppauge_hvr1600_config, |
261 | &cx->i2c_adap[0]); | 260 | &cx->i2c_adap[0]); |
262 | if (dvb->fe != NULL) { | 261 | if (dvb->fe != NULL) { |
263 | dvb_attach(mxl500x_attach, dvb->fe, | 262 | dvb_attach(mxl5005s_attach, dvb->fe, |
264 | &hauppauge_hvr1600_tuner, | 263 | &cx->i2c_adap[0], |
265 | &cx->i2c_adap[0]); | 264 | &hauppauge_hvr1600_tuner); |
266 | ret = 0; | 265 | ret = 0; |
267 | } | 266 | } |
268 | break; | 267 | break; |
269 | #endif | ||
270 | default: | 268 | default: |
271 | /* No Digital Tv Support */ | 269 | /* No Digital Tv Support */ |
272 | break; | 270 | break; |
diff --git a/drivers/media/video/cx18/cx18-fileops.c b/drivers/media/video/cx18/cx18-fileops.c index 69303065a294..1e537fe04a23 100644 --- a/drivers/media/video/cx18/cx18-fileops.c +++ b/drivers/media/video/cx18/cx18-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 cx18_claim_stream(struct cx18_open_id *id, int type) | 42 | static int cx18_claim_stream(struct cx18_open_id *id, int type) |
43 | { | 43 | { |
44 | struct cx18 *cx = id->cx; | 44 | struct cx18 *cx = id->cx; |
45 | struct cx18_stream *s = &cx->streams[type]; | 45 | struct cx18_stream *s = &cx->streams[type]; |
@@ -87,7 +87,7 @@ int cx18_claim_stream(struct cx18_open_id *id, int type) | |||
87 | 87 | ||
88 | /* This function releases a previously claimed stream. It will take into | 88 | /* This function releases a previously claimed stream. It will take into |
89 | account associated VBI streams. */ | 89 | account associated VBI streams. */ |
90 | void cx18_release_stream(struct cx18_stream *s) | 90 | static void cx18_release_stream(struct cx18_stream *s) |
91 | { | 91 | { |
92 | struct cx18 *cx = s->cx; | 92 | struct cx18 *cx = s->cx; |
93 | struct cx18_stream *s_vbi; | 93 | struct cx18_stream *s_vbi; |
@@ -318,7 +318,7 @@ static ssize_t cx18_read(struct cx18_stream *s, char __user *ubuf, | |||
318 | size_t tot_written = 0; | 318 | size_t tot_written = 0; |
319 | int single_frame = 0; | 319 | int single_frame = 0; |
320 | 320 | ||
321 | if (atomic_read(&cx->capturing) == 0 && s->id == -1) { | 321 | if (atomic_read(&cx->ana_capturing) == 0 && s->id == -1) { |
322 | /* shouldn't happen */ | 322 | /* shouldn't happen */ |
323 | CX18_DEBUG_WARN("Stream %s not initialized before read\n", | 323 | CX18_DEBUG_WARN("Stream %s not initialized before read\n", |
324 | s->name); | 324 | s->name); |
@@ -361,7 +361,8 @@ static ssize_t cx18_read(struct cx18_stream *s, char __user *ubuf, | |||
361 | cx18_enqueue(s, buf, &s->q_free); | 361 | cx18_enqueue(s, buf, &s->q_free); |
362 | cx18_vapi(cx, CX18_CPU_DE_SET_MDL, 5, | 362 | cx18_vapi(cx, CX18_CPU_DE_SET_MDL, 5, |
363 | s->handle, | 363 | s->handle, |
364 | (void *)&cx->scb->cpu_mdl[buf->id] - cx->enc_mem, | 364 | (void __iomem *)&cx->scb->cpu_mdl[buf->id] - |
365 | cx->enc_mem, | ||
365 | 1, buf->id, s->buf_size); | 366 | 1, buf->id, s->buf_size); |
366 | } else | 367 | } else |
367 | cx18_enqueue(s, buf, &s->q_io); | 368 | cx18_enqueue(s, buf, &s->q_io); |
@@ -581,7 +582,7 @@ int cx18_v4l2_close(struct inode *inode, struct file *filp) | |||
581 | cx18_call_i2c_clients(cx, VIDIOC_S_STD, &cx->std); | 582 | cx18_call_i2c_clients(cx, VIDIOC_S_STD, &cx->std); |
582 | /* Select correct audio input (i.e. TV tuner or Line in) */ | 583 | /* Select correct audio input (i.e. TV tuner or Line in) */ |
583 | cx18_audio_set_io(cx); | 584 | cx18_audio_set_io(cx); |
584 | if (atomic_read(&cx->capturing) > 0) { | 585 | if (atomic_read(&cx->ana_capturing) > 0) { |
585 | /* Undo video mute */ | 586 | /* Undo video mute */ |
586 | cx18_vapi(cx, CX18_CPU_SET_VIDEO_MUTE, 2, s->handle, | 587 | cx18_vapi(cx, CX18_CPU_SET_VIDEO_MUTE, 2, s->handle, |
587 | cx->params.video_mute | | 588 | cx->params.video_mute | |
@@ -627,7 +628,7 @@ static int cx18_serialized_open(struct cx18_stream *s, struct file *filp) | |||
627 | } | 628 | } |
628 | 629 | ||
629 | if (!test_bit(CX18_F_I_RADIO_USER, &cx->i_flags)) { | 630 | if (!test_bit(CX18_F_I_RADIO_USER, &cx->i_flags)) { |
630 | if (atomic_read(&cx->capturing) > 0) { | 631 | if (atomic_read(&cx->ana_capturing) > 0) { |
631 | /* switching to radio while capture is | 632 | /* switching to radio while capture is |
632 | in progress is not polite */ | 633 | in progress is not polite */ |
633 | cx18_release_stream(s); | 634 | cx18_release_stream(s); |
@@ -662,6 +663,8 @@ int cx18_v4l2_open(struct inode *inode, struct file *filp) | |||
662 | for (x = 0; cx == NULL && x < cx18_cards_active; x++) { | 663 | for (x = 0; cx == NULL && x < cx18_cards_active; x++) { |
663 | /* find out which stream this open was on */ | 664 | /* find out which stream this open was on */ |
664 | for (y = 0; y < CX18_MAX_STREAMS; y++) { | 665 | for (y = 0; y < CX18_MAX_STREAMS; y++) { |
666 | if (cx18_cards[x] == NULL) | ||
667 | continue; | ||
665 | s = &cx18_cards[x]->streams[y]; | 668 | s = &cx18_cards[x]->streams[y]; |
666 | if (s->v4l2dev && s->v4l2dev->minor == minor) { | 669 | if (s->v4l2dev && s->v4l2dev->minor == minor) { |
667 | cx = cx18_cards[x]; | 670 | cx = cx18_cards[x]; |
@@ -692,7 +695,7 @@ int cx18_v4l2_open(struct inode *inode, struct file *filp) | |||
692 | 695 | ||
693 | void cx18_mute(struct cx18 *cx) | 696 | void cx18_mute(struct cx18 *cx) |
694 | { | 697 | { |
695 | if (atomic_read(&cx->capturing)) | 698 | if (atomic_read(&cx->ana_capturing)) |
696 | cx18_vapi(cx, CX18_CPU_SET_AUDIO_MUTE, 2, | 699 | cx18_vapi(cx, CX18_CPU_SET_AUDIO_MUTE, 2, |
697 | cx18_find_handle(cx), 1); | 700 | cx18_find_handle(cx), 1); |
698 | CX18_DEBUG_INFO("Mute\n"); | 701 | CX18_DEBUG_INFO("Mute\n"); |
@@ -700,7 +703,7 @@ void cx18_mute(struct cx18 *cx) | |||
700 | 703 | ||
701 | void cx18_unmute(struct cx18 *cx) | 704 | void cx18_unmute(struct cx18 *cx) |
702 | { | 705 | { |
703 | if (atomic_read(&cx->capturing)) { | 706 | if (atomic_read(&cx->ana_capturing)) { |
704 | cx18_msleep_timeout(100, 0); | 707 | cx18_msleep_timeout(100, 0); |
705 | cx18_vapi(cx, CX18_CPU_SET_MISC_PARAMETERS, 2, | 708 | cx18_vapi(cx, CX18_CPU_SET_MISC_PARAMETERS, 2, |
706 | cx18_find_handle(cx), 12); | 709 | cx18_find_handle(cx), 12); |
diff --git a/drivers/media/video/cx18/cx18-fileops.h b/drivers/media/video/cx18/cx18-fileops.h index 16cdafbd24c5..46da0282fc7d 100644 --- a/drivers/media/video/cx18/cx18-fileops.h +++ b/drivers/media/video/cx18/cx18-fileops.h | |||
@@ -34,12 +34,3 @@ void cx18_stop_capture(struct cx18_open_id *id, int gop_end); | |||
34 | void cx18_mute(struct cx18 *cx); | 34 | void cx18_mute(struct cx18 *cx); |
35 | void cx18_unmute(struct cx18 *cx); | 35 | void cx18_unmute(struct cx18 *cx); |
36 | 36 | ||
37 | /* Utilities */ | ||
38 | |||
39 | /* Try to claim a stream for the filehandle. Return 0 on success, | ||
40 | -EBUSY if stream already claimed. Once a stream is claimed, it | ||
41 | remains claimed until the associated filehandle is closed. */ | ||
42 | int cx18_claim_stream(struct cx18_open_id *id, int type); | ||
43 | |||
44 | /* Release a previously claimed stream. */ | ||
45 | void cx18_release_stream(struct cx18_stream *s); | ||
diff --git a/drivers/media/video/cx18/cx18-gpio.c b/drivers/media/video/cx18/cx18-gpio.c index 19253e6b8673..ceb63653c926 100644 --- a/drivers/media/video/cx18/cx18-gpio.c +++ b/drivers/media/video/cx18/cx18-gpio.c | |||
@@ -44,31 +44,57 @@ | |||
44 | * gpio13: cs5345 reset pin | 44 | * gpio13: cs5345 reset pin |
45 | */ | 45 | */ |
46 | 46 | ||
47 | static void gpio_write(struct cx18 *cx) | ||
48 | { | ||
49 | u32 dir = cx->gpio_dir; | ||
50 | u32 val = cx->gpio_val; | ||
51 | |||
52 | write_reg((dir & 0xffff) << 16, CX18_REG_GPIO_DIR1); | ||
53 | write_reg(((dir & 0xffff) << 16) | (val & 0xffff), | ||
54 | CX18_REG_GPIO_OUT1); | ||
55 | write_reg(dir & 0xffff0000, CX18_REG_GPIO_DIR2); | ||
56 | write_reg((dir & 0xffff0000) | ((val & 0xffff0000) >> 16), | ||
57 | CX18_REG_GPIO_OUT2); | ||
58 | } | ||
59 | |||
47 | void cx18_gpio_init(struct cx18 *cx) | 60 | void cx18_gpio_init(struct cx18 *cx) |
48 | { | 61 | { |
49 | if (cx->card->gpio_init.direction == 0) | 62 | cx->gpio_dir = cx->card->gpio_init.direction; |
63 | cx->gpio_val = cx->card->gpio_init.initial_value; | ||
64 | |||
65 | if (cx->card->tuners[0].tuner == TUNER_XC2028) { | ||
66 | cx->gpio_dir |= 1 << cx->card->xceive_pin; | ||
67 | cx->gpio_val |= 1 << cx->card->xceive_pin; | ||
68 | } | ||
69 | |||
70 | if (cx->gpio_dir == 0) | ||
50 | return; | 71 | return; |
51 | 72 | ||
52 | CX18_DEBUG_INFO("GPIO initial dir: %08x out: %08x\n", | 73 | CX18_DEBUG_INFO("GPIO initial dir: %08x/%08x out: %08x/%08x\n", |
53 | read_reg(CX18_REG_GPIO_DIR1), read_reg(CX18_REG_GPIO_OUT1)); | 74 | read_reg(CX18_REG_GPIO_DIR1), read_reg(CX18_REG_GPIO_DIR2), |
75 | read_reg(CX18_REG_GPIO_OUT1), read_reg(CX18_REG_GPIO_OUT2)); | ||
54 | 76 | ||
55 | /* init output data then direction */ | 77 | gpio_write(cx); |
56 | write_reg(cx->card->gpio_init.direction << 16, CX18_REG_GPIO_DIR1); | ||
57 | write_reg(0, CX18_REG_GPIO_DIR2); | ||
58 | write_reg((cx->card->gpio_init.direction << 16) | | ||
59 | cx->card->gpio_init.initial_value, CX18_REG_GPIO_OUT1); | ||
60 | write_reg(0, CX18_REG_GPIO_OUT2); | ||
61 | } | 78 | } |
62 | 79 | ||
63 | /* Xceive tuner reset function */ | 80 | /* Xceive tuner reset function */ |
64 | int cx18_reset_tuner_gpio(void *dev, int cmd, int value) | 81 | int cx18_reset_tuner_gpio(void *dev, int cmd, int value) |
65 | { | 82 | { |
66 | struct i2c_algo_bit_data *algo = dev; | 83 | struct i2c_algo_bit_data *algo = dev; |
67 | struct cx18 *cx = algo->data; | 84 | struct cx18_i2c_algo_callback_data *cb_data = algo->data; |
68 | /* int curdir, curout;*/ | 85 | struct cx18 *cx = cb_data->cx; |
69 | 86 | ||
70 | if (cmd != XC2028_TUNER_RESET) | 87 | if (cmd != XC2028_TUNER_RESET) |
71 | return 0; | 88 | return 0; |
72 | CX18_DEBUG_INFO("Resetting tuner\n"); | 89 | CX18_DEBUG_INFO("Resetting tuner\n"); |
90 | |||
91 | cx->gpio_val &= ~(1 << cx->card->xceive_pin); | ||
92 | |||
93 | gpio_write(cx); | ||
94 | schedule_timeout_interruptible(msecs_to_jiffies(1)); | ||
95 | |||
96 | cx->gpio_val |= 1 << cx->card->xceive_pin; | ||
97 | gpio_write(cx); | ||
98 | schedule_timeout_interruptible(msecs_to_jiffies(1)); | ||
73 | return 0; | 99 | return 0; |
74 | } | 100 | } |
diff --git a/drivers/media/video/cx18/cx18-i2c.c b/drivers/media/video/cx18/cx18-i2c.c index 18c88d1e4833..1d6c51a75313 100644 --- a/drivers/media/video/cx18/cx18-i2c.c +++ b/drivers/media/video/cx18/cx18-i2c.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include "cx18-cards.h" | 25 | #include "cx18-cards.h" |
26 | #include "cx18-gpio.h" | 26 | #include "cx18-gpio.h" |
27 | #include "cx18-av-core.h" | 27 | #include "cx18-av-core.h" |
28 | #include "cx18-i2c.h" | ||
28 | 29 | ||
29 | #include <media/ir-kbd-i2c.h> | 30 | #include <media/ir-kbd-i2c.h> |
30 | 31 | ||
@@ -73,7 +74,7 @@ static const u8 hw_bus[] = { | |||
73 | }; | 74 | }; |
74 | 75 | ||
75 | /* This array should match the CX18_HW_ defines */ | 76 | /* This array should match the CX18_HW_ defines */ |
76 | static const char * const hw_drivernames[] = { | 77 | static const char * const hw_devicenames[] = { |
77 | "tuner", | 78 | "tuner", |
78 | "tveeprom", | 79 | "tveeprom", |
79 | "cs5345", | 80 | "cs5345", |
@@ -94,8 +95,7 @@ int cx18_i2c_register(struct cx18 *cx, unsigned idx) | |||
94 | id = hw_driverids[idx]; | 95 | id = hw_driverids[idx]; |
95 | bus = hw_bus[idx]; | 96 | bus = hw_bus[idx]; |
96 | memset(&info, 0, sizeof(info)); | 97 | memset(&info, 0, sizeof(info)); |
97 | strlcpy(info.driver_name, hw_drivernames[idx], | 98 | strlcpy(info.type, hw_devicenames[idx], sizeof(info.type)); |
98 | sizeof(info.driver_name)); | ||
99 | info.addr = hw_addrs[idx]; | 99 | info.addr = hw_addrs[idx]; |
100 | for (i = 0; i < I2C_CLIENTS_MAX; i++) | 100 | for (i = 0; i < I2C_CLIENTS_MAX; i++) |
101 | if (cx->i2c_clients[i] == NULL) | 101 | if (cx->i2c_clients[i] == NULL) |
@@ -278,7 +278,7 @@ static const char *cx18_i2c_id_name(u32 id) | |||
278 | 278 | ||
279 | for (i = 0; i < ARRAY_SIZE(hw_driverids); i++) | 279 | for (i = 0; i < ARRAY_SIZE(hw_driverids); i++) |
280 | if (hw_driverids[i] == id) | 280 | if (hw_driverids[i] == id) |
281 | return hw_drivernames[i]; | 281 | return hw_devicenames[i]; |
282 | return "unknown device"; | 282 | return "unknown device"; |
283 | } | 283 | } |
284 | 284 | ||
@@ -289,7 +289,7 @@ static const char *cx18_i2c_hw_name(u32 hw) | |||
289 | 289 | ||
290 | for (i = 0; i < ARRAY_SIZE(hw_driverids); i++) | 290 | for (i = 0; i < ARRAY_SIZE(hw_driverids); i++) |
291 | if (1 << i == hw) | 291 | if (1 << i == hw) |
292 | return hw_drivernames[i]; | 292 | return hw_devicenames[i]; |
293 | return "unknown device"; | 293 | return "unknown device"; |
294 | } | 294 | } |
295 | 295 | ||
diff --git a/drivers/media/video/cx18/cx18-ioctl.c b/drivers/media/video/cx18/cx18-ioctl.c index dbdcb86ec5aa..4151f1e5493f 100644 --- a/drivers/media/video/cx18/cx18-ioctl.c +++ b/drivers/media/video/cx18/cx18-ioctl.c | |||
@@ -247,7 +247,7 @@ static int cx18_try_or_set_fmt(struct cx18 *cx, int streamtype, | |||
247 | 247 | ||
248 | if (!set_fmt || (cx->params.width == w && cx->params.height == h)) | 248 | if (!set_fmt || (cx->params.width == w && cx->params.height == h)) |
249 | return 0; | 249 | return 0; |
250 | if (atomic_read(&cx->capturing) > 0) | 250 | if (atomic_read(&cx->ana_capturing) > 0) |
251 | return -EBUSY; | 251 | return -EBUSY; |
252 | 252 | ||
253 | cx->params.width = w; | 253 | cx->params.width = w; |
@@ -264,7 +264,7 @@ static int cx18_try_or_set_fmt(struct cx18 *cx, int streamtype, | |||
264 | if (fmt->type == V4L2_BUF_TYPE_VBI_CAPTURE) { | 264 | if (fmt->type == V4L2_BUF_TYPE_VBI_CAPTURE) { |
265 | if (set_fmt && streamtype == CX18_ENC_STREAM_TYPE_VBI && | 265 | if (set_fmt && streamtype == CX18_ENC_STREAM_TYPE_VBI && |
266 | cx->vbi.sliced_in->service_set && | 266 | cx->vbi.sliced_in->service_set && |
267 | atomic_read(&cx->capturing) > 0) | 267 | atomic_read(&cx->ana_capturing) > 0) |
268 | return -EBUSY; | 268 | return -EBUSY; |
269 | if (set_fmt) { | 269 | if (set_fmt) { |
270 | cx->vbi.sliced_in->service_set = 0; | 270 | cx->vbi.sliced_in->service_set = 0; |
@@ -293,7 +293,7 @@ static int cx18_try_or_set_fmt(struct cx18 *cx, int streamtype, | |||
293 | return 0; | 293 | return 0; |
294 | if (set == 0) | 294 | if (set == 0) |
295 | return -EINVAL; | 295 | return -EINVAL; |
296 | if (atomic_read(&cx->capturing) > 0 && cx->vbi.sliced_in->service_set == 0) | 296 | if (atomic_read(&cx->ana_capturing) > 0 && cx->vbi.sliced_in->service_set == 0) |
297 | return -EBUSY; | 297 | return -EBUSY; |
298 | cx18_av_cmd(cx, VIDIOC_S_FMT, fmt); | 298 | cx18_av_cmd(cx, VIDIOC_S_FMT, fmt); |
299 | memcpy(cx->vbi.sliced_in, vbifmt, sizeof(*cx->vbi.sliced_in)); | 299 | memcpy(cx->vbi.sliced_in, vbifmt, sizeof(*cx->vbi.sliced_in)); |
@@ -581,7 +581,7 @@ int cx18_v4l2_ioctls(struct cx18 *cx, struct file *filp, unsigned cmd, void *arg | |||
581 | break; | 581 | break; |
582 | 582 | ||
583 | if (test_bit(CX18_F_I_RADIO_USER, &cx->i_flags) || | 583 | if (test_bit(CX18_F_I_RADIO_USER, &cx->i_flags) || |
584 | atomic_read(&cx->capturing) > 0) { | 584 | atomic_read(&cx->ana_capturing) > 0) { |
585 | /* Switching standard would turn off the radio or mess | 585 | /* Switching standard would turn off the radio or mess |
586 | with already running streams, prevent that by | 586 | with already running streams, prevent that by |
587 | returning EBUSY. */ | 587 | returning EBUSY. */ |
@@ -677,7 +677,7 @@ int cx18_v4l2_ioctls(struct cx18 *cx, struct file *filp, unsigned cmd, void *arg | |||
677 | enc->flags = 0; | 677 | enc->flags = 0; |
678 | if (try) | 678 | if (try) |
679 | return 0; | 679 | return 0; |
680 | if (!atomic_read(&cx->capturing)) | 680 | if (!atomic_read(&cx->ana_capturing)) |
681 | return -EPERM; | 681 | return -EPERM; |
682 | if (test_and_set_bit(CX18_F_I_ENC_PAUSED, &cx->i_flags)) | 682 | if (test_and_set_bit(CX18_F_I_ENC_PAUSED, &cx->i_flags)) |
683 | return 0; | 683 | return 0; |
@@ -689,7 +689,7 @@ int cx18_v4l2_ioctls(struct cx18 *cx, struct file *filp, unsigned cmd, void *arg | |||
689 | enc->flags = 0; | 689 | enc->flags = 0; |
690 | if (try) | 690 | if (try) |
691 | return 0; | 691 | return 0; |
692 | if (!atomic_read(&cx->capturing)) | 692 | if (!atomic_read(&cx->ana_capturing)) |
693 | return -EPERM; | 693 | return -EPERM; |
694 | if (!test_and_clear_bit(CX18_F_I_ENC_PAUSED, &cx->i_flags)) | 694 | if (!test_and_clear_bit(CX18_F_I_ENC_PAUSED, &cx->i_flags)) |
695 | return 0; | 695 | return 0; |
diff --git a/drivers/media/video/cx18/cx18-irq.c b/drivers/media/video/cx18/cx18-irq.c index 6e14f8bda559..25114a5cbd57 100644 --- a/drivers/media/video/cx18/cx18-irq.c +++ b/drivers/media/video/cx18/cx18-irq.c | |||
@@ -75,7 +75,7 @@ static void epu_dma_done(struct cx18 *cx, struct cx18_mailbox *mb) | |||
75 | 75 | ||
76 | cx18_buf_sync_for_device(s, buf); | 76 | cx18_buf_sync_for_device(s, buf); |
77 | cx18_vapi(cx, CX18_CPU_DE_SET_MDL, 5, s->handle, | 77 | cx18_vapi(cx, CX18_CPU_DE_SET_MDL, 5, s->handle, |
78 | (void *)&cx->scb->cpu_mdl[buf->id] - cx->enc_mem, | 78 | (void __iomem *)&cx->scb->cpu_mdl[buf->id] - cx->enc_mem, |
79 | 1, buf->id, s->buf_size); | 79 | 1, buf->id, s->buf_size); |
80 | } else | 80 | } else |
81 | set_bit(CX18_F_B_NEED_BUF_SWAP, &buf->b_flags); | 81 | set_bit(CX18_F_B_NEED_BUF_SWAP, &buf->b_flags); |
@@ -161,13 +161,15 @@ irqreturn_t cx18_irq_handler(int irq, void *dev_id) | |||
161 | */ | 161 | */ |
162 | 162 | ||
163 | if (sw2) { | 163 | if (sw2) { |
164 | if (sw2 & (cx->scb->cpu2hpu_irq_ack | cx->scb->cpu2epu_irq_ack)) | 164 | if (sw2 & (readl(&cx->scb->cpu2hpu_irq_ack) | |
165 | readl(&cx->scb->cpu2epu_irq_ack))) | ||
165 | wake_up(&cx->mb_cpu_waitq); | 166 | wake_up(&cx->mb_cpu_waitq); |
166 | if (sw2 & (cx->scb->apu2hpu_irq_ack | cx->scb->apu2epu_irq_ack)) | 167 | if (sw2 & (readl(&cx->scb->apu2hpu_irq_ack) | |
168 | readl(&cx->scb->apu2epu_irq_ack))) | ||
167 | wake_up(&cx->mb_apu_waitq); | 169 | wake_up(&cx->mb_apu_waitq); |
168 | if (sw2 & cx->scb->epu2hpu_irq_ack) | 170 | if (sw2 & readl(&cx->scb->epu2hpu_irq_ack)) |
169 | wake_up(&cx->mb_epu_waitq); | 171 | wake_up(&cx->mb_epu_waitq); |
170 | if (sw2 & cx->scb->hpu2epu_irq_ack) | 172 | if (sw2 & readl(&cx->scb->hpu2epu_irq_ack)) |
171 | wake_up(&cx->mb_hpu_waitq); | 173 | wake_up(&cx->mb_hpu_waitq); |
172 | } | 174 | } |
173 | 175 | ||
diff --git a/drivers/media/video/cx18/cx18-mailbox.c b/drivers/media/video/cx18/cx18-mailbox.c index 0c5f328bca54..2a5ccef9185b 100644 --- a/drivers/media/video/cx18/cx18-mailbox.c +++ b/drivers/media/video/cx18/cx18-mailbox.c | |||
@@ -94,10 +94,10 @@ static const struct cx18_api_info *find_api_info(u32 cmd) | |||
94 | return NULL; | 94 | return NULL; |
95 | } | 95 | } |
96 | 96 | ||
97 | static struct cx18_mailbox *cx18_mb_is_complete(struct cx18 *cx, int rpu, | 97 | static struct cx18_mailbox __iomem *cx18_mb_is_complete(struct cx18 *cx, int rpu, |
98 | u32 *state, u32 *irq, u32 *req) | 98 | u32 *state, u32 *irq, u32 *req) |
99 | { | 99 | { |
100 | struct cx18_mailbox *mb = NULL; | 100 | struct cx18_mailbox __iomem *mb = NULL; |
101 | int wait_count = 0; | 101 | int wait_count = 0; |
102 | u32 ack; | 102 | u32 ack; |
103 | 103 | ||
@@ -142,7 +142,7 @@ static struct cx18_mailbox *cx18_mb_is_complete(struct cx18 *cx, int rpu, | |||
142 | long cx18_mb_ack(struct cx18 *cx, const struct cx18_mailbox *mb) | 142 | long cx18_mb_ack(struct cx18 *cx, const struct cx18_mailbox *mb) |
143 | { | 143 | { |
144 | const struct cx18_api_info *info = find_api_info(mb->cmd); | 144 | const struct cx18_api_info *info = find_api_info(mb->cmd); |
145 | struct cx18_mailbox *ack_mb; | 145 | struct cx18_mailbox __iomem *ack_mb; |
146 | u32 ack_irq; | 146 | u32 ack_irq; |
147 | u8 rpu = CPU; | 147 | u8 rpu = CPU; |
148 | 148 | ||
@@ -182,7 +182,7 @@ static int cx18_api_call(struct cx18 *cx, u32 cmd, int args, u32 data[]) | |||
182 | { | 182 | { |
183 | const struct cx18_api_info *info = find_api_info(cmd); | 183 | const struct cx18_api_info *info = find_api_info(cmd); |
184 | u32 state = 0, irq = 0, req, oldreq, err; | 184 | u32 state = 0, irq = 0, req, oldreq, err; |
185 | struct cx18_mailbox *mb; | 185 | struct cx18_mailbox __iomem *mb; |
186 | wait_queue_head_t *waitq; | 186 | wait_queue_head_t *waitq; |
187 | int timeout = 100; | 187 | int timeout = 100; |
188 | int cnt = 0; | 188 | int cnt = 0; |
diff --git a/drivers/media/video/cx18/cx18-queue.c b/drivers/media/video/cx18/cx18-queue.c index 65af1bb507ca..6990b77c6200 100644 --- a/drivers/media/video/cx18/cx18-queue.c +++ b/drivers/media/video/cx18/cx18-queue.c | |||
@@ -26,17 +26,6 @@ | |||
26 | #include "cx18-queue.h" | 26 | #include "cx18-queue.h" |
27 | #include "cx18-scb.h" | 27 | #include "cx18-scb.h" |
28 | 28 | ||
29 | int cx18_buf_copy_from_user(struct cx18_stream *s, struct cx18_buffer *buf, | ||
30 | const char __user *src, int copybytes) | ||
31 | { | ||
32 | if (s->buf_size - buf->bytesused < copybytes) | ||
33 | copybytes = s->buf_size - buf->bytesused; | ||
34 | if (copy_from_user(buf->buf + buf->bytesused, src, copybytes)) | ||
35 | return -EFAULT; | ||
36 | buf->bytesused += copybytes; | ||
37 | return copybytes; | ||
38 | } | ||
39 | |||
40 | void cx18_buf_swap(struct cx18_buffer *buf) | 29 | void cx18_buf_swap(struct cx18_buffer *buf) |
41 | { | 30 | { |
42 | int i; | 31 | int i; |
@@ -159,8 +148,9 @@ static void cx18_queue_move_buf(struct cx18_stream *s, struct cx18_queue *from, | |||
159 | -ENOMEM is returned if the buffers could not be obtained, 0 if all | 148 | -ENOMEM is returned if the buffers could not be obtained, 0 if all |
160 | buffers where obtained from the 'from' list and if non-zero then | 149 | buffers where obtained from the 'from' list and if non-zero then |
161 | the number of stolen buffers is returned. */ | 150 | the number of stolen buffers is returned. */ |
162 | int cx18_queue_move(struct cx18_stream *s, struct cx18_queue *from, | 151 | static int cx18_queue_move(struct cx18_stream *s, struct cx18_queue *from, |
163 | struct cx18_queue *steal, struct cx18_queue *to, int needed_bytes) | 152 | struct cx18_queue *steal, struct cx18_queue *to, |
153 | int needed_bytes) | ||
164 | { | 154 | { |
165 | unsigned long flags; | 155 | unsigned long flags; |
166 | int rc = 0; | 156 | int rc = 0; |
@@ -239,12 +229,12 @@ int cx18_stream_alloc(struct cx18_stream *s) | |||
239 | 229 | ||
240 | /* allocate stream buffers. Initially all buffers are in q_free. */ | 230 | /* allocate stream buffers. Initially all buffers are in q_free. */ |
241 | for (i = 0; i < s->buffers; i++) { | 231 | for (i = 0; i < s->buffers; i++) { |
242 | struct cx18_buffer *buf = | 232 | struct cx18_buffer *buf = kzalloc(sizeof(struct cx18_buffer), |
243 | kzalloc(sizeof(struct cx18_buffer), GFP_KERNEL); | 233 | GFP_KERNEL|__GFP_NOWARN); |
244 | 234 | ||
245 | if (buf == NULL) | 235 | if (buf == NULL) |
246 | break; | 236 | break; |
247 | buf->buf = kmalloc(s->buf_size, GFP_KERNEL); | 237 | buf->buf = kmalloc(s->buf_size, GFP_KERNEL|__GFP_NOWARN); |
248 | if (buf->buf == NULL) { | 238 | if (buf->buf == NULL) { |
249 | kfree(buf); | 239 | kfree(buf); |
250 | break; | 240 | break; |
diff --git a/drivers/media/video/cx18/cx18-queue.h b/drivers/media/video/cx18/cx18-queue.h index f86c8a6fa6e7..91423b9863a4 100644 --- a/drivers/media/video/cx18/cx18-queue.h +++ b/drivers/media/video/cx18/cx18-queue.h | |||
@@ -39,8 +39,6 @@ static inline void cx18_buf_sync_for_device(struct cx18_stream *s, | |||
39 | s->buf_size, s->dma); | 39 | s->buf_size, s->dma); |
40 | } | 40 | } |
41 | 41 | ||
42 | int cx18_buf_copy_from_user(struct cx18_stream *s, struct cx18_buffer *buf, | ||
43 | const char __user *src, int copybytes); | ||
44 | void cx18_buf_swap(struct cx18_buffer *buf); | 42 | void cx18_buf_swap(struct cx18_buffer *buf); |
45 | 43 | ||
46 | /* cx18_queue utility functions */ | 44 | /* cx18_queue utility functions */ |
@@ -48,8 +46,6 @@ void cx18_queue_init(struct cx18_queue *q); | |||
48 | void cx18_enqueue(struct cx18_stream *s, struct cx18_buffer *buf, | 46 | void cx18_enqueue(struct cx18_stream *s, struct cx18_buffer *buf, |
49 | struct cx18_queue *q); | 47 | struct cx18_queue *q); |
50 | struct cx18_buffer *cx18_dequeue(struct cx18_stream *s, struct cx18_queue *q); | 48 | struct cx18_buffer *cx18_dequeue(struct cx18_stream *s, struct cx18_queue *q); |
51 | int cx18_queue_move(struct cx18_stream *s, struct cx18_queue *from, | ||
52 | struct cx18_queue *steal, struct cx18_queue *to, int needed_bytes); | ||
53 | struct cx18_buffer *cx18_queue_find_buf(struct cx18_stream *s, u32 id, | 49 | struct cx18_buffer *cx18_queue_find_buf(struct cx18_stream *s, u32 id, |
54 | u32 bytesused); | 50 | u32 bytesused); |
55 | void cx18_flush_queues(struct cx18_stream *s); | 51 | void cx18_flush_queues(struct cx18_stream *s); |
diff --git a/drivers/media/video/cx18/cx18-streams.c b/drivers/media/video/cx18/cx18-streams.c index afb141b2027a..1b921a336092 100644 --- a/drivers/media/video/cx18/cx18-streams.c +++ b/drivers/media/video/cx18/cx18-streams.c | |||
@@ -36,12 +36,13 @@ | |||
36 | #define CX18_DSP0_INTERRUPT_MASK 0xd0004C | 36 | #define CX18_DSP0_INTERRUPT_MASK 0xd0004C |
37 | 37 | ||
38 | static struct file_operations cx18_v4l2_enc_fops = { | 38 | static struct file_operations cx18_v4l2_enc_fops = { |
39 | .owner = THIS_MODULE, | 39 | .owner = THIS_MODULE, |
40 | .read = cx18_v4l2_read, | 40 | .read = cx18_v4l2_read, |
41 | .open = cx18_v4l2_open, | 41 | .open = cx18_v4l2_open, |
42 | .ioctl = cx18_v4l2_ioctl, | 42 | .ioctl = cx18_v4l2_ioctl, |
43 | .release = cx18_v4l2_close, | 43 | .compat_ioctl = v4l_compat_ioctl32, |
44 | .poll = cx18_v4l2_enc_poll, | 44 | .release = cx18_v4l2_close, |
45 | .poll = cx18_v4l2_enc_poll, | ||
45 | }; | 46 | }; |
46 | 47 | ||
47 | /* offset from 0 to register ts v4l2 minors on */ | 48 | /* offset from 0 to register ts v4l2 minors on */ |
@@ -218,7 +219,7 @@ int cx18_streams_setup(struct cx18 *cx) | |||
218 | return 0; | 219 | return 0; |
219 | 220 | ||
220 | /* One or more streams could not be initialized. Clean 'em all up. */ | 221 | /* One or more streams could not be initialized. Clean 'em all up. */ |
221 | cx18_streams_cleanup(cx); | 222 | cx18_streams_cleanup(cx, 0); |
222 | return -ENOMEM; | 223 | return -ENOMEM; |
223 | } | 224 | } |
224 | 225 | ||
@@ -296,12 +297,12 @@ int cx18_streams_register(struct cx18 *cx) | |||
296 | return 0; | 297 | return 0; |
297 | 298 | ||
298 | /* One or more streams could not be initialized. Clean 'em all up. */ | 299 | /* One or more streams could not be initialized. Clean 'em all up. */ |
299 | cx18_streams_cleanup(cx); | 300 | cx18_streams_cleanup(cx, 1); |
300 | return -ENOMEM; | 301 | return -ENOMEM; |
301 | } | 302 | } |
302 | 303 | ||
303 | /* Unregister v4l2 devices */ | 304 | /* Unregister v4l2 devices */ |
304 | void cx18_streams_cleanup(struct cx18 *cx) | 305 | void cx18_streams_cleanup(struct cx18 *cx, int unregister) |
305 | { | 306 | { |
306 | struct video_device *vdev; | 307 | struct video_device *vdev; |
307 | int type; | 308 | int type; |
@@ -319,8 +320,11 @@ void cx18_streams_cleanup(struct cx18 *cx) | |||
319 | 320 | ||
320 | cx18_stream_free(&cx->streams[type]); | 321 | cx18_stream_free(&cx->streams[type]); |
321 | 322 | ||
322 | /* Unregister device */ | 323 | /* Unregister or release device */ |
323 | video_unregister_device(vdev); | 324 | if (unregister) |
325 | video_unregister_device(vdev); | ||
326 | else | ||
327 | video_device_release(vdev); | ||
324 | } | 328 | } |
325 | } | 329 | } |
326 | 330 | ||
@@ -440,7 +444,7 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s) | |||
440 | s->handle = data[0]; | 444 | s->handle = data[0]; |
441 | cx18_vapi(cx, CX18_CPU_SET_CHANNEL_TYPE, 2, s->handle, captype); | 445 | cx18_vapi(cx, CX18_CPU_SET_CHANNEL_TYPE, 2, s->handle, captype); |
442 | 446 | ||
443 | if (atomic_read(&cx->capturing) == 0 && !ts) { | 447 | if (atomic_read(&cx->ana_capturing) == 0 && !ts) { |
444 | /* Stuff from Windows, we don't know what it is */ | 448 | /* Stuff from Windows, we don't know what it is */ |
445 | cx18_vapi(cx, CX18_CPU_SET_VER_CROP_LINE, 2, s->handle, 0); | 449 | cx18_vapi(cx, CX18_CPU_SET_VER_CROP_LINE, 2, s->handle, 0); |
446 | cx18_vapi(cx, CX18_CPU_SET_MISC_PARAMETERS, 3, s->handle, 3, 1); | 450 | cx18_vapi(cx, CX18_CPU_SET_MISC_PARAMETERS, 3, s->handle, 3, 1); |
@@ -463,14 +467,14 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s) | |||
463 | cx2341x_update(cx, cx18_api_func, NULL, &cx->params); | 467 | cx2341x_update(cx, cx18_api_func, NULL, &cx->params); |
464 | } | 468 | } |
465 | 469 | ||
466 | if (atomic_read(&cx->capturing) == 0) { | 470 | if (atomic_read(&cx->tot_capturing) == 0) { |
467 | clear_bit(CX18_F_I_EOS, &cx->i_flags); | 471 | clear_bit(CX18_F_I_EOS, &cx->i_flags); |
468 | write_reg(7, CX18_DSP0_INTERRUPT_MASK); | 472 | write_reg(7, CX18_DSP0_INTERRUPT_MASK); |
469 | } | 473 | } |
470 | 474 | ||
471 | cx18_vapi(cx, CX18_CPU_DE_SET_MDL_ACK, 3, s->handle, | 475 | cx18_vapi(cx, CX18_CPU_DE_SET_MDL_ACK, 3, s->handle, |
472 | (void *)&cx->scb->cpu_mdl_ack[s->type][0] - cx->enc_mem, | 476 | (void __iomem *)&cx->scb->cpu_mdl_ack[s->type][0] - cx->enc_mem, |
473 | (void *)&cx->scb->cpu_mdl_ack[s->type][1] - cx->enc_mem); | 477 | (void __iomem *)&cx->scb->cpu_mdl_ack[s->type][1] - cx->enc_mem); |
474 | 478 | ||
475 | list_for_each(p, &s->q_free.list) { | 479 | list_for_each(p, &s->q_free.list) { |
476 | struct cx18_buffer *buf = list_entry(p, struct cx18_buffer, list); | 480 | struct cx18_buffer *buf = list_entry(p, struct cx18_buffer, list); |
@@ -478,8 +482,8 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s) | |||
478 | writel(buf->dma_handle, &cx->scb->cpu_mdl[buf->id].paddr); | 482 | writel(buf->dma_handle, &cx->scb->cpu_mdl[buf->id].paddr); |
479 | writel(s->buf_size, &cx->scb->cpu_mdl[buf->id].length); | 483 | writel(s->buf_size, &cx->scb->cpu_mdl[buf->id].length); |
480 | cx18_vapi(cx, CX18_CPU_DE_SET_MDL, 5, s->handle, | 484 | cx18_vapi(cx, CX18_CPU_DE_SET_MDL, 5, s->handle, |
481 | (void *)&cx->scb->cpu_mdl[buf->id] - cx->enc_mem, 1, | 485 | (void __iomem *)&cx->scb->cpu_mdl[buf->id] - cx->enc_mem, |
482 | buf->id, s->buf_size); | 486 | 1, buf->id, s->buf_size); |
483 | } | 487 | } |
484 | /* begin_capture */ | 488 | /* begin_capture */ |
485 | if (cx18_vapi(cx, CX18_CPU_CAPTURE_START, 1, s->handle)) { | 489 | if (cx18_vapi(cx, CX18_CPU_CAPTURE_START, 1, s->handle)) { |
@@ -489,7 +493,9 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s) | |||
489 | } | 493 | } |
490 | 494 | ||
491 | /* you're live! sit back and await interrupts :) */ | 495 | /* you're live! sit back and await interrupts :) */ |
492 | atomic_inc(&cx->capturing); | 496 | if (!ts) |
497 | atomic_inc(&cx->ana_capturing); | ||
498 | atomic_inc(&cx->tot_capturing); | ||
493 | return 0; | 499 | return 0; |
494 | } | 500 | } |
495 | 501 | ||
@@ -520,7 +526,7 @@ int cx18_stop_v4l2_encode_stream(struct cx18_stream *s, int gop_end) | |||
520 | 526 | ||
521 | CX18_DEBUG_INFO("Stop Capture\n"); | 527 | CX18_DEBUG_INFO("Stop Capture\n"); |
522 | 528 | ||
523 | if (atomic_read(&cx->capturing) == 0) | 529 | if (atomic_read(&cx->tot_capturing) == 0) |
524 | return 0; | 530 | return 0; |
525 | 531 | ||
526 | if (s->type == CX18_ENC_STREAM_TYPE_MPG) | 532 | if (s->type == CX18_ENC_STREAM_TYPE_MPG) |
@@ -534,7 +540,9 @@ int cx18_stop_v4l2_encode_stream(struct cx18_stream *s, int gop_end) | |||
534 | CX18_INFO("ignoring gop_end: not (yet?) supported by the firmware\n"); | 540 | CX18_INFO("ignoring gop_end: not (yet?) supported by the firmware\n"); |
535 | } | 541 | } |
536 | 542 | ||
537 | atomic_dec(&cx->capturing); | 543 | if (s->type != CX18_ENC_STREAM_TYPE_TS) |
544 | atomic_dec(&cx->ana_capturing); | ||
545 | atomic_dec(&cx->tot_capturing); | ||
538 | 546 | ||
539 | /* Clear capture and no-read bits */ | 547 | /* Clear capture and no-read bits */ |
540 | clear_bit(CX18_F_S_STREAMING, &s->s_flags); | 548 | clear_bit(CX18_F_S_STREAMING, &s->s_flags); |
@@ -542,7 +550,7 @@ int cx18_stop_v4l2_encode_stream(struct cx18_stream *s, int gop_end) | |||
542 | cx18_vapi(cx, CX18_DESTROY_TASK, 1, s->handle); | 550 | cx18_vapi(cx, CX18_DESTROY_TASK, 1, s->handle); |
543 | s->handle = 0xffffffff; | 551 | s->handle = 0xffffffff; |
544 | 552 | ||
545 | if (atomic_read(&cx->capturing) > 0) | 553 | if (atomic_read(&cx->tot_capturing) > 0) |
546 | return 0; | 554 | return 0; |
547 | 555 | ||
548 | write_reg(5, CX18_DSP0_INTERRUPT_MASK); | 556 | write_reg(5, CX18_DSP0_INTERRUPT_MASK); |
diff --git a/drivers/media/video/cx18/cx18-streams.h b/drivers/media/video/cx18/cx18-streams.h index 8c7ba7d2fa79..f327e947b24f 100644 --- a/drivers/media/video/cx18/cx18-streams.h +++ b/drivers/media/video/cx18/cx18-streams.h | |||
@@ -24,7 +24,7 @@ | |||
24 | u32 cx18_find_handle(struct cx18 *cx); | 24 | u32 cx18_find_handle(struct cx18 *cx); |
25 | int cx18_streams_setup(struct cx18 *cx); | 25 | int cx18_streams_setup(struct cx18 *cx); |
26 | int cx18_streams_register(struct cx18 *cx); | 26 | int cx18_streams_register(struct cx18 *cx); |
27 | void cx18_streams_cleanup(struct cx18 *cx); | 27 | void cx18_streams_cleanup(struct cx18 *cx, int unregister); |
28 | 28 | ||
29 | /* Capture related */ | 29 | /* Capture related */ |
30 | int cx18_start_v4l2_encode_stream(struct cx18_stream *s); | 30 | int cx18_start_v4l2_encode_stream(struct cx18_stream *s); |