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