aboutsummaryrefslogtreecommitdiffstats
path: root/sound/i2c/other
diff options
context:
space:
mode:
authorOndrej Zary <linux@rainbow-software.org>2011-05-09 17:39:26 -0400
committerTakashi Iwai <tiwai@suse.de>2011-05-10 03:29:42 -0400
commit14219d06592025541559027d0fd8f96ef75f313c (patch)
tree0a137c2c9ef92b44c4a901c0c9c7df665db95eaf /sound/i2c/other
parent59bb7f0eebe69aa32a5c7917a23a7da1c5667d73 (diff)
ALSA: tea575x: unify read/write functions
Implement generic read/write functions to access TEA575x tuners. They're now implemented 4 times (once in es1968 and 3 times in fm801). This also allows mute to work on all cards. Also improve tuner detection/initialization. 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.c98
1 files changed, 72 insertions, 26 deletions
diff --git a/sound/i2c/other/tea575x-tuner.c b/sound/i2c/other/tea575x-tuner.c
index 9f35f378a17d..31f9795daca6 100644
--- a/sound/i2c/other/tea575x-tuner.c
+++ b/sound/i2c/other/tea575x-tuner.c
@@ -77,11 +77,65 @@ 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
80static void snd_tea575x_get_freq(struct snd_tea575x *tea) 134static void snd_tea575x_get_freq(struct snd_tea575x *tea)
81{ 135{
82 unsigned long freq; 136 unsigned long freq;
83 137
84 freq = tea->ops->read(tea) & TEA575X_BIT_FREQ_MASK; 138 freq = snd_tea575x_read(tea) & TEA575X_BIT_FREQ_MASK;
85 /* freq *= 12.5 */ 139 /* freq *= 12.5 */
86 freq *= 125; 140 freq *= 125;
87 freq /= 10; 141 freq /= 10;
@@ -111,7 +165,7 @@ static void snd_tea575x_set_freq(struct snd_tea575x *tea)
111 165
112 tea->val &= ~TEA575X_BIT_FREQ_MASK; 166 tea->val &= ~TEA575X_BIT_FREQ_MASK;
113 tea->val |= freq & TEA575X_BIT_FREQ_MASK; 167 tea->val |= freq & TEA575X_BIT_FREQ_MASK;
114 tea->ops->write(tea, tea->val); 168 snd_tea575x_write(tea, tea->val);
115} 169}
116 170
117/* 171/*
@@ -139,7 +193,7 @@ static int vidioc_g_tuner(struct file *file, void *priv,
139 if (v->index > 0) 193 if (v->index > 0)
140 return -EINVAL; 194 return -EINVAL;
141 195
142 tea->ops->read(tea); 196 snd_tea575x_read(tea);
143 197
144 strcpy(v->name, "FM"); 198 strcpy(v->name, "FM");
145 v->type = V4L2_TUNER_RADIO; 199 v->type = V4L2_TUNER_RADIO;
@@ -233,10 +287,8 @@ static int vidioc_g_ctrl(struct file *file, void *priv,
233 287
234 switch (ctrl->id) { 288 switch (ctrl->id) {
235 case V4L2_CID_AUDIO_MUTE: 289 case V4L2_CID_AUDIO_MUTE:
236 if (tea->ops->mute) { 290 ctrl->value = tea->mute;
237 ctrl->value = tea->mute; 291 return 0;
238 return 0;
239 }
240 } 292 }
241 return -EINVAL; 293 return -EINVAL;
242} 294}
@@ -248,11 +300,11 @@ static int vidioc_s_ctrl(struct file *file, void *priv,
248 300
249 switch (ctrl->id) { 301 switch (ctrl->id) {
250 case V4L2_CID_AUDIO_MUTE: 302 case V4L2_CID_AUDIO_MUTE:
251 if (tea->ops->mute) { 303 if (tea->mute != ctrl->value) {
252 tea->ops->mute(tea, ctrl->value);
253 tea->mute = ctrl->value; 304 tea->mute = ctrl->value;
254 return 0; 305 snd_tea575x_set_freq(tea);
255 } 306 }
307 return 0;
256 } 308 }
257 return -EINVAL; 309 return -EINVAL;
258} 310}
@@ -317,18 +369,16 @@ static struct video_device tea575x_radio = {
317/* 369/*
318 * initialize all the tea575x chips 370 * initialize all the tea575x chips
319 */ 371 */
320void snd_tea575x_init(struct snd_tea575x *tea) 372int snd_tea575x_init(struct snd_tea575x *tea)
321{ 373{
322 int retval; 374 int retval;
323 unsigned int val;
324 struct video_device *tea575x_radio_inst; 375 struct video_device *tea575x_radio_inst;
325 376
326 val = tea->ops->read(tea); 377 tea->mute = 1;
327 if (val == 0x1ffffff || val == 0) { 378
328 snd_printk(KERN_ERR 379 snd_tea575x_write(tea, 0x55AA);
329 "tea575x-tuner: Cannot find TEA575x chip\n"); 380 if (snd_tea575x_read(tea) != 0x55AA)
330 return; 381 return -ENODEV;
331 }
332 382
333 tea->in_use = 0; 383 tea->in_use = 0;
334 tea->val = TEA575X_BIT_BAND_FM | TEA575X_BIT_SEARCH_10_40; 384 tea->val = TEA575X_BIT_BAND_FM | TEA575X_BIT_SEARCH_10_40;
@@ -337,7 +387,7 @@ void snd_tea575x_init(struct snd_tea575x *tea)
337 tea575x_radio_inst = video_device_alloc(); 387 tea575x_radio_inst = video_device_alloc();
338 if (tea575x_radio_inst == NULL) { 388 if (tea575x_radio_inst == NULL) {
339 printk(KERN_ERR "tea575x-tuner: not enough memory\n"); 389 printk(KERN_ERR "tea575x-tuner: not enough memory\n");
340 return; 390 return -ENOMEM;
341 } 391 }
342 392
343 memcpy(tea575x_radio_inst, &tea575x_radio, sizeof(tea575x_radio)); 393 memcpy(tea575x_radio_inst, &tea575x_radio, sizeof(tea575x_radio));
@@ -352,17 +402,13 @@ void snd_tea575x_init(struct snd_tea575x *tea)
352 if (retval) { 402 if (retval) {
353 printk(KERN_ERR "tea575x-tuner: can't register video device!\n"); 403 printk(KERN_ERR "tea575x-tuner: can't register video device!\n");
354 kfree(tea575x_radio_inst); 404 kfree(tea575x_radio_inst);
355 return; 405 return retval;
356 } 406 }
357 407
358 snd_tea575x_set_freq(tea); 408 snd_tea575x_set_freq(tea);
359
360 /* mute on init */
361 if (tea->ops->mute) {
362 tea->ops->mute(tea, 1);
363 tea->mute = 1;
364 }
365 tea->vd = tea575x_radio_inst; 409 tea->vd = tea575x_radio_inst;
410
411 return 0;
366} 412}
367 413
368void snd_tea575x_exit(struct snd_tea575x *tea) 414void snd_tea575x_exit(struct snd_tea575x *tea)