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