SI4703API.c
上传用户:ledjyj
上传日期:2014-08-27
资源大小:2639k
文件大小:32k
源码类别:

驱动编程

开发平台:

Unix_Linux

  1. /* SI4703 Radio Card API
  2.  * *Author: Beck.He@quantcn.com
  3.  * 2007.9.1
  4.  * This program is free software; you can redistribute it and/or modify
  5.  * it under the terms of the GNU General Public License version 2 as
  6.  * published by the Free Software Foundation.
  7.  */
  8. //#if defined (QCI_L1_UPGRADE_SILICON_FM_MODULE) 
  9. /***************************************************************************
  10.  * Include Files
  11.  ***************************************************************************/
  12. #include <linux/sched.h>
  13. #include <linux/wait.h>
  14. #include <linux/delay.h>
  15. #include <asm/hardware.h>
  16. #include <asm/arch/pxa-regs.h>
  17. #include <asm/irq.h>
  18. #include <asm/arch/gpio.h>
  19. #include "SI4703API.h"
  20. /***************************************************************************
  21.  * Macros
  22.  ***************************************************************************/
  23. /***************************************************************************
  24.  * Variables
  25.  ***************************************************************************/
  26. const u16 FM_SI47XX_DEVICE_ADDR=0x20;
  27. const u16 FM_SI47XX_WRITE=0x00;
  28. const u16 FM_SI47XX_READ=0x01;
  29. /*** For writing ***/
  30. /*** REG 0x02 POWERCFG ***/
  31. const u16 SI_DMUTE =0x4000;
  32. const u16 SI_MUTE  =0x0000;
  33. const u16 SI_MONO =0x2000;
  34. /* Quanta modify by Brian 20051111-00001100-02083-G80 */
  35. const u16 SI_SKMODE=0x0400;
  36. /* End of modification by Brian 20051111-00001100-02083-G80 */ 
  37. const u16 SI_SEEKUP=0x0200;
  38. const u16 SI_SEEKDOWN=0x0000;
  39. const u16 SI_SEEK =0x0100;
  40. const u16 SI_DISABLE=0x0040;
  41. const u16 SI_ENABLE=0x0001;
  42. const u16 SI_DSOFTMUTE=0x8000;
  43. /*** REG 0x03 CHANNEL ***/
  44. const u16 SI_TUNE=0x8000;
  45. /*** REG 0x04 SYSCONFIG1 ***/
  46. const u16 SI_RDSIEN=0x8000;
  47. const u16 SI_STCIEN=0x4000;
  48. const u16 SI_RDS=0x1000;
  49. /* Quanta modify by Brian 20051111-00001100-02083-G80 */
  50. const u16 SI_DE_50US=0x0800; // 50us for Europe and Australia
  51. const u16 SI_GPIO3_INTERRUPT=0x0010;
  52. /* End of modification by Brian 20051111-00001100-02083-G80 */ 
  53. const u16 SI_AGCD_DIS=0x0400;
  54. const u16 SI_GPIO2_INTERRUPT=0x0004;
  55. /* Quanta modify by Brian 20051111-00001100-02083-G80 */
  56. const u16 SI_GPIO2_HIGH=0x000B;
  57. const u16 SI_GPIO2_LOW =0x0008;
  58. /* End of modification by Brian 20051111-00001100-02083-G80 */ 
  59. /*** REG 0x05 SYSCONFIG2 ***/
  60. const u16 SI_RECOMMENDED_SEEKTH=0x0a00;//0x1900;
  61. /* Quanta modify by Beck.He 20051129-00001100-02083-G80 */
  62. const u16 SI_BAND =0x00C0; 
  63. /* End of modification by Beck.He 20051129-00001100-02083-G80 */
  64. const u16 SI_BAND_US =0x0000; //87.5-108MHz
  65. /* Quanta modify by Brian 20051111-00001100-02083-G80 */
  66. const u16 SI_WIDEBAND_JAPAN=0x0040;//76-108MHZ
  67. /* End of modification by Brian 20051111-00001100-02083-G80 */ 
  68. const u16 SI_BAND_JAPAN =0x0080; //76-90MHz
  69. const u16 SI_SPACE =0x0030;
  70. const u16 SI_SPACE_200KHZ=0x0000;
  71. const u16 SI_SPACE_100KHZ=0x0010;
  72. const u16 SI_SPACE_50KHZ =0x0020;
  73. const u16 SI_VOLUME =0x000F;
  74. /*** For reading ***/
  75. /*** REG 0x0A STATUSRSSI ***/
  76. const u16 SI_RDSR=0x8000;
  77. const u16 SI_STC=0x4000;
  78. const u16 SI_SF=0x2000;
  79. /* Quanta modify by Brian 20051111-00001100-02083-G80 */
  80. const u16 SI_AFCRL=0x1000;
  81. const u16 SI_RDSE=0x0E00;
  82. /* End of modification by Brian 20051111-00001100-02083-G80 */ 
  83. const u16 SI_ST=0x0100;
  84. const u16 SI_RSSI=0x00FF;
  85. /*** REG 0x0B READCHAN ***/
  86. const u16 SI_READCHAN=0x03FF;
  87. /*** REG 0x00 DEVICEID ***/
  88. const u16 SI_PN=0xF000;
  89. const u16 SI_MFGID=0x0FFF;
  90. /*** REG 0x01 CHIPID ***/
  91. const u16 REV=0xFC00;
  92. const u16 DEV=0x0200;
  93. const u16 FIRMWARE=0x01FF;
  94. /*** User defined Variables ***/
  95. static u16 AUTOSEEK=FALSE;
  96. static u8 WriteRegArray[9];
  97. static u8 ReadRegArray[25];
  98. const u16 SI_BottomOfChannel=0x0000;
  99. u8 VolumeCtrl;
  100. const u8 NORVOL=0x08;
  101. const u8 MAXVOL=0x0F;
  102. const u8 MINVOL=0x00;
  103. static u16 SeekedChannels[40];
  104. static u8 MaxSeekedChannels=40;
  105. //static Boolean AUTOSEEK=FALSE;
  106. static u8 MaxTuneIndex=0;
  107. static u8 TuneIndex=0;
  108. static u16 BandSelect;
  109. static u16 SpacingSelect;
  110. const u8 SEEKTH_TO_VALUE_LIST[]=
  111. {
  112. 0x19, 0x1A, 0x1B, 0x1C, 
  113. 0x1D, 0x1E, 0x1F, 0x20
  114. };
  115. /***************************************************************************
  116.  * Declarations & Prototypes
  117.  ***************************************************************************/
  118. #define si4703_debug 1
  119. static DECLARE_WAIT_QUEUE_HEAD(fm_wq);
  120. /***************************************************************************
  121.  * Local Functions
  122.  ***************************************************************************/
  123. /***************************************************************************
  124.  * Global Functions
  125.  ***************************************************************************/
  126. /*******************************************************************************
  127.  * Function:      FM_SI47XX_WriteReg
  128.  *
  129.  * Parameters:    RegAddr, representing address of register of FM_SI47XX from 02h to 05h
  130.  * 
  131.  *    u16 InputData, content of register for writing in FM_SI47XX
  132.  *
  133.  * Returns:       none
  134.  *
  135.  * Description:   Routine to write content into registers in FM_SI47XX
  136.  ******************************************************************************/
  137. void
  138. FM_SI47XX_WriteReg(
  139. WRITE_REG_ADDR RegAddr,
  140. u16 InputData
  141. )
  142. {
  143. u8 NumOfBytesToWrite;
  144.    
  145. NumOfBytesToWrite=RegAddr*2;
  146. WriteRegArray[RegAddr*2-1]=(InputData & 0xFF00)>>8;
  147. WriteRegArray[RegAddr*2]=InputData & 0x00FF;
  148.             SI4703_I2C_Write(&WriteRegArray[1],NumOfBytesToWrite);
  149. }
  150. /*******************************************************************************
  151.  * Function:      FM_SI47XX_ReadReg
  152.  *
  153.  * Parameters:    RegAddr, representing address of register of FM_SI47XX from 00h to 0Ah
  154.  *
  155.  * Returns:       none
  156.  *
  157.  * Description:  Routine to read content into registers in FM_SI47XX
  158.  ******************************************************************************/
  159. u16
  160. FM_SI47XX_ReadReg(
  161. READ_REG_ADDR RegAddr 
  162. )
  163. {
  164. u8 NumOfBytesToRead;
  165. NumOfBytesToRead=RegAddr*2;   SI4703_I2C_Read(&ReadRegArray[1],NumOfBytesToRead);
  166. return ((ReadRegArray[NumOfBytesToRead-1]<<8) | ReadRegArray[NumOfBytesToRead]);
  167. }
  168. /*******************************************************************************
  169.  * Function:      ReadSTC
  170.  *
  171.  * Parameters:    none
  172.  *    
  173.  * Returns:       u8
  174.  *
  175.  * Description:  Routine to return STC bit in FM_SI47XX
  176.  ******************************************************************************/
  177. u8
  178. ReadSTC(
  179. void
  180. )
  181. {
  182. if(FM_SI47XX_ReadReg(R0Ah) & SI_STC)
  183. return 1;
  184. else
  185. return 0;
  186. }
  187. /*******************************************************************************
  188.  * Function:      ReadSF
  189.  *
  190.  * Parameters:    none
  191.  *    
  192.  * Returns:       u8
  193.  *
  194.  * Description:  Routine to return SF bit in FM_SI47XX
  195.  ******************************************************************************/
  196. u8
  197. ReadSF(
  198. void
  199. )
  200. {
  201. if(FM_SI47XX_ReadReg(R0Ah) & SI_SF)
  202. return 1;
  203. else
  204. return 0;
  205. }
  206. /*******************************************************************************
  207.  * Function:      ReadST
  208.  *
  209.  * Parameters:    none
  210.  *    
  211.  * Returns:       u8
  212.  *
  213.  * Description:  Routine to return ST(stereo) bit in FM_SI47XX/01
  214.  ******************************************************************************/
  215. u8 
  216. ReadST(
  217. void
  218. )
  219. {
  220. if(FM_SI47XX_ReadReg(R0Ah) & SI_ST){
  221. return 1;
  222. }
  223. else{
  224. return 0;
  225. }
  226. }
  227. /*******************************************************************************
  228.  * Function:      ReadGpio2
  229.  *
  230.  * Parameters:    none
  231.  *    
  232.  * Returns:       u8
  233.  *
  234.  * Description:  Routine to return status of interrupt pin GPIO2 in FM_SI47XX
  235.  ******************************************************************************/
  236. u8
  237. ReadGpio2(
  238. void
  239. )
  240. {
  241. return 0;
  242. }
  243. /*******************************************************************************
  244.  * Function:      WaitGpio2
  245.  *
  246.  * Parameters:    none
  247.  *    
  248.  * Returns:       none
  249.  *
  250.  * Description:  Routine to wait interrupt pin GPIO2 on FM_SI47XX until its value is 0
  251.  ******************************************************************************/
  252. void 
  253. WaitGpio2(
  254. void
  255. )
  256. {
  257. while(ReadGpio2() !=0);
  258. return;
  259. }
  260. /*******************************************************************************
  261.  * Function:      CfgFM_SI47XXRstAsOutput
  262.  *
  263.  * Parameters:    none
  264.  *    
  265.  * Returns:       none
  266.  *
  267.  * Description:  Routine to configure GPIO53 on AD6527
  268.  ******************************************************************************/
  269. void
  270. CfgFM_SI47XXRstAsOutput(
  271. void
  272. )
  273. {
  274. }
  275. /*******************************************************************************
  276.  * Function:      WaitSTC
  277.  *
  278.  * Parameters:    none
  279.  *    
  280.  * Returns:       none
  281.  *
  282.  * Description:  Routine to wait until STC bit =1 on FM_SI47XX/01
  283.  ******************************************************************************/
  284. void
  285. WaitSTC(
  286. void
  287. )
  288. {
  289. return;
  290. }
  291. /*******************************************************************************
  292.  * Function:      ReadRDS
  293.  *
  294.  * Parameters:    none
  295.  *    
  296.  * Returns:       none
  297.  *
  298.  * Description:  Routine to read RDS bit on FM_SI47XX/01
  299.  ******************************************************************************/
  300. u8
  301. ReadRDS(
  302. void
  303. )
  304. {
  305. if(FM_SI47XX_ReadReg(R04h) & SI_RDS){
  306. return 1;
  307. }
  308. else{
  309. return 0;
  310. }
  311. }
  312. /*******************************************************************************
  313.  * Function:      ReadRDSR
  314.  *
  315.  * Parameters:    none
  316.  *    
  317.  * Returns:       none
  318.  *
  319.  * Description:  Routine to read RDSR bit on FM_SI47XX/01
  320.  ******************************************************************************/
  321. u8
  322. ReadRDSR(
  323. void
  324. )
  325. {
  326. if(FM_SI47XX_ReadReg(R0Ah) & SI_RDSR){
  327. return 1;
  328. }
  329. else{
  330. return 0;
  331. }
  332. }
  333. /*******************************************************************************
  334.  * Function:      ReadRDSE
  335.  *
  336.  * Parameters:    none
  337.  *    
  338.  * Returns:       none
  339.  *
  340.  * Description:  Routine to read RDSE bits on FM_SI47XX/01
  341.  ******************************************************************************/
  342. u8
  343. ReadRDSE(
  344. void
  345. )
  346. {
  347. return ( (FM_SI47XX_ReadReg(R0Ah) & SI_RDSE)>>9 );
  348. }
  349. /*******************************************************************************
  350.  * Function:      ReadRDS_BLOCK
  351.  *
  352.  * Parameters:    none
  353.  *    
  354.  * Returns:       none
  355.  *
  356.  * Description:  Routine to read RDSA, RDSB, RDSC and RDSD on FM_SI47XX/01
  357.  ******************************************************************************/
  358. u16
  359. ReadRDS_BLOCK(
  360. RDS_STATUS RDS_ID
  361. )
  362. {
  363. switch(RDS_ID)
  364. {
  365. case RDSA:
  366. return FM_SI47XX_ReadReg(R0Ch);
  367. break;
  368. case RDSB:
  369. return FM_SI47XX_ReadReg(R0Dh);
  370. break;
  371. case RDSC:
  372. return FM_SI47XX_ReadReg(R0Eh);
  373. break;
  374. case RDSD:
  375. return FM_SI47XX_ReadReg(R0Fh);
  376. break;
  377. default:    
  378.   return 0;   
  379.   break;
  380. }                                                       
  381. }    
  382. /*******************************************************************************
  383.  * Function:      FM_SI47XX_ReadRSSI
  384.  *
  385.  * Parameters:    none
  386.  *    
  387.  * Returns:       none
  388.  *
  389.  * Description:  Routine to read RSSI bits on FM_SI47XX/01
  390.  ******************************************************************************/
  391. u8
  392. FM_SI47XX_ReadRSSI(
  393. void
  394. )
  395. {
  396. return ( (FM_SI47XX_ReadReg(R0Ah) & SI_RSSI) );
  397. }
  398. /*******************************************************************************
  399.  * Function:      FM_SI47XX_RST_LOW
  400.  *
  401.  * Parameters:    none
  402.  *    
  403.  * Returns:       none
  404.  *
  405.  * Description:  Routine to set GPIO53 on AD6527 as low voltage
  406.  ******************************************************************************/
  407. void
  408. FM_SI47XX_RST_LOW(
  409. void
  410. )
  411. {
  412. }
  413. /*******************************************************************************
  414.  * Function:      FM_SI47XX_RST_HIGH
  415.  *
  416.  * Parameters:    none
  417.  *    
  418.  * Returns:       none
  419.  *
  420.  * Description:  Routine to set GPIO53 on AD6527 as high voltage
  421.  ******************************************************************************/
  422. void
  423. FM_SI47XX_RST_HIGH(
  424. void
  425. )
  426. {
  427. }
  428. /*******************************************************************************
  429.  * Function:      FM_SI47XX_2Wire
  430.  *
  431.  * Parameters:    none
  432.  *    
  433.  * Returns:       none
  434.  *
  435.  * Description:  Routine to configure FM_SI47XX to operate in 2-wire mode
  436.  ******************************************************************************/
  437. void 
  438. FM_SI47XX_2Wire(
  439. void
  440. )
  441. {
  442. }
  443. /*******************************************************************************
  444.  * Function:      FM_SI47XX_Reset
  445.  *
  446.  * Parameters:    none
  447.  *    
  448.  * Returns:       none
  449.  *
  450.  * Description:  Routine to reset FM_SI47XX 
  451.  ******************************************************************************/
  452. void
  453. FM_SI47XX_Reset(
  454. void
  455. )
  456. {
  457. }
  458. /*******************************************************************************
  459.  * Function:      FM_SI47XX_Init
  460.  *
  461.  * Parameters:    none
  462.  *    
  463.  * Returns:       none
  464.  *
  465.  * Description:  Routine to initialize FM_SI47XX 
  466.  ******************************************************************************/
  467. /*** Initialization of FM_SI47XX module ***/
  468. void FM_SI47XX_Init(void)
  469. {
  470.     #ifdef si4703_debug
  471.     printk(KERN_ERR "API-si4703: Init,n");
  472.     #endif
  473.   #define TOUT_EN  1<<2
  474.    OSCC |= TOUT_EN;          //clk
  475.     /* pxa272 setting     pxa_gpio_mode(123 |GPIO_OUT | GPIO_DFLT_LOW);//reset
  476.     udelay(200);
  477.     pxa_gpio_mode(123 |GPIO_OUT | GPIO_DFLT_HIGH);
  478.     pxa_gpio_mode(122 | GPIO_IN); // irq setting
  479.     set_irq_type(IRQ_GPIO(122), IRQT_FALLING);*/
  480.     enable_gpio_fm_pins();
  481.     mhn_gpio_set_level(MFP_PIN_GPIO123,GPIO_LEVEL_LOW);//pull FM_RST high
  482.     msleep(200);
  483.     mhn_gpio_set_level(MFP_PIN_GPIO123,GPIO_LEVEL_HIGH);//pull FM_RST high
  484.     set_irq_type(IRQ_GPIO(MFP2GPIO(MFP_PIN_GPIO122)), IRQT_FALLING);
  485. WriteRegArray[0]=FM_SI47XX_DEVICE_ADDR | FM_SI47XX_WRITE;
  486. ReadRegArray[0] =FM_SI47XX_DEVICE_ADDR | FM_SI47XX_READ;
  487. VolumeCtrl=MAXVOL;
  488. BandSelect=SI_BAND_US;
  489. SpacingSelect=SI_SPACE_100KHZ;
  490. }
  491. /*******************************************************************************
  492.  * Function:      FM_SI47XX_PowerUp
  493.  *
  494.  * Parameters:    Boolean  bRDSEnable, enable RDS function
  495.  *    
  496.  * Returns:       none
  497.  *
  498.  * Description:  Routine to turn on FM_SI47XX 
  499.  ******************************************************************************/
  500. void FM_SI47XX_PowerUp()
  501. {
  502.     #ifdef si4703_debug
  503.     char buf[24];
  504.     int i;
  505.     printk(KERN_ERR "API-si4703: power up,n");
  506.     #endif
  507. FM_SI47XX_WriteReg(W02h,SI_DMUTE | SI_ENABLE | SI_DSOFTMUTE);
  508. FM_SI47XX_WriteReg(W03h,SI_BottomOfChannel);
  509. //FM_SI47XX_WriteReg(W04h,SI_RDSIEN | SI_STCIEN | SI_GPIO2_INTERRUPT);
  510.        
  511. FM_SI47XX_WriteReg(W04h,SI_RDSIEN | SI_STCIEN | SI_RDS | SI_GPIO2_INTERRUPT);
  512. FM_SI47XX_WriteReg(W05h,SI_RECOMMENDED_SEEKTH | BandSelect | SpacingSelect | VolumeCtrl);
  513.      si4703_fm_wait_timeout();
  514.      if( ReadSTC() !=1) 
  515.      printk(KERN_ERR "API-si4703: tune failn");
  516. FM_SI47XX_WriteReg(W03h,FM_SI47XX_ReadChannel());
  517.  
  518.     #ifdef si4703_debug
  519.     SI4703_I2C_Read( buf,  24);
  520.     for(i=0;i<24;i++)
  521.     printk("I2C: SI4703 register contents=%xn", buf[i]);
  522.     #endif
  523. }
  524. /* End of modification by Jacky.Sun 20051202-00000100-*****-G80 */
  525. /* Quanta modify by Brian 20051111-00001100-02083-G80 */
  526. /*******************************************************************************
  527.  * Function:      FM_SI47XX_OpenRDS
  528.  *
  529.  * Parameters:    none
  530.  *    
  531.  * Returns:       none
  532.  *
  533.  * Description:  Routine to turn on RDS function of SI4701
  534.  ******************************************************************************/
  535. void
  536. FM_SI47XX_OpenRDS(
  537. void
  538. )
  539. {
  540. FM_SI47XX_WriteReg(W04h,FM_SI47XX_ReadReg(R04h) | SI_RDS);
  541. }
  542. /*******************************************************************************
  543.  * Function:      FM_SI47XX_CloseRDS
  544.  *
  545.  * Parameters:    none
  546.  *    
  547.  * Returns:       none
  548.  *
  549.  * Description:  Routine to turn off RDS function of SI4701 
  550.  ******************************************************************************/
  551. void 
  552. FM_SI47XX_CloseRDS(
  553. void
  554. )
  555. {
  556. FM_SI47XX_WriteReg(W04h,FM_SI47XX_ReadReg(R04h) & 0xCC3F);
  557. }
  558. /* End of modification by Brian 20051111-00001100-02083-G80 */
  559. /*******************************************************************************
  560.  * Function:      FM_SI47XX_SetBand
  561.  *
  562.  * Parameters:    band- set 0 for changing band to USA,EUROPE
  563.  *
  564.  *    set 1 for changing band to JAPAN
  565.  *    
  566.  * Returns:       none
  567.  *
  568.  * Description:  Routine to set FM band
  569.  ******************************************************************************/
  570. void
  571. FM_SI47XX_SetBand(
  572. u8 band
  573. )
  574. {
  575. if(band==1)
  576. BandSelect=SI_BAND_US;
  577. else
  578. BandSelect=SI_BAND_JAPAN;
  579. FM_SI47XX_WriteReg(W05h,SI_RECOMMENDED_SEEKTH | BandSelect | SpacingSelect | VolumeCtrl);
  580. }
  581. /*******************************************************************************
  582.  * Function:      FM_SI47XX_SetSpacing
  583.  *
  584.  * Parameters:    spacing- set 0 for changing channel spacing to 200KHZ
  585.  *
  586.  *       set 1 for changing channel spacing to 100KHZ
  587.  *
  588.  *       set 2 for changing channel spacing to 50KHZ
  589.  *    
  590.  * Returns:       none
  591.  *
  592.  * Description:  Routine to set FM band
  593.  ******************************************************************************/
  594. void
  595. FM_SI47XX_SetSpacing(
  596. u8 spacing
  597. )
  598. {
  599. switch(spacing){
  600. case 0:
  601. SpacingSelect=SI_SPACE_200KHZ;
  602. break;
  603. case 1:
  604. SpacingSelect=SI_SPACE_100KHZ;
  605. break;
  606. case 2:
  607. SpacingSelect=SI_SPACE_50KHZ;
  608. break;
  609. default:
  610. break;
  611. }
  612. FM_SI47XX_WriteReg(W05h,SI_RECOMMENDED_SEEKTH | BandSelect | SpacingSelect | VolumeCtrl);
  613. }
  614. /* Quanta modify by Brian 20051111-00001100-02083-G80 */
  615. /*******************************************************************************
  616.  * Function:      FM_SI47XX_SetSeekDepth
  617.  *
  618.  * Parameters:    SeekDepth
  619.  *
  620.  *    set 1 for changing band to JAPAN
  621.  *    
  622.  * Returns:       none
  623.  *
  624.  * Description:  Routine to set seeking depth of FM channel
  625.  ******************************************************************************/
  626. void 
  627. FM_SI47XX_SetSeekDepth(
  628. u8 SeekDepth
  629. )
  630. {
  631. FM_SI47XX_WriteReg(W05h,(SeekDepth<<8) | BandSelect | SpacingSelect | VolumeCtrl);
  632. }
  633. /* End of modification by Brian 20051111-00001100-02083-G80 */ 
  634. /*******************************************************************************
  635.  * Function:      FM_SI47XX_PowerDown
  636.  *
  637.  * Parameters:    none
  638.  *    
  639.  * Returns:       none
  640.  *
  641.  * Description:  Routine to turn off FM_SI47XX 
  642.  ******************************************************************************/
  643. void
  644. FM_SI47XX_PowerDown(
  645. void
  646. )
  647. {
  648.     #ifdef si4703_debug
  649.     printk(KERN_ERR "API-si4703: power down,n");
  650.     #endif
  651.     /*** Set DISABLE bit=1, perform internal power-down sequence and set ENABLE bit=0 later by device itself ***/
  652. FM_SI47XX_WriteReg(W02h,SI_ENABLE | SI_DISABLE);
  653. }
  654. /*******************************************************************************
  655.  * Function:      FM_SI47XX_Tune
  656.  *
  657.  * Parameters:    Channel- channel on FM radio, its unit value is 100Khz such as
  658.  *
  659.  *    if we want to tune 101.5Mhz radio, we must set variable Channel
  660.  *
  661.  *    =1015
  662.  *    
  663.  * Returns:       none
  664.  *
  665.  * Description:  Routine to turn off FM_SI47XX 
  666.  ******************************************************************************/
  667. void 
  668. FM_SI47XX_Tune(
  669. u16 Freq
  670. )
  671. {
  672.     #ifdef si4703_debug
  673.     printk(KERN_ERR "API-si4703: tune ,n");
  674.     #endif
  675.     /* Write address 0x03 to set channel and TUNE bit */
  676. FM_SI47XX_WriteReg(W03h,FM_SI47XX_FreqToChan(Freq) | SI_TUNE);
  677.      si4703_fm_wait_timeout();
  678.     
  679.      if( ReadSTC() !=1) 
  680.      printk(KERN_ERR "API-si4703: tune failn");
  681. FM_SI47XX_WriteReg(W03h,FM_SI47XX_ReadChannel());
  682. }
  683. /*******************************************************************************
  684.  * Function:      FM_SI47XX_TuneNextChan
  685.  *
  686.  * Parameters:    none
  687.  *    
  688.  * Returns:       none
  689.  *
  690.  * Description:  Routine to tune next channel from current channel
  691.  ******************************************************************************/
  692. void
  693. FM_SI47XX_TuneNextChan(
  694. void
  695. )
  696. {
  697.     
  698.     /* Write address 0x03 to set channel and TUNE bit */
  699. FM_SI47XX_WriteReg(W03h, SI_TUNE | ((FM_SI47XX_ReadChannel()+0x0001) &0x03FF));
  700.      si4703_fm_wait_timeout();
  701.      if( ReadSTC() !=1) 
  702.      printk(KERN_ERR "API-si4703: tune failn");
  703. FM_SI47XX_WriteReg(W03h,FM_SI47XX_ReadChannel());
  704. }
  705. /*******************************************************************************
  706.  * Function:      FM_SI47XX_TunePrevChan
  707.  *
  708.  * Parameters:    none
  709.  *    
  710.  * Returns:       none
  711.  *
  712.  * Description:  Routine to tune previous channel from current channel
  713.  ******************************************************************************/
  714. void
  715. FM_SI47XX_TunePrevChan(
  716. void
  717. )
  718. {
  719. /* Write address 0x03 to set channel and TUNE bit */
  720. FM_SI47XX_WriteReg(W03h, SI_TUNE | ((FM_SI47XX_ReadChannel()-0x0001) &0x03FF));
  721.      si4703_fm_wait_timeout();
  722.      if( ReadSTC() !=1) 
  723.      printk(KERN_ERR "API-si4703: tune failn");
  724. FM_SI47XX_WriteReg(W03h,FM_SI47XX_ReadChannel());
  725. }
  726. /*******************************************************************************
  727.  * Function:      FM_SI47XX_Seek
  728.  *
  729.  * Parameters:    SeekDirection, determine the direction of seeking on FM radio module
  730.  *    
  731.  * Returns:       SEEK_STATUS
  732.  *
  733.  * Description:  Routine to seek available channel on FM_SI47XX
  734.  ******************************************************************************/
  735. void
  736. FM_SI47XX_Seek(
  737. u16 SeekDirection, u16 *channel, u16 *scanok
  738. )
  739. {
  740.     #ifdef si4703_debug
  741.     printk(KERN_ERR "API-si4703: seek,n");
  742.     #endif
  743.     /*** Write address 0x02 to set SEEK and SEEKUP bit ***/
  744. if(SeekDirection==SEEKUP)
  745. FM_SI47XX_WriteReg(W02h,SI_DMUTE | SI_SEEK | SI_SEEKUP | SI_ENABLE | SI_DSOFTMUTE);
  746. else
  747. FM_SI47XX_WriteReg(W02h,SI_DMUTE | SI_SEEK | SI_SEEKDOWN | SI_ENABLE | SI_DSOFTMUTE);
  748.      si4703_fm_wait_timeout();
  749.      if( ReadSTC() !=1) 
  750.      printk(KERN_ERR "API-si4703: STC not set when seekingn");
  751. /*** Read SF status after seeking at address 0x0A ***/
  752. if(ReadSF()==1){
  753. *scanok = FALSE;
  754.         #ifdef si4703_debug
  755.         printk(KERN_ERR "API-si4703: seek fail,n");
  756.         #endif
  757. }
  758. else{
  759. /*** Clear STC and SF bit by setting SEEK bit to low ***/
  760. *scanok = TRUE;
  761.         #ifdef si4703_debug
  762.         printk(KERN_ERR "API-si4703: seek success,n");
  763.         #endif
  764. }
  765.     *channel = FM_SI47XX_ReadChannel();
  766. FM_SI47XX_WriteReg(W02h,SI_DMUTE | SI_ENABLE | SI_DSOFTMUTE);
  767. }
  768. /*******************************************************************************
  769.  * Function:      FM_SI47XX_SeekUp
  770.  *
  771.  * Parameters:    none
  772.  *    
  773.  * Returns:       SEEK_STATUS
  774.  *
  775.  * Description:  Routine to seek up available channel on FM_SI47XX
  776.  ******************************************************************************/
  777. SEEK_STATUS
  778. FM_SI47XX_SeekUp(
  779. void
  780. )
  781. {
  782.     return 0;
  783.     //return FM_SI47XX_Seek(SEEKUP);
  784. }
  785. /*******************************************************************************
  786.  * Function:      FM_SI47XX_SeekDown
  787.  *
  788.  * Parameters:    none
  789.  *    
  790.  * Returns:       SEEK_STATUS
  791.  *
  792.  * Description:  Routine to seek down available channel on FM_SI47XX
  793.  ******************************************************************************/
  794. SEEK_STATUS
  795. FM_SI47XX_SeekDown(
  796. void
  797. )
  798. {
  799.     return 0;
  800.     
  801.     //return FM_SI47XX_Seek(SEEKDOWN);
  802. }
  803. /*******************************************************************************
  804.  * Function:      FM_SI47XX_AutoSeek
  805.  *
  806.  * Parameters:    none
  807.  *    
  808.  * Returns:       u8
  809.  *
  810.  * Description:  Routine to seek all channels on full band automatically and return 
  811.  *
  812.  *   the number of channels seeked before
  813.  ******************************************************************************/
  814. u8
  815. FM_SI47XX_AutoSeek(
  816. void
  817. {
  818. u8 ChannelIndex=0;
  819. u16 DoneSeeking=FALSE;
  820. FM_SI47XX_EraseAllSeekedChannels();
  821. /*** Seek through all FM band automatically ***/
  822. while((DoneSeeking !=TRUE)){
  823. /* DoneSeeking if SF=1 */
  824. if(FM_SI47XX_SeekUp()==SEEKFAILURE) {
  825. DoneSeeking=TRUE;
  826. }
  827. else if( (ChannelIndex !=0) && (SeekedChannels[ChannelIndex-1]>FM_SI47XX_ReadChannel()) ){
  828. /* at least one channel in SeekedChannels list and current seeked channel is lower than previous seeked channel */
  829. DoneSeeking=TRUE;
  830. }
  831. else{
  832. /* Store channel and keep seeking */
  833. SeekedChannels[ChannelIndex]=FM_SI47XX_ReadChannel();
  834. FM_SI47XX_WriteReg(W03h,SeekedChannels[ChannelIndex]);
  835. ChannelIndex++;
  836. if(ChannelIndex==MaxSeekedChannels)
  837. DoneSeeking=TRUE;
  838. }
  839. }
  840. if(ChannelIndex>0){
  841. AUTOSEEK=TRUE;
  842. TuneIndex=0;
  843. MaxTuneIndex=ChannelIndex;
  844. /** Set default frequency after seeking automatically **/
  845. FM_SI47XX_Tune(FM_SI47XX_ChanToFreq(SeekedChannels[0]));
  846. }
  847. return ChannelIndex; /* Return NumOfChannels seeked by AutoSeek function */
  848. }
  849. /*******************************************************************************
  850.  * Function:      FM_SI47XX_TuneUp
  851.  *
  852.  * Parameters:    none
  853.  *    
  854.  * Returns:       none
  855.  *
  856.  * Description:  Routine to tune next seeked channel after seeking automatically
  857.  ******************************************************************************/
  858. void 
  859. FM_SI47XX_TuneUp(
  860. void
  861. )
  862. {
  863. if(AUTOSEEK == TRUE){
  864. if(TuneIndex==(MaxTuneIndex-1))
  865. TuneIndex=0;
  866. else
  867. TuneIndex++;
  868. FM_SI47XX_Tune(FM_SI47XX_ChanToFreq(SeekedChannels[TuneIndex]));
  869. }
  870. }
  871. /*******************************************************************************
  872.  * Function:      FM_SI47XX_TuneDown
  873.  *
  874.  * Parameters:    none
  875.  *    
  876.  * Returns:       none
  877.  *
  878.  * Description:  Routine to tune previous seeked channel after seeking automatically
  879.  ******************************************************************************/
  880. void 
  881. FM_SI47XX_TuneDown(
  882. void
  883. )
  884. {
  885. if(AUTOSEEK == TRUE){
  886. if(TuneIndex==0)
  887. TuneIndex=MaxTuneIndex-1;
  888. else
  889. TuneIndex--;
  890. FM_SI47XX_Tune(FM_SI47XX_ChanToFreq(SeekedChannels[TuneIndex]));
  891. }
  892. }
  893. /*******************************************************************************
  894.  * Function:      FM_SI47XX_EraseAllSeekedChannels
  895.  *
  896.  * Parameters:    none
  897.  *    
  898.  * Returns:       none
  899.  *
  900.  * Description:  Routine to erase all seeked channels after seeking automatically
  901.  ******************************************************************************/
  902. void 
  903. FM_SI47XX_EraseAllSeekedChannels(
  904. void
  905. )
  906. {
  907. u8 ChannelIndex;
  908. for(ChannelIndex=0;ChannelIndex<MaxSeekedChannels;ChannelIndex++)
  909. SeekedChannels[ChannelIndex]=0x0000;
  910. AUTOSEEK=FALSE;
  911. MaxTuneIndex=0;
  912. TuneIndex=0;
  913. /*** Tune to the bottom of FM band ***/
  914. FM_SI47XX_Tune(FM_SI47XX_ChanToFreq(SI_BottomOfChannel));
  915. }
  916. /*******************************************************************************
  917.  * Function:      FM_SI47XX_ReadChannel
  918.  *
  919.  * Parameters:    none
  920.  *    
  921.  * Returns:       u16
  922.  *
  923.  * Description:  Routine to return current available channel on FM_SI47XX
  924.  ******************************************************************************/
  925. u16
  926. FM_SI47XX_ReadChannel(
  927. void
  928. )
  929. {
  930. return FM_SI47XX_ReadReg(R0Bh);
  931. }
  932. /*******************************************************************************
  933.  * Function:      FM_SI47XX_ChanToFreq
  934.  *
  935.  * Parameters:    Channel- channel on FM radio, its  value starts at 0x0000
  936.  *
  937.  * Returns:       u16
  938.  *
  939.  * Description:  Routine to translate channel to frequency value
  940.  ******************************************************************************/
  941. u16
  942. FM_SI47XX_ChanToFreq(
  943. u16 Channel
  944. )
  945. {
  946. u16 Info;
  947. u16 BottomOfFreq;
  948. Info=WriteRegArray[W05h*2];
  949. /* 100KHZ as one unit */
  950.  /* Quanta modify by Beck.He 20051129-00001100-02083-G80 */
  951. if((Info & SI_BAND)==SI_BAND_US)
  952. {
  953. BottomOfFreq=875;         
  954.         }
  955. else
  956. {
  957. BottomOfFreq=760;  
  958. }
  959.  /* End of modification by Beck.He 20051129-00001100-02083-G80 */
  960. if((Info & SI_SPACE)==SI_SPACE_200KHZ){
  961. return (BottomOfFreq + (Channel <<1 ) );
  962. }
  963. else if((Info & SI_SPACE)==SI_SPACE_100KHZ){
  964. return (BottomOfFreq + Channel);
  965. }
  966. else{
  967. return (BottomOfFreq + ( Channel >>1 ) );
  968. }
  969. }
  970. /*******************************************************************************
  971.  * Function:      FM_SI47XX_FreqToChan
  972.  *
  973.  * Parameters:    Frequency- operating frequency of FM radio
  974.  *
  975.  * Returns:       u16
  976.  *
  977.  * Description:  Routine to translate frequency to channel value
  978.  ******************************************************************************/
  979. u16 
  980. FM_SI47XX_FreqToChan(
  981. u16 Frequency
  982. )
  983. {
  984. u16 Info;
  985. u16 BottomOfFreq;
  986. Info=WriteRegArray[W05h*2];
  987.  
  988.    /* Quanta modify by Beck.He 20051129-00001100-02083-G80 */      
  989.    if((Info & SI_BAND)==SI_BAND_US)                              
  990.  {                                                             
  991. BottomOfFreq=875;                                            
  992.  }                                                             
  993. else                                                          
  994.  {                                                             
  995. BottomOfFreq=760;                                           
  996.    }                                                              
  997.    /* End of modification by Beck.He 20051129-00001100-02083-G80 */
  998.     
  999. if((Info & SI_SPACE)==SI_SPACE_200KHZ){
  1000. return ((Frequency - BottomOfFreq) >>1); 
  1001. }
  1002. else if((Info & SI_SPACE)==SI_SPACE_100KHZ){
  1003. return (Frequency - BottomOfFreq) ; 
  1004. }
  1005. else{
  1006. return ((Frequency - BottomOfFreq) <<1) ; 
  1007. }
  1008. }
  1009. /*******************************************************************************
  1010.  * Function:      FM_SI47XX_Volume
  1011.  *
  1012.  * Parameters:    Direction- determine to increase volume(TURNUP) or to decrease volume(TURNDOWN)
  1013.  *    
  1014.  * Returns:       none
  1015.  *
  1016.  * Description:  Routine to control volume of FM_SI47XX
  1017.  ******************************************************************************/
  1018. void 
  1019. FM_SI47XX_Volume(
  1020. u8 vol
  1021. )
  1022. {
  1023.     #ifdef si4703_debug
  1024.     printk(KERN_ERR "API-si4703: set volume,n");
  1025.     #endif
  1026.     VolumeCtrl = vol/10+5;
  1027. FM_SI47XX_WriteReg(W05h,SI_RECOMMENDED_SEEKTH | BandSelect | SpacingSelect | VolumeCtrl);
  1028. }
  1029. /*******************************************************************************
  1030.  * Function:      FM_SI47XX_IncVolume
  1031.  *
  1032.  * Parameters:    none
  1033.  *    
  1034.  * Returns:       none
  1035.  *
  1036.  * Description:  Routine to increase volume of FM_SI47XX
  1037.  ******************************************************************************/
  1038. void
  1039. FM_SI47XX_IncVolume(
  1040. void
  1041. )
  1042. {
  1043. FM_SI47XX_Volume(TURNUP);
  1044. }
  1045. /*******************************************************************************
  1046.  * Function:      FM_SI47XX_DecVolume
  1047.  *
  1048.  * Parameters:    none
  1049.  *    
  1050.  * Returns:       none
  1051.  *
  1052.  * Description:  Routine to decrease volume of FM_SI47XX
  1053.  ******************************************************************************/
  1054. void
  1055. FM_SI47XX_DecVolume(
  1056. void
  1057. )
  1058. {
  1059. FM_SI47XX_Volume(TURNDOWN);
  1060. }
  1061. /*******************************************************************************
  1062.  * Function:      FM_SI47XX_MuteVolumeexport PATH=/proj/oe/build_mnh/cross/bin:/proj/oe/build_mnh/staging/i686-linux/bin:$PATH
  1063. export ARCH=arm
  1064. export CROSS_COMPILE=arm-angstrom-linux-gnueabi-
  1065.  *
  1066.  * Parameters:    none
  1067.  *    
  1068.  * Returns:       none
  1069.  *
  1070.  * Description:  Routine to mute volume of FM_SI47XX
  1071.  ******************************************************************************/
  1072. void
  1073. FM_SI47XX_MuteVolume(
  1074. void
  1075. )
  1076. {
  1077.     #ifdef si4703_debug
  1078.     printk(KERN_ERR "API-si4703: mute,n");
  1079.     #endif
  1080.     FM_SI47XX_WriteReg(W02h,SI_MUTE | SI_ENABLE | SI_DSOFTMUTE);
  1081. }
  1082. /*******************************************************************************
  1083.  * Function:      FM_SI47XX_DMuteVolume
  1084.  *
  1085.  * Parameters:    none
  1086.  *    
  1087.  * Returns:       none
  1088.  *
  1089.  * Description:  Routine to unmute volume of FM_SI47XX
  1090.  ******************************************************************************/
  1091. void 
  1092. FM_SI47XX_DMuteVolume(
  1093. void
  1094. )
  1095. {
  1096.     #ifdef si4703_debug
  1097.     printk(KERN_ERR "API-si4703: unmute,n");
  1098.     #endif
  1099.     FM_SI47XX_WriteReg(W02h,SI_DMUTE | SI_ENABLE | SI_DSOFTMUTE);
  1100. }