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