]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - glsdk/meta-ti-glsdk.git/blob - recipes-bsp/linux/linux-omap/wl1271/0010-drivers-media-radio-wl128x-FM-driver-RX-sources.patch
netbase: automatically bring up usb0 on BeagleBoard xM
[glsdk/meta-ti-glsdk.git] / recipes-bsp / linux / linux-omap / wl1271 / 0010-drivers-media-radio-wl128x-FM-driver-RX-sources.patch
1 From ba32e1ae2a43f33dcfd459c1456d4e612da885db Mon Sep 17 00:00:00 2001
2 From: Manjunatha Halli <manjunatha_halli@ti.com>
3 Date: Tue, 11 Jan 2011 11:31:24 +0000
4 Subject: [PATCH 10/15] drivers:media:radio: wl128x: FM driver RX sources
6 This has implementation for FM RX functionality.
7 It communicates with FM V4l2 module and FM common module
9 Signed-off-by: Manjunatha Halli <manjunatha_halli@ti.com>
10 Reviewed-by: Hans Verkuil <hverkuil@xs4all.nl>
11 ---
12  drivers/media/radio/wl128x/fmdrv_rx.c |  847 +++++++++++++++++++++++++++++++++
13  drivers/media/radio/wl128x/fmdrv_rx.h |   59 +++
14  2 files changed, 906 insertions(+), 0 deletions(-)
15  create mode 100644 drivers/media/radio/wl128x/fmdrv_rx.c
16  create mode 100644 drivers/media/radio/wl128x/fmdrv_rx.h
18 diff --git a/drivers/media/radio/wl128x/fmdrv_rx.c b/drivers/media/radio/wl128x/fmdrv_rx.c
19 new file mode 100644
20 index 0000000..ec529b5
21 --- /dev/null
22 +++ b/drivers/media/radio/wl128x/fmdrv_rx.c
23 @@ -0,0 +1,847 @@
24 +/*
25 + *  FM Driver for Connectivity chip of Texas Instruments.
26 + *  This sub-module of FM driver implements FM RX functionality.
27 + *
28 + *  Copyright (C) 2011 Texas Instruments
29 + *  Author: Raja Mani <raja_mani@ti.com>
30 + *  Author: Manjunatha Halli <manjunatha_halli@ti.com>
31 + *
32 + *  This program is free software; you can redistribute it and/or modify
33 + *  it under the terms of the GNU General Public License version 2 as
34 + *  published by the Free Software Foundation.
35 + *
36 + *  This program is distributed in the hope that it will be useful,
37 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
38 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
39 + *  GNU General Public License for more details.
40 + *
41 + *  You should have received a copy of the GNU General Public License
42 + *  along with this program; if not, write to the Free Software
43 + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
44 + *
45 + */
46 +
47 +#include "fmdrv.h"
48 +#include "fmdrv_common.h"
49 +#include "fmdrv_rx.h"
50 +
51 +void fm_rx_reset_rds_cache(struct fmdev *fmdev)
52 +{
53 +       fmdev->rx.rds.flag = FM_RDS_DISABLE;
54 +       fmdev->rx.rds.last_blk_idx = 0;
55 +       fmdev->rx.rds.wr_idx = 0;
56 +       fmdev->rx.rds.rd_idx = 0;
57 +
58 +       if (fmdev->rx.af_mode == FM_RX_RDS_AF_SWITCH_MODE_ON)
59 +               fmdev->irq_info.mask |= FM_LEV_EVENT;
60 +}
61 +
62 +void fm_rx_reset_station_info(struct fmdev *fmdev)
63 +{
64 +       fmdev->rx.stat_info.picode = FM_NO_PI_CODE;
65 +       fmdev->rx.stat_info.afcache_size = 0;
66 +       fmdev->rx.stat_info.af_list_max = 0;
67 +}
68 +
69 +u32 fm_rx_set_freq(struct fmdev *fmdev, u32 freq)
70 +{
71 +       unsigned long timeleft;
72 +       u16 payload, curr_frq, intr_flag;
73 +       u32 curr_frq_in_khz;
74 +       u32 ret, resp_len;
75 +
76 +       if (freq < fmdev->rx.region.bot_freq || freq > fmdev->rx.region.top_freq) {
77 +               fmerr("Invalid frequency %d\n", freq);
78 +               return -EINVAL;
79 +       }
80 +
81 +       /* Set audio enable */
82 +       payload = FM_RX_AUDIO_ENABLE_I2S_AND_ANALOG;
83 +
84 +       ret = fmc_send_cmd(fmdev, AUDIO_ENABLE_SET, REG_WR, &payload,
85 +                       sizeof(payload), NULL, NULL);
86 +       if (ret < 0)
87 +               return ret;
88 +
89 +       /* Set hilo to automatic selection */
90 +       payload = FM_RX_IFFREQ_HILO_AUTOMATIC;
91 +       ret = fmc_send_cmd(fmdev, HILO_SET, REG_WR, &payload,
92 +                       sizeof(payload), NULL, NULL);
93 +       if (ret < 0)
94 +               return ret;
95 +
96 +       /* Calculate frequency index and set*/
97 +       payload = (freq - fmdev->rx.region.bot_freq) / FM_FREQ_MUL;
98 +
99 +       ret = fmc_send_cmd(fmdev, FREQ_SET, REG_WR, &payload,
100 +                       sizeof(payload), NULL, NULL);
101 +       if (ret < 0)
102 +               return ret;
104 +       /* Read flags - just to clear any pending interrupts if we had */
105 +       ret = fmc_send_cmd(fmdev, FLAG_GET, REG_RD, NULL, 2, NULL, NULL);
106 +       if (ret < 0)
107 +               return ret;
109 +       /* Enable FR, BL interrupts */
110 +       intr_flag = fmdev->irq_info.mask;
111 +       fmdev->irq_info.mask = (FM_FR_EVENT | FM_BL_EVENT);
112 +       payload = fmdev->irq_info.mask;
113 +       ret = fmc_send_cmd(fmdev, INT_MASK_SET, REG_WR, &payload,
114 +                       sizeof(payload), NULL, NULL);
115 +       if (ret < 0)
116 +               return ret;
118 +       /* Start tune */
119 +       payload = FM_TUNER_PRESET_MODE;
120 +       ret = fmc_send_cmd(fmdev, TUNER_MODE_SET, REG_WR, &payload,
121 +                       sizeof(payload), NULL, NULL);
122 +       if (ret < 0)
123 +               goto exit;
125 +       /* Wait for tune ended interrupt */
126 +       init_completion(&fmdev->maintask_comp);
127 +       timeleft = wait_for_completion_timeout(&fmdev->maintask_comp,
128 +                       FM_DRV_TX_TIMEOUT);
129 +       if (!timeleft) {
130 +               fmerr("Timeout(%d sec),didn't get tune ended int\n",
131 +                          jiffies_to_msecs(FM_DRV_TX_TIMEOUT) / 1000);
132 +               ret = -ETIMEDOUT;
133 +               goto exit;
134 +       }
136 +       /* Read freq back to confirm */
137 +       ret = fmc_send_cmd(fmdev, FREQ_SET, REG_RD, NULL, 2, &curr_frq, &resp_len);
138 +       if (ret < 0)
139 +               goto exit;
141 +       curr_frq = be16_to_cpu(curr_frq);
142 +       curr_frq_in_khz = (fmdev->rx.region.bot_freq + ((u32)curr_frq * FM_FREQ_MUL));
144 +       if (curr_frq_in_khz != freq) {
145 +               pr_info("Frequency is set to (%d) but "
146 +                          "requested freq is (%d)\n", curr_frq_in_khz, freq);
147 +       }
149 +       /* Update local cache  */
150 +       fmdev->rx.freq = curr_frq_in_khz;
151 +exit:
152 +       /* Re-enable default FM interrupts */
153 +       fmdev->irq_info.mask = intr_flag;
154 +       payload = fmdev->irq_info.mask;
155 +       ret = fmc_send_cmd(fmdev, INT_MASK_SET, REG_WR, &payload,
156 +                       sizeof(payload), NULL, NULL);
157 +       if (ret < 0)
158 +               return ret;
160 +       /* Reset RDS cache and current station pointers */
161 +       fm_rx_reset_rds_cache(fmdev);
162 +       fm_rx_reset_station_info(fmdev);
164 +       return ret;
165 +}
167 +static u32 fm_rx_set_channel_spacing(struct fmdev *fmdev, u32 spacing)
168 +{
169 +       u16 payload;
170 +       u32 ret;
172 +       if (spacing > 0 && spacing <= 50000)
173 +               spacing = FM_CHANNEL_SPACING_50KHZ;
174 +       else if (spacing > 50000 && spacing <= 100000)
175 +               spacing = FM_CHANNEL_SPACING_100KHZ;
176 +       else
177 +               spacing = FM_CHANNEL_SPACING_200KHZ;
179 +       /* set channel spacing */
180 +       payload = spacing;
181 +       ret = fmc_send_cmd(fmdev, CHANL_BW_SET, REG_WR, &payload,
182 +                       sizeof(payload), NULL, NULL);
183 +       if (ret < 0)
184 +               return ret;
186 +       fmdev->rx.region.chanl_space = spacing * FM_FREQ_MUL;
188 +       return ret;
189 +}
191 +u32 fm_rx_seek(struct fmdev *fmdev, u32 seek_upward,
192 +               u32 wrap_around, u32 spacing)
193 +{
194 +       u32 resp_len;
195 +       u16 curr_frq, next_frq, last_frq;
196 +       u16 payload, int_reason, intr_flag;
197 +       u16 offset, space_idx;
198 +       unsigned long timeleft;
199 +       u32 ret;
201 +       /* Set channel spacing */
202 +       ret = fm_rx_set_channel_spacing(fmdev, spacing);
203 +       if (ret < 0) {
204 +               fmerr("Failed to set channel spacing\n");
205 +               return ret;
206 +       }
208 +       /* Read the current frequency from chip */
209 +       ret = fmc_send_cmd(fmdev, FREQ_SET, REG_RD, NULL,
210 +                       sizeof(curr_frq), &curr_frq, &resp_len);
211 +       if (ret < 0)
212 +               return ret;
214 +       curr_frq = be16_to_cpu(curr_frq);
215 +       last_frq = (fmdev->rx.region.top_freq - fmdev->rx.region.bot_freq) / FM_FREQ_MUL;
217 +       /* Check the offset in order to be aligned to the channel spacing*/
218 +       space_idx = fmdev->rx.region.chanl_space / FM_FREQ_MUL;
219 +       offset = curr_frq % space_idx;
221 +       next_frq = seek_upward ? curr_frq + space_idx /* Seek Up */ :
222 +                               curr_frq - space_idx /* Seek Down */ ;
224 +       /*
225 +        * Add or subtract offset in order to stay aligned to the channel
226 +        * spacing.
227 +        */
228 +       if ((short)next_frq < 0)
229 +               next_frq = last_frq - offset;
230 +       else if (next_frq > last_frq)
231 +               next_frq = 0 + offset;
233 +again:
234 +       /* Set calculated next frequency to perform seek */
235 +       payload = next_frq;
236 +       ret = fmc_send_cmd(fmdev, FREQ_SET, REG_WR, &payload,
237 +                       sizeof(payload), NULL, NULL);
238 +       if (ret < 0)
239 +               return ret;
241 +       /* Set search direction (0:Seek Down, 1:Seek Up) */
242 +       payload = (seek_upward ? FM_SEARCH_DIRECTION_UP : FM_SEARCH_DIRECTION_DOWN);
243 +       ret = fmc_send_cmd(fmdev, SEARCH_DIR_SET, REG_WR, &payload,
244 +                       sizeof(payload), NULL, NULL);
245 +       if (ret < 0)
246 +               return ret;
248 +       /* Read flags - just to clear any pending interrupts if we had */
249 +       ret = fmc_send_cmd(fmdev, FLAG_GET, REG_RD, NULL, 2, NULL, NULL);
250 +       if (ret < 0)
251 +               return ret;
253 +       /* Enable FR, BL interrupts */
254 +       intr_flag = fmdev->irq_info.mask;
255 +       fmdev->irq_info.mask = (FM_FR_EVENT | FM_BL_EVENT);
256 +       payload = fmdev->irq_info.mask;
257 +       ret = fmc_send_cmd(fmdev, INT_MASK_SET, REG_WR, &payload,
258 +                       sizeof(payload), NULL, NULL);
259 +       if (ret < 0)
260 +               return ret;
262 +       /* Start seek */
263 +       payload = FM_TUNER_AUTONOMOUS_SEARCH_MODE;
264 +       ret = fmc_send_cmd(fmdev, TUNER_MODE_SET, REG_WR, &payload,
265 +                       sizeof(payload), NULL, NULL);
266 +       if (ret < 0)
267 +               return ret;
269 +       /* Wait for tune ended/band limit reached interrupt */
270 +       init_completion(&fmdev->maintask_comp);
271 +       timeleft = wait_for_completion_timeout(&fmdev->maintask_comp,
272 +                       FM_DRV_RX_SEEK_TIMEOUT);
273 +       if (!timeleft) {
274 +               fmerr("Timeout(%d sec),didn't get tune ended int\n",
275 +                          jiffies_to_msecs(FM_DRV_RX_SEEK_TIMEOUT) / 1000);
276 +               return -ETIMEDOUT;
277 +       }
279 +       int_reason = fmdev->irq_info.flag & (FM_TUNE_COMPLETE | FM_BAND_LIMIT);
281 +       /* Re-enable default FM interrupts */
282 +       fmdev->irq_info.mask = intr_flag;
283 +       payload = fmdev->irq_info.mask;
284 +       ret = fmc_send_cmd(fmdev, INT_MASK_SET, REG_WR, &payload,
285 +                       sizeof(payload), NULL, NULL);
286 +       if (ret < 0)
287 +               return ret;
289 +       if (int_reason & FM_BL_EVENT) {
290 +               if (wrap_around == 0) {
291 +                       fmdev->rx.freq = seek_upward ?
292 +                               fmdev->rx.region.top_freq :
293 +                               fmdev->rx.region.bot_freq;
294 +               } else {
295 +                       fmdev->rx.freq = seek_upward ?
296 +                               fmdev->rx.region.bot_freq :
297 +                               fmdev->rx.region.top_freq;
298 +                       /* Calculate frequency index to write */
299 +                       next_frq = (fmdev->rx.freq -
300 +                                       fmdev->rx.region.bot_freq) / FM_FREQ_MUL;
301 +                       goto again;
302 +               }
303 +       } else {
304 +               /* Read freq to know where operation tune operation stopped */
305 +               ret = fmc_send_cmd(fmdev, FREQ_SET, REG_RD, NULL, 2,
306 +                               &curr_frq, &resp_len);
307 +               if (ret < 0)
308 +                       return ret;
310 +               curr_frq = be16_to_cpu(curr_frq);
311 +               fmdev->rx.freq = (fmdev->rx.region.bot_freq +
312 +                               ((u32)curr_frq * FM_FREQ_MUL));
314 +       }
315 +       /* Reset RDS cache and current station pointers */
316 +       fm_rx_reset_rds_cache(fmdev);
317 +       fm_rx_reset_station_info(fmdev);
319 +       return ret;
320 +}
322 +u32 fm_rx_set_volume(struct fmdev *fmdev, u16 vol_to_set)
323 +{
324 +       u16 payload;
325 +       u32 ret;
327 +       if (fmdev->curr_fmmode != FM_MODE_RX)
328 +               return -EPERM;
330 +       if (vol_to_set < FM_RX_VOLUME_MIN || vol_to_set > FM_RX_VOLUME_MAX) {
331 +               fmerr("Volume is not within(%d-%d) range\n",
332 +                          FM_RX_VOLUME_MIN, FM_RX_VOLUME_MAX);
333 +               return -EINVAL;
334 +       }
335 +       vol_to_set *= FM_RX_VOLUME_GAIN_STEP;
337 +       payload = vol_to_set;
338 +       ret = fmc_send_cmd(fmdev, VOLUME_SET, REG_WR, &payload,
339 +                       sizeof(payload), NULL, NULL);
340 +       if (ret < 0)
341 +               return ret;
343 +       fmdev->rx.volume = vol_to_set;
344 +       return ret;
345 +}
347 +/* Get volume */
348 +u32 fm_rx_get_volume(struct fmdev *fmdev, u16 *curr_vol)
349 +{
350 +       if (fmdev->curr_fmmode != FM_MODE_RX)
351 +               return -EPERM;
353 +       if (curr_vol == NULL) {
354 +               fmerr("Invalid memory\n");
355 +               return -ENOMEM;
356 +       }
358 +       *curr_vol = fmdev->rx.volume / FM_RX_VOLUME_GAIN_STEP;
360 +       return 0;
361 +}
363 +/* To get current band's bottom and top frequency */
364 +u32 fm_rx_get_band_freq_range(struct fmdev *fmdev, u32 *bot_freq, u32 *top_freq)
365 +{
366 +       if (bot_freq != NULL)
367 +               *bot_freq = fmdev->rx.region.bot_freq;
369 +       if (top_freq != NULL)
370 +               *top_freq = fmdev->rx.region.top_freq;
372 +       return 0;
373 +}
375 +/* Returns current band index (0-Europe/US; 1-Japan) */
376 +void fm_rx_get_region(struct fmdev *fmdev, u8 *region)
377 +{
378 +       *region = fmdev->rx.region.fm_band;
379 +}
381 +/* Sets band (0-Europe/US; 1-Japan) */
382 +u32 fm_rx_set_region(struct fmdev *fmdev, u8 region_to_set)
383 +{
384 +       u16 payload;
385 +       u32 new_frq = 0;
386 +       u32 ret;
388 +       if (region_to_set != FM_BAND_EUROPE_US &&
389 +           region_to_set != FM_BAND_JAPAN) {
390 +               fmerr("Invalid band\n");
391 +               return -EINVAL;
392 +       }
394 +       if (fmdev->rx.region.fm_band == region_to_set) {
395 +               fmerr("Requested band is already configured\n");
396 +               return 0;
397 +       }
399 +       /* Send cmd to set the band  */
400 +       payload = (u16)region_to_set;
401 +       ret = fmc_send_cmd(fmdev, BAND_SET, REG_WR, &payload,
402 +                       sizeof(payload), NULL, NULL);
403 +       if (ret < 0)
404 +               return ret;
406 +       fmc_update_region_info(fmdev, region_to_set);
408 +       /* Check whether current RX frequency is within band boundary */
409 +       if (fmdev->rx.freq < fmdev->rx.region.bot_freq)
410 +               new_frq = fmdev->rx.region.bot_freq;
411 +       else if (fmdev->rx.freq > fmdev->rx.region.top_freq)
412 +               new_frq = fmdev->rx.region.top_freq;
414 +       if (new_frq) {
415 +               fmdbg("Current freq is not within band limit boundary,"
416 +                               "switching to %d KHz\n", new_frq);
417 +                /* Current RX frequency is not in range. So, update it */
418 +               ret = fm_rx_set_freq(fmdev, new_frq);
419 +       }
421 +       return ret;
422 +}
424 +/* Reads current mute mode (Mute Off/On/Attenuate)*/
425 +u32 fm_rx_get_mute_mode(struct fmdev *fmdev, u8 *curr_mute_mode)
426 +{
427 +       if (fmdev->curr_fmmode != FM_MODE_RX)
428 +               return -EPERM;
430 +       if (curr_mute_mode == NULL) {
431 +               fmerr("Invalid memory\n");
432 +               return -ENOMEM;
433 +       }
435 +       *curr_mute_mode = fmdev->rx.mute_mode;
437 +       return 0;
438 +}
440 +static u32 fm_config_rx_mute_reg(struct fmdev *fmdev)
441 +{
442 +       u16 payload, muteval;
443 +       u32 ret;
445 +       muteval = 0;
446 +       switch (fmdev->rx.mute_mode) {
447 +       case FM_MUTE_ON:
448 +               muteval = FM_RX_AC_MUTE_MODE;
449 +               break;
451 +       case FM_MUTE_OFF:
452 +               muteval = FM_RX_UNMUTE_MODE;
453 +               break;
455 +       case FM_MUTE_ATTENUATE:
456 +               muteval = FM_RX_SOFT_MUTE_FORCE_MODE;
457 +               break;
458 +       }
459 +       if (fmdev->rx.rf_depend_mute == FM_RX_RF_DEPENDENT_MUTE_ON)
460 +               muteval |= FM_RX_RF_DEP_MODE;
461 +       else
462 +               muteval &= ~FM_RX_RF_DEP_MODE;
464 +       payload = muteval;
465 +       ret = fmc_send_cmd(fmdev, MUTE_STATUS_SET, REG_WR, &payload,
466 +                       sizeof(payload), NULL, NULL);
467 +       if (ret < 0)
468 +               return ret;
470 +       return 0;
471 +}
473 +/* Configures mute mode (Mute Off/On/Attenuate) */
474 +u32 fm_rx_set_mute_mode(struct fmdev *fmdev, u8 mute_mode_toset)
475 +{
476 +       u8 org_state;
477 +       u32 ret;
479 +       if (fmdev->rx.mute_mode == mute_mode_toset)
480 +               return 0;
482 +       org_state = fmdev->rx.mute_mode;
483 +       fmdev->rx.mute_mode = mute_mode_toset;
485 +       ret = fm_config_rx_mute_reg(fmdev);
486 +       if (ret < 0) {
487 +               fmdev->rx.mute_mode = org_state;
488 +               return ret;
489 +       }
491 +       return 0;
492 +}
494 +/* Gets RF dependent soft mute mode enable/disable status */
495 +u32 fm_rx_get_rfdepend_softmute(struct fmdev *fmdev, u8 *curr_mute_mode)
496 +{
497 +       if (fmdev->curr_fmmode != FM_MODE_RX)
498 +               return -EPERM;
500 +       if (curr_mute_mode == NULL) {
501 +               fmerr("Invalid memory\n");
502 +               return -ENOMEM;
503 +       }
505 +       *curr_mute_mode = fmdev->rx.rf_depend_mute;
507 +       return 0;
508 +}
510 +/* Sets RF dependent soft mute mode */
511 +u32 fm_rx_set_rfdepend_softmute(struct fmdev *fmdev, u8 rfdepend_mute)
512 +{
513 +       u8 org_state;
514 +       u32 ret;
516 +       if (fmdev->curr_fmmode != FM_MODE_RX)
517 +               return -EPERM;
519 +       if (rfdepend_mute != FM_RX_RF_DEPENDENT_MUTE_ON &&
520 +           rfdepend_mute != FM_RX_RF_DEPENDENT_MUTE_OFF) {
521 +               fmerr("Invalid RF dependent soft mute\n");
522 +               return -EINVAL;
523 +       }
524 +       if (fmdev->rx.rf_depend_mute == rfdepend_mute)
525 +               return 0;
527 +       org_state = fmdev->rx.rf_depend_mute;
528 +       fmdev->rx.rf_depend_mute = rfdepend_mute;
530 +       ret = fm_config_rx_mute_reg(fmdev);
531 +       if (ret < 0) {
532 +               fmdev->rx.rf_depend_mute = org_state;
533 +               return ret;
534 +       }
536 +       return 0;
537 +}
539 +/* Returns the signal strength level of current channel */
540 +u32 fm_rx_get_rssi_level(struct fmdev *fmdev, u16 *rssilvl)
541 +{
542 +       u16 curr_rssi_lel;
543 +       u32 resp_len;
544 +       u32 ret;
546 +       if (rssilvl == NULL) {
547 +               fmerr("Invalid memory\n");
548 +               return -ENOMEM;
549 +       }
550 +       /* Read current RSSI level */
551 +       ret = fmc_send_cmd(fmdev, RSSI_LVL_GET, REG_RD, NULL, 2,
552 +                       &curr_rssi_lel, &resp_len);
553 +       if (ret < 0)
554 +               return ret;
556 +       *rssilvl = be16_to_cpu(curr_rssi_lel);
558 +       return 0;
559 +}
561 +/*
562 + * Sets the signal strength level that once reached
563 + * will stop the auto search process
564 + */
565 +u32 fm_rx_set_rssi_threshold(struct fmdev *fmdev, short rssi_lvl_toset)
566 +{
567 +       u16 payload;
568 +       u32 ret;
570 +       if (rssi_lvl_toset < FM_RX_RSSI_THRESHOLD_MIN ||
571 +                       rssi_lvl_toset > FM_RX_RSSI_THRESHOLD_MAX) {
572 +               fmerr("Invalid RSSI threshold level\n");
573 +               return -EINVAL;
574 +       }
575 +       payload = (u16)rssi_lvl_toset;
576 +       ret = fmc_send_cmd(fmdev, SEARCH_LVL_SET, REG_WR, &payload,
577 +                       sizeof(payload), NULL, NULL);
578 +       if (ret < 0)
579 +               return ret;
581 +       fmdev->rx.rssi_threshold = rssi_lvl_toset;
583 +       return 0;
584 +}
586 +/* Returns current RX RSSI threshold value */
587 +u32 fm_rx_get_rssi_threshold(struct fmdev *fmdev, short *curr_rssi_lvl)
588 +{
589 +       if (fmdev->curr_fmmode != FM_MODE_RX)
590 +               return -EPERM;
592 +       if (curr_rssi_lvl == NULL) {
593 +               fmerr("Invalid memory\n");
594 +               return -ENOMEM;
595 +       }
597 +       *curr_rssi_lvl = fmdev->rx.rssi_threshold;
599 +       return 0;
600 +}
602 +/* Sets RX stereo/mono modes */
603 +u32 fm_rx_set_stereo_mono(struct fmdev *fmdev, u16 mode)
604 +{
605 +       u16 payload;
606 +       u32 ret;
608 +       if (mode != FM_STEREO_MODE && mode != FM_MONO_MODE) {
609 +               fmerr("Invalid mode\n");
610 +               return -EINVAL;
611 +       }
613 +       /* Set stereo/mono mode */
614 +       payload = (u16)mode;
615 +       ret = fmc_send_cmd(fmdev, MOST_MODE_SET, REG_WR, &payload,
616 +                       sizeof(payload), NULL, NULL);
617 +       if (ret < 0)
618 +               return ret;
620 +       /* Set stereo blending mode */
621 +       payload = FM_STEREO_SOFT_BLEND;
622 +       ret = fmc_send_cmd(fmdev, MOST_BLEND_SET, REG_WR, &payload,
623 +                       sizeof(payload), NULL, NULL);
624 +       if (ret < 0)
625 +               return ret;
627 +       return 0;
628 +}
630 +/* Gets current RX stereo/mono mode */
631 +u32 fm_rx_get_stereo_mono(struct fmdev *fmdev, u16 *mode)
632 +{
633 +       u16 curr_mode;
634 +       u32 ret, resp_len;
636 +       if (mode == NULL) {
637 +               fmerr("Invalid memory\n");
638 +               return -ENOMEM;
639 +       }
641 +       ret = fmc_send_cmd(fmdev, MOST_MODE_SET, REG_RD, NULL, 2,
642 +                       &curr_mode, &resp_len);
643 +       if (ret < 0)
644 +               return ret;
646 +       *mode = be16_to_cpu(curr_mode);
648 +       return 0;
649 +}
651 +/* Choose RX de-emphasis filter mode (50us/75us) */
652 +u32 fm_rx_set_deemphasis_mode(struct fmdev *fmdev, u16 mode)
653 +{
654 +       u16 payload;
655 +       u32 ret;
657 +       if (fmdev->curr_fmmode != FM_MODE_RX)
658 +               return -EPERM;
660 +       if (mode != FM_RX_EMPHASIS_FILTER_50_USEC &&
661 +                       mode != FM_RX_EMPHASIS_FILTER_75_USEC) {
662 +               fmerr("Invalid rx de-emphasis mode (%d)\n", mode);
663 +               return -EINVAL;
664 +       }
666 +       payload = mode;
667 +       ret = fmc_send_cmd(fmdev, DEMPH_MODE_SET, REG_WR, &payload,
668 +                       sizeof(payload), NULL, NULL);
669 +       if (ret < 0)
670 +               return ret;
672 +       fmdev->rx.deemphasis_mode = mode;
674 +       return 0;
675 +}
677 +/* Gets current RX de-emphasis filter mode */
678 +u32 fm_rx_get_deemph_mode(struct fmdev *fmdev, u16 *curr_deemphasis_mode)
679 +{
680 +       if (fmdev->curr_fmmode != FM_MODE_RX)
681 +               return -EPERM;
683 +       if (curr_deemphasis_mode == NULL) {
684 +               fmerr("Invalid memory\n");
685 +               return -ENOMEM;
686 +       }
688 +       *curr_deemphasis_mode = fmdev->rx.deemphasis_mode;
690 +       return 0;
691 +}
693 +/* Enable/Disable RX RDS */
694 +u32 fm_rx_set_rds_mode(struct fmdev *fmdev, u8 rds_en_dis)
695 +{
696 +       u16 payload;
697 +       u32 ret;
699 +       if (rds_en_dis != FM_RDS_ENABLE && rds_en_dis != FM_RDS_DISABLE) {
700 +               fmerr("Invalid rds option\n");
701 +               return -EINVAL;
702 +       }
704 +       if (rds_en_dis == FM_RDS_ENABLE
705 +           && fmdev->rx.rds.flag == FM_RDS_DISABLE) {
706 +               /* Turn on RX RDS and RDS circuit */
707 +               payload = FM_RX_PWR_SET_FM_AND_RDS_BLK_ON;
708 +               ret = fmc_send_cmd(fmdev, POWER_SET, REG_WR, &payload,
709 +                               sizeof(payload), NULL, NULL);
710 +               if (ret < 0)
711 +                       return ret;
713 +               /* Clear and reset RDS FIFO */
714 +               payload = FM_RX_RDS_FLUSH_FIFO;
715 +               ret = fmc_send_cmd(fmdev, RDS_CNTRL_SET, REG_WR, &payload,
716 +               sizeof(payload), NULL, NULL);
717 +               if (ret < 0)
718 +                       return ret;
720 +               /* Read flags - just to clear any pending interrupts. */
721 +               ret = fmc_send_cmd(fmdev, FLAG_GET, REG_RD, NULL, 2,
722 +                               NULL, NULL);
723 +               if (ret < 0)
724 +                       return ret;
726 +               /* Set RDS FIFO threshold value */
727 +               payload = FM_RX_RDS_FIFO_THRESHOLD;
728 +               ret = fmc_send_cmd(fmdev, RDS_MEM_SET, REG_WR, &payload,
729 +               sizeof(payload), NULL, NULL);
730 +               if (ret < 0)
731 +                       return ret;
733 +               /* Enable RDS interrupt */
734 +               fmdev->irq_info.mask |= FM_RDS_EVENT;
735 +               payload = fmdev->irq_info.mask;
736 +               ret = fmc_send_cmd(fmdev, INT_MASK_SET, REG_WR, &payload,
737 +                               sizeof(payload), NULL, NULL);
738 +               if (ret < 0) {
739 +                       fmdev->irq_info.mask &= ~FM_RDS_EVENT;
740 +                       return ret;
741 +               }
743 +               /* Update our local flag */
744 +               fmdev->rx.rds.flag = FM_RDS_ENABLE;
745 +       } else if (rds_en_dis == FM_RDS_DISABLE
746 +                  && fmdev->rx.rds.flag == FM_RDS_ENABLE) {
747 +               /* Turn off RX RDS */
748 +               payload = FM_RX_PWR_SET_FM_ON_RDS_OFF;
749 +               ret = fmc_send_cmd(fmdev, POWER_SET, REG_WR, &payload,
750 +                               sizeof(payload), NULL, NULL);
751 +               if (ret < 0)
752 +                       return ret;
754 +               /* Reset RDS pointers */
755 +               fmdev->rx.rds.last_blk_idx = 0;
756 +               fmdev->rx.rds.wr_idx = 0;
757 +               fmdev->rx.rds.rd_idx = 0;
758 +               fm_rx_reset_station_info(fmdev);
760 +               /* Update RDS local cache */
761 +               fmdev->irq_info.mask &= ~(FM_RDS_EVENT);
762 +               fmdev->rx.rds.flag = FM_RDS_DISABLE;
763 +       }
765 +       return 0;
766 +}
768 +/* Returns current RX RDS enable/disable status */
769 +u32 fm_rx_get_rds_mode(struct fmdev *fmdev, u8 *curr_rds_en_dis)
770 +{
771 +       if (fmdev->curr_fmmode != FM_MODE_RX)
772 +               return -EPERM;
774 +       if (curr_rds_en_dis == NULL) {
775 +               fmerr("Invalid memory\n");
776 +               return -ENOMEM;
777 +       }
779 +       *curr_rds_en_dis = fmdev->rx.rds.flag;
781 +       return 0;
782 +}
784 +/* Sets RDS operation mode (RDS/RDBS) */
785 +u32 fm_rx_set_rds_system(struct fmdev *fmdev, u8 rds_mode)
786 +{
787 +       u16 payload;
788 +       u32 ret;
790 +       if (fmdev->curr_fmmode != FM_MODE_RX)
791 +               return -EPERM;
793 +       if (rds_mode != FM_RDS_SYSTEM_RDS && rds_mode != FM_RDS_SYSTEM_RBDS) {
794 +               fmerr("Invalid rds mode\n");
795 +               return -EINVAL;
796 +       }
797 +       /* Set RDS operation mode */
798 +       payload = (u16)rds_mode;
799 +       ret = fmc_send_cmd(fmdev, RDS_SYSTEM_SET, REG_WR, &payload,
800 +                       sizeof(payload), NULL, NULL);
801 +       if (ret < 0)
802 +               return ret;
804 +       fmdev->rx.rds_mode = rds_mode;
806 +       return 0;
807 +}
809 +/* Returns current RDS operation mode */
810 +u32 fm_rx_get_rds_system(struct fmdev *fmdev, u8 *rds_mode)
811 +{
812 +       if (fmdev->curr_fmmode != FM_MODE_RX)
813 +               return -EPERM;
815 +       if (rds_mode == NULL) {
816 +               fmerr("Invalid memory\n");
817 +               return -ENOMEM;
818 +       }
820 +       *rds_mode = fmdev->rx.rds_mode;
822 +       return 0;
823 +}
825 +/* Configures Alternate Frequency switch mode */
826 +u32 fm_rx_set_af_switch(struct fmdev *fmdev, u8 af_mode)
827 +{
828 +       u16 payload;
829 +       u32 ret;
831 +       if (fmdev->curr_fmmode != FM_MODE_RX)
832 +               return -EPERM;
834 +       if (af_mode != FM_RX_RDS_AF_SWITCH_MODE_ON &&
835 +           af_mode != FM_RX_RDS_AF_SWITCH_MODE_OFF) {
836 +               fmerr("Invalid af mode\n");
837 +               return -EINVAL;
838 +       }
839 +       /* Enable/disable low RSSI interrupt based on af_mode */
840 +       if (af_mode == FM_RX_RDS_AF_SWITCH_MODE_ON)
841 +               fmdev->irq_info.mask |= FM_LEV_EVENT;
842 +       else
843 +               fmdev->irq_info.mask &= ~FM_LEV_EVENT;
845 +       payload = fmdev->irq_info.mask;
846 +       ret = fmc_send_cmd(fmdev, INT_MASK_SET, REG_WR, &payload,
847 +                       sizeof(payload), NULL, NULL);
848 +       if (ret < 0)
849 +               return ret;
851 +       fmdev->rx.af_mode = af_mode;
853 +       return 0;
854 +}
856 +/* Returns Alternate Frequency switch status */
857 +u32 fm_rx_get_af_switch(struct fmdev *fmdev, u8 *af_mode)
858 +{
859 +       if (fmdev->curr_fmmode != FM_MODE_RX)
860 +               return -EPERM;
862 +       if (af_mode == NULL) {
863 +               fmerr("Invalid memory\n");
864 +               return -ENOMEM;
865 +       }
867 +       *af_mode = fmdev->rx.af_mode;
869 +       return 0;
870 +}
871 diff --git a/drivers/media/radio/wl128x/fmdrv_rx.h b/drivers/media/radio/wl128x/fmdrv_rx.h
872 new file mode 100644
873 index 0000000..329e62f
874 --- /dev/null
875 +++ b/drivers/media/radio/wl128x/fmdrv_rx.h
876 @@ -0,0 +1,59 @@
877 +/*
878 + *  FM Driver for Connectivity chip of Texas Instruments.
879 + *  FM RX module header.
880 + *
881 + *  Copyright (C) 2011 Texas Instruments
882 + *
883 + *  This program is free software; you can redistribute it and/or modify
884 + *  it under the terms of the GNU General Public License version 2 as
885 + *  published by the Free Software Foundation.
886 + *
887 + *  This program is distributed in the hope that it will be useful,
888 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
889 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
890 + *  GNU General Public License for more details.
891 + *
892 + *  You should have received a copy of the GNU General Public License
893 + *  along with this program; if not, write to the Free Software
894 + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
895 + *
896 + */
898 +#ifndef _FMDRV_RX_H
899 +#define _FMDRV_RX_H
901 +u32 fm_rx_set_freq(struct fmdev *, u32);
902 +u32 fm_rx_set_mute_mode(struct fmdev *, u8);
903 +u32 fm_rx_set_stereo_mono(struct fmdev *, u16);
904 +u32 fm_rx_set_rds_mode(struct fmdev *, u8);
905 +u32 fm_rx_set_rds_system(struct fmdev *, u8);
906 +u32 fm_rx_set_volume(struct fmdev *, u16);
907 +u32 fm_rx_set_rssi_threshold(struct fmdev *, short);
908 +u32 fm_rx_set_region(struct fmdev *, u8);
909 +u32 fm_rx_set_rfdepend_softmute(struct fmdev *, u8);
910 +u32 fm_rx_set_deemphasis_mode(struct fmdev *, u16);
911 +u32 fm_rx_set_af_switch(struct fmdev *, u8);
913 +void fm_rx_reset_rds_cache(struct fmdev *);
914 +void fm_rx_reset_station_info(struct fmdev *);
916 +u32 fm_rx_seek(struct fmdev *, u32, u32, u32);
918 +u32 fm_rx_get_rds_mode(struct fmdev *, u8 *);
919 +u32 fm_rx_get_rds_system(struct fmdev *, u8 *);
920 +u32 fm_rx_get_mute_mode(struct fmdev *, u8 *);
921 +u32 fm_rx_get_volume(struct fmdev *, u16 *);
922 +u32 fm_rx_get_band_freq_range(struct fmdev *,
923 +                                       u32 *, u32 *);
924 +u32 fm_rx_get_stereo_mono(struct fmdev *, u16 *);
925 +u32 fm_rx_get_rssi_level(struct fmdev *, u16 *);
926 +u32 fm_rx_get_rssi_threshold(struct fmdev *, short *);
927 +u32 fm_rx_get_rfdepend_softmute(struct fmdev *, u8 *);
928 +u32 fm_rx_get_deemph_mode(struct fmdev *, u16 *);
929 +u32 fm_rx_get_af_switch(struct fmdev *, u8 *);
930 +void fm_rx_get_region(struct fmdev *, u8 *);
932 +u32 fm_rx_set_chanl_spacing(struct fmdev *, u8);
933 +u32 fm_rx_get_chanl_spacing(struct fmdev *, u8 *);
934 +#endif
936 -- 
937 1.6.6.1