aboutsummaryrefslogtreecommitdiffstats
path: root/sound/i2c/other
diff options
context:
space:
mode:
authorOndrej Zary <linux@rainbow-software.org>2011-03-19 11:32:53 -0400
committerTakashi Iwai <tiwai@suse.de>2011-03-21 07:43:54 -0400
commit375d135818f32bbe7b3f071bd54d977c4ff8d84a (patch)
tree776c6a3597d05c6801bc19771b23e3cd0ee85f68 /sound/i2c/other
parent75eb1c311da47d32ba47825226e110df703b35d0 (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/other')
-rw-r--r--sound/i2c/other/tea575x-tuner.c52
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;
37module_param(radio_nr, int, 0); 37module_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
80static 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
80static void snd_tea575x_set_freq(struct snd_tea575x *tea) 97static 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
121static int vidioc_g_tuner(struct file *file, void *priv, 134static 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