aboutsummaryrefslogtreecommitdiffstats
path: root/sound/i2c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/i2c')
-rw-r--r--sound/i2c/other/Makefile2
-rw-r--r--sound/i2c/other/tea575x-tuner.c153
2 files changed, 113 insertions, 42 deletions
diff --git a/sound/i2c/other/Makefile b/sound/i2c/other/Makefile
index 2dad40f3f622..c95d8f1aae87 100644
--- a/sound/i2c/other/Makefile
+++ b/sound/i2c/other/Makefile
@@ -14,4 +14,4 @@ snd-tea575x-tuner-objs := tea575x-tuner.o
14obj-$(CONFIG_SND_PDAUDIOCF) += snd-ak4117.o 14obj-$(CONFIG_SND_PDAUDIOCF) += snd-ak4117.o
15obj-$(CONFIG_SND_ICE1712) += snd-ak4xxx-adda.o 15obj-$(CONFIG_SND_ICE1712) += snd-ak4xxx-adda.o
16obj-$(CONFIG_SND_ICE1724) += snd-ak4114.o snd-ak4113.o snd-ak4xxx-adda.o snd-pt2258.o 16obj-$(CONFIG_SND_ICE1724) += snd-ak4114.o snd-ak4113.o snd-ak4xxx-adda.o snd-pt2258.o
17obj-$(CONFIG_SND_FM801_TEA575X) += snd-tea575x-tuner.o 17obj-$(CONFIG_SND_TEA575X) += snd-tea575x-tuner.o
diff --git a/sound/i2c/other/tea575x-tuner.c b/sound/i2c/other/tea575x-tuner.c
index ee538f1ae846..4831800239d3 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,27 +77,95 @@ static struct v4l2_queryctrl radio_qctrl[] = {
77 * lowlevel part 77 * lowlevel part
78 */ 78 */
79 79
80static void snd_tea575x_write(struct snd_tea575x *tea, unsigned int val)
81{
82 u16 l;
83 u8 data;
84
85 tea->ops->set_direction(tea, 1);
86 udelay(16);
87
88 for (l = 25; l > 0; l--) {
89 data = (val >> 24) & TEA575X_DATA;
90 val <<= 1; /* shift data */
91 tea->ops->set_pins(tea, data | TEA575X_WREN);
92 udelay(2);
93 tea->ops->set_pins(tea, data | TEA575X_WREN | TEA575X_CLK);
94 udelay(2);
95 tea->ops->set_pins(tea, data | TEA575X_WREN);
96 udelay(2);
97 }
98
99 if (!tea->mute)
100 tea->ops->set_pins(tea, 0);
101}
102
103static unsigned int snd_tea575x_read(struct snd_tea575x *tea)
104{
105 u16 l, rdata;
106 u32 data = 0;
107
108 tea->ops->set_direction(tea, 0);
109 tea->ops->set_pins(tea, 0);
110 udelay(16);
111
112 for (l = 24; l--;) {
113 tea->ops->set_pins(tea, TEA575X_CLK);
114 udelay(2);
115 if (!l)
116 tea->tuned = tea->ops->get_pins(tea) & TEA575X_MOST ? 0 : 1;
117 tea->ops->set_pins(tea, 0);
118 udelay(2);
119 data <<= 1; /* shift data */
120 rdata = tea->ops->get_pins(tea);
121 if (!l)
122 tea->stereo = (rdata & TEA575X_MOST) ? 0 : 1;
123 if (rdata & TEA575X_DATA)
124 data++;
125 udelay(2);
126 }
127
128 if (tea->mute)
129 tea->ops->set_pins(tea, TEA575X_WREN);
130
131 return data;
132}
133
134static void snd_tea575x_get_freq(struct snd_tea575x *tea)
135{
136 unsigned long freq;
137
138 freq = snd_tea575x_read(tea) & TEA575X_BIT_FREQ_MASK;
139 /* freq *= 12.5 */
140 freq *= 125;
141 freq /= 10;
142 /* crystal fixup */
143 if (tea->tea5759)
144 freq += TEA575X_FMIF;
145 else
146 freq -= TEA575X_FMIF;
147
148 tea->freq = freq * 16; /* from kHz */
149}
150
80static void snd_tea575x_set_freq(struct snd_tea575x *tea) 151static void snd_tea575x_set_freq(struct snd_tea575x *tea)
81{ 152{
82 unsigned long freq; 153 unsigned long freq;
83 154
84 freq = tea->freq / 16; /* to kHz */ 155 freq = clamp(tea->freq, FREQ_LO, FREQ_HI);
85 if (freq > 108000) 156 freq /= 16; /* to kHz */
86 freq = 108000;
87 if (freq < 87000)
88 freq = 87000;
89 /* crystal fixup */ 157 /* crystal fixup */
90 if (tea->tea5759) 158 if (tea->tea5759)
91 freq -= tea->freq_fixup; 159 freq -= TEA575X_FMIF;
92 else 160 else
93 freq += tea->freq_fixup; 161 freq += TEA575X_FMIF;
94 /* freq /= 12.5 */ 162 /* freq /= 12.5 */
95 freq *= 10; 163 freq *= 10;
96 freq /= 125; 164 freq /= 125;
97 165
98 tea->val &= ~TEA575X_BIT_FREQ_MASK; 166 tea->val &= ~TEA575X_BIT_FREQ_MASK;
99 tea->val |= freq & TEA575X_BIT_FREQ_MASK; 167 tea->val |= freq & TEA575X_BIT_FREQ_MASK;
100 tea->ops->write(tea, tea->val); 168 snd_tea575x_write(tea, tea->val);
101} 169}
102 170
103/* 171/*
@@ -109,29 +177,34 @@ static int vidioc_querycap(struct file *file, void *priv,
109{ 177{
110 struct snd_tea575x *tea = video_drvdata(file); 178 struct snd_tea575x *tea = video_drvdata(file);
111 179
112 strcpy(v->card, tea->tea5759 ? "TEA5759" : "TEA5757");
113 strlcpy(v->driver, "tea575x-tuner", sizeof(v->driver)); 180 strlcpy(v->driver, "tea575x-tuner", sizeof(v->driver));
114 strlcpy(v->card, "Maestro Radio", sizeof(v->card)); 181 strlcpy(v->card, tea->card, sizeof(v->card));
115 sprintf(v->bus_info, "PCI"); 182 strlcat(v->card, tea->tea5759 ? " TEA5759" : " TEA5757", sizeof(v->card));
183 strlcpy(v->bus_info, tea->bus_info, sizeof(v->bus_info));
116 v->version = RADIO_VERSION; 184 v->version = RADIO_VERSION;
117 v->capabilities = V4L2_CAP_TUNER; 185 v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO;
118 return 0; 186 return 0;
119} 187}
120 188
121static int vidioc_g_tuner(struct file *file, void *priv, 189static int vidioc_g_tuner(struct file *file, void *priv,
122 struct v4l2_tuner *v) 190 struct v4l2_tuner *v)
123{ 191{
192 struct snd_tea575x *tea = video_drvdata(file);
193
124 if (v->index > 0) 194 if (v->index > 0)
125 return -EINVAL; 195 return -EINVAL;
126 196
197 snd_tea575x_read(tea);
198
127 strcpy(v->name, "FM"); 199 strcpy(v->name, "FM");
128 v->type = V4L2_TUNER_RADIO; 200 v->type = V4L2_TUNER_RADIO;
201 v->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO;
129 v->rangelow = FREQ_LO; 202 v->rangelow = FREQ_LO;
130 v->rangehigh = FREQ_HI; 203 v->rangehigh = FREQ_HI;
131 v->rxsubchans = V4L2_TUNER_SUB_MONO|V4L2_TUNER_SUB_STEREO; 204 v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO;
132 v->capability = V4L2_TUNER_CAP_LOW; 205 v->audmode = tea->stereo ? V4L2_TUNER_MODE_STEREO : V4L2_TUNER_MODE_MONO;
133 v->audmode = V4L2_TUNER_MODE_MONO; 206 v->signal = tea->tuned ? 0xffff : 0;
134 v->signal = 0xffff; 207
135 return 0; 208 return 0;
136} 209}
137 210
@@ -148,7 +221,10 @@ static int vidioc_g_frequency(struct file *file, void *priv,
148{ 221{
149 struct snd_tea575x *tea = video_drvdata(file); 222 struct snd_tea575x *tea = video_drvdata(file);
150 223
224 if (f->tuner != 0)
225 return -EINVAL;
151 f->type = V4L2_TUNER_RADIO; 226 f->type = V4L2_TUNER_RADIO;
227 snd_tea575x_get_freq(tea);
152 f->frequency = tea->freq; 228 f->frequency = tea->freq;
153 return 0; 229 return 0;
154} 230}
@@ -158,6 +234,9 @@ static int vidioc_s_frequency(struct file *file, void *priv,
158{ 234{
159 struct snd_tea575x *tea = video_drvdata(file); 235 struct snd_tea575x *tea = video_drvdata(file);
160 236
237 if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO)
238 return -EINVAL;
239
161 if (f->frequency < FREQ_LO || f->frequency > FREQ_HI) 240 if (f->frequency < FREQ_LO || f->frequency > FREQ_HI)
162 return -EINVAL; 241 return -EINVAL;
163 242
@@ -209,10 +288,8 @@ static int vidioc_g_ctrl(struct file *file, void *priv,
209 288
210 switch (ctrl->id) { 289 switch (ctrl->id) {
211 case V4L2_CID_AUDIO_MUTE: 290 case V4L2_CID_AUDIO_MUTE:
212 if (tea->ops->mute) { 291 ctrl->value = tea->mute;
213 ctrl->value = tea->mute; 292 return 0;
214 return 0;
215 }
216 } 293 }
217 return -EINVAL; 294 return -EINVAL;
218} 295}
@@ -224,11 +301,11 @@ static int vidioc_s_ctrl(struct file *file, void *priv,
224 301
225 switch (ctrl->id) { 302 switch (ctrl->id) {
226 case V4L2_CID_AUDIO_MUTE: 303 case V4L2_CID_AUDIO_MUTE:
227 if (tea->ops->mute) { 304 if (tea->mute != ctrl->value) {
228 tea->ops->mute(tea, ctrl->value);
229 tea->mute = ctrl->value; 305 tea->mute = ctrl->value;
230 return 0; 306 snd_tea575x_set_freq(tea);
231 } 307 }
308 return 0;
232 } 309 }
233 return -EINVAL; 310 return -EINVAL;
234} 311}
@@ -293,18 +370,16 @@ static struct video_device tea575x_radio = {
293/* 370/*
294 * initialize all the tea575x chips 371 * initialize all the tea575x chips
295 */ 372 */
296void snd_tea575x_init(struct snd_tea575x *tea) 373int snd_tea575x_init(struct snd_tea575x *tea)
297{ 374{
298 int retval; 375 int retval;
299 unsigned int val;
300 struct video_device *tea575x_radio_inst; 376 struct video_device *tea575x_radio_inst;
301 377
302 val = tea->ops->read(tea); 378 tea->mute = 1;
303 if (val == 0x1ffffff || val == 0) { 379
304 snd_printk(KERN_ERR 380 snd_tea575x_write(tea, 0x55AA);
305 "tea575x-tuner: Cannot find TEA575x chip\n"); 381 if (snd_tea575x_read(tea) != 0x55AA)
306 return; 382 return -ENODEV;
307 }
308 383
309 tea->in_use = 0; 384 tea->in_use = 0;
310 tea->val = TEA575X_BIT_BAND_FM | TEA575X_BIT_SEARCH_10_40; 385 tea->val = TEA575X_BIT_BAND_FM | TEA575X_BIT_SEARCH_10_40;
@@ -313,7 +388,7 @@ void snd_tea575x_init(struct snd_tea575x *tea)
313 tea575x_radio_inst = video_device_alloc(); 388 tea575x_radio_inst = video_device_alloc();
314 if (tea575x_radio_inst == NULL) { 389 if (tea575x_radio_inst == NULL) {
315 printk(KERN_ERR "tea575x-tuner: not enough memory\n"); 390 printk(KERN_ERR "tea575x-tuner: not enough memory\n");
316 return; 391 return -ENOMEM;
317 } 392 }
318 393
319 memcpy(tea575x_radio_inst, &tea575x_radio, sizeof(tea575x_radio)); 394 memcpy(tea575x_radio_inst, &tea575x_radio, sizeof(tea575x_radio));
@@ -328,17 +403,13 @@ void snd_tea575x_init(struct snd_tea575x *tea)
328 if (retval) { 403 if (retval) {
329 printk(KERN_ERR "tea575x-tuner: can't register video device!\n"); 404 printk(KERN_ERR "tea575x-tuner: can't register video device!\n");
330 kfree(tea575x_radio_inst); 405 kfree(tea575x_radio_inst);
331 return; 406 return retval;
332 } 407 }
333 408
334 snd_tea575x_set_freq(tea); 409 snd_tea575x_set_freq(tea);
335
336 /* mute on init */
337 if (tea->ops->mute) {
338 tea->ops->mute(tea, 1);
339 tea->mute = 1;
340 }
341 tea->vd = tea575x_radio_inst; 410 tea->vd = tea575x_radio_inst;
411
412 return 0;
342} 413}
343 414
344void snd_tea575x_exit(struct snd_tea575x *tea) 415void snd_tea575x_exit(struct snd_tea575x *tea)