diff options
Diffstat (limited to 'drivers/media/video/cx18/cx18-controls.c')
-rw-r--r-- | drivers/media/video/cx18/cx18-controls.c | 131 |
1 files changed, 131 insertions, 0 deletions
diff --git a/drivers/media/video/cx18/cx18-controls.c b/drivers/media/video/cx18/cx18-controls.c new file mode 100644 index 00000000000..282a3d29fda --- /dev/null +++ b/drivers/media/video/cx18/cx18-controls.c | |||
@@ -0,0 +1,131 @@ | |||
1 | /* | ||
2 | * cx18 ioctl control functions | ||
3 | * | ||
4 | * Derived from ivtv-controls.c | ||
5 | * | ||
6 | * Copyright (C) 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 | ||
21 | * 02111-1307 USA | ||
22 | */ | ||
23 | #include <linux/kernel.h> | ||
24 | #include <linux/slab.h> | ||
25 | |||
26 | #include "cx18-driver.h" | ||
27 | #include "cx18-cards.h" | ||
28 | #include "cx18-ioctl.h" | ||
29 | #include "cx18-audio.h" | ||
30 | #include "cx18-mailbox.h" | ||
31 | #include "cx18-controls.h" | ||
32 | |||
33 | static int cx18_s_stream_vbi_fmt(struct cx2341x_handler *cxhdl, u32 fmt) | ||
34 | { | ||
35 | struct cx18 *cx = container_of(cxhdl, struct cx18, cxhdl); | ||
36 | int type = cxhdl->stream_type->val; | ||
37 | |||
38 | if (atomic_read(&cx->ana_capturing) > 0) | ||
39 | return -EBUSY; | ||
40 | |||
41 | if (fmt != V4L2_MPEG_STREAM_VBI_FMT_IVTV || | ||
42 | !(type == V4L2_MPEG_STREAM_TYPE_MPEG2_PS || | ||
43 | type == V4L2_MPEG_STREAM_TYPE_MPEG2_DVD || | ||
44 | type == V4L2_MPEG_STREAM_TYPE_MPEG2_SVCD)) { | ||
45 | /* Only IVTV fmt VBI insertion & only MPEG-2 PS type streams */ | ||
46 | cx->vbi.insert_mpeg = V4L2_MPEG_STREAM_VBI_FMT_NONE; | ||
47 | CX18_DEBUG_INFO("disabled insertion of sliced VBI data into " | ||
48 | "the MPEG stream\n"); | ||
49 | return 0; | ||
50 | } | ||
51 | |||
52 | /* Allocate sliced VBI buffers if needed. */ | ||
53 | if (cx->vbi.sliced_mpeg_data[0] == NULL) { | ||
54 | int i; | ||
55 | |||
56 | for (i = 0; i < CX18_VBI_FRAMES; i++) { | ||
57 | cx->vbi.sliced_mpeg_data[i] = | ||
58 | kmalloc(CX18_SLICED_MPEG_DATA_BUFSZ, GFP_KERNEL); | ||
59 | if (cx->vbi.sliced_mpeg_data[i] == NULL) { | ||
60 | while (--i >= 0) { | ||
61 | kfree(cx->vbi.sliced_mpeg_data[i]); | ||
62 | cx->vbi.sliced_mpeg_data[i] = NULL; | ||
63 | } | ||
64 | cx->vbi.insert_mpeg = | ||
65 | V4L2_MPEG_STREAM_VBI_FMT_NONE; | ||
66 | CX18_WARN("Unable to allocate buffers for " | ||
67 | "sliced VBI data insertion\n"); | ||
68 | return -ENOMEM; | ||
69 | } | ||
70 | } | ||
71 | } | ||
72 | |||
73 | cx->vbi.insert_mpeg = fmt; | ||
74 | CX18_DEBUG_INFO("enabled insertion of sliced VBI data into the MPEG PS," | ||
75 | "when sliced VBI is enabled\n"); | ||
76 | |||
77 | /* | ||
78 | * If our current settings have no lines set for capture, store a valid, | ||
79 | * default set of service lines to capture, in our current settings. | ||
80 | */ | ||
81 | if (cx18_get_service_set(cx->vbi.sliced_in) == 0) { | ||
82 | if (cx->is_60hz) | ||
83 | cx->vbi.sliced_in->service_set = | ||
84 | V4L2_SLICED_CAPTION_525; | ||
85 | else | ||
86 | cx->vbi.sliced_in->service_set = V4L2_SLICED_WSS_625; | ||
87 | cx18_expand_service_set(cx->vbi.sliced_in, cx->is_50hz); | ||
88 | } | ||
89 | return 0; | ||
90 | } | ||
91 | |||
92 | static int cx18_s_video_encoding(struct cx2341x_handler *cxhdl, u32 val) | ||
93 | { | ||
94 | struct cx18 *cx = container_of(cxhdl, struct cx18, cxhdl); | ||
95 | int is_mpeg1 = val == V4L2_MPEG_VIDEO_ENCODING_MPEG_1; | ||
96 | struct v4l2_mbus_framefmt fmt; | ||
97 | |||
98 | /* fix videodecoder resolution */ | ||
99 | fmt.width = cxhdl->width / (is_mpeg1 ? 2 : 1); | ||
100 | fmt.height = cxhdl->height; | ||
101 | fmt.code = V4L2_MBUS_FMT_FIXED; | ||
102 | v4l2_subdev_call(cx->sd_av, video, s_mbus_fmt, &fmt); | ||
103 | return 0; | ||
104 | } | ||
105 | |||
106 | static int cx18_s_audio_sampling_freq(struct cx2341x_handler *cxhdl, u32 idx) | ||
107 | { | ||
108 | static const u32 freqs[3] = { 44100, 48000, 32000 }; | ||
109 | struct cx18 *cx = container_of(cxhdl, struct cx18, cxhdl); | ||
110 | |||
111 | /* The audio clock of the digitizer must match the codec sample | ||
112 | rate otherwise you get some very strange effects. */ | ||
113 | if (idx < ARRAY_SIZE(freqs)) | ||
114 | cx18_call_all(cx, audio, s_clock_freq, freqs[idx]); | ||
115 | return 0; | ||
116 | } | ||
117 | |||
118 | static int cx18_s_audio_mode(struct cx2341x_handler *cxhdl, u32 val) | ||
119 | { | ||
120 | struct cx18 *cx = container_of(cxhdl, struct cx18, cxhdl); | ||
121 | |||
122 | cx->dualwatch_stereo_mode = val; | ||
123 | return 0; | ||
124 | } | ||
125 | |||
126 | struct cx2341x_handler_ops cx18_cxhdl_ops = { | ||
127 | .s_audio_mode = cx18_s_audio_mode, | ||
128 | .s_audio_sampling_freq = cx18_s_audio_sampling_freq, | ||
129 | .s_video_encoding = cx18_s_video_encoding, | ||
130 | .s_stream_vbi_fmt = cx18_s_stream_vbi_fmt, | ||
131 | }; | ||