diff options
author | Hans Verkuil <hverkuil@xs4all.nl> | 2007-04-27 11:31:25 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@infradead.org> | 2007-04-27 14:43:50 -0400 |
commit | 1a0adaf37c30e89e44d1470ef604a930999a5826 (patch) | |
tree | 6e6d6e823f44abdb2ed3847e00406a75bc968cef | |
parent | ac52ea3c3c04403d10acf0253180ec6f51977142 (diff) |
V4L/DVB (5345): ivtv driver for Conexant cx23416/cx23415 MPEG encoder/decoder
It took three core maintainers, over four years of work, eight new i2c
modules, eleven new V4L2 ioctls, three new DVB video ioctls, a Sliced
VBI API, a new MPEG encoder API, an enhanced DVB video MPEG decoding
API, major YUV/OSD contributions from Ian and John, web/wiki/svn/trac
support from Axel Thimm, (hardware) support from Hauppauge, support and
assistance from the v4l-dvb people and the many, many users of ivtv to
finally make it possible to merge this driver into the kernel.
Thank you all!
Signed-off-by: Kevin Thayer <nufan_wfk@yahoo.com>
Signed-off-by: Chris Kennedy <c@groovy.org>
Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: John P Harvey <john.p.harvey@btinternet.com>
Signed-off-by: Ian Armstrong <ian@iarmst.demon.co.uk>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
40 files changed, 12637 insertions, 0 deletions
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index fa0a87679190..639e8b6c35b1 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig | |||
@@ -647,6 +647,8 @@ config VIDEO_HEXIUM_GEMINI | |||
647 | 647 | ||
648 | source "drivers/media/video/cx88/Kconfig" | 648 | source "drivers/media/video/cx88/Kconfig" |
649 | 649 | ||
650 | source "drivers/media/video/ivtv/Kconfig" | ||
651 | |||
650 | config VIDEO_M32R_AR | 652 | config VIDEO_M32R_AR |
651 | tristate "AR devices" | 653 | tristate "AR devices" |
652 | depends on M32R && VIDEO_V4L1 | 654 | depends on M32R && VIDEO_V4L1 |
diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index 384f01c133c5..9c2de501612f 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile | |||
@@ -61,6 +61,7 @@ obj-$(CONFIG_VIDEO_CPIA_USB) += cpia_usb.o | |||
61 | obj-$(CONFIG_VIDEO_MEYE) += meye.o | 61 | obj-$(CONFIG_VIDEO_MEYE) += meye.o |
62 | obj-$(CONFIG_VIDEO_SAA7134) += ir-kbd-i2c.o saa7134/ | 62 | obj-$(CONFIG_VIDEO_SAA7134) += ir-kbd-i2c.o saa7134/ |
63 | obj-$(CONFIG_VIDEO_CX88) += cx88/ | 63 | obj-$(CONFIG_VIDEO_CX88) += cx88/ |
64 | obj-$(CONFIG_VIDEO_IVTV) += ivtv/ | ||
64 | obj-$(CONFIG_VIDEO_EM28XX) += em28xx/ | 65 | obj-$(CONFIG_VIDEO_EM28XX) += em28xx/ |
65 | obj-$(CONFIG_VIDEO_USBVISION) += usbvision/ | 66 | obj-$(CONFIG_VIDEO_USBVISION) += usbvision/ |
66 | obj-$(CONFIG_VIDEO_TVP5150) += tvp5150.o | 67 | obj-$(CONFIG_VIDEO_TVP5150) += tvp5150.o |
diff --git a/drivers/media/video/ivtv/Kconfig b/drivers/media/video/ivtv/Kconfig new file mode 100644 index 000000000000..88e510171347 --- /dev/null +++ b/drivers/media/video/ivtv/Kconfig | |||
@@ -0,0 +1,26 @@ | |||
1 | config VIDEO_IVTV | ||
2 | tristate "Conexant cx23416/cx23415 MPEG encoder/decoder support" | ||
3 | depends on VIDEO_V4L2 && USB && I2C && EXPERIMENTAL | ||
4 | select FW_LOADER | ||
5 | select VIDEO_TUNER | ||
6 | select VIDEO_TVEEPROM | ||
7 | select VIDEO_CX2341X | ||
8 | select VIDEO_MSP3400 | ||
9 | select VIDEO_SAA711X | ||
10 | select VIDEO_SAA7127 | ||
11 | select VIDEO_TVAUDIO | ||
12 | select VIDEO_CS53L32A | ||
13 | select VIDEO_TLV320AIC23B | ||
14 | select VIDEO_WM8775 | ||
15 | select VIDEO_WM8739 | ||
16 | select VIDEO_UPD64031A | ||
17 | select VIDEO_UPD64083 | ||
18 | ---help--- | ||
19 | This is a video4linux driver for Conexant cx23416 or cx23416 based | ||
20 | PCI personal video recorder devices. | ||
21 | |||
22 | This is used in devices such as the Hauppauge PVR-150/250/350/500 | ||
23 | cards. | ||
24 | |||
25 | To compile this driver as a module, choose M here: the | ||
26 | module will be called ivtv. | ||
diff --git a/drivers/media/video/ivtv/Makefile b/drivers/media/video/ivtv/Makefile new file mode 100644 index 000000000000..7e95148fbf4f --- /dev/null +++ b/drivers/media/video/ivtv/Makefile | |||
@@ -0,0 +1,7 @@ | |||
1 | ivtv-objs := ivtv-audio.o ivtv-cards.o ivtv-controls.o \ | ||
2 | ivtv-driver.o ivtv-fileops.o ivtv-firmware.o \ | ||
3 | ivtv-gpio.o ivtv-i2c.o ivtv-ioctl.o ivtv-irq.o \ | ||
4 | ivtv-mailbox.o ivtv-queue.o ivtv-streams.o ivtv-udma.o \ | ||
5 | ivtv-vbi.o ivtv-video.o ivtv-yuv.o | ||
6 | |||
7 | obj-$(CONFIG_VIDEO_IVTV) += ivtv.o | ||
diff --git a/drivers/media/video/ivtv/ivtv-audio.c b/drivers/media/video/ivtv/ivtv-audio.c new file mode 100644 index 000000000000..d702b8b539a1 --- /dev/null +++ b/drivers/media/video/ivtv/ivtv-audio.c | |||
@@ -0,0 +1,74 @@ | |||
1 | /* | ||
2 | Audio-related ivtv functions. | ||
3 | Copyright (C) 2003-2004 Kevin Thayer <nufan_wfk at yahoo.com> | ||
4 | Copyright (C) 2005-2007 Hans Verkuil <hverkuil@xs4all.nl> | ||
5 | |||
6 | This program is free software; you can redistribute it and/or modify | ||
7 | it under the terms of the GNU General Public License as published by | ||
8 | the Free Software Foundation; either version 2 of the License, or | ||
9 | (at your option) any later version. | ||
10 | |||
11 | This program is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program; if not, write to the Free Software | ||
18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | */ | ||
20 | |||
21 | #include "ivtv-driver.h" | ||
22 | #include "ivtv-mailbox.h" | ||
23 | #include "ivtv-i2c.h" | ||
24 | #include "ivtv-gpio.h" | ||
25 | #include "ivtv-cards.h" | ||
26 | #include "ivtv-audio.h" | ||
27 | #include <media/msp3400.h> | ||
28 | #include <linux/videodev.h> | ||
29 | |||
30 | /* Selects the audio input and output according to the current | ||
31 | settings. */ | ||
32 | int ivtv_audio_set_io(struct ivtv *itv) | ||
33 | { | ||
34 | struct v4l2_routing route; | ||
35 | u32 audio_input; | ||
36 | int mux_input; | ||
37 | |||
38 | /* Determine which input to use */ | ||
39 | if (test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags)) { | ||
40 | audio_input = itv->card->radio_input.audio_input; | ||
41 | mux_input = itv->card->radio_input.muxer_input; | ||
42 | } else { | ||
43 | audio_input = itv->card->audio_inputs[itv->audio_input].audio_input; | ||
44 | mux_input = itv->card->audio_inputs[itv->audio_input].muxer_input; | ||
45 | } | ||
46 | |||
47 | /* handle muxer chips */ | ||
48 | route.input = mux_input; | ||
49 | route.output = 0; | ||
50 | ivtv_i2c_hw(itv, itv->card->hw_muxer, VIDIOC_INT_S_AUDIO_ROUTING, &route); | ||
51 | |||
52 | route.input = audio_input; | ||
53 | if (itv->card->hw_audio & IVTV_HW_MSP34XX) { | ||
54 | route.output = MSP_OUTPUT(MSP_SC_IN_DSP_SCART1); | ||
55 | } | ||
56 | return ivtv_i2c_hw(itv, itv->card->hw_audio, VIDIOC_INT_S_AUDIO_ROUTING, &route); | ||
57 | } | ||
58 | |||
59 | void ivtv_audio_set_route(struct ivtv *itv, struct v4l2_routing *route) | ||
60 | { | ||
61 | ivtv_i2c_hw(itv, itv->card->hw_audio, VIDIOC_INT_S_AUDIO_ROUTING, route); | ||
62 | } | ||
63 | |||
64 | void ivtv_audio_set_audio_clock_freq(struct ivtv *itv, u8 freq) | ||
65 | { | ||
66 | static u32 freqs[3] = { 44100, 48000, 32000 }; | ||
67 | |||
68 | /* The audio clock of the digitizer must match the codec sample | ||
69 | rate otherwise you get some very strange effects. */ | ||
70 | if (freq > 2) | ||
71 | return; | ||
72 | ivtv_call_i2c_clients(itv, VIDIOC_INT_AUDIO_CLOCK_FREQ, &freqs[freq]); | ||
73 | } | ||
74 | |||
diff --git a/drivers/media/video/ivtv/ivtv-audio.h b/drivers/media/video/ivtv/ivtv-audio.h new file mode 100644 index 000000000000..9c42846d8124 --- /dev/null +++ b/drivers/media/video/ivtv/ivtv-audio.h | |||
@@ -0,0 +1,23 @@ | |||
1 | /* | ||
2 | Audio-related ivtv functions. | ||
3 | Copyright (C) 2003-2004 Kevin Thayer <nufan_wfk at yahoo.com> | ||
4 | Copyright (C) 2005-2007 Hans Verkuil <hverkuil@xs4all.nl> | ||
5 | |||
6 | This program is free software; you can redistribute it and/or modify | ||
7 | it under the terms of the GNU General Public License as published by | ||
8 | the Free Software Foundation; either version 2 of the License, or | ||
9 | (at your option) any later version. | ||
10 | |||
11 | This program is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program; if not, write to the Free Software | ||
18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | */ | ||
20 | |||
21 | int ivtv_audio_set_io(struct ivtv *itv); | ||
22 | void ivtv_audio_set_route(struct ivtv *itv, struct v4l2_routing *route); | ||
23 | void ivtv_audio_set_audio_clock_freq(struct ivtv *itv, u8 freq); | ||
diff --git a/drivers/media/video/ivtv/ivtv-cards.c b/drivers/media/video/ivtv/ivtv-cards.c new file mode 100644 index 000000000000..8eab02083887 --- /dev/null +++ b/drivers/media/video/ivtv/ivtv-cards.c | |||
@@ -0,0 +1,964 @@ | |||
1 | /* | ||
2 | Functions to query card hardware | ||
3 | Copyright (C) 2003-2004 Kevin Thayer <nufan_wfk at yahoo.com> | ||
4 | Copyright (C) 2005-2007 Hans Verkuil <hverkuil@xs4all.nl> | ||
5 | |||
6 | This program is free software; you can redistribute it and/or modify | ||
7 | it under the terms of the GNU General Public License as published by | ||
8 | the Free Software Foundation; either version 2 of the License, or | ||
9 | (at your option) any later version. | ||
10 | |||
11 | This program is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program; if not, write to the Free Software | ||
18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | */ | ||
20 | |||
21 | #include "ivtv-driver.h" | ||
22 | #include "ivtv-cards.h" | ||
23 | #include "ivtv-i2c.h" | ||
24 | |||
25 | #include <media/msp3400.h> | ||
26 | #include <media/wm8775.h> | ||
27 | #include <media/cs53l32a.h> | ||
28 | #include <media/cx25840.h> | ||
29 | #include <media/upd64031a.h> | ||
30 | |||
31 | #define MSP_TUNER MSP_INPUT(MSP_IN_SCART1, MSP_IN_TUNER1, \ | ||
32 | MSP_DSP_IN_TUNER, MSP_DSP_IN_TUNER) | ||
33 | #define MSP_SCART1 MSP_INPUT(MSP_IN_SCART1, MSP_IN_TUNER1, \ | ||
34 | MSP_DSP_IN_SCART, MSP_DSP_IN_SCART) | ||
35 | #define MSP_SCART2 MSP_INPUT(MSP_IN_SCART2, MSP_IN_TUNER1, \ | ||
36 | MSP_DSP_IN_SCART, MSP_DSP_IN_SCART) | ||
37 | #define MSP_SCART3 MSP_INPUT(MSP_IN_SCART3, MSP_IN_TUNER1, \ | ||
38 | MSP_DSP_IN_SCART, MSP_DSP_IN_SCART) | ||
39 | #define MSP_MONO MSP_INPUT(MSP_IN_MONO, MSP_IN_TUNER1, \ | ||
40 | MSP_DSP_IN_SCART, MSP_DSP_IN_SCART) | ||
41 | |||
42 | /********************** card configuration *******************************/ | ||
43 | |||
44 | /* Please add new PCI IDs to: http://pci-ids.ucw.cz/iii | ||
45 | This keeps the PCI ID database up to date. Note that the entries | ||
46 | must be added under vendor 0x4444 (Conexant) as subsystem IDs. | ||
47 | New vendor IDs should still be added to the vendor ID list. */ | ||
48 | |||
49 | /* Hauppauge PVR-250 cards */ | ||
50 | |||
51 | /* Note: for Hauppauge cards the tveeprom information is used instead of PCI IDs */ | ||
52 | static const struct ivtv_card ivtv_card_pvr250 = { | ||
53 | .type = IVTV_CARD_PVR_250, | ||
54 | .name = "Hauppauge WinTV PVR-250", | ||
55 | .v4l2_capabilities = IVTV_CAP_ENCODER, | ||
56 | .hw_video = IVTV_HW_SAA7115, | ||
57 | .hw_audio = IVTV_HW_MSP34XX, | ||
58 | .hw_audio_ctrl = IVTV_HW_MSP34XX, | ||
59 | .hw_all = IVTV_HW_MSP34XX | IVTV_HW_SAA7115 | | ||
60 | IVTV_HW_TVEEPROM | IVTV_HW_TUNER, | ||
61 | .video_inputs = { | ||
62 | { IVTV_CARD_INPUT_VID_TUNER, 0, IVTV_SAA71XX_COMPOSITE4 }, | ||
63 | { IVTV_CARD_INPUT_SVIDEO1, 1, IVTV_SAA71XX_SVIDEO0 }, | ||
64 | { IVTV_CARD_INPUT_COMPOSITE1, 1, IVTV_SAA71XX_COMPOSITE0 }, | ||
65 | { IVTV_CARD_INPUT_SVIDEO2, 2, IVTV_SAA71XX_SVIDEO1 }, | ||
66 | { IVTV_CARD_INPUT_COMPOSITE2, 2, IVTV_SAA71XX_COMPOSITE1 }, | ||
67 | { IVTV_CARD_INPUT_COMPOSITE3, 1, IVTV_SAA71XX_COMPOSITE5 }, | ||
68 | }, | ||
69 | .audio_inputs = { | ||
70 | { IVTV_CARD_INPUT_AUD_TUNER, MSP_TUNER }, | ||
71 | { IVTV_CARD_INPUT_LINE_IN1, MSP_SCART1 }, | ||
72 | { IVTV_CARD_INPUT_LINE_IN2, MSP_SCART3 }, | ||
73 | }, | ||
74 | .radio_input = { IVTV_CARD_INPUT_AUD_TUNER, MSP_SCART2 }, | ||
75 | }; | ||
76 | |||
77 | /* ------------------------------------------------------------------------- */ | ||
78 | |||
79 | /* Hauppauge PVR-350 cards */ | ||
80 | |||
81 | /* Outputs for Hauppauge PVR350 cards */ | ||
82 | static struct ivtv_card_output ivtv_pvr350_outputs[] = { | ||
83 | { | ||
84 | .name = "S-Video + Composite", | ||
85 | .video_output = 0, | ||
86 | }, { | ||
87 | .name = "Composite", | ||
88 | .video_output = 1, | ||
89 | }, { | ||
90 | .name = "S-Video", | ||
91 | .video_output = 2, | ||
92 | }, { | ||
93 | .name = "RGB", | ||
94 | .video_output = 3, | ||
95 | }, { | ||
96 | .name = "YUV C", | ||
97 | .video_output = 4, | ||
98 | }, { | ||
99 | .name = "YUV V", | ||
100 | .video_output = 5, | ||
101 | } | ||
102 | }; | ||
103 | |||
104 | static const struct ivtv_card ivtv_card_pvr350 = { | ||
105 | .type = IVTV_CARD_PVR_350, | ||
106 | .name = "Hauppauge WinTV PVR-350", | ||
107 | .v4l2_capabilities = IVTV_CAP_ENCODER | IVTV_CAP_DECODER, | ||
108 | .video_outputs = ivtv_pvr350_outputs, | ||
109 | .nof_outputs = ARRAY_SIZE(ivtv_pvr350_outputs), | ||
110 | .hw_video = IVTV_HW_SAA7115, | ||
111 | .hw_audio = IVTV_HW_MSP34XX, | ||
112 | .hw_audio_ctrl = IVTV_HW_MSP34XX, | ||
113 | .hw_all = IVTV_HW_MSP34XX | IVTV_HW_SAA7115 | | ||
114 | IVTV_HW_SAA7127 | IVTV_HW_TVEEPROM | IVTV_HW_TUNER, | ||
115 | .video_inputs = { | ||
116 | { IVTV_CARD_INPUT_VID_TUNER, 0, IVTV_SAA71XX_COMPOSITE4 }, | ||
117 | { IVTV_CARD_INPUT_SVIDEO1, 1, IVTV_SAA71XX_SVIDEO0 }, | ||
118 | { IVTV_CARD_INPUT_COMPOSITE1, 1, IVTV_SAA71XX_COMPOSITE0 }, | ||
119 | { IVTV_CARD_INPUT_SVIDEO2, 2, IVTV_SAA71XX_SVIDEO1 }, | ||
120 | { IVTV_CARD_INPUT_COMPOSITE2, 2, IVTV_SAA71XX_COMPOSITE1 }, | ||
121 | { IVTV_CARD_INPUT_COMPOSITE3, 1, IVTV_SAA71XX_COMPOSITE5 }, | ||
122 | }, | ||
123 | .audio_inputs = { | ||
124 | { IVTV_CARD_INPUT_AUD_TUNER, MSP_TUNER }, | ||
125 | { IVTV_CARD_INPUT_LINE_IN1, MSP_SCART1 }, | ||
126 | { IVTV_CARD_INPUT_LINE_IN2, MSP_SCART3 }, | ||
127 | }, | ||
128 | .radio_input = { IVTV_CARD_INPUT_AUD_TUNER, MSP_SCART2 }, | ||
129 | }; | ||
130 | |||
131 | /* PVR-350 V1 boards have a different audio tuner input and use a | ||
132 | saa7114 instead of a saa7115. | ||
133 | Note that the info below comes from a pre-production model so it may | ||
134 | not be correct. Especially the audio behaves strangely (mono only it seems) */ | ||
135 | static const struct ivtv_card ivtv_card_pvr350_v1 = { | ||
136 | .type = IVTV_CARD_PVR_350_V1, | ||
137 | .name = "Hauppauge WinTV PVR-350 (V1)", | ||
138 | .v4l2_capabilities = IVTV_CAP_ENCODER | IVTV_CAP_DECODER, | ||
139 | .video_outputs = ivtv_pvr350_outputs, | ||
140 | .nof_outputs = ARRAY_SIZE(ivtv_pvr350_outputs), | ||
141 | .hw_video = IVTV_HW_SAA7114, | ||
142 | .hw_audio = IVTV_HW_MSP34XX, | ||
143 | .hw_audio_ctrl = IVTV_HW_MSP34XX, | ||
144 | .hw_all = IVTV_HW_MSP34XX | IVTV_HW_SAA7114 | | ||
145 | IVTV_HW_SAA7127 | IVTV_HW_TVEEPROM | IVTV_HW_TUNER, | ||
146 | .video_inputs = { | ||
147 | { IVTV_CARD_INPUT_VID_TUNER, 0, IVTV_SAA71XX_COMPOSITE4 }, | ||
148 | { IVTV_CARD_INPUT_SVIDEO1, 1, IVTV_SAA71XX_SVIDEO0 }, | ||
149 | { IVTV_CARD_INPUT_COMPOSITE1, 1, IVTV_SAA71XX_COMPOSITE0 }, | ||
150 | { IVTV_CARD_INPUT_SVIDEO2, 2, IVTV_SAA71XX_SVIDEO1 }, | ||
151 | { IVTV_CARD_INPUT_COMPOSITE2, 2, IVTV_SAA71XX_COMPOSITE1 }, | ||
152 | { IVTV_CARD_INPUT_COMPOSITE3, 1, IVTV_SAA71XX_COMPOSITE5 }, | ||
153 | }, | ||
154 | .audio_inputs = { | ||
155 | { IVTV_CARD_INPUT_AUD_TUNER, MSP_MONO }, | ||
156 | { IVTV_CARD_INPUT_LINE_IN1, MSP_SCART1 }, | ||
157 | { IVTV_CARD_INPUT_LINE_IN2, MSP_SCART3 }, | ||
158 | }, | ||
159 | .radio_input = { IVTV_CARD_INPUT_AUD_TUNER, MSP_SCART2 }, | ||
160 | }; | ||
161 | |||
162 | /* ------------------------------------------------------------------------- */ | ||
163 | |||
164 | /* Hauppauge PVR-150/PVR-500 cards */ | ||
165 | |||
166 | static const struct ivtv_card ivtv_card_pvr150 = { | ||
167 | .type = IVTV_CARD_PVR_150, | ||
168 | .name = "Hauppauge WinTV PVR-150", | ||
169 | .v4l2_capabilities = IVTV_CAP_ENCODER, | ||
170 | .hw_video = IVTV_HW_CX25840, | ||
171 | .hw_audio = IVTV_HW_CX25840, | ||
172 | .hw_audio_ctrl = IVTV_HW_CX25840, | ||
173 | .hw_muxer = IVTV_HW_WM8775, | ||
174 | .hw_all = IVTV_HW_WM8775 | IVTV_HW_CX25840 | | ||
175 | IVTV_HW_TVEEPROM | IVTV_HW_TUNER, | ||
176 | .video_inputs = { | ||
177 | { IVTV_CARD_INPUT_VID_TUNER, 0, CX25840_COMPOSITE7 }, | ||
178 | { IVTV_CARD_INPUT_SVIDEO1, 1, CX25840_SVIDEO1 }, | ||
179 | { IVTV_CARD_INPUT_COMPOSITE1, 1, CX25840_COMPOSITE3 }, | ||
180 | { IVTV_CARD_INPUT_SVIDEO2, 2, CX25840_SVIDEO2 }, | ||
181 | { IVTV_CARD_INPUT_COMPOSITE2, 2, CX25840_COMPOSITE4 }, | ||
182 | }, | ||
183 | .audio_inputs = { | ||
184 | { IVTV_CARD_INPUT_AUD_TUNER, | ||
185 | CX25840_AUDIO8, WM8775_AIN2 }, | ||
186 | { IVTV_CARD_INPUT_LINE_IN1, | ||
187 | CX25840_AUDIO_SERIAL, WM8775_AIN2 }, | ||
188 | { IVTV_CARD_INPUT_LINE_IN2, | ||
189 | CX25840_AUDIO_SERIAL, WM8775_AIN3 }, | ||
190 | }, | ||
191 | .radio_input = { IVTV_CARD_INPUT_AUD_TUNER, | ||
192 | CX25840_AUDIO_SERIAL, WM8775_AIN4 }, | ||
193 | /* apparently needed for the IR blaster */ | ||
194 | .gpio_init = { .direction = 0x1f01, .initial_value = 0x26f3 }, | ||
195 | }; | ||
196 | |||
197 | /* ------------------------------------------------------------------------- */ | ||
198 | |||
199 | /* AVerMedia M179 cards */ | ||
200 | |||
201 | static const struct ivtv_card_pci_info ivtv_pci_m179[] = { | ||
202 | { PCI_DEVICE_ID_IVTV15, IVTV_PCI_ID_AVERMEDIA, 0xa3cf }, | ||
203 | { PCI_DEVICE_ID_IVTV15, IVTV_PCI_ID_AVERMEDIA, 0xa3ce }, | ||
204 | { 0, 0, 0 } | ||
205 | }; | ||
206 | |||
207 | static const struct ivtv_card ivtv_card_m179 = { | ||
208 | .type = IVTV_CARD_M179, | ||
209 | .name = "AVerMedia M179", | ||
210 | .v4l2_capabilities = IVTV_CAP_ENCODER, | ||
211 | .hw_video = IVTV_HW_SAA7114, | ||
212 | .hw_audio = IVTV_HW_GPIO, | ||
213 | .hw_audio_ctrl = IVTV_HW_GPIO, | ||
214 | .hw_all = IVTV_HW_GPIO | IVTV_HW_SAA7114 | IVTV_HW_TUNER, | ||
215 | .video_inputs = { | ||
216 | { IVTV_CARD_INPUT_VID_TUNER, 0, IVTV_SAA71XX_COMPOSITE4 }, | ||
217 | { IVTV_CARD_INPUT_SVIDEO1, 1, IVTV_SAA71XX_SVIDEO0 }, | ||
218 | { IVTV_CARD_INPUT_COMPOSITE1, 1, IVTV_SAA71XX_COMPOSITE3 }, | ||
219 | }, | ||
220 | .audio_inputs = { | ||
221 | { IVTV_CARD_INPUT_AUD_TUNER, IVTV_GPIO_TUNER }, | ||
222 | { IVTV_CARD_INPUT_LINE_IN1, IVTV_GPIO_LINE_IN }, | ||
223 | }, | ||
224 | .gpio_init = { .direction = 0xe380, .initial_value = 0x8290 }, | ||
225 | .gpio_audio_input = { .mask = 0x8040, .tuner = 0x8000, .linein = 0x0000 }, | ||
226 | .gpio_audio_mute = { .mask = 0x2000, .mute = 0x2000 }, | ||
227 | .gpio_audio_mode = { .mask = 0x4300, .mono = 0x4000, .stereo = 0x0200, | ||
228 | .lang1 = 0x0200, .lang2 = 0x0100, .both = 0x0000 }, | ||
229 | .gpio_audio_freq = { .mask = 0x0018, .f32000 = 0x0000, | ||
230 | .f44100 = 0x0008, .f48000 = 0x0010 }, | ||
231 | .gpio_audio_detect = { .mask = 0x4000, .stereo = 0x0000 }, | ||
232 | .tuners = { | ||
233 | /* As far as we know all M179 cards use this tuner */ | ||
234 | { .std = V4L2_STD_ALL, .tuner = TUNER_PHILIPS_NTSC }, | ||
235 | }, | ||
236 | .pci_list = ivtv_pci_m179, | ||
237 | }; | ||
238 | |||
239 | /* ------------------------------------------------------------------------- */ | ||
240 | |||
241 | /* Yuan MPG600/Kuroutoshikou ITVC16-STVLP cards */ | ||
242 | |||
243 | static const struct ivtv_card_pci_info ivtv_pci_mpg600[] = { | ||
244 | { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_YUAN1, 0xfff3 }, | ||
245 | { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_YUAN1, 0xffff }, | ||
246 | { 0, 0, 0 } | ||
247 | }; | ||
248 | |||
249 | static const struct ivtv_card ivtv_card_mpg600 = { | ||
250 | .type = IVTV_CARD_MPG600, | ||
251 | .name = "Yuan MPG600, Kuroutoshikou ITVC16-STVLP", | ||
252 | .v4l2_capabilities = IVTV_CAP_ENCODER, | ||
253 | .hw_video = IVTV_HW_SAA7115, | ||
254 | .hw_audio = IVTV_HW_GPIO, | ||
255 | .hw_audio_ctrl = IVTV_HW_GPIO, | ||
256 | .hw_all = IVTV_HW_GPIO | IVTV_HW_SAA7115 | IVTV_HW_TUNER, | ||
257 | .video_inputs = { | ||
258 | { IVTV_CARD_INPUT_VID_TUNER, 0, IVTV_SAA71XX_COMPOSITE4 }, | ||
259 | { IVTV_CARD_INPUT_SVIDEO1, 1, IVTV_SAA71XX_SVIDEO0 }, | ||
260 | { IVTV_CARD_INPUT_COMPOSITE1, 1, IVTV_SAA71XX_COMPOSITE3 }, | ||
261 | }, | ||
262 | .audio_inputs = { | ||
263 | { IVTV_CARD_INPUT_AUD_TUNER, IVTV_GPIO_TUNER }, | ||
264 | { IVTV_CARD_INPUT_LINE_IN1, IVTV_GPIO_LINE_IN }, | ||
265 | }, | ||
266 | .gpio_init = { .direction = 0x3080, .initial_value = 0x0004 }, | ||
267 | .gpio_audio_input = { .mask = 0x3000, .tuner = 0x0000, .linein = 0x2000 }, | ||
268 | .gpio_audio_mute = { .mask = 0x0001, .mute = 0x0001 }, | ||
269 | .gpio_audio_mode = { .mask = 0x000e, .mono = 0x0006, .stereo = 0x0004, | ||
270 | .lang1 = 0x0004, .lang2 = 0x0000, .both = 0x0008 }, | ||
271 | .gpio_audio_detect = { .mask = 0x0900, .stereo = 0x0100 }, | ||
272 | .tuners = { | ||
273 | /* The PAL tuner is confirmed */ | ||
274 | { .std = V4L2_STD_625_50, .tuner = TUNER_PHILIPS_FQ1216ME }, | ||
275 | { .std = V4L2_STD_ALL, .tuner = TUNER_PHILIPS_FQ1286 }, | ||
276 | }, | ||
277 | .pci_list = ivtv_pci_mpg600, | ||
278 | }; | ||
279 | |||
280 | /* ------------------------------------------------------------------------- */ | ||
281 | |||
282 | /* Yuan MPG160/Kuroutoshikou ITVC15-STVLP cards */ | ||
283 | |||
284 | static const struct ivtv_card_pci_info ivtv_pci_mpg160[] = { | ||
285 | { PCI_DEVICE_ID_IVTV15, IVTV_PCI_ID_YUAN1, 0 }, | ||
286 | { PCI_DEVICE_ID_IVTV15, IVTV_PCI_ID_IODATA, 0x40a0 }, | ||
287 | { 0, 0, 0 } | ||
288 | }; | ||
289 | |||
290 | static const struct ivtv_card ivtv_card_mpg160 = { | ||
291 | .type = IVTV_CARD_MPG160, | ||
292 | .name = "YUAN MPG160, Kuroutoshikou ITVC15-STVLP, I/O Data GV-M2TV/PCI", | ||
293 | .v4l2_capabilities = IVTV_CAP_ENCODER, | ||
294 | .hw_video = IVTV_HW_SAA7114, | ||
295 | .hw_audio = IVTV_HW_GPIO, | ||
296 | .hw_audio_ctrl = IVTV_HW_GPIO, | ||
297 | .hw_all = IVTV_HW_GPIO | IVTV_HW_SAA7114 | IVTV_HW_TUNER, | ||
298 | .video_inputs = { | ||
299 | { IVTV_CARD_INPUT_VID_TUNER, 0, IVTV_SAA71XX_COMPOSITE4 }, | ||
300 | { IVTV_CARD_INPUT_SVIDEO1, 1, IVTV_SAA71XX_SVIDEO0 }, | ||
301 | { IVTV_CARD_INPUT_COMPOSITE1, 1, IVTV_SAA71XX_COMPOSITE3 }, | ||
302 | }, | ||
303 | .audio_inputs = { | ||
304 | { IVTV_CARD_INPUT_AUD_TUNER, IVTV_GPIO_TUNER }, | ||
305 | { IVTV_CARD_INPUT_LINE_IN1, IVTV_GPIO_LINE_IN }, | ||
306 | }, | ||
307 | .gpio_init = { .direction = 0x7080, .initial_value = 0x400c }, | ||
308 | .gpio_audio_input = { .mask = 0x3000, .tuner = 0x0000, .linein = 0x2000 }, | ||
309 | .gpio_audio_mute = { .mask = 0x0001, .mute = 0x0001 }, | ||
310 | .gpio_audio_mode = { .mask = 0x000e, .mono = 0x0006, .stereo = 0x0004, | ||
311 | .lang1 = 0x0004, .lang2 = 0x0000, .both = 0x0008 }, | ||
312 | .gpio_audio_detect = { .mask = 0x0900, .stereo = 0x0100 }, | ||
313 | .tuners = { | ||
314 | { .std = V4L2_STD_625_50, .tuner = TUNER_PHILIPS_FQ1216ME }, | ||
315 | { .std = V4L2_STD_ALL, .tuner = TUNER_PHILIPS_FQ1286 }, | ||
316 | }, | ||
317 | .pci_list = ivtv_pci_mpg160, | ||
318 | }; | ||
319 | |||
320 | /* ------------------------------------------------------------------------- */ | ||
321 | |||
322 | /* Yuan PG600/Diamond PVR-550 cards */ | ||
323 | |||
324 | static const struct ivtv_card_pci_info ivtv_pci_pg600[] = { | ||
325 | { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_DIAMONDMM, 0x0070 }, | ||
326 | { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_YUAN3, 0x0600 }, | ||
327 | { 0, 0, 0 } | ||
328 | }; | ||
329 | |||
330 | static const struct ivtv_card ivtv_card_pg600 = { | ||
331 | .type = IVTV_CARD_PG600, | ||
332 | .name = "Yuan PG600, Diamond PVR-550", | ||
333 | .v4l2_capabilities = IVTV_CAP_ENCODER, | ||
334 | .hw_video = IVTV_HW_CX25840, | ||
335 | .hw_audio = IVTV_HW_CX25840, | ||
336 | .hw_audio_ctrl = IVTV_HW_CX25840, | ||
337 | .hw_all = IVTV_HW_CX25840 | IVTV_HW_TUNER, | ||
338 | .video_inputs = { | ||
339 | { IVTV_CARD_INPUT_VID_TUNER, 0, CX25840_COMPOSITE2 }, | ||
340 | { IVTV_CARD_INPUT_SVIDEO1, 1, | ||
341 | CX25840_SVIDEO_LUMA3 | CX25840_SVIDEO_CHROMA4 }, | ||
342 | { IVTV_CARD_INPUT_COMPOSITE1, 1, CX25840_COMPOSITE1 }, | ||
343 | }, | ||
344 | .audio_inputs = { | ||
345 | { IVTV_CARD_INPUT_AUD_TUNER, CX25840_AUDIO5 }, | ||
346 | { IVTV_CARD_INPUT_LINE_IN1, CX25840_AUDIO_SERIAL }, | ||
347 | }, | ||
348 | .tuners = { | ||
349 | { .std = V4L2_STD_625_50, .tuner = TUNER_PHILIPS_FQ1216ME }, | ||
350 | { .std = V4L2_STD_ALL, .tuner = TUNER_PHILIPS_FQ1286 }, | ||
351 | }, | ||
352 | .pci_list = ivtv_pci_pg600, | ||
353 | }; | ||
354 | |||
355 | /* ------------------------------------------------------------------------- */ | ||
356 | |||
357 | /* Adaptec VideOh! AVC-2410 card */ | ||
358 | |||
359 | static const struct ivtv_card_pci_info ivtv_pci_avc2410[] = { | ||
360 | { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_ADAPTEC, 0x0093 }, | ||
361 | { 0, 0, 0 } | ||
362 | }; | ||
363 | |||
364 | static const struct ivtv_card ivtv_card_avc2410 = { | ||
365 | .type = IVTV_CARD_AVC2410, | ||
366 | .name = "Adaptec VideOh! AVC-2410", | ||
367 | .v4l2_capabilities = IVTV_CAP_ENCODER, | ||
368 | .hw_video = IVTV_HW_SAA7115, | ||
369 | .hw_audio = IVTV_HW_MSP34XX, | ||
370 | .hw_audio_ctrl = IVTV_HW_MSP34XX, | ||
371 | .hw_muxer = IVTV_HW_CS53L32A, | ||
372 | .hw_all = IVTV_HW_MSP34XX | IVTV_HW_CS53L32A | | ||
373 | IVTV_HW_SAA7115 | IVTV_HW_TUNER, | ||
374 | .video_inputs = { | ||
375 | { IVTV_CARD_INPUT_VID_TUNER, 0, IVTV_SAA71XX_COMPOSITE4 }, | ||
376 | { IVTV_CARD_INPUT_SVIDEO1, 1, IVTV_SAA71XX_SVIDEO0 }, | ||
377 | { IVTV_CARD_INPUT_COMPOSITE1, 1, IVTV_SAA71XX_COMPOSITE3 }, | ||
378 | }, | ||
379 | .audio_inputs = { | ||
380 | { IVTV_CARD_INPUT_AUD_TUNER, | ||
381 | MSP_TUNER, CS53L32A_IN0 }, | ||
382 | { IVTV_CARD_INPUT_LINE_IN1, | ||
383 | MSP_SCART1, CS53L32A_IN2 }, | ||
384 | }, | ||
385 | /* This card has no eeprom and in fact the Windows driver relies | ||
386 | on the country/region setting of the user to decide which tuner | ||
387 | is available. */ | ||
388 | .tuners = { | ||
389 | /* This tuner has been verified for the AVC2410 */ | ||
390 | { .std = V4L2_STD_625_50, .tuner = TUNER_PHILIPS_FM1216ME_MK3 }, | ||
391 | /* This is a good guess, but I'm not totally sure this is | ||
392 | the correct tuner for NTSC. */ | ||
393 | { .std = V4L2_STD_ALL, .tuner = TUNER_PHILIPS_FM1236_MK3 }, | ||
394 | }, | ||
395 | .pci_list = ivtv_pci_avc2410, | ||
396 | }; | ||
397 | |||
398 | /* ------------------------------------------------------------------------- */ | ||
399 | |||
400 | /* Adaptec VideOh! AVC-2010 card */ | ||
401 | |||
402 | static const struct ivtv_card_pci_info ivtv_pci_avc2010[] = { | ||
403 | { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_ADAPTEC, 0x0092 }, | ||
404 | { 0, 0, 0 } | ||
405 | }; | ||
406 | |||
407 | static const struct ivtv_card ivtv_card_avc2010 = { | ||
408 | .type = IVTV_CARD_AVC2010, | ||
409 | .name = "Adaptec VideOh! AVC-2010", | ||
410 | .v4l2_capabilities = IVTV_CAP_ENCODER, | ||
411 | .hw_video = IVTV_HW_SAA7115, | ||
412 | .hw_audio = IVTV_HW_CS53L32A, | ||
413 | .hw_audio_ctrl = IVTV_HW_CS53L32A, | ||
414 | .hw_all = IVTV_HW_CS53L32A | IVTV_HW_SAA7115, | ||
415 | .video_inputs = { | ||
416 | { IVTV_CARD_INPUT_SVIDEO1, 0, IVTV_SAA71XX_SVIDEO0 }, | ||
417 | { IVTV_CARD_INPUT_COMPOSITE1, 0, IVTV_SAA71XX_COMPOSITE3 }, | ||
418 | }, | ||
419 | .audio_inputs = { | ||
420 | { IVTV_CARD_INPUT_LINE_IN1, CS53L32A_IN2 }, | ||
421 | }, | ||
422 | /* Does not have a tuner */ | ||
423 | .pci_list = ivtv_pci_avc2010, | ||
424 | }; | ||
425 | |||
426 | /* ------------------------------------------------------------------------- */ | ||
427 | |||
428 | /* Nagase Transgear 5000TV card */ | ||
429 | |||
430 | static const struct ivtv_card_pci_info ivtv_pci_tg5000tv[] = { | ||
431 | { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_AVERMEDIA, 0xbfff }, | ||
432 | { 0, 0, 0 } | ||
433 | }; | ||
434 | |||
435 | static const struct ivtv_card ivtv_card_tg5000tv = { | ||
436 | .type = IVTV_CARD_TG5000TV, | ||
437 | .name = "Nagase Transgear 5000TV", | ||
438 | .v4l2_capabilities = IVTV_CAP_ENCODER, | ||
439 | .hw_video = IVTV_HW_SAA7114 | IVTV_HW_UPD64031A | IVTV_HW_UPD6408X | | ||
440 | IVTV_HW_GPIO, | ||
441 | .hw_audio = IVTV_HW_GPIO, | ||
442 | .hw_audio_ctrl = IVTV_HW_GPIO, | ||
443 | .hw_all = IVTV_HW_GPIO | IVTV_HW_SAA7114 | IVTV_HW_TUNER | | ||
444 | IVTV_HW_UPD64031A | IVTV_HW_UPD6408X, | ||
445 | .video_inputs = { | ||
446 | { IVTV_CARD_INPUT_VID_TUNER, 0, IVTV_SAA71XX_SVIDEO0 }, | ||
447 | { IVTV_CARD_INPUT_SVIDEO1, 1, IVTV_SAA71XX_SVIDEO2 }, | ||
448 | { IVTV_CARD_INPUT_COMPOSITE1, 1, IVTV_SAA71XX_SVIDEO2 }, | ||
449 | }, | ||
450 | .audio_inputs = { | ||
451 | { IVTV_CARD_INPUT_AUD_TUNER, IVTV_GPIO_TUNER }, | ||
452 | { IVTV_CARD_INPUT_LINE_IN1, IVTV_GPIO_LINE_IN }, | ||
453 | }, | ||
454 | .gr_config = UPD64031A_VERTICAL_EXTERNAL, | ||
455 | .gpio_init = { .direction = 0xe080, .initial_value = 0x8000 }, | ||
456 | .gpio_audio_input = { .mask = 0x8080, .tuner = 0x8000, .linein = 0x0080 }, | ||
457 | .gpio_audio_mute = { .mask = 0x6000, .mute = 0x6000 }, | ||
458 | .gpio_audio_mode = { .mask = 0x4300, .mono = 0x4000, .stereo = 0x0200, | ||
459 | .lang1 = 0x0300, .lang2 = 0x0000, .both = 0x0200 }, | ||
460 | .gpio_video_input = { .mask = 0x0030, .tuner = 0x0000, | ||
461 | .composite = 0x0010, .svideo = 0x0020 }, | ||
462 | .tuners = { | ||
463 | { .std = V4L2_STD_525_60, .tuner = TUNER_PHILIPS_FQ1286 }, | ||
464 | }, | ||
465 | .pci_list = ivtv_pci_tg5000tv, | ||
466 | }; | ||
467 | |||
468 | /* ------------------------------------------------------------------------- */ | ||
469 | |||
470 | /* AOpen VA2000MAX-SNT6 card */ | ||
471 | |||
472 | static const struct ivtv_card_pci_info ivtv_pci_va2000[] = { | ||
473 | { PCI_DEVICE_ID_IVTV16, 0, 0xff5f }, | ||
474 | { 0, 0, 0 } | ||
475 | }; | ||
476 | |||
477 | static const struct ivtv_card ivtv_card_va2000 = { | ||
478 | .type = IVTV_CARD_VA2000MAX_SNT6, | ||
479 | .name = "AOpen VA2000MAX-SNT6", | ||
480 | .v4l2_capabilities = IVTV_CAP_ENCODER, | ||
481 | .hw_video = IVTV_HW_SAA7115 | IVTV_HW_UPD6408X, | ||
482 | .hw_audio = IVTV_HW_MSP34XX, | ||
483 | .hw_audio_ctrl = IVTV_HW_MSP34XX, | ||
484 | .hw_all = IVTV_HW_MSP34XX | IVTV_HW_SAA7115 | | ||
485 | IVTV_HW_UPD6408X | IVTV_HW_TUNER, | ||
486 | .video_inputs = { | ||
487 | { IVTV_CARD_INPUT_VID_TUNER, 0, IVTV_SAA71XX_SVIDEO0 }, | ||
488 | }, | ||
489 | .audio_inputs = { | ||
490 | { IVTV_CARD_INPUT_AUD_TUNER, MSP_TUNER }, | ||
491 | }, | ||
492 | .tuners = { | ||
493 | { .std = V4L2_STD_525_60, .tuner = TUNER_PHILIPS_FQ1286 }, | ||
494 | }, | ||
495 | .pci_list = ivtv_pci_va2000, | ||
496 | }; | ||
497 | |||
498 | /* ------------------------------------------------------------------------- */ | ||
499 | |||
500 | /* Yuan MPG600GR/Kuroutoshikou CX23416GYC-STVLP cards */ | ||
501 | |||
502 | static const struct ivtv_card_pci_info ivtv_pci_cx23416gyc[] = { | ||
503 | { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_YUAN1, 0x0600 }, | ||
504 | { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_YUAN4, 0x0600 }, | ||
505 | { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_MELCO, 0x0523 }, | ||
506 | { 0, 0, 0 } | ||
507 | }; | ||
508 | |||
509 | static const struct ivtv_card ivtv_card_cx23416gyc = { | ||
510 | .type = IVTV_CARD_CX23416GYC, | ||
511 | .name = "Yuan MPG600GR, Kuroutoshikou CX23416GYC-STVLP", | ||
512 | .v4l2_capabilities = IVTV_CAP_ENCODER, | ||
513 | .hw_video = IVTV_HW_SAA717X | IVTV_HW_GPIO | | ||
514 | IVTV_HW_UPD64031A | IVTV_HW_UPD6408X, | ||
515 | .hw_audio = IVTV_HW_SAA717X, | ||
516 | .hw_audio_ctrl = IVTV_HW_SAA717X, | ||
517 | .hw_all = IVTV_HW_GPIO | IVTV_HW_SAA717X | IVTV_HW_TUNER | | ||
518 | IVTV_HW_UPD64031A | IVTV_HW_UPD6408X, | ||
519 | .video_inputs = { | ||
520 | { IVTV_CARD_INPUT_VID_TUNER, 0, IVTV_SAA71XX_SVIDEO3 | | ||
521 | IVTV_SAA717X_TUNER_FLAG }, | ||
522 | { IVTV_CARD_INPUT_SVIDEO1, 1, IVTV_SAA71XX_SVIDEO0 }, | ||
523 | { IVTV_CARD_INPUT_COMPOSITE1, 1, IVTV_SAA71XX_SVIDEO3 }, | ||
524 | }, | ||
525 | .audio_inputs = { | ||
526 | { IVTV_CARD_INPUT_AUD_TUNER, IVTV_SAA717X_IN2 }, | ||
527 | { IVTV_CARD_INPUT_LINE_IN1, IVTV_SAA717X_IN0 }, | ||
528 | }, | ||
529 | .gr_config = UPD64031A_VERTICAL_EXTERNAL, | ||
530 | .gpio_init = { .direction = 0xf880, .initial_value = 0x8800 }, | ||
531 | .gpio_video_input = { .mask = 0x0020, .tuner = 0x0000, | ||
532 | .composite = 0x0020, .svideo = 0x0020 }, | ||
533 | .gpio_audio_freq = { .mask = 0xc000, .f32000 = 0x0000, | ||
534 | .f44100 = 0x4000, .f48000 = 0x8000 }, | ||
535 | .tuners = { | ||
536 | { .std = V4L2_STD_625_50, .tuner = TUNER_PHILIPS_FM1216ME_MK3 }, | ||
537 | { .std = V4L2_STD_ALL, .tuner = TUNER_PHILIPS_FM1236_MK3 }, | ||
538 | }, | ||
539 | .pci_list = ivtv_pci_cx23416gyc, | ||
540 | }; | ||
541 | |||
542 | static const struct ivtv_card ivtv_card_cx23416gyc_nogr = { | ||
543 | .type = IVTV_CARD_CX23416GYC_NOGR, | ||
544 | .name = "Yuan MPG600GR, Kuroutoshikou CX23416GYC-STVLP (no GR)", | ||
545 | .v4l2_capabilities = IVTV_CAP_ENCODER, | ||
546 | .hw_video = IVTV_HW_SAA717X | IVTV_HW_GPIO | IVTV_HW_UPD6408X, | ||
547 | .hw_audio = IVTV_HW_SAA717X, | ||
548 | .hw_audio_ctrl = IVTV_HW_SAA717X, | ||
549 | .hw_all = IVTV_HW_GPIO | IVTV_HW_SAA717X | IVTV_HW_TUNER | | ||
550 | IVTV_HW_UPD6408X, | ||
551 | .video_inputs = { | ||
552 | { IVTV_CARD_INPUT_VID_TUNER, 0, IVTV_SAA71XX_COMPOSITE4 | | ||
553 | IVTV_SAA717X_TUNER_FLAG }, | ||
554 | { IVTV_CARD_INPUT_SVIDEO1, 1, IVTV_SAA71XX_SVIDEO0 }, | ||
555 | { IVTV_CARD_INPUT_COMPOSITE1, 1, IVTV_SAA71XX_COMPOSITE0 }, | ||
556 | }, | ||
557 | .audio_inputs = { | ||
558 | { IVTV_CARD_INPUT_AUD_TUNER, IVTV_SAA717X_IN2 }, | ||
559 | { IVTV_CARD_INPUT_LINE_IN1, IVTV_SAA717X_IN0 }, | ||
560 | }, | ||
561 | .gpio_init = { .direction = 0xf880, .initial_value = 0x8800 }, | ||
562 | .gpio_video_input = { .mask = 0x0020, .tuner = 0x0000, | ||
563 | .composite = 0x0020, .svideo = 0x0020 }, | ||
564 | .gpio_audio_freq = { .mask = 0xc000, .f32000 = 0x0000, | ||
565 | .f44100 = 0x4000, .f48000 = 0x8000 }, | ||
566 | .tuners = { | ||
567 | { .std = V4L2_STD_625_50, .tuner = TUNER_PHILIPS_FM1216ME_MK3 }, | ||
568 | { .std = V4L2_STD_ALL, .tuner = TUNER_PHILIPS_FM1236_MK3 }, | ||
569 | }, | ||
570 | }; | ||
571 | |||
572 | static const struct ivtv_card ivtv_card_cx23416gyc_nogrycs = { | ||
573 | .type = IVTV_CARD_CX23416GYC_NOGRYCS, | ||
574 | .name = "Yuan MPG600GR, Kuroutoshikou CX23416GYC-STVLP (no GR/YCS)", | ||
575 | .v4l2_capabilities = IVTV_CAP_ENCODER, | ||
576 | .hw_video = IVTV_HW_SAA717X | IVTV_HW_GPIO, | ||
577 | .hw_audio = IVTV_HW_SAA717X, | ||
578 | .hw_audio_ctrl = IVTV_HW_SAA717X, | ||
579 | .hw_all = IVTV_HW_GPIO | IVTV_HW_SAA717X | IVTV_HW_TUNER, | ||
580 | .video_inputs = { | ||
581 | { IVTV_CARD_INPUT_VID_TUNER, 0, IVTV_SAA71XX_COMPOSITE4 | | ||
582 | IVTV_SAA717X_TUNER_FLAG }, | ||
583 | { IVTV_CARD_INPUT_SVIDEO1, 1, IVTV_SAA71XX_SVIDEO0 }, | ||
584 | { IVTV_CARD_INPUT_COMPOSITE1, 1, IVTV_SAA71XX_COMPOSITE0 }, | ||
585 | }, | ||
586 | .audio_inputs = { | ||
587 | { IVTV_CARD_INPUT_AUD_TUNER, IVTV_SAA717X_IN2 }, | ||
588 | { IVTV_CARD_INPUT_LINE_IN1, IVTV_SAA717X_IN0 }, | ||
589 | }, | ||
590 | .gpio_init = { .direction = 0xf880, .initial_value = 0x8800 }, | ||
591 | .gpio_video_input = { .mask = 0x0020, .tuner = 0x0000, | ||
592 | .composite = 0x0020, .svideo = 0x0020 }, | ||
593 | .gpio_audio_freq = { .mask = 0xc000, .f32000 = 0x0000, | ||
594 | .f44100 = 0x4000, .f48000 = 0x8000 }, | ||
595 | .tuners = { | ||
596 | { .std = V4L2_STD_625_50, .tuner = TUNER_PHILIPS_FM1216ME_MK3 }, | ||
597 | { .std = V4L2_STD_ALL, .tuner = TUNER_PHILIPS_FM1236_MK3 }, | ||
598 | }, | ||
599 | }; | ||
600 | |||
601 | /* ------------------------------------------------------------------------- */ | ||
602 | |||
603 | /* I/O Data GV-MVP/RX & GV-MVP/RX2W (dual tuner) cards */ | ||
604 | |||
605 | static const struct ivtv_card_pci_info ivtv_pci_gv_mvprx[] = { | ||
606 | { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_IODATA, 0xd01e }, | ||
607 | { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_IODATA, 0xd038 }, /* 2W unit #1 */ | ||
608 | { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_IODATA, 0xd039 }, /* 2W unit #2 */ | ||
609 | { 0, 0, 0 } | ||
610 | }; | ||
611 | |||
612 | static const struct ivtv_card ivtv_card_gv_mvprx = { | ||
613 | .type = IVTV_CARD_GV_MVPRX, | ||
614 | .name = "I/O Data GV-MVP/RX, GV-MVP/RX2W (dual tuner)", | ||
615 | .v4l2_capabilities = IVTV_CAP_ENCODER, | ||
616 | .hw_video = IVTV_HW_SAA7115 | IVTV_HW_UPD64031A | IVTV_HW_UPD6408X, | ||
617 | .hw_audio = IVTV_HW_GPIO, | ||
618 | .hw_audio_ctrl = IVTV_HW_WM8739, | ||
619 | .hw_all = IVTV_HW_GPIO | IVTV_HW_SAA7115 | IVTV_HW_TVAUDIO | | ||
620 | IVTV_HW_TUNER | IVTV_HW_WM8739 | | ||
621 | IVTV_HW_UPD64031A | IVTV_HW_UPD6408X, | ||
622 | .video_inputs = { | ||
623 | { IVTV_CARD_INPUT_VID_TUNER, 0, IVTV_SAA71XX_SVIDEO0 }, | ||
624 | { IVTV_CARD_INPUT_SVIDEO1, 1, IVTV_SAA71XX_SVIDEO1 }, | ||
625 | { IVTV_CARD_INPUT_COMPOSITE1, 1, IVTV_SAA71XX_SVIDEO2 }, | ||
626 | }, | ||
627 | .audio_inputs = { | ||
628 | { IVTV_CARD_INPUT_AUD_TUNER, IVTV_GPIO_TUNER }, | ||
629 | { IVTV_CARD_INPUT_LINE_IN1, IVTV_GPIO_LINE_IN }, | ||
630 | }, | ||
631 | .gpio_init = { .direction = 0xc301, .initial_value = 0x0200 }, | ||
632 | .gpio_audio_input = { .mask = 0xffff, .tuner = 0x0200, .linein = 0x0300 }, | ||
633 | .tuners = { | ||
634 | /* This card has the Panasonic VP27 tuner */ | ||
635 | { .std = V4L2_STD_525_60, .tuner = TUNER_PANASONIC_VP27 }, | ||
636 | }, | ||
637 | .pci_list = ivtv_pci_gv_mvprx, | ||
638 | }; | ||
639 | |||
640 | /* ------------------------------------------------------------------------- */ | ||
641 | |||
642 | /* I/O Data GV-MVP/RX2E card */ | ||
643 | |||
644 | static const struct ivtv_card_pci_info ivtv_pci_gv_mvprx2e[] = { | ||
645 | { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_IODATA, 0xd025 }, | ||
646 | {0, 0, 0} | ||
647 | }; | ||
648 | |||
649 | static const struct ivtv_card ivtv_card_gv_mvprx2e = { | ||
650 | .type = IVTV_CARD_GV_MVPRX2E, | ||
651 | .name = "I/O Data GV-MVP/RX2E", | ||
652 | .v4l2_capabilities = IVTV_CAP_ENCODER, | ||
653 | .hw_video = IVTV_HW_SAA7115, | ||
654 | .hw_audio = IVTV_HW_GPIO, | ||
655 | .hw_audio_ctrl = IVTV_HW_WM8739, | ||
656 | .hw_all = IVTV_HW_GPIO | IVTV_HW_SAA7115 | IVTV_HW_TUNER | | ||
657 | IVTV_HW_TVAUDIO | IVTV_HW_WM8739, | ||
658 | .video_inputs = { | ||
659 | { IVTV_CARD_INPUT_VID_TUNER, 0, IVTV_SAA71XX_COMPOSITE4 }, | ||
660 | { IVTV_CARD_INPUT_SVIDEO1, 1, IVTV_SAA71XX_SVIDEO0 }, | ||
661 | { IVTV_CARD_INPUT_COMPOSITE1, 1, IVTV_SAA71XX_COMPOSITE3 }, | ||
662 | }, | ||
663 | .audio_inputs = { | ||
664 | { IVTV_CARD_INPUT_AUD_TUNER, IVTV_GPIO_TUNER }, | ||
665 | { IVTV_CARD_INPUT_LINE_IN1, IVTV_GPIO_LINE_IN }, | ||
666 | }, | ||
667 | .gpio_init = { .direction = 0xc301, .initial_value = 0x0200 }, | ||
668 | .gpio_audio_input = { .mask = 0xffff, .tuner = 0x0200, .linein = 0x0300 }, | ||
669 | .tuners = { | ||
670 | /* This card has the Panasonic VP27 tuner */ | ||
671 | { .std = V4L2_STD_525_60, .tuner = TUNER_PANASONIC_VP27 }, | ||
672 | }, | ||
673 | .pci_list = ivtv_pci_gv_mvprx2e, | ||
674 | }; | ||
675 | |||
676 | /* ------------------------------------------------------------------------- */ | ||
677 | |||
678 | /* GotVIEW PCI DVD card */ | ||
679 | |||
680 | static const struct ivtv_card_pci_info ivtv_pci_gotview_pci_dvd[] = { | ||
681 | { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_YUAN1, 0x0600 }, | ||
682 | { 0, 0, 0 } | ||
683 | }; | ||
684 | |||
685 | static const struct ivtv_card ivtv_card_gotview_pci_dvd = { | ||
686 | .type = IVTV_CARD_GOTVIEW_PCI_DVD, | ||
687 | .name = "GotView PCI DVD", | ||
688 | .v4l2_capabilities = IVTV_CAP_ENCODER, | ||
689 | .hw_video = IVTV_HW_SAA717X, | ||
690 | .hw_audio = IVTV_HW_SAA717X, | ||
691 | .hw_audio_ctrl = IVTV_HW_SAA717X, | ||
692 | .hw_all = IVTV_HW_SAA717X | IVTV_HW_TUNER, | ||
693 | .video_inputs = { | ||
694 | { IVTV_CARD_INPUT_VID_TUNER, 0, IVTV_SAA71XX_COMPOSITE1 }, /* pin 116 */ | ||
695 | { IVTV_CARD_INPUT_SVIDEO1, 1, IVTV_SAA71XX_SVIDEO0 }, /* pin 114/109 */ | ||
696 | { IVTV_CARD_INPUT_COMPOSITE1, 1, IVTV_SAA71XX_COMPOSITE3 }, /* pin 118 */ | ||
697 | }, | ||
698 | .audio_inputs = { | ||
699 | { IVTV_CARD_INPUT_AUD_TUNER, IVTV_SAA717X_IN0 }, | ||
700 | { IVTV_CARD_INPUT_LINE_IN1, IVTV_SAA717X_IN2 }, | ||
701 | }, | ||
702 | .gpio_init = { .direction = 0xf000, .initial_value = 0xA000 }, | ||
703 | .tuners = { | ||
704 | /* This card has a Philips FQ1216ME MK3 tuner */ | ||
705 | { .std = V4L2_STD_625_50, .tuner = TUNER_PHILIPS_FM1216ME_MK3 }, | ||
706 | }, | ||
707 | .pci_list = ivtv_pci_gotview_pci_dvd, | ||
708 | }; | ||
709 | |||
710 | /* ------------------------------------------------------------------------- */ | ||
711 | |||
712 | /* GotVIEW PCI DVD2 Deluxe card */ | ||
713 | |||
714 | static const struct ivtv_card_pci_info ivtv_pci_gotview_pci_dvd2[] = { | ||
715 | { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_GOTVIEW1, 0x0600 }, | ||
716 | { 0, 0, 0 } | ||
717 | }; | ||
718 | |||
719 | static const struct ivtv_card ivtv_card_gotview_pci_dvd2 = { | ||
720 | .type = IVTV_CARD_GOTVIEW_PCI_DVD2, | ||
721 | .name = "GotView PCI DVD2 Deluxe", | ||
722 | .v4l2_capabilities = IVTV_CAP_ENCODER, | ||
723 | .hw_video = IVTV_HW_CX25840, | ||
724 | .hw_audio = IVTV_HW_CX25840, | ||
725 | .hw_audio_ctrl = IVTV_HW_CX25840, | ||
726 | .hw_muxer = IVTV_HW_GPIO, | ||
727 | .hw_all = IVTV_HW_CX25840 | IVTV_HW_TUNER, | ||
728 | .video_inputs = { | ||
729 | { IVTV_CARD_INPUT_VID_TUNER, 0, CX25840_COMPOSITE2 }, | ||
730 | { IVTV_CARD_INPUT_SVIDEO1, 1, | ||
731 | CX25840_SVIDEO_LUMA3 | CX25840_SVIDEO_CHROMA4 }, | ||
732 | { IVTV_CARD_INPUT_COMPOSITE1, 1, CX25840_COMPOSITE1 }, | ||
733 | }, | ||
734 | .audio_inputs = { | ||
735 | { IVTV_CARD_INPUT_AUD_TUNER, CX25840_AUDIO5, 0 }, | ||
736 | { IVTV_CARD_INPUT_LINE_IN1, CX25840_AUDIO_SERIAL, 1 }, | ||
737 | }, | ||
738 | .radio_input = { IVTV_CARD_INPUT_AUD_TUNER, CX25840_AUDIO_SERIAL, 2 }, | ||
739 | .gpio_init = { .direction = 0x0800, .initial_value = 0 }, | ||
740 | .gpio_audio_input = { .mask = 0x0800, .tuner = 0, .linein = 0, .radio = 0x0800 }, | ||
741 | .tuners = { | ||
742 | /* This card has a Philips FQ1216ME MK5 tuner */ | ||
743 | { .std = V4L2_STD_625_50, .tuner = TUNER_PHILIPS_FM1216ME_MK3 }, | ||
744 | }, | ||
745 | .pci_list = ivtv_pci_gotview_pci_dvd2, | ||
746 | }; | ||
747 | |||
748 | /* ------------------------------------------------------------------------- */ | ||
749 | |||
750 | /* Yuan MPC622 miniPCI card */ | ||
751 | |||
752 | static const struct ivtv_card_pci_info ivtv_pci_yuan_mpc622[] = { | ||
753 | { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_YUAN2, 0xd998 }, | ||
754 | { 0, 0, 0 } | ||
755 | }; | ||
756 | |||
757 | static const struct ivtv_card ivtv_card_yuan_mpc622 = { | ||
758 | .type = IVTV_CARD_YUAN_MPC622, | ||
759 | .name = "Yuan MPC622", | ||
760 | .v4l2_capabilities = IVTV_CAP_ENCODER, | ||
761 | .hw_video = IVTV_HW_CX25840, | ||
762 | .hw_audio = IVTV_HW_CX25840, | ||
763 | .hw_audio_ctrl = IVTV_HW_CX25840, | ||
764 | .hw_all = IVTV_HW_CX25840 | IVTV_HW_TUNER, | ||
765 | .video_inputs = { | ||
766 | { IVTV_CARD_INPUT_VID_TUNER, 0, CX25840_COMPOSITE2 }, | ||
767 | { IVTV_CARD_INPUT_SVIDEO1, 1, | ||
768 | CX25840_SVIDEO_LUMA3 | CX25840_SVIDEO_CHROMA4 }, | ||
769 | { IVTV_CARD_INPUT_COMPOSITE1, 1, CX25840_COMPOSITE1 }, | ||
770 | }, | ||
771 | .audio_inputs = { | ||
772 | { IVTV_CARD_INPUT_AUD_TUNER, CX25840_AUDIO5 }, | ||
773 | { IVTV_CARD_INPUT_LINE_IN1, CX25840_AUDIO_SERIAL }, | ||
774 | }, | ||
775 | .gpio_init = { .direction = 0x00ff, .initial_value = 0x0002 }, | ||
776 | .tuners = { | ||
777 | /* This card has the TDA8290/TDA8275 tuner chips */ | ||
778 | { .std = V4L2_STD_ALL, .tuner = TUNER_PHILIPS_TDA8290 }, | ||
779 | }, | ||
780 | .pci_list = ivtv_pci_yuan_mpc622, | ||
781 | }; | ||
782 | |||
783 | /* ------------------------------------------------------------------------- */ | ||
784 | |||
785 | /* DIGITAL COWBOY DCT-MTVP1 card */ | ||
786 | |||
787 | static const struct ivtv_card_pci_info ivtv_pci_dctmvtvp1[] = { | ||
788 | { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_AVERMEDIA, 0xbfff }, | ||
789 | { 0, 0, 0 } | ||
790 | }; | ||
791 | |||
792 | static const struct ivtv_card ivtv_card_dctmvtvp1 = { | ||
793 | .type = IVTV_CARD_DCTMTVP1, | ||
794 | .name = "Digital Cowboy DCT-MTVP1", | ||
795 | .v4l2_capabilities = IVTV_CAP_ENCODER, | ||
796 | .hw_video = IVTV_HW_SAA7115 | IVTV_HW_UPD64031A | IVTV_HW_UPD6408X | | ||
797 | IVTV_HW_GPIO, | ||
798 | .hw_audio = IVTV_HW_GPIO, | ||
799 | .hw_audio_ctrl = IVTV_HW_GPIO, | ||
800 | .hw_all = IVTV_HW_GPIO | IVTV_HW_SAA7115 | IVTV_HW_TUNER | | ||
801 | IVTV_HW_UPD64031A | IVTV_HW_UPD6408X, | ||
802 | .video_inputs = { | ||
803 | { IVTV_CARD_INPUT_VID_TUNER, 0, IVTV_SAA71XX_SVIDEO0 }, | ||
804 | { IVTV_CARD_INPUT_SVIDEO1, 1, IVTV_SAA71XX_SVIDEO2 }, | ||
805 | { IVTV_CARD_INPUT_COMPOSITE1, 1, IVTV_SAA71XX_SVIDEO2 }, | ||
806 | }, | ||
807 | .audio_inputs = { | ||
808 | { IVTV_CARD_INPUT_AUD_TUNER, IVTV_GPIO_TUNER }, | ||
809 | { IVTV_CARD_INPUT_LINE_IN1, IVTV_GPIO_LINE_IN }, | ||
810 | }, | ||
811 | .gpio_init = { .direction = 0xe080, .initial_value = 0x8000 }, | ||
812 | .gpio_audio_input = { .mask = 0x8080, .tuner = 0x8000, .linein = 0x0080 }, | ||
813 | .gpio_audio_mute = { .mask = 0x6000, .mute = 0x6000 }, | ||
814 | .gpio_audio_mode = { .mask = 0x4300, .mono = 0x4000, .stereo = 0x0200, | ||
815 | .lang1 = 0x0300, .lang2 = 0x0000, .both = 0x0200 }, | ||
816 | .gpio_video_input = { .mask = 0x0030, .tuner = 0x0000, | ||
817 | .composite = 0x0010, .svideo = 0x0020}, | ||
818 | .tuners = { | ||
819 | { .std = V4L2_STD_525_60, .tuner = TUNER_PHILIPS_FQ1286 }, | ||
820 | }, | ||
821 | .pci_list = ivtv_pci_dctmvtvp1, | ||
822 | }; | ||
823 | |||
824 | /* ------------------------------------------------------------------------- */ | ||
825 | |||
826 | #ifdef HAVE_XC3028 | ||
827 | |||
828 | /* Yuan PG600-2/GotView PCI DVD Lite/Club3D ZAP-TV1x01 cards */ | ||
829 | |||
830 | static const struct ivtv_card_pci_info ivtv_pci_pg600v2[] = { | ||
831 | { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_YUAN3, 0x0600 }, | ||
832 | { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_GOTVIEW2, 0x0600 }, | ||
833 | { 0, 0, 0 } | ||
834 | }; | ||
835 | |||
836 | static const struct ivtv_card ivtv_card_pg600v2 = { | ||
837 | .type = IVTV_CARD_PG600V2, | ||
838 | .name = "Yuan PG600-2, GotView PCI DVD Lite, Club3D ZAP-TV1x01", | ||
839 | .v4l2_capabilities = IVTV_CAP_ENCODER, | ||
840 | .hw_video = IVTV_HW_CX25840, | ||
841 | .hw_audio = IVTV_HW_CX25840, | ||
842 | .hw_audio_ctrl = IVTV_HW_CX25840, | ||
843 | .hw_all = IVTV_HW_CX25840 | IVTV_HW_TUNER, | ||
844 | .video_inputs = { | ||
845 | { IVTV_CARD_INPUT_VID_TUNER, 0, CX25840_COMPOSITE2 }, | ||
846 | { IVTV_CARD_INPUT_SVIDEO1, 1, | ||
847 | CX25840_SVIDEO_LUMA3 | CX25840_SVIDEO_CHROMA4 }, | ||
848 | }, | ||
849 | .audio_inputs = { | ||
850 | { IVTV_CARD_INPUT_AUD_TUNER, CX25840_AUDIO5 }, | ||
851 | { IVTV_CARD_INPUT_LINE_IN1, CX25840_AUDIO_SERIAL }, | ||
852 | }, | ||
853 | .radio_input = { IVTV_CARD_INPUT_AUD_TUNER, CX25840_AUDIO5 }, | ||
854 | .tuners = { | ||
855 | { .std = V4L2_STD_ALL, .tuner = TUNER_XCEIVE_XC3028 }, | ||
856 | }, | ||
857 | .gpio_init = { .direction = 0x1000, .initial_value = 0x1000 }, /* tuner reset */ | ||
858 | .pci_list = ivtv_pci_pg600v2, | ||
859 | }; | ||
860 | #endif | ||
861 | |||
862 | static const struct ivtv_card *ivtv_card_list[] = { | ||
863 | &ivtv_card_pvr250, | ||
864 | &ivtv_card_pvr350, | ||
865 | &ivtv_card_pvr150, | ||
866 | &ivtv_card_m179, | ||
867 | &ivtv_card_mpg600, | ||
868 | &ivtv_card_mpg160, | ||
869 | &ivtv_card_pg600, | ||
870 | &ivtv_card_avc2410, | ||
871 | &ivtv_card_avc2010, | ||
872 | &ivtv_card_tg5000tv, | ||
873 | &ivtv_card_va2000, | ||
874 | &ivtv_card_cx23416gyc, | ||
875 | &ivtv_card_gv_mvprx, | ||
876 | &ivtv_card_gv_mvprx2e, | ||
877 | &ivtv_card_gotview_pci_dvd, | ||
878 | &ivtv_card_gotview_pci_dvd2, | ||
879 | &ivtv_card_yuan_mpc622, | ||
880 | &ivtv_card_dctmvtvp1, | ||
881 | #ifdef HAVE_XC3028 | ||
882 | &ivtv_card_pg600v2, | ||
883 | #endif | ||
884 | |||
885 | /* Variations of standard cards but with the same PCI IDs. | ||
886 | These cards must come last in this list. */ | ||
887 | &ivtv_card_pvr350_v1, | ||
888 | &ivtv_card_cx23416gyc_nogr, | ||
889 | &ivtv_card_cx23416gyc_nogrycs, | ||
890 | }; | ||
891 | |||
892 | const struct ivtv_card *ivtv_get_card(u16 index) | ||
893 | { | ||
894 | if (index >= ARRAY_SIZE(ivtv_card_list)) | ||
895 | return NULL; | ||
896 | return ivtv_card_list[index]; | ||
897 | } | ||
898 | |||
899 | int ivtv_get_input(struct ivtv *itv, u16 index, struct v4l2_input *input) | ||
900 | { | ||
901 | const struct ivtv_card_video_input *card_input = itv->card->video_inputs + index; | ||
902 | static const char * const input_strs[] = { | ||
903 | "Tuner 1", | ||
904 | "S-Video 1", | ||
905 | "S-Video 2", | ||
906 | "Composite 1", | ||
907 | "Composite 2", | ||
908 | "Composite 3" | ||
909 | }; | ||
910 | |||
911 | memset(input, 0, sizeof(*input)); | ||
912 | if (index >= itv->nof_inputs) | ||
913 | return -EINVAL; | ||
914 | input->index = index; | ||
915 | strcpy(input->name, input_strs[card_input->video_type - 1]); | ||
916 | input->type = (card_input->video_type == IVTV_CARD_INPUT_VID_TUNER ? | ||
917 | V4L2_INPUT_TYPE_TUNER : V4L2_INPUT_TYPE_CAMERA); | ||
918 | input->audioset = (1 << itv->nof_audio_inputs) - 1; | ||
919 | input->std = (input->type == V4L2_INPUT_TYPE_TUNER) ? | ||
920 | itv->tuner_std : V4L2_STD_ALL; | ||
921 | return 0; | ||
922 | } | ||
923 | |||
924 | int ivtv_get_output(struct ivtv *itv, u16 index, struct v4l2_output *output) | ||
925 | { | ||
926 | const struct ivtv_card_output *card_output = itv->card->video_outputs + index; | ||
927 | |||
928 | memset(output, 0, sizeof(*output)); | ||
929 | if (index >= itv->card->nof_outputs) | ||
930 | return -EINVAL; | ||
931 | output->index = index; | ||
932 | strcpy(output->name, card_output->name); | ||
933 | output->type = V4L2_OUTPUT_TYPE_ANALOG; | ||
934 | output->audioset = 1; | ||
935 | output->std = V4L2_STD_ALL; | ||
936 | return 0; | ||
937 | } | ||
938 | |||
939 | int ivtv_get_audio_input(struct ivtv *itv, u16 index, struct v4l2_audio *audio) | ||
940 | { | ||
941 | const struct ivtv_card_audio_input *aud_input = itv->card->audio_inputs + index; | ||
942 | static const char * const input_strs[] = { | ||
943 | "Tuner 1", | ||
944 | "Line In 1", | ||
945 | "Line In 2" | ||
946 | }; | ||
947 | |||
948 | memset(audio, 0, sizeof(*audio)); | ||
949 | if (index >= itv->nof_audio_inputs) | ||
950 | return -EINVAL; | ||
951 | strcpy(audio->name, input_strs[aud_input->audio_type - 1]); | ||
952 | audio->index = index; | ||
953 | audio->capability = V4L2_AUDCAP_STEREO; | ||
954 | return 0; | ||
955 | } | ||
956 | |||
957 | int ivtv_get_audio_output(struct ivtv *itv, u16 index, struct v4l2_audioout *aud_output) | ||
958 | { | ||
959 | memset(aud_output, 0, sizeof(*aud_output)); | ||
960 | if (itv->card->video_outputs == NULL || index != 0) | ||
961 | return -EINVAL; | ||
962 | strcpy(aud_output->name, "A/V Audio Out"); | ||
963 | return 0; | ||
964 | } | ||
diff --git a/drivers/media/video/ivtv/ivtv-cards.h b/drivers/media/video/ivtv/ivtv-cards.h new file mode 100644 index 000000000000..15012f88b802 --- /dev/null +++ b/drivers/media/video/ivtv/ivtv-cards.h | |||
@@ -0,0 +1,207 @@ | |||
1 | /* | ||
2 | Functions to query card hardware | ||
3 | Copyright (C) 2003-2004 Kevin Thayer <nufan_wfk at yahoo.com> | ||
4 | Copyright (C) 2005-2007 Hans Verkuil <hverkuil@xs4all.nl> | ||
5 | |||
6 | This program is free software; you can redistribute it and/or modify | ||
7 | it under the terms of the GNU General Public License as published by | ||
8 | the Free Software Foundation; either version 2 of the License, or | ||
9 | (at your option) any later version. | ||
10 | |||
11 | This program is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program; if not, write to the Free Software | ||
18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | */ | ||
20 | |||
21 | /* hardware flags */ | ||
22 | #define IVTV_HW_CX25840 (1 << 0) | ||
23 | #define IVTV_HW_SAA7115 (1 << 1) | ||
24 | #define IVTV_HW_SAA7127 (1 << 2) | ||
25 | #define IVTV_HW_MSP34XX (1 << 3) | ||
26 | #define IVTV_HW_TUNER (1 << 4) | ||
27 | #define IVTV_HW_WM8775 (1 << 5) | ||
28 | #define IVTV_HW_CS53L32A (1 << 6) | ||
29 | #define IVTV_HW_TVEEPROM (1 << 7) | ||
30 | #define IVTV_HW_SAA7114 (1 << 8) | ||
31 | #define IVTV_HW_TVAUDIO (1 << 9) | ||
32 | #define IVTV_HW_UPD64031A (1 << 10) | ||
33 | #define IVTV_HW_UPD6408X (1 << 11) | ||
34 | #define IVTV_HW_SAA717X (1 << 12) | ||
35 | #define IVTV_HW_WM8739 (1 << 13) | ||
36 | #define IVTV_HW_GPIO (1 << 14) | ||
37 | |||
38 | #define IVTV_HW_SAA711X (IVTV_HW_SAA7115 | IVTV_HW_SAA7114) | ||
39 | |||
40 | /* video inputs */ | ||
41 | #define IVTV_CARD_INPUT_VID_TUNER 1 | ||
42 | #define IVTV_CARD_INPUT_SVIDEO1 2 | ||
43 | #define IVTV_CARD_INPUT_SVIDEO2 3 | ||
44 | #define IVTV_CARD_INPUT_COMPOSITE1 4 | ||
45 | #define IVTV_CARD_INPUT_COMPOSITE2 5 | ||
46 | #define IVTV_CARD_INPUT_COMPOSITE3 6 | ||
47 | |||
48 | /* audio inputs */ | ||
49 | #define IVTV_CARD_INPUT_AUD_TUNER 1 | ||
50 | #define IVTV_CARD_INPUT_LINE_IN1 2 | ||
51 | #define IVTV_CARD_INPUT_LINE_IN2 3 | ||
52 | |||
53 | #define IVTV_CARD_MAX_VIDEO_INPUTS 6 | ||
54 | #define IVTV_CARD_MAX_AUDIO_INPUTS 3 | ||
55 | #define IVTV_CARD_MAX_TUNERS 2 | ||
56 | |||
57 | /* SAA71XX HW inputs */ | ||
58 | #define IVTV_SAA71XX_COMPOSITE0 0 | ||
59 | #define IVTV_SAA71XX_COMPOSITE1 1 | ||
60 | #define IVTV_SAA71XX_COMPOSITE2 2 | ||
61 | #define IVTV_SAA71XX_COMPOSITE3 3 | ||
62 | #define IVTV_SAA71XX_COMPOSITE4 4 | ||
63 | #define IVTV_SAA71XX_COMPOSITE5 5 | ||
64 | #define IVTV_SAA71XX_SVIDEO0 6 | ||
65 | #define IVTV_SAA71XX_SVIDEO1 7 | ||
66 | #define IVTV_SAA71XX_SVIDEO2 8 | ||
67 | #define IVTV_SAA71XX_SVIDEO3 9 | ||
68 | |||
69 | /* SAA717X needs to mark the tuner input by ORing with this flag */ | ||
70 | #define IVTV_SAA717X_TUNER_FLAG 0x80 | ||
71 | |||
72 | /* Dummy HW input */ | ||
73 | #define IVTV_DUMMY_AUDIO 0 | ||
74 | |||
75 | /* GPIO HW inputs */ | ||
76 | #define IVTV_GPIO_TUNER 0 | ||
77 | #define IVTV_GPIO_LINE_IN 1 | ||
78 | |||
79 | /* SAA717X HW inputs */ | ||
80 | #define IVTV_SAA717X_IN0 0 | ||
81 | #define IVTV_SAA717X_IN1 1 | ||
82 | #define IVTV_SAA717X_IN2 2 | ||
83 | |||
84 | /* V4L2 capability aliases */ | ||
85 | #define IVTV_CAP_ENCODER (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_TUNER | \ | ||
86 | V4L2_CAP_AUDIO | V4L2_CAP_READWRITE | V4L2_CAP_VBI_CAPTURE | \ | ||
87 | V4L2_CAP_SLICED_VBI_CAPTURE) | ||
88 | #define IVTV_CAP_DECODER (V4L2_CAP_VBI_OUTPUT | V4L2_CAP_VIDEO_OUTPUT | \ | ||
89 | V4L2_CAP_SLICED_VBI_OUTPUT | V4L2_CAP_VIDEO_OUTPUT_OVERLAY | V4L2_CAP_VIDEO_OUTPUT_POS) | ||
90 | |||
91 | struct ivtv_card_video_input { | ||
92 | u8 video_type; /* video input type */ | ||
93 | u8 audio_index; /* index in ivtv_card_audio_input array */ | ||
94 | u16 video_input; /* hardware video input */ | ||
95 | }; | ||
96 | |||
97 | struct ivtv_card_audio_input { | ||
98 | u8 audio_type; /* audio input type */ | ||
99 | u32 audio_input; /* hardware audio input */ | ||
100 | u16 muxer_input; /* hardware muxer input for boards with a | ||
101 | multiplexer chip */ | ||
102 | }; | ||
103 | |||
104 | struct ivtv_card_output { | ||
105 | u8 name[32]; | ||
106 | u16 video_output; /* hardware video output */ | ||
107 | }; | ||
108 | |||
109 | struct ivtv_card_pci_info { | ||
110 | u16 device; | ||
111 | u16 subsystem_vendor; | ||
112 | u16 subsystem_device; | ||
113 | }; | ||
114 | |||
115 | /* GPIO definitions */ | ||
116 | |||
117 | /* The mask is the set of bits used by the operation */ | ||
118 | |||
119 | struct ivtv_gpio_init { /* set initial GPIO DIR and OUT values */ | ||
120 | u16 direction; /* DIR setting. Leave to 0 if no init is needed */ | ||
121 | u16 initial_value; | ||
122 | }; | ||
123 | |||
124 | struct ivtv_gpio_video_input { /* select tuner/line in input */ | ||
125 | u16 mask; /* leave to 0 if not supported */ | ||
126 | u16 tuner; | ||
127 | u16 composite; | ||
128 | u16 svideo; | ||
129 | }; | ||
130 | |||
131 | struct ivtv_gpio_audio_input { /* select tuner/line in input */ | ||
132 | u16 mask; /* leave to 0 if not supported */ | ||
133 | u16 tuner; | ||
134 | u16 linein; | ||
135 | u16 radio; | ||
136 | }; | ||
137 | |||
138 | struct ivtv_gpio_audio_mute { | ||
139 | u16 mask; /* leave to 0 if not supported */ | ||
140 | u16 mute; /* set this value to mute, 0 to unmute */ | ||
141 | }; | ||
142 | |||
143 | struct ivtv_gpio_audio_mode { | ||
144 | u16 mask; /* leave to 0 if not supported */ | ||
145 | u16 mono; /* set audio to mono */ | ||
146 | u16 stereo; /* set audio to stereo */ | ||
147 | u16 lang1; /* set audio to the first language */ | ||
148 | u16 lang2; /* set audio to the second language */ | ||
149 | u16 both; /* both languages are output */ | ||
150 | }; | ||
151 | |||
152 | struct ivtv_gpio_audio_freq { | ||
153 | u16 mask; /* leave to 0 if not supported */ | ||
154 | u16 f32000; | ||
155 | u16 f44100; | ||
156 | u16 f48000; | ||
157 | }; | ||
158 | |||
159 | struct ivtv_gpio_audio_detect { | ||
160 | u16 mask; /* leave to 0 if not supported */ | ||
161 | u16 stereo; /* if the input matches this value then | ||
162 | stereo is detected */ | ||
163 | }; | ||
164 | |||
165 | struct ivtv_card_tuner { | ||
166 | v4l2_std_id std; /* standard for which the tuner is suitable */ | ||
167 | int tuner; /* tuner ID (from tuner.h) */ | ||
168 | }; | ||
169 | |||
170 | /* for card information/parameters */ | ||
171 | struct ivtv_card { | ||
172 | int type; | ||
173 | char *name; | ||
174 | u32 v4l2_capabilities; | ||
175 | u32 hw_video; /* hardware used to process video */ | ||
176 | u32 hw_audio; /* hardware used to process audio */ | ||
177 | u32 hw_audio_ctrl; /* hardware used for the V4L2 controls (only 1 dev allowed) */ | ||
178 | u32 hw_muxer; /* hardware used to multiplex audio input */ | ||
179 | u32 hw_all; /* all hardware used by the board */ | ||
180 | struct ivtv_card_video_input video_inputs[IVTV_CARD_MAX_VIDEO_INPUTS]; | ||
181 | struct ivtv_card_audio_input audio_inputs[IVTV_CARD_MAX_AUDIO_INPUTS]; | ||
182 | struct ivtv_card_audio_input radio_input; | ||
183 | int nof_outputs; | ||
184 | const struct ivtv_card_output *video_outputs; | ||
185 | u8 gr_config; /* config byte for the ghost reduction device */ | ||
186 | |||
187 | /* GPIO card-specific settings */ | ||
188 | struct ivtv_gpio_init gpio_init; | ||
189 | struct ivtv_gpio_video_input gpio_video_input; | ||
190 | struct ivtv_gpio_audio_input gpio_audio_input; | ||
191 | struct ivtv_gpio_audio_mute gpio_audio_mute; | ||
192 | struct ivtv_gpio_audio_mode gpio_audio_mode; | ||
193 | struct ivtv_gpio_audio_freq gpio_audio_freq; | ||
194 | struct ivtv_gpio_audio_detect gpio_audio_detect; | ||
195 | |||
196 | struct ivtv_card_tuner tuners[IVTV_CARD_MAX_TUNERS]; | ||
197 | |||
198 | /* list of device and subsystem vendor/devices that | ||
199 | correspond to this card type. */ | ||
200 | const struct ivtv_card_pci_info *pci_list; | ||
201 | }; | ||
202 | |||
203 | int ivtv_get_input(struct ivtv *itv, u16 index, struct v4l2_input *input); | ||
204 | int ivtv_get_output(struct ivtv *itv, u16 index, struct v4l2_output *output); | ||
205 | int ivtv_get_audio_input(struct ivtv *itv, u16 index, struct v4l2_audio *input); | ||
206 | int ivtv_get_audio_output(struct ivtv *itv, u16 index, struct v4l2_audioout *output); | ||
207 | const struct ivtv_card *ivtv_get_card(u16 index); | ||
diff --git a/drivers/media/video/ivtv/ivtv-controls.c b/drivers/media/video/ivtv/ivtv-controls.c new file mode 100644 index 000000000000..7a876c3e5b19 --- /dev/null +++ b/drivers/media/video/ivtv/ivtv-controls.c | |||
@@ -0,0 +1,303 @@ | |||
1 | /* | ||
2 | ioctl control functions | ||
3 | Copyright (C) 2003-2004 Kevin Thayer <nufan_wfk at yahoo.com> | ||
4 | Copyright (C) 2005-2007 Hans Verkuil <hverkuil@xs4all.nl> | ||
5 | |||
6 | This program is free software; you can redistribute it and/or modify | ||
7 | it under the terms of the GNU General Public License as published by | ||
8 | the Free Software Foundation; either version 2 of the License, or | ||
9 | (at your option) any later version. | ||
10 | |||
11 | This program is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program; if not, write to the Free Software | ||
18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | */ | ||
20 | |||
21 | #include "ivtv-driver.h" | ||
22 | #include "ivtv-cards.h" | ||
23 | #include "ivtv-ioctl.h" | ||
24 | #include "ivtv-audio.h" | ||
25 | #include "ivtv-i2c.h" | ||
26 | #include "ivtv-mailbox.h" | ||
27 | #include "ivtv-controls.h" | ||
28 | |||
29 | static const u32 user_ctrls[] = { | ||
30 | V4L2_CID_USER_CLASS, | ||
31 | V4L2_CID_BRIGHTNESS, | ||
32 | V4L2_CID_CONTRAST, | ||
33 | V4L2_CID_SATURATION, | ||
34 | V4L2_CID_HUE, | ||
35 | V4L2_CID_AUDIO_VOLUME, | ||
36 | V4L2_CID_AUDIO_BALANCE, | ||
37 | V4L2_CID_AUDIO_BASS, | ||
38 | V4L2_CID_AUDIO_TREBLE, | ||
39 | V4L2_CID_AUDIO_MUTE, | ||
40 | V4L2_CID_AUDIO_LOUDNESS, | ||
41 | 0 | ||
42 | }; | ||
43 | |||
44 | static const u32 *ctrl_classes[] = { | ||
45 | user_ctrls, | ||
46 | cx2341x_mpeg_ctrls, | ||
47 | NULL | ||
48 | }; | ||
49 | |||
50 | static int ivtv_queryctrl(struct ivtv *itv, struct v4l2_queryctrl *qctrl) | ||
51 | { | ||
52 | const char *name; | ||
53 | |||
54 | IVTV_DEBUG_IOCTL("VIDIOC_QUERYCTRL(%08x)\n", qctrl->id); | ||
55 | |||
56 | qctrl->id = v4l2_ctrl_next(ctrl_classes, qctrl->id); | ||
57 | if (qctrl->id == 0) | ||
58 | return -EINVAL; | ||
59 | |||
60 | switch (qctrl->id) { | ||
61 | /* Standard V4L2 controls */ | ||
62 | case V4L2_CID_BRIGHTNESS: | ||
63 | case V4L2_CID_HUE: | ||
64 | case V4L2_CID_SATURATION: | ||
65 | case V4L2_CID_CONTRAST: | ||
66 | if (itv->video_dec_func(itv, VIDIOC_QUERYCTRL, qctrl)) | ||
67 | qctrl->flags |= V4L2_CTRL_FLAG_DISABLED; | ||
68 | return 0; | ||
69 | |||
70 | case V4L2_CID_AUDIO_VOLUME: | ||
71 | case V4L2_CID_AUDIO_MUTE: | ||
72 | case V4L2_CID_AUDIO_BALANCE: | ||
73 | case V4L2_CID_AUDIO_BASS: | ||
74 | case V4L2_CID_AUDIO_TREBLE: | ||
75 | case V4L2_CID_AUDIO_LOUDNESS: | ||
76 | if (ivtv_i2c_hw(itv, itv->card->hw_audio_ctrl, VIDIOC_QUERYCTRL, qctrl)) | ||
77 | qctrl->flags |= V4L2_CTRL_FLAG_DISABLED; | ||
78 | return 0; | ||
79 | |||
80 | default: | ||
81 | if (cx2341x_ctrl_query(&itv->params, qctrl)) | ||
82 | qctrl->flags |= V4L2_CTRL_FLAG_DISABLED; | ||
83 | return 0; | ||
84 | } | ||
85 | strncpy(qctrl->name, name, sizeof(qctrl->name) - 1); | ||
86 | qctrl->name[sizeof(qctrl->name) - 1] = 0; | ||
87 | return 0; | ||
88 | } | ||
89 | |||
90 | static int ivtv_querymenu(struct ivtv *itv, struct v4l2_querymenu *qmenu) | ||
91 | { | ||
92 | struct v4l2_queryctrl qctrl; | ||
93 | |||
94 | qctrl.id = qmenu->id; | ||
95 | ivtv_queryctrl(itv, &qctrl); | ||
96 | return v4l2_ctrl_query_menu(qmenu, &qctrl, cx2341x_ctrl_get_menu(qmenu->id)); | ||
97 | } | ||
98 | |||
99 | static int ivtv_s_ctrl(struct ivtv *itv, struct v4l2_control *vctrl) | ||
100 | { | ||
101 | s32 v = vctrl->value; | ||
102 | |||
103 | IVTV_DEBUG_IOCTL("VIDIOC_S_CTRL(%08x, %x)\n", vctrl->id, v); | ||
104 | |||
105 | switch (vctrl->id) { | ||
106 | /* Standard V4L2 controls */ | ||
107 | case V4L2_CID_BRIGHTNESS: | ||
108 | case V4L2_CID_HUE: | ||
109 | case V4L2_CID_SATURATION: | ||
110 | case V4L2_CID_CONTRAST: | ||
111 | return itv->video_dec_func(itv, VIDIOC_S_CTRL, vctrl); | ||
112 | |||
113 | case V4L2_CID_AUDIO_VOLUME: | ||
114 | case V4L2_CID_AUDIO_MUTE: | ||
115 | case V4L2_CID_AUDIO_BALANCE: | ||
116 | case V4L2_CID_AUDIO_BASS: | ||
117 | case V4L2_CID_AUDIO_TREBLE: | ||
118 | case V4L2_CID_AUDIO_LOUDNESS: | ||
119 | return ivtv_i2c_hw(itv, itv->card->hw_audio_ctrl, VIDIOC_S_CTRL, vctrl); | ||
120 | |||
121 | default: | ||
122 | IVTV_DEBUG_IOCTL("invalid control %x\n", vctrl->id); | ||
123 | return -EINVAL; | ||
124 | } | ||
125 | return 0; | ||
126 | } | ||
127 | |||
128 | static int ivtv_g_ctrl(struct ivtv *itv, struct v4l2_control *vctrl) | ||
129 | { | ||
130 | IVTV_DEBUG_IOCTL("VIDIOC_G_CTRL(%08x)\n", vctrl->id); | ||
131 | |||
132 | switch (vctrl->id) { | ||
133 | /* Standard V4L2 controls */ | ||
134 | case V4L2_CID_BRIGHTNESS: | ||
135 | case V4L2_CID_HUE: | ||
136 | case V4L2_CID_SATURATION: | ||
137 | case V4L2_CID_CONTRAST: | ||
138 | return itv->video_dec_func(itv, VIDIOC_G_CTRL, vctrl); | ||
139 | |||
140 | case V4L2_CID_AUDIO_VOLUME: | ||
141 | case V4L2_CID_AUDIO_MUTE: | ||
142 | case V4L2_CID_AUDIO_BALANCE: | ||
143 | case V4L2_CID_AUDIO_BASS: | ||
144 | case V4L2_CID_AUDIO_TREBLE: | ||
145 | case V4L2_CID_AUDIO_LOUDNESS: | ||
146 | return ivtv_i2c_hw(itv, itv->card->hw_audio_ctrl, VIDIOC_G_CTRL, vctrl); | ||
147 | default: | ||
148 | IVTV_DEBUG_IOCTL("invalid control %x\n", vctrl->id); | ||
149 | return -EINVAL; | ||
150 | } | ||
151 | return 0; | ||
152 | } | ||
153 | |||
154 | static int ivtv_setup_vbi_fmt(struct ivtv *itv, enum v4l2_mpeg_stream_vbi_fmt fmt) | ||
155 | { | ||
156 | if (!(itv->v4l2_cap & V4L2_CAP_SLICED_VBI_CAPTURE)) | ||
157 | return -EINVAL; | ||
158 | if (atomic_read(&itv->capturing) > 0) | ||
159 | return -EBUSY; | ||
160 | |||
161 | /* First try to allocate sliced VBI buffers if needed. */ | ||
162 | if (fmt && itv->vbi.sliced_mpeg_data[0] == NULL) { | ||
163 | int i; | ||
164 | |||
165 | for (i = 0; i < IVTV_VBI_FRAMES; i++) { | ||
166 | /* Yuck, hardcoded. Needs to be a define */ | ||
167 | itv->vbi.sliced_mpeg_data[i] = kmalloc(2049, GFP_KERNEL); | ||
168 | if (itv->vbi.sliced_mpeg_data[i] == NULL) { | ||
169 | while (--i >= 0) { | ||
170 | kfree(itv->vbi.sliced_mpeg_data[i]); | ||
171 | itv->vbi.sliced_mpeg_data[i] = NULL; | ||
172 | } | ||
173 | return -ENOMEM; | ||
174 | } | ||
175 | } | ||
176 | } | ||
177 | |||
178 | itv->vbi.insert_mpeg = fmt; | ||
179 | |||
180 | if (itv->vbi.insert_mpeg == 0) { | ||
181 | return 0; | ||
182 | } | ||
183 | /* Need sliced data for mpeg insertion */ | ||
184 | if (get_service_set(itv->vbi.sliced_in) == 0) { | ||
185 | if (itv->is_60hz) | ||
186 | itv->vbi.sliced_in->service_set = V4L2_SLICED_CAPTION_525; | ||
187 | else | ||
188 | itv->vbi.sliced_in->service_set = V4L2_SLICED_WSS_625; | ||
189 | expand_service_set(itv->vbi.sliced_in, itv->is_50hz); | ||
190 | } | ||
191 | return 0; | ||
192 | } | ||
193 | |||
194 | int ivtv_control_ioctls(struct ivtv *itv, unsigned int cmd, void *arg) | ||
195 | { | ||
196 | struct v4l2_control ctrl; | ||
197 | |||
198 | switch (cmd) { | ||
199 | case VIDIOC_QUERYMENU: | ||
200 | IVTV_DEBUG_IOCTL("VIDIOC_QUERYMENU\n"); | ||
201 | return ivtv_querymenu(itv, arg); | ||
202 | |||
203 | case VIDIOC_QUERYCTRL: | ||
204 | return ivtv_queryctrl(itv, arg); | ||
205 | |||
206 | case VIDIOC_S_CTRL: | ||
207 | return ivtv_s_ctrl(itv, arg); | ||
208 | |||
209 | case VIDIOC_G_CTRL: | ||
210 | return ivtv_g_ctrl(itv, arg); | ||
211 | |||
212 | case VIDIOC_S_EXT_CTRLS: | ||
213 | { | ||
214 | struct v4l2_ext_controls *c = arg; | ||
215 | |||
216 | if (c->ctrl_class == V4L2_CTRL_CLASS_USER) { | ||
217 | int i; | ||
218 | int err = 0; | ||
219 | |||
220 | for (i = 0; i < c->count; i++) { | ||
221 | ctrl.id = c->controls[i].id; | ||
222 | ctrl.value = c->controls[i].value; | ||
223 | err = ivtv_s_ctrl(itv, &ctrl); | ||
224 | c->controls[i].value = ctrl.value; | ||
225 | if (err) { | ||
226 | c->error_idx = i; | ||
227 | break; | ||
228 | } | ||
229 | } | ||
230 | return err; | ||
231 | } | ||
232 | IVTV_DEBUG_IOCTL("VIDIOC_S_EXT_CTRLS\n"); | ||
233 | if (c->ctrl_class == V4L2_CTRL_CLASS_MPEG) { | ||
234 | struct cx2341x_mpeg_params p = itv->params; | ||
235 | int err = cx2341x_ext_ctrls(&p, arg, cmd); | ||
236 | |||
237 | if (err) | ||
238 | return err; | ||
239 | |||
240 | if (p.video_encoding != itv->params.video_encoding) { | ||
241 | int is_mpeg1 = p.video_encoding == | ||
242 | V4L2_MPEG_VIDEO_ENCODING_MPEG_1; | ||
243 | struct v4l2_format fmt; | ||
244 | |||
245 | /* fix videodecoder resolution */ | ||
246 | fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
247 | fmt.fmt.pix.width = itv->params.width / (is_mpeg1 ? 2 : 1); | ||
248 | fmt.fmt.pix.height = itv->params.height; | ||
249 | itv->video_dec_func(itv, VIDIOC_S_FMT, &fmt); | ||
250 | } | ||
251 | err = cx2341x_update(itv, ivtv_api_func, &itv->params, &p); | ||
252 | if (!err && itv->params.stream_vbi_fmt != p.stream_vbi_fmt) { | ||
253 | err = ivtv_setup_vbi_fmt(itv, p.stream_vbi_fmt); | ||
254 | } | ||
255 | itv->params = p; | ||
256 | itv->dualwatch_stereo_mode = p.audio_properties & 0x0300; | ||
257 | ivtv_audio_set_audio_clock_freq(itv, p.audio_properties & 0x03); | ||
258 | return err; | ||
259 | } | ||
260 | return -EINVAL; | ||
261 | } | ||
262 | |||
263 | case VIDIOC_G_EXT_CTRLS: | ||
264 | { | ||
265 | struct v4l2_ext_controls *c = arg; | ||
266 | |||
267 | if (c->ctrl_class == V4L2_CTRL_CLASS_USER) { | ||
268 | int i; | ||
269 | int err = 0; | ||
270 | |||
271 | for (i = 0; i < c->count; i++) { | ||
272 | ctrl.id = c->controls[i].id; | ||
273 | ctrl.value = c->controls[i].value; | ||
274 | err = ivtv_g_ctrl(itv, &ctrl); | ||
275 | c->controls[i].value = ctrl.value; | ||
276 | if (err) { | ||
277 | c->error_idx = i; | ||
278 | break; | ||
279 | } | ||
280 | } | ||
281 | return err; | ||
282 | } | ||
283 | IVTV_DEBUG_IOCTL("VIDIOC_G_EXT_CTRLS\n"); | ||
284 | if (c->ctrl_class == V4L2_CTRL_CLASS_MPEG) | ||
285 | return cx2341x_ext_ctrls(&itv->params, arg, cmd); | ||
286 | return -EINVAL; | ||
287 | } | ||
288 | |||
289 | case VIDIOC_TRY_EXT_CTRLS: | ||
290 | { | ||
291 | struct v4l2_ext_controls *c = arg; | ||
292 | |||
293 | IVTV_DEBUG_IOCTL("VIDIOC_TRY_EXT_CTRLS\n"); | ||
294 | if (c->ctrl_class == V4L2_CTRL_CLASS_MPEG) | ||
295 | return cx2341x_ext_ctrls(&itv->params, arg, cmd); | ||
296 | return -EINVAL; | ||
297 | } | ||
298 | |||
299 | default: | ||
300 | return -EINVAL; | ||
301 | } | ||
302 | return 0; | ||
303 | } | ||
diff --git a/drivers/media/video/ivtv/ivtv-controls.h b/drivers/media/video/ivtv/ivtv-controls.h new file mode 100644 index 000000000000..5a11149725ad --- /dev/null +++ b/drivers/media/video/ivtv/ivtv-controls.h | |||
@@ -0,0 +1,21 @@ | |||
1 | /* | ||
2 | ioctl control functions | ||
3 | Copyright (C) 2003-2004 Kevin Thayer <nufan_wfk at yahoo.com> | ||
4 | Copyright (C) 2005-2007 Hans Verkuil <hverkuil@xs4all.nl> | ||
5 | |||
6 | This program is free software; you can redistribute it and/or modify | ||
7 | it under the terms of the GNU General Public License as published by | ||
8 | the Free Software Foundation; either version 2 of the License, or | ||
9 | (at your option) any later version. | ||
10 | |||
11 | This program is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program; if not, write to the Free Software | ||
18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | */ | ||
20 | |||
21 | int ivtv_control_ioctls(struct ivtv *itv, unsigned int cmd, void *arg); | ||
diff --git a/drivers/media/video/ivtv/ivtv-driver.c b/drivers/media/video/ivtv/ivtv-driver.c new file mode 100644 index 000000000000..8d3876588b88 --- /dev/null +++ b/drivers/media/video/ivtv/ivtv-driver.c | |||
@@ -0,0 +1,1385 @@ | |||
1 | /* | ||
2 | ivtv driver initialization and card probing | ||
3 | Copyright (C) 2003-2004 Kevin Thayer <nufan_wfk at yahoo.com> | ||
4 | Copyright (C) 2004 Chris Kennedy <c@groovy.org> | ||
5 | Copyright (C) 2005-2007 Hans Verkuil <hverkuil@xs4all.nl> | ||
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 02111-1307 USA | ||
20 | */ | ||
21 | |||
22 | /* Main Driver file for the ivtv project: | ||
23 | * Driver for the Conexant CX23415/CX23416 chip. | ||
24 | * Author: Kevin Thayer (nufan_wfk at yahoo.com) | ||
25 | * License: GPL | ||
26 | * http://www.ivtvdriver.org | ||
27 | * | ||
28 | * ----- | ||
29 | * MPG600/MPG160 support by T.Adachi <tadachi@tadachi-net.com> | ||
30 | * and Takeru KOMORIYA<komoriya@paken.org> | ||
31 | * | ||
32 | * AVerMedia M179 GPIO info by Chris Pinkham <cpinkham@bc2va.org> | ||
33 | * using information provided by Jiun-Kuei Jung @ AVerMedia. | ||
34 | * | ||
35 | * Kurouto Sikou CX23416GYC-STVLP tested by K.Ohta <alpha292@bremen.or.jp> | ||
36 | * using information from T.Adachi,Takeru KOMORIYA and others :-) | ||
37 | * | ||
38 | * Nagase TRANSGEAR 5000TV, Aopen VA2000MAX-STN6 and I/O data GV-MVP/RX | ||
39 | * version by T.Adachi. Special thanks Mr.Suzuki | ||
40 | */ | ||
41 | |||
42 | #include "ivtv-driver.h" | ||
43 | #include "ivtv-version.h" | ||
44 | #include "ivtv-fileops.h" | ||
45 | #include "ivtv-i2c.h" | ||
46 | #include "ivtv-firmware.h" | ||
47 | #include "ivtv-queue.h" | ||
48 | #include "ivtv-udma.h" | ||
49 | #include "ivtv-irq.h" | ||
50 | #include "ivtv-mailbox.h" | ||
51 | #include "ivtv-streams.h" | ||
52 | #include "ivtv-ioctl.h" | ||
53 | #include "ivtv-cards.h" | ||
54 | #include "ivtv-vbi.h" | ||
55 | #include "ivtv-audio.h" | ||
56 | #include "ivtv-gpio.h" | ||
57 | #include "ivtv-yuv.h" | ||
58 | |||
59 | #include <linux/vermagic.h> | ||
60 | #include <media/tveeprom.h> | ||
61 | #include <media/v4l2-chip-ident.h> | ||
62 | |||
63 | /* var to keep track of the number of array elements in use */ | ||
64 | int ivtv_cards_active = 0; | ||
65 | |||
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 | ||
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 | ||
70 | setting this to 1 you ensure that radio0 is now also radio1. */ | ||
71 | int ivtv_first_minor = 0; | ||
72 | |||
73 | /* Master variable for all ivtv info */ | ||
74 | struct ivtv *ivtv_cards[IVTV_MAX_CARDS]; | ||
75 | |||
76 | /* Protects ivtv_cards_active */ | ||
77 | spinlock_t ivtv_cards_lock = SPIN_LOCK_UNLOCKED; | ||
78 | |||
79 | /* add your revision and whatnot here */ | ||
80 | static struct pci_device_id ivtv_pci_tbl[] __devinitdata = { | ||
81 | {PCI_VENDOR_ID_ICOMP, PCI_DEVICE_ID_IVTV15, | ||
82 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, | ||
83 | {PCI_VENDOR_ID_ICOMP, PCI_DEVICE_ID_IVTV16, | ||
84 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, | ||
85 | {0,} | ||
86 | }; | ||
87 | |||
88 | MODULE_DEVICE_TABLE(pci,ivtv_pci_tbl); | ||
89 | |||
90 | const u32 yuv_offset[4] = { | ||
91 | IVTV_YUV_BUFFER_OFFSET, | ||
92 | IVTV_YUV_BUFFER_OFFSET_1, | ||
93 | IVTV_YUV_BUFFER_OFFSET_2, | ||
94 | IVTV_YUV_BUFFER_OFFSET_3 | ||
95 | }; | ||
96 | |||
97 | /* Parameter declarations */ | ||
98 | static int cardtype[IVTV_MAX_CARDS]; | ||
99 | static int tuner[IVTV_MAX_CARDS] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }; | ||
100 | static int radio[IVTV_MAX_CARDS] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }; | ||
101 | |||
102 | static int cardtype_c = 1; | ||
103 | static int tuner_c = 1; | ||
104 | static int radio_c = 1; | ||
105 | static char pal[] = "--"; | ||
106 | static char secam[] = "--"; | ||
107 | static char ntsc[] = "-"; | ||
108 | |||
109 | /* Buffers */ | ||
110 | static int enc_mpg_buffers = IVTV_DEFAULT_ENC_MPG_BUFFERS; | ||
111 | static int enc_yuv_buffers = IVTV_DEFAULT_ENC_YUV_BUFFERS; | ||
112 | static int enc_vbi_buffers = IVTV_DEFAULT_ENC_VBI_BUFFERS; | ||
113 | static int enc_pcm_buffers = IVTV_DEFAULT_ENC_PCM_BUFFERS; | ||
114 | static int dec_mpg_buffers = IVTV_DEFAULT_DEC_MPG_BUFFERS; | ||
115 | static int dec_yuv_buffers = IVTV_DEFAULT_DEC_YUV_BUFFERS; | ||
116 | static int dec_vbi_buffers = IVTV_DEFAULT_DEC_VBI_BUFFERS; | ||
117 | |||
118 | static int ivtv_yuv_mode = 0; | ||
119 | static int ivtv_yuv_threshold=480; | ||
120 | static int ivtv_pci_latency = 1; | ||
121 | |||
122 | int ivtv_debug = 0; | ||
123 | |||
124 | int newi2c = -1; | ||
125 | |||
126 | module_param_array(tuner, int, &tuner_c, 0644); | ||
127 | module_param_array(radio, bool, &radio_c, 0644); | ||
128 | module_param_array(cardtype, int, &cardtype_c, 0644); | ||
129 | module_param_string(pal, pal, sizeof(pal), 0644); | ||
130 | module_param_string(secam, secam, sizeof(secam), 0644); | ||
131 | module_param_string(ntsc, ntsc, sizeof(ntsc), 0644); | ||
132 | module_param_named(debug,ivtv_debug, int, 0644); | ||
133 | module_param(ivtv_pci_latency, int, 0644); | ||
134 | module_param(ivtv_yuv_mode, int, 0644); | ||
135 | module_param(ivtv_yuv_threshold, int, 0644); | ||
136 | module_param(ivtv_first_minor, int, 0644); | ||
137 | |||
138 | module_param(enc_mpg_buffers, int, 0644); | ||
139 | module_param(enc_yuv_buffers, int, 0644); | ||
140 | module_param(enc_vbi_buffers, int, 0644); | ||
141 | module_param(enc_pcm_buffers, int, 0644); | ||
142 | module_param(dec_mpg_buffers, int, 0644); | ||
143 | module_param(dec_yuv_buffers, int, 0644); | ||
144 | module_param(dec_vbi_buffers, int, 0644); | ||
145 | |||
146 | module_param(newi2c, int, 0644); | ||
147 | |||
148 | MODULE_PARM_DESC(tuner, "Tuner type selection,\n" | ||
149 | "\t\t\tsee tuner.h for values"); | ||
150 | MODULE_PARM_DESC(radio, | ||
151 | "Enable or disable the radio. Use only if autodetection\n" | ||
152 | "\t\t\tfails. 0 = disable, 1 = enable"); | ||
153 | MODULE_PARM_DESC(cardtype, | ||
154 | "Only use this option if your card is not detected properly.\n" | ||
155 | "\t\tSpecify card type:\n" | ||
156 | "\t\t\t 1 = WinTV PVR 250\n" | ||
157 | "\t\t\t 2 = WinTV PVR 350\n" | ||
158 | "\t\t\t 3 = WinTV PVR-150 or PVR-500\n" | ||
159 | "\t\t\t 4 = AVerMedia M179\n" | ||
160 | "\t\t\t 5 = YUAN MPG600/Kuroutoshikou iTVC16-STVLP\n" | ||
161 | "\t\t\t 6 = YUAN MPG160/Kuroutoshikou iTVC15-STVLP\n" | ||
162 | "\t\t\t 7 = YUAN PG600/DIAMONDMM PVR-550 (CX Falcon 2)\n" | ||
163 | "\t\t\t 8 = Adaptec AVC-2410\n" | ||
164 | "\t\t\t 9 = Adaptec AVC-2010\n" | ||
165 | "\t\t\t10 = NAGASE TRANSGEAR 5000TV\n" | ||
166 | "\t\t\t11 = AOpen VA2000MAX-STN6\n" | ||
167 | "\t\t\t12 = YUAN MPG600GR/Kuroutoshikou CX23416GYC-STVLP\n" | ||
168 | "\t\t\t13 = I/O Data GV-MVP/RX\n" | ||
169 | "\t\t\t14 = I/O Data GV-MVP/RX2E\n" | ||
170 | "\t\t\t15 = GOTVIEW PCI DVD\n" | ||
171 | "\t\t\t16 = GOTVIEW PCI DVD2 Deluxe\n" | ||
172 | "\t\t\t17 = Yuan MPC622\n" | ||
173 | "\t\t\t18 = Digital Cowboy DCT-MTVP1\n" | ||
174 | #ifdef HAVE_XC3028 | ||
175 | "\t\t\t19 = Yuan PG600V2/GotView PCI DVD Lite/Club3D ZAP-TV1x01\n" | ||
176 | #endif | ||
177 | "\t\t\t 0 = Autodetect (default)\n" | ||
178 | "\t\t\t-1 = Ignore this card\n\t\t"); | ||
179 | MODULE_PARM_DESC(pal, "Set PAL standard: B, G, H, D, K, I, M, N, Nc, 60"); | ||
180 | MODULE_PARM_DESC(secam, "Set SECAM standard: B, G, H, D, K, L, LC"); | ||
181 | MODULE_PARM_DESC(ntsc, "Set NTSC standard: M, J, K"); | ||
182 | MODULE_PARM_DESC(debug, | ||
183 | "Debug level (bitmask). Default: errors only\n" | ||
184 | "\t\t\t(debug = 511 gives full debugging)"); | ||
185 | MODULE_PARM_DESC(ivtv_pci_latency, | ||
186 | "Change the PCI latency to 64 if lower: 0 = No, 1 = Yes,\n" | ||
187 | "\t\t\tDefault: Yes"); | ||
188 | MODULE_PARM_DESC(ivtv_yuv_mode, | ||
189 | "Specify the yuv playback mode:\n" | ||
190 | "\t\t\t0 = interlaced\n\t\t\t1 = progressive\n\t\t\t2 = auto\n" | ||
191 | "\t\t\tDefault: 0 (interlaced)"); | ||
192 | MODULE_PARM_DESC(ivtv_yuv_threshold, | ||
193 | "If ivtv_yuv_mode is 2 (auto) then playback content as\n\t\tprogressive if src height <= ivtv_yuvthreshold\n" | ||
194 | "\t\t\tDefault: 480");; | ||
195 | MODULE_PARM_DESC(enc_mpg_buffers, | ||
196 | "Encoder MPG Buffers (in MB)\n" | ||
197 | "\t\t\tDefault: " __stringify(IVTV_DEFAULT_ENC_MPG_BUFFERS)); | ||
198 | MODULE_PARM_DESC(enc_yuv_buffers, | ||
199 | "Encoder YUV Buffers (in MB)\n" | ||
200 | "\t\t\tDefault: " __stringify(IVTV_DEFAULT_ENC_YUV_BUFFERS)); | ||
201 | MODULE_PARM_DESC(enc_vbi_buffers, | ||
202 | "Encoder VBI Buffers (in MB)\n" | ||
203 | "\t\t\tDefault: " __stringify(IVTV_DEFAULT_ENC_VBI_BUFFERS)); | ||
204 | MODULE_PARM_DESC(enc_pcm_buffers, | ||
205 | "Encoder PCM buffers (in MB)\n" | ||
206 | "\t\t\tDefault: " __stringify(IVTV_DEFAULT_ENC_PCM_BUFFERS)); | ||
207 | MODULE_PARM_DESC(dec_mpg_buffers, | ||
208 | "Decoder MPG buffers (in MB)\n" | ||
209 | "\t\t\tDefault: " __stringify(IVTV_DEFAULT_DEC_MPG_BUFFERS)); | ||
210 | MODULE_PARM_DESC(dec_yuv_buffers, | ||
211 | "Decoder YUV buffers (in MB)\n" | ||
212 | "\t\t\tDefault: " __stringify(IVTV_DEFAULT_DEC_YUV_BUFFERS)); | ||
213 | MODULE_PARM_DESC(dec_vbi_buffers, | ||
214 | "Decoder VBI buffers (in MB)\n" | ||
215 | "\t\t\tDefault: " __stringify(IVTV_DEFAULT_DEC_VBI_BUFFERS)); | ||
216 | MODULE_PARM_DESC(newi2c, | ||
217 | "Use new I2C implementation\n" | ||
218 | "\t\t\t-1 is autodetect, 0 is off, 1 is on\n" | ||
219 | "\t\t\tDefault is autodetect"); | ||
220 | |||
221 | MODULE_PARM_DESC(ivtv_first_minor, "Set minor assigned to first card"); | ||
222 | |||
223 | MODULE_AUTHOR("Kevin Thayer, Chris Kennedy, Hans Verkuil"); | ||
224 | MODULE_DESCRIPTION("CX23415/CX23416 driver"); | ||
225 | MODULE_SUPPORTED_DEVICE | ||
226 | ("CX23415/CX23416 MPEG2 encoder (WinTV PVR-150/250/350/500,\n" | ||
227 | "\t\t\tYuan MPG series and similar)"); | ||
228 | MODULE_LICENSE("GPL"); | ||
229 | |||
230 | MODULE_VERSION(IVTV_VERSION); | ||
231 | |||
232 | void ivtv_clear_irq_mask(struct ivtv *itv, u32 mask) | ||
233 | { | ||
234 | itv->irqmask &= ~mask; | ||
235 | write_reg_sync(itv->irqmask, IVTV_REG_IRQMASK); | ||
236 | } | ||
237 | |||
238 | void ivtv_set_irq_mask(struct ivtv *itv, u32 mask) | ||
239 | { | ||
240 | itv->irqmask |= mask; | ||
241 | write_reg_sync(itv->irqmask, IVTV_REG_IRQMASK); | ||
242 | } | ||
243 | |||
244 | int ivtv_set_output_mode(struct ivtv *itv, int mode) | ||
245 | { | ||
246 | int old_mode; | ||
247 | |||
248 | spin_lock(&itv->lock); | ||
249 | old_mode = itv->output_mode; | ||
250 | if (old_mode == 0) | ||
251 | itv->output_mode = old_mode = mode; | ||
252 | spin_unlock(&itv->lock); | ||
253 | return old_mode; | ||
254 | } | ||
255 | |||
256 | struct ivtv_stream *ivtv_get_output_stream(struct ivtv *itv) | ||
257 | { | ||
258 | switch (itv->output_mode) { | ||
259 | case OUT_MPG: | ||
260 | return &itv->streams[IVTV_DEC_STREAM_TYPE_MPG]; | ||
261 | case OUT_YUV: | ||
262 | return &itv->streams[IVTV_DEC_STREAM_TYPE_YUV]; | ||
263 | default: | ||
264 | return NULL; | ||
265 | } | ||
266 | } | ||
267 | |||
268 | int ivtv_waitq(wait_queue_head_t *waitq) | ||
269 | { | ||
270 | DEFINE_WAIT(wait); | ||
271 | |||
272 | prepare_to_wait(waitq, &wait, TASK_INTERRUPTIBLE); | ||
273 | schedule(); | ||
274 | finish_wait(waitq, &wait); | ||
275 | return signal_pending(current) ? -EINTR : 0; | ||
276 | } | ||
277 | |||
278 | /* Generic utility functions */ | ||
279 | int ivtv_sleep_timeout(int timeout, int intr) | ||
280 | { | ||
281 | int ret; | ||
282 | |||
283 | do { | ||
284 | set_current_state(intr ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE); | ||
285 | timeout = schedule_timeout(timeout); | ||
286 | if (intr && (ret = signal_pending(current))) | ||
287 | return ret; | ||
288 | } while (timeout); | ||
289 | return 0; | ||
290 | } | ||
291 | |||
292 | /* Release ioremapped memory */ | ||
293 | static void ivtv_iounmap(struct ivtv *itv) | ||
294 | { | ||
295 | if (itv == NULL) | ||
296 | return; | ||
297 | |||
298 | /* Release registers memory */ | ||
299 | if (itv->reg_mem != NULL) { | ||
300 | IVTV_DEBUG_INFO("releasing reg_mem\n"); | ||
301 | iounmap(itv->reg_mem); | ||
302 | itv->reg_mem = NULL; | ||
303 | } | ||
304 | /* Release io memory */ | ||
305 | if (itv->has_cx23415 && itv->dec_mem != NULL) { | ||
306 | IVTV_DEBUG_INFO("releasing dec_mem\n"); | ||
307 | iounmap(itv->dec_mem); | ||
308 | } | ||
309 | itv->dec_mem = NULL; | ||
310 | |||
311 | /* Release io memory */ | ||
312 | if (itv->enc_mem != NULL) { | ||
313 | IVTV_DEBUG_INFO("releasing enc_mem\n"); | ||
314 | iounmap(itv->enc_mem); | ||
315 | itv->enc_mem = NULL; | ||
316 | } | ||
317 | } | ||
318 | |||
319 | /* Hauppauge card? get values from tveeprom */ | ||
320 | void ivtv_read_eeprom(struct ivtv *itv, struct tveeprom *tv) | ||
321 | { | ||
322 | u8 eedata[256]; | ||
323 | |||
324 | itv->i2c_client.addr = 0xA0 >> 1; | ||
325 | tveeprom_read(&itv->i2c_client, eedata, sizeof(eedata)); | ||
326 | tveeprom_hauppauge_analog(&itv->i2c_client, tv, eedata); | ||
327 | } | ||
328 | |||
329 | static void ivtv_process_eeprom(struct ivtv *itv) | ||
330 | { | ||
331 | struct tveeprom tv; | ||
332 | int pci_slot = PCI_SLOT(itv->dev->devfn); | ||
333 | |||
334 | ivtv_read_eeprom(itv, &tv); | ||
335 | |||
336 | /* Many thanks to Steven Toth from Hauppauge for providing the | ||
337 | model numbers */ | ||
338 | switch (tv.model) { | ||
339 | /* In a few cases the PCI subsystem IDs do not correctly | ||
340 | identify the card. A better method is to check the | ||
341 | model number from the eeprom instead. */ | ||
342 | case 32000 ... 32999: | ||
343 | case 48000 ... 48099: /* 48??? range are PVR250s with a cx23415 */ | ||
344 | case 48400 ... 48599: | ||
345 | itv->card = ivtv_get_card(IVTV_CARD_PVR_250); | ||
346 | break; | ||
347 | case 48100 ... 48399: | ||
348 | case 48600 ... 48999: | ||
349 | itv->card = ivtv_get_card(IVTV_CARD_PVR_350); | ||
350 | break; | ||
351 | case 23000 ... 23999: /* PVR500 */ | ||
352 | case 25000 ... 25999: /* Low profile PVR150 */ | ||
353 | case 26000 ... 26999: /* Regular PVR150 */ | ||
354 | itv->card = ivtv_get_card(IVTV_CARD_PVR_150); | ||
355 | break; | ||
356 | case 0: | ||
357 | IVTV_ERR("Invalid EEPROM\n"); | ||
358 | return; | ||
359 | default: | ||
360 | IVTV_ERR("Unknown model %d, defaulting to PVR-150\n", tv.model); | ||
361 | itv->card = ivtv_get_card(IVTV_CARD_PVR_150); | ||
362 | break; | ||
363 | } | ||
364 | |||
365 | switch (tv.model) { | ||
366 | /* Old style PVR350 (with an saa7114) uses this input for | ||
367 | the tuner. */ | ||
368 | case 48254: | ||
369 | itv->card = ivtv_get_card(IVTV_CARD_PVR_350_V1); | ||
370 | break; | ||
371 | default: | ||
372 | break; | ||
373 | } | ||
374 | |||
375 | itv->v4l2_cap = itv->card->v4l2_capabilities; | ||
376 | itv->card_name = itv->card->name; | ||
377 | |||
378 | /* If this is a PVR500 then it should be possible to detect whether it is the | ||
379 | first or second unit by looking at the subsystem device ID: is bit 4 is | ||
380 | set, then it is the second unit (according to info from Hauppauge). | ||
381 | |||
382 | However, while this works for most cards, I have seen a few PVR500 cards | ||
383 | where both units have the same subsystem ID. | ||
384 | |||
385 | So instead I look at the reported 'PCI slot' (which is the slot on the PVR500 | ||
386 | PCI bridge) and if it is 8, then it is assumed to be the first unit, otherwise | ||
387 | it is the second unit. It is possible that it is a different slot when ivtv is | ||
388 | used in Xen, in that case I ignore this card here. The worst that can happen | ||
389 | is that the card presents itself with a non-working radio device. | ||
390 | |||
391 | This detection is needed since the eeprom reports incorrectly that a radio is | ||
392 | present on the second unit. */ | ||
393 | if (tv.model / 1000 == 23) { | ||
394 | itv->card_name = "WinTV PVR 500"; | ||
395 | if (pci_slot == 8 || pci_slot == 9) { | ||
396 | int is_first = (pci_slot & 1) == 0; | ||
397 | |||
398 | itv->card_name = is_first ? "WinTV PVR 500 (unit #1)" : | ||
399 | "WinTV PVR 500 (unit #2)"; | ||
400 | if (!is_first) { | ||
401 | IVTV_INFO("Correcting tveeprom data: no radio present on second unit\n"); | ||
402 | tv.has_radio = 0; | ||
403 | } | ||
404 | } | ||
405 | } | ||
406 | IVTV_INFO("Autodetected %s\n", itv->card_name); | ||
407 | |||
408 | switch (tv.tuner_hauppauge_model) { | ||
409 | case 85: | ||
410 | case 99: | ||
411 | case 112: | ||
412 | itv->pvr150_workaround = 1; | ||
413 | break; | ||
414 | default: | ||
415 | break; | ||
416 | } | ||
417 | if (tv.tuner_type == TUNER_ABSENT) | ||
418 | IVTV_ERR("tveeprom cannot autodetect tuner!"); | ||
419 | |||
420 | if (itv->options.tuner == -1) | ||
421 | itv->options.tuner = tv.tuner_type; | ||
422 | if (itv->options.radio == -1) | ||
423 | itv->options.radio = (tv.has_radio != 0); | ||
424 | /* only enable newi2c if an IR blaster is present */ | ||
425 | /* FIXME: for 2.6.20 the test against 2 should be removed */ | ||
426 | if (itv->options.newi2c == -1 && tv.has_ir != -1 && tv.has_ir != 2) { | ||
427 | itv->options.newi2c = (tv.has_ir & 2) ? 1 : 0; | ||
428 | if (itv->options.newi2c) { | ||
429 | IVTV_INFO("reopen i2c bus for IR-blaster support\n"); | ||
430 | exit_ivtv_i2c(itv); | ||
431 | init_ivtv_i2c(itv); | ||
432 | } | ||
433 | } | ||
434 | |||
435 | if (itv->std != 0) | ||
436 | /* user specified tuner standard */ | ||
437 | return; | ||
438 | |||
439 | /* autodetect tuner standard */ | ||
440 | if (tv.tuner_formats & V4L2_STD_PAL) { | ||
441 | IVTV_DEBUG_INFO("PAL tuner detected\n"); | ||
442 | itv->std |= V4L2_STD_PAL_BG | V4L2_STD_PAL_H; | ||
443 | } else if (tv.tuner_formats & V4L2_STD_NTSC) { | ||
444 | IVTV_DEBUG_INFO("NTSC tuner detected\n"); | ||
445 | itv->std |= V4L2_STD_NTSC_M; | ||
446 | } else if (tv.tuner_formats & V4L2_STD_SECAM) { | ||
447 | IVTV_DEBUG_INFO("SECAM tuner detected\n"); | ||
448 | itv->std |= V4L2_STD_SECAM_L; | ||
449 | } else { | ||
450 | IVTV_INFO("No tuner detected, default to NTSC-M\n"); | ||
451 | itv->std |= V4L2_STD_NTSC_M; | ||
452 | } | ||
453 | } | ||
454 | |||
455 | static v4l2_std_id ivtv_parse_std(struct ivtv *itv) | ||
456 | { | ||
457 | switch (pal[0]) { | ||
458 | case '6': | ||
459 | return V4L2_STD_PAL_60; | ||
460 | case 'b': | ||
461 | case 'B': | ||
462 | case 'g': | ||
463 | case 'G': | ||
464 | return V4L2_STD_PAL_BG; | ||
465 | case 'h': | ||
466 | case 'H': | ||
467 | return V4L2_STD_PAL_H; | ||
468 | case 'n': | ||
469 | case 'N': | ||
470 | if (pal[1] == 'c' || pal[1] == 'C') | ||
471 | return V4L2_STD_PAL_Nc; | ||
472 | return V4L2_STD_PAL_N; | ||
473 | case 'i': | ||
474 | case 'I': | ||
475 | return V4L2_STD_PAL_I; | ||
476 | case 'd': | ||
477 | case 'D': | ||
478 | case 'k': | ||
479 | case 'K': | ||
480 | return V4L2_STD_PAL_DK; | ||
481 | case 'M': | ||
482 | case 'm': | ||
483 | return V4L2_STD_PAL_M; | ||
484 | case '-': | ||
485 | break; | ||
486 | default: | ||
487 | IVTV_WARN("pal= argument not recognised\n"); | ||
488 | return 0; | ||
489 | } | ||
490 | |||
491 | switch (secam[0]) { | ||
492 | case 'b': | ||
493 | case 'B': | ||
494 | case 'g': | ||
495 | case 'G': | ||
496 | case 'h': | ||
497 | case 'H': | ||
498 | return V4L2_STD_SECAM_B | V4L2_STD_SECAM_G | V4L2_STD_SECAM_H; | ||
499 | case 'd': | ||
500 | case 'D': | ||
501 | case 'k': | ||
502 | case 'K': | ||
503 | return V4L2_STD_SECAM_DK; | ||
504 | case 'l': | ||
505 | case 'L': | ||
506 | if (secam[1] == 'C' || secam[1] == 'c') | ||
507 | return V4L2_STD_SECAM_LC; | ||
508 | return V4L2_STD_SECAM_L; | ||
509 | case '-': | ||
510 | break; | ||
511 | default: | ||
512 | IVTV_WARN("secam= argument not recognised\n"); | ||
513 | return 0; | ||
514 | } | ||
515 | |||
516 | switch (ntsc[0]) { | ||
517 | case 'm': | ||
518 | case 'M': | ||
519 | return V4L2_STD_NTSC_M; | ||
520 | case 'j': | ||
521 | case 'J': | ||
522 | return V4L2_STD_NTSC_M_JP; | ||
523 | case 'k': | ||
524 | case 'K': | ||
525 | return V4L2_STD_NTSC_M_KR; | ||
526 | case '-': | ||
527 | break; | ||
528 | default: | ||
529 | IVTV_WARN("ntsc= argument not recognised\n"); | ||
530 | return 0; | ||
531 | } | ||
532 | |||
533 | /* no match found */ | ||
534 | return 0; | ||
535 | } | ||
536 | |||
537 | static void ivtv_process_options(struct ivtv *itv) | ||
538 | { | ||
539 | const char *chipname; | ||
540 | int i, j; | ||
541 | |||
542 | itv->options.megabytes[IVTV_ENC_STREAM_TYPE_MPG] = enc_mpg_buffers; | ||
543 | itv->options.megabytes[IVTV_ENC_STREAM_TYPE_YUV] = enc_yuv_buffers; | ||
544 | itv->options.megabytes[IVTV_ENC_STREAM_TYPE_VBI] = enc_vbi_buffers; | ||
545 | itv->options.megabytes[IVTV_ENC_STREAM_TYPE_PCM] = enc_pcm_buffers; | ||
546 | itv->options.megabytes[IVTV_DEC_STREAM_TYPE_MPG] = dec_mpg_buffers; | ||
547 | itv->options.megabytes[IVTV_DEC_STREAM_TYPE_YUV] = dec_yuv_buffers; | ||
548 | itv->options.megabytes[IVTV_DEC_STREAM_TYPE_VBI] = dec_vbi_buffers; | ||
549 | itv->options.cardtype = cardtype[itv->num]; | ||
550 | itv->options.tuner = tuner[itv->num]; | ||
551 | itv->options.radio = radio[itv->num]; | ||
552 | itv->options.newi2c = newi2c; | ||
553 | |||
554 | itv->std = ivtv_parse_std(itv); | ||
555 | itv->has_cx23415 = (itv->dev->device == PCI_DEVICE_ID_IVTV15); | ||
556 | chipname = itv->has_cx23415 ? "cx23415" : "cx23416"; | ||
557 | if (itv->options.cardtype == -1) { | ||
558 | IVTV_INFO("Ignore card (detected %s based chip)\n", chipname); | ||
559 | return; | ||
560 | } | ||
561 | if ((itv->card = ivtv_get_card(itv->options.cardtype - 1))) { | ||
562 | IVTV_INFO("User specified %s card (detected %s based chip)\n", | ||
563 | itv->card->name, chipname); | ||
564 | } else if (itv->options.cardtype != 0) { | ||
565 | IVTV_ERR("Unknown user specified type, trying to autodetect card\n"); | ||
566 | } | ||
567 | if (itv->card == NULL) { | ||
568 | if (itv->dev->subsystem_vendor == IVTV_PCI_ID_HAUPPAUGE || | ||
569 | itv->dev->subsystem_vendor == IVTV_PCI_ID_HAUPPAUGE_ALT1 || | ||
570 | itv->dev->subsystem_vendor == IVTV_PCI_ID_HAUPPAUGE_ALT2) { | ||
571 | itv->card = ivtv_get_card(itv->has_cx23415 ? IVTV_CARD_PVR_350 : IVTV_CARD_PVR_150); | ||
572 | IVTV_INFO("Autodetected Hauppauge card (%s based)\n", | ||
573 | chipname); | ||
574 | } | ||
575 | } | ||
576 | if (itv->card == NULL) { | ||
577 | for (i = 0; (itv->card = ivtv_get_card(i)); i++) { | ||
578 | if (itv->card->pci_list == NULL) | ||
579 | continue; | ||
580 | for (j = 0; itv->card->pci_list[j].device; j++) { | ||
581 | if (itv->dev->device != | ||
582 | itv->card->pci_list[j].device) | ||
583 | continue; | ||
584 | if (itv->dev->subsystem_vendor != | ||
585 | itv->card->pci_list[j].subsystem_vendor) | ||
586 | continue; | ||
587 | if (itv->dev->subsystem_device != | ||
588 | itv->card->pci_list[j].subsystem_device) | ||
589 | continue; | ||
590 | IVTV_INFO("Autodetected %s card (%s based)\n", | ||
591 | itv->card->name, chipname); | ||
592 | goto done; | ||
593 | } | ||
594 | } | ||
595 | } | ||
596 | done: | ||
597 | |||
598 | if (itv->card == NULL) { | ||
599 | itv->card = ivtv_get_card(IVTV_CARD_PVR_150); | ||
600 | IVTV_ERR("Unknown card: vendor/device: %04x/%04x\n", | ||
601 | itv->dev->vendor, itv->dev->device); | ||
602 | IVTV_ERR(" subsystem vendor/device: %04x/%04x\n", | ||
603 | itv->dev->subsystem_vendor, itv->dev->subsystem_device); | ||
604 | IVTV_ERR(" %s based\n", chipname); | ||
605 | IVTV_ERR("Defaulting to %s card\n", itv->card->name); | ||
606 | IVTV_ERR("Please mail the vendor/device and subsystem vendor/device IDs and what kind of\n"); | ||
607 | IVTV_ERR("card you have to the ivtv-devel mailinglist (www.ivtvdriver.org)\n"); | ||
608 | IVTV_ERR("Prefix your subject line with [UNKNOWN CARD].\n"); | ||
609 | } | ||
610 | itv->v4l2_cap = itv->card->v4l2_capabilities; | ||
611 | itv->card_name = itv->card->name; | ||
612 | } | ||
613 | |||
614 | /* Precondition: the ivtv structure has been memset to 0. Only | ||
615 | the dev and num fields have been filled in. | ||
616 | No assumptions on the card type may be made here (see ivtv_init_struct2 | ||
617 | for that). | ||
618 | */ | ||
619 | static int __devinit ivtv_init_struct1(struct ivtv *itv) | ||
620 | { | ||
621 | itv->base_addr = pci_resource_start(itv->dev, 0); | ||
622 | itv->enc_mbox.max_mbox = 2; /* the encoder has 3 mailboxes (0-2) */ | ||
623 | itv->dec_mbox.max_mbox = 1; /* the decoder has 2 mailboxes (0-1) */ | ||
624 | |||
625 | mutex_init(&itv->i2c_bus_lock); | ||
626 | mutex_init(&itv->udma.lock); | ||
627 | |||
628 | itv->lock = SPIN_LOCK_UNLOCKED; | ||
629 | itv->dma_reg_lock = SPIN_LOCK_UNLOCKED; | ||
630 | |||
631 | itv->vbi.work_queues = create_workqueue("ivtv_vbi"); | ||
632 | if (itv->vbi.work_queues == NULL) { | ||
633 | IVTV_ERR("Could not create VBI workqueue\n"); | ||
634 | return -1; | ||
635 | } | ||
636 | |||
637 | itv->yuv_info.work_queues = create_workqueue("ivtv_yuv"); | ||
638 | if (itv->yuv_info.work_queues == NULL) { | ||
639 | IVTV_ERR("Could not create YUV workqueue\n"); | ||
640 | destroy_workqueue(itv->vbi.work_queues); | ||
641 | return -1; | ||
642 | } | ||
643 | |||
644 | INIT_WORK(&itv->vbi.work_queue, vbi_work_handler); | ||
645 | INIT_WORK(&itv->yuv_info.work_queue, ivtv_yuv_work_handler); | ||
646 | |||
647 | /* start counting open_id at 1 */ | ||
648 | itv->open_id = 1; | ||
649 | |||
650 | /* Initial settings */ | ||
651 | cx2341x_fill_defaults(&itv->params); | ||
652 | itv->params.port = CX2341X_PORT_MEMORY; | ||
653 | itv->params.capabilities = CX2341X_CAP_HAS_SLICED_VBI; | ||
654 | init_waitqueue_head(&itv->cap_w); | ||
655 | init_waitqueue_head(&itv->event_waitq); | ||
656 | init_waitqueue_head(&itv->vsync_waitq); | ||
657 | init_waitqueue_head(&itv->dma_waitq); | ||
658 | init_timer(&itv->dma_timer); | ||
659 | itv->dma_timer.function = ivtv_unfinished_dma; | ||
660 | itv->dma_timer.data = (unsigned long)itv; | ||
661 | |||
662 | itv->cur_dma_stream = -1; | ||
663 | itv->audio_stereo_mode = AUDIO_STEREO; | ||
664 | itv->audio_bilingual_mode = AUDIO_MONO_LEFT; | ||
665 | |||
666 | /* Ctrls */ | ||
667 | itv->speed = 1000; | ||
668 | |||
669 | /* VBI */ | ||
670 | itv->vbi.in.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE; | ||
671 | itv->vbi.sliced_in = &itv->vbi.in.fmt.sliced; | ||
672 | |||
673 | /* OSD */ | ||
674 | itv->osd_global_alpha_state = 1; | ||
675 | itv->osd_global_alpha = 255; | ||
676 | |||
677 | /* YUV */ | ||
678 | atomic_set(&itv->yuv_info.next_dma_frame, -1); | ||
679 | itv->yuv_info.lace_mode = ivtv_yuv_mode; | ||
680 | itv->yuv_info.lace_threshold = ivtv_yuv_threshold; | ||
681 | return 0; | ||
682 | } | ||
683 | |||
684 | /* Second initialization part. Here the card type has been | ||
685 | autodetected. */ | ||
686 | static void __devinit ivtv_init_struct2(struct ivtv *itv) | ||
687 | { | ||
688 | int i; | ||
689 | |||
690 | for (i = 0; i < IVTV_CARD_MAX_VIDEO_INPUTS; i++) | ||
691 | if (itv->card->video_inputs[i].video_type == 0) | ||
692 | break; | ||
693 | itv->nof_inputs = i; | ||
694 | for (i = 0; i < IVTV_CARD_MAX_AUDIO_INPUTS; i++) | ||
695 | if (itv->card->audio_inputs[i].audio_type == 0) | ||
696 | break; | ||
697 | itv->nof_audio_inputs = i; | ||
698 | |||
699 | /* 0x00EF = saa7114(239) 0x00F0 = saa7115(240) 0x0106 = micro */ | ||
700 | if (itv->card->hw_all & (IVTV_HW_SAA7115 | IVTV_HW_SAA717X)) | ||
701 | itv->digitizer = 0xF1; | ||
702 | else if (itv->card->hw_all & IVTV_HW_SAA7114) | ||
703 | itv->digitizer = 0xEF; | ||
704 | else /* cx25840 */ | ||
705 | itv->digitizer = 0x140; | ||
706 | |||
707 | if (itv->card->hw_all & IVTV_HW_CX25840) { | ||
708 | itv->vbi.sliced_size = 288; /* multiple of 16, real size = 284 */ | ||
709 | } else { | ||
710 | itv->vbi.sliced_size = 64; /* multiple of 16, real size = 52 */ | ||
711 | } | ||
712 | |||
713 | /* Find tuner input */ | ||
714 | for (i = 0; i < itv->nof_inputs; i++) { | ||
715 | if (itv->card->video_inputs[i].video_type == | ||
716 | IVTV_CARD_INPUT_VID_TUNER) | ||
717 | break; | ||
718 | } | ||
719 | if (i == itv->nof_inputs) | ||
720 | i = 0; | ||
721 | itv->active_input = i; | ||
722 | itv->audio_input = itv->card->video_inputs[i].audio_index; | ||
723 | if (itv->card->hw_all & IVTV_HW_CX25840) | ||
724 | itv->video_dec_func = ivtv_cx25840; | ||
725 | else if (itv->card->hw_all & IVTV_HW_SAA717X) | ||
726 | itv->video_dec_func = ivtv_saa717x; | ||
727 | else | ||
728 | itv->video_dec_func = ivtv_saa7115; | ||
729 | } | ||
730 | |||
731 | static int ivtv_setup_pci(struct ivtv *itv, struct pci_dev *dev, | ||
732 | const struct pci_device_id *pci_id) | ||
733 | { | ||
734 | u16 cmd; | ||
735 | unsigned char pci_latency; | ||
736 | |||
737 | IVTV_DEBUG_INFO("Enabling pci device\n"); | ||
738 | |||
739 | if (pci_enable_device(dev)) { | ||
740 | IVTV_ERR("Can't enable device %d!\n", itv->num); | ||
741 | return -EIO; | ||
742 | } | ||
743 | if (pci_set_dma_mask(dev, 0xffffffff)) { | ||
744 | IVTV_ERR("No suitable DMA available on card %d.\n", itv->num); | ||
745 | return -EIO; | ||
746 | } | ||
747 | if (!request_mem_region(itv->base_addr, IVTV_ENCODER_SIZE, "ivtv encoder")) { | ||
748 | IVTV_ERR("Cannot request encoder memory region on card %d.\n", itv->num); | ||
749 | return -EIO; | ||
750 | } | ||
751 | |||
752 | if (!request_mem_region(itv->base_addr + IVTV_REG_OFFSET, | ||
753 | IVTV_REG_SIZE, "ivtv registers")) { | ||
754 | IVTV_ERR("Cannot request register memory region on card %d.\n", itv->num); | ||
755 | release_mem_region(itv->base_addr, IVTV_ENCODER_SIZE); | ||
756 | return -EIO; | ||
757 | } | ||
758 | |||
759 | if (itv->has_cx23415 && | ||
760 | !request_mem_region(itv->base_addr + IVTV_DECODER_OFFSET, | ||
761 | IVTV_DECODER_SIZE, "ivtv decoder")) { | ||
762 | IVTV_ERR("Cannot request decoder memory region on card %d.\n", itv->num); | ||
763 | release_mem_region(itv->base_addr, IVTV_ENCODER_SIZE); | ||
764 | release_mem_region(itv->base_addr + IVTV_REG_OFFSET, IVTV_REG_SIZE); | ||
765 | return -EIO; | ||
766 | } | ||
767 | |||
768 | /* Check for bus mastering */ | ||
769 | pci_read_config_word(dev, PCI_COMMAND, &cmd); | ||
770 | if (!(cmd & PCI_COMMAND_MASTER)) { | ||
771 | IVTV_DEBUG_INFO("Attempting to enable Bus Mastering\n"); | ||
772 | pci_set_master(dev); | ||
773 | pci_read_config_word(dev, PCI_COMMAND, &cmd); | ||
774 | if (!(cmd & PCI_COMMAND_MASTER)) { | ||
775 | IVTV_ERR("Bus Mastering is not enabled\n"); | ||
776 | return -ENXIO; | ||
777 | } | ||
778 | } | ||
779 | IVTV_DEBUG_INFO("Bus Mastering Enabled.\n"); | ||
780 | |||
781 | pci_read_config_byte(dev, PCI_CLASS_REVISION, &itv->card_rev); | ||
782 | pci_read_config_byte(dev, PCI_LATENCY_TIMER, &pci_latency); | ||
783 | |||
784 | if (pci_latency < 64 && ivtv_pci_latency) { | ||
785 | IVTV_INFO("Unreasonably low latency timer, " | ||
786 | "setting to 64 (was %d)\n", pci_latency); | ||
787 | pci_write_config_byte(dev, PCI_LATENCY_TIMER, 64); | ||
788 | pci_read_config_byte(dev, PCI_LATENCY_TIMER, &pci_latency); | ||
789 | } | ||
790 | /* This config space value relates to DMA latencies. The | ||
791 | default value 0x8080 is too low however and will lead | ||
792 | to DMA errors. 0xffff is the max value which solves | ||
793 | these problems. */ | ||
794 | pci_write_config_dword(dev, 0x40, 0xffff); | ||
795 | |||
796 | IVTV_DEBUG_INFO("%d (rev %d) at %02x:%02x.%x, " | ||
797 | "irq: %d, latency: %d, memory: 0x%lx\n", | ||
798 | itv->dev->device, itv->card_rev, dev->bus->number, | ||
799 | PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn), | ||
800 | itv->dev->irq, pci_latency, (unsigned long)itv->base_addr); | ||
801 | |||
802 | return 0; | ||
803 | } | ||
804 | |||
805 | static void ivtv_request_module(struct ivtv *itv, const char *name) | ||
806 | { | ||
807 | if (request_module(name) != 0) { | ||
808 | IVTV_ERR("Failed to load module %s\n", name); | ||
809 | } else { | ||
810 | IVTV_DEBUG_INFO("Loaded module %s\n", name); | ||
811 | } | ||
812 | } | ||
813 | |||
814 | static void ivtv_load_and_init_modules(struct ivtv *itv) | ||
815 | { | ||
816 | struct v4l2_control ctrl; | ||
817 | u32 hw = itv->card->hw_all; | ||
818 | int i; | ||
819 | |||
820 | /* load modules */ | ||
821 | #ifndef CONFIG_VIDEO_TUNER | ||
822 | if (hw & IVTV_HW_TUNER) { | ||
823 | ivtv_request_module(itv, "tuner"); | ||
824 | #ifdef HAVE_XC3028 | ||
825 | if (itv->options.tuner == TUNER_XCEIVE_XC3028) | ||
826 | ivtv_request_module(itv, "xc3028-tuner"); | ||
827 | #endif | ||
828 | } | ||
829 | #endif | ||
830 | #ifndef CONFIG_VIDEO_CX25840 | ||
831 | if (hw & IVTV_HW_CX25840) | ||
832 | ivtv_request_module(itv, "cx25840"); | ||
833 | #endif | ||
834 | #ifndef CONFIG_VIDEO_SAA711X | ||
835 | if (hw & IVTV_HW_SAA711X) | ||
836 | ivtv_request_module(itv, "saa7115"); | ||
837 | #endif | ||
838 | #ifndef CONFIG_VIDEO_SAA7127 | ||
839 | if (hw & IVTV_HW_SAA7127) | ||
840 | ivtv_request_module(itv, "saa7127"); | ||
841 | #endif | ||
842 | if (hw & IVTV_HW_SAA717X) | ||
843 | ivtv_request_module(itv, "saa717x"); | ||
844 | #ifndef CONFIG_VIDEO_UPD64031A | ||
845 | if (hw & IVTV_HW_UPD64031A) | ||
846 | ivtv_request_module(itv, "upd64031a"); | ||
847 | #endif | ||
848 | #ifndef CONFIG_VIDEO_UPD64083 | ||
849 | if (hw & IVTV_HW_UPD6408X) | ||
850 | ivtv_request_module(itv, "upd64083"); | ||
851 | #endif | ||
852 | #ifndef CONFIG_VIDEO_MSP3400 | ||
853 | if (hw & IVTV_HW_MSP34XX) | ||
854 | ivtv_request_module(itv, "msp3400"); | ||
855 | #endif | ||
856 | if (hw & IVTV_HW_TVAUDIO) | ||
857 | ivtv_request_module(itv, "tvaudio"); | ||
858 | #ifndef CONFIG_VIDEO_WM8775 | ||
859 | if (hw & IVTV_HW_WM8775) | ||
860 | ivtv_request_module(itv, "wm8775"); | ||
861 | #endif | ||
862 | #ifndef CONFIG_VIDEO_WM8739 | ||
863 | if (hw & IVTV_HW_WM8739) | ||
864 | ivtv_request_module(itv, "wm8739"); | ||
865 | #endif | ||
866 | #ifndef CONFIG_VIDEO_CS53L32A | ||
867 | if (hw & IVTV_HW_CS53L32A) | ||
868 | ivtv_request_module(itv, "cs53l32a"); | ||
869 | #endif | ||
870 | |||
871 | /* check which i2c devices are actually found */ | ||
872 | for (i = 0; i < 32; i++) { | ||
873 | u32 device = 1 << i; | ||
874 | |||
875 | if (!(device & hw)) | ||
876 | continue; | ||
877 | if (device == IVTV_HW_GPIO) { | ||
878 | /* GPIO is always available */ | ||
879 | itv->hw_flags |= IVTV_HW_GPIO; | ||
880 | continue; | ||
881 | } | ||
882 | if (ivtv_i2c_hw_addr(itv, device) > 0) | ||
883 | itv->hw_flags |= device; | ||
884 | } | ||
885 | |||
886 | hw = itv->hw_flags; | ||
887 | |||
888 | if (itv->card->type == IVTV_CARD_CX23416GYC) { | ||
889 | /* Several variations of this card exist, detect which card | ||
890 | type should be used. */ | ||
891 | if ((hw & (IVTV_HW_UPD64031A | IVTV_HW_UPD6408X)) == 0) | ||
892 | itv->card = ivtv_get_card(IVTV_CARD_CX23416GYC_NOGRYCS); | ||
893 | else if ((hw & IVTV_HW_UPD64031A) == 0) | ||
894 | itv->card = ivtv_get_card(IVTV_CARD_CX23416GYC_NOGR); | ||
895 | } | ||
896 | |||
897 | if (hw & IVTV_HW_CX25840) { | ||
898 | /* CX25840_CID_ENABLE_PVR150_WORKAROUND */ | ||
899 | ctrl.id = V4L2_CID_PRIVATE_BASE; | ||
900 | ctrl.value = itv->pvr150_workaround; | ||
901 | itv->video_dec_func(itv, VIDIOC_S_CTRL, &ctrl); | ||
902 | |||
903 | itv->vbi.raw_decoder_line_size = 1444; | ||
904 | itv->vbi.raw_decoder_sav_odd_field = 0x20; | ||
905 | itv->vbi.raw_decoder_sav_even_field = 0x60; | ||
906 | itv->vbi.sliced_decoder_line_size = 272; | ||
907 | itv->vbi.sliced_decoder_sav_odd_field = 0xB0; | ||
908 | itv->vbi.sliced_decoder_sav_even_field = 0xF0; | ||
909 | } | ||
910 | |||
911 | if (hw & IVTV_HW_SAA711X) { | ||
912 | struct v4l2_chip_ident v = { V4L2_CHIP_MATCH_I2C_DRIVER, I2C_DRIVERID_SAA711X }; | ||
913 | |||
914 | /* determine the exact saa711x model */ | ||
915 | itv->hw_flags &= ~IVTV_HW_SAA711X; | ||
916 | |||
917 | ivtv_saa7115(itv, VIDIOC_G_CHIP_IDENT, &v); | ||
918 | if (v.ident == V4L2_IDENT_SAA7114) { | ||
919 | itv->hw_flags |= IVTV_HW_SAA7114; | ||
920 | /* VBI is not yet supported by the saa7114 driver. */ | ||
921 | itv->v4l2_cap &= ~(V4L2_CAP_SLICED_VBI_CAPTURE|V4L2_CAP_VBI_CAPTURE); | ||
922 | } | ||
923 | else { | ||
924 | itv->hw_flags |= IVTV_HW_SAA7115; | ||
925 | } | ||
926 | itv->vbi.raw_decoder_line_size = 1443; | ||
927 | itv->vbi.raw_decoder_sav_odd_field = 0x25; | ||
928 | itv->vbi.raw_decoder_sav_even_field = 0x62; | ||
929 | itv->vbi.sliced_decoder_line_size = 51; | ||
930 | itv->vbi.sliced_decoder_sav_odd_field = 0xAB; | ||
931 | itv->vbi.sliced_decoder_sav_even_field = 0xEC; | ||
932 | } | ||
933 | |||
934 | if (hw & IVTV_HW_SAA717X) { | ||
935 | itv->vbi.raw_decoder_line_size = 1443; | ||
936 | itv->vbi.raw_decoder_sav_odd_field = 0x25; | ||
937 | itv->vbi.raw_decoder_sav_even_field = 0x62; | ||
938 | itv->vbi.sliced_decoder_line_size = 51; | ||
939 | itv->vbi.sliced_decoder_sav_odd_field = 0xAB; | ||
940 | itv->vbi.sliced_decoder_sav_even_field = 0xEC; | ||
941 | } | ||
942 | } | ||
943 | |||
944 | static int __devinit ivtv_probe(struct pci_dev *dev, | ||
945 | const struct pci_device_id *pci_id) | ||
946 | { | ||
947 | int retval = 0; | ||
948 | int video_input; | ||
949 | int yuv_buf_size; | ||
950 | int vbi_buf_size; | ||
951 | int fw_retry_count = 3; | ||
952 | struct ivtv *itv; | ||
953 | struct v4l2_frequency vf; | ||
954 | |||
955 | spin_lock(&ivtv_cards_lock); | ||
956 | |||
957 | /* Make sure we've got a place for this card */ | ||
958 | if (ivtv_cards_active == IVTV_MAX_CARDS) { | ||
959 | printk(KERN_ERR "ivtv: Maximum number of cards detected (%d).\n", | ||
960 | ivtv_cards_active); | ||
961 | spin_unlock(&ivtv_cards_lock); | ||
962 | return -ENOMEM; | ||
963 | } | ||
964 | |||
965 | itv = kzalloc(sizeof(struct ivtv), GFP_ATOMIC); | ||
966 | if (itv == 0) { | ||
967 | spin_unlock(&ivtv_cards_lock); | ||
968 | return -ENOMEM; | ||
969 | } | ||
970 | ivtv_cards[ivtv_cards_active] = itv; | ||
971 | itv->dev = dev; | ||
972 | itv->num = ivtv_cards_active++; | ||
973 | snprintf(itv->name, sizeof(itv->name) - 1, "ivtv%d", itv->num); | ||
974 | if (itv->num) { | ||
975 | printk(KERN_INFO "ivtv: ====================== NEXT CARD ======================\n"); | ||
976 | } | ||
977 | |||
978 | spin_unlock(&ivtv_cards_lock); | ||
979 | |||
980 | ivtv_process_options(itv); | ||
981 | if (itv->options.cardtype == -1) { | ||
982 | retval = -ENODEV; | ||
983 | goto err; | ||
984 | } | ||
985 | if (ivtv_init_struct1(itv)) { | ||
986 | retval = -ENOMEM; | ||
987 | goto err; | ||
988 | } | ||
989 | |||
990 | IVTV_DEBUG_INFO("base addr: 0x%08x\n", itv->base_addr); | ||
991 | |||
992 | /* PCI Device Setup */ | ||
993 | if ((retval = ivtv_setup_pci(itv, dev, pci_id)) != 0) { | ||
994 | if (retval == -EIO) | ||
995 | goto free_workqueue; | ||
996 | else if (retval == -ENXIO) | ||
997 | goto free_mem; | ||
998 | } | ||
999 | /* save itv in the pci struct for later use */ | ||
1000 | pci_set_drvdata(dev, itv); | ||
1001 | |||
1002 | /* map io memory */ | ||
1003 | IVTV_DEBUG_INFO("attempting ioremap at 0x%08x len 0x%08x\n", | ||
1004 | itv->base_addr + IVTV_ENCODER_OFFSET, IVTV_ENCODER_SIZE); | ||
1005 | itv->enc_mem = ioremap_nocache(itv->base_addr + IVTV_ENCODER_OFFSET, | ||
1006 | IVTV_ENCODER_SIZE); | ||
1007 | if (!itv->enc_mem) { | ||
1008 | IVTV_ERR("ioremap failed, perhaps increasing __VMALLOC_RESERVE in page.h\n"); | ||
1009 | IVTV_ERR("or disabling CONFIG_HIMEM4G into the kernel would help\n"); | ||
1010 | retval = -ENOMEM; | ||
1011 | goto free_mem; | ||
1012 | } | ||
1013 | |||
1014 | if (itv->has_cx23415) { | ||
1015 | IVTV_DEBUG_INFO("attempting ioremap at 0x%08x len 0x%08x\n", | ||
1016 | itv->base_addr + IVTV_DECODER_OFFSET, IVTV_DECODER_SIZE); | ||
1017 | itv->dec_mem = ioremap_nocache(itv->base_addr + IVTV_DECODER_OFFSET, | ||
1018 | IVTV_DECODER_SIZE); | ||
1019 | if (!itv->dec_mem) { | ||
1020 | IVTV_ERR("ioremap failed, perhaps increasing __VMALLOC_RESERVE in page.h\n"); | ||
1021 | IVTV_ERR("or disabling CONFIG_HIMEM4G into the kernel would help\n"); | ||
1022 | retval = -ENOMEM; | ||
1023 | goto free_mem; | ||
1024 | } | ||
1025 | } | ||
1026 | else { | ||
1027 | itv->dec_mem = itv->enc_mem; | ||
1028 | } | ||
1029 | |||
1030 | /* map registers memory */ | ||
1031 | IVTV_DEBUG_INFO("attempting ioremap at 0x%08x len 0x%08x\n", | ||
1032 | itv->base_addr + IVTV_REG_OFFSET, IVTV_REG_SIZE); | ||
1033 | itv->reg_mem = | ||
1034 | ioremap_nocache(itv->base_addr + IVTV_REG_OFFSET, IVTV_REG_SIZE); | ||
1035 | if (!itv->reg_mem) { | ||
1036 | IVTV_ERR("ioremap failed, perhaps increasing __VMALLOC_RESERVE in page.h\n"); | ||
1037 | IVTV_ERR("or disabling CONFIG_HIMEM4G into the kernel would help\n"); | ||
1038 | retval = -ENOMEM; | ||
1039 | goto free_io; | ||
1040 | } | ||
1041 | |||
1042 | while (--fw_retry_count > 0) { | ||
1043 | /* load firmware */ | ||
1044 | if (ivtv_firmware_init(itv) == 0) | ||
1045 | break; | ||
1046 | if (fw_retry_count > 1) | ||
1047 | IVTV_WARN("Retry loading firmware\n"); | ||
1048 | } | ||
1049 | if (fw_retry_count == 0) { | ||
1050 | IVTV_ERR("Error initializing firmware\n"); | ||
1051 | goto free_i2c; | ||
1052 | } | ||
1053 | |||
1054 | /* Try and get firmware versions */ | ||
1055 | IVTV_DEBUG_INFO("Getting firmware version..\n"); | ||
1056 | ivtv_firmware_versions(itv); | ||
1057 | |||
1058 | /* Check yuv output filter table */ | ||
1059 | if (itv->has_cx23415) ivtv_yuv_filter_check(itv); | ||
1060 | |||
1061 | ivtv_gpio_init(itv); | ||
1062 | |||
1063 | /* active i2c */ | ||
1064 | IVTV_DEBUG_INFO("activating i2c...\n"); | ||
1065 | if (init_ivtv_i2c(itv)) { | ||
1066 | IVTV_ERR("Could not initialize i2c\n"); | ||
1067 | goto free_irq; | ||
1068 | } | ||
1069 | |||
1070 | IVTV_DEBUG_INFO("Active card count: %d.\n", ivtv_cards_active); | ||
1071 | |||
1072 | if (itv->card->hw_all & IVTV_HW_TVEEPROM) { | ||
1073 | #ifdef CONFIG_VIDEO_TVEEPROM_MODULE | ||
1074 | ivtv_request_module(itv, "tveeprom"); | ||
1075 | #endif | ||
1076 | /* Based on the model number the cardtype may be changed. | ||
1077 | The PCI IDs are not always reliable. */ | ||
1078 | ivtv_process_eeprom(itv); | ||
1079 | } | ||
1080 | |||
1081 | if (itv->std == 0) { | ||
1082 | itv->std = V4L2_STD_NTSC_M; | ||
1083 | } | ||
1084 | |||
1085 | if (itv->options.tuner == -1) { | ||
1086 | int i; | ||
1087 | |||
1088 | for (i = 0; i < IVTV_CARD_MAX_TUNERS; i++) { | ||
1089 | if ((itv->std & itv->card->tuners[i].std) == 0) | ||
1090 | continue; | ||
1091 | itv->options.tuner = itv->card->tuners[i].tuner; | ||
1092 | break; | ||
1093 | } | ||
1094 | } | ||
1095 | /* if no tuner was found, then pick the first tuner in the card list */ | ||
1096 | if (itv->options.tuner == -1 && itv->card->tuners[0].std) { | ||
1097 | itv->std = itv->card->tuners[0].std; | ||
1098 | itv->options.tuner = itv->card->tuners[0].tuner; | ||
1099 | } | ||
1100 | if (itv->options.radio == -1) | ||
1101 | itv->options.radio = (itv->card->radio_input.audio_type != 0); | ||
1102 | |||
1103 | /* The card is now fully identified, continue with card-specific | ||
1104 | initialization. */ | ||
1105 | ivtv_init_struct2(itv); | ||
1106 | |||
1107 | ivtv_load_and_init_modules(itv); | ||
1108 | |||
1109 | if (itv->std & V4L2_STD_525_60) { | ||
1110 | itv->is_60hz = 1; | ||
1111 | itv->is_out_60hz = 1; | ||
1112 | } else { | ||
1113 | itv->is_50hz = 1; | ||
1114 | itv->is_out_50hz = 1; | ||
1115 | } | ||
1116 | itv->params.video_gop_size = itv->is_60hz ? 15 : 12; | ||
1117 | |||
1118 | itv->stream_buf_size[IVTV_ENC_STREAM_TYPE_MPG] = 0x08000; | ||
1119 | itv->stream_buf_size[IVTV_ENC_STREAM_TYPE_PCM] = 0x01200; | ||
1120 | itv->stream_buf_size[IVTV_DEC_STREAM_TYPE_MPG] = 0x10000; | ||
1121 | |||
1122 | /* 0x15180 == 720 * 480 / 4, 0x19500 == 720 * 576 / 4 */ | ||
1123 | yuv_buf_size = itv->is_60hz ? 0x15180 : 0x19500; | ||
1124 | itv->stream_buf_size[IVTV_DEC_STREAM_TYPE_YUV] = yuv_buf_size / 2; | ||
1125 | itv->stream_buf_size[IVTV_ENC_STREAM_TYPE_YUV] = yuv_buf_size / 8; | ||
1126 | |||
1127 | /* Setup VBI Raw Size. Should be big enough to hold PAL. | ||
1128 | It is possible to switch between PAL and NTSC, so we need to | ||
1129 | take the largest size here. */ | ||
1130 | /* 1456 is multiple of 16, real size = 1444 */ | ||
1131 | itv->vbi.raw_size = 1456; | ||
1132 | /* We use a buffer size of 1/2 of the total size needed for a | ||
1133 | frame. This is actually very useful, since we now receive | ||
1134 | a field at a time and that makes 'compressing' the raw data | ||
1135 | down to size by stripping off the SAV codes a lot easier. | ||
1136 | Note: having two different buffer sizes prevents standard | ||
1137 | switching on the fly. We need to find a better solution... */ | ||
1138 | vbi_buf_size = itv->vbi.raw_size * (itv->is_60hz ? 24 : 36) / 2; | ||
1139 | itv->stream_buf_size[IVTV_ENC_STREAM_TYPE_VBI] = vbi_buf_size; | ||
1140 | itv->stream_buf_size[IVTV_DEC_STREAM_TYPE_VBI] = sizeof(struct v4l2_sliced_vbi_data) * 36; | ||
1141 | |||
1142 | if (itv->options.radio > 0) | ||
1143 | itv->v4l2_cap |= V4L2_CAP_RADIO; | ||
1144 | |||
1145 | retval = ivtv_streams_setup(itv); | ||
1146 | if (retval) { | ||
1147 | IVTV_ERR("Error %d setting up streams\n", retval); | ||
1148 | goto free_i2c; | ||
1149 | } | ||
1150 | |||
1151 | /* Start Threads */ | ||
1152 | IVTV_DEBUG_INFO("Starting Threads\n"); | ||
1153 | |||
1154 | /* Decoder Thread */ | ||
1155 | if (itv->card->v4l2_capabilities & V4L2_CAP_VIDEO_OUTPUT) { | ||
1156 | ivtv_init_mpeg_decoder(itv); | ||
1157 | } | ||
1158 | |||
1159 | IVTV_DEBUG_IRQ("Masking interrupts\n"); | ||
1160 | /* clear interrupt mask, effectively disabling interrupts */ | ||
1161 | ivtv_set_irq_mask(itv, 0xffffffff); | ||
1162 | |||
1163 | /* Register IRQ */ | ||
1164 | retval = request_irq(itv->dev->irq, ivtv_irq_handler, | ||
1165 | SA_SHIRQ | SA_INTERRUPT, itv->name, (void *)itv); | ||
1166 | if (retval) { | ||
1167 | IVTV_ERR("Failed to register irq %d\n", retval); | ||
1168 | goto free_streams; | ||
1169 | } | ||
1170 | |||
1171 | /* On a cx23416 this seems to be able to enable DMA to the chip? */ | ||
1172 | if (!itv->has_cx23415) | ||
1173 | write_reg_sync(0x03, IVTV_REG_DMACONTROL); | ||
1174 | |||
1175 | /* Default interrupts enabled. For the PVR350 this includes the | ||
1176 | decoder VSYNC interrupt, which is always on. It is not only used | ||
1177 | during decoding but also by the OSD. | ||
1178 | Some old PVR250 cards had a cx23415, so testing for that is too | ||
1179 | general. Instead test if the card has video output capability. */ | ||
1180 | if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) | ||
1181 | ivtv_clear_irq_mask(itv, IVTV_IRQ_MASK_INIT | IVTV_IRQ_DEC_VSYNC); | ||
1182 | else | ||
1183 | ivtv_clear_irq_mask(itv, IVTV_IRQ_MASK_INIT); | ||
1184 | |||
1185 | if (itv->options.tuner > -1) { | ||
1186 | struct tuner_setup setup; | ||
1187 | |||
1188 | setup.addr = ADDR_UNSET; | ||
1189 | setup.type = itv->options.tuner; | ||
1190 | setup.mode_mask = T_ANALOG_TV; /* matches TV tuners */ | ||
1191 | #ifdef HAVE_XC3028 | ||
1192 | setup.initmode = V4L2_TUNER_ANALOG_TV; | ||
1193 | if (itv->options.tuner == TUNER_XCEIVE_XC3028) { | ||
1194 | setup.gpio_write = ivtv_reset_tuner_gpio; | ||
1195 | setup.gpio_priv = itv; | ||
1196 | } | ||
1197 | #endif | ||
1198 | ivtv_call_i2c_clients(itv, TUNER_SET_TYPE_ADDR, &setup); | ||
1199 | } | ||
1200 | |||
1201 | vf.tuner = 0; | ||
1202 | vf.type = V4L2_TUNER_ANALOG_TV; | ||
1203 | vf.frequency = 6400; /* the tuner 'baseline' frequency */ | ||
1204 | if (itv->std & V4L2_STD_NTSC_M) { | ||
1205 | /* Why on earth? */ | ||
1206 | vf.frequency = 1076; /* ch. 4 67250*16/1000 */ | ||
1207 | } | ||
1208 | |||
1209 | /* The tuner is fixed to the standard. The other inputs (e.g. S-Video) | ||
1210 | are not. */ | ||
1211 | itv->tuner_std = itv->std; | ||
1212 | |||
1213 | video_input = itv->active_input; | ||
1214 | itv->active_input++; /* Force update of input */ | ||
1215 | ivtv_v4l2_ioctls(itv, NULL, VIDIOC_S_INPUT, &video_input); | ||
1216 | |||
1217 | /* Let the VIDIOC_S_STD ioctl do all the work, keeps the code | ||
1218 | in one place. */ | ||
1219 | itv->std++; /* Force full standard initialization */ | ||
1220 | itv->std_out = itv->std; | ||
1221 | ivtv_v4l2_ioctls(itv, NULL, VIDIOC_S_STD, &itv->tuner_std); | ||
1222 | ivtv_v4l2_ioctls(itv, NULL, VIDIOC_S_FREQUENCY, &vf); | ||
1223 | if (itv->has_cx23415) | ||
1224 | ivtv_set_osd_alpha(itv); | ||
1225 | |||
1226 | IVTV_INFO("Initialized %s, card #%d\n", itv->card_name, itv->num); | ||
1227 | |||
1228 | return 0; | ||
1229 | |||
1230 | free_irq: | ||
1231 | free_irq(itv->dev->irq, (void *)itv); | ||
1232 | free_streams: | ||
1233 | ivtv_streams_cleanup(itv); | ||
1234 | free_i2c: | ||
1235 | exit_ivtv_i2c(itv); | ||
1236 | free_io: | ||
1237 | ivtv_iounmap(itv); | ||
1238 | free_mem: | ||
1239 | release_mem_region(itv->base_addr, IVTV_ENCODER_SIZE); | ||
1240 | release_mem_region(itv->base_addr + IVTV_REG_OFFSET, IVTV_REG_SIZE); | ||
1241 | if (itv->has_cx23415) | ||
1242 | release_mem_region(itv->base_addr + IVTV_DECODER_OFFSET, IVTV_DECODER_SIZE); | ||
1243 | free_workqueue: | ||
1244 | destroy_workqueue(itv->vbi.work_queues); | ||
1245 | destroy_workqueue(itv->yuv_info.work_queues); | ||
1246 | err: | ||
1247 | if (retval == 0) | ||
1248 | retval = -ENODEV; | ||
1249 | IVTV_ERR("Error %d on initialization\n", retval); | ||
1250 | |||
1251 | kfree(ivtv_cards[ivtv_cards_active]); | ||
1252 | ivtv_cards[ivtv_cards_active] = NULL; | ||
1253 | return retval; | ||
1254 | } | ||
1255 | |||
1256 | static void ivtv_remove(struct pci_dev *pci_dev) | ||
1257 | { | ||
1258 | struct ivtv *itv = pci_get_drvdata(pci_dev); | ||
1259 | |||
1260 | IVTV_DEBUG_INFO("Removing Card #%d.\n", itv->num); | ||
1261 | |||
1262 | /* Stop all captures */ | ||
1263 | IVTV_DEBUG_INFO(" Stopping all streams.\n"); | ||
1264 | if (atomic_read(&itv->capturing) > 0) | ||
1265 | ivtv_stop_all_captures(itv); | ||
1266 | |||
1267 | /* Stop all decoding */ | ||
1268 | IVTV_DEBUG_INFO(" Stopping decoding.\n"); | ||
1269 | if (atomic_read(&itv->decoding) > 0) { | ||
1270 | int type; | ||
1271 | |||
1272 | if (test_bit(IVTV_F_I_DEC_YUV, &itv->i_flags)) | ||
1273 | type = IVTV_DEC_STREAM_TYPE_YUV; | ||
1274 | else | ||
1275 | type = IVTV_DEC_STREAM_TYPE_MPG; | ||
1276 | ivtv_stop_v4l2_decode_stream(&itv->streams[type], | ||
1277 | VIDEO_CMD_STOP_TO_BLACK | VIDEO_CMD_STOP_IMMEDIATELY, 0); | ||
1278 | } | ||
1279 | |||
1280 | /* Interrupts */ | ||
1281 | IVTV_DEBUG_INFO(" Disabling interrupts.\n"); | ||
1282 | ivtv_set_irq_mask(itv, 0xffffffff); | ||
1283 | del_timer_sync(&itv->dma_timer); | ||
1284 | |||
1285 | /* Stop all Work Queues */ | ||
1286 | IVTV_DEBUG_INFO(" Stop Work Queues.\n"); | ||
1287 | flush_workqueue(itv->vbi.work_queues); | ||
1288 | flush_workqueue(itv->yuv_info.work_queues); | ||
1289 | destroy_workqueue(itv->vbi.work_queues); | ||
1290 | destroy_workqueue(itv->yuv_info.work_queues); | ||
1291 | |||
1292 | IVTV_DEBUG_INFO(" Stopping Firmware.\n"); | ||
1293 | ivtv_halt_firmware(itv); | ||
1294 | |||
1295 | IVTV_DEBUG_INFO(" Unregistering v4l devices.\n"); | ||
1296 | ivtv_streams_cleanup(itv); | ||
1297 | IVTV_DEBUG_INFO(" Freeing dma resources.\n"); | ||
1298 | ivtv_udma_free(itv); | ||
1299 | |||
1300 | exit_ivtv_i2c(itv); | ||
1301 | |||
1302 | IVTV_DEBUG_INFO(" Releasing irq.\n"); | ||
1303 | free_irq(itv->dev->irq, (void *)itv); | ||
1304 | |||
1305 | if (itv->dev) { | ||
1306 | ivtv_iounmap(itv); | ||
1307 | } | ||
1308 | |||
1309 | IVTV_DEBUG_INFO(" Releasing mem.\n"); | ||
1310 | release_mem_region(itv->base_addr, IVTV_ENCODER_SIZE); | ||
1311 | release_mem_region(itv->base_addr + IVTV_REG_OFFSET, IVTV_REG_SIZE); | ||
1312 | if (itv->has_cx23415) | ||
1313 | release_mem_region(itv->base_addr + IVTV_DECODER_OFFSET, IVTV_DECODER_SIZE); | ||
1314 | |||
1315 | pci_disable_device(itv->dev); | ||
1316 | |||
1317 | IVTV_INFO("Removed %s, card #%d\n", itv->card_name, itv->num); | ||
1318 | } | ||
1319 | |||
1320 | /* define a pci_driver for card detection */ | ||
1321 | static struct pci_driver ivtv_pci_driver = { | ||
1322 | .name = "ivtv", | ||
1323 | .id_table = ivtv_pci_tbl, | ||
1324 | .probe = ivtv_probe, | ||
1325 | .remove = ivtv_remove, | ||
1326 | }; | ||
1327 | |||
1328 | static int module_start(void) | ||
1329 | { | ||
1330 | printk(KERN_INFO "ivtv: ==================== START INIT IVTV ====================\n"); | ||
1331 | printk(KERN_INFO "ivtv: version %s (" VERMAGIC_STRING ") loading\n", IVTV_VERSION); | ||
1332 | |||
1333 | memset(ivtv_cards, 0, sizeof(ivtv_cards)); | ||
1334 | |||
1335 | /* Validate parameters */ | ||
1336 | if (ivtv_first_minor < 0 || ivtv_first_minor >= IVTV_MAX_CARDS) { | ||
1337 | printk(KERN_ERR "ivtv: ivtv_first_minor must be between 0 and %d. Exiting...\n", | ||
1338 | IVTV_MAX_CARDS - 1); | ||
1339 | return -1; | ||
1340 | } | ||
1341 | |||
1342 | if (ivtv_debug < 0 || ivtv_debug > 511) { | ||
1343 | ivtv_debug = 0; | ||
1344 | printk(KERN_INFO "ivtv: debug value must be >= 0 and <= 511!\n"); | ||
1345 | } | ||
1346 | |||
1347 | if (pci_module_init(&ivtv_pci_driver)) { | ||
1348 | printk(KERN_ERR "ivtv: Error detecting PCI card\n"); | ||
1349 | return -ENODEV; | ||
1350 | } | ||
1351 | printk(KERN_INFO "ivtv: ==================== END INIT IVTV ====================\n"); | ||
1352 | return 0; | ||
1353 | } | ||
1354 | |||
1355 | static void module_cleanup(void) | ||
1356 | { | ||
1357 | int i, j; | ||
1358 | |||
1359 | for (i = 0; i < ivtv_cards_active; i++) { | ||
1360 | if (ivtv_cards[i] == NULL) | ||
1361 | continue; | ||
1362 | for (j = 0; j < IVTV_VBI_FRAMES; j++) { | ||
1363 | kfree(ivtv_cards[i]->vbi.sliced_mpeg_data[j]); | ||
1364 | } | ||
1365 | kfree(ivtv_cards[i]); | ||
1366 | } | ||
1367 | pci_unregister_driver(&ivtv_pci_driver); | ||
1368 | } | ||
1369 | |||
1370 | EXPORT_SYMBOL(ivtv_set_irq_mask); | ||
1371 | EXPORT_SYMBOL(ivtv_cards_active); | ||
1372 | EXPORT_SYMBOL(ivtv_cards); | ||
1373 | EXPORT_SYMBOL(ivtv_api); | ||
1374 | EXPORT_SYMBOL(ivtv_vapi); | ||
1375 | EXPORT_SYMBOL(ivtv_vapi_result); | ||
1376 | EXPORT_SYMBOL(ivtv_clear_irq_mask); | ||
1377 | EXPORT_SYMBOL(ivtv_debug); | ||
1378 | EXPORT_SYMBOL(ivtv_reset_ir_gpio); | ||
1379 | EXPORT_SYMBOL(ivtv_udma_setup); | ||
1380 | EXPORT_SYMBOL(ivtv_udma_unmap); | ||
1381 | EXPORT_SYMBOL(ivtv_udma_alloc); | ||
1382 | EXPORT_SYMBOL(ivtv_udma_prepare); | ||
1383 | |||
1384 | module_init(module_start); | ||
1385 | module_exit(module_cleanup); | ||
diff --git a/drivers/media/video/ivtv/ivtv-driver.h b/drivers/media/video/ivtv/ivtv-driver.h new file mode 100644 index 000000000000..546d7bbfcf5b --- /dev/null +++ b/drivers/media/video/ivtv/ivtv-driver.h | |||
@@ -0,0 +1,866 @@ | |||
1 | /* | ||
2 | ivtv driver internal defines and structures | ||
3 | Copyright (C) 2003-2004 Kevin Thayer <nufan_wfk at yahoo.com> | ||
4 | Copyright (C) 2004 Chris Kennedy <c@groovy.org> | ||
5 | Copyright (C) 2005-2007 Hans Verkuil <hverkuil@xs4all.nl> | ||
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 02111-1307 USA | ||
20 | */ | ||
21 | |||
22 | #ifndef IVTV_DRIVER_H | ||
23 | #define IVTV_DRIVER_H | ||
24 | |||
25 | /* Internal header for ivtv project: | ||
26 | * Driver for the cx23415/6 chip. | ||
27 | * Author: Kevin Thayer (nufan_wfk at yahoo.com) | ||
28 | * License: GPL | ||
29 | * http://www.ivtvdriver.org | ||
30 | * | ||
31 | * ----- | ||
32 | * MPG600/MPG160 support by T.Adachi <tadachi@tadachi-net.com> | ||
33 | * and Takeru KOMORIYA<komoriya@paken.org> | ||
34 | * | ||
35 | * AVerMedia M179 GPIO info by Chris Pinkham <cpinkham@bc2va.org> | ||
36 | * using information provided by Jiun-Kuei Jung @ AVerMedia. | ||
37 | */ | ||
38 | |||
39 | #include <linux/version.h> | ||
40 | #include <linux/module.h> | ||
41 | #include <linux/moduleparam.h> | ||
42 | #include <linux/init.h> | ||
43 | #include <linux/delay.h> | ||
44 | #include <linux/sched.h> | ||
45 | #include <linux/fs.h> | ||
46 | #include <linux/pci.h> | ||
47 | #include <linux/interrupt.h> | ||
48 | #include <linux/spinlock.h> | ||
49 | #include <linux/i2c.h> | ||
50 | #include <linux/i2c-algo-bit.h> | ||
51 | #include <linux/list.h> | ||
52 | #include <linux/unistd.h> | ||
53 | #include <linux/byteorder/swab.h> | ||
54 | #include <linux/pagemap.h> | ||
55 | #include <linux/workqueue.h> | ||
56 | #include <linux/mutex.h> | ||
57 | #include <asm/uaccess.h> | ||
58 | #include <asm/system.h> | ||
59 | |||
60 | #include <linux/dvb/video.h> | ||
61 | #include <linux/dvb/audio.h> | ||
62 | #include <media/v4l2-common.h> | ||
63 | #include <media/tuner.h> | ||
64 | #include <media/cx2341x.h> | ||
65 | |||
66 | /* #define HAVE_XC3028 1 */ | ||
67 | |||
68 | #include <media/ivtv.h> | ||
69 | |||
70 | #ifdef CONFIG_LIRC_I2C | ||
71 | # error "This driver is not compatible with the LIRC I2C kernel configuration option." | ||
72 | #endif /* CONFIG_LIRC_I2C */ | ||
73 | |||
74 | #ifndef CONFIG_PCI | ||
75 | # error "This driver requires kernel PCI support." | ||
76 | #endif /* CONFIG_PCI */ | ||
77 | |||
78 | #define IVTV_ENCODER_OFFSET 0x00000000 | ||
79 | #define IVTV_ENCODER_SIZE 0x00800000 /* Last half isn't needed 0x01000000 */ | ||
80 | |||
81 | #define IVTV_DECODER_OFFSET 0x01000000 | ||
82 | #define IVTV_DECODER_SIZE 0x00800000 /* Last half isn't needed 0x01000000 */ | ||
83 | |||
84 | #define IVTV_REG_OFFSET 0x02000000 | ||
85 | #define IVTV_REG_SIZE 0x00010000 | ||
86 | |||
87 | /* Buffers on hardware offsets */ | ||
88 | #define IVTV_YUV_BUFFER_OFFSET 0x001a8600 /* First YUV Buffer */ | ||
89 | #define IVTV_YUV_BUFFER_OFFSET_1 0x00240400 /* Second YUV Buffer */ | ||
90 | #define IVTV_YUV_BUFFER_OFFSET_2 0x002d8200 /* Third YUV Buffer */ | ||
91 | #define IVTV_YUV_BUFFER_OFFSET_3 0x00370000 /* Fourth YUV Buffer */ | ||
92 | #define IVTV_YUV_BUFFER_UV_OFFSET 0x65400 /* Offset to UV Buffer */ | ||
93 | |||
94 | /* Offset to filter table in firmware */ | ||
95 | #define IVTV_YUV_HORIZONTAL_FILTER_OFFSET 0x025d8 | ||
96 | #define IVTV_YUV_VERTICAL_FILTER_OFFSET 0x03358 | ||
97 | |||
98 | extern const u32 yuv_offset[4]; | ||
99 | |||
100 | /* Maximum ivtv driver instances. | ||
101 | Based on 6 PVR500s each with two PVR15s... | ||
102 | TODO: make this dynamic. I believe it is only a global in order to support | ||
103 | ivtv-fb. There must be a better way to do that. */ | ||
104 | #define IVTV_MAX_CARDS 12 | ||
105 | |||
106 | /* Supported cards */ | ||
107 | #define IVTV_CARD_PVR_250 0 /* WinTV PVR 250 */ | ||
108 | #define IVTV_CARD_PVR_350 1 /* encoder, decoder, tv-out */ | ||
109 | #define IVTV_CARD_PVR_150 2 /* WinTV PVR 150 and PVR 500 (really just two | ||
110 | PVR150s on one PCI board) */ | ||
111 | #define IVTV_CARD_M179 3 /* AVerMedia M179 (encoder only) */ | ||
112 | #define IVTV_CARD_MPG600 4 /* Kuroutoshikou ITVC16-STVLP/YUAN MPG600, encoder only */ | ||
113 | #define IVTV_CARD_MPG160 5 /* Kuroutoshikou ITVC15-STVLP/YUAN MPG160 | ||
114 | cx23415 based, but does not have tv-out */ | ||
115 | #define IVTV_CARD_PG600 6 /* YUAN PG600/DIAMONDMM PVR-550 based on the CX Falcon 2 */ | ||
116 | #define IVTV_CARD_AVC2410 7 /* Adaptec AVC-2410 */ | ||
117 | #define IVTV_CARD_AVC2010 8 /* Adaptec AVD-2010 (No Tuner) */ | ||
118 | #define IVTV_CARD_TG5000TV 9 /* NAGASE TRANSGEAR 5000TV, encoder only */ | ||
119 | #define IVTV_CARD_VA2000MAX_SNT6 10 /* VA2000MAX-STN6 */ | ||
120 | #define IVTV_CARD_CX23416GYC 11 /* Kuroutoshikou CX23416GYC-STVLP (Yuan MPG600GR OEM) */ | ||
121 | #define IVTV_CARD_GV_MVPRX 12 /* I/O Data GV-MVP/RX, RX2, RX2W */ | ||
122 | #define IVTV_CARD_GV_MVPRX2E 13 /* I/O Data GV-MVP/RX2E */ | ||
123 | #define IVTV_CARD_GOTVIEW_PCI_DVD 14 /* GotView PCI DVD */ | ||
124 | #define IVTV_CARD_GOTVIEW_PCI_DVD2 15 /* GotView PCI DVD2 */ | ||
125 | #define IVTV_CARD_YUAN_MPC622 16 /* Yuan MPC622 miniPCI */ | ||
126 | #define IVTV_CARD_DCTMTVP1 17 /* DIGITAL COWBOY DCT-MTVP1 */ | ||
127 | #ifdef HAVE_XC3028 | ||
128 | #define IVTV_CARD_PG600V2 18 /* Yuan PG600V2/GotView PCI DVD Lite/Club3D ZAP-TV1x01 */ | ||
129 | #define IVTV_CARD_LAST 18 | ||
130 | #else | ||
131 | #define IVTV_CARD_LAST 17 | ||
132 | #endif | ||
133 | |||
134 | /* Variants of existing cards but with the same PCI IDs. The driver | ||
135 | detects these based on other device information. | ||
136 | These cards must always come last. | ||
137 | New cards must be inserted above, and the indices of the cards below | ||
138 | must be adjusted accordingly. */ | ||
139 | |||
140 | /* PVR-350 V1 (uses saa7114) */ | ||
141 | #define IVTV_CARD_PVR_350_V1 (IVTV_CARD_LAST+1) | ||
142 | /* 2 variants of Kuroutoshikou CX23416GYC-STVLP (Yuan MPG600GR OEM) */ | ||
143 | #define IVTV_CARD_CX23416GYC_NOGR (IVTV_CARD_LAST+2) | ||
144 | #define IVTV_CARD_CX23416GYC_NOGRYCS (IVTV_CARD_LAST+3) | ||
145 | |||
146 | #define IVTV_ENC_STREAM_TYPE_MPG 0 | ||
147 | #define IVTV_ENC_STREAM_TYPE_YUV 1 | ||
148 | #define IVTV_ENC_STREAM_TYPE_VBI 2 | ||
149 | #define IVTV_ENC_STREAM_TYPE_PCM 3 | ||
150 | #define IVTV_ENC_STREAM_TYPE_RAD 4 | ||
151 | #define IVTV_DEC_STREAM_TYPE_MPG 5 | ||
152 | #define IVTV_DEC_STREAM_TYPE_VBI 6 | ||
153 | #define IVTV_DEC_STREAM_TYPE_VOUT 7 | ||
154 | #define IVTV_DEC_STREAM_TYPE_YUV 8 | ||
155 | #define IVTV_MAX_STREAMS 9 | ||
156 | |||
157 | #define IVTV_V4L2_DEC_MPG_OFFSET 16 /* offset from 0 to register decoder mpg v4l2 minors on */ | ||
158 | #define IVTV_V4L2_ENC_PCM_OFFSET 24 /* offset from 0 to register pcm v4l2 minors on */ | ||
159 | #define IVTV_V4L2_ENC_YUV_OFFSET 32 /* offset from 0 to register yuv v4l2 minors on */ | ||
160 | #define IVTV_V4L2_DEC_YUV_OFFSET 48 /* offset from 0 to register decoder yuv v4l2 minors on */ | ||
161 | #define IVTV_V4L2_DEC_VBI_OFFSET 8 /* offset from 0 to register decoder vbi input v4l2 minors on */ | ||
162 | #define IVTV_V4L2_DEC_VOUT_OFFSET 16 /* offset from 0 to register vbi output v4l2 minors on */ | ||
163 | |||
164 | #define IVTV_ENC_MEM_START 0x00000000 | ||
165 | #define IVTV_DEC_MEM_START 0x01000000 | ||
166 | |||
167 | /* system vendor and device IDs */ | ||
168 | #define PCI_VENDOR_ID_ICOMP 0x4444 | ||
169 | #define PCI_DEVICE_ID_IVTV15 0x0803 | ||
170 | #define PCI_DEVICE_ID_IVTV16 0x0016 | ||
171 | |||
172 | /* subsystem vendor ID */ | ||
173 | #define IVTV_PCI_ID_HAUPPAUGE 0x0070 | ||
174 | #define IVTV_PCI_ID_HAUPPAUGE_ALT1 0x0270 | ||
175 | #define IVTV_PCI_ID_HAUPPAUGE_ALT2 0x4070 | ||
176 | #define IVTV_PCI_ID_ADAPTEC 0x9005 | ||
177 | #define IVTV_PCI_ID_AVERMEDIA 0x1461 | ||
178 | #define IVTV_PCI_ID_YUAN1 0x12ab | ||
179 | #define IVTV_PCI_ID_YUAN2 0xff01 | ||
180 | #define IVTV_PCI_ID_YUAN3 0xffab | ||
181 | #define IVTV_PCI_ID_YUAN4 0xfbab | ||
182 | #define IVTV_PCI_ID_DIAMONDMM 0xff92 | ||
183 | #define IVTV_PCI_ID_IODATA 0x10fc | ||
184 | #define IVTV_PCI_ID_MELCO 0x1154 | ||
185 | #define IVTV_PCI_ID_GOTVIEW1 0xffac | ||
186 | #define IVTV_PCI_ID_GOTVIEW2 0xffad | ||
187 | |||
188 | /* Decoder Buffer hardware size on Chip */ | ||
189 | #define IVTV_DEC_MAX_BUF 0x00100000 /* max bytes in decoder buffer */ | ||
190 | #define IVTV_DEC_MIN_BUF 0x00010000 /* min bytes in dec buffer */ | ||
191 | |||
192 | /* ======================================================================== */ | ||
193 | /* ========================== START USER SETTABLE DMA VARIABLES =========== */ | ||
194 | /* ======================================================================== */ | ||
195 | |||
196 | #define IVTV_DMA_SG_OSD_ENT (2883584/PAGE_SIZE) /* sg entities */ | ||
197 | |||
198 | /* DMA Buffers, Default size in MB allocated */ | ||
199 | #define IVTV_DEFAULT_ENC_MPG_BUFFERS 4 | ||
200 | #define IVTV_DEFAULT_ENC_YUV_BUFFERS 2 | ||
201 | #define IVTV_DEFAULT_ENC_VBI_BUFFERS 1 | ||
202 | #define IVTV_DEFAULT_ENC_PCM_BUFFERS 1 | ||
203 | #define IVTV_DEFAULT_DEC_MPG_BUFFERS 1 | ||
204 | #define IVTV_DEFAULT_DEC_YUV_BUFFERS 1 | ||
205 | #define IVTV_DEFAULT_DEC_VBI_BUFFERS 1 | ||
206 | |||
207 | /* ======================================================================== */ | ||
208 | /* ========================== END USER SETTABLE DMA VARIABLES ============= */ | ||
209 | /* ======================================================================== */ | ||
210 | |||
211 | /* Decoder Status Register */ | ||
212 | #define IVTV_DMA_ERR_LIST 0x00000010 | ||
213 | #define IVTV_DMA_ERR_WRITE 0x00000008 | ||
214 | #define IVTV_DMA_ERR_READ 0x00000004 | ||
215 | #define IVTV_DMA_SUCCESS_WRITE 0x00000002 | ||
216 | #define IVTV_DMA_SUCCESS_READ 0x00000001 | ||
217 | #define IVTV_DMA_READ_ERR (IVTV_DMA_ERR_LIST | IVTV_DMA_ERR_READ) | ||
218 | #define IVTV_DMA_WRITE_ERR (IVTV_DMA_ERR_LIST | IVTV_DMA_ERR_WRITE) | ||
219 | #define IVTV_DMA_ERR (IVTV_DMA_ERR_LIST | IVTV_DMA_ERR_WRITE | IVTV_DMA_ERR_READ) | ||
220 | |||
221 | /* DMA Registers */ | ||
222 | #define IVTV_REG_DMAXFER (0x0000) | ||
223 | #define IVTV_REG_DMASTATUS (0x0004) | ||
224 | #define IVTV_REG_DECDMAADDR (0x0008) | ||
225 | #define IVTV_REG_ENCDMAADDR (0x000c) | ||
226 | #define IVTV_REG_DMACONTROL (0x0010) | ||
227 | #define IVTV_REG_IRQSTATUS (0x0040) | ||
228 | #define IVTV_REG_IRQMASK (0x0048) | ||
229 | |||
230 | /* Setup Registers */ | ||
231 | #define IVTV_REG_ENC_SDRAM_REFRESH (0x07F8) | ||
232 | #define IVTV_REG_ENC_SDRAM_PRECHARGE (0x07FC) | ||
233 | #define IVTV_REG_DEC_SDRAM_REFRESH (0x08F8) | ||
234 | #define IVTV_REG_DEC_SDRAM_PRECHARGE (0x08FC) | ||
235 | #define IVTV_REG_VDM (0x2800) | ||
236 | #define IVTV_REG_AO (0x2D00) | ||
237 | #define IVTV_REG_BYTEFLUSH (0x2D24) | ||
238 | #define IVTV_REG_SPU (0x9050) | ||
239 | #define IVTV_REG_HW_BLOCKS (0x9054) | ||
240 | #define IVTV_REG_VPU (0x9058) | ||
241 | #define IVTV_REG_APU (0xA064) | ||
242 | |||
243 | #define IVTV_IRQ_ENC_START_CAP (0x1 << 31) | ||
244 | #define IVTV_IRQ_ENC_EOS (0x1 << 30) | ||
245 | #define IVTV_IRQ_ENC_VBI_CAP (0x1 << 29) | ||
246 | #define IVTV_IRQ_ENC_VIM_RST (0x1 << 28) | ||
247 | #define IVTV_IRQ_ENC_DMA_COMPLETE (0x1 << 27) | ||
248 | #define IVTV_IRQ_DEC_AUD_MODE_CHG (0x1 << 24) | ||
249 | #define IVTV_IRQ_DEC_DATA_REQ (0x1 << 22) | ||
250 | #define IVTV_IRQ_DEC_DMA_COMPLETE (0x1 << 20) | ||
251 | #define IVTV_IRQ_DEC_VBI_RE_INSERT (0x1 << 19) | ||
252 | #define IVTV_IRQ_DMA_ERR (0x1 << 18) | ||
253 | #define IVTV_IRQ_DMA_WRITE (0x1 << 17) | ||
254 | #define IVTV_IRQ_DMA_READ (0x1 << 16) | ||
255 | #define IVTV_IRQ_DEC_VSYNC (0x1 << 10) | ||
256 | |||
257 | /* IRQ Masks */ | ||
258 | #define IVTV_IRQ_MASK_INIT (IVTV_IRQ_DMA_ERR|IVTV_IRQ_ENC_DMA_COMPLETE|IVTV_IRQ_DMA_READ) | ||
259 | |||
260 | #define IVTV_IRQ_MASK_CAPTURE (IVTV_IRQ_ENC_START_CAP | IVTV_IRQ_ENC_EOS) | ||
261 | #define IVTV_IRQ_MASK_DECODE (IVTV_IRQ_DEC_DATA_REQ|IVTV_IRQ_DEC_AUD_MODE_CHG) | ||
262 | |||
263 | /* i2c stuff */ | ||
264 | #define I2C_CLIENTS_MAX 16 | ||
265 | |||
266 | /* debugging */ | ||
267 | |||
268 | #define IVTV_DBGFLG_WARN (1 << 0) | ||
269 | #define IVTV_DBGFLG_INFO (1 << 1) | ||
270 | #define IVTV_DBGFLG_API (1 << 2) | ||
271 | #define IVTV_DBGFLG_DMA (1 << 3) | ||
272 | #define IVTV_DBGFLG_IOCTL (1 << 4) | ||
273 | #define IVTV_DBGFLG_I2C (1 << 5) | ||
274 | #define IVTV_DBGFLG_IRQ (1 << 6) | ||
275 | #define IVTV_DBGFLG_DEC (1 << 7) | ||
276 | #define IVTV_DBGFLG_YUV (1 << 8) | ||
277 | |||
278 | /* NOTE: extra space before comma in 'itv->num , ## args' is required for | ||
279 | gcc-2.95, otherwise it won't compile. */ | ||
280 | #define IVTV_DEBUG(x, type, fmt, args...) \ | ||
281 | do { \ | ||
282 | if ((x) & ivtv_debug) \ | ||
283 | printk(KERN_INFO "ivtv%d " type ": " fmt, itv->num , ## args); \ | ||
284 | } while (0) | ||
285 | #define IVTV_DEBUG_WARN(fmt, args...) IVTV_DEBUG(IVTV_DBGFLG_WARN, "warning", fmt , ## args) | ||
286 | #define IVTV_DEBUG_INFO(fmt, args...) IVTV_DEBUG(IVTV_DBGFLG_INFO, "info",fmt , ## args) | ||
287 | #define IVTV_DEBUG_API(fmt, args...) IVTV_DEBUG(IVTV_DBGFLG_API, "api", fmt , ## args) | ||
288 | #define IVTV_DEBUG_DMA(fmt, args...) IVTV_DEBUG(IVTV_DBGFLG_DMA, "dma", fmt , ## args) | ||
289 | #define IVTV_DEBUG_IOCTL(fmt, args...) IVTV_DEBUG(IVTV_DBGFLG_IOCTL, "ioctl", fmt , ## args) | ||
290 | #define IVTV_DEBUG_I2C(fmt, args...) IVTV_DEBUG(IVTV_DBGFLG_I2C, "i2c", fmt , ## args) | ||
291 | #define IVTV_DEBUG_IRQ(fmt, args...) IVTV_DEBUG(IVTV_DBGFLG_IRQ, "irq", fmt , ## args) | ||
292 | #define IVTV_DEBUG_DEC(fmt, args...) IVTV_DEBUG(IVTV_DBGFLG_DEC, "dec", fmt , ## args) | ||
293 | #define IVTV_DEBUG_YUV(fmt, args...) IVTV_DEBUG(IVTV_DBGFLG_YUV, "yuv", fmt , ## args) | ||
294 | |||
295 | #define IVTV_FB_DEBUG(x, type, fmt, args...) \ | ||
296 | do { \ | ||
297 | if ((x) & ivtv_debug) \ | ||
298 | printk(KERN_INFO "ivtv%d-fb " type ": " fmt, itv->num , ## args); \ | ||
299 | } while (0) | ||
300 | #define IVTV_FB_DEBUG_WARN(fmt, args...) IVTV_FB_DEBUG(IVTV_DBGFLG_WARN, "warning", fmt , ## args) | ||
301 | #define IVTV_FB_DEBUG_INFO(fmt, args...) IVTV_FB_DEBUG(IVTV_DBGFLG_INFO, "info", fmt , ## args) | ||
302 | #define IVTV_FB_DEBUG_API(fmt, args...) IVTV_FB_DEBUG(IVTV_DBGFLG_API, "api", fmt , ## args) | ||
303 | #define IVTV_FB_DEBUG_DMA(fmt, args...) IVTV_FB_DEBUG(IVTV_DBGFLG_DMA, "dma", fmt , ## args) | ||
304 | #define IVTV_FB_DEBUG_IOCTL(fmt, args...) IVTV_FB_DEBUG(IVTV_DBGFLG_IOCTL, "ioctl", fmt , ## args) | ||
305 | #define IVTV_FB_DEBUG_I2C(fmt, args...) IVTV_FB_DEBUG(IVTV_DBGFLG_I2C, "i2c", fmt , ## args) | ||
306 | #define IVTV_FB_DEBUG_IRQ(fmt, args...) IVTV_FB_DEBUG(IVTV_DBGFLG_IRQ, "irq", fmt , ## args) | ||
307 | #define IVTV_FB_DEBUG_DEC(fmt, args...) IVTV_FB_DEBUG(IVTV_DBGFLG_DEC, "dec", fmt , ## args) | ||
308 | #define IVTV_FB_DEBUG_YUV(fmt, args...) IVTV_FB_DEBUG(IVTV_DBGFLG_YUV, "yuv", fmt , ## args) | ||
309 | |||
310 | /* Standard kernel messages */ | ||
311 | #define IVTV_ERR(fmt, args...) printk(KERN_ERR "ivtv%d: " fmt, itv->num , ## args) | ||
312 | #define IVTV_WARN(fmt, args...) printk(KERN_WARNING "ivtv%d: " fmt, itv->num , ## args) | ||
313 | #define IVTV_INFO(fmt, args...) printk(KERN_INFO "ivtv%d: " fmt, itv->num , ## args) | ||
314 | #define IVTV_FB_ERR(fmt, args...) printk(KERN_ERR "ivtv%d-fb: " fmt, itv->num , ## args) | ||
315 | #define IVTV_FB_INFO(fmt, args...) printk(KERN_INFO "ivtv%d-fb: " fmt, itv->num , ## args) | ||
316 | |||
317 | /* Values for IVTV_API_DEC_PLAYBACK_SPEED mpeg_frame_type_mask parameter: */ | ||
318 | #define MPEG_FRAME_TYPE_IFRAME 1 | ||
319 | #define MPEG_FRAME_TYPE_IFRAME_PFRAME 3 | ||
320 | #define MPEG_FRAME_TYPE_ALL 7 | ||
321 | |||
322 | /* output modes (cx23415 only) */ | ||
323 | #define OUT_NONE 0 | ||
324 | #define OUT_MPG 1 | ||
325 | #define OUT_YUV 2 | ||
326 | #define OUT_UDMA_YUV 3 | ||
327 | #define OUT_PASSTHROUGH 4 | ||
328 | |||
329 | #define IVTV_MAX_PGM_INDEX (400) | ||
330 | |||
331 | extern int ivtv_debug; | ||
332 | |||
333 | |||
334 | struct ivtv_options { | ||
335 | int megabytes[IVTV_MAX_STREAMS]; /* Size in megabytes of each stream */ | ||
336 | int cardtype; /* force card type on load */ | ||
337 | int tuner; /* set tuner on load */ | ||
338 | int radio; /* enable/disable radio */ | ||
339 | int newi2c; /* New I2C algorithm */ | ||
340 | }; | ||
341 | |||
342 | #define IVTV_MBOX_DMA_START 6 | ||
343 | #define IVTV_MBOX_DMA_END 8 | ||
344 | #define IVTV_MBOX_DMA 9 | ||
345 | #define IVTV_MBOX_FIELD_DISPLAYED 8 | ||
346 | |||
347 | /* ivtv-specific mailbox template */ | ||
348 | struct ivtv_mailbox { | ||
349 | u32 flags; | ||
350 | u32 cmd; | ||
351 | u32 retval; | ||
352 | u32 timeout; | ||
353 | u32 data[CX2341X_MBOX_MAX_DATA]; | ||
354 | }; | ||
355 | |||
356 | struct ivtv_api_cache { | ||
357 | unsigned long last_jiffies; /* when last command was issued */ | ||
358 | u32 data[CX2341X_MBOX_MAX_DATA]; /* last sent api data */ | ||
359 | }; | ||
360 | |||
361 | struct ivtv_mailbox_data { | ||
362 | volatile struct ivtv_mailbox __iomem *mbox; | ||
363 | /* Bits 0-2 are for the encoder mailboxes, 0-1 are for the decoder mailboxes. | ||
364 | If the bit is set, then the corresponding mailbox is in use by the driver. */ | ||
365 | unsigned long busy; | ||
366 | u8 max_mbox; | ||
367 | }; | ||
368 | |||
369 | /* per-buffer bit flags */ | ||
370 | #define IVTV_F_B_NEED_BUF_SWAP 0 /* this buffer should be byte swapped */ | ||
371 | |||
372 | /* per-stream, s_flags */ | ||
373 | #define IVTV_F_S_DMA_PENDING 0 /* this stream has pending DMA */ | ||
374 | #define IVTV_F_S_DMA_HAS_VBI 1 /* the current DMA request also requests VBI data */ | ||
375 | #define IVTV_F_S_NEEDS_DATA 2 /* this decoding stream needs more data */ | ||
376 | |||
377 | #define IVTV_F_S_CLAIMED 3 /* this stream is claimed */ | ||
378 | #define IVTV_F_S_STREAMING 4 /* the fw is decoding/encoding this stream */ | ||
379 | #define IVTV_F_S_INTERNAL_USE 5 /* this stream is used internally (sliced VBI processing) */ | ||
380 | #define IVTV_F_S_PASSTHROUGH 6 /* this stream is in passthrough mode */ | ||
381 | #define IVTV_F_S_STREAMOFF 7 /* signal end of stream EOS */ | ||
382 | #define IVTV_F_S_APPL_IO 8 /* this stream is used read/written by an application */ | ||
383 | |||
384 | /* per-ivtv, i_flags */ | ||
385 | #define IVTV_F_I_DMA 0 /* DMA in progress */ | ||
386 | #define IVTV_F_I_UDMA 1 /* UDMA in progress */ | ||
387 | #define IVTV_F_I_UDMA_PENDING 2 /* UDMA pending */ | ||
388 | |||
389 | #define IVTV_F_I_SPEED_CHANGE 3 /* A speed change is in progress */ | ||
390 | #define IVTV_F_I_EOS 4 /* End of encoder stream reached */ | ||
391 | #define IVTV_F_I_RADIO_USER 5 /* The radio tuner is selected */ | ||
392 | #define IVTV_F_I_DIG_RST 6 /* Reset digitizer */ | ||
393 | #define IVTV_F_I_DEC_YUV 7 /* YUV instead of MPG is being decoded */ | ||
394 | #define IVTV_F_I_ENC_VBI 8 /* VBI DMA */ | ||
395 | #define IVTV_F_I_UPDATE_CC 9 /* CC should be updated */ | ||
396 | #define IVTV_F_I_UPDATE_WSS 10 /* WSS should be updated */ | ||
397 | #define IVTV_F_I_UPDATE_VPS 11 /* VPS should be updated */ | ||
398 | #define IVTV_F_I_DECODING_YUV 12 /* this stream is YUV frame decoding */ | ||
399 | #define IVTV_F_I_ENC_PAUSED 13 /* the encoder is paused */ | ||
400 | #define IVTV_F_I_VALID_DEC_TIMINGS 14 /* last_dec_timing is valid */ | ||
401 | |||
402 | /* Event notifications */ | ||
403 | #define IVTV_F_I_EV_DEC_STOPPED 28 /* decoder stopped event */ | ||
404 | #define IVTV_F_I_EV_VSYNC 29 /* VSYNC event */ | ||
405 | #define IVTV_F_I_EV_VSYNC_FIELD 30 /* VSYNC event field (0 = first, 1 = second field) */ | ||
406 | #define IVTV_F_I_EV_VSYNC_ENABLED 31 /* VSYNC event enabled */ | ||
407 | |||
408 | /* Scatter-Gather array element, used in DMA transfers */ | ||
409 | struct ivtv_SG_element { | ||
410 | u32 src; | ||
411 | u32 dst; | ||
412 | u32 size; | ||
413 | }; | ||
414 | |||
415 | struct ivtv_user_dma { | ||
416 | struct mutex lock; | ||
417 | int page_count; | ||
418 | struct page *map[IVTV_DMA_SG_OSD_ENT]; | ||
419 | |||
420 | /* Base Dev SG Array for cx23415/6 */ | ||
421 | struct ivtv_SG_element SGarray[IVTV_DMA_SG_OSD_ENT]; | ||
422 | dma_addr_t SG_handle; | ||
423 | int SG_length; | ||
424 | |||
425 | /* SG List of Buffers */ | ||
426 | struct scatterlist SGlist[IVTV_DMA_SG_OSD_ENT]; | ||
427 | }; | ||
428 | |||
429 | struct ivtv_dma_page_info { | ||
430 | unsigned long uaddr; | ||
431 | unsigned long first; | ||
432 | unsigned long last; | ||
433 | unsigned int offset; | ||
434 | unsigned int tail; | ||
435 | int page_count; | ||
436 | }; | ||
437 | |||
438 | struct ivtv_buffer { | ||
439 | struct list_head list; | ||
440 | dma_addr_t dma_handle; | ||
441 | unsigned long b_flags; | ||
442 | char *buf; | ||
443 | |||
444 | u32 bytesused; | ||
445 | u32 readpos; | ||
446 | }; | ||
447 | |||
448 | struct ivtv_queue { | ||
449 | struct list_head list; | ||
450 | u32 buffers; | ||
451 | u32 length; | ||
452 | u32 bytesused; | ||
453 | }; | ||
454 | |||
455 | struct ivtv; /* forward reference */ | ||
456 | |||
457 | struct ivtv_stream { | ||
458 | /* These first four fields are always set, even if the stream | ||
459 | is not actually created. */ | ||
460 | struct video_device *v4l2dev; /* NULL when stream not created */ | ||
461 | struct ivtv *itv; /* for ease of use */ | ||
462 | const char *name; /* name of the stream */ | ||
463 | int type; /* stream type */ | ||
464 | |||
465 | u32 id; | ||
466 | spinlock_t qlock; /* locks access to the queues */ | ||
467 | unsigned long s_flags; /* status flags, see above */ | ||
468 | int dma; /* can be PCI_DMA_TODEVICE, | ||
469 | PCI_DMA_FROMDEVICE or | ||
470 | PCI_DMA_NONE */ | ||
471 | u32 dma_offset; | ||
472 | u32 dma_backup; | ||
473 | u64 dma_pts; | ||
474 | |||
475 | int subtype; | ||
476 | wait_queue_head_t waitq; | ||
477 | u32 dma_last_offset; | ||
478 | |||
479 | /* Buffer Stats */ | ||
480 | u32 buffers; | ||
481 | u32 buf_size; | ||
482 | u32 buffers_stolen; | ||
483 | |||
484 | /* Buffer Queues */ | ||
485 | struct ivtv_queue q_free; /* free buffers */ | ||
486 | struct ivtv_queue q_full; /* full buffers */ | ||
487 | struct ivtv_queue q_io; /* waiting for I/O */ | ||
488 | struct ivtv_queue q_dma; /* waiting for DMA */ | ||
489 | struct ivtv_queue q_predma; /* waiting for DMA */ | ||
490 | |||
491 | /* Base Dev SG Array for cx23415/6 */ | ||
492 | struct ivtv_SG_element *SGarray; | ||
493 | dma_addr_t SG_handle; | ||
494 | int SG_length; | ||
495 | |||
496 | /* SG List of Buffers */ | ||
497 | struct scatterlist *SGlist; | ||
498 | }; | ||
499 | |||
500 | struct ivtv_open_id { | ||
501 | u32 open_id; | ||
502 | int type; | ||
503 | struct ivtv *itv; | ||
504 | }; | ||
505 | |||
506 | #define IVTV_YUV_UPDATE_HORIZONTAL 0x01 | ||
507 | #define IVTV_YUV_UPDATE_VERTICAL 0x02 | ||
508 | |||
509 | struct yuv_frame_info | ||
510 | { | ||
511 | u32 update; | ||
512 | int src_x; | ||
513 | int src_y; | ||
514 | unsigned int src_w; | ||
515 | unsigned int src_h; | ||
516 | int dst_x; | ||
517 | int dst_y; | ||
518 | unsigned int dst_w; | ||
519 | unsigned int dst_h; | ||
520 | int pan_x; | ||
521 | int pan_y; | ||
522 | u32 vis_w; | ||
523 | u32 vis_h; | ||
524 | u32 interlaced_y; | ||
525 | u32 interlaced_uv; | ||
526 | int tru_x; | ||
527 | u32 tru_w; | ||
528 | u32 tru_h; | ||
529 | u32 offset_y; | ||
530 | }; | ||
531 | |||
532 | #define IVTV_YUV_MODE_INTERLACED 0x00 | ||
533 | #define IVTV_YUV_MODE_PROGRESSIVE 0x01 | ||
534 | #define IVTV_YUV_MODE_AUTO 0x02 | ||
535 | #define IVTV_YUV_MODE_MASK 0x03 | ||
536 | |||
537 | #define IVTV_YUV_SYNC_EVEN 0x00 | ||
538 | #define IVTV_YUV_SYNC_ODD 0x04 | ||
539 | #define IVTV_YUV_SYNC_MASK 0x04 | ||
540 | |||
541 | struct yuv_playback_info | ||
542 | { | ||
543 | u32 reg_2834; | ||
544 | u32 reg_2838; | ||
545 | u32 reg_283c; | ||
546 | u32 reg_2840; | ||
547 | u32 reg_2844; | ||
548 | u32 reg_2848; | ||
549 | u32 reg_2854; | ||
550 | u32 reg_285c; | ||
551 | u32 reg_2864; | ||
552 | |||
553 | u32 reg_2870; | ||
554 | u32 reg_2874; | ||
555 | u32 reg_2890; | ||
556 | u32 reg_2898; | ||
557 | u32 reg_289c; | ||
558 | |||
559 | u32 reg_2918; | ||
560 | u32 reg_291c; | ||
561 | u32 reg_2920; | ||
562 | u32 reg_2924; | ||
563 | u32 reg_2928; | ||
564 | u32 reg_292c; | ||
565 | u32 reg_2930; | ||
566 | |||
567 | u32 reg_2934; | ||
568 | |||
569 | u32 reg_2938; | ||
570 | u32 reg_293c; | ||
571 | u32 reg_2940; | ||
572 | u32 reg_2944; | ||
573 | u32 reg_2948; | ||
574 | u32 reg_294c; | ||
575 | u32 reg_2950; | ||
576 | u32 reg_2954; | ||
577 | u32 reg_2958; | ||
578 | u32 reg_295c; | ||
579 | u32 reg_2960; | ||
580 | u32 reg_2964; | ||
581 | u32 reg_2968; | ||
582 | u32 reg_296c; | ||
583 | |||
584 | u32 reg_2970; | ||
585 | |||
586 | int v_filter_1; | ||
587 | int v_filter_2; | ||
588 | int h_filter; | ||
589 | |||
590 | u32 osd_x_offset; | ||
591 | u32 osd_y_offset; | ||
592 | |||
593 | u32 osd_x_pan; | ||
594 | u32 osd_y_pan; | ||
595 | |||
596 | u32 osd_vis_w; | ||
597 | u32 osd_vis_h; | ||
598 | |||
599 | int decode_height; | ||
600 | |||
601 | int frame_interlaced; | ||
602 | int frame_interlaced_last; | ||
603 | |||
604 | int lace_mode; | ||
605 | int lace_threshold; | ||
606 | int lace_threshold_last; | ||
607 | int lace_sync_field; | ||
608 | |||
609 | atomic_t next_dma_frame; | ||
610 | atomic_t next_fill_frame; | ||
611 | |||
612 | u32 yuv_forced_update; | ||
613 | int update_frame; | ||
614 | struct workqueue_struct *work_queues; | ||
615 | struct work_struct work_queue; | ||
616 | struct yuv_frame_info new_frame_info[4]; | ||
617 | struct yuv_frame_info old_frame_info; | ||
618 | struct yuv_frame_info old_frame_info_args; | ||
619 | |||
620 | void *blanking_ptr; | ||
621 | dma_addr_t blanking_dmaptr; | ||
622 | }; | ||
623 | |||
624 | #define IVTV_VBI_FRAMES 32 | ||
625 | |||
626 | /* VBI data */ | ||
627 | struct vbi_info { | ||
628 | u32 dec_start; | ||
629 | u32 enc_start, enc_size; | ||
630 | int fpi; | ||
631 | u32 frame; | ||
632 | u32 dma_offset; | ||
633 | u8 cc_data_odd[256]; | ||
634 | u8 cc_data_even[256]; | ||
635 | int cc_pos; | ||
636 | u8 cc_no_update; | ||
637 | u8 vps[5]; | ||
638 | u8 vps_found; | ||
639 | int wss; | ||
640 | u8 wss_found; | ||
641 | u8 wss_no_update; | ||
642 | u32 raw_decoder_line_size; | ||
643 | u8 raw_decoder_sav_odd_field; | ||
644 | u8 raw_decoder_sav_even_field; | ||
645 | u32 sliced_decoder_line_size; | ||
646 | u8 sliced_decoder_sav_odd_field; | ||
647 | u8 sliced_decoder_sav_even_field; | ||
648 | struct v4l2_format in; | ||
649 | /* convenience pointer to sliced struct in vbi_in union */ | ||
650 | struct v4l2_sliced_vbi_format *sliced_in; | ||
651 | u32 service_set_in; | ||
652 | u32 service_set_out; | ||
653 | int insert_mpeg; | ||
654 | |||
655 | /* Buffer for the maximum of 2 * 18 * packet_size sliced VBI lines. | ||
656 | One for /dev/vbi0 and one for /dev/vbi8 */ | ||
657 | struct v4l2_sliced_vbi_data sliced_data[36]; | ||
658 | struct v4l2_sliced_vbi_data sliced_dec_data[36]; | ||
659 | |||
660 | /* Buffer for VBI data inserted into MPEG stream. | ||
661 | The first byte is a dummy byte that's never used. | ||
662 | The next 16 bytes contain the MPEG header for the VBI data, | ||
663 | the remainder is the actual VBI data. | ||
664 | The max size accepted by the MPEG VBI reinsertion turns out | ||
665 | to be 1552 bytes, which happens to be 4 + (1 + 42) * (2 * 18) bytes, | ||
666 | where 4 is a four byte header, 42 is the max sliced VBI payload, 1 is | ||
667 | a single line header byte and 2 * 18 is the number of VBI lines per frame. | ||
668 | |||
669 | However, it seems that the data must be 1K aligned, so we have to | ||
670 | pad the data until the 1 or 2 K boundary. | ||
671 | |||
672 | This pointer array will allocate 2049 bytes to store each VBI frame. */ | ||
673 | u8 *sliced_mpeg_data[IVTV_VBI_FRAMES]; | ||
674 | u32 sliced_mpeg_size[IVTV_VBI_FRAMES]; | ||
675 | struct ivtv_buffer sliced_mpeg_buf; | ||
676 | u32 inserted_frame; | ||
677 | |||
678 | struct workqueue_struct *work_queues; | ||
679 | struct work_struct work_queue; | ||
680 | u32 start[2], count; | ||
681 | u32 raw_size; | ||
682 | u32 sliced_size; | ||
683 | }; | ||
684 | |||
685 | /* forward declaration of struct defined in ivtv-cards.h */ | ||
686 | struct ivtv_card; | ||
687 | |||
688 | /* Struct to hold info about ivtv cards */ | ||
689 | struct ivtv { | ||
690 | int num; /* board number, -1 during init! */ | ||
691 | char name[8]; /* board name for printk and interrupts (e.g. 'ivtv0') */ | ||
692 | struct pci_dev *dev; /* PCI device */ | ||
693 | const struct ivtv_card *card; /* card information */ | ||
694 | const char *card_name; /* full name of the card */ | ||
695 | u8 has_cx23415; /* 1 if it is a cx23415 based card, 0 for cx23416 */ | ||
696 | u8 is_50hz; | ||
697 | u8 is_60hz; | ||
698 | u8 is_out_50hz; | ||
699 | u8 is_out_60hz; | ||
700 | u8 pvr150_workaround; /* 1 if the cx25840 needs to workaround a PVR150 bug */ | ||
701 | u8 nof_inputs; /* number of video inputs */ | ||
702 | u8 nof_audio_inputs; /* number of audio inputs */ | ||
703 | u32 v4l2_cap; /* V4L2 capabilities of card */ | ||
704 | u32 hw_flags; /* Hardware description of the board */ | ||
705 | |||
706 | /* controlling Video decoder function */ | ||
707 | int (*video_dec_func)(struct ivtv *, unsigned int, void *); | ||
708 | |||
709 | struct ivtv_options options; /* User options */ | ||
710 | int stream_buf_size[IVTV_MAX_STREAMS]; /* Stream buffer size */ | ||
711 | struct ivtv_stream streams[IVTV_MAX_STREAMS]; /* Stream data */ | ||
712 | int speed; | ||
713 | u8 speed_mute_audio; | ||
714 | unsigned long i_flags; /* global ivtv flags */ | ||
715 | atomic_t capturing; /* count number of active capture streams */ | ||
716 | atomic_t decoding; /* count number of active decoding streams */ | ||
717 | u32 irq_rr_idx; /* Round-robin stream index */ | ||
718 | int cur_dma_stream; /* index of stream doing DMA */ | ||
719 | u32 dma_data_req_offset; | ||
720 | u32 dma_data_req_size; | ||
721 | int output_mode; /* NONE, MPG, YUV, UDMA YUV, passthrough */ | ||
722 | spinlock_t lock; /* lock access to this struct */ | ||
723 | int search_pack_header; | ||
724 | |||
725 | spinlock_t dma_reg_lock; /* lock access to DMA engine registers */ | ||
726 | |||
727 | /* User based DMA for OSD */ | ||
728 | struct ivtv_user_dma udma; | ||
729 | |||
730 | int open_id; /* incremented each time an open occurs, used as unique ID. | ||
731 | starts at 1, so 0 can be used as uninitialized value | ||
732 | in the stream->id. */ | ||
733 | |||
734 | u32 base_addr; | ||
735 | u32 irqmask; | ||
736 | struct timer_list dma_timer; /* Timer used to catch unfinished DMAs */ | ||
737 | |||
738 | struct vbi_info vbi; | ||
739 | |||
740 | struct ivtv_mailbox_data enc_mbox; | ||
741 | struct ivtv_mailbox_data dec_mbox; | ||
742 | struct ivtv_api_cache api_cache[256]; /* Cached API Commands */ | ||
743 | |||
744 | u8 card_rev; | ||
745 | volatile void __iomem *enc_mem, *dec_mem, *reg_mem; | ||
746 | |||
747 | u32 pgm_info_offset; | ||
748 | u32 pgm_info_num; | ||
749 | u32 pgm_info_write_idx; | ||
750 | u32 pgm_info_read_idx; | ||
751 | struct v4l2_enc_idx_entry pgm_info[IVTV_MAX_PGM_INDEX]; | ||
752 | |||
753 | u64 mpg_data_received; | ||
754 | u64 vbi_data_inserted; | ||
755 | |||
756 | wait_queue_head_t cap_w; | ||
757 | /* when the next decoder event arrives this queue is woken up */ | ||
758 | wait_queue_head_t event_waitq; | ||
759 | /* when the next decoder vsync arrives this queue is woken up */ | ||
760 | wait_queue_head_t vsync_waitq; | ||
761 | /* when the current DMA is finished this queue is woken up */ | ||
762 | wait_queue_head_t dma_waitq; | ||
763 | |||
764 | /* OSD support */ | ||
765 | unsigned long osd_video_pbase; | ||
766 | int osd_global_alpha_state; /* 0=off : 1=on */ | ||
767 | int osd_local_alpha_state; /* 0=off : 1=on */ | ||
768 | int osd_color_key_state; /* 0=off : 1=on */ | ||
769 | u8 osd_global_alpha; /* Current global alpha */ | ||
770 | u32 osd_color_key; /* Current color key */ | ||
771 | u32 osd_pixelformat; /* Current pixel format */ | ||
772 | struct v4l2_rect osd_rect; /* Current OSD position and size */ | ||
773 | struct v4l2_rect main_rect; /* Current Main window position and size */ | ||
774 | |||
775 | u32 last_dec_timing[3]; /* Store last retrieved pts/scr/frame values */ | ||
776 | |||
777 | /* i2c */ | ||
778 | struct i2c_adapter i2c_adap; | ||
779 | struct i2c_algo_bit_data i2c_algo; | ||
780 | struct i2c_client i2c_client; | ||
781 | struct mutex i2c_bus_lock; | ||
782 | int i2c_state; | ||
783 | struct i2c_client *i2c_clients[I2C_CLIENTS_MAX]; | ||
784 | |||
785 | /* v4l2 and User settings */ | ||
786 | |||
787 | /* codec settings */ | ||
788 | struct cx2341x_mpeg_params params; | ||
789 | u32 audio_input; | ||
790 | u32 active_input; | ||
791 | u32 active_output; | ||
792 | v4l2_std_id std; | ||
793 | v4l2_std_id std_out; | ||
794 | v4l2_std_id tuner_std; /* The norm of the tuner (fixed) */ | ||
795 | u8 audio_stereo_mode; | ||
796 | u8 audio_bilingual_mode; | ||
797 | |||
798 | /* dualwatch */ | ||
799 | unsigned long dualwatch_jiffies; | ||
800 | u16 dualwatch_stereo_mode; | ||
801 | |||
802 | /* Digitizer type */ | ||
803 | int digitizer; /* 0x00EF = saa7114 0x00FO = saa7115 0x0106 = mic */ | ||
804 | |||
805 | u32 lastVsyncFrame; | ||
806 | |||
807 | struct yuv_playback_info yuv_info; | ||
808 | struct osd_info *osd_info; | ||
809 | }; | ||
810 | |||
811 | /* Globals */ | ||
812 | extern struct ivtv *ivtv_cards[]; | ||
813 | extern int ivtv_cards_active; | ||
814 | extern int ivtv_first_minor; | ||
815 | extern spinlock_t ivtv_cards_lock; | ||
816 | |||
817 | /*==============Prototypes==================*/ | ||
818 | |||
819 | /* Hardware/IRQ */ | ||
820 | void ivtv_set_irq_mask(struct ivtv *itv, u32 mask); | ||
821 | void ivtv_clear_irq_mask(struct ivtv *itv, u32 mask); | ||
822 | |||
823 | /* try to set output mode, return current mode. */ | ||
824 | int ivtv_set_output_mode(struct ivtv *itv, int mode); | ||
825 | |||
826 | /* return current output stream based on current mode */ | ||
827 | struct ivtv_stream *ivtv_get_output_stream(struct ivtv *itv); | ||
828 | |||
829 | /* Return non-zero if a signal is pending */ | ||
830 | int ivtv_sleep_timeout(int timeout, int intr); | ||
831 | |||
832 | /* Wait on queue, returns -EINTR if interrupted */ | ||
833 | int ivtv_waitq(wait_queue_head_t *waitq); | ||
834 | |||
835 | /* Read Hauppauge eeprom */ | ||
836 | struct tveeprom; /* forward reference */ | ||
837 | void ivtv_read_eeprom(struct ivtv *itv, struct tveeprom *tv); | ||
838 | |||
839 | /* This is a PCI post thing, where if the pci register is not read, then | ||
840 | the write doesn't always take effect right away. By reading back the | ||
841 | register any pending PCI writes will be performed (in order), and so | ||
842 | you can be sure that the writes are guaranteed to be done. | ||
843 | |||
844 | Rarely needed, only in some timing sensitive cases. | ||
845 | Apparently if this is not done some motherboards seem | ||
846 | to kill the firmware and get into the broken state until computer is | ||
847 | rebooted. */ | ||
848 | #define write_sync(val, reg) \ | ||
849 | do { writel(val, reg); readl(reg); } while (0) | ||
850 | |||
851 | #define read_reg(reg) readl(itv->reg_mem + (reg)) | ||
852 | #define write_reg(val, reg) writel(val, itv->reg_mem + (reg)) | ||
853 | #define write_reg_sync(val, reg) \ | ||
854 | do { write_reg(val, reg); read_reg(reg); } while (0) | ||
855 | |||
856 | #define read_enc(addr) readl(itv->enc_mem + (u32)(addr)) | ||
857 | #define write_enc(val, addr) writel(val, itv->enc_mem + (u32)(addr)) | ||
858 | #define write_enc_sync(val, addr) \ | ||
859 | do { write_enc(val, addr); read_enc(addr); } while (0) | ||
860 | |||
861 | #define read_dec(addr) readl(itv->dec_mem + (u32)(addr)) | ||
862 | #define write_dec(val, addr) writel(val, itv->dec_mem + (u32)(addr)) | ||
863 | #define write_dec_sync(val, addr) \ | ||
864 | do { write_dec(val, addr); read_dec(addr); } while (0) | ||
865 | |||
866 | #endif /* IVTV_DRIVER_H */ | ||
diff --git a/drivers/media/video/ivtv/ivtv-fileops.c b/drivers/media/video/ivtv/ivtv-fileops.c new file mode 100644 index 000000000000..90e0f51e635c --- /dev/null +++ b/drivers/media/video/ivtv/ivtv-fileops.c | |||
@@ -0,0 +1,918 @@ | |||
1 | /* | ||
2 | file operation functions | ||
3 | Copyright (C) 2003-2004 Kevin Thayer <nufan_wfk at yahoo.com> | ||
4 | Copyright (C) 2004 Chris Kennedy <c@groovy.org> | ||
5 | Copyright (C) 2005-2007 Hans Verkuil <hverkuil@xs4all.nl> | ||
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 02111-1307 USA | ||
20 | */ | ||
21 | |||
22 | #include "ivtv-driver.h" | ||
23 | #include "ivtv-fileops.h" | ||
24 | #include "ivtv-i2c.h" | ||
25 | #include "ivtv-queue.h" | ||
26 | #include "ivtv-udma.h" | ||
27 | #include "ivtv-irq.h" | ||
28 | #include "ivtv-vbi.h" | ||
29 | #include "ivtv-mailbox.h" | ||
30 | #include "ivtv-audio.h" | ||
31 | #include "ivtv-streams.h" | ||
32 | #include "ivtv-yuv.h" | ||
33 | #include "ivtv-controls.h" | ||
34 | #include "ivtv-ioctl.h" | ||
35 | |||
36 | /* This function tries to claim the stream for a specific file descriptor. | ||
37 | If no one else is using this stream then the stream is claimed and | ||
38 | associated VBI streams are also automatically claimed. | ||
39 | Possible error returns: -EBUSY if someone else has claimed | ||
40 | the stream or 0 on success. */ | ||
41 | int ivtv_claim_stream(struct ivtv_open_id *id, int type) | ||
42 | { | ||
43 | struct ivtv *itv = id->itv; | ||
44 | struct ivtv_stream *s = &itv->streams[type]; | ||
45 | struct ivtv_stream *s_vbi; | ||
46 | int vbi_type; | ||
47 | |||
48 | if (test_and_set_bit(IVTV_F_S_CLAIMED, &s->s_flags)) { | ||
49 | /* someone already claimed this stream */ | ||
50 | if (s->id == id->open_id) { | ||
51 | /* yes, this file descriptor did. So that's OK. */ | ||
52 | return 0; | ||
53 | } | ||
54 | if (s->id == -1 && (type == IVTV_DEC_STREAM_TYPE_VBI || | ||
55 | type == IVTV_ENC_STREAM_TYPE_VBI)) { | ||
56 | /* VBI is handled already internally, now also assign | ||
57 | the file descriptor to this stream for external | ||
58 | reading of the stream. */ | ||
59 | s->id = id->open_id; | ||
60 | IVTV_DEBUG_INFO("Start Read VBI\n"); | ||
61 | return 0; | ||
62 | } | ||
63 | /* someone else is using this stream already */ | ||
64 | IVTV_DEBUG_INFO("Stream %d is busy\n", type); | ||
65 | return -EBUSY; | ||
66 | } | ||
67 | s->id = id->open_id; | ||
68 | if (type == IVTV_DEC_STREAM_TYPE_VBI) { | ||
69 | /* Enable reinsertion interrupt */ | ||
70 | ivtv_clear_irq_mask(itv, IVTV_IRQ_DEC_VBI_RE_INSERT); | ||
71 | } | ||
72 | |||
73 | /* IVTV_DEC_STREAM_TYPE_MPG needs to claim IVTV_DEC_STREAM_TYPE_VBI, | ||
74 | IVTV_ENC_STREAM_TYPE_MPG needs to claim IVTV_ENC_STREAM_TYPE_VBI | ||
75 | (provided VBI insertion is on and sliced VBI is selected), for all | ||
76 | other streams we're done */ | ||
77 | if (type == IVTV_DEC_STREAM_TYPE_MPG) { | ||
78 | vbi_type = IVTV_DEC_STREAM_TYPE_VBI; | ||
79 | } else if (type == IVTV_ENC_STREAM_TYPE_MPG && | ||
80 | itv->vbi.insert_mpeg && itv->vbi.sliced_in->service_set) { | ||
81 | vbi_type = IVTV_ENC_STREAM_TYPE_VBI; | ||
82 | } else { | ||
83 | return 0; | ||
84 | } | ||
85 | s_vbi = &itv->streams[vbi_type]; | ||
86 | |||
87 | if (!test_and_set_bit(IVTV_F_S_CLAIMED, &s_vbi->s_flags)) { | ||
88 | /* Enable reinsertion interrupt */ | ||
89 | if (vbi_type == IVTV_DEC_STREAM_TYPE_VBI) | ||
90 | ivtv_clear_irq_mask(itv, IVTV_IRQ_DEC_VBI_RE_INSERT); | ||
91 | } | ||
92 | /* mark that it is used internally */ | ||
93 | set_bit(IVTV_F_S_INTERNAL_USE, &s_vbi->s_flags); | ||
94 | return 0; | ||
95 | } | ||
96 | |||
97 | /* This function releases a previously claimed stream. It will take into | ||
98 | account associated VBI streams. */ | ||
99 | void ivtv_release_stream(struct ivtv_stream *s) | ||
100 | { | ||
101 | struct ivtv *itv = s->itv; | ||
102 | struct ivtv_stream *s_vbi; | ||
103 | |||
104 | s->id = -1; | ||
105 | if ((s->type == IVTV_DEC_STREAM_TYPE_VBI || s->type == IVTV_ENC_STREAM_TYPE_VBI) && | ||
106 | test_bit(IVTV_F_S_INTERNAL_USE, &s->s_flags)) { | ||
107 | /* this stream is still in use internally */ | ||
108 | return; | ||
109 | } | ||
110 | if (!test_and_clear_bit(IVTV_F_S_CLAIMED, &s->s_flags)) { | ||
111 | IVTV_DEBUG_WARN("Release stream %s not in use!\n", s->name); | ||
112 | return; | ||
113 | } | ||
114 | |||
115 | ivtv_flush_queues(s); | ||
116 | |||
117 | /* disable reinsertion interrupt */ | ||
118 | if (s->type == IVTV_DEC_STREAM_TYPE_VBI) | ||
119 | ivtv_set_irq_mask(itv, IVTV_IRQ_DEC_VBI_RE_INSERT); | ||
120 | |||
121 | /* IVTV_DEC_STREAM_TYPE_MPG needs to release IVTV_DEC_STREAM_TYPE_VBI, | ||
122 | IVTV_ENC_STREAM_TYPE_MPG needs to release IVTV_ENC_STREAM_TYPE_VBI, | ||
123 | for all other streams we're done */ | ||
124 | if (s->type == IVTV_DEC_STREAM_TYPE_MPG) | ||
125 | s_vbi = &itv->streams[IVTV_DEC_STREAM_TYPE_VBI]; | ||
126 | else if (s->type == IVTV_ENC_STREAM_TYPE_MPG) | ||
127 | s_vbi = &itv->streams[IVTV_ENC_STREAM_TYPE_VBI]; | ||
128 | else | ||
129 | return; | ||
130 | |||
131 | /* clear internal use flag */ | ||
132 | if (!test_and_clear_bit(IVTV_F_S_INTERNAL_USE, &s_vbi->s_flags)) { | ||
133 | /* was already cleared */ | ||
134 | return; | ||
135 | } | ||
136 | if (s_vbi->id != -1) { | ||
137 | /* VBI stream still claimed by a file descriptor */ | ||
138 | return; | ||
139 | } | ||
140 | /* disable reinsertion interrupt */ | ||
141 | if (s_vbi->type == IVTV_DEC_STREAM_TYPE_VBI) | ||
142 | ivtv_set_irq_mask(itv, IVTV_IRQ_DEC_VBI_RE_INSERT); | ||
143 | clear_bit(IVTV_F_S_CLAIMED, &s_vbi->s_flags); | ||
144 | ivtv_flush_queues(s_vbi); | ||
145 | } | ||
146 | |||
147 | static void ivtv_dualwatch(struct ivtv *itv) | ||
148 | { | ||
149 | struct v4l2_tuner vt; | ||
150 | u16 new_bitmap; | ||
151 | u16 new_stereo_mode; | ||
152 | const u16 stereo_mask = 0x0300; | ||
153 | const u16 dual = 0x0200; | ||
154 | |||
155 | new_stereo_mode = itv->params.audio_properties & stereo_mask; | ||
156 | memset(&vt, 0, sizeof(vt)); | ||
157 | ivtv_call_i2c_clients(itv, VIDIOC_G_TUNER, &vt); | ||
158 | if (vt.audmode == V4L2_TUNER_MODE_LANG1_LANG2 && (vt.rxsubchans & V4L2_TUNER_SUB_LANG2)) | ||
159 | new_stereo_mode = dual; | ||
160 | |||
161 | if (new_stereo_mode == itv->dualwatch_stereo_mode) | ||
162 | return; | ||
163 | |||
164 | new_bitmap = new_stereo_mode | (itv->params.audio_properties & ~stereo_mask); | ||
165 | |||
166 | IVTV_DEBUG_INFO("dualwatch: change stereo flag from 0x%x to 0x%x. new audio_bitmask=0x%ux\n", | ||
167 | itv->dualwatch_stereo_mode, new_stereo_mode, new_bitmap); | ||
168 | |||
169 | if (ivtv_vapi(itv, CX2341X_ENC_SET_AUDIO_PROPERTIES, 1, new_bitmap) == 0) { | ||
170 | itv->dualwatch_stereo_mode = new_stereo_mode; | ||
171 | return; | ||
172 | } | ||
173 | IVTV_DEBUG_INFO("dualwatch: changing stereo flag failed\n"); | ||
174 | } | ||
175 | |||
176 | static void ivtv_update_pgm_info(struct ivtv *itv) | ||
177 | { | ||
178 | u32 wr_idx = (read_enc(itv->pgm_info_offset) - itv->pgm_info_offset - 4) / 24; | ||
179 | int cnt; | ||
180 | int i = 0; | ||
181 | |||
182 | if (wr_idx >= itv->pgm_info_num) { | ||
183 | IVTV_DEBUG_WARN("Invalid PGM index %d (>= %d)\n", wr_idx, itv->pgm_info_num); | ||
184 | return; | ||
185 | } | ||
186 | cnt = (wr_idx + itv->pgm_info_num - itv->pgm_info_write_idx) % itv->pgm_info_num; | ||
187 | while (i < cnt) { | ||
188 | int idx = (itv->pgm_info_write_idx + i) % itv->pgm_info_num; | ||
189 | struct v4l2_enc_idx_entry *e = itv->pgm_info + idx; | ||
190 | u32 addr = itv->pgm_info_offset + 4 + idx * 24; | ||
191 | const int mapping[] = { V4L2_ENC_IDX_FRAME_P, V4L2_ENC_IDX_FRAME_I, V4L2_ENC_IDX_FRAME_B, 0 }; | ||
192 | |||
193 | e->offset = read_enc(addr + 4) + ((u64)read_enc(addr + 8) << 32); | ||
194 | if (e->offset > itv->mpg_data_received) { | ||
195 | break; | ||
196 | } | ||
197 | e->offset += itv->vbi_data_inserted; | ||
198 | e->length = read_enc(addr); | ||
199 | e->pts = read_enc(addr + 16) + ((u64)(read_enc(addr + 20) & 1) << 32); | ||
200 | e->flags = mapping[read_enc(addr + 12) & 3]; | ||
201 | i++; | ||
202 | } | ||
203 | itv->pgm_info_write_idx = (itv->pgm_info_write_idx + i) % itv->pgm_info_num; | ||
204 | } | ||
205 | |||
206 | static struct ivtv_buffer *ivtv_get_buffer(struct ivtv_stream *s, int non_block, int *err) | ||
207 | { | ||
208 | struct ivtv *itv = s->itv; | ||
209 | struct ivtv_stream *s_vbi = &itv->streams[IVTV_ENC_STREAM_TYPE_VBI]; | ||
210 | struct ivtv_buffer *buf; | ||
211 | DEFINE_WAIT(wait); | ||
212 | |||
213 | *err = 0; | ||
214 | while (1) { | ||
215 | if (s->type == IVTV_ENC_STREAM_TYPE_MPG) { | ||
216 | /* Process pending program info updates and pending VBI data */ | ||
217 | ivtv_update_pgm_info(itv); | ||
218 | |||
219 | if (jiffies - itv->dualwatch_jiffies > HZ) { | ||
220 | itv->dualwatch_jiffies = jiffies; | ||
221 | ivtv_dualwatch(itv); | ||
222 | } | ||
223 | |||
224 | if (test_bit(IVTV_F_S_INTERNAL_USE, &s_vbi->s_flags) && | ||
225 | !test_bit(IVTV_F_S_APPL_IO, &s_vbi->s_flags)) { | ||
226 | while ((buf = ivtv_dequeue(s_vbi, &s_vbi->q_full))) { | ||
227 | /* byteswap and process VBI data */ | ||
228 | ivtv_process_vbi_data(itv, buf, s_vbi->dma_pts, s_vbi->type); | ||
229 | ivtv_enqueue(s_vbi, buf, &s_vbi->q_free); | ||
230 | } | ||
231 | } | ||
232 | buf = &itv->vbi.sliced_mpeg_buf; | ||
233 | if (buf->readpos != buf->bytesused) { | ||
234 | return buf; | ||
235 | } | ||
236 | } | ||
237 | |||
238 | /* do we have leftover data? */ | ||
239 | buf = ivtv_dequeue(s, &s->q_io); | ||
240 | if (buf) | ||
241 | return buf; | ||
242 | |||
243 | /* do we have new data? */ | ||
244 | buf = ivtv_dequeue(s, &s->q_full); | ||
245 | if (buf) { | ||
246 | if (!test_and_clear_bit(IVTV_F_B_NEED_BUF_SWAP, &buf->b_flags)) | ||
247 | return buf; | ||
248 | if (s->type == IVTV_ENC_STREAM_TYPE_MPG) | ||
249 | /* byteswap MPG data */ | ||
250 | ivtv_buf_swap(buf); | ||
251 | else if (s->type != IVTV_DEC_STREAM_TYPE_VBI) { | ||
252 | /* byteswap and process VBI data */ | ||
253 | ivtv_process_vbi_data(itv, buf, s->dma_pts, s->type); | ||
254 | } | ||
255 | return buf; | ||
256 | } | ||
257 | /* return if file was opened with O_NONBLOCK */ | ||
258 | if (non_block) { | ||
259 | *err = -EAGAIN; | ||
260 | return NULL; | ||
261 | } | ||
262 | |||
263 | /* return if end of stream */ | ||
264 | if (s->type != IVTV_DEC_STREAM_TYPE_VBI && !test_bit(IVTV_F_S_STREAMING, &s->s_flags)) { | ||
265 | clear_bit(IVTV_F_S_STREAMOFF, &s->s_flags); | ||
266 | IVTV_DEBUG_INFO("EOS %s\n", s->name); | ||
267 | return NULL; | ||
268 | } | ||
269 | |||
270 | /* wait for more data to arrive */ | ||
271 | prepare_to_wait(&s->waitq, &wait, TASK_INTERRUPTIBLE); | ||
272 | /* New buffers might have become available before we were added to the waitqueue */ | ||
273 | if (!s->q_full.buffers) | ||
274 | schedule(); | ||
275 | finish_wait(&s->waitq, &wait); | ||
276 | if (signal_pending(current)) { | ||
277 | /* return if a signal was received */ | ||
278 | IVTV_DEBUG_INFO("User stopped %s\n", s->name); | ||
279 | *err = -EINTR; | ||
280 | return NULL; | ||
281 | } | ||
282 | } | ||
283 | } | ||
284 | |||
285 | static void ivtv_setup_sliced_vbi_buf(struct ivtv *itv) | ||
286 | { | ||
287 | int idx = itv->vbi.inserted_frame % IVTV_VBI_FRAMES; | ||
288 | |||
289 | itv->vbi.sliced_mpeg_buf.buf = itv->vbi.sliced_mpeg_data[idx]; | ||
290 | itv->vbi.sliced_mpeg_buf.bytesused = itv->vbi.sliced_mpeg_size[idx]; | ||
291 | itv->vbi.sliced_mpeg_buf.readpos = 0; | ||
292 | } | ||
293 | |||
294 | static size_t ivtv_copy_buf_to_user(struct ivtv_stream *s, struct ivtv_buffer *buf, | ||
295 | char __user *ubuf, size_t ucount) | ||
296 | { | ||
297 | struct ivtv *itv = s->itv; | ||
298 | size_t len = buf->bytesused - buf->readpos; | ||
299 | |||
300 | if (len > ucount) len = ucount; | ||
301 | if (itv->vbi.insert_mpeg && s->type == IVTV_ENC_STREAM_TYPE_MPG && | ||
302 | itv->vbi.sliced_in->service_set && buf != &itv->vbi.sliced_mpeg_buf) { | ||
303 | const char *start = buf->buf + buf->readpos; | ||
304 | const char *p = start + 1; | ||
305 | const u8 *q; | ||
306 | u8 ch = itv->search_pack_header ? 0xba : 0xe0; | ||
307 | int stuffing, i; | ||
308 | |||
309 | while (start + len > p && (q = memchr(p, 0, start + len - p))) { | ||
310 | p = q + 1; | ||
311 | if ((char *)q + 15 >= buf->buf + buf->bytesused || | ||
312 | q[1] != 0 || q[2] != 1 || q[3] != ch) { | ||
313 | continue; | ||
314 | } | ||
315 | if (!itv->search_pack_header) { | ||
316 | if ((q[6] & 0xc0) != 0x80) | ||
317 | continue; | ||
318 | if (((q[7] & 0xc0) == 0x80 && (q[9] & 0xf0) == 0x20) || | ||
319 | ((q[7] & 0xc0) == 0xc0 && (q[9] & 0xf0) == 0x30)) { | ||
320 | ch = 0xba; | ||
321 | itv->search_pack_header = 1; | ||
322 | p = q + 9; | ||
323 | } | ||
324 | continue; | ||
325 | } | ||
326 | stuffing = q[13] & 7; | ||
327 | /* all stuffing bytes must be 0xff */ | ||
328 | for (i = 0; i < stuffing; i++) | ||
329 | if (q[14 + i] != 0xff) | ||
330 | break; | ||
331 | if (i == stuffing && (q[4] & 0xc4) == 0x44 && (q[12] & 3) == 3 && | ||
332 | q[14 + stuffing] == 0 && q[15 + stuffing] == 0 && | ||
333 | q[16 + stuffing] == 1) { | ||
334 | itv->search_pack_header = 0; | ||
335 | len = (char *)q - start; | ||
336 | ivtv_setup_sliced_vbi_buf(itv); | ||
337 | break; | ||
338 | } | ||
339 | } | ||
340 | } | ||
341 | if (copy_to_user(ubuf, (u8 *)buf->buf + buf->readpos, len)) { | ||
342 | IVTV_DEBUG_WARN("copy %zd bytes to user failed for %s\n", len, s->name); | ||
343 | return -EFAULT; | ||
344 | } | ||
345 | /*IVTV_INFO("copied %lld %d %d %d %d %d vbi %d\n", itv->mpg_data_received, len, ucount, | ||
346 | buf->readpos, buf->bytesused, buf->bytesused - buf->readpos - len, | ||
347 | buf == &itv->vbi.sliced_mpeg_buf); */ | ||
348 | buf->readpos += len; | ||
349 | if (s->type == IVTV_ENC_STREAM_TYPE_MPG && buf != &itv->vbi.sliced_mpeg_buf) | ||
350 | itv->mpg_data_received += len; | ||
351 | return len; | ||
352 | } | ||
353 | |||
354 | static ssize_t ivtv_read(struct ivtv_stream *s, char __user *ubuf, size_t tot_count, int non_block) | ||
355 | { | ||
356 | struct ivtv *itv = s->itv; | ||
357 | size_t tot_written = 0; | ||
358 | int single_frame = 0; | ||
359 | |||
360 | if (atomic_read(&itv->capturing) == 0 && s->id == -1) { | ||
361 | /* shouldn't happen */ | ||
362 | IVTV_DEBUG_WARN("Stream %s not initialized before read\n", s->name); | ||
363 | return -EIO; | ||
364 | } | ||
365 | |||
366 | /* Each VBI buffer is one frame, the v4l2 API says that for VBI the frames should | ||
367 | arrive one-by-one, so make sure we never output more than one VBI frame at a time */ | ||
368 | if (s->type == IVTV_DEC_STREAM_TYPE_VBI || | ||
369 | (s->type == IVTV_ENC_STREAM_TYPE_VBI && itv->vbi.sliced_in->service_set)) | ||
370 | single_frame = 1; | ||
371 | |||
372 | for (;;) { | ||
373 | struct ivtv_buffer *buf; | ||
374 | int rc; | ||
375 | |||
376 | buf = ivtv_get_buffer(s, non_block, &rc); | ||
377 | if (buf == NULL && rc == -EAGAIN && tot_written) | ||
378 | break; | ||
379 | if (buf == NULL) | ||
380 | return rc; | ||
381 | rc = ivtv_copy_buf_to_user(s, buf, ubuf + tot_written, tot_count - tot_written); | ||
382 | if (buf != &itv->vbi.sliced_mpeg_buf) { | ||
383 | ivtv_enqueue(s, buf, (buf->readpos == buf->bytesused) ? &s->q_free : &s->q_io); | ||
384 | } | ||
385 | else if (buf->readpos == buf->bytesused) { | ||
386 | int idx = itv->vbi.inserted_frame % IVTV_VBI_FRAMES; | ||
387 | itv->vbi.sliced_mpeg_size[idx] = 0; | ||
388 | itv->vbi.inserted_frame++; | ||
389 | itv->vbi_data_inserted += buf->bytesused; | ||
390 | } | ||
391 | if (rc < 0) | ||
392 | return rc; | ||
393 | tot_written += rc; | ||
394 | |||
395 | if (tot_written == tot_count || single_frame) | ||
396 | break; | ||
397 | } | ||
398 | return tot_written; | ||
399 | } | ||
400 | |||
401 | static ssize_t ivtv_read_pos(struct ivtv_stream *s, char __user *ubuf, size_t count, | ||
402 | loff_t *pos, int non_block) | ||
403 | { | ||
404 | ssize_t rc = count ? ivtv_read(s, ubuf, count, non_block) : 0; | ||
405 | struct ivtv *itv = s->itv; | ||
406 | |||
407 | IVTV_DEBUG_INFO("read %zd from %s, got %zd\n", count, s->name, rc); | ||
408 | if (rc > 0) | ||
409 | pos += rc; | ||
410 | return rc; | ||
411 | } | ||
412 | |||
413 | int ivtv_start_capture(struct ivtv_open_id *id) | ||
414 | { | ||
415 | struct ivtv *itv = id->itv; | ||
416 | struct ivtv_stream *s = &itv->streams[id->type]; | ||
417 | struct ivtv_stream *s_vbi; | ||
418 | |||
419 | if (s->type == IVTV_ENC_STREAM_TYPE_RAD || | ||
420 | s->type == IVTV_DEC_STREAM_TYPE_MPG || | ||
421 | s->type == IVTV_DEC_STREAM_TYPE_YUV || | ||
422 | s->type == IVTV_DEC_STREAM_TYPE_VOUT) { | ||
423 | /* you cannot read from these stream types. */ | ||
424 | return -EPERM; | ||
425 | } | ||
426 | |||
427 | /* Try to claim this stream. */ | ||
428 | if (ivtv_claim_stream(id, s->type)) | ||
429 | return -EBUSY; | ||
430 | |||
431 | /* This stream does not need to start capturing */ | ||
432 | if (s->type == IVTV_DEC_STREAM_TYPE_VBI) { | ||
433 | set_bit(IVTV_F_S_APPL_IO, &s->s_flags); | ||
434 | return 0; | ||
435 | } | ||
436 | |||
437 | /* If capture is already in progress, then we also have to | ||
438 | do nothing extra. */ | ||
439 | if (test_bit(IVTV_F_S_STREAMOFF, &s->s_flags) || test_and_set_bit(IVTV_F_S_STREAMING, &s->s_flags)) { | ||
440 | set_bit(IVTV_F_S_APPL_IO, &s->s_flags); | ||
441 | return 0; | ||
442 | } | ||
443 | |||
444 | /* Start VBI capture if required */ | ||
445 | s_vbi = &itv->streams[IVTV_ENC_STREAM_TYPE_VBI]; | ||
446 | if (s->type == IVTV_ENC_STREAM_TYPE_MPG && | ||
447 | test_bit(IVTV_F_S_INTERNAL_USE, &s_vbi->s_flags) && | ||
448 | !test_and_set_bit(IVTV_F_S_STREAMING, &s_vbi->s_flags)) { | ||
449 | /* Note: the IVTV_ENC_STREAM_TYPE_VBI is claimed | ||
450 | automatically when the MPG stream is claimed. | ||
451 | We only need to start the VBI capturing. */ | ||
452 | if (ivtv_start_v4l2_encode_stream(s_vbi)) { | ||
453 | IVTV_DEBUG_WARN("VBI capture start failed\n"); | ||
454 | |||
455 | /* Failure, clean up and return an error */ | ||
456 | clear_bit(IVTV_F_S_STREAMING, &s_vbi->s_flags); | ||
457 | clear_bit(IVTV_F_S_STREAMING, &s->s_flags); | ||
458 | /* also releases the associated VBI stream */ | ||
459 | ivtv_release_stream(s); | ||
460 | return -EIO; | ||
461 | } | ||
462 | IVTV_DEBUG_INFO("VBI insertion started\n"); | ||
463 | } | ||
464 | |||
465 | /* Tell the card to start capturing */ | ||
466 | if (!ivtv_start_v4l2_encode_stream(s)) { | ||
467 | /* We're done */ | ||
468 | set_bit(IVTV_F_S_APPL_IO, &s->s_flags); | ||
469 | /* Resume a possibly paused encoder */ | ||
470 | if (test_and_clear_bit(IVTV_F_I_ENC_PAUSED, &itv->i_flags)) | ||
471 | ivtv_vapi(itv, CX2341X_ENC_PAUSE_ENCODER, 1, 1); | ||
472 | return 0; | ||
473 | } | ||
474 | |||
475 | /* failure, clean up */ | ||
476 | IVTV_DEBUG_WARN("Failed to start capturing for stream %s\n", s->name); | ||
477 | |||
478 | /* Note: the IVTV_ENC_STREAM_TYPE_VBI is released | ||
479 | automatically when the MPG stream is released. | ||
480 | We only need to stop the VBI capturing. */ | ||
481 | if (s->type == IVTV_ENC_STREAM_TYPE_MPG && | ||
482 | test_bit(IVTV_F_S_STREAMING, &s_vbi->s_flags)) { | ||
483 | ivtv_stop_v4l2_encode_stream(s_vbi, 0); | ||
484 | clear_bit(IVTV_F_S_STREAMING, &s_vbi->s_flags); | ||
485 | } | ||
486 | clear_bit(IVTV_F_S_STREAMING, &s->s_flags); | ||
487 | ivtv_release_stream(s); | ||
488 | return -EIO; | ||
489 | } | ||
490 | |||
491 | ssize_t ivtv_v4l2_read(struct file * filp, char __user *buf, size_t count, loff_t * pos) | ||
492 | { | ||
493 | struct ivtv_open_id *id = filp->private_data; | ||
494 | struct ivtv *itv = id->itv; | ||
495 | struct ivtv_stream *s = &itv->streams[id->type]; | ||
496 | int rc; | ||
497 | |||
498 | IVTV_DEBUG_IOCTL("read %zd bytes from %s\n", count, s->name); | ||
499 | |||
500 | rc = ivtv_start_capture(id); | ||
501 | if (rc) | ||
502 | return rc; | ||
503 | return ivtv_read_pos(s, buf, count, pos, filp->f_flags & O_NONBLOCK); | ||
504 | } | ||
505 | |||
506 | int ivtv_start_decoding(struct ivtv_open_id *id, int speed) | ||
507 | { | ||
508 | struct ivtv *itv = id->itv; | ||
509 | struct ivtv_stream *s = &itv->streams[id->type]; | ||
510 | |||
511 | if (atomic_read(&itv->decoding) == 0) { | ||
512 | if (ivtv_claim_stream(id, s->type)) { | ||
513 | /* someone else is using this stream already */ | ||
514 | IVTV_DEBUG_WARN("start decode, stream already claimed\n"); | ||
515 | return -EBUSY; | ||
516 | } | ||
517 | ivtv_start_v4l2_decode_stream(s, 0); | ||
518 | } | ||
519 | if (s->type == IVTV_DEC_STREAM_TYPE_MPG) | ||
520 | return ivtv_set_speed(itv, speed); | ||
521 | return 0; | ||
522 | } | ||
523 | |||
524 | ssize_t ivtv_v4l2_write(struct file *filp, const char __user *user_buf, size_t count, loff_t *pos) | ||
525 | { | ||
526 | struct ivtv_open_id *id = filp->private_data; | ||
527 | struct ivtv *itv = id->itv; | ||
528 | struct ivtv_stream *s = &itv->streams[id->type]; | ||
529 | struct ivtv_buffer *buf; | ||
530 | struct ivtv_queue q; | ||
531 | int bytes_written = 0; | ||
532 | int mode; | ||
533 | int rc; | ||
534 | DEFINE_WAIT(wait); | ||
535 | |||
536 | IVTV_DEBUG_IOCTL("write %zd bytes to %s\n", count, s->name); | ||
537 | |||
538 | if (s->type != IVTV_DEC_STREAM_TYPE_MPG && | ||
539 | s->type != IVTV_DEC_STREAM_TYPE_YUV && | ||
540 | s->type != IVTV_DEC_STREAM_TYPE_VOUT) | ||
541 | /* not decoder streams */ | ||
542 | return -EPERM; | ||
543 | |||
544 | /* Try to claim this stream */ | ||
545 | if (ivtv_claim_stream(id, s->type)) | ||
546 | return -EBUSY; | ||
547 | |||
548 | /* This stream does not need to start any decoding */ | ||
549 | if (s->type == IVTV_DEC_STREAM_TYPE_VOUT) { | ||
550 | set_bit(IVTV_F_S_APPL_IO, &s->s_flags); | ||
551 | return ivtv_write_vbi(itv, user_buf, count); | ||
552 | } | ||
553 | |||
554 | mode = s->type == IVTV_DEC_STREAM_TYPE_MPG ? OUT_MPG : OUT_YUV; | ||
555 | |||
556 | if (ivtv_set_output_mode(itv, mode) != mode) { | ||
557 | ivtv_release_stream(s); | ||
558 | return -EBUSY; | ||
559 | } | ||
560 | ivtv_queue_init(&q); | ||
561 | set_bit(IVTV_F_S_APPL_IO, &s->s_flags); | ||
562 | |||
563 | retry: | ||
564 | for (;;) { | ||
565 | /* Gather buffers */ | ||
566 | while (q.length - q.bytesused < count && (buf = ivtv_dequeue(s, &s->q_io))) | ||
567 | ivtv_enqueue(s, buf, &q); | ||
568 | while (q.length - q.bytesused < count && (buf = ivtv_dequeue(s, &s->q_free))) { | ||
569 | ivtv_enqueue(s, buf, &q); | ||
570 | } | ||
571 | if (q.buffers) | ||
572 | break; | ||
573 | if (filp->f_flags & O_NONBLOCK) | ||
574 | return -EAGAIN; | ||
575 | prepare_to_wait(&s->waitq, &wait, TASK_INTERRUPTIBLE); | ||
576 | /* New buffers might have become free before we were added to the waitqueue */ | ||
577 | if (!s->q_free.buffers) | ||
578 | schedule(); | ||
579 | finish_wait(&s->waitq, &wait); | ||
580 | if (signal_pending(current)) { | ||
581 | IVTV_DEBUG_INFO("User stopped %s\n", s->name); | ||
582 | return -EINTR; | ||
583 | } | ||
584 | } | ||
585 | |||
586 | /* copy user data into buffers */ | ||
587 | while ((buf = ivtv_dequeue(s, &q))) { | ||
588 | /* Make sure we really got all the user data */ | ||
589 | rc = ivtv_buf_copy_from_user(s, buf, user_buf, count); | ||
590 | |||
591 | if (rc < 0) { | ||
592 | ivtv_queue_move(s, &q, NULL, &s->q_free, 0); | ||
593 | return rc; | ||
594 | } | ||
595 | user_buf += rc; | ||
596 | count -= rc; | ||
597 | bytes_written += rc; | ||
598 | |||
599 | if (buf->bytesused != s->buf_size) { | ||
600 | /* incomplete, leave in q_io for next time */ | ||
601 | ivtv_enqueue(s, buf, &s->q_io); | ||
602 | break; | ||
603 | } | ||
604 | /* Byteswap MPEG buffer */ | ||
605 | if (s->type == IVTV_DEC_STREAM_TYPE_MPG) | ||
606 | ivtv_buf_swap(buf); | ||
607 | ivtv_enqueue(s, buf, &s->q_full); | ||
608 | } | ||
609 | |||
610 | /* Start decoder (returns 0 if already started) */ | ||
611 | rc = ivtv_start_decoding(id, itv->speed); | ||
612 | if (rc) { | ||
613 | IVTV_DEBUG_WARN("Failed start decode stream %s\n", s->name); | ||
614 | |||
615 | /* failure, clean up */ | ||
616 | clear_bit(IVTV_F_S_STREAMING, &s->s_flags); | ||
617 | clear_bit(IVTV_F_S_APPL_IO, &s->s_flags); | ||
618 | return rc; | ||
619 | } | ||
620 | if (test_bit(IVTV_F_S_NEEDS_DATA, &s->s_flags)) { | ||
621 | if (s->q_full.length >= itv->dma_data_req_size) { | ||
622 | int got_sig; | ||
623 | |||
624 | prepare_to_wait(&itv->dma_waitq, &wait, TASK_INTERRUPTIBLE); | ||
625 | while (!(got_sig = signal_pending(current)) && | ||
626 | test_bit(IVTV_F_S_DMA_PENDING, &s->s_flags)) { | ||
627 | schedule(); | ||
628 | } | ||
629 | finish_wait(&itv->dma_waitq, &wait); | ||
630 | if (got_sig) { | ||
631 | IVTV_DEBUG_INFO("User interrupted %s\n", s->name); | ||
632 | return -EINTR; | ||
633 | } | ||
634 | |||
635 | clear_bit(IVTV_F_S_NEEDS_DATA, &s->s_flags); | ||
636 | ivtv_queue_move(s, &s->q_full, NULL, &s->q_predma, itv->dma_data_req_size); | ||
637 | ivtv_dma_stream_dec_prepare(s, itv->dma_data_req_offset + IVTV_DECODER_OFFSET, 1); | ||
638 | } | ||
639 | } | ||
640 | /* more user data is available, wait until buffers become free | ||
641 | to transfer the rest. */ | ||
642 | if (count && !(filp->f_flags & O_NONBLOCK)) | ||
643 | goto retry; | ||
644 | IVTV_DEBUG_INFO("Wrote %d bytes to %s (%d)\n", bytes_written, s->name, s->q_full.bytesused); | ||
645 | return bytes_written; | ||
646 | } | ||
647 | |||
648 | unsigned int ivtv_v4l2_dec_poll(struct file *filp, poll_table *wait) | ||
649 | { | ||
650 | struct ivtv_open_id *id = filp->private_data; | ||
651 | struct ivtv *itv = id->itv; | ||
652 | struct ivtv_stream *s = &itv->streams[id->type]; | ||
653 | int res = 0; | ||
654 | |||
655 | /* add stream's waitq to the poll list */ | ||
656 | poll_wait(filp, &s->waitq, wait); | ||
657 | |||
658 | set_bit(IVTV_F_I_EV_VSYNC_ENABLED, &itv->i_flags); | ||
659 | if (test_bit(IVTV_F_I_EV_VSYNC, &itv->i_flags) || | ||
660 | test_bit(IVTV_F_I_EV_DEC_STOPPED, &itv->i_flags)) | ||
661 | res = POLLPRI; | ||
662 | |||
663 | /* Allow write if buffers are available for writing */ | ||
664 | if (s->q_free.buffers) | ||
665 | res |= POLLOUT | POLLWRNORM; | ||
666 | return res; | ||
667 | } | ||
668 | |||
669 | unsigned int ivtv_v4l2_enc_poll(struct file *filp, poll_table * wait) | ||
670 | { | ||
671 | struct ivtv_open_id *id = filp->private_data; | ||
672 | struct ivtv *itv = id->itv; | ||
673 | struct ivtv_stream *s = &itv->streams[id->type]; | ||
674 | int eof = test_bit(IVTV_F_S_STREAMOFF, &s->s_flags); | ||
675 | |||
676 | /* Start a capture if there is none */ | ||
677 | if (!eof && !test_bit(IVTV_F_S_STREAMING, &s->s_flags)) { | ||
678 | int rc = ivtv_start_capture(id); | ||
679 | |||
680 | if (rc) { | ||
681 | IVTV_DEBUG_INFO("Could not start capture for %s (%d)\n", | ||
682 | s->name, rc); | ||
683 | return POLLERR; | ||
684 | } | ||
685 | } | ||
686 | |||
687 | /* add stream's waitq to the poll list */ | ||
688 | poll_wait(filp, &s->waitq, wait); | ||
689 | |||
690 | if (eof || s->q_full.length) | ||
691 | return POLLIN | POLLRDNORM; | ||
692 | return 0; | ||
693 | } | ||
694 | |||
695 | void ivtv_stop_capture(struct ivtv_open_id *id, int gop_end) | ||
696 | { | ||
697 | struct ivtv *itv = id->itv; | ||
698 | struct ivtv_stream *s = &itv->streams[id->type]; | ||
699 | |||
700 | IVTV_DEBUG_IOCTL("close() of %s\n", s->name); | ||
701 | |||
702 | /* 'Unclaim' this stream */ | ||
703 | |||
704 | /* Stop capturing */ | ||
705 | if (test_bit(IVTV_F_S_STREAMING, &s->s_flags)) { | ||
706 | struct ivtv_stream *s_vbi = &itv->streams[IVTV_ENC_STREAM_TYPE_VBI]; | ||
707 | |||
708 | IVTV_DEBUG_INFO("close stopping capture\n"); | ||
709 | /* Special case: a running VBI capture for VBI insertion | ||
710 | in the mpeg stream. Need to stop that too. */ | ||
711 | if (id->type == IVTV_ENC_STREAM_TYPE_MPG && | ||
712 | test_bit(IVTV_F_S_STREAMING, &s_vbi->s_flags) && | ||
713 | !test_bit(IVTV_F_S_APPL_IO, &s_vbi->s_flags)) { | ||
714 | IVTV_DEBUG_INFO("close stopping embedded VBI capture\n"); | ||
715 | ivtv_stop_v4l2_encode_stream(s_vbi, 0); | ||
716 | } | ||
717 | if ((id->type == IVTV_DEC_STREAM_TYPE_VBI || | ||
718 | id->type == IVTV_ENC_STREAM_TYPE_VBI) && | ||
719 | test_bit(IVTV_F_S_INTERNAL_USE, &s->s_flags)) { | ||
720 | /* Also used internally, don't stop capturing */ | ||
721 | s->id = -1; | ||
722 | } | ||
723 | else { | ||
724 | ivtv_stop_v4l2_encode_stream(s, gop_end); | ||
725 | } | ||
726 | } | ||
727 | clear_bit(IVTV_F_S_APPL_IO, &s->s_flags); | ||
728 | clear_bit(IVTV_F_S_STREAMOFF, &s->s_flags); | ||
729 | |||
730 | ivtv_release_stream(s); | ||
731 | } | ||
732 | |||
733 | void ivtv_stop_decoding(struct ivtv_open_id *id, int flags, u64 pts) | ||
734 | { | ||
735 | struct ivtv *itv = id->itv; | ||
736 | struct ivtv_stream *s = &itv->streams[id->type]; | ||
737 | |||
738 | IVTV_DEBUG_IOCTL("close() of %s\n", s->name); | ||
739 | |||
740 | /* Stop decoding */ | ||
741 | if (test_bit(IVTV_F_S_STREAMING, &s->s_flags)) { | ||
742 | IVTV_DEBUG_INFO("close stopping decode\n"); | ||
743 | |||
744 | ivtv_stop_v4l2_decode_stream(s, flags, pts); | ||
745 | } | ||
746 | clear_bit(IVTV_F_S_APPL_IO, &s->s_flags); | ||
747 | clear_bit(IVTV_F_S_STREAMOFF, &s->s_flags); | ||
748 | if (id->type == IVTV_DEC_STREAM_TYPE_YUV && test_bit(IVTV_F_I_DECODING_YUV, &itv->i_flags)) { | ||
749 | /* Restore registers we've changed & clean up any mess we've made */ | ||
750 | ivtv_yuv_close(itv); | ||
751 | } | ||
752 | if (s->type == IVTV_DEC_STREAM_TYPE_YUV && itv->output_mode == OUT_YUV) | ||
753 | itv->output_mode = OUT_NONE; | ||
754 | else if (s->type == IVTV_DEC_STREAM_TYPE_MPG && itv->output_mode == OUT_MPG) | ||
755 | itv->output_mode = OUT_NONE; | ||
756 | |||
757 | itv->speed = 0; | ||
758 | ivtv_release_stream(s); | ||
759 | } | ||
760 | |||
761 | int ivtv_v4l2_close(struct inode *inode, struct file *filp) | ||
762 | { | ||
763 | struct ivtv_open_id *id = filp->private_data; | ||
764 | struct ivtv *itv = id->itv; | ||
765 | struct ivtv_stream *s = &itv->streams[id->type]; | ||
766 | |||
767 | IVTV_DEBUG_IOCTL("close() of %s\n", s->name); | ||
768 | |||
769 | /* Easy case first: this stream was never claimed by us */ | ||
770 | if (s->id != id->open_id) { | ||
771 | kfree(id); | ||
772 | return 0; | ||
773 | } | ||
774 | |||
775 | /* 'Unclaim' this stream */ | ||
776 | |||
777 | /* Stop radio */ | ||
778 | if (id->type == IVTV_ENC_STREAM_TYPE_RAD) { | ||
779 | /* Closing radio device, return to TV mode */ | ||
780 | ivtv_mute(itv); | ||
781 | /* Mark that the radio is no longer in use */ | ||
782 | clear_bit(IVTV_F_I_RADIO_USER, &itv->i_flags); | ||
783 | /* Switch tuner to TV */ | ||
784 | ivtv_call_i2c_clients(itv, VIDIOC_S_STD, &itv->std); | ||
785 | /* Select correct audio input (i.e. TV tuner or Line in) */ | ||
786 | ivtv_audio_set_io(itv); | ||
787 | /* Done! Unmute and continue. */ | ||
788 | ivtv_unmute(itv); | ||
789 | ivtv_release_stream(s); | ||
790 | } else if (s->type >= IVTV_DEC_STREAM_TYPE_MPG) { | ||
791 | ivtv_stop_decoding(id, VIDEO_CMD_STOP_TO_BLACK | VIDEO_CMD_STOP_IMMEDIATELY, 0); | ||
792 | } else { | ||
793 | ivtv_stop_capture(id, 0); | ||
794 | } | ||
795 | kfree(id); | ||
796 | return 0; | ||
797 | } | ||
798 | |||
799 | int ivtv_v4l2_open(struct inode *inode, struct file *filp) | ||
800 | { | ||
801 | int x, y = 0; | ||
802 | struct ivtv_open_id *item; | ||
803 | struct ivtv *itv = NULL; | ||
804 | struct ivtv_stream *s = NULL; | ||
805 | int minor = MINOR(inode->i_rdev); | ||
806 | |||
807 | /* Find which card this open was on */ | ||
808 | spin_lock(&ivtv_cards_lock); | ||
809 | for (x = 0; itv == NULL && x < ivtv_cards_active; x++) { | ||
810 | /* find out which stream this open was on */ | ||
811 | for (y = 0; y < IVTV_MAX_STREAMS; y++) { | ||
812 | s = &ivtv_cards[x]->streams[y]; | ||
813 | if (s->v4l2dev && s->v4l2dev->minor == minor) { | ||
814 | itv = ivtv_cards[x]; | ||
815 | break; | ||
816 | } | ||
817 | } | ||
818 | } | ||
819 | spin_unlock(&ivtv_cards_lock); | ||
820 | |||
821 | if (itv == NULL) { | ||
822 | /* Couldn't find a device registered | ||
823 | on that minor, shouldn't happen! */ | ||
824 | printk(KERN_WARNING "ivtv: no ivtv device found on minor %d\n", minor); | ||
825 | return -ENXIO; | ||
826 | } | ||
827 | |||
828 | if (y == IVTV_DEC_STREAM_TYPE_MPG && | ||
829 | test_bit(IVTV_F_S_CLAIMED, &itv->streams[IVTV_DEC_STREAM_TYPE_YUV].s_flags)) | ||
830 | return -EBUSY; | ||
831 | |||
832 | if (y == IVTV_DEC_STREAM_TYPE_YUV && | ||
833 | test_bit(IVTV_F_S_CLAIMED, &itv->streams[IVTV_DEC_STREAM_TYPE_MPG].s_flags)) | ||
834 | return -EBUSY; | ||
835 | |||
836 | if (y == IVTV_DEC_STREAM_TYPE_YUV) { | ||
837 | if (read_reg(0x82c) == 0) { | ||
838 | IVTV_ERR("Tried to open YUV output device but need to send data to mpeg decoder before it can be used\n"); | ||
839 | /* return -ENODEV; */ | ||
840 | } | ||
841 | ivtv_udma_alloc(itv); | ||
842 | } | ||
843 | |||
844 | /* Allocate memory */ | ||
845 | item = kmalloc(sizeof(struct ivtv_open_id), GFP_KERNEL); | ||
846 | if (NULL == item) { | ||
847 | IVTV_DEBUG_WARN("nomem on v4l2 open\n"); | ||
848 | return -ENOMEM; | ||
849 | } | ||
850 | item->itv = itv; | ||
851 | item->type = y; | ||
852 | |||
853 | item->open_id = itv->open_id++; | ||
854 | filp->private_data = item; | ||
855 | |||
856 | if (item->type == IVTV_ENC_STREAM_TYPE_RAD) { | ||
857 | /* Try to claim this stream */ | ||
858 | if (ivtv_claim_stream(item, item->type)) { | ||
859 | /* No, it's already in use */ | ||
860 | kfree(item); | ||
861 | return -EBUSY; | ||
862 | } | ||
863 | |||
864 | /* We have the radio */ | ||
865 | ivtv_mute(itv); | ||
866 | /* Switch tuner to radio */ | ||
867 | ivtv_call_i2c_clients(itv, AUDC_SET_RADIO, NULL); | ||
868 | /* Mark that the radio is being used. */ | ||
869 | set_bit(IVTV_F_I_RADIO_USER, &itv->i_flags); | ||
870 | /* Select the correct audio input (i.e. radio tuner) */ | ||
871 | ivtv_audio_set_io(itv); | ||
872 | /* Done! Unmute and continue. */ | ||
873 | ivtv_unmute(itv); | ||
874 | } | ||
875 | |||
876 | /* YUV or MPG Decoding Mode? */ | ||
877 | if (y == IVTV_DEC_STREAM_TYPE_MPG) | ||
878 | clear_bit(IVTV_F_I_DEC_YUV, &itv->i_flags); | ||
879 | else if (y == IVTV_DEC_STREAM_TYPE_YUV) | ||
880 | { | ||
881 | set_bit(IVTV_F_I_DEC_YUV, &itv->i_flags); | ||
882 | } | ||
883 | |||
884 | return 0; | ||
885 | } | ||
886 | |||
887 | void ivtv_mute(struct ivtv *itv) | ||
888 | { | ||
889 | struct v4l2_control ctrl = { V4L2_CID_AUDIO_MUTE, 1 }; | ||
890 | |||
891 | /* Mute sound to avoid pop */ | ||
892 | ivtv_control_ioctls(itv, VIDIOC_S_CTRL, &ctrl); | ||
893 | |||
894 | if (atomic_read(&itv->capturing)) | ||
895 | ivtv_vapi(itv, CX2341X_ENC_MUTE_AUDIO, 1, 1); | ||
896 | |||
897 | IVTV_DEBUG_INFO("Mute\n"); | ||
898 | } | ||
899 | |||
900 | void ivtv_unmute(struct ivtv *itv) | ||
901 | { | ||
902 | struct v4l2_control ctrl = { V4L2_CID_AUDIO_MUTE, 0 }; | ||
903 | |||
904 | /* initialize or refresh input */ | ||
905 | if (atomic_read(&itv->capturing) == 0) | ||
906 | ivtv_vapi(itv, CX2341X_ENC_INITIALIZE_INPUT, 0); | ||
907 | |||
908 | ivtv_sleep_timeout(HZ / 10, 0); | ||
909 | |||
910 | if (atomic_read(&itv->capturing)) { | ||
911 | ivtv_vapi(itv, CX2341X_ENC_MISC, 1, 12); | ||
912 | ivtv_vapi(itv, CX2341X_ENC_MUTE_AUDIO, 1, 0); | ||
913 | } | ||
914 | |||
915 | /* Unmute */ | ||
916 | ivtv_control_ioctls(itv, VIDIOC_S_CTRL, &ctrl); | ||
917 | IVTV_DEBUG_INFO("Unmute\n"); | ||
918 | } | ||
diff --git a/drivers/media/video/ivtv/ivtv-fileops.h b/drivers/media/video/ivtv/ivtv-fileops.h new file mode 100644 index 000000000000..1afa950209b8 --- /dev/null +++ b/drivers/media/video/ivtv/ivtv-fileops.h | |||
@@ -0,0 +1,45 @@ | |||
1 | /* | ||
2 | file operation functions | ||
3 | Copyright (C) 2003-2004 Kevin Thayer <nufan_wfk at yahoo.com> | ||
4 | Copyright (C) 2005-2007 Hans Verkuil <hverkuil@xs4all.nl> | ||
5 | |||
6 | This program is free software; you can redistribute it and/or modify | ||
7 | it under the terms of the GNU General Public License as published by | ||
8 | the Free Software Foundation; either version 2 of the License, or | ||
9 | (at your option) any later version. | ||
10 | |||
11 | This program is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program; if not, write to the Free Software | ||
18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | */ | ||
20 | |||
21 | /* Testing/Debugging */ | ||
22 | int ivtv_v4l2_open(struct inode *inode, struct file *filp); | ||
23 | ssize_t ivtv_v4l2_read(struct file *filp, char __user *buf, size_t count, | ||
24 | loff_t * pos); | ||
25 | ssize_t ivtv_v4l2_write(struct file *filp, const char __user *buf, size_t count, | ||
26 | loff_t * pos); | ||
27 | int ivtv_v4l2_close(struct inode *inode, struct file *filp); | ||
28 | unsigned int ivtv_v4l2_enc_poll(struct file *filp, poll_table * wait); | ||
29 | unsigned int ivtv_v4l2_dec_poll(struct file *filp, poll_table * wait); | ||
30 | int ivtv_start_capture(struct ivtv_open_id *id); | ||
31 | void ivtv_stop_capture(struct ivtv_open_id *id, int gop_end); | ||
32 | int ivtv_start_decoding(struct ivtv_open_id *id, int speed); | ||
33 | void ivtv_stop_decoding(struct ivtv_open_id *id, int flags, u64 pts); | ||
34 | void ivtv_mute(struct ivtv *itv); | ||
35 | void ivtv_unmute(struct ivtv *itv); | ||
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 ivtv_claim_stream(struct ivtv_open_id *id, int type); | ||
43 | |||
44 | /* Release a previously claimed stream. */ | ||
45 | void ivtv_release_stream(struct ivtv_stream *s); | ||
diff --git a/drivers/media/video/ivtv/ivtv-firmware.c b/drivers/media/video/ivtv/ivtv-firmware.c new file mode 100644 index 000000000000..d4c910b782af --- /dev/null +++ b/drivers/media/video/ivtv/ivtv-firmware.c | |||
@@ -0,0 +1,272 @@ | |||
1 | /* | ||
2 | ivtv firmware functions. | ||
3 | Copyright (C) 2003-2004 Kevin Thayer <nufan_wfk at yahoo.com> | ||
4 | Copyright (C) 2004 Chris Kennedy <c@groovy.org> | ||
5 | Copyright (C) 2005-2007 Hans Verkuil <hverkuil@xs4all.nl> | ||
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 02111-1307 USA | ||
20 | */ | ||
21 | |||
22 | #include "ivtv-driver.h" | ||
23 | #include "ivtv-mailbox.h" | ||
24 | #include "ivtv-firmware.h" | ||
25 | #include <linux/firmware.h> | ||
26 | |||
27 | #define IVTV_MASK_SPU_ENABLE 0xFFFFFFFE | ||
28 | #define IVTV_MASK_VPU_ENABLE15 0xFFFFFFF6 | ||
29 | #define IVTV_MASK_VPU_ENABLE16 0xFFFFFFFB | ||
30 | #define IVTV_CMD_VDM_STOP 0x00000000 | ||
31 | #define IVTV_CMD_AO_STOP 0x00000005 | ||
32 | #define IVTV_CMD_APU_PING 0x00000000 | ||
33 | #define IVTV_CMD_VPU_STOP15 0xFFFFFFFE | ||
34 | #define IVTV_CMD_VPU_STOP16 0xFFFFFFEE | ||
35 | #define IVTV_CMD_HW_BLOCKS_RST 0xFFFFFFFF | ||
36 | #define IVTV_CMD_SPU_STOP 0x00000001 | ||
37 | #define IVTV_CMD_SDRAM_PRECHARGE_INIT 0x0000001A | ||
38 | #define IVTV_CMD_SDRAM_REFRESH_INIT 0x80000640 | ||
39 | #define IVTV_SDRAM_SLEEPTIME (60 * HZ / 100) /* 600 ms */ | ||
40 | |||
41 | #define IVTV_DECODE_INIT_MPEG_FILENAME "v4l-cx2341x-init.mpg" | ||
42 | #define IVTV_DECODE_INIT_MPEG_SIZE (152*1024) | ||
43 | |||
44 | /* Encoder/decoder firmware sizes */ | ||
45 | #define IVTV_FW_ENC_SIZE (376836) | ||
46 | #define IVTV_FW_DEC_SIZE (256*1024) | ||
47 | |||
48 | static int load_fw_direct(const char *fn, volatile u8 __iomem *mem, struct ivtv *itv, long size) | ||
49 | { | ||
50 | const struct firmware *fw = NULL; | ||
51 | int retries = 3; | ||
52 | |||
53 | retry: | ||
54 | if (retries && request_firmware(&fw, fn, &itv->dev->dev) == 0) { | ||
55 | int i; | ||
56 | volatile u32 __iomem *dst = (volatile u32 __iomem *)mem; | ||
57 | const u32 *src = (const u32 *)fw->data; | ||
58 | |||
59 | /* temporarily allow 256 KB encoding firmwares as well for | ||
60 | compatibility with blackbird cards */ | ||
61 | if (fw->size != size && fw->size != 256 * 1024) { | ||
62 | /* Due to race conditions in firmware loading (esp. with udev <0.95) | ||
63 | the wrong file was sometimes loaded. So we check filesizes to | ||
64 | see if at least the right-sized file was loaded. If not, then we | ||
65 | retry. */ | ||
66 | IVTV_INFO("retry: file loaded was not %s (expected size %ld, got %zd)\n", fn, size, fw->size); | ||
67 | release_firmware(fw); | ||
68 | retries--; | ||
69 | goto retry; | ||
70 | } | ||
71 | for (i = 0; i < fw->size; i += 4) { | ||
72 | /* no need for endianness conversion on the ppc */ | ||
73 | __raw_writel(*src, dst); | ||
74 | dst++; | ||
75 | src++; | ||
76 | } | ||
77 | release_firmware(fw); | ||
78 | IVTV_INFO("loaded %s firmware (%zd bytes)\n", fn, fw->size); | ||
79 | return size; | ||
80 | } | ||
81 | IVTV_ERR("unable to open firmware %s (must be %ld bytes)\n", fn, size); | ||
82 | IVTV_ERR("did you put the firmware in the hotplug firmware directory?\n"); | ||
83 | return -ENOMEM; | ||
84 | } | ||
85 | |||
86 | void ivtv_halt_firmware(struct ivtv *itv) | ||
87 | { | ||
88 | IVTV_DEBUG_INFO("Preparing for firmware halt.\n"); | ||
89 | if (itv->has_cx23415 && itv->dec_mbox.mbox) | ||
90 | ivtv_vapi(itv, CX2341X_DEC_HALT_FW, 0); | ||
91 | if (itv->enc_mbox.mbox) | ||
92 | ivtv_vapi(itv, CX2341X_ENC_HALT_FW, 0); | ||
93 | |||
94 | ivtv_sleep_timeout(HZ / 100, 0); | ||
95 | itv->enc_mbox.mbox = itv->dec_mbox.mbox = NULL; | ||
96 | |||
97 | IVTV_DEBUG_INFO("Stopping VDM\n"); | ||
98 | write_reg(IVTV_CMD_VDM_STOP, IVTV_REG_VDM); | ||
99 | |||
100 | IVTV_DEBUG_INFO("Stopping AO\n"); | ||
101 | write_reg(IVTV_CMD_AO_STOP, IVTV_REG_AO); | ||
102 | |||
103 | IVTV_DEBUG_INFO("pinging (?) APU\n"); | ||
104 | write_reg(IVTV_CMD_APU_PING, IVTV_REG_APU); | ||
105 | |||
106 | IVTV_DEBUG_INFO("Stopping VPU\n"); | ||
107 | if (!itv->has_cx23415) | ||
108 | write_reg(IVTV_CMD_VPU_STOP16, IVTV_REG_VPU); | ||
109 | else | ||
110 | write_reg(IVTV_CMD_VPU_STOP15, IVTV_REG_VPU); | ||
111 | |||
112 | IVTV_DEBUG_INFO("Resetting Hw Blocks\n"); | ||
113 | write_reg(IVTV_CMD_HW_BLOCKS_RST, IVTV_REG_HW_BLOCKS); | ||
114 | |||
115 | IVTV_DEBUG_INFO("Stopping SPU\n"); | ||
116 | write_reg(IVTV_CMD_SPU_STOP, IVTV_REG_SPU); | ||
117 | |||
118 | ivtv_sleep_timeout(HZ / 100, 0); | ||
119 | |||
120 | IVTV_DEBUG_INFO("init Encoder SDRAM pre-charge\n"); | ||
121 | write_reg(IVTV_CMD_SDRAM_PRECHARGE_INIT, IVTV_REG_ENC_SDRAM_PRECHARGE); | ||
122 | |||
123 | IVTV_DEBUG_INFO("init Encoder SDRAM refresh to 1us\n"); | ||
124 | write_reg(IVTV_CMD_SDRAM_REFRESH_INIT, IVTV_REG_ENC_SDRAM_REFRESH); | ||
125 | |||
126 | if (itv->has_cx23415) { | ||
127 | IVTV_DEBUG_INFO("init Decoder SDRAM pre-charge\n"); | ||
128 | write_reg(IVTV_CMD_SDRAM_PRECHARGE_INIT, IVTV_REG_DEC_SDRAM_PRECHARGE); | ||
129 | |||
130 | IVTV_DEBUG_INFO("init Decoder SDRAM refresh to 1us\n"); | ||
131 | write_reg(IVTV_CMD_SDRAM_REFRESH_INIT, IVTV_REG_DEC_SDRAM_REFRESH); | ||
132 | } | ||
133 | |||
134 | IVTV_DEBUG_INFO("Sleeping for %dms (600 recommended)\n", | ||
135 | (int)(IVTV_SDRAM_SLEEPTIME * 1000 / HZ)); | ||
136 | ivtv_sleep_timeout(IVTV_SDRAM_SLEEPTIME, 0); | ||
137 | } | ||
138 | |||
139 | void ivtv_firmware_versions(struct ivtv *itv) | ||
140 | { | ||
141 | u32 data[CX2341X_MBOX_MAX_DATA]; | ||
142 | |||
143 | /* Encoder */ | ||
144 | ivtv_vapi_result(itv, data, CX2341X_ENC_GET_VERSION, 0); | ||
145 | IVTV_INFO("Encoder revision: 0x%08x\n", data[0]); | ||
146 | |||
147 | if (data[0] != 0x02060039) | ||
148 | IVTV_WARN("Recommended firmware version is 0x02060039.\n"); | ||
149 | |||
150 | if (itv->has_cx23415) { | ||
151 | /* Decoder */ | ||
152 | ivtv_vapi_result(itv, data, CX2341X_DEC_GET_VERSION, 0); | ||
153 | IVTV_INFO("Decoder revision: 0x%08x\n", data[0]); | ||
154 | } | ||
155 | } | ||
156 | |||
157 | static int ivtv_firmware_copy(struct ivtv *itv) | ||
158 | { | ||
159 | IVTV_DEBUG_INFO("Loading encoder image\n"); | ||
160 | if (load_fw_direct(CX2341X_FIRM_ENC_FILENAME, | ||
161 | itv->enc_mem, itv, IVTV_FW_ENC_SIZE) != IVTV_FW_ENC_SIZE) { | ||
162 | IVTV_DEBUG_WARN("failed loading encoder firmware\n"); | ||
163 | return -3; | ||
164 | } | ||
165 | if (!itv->has_cx23415) | ||
166 | return 0; | ||
167 | |||
168 | IVTV_DEBUG_INFO("Loading decoder image\n"); | ||
169 | if (load_fw_direct(CX2341X_FIRM_DEC_FILENAME, | ||
170 | itv->dec_mem, itv, IVTV_FW_DEC_SIZE) != IVTV_FW_DEC_SIZE) { | ||
171 | IVTV_DEBUG_WARN("failed loading decoder firmware\n"); | ||
172 | return -1; | ||
173 | } | ||
174 | return 0; | ||
175 | } | ||
176 | |||
177 | static volatile struct ivtv_mailbox __iomem *ivtv_search_mailbox(const volatile u8 __iomem *mem, u32 size) | ||
178 | { | ||
179 | int i; | ||
180 | |||
181 | /* mailbox is preceeded by a 16 byte 'magic cookie' starting at a 256-byte | ||
182 | address boundary */ | ||
183 | for (i = 0; i < size; i += 0x100) { | ||
184 | if (readl(mem + i) == 0x12345678 && | ||
185 | readl(mem + i + 4) == 0x34567812 && | ||
186 | readl(mem + i + 8) == 0x56781234 && | ||
187 | readl(mem + i + 12) == 0x78123456) { | ||
188 | return (volatile struct ivtv_mailbox __iomem *)(mem + i + 16); | ||
189 | } | ||
190 | } | ||
191 | return NULL; | ||
192 | } | ||
193 | |||
194 | int ivtv_firmware_init(struct ivtv *itv) | ||
195 | { | ||
196 | int err; | ||
197 | |||
198 | ivtv_halt_firmware(itv); | ||
199 | |||
200 | /* load firmware */ | ||
201 | err = ivtv_firmware_copy(itv); | ||
202 | if (err) { | ||
203 | IVTV_DEBUG_WARN("Error %d loading firmware\n", err); | ||
204 | return err; | ||
205 | } | ||
206 | |||
207 | /* start firmware */ | ||
208 | write_reg(read_reg(IVTV_REG_SPU) & IVTV_MASK_SPU_ENABLE, IVTV_REG_SPU); | ||
209 | ivtv_sleep_timeout(HZ / 10, 0); | ||
210 | if (itv->has_cx23415) | ||
211 | write_reg(read_reg(IVTV_REG_VPU) & IVTV_MASK_VPU_ENABLE15, IVTV_REG_VPU); | ||
212 | else | ||
213 | write_reg(read_reg(IVTV_REG_VPU) & IVTV_MASK_VPU_ENABLE16, IVTV_REG_VPU); | ||
214 | ivtv_sleep_timeout(HZ / 10, 0); | ||
215 | |||
216 | /* find mailboxes and ping firmware */ | ||
217 | itv->enc_mbox.mbox = ivtv_search_mailbox(itv->enc_mem, IVTV_ENCODER_SIZE); | ||
218 | if (itv->enc_mbox.mbox == NULL) | ||
219 | IVTV_ERR("Encoder mailbox not found\n"); | ||
220 | else if (ivtv_vapi(itv, CX2341X_ENC_PING_FW, 0)) { | ||
221 | IVTV_ERR("Encoder firmware dead!\n"); | ||
222 | itv->enc_mbox.mbox = NULL; | ||
223 | } | ||
224 | if (itv->enc_mbox.mbox == NULL) | ||
225 | return -ENODEV; | ||
226 | |||
227 | if (!itv->has_cx23415) | ||
228 | return 0; | ||
229 | |||
230 | itv->dec_mbox.mbox = ivtv_search_mailbox(itv->dec_mem, IVTV_DECODER_SIZE); | ||
231 | if (itv->dec_mbox.mbox == NULL) | ||
232 | IVTV_ERR("Decoder mailbox not found\n"); | ||
233 | else if (itv->has_cx23415 && ivtv_vapi(itv, CX2341X_DEC_PING_FW, 0)) { | ||
234 | IVTV_ERR("Decoder firmware dead!\n"); | ||
235 | itv->dec_mbox.mbox = NULL; | ||
236 | } | ||
237 | return itv->dec_mbox.mbox ? 0 : -ENODEV; | ||
238 | } | ||
239 | |||
240 | void ivtv_init_mpeg_decoder(struct ivtv *itv) | ||
241 | { | ||
242 | u32 data[CX2341X_MBOX_MAX_DATA]; | ||
243 | long readbytes; | ||
244 | volatile u8 __iomem *mem_offset; | ||
245 | |||
246 | data[0] = 0; | ||
247 | data[1] = itv->params.width; /* YUV source width */ | ||
248 | data[2] = itv->params.height; | ||
249 | data[3] = itv->params.audio_properties; /* Audio settings to use, | ||
250 | bitmap. see docs. */ | ||
251 | if (ivtv_api(itv, CX2341X_DEC_SET_DECODER_SOURCE, 4, data)) { | ||
252 | IVTV_ERR("ivtv_init_mpeg_decoder failed to set decoder source\n"); | ||
253 | return; | ||
254 | } | ||
255 | |||
256 | if (ivtv_vapi(itv, CX2341X_DEC_START_PLAYBACK, 2, 0, 1) != 0) { | ||
257 | IVTV_ERR("ivtv_init_mpeg_decoder failed to start playback\n"); | ||
258 | return; | ||
259 | } | ||
260 | ivtv_api_get_data(&itv->dec_mbox, IVTV_MBOX_DMA, data); | ||
261 | mem_offset = itv->dec_mem + data[1]; | ||
262 | |||
263 | if ((readbytes = load_fw_direct(IVTV_DECODE_INIT_MPEG_FILENAME, | ||
264 | mem_offset, itv, IVTV_DECODE_INIT_MPEG_SIZE)) <= 0) { | ||
265 | IVTV_DEBUG_WARN("failed to read mpeg decoder initialisation file %s\n", | ||
266 | IVTV_DECODE_INIT_MPEG_FILENAME); | ||
267 | } else { | ||
268 | ivtv_vapi(itv, CX2341X_DEC_SCHED_DMA_FROM_HOST, 3, 0, readbytes, 0); | ||
269 | ivtv_sleep_timeout(HZ / 10, 0); | ||
270 | } | ||
271 | ivtv_vapi(itv, CX2341X_DEC_STOP_PLAYBACK, 4, 0, 0, 0, 1); | ||
272 | } | ||
diff --git a/drivers/media/video/ivtv/ivtv-firmware.h b/drivers/media/video/ivtv/ivtv-firmware.h new file mode 100644 index 000000000000..8b2ffe658905 --- /dev/null +++ b/drivers/media/video/ivtv/ivtv-firmware.h | |||
@@ -0,0 +1,25 @@ | |||
1 | /* | ||
2 | ivtv firmware functions. | ||
3 | Copyright (C) 2003-2004 Kevin Thayer <nufan_wfk at yahoo.com> | ||
4 | Copyright (C) 2004 Chris Kennedy <c@groovy.org> | ||
5 | Copyright (C) 2005-2007 Hans Verkuil <hverkuil@xs4all.nl> | ||
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 02111-1307 USA | ||
20 | */ | ||
21 | |||
22 | int ivtv_firmware_init(struct ivtv *itv); | ||
23 | void ivtv_firmware_versions(struct ivtv *itv); | ||
24 | void ivtv_halt_firmware(struct ivtv *itv); | ||
25 | void ivtv_init_mpeg_decoder(struct ivtv *itv); | ||
diff --git a/drivers/media/video/ivtv/ivtv-gpio.c b/drivers/media/video/ivtv/ivtv-gpio.c new file mode 100644 index 000000000000..bc8f8ca2961f --- /dev/null +++ b/drivers/media/video/ivtv/ivtv-gpio.c | |||
@@ -0,0 +1,307 @@ | |||
1 | /* | ||
2 | gpio functions. | ||
3 | Merging GPIO support into driver: | ||
4 | Copyright (C) 2004 Chris Kennedy <c@groovy.org> | ||
5 | Copyright (C) 2005-2007 Hans Verkuil <hverkuil@xs4all.nl> | ||
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 02111-1307 USA | ||
20 | */ | ||
21 | |||
22 | #include "ivtv-driver.h" | ||
23 | #include "ivtv-cards.h" | ||
24 | #include "ivtv-gpio.h" | ||
25 | #include <media/tuner.h> | ||
26 | |||
27 | /* | ||
28 | * GPIO assignment of Yuan MPG600/MPG160 | ||
29 | * | ||
30 | * bit 15 14 13 12 | 11 10 9 8 | 7 6 5 4 | 3 2 1 0 | ||
31 | * OUTPUT IN1 IN0 AM3 AM2 AM1 AM0 | ||
32 | * INPUT DM1 DM0 | ||
33 | * | ||
34 | * IN* : Input selection | ||
35 | * IN1 IN0 | ||
36 | * 1 1 N/A | ||
37 | * 1 0 Line | ||
38 | * 0 1 N/A | ||
39 | * 0 0 Tuner | ||
40 | * | ||
41 | * AM* : Audio Mode | ||
42 | * AM3 0: Normal 1: Mixed(Sub+Main channel) | ||
43 | * AM2 0: Subchannel 1: Main channel | ||
44 | * AM1 0: Stereo 1: Mono | ||
45 | * AM0 0: Normal 1: Mute | ||
46 | * | ||
47 | * DM* : Detected tuner audio Mode | ||
48 | * DM1 0: Stereo 1: Mono | ||
49 | * DM0 0: Multiplex 1: Normal | ||
50 | * | ||
51 | * GPIO Initial Settings | ||
52 | * MPG600 MPG160 | ||
53 | * DIR 0x3080 0x7080 | ||
54 | * OUTPUT 0x000C 0x400C | ||
55 | * | ||
56 | * Special thanks to Makoto Iguchi <iguchi@tahoo.org> and Mr. Anonymous | ||
57 | * for analyzing GPIO of MPG160. | ||
58 | * | ||
59 | ***************************************************************************** | ||
60 | * | ||
61 | * GPIO assignment of Avermedia M179 (per information direct from AVerMedia) | ||
62 | * | ||
63 | * bit 15 14 13 12 | 11 10 9 8 | 7 6 5 4 | 3 2 1 0 | ||
64 | * OUTPUT IN0 AM0 IN1 AM1 AM2 IN2 BR0 BR1 | ||
65 | * INPUT | ||
66 | * | ||
67 | * IN* : Input selection | ||
68 | * IN0 IN1 IN2 | ||
69 | * * 1 * Mute | ||
70 | * 0 0 0 Line-In | ||
71 | * 1 0 0 TV Tuner Audio | ||
72 | * 0 0 1 FM Audio | ||
73 | * 1 0 1 Mute | ||
74 | * | ||
75 | * AM* : Audio Mode | ||
76 | * AM0 AM1 AM2 | ||
77 | * 0 0 0 TV Tuner Audio: L_OUT=(L+R)/2, R_OUT=SAP | ||
78 | * 0 0 1 TV Tuner Audio: L_OUT=R_OUT=SAP (SAP) | ||
79 | * 0 1 0 TV Tuner Audio: L_OUT=L, R_OUT=R (stereo) | ||
80 | * 0 1 1 TV Tuner Audio: mute | ||
81 | * 1 * * TV Tuner Audio: L_OUT=R_OUT=(L+R)/2 (mono) | ||
82 | * | ||
83 | * BR* : Audio Sample Rate (BR stands for bitrate for some reason) | ||
84 | * BR0 BR1 | ||
85 | * 0 0 32 kHz | ||
86 | * 0 1 44.1 kHz | ||
87 | * 1 0 48 kHz | ||
88 | * | ||
89 | * DM* : Detected tuner audio Mode | ||
90 | * Unknown currently | ||
91 | * | ||
92 | * Special thanks to AVerMedia Technologies, Inc. and Jiun-Kuei Jung at | ||
93 | * AVerMedia for providing the GPIO information used to add support | ||
94 | * for the M179 cards. | ||
95 | */ | ||
96 | |||
97 | /********************* GPIO stuffs *********************/ | ||
98 | |||
99 | /* GPIO registers */ | ||
100 | #define IVTV_REG_GPIO_IN 0x9008 | ||
101 | #define IVTV_REG_GPIO_OUT 0x900c | ||
102 | #define IVTV_REG_GPIO_DIR 0x9020 | ||
103 | |||
104 | void ivtv_reset_ir_gpio(struct ivtv *itv) | ||
105 | { | ||
106 | int curdir, curout; | ||
107 | |||
108 | if (itv->card->type != IVTV_CARD_PVR_150) | ||
109 | return; | ||
110 | IVTV_DEBUG_INFO("Resetting PVR150 IR\n"); | ||
111 | curout = read_reg(IVTV_REG_GPIO_OUT); | ||
112 | curdir = read_reg(IVTV_REG_GPIO_DIR); | ||
113 | curdir |= 0x80; | ||
114 | write_reg(curdir, IVTV_REG_GPIO_DIR); | ||
115 | curout = (curout & ~0xF) | 1; | ||
116 | write_reg(curout, IVTV_REG_GPIO_OUT); | ||
117 | /* We could use something else for smaller time */ | ||
118 | current->state = TASK_INTERRUPTIBLE; | ||
119 | schedule_timeout(1); | ||
120 | curout |= 2; | ||
121 | write_reg(curout, IVTV_REG_GPIO_OUT); | ||
122 | curdir &= ~0x80; | ||
123 | write_reg(curdir, IVTV_REG_GPIO_DIR); | ||
124 | } | ||
125 | |||
126 | #ifdef HAVE_XC3028 | ||
127 | int ivtv_reset_tuner_gpio(enum v4l2_tuner_type mode, void *priv, int ptr) | ||
128 | { | ||
129 | int curdir, curout; | ||
130 | struct ivtv *itv = (struct ivtv *) priv; | ||
131 | |||
132 | if (itv->card->type != IVTV_CARD_PG600V2 || itv->options.tuner != TUNER_XCEIVE_XC3028) | ||
133 | return -EINVAL; | ||
134 | IVTV_INFO("Resetting tuner.\n"); | ||
135 | curout = read_reg(IVTV_REG_GPIO_OUT); | ||
136 | curdir = read_reg(IVTV_REG_GPIO_DIR); | ||
137 | curdir |= (1 << 12); /* GPIO bit 12 */ | ||
138 | |||
139 | curout &= ~(1 << 12); | ||
140 | write_reg(curout, IVTV_REG_GPIO_OUT); | ||
141 | current->state = TASK_INTERRUPTIBLE; | ||
142 | schedule_timeout(1); | ||
143 | |||
144 | curout |= (1 << 12); | ||
145 | write_reg(curout, IVTV_REG_GPIO_OUT); | ||
146 | current->state = TASK_INTERRUPTIBLE; | ||
147 | schedule_timeout(1); | ||
148 | |||
149 | return 0; | ||
150 | } | ||
151 | #endif | ||
152 | |||
153 | void ivtv_gpio_init(struct ivtv *itv) | ||
154 | { | ||
155 | if (itv->card->gpio_init.direction == 0) | ||
156 | return; | ||
157 | |||
158 | IVTV_DEBUG_INFO("GPIO initial dir: %08x out: %08x\n", | ||
159 | read_reg(IVTV_REG_GPIO_DIR), read_reg(IVTV_REG_GPIO_OUT)); | ||
160 | |||
161 | /* init output data then direction */ | ||
162 | write_reg(itv->card->gpio_init.initial_value, IVTV_REG_GPIO_OUT); | ||
163 | write_reg(itv->card->gpio_init.direction, IVTV_REG_GPIO_DIR); | ||
164 | } | ||
165 | |||
166 | static struct v4l2_queryctrl gpio_ctrl_mute = { | ||
167 | .id = V4L2_CID_AUDIO_MUTE, | ||
168 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
169 | .name = "Mute", | ||
170 | .minimum = 0, | ||
171 | .maximum = 1, | ||
172 | .step = 1, | ||
173 | .default_value = 1, | ||
174 | .flags = 0, | ||
175 | }; | ||
176 | |||
177 | int ivtv_gpio(struct ivtv *itv, unsigned int command, void *arg) | ||
178 | { | ||
179 | struct v4l2_tuner *tuner = arg; | ||
180 | struct v4l2_control *ctrl = arg; | ||
181 | struct v4l2_routing *route = arg; | ||
182 | u16 mask, data; | ||
183 | |||
184 | switch (command) { | ||
185 | case VIDIOC_INT_AUDIO_CLOCK_FREQ: | ||
186 | mask = itv->card->gpio_audio_freq.mask; | ||
187 | switch (*(u32 *)arg) { | ||
188 | case 32000: | ||
189 | data = itv->card->gpio_audio_freq.f32000; | ||
190 | break; | ||
191 | case 44100: | ||
192 | data = itv->card->gpio_audio_freq.f44100; | ||
193 | break; | ||
194 | case 48000: | ||
195 | default: | ||
196 | data = itv->card->gpio_audio_freq.f48000; | ||
197 | break; | ||
198 | } | ||
199 | break; | ||
200 | |||
201 | case VIDIOC_G_TUNER: | ||
202 | mask = itv->card->gpio_audio_detect.mask; | ||
203 | if (mask == 0 || (read_reg(IVTV_REG_GPIO_IN) & mask)) | ||
204 | tuner->rxsubchans = V4L2_TUNER_MODE_STEREO | | ||
205 | V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2; | ||
206 | else | ||
207 | tuner->rxsubchans = V4L2_TUNER_SUB_MONO; | ||
208 | return 0; | ||
209 | |||
210 | case VIDIOC_S_TUNER: | ||
211 | mask = itv->card->gpio_audio_mode.mask; | ||
212 | switch (tuner->audmode) { | ||
213 | case V4L2_TUNER_MODE_LANG1: | ||
214 | data = itv->card->gpio_audio_mode.lang1; | ||
215 | break; | ||
216 | case V4L2_TUNER_MODE_LANG2: | ||
217 | data = itv->card->gpio_audio_mode.lang2; | ||
218 | break; | ||
219 | case V4L2_TUNER_MODE_MONO: | ||
220 | data = itv->card->gpio_audio_mode.mono; | ||
221 | break; | ||
222 | case V4L2_TUNER_MODE_STEREO: | ||
223 | case V4L2_TUNER_MODE_LANG1_LANG2: | ||
224 | default: | ||
225 | data = itv->card->gpio_audio_mode.stereo; | ||
226 | break; | ||
227 | } | ||
228 | break; | ||
229 | |||
230 | case AUDC_SET_RADIO: | ||
231 | mask = itv->card->gpio_audio_input.mask; | ||
232 | data = itv->card->gpio_audio_input.radio; | ||
233 | break; | ||
234 | |||
235 | case VIDIOC_S_STD: | ||
236 | mask = itv->card->gpio_audio_input.mask; | ||
237 | data = itv->card->gpio_audio_input.tuner; | ||
238 | break; | ||
239 | |||
240 | case VIDIOC_INT_S_AUDIO_ROUTING: | ||
241 | if (route->input > 2) | ||
242 | return -EINVAL; | ||
243 | mask = itv->card->gpio_audio_input.mask; | ||
244 | switch (route->input) { | ||
245 | case 0: | ||
246 | data = itv->card->gpio_audio_input.tuner; | ||
247 | break; | ||
248 | case 1: | ||
249 | data = itv->card->gpio_audio_input.linein; | ||
250 | break; | ||
251 | case 2: | ||
252 | default: | ||
253 | data = itv->card->gpio_audio_input.radio; | ||
254 | break; | ||
255 | } | ||
256 | break; | ||
257 | |||
258 | case VIDIOC_G_CTRL: | ||
259 | if (ctrl->id != V4L2_CID_AUDIO_MUTE) | ||
260 | return -EINVAL; | ||
261 | mask = itv->card->gpio_audio_mute.mask; | ||
262 | data = itv->card->gpio_audio_mute.mute; | ||
263 | ctrl->value = (read_reg(IVTV_REG_GPIO_OUT) & mask) == data; | ||
264 | return 0; | ||
265 | |||
266 | case VIDIOC_S_CTRL: | ||
267 | if (ctrl->id != V4L2_CID_AUDIO_MUTE) | ||
268 | return -EINVAL; | ||
269 | mask = itv->card->gpio_audio_mute.mask; | ||
270 | data = ctrl->value ? itv->card->gpio_audio_mute.mute : 0; | ||
271 | break; | ||
272 | |||
273 | case VIDIOC_QUERYCTRL: | ||
274 | { | ||
275 | struct v4l2_queryctrl *qc = arg; | ||
276 | |||
277 | if (qc->id != V4L2_CID_AUDIO_MUTE) | ||
278 | return -EINVAL; | ||
279 | *qc = gpio_ctrl_mute; | ||
280 | return 0; | ||
281 | } | ||
282 | |||
283 | case VIDIOC_LOG_STATUS: | ||
284 | IVTV_INFO("GPIO status: DIR=0x%04x OUT=0x%04x IN=0x%04x\n", | ||
285 | read_reg(IVTV_REG_GPIO_DIR), read_reg(IVTV_REG_GPIO_OUT), | ||
286 | read_reg(IVTV_REG_GPIO_IN)); | ||
287 | return 0; | ||
288 | |||
289 | case VIDIOC_INT_S_VIDEO_ROUTING: | ||
290 | if (route->input > 2) /* 0:Tuner 1:Composite 2:S-Video */ | ||
291 | return -EINVAL; | ||
292 | mask = itv->card->gpio_video_input.mask; | ||
293 | if (route->input == 0) | ||
294 | data = itv->card->gpio_video_input.tuner; | ||
295 | else if (route->input == 1) | ||
296 | data = itv->card->gpio_video_input.composite; | ||
297 | else | ||
298 | data = itv->card->gpio_video_input.svideo; | ||
299 | break; | ||
300 | |||
301 | default: | ||
302 | return -EINVAL; | ||
303 | } | ||
304 | if (mask) | ||
305 | write_reg((read_reg(IVTV_REG_GPIO_OUT) & ~mask) | (data & mask), IVTV_REG_GPIO_OUT); | ||
306 | return 0; | ||
307 | } | ||
diff --git a/drivers/media/video/ivtv/ivtv-gpio.h b/drivers/media/video/ivtv/ivtv-gpio.h new file mode 100644 index 000000000000..c301d2a39346 --- /dev/null +++ b/drivers/media/video/ivtv/ivtv-gpio.h | |||
@@ -0,0 +1,25 @@ | |||
1 | /* | ||
2 | gpio functions. | ||
3 | Copyright (C) 2004 Chris Kennedy <c@groovy.org> | ||
4 | Copyright (C) 2005-2007 Hans Verkuil <hverkuil@xs4all.nl> | ||
5 | |||
6 | This program is free software; you can redistribute it and/or modify | ||
7 | it under the terms of the GNU General Public License as published by | ||
8 | the Free Software Foundation; either version 2 of the License, or | ||
9 | (at your option) any later version. | ||
10 | |||
11 | This program is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program; if not, write to the Free Software | ||
18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | */ | ||
20 | |||
21 | /* GPIO stuff */ | ||
22 | void ivtv_gpio_init(struct ivtv *itv); | ||
23 | void ivtv_reset_ir_gpio(struct ivtv *itv); | ||
24 | int ivtv_reset_tuner_gpio(enum v4l2_tuner_type mode, void *priv, int ptr); | ||
25 | int ivtv_gpio(struct ivtv *itv, unsigned int command, void *arg); | ||
diff --git a/drivers/media/video/ivtv/ivtv-i2c.c b/drivers/media/video/ivtv/ivtv-i2c.c new file mode 100644 index 000000000000..17353415b0a3 --- /dev/null +++ b/drivers/media/video/ivtv/ivtv-i2c.c | |||
@@ -0,0 +1,750 @@ | |||
1 | /* | ||
2 | I2C functions | ||
3 | Copyright (C) 2003-2004 Kevin Thayer <nufan_wfk at yahoo.com> | ||
4 | Copyright (C) 2005-2007 Hans Verkuil <hverkuil@xs4all.nl> | ||
5 | |||
6 | This program is free software; you can redistribute it and/or modify | ||
7 | it under the terms of the GNU General Public License as published by | ||
8 | the Free Software Foundation; either version 2 of the License, or | ||
9 | (at your option) any later version. | ||
10 | |||
11 | This program is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program; if not, write to the Free Software | ||
18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | */ | ||
20 | |||
21 | /* | ||
22 | This file includes an i2c implementation that was reverse engineered | ||
23 | from the Hauppauge windows driver. Older ivtv versions used i2c-algo-bit, | ||
24 | which whilst fine under most circumstances, had trouble with the Zilog | ||
25 | CPU on the PVR-150 which handles IR functions (occasional inability to | ||
26 | communicate with the chip until it was reset) and also with the i2c | ||
27 | bus being completely unreachable when multiple PVR cards were present. | ||
28 | |||
29 | The implementation is very similar to i2c-algo-bit, but there are enough | ||
30 | subtle differences that the two are hard to merge. The general strategy | ||
31 | employed by i2c-algo-bit is to use udelay() to implement the timing | ||
32 | when putting out bits on the scl/sda lines. The general strategy taken | ||
33 | here is to poll the lines for state changes (see ivtv_waitscl and | ||
34 | ivtv_waitsda). In addition there are small delays at various locations | ||
35 | which poll the SCL line 5 times (ivtv_scldelay). I would guess that | ||
36 | since this is memory mapped I/O that the length of those delays is tied | ||
37 | to the PCI bus clock. There is some extra code to do with recovery | ||
38 | and retries. Since it is not known what causes the actual i2c problems | ||
39 | in the first place, the only goal if one was to attempt to use | ||
40 | i2c-algo-bit would be to try to make it follow the same code path. | ||
41 | This would be a lot of work, and I'm also not convinced that it would | ||
42 | provide a generic benefit to i2c-algo-bit. Therefore consider this | ||
43 | an engineering solution -- not pretty, but it works. | ||
44 | |||
45 | Some more general comments about what we are doing: | ||
46 | |||
47 | The i2c bus is a 2 wire serial bus, with clock (SCL) and data (SDA) | ||
48 | lines. To communicate on the bus (as a master, we don't act as a slave), | ||
49 | we first initiate a start condition (ivtv_start). We then write the | ||
50 | address of the device that we want to communicate with, along with a flag | ||
51 | that indicates whether this is a read or a write. The slave then issues | ||
52 | an ACK signal (ivtv_ack), which tells us that it is ready for reading / | ||
53 | writing. We then proceed with reading or writing (ivtv_read/ivtv_write), | ||
54 | and finally issue a stop condition (ivtv_stop) to make the bus available | ||
55 | to other masters. | ||
56 | |||
57 | There is an additional form of transaction where a write may be | ||
58 | immediately followed by a read. In this case, there is no intervening | ||
59 | stop condition. (Only the msp3400 chip uses this method of data transfer). | ||
60 | */ | ||
61 | |||
62 | #include "ivtv-driver.h" | ||
63 | #include "ivtv-cards.h" | ||
64 | #include "ivtv-gpio.h" | ||
65 | |||
66 | #include <media/ir-kbd-i2c.h> | ||
67 | |||
68 | /* i2c implementation for cx23415/6 chip, ivtv project. | ||
69 | * Author: Kevin Thayer (nufan_wfk at yahoo.com) | ||
70 | */ | ||
71 | /* i2c stuff */ | ||
72 | #define IVTV_REG_I2C_SETSCL_OFFSET 0x7000 | ||
73 | #define IVTV_REG_I2C_SETSDA_OFFSET 0x7004 | ||
74 | #define IVTV_REG_I2C_GETSCL_OFFSET 0x7008 | ||
75 | #define IVTV_REG_I2C_GETSDA_OFFSET 0x700c | ||
76 | |||
77 | #ifndef I2C_ADAP_CLASS_TV_ANALOG | ||
78 | #define I2C_ADAP_CLASS_TV_ANALOG I2C_CLASS_TV_ANALOG | ||
79 | #endif /* I2C_ADAP_CLASS_TV_ANALOG */ | ||
80 | |||
81 | #define IVTV_CS53L32A_I2C_ADDR 0x11 | ||
82 | #define IVTV_CX25840_I2C_ADDR 0x44 | ||
83 | #define IVTV_SAA7115_I2C_ADDR 0x21 | ||
84 | #define IVTV_SAA7127_I2C_ADDR 0x44 | ||
85 | #define IVTV_SAA717x_I2C_ADDR 0x21 | ||
86 | #define IVTV_MSP3400_I2C_ADDR 0x40 | ||
87 | #define IVTV_HAUPPAUGE_I2C_ADDR 0x50 | ||
88 | #define IVTV_WM8739_I2C_ADDR 0x1a | ||
89 | #define IVTV_WM8775_I2C_ADDR 0x1b | ||
90 | #define IVTV_TEA5767_I2C_ADDR 0x60 | ||
91 | #define IVTV_UPD64031A_I2C_ADDR 0x12 | ||
92 | #define IVTV_UPD64083_I2C_ADDR 0x5c | ||
93 | #define IVTV_TDA985X_I2C_ADDR 0x5b | ||
94 | |||
95 | /* This array should match the IVTV_HW_ defines */ | ||
96 | static const u8 hw_driverids[] = { | ||
97 | I2C_DRIVERID_CX25840, | ||
98 | I2C_DRIVERID_SAA711X, | ||
99 | I2C_DRIVERID_SAA7127, | ||
100 | I2C_DRIVERID_MSP3400, | ||
101 | I2C_DRIVERID_TUNER, | ||
102 | I2C_DRIVERID_WM8775, | ||
103 | I2C_DRIVERID_CS53L32A, | ||
104 | I2C_DRIVERID_TVEEPROM, | ||
105 | I2C_DRIVERID_SAA711X, | ||
106 | I2C_DRIVERID_TVAUDIO, | ||
107 | I2C_DRIVERID_UPD64031A, | ||
108 | I2C_DRIVERID_UPD64083, | ||
109 | I2C_DRIVERID_SAA717X, | ||
110 | I2C_DRIVERID_WM8739, | ||
111 | 0 /* IVTV_HW_GPIO dummy driver ID */ | ||
112 | }; | ||
113 | |||
114 | /* This array should match the IVTV_HW_ defines */ | ||
115 | static const char * const hw_drivernames[] = { | ||
116 | "cx2584x", | ||
117 | "saa7115", | ||
118 | "saa7127", | ||
119 | "msp3400", | ||
120 | "tuner", | ||
121 | "wm8775", | ||
122 | "cs53l32a", | ||
123 | "tveeprom", | ||
124 | "saa7114", | ||
125 | "tvaudio", | ||
126 | "upd64031a", | ||
127 | "upd64083", | ||
128 | "saa717x", | ||
129 | "wm8739", | ||
130 | "gpio", | ||
131 | }; | ||
132 | |||
133 | static int attach_inform(struct i2c_client *client) | ||
134 | { | ||
135 | struct ivtv *itv = (struct ivtv *)i2c_get_adapdata(client->adapter); | ||
136 | int i; | ||
137 | |||
138 | IVTV_DEBUG_I2C("i2c client attach\n"); | ||
139 | for (i = 0; i < I2C_CLIENTS_MAX; i++) { | ||
140 | if (itv->i2c_clients[i] == NULL) { | ||
141 | itv->i2c_clients[i] = client; | ||
142 | break; | ||
143 | } | ||
144 | } | ||
145 | if (i == I2C_CLIENTS_MAX) { | ||
146 | IVTV_ERR("insufficient room for new I2C client!\n"); | ||
147 | } | ||
148 | return 0; | ||
149 | } | ||
150 | |||
151 | static int detach_inform(struct i2c_client *client) | ||
152 | { | ||
153 | int i; | ||
154 | struct ivtv *itv = (struct ivtv *)i2c_get_adapdata(client->adapter); | ||
155 | |||
156 | IVTV_DEBUG_I2C("i2c client detach\n"); | ||
157 | for (i = 0; i < I2C_CLIENTS_MAX; i++) { | ||
158 | if (itv->i2c_clients[i] == client) { | ||
159 | itv->i2c_clients[i] = NULL; | ||
160 | break; | ||
161 | } | ||
162 | } | ||
163 | IVTV_DEBUG_I2C("i2c detach [client=%s,%s]\n", | ||
164 | client->name, (i < I2C_CLIENTS_MAX) ? "ok" : "failed"); | ||
165 | |||
166 | return 0; | ||
167 | } | ||
168 | |||
169 | /* Set the serial clock line to the desired state */ | ||
170 | static void ivtv_setscl(struct ivtv *itv, int state) | ||
171 | { | ||
172 | /* write them out */ | ||
173 | /* write bits are inverted */ | ||
174 | write_reg(~state, IVTV_REG_I2C_SETSCL_OFFSET); | ||
175 | } | ||
176 | |||
177 | /* Set the serial data line to the desired state */ | ||
178 | static void ivtv_setsda(struct ivtv *itv, int state) | ||
179 | { | ||
180 | /* write them out */ | ||
181 | /* write bits are inverted */ | ||
182 | write_reg(~state & 1, IVTV_REG_I2C_SETSDA_OFFSET); | ||
183 | } | ||
184 | |||
185 | /* Read the serial clock line */ | ||
186 | static int ivtv_getscl(struct ivtv *itv) | ||
187 | { | ||
188 | return read_reg(IVTV_REG_I2C_GETSCL_OFFSET) & 1; | ||
189 | } | ||
190 | |||
191 | /* Read the serial data line */ | ||
192 | static int ivtv_getsda(struct ivtv *itv) | ||
193 | { | ||
194 | return read_reg(IVTV_REG_I2C_GETSDA_OFFSET) & 1; | ||
195 | } | ||
196 | |||
197 | /* Implement a short delay by polling the serial clock line */ | ||
198 | static void ivtv_scldelay(struct ivtv *itv) | ||
199 | { | ||
200 | int i; | ||
201 | |||
202 | for (i = 0; i < 5; ++i) | ||
203 | ivtv_getscl(itv); | ||
204 | } | ||
205 | |||
206 | /* Wait for the serial clock line to become set to a specific value */ | ||
207 | static int ivtv_waitscl(struct ivtv *itv, int val) | ||
208 | { | ||
209 | int i; | ||
210 | |||
211 | ivtv_scldelay(itv); | ||
212 | for (i = 0; i < 1000; ++i) { | ||
213 | if (ivtv_getscl(itv) == val) | ||
214 | return 1; | ||
215 | } | ||
216 | return 0; | ||
217 | } | ||
218 | |||
219 | /* Wait for the serial data line to become set to a specific value */ | ||
220 | static int ivtv_waitsda(struct ivtv *itv, int val) | ||
221 | { | ||
222 | int i; | ||
223 | |||
224 | ivtv_scldelay(itv); | ||
225 | for (i = 0; i < 1000; ++i) { | ||
226 | if (ivtv_getsda(itv) == val) | ||
227 | return 1; | ||
228 | } | ||
229 | return 0; | ||
230 | } | ||
231 | |||
232 | /* Wait for the slave to issue an ACK */ | ||
233 | static int ivtv_ack(struct ivtv *itv) | ||
234 | { | ||
235 | int ret = 0; | ||
236 | |||
237 | if (ivtv_getscl(itv) == 1) { | ||
238 | IVTV_DEBUG_I2C("SCL was high starting an ack\n"); | ||
239 | ivtv_setscl(itv, 0); | ||
240 | if (!ivtv_waitscl(itv, 0)) { | ||
241 | IVTV_DEBUG_I2C("Could not set SCL low starting an ack\n"); | ||
242 | return -EREMOTEIO; | ||
243 | } | ||
244 | } | ||
245 | ivtv_setsda(itv, 1); | ||
246 | ivtv_scldelay(itv); | ||
247 | ivtv_setscl(itv, 1); | ||
248 | if (!ivtv_waitsda(itv, 0)) { | ||
249 | IVTV_DEBUG_I2C("Slave did not ack\n"); | ||
250 | ret = -EREMOTEIO; | ||
251 | } | ||
252 | ivtv_setscl(itv, 0); | ||
253 | if (!ivtv_waitscl(itv, 0)) { | ||
254 | IVTV_DEBUG_I2C("Failed to set SCL low after ACK\n"); | ||
255 | ret = -EREMOTEIO; | ||
256 | } | ||
257 | return ret; | ||
258 | } | ||
259 | |||
260 | /* Write a single byte to the i2c bus and wait for the slave to ACK */ | ||
261 | static int ivtv_sendbyte(struct ivtv *itv, unsigned char byte) | ||
262 | { | ||
263 | int i, bit; | ||
264 | |||
265 | IVTV_DEBUG_I2C("write %x\n",byte); | ||
266 | for (i = 0; i < 8; ++i, byte<<=1) { | ||
267 | ivtv_setscl(itv, 0); | ||
268 | if (!ivtv_waitscl(itv, 0)) { | ||
269 | IVTV_DEBUG_I2C("Error setting SCL low\n"); | ||
270 | return -EREMOTEIO; | ||
271 | } | ||
272 | bit = (byte>>7)&1; | ||
273 | ivtv_setsda(itv, bit); | ||
274 | if (!ivtv_waitsda(itv, bit)) { | ||
275 | IVTV_DEBUG_I2C("Error setting SDA\n"); | ||
276 | return -EREMOTEIO; | ||
277 | } | ||
278 | ivtv_setscl(itv, 1); | ||
279 | if (!ivtv_waitscl(itv, 1)) { | ||
280 | IVTV_DEBUG_I2C("Slave not ready for bit\n"); | ||
281 | return -EREMOTEIO; | ||
282 | } | ||
283 | } | ||
284 | ivtv_setscl(itv, 0); | ||
285 | if (!ivtv_waitscl(itv, 0)) { | ||
286 | IVTV_DEBUG_I2C("Error setting SCL low\n"); | ||
287 | return -EREMOTEIO; | ||
288 | } | ||
289 | return ivtv_ack(itv); | ||
290 | } | ||
291 | |||
292 | /* Read a byte from the i2c bus and send a NACK if applicable (i.e. for the | ||
293 | final byte) */ | ||
294 | static int ivtv_readbyte(struct ivtv *itv, unsigned char *byte, int nack) | ||
295 | { | ||
296 | int i; | ||
297 | |||
298 | *byte = 0; | ||
299 | |||
300 | ivtv_setsda(itv, 1); | ||
301 | ivtv_scldelay(itv); | ||
302 | for (i = 0; i < 8; ++i) { | ||
303 | ivtv_setscl(itv, 0); | ||
304 | ivtv_scldelay(itv); | ||
305 | ivtv_setscl(itv, 1); | ||
306 | if (!ivtv_waitscl(itv, 1)) { | ||
307 | IVTV_DEBUG_I2C("Error setting SCL high\n"); | ||
308 | return -EREMOTEIO; | ||
309 | } | ||
310 | *byte = ((*byte)<<1)|ivtv_getsda(itv); | ||
311 | } | ||
312 | ivtv_setscl(itv, 0); | ||
313 | ivtv_scldelay(itv); | ||
314 | ivtv_setsda(itv, nack); | ||
315 | ivtv_scldelay(itv); | ||
316 | ivtv_setscl(itv, 1); | ||
317 | ivtv_scldelay(itv); | ||
318 | ivtv_setscl(itv, 0); | ||
319 | ivtv_scldelay(itv); | ||
320 | IVTV_DEBUG_I2C("read %x\n",*byte); | ||
321 | return 0; | ||
322 | } | ||
323 | |||
324 | /* Issue a start condition on the i2c bus to alert slaves to prepare for | ||
325 | an address write */ | ||
326 | static int ivtv_start(struct ivtv *itv) | ||
327 | { | ||
328 | int sda; | ||
329 | |||
330 | sda = ivtv_getsda(itv); | ||
331 | if (sda != 1) { | ||
332 | IVTV_DEBUG_I2C("SDA was low at start\n"); | ||
333 | ivtv_setsda(itv, 1); | ||
334 | if (!ivtv_waitsda(itv, 1)) { | ||
335 | IVTV_DEBUG_I2C("SDA stuck low\n"); | ||
336 | return -EREMOTEIO; | ||
337 | } | ||
338 | } | ||
339 | if (ivtv_getscl(itv) != 1) { | ||
340 | ivtv_setscl(itv, 1); | ||
341 | if (!ivtv_waitscl(itv, 1)) { | ||
342 | IVTV_DEBUG_I2C("SCL stuck low at start\n"); | ||
343 | return -EREMOTEIO; | ||
344 | } | ||
345 | } | ||
346 | ivtv_setsda(itv, 0); | ||
347 | ivtv_scldelay(itv); | ||
348 | return 0; | ||
349 | } | ||
350 | |||
351 | /* Issue a stop condition on the i2c bus to release it */ | ||
352 | static int ivtv_stop(struct ivtv *itv) | ||
353 | { | ||
354 | int i; | ||
355 | |||
356 | if (ivtv_getscl(itv) != 0) { | ||
357 | IVTV_DEBUG_I2C("SCL not low when stopping\n"); | ||
358 | ivtv_setscl(itv, 0); | ||
359 | if (!ivtv_waitscl(itv, 0)) { | ||
360 | IVTV_DEBUG_I2C("SCL could not be set low\n"); | ||
361 | } | ||
362 | } | ||
363 | ivtv_setsda(itv, 0); | ||
364 | ivtv_scldelay(itv); | ||
365 | ivtv_setscl(itv, 1); | ||
366 | if (!ivtv_waitscl(itv, 1)) { | ||
367 | IVTV_DEBUG_I2C("SCL could not be set high\n"); | ||
368 | return -EREMOTEIO; | ||
369 | } | ||
370 | ivtv_scldelay(itv); | ||
371 | ivtv_setsda(itv, 1); | ||
372 | if (!ivtv_waitsda(itv, 1)) { | ||
373 | IVTV_DEBUG_I2C("resetting I2C\n"); | ||
374 | for (i = 0; i < 16; ++i) { | ||
375 | ivtv_setscl(itv, 0); | ||
376 | ivtv_scldelay(itv); | ||
377 | ivtv_setscl(itv, 1); | ||
378 | ivtv_scldelay(itv); | ||
379 | ivtv_setsda(itv, 1); | ||
380 | } | ||
381 | ivtv_waitsda(itv, 1); | ||
382 | return -EREMOTEIO; | ||
383 | } | ||
384 | return 0; | ||
385 | } | ||
386 | |||
387 | /* Write a message to the given i2c slave. do_stop may be 0 to prevent | ||
388 | issuing the i2c stop condition (when following with a read) */ | ||
389 | static int ivtv_write(struct ivtv *itv, unsigned char addr, unsigned char *data, u32 len, int do_stop) | ||
390 | { | ||
391 | int retry, ret = -EREMOTEIO; | ||
392 | u32 i; | ||
393 | |||
394 | for (retry = 0; ret != 0 && retry < 8; ++retry) { | ||
395 | ret = ivtv_start(itv); | ||
396 | |||
397 | if (ret == 0) { | ||
398 | ret = ivtv_sendbyte(itv, addr<<1); | ||
399 | for (i = 0; ret == 0 && i < len; ++i) | ||
400 | ret = ivtv_sendbyte(itv, data[i]); | ||
401 | } | ||
402 | if (ret != 0 || do_stop) { | ||
403 | ivtv_stop(itv); | ||
404 | } | ||
405 | } | ||
406 | if (ret) | ||
407 | IVTV_DEBUG_I2C("i2c write to %x failed\n", addr); | ||
408 | return ret; | ||
409 | } | ||
410 | |||
411 | /* Read data from the given i2c slave. A stop condition is always issued. */ | ||
412 | static int ivtv_read(struct ivtv *itv, unsigned char addr, unsigned char *data, u32 len) | ||
413 | { | ||
414 | int retry, ret = -EREMOTEIO; | ||
415 | u32 i; | ||
416 | |||
417 | for (retry = 0; ret != 0 && retry < 8; ++retry) { | ||
418 | ret = ivtv_start(itv); | ||
419 | if (ret == 0) | ||
420 | ret = ivtv_sendbyte(itv, (addr << 1) | 1); | ||
421 | for (i = 0; ret == 0 && i < len; ++i) { | ||
422 | ret = ivtv_readbyte(itv, &data[i], i == len - 1); | ||
423 | } | ||
424 | ivtv_stop(itv); | ||
425 | } | ||
426 | if (ret) | ||
427 | IVTV_DEBUG_I2C("i2c read from %x failed\n", addr); | ||
428 | return ret; | ||
429 | } | ||
430 | |||
431 | /* Kernel i2c transfer implementation. Takes a number of messages to be read | ||
432 | or written. If a read follows a write, this will occur without an | ||
433 | intervening stop condition */ | ||
434 | static int ivtv_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num) | ||
435 | { | ||
436 | struct ivtv *itv = i2c_get_adapdata(i2c_adap); | ||
437 | int retval; | ||
438 | int i; | ||
439 | |||
440 | mutex_lock(&itv->i2c_bus_lock); | ||
441 | for (i = retval = 0; retval == 0 && i < num; i++) { | ||
442 | if (msgs[i].flags & I2C_M_RD) | ||
443 | retval = ivtv_read(itv, msgs[i].addr, msgs[i].buf, msgs[i].len); | ||
444 | else { | ||
445 | /* if followed by a read, don't stop */ | ||
446 | int stop = !(i + 1 < num && msgs[i + 1].flags == I2C_M_RD); | ||
447 | |||
448 | retval = ivtv_write(itv, msgs[i].addr, msgs[i].buf, msgs[i].len, stop); | ||
449 | } | ||
450 | } | ||
451 | mutex_unlock(&itv->i2c_bus_lock); | ||
452 | return retval ? retval : num; | ||
453 | } | ||
454 | |||
455 | /* Kernel i2c capabilities */ | ||
456 | static u32 ivtv_functionality(struct i2c_adapter *adap) | ||
457 | { | ||
458 | return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; | ||
459 | } | ||
460 | |||
461 | static struct i2c_algorithm ivtv_algo = { | ||
462 | .master_xfer = ivtv_xfer, | ||
463 | .functionality = ivtv_functionality, | ||
464 | }; | ||
465 | |||
466 | /* template for our-bit banger */ | ||
467 | static struct i2c_adapter ivtv_i2c_adap_hw_template = { | ||
468 | .name = "ivtv i2c driver", | ||
469 | .id = I2C_HW_B_CX2341X, | ||
470 | .algo = &ivtv_algo, | ||
471 | .algo_data = NULL, /* filled from template */ | ||
472 | .client_register = attach_inform, | ||
473 | .client_unregister = detach_inform, | ||
474 | .owner = THIS_MODULE, | ||
475 | #ifdef I2C_ADAP_CLASS_TV_ANALOG | ||
476 | .class = I2C_ADAP_CLASS_TV_ANALOG, | ||
477 | #endif | ||
478 | }; | ||
479 | |||
480 | static void ivtv_setscl_old(void *data, int state) | ||
481 | { | ||
482 | struct ivtv *itv = (struct ivtv *)data; | ||
483 | |||
484 | if (state) | ||
485 | itv->i2c_state |= 0x01; | ||
486 | else | ||
487 | itv->i2c_state &= ~0x01; | ||
488 | |||
489 | /* write them out */ | ||
490 | /* write bits are inverted */ | ||
491 | write_reg(~itv->i2c_state, IVTV_REG_I2C_SETSCL_OFFSET); | ||
492 | } | ||
493 | |||
494 | static void ivtv_setsda_old(void *data, int state) | ||
495 | { | ||
496 | struct ivtv *itv = (struct ivtv *)data; | ||
497 | |||
498 | if (state) | ||
499 | itv->i2c_state |= 0x01; | ||
500 | else | ||
501 | itv->i2c_state &= ~0x01; | ||
502 | |||
503 | /* write them out */ | ||
504 | /* write bits are inverted */ | ||
505 | write_reg(~itv->i2c_state, IVTV_REG_I2C_SETSDA_OFFSET); | ||
506 | } | ||
507 | |||
508 | static int ivtv_getscl_old(void *data) | ||
509 | { | ||
510 | struct ivtv *itv = (struct ivtv *)data; | ||
511 | |||
512 | return read_reg(IVTV_REG_I2C_GETSCL_OFFSET) & 1; | ||
513 | } | ||
514 | |||
515 | static int ivtv_getsda_old(void *data) | ||
516 | { | ||
517 | struct ivtv *itv = (struct ivtv *)data; | ||
518 | |||
519 | return read_reg(IVTV_REG_I2C_GETSDA_OFFSET) & 1; | ||
520 | } | ||
521 | |||
522 | /* template for i2c-bit-algo */ | ||
523 | static struct i2c_adapter ivtv_i2c_adap_template = { | ||
524 | .name = "ivtv i2c driver", | ||
525 | .id = I2C_HW_B_CX2341X, /* algo-bit is OR'd with this */ | ||
526 | .algo = NULL, /* set by i2c-algo-bit */ | ||
527 | .algo_data = NULL, /* filled from template */ | ||
528 | .client_register = attach_inform, | ||
529 | .client_unregister = detach_inform, | ||
530 | .owner = THIS_MODULE, | ||
531 | #ifdef I2C_ADAP_CLASS_TV_ANALOG | ||
532 | .class = I2C_ADAP_CLASS_TV_ANALOG, | ||
533 | #endif | ||
534 | }; | ||
535 | |||
536 | static struct i2c_algo_bit_data ivtv_i2c_algo_template = { | ||
537 | NULL, /* ?? */ | ||
538 | ivtv_setsda_old, /* setsda function */ | ||
539 | ivtv_setscl_old, /* " */ | ||
540 | ivtv_getsda_old, /* " */ | ||
541 | ivtv_getscl_old, /* " */ | ||
542 | 10, /* udelay */ | ||
543 | 200 /* timeout */ | ||
544 | }; | ||
545 | |||
546 | static struct i2c_client ivtv_i2c_client_template = { | ||
547 | .name = "ivtv internal use only", | ||
548 | }; | ||
549 | |||
550 | int ivtv_call_i2c_client(struct ivtv *itv, int addr, unsigned int cmd, void *arg) | ||
551 | { | ||
552 | struct i2c_client *client; | ||
553 | int retval; | ||
554 | int i; | ||
555 | |||
556 | IVTV_DEBUG_I2C("call_i2c_client addr=%02x\n", addr); | ||
557 | for (i = 0; i < I2C_CLIENTS_MAX; i++) { | ||
558 | client = itv->i2c_clients[i]; | ||
559 | if (client == NULL) { | ||
560 | continue; | ||
561 | } | ||
562 | if (client->driver->command == NULL) { | ||
563 | continue; | ||
564 | } | ||
565 | if (addr == client->addr) { | ||
566 | retval = client->driver->command(client, cmd, arg); | ||
567 | return retval; | ||
568 | } | ||
569 | } | ||
570 | IVTV_ERR("i2c addr 0x%02x not found for command 0x%x!\n", addr, cmd); | ||
571 | return -ENODEV; | ||
572 | } | ||
573 | |||
574 | /* Find the i2c device based on the driver ID and return | ||
575 | its i2c address or -ENODEV if no matching device was found. */ | ||
576 | int ivtv_i2c_id_addr(struct ivtv *itv, u32 id) | ||
577 | { | ||
578 | struct i2c_client *client; | ||
579 | int retval = -ENODEV; | ||
580 | int i; | ||
581 | |||
582 | for (i = 0; i < I2C_CLIENTS_MAX; i++) { | ||
583 | client = itv->i2c_clients[i]; | ||
584 | if (client == NULL) | ||
585 | continue; | ||
586 | if (id == client->driver->id) { | ||
587 | retval = client->addr; | ||
588 | break; | ||
589 | } | ||
590 | } | ||
591 | return retval; | ||
592 | } | ||
593 | |||
594 | /* Find the i2c device name matching the DRIVERID */ | ||
595 | static const char *ivtv_i2c_id_name(u32 id) | ||
596 | { | ||
597 | int i; | ||
598 | |||
599 | for (i = 0; i < ARRAY_SIZE(hw_driverids); i++) | ||
600 | if (hw_driverids[i] == id) | ||
601 | return hw_drivernames[i]; | ||
602 | return "unknown device"; | ||
603 | } | ||
604 | |||
605 | /* Find the i2c device name matching the IVTV_HW_ flag */ | ||
606 | static const char *ivtv_i2c_hw_name(u32 hw) | ||
607 | { | ||
608 | int i; | ||
609 | |||
610 | for (i = 0; i < ARRAY_SIZE(hw_driverids); i++) | ||
611 | if (1 << i == hw) | ||
612 | return hw_drivernames[i]; | ||
613 | return "unknown device"; | ||
614 | } | ||
615 | |||
616 | /* Find the i2c device matching the IVTV_HW_ flag and return | ||
617 | its i2c address or -ENODEV if no matching device was found. */ | ||
618 | int ivtv_i2c_hw_addr(struct ivtv *itv, u32 hw) | ||
619 | { | ||
620 | int i; | ||
621 | |||
622 | for (i = 0; i < ARRAY_SIZE(hw_driverids); i++) | ||
623 | if (1 << i == hw) | ||
624 | return ivtv_i2c_id_addr(itv, hw_driverids[i]); | ||
625 | return -ENODEV; | ||
626 | } | ||
627 | |||
628 | /* Calls i2c device based on IVTV_HW_ flag. If hw == 0, then do nothing. | ||
629 | If hw == IVTV_HW_GPIO then call the gpio handler. */ | ||
630 | int ivtv_i2c_hw(struct ivtv *itv, u32 hw, unsigned int cmd, void *arg) | ||
631 | { | ||
632 | int addr; | ||
633 | |||
634 | if (hw == IVTV_HW_GPIO) | ||
635 | return ivtv_gpio(itv, cmd, arg); | ||
636 | if (hw == 0) | ||
637 | return 0; | ||
638 | |||
639 | addr = ivtv_i2c_hw_addr(itv, hw); | ||
640 | if (addr < 0) { | ||
641 | IVTV_ERR("i2c hardware 0x%08x (%s) not found for command 0x%x!\n", | ||
642 | hw, ivtv_i2c_hw_name(hw), cmd); | ||
643 | return addr; | ||
644 | } | ||
645 | return ivtv_call_i2c_client(itv, addr, cmd, arg); | ||
646 | } | ||
647 | |||
648 | /* Calls i2c device based on I2C driver ID. */ | ||
649 | int ivtv_i2c_id(struct ivtv *itv, u32 id, unsigned int cmd, void *arg) | ||
650 | { | ||
651 | int addr; | ||
652 | |||
653 | addr = ivtv_i2c_id_addr(itv, id); | ||
654 | if (addr < 0) { | ||
655 | IVTV_ERR("i2c ID 0x%08x (%s) not found for command 0x%x!\n", | ||
656 | id, ivtv_i2c_id_name(id), cmd); | ||
657 | return addr; | ||
658 | } | ||
659 | return ivtv_call_i2c_client(itv, addr, cmd, arg); | ||
660 | } | ||
661 | |||
662 | int ivtv_cx25840(struct ivtv *itv, unsigned int cmd, void *arg) | ||
663 | { | ||
664 | return ivtv_call_i2c_client(itv, IVTV_CX25840_I2C_ADDR, cmd, arg); | ||
665 | } | ||
666 | |||
667 | int ivtv_saa7115(struct ivtv *itv, unsigned int cmd, void *arg) | ||
668 | { | ||
669 | return ivtv_call_i2c_client(itv, IVTV_SAA7115_I2C_ADDR, cmd, arg); | ||
670 | } | ||
671 | |||
672 | int ivtv_saa7127(struct ivtv *itv, unsigned int cmd, void *arg) | ||
673 | { | ||
674 | return ivtv_call_i2c_client(itv, IVTV_SAA7127_I2C_ADDR, cmd, arg); | ||
675 | } | ||
676 | |||
677 | int ivtv_saa717x(struct ivtv *itv, unsigned int cmd, void *arg) | ||
678 | { | ||
679 | return ivtv_call_i2c_client(itv, IVTV_SAA717x_I2C_ADDR, cmd, arg); | ||
680 | } | ||
681 | |||
682 | int ivtv_msp34xx(struct ivtv *itv, unsigned int cmd, void *arg) | ||
683 | { | ||
684 | return ivtv_call_i2c_client(itv, IVTV_MSP3400_I2C_ADDR, cmd, arg); | ||
685 | } | ||
686 | |||
687 | int ivtv_upd64031a(struct ivtv *itv, unsigned int cmd, void *arg) | ||
688 | { | ||
689 | return ivtv_call_i2c_client(itv, IVTV_UPD64031A_I2C_ADDR, cmd, arg); | ||
690 | } | ||
691 | |||
692 | int ivtv_upd64083(struct ivtv *itv, unsigned int cmd, void *arg) | ||
693 | { | ||
694 | return ivtv_call_i2c_client(itv, IVTV_UPD64083_I2C_ADDR, cmd, arg); | ||
695 | } | ||
696 | |||
697 | /* broadcast cmd for all I2C clients and for the gpio subsystem */ | ||
698 | void ivtv_call_i2c_clients(struct ivtv *itv, unsigned int cmd, void *arg) | ||
699 | { | ||
700 | if (itv->i2c_adap.algo == NULL) { | ||
701 | IVTV_ERR("adapter is not set"); | ||
702 | return; | ||
703 | } | ||
704 | i2c_clients_command(&itv->i2c_adap, cmd, arg); | ||
705 | if (itv->hw_flags & IVTV_HW_GPIO) | ||
706 | ivtv_gpio(itv, cmd, arg); | ||
707 | } | ||
708 | |||
709 | /* init + register i2c algo-bit adapter */ | ||
710 | int __devinit init_ivtv_i2c(struct ivtv *itv) | ||
711 | { | ||
712 | IVTV_DEBUG_I2C("i2c init\n"); | ||
713 | |||
714 | if (itv->options.newi2c > 0) { | ||
715 | memcpy(&itv->i2c_adap, &ivtv_i2c_adap_hw_template, | ||
716 | sizeof(struct i2c_adapter)); | ||
717 | } else { | ||
718 | memcpy(&itv->i2c_adap, &ivtv_i2c_adap_template, | ||
719 | sizeof(struct i2c_adapter)); | ||
720 | memcpy(&itv->i2c_algo, &ivtv_i2c_algo_template, | ||
721 | sizeof(struct i2c_algo_bit_data)); | ||
722 | itv->i2c_algo.data = itv; | ||
723 | itv->i2c_adap.algo_data = &itv->i2c_algo; | ||
724 | } | ||
725 | |||
726 | sprintf(itv->i2c_adap.name + strlen(itv->i2c_adap.name), " #%d", | ||
727 | itv->num); | ||
728 | i2c_set_adapdata(&itv->i2c_adap, itv); | ||
729 | |||
730 | memcpy(&itv->i2c_client, &ivtv_i2c_client_template, | ||
731 | sizeof(struct i2c_client)); | ||
732 | itv->i2c_client.adapter = &itv->i2c_adap; | ||
733 | itv->i2c_adap.dev.parent = &itv->dev->dev; | ||
734 | |||
735 | IVTV_DEBUG_I2C("setting scl and sda to 1\n"); | ||
736 | ivtv_setscl(itv, 1); | ||
737 | ivtv_setsda(itv, 1); | ||
738 | |||
739 | if (itv->options.newi2c > 0) | ||
740 | return i2c_add_adapter(&itv->i2c_adap); | ||
741 | else | ||
742 | return i2c_bit_add_bus(&itv->i2c_adap); | ||
743 | } | ||
744 | |||
745 | void __devexit exit_ivtv_i2c(struct ivtv *itv) | ||
746 | { | ||
747 | IVTV_DEBUG_I2C("i2c exit\n"); | ||
748 | |||
749 | i2c_del_adapter(&itv->i2c_adap); | ||
750 | } | ||
diff --git a/drivers/media/video/ivtv/ivtv-i2c.h b/drivers/media/video/ivtv/ivtv-i2c.h new file mode 100644 index 000000000000..136dd684f4b5 --- /dev/null +++ b/drivers/media/video/ivtv/ivtv-i2c.h | |||
@@ -0,0 +1,38 @@ | |||
1 | /* | ||
2 | I2C functions | ||
3 | Copyright (C) 2003-2004 Kevin Thayer <nufan_wfk at yahoo.com> | ||
4 | Copyright (C) 2005-2007 Hans Verkuil <hverkuil@xs4all.nl> | ||
5 | |||
6 | This program is free software; you can redistribute it and/or modify | ||
7 | it under the terms of the GNU General Public License as published by | ||
8 | the Free Software Foundation; either version 2 of the License, or | ||
9 | (at your option) any later version. | ||
10 | |||
11 | This program is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program; if not, write to the Free Software | ||
18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | */ | ||
20 | |||
21 | int ivtv_cx25840(struct ivtv *itv, unsigned int cmd, void *arg); | ||
22 | int ivtv_saa7115(struct ivtv *itv, unsigned int cmd, void *arg); | ||
23 | int ivtv_saa7127(struct ivtv *itv, unsigned int cmd, void *arg); | ||
24 | int ivtv_saa717x(struct ivtv *itv, unsigned int cmd, void *arg); | ||
25 | int ivtv_msp34xx(struct ivtv *itv, unsigned int cmd, void *arg); | ||
26 | int ivtv_upd64031a(struct ivtv *itv, unsigned int cmd, void *arg); | ||
27 | int ivtv_upd64083(struct ivtv *itv, unsigned int cmd, void *arg); | ||
28 | |||
29 | int ivtv_i2c_id_addr(struct ivtv *itv, u32 id); | ||
30 | int ivtv_i2c_hw_addr(struct ivtv *itv, u32 hw); | ||
31 | int ivtv_i2c_hw(struct ivtv *itv, u32 hw, unsigned int cmd, void *arg); | ||
32 | int ivtv_i2c_id(struct ivtv *itv, u32 id, unsigned int cmd, void *arg); | ||
33 | int ivtv_call_i2c_client(struct ivtv *itv, int addr, unsigned int cmd, void *arg); | ||
34 | void ivtv_call_i2c_clients(struct ivtv *itv, unsigned int cmd, void *arg); | ||
35 | |||
36 | /* init + register i2c algo-bit adapter */ | ||
37 | int __devinit init_ivtv_i2c(struct ivtv *itv); | ||
38 | void __devexit exit_ivtv_i2c(struct ivtv *itv); | ||
diff --git a/drivers/media/video/ivtv/ivtv-ioctl.c b/drivers/media/video/ivtv/ivtv-ioctl.c new file mode 100644 index 000000000000..448e8dd5b42f --- /dev/null +++ b/drivers/media/video/ivtv/ivtv-ioctl.c | |||
@@ -0,0 +1,1555 @@ | |||
1 | /* | ||
2 | ioctl system call | ||
3 | Copyright (C) 2003-2004 Kevin Thayer <nufan_wfk at yahoo.com> | ||
4 | Copyright (C) 2005-2007 Hans Verkuil <hverkuil@xs4all.nl> | ||
5 | |||
6 | This program is free software; you can redistribute it and/or modify | ||
7 | it under the terms of the GNU General Public License as published by | ||
8 | the Free Software Foundation; either version 2 of the License, or | ||
9 | (at your option) any later version. | ||
10 | |||
11 | This program is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program; if not, write to the Free Software | ||
18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | */ | ||
20 | |||
21 | #include "ivtv-driver.h" | ||
22 | #include "ivtv-version.h" | ||
23 | #include "ivtv-mailbox.h" | ||
24 | #include "ivtv-i2c.h" | ||
25 | #include "ivtv-queue.h" | ||
26 | #include "ivtv-fileops.h" | ||
27 | #include "ivtv-vbi.h" | ||
28 | #include "ivtv-audio.h" | ||
29 | #include "ivtv-video.h" | ||
30 | #include "ivtv-streams.h" | ||
31 | #include "ivtv-yuv.h" | ||
32 | #include "ivtv-ioctl.h" | ||
33 | #include "ivtv-gpio.h" | ||
34 | #include "ivtv-controls.h" | ||
35 | #include "ivtv-cards.h" | ||
36 | #include <media/saa7127.h> | ||
37 | #include <media/tveeprom.h> | ||
38 | #include <media/v4l2-chip-ident.h> | ||
39 | #include <linux/dvb/audio.h> | ||
40 | #include <linux/i2c-id.h> | ||
41 | |||
42 | u16 service2vbi(int type) | ||
43 | { | ||
44 | switch (type) { | ||
45 | case V4L2_SLICED_TELETEXT_B: | ||
46 | return IVTV_SLICED_TYPE_TELETEXT_B; | ||
47 | case V4L2_SLICED_CAPTION_525: | ||
48 | return IVTV_SLICED_TYPE_CAPTION_525; | ||
49 | case V4L2_SLICED_WSS_625: | ||
50 | return IVTV_SLICED_TYPE_WSS_625; | ||
51 | case V4L2_SLICED_VPS: | ||
52 | return IVTV_SLICED_TYPE_VPS; | ||
53 | default: | ||
54 | return 0; | ||
55 | } | ||
56 | } | ||
57 | |||
58 | static int valid_service_line(int field, int line, int is_pal) | ||
59 | { | ||
60 | return (is_pal && line >= 6 && (line != 23 || field == 0)) || | ||
61 | (!is_pal && line >= 10 && line < 22); | ||
62 | } | ||
63 | |||
64 | static u16 select_service_from_set(int field, int line, u16 set, int is_pal) | ||
65 | { | ||
66 | u16 valid_set = (is_pal ? V4L2_SLICED_VBI_625 : V4L2_SLICED_VBI_525); | ||
67 | int i; | ||
68 | |||
69 | set = set & valid_set; | ||
70 | if (set == 0 || !valid_service_line(field, line, is_pal)) { | ||
71 | return 0; | ||
72 | } | ||
73 | if (!is_pal) { | ||
74 | if (line == 21 && (set & V4L2_SLICED_CAPTION_525)) | ||
75 | return V4L2_SLICED_CAPTION_525; | ||
76 | } | ||
77 | else { | ||
78 | if (line == 16 && field == 0 && (set & V4L2_SLICED_VPS)) | ||
79 | return V4L2_SLICED_VPS; | ||
80 | if (line == 23 && field == 0 && (set & V4L2_SLICED_WSS_625)) | ||
81 | return V4L2_SLICED_WSS_625; | ||
82 | if (line == 23) | ||
83 | return 0; | ||
84 | } | ||
85 | for (i = 0; i < 32; i++) { | ||
86 | if ((1 << i) & set) | ||
87 | return 1 << i; | ||
88 | } | ||
89 | return 0; | ||
90 | } | ||
91 | |||
92 | void expand_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal) | ||
93 | { | ||
94 | u16 set = fmt->service_set; | ||
95 | int f, l; | ||
96 | |||
97 | fmt->service_set = 0; | ||
98 | for (f = 0; f < 2; f++) { | ||
99 | for (l = 0; l < 24; l++) { | ||
100 | fmt->service_lines[f][l] = select_service_from_set(f, l, set, is_pal); | ||
101 | } | ||
102 | } | ||
103 | } | ||
104 | |||
105 | static int check_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal) | ||
106 | { | ||
107 | int f, l; | ||
108 | u16 set = 0; | ||
109 | |||
110 | for (f = 0; f < 2; f++) { | ||
111 | for (l = 0; l < 24; l++) { | ||
112 | fmt->service_lines[f][l] = select_service_from_set(f, l, fmt->service_lines[f][l], is_pal); | ||
113 | set |= fmt->service_lines[f][l]; | ||
114 | } | ||
115 | } | ||
116 | return set != 0; | ||
117 | } | ||
118 | |||
119 | u16 get_service_set(struct v4l2_sliced_vbi_format *fmt) | ||
120 | { | ||
121 | int f, l; | ||
122 | u16 set = 0; | ||
123 | |||
124 | for (f = 0; f < 2; f++) { | ||
125 | for (l = 0; l < 24; l++) { | ||
126 | set |= fmt->service_lines[f][l]; | ||
127 | } | ||
128 | } | ||
129 | return set; | ||
130 | } | ||
131 | |||
132 | static const struct { | ||
133 | v4l2_std_id std; | ||
134 | char *name; | ||
135 | } enum_stds[] = { | ||
136 | { V4L2_STD_PAL_BG | V4L2_STD_PAL_H, "PAL-BGH" }, | ||
137 | { V4L2_STD_PAL_DK, "PAL-DK" }, | ||
138 | { V4L2_STD_PAL_I, "PAL-I" }, | ||
139 | { V4L2_STD_PAL_M, "PAL-M" }, | ||
140 | { V4L2_STD_PAL_N, "PAL-N" }, | ||
141 | { V4L2_STD_PAL_Nc, "PAL-Nc" }, | ||
142 | { V4L2_STD_SECAM_B | V4L2_STD_SECAM_G | V4L2_STD_SECAM_H, "SECAM-BGH" }, | ||
143 | { V4L2_STD_SECAM_DK, "SECAM-DK" }, | ||
144 | { V4L2_STD_SECAM_L, "SECAM-L" }, | ||
145 | { V4L2_STD_SECAM_LC, "SECAM-L'" }, | ||
146 | { V4L2_STD_NTSC_M, "NTSC-M" }, | ||
147 | { V4L2_STD_NTSC_M_JP, "NTSC-J" }, | ||
148 | { V4L2_STD_NTSC_M_KR, "NTSC-K" }, | ||
149 | }; | ||
150 | |||
151 | static const struct v4l2_standard ivtv_std_60hz = | ||
152 | { | ||
153 | .frameperiod = {.numerator = 1001, .denominator = 30000}, | ||
154 | .framelines = 525, | ||
155 | }; | ||
156 | |||
157 | static const struct v4l2_standard ivtv_std_50hz = | ||
158 | { | ||
159 | .frameperiod = {.numerator = 1, .denominator = 25}, | ||
160 | .framelines = 625, | ||
161 | }; | ||
162 | |||
163 | void ivtv_set_osd_alpha(struct ivtv *itv) | ||
164 | { | ||
165 | ivtv_vapi(itv, CX2341X_OSD_SET_GLOBAL_ALPHA, 3, | ||
166 | itv->osd_global_alpha_state, itv->osd_global_alpha, !itv->osd_local_alpha_state); | ||
167 | ivtv_vapi(itv, CX2341X_OSD_SET_CHROMA_KEY, 2, itv->osd_color_key_state, itv->osd_color_key); | ||
168 | } | ||
169 | |||
170 | int ivtv_set_speed(struct ivtv *itv, int speed) | ||
171 | { | ||
172 | u32 data[CX2341X_MBOX_MAX_DATA]; | ||
173 | struct ivtv_stream *s; | ||
174 | int single_step = (speed == 1 || speed == -1); | ||
175 | DEFINE_WAIT(wait); | ||
176 | |||
177 | if (speed == 0) speed = 1000; | ||
178 | |||
179 | /* No change? */ | ||
180 | if (speed == itv->speed && !single_step) | ||
181 | return 0; | ||
182 | |||
183 | s = &itv->streams[IVTV_DEC_STREAM_TYPE_MPG]; | ||
184 | |||
185 | if (single_step && (speed < 0) == (itv->speed < 0)) { | ||
186 | /* Single step video and no need to change direction */ | ||
187 | ivtv_vapi(itv, CX2341X_DEC_STEP_VIDEO, 1, 0); | ||
188 | itv->speed = speed; | ||
189 | return 0; | ||
190 | } | ||
191 | if (single_step) | ||
192 | /* Need to change direction */ | ||
193 | speed = speed < 0 ? -1000 : 1000; | ||
194 | |||
195 | data[0] = (speed > 1000 || speed < -1000) ? 0x80000000 : 0; | ||
196 | data[0] |= (speed > 1000 || speed < -1500) ? 0x40000000 : 0; | ||
197 | data[1] = (speed < 0); | ||
198 | data[2] = speed < 0 ? 3 : 7; | ||
199 | data[3] = itv->params.video_b_frames; | ||
200 | data[4] = (speed == 1500 || speed == 500) ? itv->speed_mute_audio : 0; | ||
201 | data[5] = 0; | ||
202 | data[6] = 0; | ||
203 | |||
204 | if (speed == 1500 || speed == -1500) data[0] |= 1; | ||
205 | else if (speed == 2000 || speed == -2000) data[0] |= 2; | ||
206 | else if (speed > -1000 && speed < 0) data[0] |= (-1000 / speed); | ||
207 | else if (speed < 1000 && speed > 0) data[0] |= (1000 / speed); | ||
208 | |||
209 | /* If not decoding, just change speed setting */ | ||
210 | if (atomic_read(&itv->decoding) > 0) { | ||
211 | int got_sig = 0; | ||
212 | |||
213 | /* Stop all DMA and decoding activity */ | ||
214 | ivtv_vapi(itv, CX2341X_DEC_PAUSE_PLAYBACK, 1, 0); | ||
215 | |||
216 | /* Wait for any DMA to finish */ | ||
217 | prepare_to_wait(&itv->dma_waitq, &wait, TASK_INTERRUPTIBLE); | ||
218 | while (itv->i_flags & IVTV_F_I_DMA) { | ||
219 | got_sig = signal_pending(current); | ||
220 | if (got_sig) | ||
221 | break; | ||
222 | got_sig = 0; | ||
223 | schedule(); | ||
224 | } | ||
225 | finish_wait(&itv->dma_waitq, &wait); | ||
226 | if (got_sig) | ||
227 | return -EINTR; | ||
228 | |||
229 | /* Change Speed safely */ | ||
230 | ivtv_api(itv, CX2341X_DEC_SET_PLAYBACK_SPEED, 7, data); | ||
231 | IVTV_DEBUG_INFO("Setting Speed to 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n", | ||
232 | data[0], data[1], data[2], data[3], data[4], data[5], data[6]); | ||
233 | } | ||
234 | if (single_step) { | ||
235 | speed = (speed < 0) ? -1 : 1; | ||
236 | ivtv_vapi(itv, CX2341X_DEC_STEP_VIDEO, 1, 0); | ||
237 | } | ||
238 | itv->speed = speed; | ||
239 | return 0; | ||
240 | } | ||
241 | |||
242 | static int ivtv_validate_speed(int cur_speed, int new_speed) | ||
243 | { | ||
244 | int fact = new_speed < 0 ? -1 : 1; | ||
245 | int s; | ||
246 | |||
247 | if (new_speed < 0) new_speed = -new_speed; | ||
248 | if (cur_speed < 0) cur_speed = -cur_speed; | ||
249 | |||
250 | if (cur_speed <= new_speed) { | ||
251 | if (new_speed > 1500) return fact * 2000; | ||
252 | if (new_speed > 1000) return fact * 1500; | ||
253 | } | ||
254 | else { | ||
255 | if (new_speed >= 2000) return fact * 2000; | ||
256 | if (new_speed >= 1500) return fact * 1500; | ||
257 | if (new_speed >= 1000) return fact * 1000; | ||
258 | } | ||
259 | if (new_speed == 0) return 1000; | ||
260 | if (new_speed == 1 || new_speed == 1000) return fact * new_speed; | ||
261 | |||
262 | s = new_speed; | ||
263 | new_speed = 1000 / new_speed; | ||
264 | if (1000 / cur_speed == new_speed) | ||
265 | new_speed += (cur_speed < s) ? -1 : 1; | ||
266 | if (new_speed > 60) return 1000 / (fact * 60); | ||
267 | return 1000 / (fact * new_speed); | ||
268 | } | ||
269 | |||
270 | static int ivtv_video_command(struct ivtv *itv, struct ivtv_open_id *id, | ||
271 | struct video_command *vc, int try) | ||
272 | { | ||
273 | struct ivtv_stream *s = &itv->streams[IVTV_DEC_STREAM_TYPE_MPG]; | ||
274 | |||
275 | if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) | ||
276 | return -EINVAL; | ||
277 | |||
278 | switch (vc->cmd) { | ||
279 | case VIDEO_CMD_PLAY: { | ||
280 | vc->play.speed = ivtv_validate_speed(itv->speed, vc->play.speed); | ||
281 | if (vc->play.speed < 0) | ||
282 | vc->play.format = VIDEO_PLAY_FMT_GOP; | ||
283 | if (try) break; | ||
284 | |||
285 | if (ivtv_set_output_mode(itv, OUT_MPG) != OUT_MPG) | ||
286 | return -EBUSY; | ||
287 | return ivtv_start_decoding(id, vc->play.speed); | ||
288 | } | ||
289 | |||
290 | case VIDEO_CMD_STOP: | ||
291 | if (vc->flags & VIDEO_CMD_STOP_IMMEDIATELY) | ||
292 | vc->stop.pts = 0; | ||
293 | if (try) break; | ||
294 | if (atomic_read(&itv->decoding) == 0) | ||
295 | return 0; | ||
296 | if (itv->output_mode != OUT_MPG) | ||
297 | return -EBUSY; | ||
298 | |||
299 | itv->output_mode = OUT_NONE; | ||
300 | return ivtv_stop_v4l2_decode_stream(s, vc->flags, vc->stop.pts); | ||
301 | |||
302 | case VIDEO_CMD_FREEZE: | ||
303 | if (try) break; | ||
304 | if (itv->output_mode != OUT_MPG) | ||
305 | return -EBUSY; | ||
306 | if (atomic_read(&itv->decoding) > 0) { | ||
307 | ivtv_vapi(itv, CX2341X_DEC_PAUSE_PLAYBACK, 1, | ||
308 | (vc->flags & VIDEO_CMD_FREEZE_TO_BLACK) ? 1 : 0); | ||
309 | } | ||
310 | break; | ||
311 | |||
312 | case VIDEO_CMD_CONTINUE: | ||
313 | if (try) break; | ||
314 | if (itv->output_mode != OUT_MPG) | ||
315 | return -EBUSY; | ||
316 | if (atomic_read(&itv->decoding) > 0) { | ||
317 | ivtv_vapi(itv, CX2341X_DEC_START_PLAYBACK, 2, 0, 0); | ||
318 | } | ||
319 | break; | ||
320 | |||
321 | default: | ||
322 | return -EINVAL; | ||
323 | } | ||
324 | return 0; | ||
325 | } | ||
326 | |||
327 | static int ivtv_itvc(struct ivtv *itv, unsigned int cmd, void *arg) | ||
328 | { | ||
329 | struct v4l2_register *regs = arg; | ||
330 | unsigned long flags; | ||
331 | volatile u8 __iomem *reg_start; | ||
332 | |||
333 | if (!capable(CAP_SYS_ADMIN)) | ||
334 | return -EPERM; | ||
335 | if (regs->reg >= IVTV_REG_OFFSET && regs->reg < IVTV_REG_OFFSET + IVTV_REG_SIZE) | ||
336 | reg_start = itv->reg_mem - IVTV_REG_OFFSET; | ||
337 | else if (itv->has_cx23415 && regs->reg >= IVTV_DECODER_OFFSET && | ||
338 | regs->reg < IVTV_DECODER_OFFSET + IVTV_DECODER_SIZE) | ||
339 | reg_start = itv->dec_mem - IVTV_DECODER_OFFSET; | ||
340 | else if (regs->reg >= 0 && regs->reg < IVTV_ENCODER_SIZE) | ||
341 | reg_start = itv->enc_mem; | ||
342 | else | ||
343 | return -EINVAL; | ||
344 | |||
345 | spin_lock_irqsave(&ivtv_cards_lock, flags); | ||
346 | if (cmd == VIDIOC_DBG_G_REGISTER) { | ||
347 | regs->val = readl(regs->reg + reg_start); | ||
348 | } else { | ||
349 | writel(regs->val, regs->reg + reg_start); | ||
350 | } | ||
351 | spin_unlock_irqrestore(&ivtv_cards_lock, flags); | ||
352 | return 0; | ||
353 | } | ||
354 | |||
355 | static int ivtv_get_fmt(struct ivtv *itv, int streamtype, struct v4l2_format *fmt) | ||
356 | { | ||
357 | switch (fmt->type) { | ||
358 | case V4L2_BUF_TYPE_VIDEO_OUTPUT: | ||
359 | if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) | ||
360 | return -EINVAL; | ||
361 | fmt->fmt.pix.left = itv->main_rect.left; | ||
362 | fmt->fmt.pix.top = itv->main_rect.top; | ||
363 | fmt->fmt.pix.width = itv->main_rect.width; | ||
364 | fmt->fmt.pix.height = itv->main_rect.height; | ||
365 | fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; | ||
366 | fmt->fmt.pix.field = V4L2_FIELD_INTERLACED; | ||
367 | if (itv->output_mode == OUT_UDMA_YUV) { | ||
368 | switch (itv->yuv_info.lace_mode & IVTV_YUV_MODE_MASK) { | ||
369 | case IVTV_YUV_MODE_INTERLACED: | ||
370 | fmt->fmt.pix.field = (itv->yuv_info.lace_mode & IVTV_YUV_SYNC_MASK) ? | ||
371 | V4L2_FIELD_INTERLACED_BT : V4L2_FIELD_INTERLACED_TB; | ||
372 | break; | ||
373 | case IVTV_YUV_MODE_PROGRESSIVE: | ||
374 | fmt->fmt.pix.field = V4L2_FIELD_NONE; | ||
375 | break; | ||
376 | default: | ||
377 | fmt->fmt.pix.field = V4L2_FIELD_ANY; | ||
378 | break; | ||
379 | } | ||
380 | fmt->fmt.pix.pixelformat = V4L2_PIX_FMT_HM12; | ||
381 | /* YUV size is (Y=(h*w) + UV=(h*(w/2))) */ | ||
382 | fmt->fmt.pix.sizeimage = | ||
383 | fmt->fmt.pix.height * fmt->fmt.pix.width + | ||
384 | fmt->fmt.pix.height * (fmt->fmt.pix.width / 2); | ||
385 | } | ||
386 | else if (itv->output_mode == OUT_YUV || | ||
387 | streamtype == IVTV_ENC_STREAM_TYPE_YUV || | ||
388 | streamtype == IVTV_DEC_STREAM_TYPE_YUV) { | ||
389 | fmt->fmt.pix.pixelformat = V4L2_PIX_FMT_HM12; | ||
390 | /* YUV size is (Y=(h*w) + UV=(h*(w/2))) */ | ||
391 | fmt->fmt.pix.sizeimage = | ||
392 | fmt->fmt.pix.height * fmt->fmt.pix.width + | ||
393 | fmt->fmt.pix.height * (fmt->fmt.pix.width / 2); | ||
394 | } else { | ||
395 | fmt->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; | ||
396 | fmt->fmt.pix.sizeimage = 128 * 1024; | ||
397 | } | ||
398 | break; | ||
399 | |||
400 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | ||
401 | fmt->fmt.pix.left = 0; | ||
402 | fmt->fmt.pix.top = 0; | ||
403 | fmt->fmt.pix.width = itv->params.width; | ||
404 | fmt->fmt.pix.height = itv->params.height; | ||
405 | fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; | ||
406 | fmt->fmt.pix.field = V4L2_FIELD_INTERLACED; | ||
407 | if (streamtype == IVTV_ENC_STREAM_TYPE_YUV || | ||
408 | streamtype == IVTV_DEC_STREAM_TYPE_YUV) { | ||
409 | fmt->fmt.pix.pixelformat = V4L2_PIX_FMT_HM12; | ||
410 | /* YUV size is (Y=(h*w) + UV=(h*(w/2))) */ | ||
411 | fmt->fmt.pix.sizeimage = | ||
412 | fmt->fmt.pix.height * fmt->fmt.pix.width + | ||
413 | fmt->fmt.pix.height * (fmt->fmt.pix.width / 2); | ||
414 | } else { | ||
415 | fmt->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; | ||
416 | fmt->fmt.pix.sizeimage = 128 * 1024; | ||
417 | } | ||
418 | break; | ||
419 | |||
420 | case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: | ||
421 | if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) | ||
422 | return -EINVAL; | ||
423 | fmt->fmt.win.chromakey = itv->osd_color_key; | ||
424 | fmt->fmt.win.global_alpha = itv->osd_global_alpha; | ||
425 | break; | ||
426 | |||
427 | case V4L2_BUF_TYPE_VBI_CAPTURE: | ||
428 | fmt->fmt.vbi.sampling_rate = 27000000; | ||
429 | fmt->fmt.vbi.offset = 248; | ||
430 | fmt->fmt.vbi.samples_per_line = itv->vbi.raw_decoder_line_size - 4; | ||
431 | fmt->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY; | ||
432 | fmt->fmt.vbi.start[0] = itv->vbi.start[0]; | ||
433 | fmt->fmt.vbi.start[1] = itv->vbi.start[1]; | ||
434 | fmt->fmt.vbi.count[0] = fmt->fmt.vbi.count[1] = itv->vbi.count; | ||
435 | break; | ||
436 | |||
437 | case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: | ||
438 | { | ||
439 | struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced; | ||
440 | |||
441 | if (!(itv->v4l2_cap & V4L2_CAP_SLICED_VBI_OUTPUT)) | ||
442 | return -EINVAL; | ||
443 | vbifmt->io_size = sizeof(struct v4l2_sliced_vbi_data) * 36; | ||
444 | memset(vbifmt->reserved, 0, sizeof(vbifmt->reserved)); | ||
445 | memset(vbifmt->service_lines, 0, sizeof(vbifmt->service_lines)); | ||
446 | if (itv->is_60hz) { | ||
447 | vbifmt->service_lines[0][21] = V4L2_SLICED_CAPTION_525; | ||
448 | vbifmt->service_lines[1][21] = V4L2_SLICED_CAPTION_525; | ||
449 | } else { | ||
450 | vbifmt->service_lines[0][23] = V4L2_SLICED_WSS_625; | ||
451 | vbifmt->service_lines[0][16] = V4L2_SLICED_VPS; | ||
452 | } | ||
453 | vbifmt->service_set = get_service_set(vbifmt); | ||
454 | break; | ||
455 | } | ||
456 | |||
457 | case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: | ||
458 | { | ||
459 | struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced; | ||
460 | |||
461 | vbifmt->io_size = sizeof(struct v4l2_sliced_vbi_data) * 36; | ||
462 | memset(vbifmt->reserved, 0, sizeof(vbifmt->reserved)); | ||
463 | memset(vbifmt->service_lines, 0, sizeof(vbifmt->service_lines)); | ||
464 | |||
465 | if (streamtype == IVTV_DEC_STREAM_TYPE_VBI) { | ||
466 | vbifmt->service_set = itv->is_50hz ? V4L2_SLICED_VBI_625 : | ||
467 | V4L2_SLICED_VBI_525; | ||
468 | expand_service_set(vbifmt, itv->is_50hz); | ||
469 | break; | ||
470 | } | ||
471 | |||
472 | itv->video_dec_func(itv, VIDIOC_G_FMT, fmt); | ||
473 | vbifmt->service_set = get_service_set(vbifmt); | ||
474 | break; | ||
475 | } | ||
476 | case V4L2_BUF_TYPE_VBI_OUTPUT: | ||
477 | case V4L2_BUF_TYPE_VIDEO_OVERLAY: | ||
478 | default: | ||
479 | return -EINVAL; | ||
480 | } | ||
481 | return 0; | ||
482 | } | ||
483 | |||
484 | static int ivtv_try_or_set_fmt(struct ivtv *itv, int streamtype, | ||
485 | struct v4l2_format *fmt, int set_fmt) | ||
486 | { | ||
487 | struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced; | ||
488 | u16 set; | ||
489 | |||
490 | if (fmt->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) { | ||
491 | struct v4l2_rect r; | ||
492 | int field; | ||
493 | |||
494 | if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) | ||
495 | return -EINVAL; | ||
496 | field = fmt->fmt.pix.field; | ||
497 | r.top = fmt->fmt.pix.top; | ||
498 | r.left = fmt->fmt.pix.left; | ||
499 | r.width = fmt->fmt.pix.width; | ||
500 | r.height = fmt->fmt.pix.height; | ||
501 | ivtv_get_fmt(itv, streamtype, fmt); | ||
502 | if (itv->output_mode != OUT_UDMA_YUV) { | ||
503 | /* TODO: would setting the rect also be valid for this mode? */ | ||
504 | fmt->fmt.pix.top = r.top; | ||
505 | fmt->fmt.pix.left = r.left; | ||
506 | fmt->fmt.pix.width = r.width; | ||
507 | fmt->fmt.pix.height = r.height; | ||
508 | } | ||
509 | if (itv->output_mode == OUT_UDMA_YUV) { | ||
510 | /* TODO: add checks for validity */ | ||
511 | fmt->fmt.pix.field = field; | ||
512 | } | ||
513 | if (set_fmt) { | ||
514 | if (itv->output_mode == OUT_UDMA_YUV) { | ||
515 | switch (field) { | ||
516 | case V4L2_FIELD_NONE: | ||
517 | itv->yuv_info.lace_mode = IVTV_YUV_MODE_PROGRESSIVE; | ||
518 | break; | ||
519 | case V4L2_FIELD_ANY: | ||
520 | itv->yuv_info.lace_mode = IVTV_YUV_MODE_AUTO; | ||
521 | break; | ||
522 | case V4L2_FIELD_INTERLACED_BT: | ||
523 | itv->yuv_info.lace_mode = | ||
524 | IVTV_YUV_MODE_INTERLACED|IVTV_YUV_SYNC_ODD; | ||
525 | break; | ||
526 | case V4L2_FIELD_INTERLACED_TB: | ||
527 | default: | ||
528 | itv->yuv_info.lace_mode = IVTV_YUV_MODE_INTERLACED; | ||
529 | break; | ||
530 | } | ||
531 | itv->yuv_info.lace_sync_field = (itv->yuv_info.lace_mode & IVTV_YUV_SYNC_MASK) == IVTV_YUV_SYNC_EVEN ? 0 : 1; | ||
532 | |||
533 | /* Force update of yuv registers */ | ||
534 | itv->yuv_info.yuv_forced_update = 1; | ||
535 | return 0; | ||
536 | } | ||
537 | if (!ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 4, | ||
538 | r.width, r.height, r.left, r.top)) | ||
539 | itv->main_rect = r; | ||
540 | else | ||
541 | return -EINVAL; | ||
542 | } | ||
543 | return 0; | ||
544 | } | ||
545 | |||
546 | if (fmt->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY) { | ||
547 | if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) | ||
548 | return -EINVAL; | ||
549 | if (set_fmt) { | ||
550 | itv->osd_color_key = fmt->fmt.win.chromakey; | ||
551 | itv->osd_global_alpha = fmt->fmt.win.global_alpha; | ||
552 | ivtv_set_osd_alpha(itv); | ||
553 | } | ||
554 | return 0; | ||
555 | } | ||
556 | |||
557 | /* set window size */ | ||
558 | if (fmt->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { | ||
559 | int w = fmt->fmt.pix.width; | ||
560 | int h = fmt->fmt.pix.height; | ||
561 | |||
562 | if (w > 720) w = 720; | ||
563 | else if (w < 1) w = 1; | ||
564 | if (h > (itv->is_50hz ? 576 : 480)) h = (itv->is_50hz ? 576 : 480); | ||
565 | else if (h < 2) h = 2; | ||
566 | ivtv_get_fmt(itv, streamtype, fmt); | ||
567 | fmt->fmt.pix.width = w; | ||
568 | fmt->fmt.pix.height = h; | ||
569 | |||
570 | if (!set_fmt || (itv->params.width == w && itv->params.height == h)) | ||
571 | return 0; | ||
572 | if (atomic_read(&itv->capturing) > 0) | ||
573 | return -EBUSY; | ||
574 | |||
575 | itv->params.width = w; | ||
576 | itv->params.height = h; | ||
577 | if (w != 720 || h != (itv->is_50hz ? 576 : 480)) | ||
578 | itv->params.video_temporal_filter = 0; | ||
579 | else | ||
580 | itv->params.video_temporal_filter = 8; | ||
581 | itv->video_dec_func(itv, VIDIOC_S_FMT, fmt); | ||
582 | return ivtv_get_fmt(itv, streamtype, fmt); | ||
583 | } | ||
584 | |||
585 | /* set raw VBI format */ | ||
586 | if (fmt->type == V4L2_BUF_TYPE_VBI_CAPTURE) { | ||
587 | if (set_fmt && streamtype == IVTV_ENC_STREAM_TYPE_VBI && | ||
588 | itv->vbi.sliced_in->service_set && | ||
589 | atomic_read(&itv->capturing) > 0) { | ||
590 | return -EBUSY; | ||
591 | } | ||
592 | if (set_fmt) { | ||
593 | itv->vbi.sliced_in->service_set = 0; | ||
594 | itv->video_dec_func(itv, VIDIOC_S_FMT, &itv->vbi.in); | ||
595 | } | ||
596 | return ivtv_get_fmt(itv, streamtype, fmt); | ||
597 | } | ||
598 | |||
599 | /* set sliced VBI output | ||
600 | In principle the user could request that only certain | ||
601 | VBI types are output and that the others are ignored. | ||
602 | I.e., suppress CC in the even fields or only output | ||
603 | WSS and no VPS. Currently though there is no choice. */ | ||
604 | if (fmt->type == V4L2_BUF_TYPE_SLICED_VBI_OUTPUT) | ||
605 | return ivtv_get_fmt(itv, streamtype, fmt); | ||
606 | |||
607 | /* any else but sliced VBI capture is an error */ | ||
608 | if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) | ||
609 | return -EINVAL; | ||
610 | |||
611 | if (streamtype == IVTV_DEC_STREAM_TYPE_VBI) | ||
612 | return ivtv_get_fmt(itv, streamtype, fmt); | ||
613 | |||
614 | /* set sliced VBI capture format */ | ||
615 | vbifmt->io_size = sizeof(struct v4l2_sliced_vbi_data) * 36; | ||
616 | memset(vbifmt->reserved, 0, sizeof(vbifmt->reserved)); | ||
617 | |||
618 | if (vbifmt->service_set) | ||
619 | expand_service_set(vbifmt, itv->is_50hz); | ||
620 | set = check_service_set(vbifmt, itv->is_50hz); | ||
621 | vbifmt->service_set = get_service_set(vbifmt); | ||
622 | |||
623 | if (!set_fmt) | ||
624 | return 0; | ||
625 | if (set == 0) | ||
626 | return -EINVAL; | ||
627 | if (atomic_read(&itv->capturing) > 0 && itv->vbi.sliced_in->service_set == 0) { | ||
628 | return -EBUSY; | ||
629 | } | ||
630 | itv->video_dec_func(itv, VIDIOC_S_FMT, fmt); | ||
631 | memcpy(itv->vbi.sliced_in, vbifmt, sizeof(*itv->vbi.sliced_in)); | ||
632 | return 0; | ||
633 | } | ||
634 | |||
635 | static int ivtv_internal_ioctls(struct file *filp, unsigned int cmd, void *arg) | ||
636 | { | ||
637 | struct ivtv_open_id *id = (struct ivtv_open_id *)filp->private_data; | ||
638 | struct ivtv *itv = id->itv; | ||
639 | struct v4l2_register *reg = arg; | ||
640 | |||
641 | switch (cmd) { | ||
642 | /* ioctls to allow direct access to the encoder registers for testing */ | ||
643 | case VIDIOC_DBG_G_REGISTER: | ||
644 | IVTV_DEBUG_IOCTL("VIDIOC_DBG_G_REGISTER\n"); | ||
645 | if (v4l2_chip_match_host(reg->match_type, reg->match_chip)) | ||
646 | return ivtv_itvc(itv, cmd, arg); | ||
647 | if (reg->match_type == V4L2_CHIP_MATCH_I2C_DRIVER) | ||
648 | return ivtv_i2c_id(itv, reg->match_chip, cmd, arg); | ||
649 | return ivtv_call_i2c_client(itv, reg->match_chip, cmd, arg); | ||
650 | |||
651 | case VIDIOC_DBG_S_REGISTER: | ||
652 | IVTV_DEBUG_IOCTL("VIDIOC_DBG_S_REGISTER\n"); | ||
653 | if (v4l2_chip_match_host(reg->match_type, reg->match_chip)) | ||
654 | return ivtv_itvc(itv, cmd, arg); | ||
655 | if (reg->match_type == V4L2_CHIP_MATCH_I2C_DRIVER) | ||
656 | return ivtv_i2c_id(itv, reg->match_chip, cmd, arg); | ||
657 | return ivtv_call_i2c_client(itv, reg->match_chip, cmd, arg); | ||
658 | |||
659 | case VIDIOC_G_CHIP_IDENT: { | ||
660 | struct v4l2_chip_ident *chip = arg; | ||
661 | |||
662 | IVTV_DEBUG_IOCTL("VIDIOC_G_CHIP_IDENT\n"); | ||
663 | chip->ident = V4L2_IDENT_NONE; | ||
664 | chip->revision = 0; | ||
665 | if (reg->match_type == V4L2_CHIP_MATCH_HOST) { | ||
666 | if (v4l2_chip_match_host(reg->match_type, reg->match_chip)) { | ||
667 | struct v4l2_chip_ident *chip = arg; | ||
668 | |||
669 | chip->ident = itv->has_cx23415 ? V4L2_IDENT_CX23415 : V4L2_IDENT_CX23416; | ||
670 | } | ||
671 | return 0; | ||
672 | } | ||
673 | if (reg->match_type == V4L2_CHIP_MATCH_I2C_DRIVER) | ||
674 | return ivtv_i2c_id(itv, reg->match_chip, cmd, arg); | ||
675 | if (reg->match_type == V4L2_CHIP_MATCH_I2C_ADDR) | ||
676 | return ivtv_call_i2c_client(itv, reg->match_chip, cmd, arg); | ||
677 | return -EINVAL; | ||
678 | } | ||
679 | |||
680 | case VIDIOC_INT_S_AUDIO_ROUTING: { | ||
681 | struct v4l2_routing *route = arg; | ||
682 | |||
683 | IVTV_DEBUG_IOCTL("VIDIOC_INT_S_AUDIO_ROUTING\n"); | ||
684 | ivtv_audio_set_route(itv, route); | ||
685 | break; | ||
686 | } | ||
687 | |||
688 | case VIDIOC_INT_RESET: | ||
689 | IVTV_DEBUG_IOCTL("VIDIOC_INT_RESET\n"); | ||
690 | ivtv_reset_ir_gpio(itv); | ||
691 | break; | ||
692 | |||
693 | default: | ||
694 | return -EINVAL; | ||
695 | } | ||
696 | return 0; | ||
697 | } | ||
698 | |||
699 | int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void *arg) | ||
700 | { | ||
701 | struct ivtv_open_id *id = NULL; | ||
702 | |||
703 | if (filp) id = (struct ivtv_open_id *)filp->private_data; | ||
704 | |||
705 | switch (cmd) { | ||
706 | case VIDIOC_QUERYCAP:{ | ||
707 | struct v4l2_capability *vcap = arg; | ||
708 | |||
709 | IVTV_DEBUG_IOCTL("VIDIOC_QUERYCAP\n"); | ||
710 | |||
711 | memset(vcap, 0, sizeof(*vcap)); | ||
712 | strcpy(vcap->driver, IVTV_DRIVER_NAME); /* driver name */ | ||
713 | strcpy(vcap->card, itv->card_name); /* card type */ | ||
714 | strcpy(vcap->bus_info, pci_name(itv->dev)); /* bus info... */ | ||
715 | vcap->version = IVTV_DRIVER_VERSION; /* version */ | ||
716 | vcap->capabilities = itv->v4l2_cap; /* capabilities */ | ||
717 | |||
718 | /* reserved.. must set to 0! */ | ||
719 | vcap->reserved[0] = vcap->reserved[1] = | ||
720 | vcap->reserved[2] = vcap->reserved[3] = 0; | ||
721 | break; | ||
722 | } | ||
723 | |||
724 | case VIDIOC_ENUMAUDIO:{ | ||
725 | struct v4l2_audio *vin = arg; | ||
726 | |||
727 | IVTV_DEBUG_IOCTL("VIDIOC_ENUMAUDIO\n"); | ||
728 | |||
729 | return ivtv_get_audio_input(itv, vin->index, vin); | ||
730 | } | ||
731 | |||
732 | case VIDIOC_G_AUDIO:{ | ||
733 | struct v4l2_audio *vin = arg; | ||
734 | |||
735 | IVTV_DEBUG_IOCTL("VIDIOC_G_AUDIO\n"); | ||
736 | vin->index = itv->audio_input; | ||
737 | return ivtv_get_audio_input(itv, vin->index, vin); | ||
738 | } | ||
739 | |||
740 | case VIDIOC_S_AUDIO:{ | ||
741 | struct v4l2_audio *vout = arg; | ||
742 | |||
743 | IVTV_DEBUG_IOCTL("VIDIOC_S_AUDIO\n"); | ||
744 | |||
745 | if (vout->index >= itv->nof_audio_inputs) | ||
746 | return -EINVAL; | ||
747 | itv->audio_input = vout->index; | ||
748 | ivtv_audio_set_io(itv); | ||
749 | break; | ||
750 | } | ||
751 | |||
752 | case VIDIOC_ENUMAUDOUT:{ | ||
753 | struct v4l2_audioout *vin = arg; | ||
754 | |||
755 | IVTV_DEBUG_IOCTL("VIDIOC_ENUMAUDOUT\n"); | ||
756 | |||
757 | /* set it to defaults from our table */ | ||
758 | return ivtv_get_audio_output(itv, vin->index, vin); | ||
759 | } | ||
760 | |||
761 | case VIDIOC_G_AUDOUT:{ | ||
762 | struct v4l2_audioout *vin = arg; | ||
763 | |||
764 | IVTV_DEBUG_IOCTL("VIDIOC_G_AUDOUT\n"); | ||
765 | vin->index = 0; | ||
766 | return ivtv_get_audio_output(itv, vin->index, vin); | ||
767 | } | ||
768 | |||
769 | case VIDIOC_S_AUDOUT:{ | ||
770 | struct v4l2_audioout *vout = arg; | ||
771 | |||
772 | IVTV_DEBUG_IOCTL("VIDIOC_S_AUDOUT\n"); | ||
773 | |||
774 | return ivtv_get_audio_output(itv, vout->index, vout); | ||
775 | } | ||
776 | |||
777 | case VIDIOC_ENUMINPUT:{ | ||
778 | struct v4l2_input *vin = arg; | ||
779 | |||
780 | IVTV_DEBUG_IOCTL("VIDIOC_ENUMINPUT\n"); | ||
781 | |||
782 | /* set it to defaults from our table */ | ||
783 | return ivtv_get_input(itv, vin->index, vin); | ||
784 | } | ||
785 | |||
786 | case VIDIOC_ENUMOUTPUT:{ | ||
787 | struct v4l2_output *vout = arg; | ||
788 | |||
789 | IVTV_DEBUG_IOCTL("VIDIOC_ENUMOUTPUT\n"); | ||
790 | |||
791 | return ivtv_get_output(itv, vout->index, vout); | ||
792 | } | ||
793 | |||
794 | case VIDIOC_TRY_FMT: | ||
795 | case VIDIOC_S_FMT: { | ||
796 | struct v4l2_format *fmt = arg; | ||
797 | |||
798 | if (cmd == VIDIOC_S_FMT) { | ||
799 | IVTV_DEBUG_IOCTL("VIDIOC_S_FMT\n"); | ||
800 | } else { | ||
801 | IVTV_DEBUG_IOCTL("VIDIOC_TRY_FMT\n"); | ||
802 | } | ||
803 | return ivtv_try_or_set_fmt(itv, id->type, fmt, cmd == VIDIOC_S_FMT); | ||
804 | } | ||
805 | |||
806 | case VIDIOC_G_FMT: { | ||
807 | struct v4l2_format *fmt = arg; | ||
808 | int type = fmt->type; | ||
809 | |||
810 | IVTV_DEBUG_IOCTL("VIDIOC_G_FMT\n"); | ||
811 | memset(fmt, 0, sizeof(*fmt)); | ||
812 | fmt->type = type; | ||
813 | return ivtv_get_fmt(itv, id->type, fmt); | ||
814 | } | ||
815 | |||
816 | case VIDIOC_S_CROP: { | ||
817 | struct v4l2_crop *crop = arg; | ||
818 | |||
819 | IVTV_DEBUG_IOCTL("VIDIOC_S_CROP\n"); | ||
820 | if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
821 | return -EINVAL; | ||
822 | return itv->video_dec_func(itv, VIDIOC_S_CROP, arg); | ||
823 | } | ||
824 | |||
825 | case VIDIOC_G_CROP: { | ||
826 | struct v4l2_crop *crop = arg; | ||
827 | |||
828 | IVTV_DEBUG_IOCTL("VIDIOC_G_CROP\n"); | ||
829 | if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
830 | return -EINVAL; | ||
831 | return itv->video_dec_func(itv, VIDIOC_G_CROP, arg); | ||
832 | } | ||
833 | |||
834 | case VIDIOC_ENUM_FMT: { | ||
835 | static struct v4l2_fmtdesc formats[] = { | ||
836 | { 0, 0, 0, | ||
837 | "HM12 (YUV 4:1:1)", V4L2_PIX_FMT_HM12, | ||
838 | { 0, 0, 0, 0 } | ||
839 | }, | ||
840 | { 1, 0, V4L2_FMT_FLAG_COMPRESSED, | ||
841 | "MPEG", V4L2_PIX_FMT_MPEG, | ||
842 | { 0, 0, 0, 0 } | ||
843 | } | ||
844 | }; | ||
845 | struct v4l2_fmtdesc *fmt = arg; | ||
846 | enum v4l2_buf_type type = fmt->type; | ||
847 | |||
848 | switch (type) { | ||
849 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | ||
850 | break; | ||
851 | case V4L2_BUF_TYPE_VIDEO_OUTPUT: | ||
852 | if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) | ||
853 | return -EINVAL; | ||
854 | break; | ||
855 | default: | ||
856 | return -EINVAL; | ||
857 | } | ||
858 | if (fmt->index > 1) | ||
859 | return -EINVAL; | ||
860 | *fmt = formats[fmt->index]; | ||
861 | fmt->type = type; | ||
862 | return 0; | ||
863 | } | ||
864 | |||
865 | case VIDIOC_G_INPUT:{ | ||
866 | IVTV_DEBUG_IOCTL("VIDIOC_G_INPUT\n"); | ||
867 | |||
868 | *(int *)arg = itv->active_input; | ||
869 | break; | ||
870 | } | ||
871 | |||
872 | case VIDIOC_S_INPUT:{ | ||
873 | int inp = *(int *)arg; | ||
874 | |||
875 | IVTV_DEBUG_IOCTL("VIDIOC_S_INPUT\n"); | ||
876 | |||
877 | if (inp < 0 || inp >= itv->nof_inputs) | ||
878 | return -EINVAL; | ||
879 | |||
880 | if (inp == itv->active_input) { | ||
881 | IVTV_DEBUG_INFO("Input unchanged\n"); | ||
882 | break; | ||
883 | } | ||
884 | IVTV_DEBUG_INFO("Changing input from %d to %d\n", | ||
885 | itv->active_input, inp); | ||
886 | |||
887 | itv->active_input = inp; | ||
888 | /* Set the audio input to whatever is appropriate for the | ||
889 | input type. */ | ||
890 | itv->audio_input = itv->card->video_inputs[inp].audio_index; | ||
891 | |||
892 | /* prevent others from messing with the streams until | ||
893 | we're finished changing inputs. */ | ||
894 | ivtv_mute(itv); | ||
895 | ivtv_video_set_io(itv); | ||
896 | ivtv_audio_set_io(itv); | ||
897 | ivtv_unmute(itv); | ||
898 | break; | ||
899 | } | ||
900 | |||
901 | case VIDIOC_G_OUTPUT:{ | ||
902 | IVTV_DEBUG_IOCTL("VIDIOC_G_OUTPUT\n"); | ||
903 | |||
904 | if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) | ||
905 | return -EINVAL; | ||
906 | *(int *)arg = itv->active_output; | ||
907 | break; | ||
908 | } | ||
909 | |||
910 | case VIDIOC_S_OUTPUT:{ | ||
911 | int outp = *(int *)arg; | ||
912 | struct v4l2_routing route; | ||
913 | |||
914 | IVTV_DEBUG_IOCTL("VIDIOC_S_OUTPUT\n"); | ||
915 | |||
916 | if (outp >= itv->card->nof_outputs) | ||
917 | return -EINVAL; | ||
918 | |||
919 | if (outp == itv->active_output) { | ||
920 | IVTV_DEBUG_INFO("Output unchanged\n"); | ||
921 | break; | ||
922 | } | ||
923 | IVTV_DEBUG_INFO("Changing output from %d to %d\n", | ||
924 | itv->active_output, outp); | ||
925 | |||
926 | itv->active_output = outp; | ||
927 | route.input = SAA7127_INPUT_TYPE_NORMAL; | ||
928 | route.output = itv->card->video_outputs[outp].video_output; | ||
929 | ivtv_saa7127(itv, VIDIOC_INT_S_VIDEO_ROUTING, &route); | ||
930 | break; | ||
931 | } | ||
932 | |||
933 | case VIDIOC_G_FREQUENCY:{ | ||
934 | struct v4l2_frequency *vf = arg; | ||
935 | |||
936 | IVTV_DEBUG_IOCTL("VIDIOC_G_FREQUENCY\n"); | ||
937 | |||
938 | if (vf->tuner != 0) | ||
939 | return -EINVAL; | ||
940 | ivtv_call_i2c_clients(itv, cmd, arg); | ||
941 | break; | ||
942 | } | ||
943 | |||
944 | case VIDIOC_S_FREQUENCY:{ | ||
945 | struct v4l2_frequency vf = *(struct v4l2_frequency *)arg; | ||
946 | |||
947 | IVTV_DEBUG_IOCTL("VIDIOC_S_FREQUENCY\n"); | ||
948 | |||
949 | if (vf.tuner != 0) | ||
950 | return -EINVAL; | ||
951 | |||
952 | ivtv_mute(itv); | ||
953 | IVTV_DEBUG_INFO("v4l2 ioctl: set frequency %d\n", vf.frequency); | ||
954 | ivtv_call_i2c_clients(itv, cmd, &vf); | ||
955 | ivtv_unmute(itv); | ||
956 | break; | ||
957 | } | ||
958 | |||
959 | case VIDIOC_ENUMSTD:{ | ||
960 | struct v4l2_standard *vs = arg; | ||
961 | int idx = vs->index; | ||
962 | |||
963 | IVTV_DEBUG_IOCTL("VIDIOC_ENUMSTD\n"); | ||
964 | |||
965 | if (idx < 0 || idx >= ARRAY_SIZE(enum_stds)) | ||
966 | return -EINVAL; | ||
967 | |||
968 | *vs = (enum_stds[idx].std & V4L2_STD_525_60) ? | ||
969 | ivtv_std_60hz : ivtv_std_50hz; | ||
970 | vs->index = idx; | ||
971 | vs->id = enum_stds[idx].std; | ||
972 | strcpy(vs->name, enum_stds[idx].name); | ||
973 | break; | ||
974 | } | ||
975 | |||
976 | case VIDIOC_G_STD:{ | ||
977 | IVTV_DEBUG_IOCTL("VIDIOC_G_STD\n"); | ||
978 | *(v4l2_std_id *) arg = itv->std; | ||
979 | break; | ||
980 | } | ||
981 | |||
982 | case VIDIOC_S_STD: { | ||
983 | v4l2_std_id std = *(v4l2_std_id *) arg; | ||
984 | |||
985 | IVTV_DEBUG_IOCTL("VIDIOC_S_STD\n"); | ||
986 | |||
987 | if ((std & V4L2_STD_ALL) == 0) | ||
988 | return -EINVAL; | ||
989 | |||
990 | if (std == itv->std) | ||
991 | break; | ||
992 | |||
993 | if (test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags) || | ||
994 | atomic_read(&itv->capturing) > 0 || | ||
995 | atomic_read(&itv->decoding) > 0) { | ||
996 | /* Switching standard would turn off the radio or mess | ||
997 | with already running streams, prevent that by | ||
998 | returning EBUSY. */ | ||
999 | return -EBUSY; | ||
1000 | } | ||
1001 | |||
1002 | itv->std = std; | ||
1003 | itv->is_60hz = (std & V4L2_STD_525_60) ? 1 : 0; | ||
1004 | itv->params.is_50hz = itv->is_50hz = !itv->is_60hz; | ||
1005 | itv->params.width = 720; | ||
1006 | itv->params.height = itv->is_50hz ? 576 : 480; | ||
1007 | itv->vbi.count = itv->is_50hz ? 18 : 12; | ||
1008 | itv->vbi.start[0] = itv->is_50hz ? 6 : 10; | ||
1009 | itv->vbi.start[1] = itv->is_50hz ? 318 : 273; | ||
1010 | if (itv->hw_flags & IVTV_HW_CX25840) { | ||
1011 | itv->vbi.sliced_decoder_line_size = itv->is_60hz ? 272 : 284; | ||
1012 | } | ||
1013 | IVTV_DEBUG_INFO("Switching standard to %llx.\n", itv->std); | ||
1014 | |||
1015 | /* Tuner */ | ||
1016 | ivtv_call_i2c_clients(itv, VIDIOC_S_STD, &itv->std); | ||
1017 | |||
1018 | if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) { | ||
1019 | /* set display standard */ | ||
1020 | itv->std_out = std; | ||
1021 | itv->is_out_60hz = itv->is_60hz; | ||
1022 | itv->is_out_50hz = itv->is_50hz; | ||
1023 | ivtv_call_i2c_clients(itv, VIDIOC_INT_S_STD_OUTPUT, &itv->std_out); | ||
1024 | ivtv_vapi(itv, CX2341X_DEC_SET_STANDARD, 1, itv->is_out_50hz); | ||
1025 | itv->main_rect.left = itv->main_rect.top = 0; | ||
1026 | itv->main_rect.width = 720; | ||
1027 | itv->main_rect.height = itv->params.height; | ||
1028 | ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 4, | ||
1029 | 720, itv->main_rect.height, 0, 0); | ||
1030 | } | ||
1031 | break; | ||
1032 | } | ||
1033 | |||
1034 | case VIDIOC_S_TUNER: { /* Setting tuner can only set audio mode */ | ||
1035 | struct v4l2_tuner *vt = arg; | ||
1036 | |||
1037 | IVTV_DEBUG_IOCTL("VIDIOC_S_TUNER\n"); | ||
1038 | |||
1039 | if (vt->index != 0) | ||
1040 | return -EINVAL; | ||
1041 | |||
1042 | ivtv_call_i2c_clients(itv, VIDIOC_S_TUNER, vt); | ||
1043 | break; | ||
1044 | } | ||
1045 | |||
1046 | case VIDIOC_G_TUNER: { | ||
1047 | struct v4l2_tuner *vt = arg; | ||
1048 | |||
1049 | IVTV_DEBUG_IOCTL("VIDIOC_G_TUNER\n"); | ||
1050 | |||
1051 | if (vt->index != 0) | ||
1052 | return -EINVAL; | ||
1053 | |||
1054 | memset(vt, 0, sizeof(*vt)); | ||
1055 | ivtv_call_i2c_clients(itv, VIDIOC_G_TUNER, vt); | ||
1056 | |||
1057 | if (test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags)) { | ||
1058 | strcpy(vt->name, "ivtv Radio Tuner"); | ||
1059 | vt->type = V4L2_TUNER_RADIO; | ||
1060 | } else { | ||
1061 | strcpy(vt->name, "ivtv TV Tuner"); | ||
1062 | vt->type = V4L2_TUNER_ANALOG_TV; | ||
1063 | } | ||
1064 | break; | ||
1065 | } | ||
1066 | |||
1067 | case VIDIOC_G_SLICED_VBI_CAP: { | ||
1068 | struct v4l2_sliced_vbi_cap *cap = arg; | ||
1069 | int set = itv->is_50hz ? V4L2_SLICED_VBI_625 : V4L2_SLICED_VBI_525; | ||
1070 | int f, l; | ||
1071 | enum v4l2_buf_type type = cap->type; | ||
1072 | |||
1073 | IVTV_DEBUG_IOCTL("VIDIOC_G_SLICED_VBI_CAP\n"); | ||
1074 | memset(cap, 0, sizeof(*cap)); | ||
1075 | cap->type = type; | ||
1076 | if (type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) { | ||
1077 | for (f = 0; f < 2; f++) { | ||
1078 | for (l = 0; l < 24; l++) { | ||
1079 | if (valid_service_line(f, l, itv->is_50hz)) { | ||
1080 | cap->service_lines[f][l] = set; | ||
1081 | } | ||
1082 | } | ||
1083 | } | ||
1084 | return 0; | ||
1085 | } | ||
1086 | if (type == V4L2_BUF_TYPE_SLICED_VBI_OUTPUT) { | ||
1087 | if (!(itv->v4l2_cap & V4L2_CAP_SLICED_VBI_OUTPUT)) | ||
1088 | return -EINVAL; | ||
1089 | if (itv->is_60hz) { | ||
1090 | cap->service_lines[0][21] = V4L2_SLICED_CAPTION_525; | ||
1091 | cap->service_lines[1][21] = V4L2_SLICED_CAPTION_525; | ||
1092 | } else { | ||
1093 | cap->service_lines[0][23] = V4L2_SLICED_WSS_625; | ||
1094 | cap->service_lines[0][16] = V4L2_SLICED_VPS; | ||
1095 | } | ||
1096 | return 0; | ||
1097 | } | ||
1098 | return -EINVAL; | ||
1099 | } | ||
1100 | |||
1101 | case VIDIOC_LOG_STATUS: | ||
1102 | { | ||
1103 | int has_output = itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT; | ||
1104 | struct v4l2_input vidin; | ||
1105 | struct v4l2_audio audin; | ||
1106 | int i; | ||
1107 | |||
1108 | IVTV_INFO("================= START STATUS CARD #%d =================\n", itv->num); | ||
1109 | if (itv->hw_flags & IVTV_HW_TVEEPROM) { | ||
1110 | struct tveeprom tv; | ||
1111 | |||
1112 | ivtv_read_eeprom(itv, &tv); | ||
1113 | } | ||
1114 | ivtv_call_i2c_clients(itv, VIDIOC_LOG_STATUS, NULL); | ||
1115 | ivtv_get_input(itv, itv->active_input, &vidin); | ||
1116 | ivtv_get_audio_input(itv, itv->audio_input, &audin); | ||
1117 | IVTV_INFO("Video Input: %s\n", vidin.name); | ||
1118 | IVTV_INFO("Audio Input: %s\n", audin.name); | ||
1119 | if (has_output) { | ||
1120 | struct v4l2_output vidout; | ||
1121 | struct v4l2_audioout audout; | ||
1122 | int mode = itv->output_mode; | ||
1123 | static const char * const output_modes[] = { | ||
1124 | "None", | ||
1125 | "MPEG Streaming", | ||
1126 | "YUV Streaming", | ||
1127 | "YUV Frames", | ||
1128 | "Passthrough", | ||
1129 | }; | ||
1130 | |||
1131 | ivtv_get_output(itv, itv->active_output, &vidout); | ||
1132 | ivtv_get_audio_output(itv, 0, &audout); | ||
1133 | IVTV_INFO("Video Output: %s\n", vidout.name); | ||
1134 | IVTV_INFO("Audio Output: %s\n", audout.name); | ||
1135 | if (mode < 0 || mode > OUT_PASSTHROUGH) | ||
1136 | mode = OUT_NONE; | ||
1137 | IVTV_INFO("Output Mode: %s\n", output_modes[mode]); | ||
1138 | } | ||
1139 | IVTV_INFO("Tuner: %s\n", | ||
1140 | test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags) ? "Radio" : "TV"); | ||
1141 | cx2341x_log_status(&itv->params, itv->name); | ||
1142 | IVTV_INFO("Status flags: 0x%08lx\n", itv->i_flags); | ||
1143 | for (i = 0; i < IVTV_MAX_STREAMS; i++) { | ||
1144 | struct ivtv_stream *s = &itv->streams[i]; | ||
1145 | |||
1146 | if (s->v4l2dev == NULL || s->buffers == 0) | ||
1147 | continue; | ||
1148 | IVTV_INFO("Stream %s: status 0x%04lx, %d%% of %d KiB (%d buffers) in use\n", s->name, s->s_flags, | ||
1149 | (s->buffers - s->q_free.buffers) * 100 / s->buffers, | ||
1150 | (s->buffers * s->buf_size) / 1024, s->buffers); | ||
1151 | } | ||
1152 | IVTV_INFO("Read MPEG/VBI: %lld/%lld bytes\n", itv->mpg_data_received, itv->vbi_data_inserted); | ||
1153 | IVTV_INFO("================== END STATUS CARD #%d ==================\n", itv->num); | ||
1154 | break; | ||
1155 | } | ||
1156 | |||
1157 | default: | ||
1158 | return -EINVAL; | ||
1159 | } | ||
1160 | return 0; | ||
1161 | } | ||
1162 | |||
1163 | static int ivtv_ivtv_ioctls(struct file *filp, unsigned int cmd, void *arg) | ||
1164 | { | ||
1165 | struct ivtv_open_id *id = (struct ivtv_open_id *)filp->private_data; | ||
1166 | struct ivtv *itv = id->itv; | ||
1167 | int nonblocking = filp->f_flags & O_NONBLOCK; | ||
1168 | struct ivtv_stream *s = &itv->streams[id->type]; | ||
1169 | |||
1170 | switch (cmd) { | ||
1171 | case IVTV_IOC_DMA_FRAME: { | ||
1172 | struct ivtv_dma_frame *args = arg; | ||
1173 | |||
1174 | IVTV_DEBUG_IOCTL("IVTV_IOC_DMA_FRAME\n"); | ||
1175 | if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) | ||
1176 | return -EINVAL; | ||
1177 | if (args->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) | ||
1178 | return -EINVAL; | ||
1179 | if (itv->output_mode == OUT_UDMA_YUV && args->y_source == NULL) | ||
1180 | return 0; | ||
1181 | if (ivtv_claim_stream(id, id->type)) { | ||
1182 | return -EBUSY; | ||
1183 | } | ||
1184 | if (ivtv_set_output_mode(itv, OUT_UDMA_YUV) != OUT_UDMA_YUV) { | ||
1185 | ivtv_release_stream(s); | ||
1186 | return -EBUSY; | ||
1187 | } | ||
1188 | if (args->y_source == NULL) | ||
1189 | return 0; | ||
1190 | return ivtv_yuv_prep_frame(itv, args); | ||
1191 | } | ||
1192 | |||
1193 | case VIDEO_GET_PTS: { | ||
1194 | u32 data[CX2341X_MBOX_MAX_DATA]; | ||
1195 | u64 *pts = arg; | ||
1196 | |||
1197 | IVTV_DEBUG_IOCTL("VIDEO_GET_PTS\n"); | ||
1198 | if (s->type < IVTV_DEC_STREAM_TYPE_MPG) { | ||
1199 | *pts = s->dma_pts; | ||
1200 | break; | ||
1201 | } | ||
1202 | if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) | ||
1203 | return -EINVAL; | ||
1204 | |||
1205 | if (test_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags)) { | ||
1206 | *pts = (u64) ((u64)itv->last_dec_timing[2] << 32) | | ||
1207 | (u64)itv->last_dec_timing[1]; | ||
1208 | break; | ||
1209 | } | ||
1210 | *pts = 0; | ||
1211 | if (atomic_read(&itv->decoding)) { | ||
1212 | if (ivtv_api(itv, CX2341X_DEC_GET_TIMING_INFO, 5, data)) { | ||
1213 | IVTV_DEBUG_WARN("GET_TIMING: couldn't read clock\n"); | ||
1214 | return -EIO; | ||
1215 | } | ||
1216 | memcpy(itv->last_dec_timing, data, sizeof(itv->last_dec_timing)); | ||
1217 | set_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags); | ||
1218 | *pts = (u64) ((u64) data[2] << 32) | (u64) data[1]; | ||
1219 | /*timing->scr = (u64) (((u64) data[4] << 32) | (u64) (data[3]));*/ | ||
1220 | } | ||
1221 | break; | ||
1222 | } | ||
1223 | |||
1224 | case VIDEO_GET_FRAME_COUNT: { | ||
1225 | u32 data[CX2341X_MBOX_MAX_DATA]; | ||
1226 | u64 *frame = arg; | ||
1227 | |||
1228 | IVTV_DEBUG_IOCTL("VIDEO_GET_FRAME_COUNT\n"); | ||
1229 | if (s->type < IVTV_DEC_STREAM_TYPE_MPG) { | ||
1230 | *frame = 0; | ||
1231 | break; | ||
1232 | } | ||
1233 | if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) | ||
1234 | return -EINVAL; | ||
1235 | |||
1236 | if (test_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags)) { | ||
1237 | *frame = itv->last_dec_timing[0]; | ||
1238 | break; | ||
1239 | } | ||
1240 | *frame = 0; | ||
1241 | if (atomic_read(&itv->decoding)) { | ||
1242 | if (ivtv_api(itv, CX2341X_DEC_GET_TIMING_INFO, 5, data)) { | ||
1243 | IVTV_DEBUG_WARN("GET_TIMING: couldn't read clock\n"); | ||
1244 | return -EIO; | ||
1245 | } | ||
1246 | memcpy(itv->last_dec_timing, data, sizeof(itv->last_dec_timing)); | ||
1247 | set_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags); | ||
1248 | *frame = data[0]; | ||
1249 | } | ||
1250 | break; | ||
1251 | } | ||
1252 | |||
1253 | case VIDEO_PLAY: { | ||
1254 | struct video_command vc; | ||
1255 | |||
1256 | IVTV_DEBUG_IOCTL("VIDEO_PLAY\n"); | ||
1257 | memset(&vc, 0, sizeof(vc)); | ||
1258 | vc.cmd = VIDEO_CMD_PLAY; | ||
1259 | return ivtv_video_command(itv, id, &vc, 0); | ||
1260 | } | ||
1261 | |||
1262 | case VIDEO_STOP: { | ||
1263 | struct video_command vc; | ||
1264 | |||
1265 | IVTV_DEBUG_IOCTL("VIDEO_STOP\n"); | ||
1266 | memset(&vc, 0, sizeof(vc)); | ||
1267 | vc.cmd = VIDEO_CMD_STOP; | ||
1268 | vc.flags = VIDEO_CMD_STOP_TO_BLACK | VIDEO_CMD_STOP_IMMEDIATELY; | ||
1269 | return ivtv_video_command(itv, id, &vc, 0); | ||
1270 | } | ||
1271 | |||
1272 | case VIDEO_FREEZE: { | ||
1273 | struct video_command vc; | ||
1274 | |||
1275 | IVTV_DEBUG_IOCTL("VIDEO_FREEZE\n"); | ||
1276 | memset(&vc, 0, sizeof(vc)); | ||
1277 | vc.cmd = VIDEO_CMD_FREEZE; | ||
1278 | return ivtv_video_command(itv, id, &vc, 0); | ||
1279 | } | ||
1280 | |||
1281 | case VIDEO_CONTINUE: { | ||
1282 | struct video_command vc; | ||
1283 | |||
1284 | IVTV_DEBUG_IOCTL("VIDEO_CONTINUE\n"); | ||
1285 | memset(&vc, 0, sizeof(vc)); | ||
1286 | vc.cmd = VIDEO_CMD_CONTINUE; | ||
1287 | return ivtv_video_command(itv, id, &vc, 0); | ||
1288 | } | ||
1289 | |||
1290 | case VIDEO_COMMAND: | ||
1291 | case VIDEO_TRY_COMMAND: { | ||
1292 | struct video_command *vc = arg; | ||
1293 | int try = (cmd == VIDEO_TRY_COMMAND); | ||
1294 | |||
1295 | if (try) | ||
1296 | IVTV_DEBUG_IOCTL("VIDEO_TRY_COMMAND\n"); | ||
1297 | else | ||
1298 | IVTV_DEBUG_IOCTL("VIDEO_COMMAND\n"); | ||
1299 | return ivtv_video_command(itv, id, vc, try); | ||
1300 | } | ||
1301 | |||
1302 | case VIDEO_GET_EVENT: { | ||
1303 | struct video_event *ev = arg; | ||
1304 | DEFINE_WAIT(wait); | ||
1305 | |||
1306 | IVTV_DEBUG_IOCTL("VIDEO_GET_EVENT\n"); | ||
1307 | if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) | ||
1308 | return -EINVAL; | ||
1309 | memset(ev, 0, sizeof(*ev)); | ||
1310 | set_bit(IVTV_F_I_EV_VSYNC_ENABLED, &itv->i_flags); | ||
1311 | |||
1312 | while (1) { | ||
1313 | if (test_and_clear_bit(IVTV_F_I_EV_DEC_STOPPED, &itv->i_flags)) | ||
1314 | ev->type = VIDEO_EVENT_DECODER_STOPPED; | ||
1315 | else if (test_and_clear_bit(IVTV_F_I_EV_VSYNC, &itv->i_flags)) { | ||
1316 | ev->type = VIDEO_EVENT_VSYNC; | ||
1317 | ev->timestamp = test_bit(IVTV_F_I_EV_VSYNC_FIELD, &itv->i_flags) ? | ||
1318 | 1 : 0; | ||
1319 | clear_bit(IVTV_F_I_EV_VSYNC_ENABLED, &itv->i_flags); | ||
1320 | } | ||
1321 | if (ev->type) | ||
1322 | return 0; | ||
1323 | if (nonblocking) | ||
1324 | return -EAGAIN; | ||
1325 | /* wait for event */ | ||
1326 | prepare_to_wait(&itv->event_waitq, &wait, TASK_INTERRUPTIBLE); | ||
1327 | if ((itv->i_flags & (IVTV_F_I_EV_DEC_STOPPED|IVTV_F_I_EV_VSYNC)) == 0) | ||
1328 | schedule(); | ||
1329 | finish_wait(&itv->event_waitq, &wait); | ||
1330 | if (signal_pending(current)) { | ||
1331 | /* return if a signal was received */ | ||
1332 | IVTV_DEBUG_INFO("User stopped wait for event\n"); | ||
1333 | return -EINTR; | ||
1334 | } | ||
1335 | } | ||
1336 | break; | ||
1337 | } | ||
1338 | |||
1339 | case VIDIOC_G_ENC_INDEX: { | ||
1340 | struct v4l2_enc_idx *idx = arg; | ||
1341 | int i; | ||
1342 | |||
1343 | IVTV_DEBUG_IOCTL("VIDIOC_G_ENC_INDEX\n"); | ||
1344 | idx->entries = (itv->pgm_info_write_idx + IVTV_MAX_PGM_INDEX - itv->pgm_info_read_idx) % | ||
1345 | IVTV_MAX_PGM_INDEX; | ||
1346 | if (idx->entries > V4L2_ENC_IDX_ENTRIES) | ||
1347 | idx->entries = V4L2_ENC_IDX_ENTRIES; | ||
1348 | for (i = 0; i < idx->entries; i++) { | ||
1349 | idx->entry[i] = itv->pgm_info[(itv->pgm_info_read_idx + i) % IVTV_MAX_PGM_INDEX]; | ||
1350 | } | ||
1351 | itv->pgm_info_read_idx = (itv->pgm_info_read_idx + idx->entries) % IVTV_MAX_PGM_INDEX; | ||
1352 | break; | ||
1353 | } | ||
1354 | |||
1355 | case VIDIOC_ENCODER_CMD: | ||
1356 | case VIDIOC_TRY_ENCODER_CMD: { | ||
1357 | struct v4l2_encoder_cmd *enc = arg; | ||
1358 | int try = cmd == VIDIOC_TRY_ENCODER_CMD; | ||
1359 | |||
1360 | if (try) | ||
1361 | IVTV_DEBUG_IOCTL("VIDIOC_TRY_ENCODER_CMD\n"); | ||
1362 | else | ||
1363 | IVTV_DEBUG_IOCTL("VIDIOC_ENCODER_CMD\n"); | ||
1364 | switch (enc->cmd) { | ||
1365 | case V4L2_ENC_CMD_START: | ||
1366 | return ivtv_start_capture(id); | ||
1367 | |||
1368 | case V4L2_ENC_CMD_STOP: | ||
1369 | ivtv_stop_capture(id, enc->flags & V4L2_ENC_CMD_STOP_AT_GOP_END); | ||
1370 | return 0; | ||
1371 | |||
1372 | case V4L2_ENC_CMD_PAUSE: | ||
1373 | if (!atomic_read(&itv->capturing)) | ||
1374 | return -EPERM; | ||
1375 | if (test_and_set_bit(IVTV_F_I_ENC_PAUSED, &itv->i_flags)) | ||
1376 | return 0; | ||
1377 | ivtv_mute(itv); | ||
1378 | ivtv_vapi(itv, CX2341X_ENC_PAUSE_ENCODER, 1, 0); | ||
1379 | break; | ||
1380 | |||
1381 | case V4L2_ENC_CMD_RESUME: | ||
1382 | if (!atomic_read(&itv->capturing)) | ||
1383 | return -EPERM; | ||
1384 | if (!test_and_clear_bit(IVTV_F_I_ENC_PAUSED, &itv->i_flags)) | ||
1385 | return 0; | ||
1386 | ivtv_vapi(itv, CX2341X_ENC_PAUSE_ENCODER, 1, 1); | ||
1387 | ivtv_unmute(itv); | ||
1388 | break; | ||
1389 | } | ||
1390 | break; | ||
1391 | } | ||
1392 | |||
1393 | case VIDIOC_G_FBUF: { | ||
1394 | struct v4l2_framebuffer *fb = arg; | ||
1395 | |||
1396 | IVTV_DEBUG_IOCTL("VIDIOC_G_FBUF\n"); | ||
1397 | memset(fb, 0, sizeof(*fb)); | ||
1398 | if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT_OVERLAY)) | ||
1399 | break; | ||
1400 | fb->capability = V4L2_FBUF_CAP_EXTERNOVERLAY | V4L2_FBUF_CAP_CHROMAKEY | | ||
1401 | V4L2_FBUF_CAP_LOCAL_ALPHA | V4L2_FBUF_CAP_GLOBAL_ALPHA; | ||
1402 | fb->fmt.pixelformat = itv->osd_pixelformat; | ||
1403 | fb->fmt.width = itv->osd_rect.width; | ||
1404 | fb->fmt.height = itv->osd_rect.height; | ||
1405 | fb->fmt.left = itv->osd_rect.left; | ||
1406 | fb->fmt.top = itv->osd_rect.top; | ||
1407 | fb->base = (void *)itv->osd_video_pbase; | ||
1408 | if (itv->osd_global_alpha_state) | ||
1409 | fb->flags |= V4L2_FBUF_FLAG_GLOBAL_ALPHA; | ||
1410 | if (itv->osd_local_alpha_state) | ||
1411 | fb->flags |= V4L2_FBUF_FLAG_LOCAL_ALPHA; | ||
1412 | if (itv->osd_color_key_state) | ||
1413 | fb->flags |= V4L2_FBUF_FLAG_CHROMAKEY; | ||
1414 | break; | ||
1415 | } | ||
1416 | |||
1417 | case VIDIOC_S_FBUF: { | ||
1418 | struct v4l2_framebuffer *fb = arg; | ||
1419 | |||
1420 | IVTV_DEBUG_IOCTL("VIDIOC_S_FBUF\n"); | ||
1421 | if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT_OVERLAY)) | ||
1422 | break; | ||
1423 | itv->osd_global_alpha_state = (fb->flags & V4L2_FBUF_FLAG_GLOBAL_ALPHA) != 0; | ||
1424 | itv->osd_local_alpha_state = (fb->flags & V4L2_FBUF_FLAG_LOCAL_ALPHA) != 0; | ||
1425 | itv->osd_color_key_state = (fb->flags & V4L2_FBUF_FLAG_CHROMAKEY) != 0; | ||
1426 | break; | ||
1427 | } | ||
1428 | |||
1429 | default: | ||
1430 | return -EINVAL; | ||
1431 | } | ||
1432 | return 0; | ||
1433 | } | ||
1434 | |||
1435 | static int ivtv_v4l2_do_ioctl(struct inode *inode, struct file *filp, | ||
1436 | unsigned int cmd, void *arg) | ||
1437 | { | ||
1438 | struct ivtv_open_id *id = (struct ivtv_open_id *)filp->private_data; | ||
1439 | struct ivtv *itv = id->itv; | ||
1440 | |||
1441 | IVTV_DEBUG_IOCTL("v4l2 ioctl 0x%08x\n", cmd); | ||
1442 | |||
1443 | switch (cmd) { | ||
1444 | case VIDIOC_DBG_G_REGISTER: | ||
1445 | case VIDIOC_DBG_S_REGISTER: | ||
1446 | case VIDIOC_G_CHIP_IDENT: | ||
1447 | case VIDIOC_INT_S_AUDIO_ROUTING: | ||
1448 | case VIDIOC_INT_RESET: | ||
1449 | return ivtv_internal_ioctls(filp, cmd, arg); | ||
1450 | |||
1451 | case VIDIOC_QUERYCAP: | ||
1452 | case VIDIOC_ENUMINPUT: | ||
1453 | case VIDIOC_G_INPUT: | ||
1454 | case VIDIOC_S_INPUT: | ||
1455 | case VIDIOC_ENUMOUTPUT: | ||
1456 | case VIDIOC_G_OUTPUT: | ||
1457 | case VIDIOC_S_OUTPUT: | ||
1458 | case VIDIOC_G_FMT: | ||
1459 | case VIDIOC_S_FMT: | ||
1460 | case VIDIOC_TRY_FMT: | ||
1461 | case VIDIOC_ENUM_FMT: | ||
1462 | case VIDIOC_G_CROP: | ||
1463 | case VIDIOC_S_CROP: | ||
1464 | case VIDIOC_G_FREQUENCY: | ||
1465 | case VIDIOC_S_FREQUENCY: | ||
1466 | case VIDIOC_ENUMSTD: | ||
1467 | case VIDIOC_G_STD: | ||
1468 | case VIDIOC_S_STD: | ||
1469 | case VIDIOC_S_TUNER: | ||
1470 | case VIDIOC_G_TUNER: | ||
1471 | case VIDIOC_ENUMAUDIO: | ||
1472 | case VIDIOC_S_AUDIO: | ||
1473 | case VIDIOC_G_AUDIO: | ||
1474 | case VIDIOC_ENUMAUDOUT: | ||
1475 | case VIDIOC_S_AUDOUT: | ||
1476 | case VIDIOC_G_AUDOUT: | ||
1477 | case VIDIOC_G_SLICED_VBI_CAP: | ||
1478 | case VIDIOC_LOG_STATUS: | ||
1479 | return ivtv_v4l2_ioctls(itv, filp, cmd, arg); | ||
1480 | |||
1481 | case VIDIOC_QUERYMENU: | ||
1482 | case VIDIOC_QUERYCTRL: | ||
1483 | case VIDIOC_S_CTRL: | ||
1484 | case VIDIOC_G_CTRL: | ||
1485 | case VIDIOC_S_EXT_CTRLS: | ||
1486 | case VIDIOC_G_EXT_CTRLS: | ||
1487 | case VIDIOC_TRY_EXT_CTRLS: | ||
1488 | return ivtv_control_ioctls(itv, cmd, arg); | ||
1489 | |||
1490 | case IVTV_IOC_DMA_FRAME: | ||
1491 | case VIDEO_GET_PTS: | ||
1492 | case VIDEO_GET_FRAME_COUNT: | ||
1493 | case VIDEO_GET_EVENT: | ||
1494 | case VIDEO_PLAY: | ||
1495 | case VIDEO_STOP: | ||
1496 | case VIDEO_FREEZE: | ||
1497 | case VIDEO_CONTINUE: | ||
1498 | case VIDEO_COMMAND: | ||
1499 | case VIDEO_TRY_COMMAND: | ||
1500 | case VIDIOC_G_ENC_INDEX: | ||
1501 | case VIDIOC_ENCODER_CMD: | ||
1502 | case VIDIOC_TRY_ENCODER_CMD: | ||
1503 | case VIDIOC_G_FBUF: | ||
1504 | case VIDIOC_S_FBUF: | ||
1505 | return ivtv_ivtv_ioctls(filp, cmd, arg); | ||
1506 | |||
1507 | case 0x00005401: /* Handle isatty() calls */ | ||
1508 | return -EINVAL; | ||
1509 | default: | ||
1510 | return v4l_compat_translate_ioctl(inode, filp, cmd, arg, | ||
1511 | ivtv_v4l2_do_ioctl); | ||
1512 | } | ||
1513 | return 0; | ||
1514 | } | ||
1515 | |||
1516 | int ivtv_v4l2_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, | ||
1517 | unsigned long arg) | ||
1518 | { | ||
1519 | struct ivtv_open_id *id = (struct ivtv_open_id *)filp->private_data; | ||
1520 | struct ivtv *itv = id->itv; | ||
1521 | |||
1522 | /* Filter dvb ioctls that cannot be handled by video_usercopy */ | ||
1523 | switch (cmd) { | ||
1524 | case VIDEO_SELECT_SOURCE: | ||
1525 | IVTV_DEBUG_IOCTL("VIDEO_SELECT_SOURCE\n"); | ||
1526 | if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) | ||
1527 | return -EINVAL; | ||
1528 | return ivtv_passthrough_mode(itv, arg == VIDEO_SOURCE_DEMUX); | ||
1529 | |||
1530 | case AUDIO_SET_MUTE: | ||
1531 | IVTV_DEBUG_IOCTL("AUDIO_SET_MUTE\n"); | ||
1532 | itv->speed_mute_audio = arg; | ||
1533 | return 0; | ||
1534 | |||
1535 | case AUDIO_CHANNEL_SELECT: | ||
1536 | IVTV_DEBUG_IOCTL("AUDIO_CHANNEL_SELECT\n"); | ||
1537 | if (arg > AUDIO_STEREO_SWAPPED) | ||
1538 | return -EINVAL; | ||
1539 | itv->audio_stereo_mode = arg; | ||
1540 | ivtv_vapi(itv, CX2341X_DEC_SET_AUDIO_MODE, 2, itv->audio_bilingual_mode, itv->audio_stereo_mode); | ||
1541 | return 0; | ||
1542 | |||
1543 | case AUDIO_BILINGUAL_CHANNEL_SELECT: | ||
1544 | IVTV_DEBUG_IOCTL("AUDIO_BILINGUAL_CHANNEL_SELECT\n"); | ||
1545 | if (arg > AUDIO_STEREO_SWAPPED) | ||
1546 | return -EINVAL; | ||
1547 | itv->audio_bilingual_mode = arg; | ||
1548 | ivtv_vapi(itv, CX2341X_DEC_SET_AUDIO_MODE, 2, itv->audio_bilingual_mode, itv->audio_stereo_mode); | ||
1549 | return 0; | ||
1550 | |||
1551 | default: | ||
1552 | break; | ||
1553 | } | ||
1554 | return video_usercopy(inode, filp, cmd, arg, ivtv_v4l2_do_ioctl); | ||
1555 | } | ||
diff --git a/drivers/media/video/ivtv/ivtv-ioctl.h b/drivers/media/video/ivtv/ivtv-ioctl.h new file mode 100644 index 000000000000..cbccf7a9f65c --- /dev/null +++ b/drivers/media/video/ivtv/ivtv-ioctl.h | |||
@@ -0,0 +1,28 @@ | |||
1 | /* | ||
2 | ioctl system call | ||
3 | Copyright (C) 2003-2004 Kevin Thayer <nufan_wfk at yahoo.com> | ||
4 | Copyright (C) 2005-2007 Hans Verkuil <hverkuil@xs4all.nl> | ||
5 | |||
6 | This program is free software; you can redistribute it and/or modify | ||
7 | it under the terms of the GNU General Public License as published by | ||
8 | the Free Software Foundation; either version 2 of the License, or | ||
9 | (at your option) any later version. | ||
10 | |||
11 | This program is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program; if not, write to the Free Software | ||
18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | */ | ||
20 | |||
21 | u16 service2vbi(int type); | ||
22 | void expand_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal); | ||
23 | u16 get_service_set(struct v4l2_sliced_vbi_format *fmt); | ||
24 | int ivtv_v4l2_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, | ||
25 | unsigned long arg); | ||
26 | int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void *arg); | ||
27 | void ivtv_set_osd_alpha(struct ivtv *itv); | ||
28 | int ivtv_set_speed(struct ivtv *itv, int speed); | ||
diff --git a/drivers/media/video/ivtv/ivtv-irq.c b/drivers/media/video/ivtv/ivtv-irq.c new file mode 100644 index 000000000000..0656e18b7c7e --- /dev/null +++ b/drivers/media/video/ivtv/ivtv-irq.c | |||
@@ -0,0 +1,818 @@ | |||
1 | /* interrupt handling | ||
2 | Copyright (C) 2003-2004 Kevin Thayer <nufan_wfk at yahoo.com> | ||
3 | Copyright (C) 2004 Chris Kennedy <c@groovy.org> | ||
4 | Copyright (C) 2005-2007 Hans Verkuil <hverkuil@xs4all.nl> | ||
5 | |||
6 | This program is free software; you can redistribute it and/or modify | ||
7 | it under the terms of the GNU General Public License as published by | ||
8 | the Free Software Foundation; either version 2 of the License, or | ||
9 | (at your option) any later version. | ||
10 | |||
11 | This program is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program; if not, write to the Free Software | ||
18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | */ | ||
20 | |||
21 | #include "ivtv-driver.h" | ||
22 | #include "ivtv-firmware.h" | ||
23 | #include "ivtv-fileops.h" | ||
24 | #include "ivtv-queue.h" | ||
25 | #include "ivtv-udma.h" | ||
26 | #include "ivtv-irq.h" | ||
27 | #include "ivtv-ioctl.h" | ||
28 | #include "ivtv-mailbox.h" | ||
29 | #include "ivtv-vbi.h" | ||
30 | |||
31 | #define DMA_MAGIC_COOKIE 0x000001fe | ||
32 | |||
33 | #define SLICED_VBI_PIO 1 | ||
34 | |||
35 | static void ivtv_dma_dec_start(struct ivtv_stream *s); | ||
36 | |||
37 | static const int ivtv_stream_map[] = { | ||
38 | IVTV_ENC_STREAM_TYPE_MPG, | ||
39 | IVTV_ENC_STREAM_TYPE_YUV, | ||
40 | IVTV_ENC_STREAM_TYPE_PCM, | ||
41 | IVTV_ENC_STREAM_TYPE_VBI, | ||
42 | }; | ||
43 | |||
44 | static inline int ivtv_use_pio(struct ivtv_stream *s) | ||
45 | { | ||
46 | struct ivtv *itv = s->itv; | ||
47 | |||
48 | return s->dma == PCI_DMA_NONE || | ||
49 | (SLICED_VBI_PIO && s->type == IVTV_ENC_STREAM_TYPE_VBI && itv->vbi.sliced_in->service_set); | ||
50 | } | ||
51 | |||
52 | /* Determine the required DMA size, setup enough buffers in the predma queue and | ||
53 | actually copy the data from the card to the buffers in case a PIO transfer is | ||
54 | required for this stream. | ||
55 | */ | ||
56 | static int stream_enc_dma_append(struct ivtv_stream *s, u32 data[CX2341X_MBOX_MAX_DATA]) | ||
57 | { | ||
58 | struct ivtv *itv = s->itv; | ||
59 | struct ivtv_buffer *buf; | ||
60 | struct list_head *p; | ||
61 | u32 bytes_needed = 0; | ||
62 | u32 offset, size; | ||
63 | u32 UVoffset = 0, UVsize = 0; | ||
64 | int skip_bufs = s->q_predma.buffers; | ||
65 | int idx = s->SG_length; | ||
66 | int rc; | ||
67 | |||
68 | /* sanity checks */ | ||
69 | if (s->v4l2dev == NULL) { | ||
70 | IVTV_DEBUG_WARN("Stream %s not started\n", s->name); | ||
71 | return -1; | ||
72 | } | ||
73 | if (!test_bit(IVTV_F_S_CLAIMED, &s->s_flags)) { | ||
74 | IVTV_DEBUG_WARN("Stream %s not open\n", s->name); | ||
75 | return -1; | ||
76 | } | ||
77 | |||
78 | /* determine offset, size and PTS for the various streams */ | ||
79 | switch (s->type) { | ||
80 | case IVTV_ENC_STREAM_TYPE_MPG: | ||
81 | offset = data[1]; | ||
82 | size = data[2]; | ||
83 | s->dma_pts = 0; | ||
84 | break; | ||
85 | |||
86 | case IVTV_ENC_STREAM_TYPE_YUV: | ||
87 | offset = data[1]; | ||
88 | size = data[2]; | ||
89 | UVoffset = data[3]; | ||
90 | UVsize = data[4]; | ||
91 | s->dma_pts = ((u64) data[5] << 32) | data[6]; | ||
92 | break; | ||
93 | |||
94 | case IVTV_ENC_STREAM_TYPE_PCM: | ||
95 | offset = data[1] + 12; | ||
96 | size = data[2] - 12; | ||
97 | s->dma_pts = read_dec(offset - 8) | | ||
98 | ((u64)(read_dec(offset - 12)) << 32); | ||
99 | if (itv->has_cx23415) | ||
100 | offset += IVTV_DECODER_OFFSET; | ||
101 | break; | ||
102 | |||
103 | case IVTV_ENC_STREAM_TYPE_VBI: | ||
104 | size = itv->vbi.enc_size * itv->vbi.fpi; | ||
105 | offset = read_enc(itv->vbi.enc_start - 4) + 12; | ||
106 | if (offset == 12) { | ||
107 | IVTV_DEBUG_INFO("VBI offset == 0\n"); | ||
108 | return -1; | ||
109 | } | ||
110 | s->dma_pts = read_enc(offset - 4) | ((u64)read_enc(offset - 8) << 32); | ||
111 | break; | ||
112 | |||
113 | case IVTV_DEC_STREAM_TYPE_VBI: | ||
114 | size = read_dec(itv->vbi.dec_start + 4) + 8; | ||
115 | offset = read_dec(itv->vbi.dec_start) + itv->vbi.dec_start; | ||
116 | s->dma_pts = 0; | ||
117 | offset += IVTV_DECODER_OFFSET; | ||
118 | break; | ||
119 | default: | ||
120 | /* shouldn't happen */ | ||
121 | return -1; | ||
122 | } | ||
123 | |||
124 | /* if this is the start of the DMA then fill in the magic cookie */ | ||
125 | if (s->SG_length == 0) { | ||
126 | if (itv->has_cx23415 && (s->type == IVTV_ENC_STREAM_TYPE_PCM || | ||
127 | s->type == IVTV_DEC_STREAM_TYPE_VBI)) { | ||
128 | s->dma_backup = read_dec(offset - IVTV_DECODER_OFFSET); | ||
129 | write_dec_sync(cpu_to_le32(DMA_MAGIC_COOKIE), offset - IVTV_DECODER_OFFSET); | ||
130 | } | ||
131 | else { | ||
132 | s->dma_backup = read_enc(offset); | ||
133 | write_enc_sync(cpu_to_le32(DMA_MAGIC_COOKIE), offset); | ||
134 | } | ||
135 | s->dma_offset = offset; | ||
136 | } | ||
137 | |||
138 | bytes_needed = size; | ||
139 | if (s->type == IVTV_ENC_STREAM_TYPE_YUV) { | ||
140 | /* The size for the Y samples needs to be rounded upwards to a | ||
141 | multiple of the buf_size. The UV samples then start in the | ||
142 | next buffer. */ | ||
143 | bytes_needed = s->buf_size * ((bytes_needed + s->buf_size - 1) / s->buf_size); | ||
144 | bytes_needed += UVsize; | ||
145 | } | ||
146 | |||
147 | IVTV_DEBUG_DMA("%s %s: 0x%08x bytes at 0x%08x\n", | ||
148 | ivtv_use_pio(s) ? "PIO" : "DMA", s->name, bytes_needed, offset); | ||
149 | |||
150 | rc = ivtv_queue_move(s, &s->q_free, &s->q_full, &s->q_predma, bytes_needed); | ||
151 | if (rc < 0) { /* Insufficient buffers */ | ||
152 | IVTV_DEBUG_WARN("Cannot obtain %d bytes for %s data transfer\n", | ||
153 | bytes_needed, s->name); | ||
154 | return -1; | ||
155 | } | ||
156 | if (rc && !s->buffers_stolen && (s->s_flags & IVTV_F_S_APPL_IO)) { | ||
157 | IVTV_WARN("All %s stream buffers are full. Dropping data.\n", s->name); | ||
158 | IVTV_WARN("Cause: the application is not reading fast enough.\n"); | ||
159 | } | ||
160 | s->buffers_stolen = rc; | ||
161 | |||
162 | /* got the buffers, now fill in SGarray (DMA) or copy the data from the card | ||
163 | to the buffers (PIO). */ | ||
164 | buf = list_entry(s->q_predma.list.next, struct ivtv_buffer, list); | ||
165 | memset(buf->buf, 0, 128); | ||
166 | list_for_each(p, &s->q_predma.list) { | ||
167 | struct ivtv_buffer *buf = list_entry(p, struct ivtv_buffer, list); | ||
168 | |||
169 | if (skip_bufs-- > 0) | ||
170 | continue; | ||
171 | if (!ivtv_use_pio(s)) { | ||
172 | s->SGarray[idx].dst = cpu_to_le32(buf->dma_handle); | ||
173 | s->SGarray[idx].src = cpu_to_le32(offset); | ||
174 | s->SGarray[idx].size = cpu_to_le32(s->buf_size); | ||
175 | } | ||
176 | buf->bytesused = (size < s->buf_size) ? size : s->buf_size; | ||
177 | |||
178 | /* If PIO, then copy the data from the card to the buffer */ | ||
179 | if (s->type == IVTV_DEC_STREAM_TYPE_VBI) { | ||
180 | memcpy_fromio(buf->buf, itv->dec_mem + offset - IVTV_DECODER_OFFSET, buf->bytesused); | ||
181 | } | ||
182 | else if (ivtv_use_pio(s)) { | ||
183 | memcpy_fromio(buf->buf, itv->enc_mem + offset, buf->bytesused); | ||
184 | } | ||
185 | |||
186 | s->q_predma.bytesused += buf->bytesused; | ||
187 | size -= buf->bytesused; | ||
188 | offset += s->buf_size; | ||
189 | |||
190 | /* Sync SG buffers */ | ||
191 | ivtv_buf_sync_for_device(s, buf); | ||
192 | |||
193 | if (size == 0) { /* YUV */ | ||
194 | /* process the UV section */ | ||
195 | offset = UVoffset; | ||
196 | size = UVsize; | ||
197 | } | ||
198 | idx++; | ||
199 | } | ||
200 | s->SG_length = idx; | ||
201 | return 0; | ||
202 | } | ||
203 | |||
204 | static void dma_post(struct ivtv_stream *s) | ||
205 | { | ||
206 | struct ivtv *itv = s->itv; | ||
207 | struct ivtv_buffer *buf = NULL; | ||
208 | struct list_head *p; | ||
209 | u32 offset; | ||
210 | u32 *u32buf; | ||
211 | int x = 0; | ||
212 | |||
213 | if (ivtv_use_pio(s)) { | ||
214 | if (s->q_predma.bytesused) | ||
215 | ivtv_queue_move(s, &s->q_predma, NULL, &s->q_dma, s->q_predma.bytesused); | ||
216 | s->SG_length = 0; | ||
217 | } | ||
218 | IVTV_DEBUG_DMA("%s %s completed (%x)\n", ivtv_use_pio(s) ? "PIO" : "DMA", | ||
219 | s->name, s->dma_offset); | ||
220 | list_for_each(p, &s->q_dma.list) { | ||
221 | buf = list_entry(p, struct ivtv_buffer, list); | ||
222 | u32buf = (u32 *)buf->buf; | ||
223 | |||
224 | /* Sync Buffer */ | ||
225 | ivtv_buf_sync_for_cpu(s, buf); | ||
226 | |||
227 | if (x == 0) { | ||
228 | offset = s->dma_last_offset; | ||
229 | if (u32buf[offset / 4] != DMA_MAGIC_COOKIE) | ||
230 | { | ||
231 | for (offset = 0; offset < 64; offset++) { | ||
232 | if (u32buf[offset] == DMA_MAGIC_COOKIE) { | ||
233 | break; | ||
234 | } | ||
235 | } | ||
236 | offset *= 4; | ||
237 | if (offset == 256) { | ||
238 | IVTV_DEBUG_WARN("%s: Couldn't find start of buffer within the first 256 bytes\n", s->name); | ||
239 | offset = s->dma_last_offset; | ||
240 | } | ||
241 | if (s->dma_last_offset != offset) | ||
242 | IVTV_DEBUG_WARN("%s: offset %d -> %d\n", s->name, s->dma_last_offset, offset); | ||
243 | s->dma_last_offset = offset; | ||
244 | } | ||
245 | if (itv->has_cx23415 && (s->type == IVTV_ENC_STREAM_TYPE_PCM || | ||
246 | s->type == IVTV_DEC_STREAM_TYPE_VBI)) { | ||
247 | write_dec_sync(0, s->dma_offset - IVTV_DECODER_OFFSET); | ||
248 | } | ||
249 | else { | ||
250 | write_enc_sync(0, s->dma_offset); | ||
251 | } | ||
252 | if (offset) { | ||
253 | buf->bytesused -= offset; | ||
254 | memcpy(buf->buf, buf->buf + offset, buf->bytesused + offset); | ||
255 | } | ||
256 | *u32buf = cpu_to_le32(s->dma_backup); | ||
257 | } | ||
258 | x++; | ||
259 | /* flag byteswap ABCD -> DCBA for MPG & VBI data outside irq */ | ||
260 | if (s->type == IVTV_ENC_STREAM_TYPE_MPG || | ||
261 | s->type == IVTV_ENC_STREAM_TYPE_VBI) | ||
262 | set_bit(IVTV_F_B_NEED_BUF_SWAP, &buf->b_flags); | ||
263 | } | ||
264 | if (buf) | ||
265 | buf->bytesused += s->dma_last_offset; | ||
266 | if (buf && s->type == IVTV_DEC_STREAM_TYPE_VBI) { | ||
267 | /* Parse and Groom VBI Data */ | ||
268 | s->q_dma.bytesused -= buf->bytesused; | ||
269 | ivtv_process_vbi_data(itv, buf, 0, s->type); | ||
270 | s->q_dma.bytesused += buf->bytesused; | ||
271 | if (s->id == -1) { | ||
272 | ivtv_queue_move(s, &s->q_dma, NULL, &s->q_free, 0); | ||
273 | return; | ||
274 | } | ||
275 | } | ||
276 | ivtv_queue_move(s, &s->q_dma, NULL, &s->q_full, s->q_dma.bytesused); | ||
277 | if (s->id != -1) | ||
278 | wake_up(&s->waitq); | ||
279 | } | ||
280 | |||
281 | void ivtv_dma_stream_dec_prepare(struct ivtv_stream *s, u32 offset, int lock) | ||
282 | { | ||
283 | struct ivtv *itv = s->itv; | ||
284 | struct ivtv_buffer *buf; | ||
285 | struct list_head *p; | ||
286 | u32 y_size = itv->params.height * itv->params.width; | ||
287 | u32 uv_offset = offset + IVTV_YUV_BUFFER_UV_OFFSET; | ||
288 | int y_done = 0; | ||
289 | int bytes_written = 0; | ||
290 | unsigned long flags = 0; | ||
291 | int idx = 0; | ||
292 | |||
293 | IVTV_DEBUG_DMA("DEC PREPARE DMA %s: %08x %08x\n", s->name, s->q_predma.bytesused, offset); | ||
294 | buf = list_entry(s->q_predma.list.next, struct ivtv_buffer, list); | ||
295 | list_for_each(p, &s->q_predma.list) { | ||
296 | struct ivtv_buffer *buf = list_entry(p, struct ivtv_buffer, list); | ||
297 | |||
298 | /* YUV UV Offset from Y Buffer */ | ||
299 | if (s->type == IVTV_DEC_STREAM_TYPE_YUV && !y_done && bytes_written >= y_size) { | ||
300 | offset = uv_offset; | ||
301 | y_done = 1; | ||
302 | } | ||
303 | s->SGarray[idx].src = cpu_to_le32(buf->dma_handle); | ||
304 | s->SGarray[idx].dst = cpu_to_le32(offset); | ||
305 | s->SGarray[idx].size = cpu_to_le32(buf->bytesused); | ||
306 | |||
307 | offset += buf->bytesused; | ||
308 | bytes_written += buf->bytesused; | ||
309 | |||
310 | /* Sync SG buffers */ | ||
311 | ivtv_buf_sync_for_device(s, buf); | ||
312 | idx++; | ||
313 | } | ||
314 | s->SG_length = idx; | ||
315 | |||
316 | /* Mark last buffer size for Interrupt flag */ | ||
317 | s->SGarray[s->SG_length - 1].size |= cpu_to_le32(0x80000000); | ||
318 | |||
319 | /* Sync Hardware SG List of buffers */ | ||
320 | ivtv_stream_sync_for_device(s); | ||
321 | if (lock) | ||
322 | spin_lock_irqsave(&itv->dma_reg_lock, flags); | ||
323 | if (!test_bit(IVTV_F_I_DMA, &itv->i_flags)) { | ||
324 | ivtv_dma_dec_start(s); | ||
325 | } | ||
326 | else { | ||
327 | set_bit(IVTV_F_S_DMA_PENDING, &s->s_flags); | ||
328 | } | ||
329 | if (lock) | ||
330 | spin_unlock_irqrestore(&itv->dma_reg_lock, flags); | ||
331 | } | ||
332 | |||
333 | /* start the encoder DMA */ | ||
334 | static void ivtv_dma_enc_start(struct ivtv_stream *s) | ||
335 | { | ||
336 | struct ivtv *itv = s->itv; | ||
337 | struct ivtv_stream *s_vbi = &itv->streams[IVTV_ENC_STREAM_TYPE_VBI]; | ||
338 | int i; | ||
339 | |||
340 | if (s->q_predma.bytesused) | ||
341 | ivtv_queue_move(s, &s->q_predma, NULL, &s->q_dma, s->q_predma.bytesused); | ||
342 | IVTV_DEBUG_DMA("start DMA for %s\n", s->name); | ||
343 | s->SGarray[s->SG_length - 1].size = cpu_to_le32(le32_to_cpu(s->SGarray[s->SG_length - 1].size) + 256); | ||
344 | |||
345 | /* If this is an MPEG stream, and VBI data is also pending, then append the | ||
346 | VBI DMA to the MPEG DMA and transfer both sets of data at once. | ||
347 | |||
348 | VBI DMA is a second class citizen compared to MPEG and mixing them together | ||
349 | will confuse the firmware (the end of a VBI DMA is seen as the end of a | ||
350 | MPEG DMA, thus effectively dropping an MPEG frame). So instead we make | ||
351 | sure we only use the MPEG DMA to transfer the VBI DMA if both are in | ||
352 | use. This way no conflicts occur. */ | ||
353 | clear_bit(IVTV_F_S_DMA_HAS_VBI, &s->s_flags); | ||
354 | if (s->type == IVTV_ENC_STREAM_TYPE_MPG && s_vbi->SG_length && | ||
355 | s->SG_length + s_vbi->SG_length <= s->buffers) { | ||
356 | ivtv_queue_move(s_vbi, &s_vbi->q_predma, NULL, &s_vbi->q_dma, s_vbi->q_predma.bytesused); | ||
357 | s_vbi->SGarray[s_vbi->SG_length - 1].size = cpu_to_le32(le32_to_cpu(s_vbi->SGarray[s->SG_length - 1].size) + 256); | ||
358 | for (i = 0; i < s_vbi->SG_length; i++) { | ||
359 | s->SGarray[s->SG_length++] = s_vbi->SGarray[i]; | ||
360 | } | ||
361 | itv->vbi.dma_offset = s_vbi->dma_offset; | ||
362 | s_vbi->SG_length = 0; | ||
363 | set_bit(IVTV_F_S_DMA_HAS_VBI, &s->s_flags); | ||
364 | IVTV_DEBUG_DMA("include DMA for %s\n", s->name); | ||
365 | } | ||
366 | |||
367 | /* Mark last buffer size for Interrupt flag */ | ||
368 | s->SGarray[s->SG_length - 1].size |= cpu_to_le32(0x80000000); | ||
369 | |||
370 | /* Sync Hardware SG List of buffers */ | ||
371 | ivtv_stream_sync_for_device(s); | ||
372 | write_reg(s->SG_handle, IVTV_REG_ENCDMAADDR); | ||
373 | write_reg_sync(read_reg(IVTV_REG_DMAXFER) | 0x02, IVTV_REG_DMAXFER); | ||
374 | set_bit(IVTV_F_I_DMA, &itv->i_flags); | ||
375 | itv->cur_dma_stream = s->type; | ||
376 | itv->dma_timer.expires = jiffies + HZ / 10; | ||
377 | add_timer(&itv->dma_timer); | ||
378 | } | ||
379 | |||
380 | static void ivtv_dma_dec_start(struct ivtv_stream *s) | ||
381 | { | ||
382 | struct ivtv *itv = s->itv; | ||
383 | |||
384 | if (s->q_predma.bytesused) | ||
385 | ivtv_queue_move(s, &s->q_predma, NULL, &s->q_dma, s->q_predma.bytesused); | ||
386 | IVTV_DEBUG_DMA("start DMA for %s\n", s->name); | ||
387 | /* put SG Handle into register 0x0c */ | ||
388 | write_reg(s->SG_handle, IVTV_REG_DECDMAADDR); | ||
389 | write_reg_sync(read_reg(IVTV_REG_DMAXFER) | 0x01, IVTV_REG_DMAXFER); | ||
390 | set_bit(IVTV_F_I_DMA, &itv->i_flags); | ||
391 | itv->cur_dma_stream = s->type; | ||
392 | itv->dma_timer.expires = jiffies + HZ / 10; | ||
393 | add_timer(&itv->dma_timer); | ||
394 | } | ||
395 | |||
396 | static void ivtv_irq_dma_read(struct ivtv *itv) | ||
397 | { | ||
398 | struct ivtv_stream *s = NULL; | ||
399 | struct ivtv_buffer *buf; | ||
400 | int hw_stream_type; | ||
401 | |||
402 | IVTV_DEBUG_IRQ("DEC DMA READ\n"); | ||
403 | del_timer(&itv->dma_timer); | ||
404 | if (read_reg(IVTV_REG_DMASTATUS) & 0x14) { | ||
405 | IVTV_DEBUG_WARN("DEC DMA ERROR %x\n", read_reg(IVTV_REG_DMASTATUS)); | ||
406 | write_reg(read_reg(IVTV_REG_DMASTATUS) & 3, IVTV_REG_DMASTATUS); | ||
407 | } | ||
408 | if (!test_bit(IVTV_F_I_UDMA, &itv->i_flags)) { | ||
409 | if (test_bit(IVTV_F_I_DEC_YUV, &itv->i_flags)) { | ||
410 | s = &itv->streams[IVTV_DEC_STREAM_TYPE_YUV]; | ||
411 | hw_stream_type = 2; | ||
412 | } | ||
413 | else { | ||
414 | s = &itv->streams[IVTV_DEC_STREAM_TYPE_MPG]; | ||
415 | hw_stream_type = 0; | ||
416 | } | ||
417 | IVTV_DEBUG_DMA("DEC DATA READ %s: %d\n", s->name, s->q_dma.bytesused); | ||
418 | |||
419 | ivtv_stream_sync_for_cpu(s); | ||
420 | |||
421 | /* For some reason must kick the firmware, like PIO mode, | ||
422 | I think this tells the firmware we are done and the size | ||
423 | of the xfer so it can calculate what we need next. | ||
424 | I think we can do this part ourselves but would have to | ||
425 | fully calculate xfer info ourselves and not use interrupts | ||
426 | */ | ||
427 | ivtv_vapi(itv, CX2341X_DEC_SCHED_DMA_FROM_HOST, 3, 0, s->q_dma.bytesused, | ||
428 | hw_stream_type); | ||
429 | |||
430 | /* Free last DMA call */ | ||
431 | while ((buf = ivtv_dequeue(s, &s->q_dma)) != NULL) { | ||
432 | ivtv_buf_sync_for_cpu(s, buf); | ||
433 | ivtv_enqueue(s, buf, &s->q_free); | ||
434 | } | ||
435 | wake_up(&s->waitq); | ||
436 | } | ||
437 | clear_bit(IVTV_F_I_UDMA, &itv->i_flags); | ||
438 | clear_bit(IVTV_F_I_DMA, &itv->i_flags); | ||
439 | itv->cur_dma_stream = -1; | ||
440 | wake_up(&itv->dma_waitq); | ||
441 | } | ||
442 | |||
443 | static void ivtv_irq_enc_dma_complete(struct ivtv *itv) | ||
444 | { | ||
445 | u32 data[CX2341X_MBOX_MAX_DATA]; | ||
446 | struct ivtv_stream *s; | ||
447 | |||
448 | del_timer(&itv->dma_timer); | ||
449 | ivtv_api_get_data(&itv->enc_mbox, IVTV_MBOX_DMA_END, data); | ||
450 | IVTV_DEBUG_IRQ("ENC DMA COMPLETE %x %d\n", data[0], data[1]); | ||
451 | if (test_and_clear_bit(IVTV_F_I_ENC_VBI, &itv->i_flags)) | ||
452 | data[1] = 3; | ||
453 | else if (data[1] > 2) | ||
454 | return; | ||
455 | s = &itv->streams[ivtv_stream_map[data[1]]]; | ||
456 | if (data[0] & 0x18) { | ||
457 | IVTV_DEBUG_WARN("ENC DMA ERROR %x\n", data[0]); | ||
458 | write_reg(read_reg(IVTV_REG_DMASTATUS) & 3, IVTV_REG_DMASTATUS); | ||
459 | ivtv_vapi(itv, CX2341X_ENC_SCHED_DMA_TO_HOST, 3, 0, 0, data[1]); | ||
460 | } | ||
461 | s->SG_length = 0; | ||
462 | clear_bit(IVTV_F_I_DMA, &itv->i_flags); | ||
463 | itv->cur_dma_stream = -1; | ||
464 | dma_post(s); | ||
465 | ivtv_stream_sync_for_cpu(s); | ||
466 | if (test_and_clear_bit(IVTV_F_S_DMA_HAS_VBI, &s->s_flags)) { | ||
467 | u32 tmp; | ||
468 | |||
469 | s = &itv->streams[IVTV_ENC_STREAM_TYPE_VBI]; | ||
470 | tmp = s->dma_offset; | ||
471 | s->dma_offset = itv->vbi.dma_offset; | ||
472 | dma_post(s); | ||
473 | s->dma_offset = tmp; | ||
474 | } | ||
475 | wake_up(&itv->dma_waitq); | ||
476 | } | ||
477 | |||
478 | static void ivtv_irq_dma_err(struct ivtv *itv) | ||
479 | { | ||
480 | u32 data[CX2341X_MBOX_MAX_DATA]; | ||
481 | |||
482 | del_timer(&itv->dma_timer); | ||
483 | ivtv_api_get_data(&itv->enc_mbox, IVTV_MBOX_DMA_END, data); | ||
484 | IVTV_DEBUG_WARN("DMA ERROR %08x %08x %08x %d\n", data[0], data[1], | ||
485 | read_reg(IVTV_REG_DMASTATUS), itv->cur_dma_stream); | ||
486 | if (!test_bit(IVTV_F_I_UDMA, &itv->i_flags) && | ||
487 | itv->cur_dma_stream >= 0 && itv->cur_dma_stream < IVTV_MAX_STREAMS) { | ||
488 | struct ivtv_stream *s = &itv->streams[itv->cur_dma_stream]; | ||
489 | |||
490 | /* retry */ | ||
491 | write_reg(read_reg(IVTV_REG_DMASTATUS) & 3, IVTV_REG_DMASTATUS); | ||
492 | if (s->type >= IVTV_DEC_STREAM_TYPE_MPG) | ||
493 | ivtv_dma_dec_start(s); | ||
494 | else | ||
495 | ivtv_dma_enc_start(s); | ||
496 | return; | ||
497 | } | ||
498 | clear_bit(IVTV_F_I_UDMA, &itv->i_flags); | ||
499 | clear_bit(IVTV_F_I_DMA, &itv->i_flags); | ||
500 | itv->cur_dma_stream = -1; | ||
501 | wake_up(&itv->dma_waitq); | ||
502 | } | ||
503 | |||
504 | static void ivtv_irq_enc_start_cap(struct ivtv *itv) | ||
505 | { | ||
506 | u32 data[CX2341X_MBOX_MAX_DATA]; | ||
507 | struct ivtv_stream *s; | ||
508 | |||
509 | /* Get DMA destination and size arguments from card */ | ||
510 | ivtv_api_get_data(&itv->enc_mbox, IVTV_MBOX_DMA, data); | ||
511 | IVTV_DEBUG_IRQ("ENC START CAP %d: %08x %08x\n", data[0], data[1], data[2]); | ||
512 | |||
513 | if (data[0] > 2 || data[1] == 0 || data[2] == 0) { | ||
514 | IVTV_DEBUG_WARN("Unknown input: %08x %08x %08x\n", | ||
515 | data[0], data[1], data[2]); | ||
516 | return; | ||
517 | } | ||
518 | clear_bit(IVTV_F_I_ENC_VBI, &itv->i_flags); | ||
519 | s = &itv->streams[ivtv_stream_map[data[0]]]; | ||
520 | if (!stream_enc_dma_append(s, data)) { | ||
521 | if (ivtv_use_pio(s)) { | ||
522 | dma_post(s); | ||
523 | ivtv_vapi(itv, CX2341X_ENC_SCHED_DMA_TO_HOST, 3, 0, 0, data[0]); | ||
524 | } | ||
525 | else { | ||
526 | set_bit(IVTV_F_S_DMA_PENDING, &s->s_flags); | ||
527 | } | ||
528 | } | ||
529 | } | ||
530 | |||
531 | static void ivtv_irq_enc_vbi_cap(struct ivtv *itv) | ||
532 | { | ||
533 | struct ivtv_stream *s_mpg = &itv->streams[IVTV_ENC_STREAM_TYPE_MPG]; | ||
534 | u32 data[CX2341X_MBOX_MAX_DATA]; | ||
535 | struct ivtv_stream *s; | ||
536 | |||
537 | IVTV_DEBUG_IRQ("ENC START VBI CAP\n"); | ||
538 | s = &itv->streams[IVTV_ENC_STREAM_TYPE_VBI]; | ||
539 | |||
540 | if (ivtv_use_pio(s)) { | ||
541 | if (stream_enc_dma_append(s, data)) | ||
542 | return; | ||
543 | if (s->q_predma.bytesused) | ||
544 | ivtv_queue_move(s, &s->q_predma, NULL, &s->q_dma, s->q_predma.bytesused); | ||
545 | s->SG_length = 0; | ||
546 | dma_post(s); | ||
547 | return; | ||
548 | } | ||
549 | /* If more than two VBI buffers are pending, then | ||
550 | clear the old ones and start with this new one. | ||
551 | This can happen during transition stages when MPEG capturing is | ||
552 | started, but the first interrupts haven't arrived yet. During | ||
553 | that period VBI requests can accumulate without being able to | ||
554 | DMA the data. Since at most four VBI DMA buffers are available, | ||
555 | we just drop the old requests when there are already three | ||
556 | requests queued. */ | ||
557 | if (s->SG_length > 2) { | ||
558 | struct list_head *p; | ||
559 | list_for_each(p, &s->q_predma.list) { | ||
560 | struct ivtv_buffer *buf = list_entry(p, struct ivtv_buffer, list); | ||
561 | ivtv_buf_sync_for_cpu(s, buf); | ||
562 | } | ||
563 | ivtv_queue_move(s, &s->q_predma, NULL, &s->q_free, 0); | ||
564 | s->SG_length = 0; | ||
565 | } | ||
566 | /* if we can append the data, and the MPEG stream isn't capturing, | ||
567 | then start a DMA request for just the VBI data. */ | ||
568 | if (!stream_enc_dma_append(s, data) && | ||
569 | !test_bit(IVTV_F_S_STREAMING, &s_mpg->s_flags)) { | ||
570 | set_bit(IVTV_F_I_ENC_VBI, &itv->i_flags); | ||
571 | set_bit(IVTV_F_S_DMA_PENDING, &s->s_flags); | ||
572 | } | ||
573 | } | ||
574 | |||
575 | static void ivtv_irq_dev_vbi_reinsert(struct ivtv *itv) | ||
576 | { | ||
577 | u32 data[CX2341X_MBOX_MAX_DATA]; | ||
578 | struct ivtv_stream *s = &itv->streams[IVTV_DEC_STREAM_TYPE_VBI]; | ||
579 | |||
580 | IVTV_DEBUG_IRQ("DEC VBI REINSERT\n"); | ||
581 | if (test_bit(IVTV_F_S_CLAIMED, &s->s_flags) && | ||
582 | !stream_enc_dma_append(s, data)) { | ||
583 | dma_post(s); | ||
584 | } | ||
585 | } | ||
586 | |||
587 | static void ivtv_irq_dec_data_req(struct ivtv *itv) | ||
588 | { | ||
589 | u32 data[CX2341X_MBOX_MAX_DATA]; | ||
590 | struct ivtv_stream *s; | ||
591 | |||
592 | /* YUV or MPG */ | ||
593 | ivtv_api_get_data(&itv->dec_mbox, IVTV_MBOX_DMA, data); | ||
594 | |||
595 | if (test_bit(IVTV_F_I_DEC_YUV, &itv->i_flags)) { | ||
596 | itv->dma_data_req_size = itv->params.width * itv->params.height * 3 / 2; | ||
597 | itv->dma_data_req_offset = data[1] ? data[1] : yuv_offset[0]; | ||
598 | s = &itv->streams[IVTV_DEC_STREAM_TYPE_YUV]; | ||
599 | } | ||
600 | else { | ||
601 | itv->dma_data_req_size = data[2] >= 0x10000 ? 0x10000 : data[2]; | ||
602 | itv->dma_data_req_offset = data[1]; | ||
603 | s = &itv->streams[IVTV_DEC_STREAM_TYPE_MPG]; | ||
604 | } | ||
605 | IVTV_DEBUG_IRQ("DEC DATA REQ %s: %d %08x %u\n", s->name, s->q_full.bytesused, | ||
606 | itv->dma_data_req_offset, itv->dma_data_req_size); | ||
607 | if (itv->dma_data_req_size == 0 || s->q_full.bytesused < itv->dma_data_req_size) { | ||
608 | set_bit(IVTV_F_S_NEEDS_DATA, &s->s_flags); | ||
609 | } | ||
610 | else { | ||
611 | clear_bit(IVTV_F_S_NEEDS_DATA, &s->s_flags); | ||
612 | ivtv_queue_move(s, &s->q_full, NULL, &s->q_predma, itv->dma_data_req_size); | ||
613 | ivtv_dma_stream_dec_prepare(s, itv->dma_data_req_offset + IVTV_DECODER_OFFSET, 0); | ||
614 | } | ||
615 | } | ||
616 | |||
617 | static void ivtv_irq_vsync(struct ivtv *itv) | ||
618 | { | ||
619 | /* The vsync interrupt is unusual in that it won't clear until | ||
620 | * the end of the first line for the current field, at which | ||
621 | * point it clears itself. This can result in repeated vsync | ||
622 | * interrupts, or a missed vsync. Read some of the registers | ||
623 | * to determine the line being displayed and ensure we handle | ||
624 | * one vsync per frame. | ||
625 | */ | ||
626 | unsigned int frame = read_reg(0x28c0) & 1; | ||
627 | int last_dma_frame = atomic_read(&itv->yuv_info.next_dma_frame); | ||
628 | |||
629 | if (0) IVTV_DEBUG_IRQ("DEC VSYNC\n"); | ||
630 | |||
631 | if (((frame ^ itv->yuv_info.lace_sync_field) == 0 && ((itv->lastVsyncFrame & 1) ^ itv->yuv_info.lace_sync_field)) || | ||
632 | (frame != (itv->lastVsyncFrame & 1) && !itv->yuv_info.frame_interlaced)) { | ||
633 | int next_dma_frame = last_dma_frame; | ||
634 | |||
635 | if (next_dma_frame >= 0 && next_dma_frame != atomic_read(&itv->yuv_info.next_fill_frame)) { | ||
636 | write_reg(yuv_offset[next_dma_frame] >> 4, 0x82c); | ||
637 | write_reg((yuv_offset[next_dma_frame] + IVTV_YUV_BUFFER_UV_OFFSET) >> 4, 0x830); | ||
638 | write_reg(yuv_offset[next_dma_frame] >> 4, 0x834); | ||
639 | write_reg((yuv_offset[next_dma_frame] + IVTV_YUV_BUFFER_UV_OFFSET) >> 4, 0x838); | ||
640 | next_dma_frame = (next_dma_frame + 1) & 0x3; | ||
641 | atomic_set(&itv->yuv_info.next_dma_frame, next_dma_frame); | ||
642 | } | ||
643 | } | ||
644 | if (frame != (itv->lastVsyncFrame & 1)) { | ||
645 | struct ivtv_stream *s = ivtv_get_output_stream(itv); | ||
646 | |||
647 | itv->lastVsyncFrame += 1; | ||
648 | if (frame == 0) { | ||
649 | clear_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags); | ||
650 | clear_bit(IVTV_F_I_EV_VSYNC_FIELD, &itv->i_flags); | ||
651 | } | ||
652 | else { | ||
653 | set_bit(IVTV_F_I_EV_VSYNC_FIELD, &itv->i_flags); | ||
654 | } | ||
655 | if (test_bit(IVTV_F_I_EV_VSYNC_ENABLED, &itv->i_flags)) { | ||
656 | set_bit(IVTV_F_I_EV_VSYNC, &itv->i_flags); | ||
657 | wake_up(&itv->event_waitq); | ||
658 | } | ||
659 | wake_up(&itv->vsync_waitq); | ||
660 | if (s) | ||
661 | wake_up(&s->waitq); | ||
662 | |||
663 | /* Send VBI to saa7127 */ | ||
664 | if (frame) | ||
665 | vbi_schedule_work(itv); | ||
666 | |||
667 | /* Check if we need to update the yuv registers */ | ||
668 | if ((itv->yuv_info.yuv_forced_update || itv->yuv_info.new_frame_info[last_dma_frame].update) && last_dma_frame != -1) { | ||
669 | if (!itv->yuv_info.new_frame_info[last_dma_frame].update) | ||
670 | last_dma_frame = (last_dma_frame - 1) & 3; | ||
671 | |||
672 | if (itv->yuv_info.new_frame_info[last_dma_frame].src_w) { | ||
673 | itv->yuv_info.update_frame = last_dma_frame; | ||
674 | itv->yuv_info.new_frame_info[last_dma_frame].update = 0; | ||
675 | itv->yuv_info.yuv_forced_update = 0; | ||
676 | queue_work(itv->yuv_info.work_queues, &itv->yuv_info.work_queue); | ||
677 | } | ||
678 | } | ||
679 | } | ||
680 | } | ||
681 | |||
682 | #define IVTV_IRQ_DMA (IVTV_IRQ_DMA_READ | IVTV_IRQ_ENC_DMA_COMPLETE | IVTV_IRQ_DMA_ERR | IVTV_IRQ_ENC_START_CAP | IVTV_IRQ_ENC_VBI_CAP | IVTV_IRQ_DEC_DATA_REQ) | ||
683 | |||
684 | irqreturn_t ivtv_irq_handler(int irq, void *dev_id) | ||
685 | { | ||
686 | struct ivtv *itv = (struct ivtv *)dev_id; | ||
687 | u32 combo; | ||
688 | u32 stat; | ||
689 | int i; | ||
690 | u8 vsync_force = 0; | ||
691 | |||
692 | spin_lock(&itv->dma_reg_lock); | ||
693 | /* get contents of irq status register */ | ||
694 | stat = read_reg(IVTV_REG_IRQSTATUS); | ||
695 | |||
696 | combo = ~itv->irqmask & stat; | ||
697 | |||
698 | /* Clear out IRQ */ | ||
699 | if (combo) write_reg(combo, IVTV_REG_IRQSTATUS); | ||
700 | |||
701 | if (0 == combo) { | ||
702 | /* The vsync interrupt is unusual and clears itself. If we | ||
703 | * took too long, we may have missed it. Do some checks | ||
704 | */ | ||
705 | if (~itv->irqmask & IVTV_IRQ_DEC_VSYNC) { | ||
706 | /* vsync is enabled, see if we're in a new field */ | ||
707 | if ((itv->lastVsyncFrame & 1) != (read_reg(0x28c0) & 1)) { | ||
708 | /* New field, looks like we missed it */ | ||
709 | IVTV_DEBUG_YUV("VSync interrupt missed %d\n",read_reg(0x28c0)>>16); | ||
710 | vsync_force = 1; | ||
711 | } | ||
712 | } | ||
713 | |||
714 | if (!vsync_force) { | ||
715 | /* No Vsync expected, wasn't for us */ | ||
716 | spin_unlock(&itv->dma_reg_lock); | ||
717 | return IRQ_NONE; | ||
718 | } | ||
719 | } | ||
720 | |||
721 | /* Exclude interrupts noted below from the output, otherwise the log is flooded with | ||
722 | these messages */ | ||
723 | if (combo & ~0xff6d0400) | ||
724 | IVTV_DEBUG_IRQ("======= valid IRQ bits: 0x%08x ======\n", combo); | ||
725 | |||
726 | if (combo & IVTV_IRQ_DEC_DMA_COMPLETE) { | ||
727 | IVTV_DEBUG_IRQ("DEC DMA COMPLETE\n"); | ||
728 | } | ||
729 | |||
730 | if (combo & IVTV_IRQ_DMA_READ) { | ||
731 | ivtv_irq_dma_read(itv); | ||
732 | } | ||
733 | |||
734 | if (combo & IVTV_IRQ_ENC_DMA_COMPLETE) { | ||
735 | ivtv_irq_enc_dma_complete(itv); | ||
736 | } | ||
737 | |||
738 | if (combo & IVTV_IRQ_DMA_ERR) { | ||
739 | ivtv_irq_dma_err(itv); | ||
740 | } | ||
741 | |||
742 | if (combo & IVTV_IRQ_ENC_START_CAP) { | ||
743 | ivtv_irq_enc_start_cap(itv); | ||
744 | } | ||
745 | |||
746 | if (combo & IVTV_IRQ_ENC_VBI_CAP) { | ||
747 | ivtv_irq_enc_vbi_cap(itv); | ||
748 | } | ||
749 | |||
750 | if (combo & IVTV_IRQ_DEC_VBI_RE_INSERT) { | ||
751 | ivtv_irq_dev_vbi_reinsert(itv); | ||
752 | } | ||
753 | |||
754 | if (combo & IVTV_IRQ_ENC_EOS) { | ||
755 | IVTV_DEBUG_IRQ("ENC EOS\n"); | ||
756 | set_bit(IVTV_F_I_EOS, &itv->i_flags); | ||
757 | wake_up(&itv->cap_w); | ||
758 | } | ||
759 | |||
760 | if (combo & IVTV_IRQ_DEC_DATA_REQ) { | ||
761 | ivtv_irq_dec_data_req(itv); | ||
762 | } | ||
763 | |||
764 | /* Decoder Vertical Sync - We can't rely on 'combo', so check if vsync enabled */ | ||
765 | if (~itv->irqmask & IVTV_IRQ_DEC_VSYNC) { | ||
766 | ivtv_irq_vsync(itv); | ||
767 | } | ||
768 | |||
769 | if (combo & IVTV_IRQ_ENC_VIM_RST) { | ||
770 | IVTV_DEBUG_IRQ("VIM RST\n"); | ||
771 | /*ivtv_vapi(itv, CX2341X_ENC_REFRESH_INPUT, 0); */ | ||
772 | } | ||
773 | |||
774 | if (combo & IVTV_IRQ_DEC_AUD_MODE_CHG) { | ||
775 | IVTV_DEBUG_INFO("Stereo mode changed\n"); | ||
776 | } | ||
777 | |||
778 | if ((combo & IVTV_IRQ_DMA) && !test_bit(IVTV_F_I_DMA, &itv->i_flags)) { | ||
779 | for (i = 0; i < IVTV_MAX_STREAMS; i++) { | ||
780 | int idx = (i + itv->irq_rr_idx++) % IVTV_MAX_STREAMS; | ||
781 | struct ivtv_stream *s = &itv->streams[idx]; | ||
782 | |||
783 | if (!test_and_clear_bit(IVTV_F_S_DMA_PENDING, &s->s_flags)) | ||
784 | continue; | ||
785 | if (s->type >= IVTV_DEC_STREAM_TYPE_MPG) | ||
786 | ivtv_dma_dec_start(s); | ||
787 | else | ||
788 | ivtv_dma_enc_start(s); | ||
789 | break; | ||
790 | } | ||
791 | if (i == IVTV_MAX_STREAMS && test_and_clear_bit(IVTV_F_I_UDMA_PENDING, &itv->i_flags)) { | ||
792 | ivtv_udma_start(itv); | ||
793 | } | ||
794 | } | ||
795 | |||
796 | spin_unlock(&itv->dma_reg_lock); | ||
797 | |||
798 | /* If we've just handled a 'forced' vsync, it's safest to say it | ||
799 | * wasn't ours. Another device may have triggered it at just | ||
800 | * the right time. | ||
801 | */ | ||
802 | return vsync_force ? IRQ_NONE : IRQ_HANDLED; | ||
803 | } | ||
804 | |||
805 | void ivtv_unfinished_dma(unsigned long arg) | ||
806 | { | ||
807 | struct ivtv *itv = (struct ivtv *)arg; | ||
808 | |||
809 | if (!test_bit(IVTV_F_I_DMA, &itv->i_flags)) | ||
810 | return; | ||
811 | IVTV_ERR("DMA TIMEOUT %08x %d\n", read_reg(IVTV_REG_DMASTATUS), itv->cur_dma_stream); | ||
812 | |||
813 | write_reg(read_reg(IVTV_REG_DMASTATUS) & 3, IVTV_REG_DMASTATUS); | ||
814 | clear_bit(IVTV_F_I_UDMA, &itv->i_flags); | ||
815 | clear_bit(IVTV_F_I_DMA, &itv->i_flags); | ||
816 | itv->cur_dma_stream = -1; | ||
817 | wake_up(&itv->dma_waitq); | ||
818 | } | ||
diff --git a/drivers/media/video/ivtv/ivtv-irq.h b/drivers/media/video/ivtv/ivtv-irq.h new file mode 100644 index 000000000000..ed96205e87a2 --- /dev/null +++ b/drivers/media/video/ivtv/ivtv-irq.h | |||
@@ -0,0 +1,24 @@ | |||
1 | /* | ||
2 | interrupt handling | ||
3 | Copyright (C) 2003-2004 Kevin Thayer <nufan_wfk at yahoo.com> | ||
4 | Copyright (C) 2004 Chris Kennedy <c@groovy.org> | ||
5 | Copyright (C) 2005-2007 Hans Verkuil <hverkuil@xs4all.nl> | ||
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 02111-1307 USA | ||
20 | */ | ||
21 | |||
22 | irqreturn_t ivtv_irq_handler(int irq, void *dev_id); | ||
23 | void ivtv_dma_stream_dec_prepare(struct ivtv_stream *s, u32 offset, int lock); | ||
24 | void ivtv_unfinished_dma(unsigned long arg); | ||
diff --git a/drivers/media/video/ivtv/ivtv-mailbox.c b/drivers/media/video/ivtv/ivtv-mailbox.c new file mode 100644 index 000000000000..6ae42a3b03cc --- /dev/null +++ b/drivers/media/video/ivtv/ivtv-mailbox.c | |||
@@ -0,0 +1,360 @@ | |||
1 | /* | ||
2 | mailbox functions | ||
3 | Copyright (C) 2003-2004 Kevin Thayer <nufan_wfk at yahoo.com> | ||
4 | Copyright (C) 2004 Chris Kennedy <c@groovy.org> | ||
5 | Copyright (C) 2005-2007 Hans Verkuil <hverkuil@xs4all.nl> | ||
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 02111-1307 USA | ||
20 | */ | ||
21 | |||
22 | #include <stdarg.h> | ||
23 | |||
24 | #include "ivtv-driver.h" | ||
25 | #include "ivtv-mailbox.h" | ||
26 | |||
27 | /* Firmware mailbox flags*/ | ||
28 | #define IVTV_MBOX_FIRMWARE_DONE 0x00000004 | ||
29 | #define IVTV_MBOX_DRIVER_DONE 0x00000002 | ||
30 | #define IVTV_MBOX_DRIVER_BUSY 0x00000001 | ||
31 | #define IVTV_MBOX_FREE 0x00000000 | ||
32 | |||
33 | /* Firmware mailbox standard timeout */ | ||
34 | #define IVTV_API_STD_TIMEOUT 0x02000000 | ||
35 | |||
36 | #define API_CACHE (1 << 0) /* Allow the command to be stored in the cache */ | ||
37 | #define API_RESULT (1 << 1) /* Allow 1 second for this cmd to end */ | ||
38 | #define API_FAST_RESULT (3 << 1) /* Allow 0.1 second for this cmd to end */ | ||
39 | #define API_DMA (1 << 3) /* DMA mailbox, has special handling */ | ||
40 | #define API_NO_WAIT_MB (1 << 4) /* Command may not wait for a free mailbox */ | ||
41 | #define API_NO_WAIT_RES (1 << 5) /* Command may not wait for the result */ | ||
42 | |||
43 | struct ivtv_api_info { | ||
44 | int flags; /* Flags, see above */ | ||
45 | const char *name; /* The name of the command */ | ||
46 | }; | ||
47 | |||
48 | #define API_ENTRY(x, f) [x] = { (f), #x } | ||
49 | |||
50 | static const struct ivtv_api_info api_info[256] = { | ||
51 | /* MPEG encoder API */ | ||
52 | API_ENTRY(CX2341X_ENC_PING_FW, API_FAST_RESULT), | ||
53 | API_ENTRY(CX2341X_ENC_START_CAPTURE, API_RESULT), | ||
54 | API_ENTRY(CX2341X_ENC_STOP_CAPTURE, API_RESULT), | ||
55 | API_ENTRY(CX2341X_ENC_SET_AUDIO_ID, API_CACHE), | ||
56 | API_ENTRY(CX2341X_ENC_SET_VIDEO_ID, API_CACHE), | ||
57 | API_ENTRY(CX2341X_ENC_SET_PCR_ID, API_CACHE), | ||
58 | API_ENTRY(CX2341X_ENC_SET_FRAME_RATE, API_CACHE), | ||
59 | API_ENTRY(CX2341X_ENC_SET_FRAME_SIZE, API_CACHE), | ||
60 | API_ENTRY(CX2341X_ENC_SET_BIT_RATE, API_CACHE), | ||
61 | API_ENTRY(CX2341X_ENC_SET_GOP_PROPERTIES, API_CACHE), | ||
62 | API_ENTRY(CX2341X_ENC_SET_ASPECT_RATIO, API_CACHE), | ||
63 | API_ENTRY(CX2341X_ENC_SET_DNR_FILTER_MODE, API_CACHE), | ||
64 | API_ENTRY(CX2341X_ENC_SET_DNR_FILTER_PROPS, API_CACHE), | ||
65 | API_ENTRY(CX2341X_ENC_SET_CORING_LEVELS, API_CACHE), | ||
66 | API_ENTRY(CX2341X_ENC_SET_SPATIAL_FILTER_TYPE, API_CACHE), | ||
67 | API_ENTRY(CX2341X_ENC_SET_VBI_LINE, API_RESULT), | ||
68 | API_ENTRY(CX2341X_ENC_SET_STREAM_TYPE, API_CACHE), | ||
69 | API_ENTRY(CX2341X_ENC_SET_OUTPUT_PORT, API_CACHE), | ||
70 | API_ENTRY(CX2341X_ENC_SET_AUDIO_PROPERTIES, API_CACHE), | ||
71 | API_ENTRY(CX2341X_ENC_HALT_FW, API_FAST_RESULT), | ||
72 | API_ENTRY(CX2341X_ENC_GET_VERSION, API_FAST_RESULT), | ||
73 | API_ENTRY(CX2341X_ENC_SET_GOP_CLOSURE, API_CACHE), | ||
74 | API_ENTRY(CX2341X_ENC_GET_SEQ_END, API_RESULT), | ||
75 | API_ENTRY(CX2341X_ENC_SET_PGM_INDEX_INFO, API_FAST_RESULT), | ||
76 | API_ENTRY(CX2341X_ENC_SET_VBI_CONFIG, API_RESULT), | ||
77 | API_ENTRY(CX2341X_ENC_SET_DMA_BLOCK_SIZE, API_CACHE), | ||
78 | API_ENTRY(CX2341X_ENC_GET_PREV_DMA_INFO_MB_10, API_FAST_RESULT), | ||
79 | API_ENTRY(CX2341X_ENC_GET_PREV_DMA_INFO_MB_9, API_FAST_RESULT), | ||
80 | API_ENTRY(CX2341X_ENC_SCHED_DMA_TO_HOST, API_DMA), | ||
81 | API_ENTRY(CX2341X_ENC_INITIALIZE_INPUT, API_RESULT), | ||
82 | API_ENTRY(CX2341X_ENC_SET_FRAME_DROP_RATE, API_CACHE), | ||
83 | API_ENTRY(CX2341X_ENC_PAUSE_ENCODER, API_RESULT), | ||
84 | API_ENTRY(CX2341X_ENC_REFRESH_INPUT, API_NO_WAIT_MB), | ||
85 | API_ENTRY(CX2341X_ENC_SET_COPYRIGHT, API_CACHE), | ||
86 | API_ENTRY(CX2341X_ENC_SET_EVENT_NOTIFICATION, API_RESULT), | ||
87 | API_ENTRY(CX2341X_ENC_SET_NUM_VSYNC_LINES, API_CACHE), | ||
88 | API_ENTRY(CX2341X_ENC_SET_PLACEHOLDER, API_CACHE), | ||
89 | API_ENTRY(CX2341X_ENC_MUTE_VIDEO, API_RESULT), | ||
90 | API_ENTRY(CX2341X_ENC_MUTE_AUDIO, API_RESULT), | ||
91 | API_ENTRY(CX2341X_ENC_SET_VERT_CROP_LINE, API_FAST_RESULT), | ||
92 | API_ENTRY(CX2341X_ENC_MISC, API_FAST_RESULT), | ||
93 | /* Obsolete PULLDOWN API command */ | ||
94 | API_ENTRY(0xb1, API_CACHE), | ||
95 | |||
96 | /* MPEG decoder API */ | ||
97 | API_ENTRY(CX2341X_DEC_PING_FW, API_FAST_RESULT), | ||
98 | API_ENTRY(CX2341X_DEC_START_PLAYBACK, API_RESULT), | ||
99 | API_ENTRY(CX2341X_DEC_STOP_PLAYBACK, API_RESULT), | ||
100 | API_ENTRY(CX2341X_DEC_SET_PLAYBACK_SPEED, API_RESULT), | ||
101 | API_ENTRY(CX2341X_DEC_STEP_VIDEO, API_RESULT), | ||
102 | API_ENTRY(CX2341X_DEC_SET_DMA_BLOCK_SIZE, API_CACHE), | ||
103 | API_ENTRY(CX2341X_DEC_GET_XFER_INFO, API_FAST_RESULT), | ||
104 | API_ENTRY(CX2341X_DEC_GET_DMA_STATUS, API_FAST_RESULT), | ||
105 | API_ENTRY(CX2341X_DEC_SCHED_DMA_FROM_HOST, API_DMA), | ||
106 | API_ENTRY(CX2341X_DEC_PAUSE_PLAYBACK, API_RESULT), | ||
107 | API_ENTRY(CX2341X_DEC_HALT_FW, API_FAST_RESULT), | ||
108 | API_ENTRY(CX2341X_DEC_SET_STANDARD, API_CACHE), | ||
109 | API_ENTRY(CX2341X_DEC_GET_VERSION, API_FAST_RESULT), | ||
110 | API_ENTRY(CX2341X_DEC_SET_STREAM_INPUT, API_CACHE), | ||
111 | API_ENTRY(CX2341X_DEC_GET_TIMING_INFO, API_RESULT /*| API_NO_WAIT_RES*/), | ||
112 | API_ENTRY(CX2341X_DEC_SET_AUDIO_MODE, API_CACHE), | ||
113 | API_ENTRY(CX2341X_DEC_SET_EVENT_NOTIFICATION, API_RESULT), | ||
114 | API_ENTRY(CX2341X_DEC_SET_DISPLAY_BUFFERS, API_CACHE), | ||
115 | API_ENTRY(CX2341X_DEC_EXTRACT_VBI, API_RESULT), | ||
116 | API_ENTRY(CX2341X_DEC_SET_DECODER_SOURCE, API_FAST_RESULT), | ||
117 | API_ENTRY(CX2341X_DEC_SET_PREBUFFERING, API_CACHE), | ||
118 | |||
119 | /* OSD API */ | ||
120 | API_ENTRY(CX2341X_OSD_GET_FRAMEBUFFER, API_FAST_RESULT), | ||
121 | API_ENTRY(CX2341X_OSD_GET_PIXEL_FORMAT, API_FAST_RESULT), | ||
122 | API_ENTRY(CX2341X_OSD_SET_PIXEL_FORMAT, API_CACHE), | ||
123 | API_ENTRY(CX2341X_OSD_GET_STATE, API_FAST_RESULT), | ||
124 | API_ENTRY(CX2341X_OSD_SET_STATE, API_CACHE), | ||
125 | API_ENTRY(CX2341X_OSD_GET_OSD_COORDS, API_FAST_RESULT), | ||
126 | API_ENTRY(CX2341X_OSD_SET_OSD_COORDS, API_CACHE), | ||
127 | API_ENTRY(CX2341X_OSD_GET_SCREEN_COORDS, API_FAST_RESULT), | ||
128 | API_ENTRY(CX2341X_OSD_SET_SCREEN_COORDS, API_CACHE), | ||
129 | API_ENTRY(CX2341X_OSD_GET_GLOBAL_ALPHA, API_FAST_RESULT), | ||
130 | API_ENTRY(CX2341X_OSD_SET_GLOBAL_ALPHA, API_CACHE), | ||
131 | API_ENTRY(CX2341X_OSD_SET_BLEND_COORDS, API_CACHE), | ||
132 | API_ENTRY(CX2341X_OSD_GET_FLICKER_STATE, API_FAST_RESULT), | ||
133 | API_ENTRY(CX2341X_OSD_SET_FLICKER_STATE, API_CACHE), | ||
134 | API_ENTRY(CX2341X_OSD_BLT_COPY, API_RESULT), | ||
135 | API_ENTRY(CX2341X_OSD_BLT_FILL, API_RESULT), | ||
136 | API_ENTRY(CX2341X_OSD_BLT_TEXT, API_RESULT), | ||
137 | API_ENTRY(CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, API_CACHE), | ||
138 | API_ENTRY(CX2341X_OSD_SET_CHROMA_KEY, API_CACHE), | ||
139 | API_ENTRY(CX2341X_OSD_GET_ALPHA_CONTENT_INDEX, API_FAST_RESULT), | ||
140 | API_ENTRY(CX2341X_OSD_SET_ALPHA_CONTENT_INDEX, API_CACHE) | ||
141 | }; | ||
142 | |||
143 | static int try_mailbox(struct ivtv *itv, struct ivtv_mailbox_data *mbdata, int mb) | ||
144 | { | ||
145 | u32 flags = readl(&mbdata->mbox[mb].flags); | ||
146 | int is_free = flags == IVTV_MBOX_FREE || (flags & IVTV_MBOX_FIRMWARE_DONE); | ||
147 | |||
148 | /* if the mailbox is free, then try to claim it */ | ||
149 | if (is_free && !test_and_set_bit(mb, &mbdata->busy)) { | ||
150 | write_sync(IVTV_MBOX_DRIVER_BUSY, &mbdata->mbox[mb].flags); | ||
151 | return 1; | ||
152 | } | ||
153 | return 0; | ||
154 | } | ||
155 | |||
156 | /* Try to find a free mailbox. Note mailbox 0 is reserved for DMA and so is not | ||
157 | attempted here. */ | ||
158 | static int get_mailbox(struct ivtv *itv, struct ivtv_mailbox_data *mbdata, int flags) | ||
159 | { | ||
160 | unsigned long then = jiffies; | ||
161 | int i, mb; | ||
162 | int max_mbox = mbdata->max_mbox; | ||
163 | int retries = 100; | ||
164 | |||
165 | /* All slow commands use the same mailbox, serializing them and also | ||
166 | leaving the other mailbox free for simple fast commands. */ | ||
167 | if ((flags & API_FAST_RESULT) == API_RESULT) | ||
168 | max_mbox = 1; | ||
169 | |||
170 | /* find free non-DMA mailbox */ | ||
171 | for (i = 0; i < retries; i++) { | ||
172 | for (mb = 1; mb <= max_mbox; mb++) | ||
173 | if (try_mailbox(itv, mbdata, mb)) | ||
174 | return mb; | ||
175 | |||
176 | /* Sleep before a retry, if not atomic */ | ||
177 | if (!(flags & API_NO_WAIT_MB)) { | ||
178 | if (jiffies - then > retries * HZ / 100) | ||
179 | break; | ||
180 | ivtv_sleep_timeout(HZ / 100, 0); | ||
181 | } | ||
182 | } | ||
183 | return -ENODEV; | ||
184 | } | ||
185 | |||
186 | static void write_mailbox(volatile struct ivtv_mailbox __iomem *mbox, int cmd, int args, u32 data[]) | ||
187 | { | ||
188 | int i; | ||
189 | |||
190 | write_sync(cmd, &mbox->cmd); | ||
191 | write_sync(IVTV_API_STD_TIMEOUT, &mbox->timeout); | ||
192 | |||
193 | for (i = 0; i < CX2341X_MBOX_MAX_DATA; i++) | ||
194 | write_sync(data[i], &mbox->data[i]); | ||
195 | |||
196 | write_sync(IVTV_MBOX_DRIVER_DONE | IVTV_MBOX_DRIVER_BUSY, &mbox->flags); | ||
197 | } | ||
198 | |||
199 | static void clear_all_mailboxes(struct ivtv *itv, struct ivtv_mailbox_data *mbdata) | ||
200 | { | ||
201 | int i; | ||
202 | |||
203 | for (i = 0; i <= mbdata->max_mbox; i++) { | ||
204 | IVTV_DEBUG_WARN("Clearing mailbox %d: cmd 0x%08x flags 0x%08x\n", | ||
205 | i, readl(&mbdata->mbox[i].cmd), readl(&mbdata->mbox[i].flags)); | ||
206 | write_sync(0, &mbdata->mbox[i].flags); | ||
207 | clear_bit(i, &mbdata->busy); | ||
208 | } | ||
209 | } | ||
210 | |||
211 | static int ivtv_api_call(struct ivtv *itv, int cmd, int args, u32 data[]) | ||
212 | { | ||
213 | struct ivtv_mailbox_data *mbdata = (cmd >= 128) ? &itv->enc_mbox : &itv->dec_mbox; | ||
214 | volatile struct ivtv_mailbox __iomem *mbox; | ||
215 | int api_timeout = HZ; | ||
216 | int flags, mb, i; | ||
217 | unsigned long then; | ||
218 | |||
219 | /* sanity checks */ | ||
220 | if (NULL == mbdata) { | ||
221 | IVTV_ERR("No mailbox allocated\n"); | ||
222 | return -ENODEV; | ||
223 | } | ||
224 | if (args < 0 || args > CX2341X_MBOX_MAX_DATA || | ||
225 | cmd < 0 || cmd > 255 || api_info[cmd].name == NULL) { | ||
226 | IVTV_ERR("Invalid API call: cmd = 0x%02x, args = %d\n", cmd, args); | ||
227 | return -EINVAL; | ||
228 | } | ||
229 | |||
230 | IVTV_DEBUG_API("API Call: %s\n", api_info[cmd].name); | ||
231 | |||
232 | /* clear possibly uninitialized part of data array */ | ||
233 | for (i = args; i < CX2341X_MBOX_MAX_DATA; i++) | ||
234 | data[i] = 0; | ||
235 | |||
236 | /* If this command was issued within the last 30 minutes and with identical | ||
237 | data, then just return 0 as there is no need to issue this command again. | ||
238 | Just an optimization to prevent unnecessary use of mailboxes. */ | ||
239 | if (itv->api_cache[cmd].last_jiffies && | ||
240 | jiffies - itv->api_cache[cmd].last_jiffies < HZ * 1800 && | ||
241 | !memcmp(data, itv->api_cache[cmd].data, sizeof(itv->api_cache[cmd].data))) { | ||
242 | itv->api_cache[cmd].last_jiffies = jiffies; | ||
243 | return 0; | ||
244 | } | ||
245 | |||
246 | flags = api_info[cmd].flags; | ||
247 | |||
248 | if (flags & API_DMA) { | ||
249 | for (i = 0; i < 100; i++) { | ||
250 | mb = i % (mbdata->max_mbox + 1); | ||
251 | if (try_mailbox(itv, mbdata, mb)) { | ||
252 | write_mailbox(&mbdata->mbox[mb], cmd, args, data); | ||
253 | clear_bit(mb, &mbdata->busy); | ||
254 | return 0; | ||
255 | } | ||
256 | IVTV_DEBUG_WARN("%s: mailbox %d not free %08x\n", | ||
257 | api_info[cmd].name, mb, readl(&mbdata->mbox[mb].flags)); | ||
258 | } | ||
259 | IVTV_WARN("Could not find free DMA mailbox for %s\n", api_info[cmd].name); | ||
260 | clear_all_mailboxes(itv, mbdata); | ||
261 | return -EBUSY; | ||
262 | } | ||
263 | |||
264 | if ((flags & API_FAST_RESULT) == API_FAST_RESULT) | ||
265 | api_timeout = HZ / 10; | ||
266 | |||
267 | mb = get_mailbox(itv, mbdata, flags); | ||
268 | if (mb < 0) { | ||
269 | IVTV_DEBUG_WARN("No free mailbox found (%s)\n", api_info[cmd].name); | ||
270 | clear_all_mailboxes(itv, mbdata); | ||
271 | return -EBUSY; | ||
272 | } | ||
273 | mbox = &mbdata->mbox[mb]; | ||
274 | write_mailbox(mbox, cmd, args, data); | ||
275 | if (flags & API_CACHE) { | ||
276 | memcpy(itv->api_cache[cmd].data, data, sizeof(itv->api_cache[cmd].data)); | ||
277 | itv->api_cache[cmd].last_jiffies = jiffies; | ||
278 | } | ||
279 | if ((flags & API_RESULT) == 0) { | ||
280 | clear_bit(mb, &mbdata->busy); | ||
281 | return 0; | ||
282 | } | ||
283 | |||
284 | /* Get results */ | ||
285 | then = jiffies; | ||
286 | |||
287 | while (!(readl(&mbox->flags) & IVTV_MBOX_FIRMWARE_DONE)) { | ||
288 | if (jiffies - then > api_timeout) { | ||
289 | IVTV_DEBUG_WARN("Could not get result (%s)\n", api_info[cmd].name); | ||
290 | /* reset the mailbox, but it is likely too late already */ | ||
291 | write_sync(0, &mbox->flags); | ||
292 | clear_bit(mb, &mbdata->busy); | ||
293 | return -EIO; | ||
294 | } | ||
295 | if (flags & API_NO_WAIT_RES) | ||
296 | mdelay(1); | ||
297 | else | ||
298 | ivtv_sleep_timeout(HZ / 100, 0); | ||
299 | } | ||
300 | if (jiffies - then > HZ / 10) | ||
301 | IVTV_DEBUG_WARN("%s took %lu jiffies (%d per HZ)\n", | ||
302 | api_info[cmd].name, jiffies - then, HZ); | ||
303 | |||
304 | for (i = 0; i < CX2341X_MBOX_MAX_DATA; i++) | ||
305 | data[i] = readl(&mbox->data[i]); | ||
306 | write_sync(0, &mbox->flags); | ||
307 | clear_bit(mb, &mbdata->busy); | ||
308 | return 0; | ||
309 | } | ||
310 | |||
311 | int ivtv_api(struct ivtv *itv, int cmd, int args, u32 data[]) | ||
312 | { | ||
313 | int res = ivtv_api_call(itv, cmd, args, data); | ||
314 | |||
315 | /* Allow a single retry, probably already too late though. | ||
316 | If there is no free mailbox then that is usually an indication | ||
317 | of a more serious problem. */ | ||
318 | return (res == -EBUSY) ? ivtv_api_call(itv, cmd, args, data) : res; | ||
319 | } | ||
320 | |||
321 | int ivtv_api_func(void *priv, int cmd, int in, int out, u32 data[CX2341X_MBOX_MAX_DATA]) | ||
322 | { | ||
323 | return ivtv_api(priv, cmd, in, data); | ||
324 | } | ||
325 | |||
326 | int ivtv_vapi_result(struct ivtv *itv, u32 data[CX2341X_MBOX_MAX_DATA], int cmd, int args, ...) | ||
327 | { | ||
328 | va_list ap; | ||
329 | int i; | ||
330 | |||
331 | va_start(ap, args); | ||
332 | for (i = 0; i < args; i++) { | ||
333 | data[i] = va_arg(ap, u32); | ||
334 | } | ||
335 | va_end(ap); | ||
336 | return ivtv_api(itv, cmd, args, data); | ||
337 | } | ||
338 | |||
339 | int ivtv_vapi(struct ivtv *itv, int cmd, int args, ...) | ||
340 | { | ||
341 | u32 data[CX2341X_MBOX_MAX_DATA]; | ||
342 | va_list ap; | ||
343 | int i; | ||
344 | |||
345 | va_start(ap, args); | ||
346 | for (i = 0; i < args; i++) { | ||
347 | data[i] = va_arg(ap, u32); | ||
348 | } | ||
349 | va_end(ap); | ||
350 | return ivtv_api(itv, cmd, args, data); | ||
351 | } | ||
352 | |||
353 | /* This one is for stuff that can't sleep.. irq handlers, etc.. */ | ||
354 | void ivtv_api_get_data(struct ivtv_mailbox_data *mbdata, int mb, u32 data[]) | ||
355 | { | ||
356 | int i; | ||
357 | |||
358 | for (i = 0; i < CX2341X_MBOX_MAX_DATA; i++) | ||
359 | data[i] = readl(&mbdata->mbox[mb].data[i]); | ||
360 | } | ||
diff --git a/drivers/media/video/ivtv/ivtv-mailbox.h b/drivers/media/video/ivtv/ivtv-mailbox.h new file mode 100644 index 000000000000..79b8aec14370 --- /dev/null +++ b/drivers/media/video/ivtv/ivtv-mailbox.h | |||
@@ -0,0 +1,25 @@ | |||
1 | /* | ||
2 | mailbox functions | ||
3 | Copyright (C) 2003-2004 Kevin Thayer <nufan_wfk at yahoo.com> | ||
4 | Copyright (C) 2005-2007 Hans Verkuil <hverkuil@xs4all.nl> | ||
5 | |||
6 | This program is free software; you can redistribute it and/or modify | ||
7 | it under the terms of the GNU General Public License as published by | ||
8 | the Free Software Foundation; either version 2 of the License, or | ||
9 | (at your option) any later version. | ||
10 | |||
11 | This program is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program; if not, write to the Free Software | ||
18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | */ | ||
20 | |||
21 | void ivtv_api_get_data(struct ivtv_mailbox_data *mbox, int mb, u32 data[]); | ||
22 | int ivtv_api(struct ivtv *itv, int cmd, int args, u32 data[]); | ||
23 | int ivtv_vapi_result(struct ivtv *itv, u32 data[CX2341X_MBOX_MAX_DATA], int cmd, int args, ...); | ||
24 | int ivtv_vapi(struct ivtv *itv, int cmd, int args, ...); | ||
25 | int ivtv_api_func(void *priv, int cmd, int in, int out, u32 data[CX2341X_MBOX_MAX_DATA]); | ||
diff --git a/drivers/media/video/ivtv/ivtv-queue.c b/drivers/media/video/ivtv/ivtv-queue.c new file mode 100644 index 000000000000..ccfcef1ad91a --- /dev/null +++ b/drivers/media/video/ivtv/ivtv-queue.c | |||
@@ -0,0 +1,262 @@ | |||
1 | /* | ||
2 | buffer queues. | ||
3 | Copyright (C) 2003-2004 Kevin Thayer <nufan_wfk at yahoo.com> | ||
4 | Copyright (C) 2004 Chris Kennedy <c@groovy.org> | ||
5 | Copyright (C) 2005-2007 Hans Verkuil <hverkuil@xs4all.nl> | ||
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 02111-1307 USA | ||
20 | */ | ||
21 | |||
22 | #include "ivtv-driver.h" | ||
23 | #include "ivtv-streams.h" | ||
24 | #include "ivtv-queue.h" | ||
25 | #include "ivtv-mailbox.h" | ||
26 | |||
27 | int ivtv_buf_copy_from_user(struct ivtv_stream *s, struct ivtv_buffer *buf, const char __user *src, int copybytes) | ||
28 | { | ||
29 | if (s->buf_size - buf->bytesused < copybytes) | ||
30 | copybytes = s->buf_size - buf->bytesused; | ||
31 | if (copy_from_user(buf->buf + buf->bytesused, src, copybytes)) { | ||
32 | return -EFAULT; | ||
33 | } | ||
34 | buf->bytesused += copybytes; | ||
35 | return copybytes; | ||
36 | } | ||
37 | |||
38 | void ivtv_buf_swap(struct ivtv_buffer *buf) | ||
39 | { | ||
40 | int i; | ||
41 | |||
42 | for (i = 0; i < buf->bytesused; i += 4) | ||
43 | swab32s((u32 *)(buf->buf + i)); | ||
44 | } | ||
45 | |||
46 | void ivtv_queue_init(struct ivtv_queue *q) | ||
47 | { | ||
48 | INIT_LIST_HEAD(&q->list); | ||
49 | q->buffers = 0; | ||
50 | q->length = 0; | ||
51 | q->bytesused = 0; | ||
52 | } | ||
53 | |||
54 | void ivtv_enqueue(struct ivtv_stream *s, struct ivtv_buffer *buf, struct ivtv_queue *q) | ||
55 | { | ||
56 | unsigned long flags = 0; | ||
57 | |||
58 | /* clear the buffer if it is going to be enqueued to the free queue */ | ||
59 | if (q == &s->q_free) { | ||
60 | buf->bytesused = 0; | ||
61 | buf->readpos = 0; | ||
62 | buf->b_flags = 0; | ||
63 | } | ||
64 | spin_lock_irqsave(&s->qlock, flags); | ||
65 | list_add_tail(&buf->list, &q->list); | ||
66 | q->buffers++; | ||
67 | q->length += s->buf_size; | ||
68 | q->bytesused += buf->bytesused - buf->readpos; | ||
69 | spin_unlock_irqrestore(&s->qlock, flags); | ||
70 | } | ||
71 | |||
72 | struct ivtv_buffer *ivtv_dequeue(struct ivtv_stream *s, struct ivtv_queue *q) | ||
73 | { | ||
74 | struct ivtv_buffer *buf = NULL; | ||
75 | unsigned long flags = 0; | ||
76 | |||
77 | spin_lock_irqsave(&s->qlock, flags); | ||
78 | if (!list_empty(&q->list)) { | ||
79 | buf = list_entry(q->list.next, struct ivtv_buffer, list); | ||
80 | list_del_init(q->list.next); | ||
81 | q->buffers--; | ||
82 | q->length -= s->buf_size; | ||
83 | q->bytesused -= buf->bytesused - buf->readpos; | ||
84 | } | ||
85 | spin_unlock_irqrestore(&s->qlock, flags); | ||
86 | return buf; | ||
87 | } | ||
88 | |||
89 | static void ivtv_queue_move_buf(struct ivtv_stream *s, struct ivtv_queue *from, | ||
90 | struct ivtv_queue *to, int clear, int full) | ||
91 | { | ||
92 | struct ivtv_buffer *buf = list_entry(from->list.next, struct ivtv_buffer, list); | ||
93 | |||
94 | list_move_tail(from->list.next, &to->list); | ||
95 | from->buffers--; | ||
96 | from->length -= s->buf_size; | ||
97 | from->bytesused -= buf->bytesused - buf->readpos; | ||
98 | /* special handling for q_free */ | ||
99 | if (clear) | ||
100 | buf->bytesused = buf->readpos = buf->b_flags = 0; | ||
101 | else if (full) { | ||
102 | /* special handling for stolen buffers, assume | ||
103 | all bytes are used. */ | ||
104 | buf->bytesused = s->buf_size; | ||
105 | buf->readpos = buf->b_flags = 0; | ||
106 | } | ||
107 | to->buffers++; | ||
108 | to->length += s->buf_size; | ||
109 | to->bytesused += buf->bytesused - buf->readpos; | ||
110 | } | ||
111 | |||
112 | /* Move 'needed_bytes' worth of buffers from queue 'from' into queue 'to'. | ||
113 | If 'needed_bytes' == 0, then move all buffers from 'from' into 'to'. | ||
114 | If 'steal' != NULL, then buffers may also taken from that queue if | ||
115 | needed. | ||
116 | |||
117 | The buffer is automatically cleared if it goes to the free queue. It is | ||
118 | also cleared if buffers need to be taken from the 'steal' queue and | ||
119 | the 'from' queue is the free queue. | ||
120 | |||
121 | When 'from' is q_free, then needed_bytes is compared to the total | ||
122 | available buffer length, otherwise needed_bytes is compared to the | ||
123 | bytesused value. For the 'steal' queue the total available buffer | ||
124 | length is always used. | ||
125 | |||
126 | -ENOMEM is returned if the buffers could not be obtained, 0 if all | ||
127 | buffers where obtained from the 'from' list and if non-zero then | ||
128 | the number of stolen buffers is returned. */ | ||
129 | int ivtv_queue_move(struct ivtv_stream *s, struct ivtv_queue *from, struct ivtv_queue *steal, | ||
130 | struct ivtv_queue *to, int needed_bytes) | ||
131 | { | ||
132 | unsigned long flags; | ||
133 | int rc = 0; | ||
134 | int from_free = from == &s->q_free; | ||
135 | int to_free = to == &s->q_free; | ||
136 | int bytes_available; | ||
137 | |||
138 | spin_lock_irqsave(&s->qlock, flags); | ||
139 | if (needed_bytes == 0) { | ||
140 | from_free = 1; | ||
141 | needed_bytes = from->length; | ||
142 | } | ||
143 | |||
144 | bytes_available = from_free ? from->length : from->bytesused; | ||
145 | bytes_available += steal ? steal->length : 0; | ||
146 | |||
147 | if (bytes_available < needed_bytes) { | ||
148 | spin_unlock_irqrestore(&s->qlock, flags); | ||
149 | return -ENOMEM; | ||
150 | } | ||
151 | if (from_free) { | ||
152 | u32 old_length = to->length; | ||
153 | |||
154 | while (to->length - old_length < needed_bytes) { | ||
155 | if (list_empty(&from->list)) | ||
156 | from = steal; | ||
157 | if (from == steal) | ||
158 | rc++; /* keep track of 'stolen' buffers */ | ||
159 | ivtv_queue_move_buf(s, from, to, 1, 0); | ||
160 | } | ||
161 | } | ||
162 | else { | ||
163 | u32 old_bytesused = to->bytesused; | ||
164 | |||
165 | while (to->bytesused - old_bytesused < needed_bytes) { | ||
166 | if (list_empty(&from->list)) | ||
167 | from = steal; | ||
168 | if (from == steal) | ||
169 | rc++; /* keep track of 'stolen' buffers */ | ||
170 | ivtv_queue_move_buf(s, from, to, to_free, rc); | ||
171 | } | ||
172 | } | ||
173 | spin_unlock_irqrestore(&s->qlock, flags); | ||
174 | return rc; | ||
175 | } | ||
176 | |||
177 | void ivtv_flush_queues(struct ivtv_stream *s) | ||
178 | { | ||
179 | ivtv_queue_move(s, &s->q_io, NULL, &s->q_free, 0); | ||
180 | ivtv_queue_move(s, &s->q_full, NULL, &s->q_free, 0); | ||
181 | ivtv_queue_move(s, &s->q_dma, NULL, &s->q_free, 0); | ||
182 | ivtv_queue_move(s, &s->q_predma, NULL, &s->q_free, 0); | ||
183 | } | ||
184 | |||
185 | int ivtv_stream_alloc(struct ivtv_stream *s) | ||
186 | { | ||
187 | struct ivtv *itv = s->itv; | ||
188 | int SGsize = sizeof(struct ivtv_SG_element) * s->buffers; | ||
189 | int i; | ||
190 | |||
191 | if (s->buffers == 0) | ||
192 | return 0; | ||
193 | |||
194 | IVTV_DEBUG_INFO("Allocate %s%s stream: %d x %d buffers (%dkB total)\n", | ||
195 | s->dma != PCI_DMA_NONE ? "DMA " : "", | ||
196 | s->name, s->buffers, s->buf_size, s->buffers * s->buf_size / 1024); | ||
197 | |||
198 | /* Allocate DMA SG Arrays */ | ||
199 | if (s->dma != PCI_DMA_NONE) { | ||
200 | s->SGarray = (struct ivtv_SG_element *)kzalloc(SGsize, GFP_KERNEL); | ||
201 | if (s->SGarray == NULL) { | ||
202 | IVTV_ERR("Could not allocate SGarray for %s stream\n", s->name); | ||
203 | return -ENOMEM; | ||
204 | } | ||
205 | s->SG_length = 0; | ||
206 | s->SG_handle = pci_map_single(itv->dev, s->SGarray, SGsize, s->dma); | ||
207 | ivtv_stream_sync_for_cpu(s); | ||
208 | } | ||
209 | |||
210 | /* allocate stream buffers. Initially all buffers are in q_free. */ | ||
211 | for (i = 0; i < s->buffers; i++) { | ||
212 | struct ivtv_buffer *buf = kzalloc(sizeof(struct ivtv_buffer), GFP_KERNEL); | ||
213 | |||
214 | if (buf == NULL) | ||
215 | break; | ||
216 | buf->buf = kmalloc(s->buf_size + 256, GFP_KERNEL); | ||
217 | if (buf->buf == NULL) { | ||
218 | kfree(buf); | ||
219 | break; | ||
220 | } | ||
221 | INIT_LIST_HEAD(&buf->list); | ||
222 | if (s->dma != PCI_DMA_NONE) { | ||
223 | buf->dma_handle = pci_map_single(s->itv->dev, | ||
224 | buf->buf, s->buf_size + 256, s->dma); | ||
225 | ivtv_buf_sync_for_cpu(s, buf); | ||
226 | } | ||
227 | ivtv_enqueue(s, buf, &s->q_free); | ||
228 | } | ||
229 | if (i == s->buffers) | ||
230 | return 0; | ||
231 | IVTV_ERR("Couldn't allocate buffers for %s stream\n", s->name); | ||
232 | ivtv_stream_free(s); | ||
233 | return -ENOMEM; | ||
234 | } | ||
235 | |||
236 | void ivtv_stream_free(struct ivtv_stream *s) | ||
237 | { | ||
238 | struct ivtv_buffer *buf; | ||
239 | |||
240 | /* move all buffers to q_free */ | ||
241 | ivtv_flush_queues(s); | ||
242 | |||
243 | /* empty q_free */ | ||
244 | while ((buf = ivtv_dequeue(s, &s->q_free))) { | ||
245 | if (s->dma != PCI_DMA_NONE) | ||
246 | pci_unmap_single(s->itv->dev, buf->dma_handle, | ||
247 | s->buf_size + 256, s->dma); | ||
248 | kfree(buf->buf); | ||
249 | kfree(buf); | ||
250 | } | ||
251 | |||
252 | /* Free SG Array/Lists */ | ||
253 | if (s->SGarray != NULL) { | ||
254 | if (s->SG_handle != IVTV_DMA_UNMAPPED) { | ||
255 | pci_unmap_single(s->itv->dev, s->SG_handle, | ||
256 | sizeof(struct ivtv_SG_element) * s->buffers, PCI_DMA_TODEVICE); | ||
257 | s->SG_handle = IVTV_DMA_UNMAPPED; | ||
258 | } | ||
259 | s->SGarray = NULL; | ||
260 | s->SG_length = 0; | ||
261 | } | ||
262 | } | ||
diff --git a/drivers/media/video/ivtv/ivtv-queue.h b/drivers/media/video/ivtv/ivtv-queue.h new file mode 100644 index 000000000000..903edd4b4381 --- /dev/null +++ b/drivers/media/video/ivtv/ivtv-queue.h | |||
@@ -0,0 +1,64 @@ | |||
1 | /* | ||
2 | buffer queues. | ||
3 | Copyright (C) 2003-2004 Kevin Thayer <nufan_wfk at yahoo.com> | ||
4 | Copyright (C) 2004 Chris Kennedy <c@groovy.org> | ||
5 | Copyright (C) 2005-2007 Hans Verkuil <hverkuil@xs4all.nl> | ||
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 02111-1307 USA | ||
20 | */ | ||
21 | |||
22 | #define IVTV_DMA_UNMAPPED ((u32) -1) | ||
23 | |||
24 | /* ivtv_buffer utility functions */ | ||
25 | static inline void ivtv_buf_sync_for_cpu(struct ivtv_stream *s, struct ivtv_buffer *buf) | ||
26 | { | ||
27 | if (s->dma != PCI_DMA_NONE) | ||
28 | pci_dma_sync_single_for_cpu(s->itv->dev, buf->dma_handle, | ||
29 | s->buf_size + 256, s->dma); | ||
30 | } | ||
31 | |||
32 | static inline void ivtv_buf_sync_for_device(struct ivtv_stream *s, struct ivtv_buffer *buf) | ||
33 | { | ||
34 | if (s->dma != PCI_DMA_NONE) | ||
35 | pci_dma_sync_single_for_device(s->itv->dev, buf->dma_handle, | ||
36 | s->buf_size + 256, s->dma); | ||
37 | } | ||
38 | |||
39 | int ivtv_buf_copy_from_user(struct ivtv_stream *s, struct ivtv_buffer *buf, const char __user *src, int copybytes); | ||
40 | void ivtv_buf_swap(struct ivtv_buffer *buf); | ||
41 | |||
42 | /* ivtv_queue utility functions */ | ||
43 | void ivtv_queue_init(struct ivtv_queue *q); | ||
44 | void ivtv_enqueue(struct ivtv_stream *s, struct ivtv_buffer *buf, struct ivtv_queue *q); | ||
45 | struct ivtv_buffer *ivtv_dequeue(struct ivtv_stream *s, struct ivtv_queue *q); | ||
46 | int ivtv_queue_move(struct ivtv_stream *s, struct ivtv_queue *from, struct ivtv_queue *steal, | ||
47 | struct ivtv_queue *to, int needed_bytes); | ||
48 | void ivtv_flush_queues(struct ivtv_stream *s); | ||
49 | |||
50 | /* ivtv_stream utility functions */ | ||
51 | int ivtv_stream_alloc(struct ivtv_stream *s); | ||
52 | void ivtv_stream_free(struct ivtv_stream *s); | ||
53 | |||
54 | static inline void ivtv_stream_sync_for_cpu(struct ivtv_stream *s) | ||
55 | { | ||
56 | pci_dma_sync_single_for_cpu(s->itv->dev, s->SG_handle, | ||
57 | sizeof(struct ivtv_SG_element) * s->buffers, PCI_DMA_TODEVICE); | ||
58 | } | ||
59 | |||
60 | static inline void ivtv_stream_sync_for_device(struct ivtv_stream *s) | ||
61 | { | ||
62 | pci_dma_sync_single_for_device(s->itv->dev, s->SG_handle, | ||
63 | sizeof(struct ivtv_SG_element) * s->buffers, PCI_DMA_TODEVICE); | ||
64 | } | ||
diff --git a/drivers/media/video/ivtv/ivtv-streams.c b/drivers/media/video/ivtv/ivtv-streams.c new file mode 100644 index 000000000000..73a1c933d8f7 --- /dev/null +++ b/drivers/media/video/ivtv/ivtv-streams.c | |||
@@ -0,0 +1,977 @@ | |||
1 | /* | ||
2 | init/start/stop/exit stream functions | ||
3 | Copyright (C) 2003-2004 Kevin Thayer <nufan_wfk at yahoo.com> | ||
4 | Copyright (C) 2004 Chris Kennedy <c@groovy.org> | ||
5 | Copyright (C) 2005-2007 Hans Verkuil <hverkuil@xs4all.nl> | ||
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 02111-1307 USA | ||
20 | */ | ||
21 | |||
22 | /* License: GPL | ||
23 | * Author: Kevin Thayer <nufan_wfk at yahoo dot com> | ||
24 | * | ||
25 | * This file will hold API related functions, both internal (firmware api) | ||
26 | * and external (v4l2, etc) | ||
27 | * | ||
28 | * ----- | ||
29 | * MPG600/MPG160 support by T.Adachi <tadachi@tadachi-net.com> | ||
30 | * and Takeru KOMORIYA<komoriya@paken.org> | ||
31 | * | ||
32 | * AVerMedia M179 GPIO info by Chris Pinkham <cpinkham@bc2va.org> | ||
33 | * using information provided by Jiun-Kuei Jung @ AVerMedia. | ||
34 | */ | ||
35 | |||
36 | #include "ivtv-driver.h" | ||
37 | #include "ivtv-fileops.h" | ||
38 | #include "ivtv-i2c.h" | ||
39 | #include "ivtv-queue.h" | ||
40 | #include "ivtv-mailbox.h" | ||
41 | #include "ivtv-audio.h" | ||
42 | #include "ivtv-video.h" | ||
43 | #include "ivtv-vbi.h" | ||
44 | #include "ivtv-ioctl.h" | ||
45 | #include "ivtv-irq.h" | ||
46 | #include "ivtv-streams.h" | ||
47 | #include "ivtv-cards.h" | ||
48 | |||
49 | static struct file_operations ivtv_v4l2_enc_fops = { | ||
50 | .owner = THIS_MODULE, | ||
51 | .read = ivtv_v4l2_read, | ||
52 | .write = ivtv_v4l2_write, | ||
53 | .open = ivtv_v4l2_open, | ||
54 | .ioctl = ivtv_v4l2_ioctl, | ||
55 | .release = ivtv_v4l2_close, | ||
56 | .poll = ivtv_v4l2_enc_poll, | ||
57 | }; | ||
58 | |||
59 | static struct file_operations ivtv_v4l2_dec_fops = { | ||
60 | .owner = THIS_MODULE, | ||
61 | .read = ivtv_v4l2_read, | ||
62 | .write = ivtv_v4l2_write, | ||
63 | .open = ivtv_v4l2_open, | ||
64 | .ioctl = ivtv_v4l2_ioctl, | ||
65 | .release = ivtv_v4l2_close, | ||
66 | .poll = ivtv_v4l2_dec_poll, | ||
67 | }; | ||
68 | |||
69 | struct { | ||
70 | const char *name; | ||
71 | int vfl_type; | ||
72 | int minor_offset; | ||
73 | int dma, pio; | ||
74 | enum v4l2_buf_type buf_type; | ||
75 | struct file_operations *fops; | ||
76 | } ivtv_stream_info[] = { | ||
77 | { /* IVTV_ENC_STREAM_TYPE_MPG */ | ||
78 | "encoder MPEG", | ||
79 | VFL_TYPE_GRABBER, 0, | ||
80 | PCI_DMA_FROMDEVICE, 0, V4L2_BUF_TYPE_VIDEO_CAPTURE, | ||
81 | &ivtv_v4l2_enc_fops | ||
82 | }, | ||
83 | { /* IVTV_ENC_STREAM_TYPE_YUV */ | ||
84 | "encoder YUV", | ||
85 | VFL_TYPE_GRABBER, IVTV_V4L2_ENC_YUV_OFFSET, | ||
86 | PCI_DMA_FROMDEVICE, 0, V4L2_BUF_TYPE_VIDEO_CAPTURE, | ||
87 | &ivtv_v4l2_enc_fops | ||
88 | }, | ||
89 | { /* IVTV_ENC_STREAM_TYPE_VBI */ | ||
90 | "encoder VBI", | ||
91 | VFL_TYPE_VBI, 0, | ||
92 | PCI_DMA_FROMDEVICE, 0, V4L2_BUF_TYPE_VBI_CAPTURE, | ||
93 | &ivtv_v4l2_enc_fops | ||
94 | }, | ||
95 | { /* IVTV_ENC_STREAM_TYPE_PCM */ | ||
96 | "encoder PCM audio", | ||
97 | VFL_TYPE_GRABBER, IVTV_V4L2_ENC_PCM_OFFSET, | ||
98 | PCI_DMA_FROMDEVICE, 0, V4L2_BUF_TYPE_PRIVATE, | ||
99 | &ivtv_v4l2_enc_fops | ||
100 | }, | ||
101 | { /* IVTV_ENC_STREAM_TYPE_RAD */ | ||
102 | "encoder radio", | ||
103 | VFL_TYPE_RADIO, 0, | ||
104 | PCI_DMA_NONE, 1, V4L2_BUF_TYPE_PRIVATE, | ||
105 | &ivtv_v4l2_enc_fops | ||
106 | }, | ||
107 | { /* IVTV_DEC_STREAM_TYPE_MPG */ | ||
108 | "decoder MPEG", | ||
109 | VFL_TYPE_GRABBER, IVTV_V4L2_DEC_MPG_OFFSET, | ||
110 | PCI_DMA_TODEVICE, 0, V4L2_BUF_TYPE_VIDEO_OUTPUT, | ||
111 | &ivtv_v4l2_dec_fops | ||
112 | }, | ||
113 | { /* IVTV_DEC_STREAM_TYPE_VBI */ | ||
114 | "decoder VBI", | ||
115 | VFL_TYPE_VBI, IVTV_V4L2_DEC_VBI_OFFSET, | ||
116 | PCI_DMA_NONE, 1, V4L2_BUF_TYPE_VBI_CAPTURE, | ||
117 | &ivtv_v4l2_enc_fops | ||
118 | }, | ||
119 | { /* IVTV_DEC_STREAM_TYPE_VOUT */ | ||
120 | "decoder VOUT", | ||
121 | VFL_TYPE_VBI, IVTV_V4L2_DEC_VOUT_OFFSET, | ||
122 | PCI_DMA_NONE, 1, V4L2_BUF_TYPE_VBI_OUTPUT, | ||
123 | &ivtv_v4l2_dec_fops | ||
124 | }, | ||
125 | { /* IVTV_DEC_STREAM_TYPE_YUV */ | ||
126 | "decoder YUV", | ||
127 | VFL_TYPE_GRABBER, IVTV_V4L2_DEC_YUV_OFFSET, | ||
128 | PCI_DMA_TODEVICE, 0, V4L2_BUF_TYPE_VIDEO_OUTPUT, | ||
129 | &ivtv_v4l2_dec_fops | ||
130 | } | ||
131 | }; | ||
132 | |||
133 | static void ivtv_stream_init(struct ivtv *itv, int type) | ||
134 | { | ||
135 | struct ivtv_stream *s = &itv->streams[type]; | ||
136 | struct video_device *dev = s->v4l2dev; | ||
137 | |||
138 | /* we need to keep v4l2dev, so restore it afterwards */ | ||
139 | memset(s, 0, sizeof(*s)); | ||
140 | s->v4l2dev = dev; | ||
141 | |||
142 | /* initialize ivtv_stream fields */ | ||
143 | s->itv = itv; | ||
144 | s->type = type; | ||
145 | s->name = ivtv_stream_info[type].name; | ||
146 | |||
147 | if (ivtv_stream_info[type].pio) | ||
148 | s->dma = PCI_DMA_NONE; | ||
149 | else | ||
150 | s->dma = ivtv_stream_info[type].dma; | ||
151 | s->buf_size = itv->stream_buf_size[type]; | ||
152 | if (s->buf_size) | ||
153 | s->buffers = itv->options.megabytes[type] * 1024 * 1024 / s->buf_size; | ||
154 | spin_lock_init(&s->qlock); | ||
155 | init_waitqueue_head(&s->waitq); | ||
156 | s->id = -1; | ||
157 | s->SG_handle = IVTV_DMA_UNMAPPED; | ||
158 | ivtv_queue_init(&s->q_free); | ||
159 | ivtv_queue_init(&s->q_full); | ||
160 | ivtv_queue_init(&s->q_dma); | ||
161 | ivtv_queue_init(&s->q_predma); | ||
162 | ivtv_queue_init(&s->q_io); | ||
163 | } | ||
164 | |||
165 | static int ivtv_reg_dev(struct ivtv *itv, int type) | ||
166 | { | ||
167 | struct ivtv_stream *s = &itv->streams[type]; | ||
168 | int vfl_type = ivtv_stream_info[type].vfl_type; | ||
169 | int minor_offset = ivtv_stream_info[type].minor_offset; | ||
170 | int minor; | ||
171 | |||
172 | /* These four fields are always initialized. If v4l2dev == NULL, then | ||
173 | this stream is not in use. In that case no other fields but these | ||
174 | four can be used. */ | ||
175 | s->v4l2dev = NULL; | ||
176 | s->itv = itv; | ||
177 | s->type = type; | ||
178 | s->name = ivtv_stream_info[type].name; | ||
179 | |||
180 | /* Check whether the radio is supported */ | ||
181 | if (type == IVTV_ENC_STREAM_TYPE_RAD && !(itv->v4l2_cap & V4L2_CAP_RADIO)) | ||
182 | return 0; | ||
183 | if (type >= IVTV_DEC_STREAM_TYPE_MPG && !(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) | ||
184 | return 0; | ||
185 | |||
186 | if (minor_offset >= 0) | ||
187 | /* card number + user defined offset + device offset */ | ||
188 | minor = itv->num + ivtv_first_minor + minor_offset; | ||
189 | else | ||
190 | minor = -1; | ||
191 | |||
192 | /* User explicitly selected 0 buffers for these streams, so don't | ||
193 | create them. */ | ||
194 | if (minor >= 0 && ivtv_stream_info[type].dma != PCI_DMA_NONE && | ||
195 | itv->options.megabytes[type] == 0) { | ||
196 | IVTV_INFO("Disabled %s device\n", ivtv_stream_info[type].name); | ||
197 | return 0; | ||
198 | } | ||
199 | |||
200 | ivtv_stream_init(itv, type); | ||
201 | |||
202 | /* allocate and initialize the v4l2 video device structure */ | ||
203 | s->v4l2dev = video_device_alloc(); | ||
204 | if (s->v4l2dev == NULL) { | ||
205 | IVTV_ERR("Couldn't allocate v4l2 video_device for %s\n", s->name); | ||
206 | return -ENOMEM; | ||
207 | } | ||
208 | |||
209 | s->v4l2dev->type = VID_TYPE_CAPTURE | VID_TYPE_TUNER | VID_TYPE_TELETEXT | | ||
210 | VID_TYPE_CLIPPING | VID_TYPE_SCALES | VID_TYPE_MPEG_ENCODER; | ||
211 | if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) { | ||
212 | s->v4l2dev->type |= VID_TYPE_MPEG_DECODER; | ||
213 | } | ||
214 | snprintf(s->v4l2dev->name, sizeof(s->v4l2dev->name), "ivtv%d %s", | ||
215 | itv->num, s->name); | ||
216 | |||
217 | s->v4l2dev->minor = minor; | ||
218 | s->v4l2dev->dev = &itv->dev->dev; | ||
219 | s->v4l2dev->fops = ivtv_stream_info[type].fops; | ||
220 | s->v4l2dev->release = video_device_release; | ||
221 | |||
222 | if (minor >= 0) { | ||
223 | /* Register device. First try the desired minor, then any free one. */ | ||
224 | if (video_register_device(s->v4l2dev, vfl_type, minor) && | ||
225 | video_register_device(s->v4l2dev, vfl_type, -1)) { | ||
226 | IVTV_ERR("Couldn't register v4l2 device for %s minor %d\n", | ||
227 | s->name, minor); | ||
228 | video_device_release(s->v4l2dev); | ||
229 | s->v4l2dev = NULL; | ||
230 | return -ENOMEM; | ||
231 | } | ||
232 | } | ||
233 | else { | ||
234 | /* Don't register a 'hidden' stream (OSD) */ | ||
235 | IVTV_INFO("Created framebuffer stream for %s\n", s->name); | ||
236 | return 0; | ||
237 | } | ||
238 | |||
239 | switch (vfl_type) { | ||
240 | case VFL_TYPE_GRABBER: | ||
241 | IVTV_INFO("Registered device video%d for %s (%d MB)\n", | ||
242 | s->v4l2dev->minor, s->name, itv->options.megabytes[type]); | ||
243 | break; | ||
244 | case VFL_TYPE_RADIO: | ||
245 | IVTV_INFO("Registered device radio%d for %s\n", | ||
246 | s->v4l2dev->minor - MINOR_VFL_TYPE_RADIO_MIN, s->name); | ||
247 | break; | ||
248 | case VFL_TYPE_VBI: | ||
249 | if (itv->options.megabytes[type]) | ||
250 | IVTV_INFO("Registered device vbi%d for %s (%d MB)\n", | ||
251 | s->v4l2dev->minor - MINOR_VFL_TYPE_VBI_MIN, | ||
252 | s->name, itv->options.megabytes[type]); | ||
253 | else | ||
254 | IVTV_INFO("Registered device vbi%d for %s\n", | ||
255 | s->v4l2dev->minor - MINOR_VFL_TYPE_VBI_MIN, s->name); | ||
256 | break; | ||
257 | } | ||
258 | return 0; | ||
259 | } | ||
260 | |||
261 | /* Initialize v4l2 variables and register v4l2 devices */ | ||
262 | int ivtv_streams_setup(struct ivtv *itv) | ||
263 | { | ||
264 | int type; | ||
265 | |||
266 | /* Setup V4L2 Devices */ | ||
267 | for (type = 0; type < IVTV_MAX_STREAMS; type++) { | ||
268 | /* Register Device */ | ||
269 | if (ivtv_reg_dev(itv, type)) | ||
270 | break; | ||
271 | |||
272 | if (itv->streams[type].v4l2dev == NULL) | ||
273 | continue; | ||
274 | |||
275 | /* Allocate Stream */ | ||
276 | if (ivtv_stream_alloc(&itv->streams[type])) | ||
277 | break; | ||
278 | } | ||
279 | if (type == IVTV_MAX_STREAMS) { | ||
280 | return 0; | ||
281 | } | ||
282 | |||
283 | /* One or more streams could not be initialized. Clean 'em all up. */ | ||
284 | ivtv_streams_cleanup(itv); | ||
285 | return -ENOMEM; | ||
286 | } | ||
287 | |||
288 | /* Unregister v4l2 devices */ | ||
289 | void ivtv_streams_cleanup(struct ivtv *itv) | ||
290 | { | ||
291 | int type; | ||
292 | |||
293 | /* Teardown all streams */ | ||
294 | for (type = 0; type < IVTV_MAX_STREAMS; type++) { | ||
295 | struct video_device *vdev = itv->streams[type].v4l2dev; | ||
296 | |||
297 | itv->streams[type].v4l2dev = NULL; | ||
298 | if (vdev == NULL) | ||
299 | continue; | ||
300 | |||
301 | ivtv_stream_free(&itv->streams[type]); | ||
302 | /* Free Device */ | ||
303 | if (vdev->minor == -1) /* 'Hidden' never registered stream (OSD) */ | ||
304 | video_device_release(vdev); | ||
305 | else /* All others, just unregister. */ | ||
306 | video_unregister_device(vdev); | ||
307 | } | ||
308 | } | ||
309 | |||
310 | static void ivtv_vbi_setup(struct ivtv *itv) | ||
311 | { | ||
312 | int raw = itv->vbi.sliced_in->service_set == 0; | ||
313 | u32 data[CX2341X_MBOX_MAX_DATA]; | ||
314 | int lines; | ||
315 | int i; | ||
316 | |||
317 | /* If Embed then streamtype must be Program */ | ||
318 | /* TODO: should we really do this? */ | ||
319 | if (0 && !raw && itv->vbi.insert_mpeg) { | ||
320 | itv->params.stream_type = 0; | ||
321 | |||
322 | /* assign stream type */ | ||
323 | ivtv_vapi(itv, CX2341X_ENC_SET_STREAM_TYPE, 1, itv->params.stream_type); | ||
324 | } | ||
325 | |||
326 | /* Reset VBI */ | ||
327 | ivtv_vapi(itv, CX2341X_ENC_SET_VBI_LINE, 5, 0xffff , 0, 0, 0, 0); | ||
328 | |||
329 | if (itv->is_60hz) { | ||
330 | itv->vbi.count = 12; | ||
331 | itv->vbi.start[0] = 10; | ||
332 | itv->vbi.start[1] = 273; | ||
333 | } else { /* PAL/SECAM */ | ||
334 | itv->vbi.count = 18; | ||
335 | itv->vbi.start[0] = 6; | ||
336 | itv->vbi.start[1] = 318; | ||
337 | } | ||
338 | |||
339 | /* setup VBI registers */ | ||
340 | itv->video_dec_func(itv, VIDIOC_S_FMT, &itv->vbi.in); | ||
341 | |||
342 | /* determine number of lines and total number of VBI bytes. | ||
343 | A raw line takes 1443 bytes: 2 * 720 + 4 byte frame header - 1 | ||
344 | The '- 1' byte is probably an unused U or V byte. Or something... | ||
345 | A sliced line takes 51 bytes: 4 byte frame header, 4 byte internal | ||
346 | header, 42 data bytes + checksum (to be confirmed) */ | ||
347 | if (raw) { | ||
348 | lines = itv->vbi.count * 2; | ||
349 | } else { | ||
350 | lines = itv->is_60hz ? 24 : 38; | ||
351 | if (itv->is_60hz && (itv->hw_flags & IVTV_HW_CX25840)) | ||
352 | lines += 2; | ||
353 | } | ||
354 | |||
355 | itv->vbi.enc_size = lines * (raw ? itv->vbi.raw_size : itv->vbi.sliced_size); | ||
356 | |||
357 | /* Note: sliced vs raw flag doesn't seem to have any effect | ||
358 | TODO: check mode (0x02) value with older ivtv versions. */ | ||
359 | data[0] = raw | 0x02 | (0xbd << 8); | ||
360 | |||
361 | /* Every X number of frames a VBI interrupt arrives (frames as in 25 or 30 fps) */ | ||
362 | data[1] = 1; | ||
363 | /* The VBI frames are stored in a ringbuffer with this size (with a VBI frame as unit) */ | ||
364 | data[2] = raw ? 4 : 8; | ||
365 | /* The start/stop codes determine which VBI lines end up in the raw VBI data area. | ||
366 | The codes are from table 24 in the saa7115 datasheet. Each raw/sliced/video line | ||
367 | is framed with codes FF0000XX where XX is the SAV/EAV (Start/End of Active Video) | ||
368 | code. These values for raw VBI are obtained from a driver disassembly. The sliced | ||
369 | start/stop codes was deduced from this, but they do not appear in the driver. | ||
370 | Other code pairs that I found are: 0x250E6249/0x13545454 and 0x25256262/0x38137F54. | ||
371 | However, I have no idea what these values are for. */ | ||
372 | if (itv->hw_flags & IVTV_HW_CX25840) { | ||
373 | /* Setup VBI for the cx25840 digitizer */ | ||
374 | if (raw) { | ||
375 | data[3] = 0x20602060; | ||
376 | data[4] = 0x30703070; | ||
377 | } else { | ||
378 | data[3] = 0xB0F0B0F0; | ||
379 | data[4] = 0xA0E0A0E0; | ||
380 | } | ||
381 | /* Lines per frame */ | ||
382 | data[5] = lines; | ||
383 | /* bytes per line */ | ||
384 | data[6] = (raw ? itv->vbi.raw_size : itv->vbi.sliced_size); | ||
385 | } else { | ||
386 | /* Setup VBI for the saa7115 digitizer */ | ||
387 | if (raw) { | ||
388 | data[3] = 0x25256262; | ||
389 | data[4] = 0x387F7F7F; | ||
390 | } else { | ||
391 | data[3] = 0xABABECEC; | ||
392 | data[4] = 0xB6F1F1F1; | ||
393 | } | ||
394 | /* Lines per frame */ | ||
395 | data[5] = lines; | ||
396 | /* bytes per line */ | ||
397 | data[6] = itv->vbi.enc_size / lines; | ||
398 | } | ||
399 | |||
400 | IVTV_DEBUG_INFO( | ||
401 | "Setup VBI API header 0x%08x pkts %d buffs %d ln %d sz %d\n", | ||
402 | data[0], data[1], data[2], data[5], data[6]); | ||
403 | |||
404 | ivtv_api(itv, CX2341X_ENC_SET_VBI_CONFIG, 7, data); | ||
405 | |||
406 | /* returns the VBI encoder memory area. */ | ||
407 | itv->vbi.enc_start = data[2]; | ||
408 | itv->vbi.fpi = data[0]; | ||
409 | if (!itv->vbi.fpi) | ||
410 | itv->vbi.fpi = 1; | ||
411 | |||
412 | IVTV_DEBUG_INFO("Setup VBI start 0x%08x frames %d fpi %d lines 0x%08x\n", | ||
413 | itv->vbi.enc_start, data[1], itv->vbi.fpi, itv->digitizer); | ||
414 | |||
415 | /* select VBI lines. | ||
416 | Note that the sliced argument seems to have no effect. */ | ||
417 | for (i = 2; i <= 24; i++) { | ||
418 | int valid; | ||
419 | |||
420 | if (itv->is_60hz) { | ||
421 | valid = i >= 10 && i < 22; | ||
422 | } else { | ||
423 | valid = i >= 6 && i < 24; | ||
424 | } | ||
425 | ivtv_vapi(itv, CX2341X_ENC_SET_VBI_LINE, 5, i - 1, | ||
426 | valid, 0 , 0, 0); | ||
427 | ivtv_vapi(itv, CX2341X_ENC_SET_VBI_LINE, 5, (i - 1) | 0x80000000, | ||
428 | valid, 0, 0, 0); | ||
429 | } | ||
430 | |||
431 | /* Remaining VBI questions: | ||
432 | - Is it possible to select particular VBI lines only for inclusion in the MPEG | ||
433 | stream? Currently you can only get the first X lines. | ||
434 | - Is mixed raw and sliced VBI possible? | ||
435 | - What's the meaning of the raw/sliced flag? | ||
436 | - What's the meaning of params 2, 3 & 4 of the Select VBI command? */ | ||
437 | } | ||
438 | |||
439 | int ivtv_start_v4l2_encode_stream(struct ivtv_stream *s) | ||
440 | { | ||
441 | u32 data[CX2341X_MBOX_MAX_DATA]; | ||
442 | struct ivtv *itv = s->itv; | ||
443 | int captype = 0, subtype = 0; | ||
444 | int enable_passthrough = 0; | ||
445 | |||
446 | if (s->v4l2dev == NULL) | ||
447 | return -EINVAL; | ||
448 | |||
449 | IVTV_DEBUG_INFO("Start encoder stream %s\n", s->name); | ||
450 | |||
451 | switch (s->type) { | ||
452 | case IVTV_ENC_STREAM_TYPE_MPG: | ||
453 | captype = 0; | ||
454 | subtype = 3; | ||
455 | |||
456 | /* Stop Passthrough */ | ||
457 | if (itv->output_mode == OUT_PASSTHROUGH) { | ||
458 | ivtv_passthrough_mode(itv, 0); | ||
459 | enable_passthrough = 1; | ||
460 | } | ||
461 | itv->mpg_data_received = itv->vbi_data_inserted = 0; | ||
462 | itv->dualwatch_jiffies = jiffies; | ||
463 | itv->dualwatch_stereo_mode = itv->params.audio_properties & 0x0300; | ||
464 | itv->search_pack_header = 0; | ||
465 | break; | ||
466 | |||
467 | case IVTV_ENC_STREAM_TYPE_YUV: | ||
468 | if (itv->output_mode == OUT_PASSTHROUGH) { | ||
469 | captype = 2; | ||
470 | subtype = 11; /* video+audio+decoder */ | ||
471 | break; | ||
472 | } | ||
473 | captype = 1; | ||
474 | subtype = 1; | ||
475 | break; | ||
476 | case IVTV_ENC_STREAM_TYPE_PCM: | ||
477 | captype = 1; | ||
478 | subtype = 2; | ||
479 | break; | ||
480 | case IVTV_ENC_STREAM_TYPE_VBI: | ||
481 | captype = 1; | ||
482 | subtype = 4; | ||
483 | |||
484 | itv->vbi.frame = 0; | ||
485 | itv->vbi.inserted_frame = 0; | ||
486 | memset(itv->vbi.sliced_mpeg_size, | ||
487 | 0, sizeof(itv->vbi.sliced_mpeg_size)); | ||
488 | break; | ||
489 | default: | ||
490 | return -EINVAL; | ||
491 | } | ||
492 | s->subtype = subtype; | ||
493 | s->buffers_stolen = 0; | ||
494 | |||
495 | /* mute/unmute video */ | ||
496 | ivtv_vapi(itv, CX2341X_ENC_MUTE_VIDEO, 1, test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags) ? 1 : 0); | ||
497 | |||
498 | /* Clear Streamoff flags in case left from last capture */ | ||
499 | clear_bit(IVTV_F_S_STREAMOFF, &s->s_flags); | ||
500 | |||
501 | if (atomic_read(&itv->capturing) == 0) { | ||
502 | /* Always use frame based mode. Experiments have demonstrated that byte | ||
503 | stream based mode results in dropped frames and corruption. Not often, | ||
504 | but occasionally. Many thanks go to Leonard Orb who spent a lot of | ||
505 | effort and time trying to trace the cause of the drop outs. */ | ||
506 | /* 1 frame per DMA */ | ||
507 | /*ivtv_vapi(itv, CX2341X_ENC_SET_DMA_BLOCK_SIZE, 2, 128, 0); */ | ||
508 | ivtv_vapi(itv, CX2341X_ENC_SET_DMA_BLOCK_SIZE, 2, 1, 1); | ||
509 | |||
510 | /* Stuff from Windows, we don't know what it is */ | ||
511 | ivtv_vapi(itv, CX2341X_ENC_SET_VERT_CROP_LINE, 1, 0); | ||
512 | /* According to the docs, this should be correct. However, this is | ||
513 | untested. I don't dare enable this without having tested it. | ||
514 | Only very few old cards actually have this hardware combination. | ||
515 | ivtv_vapi(itv, CX2341X_ENC_SET_VERT_CROP_LINE, 1, | ||
516 | ((itv->hw_flags & IVTV_HW_SAA7114) && itv->is_60hz) ? 10001 : 0); | ||
517 | */ | ||
518 | ivtv_vapi(itv, CX2341X_ENC_MISC, 2, 3, !itv->has_cx23415); | ||
519 | ivtv_vapi(itv, CX2341X_ENC_MISC, 2, 8, 0); | ||
520 | ivtv_vapi(itv, CX2341X_ENC_MISC, 2, 4, 1); | ||
521 | ivtv_vapi(itv, CX2341X_ENC_MISC, 1, 12); | ||
522 | |||
523 | /* assign placeholder */ | ||
524 | ivtv_vapi(itv, CX2341X_ENC_SET_PLACEHOLDER, 12, | ||
525 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); | ||
526 | |||
527 | ivtv_vapi(itv, CX2341X_ENC_SET_NUM_VSYNC_LINES, 2, itv->digitizer, itv->digitizer); | ||
528 | |||
529 | /* Setup VBI */ | ||
530 | if (itv->v4l2_cap & V4L2_CAP_VBI_CAPTURE) { | ||
531 | ivtv_vbi_setup(itv); | ||
532 | } | ||
533 | |||
534 | /* assign program index info. Mask 7: select I/P/B, Num_req: 400 max */ | ||
535 | ivtv_vapi_result(itv, data, CX2341X_ENC_SET_PGM_INDEX_INFO, 2, 7, 400); | ||
536 | itv->pgm_info_offset = data[0]; | ||
537 | itv->pgm_info_num = data[1]; | ||
538 | itv->pgm_info_write_idx = 0; | ||
539 | itv->pgm_info_read_idx = 0; | ||
540 | |||
541 | IVTV_DEBUG_INFO("PGM Index at 0x%08x with %d elements\n", | ||
542 | itv->pgm_info_offset, itv->pgm_info_num); | ||
543 | |||
544 | /* Setup API for Stream */ | ||
545 | cx2341x_update(itv, ivtv_api_func, NULL, &itv->params); | ||
546 | } | ||
547 | |||
548 | /* Vsync Setup */ | ||
549 | if (itv->has_cx23415 && !test_and_set_bit(IVTV_F_I_DIG_RST, &itv->i_flags)) { | ||
550 | /* event notification (on) */ | ||
551 | ivtv_vapi(itv, CX2341X_ENC_SET_EVENT_NOTIFICATION, 4, 0, 1, IVTV_IRQ_ENC_VIM_RST, -1); | ||
552 | ivtv_clear_irq_mask(itv, IVTV_IRQ_ENC_VIM_RST); | ||
553 | } | ||
554 | |||
555 | if (atomic_read(&itv->capturing) == 0) { | ||
556 | /* Clear all Pending Interrupts */ | ||
557 | ivtv_set_irq_mask(itv, IVTV_IRQ_MASK_CAPTURE); | ||
558 | |||
559 | clear_bit(IVTV_F_I_EOS, &itv->i_flags); | ||
560 | |||
561 | /* Initialize Digitizer for Capture */ | ||
562 | ivtv_vapi(itv, CX2341X_ENC_INITIALIZE_INPUT, 0); | ||
563 | |||
564 | ivtv_sleep_timeout(HZ / 10, 0); | ||
565 | } | ||
566 | |||
567 | /* begin_capture */ | ||
568 | if (ivtv_vapi(itv, CX2341X_ENC_START_CAPTURE, 2, captype, subtype)) | ||
569 | { | ||
570 | IVTV_DEBUG_WARN( "Error starting capture!\n"); | ||
571 | return -EINVAL; | ||
572 | } | ||
573 | |||
574 | /* Start Passthrough */ | ||
575 | if (enable_passthrough) { | ||
576 | ivtv_passthrough_mode(itv, 1); | ||
577 | } | ||
578 | |||
579 | if (s->type == IVTV_ENC_STREAM_TYPE_VBI) | ||
580 | ivtv_clear_irq_mask(itv, IVTV_IRQ_ENC_VBI_CAP); | ||
581 | else | ||
582 | ivtv_clear_irq_mask(itv, IVTV_IRQ_MASK_CAPTURE); | ||
583 | |||
584 | /* you're live! sit back and await interrupts :) */ | ||
585 | atomic_inc(&itv->capturing); | ||
586 | return 0; | ||
587 | } | ||
588 | |||
589 | static int ivtv_setup_v4l2_decode_stream(struct ivtv_stream *s) | ||
590 | { | ||
591 | u32 data[CX2341X_MBOX_MAX_DATA]; | ||
592 | struct ivtv *itv = s->itv; | ||
593 | int datatype; | ||
594 | |||
595 | if (s->v4l2dev == NULL) | ||
596 | return -EINVAL; | ||
597 | |||
598 | IVTV_DEBUG_INFO("Setting some initial decoder settings\n"); | ||
599 | |||
600 | /* disable VBI signals, if the MPEG stream contains VBI data, | ||
601 | then that data will be processed automatically for you. */ | ||
602 | ivtv_disable_vbi(itv); | ||
603 | |||
604 | /* set audio mode to left/stereo for dual/stereo mode. */ | ||
605 | ivtv_vapi(itv, CX2341X_DEC_SET_AUDIO_MODE, 2, itv->audio_bilingual_mode, itv->audio_stereo_mode); | ||
606 | |||
607 | /* set number of internal decoder buffers */ | ||
608 | ivtv_vapi(itv, CX2341X_DEC_SET_DISPLAY_BUFFERS, 1, 0); | ||
609 | |||
610 | /* prebuffering */ | ||
611 | ivtv_vapi(itv, CX2341X_DEC_SET_PREBUFFERING, 1, 1); | ||
612 | |||
613 | /* extract from user packets */ | ||
614 | ivtv_vapi_result(itv, data, CX2341X_DEC_EXTRACT_VBI, 1, 1); | ||
615 | itv->vbi.dec_start = data[0]; | ||
616 | |||
617 | IVTV_DEBUG_INFO("Decoder VBI RE-Insert start 0x%08x size 0x%08x\n", | ||
618 | itv->vbi.dec_start, data[1]); | ||
619 | |||
620 | /* set decoder source settings */ | ||
621 | /* Data type: 0 = mpeg from host, | ||
622 | 1 = yuv from encoder, | ||
623 | 2 = yuv_from_host */ | ||
624 | switch (s->type) { | ||
625 | case IVTV_DEC_STREAM_TYPE_YUV: | ||
626 | datatype = itv->output_mode == OUT_PASSTHROUGH ? 1 : 2; | ||
627 | IVTV_DEBUG_INFO("Setup DEC YUV Stream data[0] = %d\n", datatype); | ||
628 | break; | ||
629 | case IVTV_DEC_STREAM_TYPE_MPG: | ||
630 | default: | ||
631 | datatype = 0; | ||
632 | break; | ||
633 | } | ||
634 | if (ivtv_vapi(itv, CX2341X_DEC_SET_DECODER_SOURCE, 4, datatype, | ||
635 | itv->params.width, itv->params.height, itv->params.audio_properties)) { | ||
636 | IVTV_DEBUG_WARN("COULDN'T INITIALIZE DECODER SOURCE\n"); | ||
637 | } | ||
638 | return 0; | ||
639 | } | ||
640 | |||
641 | int ivtv_start_v4l2_decode_stream(struct ivtv_stream *s, int gop_offset) | ||
642 | { | ||
643 | struct ivtv *itv = s->itv; | ||
644 | |||
645 | if (s->v4l2dev == NULL) | ||
646 | return -EINVAL; | ||
647 | |||
648 | if (test_and_set_bit(IVTV_F_S_STREAMING, &s->s_flags)) | ||
649 | return 0; /* already started */ | ||
650 | |||
651 | IVTV_DEBUG_INFO("Starting decode stream %s (gop_offset %d)\n", s->name, gop_offset); | ||
652 | |||
653 | /* Clear Streamoff */ | ||
654 | if (s->type == IVTV_DEC_STREAM_TYPE_YUV) { | ||
655 | /* Initialize Decoder */ | ||
656 | /* Reprogram Decoder YUV Buffers for YUV */ | ||
657 | write_reg(yuv_offset[0] >> 4, 0x82c); | ||
658 | write_reg((yuv_offset[0] + IVTV_YUV_BUFFER_UV_OFFSET) >> 4, 0x830); | ||
659 | write_reg(yuv_offset[0] >> 4, 0x834); | ||
660 | write_reg((yuv_offset[0] + IVTV_YUV_BUFFER_UV_OFFSET) >> 4, 0x838); | ||
661 | |||
662 | write_reg_sync(0x00000000 | (0x0c << 16) | (0x0b << 8), 0x2d24); | ||
663 | |||
664 | write_reg_sync(0x00108080, 0x2898); | ||
665 | /* Enable YUV decoder output */ | ||
666 | write_reg_sync(0x01, IVTV_REG_VDM); | ||
667 | } | ||
668 | |||
669 | ivtv_setup_v4l2_decode_stream(s); | ||
670 | |||
671 | /* set dma size to 65536 bytes */ | ||
672 | ivtv_vapi(itv, CX2341X_DEC_SET_DMA_BLOCK_SIZE, 1, 65536); | ||
673 | |||
674 | clear_bit(IVTV_F_S_STREAMOFF, &s->s_flags); | ||
675 | |||
676 | /* Zero out decoder counters */ | ||
677 | writel(0, &itv->dec_mbox.mbox[IVTV_MBOX_FIELD_DISPLAYED].data[0]); | ||
678 | writel(0, &itv->dec_mbox.mbox[IVTV_MBOX_FIELD_DISPLAYED].data[1]); | ||
679 | writel(0, &itv->dec_mbox.mbox[IVTV_MBOX_FIELD_DISPLAYED].data[2]); | ||
680 | writel(0, &itv->dec_mbox.mbox[IVTV_MBOX_FIELD_DISPLAYED].data[3]); | ||
681 | writel(0, &itv->dec_mbox.mbox[IVTV_MBOX_DMA].data[0]); | ||
682 | writel(0, &itv->dec_mbox.mbox[IVTV_MBOX_DMA].data[1]); | ||
683 | writel(0, &itv->dec_mbox.mbox[IVTV_MBOX_DMA].data[2]); | ||
684 | writel(0, &itv->dec_mbox.mbox[IVTV_MBOX_DMA].data[3]); | ||
685 | |||
686 | /* turn on notification of dual/stereo mode change */ | ||
687 | ivtv_vapi(itv, CX2341X_DEC_SET_EVENT_NOTIFICATION, 4, 0, 1, IVTV_IRQ_DEC_AUD_MODE_CHG, -1); | ||
688 | |||
689 | /* start playback */ | ||
690 | ivtv_vapi(itv, CX2341X_DEC_START_PLAYBACK, 2, gop_offset, 0); | ||
691 | |||
692 | /* Clear the following Interrupt mask bits for decoding */ | ||
693 | ivtv_clear_irq_mask(itv, IVTV_IRQ_MASK_DECODE); | ||
694 | IVTV_DEBUG_IRQ("IRQ Mask is now: 0x%08x\n", itv->irqmask); | ||
695 | |||
696 | /* you're live! sit back and await interrupts :) */ | ||
697 | atomic_inc(&itv->decoding); | ||
698 | return 0; | ||
699 | } | ||
700 | |||
701 | void ivtv_stop_all_captures(struct ivtv *itv) | ||
702 | { | ||
703 | int i; | ||
704 | |||
705 | for (i = IVTV_MAX_STREAMS - 1; i >= 0; i--) { | ||
706 | struct ivtv_stream *s = &itv->streams[i]; | ||
707 | |||
708 | if (s->v4l2dev == NULL) | ||
709 | continue; | ||
710 | if (test_bit(IVTV_F_S_STREAMING, &s->s_flags)) { | ||
711 | ivtv_stop_v4l2_encode_stream(s, 0); | ||
712 | } | ||
713 | } | ||
714 | } | ||
715 | |||
716 | int ivtv_stop_v4l2_encode_stream(struct ivtv_stream *s, int gop_end) | ||
717 | { | ||
718 | struct ivtv *itv = s->itv; | ||
719 | DECLARE_WAITQUEUE(wait, current); | ||
720 | int cap_type; | ||
721 | unsigned long then; | ||
722 | int stopmode; | ||
723 | u32 data[CX2341X_MBOX_MAX_DATA]; | ||
724 | |||
725 | if (s->v4l2dev == NULL) | ||
726 | return -EINVAL; | ||
727 | |||
728 | /* This function assumes that you are allowed to stop the capture | ||
729 | and that we are actually capturing */ | ||
730 | |||
731 | IVTV_DEBUG_INFO("Stop Capture\n"); | ||
732 | |||
733 | if (s->type == IVTV_DEC_STREAM_TYPE_VOUT) | ||
734 | return 0; | ||
735 | if (atomic_read(&itv->capturing) == 0) | ||
736 | return 0; | ||
737 | |||
738 | switch (s->type) { | ||
739 | case IVTV_ENC_STREAM_TYPE_YUV: | ||
740 | cap_type = 1; | ||
741 | break; | ||
742 | case IVTV_ENC_STREAM_TYPE_PCM: | ||
743 | cap_type = 1; | ||
744 | break; | ||
745 | case IVTV_ENC_STREAM_TYPE_VBI: | ||
746 | cap_type = 1; | ||
747 | break; | ||
748 | case IVTV_ENC_STREAM_TYPE_MPG: | ||
749 | default: | ||
750 | cap_type = 0; | ||
751 | break; | ||
752 | } | ||
753 | |||
754 | /* Stop Capture Mode */ | ||
755 | if (s->type == IVTV_ENC_STREAM_TYPE_MPG && gop_end) { | ||
756 | stopmode = 0; | ||
757 | } else { | ||
758 | stopmode = 1; | ||
759 | } | ||
760 | |||
761 | /* end_capture */ | ||
762 | /* when: 0 = end of GOP 1 = NOW!, type: 0 = mpeg, subtype: 3 = video+audio */ | ||
763 | ivtv_vapi(itv, CX2341X_ENC_STOP_CAPTURE, 3, stopmode, cap_type, s->subtype); | ||
764 | |||
765 | /* only run these if we're shutting down the last cap */ | ||
766 | if (atomic_read(&itv->capturing) - 1 == 0) { | ||
767 | /* event notification (off) */ | ||
768 | if (test_and_clear_bit(IVTV_F_I_DIG_RST, &itv->i_flags)) { | ||
769 | /* type: 0 = refresh */ | ||
770 | /* on/off: 0 = off, intr: 0x10000000, mbox_id: -1: none */ | ||
771 | ivtv_vapi(itv, CX2341X_ENC_SET_EVENT_NOTIFICATION, 4, 0, 0, IVTV_IRQ_ENC_VIM_RST, -1); | ||
772 | ivtv_set_irq_mask(itv, IVTV_IRQ_ENC_VIM_RST); | ||
773 | } | ||
774 | } | ||
775 | |||
776 | then = jiffies; | ||
777 | |||
778 | if (!test_bit(IVTV_F_S_PASSTHROUGH, &s->s_flags)) { | ||
779 | if (s->type == IVTV_ENC_STREAM_TYPE_MPG && gop_end) { | ||
780 | /* only run these if we're shutting down the last cap */ | ||
781 | unsigned long duration; | ||
782 | |||
783 | then = jiffies; | ||
784 | add_wait_queue(&itv->cap_w, &wait); | ||
785 | |||
786 | set_current_state(TASK_INTERRUPTIBLE); | ||
787 | |||
788 | /* wait 2s for EOS interrupt */ | ||
789 | while (!test_bit(IVTV_F_I_EOS, &itv->i_flags) && jiffies < then + 2 * HZ) { | ||
790 | schedule_timeout(HZ / 100); | ||
791 | } | ||
792 | |||
793 | /* To convert jiffies to ms, we must multiply by 1000 | ||
794 | * and divide by HZ. To avoid runtime division, we | ||
795 | * convert this to multiplication by 1000/HZ. | ||
796 | * Since integer division truncates, we get the best | ||
797 | * accuracy if we do a rounding calculation of the constant. | ||
798 | * Think of the case where HZ is 1024. | ||
799 | */ | ||
800 | duration = ((1000 + HZ / 2) / HZ) * (jiffies - then); | ||
801 | |||
802 | if (!test_bit(IVTV_F_I_EOS, &itv->i_flags)) { | ||
803 | IVTV_DEBUG_WARN("%s: EOS interrupt not received! stopping anyway.\n", s->name); | ||
804 | IVTV_DEBUG_WARN("%s: waited %lu ms.\n", s->name, duration); | ||
805 | } else { | ||
806 | IVTV_DEBUG_INFO("%s: EOS took %lu ms to occur.\n", s->name, duration); | ||
807 | } | ||
808 | set_current_state(TASK_RUNNING); | ||
809 | remove_wait_queue(&itv->cap_w, &wait); | ||
810 | } | ||
811 | |||
812 | then = jiffies; | ||
813 | /* Make sure DMA is complete */ | ||
814 | add_wait_queue(&s->waitq, &wait); | ||
815 | set_current_state(TASK_INTERRUPTIBLE); | ||
816 | do { | ||
817 | /* check if DMA is pending */ | ||
818 | if ((s->type == IVTV_ENC_STREAM_TYPE_MPG) && /* MPG Only */ | ||
819 | (read_reg(IVTV_REG_DMASTATUS) & 0x02)) { | ||
820 | /* Check for last DMA */ | ||
821 | ivtv_vapi_result(itv, data, CX2341X_ENC_GET_SEQ_END, 2, 0, 0); | ||
822 | |||
823 | if (data[0] == 1) { | ||
824 | IVTV_DEBUG_DMA("%s: Last DMA of size 0x%08x\n", s->name, data[1]); | ||
825 | break; | ||
826 | } | ||
827 | } else if (read_reg(IVTV_REG_DMASTATUS) & 0x02) { | ||
828 | break; | ||
829 | } | ||
830 | |||
831 | ivtv_sleep_timeout(HZ / 100, 1); | ||
832 | } while (then + HZ * 2 > jiffies); | ||
833 | |||
834 | set_current_state(TASK_RUNNING); | ||
835 | remove_wait_queue(&s->waitq, &wait); | ||
836 | } | ||
837 | |||
838 | atomic_dec(&itv->capturing); | ||
839 | |||
840 | /* Clear capture and no-read bits */ | ||
841 | clear_bit(IVTV_F_S_STREAMING, &s->s_flags); | ||
842 | |||
843 | if (s->type == IVTV_ENC_STREAM_TYPE_VBI) | ||
844 | ivtv_set_irq_mask(itv, IVTV_IRQ_ENC_VBI_CAP); | ||
845 | |||
846 | if (atomic_read(&itv->capturing) > 0) { | ||
847 | return 0; | ||
848 | } | ||
849 | |||
850 | /* Set the following Interrupt mask bits for capture */ | ||
851 | ivtv_set_irq_mask(itv, IVTV_IRQ_MASK_CAPTURE); | ||
852 | |||
853 | wake_up(&s->waitq); | ||
854 | |||
855 | return 0; | ||
856 | } | ||
857 | |||
858 | int ivtv_stop_v4l2_decode_stream(struct ivtv_stream *s, int flags, u64 pts) | ||
859 | { | ||
860 | struct ivtv *itv = s->itv; | ||
861 | |||
862 | if (s->v4l2dev == NULL) | ||
863 | return -EINVAL; | ||
864 | |||
865 | if (s->type != IVTV_DEC_STREAM_TYPE_YUV && s->type != IVTV_DEC_STREAM_TYPE_MPG) | ||
866 | return -EINVAL; | ||
867 | |||
868 | if (!test_bit(IVTV_F_S_STREAMING, &s->s_flags)) | ||
869 | return 0; | ||
870 | |||
871 | IVTV_DEBUG_INFO("Stop Decode at %llu, flags: %x\n", pts, flags); | ||
872 | |||
873 | /* Stop Decoder */ | ||
874 | if (!(flags & VIDEO_CMD_STOP_IMMEDIATELY) || pts) { | ||
875 | u32 tmp = 0; | ||
876 | |||
877 | /* Wait until the decoder is no longer running */ | ||
878 | if (pts) { | ||
879 | ivtv_vapi(itv, CX2341X_DEC_STOP_PLAYBACK, 3, | ||
880 | 0, (u32)(pts & 0xffffffff), (u32)(pts >> 32)); | ||
881 | } | ||
882 | while (1) { | ||
883 | u32 data[CX2341X_MBOX_MAX_DATA]; | ||
884 | ivtv_vapi_result(itv, data, CX2341X_DEC_GET_XFER_INFO, 0); | ||
885 | if (s->q_full.buffers + s->q_dma.buffers == 0) { | ||
886 | if (tmp == data[3]) | ||
887 | break; | ||
888 | tmp = data[3]; | ||
889 | } | ||
890 | if (ivtv_sleep_timeout(HZ/10, 1)) | ||
891 | break; | ||
892 | } | ||
893 | } | ||
894 | ivtv_vapi(itv, CX2341X_DEC_STOP_PLAYBACK, 3, flags & VIDEO_CMD_STOP_TO_BLACK, 0, 0); | ||
895 | |||
896 | /* turn off notification of dual/stereo mode change */ | ||
897 | ivtv_vapi(itv, CX2341X_DEC_SET_EVENT_NOTIFICATION, 4, 0, 0, IVTV_IRQ_DEC_AUD_MODE_CHG, -1); | ||
898 | |||
899 | ivtv_set_irq_mask(itv, IVTV_IRQ_MASK_DECODE); | ||
900 | |||
901 | clear_bit(IVTV_F_S_NEEDS_DATA, &s->s_flags); | ||
902 | clear_bit(IVTV_F_S_STREAMING, &s->s_flags); | ||
903 | ivtv_flush_queues(s); | ||
904 | |||
905 | if (!test_bit(IVTV_F_S_PASSTHROUGH, &s->s_flags)) { | ||
906 | /* disable VBI on TV-out */ | ||
907 | ivtv_disable_vbi(itv); | ||
908 | } | ||
909 | |||
910 | /* decrement decoding */ | ||
911 | atomic_dec(&itv->decoding); | ||
912 | |||
913 | set_bit(IVTV_F_I_EV_DEC_STOPPED, &itv->i_flags); | ||
914 | wake_up(&itv->event_waitq); | ||
915 | |||
916 | /* wake up wait queues */ | ||
917 | wake_up(&s->waitq); | ||
918 | |||
919 | return 0; | ||
920 | } | ||
921 | |||
922 | int ivtv_passthrough_mode(struct ivtv *itv, int enable) | ||
923 | { | ||
924 | struct ivtv_stream *yuv_stream = &itv->streams[IVTV_ENC_STREAM_TYPE_YUV]; | ||
925 | struct ivtv_stream *dec_stream = &itv->streams[IVTV_DEC_STREAM_TYPE_YUV]; | ||
926 | |||
927 | if (yuv_stream->v4l2dev == NULL || dec_stream->v4l2dev == NULL) | ||
928 | return -EINVAL; | ||
929 | |||
930 | IVTV_DEBUG_INFO("ivtv ioctl: Select passthrough mode\n"); | ||
931 | |||
932 | /* Prevent others from starting/stopping streams while we | ||
933 | initiate/terminate passthrough mode */ | ||
934 | if (enable) { | ||
935 | if (itv->output_mode == OUT_PASSTHROUGH) { | ||
936 | return 0; | ||
937 | } | ||
938 | if (ivtv_set_output_mode(itv, OUT_PASSTHROUGH) != OUT_PASSTHROUGH) | ||
939 | return -EBUSY; | ||
940 | |||
941 | /* Fully initialize stream, and then unflag init */ | ||
942 | set_bit(IVTV_F_S_PASSTHROUGH, &dec_stream->s_flags); | ||
943 | set_bit(IVTV_F_S_STREAMING, &dec_stream->s_flags); | ||
944 | |||
945 | /* Setup YUV Decoder */ | ||
946 | ivtv_setup_v4l2_decode_stream(dec_stream); | ||
947 | |||
948 | /* Start Decoder */ | ||
949 | ivtv_vapi(itv, CX2341X_DEC_START_PLAYBACK, 2, 0, 1); | ||
950 | atomic_inc(&itv->decoding); | ||
951 | |||
952 | /* Setup capture if not already done */ | ||
953 | if (atomic_read(&itv->capturing) == 0) { | ||
954 | cx2341x_update(itv, ivtv_api_func, NULL, &itv->params); | ||
955 | } | ||
956 | |||
957 | /* Start Passthrough Mode */ | ||
958 | ivtv_vapi(itv, CX2341X_ENC_START_CAPTURE, 2, 2, 11); | ||
959 | atomic_inc(&itv->capturing); | ||
960 | return 0; | ||
961 | } | ||
962 | |||
963 | if (itv->output_mode != OUT_PASSTHROUGH) | ||
964 | return 0; | ||
965 | |||
966 | /* Stop Passthrough Mode */ | ||
967 | ivtv_vapi(itv, CX2341X_ENC_STOP_CAPTURE, 3, 1, 2, 11); | ||
968 | ivtv_vapi(itv, CX2341X_DEC_STOP_PLAYBACK, 3, 1, 0, 0); | ||
969 | |||
970 | atomic_dec(&itv->capturing); | ||
971 | atomic_dec(&itv->decoding); | ||
972 | clear_bit(IVTV_F_S_PASSTHROUGH, &dec_stream->s_flags); | ||
973 | clear_bit(IVTV_F_S_STREAMING, &dec_stream->s_flags); | ||
974 | itv->output_mode = OUT_NONE; | ||
975 | |||
976 | return 0; | ||
977 | } | ||
diff --git a/drivers/media/video/ivtv/ivtv-streams.h b/drivers/media/video/ivtv/ivtv-streams.h new file mode 100644 index 000000000000..8597b75384a7 --- /dev/null +++ b/drivers/media/video/ivtv/ivtv-streams.h | |||
@@ -0,0 +1,31 @@ | |||
1 | /* | ||
2 | init/start/stop/exit stream functions | ||
3 | Copyright (C) 2003-2004 Kevin Thayer <nufan_wfk at yahoo.com> | ||
4 | Copyright (C) 2005-2007 Hans Verkuil <hverkuil@xs4all.nl> | ||
5 | |||
6 | This program is free software; you can redistribute it and/or modify | ||
7 | it under the terms of the GNU General Public License as published by | ||
8 | the Free Software Foundation; either version 2 of the License, or | ||
9 | (at your option) any later version. | ||
10 | |||
11 | This program is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program; if not, write to the Free Software | ||
18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | */ | ||
20 | |||
21 | int ivtv_streams_setup(struct ivtv *itv); | ||
22 | void ivtv_streams_cleanup(struct ivtv *itv); | ||
23 | |||
24 | /* Capture related */ | ||
25 | int ivtv_start_v4l2_encode_stream(struct ivtv_stream *s); | ||
26 | int ivtv_stop_v4l2_encode_stream(struct ivtv_stream *s, int gop_end); | ||
27 | int ivtv_start_v4l2_decode_stream(struct ivtv_stream *s, int gop_offset); | ||
28 | int ivtv_stop_v4l2_decode_stream(struct ivtv_stream *s, int flags, u64 pts); | ||
29 | |||
30 | void ivtv_stop_all_captures(struct ivtv *itv); | ||
31 | int ivtv_passthrough_mode(struct ivtv *itv, int enable); | ||
diff --git a/drivers/media/video/ivtv/ivtv-udma.c b/drivers/media/video/ivtv/ivtv-udma.c new file mode 100644 index 000000000000..bd642e1aafc3 --- /dev/null +++ b/drivers/media/video/ivtv/ivtv-udma.c | |||
@@ -0,0 +1,200 @@ | |||
1 | /* | ||
2 | User DMA | ||
3 | |||
4 | Copyright (C) 2003-2004 Kevin Thayer <nufan_wfk at yahoo.com> | ||
5 | Copyright (C) 2004 Chris Kennedy <c@groovy.org> | ||
6 | Copyright (C) 2005-2007 Hans Verkuil <hverkuil@xs4all.nl> | ||
7 | |||
8 | 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 | the Free Software Foundation; either version 2 of the License, or | ||
11 | (at your option) any later version. | ||
12 | |||
13 | This program is distributed in the hope that it will be useful, | ||
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | GNU General Public License for more details. | ||
17 | |||
18 | You should have received a copy of the GNU General Public License | ||
19 | along with this program; if not, write to the Free Software | ||
20 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
21 | */ | ||
22 | |||
23 | #include "ivtv-driver.h" | ||
24 | #include "ivtv-streams.h" | ||
25 | #include "ivtv-udma.h" | ||
26 | |||
27 | void ivtv_udma_get_page_info(struct ivtv_dma_page_info *dma_page, unsigned long first, unsigned long size) | ||
28 | { | ||
29 | dma_page->uaddr = first & PAGE_MASK; | ||
30 | dma_page->offset = first & ~PAGE_MASK; | ||
31 | dma_page->tail = 1 + ((first+size-1) & ~PAGE_MASK); | ||
32 | dma_page->first = (first & PAGE_MASK) >> PAGE_SHIFT; | ||
33 | dma_page->last = ((first+size-1) & PAGE_MASK) >> PAGE_SHIFT; | ||
34 | dma_page->page_count = dma_page->last - dma_page->first + 1; | ||
35 | if (dma_page->page_count == 1) dma_page->tail -= dma_page->offset; | ||
36 | } | ||
37 | |||
38 | int ivtv_udma_fill_sg_list (struct ivtv_user_dma *dma, struct ivtv_dma_page_info *dma_page, int map_offset) | ||
39 | { | ||
40 | int i, offset; | ||
41 | |||
42 | offset = dma_page->offset; | ||
43 | |||
44 | /* Fill SG Array with new values */ | ||
45 | for (i = 0; i < dma_page->page_count; i++) { | ||
46 | if (i == dma_page->page_count - 1) { | ||
47 | dma->SGlist[map_offset].length = dma_page->tail; | ||
48 | } | ||
49 | else { | ||
50 | dma->SGlist[map_offset].length = PAGE_SIZE - offset; | ||
51 | } | ||
52 | dma->SGlist[map_offset].offset = offset; | ||
53 | dma->SGlist[map_offset].page = dma->map[map_offset]; | ||
54 | offset = 0; | ||
55 | map_offset++; | ||
56 | } | ||
57 | return map_offset; | ||
58 | } | ||
59 | |||
60 | void ivtv_udma_fill_sg_array (struct ivtv_user_dma *dma, u32 buffer_offset, u32 buffer_offset_2, u32 split) { | ||
61 | int i; | ||
62 | struct scatterlist *sg; | ||
63 | |||
64 | for (i = 0, sg = dma->SGlist; i < dma->SG_length; i++, sg++) { | ||
65 | dma->SGarray[i].size = cpu_to_le32(sg_dma_len(sg)); | ||
66 | dma->SGarray[i].src = cpu_to_le32(sg_dma_address(sg)); | ||
67 | dma->SGarray[i].dst = cpu_to_le32(buffer_offset); | ||
68 | buffer_offset += sg_dma_len(sg); | ||
69 | |||
70 | split -= sg_dma_len(sg); | ||
71 | if (split == 0) | ||
72 | buffer_offset = buffer_offset_2; | ||
73 | } | ||
74 | } | ||
75 | |||
76 | /* User DMA Buffers */ | ||
77 | void ivtv_udma_alloc(struct ivtv *itv) | ||
78 | { | ||
79 | if (itv->udma.SG_handle == 0) { | ||
80 | /* Map DMA Page Array Buffer */ | ||
81 | itv->udma.SG_handle = pci_map_single(itv->dev, itv->udma.SGarray, | ||
82 | sizeof(itv->udma.SGarray), PCI_DMA_TODEVICE); | ||
83 | ivtv_udma_sync_for_cpu(itv); | ||
84 | } | ||
85 | } | ||
86 | |||
87 | int ivtv_udma_setup(struct ivtv *itv, unsigned long ivtv_dest_addr, | ||
88 | void __user *userbuf, int size_in_bytes) | ||
89 | { | ||
90 | struct ivtv_dma_page_info user_dma; | ||
91 | struct ivtv_user_dma *dma = &itv->udma; | ||
92 | int err; | ||
93 | |||
94 | IVTV_DEBUG_DMA("ivtv_udma_setup, dst: 0x%08x\n", (unsigned int)ivtv_dest_addr); | ||
95 | |||
96 | /* Still in USE */ | ||
97 | if (dma->SG_length || dma->page_count) { | ||
98 | IVTV_DEBUG_WARN("ivtv_udma_setup: SG_length %d page_count %d still full?\n", | ||
99 | dma->SG_length, dma->page_count); | ||
100 | return -EBUSY; | ||
101 | } | ||
102 | |||
103 | ivtv_udma_get_page_info(&user_dma, (unsigned long)userbuf, size_in_bytes); | ||
104 | |||
105 | if (user_dma.page_count <= 0) { | ||
106 | IVTV_DEBUG_WARN("ivtv_udma_setup: Error %d page_count from %d bytes %d offset\n", | ||
107 | user_dma.page_count, size_in_bytes, user_dma.offset); | ||
108 | return -EINVAL; | ||
109 | } | ||
110 | |||
111 | /* Get user pages for DMA Xfer */ | ||
112 | down_read(¤t->mm->mmap_sem); | ||
113 | err = get_user_pages(current, current->mm, | ||
114 | user_dma.uaddr, user_dma.page_count, 0, 1, dma->map, NULL); | ||
115 | up_read(¤t->mm->mmap_sem); | ||
116 | |||
117 | if (user_dma.page_count != err) { | ||
118 | IVTV_DEBUG_WARN("failed to map user pages, returned %d instead of %d\n", | ||
119 | err, user_dma.page_count); | ||
120 | return -EINVAL; | ||
121 | } | ||
122 | |||
123 | dma->page_count = user_dma.page_count; | ||
124 | |||
125 | /* Fill SG List with new values */ | ||
126 | ivtv_udma_fill_sg_list(dma, &user_dma, 0); | ||
127 | |||
128 | /* Map SG List */ | ||
129 | dma->SG_length = pci_map_sg(itv->dev, dma->SGlist, dma->page_count, PCI_DMA_TODEVICE); | ||
130 | |||
131 | /* Fill SG Array with new values */ | ||
132 | ivtv_udma_fill_sg_array (dma, ivtv_dest_addr, 0, -1); | ||
133 | |||
134 | /* Tag SG Array with Interrupt Bit */ | ||
135 | dma->SGarray[dma->SG_length - 1].size |= cpu_to_le32(0x80000000); | ||
136 | |||
137 | ivtv_udma_sync_for_device(itv); | ||
138 | return dma->page_count; | ||
139 | } | ||
140 | |||
141 | void ivtv_udma_unmap(struct ivtv *itv) | ||
142 | { | ||
143 | struct ivtv_user_dma *dma = &itv->udma; | ||
144 | int i; | ||
145 | |||
146 | IVTV_DEBUG_INFO("ivtv_unmap_user_dma\n"); | ||
147 | |||
148 | /* Nothing to free */ | ||
149 | if (dma->page_count == 0) | ||
150 | return; | ||
151 | |||
152 | /* Unmap Scatterlist */ | ||
153 | if (dma->SG_length) { | ||
154 | pci_unmap_sg(itv->dev, dma->SGlist, dma->page_count, PCI_DMA_TODEVICE); | ||
155 | dma->SG_length = 0; | ||
156 | } | ||
157 | /* sync DMA */ | ||
158 | ivtv_udma_sync_for_cpu(itv); | ||
159 | |||
160 | /* Release User Pages */ | ||
161 | for (i = 0; i < dma->page_count; i++) { | ||
162 | put_page(dma->map[i]); | ||
163 | } | ||
164 | dma->page_count = 0; | ||
165 | } | ||
166 | |||
167 | void ivtv_udma_free(struct ivtv *itv) | ||
168 | { | ||
169 | /* Unmap SG Array */ | ||
170 | if (itv->udma.SG_handle) { | ||
171 | pci_unmap_single(itv->dev, itv->udma.SG_handle, | ||
172 | sizeof(itv->udma.SGarray), PCI_DMA_TODEVICE); | ||
173 | } | ||
174 | |||
175 | /* Unmap Scatterlist */ | ||
176 | if (itv->udma.SG_length) { | ||
177 | pci_unmap_sg(itv->dev, itv->udma.SGlist, itv->udma.page_count, PCI_DMA_TODEVICE); | ||
178 | } | ||
179 | } | ||
180 | |||
181 | void ivtv_udma_start(struct ivtv *itv) | ||
182 | { | ||
183 | IVTV_DEBUG_DMA("start UDMA\n"); | ||
184 | write_reg(itv->udma.SG_handle, IVTV_REG_DECDMAADDR); | ||
185 | write_reg_sync(read_reg(IVTV_REG_DMAXFER) | 0x01, IVTV_REG_DMAXFER); | ||
186 | set_bit(IVTV_F_I_DMA, &itv->i_flags); | ||
187 | set_bit(IVTV_F_I_UDMA, &itv->i_flags); | ||
188 | } | ||
189 | |||
190 | void ivtv_udma_prepare(struct ivtv *itv) | ||
191 | { | ||
192 | unsigned long flags; | ||
193 | |||
194 | spin_lock_irqsave(&itv->dma_reg_lock, flags); | ||
195 | if (!test_bit(IVTV_F_I_DMA, &itv->i_flags)) | ||
196 | ivtv_udma_start(itv); | ||
197 | else | ||
198 | set_bit(IVTV_F_I_UDMA_PENDING, &itv->i_flags); | ||
199 | spin_unlock_irqrestore(&itv->dma_reg_lock, flags); | ||
200 | } | ||
diff --git a/drivers/media/video/ivtv/ivtv-udma.h b/drivers/media/video/ivtv/ivtv-udma.h new file mode 100644 index 000000000000..e131bccedec0 --- /dev/null +++ b/drivers/media/video/ivtv/ivtv-udma.h | |||
@@ -0,0 +1,43 @@ | |||
1 | /* | ||
2 | Copyright (C) 2003-2004 Kevin Thayer <nufan_wfk at yahoo.com> | ||
3 | Copyright (C) 2004 Chris Kennedy <c@groovy.org> | ||
4 | Copyright (C) 2006-2007 Hans Verkuil <hverkuil@xs4all.nl> | ||
5 | |||
6 | This program is free software; you can redistribute it and/or modify | ||
7 | it under the terms of the GNU General Public License as published by | ||
8 | the Free Software Foundation; either version 2 of the License, or | ||
9 | (at your option) any later version. | ||
10 | |||
11 | This program is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program; if not, write to the Free Software | ||
18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | */ | ||
20 | |||
21 | /* User DMA functions */ | ||
22 | void ivtv_udma_get_page_info(struct ivtv_dma_page_info *dma_page, unsigned long first, unsigned long size); | ||
23 | int ivtv_udma_fill_sg_list(struct ivtv_user_dma *dma, struct ivtv_dma_page_info *dma_page, int map_offset); | ||
24 | void ivtv_udma_fill_sg_array(struct ivtv_user_dma *dma, u32 buffer_offset, u32 buffer_offset_2, u32 split); | ||
25 | int ivtv_udma_setup(struct ivtv *itv, unsigned long ivtv_dest_addr, | ||
26 | void __user *userbuf, int size_in_bytes); | ||
27 | void ivtv_udma_unmap(struct ivtv *itv); | ||
28 | void ivtv_udma_free(struct ivtv *itv); | ||
29 | void ivtv_udma_alloc(struct ivtv *itv); | ||
30 | void ivtv_udma_prepare(struct ivtv *itv); | ||
31 | void ivtv_udma_start(struct ivtv *itv); | ||
32 | |||
33 | static inline void ivtv_udma_sync_for_device(struct ivtv *itv) | ||
34 | { | ||
35 | pci_dma_sync_single_for_device((struct pci_dev *)itv->dev, itv->udma.SG_handle, | ||
36 | sizeof(itv->udma.SGarray), PCI_DMA_TODEVICE); | ||
37 | } | ||
38 | |||
39 | static inline void ivtv_udma_sync_for_cpu(struct ivtv *itv) | ||
40 | { | ||
41 | pci_dma_sync_single_for_cpu((struct pci_dev *)itv->dev, itv->udma.SG_handle, | ||
42 | sizeof(itv->udma.SGarray), PCI_DMA_TODEVICE); | ||
43 | } | ||
diff --git a/drivers/media/video/ivtv/ivtv-vbi.c b/drivers/media/video/ivtv/ivtv-vbi.c new file mode 100644 index 000000000000..b53ca508dacc --- /dev/null +++ b/drivers/media/video/ivtv/ivtv-vbi.c | |||
@@ -0,0 +1,545 @@ | |||
1 | /* | ||
2 | Vertical Blank Interval support functions | ||
3 | Copyright (C) 2004-2007 Hans Verkuil <hverkuil@xs4all.nl> | ||
4 | |||
5 | This program is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published by | ||
7 | the Free Software Foundation; either version 2 of the License, or | ||
8 | (at your option) any later version. | ||
9 | |||
10 | This program is distributed in the hope that it will be useful, | ||
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | GNU General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with this program; if not, write to the Free Software | ||
17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
18 | */ | ||
19 | |||
20 | #include "ivtv-driver.h" | ||
21 | #include "ivtv-video.h" | ||
22 | #include "ivtv-vbi.h" | ||
23 | #include "ivtv-ioctl.h" | ||
24 | #include "ivtv-queue.h" | ||
25 | |||
26 | static int odd_parity(u8 c) | ||
27 | { | ||
28 | c ^= (c >> 4); | ||
29 | c ^= (c >> 2); | ||
30 | c ^= (c >> 1); | ||
31 | |||
32 | return c & 1; | ||
33 | } | ||
34 | |||
35 | void vbi_schedule_work(struct ivtv *itv) | ||
36 | { | ||
37 | queue_work(itv->vbi.work_queues, &itv->vbi.work_queue); | ||
38 | } | ||
39 | |||
40 | static void passthrough_vbi_data(struct ivtv *itv, int cnt) | ||
41 | { | ||
42 | int wss = 0; | ||
43 | u8 cc[4] = { 0x80, 0x80, 0x80, 0x80 }; | ||
44 | u8 vps[13]; | ||
45 | int found_cc = 0; | ||
46 | int found_wss = 0; | ||
47 | int found_vps = 0; | ||
48 | int cc_pos = itv->vbi.cc_pos; | ||
49 | int i; | ||
50 | |||
51 | for (i = 0; i < cnt; i++) { | ||
52 | struct v4l2_sliced_vbi_data *d = itv->vbi.sliced_dec_data + i; | ||
53 | |||
54 | if (d->id == V4L2_SLICED_CAPTION_525 && d->line == 21) { | ||
55 | found_cc = 1; | ||
56 | if (d->field) { | ||
57 | cc[2] = d->data[0]; | ||
58 | cc[3] = d->data[1]; | ||
59 | } else { | ||
60 | cc[0] = d->data[0]; | ||
61 | cc[1] = d->data[1]; | ||
62 | } | ||
63 | } | ||
64 | else if (d->id == V4L2_SLICED_VPS && d->line == 16 && d->field == 0) { | ||
65 | memcpy(vps, d->data, sizeof(vps)); | ||
66 | found_vps = 1; | ||
67 | } | ||
68 | else if (d->id == V4L2_SLICED_WSS_625 && d->line == 23 && d->field == 0) { | ||
69 | wss = d->data[0] | d->data[1] << 8; | ||
70 | found_wss = 1; | ||
71 | } | ||
72 | } | ||
73 | |||
74 | if (itv->vbi.wss_found != found_wss || itv->vbi.wss != wss) { | ||
75 | itv->vbi.wss = wss; | ||
76 | itv->vbi.wss_found = found_wss; | ||
77 | set_bit(IVTV_F_I_UPDATE_WSS, &itv->i_flags); | ||
78 | } | ||
79 | |||
80 | if (found_vps || itv->vbi.vps_found) { | ||
81 | itv->vbi.vps[0] = vps[2]; | ||
82 | itv->vbi.vps[1] = vps[8]; | ||
83 | itv->vbi.vps[2] = vps[9]; | ||
84 | itv->vbi.vps[3] = vps[10]; | ||
85 | itv->vbi.vps[4] = vps[11]; | ||
86 | itv->vbi.vps_found = found_vps; | ||
87 | set_bit(IVTV_F_I_UPDATE_VPS, &itv->i_flags); | ||
88 | } | ||
89 | |||
90 | if (found_cc && cc_pos < sizeof(itv->vbi.cc_data_even)) { | ||
91 | itv->vbi.cc_data_odd[cc_pos] = cc[0]; | ||
92 | itv->vbi.cc_data_odd[cc_pos + 1] = cc[1]; | ||
93 | itv->vbi.cc_data_even[cc_pos] = cc[2]; | ||
94 | itv->vbi.cc_data_even[cc_pos + 1] = cc[3]; | ||
95 | itv->vbi.cc_pos = cc_pos + 2; | ||
96 | set_bit(IVTV_F_I_UPDATE_CC, &itv->i_flags); | ||
97 | } | ||
98 | } | ||
99 | |||
100 | static void copy_vbi_data(struct ivtv *itv, int lines, u32 pts_stamp) | ||
101 | { | ||
102 | int line = 0; | ||
103 | int i; | ||
104 | u32 linemask[2] = { 0, 0 }; | ||
105 | unsigned short size; | ||
106 | static const u8 mpeg_hdr_data[] = { | ||
107 | 0x00, 0x00, 0x01, 0xba, 0x44, 0x00, 0x0c, 0x66, | ||
108 | 0x24, 0x01, 0x01, 0xd1, 0xd3, 0xfa, 0xff, 0xff, | ||
109 | 0x00, 0x00, 0x01, 0xbd, 0x00, 0x1a, 0x84, 0x80, | ||
110 | 0x07, 0x21, 0x00, 0x5d, 0x63, 0xa7, 0xff, 0xff | ||
111 | }; | ||
112 | const int sd = sizeof(mpeg_hdr_data); /* start of vbi data */ | ||
113 | int idx = itv->vbi.frame % IVTV_VBI_FRAMES; | ||
114 | u8 *dst = &itv->vbi.sliced_mpeg_data[idx][0]; | ||
115 | |||
116 | for (i = 0; i < lines; i++) { | ||
117 | int f, l; | ||
118 | |||
119 | if (itv->vbi.sliced_data[i].id == 0) | ||
120 | continue; | ||
121 | |||
122 | l = itv->vbi.sliced_data[i].line - 6; | ||
123 | f = itv->vbi.sliced_data[i].field; | ||
124 | if (f) | ||
125 | l += 18; | ||
126 | if (l < 32) | ||
127 | linemask[0] |= (1 << l); | ||
128 | else | ||
129 | linemask[1] |= (1 << (l - 32)); | ||
130 | dst[sd + 12 + line * 43] = service2vbi(itv->vbi.sliced_data[i].id); | ||
131 | memcpy(dst + sd + 12 + line * 43 + 1, itv->vbi.sliced_data[i].data, 42); | ||
132 | line++; | ||
133 | } | ||
134 | memcpy(dst, mpeg_hdr_data, sizeof(mpeg_hdr_data)); | ||
135 | if (line == 36) { | ||
136 | /* All lines are used, so there is no space for the linemask | ||
137 | (the max size of the VBI data is 36 * 43 + 4 bytes). | ||
138 | So in this case we use the magic number 'ITV0'. */ | ||
139 | memcpy(dst + sd, "ITV0", 4); | ||
140 | memcpy(dst + sd + 4, dst + sd + 12, line * 43); | ||
141 | size = 4 + ((43 * line + 3) & ~3); | ||
142 | } else { | ||
143 | memcpy(dst + sd, "itv0", 4); | ||
144 | memcpy(dst + sd + 4, &linemask[0], 8); | ||
145 | size = 12 + ((43 * line + 3) & ~3); | ||
146 | } | ||
147 | dst[4+16] = (size + 10) >> 8; | ||
148 | dst[5+16] = (size + 10) & 0xff; | ||
149 | dst[9+16] = 0x21 | ((pts_stamp >> 29) & 0x6); | ||
150 | dst[10+16] = (pts_stamp >> 22) & 0xff; | ||
151 | dst[11+16] = 1 | ((pts_stamp >> 14) & 0xff); | ||
152 | dst[12+16] = (pts_stamp >> 7) & 0xff; | ||
153 | dst[13+16] = 1 | ((pts_stamp & 0x7f) << 1); | ||
154 | itv->vbi.sliced_mpeg_size[idx] = sd + size; | ||
155 | } | ||
156 | |||
157 | static int ivtv_convert_ivtv_vbi(struct ivtv *itv, u8 *p) | ||
158 | { | ||
159 | u32 linemask[2]; | ||
160 | int i, l, id2; | ||
161 | int line = 0; | ||
162 | |||
163 | if (!memcmp(p, "itv0", 4)) { | ||
164 | memcpy(linemask, p + 4, 8); | ||
165 | p += 12; | ||
166 | } else if (!memcmp(p, "ITV0", 4)) { | ||
167 | linemask[0] = 0xffffffff; | ||
168 | linemask[1] = 0xf; | ||
169 | p += 4; | ||
170 | } else { | ||
171 | /* unknown VBI data stream */ | ||
172 | return 0; | ||
173 | } | ||
174 | for (i = 0; i < 36; i++) { | ||
175 | int err = 0; | ||
176 | |||
177 | if (i < 32 && !(linemask[0] & (1 << i))) | ||
178 | continue; | ||
179 | if (i >= 32 && !(linemask[1] & (1 << (i - 32)))) | ||
180 | continue; | ||
181 | id2 = *p & 0xf; | ||
182 | switch (id2) { | ||
183 | case IVTV_SLICED_TYPE_TELETEXT_B: | ||
184 | id2 = V4L2_SLICED_TELETEXT_B; | ||
185 | break; | ||
186 | case IVTV_SLICED_TYPE_CAPTION_525: | ||
187 | id2 = V4L2_SLICED_CAPTION_525; | ||
188 | err = !odd_parity(p[1]) || !odd_parity(p[2]); | ||
189 | break; | ||
190 | case IVTV_SLICED_TYPE_VPS: | ||
191 | id2 = V4L2_SLICED_VPS; | ||
192 | break; | ||
193 | case IVTV_SLICED_TYPE_WSS_625: | ||
194 | id2 = V4L2_SLICED_WSS_625; | ||
195 | break; | ||
196 | default: | ||
197 | id2 = 0; | ||
198 | break; | ||
199 | } | ||
200 | if (err == 0) { | ||
201 | l = (i < 18) ? i + 6 : i - 18 + 6; | ||
202 | itv->vbi.sliced_dec_data[line].line = l; | ||
203 | itv->vbi.sliced_dec_data[line].field = i >= 18; | ||
204 | itv->vbi.sliced_dec_data[line].id = id2; | ||
205 | memcpy(itv->vbi.sliced_dec_data[line].data, p + 1, 42); | ||
206 | line++; | ||
207 | } | ||
208 | p += 43; | ||
209 | } | ||
210 | while (line < 36) { | ||
211 | itv->vbi.sliced_dec_data[line].id = 0; | ||
212 | itv->vbi.sliced_dec_data[line].line = 0; | ||
213 | itv->vbi.sliced_dec_data[line].field = 0; | ||
214 | line++; | ||
215 | } | ||
216 | return line * sizeof(itv->vbi.sliced_dec_data[0]); | ||
217 | } | ||
218 | |||
219 | ssize_t ivtv_write_vbi(struct ivtv *itv, const char __user *ubuf, size_t count) | ||
220 | { | ||
221 | /* Should be a __user pointer, but sparse doesn't parse this bit correctly. */ | ||
222 | const struct v4l2_sliced_vbi_data *p = (const struct v4l2_sliced_vbi_data *)ubuf; | ||
223 | u8 cc[4] = { 0x80, 0x80, 0x80, 0x80 }; | ||
224 | int found_cc = 0; | ||
225 | int cc_pos = itv->vbi.cc_pos; | ||
226 | |||
227 | if (itv->vbi.service_set_out == 0) | ||
228 | return -EPERM; | ||
229 | |||
230 | while (count >= sizeof(struct v4l2_sliced_vbi_data)) { | ||
231 | switch (p->id) { | ||
232 | case V4L2_SLICED_CAPTION_525: | ||
233 | if (p->id == V4L2_SLICED_CAPTION_525 && | ||
234 | p->line == 21 && | ||
235 | (itv->vbi.service_set_out & | ||
236 | V4L2_SLICED_CAPTION_525) == 0) { | ||
237 | break; | ||
238 | } | ||
239 | found_cc = 1; | ||
240 | if (p->field) { | ||
241 | cc[2] = p->data[0]; | ||
242 | cc[3] = p->data[1]; | ||
243 | } else { | ||
244 | cc[0] = p->data[0]; | ||
245 | cc[1] = p->data[1]; | ||
246 | } | ||
247 | break; | ||
248 | |||
249 | case V4L2_SLICED_VPS: | ||
250 | if (p->line == 16 && p->field == 0 && | ||
251 | (itv->vbi.service_set_out & V4L2_SLICED_VPS)) { | ||
252 | itv->vbi.vps[0] = p->data[2]; | ||
253 | itv->vbi.vps[1] = p->data[8]; | ||
254 | itv->vbi.vps[2] = p->data[9]; | ||
255 | itv->vbi.vps[3] = p->data[10]; | ||
256 | itv->vbi.vps[4] = p->data[11]; | ||
257 | itv->vbi.vps_found = 1; | ||
258 | set_bit(IVTV_F_I_UPDATE_VPS, &itv->i_flags); | ||
259 | } | ||
260 | break; | ||
261 | |||
262 | case V4L2_SLICED_WSS_625: | ||
263 | if (p->line == 23 && p->field == 0 && | ||
264 | (itv->vbi.service_set_out & V4L2_SLICED_WSS_625)) { | ||
265 | /* No lock needed for WSS */ | ||
266 | itv->vbi.wss = p->data[0] | (p->data[1] << 8); | ||
267 | itv->vbi.wss_found = 1; | ||
268 | set_bit(IVTV_F_I_UPDATE_WSS, &itv->i_flags); | ||
269 | } | ||
270 | break; | ||
271 | |||
272 | default: | ||
273 | break; | ||
274 | } | ||
275 | count -= sizeof(*p); | ||
276 | p++; | ||
277 | } | ||
278 | |||
279 | if (found_cc && cc_pos < sizeof(itv->vbi.cc_data_even)) { | ||
280 | itv->vbi.cc_data_odd[cc_pos] = cc[0]; | ||
281 | itv->vbi.cc_data_odd[cc_pos + 1] = cc[1]; | ||
282 | itv->vbi.cc_data_even[cc_pos] = cc[2]; | ||
283 | itv->vbi.cc_data_even[cc_pos + 1] = cc[3]; | ||
284 | itv->vbi.cc_pos = cc_pos + 2; | ||
285 | set_bit(IVTV_F_I_UPDATE_CC, &itv->i_flags); | ||
286 | } | ||
287 | |||
288 | return (const char __user *)p - ubuf; | ||
289 | } | ||
290 | |||
291 | /* Compress raw VBI format, removes leading SAV codes and surplus space after the | ||
292 | field. | ||
293 | Returns new compressed size. */ | ||
294 | static u32 compress_raw_buf(struct ivtv *itv, u8 *buf, u32 size) | ||
295 | { | ||
296 | u32 line_size = itv->vbi.raw_decoder_line_size; | ||
297 | u32 lines = itv->vbi.count; | ||
298 | u8 sav1 = itv->vbi.raw_decoder_sav_odd_field; | ||
299 | u8 sav2 = itv->vbi.raw_decoder_sav_even_field; | ||
300 | u8 *q = buf; | ||
301 | u8 *p; | ||
302 | int i; | ||
303 | |||
304 | for (i = 0; i < lines; i++) { | ||
305 | p = buf + i * line_size; | ||
306 | |||
307 | /* Look for SAV code */ | ||
308 | if (p[0] != 0xff || p[1] || p[2] || (p[3] != sav1 && p[3] != sav2)) { | ||
309 | break; | ||
310 | } | ||
311 | memcpy(q, p + 4, line_size - 4); | ||
312 | q += line_size - 4; | ||
313 | } | ||
314 | return lines * (line_size - 4); | ||
315 | } | ||
316 | |||
317 | |||
318 | /* Compressed VBI format, all found sliced blocks put next to one another | ||
319 | Returns new compressed size */ | ||
320 | static u32 compress_sliced_buf(struct ivtv *itv, u32 line, u8 *buf, u32 size, u8 sav) | ||
321 | { | ||
322 | u32 line_size = itv->vbi.sliced_decoder_line_size; | ||
323 | struct v4l2_decode_vbi_line vbi; | ||
324 | int i; | ||
325 | |||
326 | /* find the first valid line */ | ||
327 | for (i = 0; i < size; i++, buf++) { | ||
328 | if (buf[0] == 0xff && !buf[1] && !buf[2] && buf[3] == sav) | ||
329 | break; | ||
330 | } | ||
331 | |||
332 | size -= i; | ||
333 | if (size < line_size) { | ||
334 | return line; | ||
335 | } | ||
336 | for (i = 0; i < size / line_size; i++) { | ||
337 | u8 *p = buf + i * line_size; | ||
338 | |||
339 | /* Look for SAV code */ | ||
340 | if (p[0] != 0xff || p[1] || p[2] || p[3] != sav) { | ||
341 | continue; | ||
342 | } | ||
343 | vbi.p = p + 4; | ||
344 | itv->video_dec_func(itv, VIDIOC_INT_DECODE_VBI_LINE, &vbi); | ||
345 | if (vbi.type) { | ||
346 | itv->vbi.sliced_data[line].id = vbi.type; | ||
347 | itv->vbi.sliced_data[line].field = vbi.is_second_field; | ||
348 | itv->vbi.sliced_data[line].line = vbi.line; | ||
349 | memcpy(itv->vbi.sliced_data[line].data, vbi.p, 42); | ||
350 | line++; | ||
351 | } | ||
352 | } | ||
353 | return line; | ||
354 | } | ||
355 | |||
356 | void ivtv_process_vbi_data(struct ivtv *itv, struct ivtv_buffer *buf, | ||
357 | u64 pts_stamp, int streamtype) | ||
358 | { | ||
359 | u8 *p = (u8 *) buf->buf; | ||
360 | u32 size = buf->bytesused; | ||
361 | int y; | ||
362 | |||
363 | /* Raw VBI data */ | ||
364 | if (streamtype == IVTV_ENC_STREAM_TYPE_VBI && itv->vbi.sliced_in->service_set == 0) { | ||
365 | u8 type; | ||
366 | |||
367 | ivtv_buf_swap(buf); | ||
368 | |||
369 | type = p[3]; | ||
370 | |||
371 | size = buf->bytesused = compress_raw_buf(itv, p, size); | ||
372 | |||
373 | /* second field of the frame? */ | ||
374 | if (type == itv->vbi.raw_decoder_sav_even_field) { | ||
375 | /* Dirty hack needed for backwards | ||
376 | compatibility of old VBI software. */ | ||
377 | p += size - 4; | ||
378 | memcpy(p, &itv->vbi.frame, 4); | ||
379 | itv->vbi.frame++; | ||
380 | } | ||
381 | return; | ||
382 | } | ||
383 | |||
384 | /* Sliced VBI data with data insertion */ | ||
385 | if (streamtype == IVTV_ENC_STREAM_TYPE_VBI) { | ||
386 | int lines; | ||
387 | |||
388 | ivtv_buf_swap(buf); | ||
389 | |||
390 | /* first field */ | ||
391 | lines = compress_sliced_buf(itv, 0, p, size / 2, | ||
392 | itv->vbi.sliced_decoder_sav_odd_field); | ||
393 | /* second field */ | ||
394 | /* experimentation shows that the second half does not always begin | ||
395 | at the exact address. So start a bit earlier (hence 32). */ | ||
396 | lines = compress_sliced_buf(itv, lines, p + size / 2 - 32, size / 2 + 32, | ||
397 | itv->vbi.sliced_decoder_sav_even_field); | ||
398 | /* always return at least one empty line */ | ||
399 | if (lines == 0) { | ||
400 | itv->vbi.sliced_data[0].id = 0; | ||
401 | itv->vbi.sliced_data[0].line = 0; | ||
402 | itv->vbi.sliced_data[0].field = 0; | ||
403 | lines = 1; | ||
404 | } | ||
405 | buf->bytesused = size = lines * sizeof(itv->vbi.sliced_data[0]); | ||
406 | memcpy(p, &itv->vbi.sliced_data[0], size); | ||
407 | |||
408 | if (itv->vbi.insert_mpeg) { | ||
409 | copy_vbi_data(itv, lines, pts_stamp); | ||
410 | } | ||
411 | itv->vbi.frame++; | ||
412 | return; | ||
413 | } | ||
414 | |||
415 | /* Sliced VBI re-inserted from an MPEG stream */ | ||
416 | if (streamtype == IVTV_DEC_STREAM_TYPE_VBI) { | ||
417 | /* If the size is not 4-byte aligned, then the starting address | ||
418 | for the swapping is also shifted. After swapping the data the | ||
419 | real start address of the VBI data is exactly 4 bytes after the | ||
420 | original start. It's a bit fiddly but it works like a charm. | ||
421 | Non-4-byte alignment happens when an lseek is done on the input | ||
422 | mpeg file to a non-4-byte aligned position. So on arrival here | ||
423 | the VBI data is also non-4-byte aligned. */ | ||
424 | int offset = size & 3; | ||
425 | int cnt; | ||
426 | |||
427 | if (offset) { | ||
428 | p += 4 - offset; | ||
429 | } | ||
430 | /* Swap Buffer */ | ||
431 | for (y = 0; y < size; y += 4) { | ||
432 | swab32s((u32 *)(p + y)); | ||
433 | } | ||
434 | |||
435 | cnt = ivtv_convert_ivtv_vbi(itv, p + offset); | ||
436 | memcpy(buf->buf, itv->vbi.sliced_dec_data, cnt); | ||
437 | buf->bytesused = cnt; | ||
438 | |||
439 | passthrough_vbi_data(itv, cnt / sizeof(itv->vbi.sliced_dec_data[0])); | ||
440 | return; | ||
441 | } | ||
442 | } | ||
443 | |||
444 | void ivtv_disable_vbi(struct ivtv *itv) | ||
445 | { | ||
446 | clear_bit(IVTV_F_I_UPDATE_WSS, &itv->i_flags); | ||
447 | clear_bit(IVTV_F_I_UPDATE_VPS, &itv->i_flags); | ||
448 | clear_bit(IVTV_F_I_UPDATE_CC, &itv->i_flags); | ||
449 | ivtv_set_wss(itv, 0, 0); | ||
450 | ivtv_set_cc(itv, 0, 0, 0, 0, 0); | ||
451 | ivtv_set_vps(itv, 0, 0, 0, 0, 0, 0); | ||
452 | itv->vbi.vps_found = itv->vbi.wss_found = 0; | ||
453 | itv->vbi.wss = 0; | ||
454 | itv->vbi.cc_pos = 0; | ||
455 | } | ||
456 | |||
457 | void vbi_work_handler(struct work_struct *work) | ||
458 | { | ||
459 | struct vbi_info *info = container_of(work, struct vbi_info, work_queue); | ||
460 | struct ivtv *itv = container_of(info, struct ivtv, vbi); | ||
461 | struct v4l2_sliced_vbi_data data; | ||
462 | DEFINE_WAIT(wait); | ||
463 | |||
464 | /* Lock */ | ||
465 | if (itv->output_mode == OUT_PASSTHROUGH) { | ||
466 | /* Note: currently only the saa7115 is used in a PVR350, | ||
467 | so these commands are for now saa7115 specific. */ | ||
468 | if (itv->is_50hz) { | ||
469 | data.id = V4L2_SLICED_WSS_625; | ||
470 | data.field = 0; | ||
471 | |||
472 | if (itv->video_dec_func(itv, VIDIOC_INT_G_VBI_DATA, &data) == 0) { | ||
473 | ivtv_set_wss(itv, 1, data.data[0] & 0xf); | ||
474 | itv->vbi.wss_no_update = 0; | ||
475 | } else if (itv->vbi.wss_no_update == 4) { | ||
476 | ivtv_set_wss(itv, 1, 0x8); /* 4x3 full format */ | ||
477 | } else { | ||
478 | itv->vbi.wss_no_update++; | ||
479 | } | ||
480 | } | ||
481 | else { | ||
482 | u8 c1 = 0, c2 = 0, c3 = 0, c4 = 0; | ||
483 | int mode = 0; | ||
484 | |||
485 | data.id = V4L2_SLICED_CAPTION_525; | ||
486 | data.field = 0; | ||
487 | if (itv->video_dec_func(itv, VIDIOC_INT_G_VBI_DATA, &data) == 0) { | ||
488 | mode |= 1; | ||
489 | c1 = data.data[0]; | ||
490 | c2 = data.data[1]; | ||
491 | } | ||
492 | data.field = 1; | ||
493 | if (itv->video_dec_func(itv, VIDIOC_INT_G_VBI_DATA, &data) == 0) { | ||
494 | mode |= 2; | ||
495 | c3 = data.data[0]; | ||
496 | c4 = data.data[1]; | ||
497 | } | ||
498 | if (mode) { | ||
499 | itv->vbi.cc_no_update = 0; | ||
500 | ivtv_set_cc(itv, mode, c1, c2, c3, c4); | ||
501 | } else if (itv->vbi.cc_no_update == 4) { | ||
502 | ivtv_set_cc(itv, 0, 0, 0, 0, 0); | ||
503 | } else { | ||
504 | itv->vbi.cc_no_update++; | ||
505 | } | ||
506 | } | ||
507 | return; | ||
508 | } | ||
509 | |||
510 | if (test_and_clear_bit(IVTV_F_I_UPDATE_WSS, &itv->i_flags)) { | ||
511 | /* Lock */ | ||
512 | ivtv_set_wss(itv, itv->vbi.wss_found, itv->vbi.wss & 0xf); | ||
513 | } | ||
514 | |||
515 | if (test_and_clear_bit(IVTV_F_I_UPDATE_CC, &itv->i_flags)) { | ||
516 | if (itv->vbi.cc_pos == 0) { | ||
517 | ivtv_set_cc(itv, 3, 0x80, 0x80, 0x80, 0x80); | ||
518 | } | ||
519 | while (itv->vbi.cc_pos) { | ||
520 | u8 cc_odd0 = itv->vbi.cc_data_odd[0]; | ||
521 | u8 cc_odd1 = itv->vbi.cc_data_odd[1]; | ||
522 | u8 cc_even0 = itv->vbi.cc_data_even[0]; | ||
523 | u8 cc_even1 = itv->vbi.cc_data_even[1]; | ||
524 | |||
525 | memcpy(itv->vbi.cc_data_odd, itv->vbi.cc_data_odd + 2, sizeof(itv->vbi.cc_data_odd) - 2); | ||
526 | memcpy(itv->vbi.cc_data_even, itv->vbi.cc_data_even + 2, sizeof(itv->vbi.cc_data_even) - 2); | ||
527 | itv->vbi.cc_pos -= 2; | ||
528 | if (itv->vbi.cc_pos && cc_odd0 == 0x80 && cc_odd1 == 0x80) | ||
529 | continue; | ||
530 | |||
531 | /* Send to Saa7127 */ | ||
532 | ivtv_set_cc(itv, 3, cc_odd0, cc_odd1, cc_even0, cc_even1); | ||
533 | if (itv->vbi.cc_pos == 0) | ||
534 | set_bit(IVTV_F_I_UPDATE_CC, &itv->i_flags); | ||
535 | break; | ||
536 | } | ||
537 | } | ||
538 | |||
539 | if (test_and_clear_bit(IVTV_F_I_UPDATE_VPS, &itv->i_flags)) { | ||
540 | /* Lock */ | ||
541 | ivtv_set_vps(itv, itv->vbi.vps_found, | ||
542 | itv->vbi.vps[0], itv->vbi.vps[1], | ||
543 | itv->vbi.vps[2], itv->vbi.vps[3], itv->vbi.vps[4]); | ||
544 | } | ||
545 | } | ||
diff --git a/drivers/media/video/ivtv/ivtv-vbi.h b/drivers/media/video/ivtv/ivtv-vbi.h new file mode 100644 index 000000000000..c897e9bd4f92 --- /dev/null +++ b/drivers/media/video/ivtv/ivtv-vbi.h | |||
@@ -0,0 +1,27 @@ | |||
1 | /* | ||
2 | Vertical Blank Interval support functions | ||
3 | Copyright (C) 2004-2007 Hans Verkuil <hverkuil@xs4all.nl> | ||
4 | |||
5 | This program is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published by | ||
7 | the Free Software Foundation; either version 2 of the License, or | ||
8 | (at your option) any later version. | ||
9 | |||
10 | This program is distributed in the hope that it will be useful, | ||
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | GNU General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with this program; if not, write to the Free Software | ||
17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
18 | */ | ||
19 | |||
20 | ssize_t ivtv_write_vbi(struct ivtv *itv, const char __user *ubuf, size_t count); | ||
21 | void ivtv_process_vbi_data(struct ivtv *itv, struct ivtv_buffer *buf, | ||
22 | u64 pts_stamp, int streamtype); | ||
23 | int ivtv_used_line(struct ivtv *itv, int line, int field); | ||
24 | void ivtv_disable_vbi(struct ivtv *itv); | ||
25 | void ivtv_set_vbi(unsigned long arg); | ||
26 | void vbi_work_handler(struct work_struct *work); | ||
27 | void vbi_schedule_work(struct ivtv *itv); | ||
diff --git a/drivers/media/video/ivtv/ivtv-version.h b/drivers/media/video/ivtv/ivtv-version.h new file mode 100644 index 000000000000..85530a3cd369 --- /dev/null +++ b/drivers/media/video/ivtv/ivtv-version.h | |||
@@ -0,0 +1,26 @@ | |||
1 | /* | ||
2 | ivtv driver version information | ||
3 | Copyright (C) 2005-2007 Hans Verkuil <hverkuil@xs4all.nl> | ||
4 | |||
5 | This program is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published by | ||
7 | the Free Software Foundation; either version 2 of the License, or | ||
8 | (at your option) any later version. | ||
9 | |||
10 | This program is distributed in the hope that it will be useful, | ||
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | GNU General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with this program; if not, write to the Free Software | ||
17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
18 | */ | ||
19 | |||
20 | #define IVTV_DRIVER_NAME "ivtv" | ||
21 | #define IVTV_DRIVER_VERSION_MAJOR 1 | ||
22 | #define IVTV_DRIVER_VERSION_MINOR 0 | ||
23 | #define IVTV_DRIVER_VERSION_PATCHLEVEL 0 | ||
24 | |||
25 | #define IVTV_VERSION __stringify(IVTV_DRIVER_VERSION_MAJOR) "." __stringify(IVTV_DRIVER_VERSION_MINOR) "." __stringify(IVTV_DRIVER_VERSION_PATCHLEVEL) | ||
26 | #define IVTV_DRIVER_VERSION KERNEL_VERSION(IVTV_DRIVER_VERSION_MAJOR,IVTV_DRIVER_VERSION_MINOR,IVTV_DRIVER_VERSION_PATCHLEVEL) | ||
diff --git a/drivers/media/video/ivtv/ivtv-video.c b/drivers/media/video/ivtv/ivtv-video.c new file mode 100644 index 000000000000..77e42d13cdee --- /dev/null +++ b/drivers/media/video/ivtv/ivtv-video.c | |||
@@ -0,0 +1,150 @@ | |||
1 | /* | ||
2 | saa7127 interface functions | ||
3 | Copyright (C) 2004-2007 Hans Verkuil <hverkuil@xs4all.nl> | ||
4 | |||
5 | This program is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published by | ||
7 | the Free Software Foundation; either version 2 of the License, or | ||
8 | (at your option) any later version. | ||
9 | |||
10 | This program is distributed in the hope that it will be useful, | ||
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | GNU General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with this program; if not, write to the Free Software | ||
17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
18 | */ | ||
19 | |||
20 | #include "ivtv-driver.h" | ||
21 | #include "ivtv-video.h" | ||
22 | #include "ivtv-i2c.h" | ||
23 | #include "ivtv-gpio.h" | ||
24 | #include "ivtv-cards.h" | ||
25 | #include <media/upd64031a.h> | ||
26 | #include <media/upd64083.h> | ||
27 | |||
28 | void ivtv_set_vps(struct ivtv *itv, int enabled, u8 vps1, u8 vps2, u8 vps3, | ||
29 | u8 vps4, u8 vps5) | ||
30 | { | ||
31 | struct v4l2_sliced_vbi_data data; | ||
32 | |||
33 | if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) | ||
34 | return; | ||
35 | data.id = V4L2_SLICED_VPS; | ||
36 | data.field = 0; | ||
37 | data.line = enabled ? 16 : 0; | ||
38 | data.data[4] = vps1; | ||
39 | data.data[10] = vps2; | ||
40 | data.data[11] = vps3; | ||
41 | data.data[12] = vps4; | ||
42 | data.data[13] = vps5; | ||
43 | ivtv_saa7127(itv, VIDIOC_INT_S_VBI_DATA, &data); | ||
44 | } | ||
45 | |||
46 | void ivtv_set_cc(struct ivtv *itv, int mode, u8 cc1, u8 cc2, u8 cc3, u8 cc4) | ||
47 | { | ||
48 | struct v4l2_sliced_vbi_data data; | ||
49 | |||
50 | if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) | ||
51 | return; | ||
52 | data.id = V4L2_SLICED_CAPTION_525; | ||
53 | data.field = 0; | ||
54 | data.line = (mode & 1) ? 21 : 0; | ||
55 | data.data[0] = cc1; | ||
56 | data.data[1] = cc2; | ||
57 | ivtv_saa7127(itv, VIDIOC_INT_S_VBI_DATA, &data); | ||
58 | data.field = 1; | ||
59 | data.line = (mode & 2) ? 21 : 0; | ||
60 | data.data[0] = cc3; | ||
61 | data.data[1] = cc4; | ||
62 | ivtv_saa7127(itv, VIDIOC_INT_S_VBI_DATA, &data); | ||
63 | } | ||
64 | |||
65 | void ivtv_set_wss(struct ivtv *itv, int enabled, int mode) | ||
66 | { | ||
67 | struct v4l2_sliced_vbi_data data; | ||
68 | |||
69 | if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) | ||
70 | return; | ||
71 | /* When using a 50 Hz system, always turn on the | ||
72 | wide screen signal with 4x3 ratio as the default. | ||
73 | Turning this signal on and off can confuse certain | ||
74 | TVs. As far as I can tell there is no reason not to | ||
75 | transmit this signal. */ | ||
76 | if ((itv->std & V4L2_STD_625_50) && !enabled) { | ||
77 | enabled = 1; | ||
78 | mode = 0x08; /* 4x3 full format */ | ||
79 | } | ||
80 | data.id = V4L2_SLICED_WSS_625; | ||
81 | data.field = 0; | ||
82 | data.line = enabled ? 23 : 0; | ||
83 | data.data[0] = mode & 0xff; | ||
84 | data.data[1] = (mode >> 8) & 0xff; | ||
85 | ivtv_saa7127(itv, VIDIOC_INT_S_VBI_DATA, &data); | ||
86 | } | ||
87 | |||
88 | void ivtv_encoder_enable(struct ivtv *itv, int enabled) | ||
89 | { | ||
90 | if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) { | ||
91 | ivtv_saa7127(itv, enabled ? VIDIOC_STREAMON : VIDIOC_STREAMOFF, | ||
92 | &enabled); | ||
93 | } | ||
94 | } | ||
95 | |||
96 | void ivtv_video_set_io(struct ivtv *itv) | ||
97 | { | ||
98 | struct v4l2_routing route; | ||
99 | int inp = itv->active_input; | ||
100 | u32 type; | ||
101 | |||
102 | route.input = itv->card->video_inputs[inp].video_input; | ||
103 | route.output = 0; | ||
104 | itv->video_dec_func(itv, VIDIOC_INT_S_VIDEO_ROUTING, &route); | ||
105 | |||
106 | type = itv->card->video_inputs[inp].video_type; | ||
107 | |||
108 | if (type == IVTV_CARD_INPUT_VID_TUNER) { | ||
109 | route.input = 0; /* Tuner */ | ||
110 | } else if (type < IVTV_CARD_INPUT_COMPOSITE1) { | ||
111 | route.input = 2; /* S-Video */ | ||
112 | } else { | ||
113 | route.input = 1; /* Composite */ | ||
114 | } | ||
115 | |||
116 | if (itv->card->hw_video & IVTV_HW_GPIO) | ||
117 | ivtv_gpio(itv, VIDIOC_INT_S_VIDEO_ROUTING, &route); | ||
118 | |||
119 | if (itv->card->hw_video & IVTV_HW_UPD64031A) { | ||
120 | if (type == IVTV_CARD_INPUT_VID_TUNER || | ||
121 | type >= IVTV_CARD_INPUT_COMPOSITE1) { | ||
122 | /* Composite: GR on, connect to 3DYCS */ | ||
123 | route.input = UPD64031A_GR_ON | UPD64031A_3DYCS_COMPOSITE; | ||
124 | } else { | ||
125 | /* S-Video: GR bypassed, turn it off */ | ||
126 | route.input = UPD64031A_GR_OFF | UPD64031A_3DYCS_DISABLE; | ||
127 | } | ||
128 | route.input |= itv->card->gr_config; | ||
129 | |||
130 | ivtv_upd64031a(itv, VIDIOC_INT_S_VIDEO_ROUTING, &route); | ||
131 | } | ||
132 | |||
133 | if (itv->card->hw_video & IVTV_HW_UPD6408X) { | ||
134 | route.input = UPD64083_YCS_MODE; | ||
135 | if (type > IVTV_CARD_INPUT_VID_TUNER && | ||
136 | type < IVTV_CARD_INPUT_COMPOSITE1) { | ||
137 | /* S-Video uses YCNR mode and internal Y-ADC, the upd64031a | ||
138 | is not used. */ | ||
139 | route.input |= UPD64083_YCNR_MODE; | ||
140 | } | ||
141 | else if (itv->card->hw_video & IVTV_HW_UPD64031A) { | ||
142 | /* Use upd64031a output for tuner and composite(CX23416GYC only) inputs */ | ||
143 | if ((type == IVTV_CARD_INPUT_VID_TUNER)|| | ||
144 | (itv->card->type == IVTV_CARD_CX23416GYC)) { | ||
145 | route.input |= UPD64083_EXT_Y_ADC; | ||
146 | } | ||
147 | } | ||
148 | ivtv_upd64083(itv, VIDIOC_INT_S_VIDEO_ROUTING, &route); | ||
149 | } | ||
150 | } | ||
diff --git a/drivers/media/video/ivtv/ivtv-video.h b/drivers/media/video/ivtv/ivtv-video.h new file mode 100644 index 000000000000..5efedebe317b --- /dev/null +++ b/drivers/media/video/ivtv/ivtv-video.h | |||
@@ -0,0 +1,25 @@ | |||
1 | /* | ||
2 | saa7127 interface functions | ||
3 | Copyright (C) 2004-2007 Hans Verkuil <hverkuil@xs4all.nl> | ||
4 | |||
5 | This program is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published by | ||
7 | the Free Software Foundation; either version 2 of the License, or | ||
8 | (at your option) any later version. | ||
9 | |||
10 | This program is distributed in the hope that it will be useful, | ||
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | GNU General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with this program; if not, write to the Free Software | ||
17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
18 | */ | ||
19 | |||
20 | void ivtv_set_wss(struct ivtv *itv, int enabled, int mode); | ||
21 | void ivtv_set_cc(struct ivtv *itv, int mode, u8 cc1, u8 cc2, u8 cc3, u8 cc4); | ||
22 | void ivtv_set_vps(struct ivtv *itv, int enabled, u8 vps1, u8 vps2, u8 vps3, | ||
23 | u8 vps4, u8 vps5); | ||
24 | void ivtv_encoder_enable(struct ivtv *itv, int enabled); | ||
25 | void ivtv_video_set_io(struct ivtv *itv); | ||
diff --git a/drivers/media/video/ivtv/ivtv-yuv.c b/drivers/media/video/ivtv/ivtv-yuv.c new file mode 100644 index 000000000000..e49ecef93046 --- /dev/null +++ b/drivers/media/video/ivtv/ivtv-yuv.c | |||
@@ -0,0 +1,1129 @@ | |||
1 | /* | ||
2 | yuv support | ||
3 | |||
4 | Copyright (C) 2007 Ian Armstrong <ian@iarmst.demon.co.uk> | ||
5 | |||
6 | This program is free software; you can redistribute it and/or modify | ||
7 | it under the terms of the GNU General Public License as published by | ||
8 | the Free Software Foundation; either version 2 of the License, or | ||
9 | (at your option) any later version. | ||
10 | |||
11 | This program is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program; if not, write to the Free Software | ||
18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | */ | ||
20 | |||
21 | #include "ivtv-driver.h" | ||
22 | #include "ivtv-queue.h" | ||
23 | #include "ivtv-udma.h" | ||
24 | #include "ivtv-irq.h" | ||
25 | |||
26 | static int ivtv_yuv_prep_user_dma(struct ivtv *itv, struct ivtv_user_dma *dma, | ||
27 | struct ivtv_dma_frame *args) | ||
28 | { | ||
29 | struct ivtv_dma_page_info y_dma; | ||
30 | struct ivtv_dma_page_info uv_dma; | ||
31 | |||
32 | int i; | ||
33 | int y_pages, uv_pages; | ||
34 | |||
35 | unsigned long y_buffer_offset, uv_buffer_offset; | ||
36 | int y_decode_height, uv_decode_height, y_size; | ||
37 | int frame = atomic_read(&itv->yuv_info.next_fill_frame); | ||
38 | |||
39 | y_buffer_offset = IVTV_DEC_MEM_START + yuv_offset[frame]; | ||
40 | uv_buffer_offset = y_buffer_offset + IVTV_YUV_BUFFER_UV_OFFSET; | ||
41 | |||
42 | y_decode_height = uv_decode_height = args->src.height + args->src.top; | ||
43 | |||
44 | if (y_decode_height < 512-16) | ||
45 | y_buffer_offset += 720 * 16; | ||
46 | |||
47 | if (y_decode_height & 15) | ||
48 | y_decode_height = (y_decode_height + 16) & ~15; | ||
49 | |||
50 | if (uv_decode_height & 31) | ||
51 | uv_decode_height = (uv_decode_height + 32) & ~31; | ||
52 | |||
53 | y_size = 720 * y_decode_height; | ||
54 | |||
55 | /* Still in USE */ | ||
56 | if (dma->SG_length || dma->page_count) { | ||
57 | IVTV_DEBUG_WARN("prep_user_dma: SG_length %d page_count %d still full?\n", | ||
58 | dma->SG_length, dma->page_count); | ||
59 | return -EBUSY; | ||
60 | } | ||
61 | |||
62 | ivtv_udma_get_page_info (&y_dma, (unsigned long)args->y_source, 720 * y_decode_height); | ||
63 | ivtv_udma_get_page_info (&uv_dma, (unsigned long)args->uv_source, 360 * uv_decode_height); | ||
64 | |||
65 | /* Get user pages for DMA Xfer */ | ||
66 | down_read(¤t->mm->mmap_sem); | ||
67 | y_pages = get_user_pages(current, current->mm, y_dma.uaddr, y_dma.page_count, 0, 1, &dma->map[0], NULL); | ||
68 | uv_pages = get_user_pages(current, current->mm, uv_dma.uaddr, uv_dma.page_count, 0, 1, &dma->map[y_pages], NULL); | ||
69 | up_read(¤t->mm->mmap_sem); | ||
70 | |||
71 | dma->page_count = y_dma.page_count + uv_dma.page_count; | ||
72 | |||
73 | if (y_pages + uv_pages != dma->page_count) { | ||
74 | IVTV_DEBUG_WARN("failed to map user pages, returned %d instead of %d\n", | ||
75 | y_pages + uv_pages, dma->page_count); | ||
76 | |||
77 | for (i = 0; i < dma->page_count; i++) { | ||
78 | put_page(dma->map[i]); | ||
79 | } | ||
80 | dma->page_count = 0; | ||
81 | return -EINVAL; | ||
82 | } | ||
83 | |||
84 | /* Fill & map SG List */ | ||
85 | ivtv_udma_fill_sg_list (dma, &uv_dma, ivtv_udma_fill_sg_list (dma, &y_dma, 0)); | ||
86 | dma->SG_length = pci_map_sg(itv->dev, dma->SGlist, dma->page_count, PCI_DMA_TODEVICE); | ||
87 | |||
88 | /* Fill SG Array with new values */ | ||
89 | ivtv_udma_fill_sg_array (dma, y_buffer_offset, uv_buffer_offset, y_size); | ||
90 | |||
91 | /* If we've offset the y plane, ensure top area is blanked */ | ||
92 | if (args->src.height + args->src.top < 512-16) { | ||
93 | if (itv->yuv_info.blanking_dmaptr) { | ||
94 | dma->SGarray[dma->SG_length].size = cpu_to_le32(720*16); | ||
95 | dma->SGarray[dma->SG_length].src = cpu_to_le32(itv->yuv_info.blanking_dmaptr); | ||
96 | dma->SGarray[dma->SG_length].dst = cpu_to_le32(IVTV_DEC_MEM_START + yuv_offset[frame]); | ||
97 | dma->SG_length++; | ||
98 | } | ||
99 | } | ||
100 | |||
101 | /* Tag SG Array with Interrupt Bit */ | ||
102 | dma->SGarray[dma->SG_length - 1].size |= cpu_to_le32(0x80000000); | ||
103 | |||
104 | ivtv_udma_sync_for_device(itv); | ||
105 | return 0; | ||
106 | } | ||
107 | |||
108 | /* We rely on a table held in the firmware - Quick check. */ | ||
109 | int ivtv_yuv_filter_check(struct ivtv *itv) | ||
110 | { | ||
111 | int i, offset_y, offset_uv; | ||
112 | |||
113 | for (i=0, offset_y = 16, offset_uv = 4; i<16; i++, offset_y += 24, offset_uv += 12) { | ||
114 | if ((read_dec(IVTV_YUV_HORIZONTAL_FILTER_OFFSET + offset_y) != i << 16) || | ||
115 | (read_dec(IVTV_YUV_VERTICAL_FILTER_OFFSET + offset_uv) != i << 16)) { | ||
116 | IVTV_WARN ("YUV filter table not found in firmware.\n"); | ||
117 | return -1; | ||
118 | } | ||
119 | } | ||
120 | return 0; | ||
121 | } | ||
122 | |||
123 | static void ivtv_yuv_filter(struct ivtv *itv, int h_filter, int v_filter_1, int v_filter_2) | ||
124 | { | ||
125 | int filter_index, filter_line; | ||
126 | |||
127 | /* If any filter is -1, then don't update it */ | ||
128 | if (h_filter > -1) { | ||
129 | if (h_filter > 4) h_filter = 4; | ||
130 | filter_index = h_filter * 384; | ||
131 | filter_line = 0; | ||
132 | while (filter_line < 16) { | ||
133 | write_reg(read_dec(IVTV_YUV_HORIZONTAL_FILTER_OFFSET + filter_index), 0x02804); | ||
134 | write_reg(read_dec(IVTV_YUV_HORIZONTAL_FILTER_OFFSET + filter_index), 0x0281c); | ||
135 | filter_index += 4; | ||
136 | write_reg(read_dec(IVTV_YUV_HORIZONTAL_FILTER_OFFSET + filter_index), 0x02808); | ||
137 | write_reg(read_dec(IVTV_YUV_HORIZONTAL_FILTER_OFFSET + filter_index), 0x02820); | ||
138 | filter_index += 4; | ||
139 | write_reg(read_dec(IVTV_YUV_HORIZONTAL_FILTER_OFFSET + filter_index), 0x0280c); | ||
140 | write_reg(read_dec(IVTV_YUV_HORIZONTAL_FILTER_OFFSET + filter_index), 0x02824); | ||
141 | filter_index += 4; | ||
142 | write_reg(read_dec(IVTV_YUV_HORIZONTAL_FILTER_OFFSET + filter_index), 0x02810); | ||
143 | write_reg(read_dec(IVTV_YUV_HORIZONTAL_FILTER_OFFSET + filter_index), 0x02828); | ||
144 | filter_index += 4; | ||
145 | write_reg(read_dec(IVTV_YUV_HORIZONTAL_FILTER_OFFSET + filter_index), 0x02814); | ||
146 | write_reg(read_dec(IVTV_YUV_HORIZONTAL_FILTER_OFFSET + filter_index), 0x0282c); | ||
147 | filter_index += 8; | ||
148 | write_reg(0, 0x02818); | ||
149 | write_reg(0, 0x02830); | ||
150 | filter_line ++; | ||
151 | } | ||
152 | IVTV_DEBUG_YUV("h_filter -> %d\n",h_filter); | ||
153 | } | ||
154 | |||
155 | if (v_filter_1 > -1) { | ||
156 | if (v_filter_1 > 4) v_filter_1 = 4; | ||
157 | filter_index = v_filter_1 * 192; | ||
158 | filter_line = 0; | ||
159 | while (filter_line < 16) { | ||
160 | write_reg(read_dec(IVTV_YUV_VERTICAL_FILTER_OFFSET + filter_index), 0x02900); | ||
161 | filter_index += 4; | ||
162 | write_reg(read_dec(IVTV_YUV_VERTICAL_FILTER_OFFSET + filter_index), 0x02904); | ||
163 | filter_index += 8; | ||
164 | write_reg(0, 0x02908); | ||
165 | filter_line ++; | ||
166 | } | ||
167 | IVTV_DEBUG_YUV("v_filter_1 -> %d\n",v_filter_1); | ||
168 | } | ||
169 | |||
170 | if (v_filter_2 > -1) { | ||
171 | if (v_filter_2 > 4) v_filter_2 = 4; | ||
172 | filter_index = v_filter_2 * 192; | ||
173 | filter_line = 0; | ||
174 | while (filter_line < 16) { | ||
175 | write_reg(read_dec(IVTV_YUV_VERTICAL_FILTER_OFFSET + filter_index), 0x0290c); | ||
176 | filter_index += 4; | ||
177 | write_reg(read_dec(IVTV_YUV_VERTICAL_FILTER_OFFSET + filter_index), 0x02910); | ||
178 | filter_index += 8; | ||
179 | write_reg(0, 0x02914); | ||
180 | filter_line ++; | ||
181 | } | ||
182 | IVTV_DEBUG_YUV("v_filter_2 -> %d\n",v_filter_2); | ||
183 | } | ||
184 | } | ||
185 | |||
186 | static void ivtv_yuv_handle_horizontal(struct ivtv *itv, struct yuv_frame_info *window) | ||
187 | { | ||
188 | u32 reg_2834, reg_2838, reg_283c; | ||
189 | u32 reg_2844, reg_2854, reg_285c; | ||
190 | u32 reg_2864, reg_2874, reg_2890; | ||
191 | u32 reg_2870, reg_2870_base, reg_2870_offset; | ||
192 | int x_cutoff; | ||
193 | int h_filter; | ||
194 | u32 master_width; | ||
195 | |||
196 | IVTV_DEBUG_WARN( "Need to adjust to width %d src_w %d dst_w %d src_x %d dst_x %d\n", | ||
197 | window->tru_w, window->src_w, window->dst_w,window->src_x, window->dst_x); | ||
198 | |||
199 | /* How wide is the src image */ | ||
200 | x_cutoff = window->src_w + window->src_x; | ||
201 | |||
202 | /* Set the display width */ | ||
203 | reg_2834 = window->dst_w; | ||
204 | reg_2838 = reg_2834; | ||
205 | |||
206 | /* Set the display position */ | ||
207 | reg_2890 = window->dst_x; | ||
208 | |||
209 | /* Index into the image horizontally */ | ||
210 | reg_2870 = 0; | ||
211 | |||
212 | /* 2870 is normally fudged to align video coords with osd coords. | ||
213 | If running full screen, it causes an unwanted left shift | ||
214 | Remove the fudge if we almost fill the screen. | ||
215 | Gradually adjust the offset to avoid the video 'snapping' | ||
216 | left/right if it gets dragged through this region. | ||
217 | Only do this if osd is full width. */ | ||
218 | if (window->vis_w == 720) { | ||
219 | if ((window->tru_x - window->pan_x > -1) && (window->tru_x - window->pan_x <= 40) && (window->dst_w >= 680)){ | ||
220 | reg_2870 = 10 - (window->tru_x - window->pan_x) / 4; | ||
221 | } | ||
222 | else if ((window->tru_x - window->pan_x < 0) && (window->tru_x - window->pan_x >= -20) && (window->dst_w >= 660)) { | ||
223 | reg_2870 = (10 + (window->tru_x - window->pan_x) / 2); | ||
224 | } | ||
225 | |||
226 | if (window->dst_w >= window->src_w) | ||
227 | reg_2870 = reg_2870 << 16 | reg_2870; | ||
228 | else | ||
229 | reg_2870 = ((reg_2870 & ~1) << 15) | (reg_2870 & ~1); | ||
230 | } | ||
231 | |||
232 | if (window->dst_w < window->src_w) | ||
233 | reg_2870 = 0x000d000e - reg_2870; | ||
234 | else | ||
235 | reg_2870 = 0x0012000e - reg_2870; | ||
236 | |||
237 | /* We're also using 2870 to shift the image left (src_x & negative dst_x) */ | ||
238 | reg_2870_offset = (window->src_x*((window->dst_w << 21)/window->src_w))>>19; | ||
239 | |||
240 | if (window->dst_w >= window->src_w) { | ||
241 | x_cutoff &= ~1; | ||
242 | master_width = (window->src_w * 0x00200000) / (window->dst_w); | ||
243 | if (master_width * window->dst_w != window->src_w * 0x00200000) master_width ++; | ||
244 | reg_2834 = (reg_2834 << 16) | x_cutoff; | ||
245 | reg_2838 = (reg_2838 << 16) | x_cutoff; | ||
246 | reg_283c = master_width >> 2; | ||
247 | reg_2844 = master_width >> 2; | ||
248 | reg_2854 = master_width; | ||
249 | reg_285c = master_width >> 1; | ||
250 | reg_2864 = master_width >> 1; | ||
251 | |||
252 | /* We also need to factor in the scaling | ||
253 | (src_w - dst_w) / (src_w / 4) */ | ||
254 | if (window->dst_w > window->src_w) | ||
255 | reg_2870_base = ((window->dst_w - window->src_w)<<16) / (window->src_w <<14); | ||
256 | else | ||
257 | reg_2870_base = 0; | ||
258 | |||
259 | reg_2870 += (((reg_2870_offset << 14) & 0xFFFF0000) | reg_2870_offset >> 2) + (reg_2870_base << 17 | reg_2870_base); | ||
260 | reg_2874 = 0; | ||
261 | } | ||
262 | else if (window->dst_w < window->src_w / 2) { | ||
263 | master_width = (window->src_w * 0x00080000) / window->dst_w; | ||
264 | if (master_width * window->dst_w != window->src_w * 0x00080000) master_width ++; | ||
265 | reg_2834 = (reg_2834 << 16) | x_cutoff; | ||
266 | reg_2838 = (reg_2838 << 16) | x_cutoff; | ||
267 | reg_283c = master_width >> 2; | ||
268 | reg_2844 = master_width >> 1; | ||
269 | reg_2854 = master_width; | ||
270 | reg_285c = master_width >> 1; | ||
271 | reg_2864 = master_width >> 1; | ||
272 | reg_2870 += (((reg_2870_offset << 15) & 0xFFFF0000) | reg_2870_offset); | ||
273 | reg_2870 += (5 - (((window->src_w + window->src_w / 2) - 1) / window->dst_w)) << 16; | ||
274 | reg_2874 = 0x00000012; | ||
275 | } | ||
276 | else { | ||
277 | master_width = (window->src_w * 0x00100000) / window->dst_w; | ||
278 | if (master_width * window->dst_w != window->src_w * 0x00100000) master_width ++; | ||
279 | reg_2834 = (reg_2834 << 16) | x_cutoff; | ||
280 | reg_2838 = (reg_2838 << 16) | x_cutoff; | ||
281 | reg_283c = master_width >> 2; | ||
282 | reg_2844 = master_width >> 1; | ||
283 | reg_2854 = master_width; | ||
284 | reg_285c = master_width >> 1; | ||
285 | reg_2864 = master_width >> 1; | ||
286 | reg_2870 += (((reg_2870_offset << 14) & 0xFFFF0000) | reg_2870_offset >> 1); | ||
287 | reg_2870 += (5 - (((window->src_w * 3) - 1) / window->dst_w)) << 16; | ||
288 | reg_2874 = 0x00000001; | ||
289 | } | ||
290 | |||
291 | /* Select the horizontal filter */ | ||
292 | if (window->src_w == window->dst_w) { | ||
293 | /* An exact size match uses filter 0 */ | ||
294 | h_filter = 0; | ||
295 | } | ||
296 | else { | ||
297 | /* Figure out which filter to use */ | ||
298 | h_filter = ((window->src_w << 16) / window->dst_w) >> 15; | ||
299 | h_filter = (h_filter >> 1) + (h_filter & 1); | ||
300 | /* Only an exact size match can use filter 0 */ | ||
301 | if (h_filter == 0) h_filter = 1; | ||
302 | } | ||
303 | |||
304 | write_reg(reg_2834, 0x02834); | ||
305 | write_reg(reg_2838, 0x02838); | ||
306 | IVTV_DEBUG_YUV("Update reg 0x2834 %08x->%08x 0x2838 %08x->%08x\n",itv->yuv_info.reg_2834, reg_2834, itv->yuv_info.reg_2838, reg_2838); | ||
307 | |||
308 | write_reg(reg_283c, 0x0283c); | ||
309 | write_reg(reg_2844, 0x02844); | ||
310 | |||
311 | IVTV_DEBUG_YUV("Update reg 0x283c %08x->%08x 0x2844 %08x->%08x\n",itv->yuv_info.reg_283c, reg_283c, itv->yuv_info.reg_2844, reg_2844); | ||
312 | |||
313 | write_reg(0x00080514, 0x02840); | ||
314 | write_reg(0x00100514, 0x02848); | ||
315 | IVTV_DEBUG_YUV("Update reg 0x2840 %08x->%08x 0x2848 %08x->%08x\n",itv->yuv_info.reg_2840, 0x00080514, itv->yuv_info.reg_2848, 0x00100514); | ||
316 | |||
317 | write_reg(reg_2854, 0x02854); | ||
318 | IVTV_DEBUG_YUV("Update reg 0x2854 %08x->%08x \n",itv->yuv_info.reg_2854, reg_2854); | ||
319 | |||
320 | write_reg(reg_285c, 0x0285c); | ||
321 | write_reg(reg_2864, 0x02864); | ||
322 | IVTV_DEBUG_YUV("Update reg 0x285c %08x->%08x 0x2864 %08x->%08x\n",itv->yuv_info.reg_285c, reg_285c, itv->yuv_info.reg_2864, reg_2864); | ||
323 | |||
324 | write_reg(reg_2874, 0x02874); | ||
325 | IVTV_DEBUG_YUV("Update reg 0x2874 %08x->%08x\n",itv->yuv_info.reg_2874, reg_2874); | ||
326 | |||
327 | write_reg(reg_2870, 0x02870); | ||
328 | IVTV_DEBUG_YUV("Update reg 0x2870 %08x->%08x\n",itv->yuv_info.reg_2870, reg_2870); | ||
329 | |||
330 | write_reg( reg_2890,0x02890); | ||
331 | IVTV_DEBUG_YUV("Update reg 0x2890 %08x->%08x\n",itv->yuv_info.reg_2890, reg_2890); | ||
332 | |||
333 | /* Only update the filter if we really need to */ | ||
334 | if (h_filter != itv->yuv_info.h_filter) { | ||
335 | ivtv_yuv_filter (itv,h_filter,-1,-1); | ||
336 | itv->yuv_info.h_filter = h_filter; | ||
337 | } | ||
338 | } | ||
339 | |||
340 | static void ivtv_yuv_handle_vertical(struct ivtv *itv, struct yuv_frame_info *window) | ||
341 | { | ||
342 | u32 master_height; | ||
343 | u32 reg_2918, reg_291c, reg_2920, reg_2928; | ||
344 | u32 reg_2930, reg_2934, reg_293c; | ||
345 | u32 reg_2940, reg_2944, reg_294c; | ||
346 | u32 reg_2950, reg_2954, reg_2958, reg_295c; | ||
347 | u32 reg_2960, reg_2964, reg_2968, reg_296c; | ||
348 | u32 reg_289c; | ||
349 | u32 src_y_major_y, src_y_minor_y; | ||
350 | u32 src_y_major_uv, src_y_minor_uv; | ||
351 | u32 reg_2964_base, reg_2968_base; | ||
352 | int v_filter_1, v_filter_2; | ||
353 | |||
354 | IVTV_DEBUG_WARN("Need to adjust to height %d src_h %d dst_h %d src_y %d dst_y %d\n", | ||
355 | window->tru_h, window->src_h, window->dst_h,window->src_y, window->dst_y); | ||
356 | |||
357 | /* What scaling mode is being used... */ | ||
358 | if (window->interlaced_y) { | ||
359 | IVTV_DEBUG_YUV("Scaling mode Y: Interlaced\n"); | ||
360 | } | ||
361 | else { | ||
362 | IVTV_DEBUG_YUV("Scaling mode Y: Progressive\n"); | ||
363 | } | ||
364 | |||
365 | if (window->interlaced_uv) { | ||
366 | IVTV_DEBUG_YUV("Scaling mode UV: Interlaced\n"); | ||
367 | } | ||
368 | else { | ||
369 | IVTV_DEBUG_YUV("Scaling mode UV: Progressive\n"); | ||
370 | } | ||
371 | |||
372 | /* What is the source video being treated as... */ | ||
373 | if (itv->yuv_info.frame_interlaced) { | ||
374 | IVTV_DEBUG_WARN("Source video: Interlaced\n"); | ||
375 | } | ||
376 | else { | ||
377 | IVTV_DEBUG_WARN("Source video: Non-interlaced\n"); | ||
378 | } | ||
379 | |||
380 | /* We offset into the image using two different index methods, so split | ||
381 | the y source coord into two parts. */ | ||
382 | if (window->src_y < 8) { | ||
383 | src_y_minor_uv = window->src_y; | ||
384 | src_y_major_uv = 0; | ||
385 | } | ||
386 | else { | ||
387 | src_y_minor_uv = 8; | ||
388 | src_y_major_uv = window->src_y - 8; | ||
389 | } | ||
390 | |||
391 | src_y_minor_y = src_y_minor_uv; | ||
392 | src_y_major_y = src_y_major_uv; | ||
393 | |||
394 | if (window->offset_y) src_y_minor_y += 16; | ||
395 | |||
396 | if (window->interlaced_y) | ||
397 | reg_2918 = (window->dst_h << 16) | (window->src_h + src_y_minor_y); | ||
398 | else | ||
399 | reg_2918 = (window->dst_h << 16) | ((window->src_h + src_y_minor_y) << 1); | ||
400 | |||
401 | if (window->interlaced_uv) | ||
402 | reg_291c = (window->dst_h << 16) | ((window->src_h + src_y_minor_uv) >> 1); | ||
403 | else | ||
404 | reg_291c = (window->dst_h << 16) | (window->src_h + src_y_minor_uv); | ||
405 | |||
406 | reg_2964_base = (src_y_minor_y * ((window->dst_h << 16)/window->src_h)) >> 14; | ||
407 | reg_2968_base = (src_y_minor_uv * ((window->dst_h << 16)/window->src_h)) >> 14; | ||
408 | |||
409 | if (window->dst_h / 2 >= window->src_h && !window->interlaced_y) { | ||
410 | master_height = (window->src_h * 0x00400000) / window->dst_h; | ||
411 | if ((window->src_h * 0x00400000) - (master_height * window->dst_h) >= window->dst_h / 2) master_height ++; | ||
412 | reg_2920 = master_height >> 2; | ||
413 | reg_2928 = master_height >> 3; | ||
414 | reg_2930 = master_height; | ||
415 | reg_2940 = master_height >> 1; | ||
416 | reg_2964_base >>= 3; | ||
417 | reg_2968_base >>= 3; | ||
418 | reg_296c = 0x00000000; | ||
419 | } | ||
420 | else if (window->dst_h >= window->src_h) { | ||
421 | master_height = (window->src_h * 0x00400000) / window->dst_h; | ||
422 | master_height = (master_height >> 1) + (master_height & 1); | ||
423 | reg_2920 = master_height >> 2; | ||
424 | reg_2928 = master_height >> 2; | ||
425 | reg_2930 = master_height; | ||
426 | reg_2940 = master_height >> 1; | ||
427 | reg_296c = 0x00000000; | ||
428 | if (window->interlaced_y) { | ||
429 | reg_2964_base >>= 3; | ||
430 | } | ||
431 | else { | ||
432 | reg_296c ++; | ||
433 | reg_2964_base >>= 2; | ||
434 | } | ||
435 | if (window->interlaced_uv) reg_2928 >>= 1; | ||
436 | reg_2968_base >>= 3; | ||
437 | } | ||
438 | else if (window->dst_h >= window->src_h / 2) { | ||
439 | master_height = (window->src_h * 0x00200000) / window->dst_h; | ||
440 | master_height = (master_height >> 1) + (master_height & 1); | ||
441 | reg_2920 = master_height >> 2; | ||
442 | reg_2928 = master_height >> 2; | ||
443 | reg_2930 = master_height; | ||
444 | reg_2940 = master_height; | ||
445 | reg_296c = 0x00000101; | ||
446 | if (window->interlaced_y) { | ||
447 | reg_2964_base >>= 2; | ||
448 | } | ||
449 | else { | ||
450 | reg_296c ++; | ||
451 | reg_2964_base >>= 1; | ||
452 | } | ||
453 | if (window->interlaced_uv) reg_2928 >>= 1; | ||
454 | reg_2968_base >>= 2; | ||
455 | } | ||
456 | else { | ||
457 | master_height = (window->src_h * 0x00100000) / window->dst_h; | ||
458 | master_height = (master_height >> 1) + (master_height & 1); | ||
459 | reg_2920 = master_height >> 2; | ||
460 | reg_2928 = master_height >> 2; | ||
461 | reg_2930 = master_height; | ||
462 | reg_2940 = master_height; | ||
463 | reg_2964_base >>= 1; | ||
464 | reg_2968_base >>= 2; | ||
465 | reg_296c = 0x00000102; | ||
466 | } | ||
467 | |||
468 | /* FIXME These registers change depending on scaled / unscaled output | ||
469 | We really need to work out what they should be */ | ||
470 | if (window->src_h == window->dst_h){ | ||
471 | reg_2934 = 0x00020000; | ||
472 | reg_293c = 0x00100000; | ||
473 | reg_2944 = 0x00040000; | ||
474 | reg_294c = 0x000b0000; | ||
475 | } | ||
476 | else { | ||
477 | reg_2934 = 0x00000FF0; | ||
478 | reg_293c = 0x00000FF0; | ||
479 | reg_2944 = 0x00000FF0; | ||
480 | reg_294c = 0x00000FF0; | ||
481 | } | ||
482 | |||
483 | /* The first line to be displayed */ | ||
484 | reg_2950 = 0x00010000 + src_y_major_y; | ||
485 | if (window->interlaced_y) reg_2950 += 0x00010000; | ||
486 | reg_2954 = reg_2950 + 1; | ||
487 | |||
488 | reg_2958 = 0x00010000 + (src_y_major_y >> 1); | ||
489 | if (window->interlaced_uv) reg_2958 += 0x00010000; | ||
490 | reg_295c = reg_2958 + 1; | ||
491 | |||
492 | if (itv->yuv_info.decode_height == 480) | ||
493 | reg_289c = 0x011e0017; | ||
494 | else | ||
495 | reg_289c = 0x01500017; | ||
496 | |||
497 | if (window->dst_y < 0) | ||
498 | reg_289c = (reg_289c - ((window->dst_y & ~1)<<15))-(window->dst_y >>1); | ||
499 | else | ||
500 | reg_289c = (reg_289c + ((window->dst_y & ~1)<<15))+(window->dst_y >>1); | ||
501 | |||
502 | /* How much of the source to decode. | ||
503 | Take into account the source offset */ | ||
504 | reg_2960 = ((src_y_minor_y + window->src_h + src_y_major_y) - 1 ) | | ||
505 | ((((src_y_minor_uv + window->src_h + src_y_major_uv) - 1) & ~1) << 15); | ||
506 | |||
507 | /* Calculate correct value for register 2964 */ | ||
508 | if (window->src_h == window->dst_h) | ||
509 | reg_2964 = 1; | ||
510 | else { | ||
511 | reg_2964 = 2 + ((window->dst_h << 1) / window->src_h); | ||
512 | reg_2964 = (reg_2964 >> 1) + (reg_2964 & 1); | ||
513 | } | ||
514 | reg_2968 = (reg_2964 << 16) + reg_2964 + (reg_2964 >> 1); | ||
515 | reg_2964 = (reg_2964 << 16) + reg_2964 + (reg_2964 * 46 / 94); | ||
516 | |||
517 | /* Okay, we've wasted time working out the correct value, | ||
518 | but if we use it, it fouls the the window alignment. | ||
519 | Fudge it to what we want... */ | ||
520 | reg_2964 = 0x00010001 + ((reg_2964 & 0x0000FFFF) - (reg_2964 >> 16)); | ||
521 | reg_2968 = 0x00010001 + ((reg_2968 & 0x0000FFFF) - (reg_2968 >> 16)); | ||
522 | |||
523 | /* Deviate further from what it should be. I find the flicker headache | ||
524 | inducing so try to reduce it slightly. Leave 2968 as-is otherwise | ||
525 | colours foul. */ | ||
526 | if ((reg_2964 != 0x00010001) && (window->dst_h / 2 <= window->src_h)) | ||
527 | reg_2964 = (reg_2964 & 0xFFFF0000) + ((reg_2964 & 0x0000FFFF)/2); | ||
528 | |||
529 | if (!window->interlaced_y) reg_2964 -= 0x00010001; | ||
530 | if (!window->interlaced_uv) reg_2968 -= 0x00010001; | ||
531 | |||
532 | reg_2964 += ((reg_2964_base << 16) | reg_2964_base); | ||
533 | reg_2968 += ((reg_2968_base << 16) | reg_2968_base); | ||
534 | |||
535 | /* Select the vertical filter */ | ||
536 | if (window->src_h == window->dst_h) { | ||
537 | /* An exact size match uses filter 0/1 */ | ||
538 | v_filter_1 = 0; | ||
539 | v_filter_2 = 1; | ||
540 | } | ||
541 | else { | ||
542 | /* Figure out which filter to use */ | ||
543 | v_filter_1 = ((window->src_h << 16) / window->dst_h) >> 15; | ||
544 | v_filter_1 = (v_filter_1 >> 1) + (v_filter_1 & 1); | ||
545 | /* Only an exact size match can use filter 0 */ | ||
546 | if (v_filter_1 == 0) v_filter_1 = 1; | ||
547 | v_filter_2 = v_filter_1; | ||
548 | } | ||
549 | |||
550 | write_reg(reg_2934, 0x02934); | ||
551 | write_reg(reg_293c, 0x0293c); | ||
552 | IVTV_DEBUG_YUV("Update reg 0x2934 %08x->%08x 0x293c %08x->%08x\n",itv->yuv_info.reg_2934, reg_2934, itv->yuv_info.reg_293c, reg_293c); | ||
553 | write_reg(reg_2944, 0x02944); | ||
554 | write_reg(reg_294c, 0x0294c); | ||
555 | IVTV_DEBUG_YUV("Update reg 0x2944 %08x->%08x 0x294c %08x->%08x\n",itv->yuv_info.reg_2944, reg_2944, itv->yuv_info.reg_294c, reg_294c); | ||
556 | |||
557 | /* Ensure 2970 is 0 (does it ever change ?) */ | ||
558 | /* write_reg(0,0x02970); */ | ||
559 | /* IVTV_DEBUG_YUV("Update reg 0x2970 %08x->%08x\n",itv->yuv_info.reg_2970, 0); */ | ||
560 | |||
561 | write_reg(reg_2930, 0x02938); | ||
562 | write_reg(reg_2930, 0x02930); | ||
563 | IVTV_DEBUG_YUV("Update reg 0x2930 %08x->%08x 0x2938 %08x->%08x\n",itv->yuv_info.reg_2930, reg_2930, itv->yuv_info.reg_2938, reg_2930); | ||
564 | |||
565 | write_reg(reg_2928, 0x02928); | ||
566 | write_reg(reg_2928+0x514, 0x0292C); | ||
567 | IVTV_DEBUG_YUV("Update reg 0x2928 %08x->%08x 0x292c %08x->%08x\n",itv->yuv_info.reg_2928, reg_2928, itv->yuv_info.reg_292c, reg_2928+0x514); | ||
568 | |||
569 | write_reg(reg_2920, 0x02920); | ||
570 | write_reg(reg_2920+0x514, 0x02924); | ||
571 | IVTV_DEBUG_YUV("Update reg 0x2920 %08x->%08x 0x2924 %08x->%08x\n",itv->yuv_info.reg_2920, reg_2920, itv->yuv_info.reg_2924, 0x514+reg_2920); | ||
572 | |||
573 | write_reg (reg_2918,0x02918); | ||
574 | write_reg (reg_291c,0x0291C); | ||
575 | IVTV_DEBUG_YUV("Update reg 0x2918 %08x->%08x 0x291C %08x->%08x\n",itv->yuv_info.reg_2918,reg_2918,itv->yuv_info.reg_291c,reg_291c); | ||
576 | |||
577 | write_reg(reg_296c, 0x0296c); | ||
578 | IVTV_DEBUG_YUV("Update reg 0x296c %08x->%08x\n",itv->yuv_info.reg_296c, reg_296c); | ||
579 | |||
580 | write_reg(reg_2940, 0x02948); | ||
581 | write_reg(reg_2940, 0x02940); | ||
582 | IVTV_DEBUG_YUV("Update reg 0x2940 %08x->%08x 0x2948 %08x->%08x\n",itv->yuv_info.reg_2940, reg_2940, itv->yuv_info.reg_2948, reg_2940); | ||
583 | |||
584 | write_reg(reg_2950, 0x02950); | ||
585 | write_reg(reg_2954, 0x02954); | ||
586 | IVTV_DEBUG_YUV("Update reg 0x2950 %08x->%08x 0x2954 %08x->%08x\n",itv->yuv_info.reg_2950, reg_2950, itv->yuv_info.reg_2954, reg_2954); | ||
587 | |||
588 | write_reg(reg_2958, 0x02958); | ||
589 | write_reg(reg_295c, 0x0295C); | ||
590 | IVTV_DEBUG_YUV("Update reg 0x2958 %08x->%08x 0x295C %08x->%08x\n",itv->yuv_info.reg_2958, reg_2958, itv->yuv_info.reg_295c, reg_295c); | ||
591 | |||
592 | write_reg(reg_2960, 0x02960); | ||
593 | IVTV_DEBUG_YUV("Update reg 0x2960 %08x->%08x \n",itv->yuv_info.reg_2960, reg_2960); | ||
594 | |||
595 | write_reg(reg_2964, 0x02964); | ||
596 | write_reg(reg_2968, 0x02968); | ||
597 | IVTV_DEBUG_YUV("Update reg 0x2964 %08x->%08x 0x2968 %08x->%08x\n",itv->yuv_info.reg_2964, reg_2964, itv->yuv_info.reg_2968, reg_2968); | ||
598 | |||
599 | write_reg( reg_289c,0x0289c); | ||
600 | IVTV_DEBUG_YUV("Update reg 0x289c %08x->%08x\n",itv->yuv_info.reg_289c, reg_289c); | ||
601 | |||
602 | /* Only update filter 1 if we really need to */ | ||
603 | if (v_filter_1 != itv->yuv_info.v_filter_1) { | ||
604 | ivtv_yuv_filter (itv,-1,v_filter_1,-1); | ||
605 | itv->yuv_info.v_filter_1 = v_filter_1; | ||
606 | } | ||
607 | |||
608 | /* Only update filter 2 if we really need to */ | ||
609 | if (v_filter_2 != itv->yuv_info.v_filter_2) { | ||
610 | ivtv_yuv_filter (itv,-1,-1,v_filter_2); | ||
611 | itv->yuv_info.v_filter_2 = v_filter_2; | ||
612 | } | ||
613 | |||
614 | itv->yuv_info.frame_interlaced_last = itv->yuv_info.frame_interlaced; | ||
615 | itv->yuv_info.lace_threshold_last = itv->yuv_info.lace_threshold; | ||
616 | } | ||
617 | |||
618 | /* Modify the supplied coordinate information to fit the visible osd area */ | ||
619 | static u32 ivtv_yuv_window_setup (struct ivtv *itv, struct yuv_frame_info *window) | ||
620 | { | ||
621 | int osd_crop; | ||
622 | u32 osd_scale; | ||
623 | u32 yuv_update = 0; | ||
624 | |||
625 | /* Work out the lace settings */ | ||
626 | switch (itv->yuv_info.lace_mode) { | ||
627 | case IVTV_YUV_MODE_PROGRESSIVE: /* Progressive mode */ | ||
628 | itv->yuv_info.frame_interlaced = 0; | ||
629 | if (window->tru_h < 512 || (window->tru_h > 576 && window->tru_h < 1021)) | ||
630 | window->interlaced_y = 0; | ||
631 | else | ||
632 | window->interlaced_y = 1; | ||
633 | |||
634 | if (window->tru_h < 1021 && (window->dst_h >= window->src_h /2)) | ||
635 | window->interlaced_uv = 0; | ||
636 | else | ||
637 | window->interlaced_uv = 1; | ||
638 | break; | ||
639 | |||
640 | case IVTV_YUV_MODE_AUTO: | ||
641 | if (window->tru_h <= itv->yuv_info.lace_threshold || window->tru_h > 576 || window->tru_w > 720){ | ||
642 | itv->yuv_info.frame_interlaced = 0; | ||
643 | if ((window->tru_h < 512) || | ||
644 | (window->tru_h > 576 && window->tru_h < 1021) || | ||
645 | (window->tru_w > 720 && window->tru_h < 1021)) | ||
646 | window->interlaced_y = 0; | ||
647 | else | ||
648 | window->interlaced_y = 1; | ||
649 | |||
650 | if (window->tru_h < 1021 && (window->dst_h >= window->src_h /2)) | ||
651 | window->interlaced_uv = 0; | ||
652 | else | ||
653 | window->interlaced_uv = 1; | ||
654 | } | ||
655 | else { | ||
656 | itv->yuv_info.frame_interlaced = 1; | ||
657 | window->interlaced_y = 1; | ||
658 | window->interlaced_uv = 1; | ||
659 | } | ||
660 | break; | ||
661 | |||
662 | case IVTV_YUV_MODE_INTERLACED: /* Interlace mode */ | ||
663 | default: | ||
664 | itv->yuv_info.frame_interlaced = 1; | ||
665 | window->interlaced_y = 1; | ||
666 | window->interlaced_uv = 1; | ||
667 | break; | ||
668 | } | ||
669 | |||
670 | /* Sorry, but no negative coords for src */ | ||
671 | if (window->src_x < 0) window->src_x = 0; | ||
672 | if (window->src_y < 0) window->src_y = 0; | ||
673 | |||
674 | /* Can only reduce width down to 1/4 original size */ | ||
675 | if ((osd_crop = window->src_w - ( 4 * window->dst_w )) > 0) { | ||
676 | window->src_x += osd_crop / 2; | ||
677 | window->src_w = (window->src_w - osd_crop) & ~3; | ||
678 | window->dst_w = window->src_w / 4; | ||
679 | window->dst_w += window->dst_w & 1; | ||
680 | } | ||
681 | |||
682 | /* Can only reduce height down to 1/4 original size */ | ||
683 | if (window->src_h / window->dst_h >= 2) { | ||
684 | /* Overflow may be because we're running progressive, so force mode switch */ | ||
685 | window->interlaced_y = 1; | ||
686 | /* Make sure we're still within limits for interlace */ | ||
687 | if ((osd_crop = window->src_h - ( 4 * window->dst_h )) > 0) { | ||
688 | /* If we reach here we'll have to force the height. */ | ||
689 | window->src_y += osd_crop / 2; | ||
690 | window->src_h = (window->src_h - osd_crop) & ~3; | ||
691 | window->dst_h = window->src_h / 4; | ||
692 | window->dst_h += window->dst_h & 1; | ||
693 | } | ||
694 | } | ||
695 | |||
696 | /* If there's nothing to safe to display, we may as well stop now */ | ||
697 | if ((int)window->dst_w <= 2 || (int)window->dst_h <= 2 || (int)window->src_w <= 2 || (int)window->src_h <= 2) { | ||
698 | return 0; | ||
699 | } | ||
700 | |||
701 | /* Ensure video remains inside OSD area */ | ||
702 | osd_scale = (window->src_h << 16) / window->dst_h; | ||
703 | |||
704 | if ((osd_crop = window->pan_y - window->dst_y) > 0) { | ||
705 | /* Falls off the upper edge - crop */ | ||
706 | window->src_y += (osd_scale * osd_crop) >> 16; | ||
707 | window->src_h -= (osd_scale * osd_crop) >> 16; | ||
708 | window->dst_h -= osd_crop; | ||
709 | window->dst_y = 0; | ||
710 | } | ||
711 | else { | ||
712 | window->dst_y -= window->pan_y; | ||
713 | } | ||
714 | |||
715 | if ((osd_crop = window->dst_h + window->dst_y - window->vis_h) > 0) { | ||
716 | /* Falls off the lower edge - crop */ | ||
717 | window->dst_h -= osd_crop; | ||
718 | window->src_h -= (osd_scale * osd_crop) >> 16; | ||
719 | } | ||
720 | |||
721 | osd_scale = (window->src_w << 16) / window->dst_w; | ||
722 | |||
723 | if ((osd_crop = window->pan_x - window->dst_x) > 0) { | ||
724 | /* Fall off the left edge - crop */ | ||
725 | window->src_x += (osd_scale * osd_crop) >> 16; | ||
726 | window->src_w -= (osd_scale * osd_crop) >> 16; | ||
727 | window->dst_w -= osd_crop; | ||
728 | window->dst_x = 0; | ||
729 | } | ||
730 | else { | ||
731 | window->dst_x -= window->pan_x; | ||
732 | } | ||
733 | |||
734 | if ((osd_crop = window->dst_w + window->dst_x - window->vis_w) > 0) { | ||
735 | /* Falls off the right edge - crop */ | ||
736 | window->dst_w -= osd_crop; | ||
737 | window->src_w -= (osd_scale * osd_crop) >> 16; | ||
738 | } | ||
739 | |||
740 | /* The OSD can be moved. Track to it */ | ||
741 | window->dst_x += itv->yuv_info.osd_x_offset; | ||
742 | window->dst_y += itv->yuv_info.osd_y_offset; | ||
743 | |||
744 | /* Width & height for both src & dst must be even. | ||
745 | Same for coordinates. */ | ||
746 | window->dst_w &= ~1; | ||
747 | window->dst_x &= ~1; | ||
748 | |||
749 | window->src_w += window->src_x & 1; | ||
750 | window->src_x &= ~1; | ||
751 | |||
752 | window->src_w &= ~1; | ||
753 | window->dst_w &= ~1; | ||
754 | |||
755 | window->dst_h &= ~1; | ||
756 | window->dst_y &= ~1; | ||
757 | |||
758 | window->src_h += window->src_y & 1; | ||
759 | window->src_y &= ~1; | ||
760 | |||
761 | window->src_h &= ~1; | ||
762 | window->dst_h &= ~1; | ||
763 | |||
764 | /* Due to rounding, we may have reduced the output size to <1/4 of the source | ||
765 | Check again, but this time just resize. Don't change source coordinates */ | ||
766 | if (window->dst_w < window->src_w / 4) { | ||
767 | window->src_w &= ~3; | ||
768 | window->dst_w = window->src_w / 4; | ||
769 | window->dst_w += window->dst_w & 1; | ||
770 | } | ||
771 | if (window->dst_h < window->src_h / 4) { | ||
772 | window->src_h &= ~3; | ||
773 | window->dst_h = window->src_h / 4; | ||
774 | window->dst_h += window->dst_h & 1; | ||
775 | } | ||
776 | |||
777 | /* Check again. If there's nothing to safe to display, stop now */ | ||
778 | if ((int)window->dst_w <= 2 || (int)window->dst_h <= 2 || (int)window->src_w <= 2 || (int)window->src_h <= 2) { | ||
779 | return 0; | ||
780 | } | ||
781 | |||
782 | /* Both x offset & width are linked, so they have to be done together */ | ||
783 | if ((itv->yuv_info.old_frame_info.dst_w != window->dst_w) || | ||
784 | (itv->yuv_info.old_frame_info.src_w != window->src_w) || | ||
785 | (itv->yuv_info.old_frame_info.dst_x != window->dst_x) || | ||
786 | (itv->yuv_info.old_frame_info.src_x != window->src_x) || | ||
787 | (itv->yuv_info.old_frame_info.pan_x != window->pan_x) || | ||
788 | (itv->yuv_info.old_frame_info.vis_w != window->vis_w)) { | ||
789 | yuv_update |= IVTV_YUV_UPDATE_HORIZONTAL; | ||
790 | } | ||
791 | |||
792 | if ((itv->yuv_info.old_frame_info.src_h != window->src_h) || | ||
793 | (itv->yuv_info.old_frame_info.dst_h != window->dst_h) || | ||
794 | (itv->yuv_info.old_frame_info.dst_y != window->dst_y) || | ||
795 | (itv->yuv_info.old_frame_info.src_y != window->src_y) || | ||
796 | (itv->yuv_info.old_frame_info.pan_y != window->pan_y) || | ||
797 | (itv->yuv_info.old_frame_info.vis_h != window->vis_h) || | ||
798 | (itv->yuv_info.old_frame_info.interlaced_y != window->interlaced_y) || | ||
799 | (itv->yuv_info.old_frame_info.interlaced_uv != window->interlaced_uv)) { | ||
800 | yuv_update |= IVTV_YUV_UPDATE_VERTICAL; | ||
801 | } | ||
802 | |||
803 | return yuv_update; | ||
804 | } | ||
805 | |||
806 | /* Update the scaling register to the requested value */ | ||
807 | void ivtv_yuv_work_handler (struct work_struct *work) | ||
808 | { | ||
809 | struct yuv_playback_info *info = container_of(work, struct yuv_playback_info, work_queue); | ||
810 | struct ivtv *itv = container_of(info, struct ivtv, yuv_info); | ||
811 | DEFINE_WAIT(wait); | ||
812 | |||
813 | struct yuv_frame_info window; | ||
814 | u32 yuv_update; | ||
815 | |||
816 | int frame = itv->yuv_info.update_frame; | ||
817 | |||
818 | /* IVTV_DEBUG_YUV("Update yuv registers for frame %d\n",frame); */ | ||
819 | memcpy(&window, &itv->yuv_info.new_frame_info[frame], sizeof (window)); | ||
820 | |||
821 | /* Update the osd pan info */ | ||
822 | window.pan_x = itv->yuv_info.osd_x_pan; | ||
823 | window.pan_y = itv->yuv_info.osd_y_pan; | ||
824 | window.vis_w = itv->yuv_info.osd_vis_w; | ||
825 | window.vis_h = itv->yuv_info.osd_vis_h; | ||
826 | |||
827 | /* Calculate the display window coordinates. Exit if nothing left */ | ||
828 | if (!(yuv_update = ivtv_yuv_window_setup (itv, &window))) | ||
829 | return; | ||
830 | |||
831 | /* Update horizontal settings */ | ||
832 | if (yuv_update & IVTV_YUV_UPDATE_HORIZONTAL) | ||
833 | ivtv_yuv_handle_horizontal(itv, &window); | ||
834 | |||
835 | if (yuv_update & IVTV_YUV_UPDATE_VERTICAL) | ||
836 | ivtv_yuv_handle_vertical(itv, &window); | ||
837 | |||
838 | memcpy(&itv->yuv_info.old_frame_info, &window, sizeof (itv->yuv_info.old_frame_info)); | ||
839 | } | ||
840 | |||
841 | static void ivtv_yuv_init (struct ivtv *itv) | ||
842 | { | ||
843 | IVTV_DEBUG_YUV("ivtv_yuv_init\n"); | ||
844 | |||
845 | /* Take a snapshot of the current register settings */ | ||
846 | itv->yuv_info.reg_2834 = read_reg(0x02834); | ||
847 | itv->yuv_info.reg_2838 = read_reg(0x02838); | ||
848 | itv->yuv_info.reg_283c = read_reg(0x0283c); | ||
849 | itv->yuv_info.reg_2840 = read_reg(0x02840); | ||
850 | itv->yuv_info.reg_2844 = read_reg(0x02844); | ||
851 | itv->yuv_info.reg_2848 = read_reg(0x02848); | ||
852 | itv->yuv_info.reg_2854 = read_reg(0x02854); | ||
853 | itv->yuv_info.reg_285c = read_reg(0x0285c); | ||
854 | itv->yuv_info.reg_2864 = read_reg(0x02864); | ||
855 | itv->yuv_info.reg_2870 = read_reg(0x02870); | ||
856 | itv->yuv_info.reg_2874 = read_reg(0x02874); | ||
857 | itv->yuv_info.reg_2898 = read_reg(0x02898); | ||
858 | itv->yuv_info.reg_2890 = read_reg(0x02890); | ||
859 | |||
860 | itv->yuv_info.reg_289c = read_reg(0x0289c); | ||
861 | itv->yuv_info.reg_2918 = read_reg(0x02918); | ||
862 | itv->yuv_info.reg_291c = read_reg(0x0291c); | ||
863 | itv->yuv_info.reg_2920 = read_reg(0x02920); | ||
864 | itv->yuv_info.reg_2924 = read_reg(0x02924); | ||
865 | itv->yuv_info.reg_2928 = read_reg(0x02928); | ||
866 | itv->yuv_info.reg_292c = read_reg(0x0292c); | ||
867 | itv->yuv_info.reg_2930 = read_reg(0x02930); | ||
868 | itv->yuv_info.reg_2934 = read_reg(0x02934); | ||
869 | itv->yuv_info.reg_2938 = read_reg(0x02938); | ||
870 | itv->yuv_info.reg_293c = read_reg(0x0293c); | ||
871 | itv->yuv_info.reg_2940 = read_reg(0x02940); | ||
872 | itv->yuv_info.reg_2944 = read_reg(0x02944); | ||
873 | itv->yuv_info.reg_2948 = read_reg(0x02948); | ||
874 | itv->yuv_info.reg_294c = read_reg(0x0294c); | ||
875 | itv->yuv_info.reg_2950 = read_reg(0x02950); | ||
876 | itv->yuv_info.reg_2954 = read_reg(0x02954); | ||
877 | itv->yuv_info.reg_2958 = read_reg(0x02958); | ||
878 | itv->yuv_info.reg_295c = read_reg(0x0295c); | ||
879 | itv->yuv_info.reg_2960 = read_reg(0x02960); | ||
880 | itv->yuv_info.reg_2964 = read_reg(0x02964); | ||
881 | itv->yuv_info.reg_2968 = read_reg(0x02968); | ||
882 | itv->yuv_info.reg_296c = read_reg(0x0296c); | ||
883 | itv->yuv_info.reg_2970 = read_reg(0x02970); | ||
884 | |||
885 | itv->yuv_info.v_filter_1 = -1; | ||
886 | itv->yuv_info.v_filter_2 = -1; | ||
887 | itv->yuv_info.h_filter = -1; | ||
888 | |||
889 | /* Set some valid size info */ | ||
890 | itv->yuv_info.osd_x_offset = read_reg(0x02a04) & 0x00000FFF; | ||
891 | itv->yuv_info.osd_y_offset = (read_reg(0x02a04) >> 16) & 0x00000FFF; | ||
892 | |||
893 | /* Bit 2 of reg 2878 indicates current decoder output format | ||
894 | 0 : NTSC 1 : PAL */ | ||
895 | if (read_reg(0x2878) & 4) | ||
896 | itv->yuv_info.decode_height = 576; | ||
897 | else | ||
898 | itv->yuv_info.decode_height = 480; | ||
899 | |||
900 | /* If no visible size set, assume full size */ | ||
901 | if (!itv->yuv_info.osd_vis_w) itv->yuv_info.osd_vis_w = 720 - itv->yuv_info.osd_x_offset; | ||
902 | if (!itv->yuv_info.osd_vis_h) itv->yuv_info.osd_vis_h = itv->yuv_info.decode_height - itv->yuv_info.osd_y_offset; | ||
903 | |||
904 | /* We need a buffer for blanking when Y plane is offset - non-fatal if we can't get one */ | ||
905 | itv->yuv_info.blanking_ptr = kzalloc(720*16,GFP_KERNEL); | ||
906 | if (itv->yuv_info.blanking_ptr) { | ||
907 | itv->yuv_info.blanking_dmaptr = pci_map_single(itv->dev, itv->yuv_info.blanking_ptr, 720*16, PCI_DMA_TODEVICE); | ||
908 | } | ||
909 | else { | ||
910 | itv->yuv_info.blanking_dmaptr = 0; | ||
911 | IVTV_DEBUG_WARN ("Failed to allocate yuv blanking buffer\n"); | ||
912 | } | ||
913 | |||
914 | IVTV_DEBUG_WARN("Enable video output\n"); | ||
915 | write_reg_sync(0x00108080, 0x2898); | ||
916 | |||
917 | /* Enable YUV decoder output */ | ||
918 | write_reg_sync(0x01, IVTV_REG_VDM); | ||
919 | |||
920 | set_bit(IVTV_F_I_DECODING_YUV, &itv->i_flags); | ||
921 | atomic_set(&itv->yuv_info.next_dma_frame,0); | ||
922 | } | ||
923 | |||
924 | int ivtv_yuv_prep_frame(struct ivtv *itv, struct ivtv_dma_frame *args) | ||
925 | { | ||
926 | DEFINE_WAIT(wait); | ||
927 | int rc = 0; | ||
928 | int got_sig = 0; | ||
929 | int frame, next_fill_frame, last_fill_frame; | ||
930 | |||
931 | IVTV_DEBUG_INFO("yuv_prep_frame\n"); | ||
932 | |||
933 | if (atomic_read(&itv->yuv_info.next_dma_frame) == -1) ivtv_yuv_init(itv); | ||
934 | |||
935 | frame = atomic_read(&itv->yuv_info.next_fill_frame); | ||
936 | next_fill_frame = (frame + 1) & 0x3; | ||
937 | last_fill_frame = (atomic_read(&itv->yuv_info.next_dma_frame)+1) & 0x3; | ||
938 | |||
939 | if (next_fill_frame != last_fill_frame && last_fill_frame != frame) { | ||
940 | /* Buffers are full - Overwrite the last frame */ | ||
941 | next_fill_frame = frame; | ||
942 | frame = (frame - 1) & 3; | ||
943 | } | ||
944 | |||
945 | /* Take a snapshot of the yuv coordinate information */ | ||
946 | itv->yuv_info.new_frame_info[frame].src_x = args->src.left; | ||
947 | itv->yuv_info.new_frame_info[frame].src_y = args->src.top; | ||
948 | itv->yuv_info.new_frame_info[frame].src_w = args->src.width; | ||
949 | itv->yuv_info.new_frame_info[frame].src_h = args->src.height; | ||
950 | itv->yuv_info.new_frame_info[frame].dst_x = args->dst.left; | ||
951 | itv->yuv_info.new_frame_info[frame].dst_y = args->dst.top; | ||
952 | itv->yuv_info.new_frame_info[frame].dst_w = args->dst.width; | ||
953 | itv->yuv_info.new_frame_info[frame].dst_h = args->dst.height; | ||
954 | itv->yuv_info.new_frame_info[frame].tru_x = args->dst.left; | ||
955 | itv->yuv_info.new_frame_info[frame].tru_w = args->src_width; | ||
956 | itv->yuv_info.new_frame_info[frame].tru_h = args->src_height; | ||
957 | |||
958 | /* Are we going to offset the Y plane */ | ||
959 | if (args->src.height + args->src.top < 512-16) | ||
960 | itv->yuv_info.new_frame_info[frame].offset_y = 1; | ||
961 | else | ||
962 | itv->yuv_info.new_frame_info[frame].offset_y = 0; | ||
963 | |||
964 | /* Snapshot the osd pan info */ | ||
965 | itv->yuv_info.new_frame_info[frame].pan_x = itv->yuv_info.osd_x_pan; | ||
966 | itv->yuv_info.new_frame_info[frame].pan_y = itv->yuv_info.osd_y_pan; | ||
967 | itv->yuv_info.new_frame_info[frame].vis_w = itv->yuv_info.osd_vis_w; | ||
968 | itv->yuv_info.new_frame_info[frame].vis_h = itv->yuv_info.osd_vis_h; | ||
969 | |||
970 | itv->yuv_info.new_frame_info[frame].update = 0; | ||
971 | itv->yuv_info.new_frame_info[frame].interlaced_y = 0; | ||
972 | itv->yuv_info.new_frame_info[frame].interlaced_uv = 0; | ||
973 | |||
974 | if (memcmp (&itv->yuv_info.old_frame_info_args, &itv->yuv_info.new_frame_info[frame], | ||
975 | sizeof (itv->yuv_info.new_frame_info[frame]))) { | ||
976 | memcpy(&itv->yuv_info.old_frame_info_args, &itv->yuv_info.new_frame_info[frame], sizeof (itv->yuv_info.old_frame_info_args)); | ||
977 | itv->yuv_info.new_frame_info[frame].update = 1; | ||
978 | /* IVTV_DEBUG_YUV ("Requesting register update for frame %d\n",frame); */ | ||
979 | } | ||
980 | |||
981 | /* DMA the frame */ | ||
982 | mutex_lock(&itv->udma.lock); | ||
983 | |||
984 | if ((rc = ivtv_yuv_prep_user_dma(itv, &itv->udma, args)) != 0) { | ||
985 | mutex_unlock(&itv->udma.lock); | ||
986 | return rc; | ||
987 | } | ||
988 | |||
989 | ivtv_udma_prepare(itv); | ||
990 | prepare_to_wait(&itv->dma_waitq, &wait, TASK_INTERRUPTIBLE); | ||
991 | /* if no UDMA is pending and no UDMA is in progress, then the DMA | ||
992 | is finished */ | ||
993 | while (itv->i_flags & (IVTV_F_I_UDMA_PENDING | IVTV_F_I_UDMA)) { | ||
994 | /* don't interrupt if the DMA is in progress but break off | ||
995 | a still pending DMA. */ | ||
996 | got_sig = signal_pending(current); | ||
997 | if (got_sig && test_and_clear_bit(IVTV_F_I_UDMA_PENDING, &itv->i_flags)) | ||
998 | break; | ||
999 | got_sig = 0; | ||
1000 | schedule(); | ||
1001 | } | ||
1002 | finish_wait(&itv->dma_waitq, &wait); | ||
1003 | |||
1004 | /* Unmap Last DMA Xfer */ | ||
1005 | ivtv_udma_unmap(itv); | ||
1006 | |||
1007 | if (got_sig) { | ||
1008 | IVTV_DEBUG_INFO("User stopped YUV UDMA\n"); | ||
1009 | mutex_unlock(&itv->udma.lock); | ||
1010 | return -EINTR; | ||
1011 | } | ||
1012 | |||
1013 | atomic_set(&itv->yuv_info.next_fill_frame, next_fill_frame); | ||
1014 | |||
1015 | mutex_unlock(&itv->udma.lock); | ||
1016 | return rc; | ||
1017 | } | ||
1018 | |||
1019 | void ivtv_yuv_close(struct ivtv *itv) | ||
1020 | { | ||
1021 | int h_filter, v_filter_1, v_filter_2; | ||
1022 | |||
1023 | IVTV_DEBUG_YUV("ivtv_yuv_close\n"); | ||
1024 | ivtv_waitq(&itv->vsync_waitq); | ||
1025 | |||
1026 | atomic_set(&itv->yuv_info.next_dma_frame, -1); | ||
1027 | atomic_set(&itv->yuv_info.next_fill_frame, 0); | ||
1028 | |||
1029 | /* Reset registers we have changed so mpeg playback works */ | ||
1030 | |||
1031 | /* If we fully restore this register, the display may remain active. | ||
1032 | Restore, but set one bit to blank the video. Firmware will always | ||
1033 | clear this bit when needed, so not a problem. */ | ||
1034 | write_reg(itv->yuv_info.reg_2898 | 0x01000000, 0x2898); | ||
1035 | |||
1036 | write_reg(itv->yuv_info.reg_2834, 0x02834); | ||
1037 | write_reg(itv->yuv_info.reg_2838, 0x02838); | ||
1038 | write_reg(itv->yuv_info.reg_283c, 0x0283c); | ||
1039 | write_reg(itv->yuv_info.reg_2840, 0x02840); | ||
1040 | write_reg(itv->yuv_info.reg_2844, 0x02844); | ||
1041 | write_reg(itv->yuv_info.reg_2848, 0x02848); | ||
1042 | write_reg(itv->yuv_info.reg_2854, 0x02854); | ||
1043 | write_reg(itv->yuv_info.reg_285c, 0x0285c); | ||
1044 | write_reg(itv->yuv_info.reg_2864, 0x02864); | ||
1045 | write_reg(itv->yuv_info.reg_2870, 0x02870); | ||
1046 | write_reg(itv->yuv_info.reg_2874, 0x02874); | ||
1047 | write_reg(itv->yuv_info.reg_2890, 0x02890); | ||
1048 | write_reg(itv->yuv_info.reg_289c, 0x0289c); | ||
1049 | |||
1050 | write_reg(itv->yuv_info.reg_2918, 0x02918); | ||
1051 | write_reg(itv->yuv_info.reg_291c, 0x0291c); | ||
1052 | write_reg(itv->yuv_info.reg_2920, 0x02920); | ||
1053 | write_reg(itv->yuv_info.reg_2924, 0x02924); | ||
1054 | write_reg(itv->yuv_info.reg_2928, 0x02928); | ||
1055 | write_reg(itv->yuv_info.reg_292c, 0x0292c); | ||
1056 | write_reg(itv->yuv_info.reg_2930, 0x02930); | ||
1057 | write_reg(itv->yuv_info.reg_2934, 0x02934); | ||
1058 | write_reg(itv->yuv_info.reg_2938, 0x02938); | ||
1059 | write_reg(itv->yuv_info.reg_293c, 0x0293c); | ||
1060 | write_reg(itv->yuv_info.reg_2940, 0x02940); | ||
1061 | write_reg(itv->yuv_info.reg_2944, 0x02944); | ||
1062 | write_reg(itv->yuv_info.reg_2948, 0x02948); | ||
1063 | write_reg(itv->yuv_info.reg_294c, 0x0294c); | ||
1064 | write_reg(itv->yuv_info.reg_2950, 0x02950); | ||
1065 | write_reg(itv->yuv_info.reg_2954, 0x02954); | ||
1066 | write_reg(itv->yuv_info.reg_2958, 0x02958); | ||
1067 | write_reg(itv->yuv_info.reg_295c, 0x0295c); | ||
1068 | write_reg(itv->yuv_info.reg_2960, 0x02960); | ||
1069 | write_reg(itv->yuv_info.reg_2964, 0x02964); | ||
1070 | write_reg(itv->yuv_info.reg_2968, 0x02968); | ||
1071 | write_reg(itv->yuv_info.reg_296c, 0x0296c); | ||
1072 | write_reg(itv->yuv_info.reg_2970, 0x02970); | ||
1073 | |||
1074 | /* Prepare to restore filters */ | ||
1075 | |||
1076 | /* First the horizontal filter */ | ||
1077 | if ((itv->yuv_info.reg_2834 & 0x0000FFFF) == (itv->yuv_info.reg_2834 >> 16)) { | ||
1078 | /* An exact size match uses filter 0 */ | ||
1079 | h_filter = 0; | ||
1080 | } | ||
1081 | else { | ||
1082 | /* Figure out which filter to use */ | ||
1083 | h_filter = ((itv->yuv_info.reg_2834 << 16) / (itv->yuv_info.reg_2834 >> 16)) >> 15; | ||
1084 | h_filter = (h_filter >> 1) + (h_filter & 1); | ||
1085 | /* Only an exact size match can use filter 0. */ | ||
1086 | if (h_filter < 1) h_filter = 1; | ||
1087 | } | ||
1088 | |||
1089 | /* Now the vertical filter */ | ||
1090 | if ((itv->yuv_info.reg_2918 & 0x0000FFFF) == (itv->yuv_info.reg_2918 >> 16)) { | ||
1091 | /* An exact size match uses filter 0/1 */ | ||
1092 | v_filter_1 = 0; | ||
1093 | v_filter_2 = 1; | ||
1094 | } | ||
1095 | else { | ||
1096 | /* Figure out which filter to use */ | ||
1097 | v_filter_1 = ((itv->yuv_info.reg_2918 << 16) / (itv->yuv_info.reg_2918 >> 16)) >> 15; | ||
1098 | v_filter_1 = (v_filter_1 >> 1) + (v_filter_1 & 1); | ||
1099 | /* Only an exact size match can use filter 0 */ | ||
1100 | if (v_filter_1 == 0) v_filter_1 = 1; | ||
1101 | v_filter_2 = v_filter_1; | ||
1102 | } | ||
1103 | |||
1104 | /* Now restore the filters */ | ||
1105 | ivtv_yuv_filter (itv,h_filter,v_filter_1,v_filter_2); | ||
1106 | |||
1107 | /* and clear a few registers */ | ||
1108 | write_reg(0, 0x02814); | ||
1109 | write_reg(0, 0x0282c); | ||
1110 | write_reg(0, 0x02904); | ||
1111 | write_reg(0, 0x02910); | ||
1112 | |||
1113 | /* Release the blanking buffer */ | ||
1114 | if (itv->yuv_info.blanking_ptr) { | ||
1115 | kfree (itv->yuv_info.blanking_ptr); | ||
1116 | itv->yuv_info.blanking_ptr = NULL; | ||
1117 | pci_unmap_single(itv->dev, itv->yuv_info.blanking_dmaptr, 720*16, PCI_DMA_TODEVICE); | ||
1118 | } | ||
1119 | |||
1120 | /* Invalidate the old dimension information */ | ||
1121 | itv->yuv_info.old_frame_info.src_w = 0; | ||
1122 | itv->yuv_info.old_frame_info.src_h = 0; | ||
1123 | itv->yuv_info.old_frame_info_args.src_w = 0; | ||
1124 | itv->yuv_info.old_frame_info_args.src_h = 0; | ||
1125 | |||
1126 | /* All done. */ | ||
1127 | clear_bit(IVTV_F_I_DECODING_YUV, &itv->i_flags); | ||
1128 | } | ||
1129 | |||
diff --git a/drivers/media/video/ivtv/ivtv-yuv.h b/drivers/media/video/ivtv/ivtv-yuv.h new file mode 100644 index 000000000000..31128733e784 --- /dev/null +++ b/drivers/media/video/ivtv/ivtv-yuv.h | |||
@@ -0,0 +1,24 @@ | |||
1 | /* | ||
2 | yuv support | ||
3 | |||
4 | Copyright (C) 2007 Ian Armstrong <ian@iarmst.demon.co.uk> | ||
5 | |||
6 | This program is free software; you can redistribute it and/or modify | ||
7 | it under the terms of the GNU General Public License as published by | ||
8 | the Free Software Foundation; either version 2 of the License, or | ||
9 | (at your option) any later version. | ||
10 | |||
11 | This program is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program; if not, write to the Free Software | ||
18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | */ | ||
20 | |||
21 | int ivtv_yuv_filter_check(struct ivtv *itv); | ||
22 | int ivtv_yuv_prep_frame(struct ivtv *itv, struct ivtv_dma_frame *args); | ||
23 | void ivtv_yuv_close(struct ivtv *itv); | ||
24 | void ivtv_yuv_work_handler (struct work_struct *work); | ||
diff --git a/include/media/ivtv.h b/include/media/ivtv.h new file mode 100644 index 000000000000..412b48ea8eda --- /dev/null +++ b/include/media/ivtv.h | |||
@@ -0,0 +1,65 @@ | |||
1 | /* | ||
2 | Public ivtv API header | ||
3 | Copyright (C) 2003-2004 Kevin Thayer <nufan_wfk at yahoo.com> | ||
4 | Copyright (C) 2004-2007 Hans Verkuil <hverkuil@xs4all.nl> | ||
5 | |||
6 | This program is free software; you can redistribute it and/or modify | ||
7 | it under the terms of the GNU General Public License as published by | ||
8 | the Free Software Foundation; either version 2 of the License, or | ||
9 | (at your option) any later version. | ||
10 | |||
11 | This program is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program; if not, write to the Free Software | ||
18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | */ | ||
20 | |||
21 | #ifndef _LINUX_IVTV_H | ||
22 | #define _LINUX_IVTV_H | ||
23 | |||
24 | /* ivtv knows several distinct output modes: MPEG streaming, | ||
25 | YUV streaming, YUV updates through user DMA and the passthrough | ||
26 | mode. | ||
27 | |||
28 | In order to clearly tell the driver that we are in user DMA | ||
29 | YUV mode you need to call IVTV_IOC_DMA_FRAME with y_source == NULL | ||
30 | first (althrough if you don't then the first time | ||
31 | DMA_FRAME is called the mode switch is done automatically). | ||
32 | |||
33 | When you close the file handle the user DMA mode is exited again. | ||
34 | |||
35 | While in one mode, you cannot use another mode (EBUSY is returned). | ||
36 | |||
37 | All this means that if you want to change the YUV interlacing | ||
38 | for the user DMA YUV mode you first need to do call IVTV_IOC_DMA_FRAME | ||
39 | with y_source == NULL before you can set the correct format using | ||
40 | VIDIOC_S_FMT. | ||
41 | |||
42 | Eventually all this should be replaced with a proper V4L2 API, | ||
43 | but for now we have to do it this way. */ | ||
44 | |||
45 | struct ivtv_dma_frame { | ||
46 | enum v4l2_buf_type type; /* V4L2_BUF_TYPE_VIDEO_OUTPUT */ | ||
47 | __u32 pixelformat; /* 0 == same as destination */ | ||
48 | void __user *y_source; /* if NULL and type == V4L2_BUF_TYPE_VIDEO_OUTPUT, | ||
49 | then just switch to user DMA YUV output mode */ | ||
50 | void __user *uv_source; /* Unused for RGB pixelformats */ | ||
51 | struct v4l2_rect src; | ||
52 | struct v4l2_rect dst; | ||
53 | __u32 src_width; | ||
54 | __u32 src_height; | ||
55 | }; | ||
56 | |||
57 | #define IVTV_IOC_DMA_FRAME _IOW ('V', BASE_VIDIOC_PRIVATE+0, struct ivtv_dma_frame) | ||
58 | |||
59 | /* These are the VBI types as they appear in the embedded VBI private packets. */ | ||
60 | #define IVTV_SLICED_TYPE_TELETEXT_B (1) | ||
61 | #define IVTV_SLICED_TYPE_CAPTION_525 (4) | ||
62 | #define IVTV_SLICED_TYPE_WSS_625 (5) | ||
63 | #define IVTV_SLICED_TYPE_VPS (7) | ||
64 | |||
65 | #endif /* _LINUX_IVTV_H */ | ||