diff options
author | Ondrej Zary <linux@rainbow-software.org> | 2011-03-19 11:32:53 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2011-03-21 07:43:54 -0400 |
commit | 375d135818f32bbe7b3f071bd54d977c4ff8d84a (patch) | |
tree | 776c6a3597d05c6801bc19771b23e3cd0ee85f68 /sound/i2c | |
parent | 75eb1c311da47d32ba47825226e110df703b35d0 (diff) |
ALSA: tea575x-tuner: various improvements
Improve tea575x-tuner with various good things from radio-maestro:
- extend frequency range to 50-150MHz
- fix querycap(): card name, CAP_RADIO
- improve g_tuner(): CAP_STEREO, stereo and tuned indication
- improve g_frequency(): tuner index checking and reading frequency from HW
- improve s_frequency(): tuner index and type checking
Signed-off-by: Ondrej Zary <linux@rainbow-software.org>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/i2c')
-rw-r--r-- | sound/i2c/other/tea575x-tuner.c | 52 |
1 files changed, 38 insertions, 14 deletions
diff --git a/sound/i2c/other/tea575x-tuner.c b/sound/i2c/other/tea575x-tuner.c index ee538f1ae846..9f35f378a17d 100644 --- a/sound/i2c/other/tea575x-tuner.c +++ b/sound/i2c/other/tea575x-tuner.c | |||
@@ -37,8 +37,8 @@ static int radio_nr = -1; | |||
37 | module_param(radio_nr, int, 0); | 37 | module_param(radio_nr, int, 0); |
38 | 38 | ||
39 | #define RADIO_VERSION KERNEL_VERSION(0, 0, 2) | 39 | #define RADIO_VERSION KERNEL_VERSION(0, 0, 2) |
40 | #define FREQ_LO (87 * 16000) | 40 | #define FREQ_LO (50UL * 16000) |
41 | #define FREQ_HI (108 * 16000) | 41 | #define FREQ_HI (150UL * 16000) |
42 | 42 | ||
43 | /* | 43 | /* |
44 | * definitions | 44 | * definitions |
@@ -77,15 +77,29 @@ static struct v4l2_queryctrl radio_qctrl[] = { | |||
77 | * lowlevel part | 77 | * lowlevel part |
78 | */ | 78 | */ |
79 | 79 | ||
80 | static void snd_tea575x_get_freq(struct snd_tea575x *tea) | ||
81 | { | ||
82 | unsigned long freq; | ||
83 | |||
84 | freq = tea->ops->read(tea) & TEA575X_BIT_FREQ_MASK; | ||
85 | /* freq *= 12.5 */ | ||
86 | freq *= 125; | ||
87 | freq /= 10; | ||
88 | /* crystal fixup */ | ||
89 | if (tea->tea5759) | ||
90 | freq += tea->freq_fixup; | ||
91 | else | ||
92 | freq -= tea->freq_fixup; | ||
93 | |||
94 | tea->freq = freq * 16; /* from kHz */ | ||
95 | } | ||
96 | |||
80 | static void snd_tea575x_set_freq(struct snd_tea575x *tea) | 97 | static void snd_tea575x_set_freq(struct snd_tea575x *tea) |
81 | { | 98 | { |
82 | unsigned long freq; | 99 | unsigned long freq; |
83 | 100 | ||
84 | freq = tea->freq / 16; /* to kHz */ | 101 | freq = clamp(tea->freq, FREQ_LO, FREQ_HI); |
85 | if (freq > 108000) | 102 | freq /= 16; /* to kHz */ |
86 | freq = 108000; | ||
87 | if (freq < 87000) | ||
88 | freq = 87000; | ||
89 | /* crystal fixup */ | 103 | /* crystal fixup */ |
90 | if (tea->tea5759) | 104 | if (tea->tea5759) |
91 | freq -= tea->freq_fixup; | 105 | freq -= tea->freq_fixup; |
@@ -109,29 +123,33 @@ static int vidioc_querycap(struct file *file, void *priv, | |||
109 | { | 123 | { |
110 | struct snd_tea575x *tea = video_drvdata(file); | 124 | struct snd_tea575x *tea = video_drvdata(file); |
111 | 125 | ||
112 | strcpy(v->card, tea->tea5759 ? "TEA5759" : "TEA5757"); | ||
113 | strlcpy(v->driver, "tea575x-tuner", sizeof(v->driver)); | 126 | strlcpy(v->driver, "tea575x-tuner", sizeof(v->driver)); |
114 | strlcpy(v->card, "Maestro Radio", sizeof(v->card)); | 127 | strlcpy(v->card, tea->tea5759 ? "TEA5759" : "TEA5757", sizeof(v->card)); |
115 | sprintf(v->bus_info, "PCI"); | 128 | sprintf(v->bus_info, "PCI"); |
116 | v->version = RADIO_VERSION; | 129 | v->version = RADIO_VERSION; |
117 | v->capabilities = V4L2_CAP_TUNER; | 130 | v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO; |
118 | return 0; | 131 | return 0; |
119 | } | 132 | } |
120 | 133 | ||
121 | static int vidioc_g_tuner(struct file *file, void *priv, | 134 | static int vidioc_g_tuner(struct file *file, void *priv, |
122 | struct v4l2_tuner *v) | 135 | struct v4l2_tuner *v) |
123 | { | 136 | { |
137 | struct snd_tea575x *tea = video_drvdata(file); | ||
138 | |||
124 | if (v->index > 0) | 139 | if (v->index > 0) |
125 | return -EINVAL; | 140 | return -EINVAL; |
126 | 141 | ||
142 | tea->ops->read(tea); | ||
143 | |||
127 | strcpy(v->name, "FM"); | 144 | strcpy(v->name, "FM"); |
128 | v->type = V4L2_TUNER_RADIO; | 145 | v->type = V4L2_TUNER_RADIO; |
146 | v->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO; | ||
129 | v->rangelow = FREQ_LO; | 147 | v->rangelow = FREQ_LO; |
130 | v->rangehigh = FREQ_HI; | 148 | v->rangehigh = FREQ_HI; |
131 | v->rxsubchans = V4L2_TUNER_SUB_MONO|V4L2_TUNER_SUB_STEREO; | 149 | v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO; |
132 | v->capability = V4L2_TUNER_CAP_LOW; | 150 | v->audmode = tea->stereo ? V4L2_TUNER_MODE_STEREO : V4L2_TUNER_MODE_MONO; |
133 | v->audmode = V4L2_TUNER_MODE_MONO; | 151 | v->signal = tea->tuned ? 0xffff : 0; |
134 | v->signal = 0xffff; | 152 | |
135 | return 0; | 153 | return 0; |
136 | } | 154 | } |
137 | 155 | ||
@@ -148,7 +166,10 @@ static int vidioc_g_frequency(struct file *file, void *priv, | |||
148 | { | 166 | { |
149 | struct snd_tea575x *tea = video_drvdata(file); | 167 | struct snd_tea575x *tea = video_drvdata(file); |
150 | 168 | ||
169 | if (f->tuner != 0) | ||
170 | return -EINVAL; | ||
151 | f->type = V4L2_TUNER_RADIO; | 171 | f->type = V4L2_TUNER_RADIO; |
172 | snd_tea575x_get_freq(tea); | ||
152 | f->frequency = tea->freq; | 173 | f->frequency = tea->freq; |
153 | return 0; | 174 | return 0; |
154 | } | 175 | } |
@@ -158,6 +179,9 @@ static int vidioc_s_frequency(struct file *file, void *priv, | |||
158 | { | 179 | { |
159 | struct snd_tea575x *tea = video_drvdata(file); | 180 | struct snd_tea575x *tea = video_drvdata(file); |
160 | 181 | ||
182 | if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO) | ||
183 | return -EINVAL; | ||
184 | |||
161 | if (f->frequency < FREQ_LO || f->frequency > FREQ_HI) | 185 | if (f->frequency < FREQ_LO || f->frequency > FREQ_HI) |
162 | return -EINVAL; | 186 | return -EINVAL; |
163 | 187 | ||