blob: 33775ae156579d7111fe64d64cbc6cc68a7a97ce [file] [log] [blame]
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001/* Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 */
13/*
14 * Qualcomm Tavarua FM core driver
15 */
16
17/* driver definitions */
18#define DRIVER_AUTHOR "Qualcomm"
19#define DRIVER_NAME "radio-tavarua"
20#define DRIVER_CARD "Qualcomm FM Radio Transceiver"
21#define DRIVER_DESC "I2C radio driver for Qualcomm FM Radio Transceiver "
22#define DRIVER_VERSION "1.0.0"
23
24#include <linux/version.h>
25#include <linux/init.h> /* Initdata */
26#include <linux/delay.h> /* udelay */
27#include <linux/uaccess.h> /* copy to/from user */
28#include <linux/kfifo.h> /* lock free circular buffer */
29#include <linux/param.h>
30#include <linux/i2c.h>
31#include <linux/irq.h>
32#include <linux/interrupt.h>
33
34/* kernel includes */
35#include <linux/kernel.h>
36#include <linux/module.h>
37#include <linux/version.h>
38#include <linux/videodev2.h>
39#include <linux/mutex.h>
40#include <media/v4l2-common.h>
41#include <asm/unaligned.h>
42#include <media/v4l2-ioctl.h>
43#include <linux/unistd.h>
44#include <asm/atomic.h>
45#include <media/tavarua.h>
46#include <linux/mfd/marimba.h>
47#include <linux/platform_device.h>
48#include <linux/workqueue.h>
49#include <linux/slab.h>
50/*
51regional parameters for radio device
52*/
53struct region_params_t {
54 enum tavarua_region_t region;
55 unsigned int band_high;
56 unsigned int band_low;
57 char emphasis;
58 char rds_std;
59 char spacing;
60};
61
62struct srch_params_t {
63 unsigned short srch_pi;
64 unsigned char srch_pty;
65 unsigned int preset_num;
66 int get_list;
67};
68
69/* Main radio device structure,
70acts as a shadow copy of the
71actual tavaura registers */
72struct tavarua_device {
73 struct video_device *videodev;
74 /* driver management */
75 int users;
76 /* top level driver data */
77 struct marimba *marimba;
78 struct device *dev;
79 /* platform specific functionality */
80 struct marimba_fm_platform_data *pdata;
81 unsigned int chipID;
82 /*RDS buffers + Radio event buffer*/
83 struct kfifo data_buf[TAVARUA_BUF_MAX];
84 /* search paramters */
85 struct srch_params_t srch_params;
86 /* keep track of pending xfrs */
87 int pending_xfrs[TAVARUA_XFR_MAX];
88 int xfr_bytes_left;
89 int xfr_in_progress;
90 /* Transmit data */
91 enum tavarua_xfr_ctrl_t tx_mode;
92 /* synchrnous xfr data */
93 unsigned char sync_xfr_regs[XFR_REG_NUM];
94 struct completion sync_xfr_start;
95 struct completion sync_req_done;
96 int tune_req;
97 /* internal register status */
98 unsigned char registers[RADIO_REGISTERS];
99 /* regional settings */
100 struct region_params_t region_params;
101 /* power mode */
102 int lp_mode;
103 int handle_irq;
104 /* global lock */
105 struct mutex lock;
106 /* buffer locks*/
107 spinlock_t buf_lock[TAVARUA_BUF_MAX];
108 /* work queue */
109 struct workqueue_struct *wqueue;
110 struct delayed_work work;
111 /* wait queue for blocking event read */
112 wait_queue_head_t event_queue;
113 /* wait queue for raw rds read */
114 wait_queue_head_t read_queue;
115 /* PTY for FM Tx */
116 int pty;
117 /* PI for FM TX */
118 int pi;
119 /*PS repeatcount for PS Tx */
120 int ps_repeatcount;
121};
122
123/**************************************************************************
124 * Module Parameters
125 **************************************************************************/
126
127/* Radio Nr */
128static int radio_nr = -1;
129module_param(radio_nr, int, 0);
130MODULE_PARM_DESC(radio_nr, "Radio Nr");
131static int wait_timeout = WAIT_TIMEOUT;
132/* Bahama's version*/
133static u8 bahama_version;
134/* RDS buffer blocks */
135static unsigned int rds_buf = 100;
136module_param(rds_buf, uint, 0);
137MODULE_PARM_DESC(rds_buf, "RDS buffer entries: *100*");
138/* static variables */
139static struct tavarua_device *private_data;
140/* forward declerations */
141static int tavarua_disable_interrupts(struct tavarua_device *radio);
142static int tavarua_setup_interrupts(struct tavarua_device *radio,
143 enum radio_state_t state);
144static int tavarua_start(struct tavarua_device *radio,
145 enum radio_state_t state);
146static int tavarua_request_irq(struct tavarua_device *radio);
147static void start_pending_xfr(struct tavarua_device *radio);
148/* work function */
149static void read_int_stat(struct work_struct *work);
150
151static int is_bahama(void)
152{
153 int id = 0;
154
155 switch (id = adie_get_detected_connectivity_type()) {
156 case BAHAMA_ID:
157 FMDBG("It is Bahama\n");
158 return 1;
159
160 case MARIMBA_ID:
161 FMDBG("It is Marimba\n");
162 return 0;
163 default:
164 printk(KERN_ERR "%s: unexpected adie connectivity type: %d\n",
165 __func__, id);
166 return -ENODEV;
167 }
168}
169
170static int set_fm_slave_id(struct tavarua_device *radio)
171{
172 int bahama_present = is_bahama();
173
174 if (bahama_present == -ENODEV)
175 return -ENODEV;
176
177 if (bahama_present)
178 radio->marimba->mod_id = SLAVE_ID_BAHAMA_FM;
179 else
180 radio->marimba->mod_id = MARIMBA_SLAVE_ID_FM;
181
182 return 0;
183}
184
185/*=============================================================================
186FUNCTION: tavarua_isr
187=============================================================================*/
188/**
189 This function is called when GPIO is toggled. This functions queues the event
190 to interrupt queue, which is later handled by isr handling funcion.
191 i.e. INIT_DELAYED_WORK(&radio->work, read_int_stat);
192
193 @param irq: irq that is toggled.
194 @param dev_id: structure pointer passed by client.
195
196 @return IRQ_HANDLED.
197*/
198static irqreturn_t tavarua_isr(int irq, void *dev_id)
199{
200 struct tavarua_device *radio = dev_id;
201 /* schedule a tasklet to handle host intr */
202 /* The call to queue_delayed_work ensures that a minimum delay (in jiffies)
203 * passes before the work is actually executed. The return value from the
204 * function is nonzero if the work_struct was actually added to queue
205 * (otherwise, it may have already been there and will not be added a second
206 * time).
207 */
208 queue_delayed_work(radio->wqueue, &radio->work,
209 msecs_to_jiffies(TAVARUA_DELAY));
210 return IRQ_HANDLED;
211}
212
213/**************************************************************************
214 * Interface to radio internal registers over top level marimba driver
215 *************************************************************************/
216
217/*=============================================================================
218FUNCTION: tavarua_read_registers
219=============================================================================*/
220/**
221 This function is called to read a number of bytes from an I2C interface.
222 The bytes read are stored in internal register status (shadow copy).
223
224 @param radio: structure pointer passed by client.
225 @param offset: register offset.
226 @param len: num of bytes.
227
228 @return => 0 if successful.
229 @return < 0 if failure.
230*/
231static int tavarua_read_registers(struct tavarua_device *radio,
232 unsigned char offset, int len)
233{
234 int retval = 0, i = 0;
235 retval = set_fm_slave_id(radio);
236
237 if (retval == -ENODEV)
238 return retval;
239
240 FMDBG_I2C("I2C Slave: %x, Read Offset(%x): Data [",
241 radio->marimba->mod_id,
242 offset);
243
244 retval = marimba_read(radio->marimba, offset,
245 &radio->registers[offset], len);
246
247 if (retval > 0) {
248 for (i = 0; i < len; i++)
249 FMDBG_I2C("%02x ", radio->registers[offset+i]);
250 FMDBG_I2C(" ]\n");
251
252 }
253 return retval;
254}
255
256/*=============================================================================
257FUNCTION: tavarua_write_register
258=============================================================================*/
259/**
260 This function is called to write a byte over the I2C interface.
261 The corresponding shadow copy is stored in internal register status.
262
263 @param radio: structure pointer passed by client.
264 @param offset: register offset.
265 @param value: buffer to be written to the registers.
266
267 @return => 0 if successful.
268 @return < 0 if failure.
269*/
270static int tavarua_write_register(struct tavarua_device *radio,
271 unsigned char offset, unsigned char value)
272{
273 int retval;
274 retval = set_fm_slave_id(radio);
275
276 if (retval == -ENODEV)
277 return retval;
278
279 FMDBG_I2C("I2C Slave: %x, Write Offset(%x): Data[",
280 radio->marimba->mod_id,
281 offset);
282 retval = marimba_write(radio->marimba, offset, &value, 1);
283 if (retval > 0) {
284 if (offset < RADIO_REGISTERS) {
285 radio->registers[offset] = value;
286 FMDBG_I2C("%02x ", radio->registers[offset]);
287 }
288 FMDBG_I2C(" ]\n");
289 }
290 return retval;
291}
292
293/*=============================================================================
294FUNCTION: tavarua_write_registers
295=============================================================================*/
296/**
297 This function is called to write a number of bytes over the I2C interface.
298 The corresponding shadow copy is stored in internal register status.
299
300 @param radio: structure pointer passed by client.
301 @param offset: register offset.
302 @param buf: buffer to be written to the registers.
303 @param len: num of bytes.
304
305 @return => 0 if successful.
306 @return < 0 if failure.
307*/
308static int tavarua_write_registers(struct tavarua_device *radio,
309 unsigned char offset, unsigned char *buf, int len)
310{
311
312 int i;
313 int retval;
314 retval = set_fm_slave_id(radio);
315
316 if (retval == -ENODEV)
317 return retval;
318
319 FMDBG_I2C("I2C Slave: %x, Write Offset(%x): Data[",
320 radio->marimba->mod_id,
321 offset);
322 retval = marimba_write(radio->marimba, offset, buf, len);
323 if (retval > 0) { /* if write successful, update internal state too */
324 for (i = 0; i < len; i++) {
325 if ((offset+i) < RADIO_REGISTERS) {
326 radio->registers[offset+i] = buf[i];
327 FMDBG_I2C("%x ", radio->registers[offset+i]);
328 }
329 }
330 FMDBG_I2C(" ]\n");
331 }
332 return retval;
333}
334
335/*=============================================================================
336FUNCTION: read_data_blocks
337=============================================================================*/
338/**
339 This function reads Raw RDS blocks from Core regs to driver
340 internal regs (shadow copy).
341
342 @param radio: structure pointer passed by client.
343 @param offset: register offset.
344
345 @return => 0 if successful.
346 @return < 0 if failure.
347*/
348static int read_data_blocks(struct tavarua_device *radio, unsigned char offset)
349{
350 /* read all 3 RDS blocks */
351 return tavarua_read_registers(radio, offset, RDS_BLOCK*4);
352}
353
354/*=============================================================================
355FUNCTION: tavarua_rds_read
356=============================================================================*/
357/**
358 This is a rds processing function reads that reads Raw RDS blocks from Core
359 regs to driver internal regs (shadow copy). It then fills the V4L2 RDS buffer,
360 which is read by App using JNI interface.
361
362 @param radio: structure pointer passed by client.
363
364 @return None.
365*/
366static void tavarua_rds_read(struct tavarua_device *radio)
367{
368 struct kfifo *rds_buf = &radio->data_buf[TAVARUA_BUF_RAW_RDS];
369 unsigned char blocknum;
370 unsigned char tmp[3];
371
372 if (read_data_blocks(radio, RAW_RDS) < 0)
373 return;
374 /* copy all four RDS blocks to internal buffer */
375 for (blocknum = 0; blocknum < RDS_BLOCKS_NUM; blocknum++) {
376 /* Fill the V4L2 RDS buffer */
377 put_unaligned(cpu_to_le16(radio->registers[RAW_RDS +
378 blocknum*RDS_BLOCK]), (unsigned short *) tmp);
379 tmp[2] = blocknum; /* offset name */
380 tmp[2] |= blocknum << 3; /* received offset */
381 tmp[2] |= 0x40; /* corrected error(s) */
382
383 /* copy RDS block to internal buffer */
384 kfifo_in_locked(rds_buf, tmp, 3, &radio->buf_lock[TAVARUA_BUF_RAW_RDS]);
385 }
386 /* wake up read queue */
387 if (kfifo_len(rds_buf))
388 wake_up_interruptible(&radio->read_queue);
389
390}
391
392/*=============================================================================
393FUNCTION: request_read_xfr
394=============================================================================*/
395/**
396 This function sets the desired MODE in the XFRCTRL register and also sets the
397 CTRL field to read.
398 This is an asynchronous way of reading the XFR registers. Client would request
399 by setting the desired mode in the XFRCTRL register and then would initiate
400 the actual data register read by calling copy_from_xfr up on SOC signals
401 success.
402
403 NOTE:
404
405 The Data Transfer (XFR) registers are used to pass various data and
406 configuration parameters between the Core and host processor.
407
408 To read from the XFR registers, the host processor must set the desired MODE
409 in the XFRCTRL register and set the CTRL field to read. The Core will then
410 populate the XFRDAT0 - XFRDAT15 registers with the defined mode bytes. The
411 Core will set the TRANSFER interrupt status bit and interrupt the host if the
412 TRANSFERCTRL interrupt control bit is set. The host can then extract the XFR
413 mode bytes once it detects that the Core has updated the registers.
414
415 @param radio: structure pointer passed by client.
416
417 @return Always returns 0.
418*/
419static int request_read_xfr(struct tavarua_device *radio,
420 enum tavarua_xfr_ctrl_t mode){
421
422 tavarua_write_register(radio, XFRCTRL, mode);
423 msleep(TAVARUA_DELAY);
424 return 0;
425}
426
427/*=============================================================================
428FUNCTION: copy_from_xfr
429=============================================================================*/
430/**
431 This function is used to read XFR mode bytes once it detects that the Core
432 has updated the registers. It also updates XFR regs to the appropriate
433 internal buffer n bytes.
434
435 NOTE:
436
437 This function should be used in conjuction with request_read_xfr. Refer
438 request_read_xfr for XFR mode transaction details.
439
440 @param radio: structure pointer passed by client.
441 @param buf_type: Index into RDS/Radio event buffer to use.
442 @param len: num of bytes.
443
444 @return Always returns 0.
445*/
446static int copy_from_xfr(struct tavarua_device *radio,
447 enum tavarua_buf_t buf_type, unsigned int n){
448
449 struct kfifo *data_fifo = &radio->data_buf[buf_type];
450 unsigned char *xfr_regs = &radio->registers[XFRCTRL+1];
451 kfifo_in_locked(data_fifo, xfr_regs, n, &radio->buf_lock[buf_type]);
452 return 0;
453}
454
455/*=============================================================================
456FUNCTION: write_to_xfr
457=============================================================================*/
458/**
459 This function sets the desired MODE in the XFRCTRL register and it also sets
460 the CTRL field and data to write.
461 This also writes all the XFRDATx registers with the desired input buffer.
462
463 NOTE:
464
465 The Data Transfer (XFR) registers are used to pass various data and
466 configuration parameters between the Core and host processor.
467
468 To write data to the Core, the host processor updates XFRDAT0 - XFRDAT15 with
469 the appropriate mode bytes. The host processor must then set the desired MODE
470 in the XFRCTRL register and set the CTRL field to write. The core will detect
471 that the XFRCTRL register was written to and will read the XFR mode bytes.
472 After reading all the mode bytes, the Core will set the TRANSFER interrupt
473 status bit and interrupt the host if the TRANSFERCTRL interrupt control bit
474 is set.
475
476 @param radio: structure pointer passed by client.
477 @param mode: XFR mode to write in XFRCTRL register.
478 @param buf: buffer to be written to the registers.
479 @param len: num of bytes.
480
481 @return => 0 if successful.
482 @return < 0 if failure.
483*/
484static int write_to_xfr(struct tavarua_device *radio, unsigned char mode,
485 char *buf, int len)
486{
487 char buffer[len+1];
488 memcpy(buffer+1, buf, len);
489 /* buffer[0] corresponds to XFRCTRL register
490 set the CTRL bit to 1 for write mode
491 */
492 buffer[0] = ((1<<7) | mode);
493 return tavarua_write_registers(radio, XFRCTRL, buffer, sizeof(buffer));
494}
495
496/*=============================================================================
497FUNCTION: xfr_intf_own
498=============================================================================*/
499/**
500 This function is used to check if there is any pending XFR mode operation.
501 If yes, wait for it to complete, else update the flag to indicate XFR
502 operation is in progress
503
504 @param radio: structure pointer passed by client.
505
506 @return 0 on success.
507 -ETIME on timeout.
508*/
509static int xfr_intf_own(struct tavarua_device *radio)
510{
511
512 mutex_lock(&radio->lock);
513 if (radio->xfr_in_progress) {
514 radio->pending_xfrs[TAVARUA_XFR_SYNC] = 1;
515 mutex_unlock(&radio->lock);
516 if (!wait_for_completion_timeout(&radio->sync_xfr_start,
517 msecs_to_jiffies(wait_timeout)))
518 return -ETIME;
519 } else {
520 FMDBG("gained ownership of xfr\n");
521 radio->xfr_in_progress = 1;
522 mutex_unlock(&radio->lock);
523 }
524 return 0;
525}
526
527/*=============================================================================
528FUNCTION: sync_read_xfr
529=============================================================================*/
530/**
531 This function is used to do synchronous XFR read operation.
532
533 @param radio: structure pointer passed by client.
534 @param xfr_type: XFR mode to write in XFRCTRL register.
535 @param buf: buffer to be read from the core.
536
537 @return => 0 if successful.
538 @return < 0 if failure.
539*/
540static int sync_read_xfr(struct tavarua_device *radio,
541 enum tavarua_xfr_ctrl_t xfr_type, unsigned char *buf)
542{
543 int retval;
544 retval = xfr_intf_own(radio);
545 if (retval < 0)
546 return retval;
547 retval = tavarua_write_register(radio, XFRCTRL, xfr_type);
548
549 if (retval >= 0) {
550 /* Wait for interrupt i.e. complete
551 (&radio->sync_req_done); call */
552 if (!wait_for_completion_timeout(&radio->sync_req_done,
553 msecs_to_jiffies(wait_timeout)) || (retval < 0)) {
554 retval = -ETIME;
555 } else {
556 memcpy(buf, radio->sync_xfr_regs, XFR_REG_NUM);
557 }
558 }
559 radio->xfr_in_progress = 0;
560 start_pending_xfr(radio);
561 FMDBG("%s: %d\n", __func__, retval);
562 return retval;
563}
564
565/*=============================================================================
566FUNCTION: sync_write_xfr
567=============================================================================*/
568/**
569 This function is used to do synchronous XFR write operation.
570
571 @param radio: structure pointer passed by client.
572 @param xfr_type: XFR mode to write in XFRCTRL register.
573 @param buf: buffer to be written to the core.
574
575 @return => 0 if successful.
576 @return < 0 if failure.
577*/
578static int sync_write_xfr(struct tavarua_device *radio,
579 enum tavarua_xfr_ctrl_t xfr_type, unsigned char *buf)
580{
581 int retval;
582 retval = xfr_intf_own(radio);
583 if (retval < 0)
584 return retval;
585 retval = write_to_xfr(radio, xfr_type, buf, XFR_REG_NUM);
586
587 if (retval >= 0) {
588 /* Wait for interrupt i.e. complete
589 (&radio->sync_req_done); call */
590 if (!wait_for_completion_timeout(&radio->sync_req_done,
591 msecs_to_jiffies(wait_timeout)) || (retval < 0)) {
592 FMDBG("Write xfr timeout");
593 }
594 }
595 radio->xfr_in_progress = 0;
596 start_pending_xfr(radio);
597 FMDBG("%s: %d\n", __func__, retval);
598 return retval;
599}
600
601
602/*=============================================================================
603FUNCTION: start_pending_xfr
604=============================================================================*/
605/**
606 This function checks if their are any pending xfr interrupts and if
607 the interrupts are either RDS PS, RDS RT, RDS AF, SCANNEXT, SEARCH or SYNC
608 then initiates corresponding read operation. Preference is given to RAW RDS
609 data (SYNC) over processed data (PS, RT, AF, etc) from core.
610
611 @param radio: structure pointer passed by client.
612
613 @return None.
614*/
615static void start_pending_xfr(struct tavarua_device *radio)
616{
617 int i;
618 enum tavarua_xfr_t xfr;
619 for (i = 0; i < TAVARUA_XFR_MAX; i++) {
620 if (radio->pending_xfrs[i]) {
621 radio->xfr_in_progress = 1;
622 xfr = (enum tavarua_xfr_t)i;
623 switch (xfr) {
624 /* priority given to synchronous xfrs */
625 case TAVARUA_XFR_SYNC:
626 complete(&radio->sync_xfr_start);
627 break;
628 /* asynchrnous xfrs */
629 case TAVARUA_XFR_SRCH_LIST:
630 request_read_xfr(radio, RX_STATIONS_0);
631 break;
632 case TAVARUA_XFR_RT_RDS:
633 request_read_xfr(radio, RDS_RT_0);
634 break;
635 case TAVARUA_XFR_PS_RDS:
636 request_read_xfr(radio, RDS_PS_0);
637 break;
638 case TAVARUA_XFR_AF_LIST:
639 request_read_xfr(radio, RDS_AF_0);
640 break;
641 default:
642 FMDERR("%s: Unsupported XFR %d\n",
643 __func__, xfr);
644 }
645 radio->pending_xfrs[i] = 0;
646 FMDBG("resurrect xfr %d\n", i);
647 }
648 }
649 return;
650}
651
652/*=============================================================================
653FUNCTION: tavarua_q_event
654=============================================================================*/
655/**
656 This function is called to queue an event for user.
657
658 NOTE:
659 Applications call the VIDIOC_QBUF ioctl to enqueue an empty (capturing) or
660 filled (output) buffer in the driver's incoming queue.
661
662 Pleaes refer tavarua_probe where we register different ioctl's for FM.
663
664 @param radio: structure pointer passed by client.
665 @param event: event to be queued.
666
667 @return None.
668*/
669static void tavarua_q_event(struct tavarua_device *radio,
670 enum tavarua_evt_t event)
671{
672
673 struct kfifo *data_b = &radio->data_buf[TAVARUA_BUF_EVENTS];
674 unsigned char evt = event;
675 FMDBG("updating event_q with event %x\n", event);
676 if (kfifo_in_locked(data_b, &evt, 1, &radio->buf_lock[TAVARUA_BUF_EVENTS]))
677 wake_up_interruptible(&radio->event_queue);
678}
679
680/*=============================================================================
681FUNCTION: tavarua_start_xfr
682=============================================================================*/
683/**
684 This function is called to process interrupts which require multiple XFR
685 operations (RDS search, RDS PS, RDS RT, etc). if any XFR operation is
686 already in progress we store information about pending interrupt, which
687 will be processed in future when current pending operation is done.
688
689 @param radio: structure pointer passed by client.
690 @param pending_id: XFR operation (which requires multiple XFR operations in
691 steps) to start.
692 @param xfr_id: XFR mode to write in XFRCTRL register.
693
694 @return None.
695*/
696static void tavarua_start_xfr(struct tavarua_device *radio,
697 enum tavarua_xfr_t pending_id, enum tavarua_xfr_ctrl_t xfr_id)
698{
699 if (radio->xfr_in_progress)
700 radio->pending_xfrs[pending_id] = 1;
701 else {
702 radio->xfr_in_progress = 1;
703 request_read_xfr(radio, xfr_id);
704 }
705}
706
707/*=============================================================================
708FUNCTION: tavarua_handle_interrupts
709=============================================================================*/
710/**
711 This function processes the interrupts.
712
713 NOTE:
714 tavarua_q_event is used to queue events in App buffer. i.e. App calls the
715 VIDIOC_QBUF ioctl to enqueue an empty (capturing) buffer, which is filled
716 by tavarua_q_event call.
717
718 Any async event that requires multiple steps, i.e. search, RT, PS, etc is
719 handled one at a time. (We preserve other interrupts when processing one).
720 Sync interrupts are given priority.
721
722 @param radio: structure pointer passed by client.
723
724 @return None.
725*/
726static void tavarua_handle_interrupts(struct tavarua_device *radio)
727{
728 int i;
729 int retval;
730 unsigned char xfr_status;
731 if (!radio->handle_irq) {
732 FMDBG("IRQ happend, but I wont handle it\n");
733 return;
734 }
735 mutex_lock(&radio->lock);
736 tavarua_read_registers(radio, STATUS_REG1, STATUS_REG_NUM);
737
738 FMDBG("INTSTAT1 <%x>\n", radio->registers[STATUS_REG1]);
739 FMDBG("INTSTAT2 <%x>\n", radio->registers[STATUS_REG2]);
740 FMDBG("INTSTAT3 <%x>\n", radio->registers[STATUS_REG3]);
741
742 if (radio->registers[STATUS_REG1] & READY) {
743 complete(&radio->sync_req_done);
744 tavarua_q_event(radio, TAVARUA_EVT_RADIO_READY);
745 }
746
747 /* Tune completed */
748 if (radio->registers[STATUS_REG1] & TUNE) {
749 if (radio->tune_req) {
750 complete(&radio->sync_req_done);
751 radio->tune_req = 0;
752 }
753 tavarua_q_event(radio, TAVARUA_EVT_TUNE_SUCC);
754 if (radio->srch_params.get_list) {
755 tavarua_start_xfr(radio, TAVARUA_XFR_SRCH_LIST,
756 RX_STATIONS_0);
757 }
758 radio->srch_params.get_list = 0;
759 radio->xfr_in_progress = 0;
760 radio->xfr_bytes_left = 0;
761 for (i = 0; i < TAVARUA_BUF_MAX; i++) {
762 if (i >= TAVARUA_BUF_RT_RDS)
763 kfifo_reset(&radio->data_buf[i]);
764 }
765 for (i = 0; i < TAVARUA_XFR_MAX; i++) {
766 if (i >= TAVARUA_XFR_RT_RDS)
767 radio->pending_xfrs[i] = 0;
768 }
769 retval = tavarua_read_registers(radio, TUNECTRL, 1);
770 /* send to user station parameters */
771 if (retval > -1) {
772 /* Signal strength */
773 if (!(radio->registers[TUNECTRL] & SIGSTATE))
774 tavarua_q_event(radio, TAVARUA_EVT_BELOW_TH);
775 else
776 tavarua_q_event(radio, TAVARUA_EVT_ABOVE_TH);
777 /* mono/stereo */
778 if ((radio->registers[TUNECTRL] & MOSTSTATE))
779 tavarua_q_event(radio, TAVARUA_EVT_STEREO);
780 else
781 tavarua_q_event(radio, TAVARUA_EVT_MONO);
782 /* is RDS available */
783 if ((radio->registers[TUNECTRL] & RDSSYNC))
784 tavarua_q_event(radio, TAVARUA_EVT_RDS_AVAIL);
785 else
786 tavarua_q_event(radio,
787 TAVARUA_EVT_RDS_NOT_AVAIL);
788 }
789
790 } else {
791 if (radio->tune_req) {
792 FMDERR("Tune INT is pending\n");
793 mutex_unlock(&radio->lock);
794 return;
795 }
796 }
797 /* Search completed (read FREQ) */
798 if (radio->registers[STATUS_REG1] & SEARCH)
799 tavarua_q_event(radio, TAVARUA_EVT_SEEK_COMPLETE);
800
801 /* Scanning for next station */
802 if (radio->registers[STATUS_REG1] & SCANNEXT)
803 tavarua_q_event(radio, TAVARUA_EVT_SCAN_NEXT);
804
805 /* Signal indicator change (read SIGSTATE) */
806 if (radio->registers[STATUS_REG1] & SIGNAL) {
807 retval = tavarua_read_registers(radio, TUNECTRL, 1);
808 if (retval > -1) {
809 if (!(radio->registers[TUNECTRL] & SIGSTATE))
810 tavarua_q_event(radio, TAVARUA_EVT_BELOW_TH);
811 else
812 tavarua_q_event(radio, TAVARUA_EVT_ABOVE_TH);
813 }
814 }
815
816 /* RDS synchronization state change (read RDSSYNC) */
817 if (radio->registers[STATUS_REG1] & SYNC) {
818 retval = tavarua_read_registers(radio, TUNECTRL, 1);
819 if (retval > -1) {
820 if ((radio->registers[TUNECTRL] & RDSSYNC))
821 tavarua_q_event(radio, TAVARUA_EVT_RDS_AVAIL);
822 else
823 tavarua_q_event(radio,
824 TAVARUA_EVT_RDS_NOT_AVAIL);
825 }
826 }
827
828 /* Audio Control indicator (read AUDIOIND) */
829 if (radio->registers[STATUS_REG1] & AUDIO) {
830 retval = tavarua_read_registers(radio, AUDIOIND, 1);
831 if (retval > -1) {
832 if ((radio->registers[AUDIOIND] & 0x01))
833 tavarua_q_event(radio, TAVARUA_EVT_STEREO);
834 else
835 tavarua_q_event(radio, TAVARUA_EVT_MONO);
836 }
837 }
838
839 /* interrupt register 2 */
840
841 /* New unread RDS data group available */
842 if (radio->registers[STATUS_REG2] & RDSDAT) {
843 FMDBG("Raw RDS Available\n");
844 tavarua_rds_read(radio);
845 tavarua_q_event(radio, TAVARUA_EVT_NEW_RAW_RDS);
846 }
847
848 /* New RDS Program Service Table available */
849 if (radio->registers[STATUS_REG2] & RDSPS) {
850 FMDBG("New PS RDS\n");
851 tavarua_start_xfr(radio, TAVARUA_XFR_PS_RDS, RDS_PS_0);
852 }
853
854 /* New RDS Radio Text available */
855 if (radio->registers[STATUS_REG2] & RDSRT) {
856 FMDBG("New RT RDS\n");
857 tavarua_start_xfr(radio, TAVARUA_XFR_RT_RDS, RDS_RT_0);
858 }
859
860 /* New RDS Radio Text available */
861 if (radio->registers[STATUS_REG2] & RDSAF) {
862 FMDBG("New AF RDS\n");
863 tavarua_start_xfr(radio, TAVARUA_XFR_AF_LIST, RDS_AF_0);
864 }
865 /* Trasmitter an RDS Group */
866 if (radio->registers[STATUS_REG2] & TXRDSDAT) {
867 FMDBG("New TXRDSDAT\n");
868 tavarua_q_event(radio, TAVARUA_EVT_TXRDSDAT);
869 }
870
871 /* Complete RDS buffer is available for transmission */
872 if (radio->registers[STATUS_REG2] & TXRDSDONE) {
873 FMDBG("New TXRDSDAT\n");
874 tavarua_q_event(radio, TAVARUA_EVT_TXRDSDONE);
875 }
876 /* interrupt register 3 */
877
878 /* Data transfer (XFR) completed */
879 if (radio->registers[STATUS_REG3] & TRANSFER) {
880 FMDBG("XFR Interrupt\n");
881 tavarua_read_registers(radio, XFRCTRL, XFR_REG_NUM+1);
882 FMDBG("XFRCTRL IS: %x\n", radio->registers[XFRCTRL]);
883 xfr_status = radio->registers[XFRCTRL];
884 switch (xfr_status) {
885 case RDS_PS_0:
886 FMDBG("PS Header\n");
887 copy_from_xfr(radio, TAVARUA_BUF_PS_RDS, 5);
888 radio->xfr_bytes_left = (radio->registers[XFRCTRL+1] &
889 0x0F) * 8;
890 FMDBG("PS RDS Length: %d\n", radio->xfr_bytes_left);
891 if ((radio->xfr_bytes_left > 0) &&
892 (radio->xfr_bytes_left < 97))
893 request_read_xfr(radio, RDS_PS_1);
894 else
895 radio->xfr_in_progress = 0;
896 break;
897 case RDS_PS_1:
898 case RDS_PS_2:
899 case RDS_PS_3:
900 case RDS_PS_4:
901 case RDS_PS_5:
902 case RDS_PS_6:
903 FMDBG("PS Data\n");
904 copy_from_xfr(radio, TAVARUA_BUF_PS_RDS, XFR_REG_NUM);
905 radio->xfr_bytes_left -= XFR_REG_NUM;
906 if (radio->xfr_bytes_left > 0) {
907 if ((xfr_status + 1) > RDS_PS_6)
908 request_read_xfr(radio, RDS_PS_6);
909 else
910 request_read_xfr(radio, xfr_status+1);
911 } else {
912 radio->xfr_in_progress = 0;
913 tavarua_q_event(radio, TAVARUA_EVT_NEW_PS_RDS);
914 }
915 break;
916 case RDS_RT_0:
917 FMDBG("RT Header\n");
918 copy_from_xfr(radio, TAVARUA_BUF_RT_RDS, 5);
919 radio->xfr_bytes_left = radio->registers[XFRCTRL+1]
920 & 0x7F;
921 FMDBG("RT RDS Length: %d\n", radio->xfr_bytes_left);
922 /*RT_1 to RT_4 16 byte registers so 64 bytes */
923 if ((radio->xfr_bytes_left > 0)
924 && (radio->xfr_bytes_left < 65))
925 request_read_xfr(radio, RDS_RT_1);
926 break;
927 case RDS_RT_1:
928 case RDS_RT_2:
929 case RDS_RT_3:
930 case RDS_RT_4:
931 FMDBG("xfr interrupt RT data\n");
932 copy_from_xfr(radio, TAVARUA_BUF_RT_RDS, XFR_REG_NUM);
933 radio->xfr_bytes_left -= XFR_REG_NUM;
934 if (radio->xfr_bytes_left > 0)
935 request_read_xfr(radio, xfr_status+1);
936 else {
937 radio->xfr_in_progress = 0;
938 tavarua_q_event(radio, TAVARUA_EVT_NEW_RT_RDS);
939 }
940 break;
941 case RDS_AF_0:
942 copy_from_xfr(radio, TAVARUA_BUF_AF_LIST,
943 XFR_REG_NUM);
944 radio->xfr_bytes_left = radio->registers[XFRCTRL+5]-11;
945 if (radio->xfr_bytes_left > 0)
946 request_read_xfr(radio, RDS_AF_1);
947 else
948 radio->xfr_in_progress = 0;
949 break;
950 case RDS_AF_1:
951 copy_from_xfr(radio, TAVARUA_BUF_AF_LIST,
952 radio->xfr_bytes_left);
953 tavarua_q_event(radio, TAVARUA_EVT_NEW_AF_LIST);
954 radio->xfr_in_progress = 0;
955 break;
956 case RX_CONFIG:
957 case RADIO_CONFIG:
958 case RDS_CONFIG:
959 memcpy(radio->sync_xfr_regs,
960 &radio->registers[XFRCTRL+1], XFR_REG_NUM);
961 complete(&radio->sync_req_done);
962 break;
963 case RX_STATIONS_0:
964 FMDBG("Search list has %d stations\n",
965 radio->registers[XFRCTRL+1]);
966 radio->xfr_bytes_left = radio->registers[XFRCTRL+1]*2;
967 if (radio->xfr_bytes_left > 14) {
968 copy_from_xfr(radio, TAVARUA_BUF_SRCH_LIST,
969 XFR_REG_NUM);
970 request_read_xfr(radio, RX_STATIONS_1);
971 } else if (radio->xfr_bytes_left) {
972 FMDBG("In else RX_STATIONS_0\n");
973 copy_from_xfr(radio, TAVARUA_BUF_SRCH_LIST,
974 radio->xfr_bytes_left+1);
975 tavarua_q_event(radio,
976 TAVARUA_EVT_NEW_SRCH_LIST);
977 radio->xfr_in_progress = 0;
978 }
979 break;
980 case RX_STATIONS_1:
981 FMDBG("In RX_STATIONS_1");
982 copy_from_xfr(radio, TAVARUA_BUF_SRCH_LIST,
983 radio->xfr_bytes_left);
984 tavarua_q_event(radio, TAVARUA_EVT_NEW_SRCH_LIST);
985 radio->xfr_in_progress = 0;
986 break;
987 case PHY_TXGAIN:
988 FMDBG("read PHY_TXGAIN is successful");
989 complete(&radio->sync_req_done);
990 break;
991 case (0x80 | RX_CONFIG):
992 case (0x80 | RADIO_CONFIG):
993 case (0x80 | RDS_CONFIG):
994 case (0x80 | INT_CTRL):
995 complete(&radio->sync_req_done);
996 break;
997 case (0x80 | RDS_RT_0):
998 FMDBG("RT Header Sent\n");
999 complete(&radio->sync_req_done);
1000 break;
1001 case (0x80 | RDS_RT_1):
1002 case (0x80 | RDS_RT_2):
1003 case (0x80 | RDS_RT_3):
1004 case (0x80 | RDS_RT_4):
1005 FMDBG("xfr interrupt RT data Sent\n");
1006 complete(&radio->sync_req_done);
1007 break;
1008 /*TX Specific transfer */
1009 case (0x80 | RDS_PS_0):
1010 FMDBG("PS Header Sent\n");
1011 complete(&radio->sync_req_done);
1012 break;
1013 case (0x80 | RDS_PS_1):
1014 case (0x80 | RDS_PS_2):
1015 case (0x80 | RDS_PS_3):
1016 case (0x80 | RDS_PS_4):
1017 case (0x80 | RDS_PS_5):
1018 case (0x80 | RDS_PS_6):
1019 FMDBG("xfr interrupt PS data Sent\n");
1020 complete(&radio->sync_req_done);
1021 break;
1022 case (0x80 | PHY_TXGAIN):
1023 FMDBG("write PHY_TXGAIN is successful");
1024 complete(&radio->sync_req_done);
1025 break;
1026 default:
1027 FMDERR("UNKNOWN XFR = %d\n", xfr_status);
1028 }
1029 if (!radio->xfr_in_progress)
1030 start_pending_xfr(radio);
1031
1032 }
1033
1034 /* Error occurred. Read ERRCODE to determine cause */
1035 if (radio->registers[STATUS_REG3] & ERROR) {
1036#ifdef FM_DEBUG
1037 unsigned char xfr_buf[XFR_REG_NUM];
1038 int retval = sync_read_xfr(radio, ERROR_CODE, xfr_buf);
1039 FMDBG("retval of ERROR_CODE read : %d\n", retval);
1040#endif
1041 FMDERR("ERROR STATE\n");
1042 }
1043
1044 mutex_unlock(&radio->lock);
1045 FMDBG("Work is done\n");
1046
1047}
1048
1049/*=============================================================================
1050FUNCTION: read_int_stat
1051=============================================================================*/
1052/**
1053 This function is scheduled whenever there is an interrupt pending in interrupt
1054 queue. i.e. kfmradio.
1055
1056 Whenever there is a GPIO interrupt, a delayed work will be queued in to the
1057 'kfmradio' work queue. Upon execution of this work in the queue, a a call
1058 to read_int_stat function will be made , which would in turn handle the
1059 interrupts by reading the INTSTATx registers.
1060 NOTE:
1061 Tasks to be run out of a workqueue need to be packaged in a struct
1062 work_struct structure.
1063
1064 @param work: work_struct structure.
1065
1066 @return None.
1067*/
1068static void read_int_stat(struct work_struct *work)
1069{
1070 struct tavarua_device *radio = container_of(work,
1071 struct tavarua_device, work.work);
1072 tavarua_handle_interrupts(radio);
1073}
1074
1075/*************************************************************************
1076 * irq helper functions
1077 ************************************************************************/
1078
1079/*=============================================================================
1080FUNCTION: tavarua_request_irq
1081=============================================================================*/
1082/**
1083 This function is called to acquire a FM GPIO and enable FM interrupts.
1084
1085 @param radio: structure pointer passed by client.
1086
1087 @return 0 if success else otherwise.
1088*/
1089static int tavarua_request_irq(struct tavarua_device *radio)
1090{
1091 int retval;
1092 int irq = radio->pdata->irq;
1093 if (radio == NULL)
1094 return -EINVAL;
1095
1096 /* A workqueue created with create_workqueue() will have one worker thread
1097 * for each CPU on the system; create_singlethread_workqueue(), instead,
1098 * creates a workqueue with a single worker process. The name of the queue
1099 * is limited to ten characters; it is only used for generating the "command"
1100 * for the kernel thread(s) (which can be seen in ps or top).
1101 */
1102 radio->wqueue = create_singlethread_workqueue("kfmradio");
1103 if (!radio->wqueue)
1104 return -ENOMEM;
1105 /* allocate an interrupt line */
1106 /* On success, request_irq() returns 0 if everything goes as
1107 planned. Your interrupt handler will start receiving its
1108 interrupts immediately. On failure, request_irq()
1109 returns:
1110 -EINVAL
1111 The IRQ number you requested was either
1112 invalid or reserved, or your passed a NULL
1113 pointer for the handler() parameter.
1114
1115 -EBUSY The IRQ you requested is already being
1116 handled, and the IRQ cannot be shared.
1117
1118 -ENXIO The m68k returns this value for an invalid
1119 IRQ number.
1120 */
1121 /* Use request_any_context_irq, So that it might work for nested or
1122 nested interrupts. in MSM8x60, FM is connected to PMIC GPIO and it
1123 is a nested interrupt*/
1124 retval = request_any_context_irq(irq, tavarua_isr,
1125 IRQ_TYPE_EDGE_FALLING, "fm interrupt", radio);
1126 if (retval < 0) {
1127 FMDERR("Couldn't acquire FM gpio %d\n", irq);
1128 return retval;
1129 } else {
1130 FMDBG("FM GPIO %d registered\n", irq);
1131 }
1132 retval = enable_irq_wake(irq);
1133 if (retval < 0) {
1134 FMDERR("Could not enable FM interrupt\n ");
1135 free_irq(irq , radio);
1136 }
1137 return retval;
1138}
1139
1140/*=============================================================================
1141FUNCTION: tavarua_disable_irq
1142=============================================================================*/
1143/**
1144 This function is called to disable FM irq and free up FM interrupt handling
1145 resources.
1146
1147 @param radio: structure pointer passed by client.
1148
1149 @return 0 if success else otherwise.
1150*/
1151static int tavarua_disable_irq(struct tavarua_device *radio)
1152{
1153 int irq;
1154 if (!radio)
1155 return -EINVAL;
1156 irq = radio->pdata->irq;
1157 disable_irq_wake(irq);
1158 cancel_delayed_work_sync(&radio->work);
1159 flush_workqueue(radio->wqueue);
1160 free_irq(irq, radio);
1161 destroy_workqueue(radio->wqueue);
1162 return 0;
1163}
1164
1165/*************************************************************************
1166 * fops/IOCTL helper functions
1167 ************************************************************************/
1168
1169/*=============================================================================
1170FUNCTION: tavarua_search
1171=============================================================================*/
1172/**
1173 This interface sets the search control features.
1174
1175 @param radio: structure pointer passed by client.
1176 @param on: The value of a control.
1177 @param dir: FM search direction.
1178
1179 @return => 0 if successful.
1180 @return < 0 if failure.
1181*/
1182static int tavarua_search(struct tavarua_device *radio, int on, int dir)
1183{
1184 enum search_t srch = radio->registers[SRCHCTRL] & SRCH_MODE;
1185
1186 FMDBG("In tavarua_search\n");
1187 if (on) {
1188 radio->registers[SRCHRDS1] = 0x00;
1189 radio->registers[SRCHRDS2] = 0x00;
1190 /* Set freq band */
1191 switch (srch) {
1192 case SCAN_FOR_STRONG:
1193 case SCAN_FOR_WEAK:
1194 radio->srch_params.get_list = 1;
1195 radio->registers[SRCHRDS2] =
1196 radio->srch_params.preset_num;
1197 break;
1198 case RDS_SEEK_PTY:
1199 case RDS_SCAN_PTY:
1200 radio->registers[SRCHRDS2] =
1201 radio->srch_params.srch_pty;
1202 break;
1203 case RDS_SEEK_PI:
1204 radio->registers[SRCHRDS1] =
1205 (radio->srch_params.srch_pi & 0xFF00) >> 8;
1206 radio->registers[SRCHRDS2] =
1207 (radio->srch_params.srch_pi & 0x00FF);
1208 break;
1209 default:
1210 break;
1211 }
1212 radio->registers[SRCHCTRL] |= SRCH_ON;
1213 } else {
1214 radio->registers[SRCHCTRL] &= ~SRCH_ON;
1215 radio->srch_params.get_list = 0;
1216 }
1217 radio->registers[SRCHCTRL] = (dir << 3) |
1218 (radio->registers[SRCHCTRL] & 0xF7);
1219
1220 FMDBG("SRCHCTRL <%x>\n", radio->registers[SRCHCTRL]);
1221 FMDBG("Search Started\n");
1222 return tavarua_write_registers(radio, SRCHRDS1,
1223 &radio->registers[SRCHRDS1], 3);
1224}
1225
1226/*=============================================================================
1227FUNCTION: tavarua_set_region
1228=============================================================================*/
1229/**
1230 This interface configures the FM radio.
1231
1232 @param radio: structure pointer passed by client.
1233 @param req_region: FM band types. These types defines the FM band minimum and
1234 maximum frequencies in the FM band.
1235
1236 @return => 0 if successful.
1237 @return < 0 if failure.
1238*/
1239static int tavarua_set_region(struct tavarua_device *radio,
1240 int req_region)
1241{
1242 int retval = 0;
1243 unsigned char xfr_buf[XFR_REG_NUM];
1244 unsigned char value;
1245 unsigned int spacing = 0.100 * FREQ_MUL;
1246 unsigned int band_low, band_high;
1247 unsigned int low_band_limit = 76.0 * FREQ_MUL;
1248 enum tavarua_region_t region = req_region;
1249
1250 /* Set freq band */
1251 switch (region) {
1252 case TAVARUA_REGION_US:
1253 case TAVARUA_REGION_EU:
1254 case TAVARUA_REGION_JAPAN_WIDE:
1255 SET_REG_FIELD(radio->registers[RDCTRL], 0,
1256 RDCTRL_BAND_OFFSET, RDCTRL_BAND_MASK);
1257 break;
1258 case TAVARUA_REGION_JAPAN:
1259 SET_REG_FIELD(radio->registers[RDCTRL], 1,
1260 RDCTRL_BAND_OFFSET, RDCTRL_BAND_MASK);
1261 break;
1262 default:
1263 retval = sync_read_xfr(radio, RADIO_CONFIG, xfr_buf);
1264 if (retval < 0) {
1265 FMDERR("failed to get RADIO_CONFIG\n");
1266 return retval;
1267 }
1268 band_low = (radio->region_params.band_low -
1269 low_band_limit) / spacing;
1270 band_high = (radio->region_params.band_high -
1271 low_band_limit) / spacing;
1272 FMDBG("low_band: %x, high_band: %x\n", band_low, band_high);
1273 xfr_buf[0] = band_low >> 8;
1274 xfr_buf[1] = band_low & 0xFF;
1275 xfr_buf[2] = band_high >> 8;
1276 xfr_buf[3] = band_high & 0xFF;
1277 retval = sync_write_xfr(radio, RADIO_CONFIG, xfr_buf);
1278 if (retval < 0) {
1279 FMDERR("Could not set regional settings\n");
1280 return retval;
1281 }
1282 break;
1283 }
1284
1285 /* Set channel spacing */
1286 switch (region) {
1287 case TAVARUA_REGION_US:
1288 case TAVARUA_REGION_EU:
1289 value = 0;
1290 break;
1291 case TAVARUA_REGION_JAPAN:
1292 value = 1;
1293 break;
1294 case TAVARUA_REGION_JAPAN_WIDE:
1295 value = 2;
1296 break;
1297 default:
1298 value = radio->region_params.spacing;
1299 }
1300
1301 SET_REG_FIELD(radio->registers[RDCTRL], value,
1302 RDCTRL_CHSPACE_OFFSET, RDCTRL_CHSPACE_MASK);
1303
1304 /* Set De-emphasis and soft band range*/
1305 switch (region) {
1306 case TAVARUA_REGION_US:
1307 case TAVARUA_REGION_JAPAN:
1308 case TAVARUA_REGION_JAPAN_WIDE:
1309 value = 0;
1310 break;
1311 case TAVARUA_REGION_EU:
1312 value = 1;
1313 break;
1314 default:
1315 value = radio->region_params.emphasis;
1316 }
1317
1318 SET_REG_FIELD(radio->registers[RDCTRL], value,
1319 RDCTRL_DEEMPHASIS_OFFSET, RDCTRL_DEEMPHASIS_MASK);
1320
1321 /* set RDS standard */
1322 switch (region) {
1323 default:
1324 value = radio->region_params.rds_std;
1325 break;
1326 case TAVARUA_REGION_US:
1327 value = 0;
1328 break;
1329 case TAVARUA_REGION_EU:
1330 value = 1;
1331 break;
1332 }
1333 SET_REG_FIELD(radio->registers[RDSCTRL], value,
1334 RDSCTRL_STANDARD_OFFSET, RDSCTRL_STANDARD_MASK);
1335
1336 FMDBG("RDSCTRLL %x\n", radio->registers[RDSCTRL]);
1337 retval = tavarua_write_register(radio, RDSCTRL,
1338 radio->registers[RDSCTRL]);
1339 if (retval < 0)
1340 return retval;
1341
1342 FMDBG("RDCTRL: %x\n", radio->registers[RDCTRL]);
1343 retval = tavarua_write_register(radio, RDCTRL,
1344 radio->registers[RDCTRL]);
1345 if (retval < 0) {
1346 FMDERR("Could not set region in rdctrl\n");
1347 return retval;
1348 }
1349
1350 /* setting soft band */
1351 switch (region) {
1352 case TAVARUA_REGION_US:
1353 case TAVARUA_REGION_EU:
1354 radio->region_params.band_low = 87.5 * FREQ_MUL;
1355 radio->region_params.band_high = 108 * FREQ_MUL;
1356 break;
1357 case TAVARUA_REGION_JAPAN:
1358 radio->region_params.band_low = 76 * FREQ_MUL;
1359 radio->region_params.band_high = 90 * FREQ_MUL;
1360 break;
1361 case TAVARUA_REGION_JAPAN_WIDE:
1362 radio->region_params.band_low = 90 * FREQ_MUL;
1363 radio->region_params.band_high = 108 * FREQ_MUL;
1364 break;
1365 default:
1366 break;
1367 }
1368 radio->region_params.region = region;
1369 return retval;
1370}
1371
1372/*=============================================================================
1373FUNCTION: tavarua_get_freq
1374=============================================================================*/
1375/**
1376 This interface gets the current frequency.
1377
1378 @param radio: structure pointer passed by client.
1379 @param freq: struct v4l2_frequency. This will be set to the resultant
1380 frequency in units of 62.5 kHz on success.
1381
1382 NOTE:
1383 To get the current tuner or modulator radio frequency applications set the
1384 tuner field of a struct v4l2_frequency to the respective tuner or modulator
1385 number (only input devices have tuners, only output devices have modulators),
1386 zero out the reserved array and call the VIDIOC_G_FREQUENCY ioctl with a
1387 pointer to this structure. The driver stores the current frequency in the
1388 frequency field.
1389
1390 Tuning frequency is in units of 62.5 kHz, or if the struct v4l2_tuner or
1391 struct v4l2_modulator capabilities flag V4L2_TUNER_CAP_LOW is set, in
1392 units of 62.5 Hz.
1393
1394 @return => 0 if successful.
1395 @return < 0 if failure.
1396*/
1397static int tavarua_get_freq(struct tavarua_device *radio,
1398 struct v4l2_frequency *freq)
1399{
1400 int retval;
1401 unsigned short chan;
1402 unsigned int band_bottom;
1403 unsigned int spacing;
1404 band_bottom = radio->region_params.band_low;
1405 spacing = 0.100 * FREQ_MUL;
1406 /* read channel */
1407 retval = tavarua_read_registers(radio, FREQ, 2);
1408 chan = radio->registers[FREQ];
1409
1410 /* Frequency (MHz) = 100 (kHz) x Channel + Bottom of Band (MHz) */
1411 freq->frequency = spacing * chan + band_bottom;
1412 if (radio->registers[TUNECTRL] & ADD_OFFSET)
1413 freq->frequency += 800;
1414 return retval;
1415}
1416
1417/*=============================================================================
1418FUNCTION: tavarua_set_freq
1419=============================================================================*/
1420/**
1421 This interface sets the current frequency.
1422
1423 @param radio: structure pointer passed by client.
1424 @param freq: desired frequency sent by the client in 62.5 kHz units.
1425
1426 NOTE:
1427 To change the current tuner or modulator radio frequency, applications
1428 initialize the tuner, type and frequency fields, and the reserved array of a
1429 struct v4l2_frequency and call the VIDIOC_S_FREQUENCY ioctl with a pointer to
1430 this structure. When the requested frequency is not possible the driver
1431 assumes the closest possible value. However VIDIOC_S_FREQUENCY is a
1432 write-only ioctl, it does not return the actual new frequency.
1433
1434 Tuning frequency is in units of 62.5 kHz, or if the struct v4l2_tuner
1435 or struct v4l2_modulator capabilities flag V4L2_TUNER_CAP_LOW is set,
1436 in units of 62.5 Hz.
1437
1438 @return => 0 if successful.
1439 @return < 0 if failure.
1440*/
1441static int tavarua_set_freq(struct tavarua_device *radio, unsigned int freq)
1442{
1443
1444 unsigned int band_bottom;
1445 unsigned char chan;
1446 unsigned char cmd[] = {0x00, 0x00};
1447 unsigned int spacing;
1448 int retval;
1449 band_bottom = radio->region_params.band_low;
1450 spacing = 0.100 * FREQ_MUL;
1451 if ((freq % 1600) == 800) {
1452 cmd[1] = ADD_OFFSET;
1453 freq -= 800;
1454 }
1455 /* Chan = [ Freq (Mhz) - Bottom of Band (MHz) ] / 100 (kHz) */
1456 chan = (freq - band_bottom) / spacing;
1457
1458 cmd[0] = chan;
1459 cmd[1] |= TUNE_STATION;
1460 radio->tune_req = 1;
1461 retval = tavarua_write_registers(radio, FREQ, cmd, 2);
1462 if (retval < 0)
1463 radio->tune_req = 0;
1464 return retval;
1465
1466}
1467
1468/**************************************************************************
1469 * File Operations Interface
1470 *************************************************************************/
1471
1472/*=============================================================================
1473FUNCTION: tavarua_fops_read
1474=============================================================================*/
1475/**
1476 This function is called when a process, which already opened the dev file,
1477 attempts to read from it.
1478
1479 In case of tavarua driver, it is called to read RDS data.
1480
1481 @param file: file descriptor.
1482 @param buf: The buffer to fill with data.
1483 @param count: The length of the buffer in bytes.
1484 @param ppos: Our offset in the file.
1485
1486 @return The number of bytes put into the buffer on sucess.
1487 -EFAULT if there is no access to user buffer
1488*/
1489static ssize_t tavarua_fops_read(struct file *file, char __user *buf,
1490 size_t count, loff_t *ppos)
1491{
1492 struct tavarua_device *radio = video_get_drvdata(video_devdata(file));
1493 struct kfifo *rds_buf = &radio->data_buf[TAVARUA_BUF_RAW_RDS];
1494
1495 /* block if no new data available */
1496 while (!kfifo_len(rds_buf)) {
1497 if (file->f_flags & O_NONBLOCK)
1498 return -EWOULDBLOCK;
1499 if (wait_event_interruptible(radio->read_queue,
1500 kfifo_len(rds_buf)) < 0)
1501 return -EINTR;
1502 }
1503
1504 /* calculate block count from byte count */
1505 count /= BYTES_PER_BLOCK;
1506
1507
1508 /* check if we can write to the user buffer */
1509 if (!access_ok(VERIFY_WRITE, buf, count*BYTES_PER_BLOCK))
1510 return -EFAULT;
1511
1512 /* copy RDS block out of internal buffer and to user buffer */
1513 return kfifo_out_locked(rds_buf, buf, count*BYTES_PER_BLOCK,
1514 &radio->buf_lock[TAVARUA_BUF_RAW_RDS]);
1515}
1516
1517/*=============================================================================
1518FUNCTION: tavarua_fops_write
1519=============================================================================*/
1520/**
1521 This function is called when a process, which already opened the dev file,
1522 attempts to write to it.
1523
1524 In case of tavarua driver, it is called to write RDS data to host.
1525
1526 @param file: file descriptor.
1527 @param buf: The buffer which has data to write.
1528 @param count: The length of the buffer.
1529 @param ppos: Our offset in the file.
1530
1531 @return The number of bytes written from the buffer.
1532*/
1533static ssize_t tavarua_fops_write(struct file *file, const char __user *data,
1534 size_t count, loff_t *ppos)
1535{
1536 struct tavarua_device *radio = video_get_drvdata(video_devdata(file));
1537 int retval = 0;
1538 int bytes_to_copy;
1539 int bytes_copied = 0;
1540 int bytes_left;
1541 int chunk_index = 0;
1542 unsigned char tx_data[XFR_REG_NUM];
1543 /* Disable TX of this type first */
1544 switch (radio->tx_mode) {
1545 case TAVARUA_TX_RT:
1546 bytes_left = min((int)count, MAX_RT_LENGTH);
1547 tx_data[1] = 0;
1548 break;
1549 case TAVARUA_TX_PS:
1550 bytes_left = min((int)count, MAX_PS_LENGTH);
1551 tx_data[4] = 0;
1552 break;
1553 default:
1554 FMDERR("%s: Unknown TX mode\n", __func__);
1555 return -1;
1556 }
1557 retval = sync_write_xfr(radio, radio->tx_mode, tx_data);
1558 if (retval < 0)
1559 return retval;
1560
1561 /* send payload to FM hardware */
1562 while (bytes_left) {
1563 chunk_index++;
1564 bytes_to_copy = min(bytes_left, XFR_REG_NUM);
1565 if (copy_from_user(tx_data, data + bytes_copied, bytes_to_copy))
1566 return -EFAULT;
1567 retval = sync_write_xfr(radio, radio->tx_mode +
1568 chunk_index, tx_data);
1569 if (retval < 0)
1570 return retval;
1571
1572 bytes_copied += bytes_to_copy;
1573 bytes_left -= bytes_to_copy;
1574 }
1575
1576 /* send the header */
1577 switch (radio->tx_mode) {
1578 case TAVARUA_TX_RT:
1579 FMDBG("Writing RT header\n");
1580 tx_data[0] = bytes_copied;
1581 tx_data[1] = TX_ON | 0x03; /* on | PTY */
1582 tx_data[2] = 0x12; /* PI high */
1583 tx_data[3] = 0x34; /* PI low */
1584 break;
1585 case TAVARUA_TX_PS:
1586 FMDBG("Writing PS header\n");
1587 tx_data[0] = chunk_index;
1588 tx_data[1] = 0x03; /* PTY */
1589 tx_data[2] = 0x12; /* PI high */
1590 tx_data[3] = 0x34; /* PI low */
1591 tx_data[4] = TX_ON | 0x01;
1592 break;
1593 default:
1594 FMDERR("%s: Unknown TX mode\n", __func__);
1595 return -1;
1596 }
1597 retval = sync_write_xfr(radio, radio->tx_mode, tx_data);
1598 if (retval < 0)
1599 return retval;
1600 FMDBG("done writing: %d\n", retval);
1601 return bytes_copied;
1602}
1603
1604/*=============================================================================
1605FUNCTION: tavarua_fops_open
1606=============================================================================*/
1607/**
1608 This function is called when a process tries to open the device file, like
1609 "cat /dev/mycharfile"
1610
1611 @param file: file descriptor.
1612
1613 @return => 0 if successful.
1614 @return < 0 if failure.
1615*/
1616static int tavarua_fops_open(struct file *file)
1617{
1618 struct tavarua_device *radio = video_get_drvdata(video_devdata(file));
1619 int retval = -ENODEV;
1620 unsigned char value;
1621 /* FM core bring up */
1622 int i = 0;
1623 char fm_ctl0_part1[] = { 0xCA, 0xCE, 0xD6 };
1624 char fm_ctl1[] = { 0x03 };
1625 char fm_ctl0_part2[] = { 0xB6, 0xB7 };
1626 char buffer[] = {0x00, 0x48, 0x8A, 0x8E, 0x97, 0xB7};
1627 int bahama_present = -ENODEV;
1628
1629 mutex_lock(&radio->lock);
1630 if (radio->users) {
1631 mutex_unlock(&radio->lock);
1632 return -EBUSY;
1633 } else {
1634 radio->users++;
1635 }
1636 mutex_unlock(&radio->lock);
1637
1638 /* initial gpio pin config & Power up */
1639 retval = radio->pdata->fm_setup(radio->pdata);
1640 if (retval) {
1641 printk(KERN_ERR "%s: failed config gpio & pmic\n", __func__);
1642 goto open_err_setup;
1643 }
1644 if (radio->pdata->config_i2s_gpio != NULL) {
1645 retval = radio->pdata->config_i2s_gpio(FM_I2S_ON);
1646 if (retval) {
1647 printk(KERN_ERR "%s: failed config gpio\n", __func__);
1648 goto config_i2s_err;
1649 }
1650 }
1651 /* enable irq */
1652 retval = tavarua_request_irq(radio);
1653 if (retval < 0) {
1654 printk(KERN_ERR "%s: failed to request irq\n", __func__);
1655 goto open_err_req_irq;
1656 }
1657 /* call top level marimba interface here to enable FM core */
1658 FMDBG("initializing SoC\n");
1659
1660 bahama_present = is_bahama();
1661
1662 if (bahama_present == -ENODEV)
1663 return -ENODEV;
1664
1665 if (bahama_present)
1666 radio->marimba->mod_id = SLAVE_ID_BAHAMA;
1667 else
1668 radio->marimba->mod_id = MARIMBA_SLAVE_ID_MARIMBA;
1669
1670 value = FM_ENABLE;
1671 retval = marimba_write_bit_mask(radio->marimba,
1672 MARIMBA_XO_BUFF_CNTRL, &value, 1, value);
1673 if (retval < 0) {
1674 printk(KERN_ERR "%s:XO_BUFF_CNTRL write failed\n",
1675 __func__);
1676 goto open_err_all;
1677 }
1678
1679
1680 /* Bring up FM core */
1681 if (bahama_present) {
1682
1683 radio->marimba->mod_id = SLAVE_ID_BAHAMA;
1684 /* Read the Bahama version*/
1685 retval = marimba_read_bit_mask(radio->marimba,
1686 0x00, &bahama_version, 1, 0x1F);
1687 if (retval < 0) {
1688 printk(KERN_ERR "%s: version read failed",
1689 __func__);
1690 goto open_err_all;
1691 }
Rahul Kashyapc88b6e32011-07-07 10:52:16 +05301692
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001693 /* Check for Bahama V2 variant*/
1694 if (bahama_version == 0x09) {
1695
1696 /* In case of Bahama v2, forcefully enable the
1697 * internal analog and digital voltage controllers
1698 */
1699 value = 0x06;
1700 /* value itself used as mask in these writes*/
1701 retval = marimba_write_bit_mask(radio->marimba,
1702 BAHAMA_LDO_DREG_CTL0, &value, 1, value);
1703 if (retval < 0) {
1704 printk(KERN_ERR "%s:0xF0 write failed\n",
1705 __func__);
1706 goto open_err_all;
1707 }
1708 value = 0x86;
1709 retval = marimba_write_bit_mask(radio->marimba,
1710 BAHAMA_LDO_AREG_CTL0, &value, 1, value);
1711 if (retval < 0) {
1712 printk(KERN_ERR "%s:0xF4 write failed\n",
1713 __func__);
1714 goto open_err_all;
1715 }
1716 }
1717
1718 /*write FM mode*/
1719 retval = tavarua_write_register(radio, BAHAMA_FM_MODE_REG,
1720 BAHAMA_FM_MODE_NORMAL);
1721 if (retval < 0) {
1722 printk(KERN_ERR "failed to set the FM mode: %d\n",
1723 retval);
1724 goto open_err_all;
1725 }
1726 /*Write first sequence of bytes to FM_CTL0*/
1727 for (i = 0; i < 3; i++) {
1728 retval = tavarua_write_register(radio,
1729 BAHAMA_FM_CTL0_REG, fm_ctl0_part1[i]);
1730 if (retval < 0) {
1731 printk(KERN_ERR "FM_CTL0:set-1 failure: %d\n",
1732 retval);
1733 goto open_err_all;
1734 }
1735 }
1736 /*Write the FM_CTL1 sequence*/
1737 for (i = 0; i < 1; i++) {
1738 retval = tavarua_write_register(radio,
1739 BAHAMA_FM_CTL1_REG, fm_ctl1[i]);
1740 if (retval < 0) {
1741 printk(KERN_ERR "FM_CTL1 write failure: %d\n",
1742 retval);
1743 goto open_err_all;
1744 }
1745 }
1746 /*Write second sequence of bytes to FM_CTL0*/
1747 for (i = 0; i < 2; i++) {
1748 retval = tavarua_write_register(radio,
1749 BAHAMA_FM_CTL0_REG, fm_ctl0_part2[i]);
1750 if (retval < 0) {
1751 printk(KERN_ERR "FM_CTL0:set-2 failure: %d\n",
1752 retval);
1753 goto open_err_all;
1754 }
1755 }
1756 } else {
1757 retval = tavarua_write_registers(radio, LEAKAGE_CNTRL,
1758 buffer, 6);
1759 if (retval < 0) {
1760 printk(KERN_ERR "%s: failed to bring up FM Core\n",
1761 __func__);
1762 goto open_err_all;
1763 }
1764 }
1765 /* Wait for interrupt i.e. complete(&radio->sync_req_done); call */
1766 /*Initialize the completion variable for
1767 for the proper behavior*/
1768 init_completion(&radio->sync_req_done);
1769 if (!wait_for_completion_timeout(&radio->sync_req_done,
1770 msecs_to_jiffies(wait_timeout))) {
1771 retval = -1;
1772 FMDERR("Timeout waiting for initialization\n");
1773 }
1774
1775 /* get Chip ID */
1776 retval = tavarua_write_register(radio, XFRCTRL, CHIPID);
1777 if (retval < 0)
1778 goto open_err_all;
1779 msleep(TAVARUA_DELAY);
1780 tavarua_read_registers(radio, XFRCTRL, XFR_REG_NUM+1);
1781 if (radio->registers[XFRCTRL] != CHIPID)
1782 goto open_err_all;
1783
1784 radio->chipID = (radio->registers[XFRCTRL+2] << 24) |
1785 (radio->registers[XFRCTRL+5] << 16) |
1786 (radio->registers[XFRCTRL+6] << 8) |
1787 (radio->registers[XFRCTRL+7]);
1788
1789 printk(KERN_WARNING DRIVER_NAME ": Chip ID %x\n", radio->chipID);
1790 if (radio->chipID == MARIMBA_A0) {
1791 printk(KERN_WARNING DRIVER_NAME ": Unsupported hardware: %x\n",
1792 radio->chipID);
1793 retval = -1;
1794 goto open_err_all;
1795 }
1796
1797 radio->handle_irq = 0;
1798 radio->marimba->mod_id = SLAVE_ID_BAHAMA;
1799 marimba_set_fm_status(radio->marimba, true);
1800 return 0;
1801
1802
1803open_err_all:
1804 /*Disable FM in case of error*/
1805 value = 0x00;
1806 marimba_write_bit_mask(radio->marimba, MARIMBA_XO_BUFF_CNTRL,
1807 &value, 1, value);
1808 tavarua_disable_irq(radio);
1809open_err_req_irq:
1810 if (radio->pdata->config_i2s_gpio != NULL)
1811 radio->pdata->config_i2s_gpio(FM_I2S_OFF);
1812config_i2s_err:
1813 radio->pdata->fm_shutdown(radio->pdata);
1814open_err_setup:
1815 radio->handle_irq = 1;
1816 radio->users = 0;
1817 return retval;
1818}
1819
1820/*=============================================================================
1821FUNCTION: tavarua_fops_release
1822=============================================================================*/
1823/**
1824 This function is called when a process closes the device file.
1825
1826 @param file: file descriptor.
1827
1828 @return => 0 if successful.
1829 @return < 0 if failure.
1830*/
1831static int tavarua_fops_release(struct file *file)
1832{
1833 int retval;
1834 struct tavarua_device *radio = video_get_drvdata(video_devdata(file));
1835 unsigned char value;
1836 int i = 0;
1837 /*FM Core shutdown sequence for Bahama*/
1838 char fm_ctl0_part1[] = { 0xB7 };
1839 char fm_ctl1[] = { 0x03 };
1840 char fm_ctl0_part2[] = { 0x9F, 0x48, 0x02 };
1841 int bahama_present = -ENODEV;
1842 /*FM Core shutdown sequence for Marimba*/
1843 char buffer[] = {0x18, 0xB7, 0x48};
1844 bool bt_status = false;
1845 int index;
1846 /* internal regulator controllers DREG_CTL0, AREG_CTL0
1847 * has to be kept in the valid state based on the bt status.
1848 * 1st row is the state when no clients are active,
1849 * and the second when bt is in on state.
1850 */
1851 char internal_vreg_ctl[2][2] = {
1852 { 0x04, 0x84 },
1853 { 0x00, 0x80 }
1854 };
1855
1856 if (!radio)
1857 return -ENODEV;
1858 FMDBG("In %s", __func__);
1859
1860 /* disable radio ctrl */
1861 retval = tavarua_write_register(radio, RDCTRL, 0x00);
1862
1863 FMDBG("%s, Disable IRQs\n", __func__);
1864 /* disable irq */
1865 retval = tavarua_disable_irq(radio);
1866 if (retval < 0) {
1867 printk(KERN_ERR "%s: failed to disable irq\n", __func__);
1868 return retval;
1869 }
1870
1871 bahama_present = is_bahama();
1872
1873 if (bahama_present == -ENODEV)
1874 return -ENODEV;
1875
1876 if (bahama_present) {
1877 /*Write first sequence of bytes to FM_CTL0*/
1878 for (i = 0; i < 1; i++) {
1879 retval = tavarua_write_register(radio,
1880 BAHAMA_FM_CTL0_REG, fm_ctl0_part1[i]);
1881 if (retval < 0) {
1882 printk(KERN_ERR "FM_CTL0:Set-1 failure: %d\n",
1883 retval);
1884 break;
1885 }
1886 }
1887 /*Write the FM_CTL1 sequence*/
1888 for (i = 0; i < 1; i++) {
1889 retval = tavarua_write_register(radio,
1890 BAHAMA_FM_CTL1_REG, fm_ctl1[i]);
1891 if (retval < 0) {
1892 printk(KERN_ERR "FM_CTL1 failure: %d\n",
1893 retval);
1894 break;
1895 }
1896 }
1897 /*Write second sequence of bytes to FM_CTL0*/
1898 for (i = 0; i < 3; i++) {
1899 retval = tavarua_write_register(radio,
1900 BAHAMA_FM_CTL0_REG, fm_ctl0_part2[i]);
1901 if (retval < 0) {
1902 printk(KERN_ERR "FM_CTL0:Set-2 failure: %d\n",
1903 retval);
1904 break;
1905 }
1906 }
1907 } else {
1908
1909 retval = tavarua_write_registers(radio, FM_CTL0,
1910 buffer, sizeof(buffer)/sizeof(buffer[0]));
1911 if (retval < 0) {
1912 printk(KERN_ERR "%s: failed to bring down the FM Core\n",
1913 __func__);
1914 return retval;
1915 }
1916 }
1917 radio->marimba->mod_id = SLAVE_ID_BAHAMA;
1918 bt_status = marimba_get_bt_status(radio->marimba);
1919 /* Set the index based on the bt status*/
1920 index = bt_status ? 1 : 0;
1921 /* Check for Bahama's existance and Bahama V2 variant*/
1922 if (bahama_present && (bahama_version == 0x09)) {
1923 radio->marimba->mod_id = SLAVE_ID_BAHAMA;
1924 /* actual value itself used as mask*/
1925 retval = marimba_write_bit_mask(radio->marimba,
1926 BAHAMA_LDO_DREG_CTL0, &internal_vreg_ctl[bt_status][0],
1927 1, internal_vreg_ctl[index][0]);
1928 if (retval < 0) {
1929 printk(KERN_ERR "%s:0xF0 write failed\n", __func__);
1930 return retval;
1931 }
1932 /* actual value itself used as mask*/
1933 retval = marimba_write_bit_mask(radio->marimba,
1934 BAHAMA_LDO_AREG_CTL0, &internal_vreg_ctl[bt_status][1],
1935 1, internal_vreg_ctl[index][1]);
1936 if (retval < 0) {
1937 printk(KERN_ERR "%s:0xF4 write failed\n", __func__);
1938 return retval;
1939 }
1940 } else {
1941 /* disable fm core */
1942 radio->marimba->mod_id = MARIMBA_SLAVE_ID_MARIMBA;
1943 }
1944
1945 value = 0x00;
1946 retval = marimba_write_bit_mask(radio->marimba, MARIMBA_XO_BUFF_CNTRL,
1947 &value, 1, FM_ENABLE);
1948 if (retval < 0) {
1949 printk(KERN_ERR "%s:XO_BUFF_CNTRL write failed\n", __func__);
1950 return retval;
1951 }
1952 FMDBG("%s, Calling fm_shutdown\n", __func__);
1953 /* teardown gpio and pmic */
Rahul Kashyapc88b6e32011-07-07 10:52:16 +05301954
1955 marimba_set_fm_status(radio->marimba, false);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001956 radio->pdata->fm_shutdown(radio->pdata);
1957 if (radio->pdata->config_i2s_gpio != NULL)
1958 radio->pdata->config_i2s_gpio(FM_I2S_OFF);
1959 radio->handle_irq = 1;
1960 radio->users = 0;
1961 radio->marimba->mod_id = SLAVE_ID_BAHAMA;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001962 return 0;
1963}
1964
1965/*
1966 * tavarua_fops - file operations interface
1967 */
1968static const struct v4l2_file_operations tavarua_fops = {
1969 .owner = THIS_MODULE,
1970 .read = tavarua_fops_read,
1971 .write = tavarua_fops_write,
1972 .ioctl = video_ioctl2,
1973 .open = tavarua_fops_open,
1974 .release = tavarua_fops_release,
1975};
1976
1977/*************************************************************************
1978 * Video4Linux Interface
1979 *************************************************************************/
1980
1981/*
1982 * tavarua_v4l2_queryctrl - query control
1983 */
1984static struct v4l2_queryctrl tavarua_v4l2_queryctrl[] = {
1985 {
1986 .id = V4L2_CID_AUDIO_VOLUME,
1987 .type = V4L2_CTRL_TYPE_INTEGER,
1988 .name = "Volume",
1989 .minimum = 0,
1990 .maximum = 15,
1991 .step = 1,
1992 .default_value = 15,
1993 },
1994 {
1995 .id = V4L2_CID_AUDIO_BALANCE,
1996 .flags = V4L2_CTRL_FLAG_DISABLED,
1997 },
1998 {
1999 .id = V4L2_CID_AUDIO_BASS,
2000 .flags = V4L2_CTRL_FLAG_DISABLED,
2001 },
2002 {
2003 .id = V4L2_CID_AUDIO_TREBLE,
2004 .flags = V4L2_CTRL_FLAG_DISABLED,
2005 },
2006 {
2007 .id = V4L2_CID_AUDIO_MUTE,
2008 .type = V4L2_CTRL_TYPE_BOOLEAN,
2009 .name = "Mute",
2010 .minimum = 0,
2011 .maximum = 1,
2012 .step = 1,
2013 .default_value = 1,
2014 },
2015 {
2016 .id = V4L2_CID_AUDIO_LOUDNESS,
2017 .flags = V4L2_CTRL_FLAG_DISABLED,
2018 },
2019 {
2020 .id = V4L2_CID_PRIVATE_TAVARUA_SRCHMODE,
2021 .type = V4L2_CTRL_TYPE_INTEGER,
2022 .name = "Search mode",
2023 .minimum = 0,
2024 .maximum = 7,
2025 .step = 1,
2026 .default_value = 0,
2027 },
2028 {
2029 .id = V4L2_CID_PRIVATE_TAVARUA_SCANDWELL,
2030 .type = V4L2_CTRL_TYPE_INTEGER,
2031 .name = "Search dwell time",
2032 .minimum = 0,
2033 .maximum = 7,
2034 .step = 1,
2035 .default_value = 0,
2036 },
2037 {
2038 .id = V4L2_CID_PRIVATE_TAVARUA_SRCHON,
2039 .type = V4L2_CTRL_TYPE_BOOLEAN,
2040 .name = "Search on/off",
2041 .minimum = 0,
2042 .maximum = 1,
2043 .step = 1,
2044 .default_value = 1,
2045
2046 },
2047 {
2048 .id = V4L2_CID_PRIVATE_TAVARUA_STATE,
2049 .type = V4L2_CTRL_TYPE_INTEGER,
2050 .name = "radio 0ff/rx/tx/reset",
2051 .minimum = 0,
2052 .maximum = 3,
2053 .step = 1,
2054 .default_value = 1,
2055
2056 },
2057 {
2058 .id = V4L2_CID_PRIVATE_TAVARUA_REGION,
2059 .type = V4L2_CTRL_TYPE_INTEGER,
2060 .name = "radio standard",
2061 .minimum = 0,
2062 .maximum = 2,
2063 .step = 1,
2064 .default_value = 0,
2065 },
2066 {
2067 .id = V4L2_CID_PRIVATE_TAVARUA_SIGNAL_TH,
2068 .type = V4L2_CTRL_TYPE_INTEGER,
2069 .name = "Signal Threshold",
2070 .minimum = 0x80,
2071 .maximum = 0x7F,
2072 .step = 1,
2073 .default_value = 0,
2074 },
2075 {
2076 .id = V4L2_CID_PRIVATE_TAVARUA_SRCH_PTY,
2077 .type = V4L2_CTRL_TYPE_INTEGER,
2078 .name = "Search PTY",
2079 .minimum = 0,
2080 .maximum = 31,
2081 .default_value = 0,
2082 },
2083 {
2084 .id = V4L2_CID_PRIVATE_TAVARUA_SRCH_PI,
2085 .type = V4L2_CTRL_TYPE_INTEGER,
2086 .name = "Search PI",
2087 .minimum = 0,
2088 .maximum = 0xFF,
2089 .default_value = 0,
2090 },
2091 {
2092 .id = V4L2_CID_PRIVATE_TAVARUA_SRCH_CNT,
2093 .type = V4L2_CTRL_TYPE_INTEGER,
2094 .name = "Preset num",
2095 .minimum = 0,
2096 .maximum = 12,
2097 .default_value = 0,
2098 },
2099 {
2100 .id = V4L2_CID_PRIVATE_TAVARUA_EMPHASIS,
2101 .type = V4L2_CTRL_TYPE_BOOLEAN,
2102 .name = "Emphasis",
2103 .minimum = 0,
2104 .maximum = 1,
2105 .default_value = 0,
2106 },
2107 {
2108 .id = V4L2_CID_PRIVATE_TAVARUA_RDS_STD,
2109 .type = V4L2_CTRL_TYPE_BOOLEAN,
2110 .name = "RDS standard",
2111 .minimum = 0,
2112 .maximum = 1,
2113 .default_value = 0,
2114 },
2115 {
2116 .id = V4L2_CID_PRIVATE_TAVARUA_SPACING,
2117 .type = V4L2_CTRL_TYPE_INTEGER,
2118 .name = "Channel spacing",
2119 .minimum = 0,
2120 .maximum = 2,
2121 .default_value = 0,
2122 },
2123 {
2124 .id = V4L2_CID_PRIVATE_TAVARUA_RDSON,
2125 .type = V4L2_CTRL_TYPE_BOOLEAN,
2126 .name = "RDS on/off",
2127 .minimum = 0,
2128 .maximum = 1,
2129 .default_value = 0,
2130 },
2131 {
2132 .id = V4L2_CID_PRIVATE_TAVARUA_RDSGROUP_MASK,
2133 .type = V4L2_CTRL_TYPE_INTEGER,
2134 .name = "RDS group mask",
2135 .minimum = 0,
2136 .maximum = 0xFFFFFFFF,
2137 .default_value = 0,
2138 },
2139 {
2140 .id = V4L2_CID_PRIVATE_TAVARUA_RDSGROUP_PROC,
2141 .type = V4L2_CTRL_TYPE_INTEGER,
2142 .name = "RDS processing",
2143 .minimum = 0,
2144 .maximum = 0xFF,
2145 .default_value = 0,
2146 },
2147 {
2148 .id = V4L2_CID_PRIVATE_TAVARUA_RDSD_BUF,
2149 .type = V4L2_CTRL_TYPE_INTEGER,
2150 .name = "RDS data groups to buffer",
2151 .minimum = 1,
2152 .maximum = 21,
2153 .default_value = 0,
2154 },
2155 {
2156 .id = V4L2_CID_PRIVATE_TAVARUA_PSALL,
2157 .type = V4L2_CTRL_TYPE_BOOLEAN,
2158 .name = "pass all ps strings",
2159 .minimum = 0,
2160 .maximum = 1,
2161 .default_value = 0,
2162 },
2163 {
2164 .id = V4L2_CID_PRIVATE_TAVARUA_LP_MODE,
2165 .type = V4L2_CTRL_TYPE_BOOLEAN,
2166 .name = "Low power mode",
2167 .minimum = 0,
2168 .maximum = 1,
2169 .default_value = 0,
2170 },
2171 {
2172 .id = V4L2_CID_PRIVATE_TAVARUA_ANTENNA,
2173 .type = V4L2_CTRL_TYPE_BOOLEAN,
2174 .name = "headset/internal",
2175 .minimum = 0,
2176 .maximum = 1,
2177 .default_value = 0,
2178 },
2179 /* Private controls for FM TX*/
2180 {
2181 .id = V4L2_CID_PRIVATE_TAVARUA_TX_SETPSREPEATCOUNT,
2182 .type = V4L2_CTRL_TYPE_INTEGER,
2183 .name = "Set PS REPEATCOUNT",
2184 .minimum = 0,
2185 .maximum = 15,
2186 },
2187 {
2188 .id = V4L2_CID_PRIVATE_TAVARUA_STOP_RDS_TX_PS_NAME,
2189 .type = V4L2_CTRL_TYPE_BOOLEAN,
2190 .name = "Stop PS NAME",
2191 .minimum = 0,
2192 .maximum = 1,
2193 },
2194 {
2195 .id = V4L2_CID_PRIVATE_TAVARUA_STOP_RDS_TX_RT,
2196 .type = V4L2_CTRL_TYPE_BOOLEAN,
2197 .name = "Stop RT",
2198 .minimum = 0,
2199 .maximum = 1,
2200 },
2201
2202};
2203
2204/*=============================================================================
2205FUNCTION: tavarua_vidioc_querycap
2206=============================================================================*/
2207/**
2208 This function is called to query device capabilities.
2209
2210 NOTE:
2211 All V4L2 devices support the VIDIOC_QUERYCAP ioctl. It is used to identify
2212 kernel devices compatible with this specification and to obtain information
2213 about driver and hardware capabilities. The ioctl takes a pointer to a struct
2214 v4l2_capability which is filled by the driver. When the driver is not
2215 compatible with this specification the ioctl returns an EINVAL error code.
2216
2217 @param file: File descriptor returned by open().
2218 @param capability: pointer to struct v4l2_capability.
2219
2220 @return On success 0 is returned, else error code.
2221 @return EINVAL: The device is not compatible with this specification.
2222*/
2223static int tavarua_vidioc_querycap(struct file *file, void *priv,
2224 struct v4l2_capability *capability)
2225{
2226 struct tavarua_device *radio = video_get_drvdata(video_devdata(file));
2227
2228 strlcpy(capability->driver, DRIVER_NAME, sizeof(capability->driver));
2229 strlcpy(capability->card, DRIVER_CARD, sizeof(capability->card));
2230 sprintf(capability->bus_info, "I2C");
2231 capability->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO;
2232
2233 capability->version = radio->chipID;
2234
2235 return 0;
2236}
2237
2238/*=============================================================================
2239FUNCTION: tavarua_vidioc_queryctrl
2240=============================================================================*/
2241/**
2242 This function is called to query the device and driver for supported video
2243 controls (enumerate control items).
2244
2245 NOTE:
2246 To query the attributes of a control, the applications set the id field of
2247 a struct v4l2_queryctrl and call the VIDIOC_QUERYCTRL ioctl with a pointer
2248 to this structure. The driver fills the rest of the structure or returns an
2249 EINVAL error code when the id is invalid.
2250
2251 @param file: File descriptor returned by open().
2252 @param qc: pointer to struct v4l2_queryctrl.
2253
2254 @return On success 0 is returned, else error code.
2255 @return EINVAL: The struct v4l2_queryctrl id is invalid.
2256*/
2257static int tavarua_vidioc_queryctrl(struct file *file, void *priv,
2258 struct v4l2_queryctrl *qc)
2259{
2260 unsigned char i;
2261 int retval = -EINVAL;
2262
2263 for (i = 0; i < ARRAY_SIZE(tavarua_v4l2_queryctrl); i++) {
2264 if (qc->id && qc->id == tavarua_v4l2_queryctrl[i].id) {
2265 memcpy(qc, &(tavarua_v4l2_queryctrl[i]), sizeof(*qc));
2266 retval = 0;
2267 break;
2268 }
2269 }
2270 if (retval < 0)
2271 printk(KERN_WARNING DRIVER_NAME
2272 ": query conv4ltrol failed with %d\n", retval);
2273
2274 return retval;
2275}
2276static int peek_MPX_DCC(struct tavarua_device *radio)
2277{
2278 int retval = 0;
2279 unsigned char xfr_buf[XFR_REG_NUM];
2280 int MPX_DCC[] = { 0 };
2281 int DCC = 0;
2282 int ct = 0;
2283 unsigned char size = 0;
2284
2285 /*
2286 Poking the MPX_DCC_BYPASS register to freeze the
2287 value of MPX_DCC from changing while we access it
2288 */
2289
2290 /*Poking the MPX_DCC_BYPASS register : 0x88C0 */
2291 size = 0x01;
2292 xfr_buf[0] = (XFR_POKE_MODE | (size << 1));
2293 xfr_buf[1] = MPX_DCC_BYPASS_POKE_MSB;
2294 xfr_buf[2] = MPX_DCC_BYPASS_POKE_LSB;
2295 xfr_buf[3] = 0x01;
2296
2297 retval = tavarua_write_registers(radio, XFRCTRL, xfr_buf, 4);
2298 if (retval < 0) {
2299 FMDBG("Failed to write\n");
2300 return retval;
2301 }
2302 /*Wait for the XFR interrupt */
2303 msleep(TAVARUA_DELAY*15);
2304
2305 for (ct = 0; ct < 5; ct++)
2306 xfr_buf[ct] = 0;
2307
2308 /* Peeking Regs 0x88C2-0x88C4 */
2309 size = 0x03;
2310 xfr_buf[0] = (XFR_PEEK_MODE | (size << 1));
2311 xfr_buf[1] = MPX_DCC_PEEK_MSB_REG1;
2312 xfr_buf[2] = MPX_DCC_PEEK_LSB_REG1;
2313 retval = tavarua_write_registers(radio, XFRCTRL, xfr_buf, 3);
2314 if (retval < 0) {
2315 FMDBG("Failed to write\n");
2316 return retval;
2317 }
2318 /*Wait for the XFR interrupt */
2319 msleep(TAVARUA_DELAY*10);
2320 retval = tavarua_read_registers(radio, XFRDAT0, 3);
2321 if (retval < 0) {
2322 printk(KERN_INFO "INT_DET: Read failure\n");
2323 return retval;
2324 }
2325 MPX_DCC[0] = (int)radio->registers[XFRDAT0];
2326 MPX_DCC[1] = (int)radio->registers[XFRDAT1];
2327 MPX_DCC[2] = (int)radio->registers[XFRDAT2];
2328
2329 /*
2330 Form the final MPX_DCC parameter
2331 MPX_DCC[0] will form the LSB part
2332 MPX_DCC[1] will be the middle part and 4 bits of
2333 MPX_DCC[2] will be the MSB par of the 20-bit signed MPX_DCC
2334 */
2335
2336 DCC = ((int)MPX_DCC[2] << 16) | ((int)MPX_DCC[1] << 8) |
2337 ((int)MPX_DCC[0]);
2338
2339 /*
2340 if bit-19 is '1',set remaining bits to '1' & make it -tive
2341 */
2342 if (DCC & 0x00080000) {
2343 FMDBG(KERN_INFO "bit-19 is '1'\n");
2344 DCC |= 0xFFF00000;
2345 }
2346
2347 /*
2348 Poking the MPX_DCC_BYPASS register to be back to normal
2349 */
2350
2351 /*Poking the MPX_DCC_BYPASS register : 0x88C0 */
2352 size = 0x01;
2353 xfr_buf[0] = (XFR_POKE_MODE | (size << 1));
2354 xfr_buf[1] = MPX_DCC_BYPASS_POKE_MSB;
2355 xfr_buf[2] = MPX_DCC_BYPASS_POKE_LSB;
2356 xfr_buf[3] = 0x00;
2357
2358 retval = tavarua_write_registers(radio, XFRCTRL, xfr_buf, 4);
2359 if (retval < 0) {
2360 FMDBG("Failed to write\n");
2361 return retval;
2362 }
2363 /*Wait for the XFR interrupt */
2364 msleep(TAVARUA_DELAY*10);
2365
2366 return DCC;
2367}
2368/*=============================================================================
2369FUNCTION: tavarua_vidioc_g_ctrl
2370=============================================================================*/
2371/**
2372 This function is called to get the value of a control.
2373
2374 NOTE:
2375 To get the current value of a control, applications initialize the id field
2376 of a struct v4l2_control and call the VIDIOC_G_CTRL ioctl with a pointer to
2377 this structure.
2378
2379 When the id is invalid drivers return an EINVAL error code. When the value is
2380 out of bounds drivers can choose to take the closest valid value or return an
2381 ERANGE error code, whatever seems more appropriate.
2382
2383 @param file: File descriptor returned by open().
2384 @param ctrl: pointer to struct v4l2_control.
2385
2386 @return On success 0 is returned, else error code.
2387 @return EINVAL: The struct v4l2_control id is invalid.
2388 @return ERANGE: The struct v4l2_control value is out of bounds.
2389 @return EBUSY: The control is temporarily not changeable, possibly because
2390 another applications took over control of the device function this control
2391 belongs to.
2392*/
2393static int tavarua_vidioc_g_ctrl(struct file *file, void *priv,
2394 struct v4l2_control *ctrl)
2395{
2396 struct tavarua_device *radio = video_get_drvdata(video_devdata(file));
2397 int retval = 0;
2398 unsigned char xfr_buf[XFR_REG_NUM];
2399 signed char cRmssiThreshold;
2400 signed char ioc;
2401 unsigned char size = 0;
2402
2403 switch (ctrl->id) {
2404 case V4L2_CID_AUDIO_VOLUME:
2405 break;
2406 case V4L2_CID_AUDIO_MUTE:
2407 ctrl->value = radio->registers[IOCTRL] & 0x03 ;
2408 break;
2409 case V4L2_CID_PRIVATE_TAVARUA_SRCHMODE:
2410 ctrl->value = radio->registers[SRCHCTRL] & SRCH_MODE;
2411 break;
2412 case V4L2_CID_PRIVATE_TAVARUA_SCANDWELL:
2413 ctrl->value = (radio->registers[SRCHCTRL] & SCAN_DWELL) >> 4;
2414 break;
2415 case V4L2_CID_PRIVATE_TAVARUA_SRCHON:
2416 ctrl->value = (radio->registers[SRCHCTRL] & SRCH_ON) >> 7 ;
2417 break;
2418 case V4L2_CID_PRIVATE_TAVARUA_STATE:
2419 ctrl->value = (radio->registers[RDCTRL] & 0x03);
2420 break;
2421 case V4L2_CID_PRIVATE_TAVARUA_IOVERC:
2422 retval = tavarua_read_registers(radio, IOVERC, 1);
2423 if (retval < 0)
2424 return retval;
2425 ioc = radio->registers[IOVERC];
2426 ctrl->value = ioc;
2427 break;
2428 case V4L2_CID_PRIVATE_TAVARUA_INTDET:
2429 size = 0x1;
2430 xfr_buf[0] = (XFR_PEEK_MODE | (size << 1));
2431 xfr_buf[1] = INTDET_PEEK_MSB;
2432 xfr_buf[2] = INTDET_PEEK_LSB;
2433 retval = tavarua_write_registers(radio, XFRCTRL, xfr_buf, 3);
2434 if (retval < 0) {
2435 FMDBG("Failed to write\n");
2436 return retval;
2437 }
2438 FMDBG("INT_DET:Sync write success\n");
2439 /*Wait for the XFR interrupt */
2440 msleep(TAVARUA_DELAY*10);
2441 /* Read the XFRDAT0 register populated by FM SoC */
2442 retval = tavarua_read_registers(radio, XFRDAT0, 3);
2443 if (retval < 0) {
2444 FMDBG("INT_DET: Read failure\n");
2445 return retval;
2446 }
2447 ctrl->value = radio->registers[XFRDAT0];
2448 break;
2449 case V4L2_CID_PRIVATE_TAVARUA_MPX_DCC:
2450 ctrl->value = peek_MPX_DCC(radio);
2451 break;
2452 case V4L2_CID_PRIVATE_TAVARUA_REGION:
2453 ctrl->value = radio->region_params.region;
2454 break;
2455 case V4L2_CID_PRIVATE_TAVARUA_SIGNAL_TH:
2456 retval = sync_read_xfr(radio, RX_CONFIG, xfr_buf);
2457 if (retval < 0) {
2458 FMDBG("[G IOCTL=V4L2_CID_PRIVATE_TAVARUA_SIGNAL_TH]\n");
2459 FMDBG("sync_read_xfr error: [retval=%d]\n", retval);
2460 break;
2461 }
2462 /* Since RMSSI Threshold is signed value */
2463 cRmssiThreshold = (signed char)xfr_buf[0];
2464 ctrl->value = cRmssiThreshold;
2465 FMDBG("cRmssiThreshold: %d\n", cRmssiThreshold);
2466 break;
2467 case V4L2_CID_PRIVATE_TAVARUA_SRCH_PTY:
2468 ctrl->value = radio->srch_params.srch_pty;
2469 break;
2470 case V4L2_CID_PRIVATE_TAVARUA_SRCH_PI:
2471 ctrl->value = radio->srch_params.srch_pi;
2472 break;
2473 case V4L2_CID_PRIVATE_TAVARUA_SRCH_CNT:
2474 ctrl->value = radio->srch_params.preset_num;
2475 break;
2476 case V4L2_CID_PRIVATE_TAVARUA_EMPHASIS:
2477 ctrl->value = radio->region_params.emphasis;
2478 break;
2479 case V4L2_CID_PRIVATE_TAVARUA_RDS_STD:
2480 ctrl->value = radio->region_params.rds_std;
2481 break;
2482 case V4L2_CID_PRIVATE_TAVARUA_SPACING:
2483 ctrl->value = radio->region_params.spacing;
2484 break;
2485 case V4L2_CID_PRIVATE_TAVARUA_RDSON:
2486 ctrl->value = radio->registers[RDSCTRL] & RDS_ON;
2487 break;
2488 case V4L2_CID_PRIVATE_TAVARUA_RDSGROUP_MASK:
2489 retval = sync_read_xfr(radio, RDS_CONFIG, xfr_buf);
2490 if (retval > -1)
2491 ctrl->value = (xfr_buf[8] << 24) |
2492 (xfr_buf[9] << 16) |
2493 (xfr_buf[10] << 8) |
2494 xfr_buf[11];
2495 break;
2496 case V4L2_CID_PRIVATE_TAVARUA_RDSGROUP_PROC:
2497 retval = tavarua_read_registers(radio, ADVCTRL, 1);
2498 if (retval > -1)
2499 ctrl->value = radio->registers[ADVCTRL];
2500 break;
2501 case V4L2_CID_PRIVATE_TAVARUA_RDSD_BUF:
2502 retval = sync_read_xfr(radio, RDS_CONFIG, xfr_buf);
2503 if (retval > -1)
2504 ctrl->value = xfr_buf[1];
2505 break;
2506 case V4L2_CID_PRIVATE_TAVARUA_PSALL:
2507 retval = sync_read_xfr(radio, RDS_CONFIG, xfr_buf);
2508 if (retval > -1)
2509 ctrl->value = xfr_buf[12] & RDS_CONFIG_PSALL;
2510 break;
2511 case V4L2_CID_PRIVATE_TAVARUA_LP_MODE:
2512 ctrl->value = radio->lp_mode;
2513 break;
2514 case V4L2_CID_PRIVATE_TAVARUA_ANTENNA:
2515 ctrl->value = GET_REG_FIELD(radio->registers[IOCTRL],
2516 IOC_ANTENNA_OFFSET, IOC_ANTENNA_MASK);
2517 break;
2518 default:
2519 retval = -EINVAL;
2520 }
2521 if (retval < 0)
2522 printk(KERN_WARNING DRIVER_NAME
2523 ": get control failed with %d, id: %d\n", retval, ctrl->id);
2524
2525 return retval;
2526}
2527
2528static int tavarua_vidioc_s_ext_ctrls(struct file *file, void *priv,
2529 struct v4l2_ext_controls *ctrl)
2530{
2531 int retval = 0;
2532 int bytes_to_copy;
2533 int bytes_copied = 0;
2534 int bytes_left = 0;
2535 int chunk_index = 0;
2536 char tx_data[XFR_REG_NUM];
2537 struct tavarua_device *radio = video_get_drvdata(video_devdata(file));
2538 char *data = NULL;
2539 int extra_name_byte = 0;
2540 int name_bytes = 0;
2541
2542 switch ((ctrl->controls[0]).id) {
2543 case V4L2_CID_RDS_TX_PS_NAME: {
2544 FMDBG("In V4L2_CID_RDS_TX_PS_NAME\n");
2545 /*Pass a sample PS string */
2546
2547 chunk_index = 0;
2548 bytes_copied = 0;
2549 bytes_left = min((int)(ctrl->controls[0]).size,
2550 MAX_PS_LENGTH);
2551 data = (ctrl->controls[0]).string;
2552
2553 /* send payload to FM hardware */
2554 while (bytes_left) {
2555 chunk_index++;
2556 FMDBG("chunk is %d", chunk_index);
2557 bytes_to_copy = min(bytes_left, XFR_REG_NUM);
2558 /*Clear the tx_data */
2559 memset(tx_data, 0, XFR_REG_NUM);
2560 if (copy_from_user(tx_data,
2561 data + bytes_copied, bytes_to_copy))
2562 return -EFAULT;
2563 retval = sync_write_xfr(radio,
2564 RDS_PS_0 + chunk_index, tx_data);
2565 if (retval < 0) {
2566 FMDBG("sync_write_xfr: %d", retval);
2567 return retval;
2568 }
2569 bytes_copied += bytes_to_copy;
2570 bytes_left -= bytes_to_copy;
2571 }
2572 memset(tx_data, 0, XFR_REG_NUM);
2573 /*Write the PS Header*/
2574 FMDBG("Writing PS header\n");
2575 extra_name_byte = (bytes_copied%8) ? 1 : 0;
2576 name_bytes = (bytes_copied/8) + extra_name_byte;
2577 /*8 bytes are grouped as 1 name */
2578 tx_data[0] = (name_bytes) & MASK_TXREPCOUNT;
2579 tx_data[1] = radio->pty & MASK_PTY; /* PTY */
2580 tx_data[2] = ((radio->pi & MASK_PI_MSB) >> 8);
2581 tx_data[3] = radio->pi & MASK_PI_LSB;
2582 /* TX ctrl + repeatCount*/
2583 tx_data[4] = TX_ON |
2584 (radio->ps_repeatcount & MASK_TXREPCOUNT);
2585 retval = sync_write_xfr(radio, RDS_PS_0, tx_data);
2586 if (retval < 0) {
2587 FMDBG("sync_write_xfr returned %d", retval);
2588 return retval;
2589 }
2590 } break;
2591 case V4L2_CID_RDS_TX_RADIO_TEXT: {
2592 chunk_index = 0;
2593 bytes_copied = 0;
2594 FMDBG("In V4L2_CID_RDS_TX_RADIO_TEXT\n");
2595 /*Pass a sample PS string */
2596 FMDBG("Passed RT String : %s\n",
2597 (ctrl->controls[0]).string);
2598 bytes_left =
2599 min((int)(ctrl->controls[0]).size, MAX_RT_LENGTH);
2600 data = (ctrl->controls[0]).string;
2601 /* send payload to FM hardware */
2602 while (bytes_left) {
2603 chunk_index++;
2604 bytes_to_copy = min(bytes_left, XFR_REG_NUM);
2605 memset(tx_data, 0, XFR_REG_NUM);
2606 if (copy_from_user(tx_data,
2607 data + bytes_copied, bytes_to_copy))
2608 return -EFAULT;
2609 retval = sync_write_xfr(radio,
2610 RDS_RT_0 + chunk_index, tx_data);
2611 if (retval < 0)
2612 return retval;
2613 bytes_copied += bytes_to_copy;
2614 bytes_left -= bytes_to_copy;
2615 }
2616 /*Write the RT Header */
2617 tx_data[0] = bytes_copied;
2618 /* PTY */
2619 tx_data[1] = TX_ON | ((radio->pty & MASK_PTY) >> 8);
2620 /* PI high */
2621 tx_data[2] = ((radio->pi & MASK_PI_MSB) >> 8);
2622 /* PI low */
2623 tx_data[3] = radio->pi & MASK_PI_LSB;
2624 retval = sync_write_xfr(radio, RDS_RT_0 , tx_data);
2625 if (retval < 0)
2626 return retval;
2627 FMDBG("done RT writing: %d\n", retval);
2628 } break;
2629 default:
2630 {
2631 FMDBG("Shouldn't reach here\n");
2632 retval = -1;
2633 }
2634 }
2635 return retval;
2636}
2637
2638/*=============================================================================
2639FUNCTION: tavarua_vidioc_s_ctrl
2640=============================================================================*/
2641/**
2642 This function is called to set the value of a control.
2643
2644 NOTE:
2645 To change the value of a control, applications initialize the id and value
2646 fields of a struct v4l2_control and call the VIDIOC_S_CTRL ioctl.
2647
2648 When the id is invalid drivers return an EINVAL error code. When the value is
2649 out of bounds drivers can choose to take the closest valid value or return an
2650 ERANGE error code, whatever seems more appropriate.
2651
2652 @param file: File descriptor returned by open().
2653 @param ctrl: pointer to struct v4l2_control.
2654
2655 @return On success 0 is returned, else error code.
2656 @return EINVAL: The struct v4l2_control id is invalid.
2657 @return ERANGE: The struct v4l2_control value is out of bounds.
2658 @return EBUSY: The control is temporarily not changeable, possibly because
2659 another applications took over control of the device function this control
2660 belongs to.
2661*/
2662static int tavarua_vidioc_s_ctrl(struct file *file, void *priv,
2663 struct v4l2_control *ctrl)
2664{
2665 struct tavarua_device *radio = video_get_drvdata(video_devdata(file));
2666 int retval = 0;
2667 unsigned char value;
2668 unsigned char xfr_buf[XFR_REG_NUM];
2669 unsigned char tx_data[XFR_REG_NUM];
2670
2671 switch (ctrl->id) {
2672 case V4L2_CID_AUDIO_VOLUME:
2673 break;
2674 case V4L2_CID_AUDIO_MUTE:
2675 value = (radio->registers[IOCTRL] & ~IOC_HRD_MUTE) |
2676 (ctrl->value & 0x03);
2677 retval = tavarua_write_register(radio, IOCTRL, value);
2678 break;
2679 case V4L2_CID_PRIVATE_TAVARUA_SRCHMODE:
2680 value = (radio->registers[SRCHCTRL] & ~SRCH_MODE) |
2681 ctrl->value;
2682 radio->registers[SRCHCTRL] = value;
2683 break;
2684 case V4L2_CID_PRIVATE_TAVARUA_SCANDWELL:
2685 value = (radio->registers[SRCHCTRL] & ~SCAN_DWELL) |
2686 (ctrl->value << 4);
2687 radio->registers[SRCHCTRL] = value;
2688 break;
2689 /* start/stop search */
2690 case V4L2_CID_PRIVATE_TAVARUA_SRCHON:
2691 FMDBG("starting search\n");
2692 tavarua_search(radio, ctrl->value, SRCH_DIR_UP);
2693 break;
2694 case V4L2_CID_PRIVATE_TAVARUA_STATE:
2695 /* check if already on */
2696 radio->handle_irq = 1;
2697 if (((ctrl->value == FM_RECV) || (ctrl->value == FM_TRANS))
2698 && !(radio->registers[RDCTRL] &
2699 ctrl->value)) {
2700 FMDBG("clearing flags\n");
2701 init_completion(&radio->sync_xfr_start);
2702 init_completion(&radio->sync_req_done);
2703 radio->xfr_in_progress = 0;
2704 radio->xfr_bytes_left = 0;
2705 FMDBG("turning on ..\n");
2706 retval = tavarua_start(radio, ctrl->value);
2707 if (retval >= 0) {
2708 FMDBG("Setting audio path ...\n");
2709 retval = tavarua_set_audio_path(
2710 TAVARUA_AUDIO_OUT_DIGITAL_ON,
2711 TAVARUA_AUDIO_OUT_ANALOG_OFF);
2712 if (retval < 0) {
2713 FMDERR("Error in tavarua_set_audio_path"
2714 " %d\n", retval);
2715 }
2716 /* Enabling 'SoftMute' and 'SignalBlending' features */
2717 value = (radio->registers[IOCTRL] |
2718 IOC_SFT_MUTE | IOC_SIG_BLND);
2719 retval = tavarua_write_register(radio, IOCTRL, value);
2720 if (retval < 0)
2721 FMDBG("SMute and SBlending not enabled\n");
2722 }
2723 }
2724 /* check if off */
2725 else if ((ctrl->value == FM_OFF) && radio->registers[RDCTRL]) {
2726 FMDBG("turning off...\n");
2727 retval = tavarua_write_register(radio, RDCTRL,
2728 ctrl->value);
2729 /*Make it synchronous
2730 Block it till READY interrupt
2731 Wait for interrupt i.e.
2732 complete(&radio->sync_req_done)
2733 */
2734
2735 if (retval >= 0) {
2736
2737 if (!wait_for_completion_timeout(
2738 &radio->sync_req_done,
2739 msecs_to_jiffies(wait_timeout)))
2740 FMDBG("turning off timedout...\n");
2741 }
2742 }
2743 break;
2744 case V4L2_CID_PRIVATE_TAVARUA_REGION:
2745 retval = tavarua_set_region(radio, ctrl->value);
2746 break;
2747 case V4L2_CID_PRIVATE_TAVARUA_SIGNAL_TH:
2748 retval = sync_read_xfr(radio, RX_CONFIG, xfr_buf);
2749 if (retval < 0) {
2750 FMDERR("V4L2_CID_PRIVATE_TAVARUA_SIGNAL_TH]\n");
2751 FMDERR("sync_read_xfr [retval=%d]\n", retval);
2752 break;
2753 }
2754 /* RMSSI Threshold is a signed 8 bit value */
2755 xfr_buf[0] = (unsigned char)ctrl->value;
2756 xfr_buf[1] = (unsigned char)ctrl->value;
2757 xfr_buf[4] = 0x01;
2758 retval = sync_write_xfr(radio, RX_CONFIG, xfr_buf);
2759 if (retval < 0) {
2760 FMDERR("V4L2_CID_PRIVATE_TAVARUA_SIGNAL_TH]\n");
2761 FMDERR("sync_write_xfr [retval=%d]\n", retval);
2762 break;
2763 }
2764 break;
2765 case V4L2_CID_PRIVATE_TAVARUA_SRCH_PTY:
2766 radio->srch_params.srch_pty = ctrl->value;
2767 break;
2768 case V4L2_CID_PRIVATE_TAVARUA_SRCH_PI:
2769 radio->srch_params.srch_pi = ctrl->value;
2770 break;
2771 case V4L2_CID_PRIVATE_TAVARUA_SRCH_CNT:
2772 radio->srch_params.preset_num = ctrl->value;
2773 break;
2774 case V4L2_CID_PRIVATE_TAVARUA_EMPHASIS:
2775 radio->region_params.emphasis = ctrl->value;
2776 break;
2777 case V4L2_CID_PRIVATE_TAVARUA_RDS_STD:
2778 radio->region_params.rds_std = ctrl->value;
2779 break;
2780 case V4L2_CID_PRIVATE_TAVARUA_SPACING:
2781 radio->region_params.spacing = ctrl->value;
2782 break;
2783 case V4L2_CID_PRIVATE_TAVARUA_RDSON:
2784 retval = 0;
2785 if (ctrl->value != (radio->registers[RDSCTRL] & RDS_ON)) {
2786 value = radio->registers[RDSCTRL] | ctrl->value;
2787 retval = tavarua_write_register(radio, RDSCTRL, value);
2788 }
2789 break;
2790 case V4L2_CID_PRIVATE_TAVARUA_RDSGROUP_MASK:
2791 retval = sync_read_xfr(radio, RDS_CONFIG, xfr_buf);
2792 if (retval < 0)
2793 break;
2794 xfr_buf[8] = (ctrl->value & 0xFF000000) >> 24;
2795 xfr_buf[9] = (ctrl->value & 0x00FF0000) >> 16;
2796 xfr_buf[10] = (ctrl->value & 0x0000FF00) >> 8;
2797 xfr_buf[11] = (ctrl->value & 0x000000FF);
2798 retval = sync_write_xfr(radio, RDS_CONFIG, xfr_buf);
2799 break;
2800 case V4L2_CID_PRIVATE_TAVARUA_RDSGROUP_PROC:
2801 value = radio->registers[ADVCTRL] | ctrl->value ;
2802 retval = tavarua_write_register(radio, ADVCTRL, value);
2803 break;
2804 case V4L2_CID_PRIVATE_TAVARUA_RDSD_BUF:
2805 retval = sync_read_xfr(radio, RDS_CONFIG, xfr_buf);
2806 if (retval < 0)
2807 break;
2808 xfr_buf[1] = ctrl->value;
2809 retval = sync_write_xfr(radio, RDS_CONFIG, xfr_buf);
2810 break;
2811 case V4L2_CID_PRIVATE_TAVARUA_PSALL:
2812 retval = sync_read_xfr(radio, RDS_CONFIG, xfr_buf);
2813 value = ctrl->value & RDS_CONFIG_PSALL;
2814 if (retval < 0)
2815 break;
2816 xfr_buf[12] &= ~RDS_CONFIG_PSALL;
2817 xfr_buf[12] |= value;
2818 retval = sync_write_xfr(radio, RDS_CONFIG, xfr_buf);
2819 break;
2820 case V4L2_CID_PRIVATE_TAVARUA_LP_MODE:
2821 retval = 0;
2822 if (ctrl->value == radio->lp_mode)
2823 break;
2824 if (ctrl->value) {
2825 FMDBG("going into low power mode\n");
2826 retval = tavarua_disable_interrupts(radio);
2827 } else {
2828 FMDBG("going into normal power mode\n");
2829 tavarua_setup_interrupts(radio,
2830 (radio->registers[RDCTRL] & 0x03));
2831 }
2832 break;
2833 case V4L2_CID_PRIVATE_TAVARUA_ANTENNA:
2834 SET_REG_FIELD(radio->registers[IOCTRL], ctrl->value,
2835 IOC_ANTENNA_OFFSET, IOC_ANTENNA_MASK);
2836 break;
2837 /* TX Controls */
2838
2839 case V4L2_CID_RDS_TX_PTY: {
2840 radio->pty = ctrl->value;
2841 } break;
2842 case V4L2_CID_RDS_TX_PI: {
2843 radio->pi = ctrl->value;
2844 } break;
2845 case V4L2_CID_PRIVATE_TAVARUA_STOP_RDS_TX_PS_NAME: {
2846 FMDBG("In STOP_RDS_TX_PS_NAME\n");
2847 /*Pass a sample PS string */
2848 memset(tx_data, '0', XFR_REG_NUM);
2849 FMDBG("Writing PS header\n");
2850 retval = sync_write_xfr(radio, RDS_PS_0, tx_data);
2851 FMDBG("retval of PS Header write: %d", retval);
2852
2853 } break;
2854
2855 case V4L2_CID_PRIVATE_TAVARUA_STOP_RDS_TX_RT: {
2856 memset(tx_data, '0', XFR_REG_NUM);
2857 FMDBG("Writing RT header\n");
2858 retval = sync_write_xfr(radio, RDS_RT_0, tx_data);
2859 FMDBG("retval of Header write: %d", retval);
2860
2861 } break;
2862
2863 case V4L2_CID_PRIVATE_TAVARUA_TX_SETPSREPEATCOUNT: {
2864 radio->ps_repeatcount = ctrl->value;
2865 } break;
2866 case V4L2_CID_TUNE_POWER_LEVEL: {
2867 unsigned char tx_power_lvl_config[FM_TX_PWR_LVL_MAX+1] = {
2868 0x85, /* tx_da<5:3> = 0 lpf<2:0> = 5*/
2869 0x95, /* tx_da<5:3> = 2 lpf<2:0> = 5*/
2870 0x9D, /* tx_da<5:3> = 3 lpf<2:0> = 5*/
2871 0xA5, /* tx_da<5:3> = 4 lpf<2:0> = 5*/
2872 0xAD, /* tx_da<5:3> = 5 lpf<2:0> = 5*/
2873 0xB5, /* tx_da<5:3> = 6 lpf<2:0> = 5*/
2874 0xBD, /* tx_da<5:3> = 7 lpf<2:0> = 5*/
2875 0xBF /* tx_da<5:3> = 7 lpf<2:0> = 7*/
2876 };
2877 if (ctrl->value > FM_TX_PWR_LVL_MAX)
2878 ctrl->value = FM_TX_PWR_LVL_MAX;
2879 if (ctrl->value < FM_TX_PWR_LVL_0)
2880 ctrl->value = FM_TX_PWR_LVL_0;
2881 retval = sync_read_xfr(radio, PHY_TXGAIN, xfr_buf);
2882 FMDBG("return for PHY_TXGAIN is %d", retval);
2883 if (retval < 0) {
2884 FMDBG("read failed");
2885 break;
2886 }
2887 xfr_buf[2] = tx_power_lvl_config[ctrl->value];
2888 retval = sync_write_xfr(radio, PHY_TXGAIN, xfr_buf);
2889 FMDBG("return for write PHY_TXGAIN is %d", retval);
2890 if (retval < 0)
2891 FMDBG("write failed");
2892 } break;
2893
2894 default:
2895 retval = -EINVAL;
2896 }
2897 if (retval < 0)
2898 printk(KERN_WARNING DRIVER_NAME
2899 ": set control failed with %d, id : %d\n", retval, ctrl->id);
2900
2901 return retval;
2902}
2903
2904/*=============================================================================
2905FUNCTION: tavarua_vidioc_g_tuner
2906=============================================================================*/
2907/**
2908 This function is called to get tuner attributes.
2909
2910 NOTE:
2911 To query the attributes of a tuner, applications initialize the index field
2912 and zero out the reserved array of a struct v4l2_tuner and call the
2913 VIDIOC_G_TUNER ioctl with a pointer to this structure. Drivers fill the rest
2914 of the structure or return an EINVAL error code when the index is out of
2915 bounds. To enumerate all tuners applications shall begin at index zero,
2916 incrementing by one until the driver returns EINVAL.
2917
2918 @param file: File descriptor returned by open().
2919 @param tuner: pointer to struct v4l2_tuner.
2920
2921 @return On success 0 is returned, else error code.
2922 @return EINVAL: The struct v4l2_tuner index is out of bounds.
2923*/
2924static int tavarua_vidioc_g_tuner(struct file *file, void *priv,
2925 struct v4l2_tuner *tuner)
2926{
2927 struct tavarua_device *radio = video_get_drvdata(video_devdata(file));
2928 int retval;
2929 unsigned char xfr_buf[XFR_REG_NUM];
2930 char rmssi = 0;
2931 unsigned char size = 0;
2932
2933 if (tuner->index > 0)
2934 return -EINVAL;
2935
2936 /* read status rssi */
2937 retval = tavarua_read_registers(radio, IOCTRL, 1);
2938 if (retval < 0)
2939 return retval;
2940 /* read RMSSI */
2941 size = 0x1;
2942 xfr_buf[0] = (XFR_PEEK_MODE | (size << 1));
2943 xfr_buf[1] = RMSSI_PEEK_MSB;
2944 xfr_buf[2] = RMSSI_PEEK_LSB;
2945 retval = tavarua_write_registers(radio, XFRCTRL, xfr_buf, 3);
2946 msleep(TAVARUA_DELAY*10);
2947 retval = tavarua_read_registers(radio, XFRDAT0, 3);
2948 rmssi = radio->registers[XFRDAT0];
2949 tuner->signal = rmssi;
2950
2951 strcpy(tuner->name, "FM");
2952 tuner->type = V4L2_TUNER_RADIO;
2953 tuner->rangelow = radio->region_params.band_low;
2954 tuner->rangehigh = radio->region_params.band_high;
2955 tuner->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO;
2956 tuner->capability = V4L2_TUNER_CAP_LOW;
2957
2958 /* Stereo indicator == Stereo (instead of Mono) */
2959 if (radio->registers[IOCTRL] & IOC_MON_STR)
2960 tuner->audmode = V4L2_TUNER_MODE_STEREO;
2961 else
2962 tuner->audmode = V4L2_TUNER_MODE_MONO;
2963
2964 /* automatic frequency control: -1: freq to low, 1 freq to high */
2965 tuner->afc = 0;
2966
2967 return 0;
2968}
2969
2970/*=============================================================================
2971FUNCTION: tavarua_vidioc_s_tuner
2972=============================================================================*/
2973/**
2974 This function is called to set tuner attributes. Used to set mono/stereo mode.
2975
2976 NOTE:
2977 Tuners have two writable properties, the audio mode and the radio frequency.
2978 To change the audio mode, applications initialize the index, audmode and
2979 reserved fields and call the VIDIOC_S_TUNER ioctl. This will not change the
2980 current tuner, which is determined by the current video input. Drivers may
2981 choose a different audio mode if the requested mode is invalid or unsupported.
2982 Since this is a write-only ioctl, it does not return the actually selected
2983 audio mode.
2984
2985 To change the radio frequency the VIDIOC_S_FREQUENCY ioctl is available.
2986
2987 @param file: File descriptor returned by open().
2988 @param tuner: pointer to struct v4l2_tuner.
2989
2990 @return On success 0 is returned, else error code.
2991 @return -EINVAL: The struct v4l2_tuner index is out of bounds.
2992*/
2993static int tavarua_vidioc_s_tuner(struct file *file, void *priv,
2994 struct v4l2_tuner *tuner)
2995{
2996 struct tavarua_device *radio = video_get_drvdata(video_devdata(file));
2997 int retval;
2998 int audmode;
2999 if (tuner->index > 0)
3000 return -EINVAL;
3001
3002 FMDBG("%s: set low to %d\n", __func__, tuner->rangelow);
3003 radio->region_params.band_low = tuner->rangelow;
3004 radio->region_params.band_high = tuner->rangehigh;
3005 if (tuner->audmode == V4L2_TUNER_MODE_MONO)
3006 /* Mono */
3007 audmode = (radio->registers[IOCTRL] | IOC_MON_STR);
3008 else
3009 /* Stereo */
3010 audmode = (radio->registers[IOCTRL] & ~IOC_MON_STR);
3011 retval = tavarua_write_register(radio, IOCTRL, audmode);
3012 if (retval < 0)
3013 printk(KERN_WARNING DRIVER_NAME
3014 ": set tuner failed with %d\n", retval);
3015
3016 return retval;
3017}
3018
3019/*=============================================================================
3020FUNCTION: tavarua_vidioc_g_frequency
3021=============================================================================*/
3022/**
3023 This function is called to get tuner or modulator radio frequency.
3024
3025 NOTE:
3026 To get the current tuner or modulator radio frequency applications set the
3027 tuner field of a struct v4l2_frequency to the respective tuner or modulator
3028 number (only input devices have tuners, only output devices have modulators),
3029 zero out the reserved array and call the VIDIOC_G_FREQUENCY ioctl with a
3030 pointer to this structure. The driver stores the current frequency in the
3031 frequency field.
3032
3033 @param file: File descriptor returned by open().
3034 @param freq: pointer to struct v4l2_frequency. This will be set to the
3035 resultant
3036 frequency in 62.5 khz on success.
3037
3038 @return On success 0 is returned, else error code.
3039 @return EINVAL: The tuner index is out of bounds or the value in the type
3040 field is wrong.
3041*/
3042static int tavarua_vidioc_g_frequency(struct file *file, void *priv,
3043 struct v4l2_frequency *freq)
3044{
3045 struct tavarua_device *radio = video_get_drvdata(video_devdata(file));
3046 freq->type = V4L2_TUNER_RADIO;
3047 return tavarua_get_freq(radio, freq);
3048
3049}
3050
3051/*=============================================================================
3052FUNCTION: tavarua_vidioc_s_frequency
3053=============================================================================*/
3054/**
3055 This function is called to set tuner or modulator radio frequency.
3056
3057 NOTE:
3058 To change the current tuner or modulator radio frequency applications
3059 initialize the tuner, type and frequency fields, and the reserved array of
3060 a struct v4l2_frequency and call the VIDIOC_S_FREQUENCY ioctl with a pointer
3061 to this structure. When the requested frequency is not possible the driver
3062 assumes the closest possible value. However VIDIOC_S_FREQUENCY is a
3063 write-only ioctl, it does not return the actual new frequency.
3064
3065 @param file: File descriptor returned by open().
3066 @param freq: pointer to struct v4l2_frequency.
3067
3068 @return On success 0 is returned, else error code.
3069 @return EINVAL: The tuner index is out of bounds or the value in the type
3070 field is wrong.
3071*/
3072static int tavarua_vidioc_s_frequency(struct file *file, void *priv,
3073 struct v4l2_frequency *freq)
3074{
3075 struct tavarua_device *radio = video_get_drvdata(video_devdata(file));
3076 int retval = -1;
3077 struct v4l2_frequency getFreq;
3078
3079 FMDBG("%s\n", __func__);
3080
3081 if (freq->type != V4L2_TUNER_RADIO)
3082 return -EINVAL;
3083
3084 FMDBG("Calling tavarua_set_freq\n");
3085
3086 INIT_COMPLETION(radio->sync_req_done);
3087 retval = tavarua_set_freq(radio, freq->frequency);
3088 if (retval < 0) {
3089 printk(KERN_WARNING DRIVER_NAME
3090 ": set frequency failed with %d\n", retval);
3091 } else {
3092 /* Wait for interrupt i.e. complete
3093 (&radio->sync_req_done); call */
3094 if (!wait_for_completion_timeout(&radio->sync_req_done,
3095 msecs_to_jiffies(wait_timeout))) {
3096 FMDERR("Timeout: No Tune response");
3097 retval = tavarua_get_freq(radio, &getFreq);
3098 radio->tune_req = 0;
3099 if (retval > 0) {
3100 if (getFreq.frequency == freq->frequency) {
3101 /** This is success, queut the event*/
3102 tavarua_q_event(radio,
3103 TAVARUA_EVT_TUNE_SUCC);
3104 return 0;
3105 } else {
3106 return -EIO;
3107 }
3108 }
3109 }
3110 }
3111 radio->tune_req = 0;
3112 return retval;
3113}
3114
3115/*=============================================================================
3116FUNCTION: tavarua_vidioc_dqbuf
3117=============================================================================*/
3118/**
3119 This function is called to exchange a buffer with the driver.
3120 This is main buffer function, in essense its equivalent to a blocking
3121 read call.
3122
3123 Applications call the VIDIOC_DQBUF ioctl to dequeue a filled (capturing) or
3124 displayed (output) buffer from the driver's outgoing queue. They just set
3125 the type and memory fields of a struct v4l2_buffer as above, when VIDIOC_DQBUF
3126 is called with a pointer to this structure the driver fills the remaining
3127 fields or returns an error code.
3128
3129 NOTE:
3130 By default VIDIOC_DQBUF blocks when no buffer is in the outgoing queue.
3131 When the O_NONBLOCK flag was given to the open() function, VIDIOC_DQBUF
3132 returns immediately with an EAGAIN error code when no buffer is available.
3133
3134 @param file: File descriptor returned by open().
3135 @param buffer: pointer to struct v4l2_buffer.
3136
3137 @return On success 0 is returned, else error code.
3138 @return EAGAIN: Non-blocking I/O has been selected using O_NONBLOCK and no
3139 buffer was in the outgoing queue.
3140 @return EINVAL: The buffer type is not supported, or the index is out of
3141 bounds, or no buffers have been allocated yet, or the userptr or length are
3142 invalid.
3143 @return ENOMEM: Not enough physical or virtual memory was available to enqueue
3144 a user pointer buffer.
3145 @return EIO: VIDIOC_DQBUF failed due to an internal error. Can also indicate
3146 temporary problems like signal loss. Note the driver might dequeue an (empty)
3147 buffer despite returning an error, or even stop capturing.
3148*/
3149static int tavarua_vidioc_dqbuf(struct file *file, void *priv,
3150 struct v4l2_buffer *buffer)
3151{
3152
3153 struct tavarua_device *radio = video_get_drvdata(video_devdata(file));
3154 enum tavarua_buf_t buf_type = buffer->index;
3155 struct kfifo *data_fifo;
3156 unsigned char *buf = (unsigned char *)buffer->m.userptr;
3157 unsigned int len = buffer->length;
3158 FMDBG("%s: requesting buffer %d\n", __func__, buf_type);
3159 /* check if we can access the user buffer */
3160 if (!access_ok(VERIFY_WRITE, buf, len))
3161 return -EFAULT;
3162 if ((buf_type < TAVARUA_BUF_MAX) && (buf_type >= 0)) {
3163 data_fifo = &radio->data_buf[buf_type];
3164 if (buf_type == TAVARUA_BUF_EVENTS) {
3165 if (wait_event_interruptible(radio->event_queue,
3166 kfifo_len(data_fifo)) < 0) {
3167 return -EINTR;
3168 }
3169 }
3170 } else {
3171 FMDERR("invalid buffer type\n");
3172 return -EINVAL;
3173 }
3174 buffer->bytesused = kfifo_out_locked(data_fifo, buf, len,
3175 &radio->buf_lock[buf_type]);
3176
3177 return 0;
3178}
3179
3180/*=============================================================================
3181FUNCTION: tavarua_vidioc_g_fmt_type_private
3182=============================================================================*/
3183/**
3184 This function is here to make the v4l2 framework happy.
3185 We cannot use private buffers without it.
3186
3187 @param file: File descriptor returned by open().
3188 @param f: pointer to struct v4l2_format.
3189
3190 @return On success 0 is returned, else error code.
3191 @return EINVAL: The tuner index is out of bounds or the value in the type
3192 field is wrong.
3193*/
3194static int tavarua_vidioc_g_fmt_type_private(struct file *file, void *priv,
3195 struct v4l2_format *f)
3196{
3197 return 0;
3198
3199}
3200
3201/*=============================================================================
3202FUNCTION: tavarua_vidioc_s_hw_freq_seek
3203=============================================================================*/
3204/**
3205 This function is called to perform a hardware frequency seek.
3206
3207 Start a hardware frequency seek from the current frequency. To do this
3208 applications initialize the tuner, type, seek_upward and wrap_around fields,
3209 and zero out the reserved array of a struct v4l2_hw_freq_seek and call the
3210 VIDIOC_S_HW_FREQ_SEEK ioctl with a pointer to this structure.
3211
3212 This ioctl is supported if the V4L2_CAP_HW_FREQ_SEEK capability is set.
3213
3214 @param file: File descriptor returned by open().
3215 @param seek: pointer to struct v4l2_hw_freq_seek.
3216
3217 @return On success 0 is returned, else error code.
3218 @return EINVAL: The tuner index is out of bounds or the value in the type
3219 field is wrong.
3220 @return EAGAIN: The ioctl timed-out. Try again.
3221*/
3222static int tavarua_vidioc_s_hw_freq_seek(struct file *file, void *priv,
3223 struct v4l2_hw_freq_seek *seek)
3224{
3225 struct tavarua_device *radio = video_get_drvdata(video_devdata(file));
3226 int dir;
3227 if (seek->seek_upward)
3228 dir = SRCH_DIR_UP;
3229 else
3230 dir = SRCH_DIR_DOWN;
3231 FMDBG("starting search\n");
3232 return tavarua_search(radio, CTRL_ON, dir);
3233}
3234
3235/*
3236 * tavarua_viddev_tamples - video device interface
3237 */
3238static const struct v4l2_ioctl_ops tavarua_ioctl_ops = {
3239 .vidioc_querycap = tavarua_vidioc_querycap,
3240 .vidioc_queryctrl = tavarua_vidioc_queryctrl,
3241 .vidioc_g_ctrl = tavarua_vidioc_g_ctrl,
3242 .vidioc_s_ctrl = tavarua_vidioc_s_ctrl,
3243 .vidioc_g_tuner = tavarua_vidioc_g_tuner,
3244 .vidioc_s_tuner = tavarua_vidioc_s_tuner,
3245 .vidioc_g_frequency = tavarua_vidioc_g_frequency,
3246 .vidioc_s_frequency = tavarua_vidioc_s_frequency,
3247 .vidioc_s_hw_freq_seek = tavarua_vidioc_s_hw_freq_seek,
3248 .vidioc_dqbuf = tavarua_vidioc_dqbuf,
3249 .vidioc_g_fmt_type_private = tavarua_vidioc_g_fmt_type_private,
3250 .vidioc_s_ext_ctrls = tavarua_vidioc_s_ext_ctrls,
3251};
3252
3253static struct video_device tavarua_viddev_template = {
3254 .fops = &tavarua_fops,
3255 .ioctl_ops = &tavarua_ioctl_ops,
3256 .name = DRIVER_NAME,
3257 .release = video_device_release,
3258};
3259
3260/*==============================================================
3261FUNCTION: FmQSocCom_EnableInterrupts
3262==============================================================*/
3263/**
3264 This function enable interrupts.
3265
3266 @param radio: structure pointer passed by client.
3267 @param state: FM radio state (receiver/transmitter/off/reset).
3268
3269 @return => 0 if successful.
3270 @return < 0 if failure.
3271*/
3272static int tavarua_setup_interrupts(struct tavarua_device *radio,
3273 enum radio_state_t state)
3274{
3275 int retval;
3276 unsigned char int_ctrl[XFR_REG_NUM];
3277
3278 if (!radio->lp_mode)
3279 return 0;
3280
3281 int_ctrl[STATUS_REG1] = READY | TUNE | SEARCH | SCANNEXT |
3282 SIGNAL | INTF | SYNC | AUDIO;
3283 if (state == FM_RECV)
3284 int_ctrl[STATUS_REG2] = RDSDAT | RDSRT | RDSPS | RDSAF;
3285 else
3286 int_ctrl[STATUS_REG2] = TXRDSDAT | TXRDSDONE;
3287
3288 int_ctrl[STATUS_REG3] = TRANSFER | ERROR;
3289
3290 /* use xfr for interrupt setup */
3291 if (radio->chipID == MARIMBA_2_1 || radio->chipID == BAHAMA_1_0
3292 || radio->chipID == BAHAMA_2_0) {
3293 FMDBG("Setting interrupts\n");
3294 retval = sync_write_xfr(radio, INT_CTRL, int_ctrl);
3295 /* use register write to setup interrupts */
3296 } else {
3297 retval = tavarua_write_register(radio,
3298 STATUS_REG1, int_ctrl[STATUS_REG1]);
3299 if (retval < 0)
3300 return retval;
3301
3302 retval = tavarua_write_register(radio,
3303 STATUS_REG2, int_ctrl[STATUS_REG2]);
3304 if (retval < 0)
3305 return retval;
3306
3307 retval = tavarua_write_register(radio,
3308 STATUS_REG3, int_ctrl[STATUS_REG3]);
3309 if (retval < 0)
3310 return retval;
3311 }
3312
3313 radio->lp_mode = 0;
3314 /* tavarua_handle_interrupts force reads all the interrupt status
3315 * registers and it is not valid for MBA 2.1
3316 */
3317 if ((radio->chipID != MARIMBA_2_1) && (radio->chipID != BAHAMA_1_0)
3318 && (radio->chipID != BAHAMA_2_0))
3319 tavarua_handle_interrupts(radio);
3320
3321 return retval;
3322
3323}
3324
3325/*==============================================================
3326FUNCTION: tavarua_disable_interrupts
3327==============================================================*/
3328/**
3329 This function disables interrupts.
3330
3331 @param radio: structure pointer passed by client.
3332
3333 @return => 0 if successful.
3334 @return < 0 if failure.
3335*/
3336static int tavarua_disable_interrupts(struct tavarua_device *radio)
3337{
3338 unsigned char lpm_buf[XFR_REG_NUM];
3339 int retval;
3340 if (radio->lp_mode)
3341 return 0;
3342 FMDBG("%s\n", __func__);
3343 /* In Low power mode, disable all the interrupts that are not being
3344 waited by the Application */
3345 lpm_buf[STATUS_REG1] = TUNE | SEARCH | SCANNEXT;
3346 lpm_buf[STATUS_REG2] = 0x00;
3347 lpm_buf[STATUS_REG3] = TRANSFER;
3348 /* use xfr for interrupt setup */
3349 wait_timeout = 100;
3350 if (radio->chipID == MARIMBA_2_1 || radio->chipID == BAHAMA_1_0
3351 || radio->chipID == BAHAMA_2_0)
3352 retval = sync_write_xfr(radio, INT_CTRL, lpm_buf);
3353 /* use register write to setup interrupts */
3354 else
3355 retval = tavarua_write_registers(radio, STATUS_REG1, lpm_buf,
3356 ARRAY_SIZE(lpm_buf));
3357
3358 /*INT_CTL writes may fail with TIME_OUT as all the
3359 interrupts have been disabled
3360 */
3361 if (retval > -1 || retval == -ETIME) {
3362 radio->lp_mode = 1;
3363 /*Consider timeout as a valid case here*/
3364 retval = 0;
3365 }
3366 wait_timeout = WAIT_TIMEOUT;
3367 return retval;
3368
3369}
3370
3371/*==============================================================
3372FUNCTION: tavarua_start
3373==============================================================*/
3374/**
3375 Starts/enables the device (FM radio).
3376
3377 @param radio: structure pointer passed by client.
3378 @param state: FM radio state (receiver/transmitter/off/reset).
3379
3380 @return On success 0 is returned, else error code.
3381*/
3382static int tavarua_start(struct tavarua_device *radio,
3383 enum radio_state_t state)
3384{
3385
3386 int retval;
3387 FMDBG("%s <%d>\n", __func__, state);
3388 /* set geographic region */
3389 radio->region_params.region = TAVARUA_REGION_US;
3390
3391 /* set radio mode */
3392 retval = tavarua_write_register(radio, RDCTRL, state);
3393 if (retval < 0)
3394 return retval;
3395 /* wait for radio to init */
3396 msleep(RADIO_INIT_TIME);
3397 /* enable interrupts */
3398 tavarua_setup_interrupts(radio, state);
3399 /* default region is US */
3400 radio->region_params.band_low = US_LOW_BAND * FREQ_MUL;
3401 radio->region_params.band_high = US_HIGH_BAND * FREQ_MUL;
3402
3403 return 0;
3404}
3405
3406/*==============================================================
3407FUNCTION: tavarua_suspend
3408==============================================================*/
3409/**
3410 Save state and stop all devices in system.
3411
3412 @param pdev: platform device to be suspended.
3413 @param state: Power state to put each device in.
3414
3415 @return On success 0 is returned, else error code.
3416*/
3417static int tavarua_suspend(struct platform_device *pdev, pm_message_t state)
3418{
3419 struct tavarua_device *radio = platform_get_drvdata(pdev);
3420 int retval;
3421 int users = 0;
3422 printk(KERN_INFO DRIVER_NAME "%s: radio suspend\n\n", __func__);
3423 if (radio) {
3424 mutex_lock(&radio->lock);
3425 users = radio->users;
3426 mutex_unlock(&radio->lock);
3427 if (users) {
3428 retval = tavarua_disable_interrupts(radio);
3429 if (retval < 0) {
3430 printk(KERN_INFO DRIVER_NAME
3431 "tavarua_suspend error %d\n", retval);
3432 return -EIO;
3433 }
3434 }
3435 }
3436 return 0;
3437}
3438
3439/*==============================================================
3440FUNCTION: tavarua_resume
3441==============================================================*/
3442/**
3443 Restore state of each device in system.
3444
3445 @param pdev: platform device to be resumed.
3446
3447 @return On success 0 is returned, else error code.
3448*/
3449static int tavarua_resume(struct platform_device *pdev)
3450{
3451
3452 struct tavarua_device *radio = platform_get_drvdata(pdev);
3453 int retval;
3454 int users = 0;
3455 printk(KERN_INFO DRIVER_NAME "%s: radio resume\n\n", __func__);
3456 if (radio) {
3457 mutex_lock(&radio->lock);
3458 users = radio->users;
3459 mutex_unlock(&radio->lock);
3460
3461 if (users) {
3462 retval = tavarua_setup_interrupts(radio,
3463 (radio->registers[RDCTRL] & 0x03));
3464 if (retval < 0) {
3465 printk(KERN_INFO DRIVER_NAME "Error in \
3466 tavarua_resume %d\n", retval);
3467 return -EIO;
3468 }
3469 }
3470 }
3471 return 0;
3472}
3473
3474/*==============================================================
3475FUNCTION: tavarua_set_audio_path
3476==============================================================*/
3477/**
3478 This function will configure the audio path to and from the
3479 FM core.
3480
3481 This interface is expected to be called from the multimedia
3482 driver's thread. This interface should only be called when
3483 the FM hardware is enabled. If the FM hardware is not
3484 currently enabled, this interface will return an error.
3485
3486 @param digital_on: Digital audio from the FM core should be enabled/disbled.
3487 @param analog_on: Analog audio from the FM core should be enabled/disbled.
3488
3489 @return On success 0 is returned, else error code.
3490*/
3491int tavarua_set_audio_path(int digital_on, int analog_on)
3492{
3493 struct tavarua_device *radio = private_data;
3494 int rx_on = radio->registers[RDCTRL] & FM_RECV;
3495 if (!radio)
3496 return -ENOMEM;
3497 /* RX */
3498 FMDBG("%s: digital: %d analog: %d\n", __func__, digital_on, analog_on);
3499 SET_REG_FIELD(radio->registers[AUDIOCTRL],
3500 ((rx_on && analog_on) ? 1 : 0),
3501 AUDIORX_ANALOG_OFFSET,
3502 AUDIORX_ANALOG_MASK);
3503 SET_REG_FIELD(radio->registers[AUDIOCTRL],
3504 ((rx_on && digital_on) ? 1 : 0),
3505 AUDIORX_DIGITAL_OFFSET,
3506 AUDIORX_DIGITAL_MASK);
3507 SET_REG_FIELD(radio->registers[AUDIOCTRL],
3508 (rx_on ? 0 : 1),
3509 AUDIOTX_OFFSET,
3510 AUDIOTX_MASK);
3511 /*
3512
3513 I2S Master/Slave configuration:
3514 Setting the FM SoC as I2S Master/Slave
3515 'false' - FM SoC is I2S Slave
3516 'true' - FM SoC is I2S Master
3517
3518 We get this infomation from the respective target's board file :
3519 MSM7x30 - FM SoC is I2S Slave
3520 MSM8x60 - FM SoC is I2S Slave
3521 MSM7x27A - FM SoC is I2S Master
3522 */
3523
3524 if (!radio->pdata->is_fm_soc_i2s_master) {
3525 FMDBG("FM SoC is I2S Slave\n");
3526 SET_REG_FIELD(radio->registers[AUDIOCTRL],
3527 (0),
3528 I2SCTRL_OFFSET,
3529 I2SCTRL_MASK);
3530 } else {
3531 FMDBG("FM SoC is I2S Master\n");
3532 SET_REG_FIELD(radio->registers[AUDIOCTRL],
3533 (1),
3534 I2SCTRL_OFFSET,
3535 I2SCTRL_MASK);
3536 }
3537 FMDBG("%s: %x\n", __func__, radio->registers[AUDIOCTRL]);
3538 return tavarua_write_register(radio, AUDIOCTRL,
3539 radio->registers[AUDIOCTRL]);
3540
3541}
3542
3543/*==============================================================
3544FUNCTION: tavarua_probe
3545==============================================================*/
3546/**
3547 Once called this functions initiates, allocates resources and registers video
3548 tuner device with the v4l2 framework.
3549
3550 NOTE:
3551 probe() should verify that the specified device hardware
3552 actually exists; sometimes platform setup code can't be sure. The probing
3553 can use device resources, including clocks, and device platform_data.
3554
3555 @param pdev: platform device to be probed.
3556
3557 @return On success 0 is returned, else error code.
3558 -ENOMEM in low memory cases
3559*/
3560static int __init tavarua_probe(struct platform_device *pdev)
3561{
3562
3563 struct marimba_fm_platform_data *tavarua_pdata;
3564 struct tavarua_device *radio;
3565 int retval;
3566 int i;
3567 FMDBG("%s: probe called\n", __func__);
3568 /* private data allocation */
3569 radio = kzalloc(sizeof(struct tavarua_device), GFP_KERNEL);
3570 if (!radio) {
3571 retval = -ENOMEM;
3572 goto err_initial;
3573 }
3574
3575 radio->marimba = platform_get_drvdata(pdev);
3576 tavarua_pdata = pdev->dev.platform_data;
3577 radio->pdata = tavarua_pdata;
3578 radio->dev = &pdev->dev;
3579 platform_set_drvdata(pdev, radio);
3580
3581 /* video device allocation */
3582 radio->videodev = video_device_alloc();
3583 if (!radio->videodev)
3584 goto err_radio;
3585
3586 /* initial configuration */
3587 memcpy(radio->videodev, &tavarua_viddev_template,
3588 sizeof(tavarua_viddev_template));
3589
3590 /*allocate internal buffers for decoded rds and event buffer*/
3591 for (i = 0; i < TAVARUA_BUF_MAX; i++) {
3592 int kfifo_alloc_rc=0;
3593 spin_lock_init(&radio->buf_lock[i]);
3594
3595 if (i == TAVARUA_BUF_RAW_RDS)
3596 kfifo_alloc_rc = kfifo_alloc(&radio->data_buf[i],
3597 rds_buf*3, GFP_KERNEL);
3598 else
3599 kfifo_alloc_rc = kfifo_alloc(&radio->data_buf[i],
3600 STD_BUF_SIZE, GFP_KERNEL);
3601
3602 if (kfifo_alloc_rc!=0) {
3603 printk(KERN_ERR "%s: failed allocating buffers %d\n",
3604 __func__, kfifo_alloc_rc);
3605 goto err_bufs;
3606 }
3607 }
3608 /* init xfr status */
3609 radio->users = 0;
3610 radio->xfr_in_progress = 0;
3611 radio->xfr_bytes_left = 0;
3612 for (i = 0; i < TAVARUA_XFR_MAX; i++)
3613 radio->pending_xfrs[i] = 0;
3614
3615 /* init transmit data */
3616 radio->tx_mode = TAVARUA_TX_RT;
3617 /* Init RT and PS Tx datas*/
3618 radio->pty = 0;
3619 radio->pi = 0;
3620 radio->ps_repeatcount = 0;
3621 /* init search params */
3622 radio->srch_params.srch_pty = 0;
3623 radio->srch_params.srch_pi = 0;
3624 radio->srch_params.preset_num = 0;
3625 radio->srch_params.get_list = 0;
3626 /* radio initializes to low power mode */
3627 radio->lp_mode = 1;
3628 radio->handle_irq = 1;
3629 /* init lock */
3630 mutex_init(&radio->lock);
3631 /* init completion flags */
3632 init_completion(&radio->sync_xfr_start);
3633 init_completion(&radio->sync_req_done);
3634 radio->tune_req = 0;
3635 /* initialize wait queue for event read */
3636 init_waitqueue_head(&radio->event_queue);
3637 /* initialize wait queue for raw rds read */
3638 init_waitqueue_head(&radio->read_queue);
3639
3640 video_set_drvdata(radio->videodev, radio);
3641 /*Start the worker thread for event handling and register read_int_stat
3642 as worker function*/
3643 INIT_DELAYED_WORK(&radio->work, read_int_stat);
3644
3645 /* register video device */
3646 if (video_register_device(radio->videodev, VFL_TYPE_RADIO, radio_nr)) {
3647 printk(KERN_WARNING DRIVER_NAME
3648 ": Could not register video device\n");
3649 goto err_all;
3650 }
3651 private_data = radio;
3652 return 0;
3653
3654err_all:
3655 video_device_release(radio->videodev);
3656err_bufs:
3657 for (; i > -1; i--)
3658 kfifo_free(&radio->data_buf[i]);
3659err_radio:
3660 kfree(radio);
3661err_initial:
3662 return retval;
3663}
3664
3665/*==============================================================
3666FUNCTION: tavarua_remove
3667==============================================================*/
3668/**
3669 Removes the device.
3670
3671 @param pdev: platform device to be removed.
3672
3673 @return On success 0 is returned, else error code.
3674*/
3675static int __devexit tavarua_remove(struct platform_device *pdev)
3676{
3677 int i;
3678 struct tavarua_device *radio = platform_get_drvdata(pdev);
3679
3680 /* disable irq */
3681 tavarua_disable_irq(radio);
3682
3683 video_unregister_device(radio->videodev);
3684
3685 /* free internal buffers */
3686 for (i = 0; i < TAVARUA_BUF_MAX; i++)
3687 kfifo_free(&radio->data_buf[i]);
3688
3689 /* free state struct */
3690 kfree(radio);
3691
3692 platform_set_drvdata(pdev, NULL);
3693
3694 return 0;
3695}
3696
3697/*
3698 Platform drivers follow the standard driver model convention, where
3699 discovery/enumeration is handled outside the drivers, and drivers
3700 provide probe() and remove() methods. They support power management
3701 and shutdown notifications using the standard conventions.
3702*/
3703static struct platform_driver tavarua_driver = {
3704 .driver = {
3705 .owner = THIS_MODULE,
3706 .name = "marimba_fm",
3707 },
3708 .remove = __devexit_p(tavarua_remove),
3709 .suspend = tavarua_suspend,
3710 .resume = tavarua_resume,
3711}; /* platform device we're adding */
3712
3713
3714/*************************************************************************
3715 * Module Interface
3716 ************************************************************************/
3717
3718/*==============================================================
3719FUNCTION: radio_module_init
3720==============================================================*/
3721/**
3722 Module entry - add a platform-level device.
3723
3724 @return Returns zero if the driver registered and bound to a device, else
3725 returns a negative error code when the driver not registered.
3726*/
3727static int __init radio_module_init(void)
3728{
3729 printk(KERN_INFO DRIVER_DESC ", Version " DRIVER_VERSION "\n");
3730 return platform_driver_probe(&tavarua_driver, tavarua_probe);
3731}
3732
3733/*==============================================================
3734FUNCTION: radio_module_exit
3735==============================================================*/
3736/**
3737 Module exit - removes a platform-level device.
3738
3739 NOTE:
3740 Note that this function will also release all memory- and port-based
3741 resources owned by the device (dev->resource).
3742
3743 @return none.
3744*/
3745static void __exit radio_module_exit(void)
3746{
3747 platform_driver_unregister(&tavarua_driver);
3748}
3749
3750MODULE_LICENSE("GPL v2");
3751MODULE_AUTHOR(DRIVER_AUTHOR);
3752MODULE_DESCRIPTION(DRIVER_DESC);
3753MODULE_VERSION(DRIVER_VERSION);
3754
3755module_init(radio_module_init);
3756module_exit(radio_module_exit);
3757