diff options
author | Ondrej Zary <linux@rainbow-software.org> | 2013-07-28 15:01:44 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <m.chehab@samsung.com> | 2013-08-18 07:09:59 -0400 |
commit | 338c658a646721e94ca827c74163703612e164c5 (patch) | |
tree | 7e245f2ea24b0ff43927023527eb8b2b43c826d6 /sound | |
parent | 59b564599bc66f086856b09e480f89555d47b35c (diff) |
[media] tea575x: Move from sound to media
Move tea575x from sound/i2c/other to drivers/media/radio
Includes Kconfig changes by Hans Verkuil.
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Ondrej Zary <linux@rainbow-software.org>
Acked-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
Diffstat (limited to 'sound')
-rw-r--r-- | sound/i2c/other/Makefile | 2 | ||||
-rw-r--r-- | sound/i2c/other/tea575x-tuner.c | 584 | ||||
-rw-r--r-- | sound/pci/Kconfig | 9 |
3 files changed, 4 insertions, 591 deletions
diff --git a/sound/i2c/other/Makefile b/sound/i2c/other/Makefile index c95d8f1aae87..5526b03b95a2 100644 --- a/sound/i2c/other/Makefile +++ b/sound/i2c/other/Makefile | |||
@@ -8,10 +8,8 @@ snd-ak4117-objs := ak4117.o | |||
8 | snd-ak4113-objs := ak4113.o | 8 | snd-ak4113-objs := ak4113.o |
9 | snd-ak4xxx-adda-objs := ak4xxx-adda.o | 9 | snd-ak4xxx-adda-objs := ak4xxx-adda.o |
10 | snd-pt2258-objs := pt2258.o | 10 | snd-pt2258-objs := pt2258.o |
11 | snd-tea575x-tuner-objs := tea575x-tuner.o | ||
12 | 11 | ||
13 | # Module Dependency | 12 | # Module Dependency |
14 | obj-$(CONFIG_SND_PDAUDIOCF) += snd-ak4117.o | 13 | obj-$(CONFIG_SND_PDAUDIOCF) += snd-ak4117.o |
15 | obj-$(CONFIG_SND_ICE1712) += snd-ak4xxx-adda.o | 14 | obj-$(CONFIG_SND_ICE1712) += snd-ak4xxx-adda.o |
16 | obj-$(CONFIG_SND_ICE1724) += snd-ak4114.o snd-ak4113.o snd-ak4xxx-adda.o snd-pt2258.o | 15 | obj-$(CONFIG_SND_ICE1724) += snd-ak4114.o snd-ak4113.o snd-ak4xxx-adda.o snd-pt2258.o |
17 | obj-$(CONFIG_SND_TEA575X) += snd-tea575x-tuner.o | ||
diff --git a/sound/i2c/other/tea575x-tuner.c b/sound/i2c/other/tea575x-tuner.c deleted file mode 100644 index cef06981b7c9..000000000000 --- a/sound/i2c/other/tea575x-tuner.c +++ /dev/null | |||
@@ -1,584 +0,0 @@ | |||
1 | /* | ||
2 | * ALSA driver for TEA5757/5759 Philips AM/FM radio tuner chips | ||
3 | * | ||
4 | * Copyright (c) 2004 Jaroslav Kysela <perex@perex.cz> | ||
5 | * | ||
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 | |||
23 | #include <asm/io.h> | ||
24 | #include <linux/delay.h> | ||
25 | #include <linux/module.h> | ||
26 | #include <linux/init.h> | ||
27 | #include <linux/slab.h> | ||
28 | #include <linux/sched.h> | ||
29 | #include <media/v4l2-device.h> | ||
30 | #include <media/v4l2-dev.h> | ||
31 | #include <media/v4l2-fh.h> | ||
32 | #include <media/v4l2-ioctl.h> | ||
33 | #include <media/v4l2-event.h> | ||
34 | #include <media/tea575x.h> | ||
35 | |||
36 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); | ||
37 | MODULE_DESCRIPTION("Routines for control of TEA5757/5759 Philips AM/FM radio tuner chips"); | ||
38 | MODULE_LICENSE("GPL"); | ||
39 | |||
40 | /* | ||
41 | * definitions | ||
42 | */ | ||
43 | |||
44 | #define TEA575X_BIT_SEARCH (1<<24) /* 1 = search action, 0 = tuned */ | ||
45 | #define TEA575X_BIT_UPDOWN (1<<23) /* 0 = search down, 1 = search up */ | ||
46 | #define TEA575X_BIT_MONO (1<<22) /* 0 = stereo, 1 = mono */ | ||
47 | #define TEA575X_BIT_BAND_MASK (3<<20) | ||
48 | #define TEA575X_BIT_BAND_FM (0<<20) | ||
49 | #define TEA575X_BIT_BAND_MW (1<<20) | ||
50 | #define TEA575X_BIT_BAND_LW (2<<20) | ||
51 | #define TEA575X_BIT_BAND_SW (3<<20) | ||
52 | #define TEA575X_BIT_PORT_0 (1<<19) /* user bit */ | ||
53 | #define TEA575X_BIT_PORT_1 (1<<18) /* user bit */ | ||
54 | #define TEA575X_BIT_SEARCH_MASK (3<<16) /* search level */ | ||
55 | #define TEA575X_BIT_SEARCH_5_28 (0<<16) /* FM >5uV, AM >28uV */ | ||
56 | #define TEA575X_BIT_SEARCH_10_40 (1<<16) /* FM >10uV, AM > 40uV */ | ||
57 | #define TEA575X_BIT_SEARCH_30_63 (2<<16) /* FM >30uV, AM > 63uV */ | ||
58 | #define TEA575X_BIT_SEARCH_150_1000 (3<<16) /* FM > 150uV, AM > 1000uV */ | ||
59 | #define TEA575X_BIT_DUMMY (1<<15) /* buffer */ | ||
60 | #define TEA575X_BIT_FREQ_MASK 0x7fff | ||
61 | |||
62 | enum { BAND_FM, BAND_FM_JAPAN, BAND_AM }; | ||
63 | |||
64 | static const struct v4l2_frequency_band bands[] = { | ||
65 | { | ||
66 | .type = V4L2_TUNER_RADIO, | ||
67 | .index = 0, | ||
68 | .capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO | | ||
69 | V4L2_TUNER_CAP_FREQ_BANDS, | ||
70 | .rangelow = 87500 * 16, | ||
71 | .rangehigh = 108000 * 16, | ||
72 | .modulation = V4L2_BAND_MODULATION_FM, | ||
73 | }, | ||
74 | { | ||
75 | .type = V4L2_TUNER_RADIO, | ||
76 | .index = 0, | ||
77 | .capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO | | ||
78 | V4L2_TUNER_CAP_FREQ_BANDS, | ||
79 | .rangelow = 76000 * 16, | ||
80 | .rangehigh = 91000 * 16, | ||
81 | .modulation = V4L2_BAND_MODULATION_FM, | ||
82 | }, | ||
83 | { | ||
84 | .type = V4L2_TUNER_RADIO, | ||
85 | .index = 1, | ||
86 | .capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_FREQ_BANDS, | ||
87 | .rangelow = 530 * 16, | ||
88 | .rangehigh = 1710 * 16, | ||
89 | .modulation = V4L2_BAND_MODULATION_AM, | ||
90 | }, | ||
91 | }; | ||
92 | |||
93 | /* | ||
94 | * lowlevel part | ||
95 | */ | ||
96 | |||
97 | static void snd_tea575x_write(struct snd_tea575x *tea, unsigned int val) | ||
98 | { | ||
99 | u16 l; | ||
100 | u8 data; | ||
101 | |||
102 | if (tea->ops->write_val) | ||
103 | return tea->ops->write_val(tea, val); | ||
104 | |||
105 | tea->ops->set_direction(tea, 1); | ||
106 | udelay(16); | ||
107 | |||
108 | for (l = 25; l > 0; l--) { | ||
109 | data = (val >> 24) & TEA575X_DATA; | ||
110 | val <<= 1; /* shift data */ | ||
111 | tea->ops->set_pins(tea, data | TEA575X_WREN); | ||
112 | udelay(2); | ||
113 | tea->ops->set_pins(tea, data | TEA575X_WREN | TEA575X_CLK); | ||
114 | udelay(2); | ||
115 | tea->ops->set_pins(tea, data | TEA575X_WREN); | ||
116 | udelay(2); | ||
117 | } | ||
118 | |||
119 | if (!tea->mute) | ||
120 | tea->ops->set_pins(tea, 0); | ||
121 | } | ||
122 | |||
123 | static u32 snd_tea575x_read(struct snd_tea575x *tea) | ||
124 | { | ||
125 | u16 l, rdata; | ||
126 | u32 data = 0; | ||
127 | |||
128 | if (tea->ops->read_val) | ||
129 | return tea->ops->read_val(tea); | ||
130 | |||
131 | tea->ops->set_direction(tea, 0); | ||
132 | tea->ops->set_pins(tea, 0); | ||
133 | udelay(16); | ||
134 | |||
135 | for (l = 24; l--;) { | ||
136 | tea->ops->set_pins(tea, TEA575X_CLK); | ||
137 | udelay(2); | ||
138 | if (!l) | ||
139 | tea->tuned = tea->ops->get_pins(tea) & TEA575X_MOST ? 0 : 1; | ||
140 | tea->ops->set_pins(tea, 0); | ||
141 | udelay(2); | ||
142 | data <<= 1; /* shift data */ | ||
143 | rdata = tea->ops->get_pins(tea); | ||
144 | if (!l) | ||
145 | tea->stereo = (rdata & TEA575X_MOST) ? 0 : 1; | ||
146 | if (rdata & TEA575X_DATA) | ||
147 | data++; | ||
148 | udelay(2); | ||
149 | } | ||
150 | |||
151 | if (tea->mute) | ||
152 | tea->ops->set_pins(tea, TEA575X_WREN); | ||
153 | |||
154 | return data; | ||
155 | } | ||
156 | |||
157 | static u32 snd_tea575x_val_to_freq(struct snd_tea575x *tea, u32 val) | ||
158 | { | ||
159 | u32 freq = val & TEA575X_BIT_FREQ_MASK; | ||
160 | |||
161 | if (freq == 0) | ||
162 | return freq; | ||
163 | |||
164 | switch (tea->band) { | ||
165 | case BAND_FM: | ||
166 | /* freq *= 12.5 */ | ||
167 | freq *= 125; | ||
168 | freq /= 10; | ||
169 | /* crystal fixup */ | ||
170 | freq -= TEA575X_FMIF; | ||
171 | break; | ||
172 | case BAND_FM_JAPAN: | ||
173 | /* freq *= 12.5 */ | ||
174 | freq *= 125; | ||
175 | freq /= 10; | ||
176 | /* crystal fixup */ | ||
177 | freq += TEA575X_FMIF; | ||
178 | break; | ||
179 | case BAND_AM: | ||
180 | /* crystal fixup */ | ||
181 | freq -= TEA575X_AMIF; | ||
182 | break; | ||
183 | } | ||
184 | |||
185 | return clamp(freq * 16, bands[tea->band].rangelow, | ||
186 | bands[tea->band].rangehigh); /* from kHz */ | ||
187 | } | ||
188 | |||
189 | static u32 snd_tea575x_get_freq(struct snd_tea575x *tea) | ||
190 | { | ||
191 | return snd_tea575x_val_to_freq(tea, snd_tea575x_read(tea)); | ||
192 | } | ||
193 | |||
194 | void snd_tea575x_set_freq(struct snd_tea575x *tea) | ||
195 | { | ||
196 | u32 freq = tea->freq / 16; /* to kHz */ | ||
197 | u32 band = 0; | ||
198 | |||
199 | switch (tea->band) { | ||
200 | case BAND_FM: | ||
201 | band = TEA575X_BIT_BAND_FM; | ||
202 | /* crystal fixup */ | ||
203 | freq += TEA575X_FMIF; | ||
204 | /* freq /= 12.5 */ | ||
205 | freq *= 10; | ||
206 | freq /= 125; | ||
207 | break; | ||
208 | case BAND_FM_JAPAN: | ||
209 | band = TEA575X_BIT_BAND_FM; | ||
210 | /* crystal fixup */ | ||
211 | freq -= TEA575X_FMIF; | ||
212 | /* freq /= 12.5 */ | ||
213 | freq *= 10; | ||
214 | freq /= 125; | ||
215 | break; | ||
216 | case BAND_AM: | ||
217 | band = TEA575X_BIT_BAND_MW; | ||
218 | /* crystal fixup */ | ||
219 | freq += TEA575X_AMIF; | ||
220 | break; | ||
221 | } | ||
222 | |||
223 | tea->val &= ~(TEA575X_BIT_FREQ_MASK | TEA575X_BIT_BAND_MASK); | ||
224 | tea->val |= band; | ||
225 | tea->val |= freq & TEA575X_BIT_FREQ_MASK; | ||
226 | snd_tea575x_write(tea, tea->val); | ||
227 | tea->freq = snd_tea575x_val_to_freq(tea, tea->val); | ||
228 | } | ||
229 | |||
230 | /* | ||
231 | * Linux Video interface | ||
232 | */ | ||
233 | |||
234 | static int vidioc_querycap(struct file *file, void *priv, | ||
235 | struct v4l2_capability *v) | ||
236 | { | ||
237 | struct snd_tea575x *tea = video_drvdata(file); | ||
238 | |||
239 | strlcpy(v->driver, tea->v4l2_dev->name, sizeof(v->driver)); | ||
240 | strlcpy(v->card, tea->card, sizeof(v->card)); | ||
241 | strlcat(v->card, tea->tea5759 ? " TEA5759" : " TEA5757", sizeof(v->card)); | ||
242 | strlcpy(v->bus_info, tea->bus_info, sizeof(v->bus_info)); | ||
243 | v->device_caps = V4L2_CAP_TUNER | V4L2_CAP_RADIO; | ||
244 | if (!tea->cannot_read_data) | ||
245 | v->device_caps |= V4L2_CAP_HW_FREQ_SEEK; | ||
246 | v->capabilities = v->device_caps | V4L2_CAP_DEVICE_CAPS; | ||
247 | return 0; | ||
248 | } | ||
249 | |||
250 | static int vidioc_enum_freq_bands(struct file *file, void *priv, | ||
251 | struct v4l2_frequency_band *band) | ||
252 | { | ||
253 | struct snd_tea575x *tea = video_drvdata(file); | ||
254 | int index; | ||
255 | |||
256 | if (band->tuner != 0) | ||
257 | return -EINVAL; | ||
258 | |||
259 | switch (band->index) { | ||
260 | case 0: | ||
261 | if (tea->tea5759) | ||
262 | index = BAND_FM_JAPAN; | ||
263 | else | ||
264 | index = BAND_FM; | ||
265 | break; | ||
266 | case 1: | ||
267 | if (tea->has_am) { | ||
268 | index = BAND_AM; | ||
269 | break; | ||
270 | } | ||
271 | /* Fall through */ | ||
272 | default: | ||
273 | return -EINVAL; | ||
274 | } | ||
275 | |||
276 | *band = bands[index]; | ||
277 | if (!tea->cannot_read_data) | ||
278 | band->capability |= V4L2_TUNER_CAP_HWSEEK_BOUNDED; | ||
279 | |||
280 | return 0; | ||
281 | } | ||
282 | |||
283 | static int vidioc_g_tuner(struct file *file, void *priv, | ||
284 | struct v4l2_tuner *v) | ||
285 | { | ||
286 | struct snd_tea575x *tea = video_drvdata(file); | ||
287 | struct v4l2_frequency_band band_fm = { 0, }; | ||
288 | |||
289 | if (v->index > 0) | ||
290 | return -EINVAL; | ||
291 | |||
292 | snd_tea575x_read(tea); | ||
293 | vidioc_enum_freq_bands(file, priv, &band_fm); | ||
294 | |||
295 | memset(v, 0, sizeof(*v)); | ||
296 | strlcpy(v->name, tea->has_am ? "FM/AM" : "FM", sizeof(v->name)); | ||
297 | v->type = V4L2_TUNER_RADIO; | ||
298 | v->capability = band_fm.capability; | ||
299 | v->rangelow = tea->has_am ? bands[BAND_AM].rangelow : band_fm.rangelow; | ||
300 | v->rangehigh = band_fm.rangehigh; | ||
301 | v->rxsubchans = tea->stereo ? V4L2_TUNER_SUB_STEREO : V4L2_TUNER_SUB_MONO; | ||
302 | v->audmode = (tea->val & TEA575X_BIT_MONO) ? | ||
303 | V4L2_TUNER_MODE_MONO : V4L2_TUNER_MODE_STEREO; | ||
304 | v->signal = tea->tuned ? 0xffff : 0; | ||
305 | return 0; | ||
306 | } | ||
307 | |||
308 | static int vidioc_s_tuner(struct file *file, void *priv, | ||
309 | const struct v4l2_tuner *v) | ||
310 | { | ||
311 | struct snd_tea575x *tea = video_drvdata(file); | ||
312 | u32 orig_val = tea->val; | ||
313 | |||
314 | if (v->index) | ||
315 | return -EINVAL; | ||
316 | tea->val &= ~TEA575X_BIT_MONO; | ||
317 | if (v->audmode == V4L2_TUNER_MODE_MONO) | ||
318 | tea->val |= TEA575X_BIT_MONO; | ||
319 | /* Only apply changes if currently tuning FM */ | ||
320 | if (tea->band != BAND_AM && tea->val != orig_val) | ||
321 | snd_tea575x_set_freq(tea); | ||
322 | |||
323 | return 0; | ||
324 | } | ||
325 | |||
326 | static int vidioc_g_frequency(struct file *file, void *priv, | ||
327 | struct v4l2_frequency *f) | ||
328 | { | ||
329 | struct snd_tea575x *tea = video_drvdata(file); | ||
330 | |||
331 | if (f->tuner != 0) | ||
332 | return -EINVAL; | ||
333 | f->type = V4L2_TUNER_RADIO; | ||
334 | f->frequency = tea->freq; | ||
335 | return 0; | ||
336 | } | ||
337 | |||
338 | static int vidioc_s_frequency(struct file *file, void *priv, | ||
339 | const struct v4l2_frequency *f) | ||
340 | { | ||
341 | struct snd_tea575x *tea = video_drvdata(file); | ||
342 | |||
343 | if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO) | ||
344 | return -EINVAL; | ||
345 | |||
346 | if (tea->has_am && f->frequency < (20000 * 16)) | ||
347 | tea->band = BAND_AM; | ||
348 | else if (tea->tea5759) | ||
349 | tea->band = BAND_FM_JAPAN; | ||
350 | else | ||
351 | tea->band = BAND_FM; | ||
352 | |||
353 | tea->freq = clamp_t(u32, f->frequency, bands[tea->band].rangelow, | ||
354 | bands[tea->band].rangehigh); | ||
355 | snd_tea575x_set_freq(tea); | ||
356 | return 0; | ||
357 | } | ||
358 | |||
359 | static int vidioc_s_hw_freq_seek(struct file *file, void *fh, | ||
360 | const struct v4l2_hw_freq_seek *a) | ||
361 | { | ||
362 | struct snd_tea575x *tea = video_drvdata(file); | ||
363 | unsigned long timeout; | ||
364 | int i, spacing; | ||
365 | |||
366 | if (tea->cannot_read_data) | ||
367 | return -ENOTTY; | ||
368 | if (a->tuner || a->wrap_around) | ||
369 | return -EINVAL; | ||
370 | |||
371 | if (file->f_flags & O_NONBLOCK) | ||
372 | return -EWOULDBLOCK; | ||
373 | |||
374 | if (a->rangelow || a->rangehigh) { | ||
375 | for (i = 0; i < ARRAY_SIZE(bands); i++) { | ||
376 | if ((i == BAND_FM && tea->tea5759) || | ||
377 | (i == BAND_FM_JAPAN && !tea->tea5759) || | ||
378 | (i == BAND_AM && !tea->has_am)) | ||
379 | continue; | ||
380 | if (bands[i].rangelow == a->rangelow && | ||
381 | bands[i].rangehigh == a->rangehigh) | ||
382 | break; | ||
383 | } | ||
384 | if (i == ARRAY_SIZE(bands)) | ||
385 | return -EINVAL; /* No matching band found */ | ||
386 | if (i != tea->band) { | ||
387 | tea->band = i; | ||
388 | tea->freq = clamp(tea->freq, bands[i].rangelow, | ||
389 | bands[i].rangehigh); | ||
390 | snd_tea575x_set_freq(tea); | ||
391 | } | ||
392 | } | ||
393 | |||
394 | spacing = (tea->band == BAND_AM) ? 5 : 50; /* kHz */ | ||
395 | |||
396 | /* clear the frequency, HW will fill it in */ | ||
397 | tea->val &= ~TEA575X_BIT_FREQ_MASK; | ||
398 | tea->val |= TEA575X_BIT_SEARCH; | ||
399 | if (a->seek_upward) | ||
400 | tea->val |= TEA575X_BIT_UPDOWN; | ||
401 | else | ||
402 | tea->val &= ~TEA575X_BIT_UPDOWN; | ||
403 | snd_tea575x_write(tea, tea->val); | ||
404 | timeout = jiffies + msecs_to_jiffies(10000); | ||
405 | for (;;) { | ||
406 | if (time_after(jiffies, timeout)) | ||
407 | break; | ||
408 | if (schedule_timeout_interruptible(msecs_to_jiffies(10))) { | ||
409 | /* some signal arrived, stop search */ | ||
410 | tea->val &= ~TEA575X_BIT_SEARCH; | ||
411 | snd_tea575x_set_freq(tea); | ||
412 | return -ERESTARTSYS; | ||
413 | } | ||
414 | if (!(snd_tea575x_read(tea) & TEA575X_BIT_SEARCH)) { | ||
415 | u32 freq; | ||
416 | |||
417 | /* Found a frequency, wait until it can be read */ | ||
418 | for (i = 0; i < 100; i++) { | ||
419 | msleep(10); | ||
420 | freq = snd_tea575x_get_freq(tea); | ||
421 | if (freq) /* available */ | ||
422 | break; | ||
423 | } | ||
424 | if (freq == 0) /* shouldn't happen */ | ||
425 | break; | ||
426 | /* | ||
427 | * if we moved by less than the spacing, or in the | ||
428 | * wrong direction, continue seeking | ||
429 | */ | ||
430 | if (abs(tea->freq - freq) < 16 * spacing || | ||
431 | (a->seek_upward && freq < tea->freq) || | ||
432 | (!a->seek_upward && freq > tea->freq)) { | ||
433 | snd_tea575x_write(tea, tea->val); | ||
434 | continue; | ||
435 | } | ||
436 | tea->freq = freq; | ||
437 | tea->val &= ~TEA575X_BIT_SEARCH; | ||
438 | return 0; | ||
439 | } | ||
440 | } | ||
441 | tea->val &= ~TEA575X_BIT_SEARCH; | ||
442 | snd_tea575x_set_freq(tea); | ||
443 | return -ENODATA; | ||
444 | } | ||
445 | |||
446 | static int tea575x_s_ctrl(struct v4l2_ctrl *ctrl) | ||
447 | { | ||
448 | struct snd_tea575x *tea = container_of(ctrl->handler, struct snd_tea575x, ctrl_handler); | ||
449 | |||
450 | switch (ctrl->id) { | ||
451 | case V4L2_CID_AUDIO_MUTE: | ||
452 | tea->mute = ctrl->val; | ||
453 | snd_tea575x_set_freq(tea); | ||
454 | return 0; | ||
455 | } | ||
456 | |||
457 | return -EINVAL; | ||
458 | } | ||
459 | |||
460 | static const struct v4l2_file_operations tea575x_fops = { | ||
461 | .unlocked_ioctl = video_ioctl2, | ||
462 | .open = v4l2_fh_open, | ||
463 | .release = v4l2_fh_release, | ||
464 | .poll = v4l2_ctrl_poll, | ||
465 | }; | ||
466 | |||
467 | static const struct v4l2_ioctl_ops tea575x_ioctl_ops = { | ||
468 | .vidioc_querycap = vidioc_querycap, | ||
469 | .vidioc_g_tuner = vidioc_g_tuner, | ||
470 | .vidioc_s_tuner = vidioc_s_tuner, | ||
471 | .vidioc_g_frequency = vidioc_g_frequency, | ||
472 | .vidioc_s_frequency = vidioc_s_frequency, | ||
473 | .vidioc_s_hw_freq_seek = vidioc_s_hw_freq_seek, | ||
474 | .vidioc_enum_freq_bands = vidioc_enum_freq_bands, | ||
475 | .vidioc_log_status = v4l2_ctrl_log_status, | ||
476 | .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, | ||
477 | .vidioc_unsubscribe_event = v4l2_event_unsubscribe, | ||
478 | }; | ||
479 | |||
480 | static const struct video_device tea575x_radio = { | ||
481 | .ioctl_ops = &tea575x_ioctl_ops, | ||
482 | .release = video_device_release_empty, | ||
483 | }; | ||
484 | |||
485 | static const struct v4l2_ctrl_ops tea575x_ctrl_ops = { | ||
486 | .s_ctrl = tea575x_s_ctrl, | ||
487 | }; | ||
488 | |||
489 | |||
490 | int snd_tea575x_hw_init(struct snd_tea575x *tea) | ||
491 | { | ||
492 | tea->mute = true; | ||
493 | |||
494 | /* Not all devices can or know how to read the data back. | ||
495 | Such devices can set cannot_read_data to true. */ | ||
496 | if (!tea->cannot_read_data) { | ||
497 | snd_tea575x_write(tea, 0x55AA); | ||
498 | if (snd_tea575x_read(tea) != 0x55AA) | ||
499 | return -ENODEV; | ||
500 | } | ||
501 | |||
502 | tea->val = TEA575X_BIT_BAND_FM | TEA575X_BIT_SEARCH_5_28; | ||
503 | tea->freq = 90500 * 16; /* 90.5Mhz default */ | ||
504 | snd_tea575x_set_freq(tea); | ||
505 | |||
506 | return 0; | ||
507 | } | ||
508 | EXPORT_SYMBOL(snd_tea575x_hw_init); | ||
509 | |||
510 | int snd_tea575x_init(struct snd_tea575x *tea, struct module *owner) | ||
511 | { | ||
512 | int retval = snd_tea575x_hw_init(tea); | ||
513 | |||
514 | if (retval) | ||
515 | return retval; | ||
516 | |||
517 | tea->vd = tea575x_radio; | ||
518 | video_set_drvdata(&tea->vd, tea); | ||
519 | mutex_init(&tea->mutex); | ||
520 | strlcpy(tea->vd.name, tea->v4l2_dev->name, sizeof(tea->vd.name)); | ||
521 | tea->vd.lock = &tea->mutex; | ||
522 | tea->vd.v4l2_dev = tea->v4l2_dev; | ||
523 | tea->fops = tea575x_fops; | ||
524 | tea->fops.owner = owner; | ||
525 | tea->vd.fops = &tea->fops; | ||
526 | set_bit(V4L2_FL_USE_FH_PRIO, &tea->vd.flags); | ||
527 | /* disable hw_freq_seek if we can't use it */ | ||
528 | if (tea->cannot_read_data) | ||
529 | v4l2_disable_ioctl(&tea->vd, VIDIOC_S_HW_FREQ_SEEK); | ||
530 | |||
531 | if (!tea->cannot_mute) { | ||
532 | tea->vd.ctrl_handler = &tea->ctrl_handler; | ||
533 | v4l2_ctrl_handler_init(&tea->ctrl_handler, 1); | ||
534 | v4l2_ctrl_new_std(&tea->ctrl_handler, &tea575x_ctrl_ops, | ||
535 | V4L2_CID_AUDIO_MUTE, 0, 1, 1, 1); | ||
536 | retval = tea->ctrl_handler.error; | ||
537 | if (retval) { | ||
538 | v4l2_err(tea->v4l2_dev, "can't initialize controls\n"); | ||
539 | v4l2_ctrl_handler_free(&tea->ctrl_handler); | ||
540 | return retval; | ||
541 | } | ||
542 | |||
543 | if (tea->ext_init) { | ||
544 | retval = tea->ext_init(tea); | ||
545 | if (retval) { | ||
546 | v4l2_ctrl_handler_free(&tea->ctrl_handler); | ||
547 | return retval; | ||
548 | } | ||
549 | } | ||
550 | |||
551 | v4l2_ctrl_handler_setup(&tea->ctrl_handler); | ||
552 | } | ||
553 | |||
554 | retval = video_register_device(&tea->vd, VFL_TYPE_RADIO, tea->radio_nr); | ||
555 | if (retval) { | ||
556 | v4l2_err(tea->v4l2_dev, "can't register video device!\n"); | ||
557 | v4l2_ctrl_handler_free(tea->vd.ctrl_handler); | ||
558 | return retval; | ||
559 | } | ||
560 | |||
561 | return 0; | ||
562 | } | ||
563 | |||
564 | void snd_tea575x_exit(struct snd_tea575x *tea) | ||
565 | { | ||
566 | video_unregister_device(&tea->vd); | ||
567 | v4l2_ctrl_handler_free(tea->vd.ctrl_handler); | ||
568 | } | ||
569 | |||
570 | static int __init alsa_tea575x_module_init(void) | ||
571 | { | ||
572 | return 0; | ||
573 | } | ||
574 | |||
575 | static void __exit alsa_tea575x_module_exit(void) | ||
576 | { | ||
577 | } | ||
578 | |||
579 | module_init(alsa_tea575x_module_init) | ||
580 | module_exit(alsa_tea575x_module_exit) | ||
581 | |||
582 | EXPORT_SYMBOL(snd_tea575x_init); | ||
583 | EXPORT_SYMBOL(snd_tea575x_exit); | ||
584 | EXPORT_SYMBOL(snd_tea575x_set_freq); | ||
diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig index fe6fa93a6262..9df80efa4692 100644 --- a/sound/pci/Kconfig +++ b/sound/pci/Kconfig | |||
@@ -1,10 +1,5 @@ | |||
1 | # ALSA PCI drivers | 1 | # ALSA PCI drivers |
2 | 2 | ||
3 | config SND_TEA575X | ||
4 | tristate | ||
5 | depends on SND_FM801_TEA575X_BOOL || SND_ES1968_RADIO || RADIO_SF16FMR2 || RADIO_MAXIRADIO || RADIO_SHARK | ||
6 | default SND_FM801 || SND_ES1968 || RADIO_SF16FMR2 || RADIO_MAXIRADIO || RADIO_SHARK | ||
7 | |||
8 | menuconfig SND_PCI | 3 | menuconfig SND_PCI |
9 | bool "PCI sound devices" | 4 | bool "PCI sound devices" |
10 | depends on PCI | 5 | depends on PCI |
@@ -542,7 +537,9 @@ config SND_ES1968_INPUT | |||
542 | config SND_ES1968_RADIO | 537 | config SND_ES1968_RADIO |
543 | bool "Enable TEA5757 radio tuner support for es1968" | 538 | bool "Enable TEA5757 radio tuner support for es1968" |
544 | depends on SND_ES1968 | 539 | depends on SND_ES1968 |
540 | depends on MEDIA_RADIO_SUPPORT | ||
545 | depends on VIDEO_V4L2=y || VIDEO_V4L2=SND_ES1968 | 541 | depends on VIDEO_V4L2=y || VIDEO_V4L2=SND_ES1968 |
542 | select RADIO_TEA575X | ||
546 | help | 543 | help |
547 | Say Y here to include support for TEA5757 radio tuner integrated on | 544 | Say Y here to include support for TEA5757 radio tuner integrated on |
548 | some MediaForte cards (e.g. SF64-PCE2). | 545 | some MediaForte cards (e.g. SF64-PCE2). |
@@ -562,7 +559,9 @@ config SND_FM801 | |||
562 | config SND_FM801_TEA575X_BOOL | 559 | config SND_FM801_TEA575X_BOOL |
563 | bool "ForteMedia FM801 + TEA5757 tuner" | 560 | bool "ForteMedia FM801 + TEA5757 tuner" |
564 | depends on SND_FM801 | 561 | depends on SND_FM801 |
562 | depends on MEDIA_RADIO_SUPPORT | ||
565 | depends on VIDEO_V4L2=y || VIDEO_V4L2=SND_FM801 | 563 | depends on VIDEO_V4L2=y || VIDEO_V4L2=SND_FM801 |
564 | select RADIO_TEA575X | ||
566 | help | 565 | help |
567 | Say Y here to include support for soundcards based on the ForteMedia | 566 | Say Y here to include support for soundcards based on the ForteMedia |
568 | FM801 chip with a TEA5757 tuner (MediaForte SF256-PCS, SF256-PCP and | 567 | FM801 chip with a TEA5757 tuner (MediaForte SF256-PCS, SF256-PCP and |