From 871480933a1c28f8a9fed4c4d34d06c439a7a422 Mon Sep 17 00:00:00 2001 From: Srikant Patnaik Date: Sun, 11 Jan 2015 12:28:04 +0530 Subject: Moved, renamed, and deleted files The original directory structure was scattered and unorganized. Changes are basically to make it look like kernel structure. --- .../drivers/net/wireless/rda/rda_fm/Makefile | 1 - ANDROID_3.4.5/drivers/net/wireless/rda/rda_fm/fm.h | 517 ----- .../drivers/net/wireless/rda/rda_fm/fm_drv.c | 2257 -------------------- 3 files changed, 2775 deletions(-) delete mode 100755 ANDROID_3.4.5/drivers/net/wireless/rda/rda_fm/Makefile delete mode 100755 ANDROID_3.4.5/drivers/net/wireless/rda/rda_fm/fm.h delete mode 100755 ANDROID_3.4.5/drivers/net/wireless/rda/rda_fm/fm_drv.c (limited to 'ANDROID_3.4.5/drivers/net/wireless/rda/rda_fm') diff --git a/ANDROID_3.4.5/drivers/net/wireless/rda/rda_fm/Makefile b/ANDROID_3.4.5/drivers/net/wireless/rda/rda_fm/Makefile deleted file mode 100755 index fe6851a5..00000000 --- a/ANDROID_3.4.5/drivers/net/wireless/rda/rda_fm/Makefile +++ /dev/null @@ -1 +0,0 @@ -obj-m := fm_drv.o diff --git a/ANDROID_3.4.5/drivers/net/wireless/rda/rda_fm/fm.h b/ANDROID_3.4.5/drivers/net/wireless/rda/rda_fm/fm.h deleted file mode 100755 index c97c85e8..00000000 --- a/ANDROID_3.4.5/drivers/net/wireless/rda/rda_fm/fm.h +++ /dev/null @@ -1,517 +0,0 @@ -/* Copyright Statement: - * - * This software/firmware and related documentation ("MediaTek Software") are - * protected under relevant copyright laws. The information contained herein - * is confidential and proprietary to MediaTek Inc. and/or its licensors. - * Without the prior written permission of MediaTek inc. and/or its licensors, - * any reproduction, modification, use or disclosure of MediaTek Software, - * and information contained herein, in whole or in part, shall be strictly prohibited. - */ -/* MediaTek Inc. (C) 2010. All rights reserved. - * - * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES - * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE") - * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON - * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT. - * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE - * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR - * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH - * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES - * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES - * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK - * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR - * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND - * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE, - * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE, - * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO - * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. - * - * The following software/firmware and/or related documentation ("MediaTek Software") - * have been modified by MediaTek Inc. All revisions are subject to any receiver's - * applicable license agreements with MediaTek Inc. - */ - -/* alps/ALPS_SW/TRUNK/MAIN/alps/kernel/arch/arm/mach-mt6516/include/mach/fm.h - * - * (C) Copyright 2009 - * MediaTek - * William Chung - * - * MT6516 AR10x0 FM Radio Driver - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef __FM_H__ -#define __FM_H__ - -//#define FMDEBUG - -#include -#include - -//scan sort algorithm -enum{ - FM_SCAN_SORT_NON = 0, - FM_SCAN_SORT_UP, - FM_SCAN_SORT_DOWN, - FM_SCAN_SORT_MAX -}; - -//***************************************************************************************** -//***********************************FM config for customer *********************************** -//***************************************************************************************** -//RX -#define FMR_RSSI_TH_LONG 0x0301 //FM radio long antenna RSSI threshold(11.375dBuV) -#define FMR_RSSI_TH_SHORT 0x02E0 //FM radio short antenna RSSI threshold(-1dBuV) -#define FMR_CQI_TH 0x00E9 //FM radio Channel quality indicator threshold(0x0000~0x00FF) -#define FMR_SEEK_SPACE 1 //FM radio seek space,1:100KHZ; 2:200KHZ -#define FMR_SCAN_CH_SIZE 40 //FM radio scan max channel size -#define FMR_BAND 1 //FM radio band, 1:87.5MHz~108.0MHz; 2:76.0MHz~90.0MHz; 3:76.0MHz~108.0MHz; 4:special -#define FMR_BAND_FREQ_L 875 //FM radio special band low freq(Default 87.5MHz) -#define FMR_BAND_FREQ_H 1080 //FM radio special band high freq(Default 108.0MHz) -#define FM_SCAN_SORT_SELECT FM_SCAN_SORT_NON - -//TX - -//***************************************************************************************** -//***********************************FM config for engineer *********************************** -//***************************************************************************************** -//RX -#define FMR_MR_TH 0x01BD //FM radio MR threshold -#define ADDR_SCAN_TH 0xE0 //scan thrshold register -#define ADDR_CQI_TH 0xE1 //scan CQI register - -//TX -#define FMTX_SCAN_HOLE_LOW 923 //92.3MHz~95.4MHz should not show to user -#define FMTX_SCAN_HOLE_HIGH 954 //92.3MHz~95.4MHz should not show to user -//***************************************************************************************** - -#define FM_NAME "fm" -#define FM_DEVICE_NAME "/dev/fm" - -// errno -#define FM_SUCCESS 0 -#define FM_FAILED 1 -#define FM_EPARM 2 -#define FM_BADSTATUS 3 -#define FM_TUNE_FAILED 4 -#define FM_SEEK_FAILED 5 -#define FM_BUSY 6 -#define FM_SCAN_FAILED 7 - -// band - -#define FM_BAND_UNKNOWN 0 -#define FM_BAND_UE 1 // US/Europe band 87.5MHz ~ 108MHz (DEFAULT) -#define FM_BAND_JAPAN 2 // Japan band 76MHz ~ 90MHz -#define FM_BAND_JAPANW 3 // Japan wideband 76MHZ ~ 108MHz -#define FM_BAND_SPECIAL 4 // special band between 76MHZ and 108MHz -#define FM_BAND_DEFAULT FM_BAND_UE -#define FM_FREQ_MIN FMR_BAND_FREQ_L -#define FM_FREQ_MAX FMR_BAND_FREQ_H -#define FM_RAIDO_BAND FM_BAND_UE -// space -#define FM_SPACE_UNKNOWN 0 -#define FM_SPACE_100K 1 -#define FM_SPACE_200K 2 -#define FM_SPACE_DEFAULT FMR_SEEK_SPACE -#define FM_SEEK_SPACE FMR_SEEK_SPACE - -//max scan chl num -#define FM_MAX_CHL_SIZE FMR_SCAN_CH_SIZE -// auto HiLo -#define FM_AUTO_HILO_OFF 0 -#define FM_AUTO_HILO_ON 1 - -// seek direction -#define FM_SEEK_UP 0 -#define FM_SEEK_DOWN 1 - -#define FM_CHIP_AR1000 0x1000 -#define FM_CHIP_MT5192 0x91 -#define FM_CHIP_MT5193 0x92 -#define FM_CHIP_MT6616 0x6616 -#define FM_CHIP_MT6626 0x6626 -#define FM_CHIP_MT6628 0x6628 -#define FM_CHIP_MT6620 0x6620 -#define FM_CHIP_UNSUPPORTED 0xffff - -// seek threshold -#define FM_SEEKTH_LEVEL_DEFAULT 4 - -#define FM_IOC_MAGIC 0xf5 // FIXME: any conflict? - -struct fm_tune_parm { - uint8_t err; - uint8_t band; - uint8_t space; - uint8_t hilo; - uint16_t freq; // IN/OUT parameter -}; - -struct fm_seek_parm { - uint8_t err; - uint8_t band; - uint8_t space; - uint8_t hilo; - uint8_t seekdir; - uint8_t seekth; - uint16_t freq; // IN/OUT parameter -}; - -struct fm_scan_parm { - uint8_t err; - uint8_t band; - uint8_t space; - uint8_t hilo; - uint16_t freq; // OUT parameter - uint16_t ScanTBL[16]; //need no less than the chip - uint16_t ScanTBLSize; //IN/OUT parameter -}; - -struct fm_ch_rssi{ - uint16_t freq; - uint16_t rssi; -}; - -struct fm_rssi_req{ - uint16_t num; - uint16_t read_cnt; - struct fm_ch_rssi cr[16*16]; -}; - -#if 1 -#define NEED_DEF_RDS 1 -#else -#define NEED_DEF_RDS 0 -#endif - -#if NEED_DEF_RDS -//For RDS feature -typedef struct -{ - uint8_t TP; - uint8_t TA; - uint8_t Music; - uint8_t Stereo; - uint8_t Artificial_Head; - uint8_t Compressed; - uint8_t Dynamic_PTY; - uint8_t Text_AB; - uint32_t flag_status; -}RDSFlag_Struct; - -typedef struct -{ - uint16_t Month; - uint16_t Day; - uint16_t Year; - uint16_t Hour; - uint16_t Minute; - uint8_t Local_Time_offset_signbit; - uint8_t Local_Time_offset_half_hour; -}CT_Struct; - -typedef struct -{ - int16_t AF_Num; - int16_t AF[2][25]; //100KHz - uint8_t Addr_Cnt; - uint8_t isMethod_A; - uint8_t isAFNum_Get; -}AF_Info; - -typedef struct -{ - uint8_t PS[4][8]; - uint8_t Addr_Cnt; -}PS_Info; - -typedef struct -{ - uint8_t TextData[4][64]; - uint8_t GetLength; - uint8_t isRTDisplay; - uint8_t TextLength; - uint8_t isTypeA; - uint8_t BufCnt; - uint16_t Addr_Cnt; -}RT_Info; - -struct rds_raw_data -{ - int dirty; //indicate if the data changed or not - int len; //the data len form chip - uint8_t data[146]; -}; - -struct rds_group_cnt -{ - unsigned long total; - unsigned long groupA[16]; //RDS groupA counter - unsigned long groupB[16]; //RDS groupB counter -}; - -enum rds_group_cnt_opcode -{ - RDS_GROUP_CNT_READ = 0, - RDS_GROUP_CNT_WRITE, - RDS_GROUP_CNT_RESET, - RDS_GROUP_CNT_MAX -}; - -struct rds_group_cnt_req -{ - int err; - enum rds_group_cnt_opcode op; - struct rds_group_cnt gc; -}; - -typedef struct -{ - CT_Struct CT; - RDSFlag_Struct RDSFlag; - uint16_t PI; - uint8_t Switch_TP; - uint8_t PTY; - AF_Info AF_Data; - AF_Info AFON_Data; - uint8_t Radio_Page_Code; - uint16_t Program_Item_Number_Code; - uint8_t Extend_Country_Code; - uint16_t Language_Code; - PS_Info PS_Data; - uint8_t PS_ON[8]; - RT_Info RT_Data; - uint16_t event_status; //will use RDSFlag_Struct RDSFlag->flag_status to check which event, is that ok? - struct rds_group_cnt gc; -} RDSData_Struct; - - -//Need care the following definition. -//valid Rds Flag for notify -typedef enum { - RDS_FLAG_IS_TP = 0x0001, // Program is a traffic program - RDS_FLAG_IS_TA = 0x0002, // Program currently broadcasts a traffic ann. - RDS_FLAG_IS_MUSIC = 0x0004, // Program currently broadcasts music - RDS_FLAG_IS_STEREO = 0x0008, // Program is transmitted in stereo - RDS_FLAG_IS_ARTIFICIAL_HEAD = 0x0010, // Program is an artificial head recording - RDS_FLAG_IS_COMPRESSED = 0x0020, // Program content is compressed - RDS_FLAG_IS_DYNAMIC_PTY = 0x0040, // Program type can change - RDS_FLAG_TEXT_AB = 0x0080 // If this flag changes state, a new radio text string begins -} RdsFlag; - -typedef enum { - RDS_EVENT_FLAGS = 0x0001, // One of the RDS flags has changed state - RDS_EVENT_PI_CODE = 0x0002, // The program identification code has changed - RDS_EVENT_PTY_CODE = 0x0004, // The program type code has changed - RDS_EVENT_PROGRAMNAME = 0x0008, // The program name has changed - RDS_EVENT_UTCDATETIME = 0x0010, // A new UTC date/time is available - RDS_EVENT_LOCDATETIME = 0x0020, // A new local date/time is available - RDS_EVENT_LAST_RADIOTEXT = 0x0040, // A radio text string was completed - RDS_EVENT_AF = 0x0080, // Current Channel RF signal strength too weak, need do AF switch - RDS_EVENT_AF_LIST = 0x0100, // An alternative frequency list is ready - RDS_EVENT_AFON_LIST = 0x0200, // An alternative frequency list is ready - RDS_EVENT_TAON = 0x0400, // Other Network traffic announcement start - RDS_EVENT_TAON_OFF = 0x0800, // Other Network traffic announcement finished. - RDS_EVENT_RDS = 0x2000, // RDS Interrupt had arrived durint timer period - RDS_EVENT_NO_RDS = 0x4000, // RDS Interrupt not arrived durint timer period - RDS_EVENT_RDS_TIMER = 0x8000 // Timer for RDS Bler Check. ---- BLER block error rate -} RdsEvent; -#endif - -struct fm_rds_tx_parm { - uint8_t err; - uint16_t pi; - uint16_t ps[12]; // 4 ps - uint16_t other_rds[87]; // 0~29 other groups - uint8_t other_rds_cnt; // # of other group -}; - -typedef struct fm_rds_tx_req{ - unsigned char pty; // 0~31 integer - unsigned char rds_rbds; // 0:RDS, 1:RBDS - unsigned char dyn_pty; // 0:static, 1:dynamic - unsigned short pi_code; // 2-byte hex - unsigned char ps_buf[8]; // hex buf of PS - unsigned char ps_len; // length of PS, must be 0 / 8" - unsigned char af; // 0~204, 0:not used, 1~204:(87.5+0.1*af)MHz - unsigned char ah; // Artificial head, 0:no, 1:yes - unsigned char stereo; // 0:mono, 1:stereo - unsigned char compress; // Audio compress, 0:no, 1:yes - unsigned char tp; // traffic program, 0:no, 1:yes - unsigned char ta; // traffic announcement, 0:no, 1:yes - unsigned char speech; // 0:music, 1:speech -}fm_rds_tx_req; - -#define TX_SCAN_MAX 10 -#define TX_SCAN_MIN 1 -struct fm_tx_scan_parm { - uint8_t err; - uint8_t band; //87.6~108MHz - uint8_t space; - uint8_t hilo; - uint16_t freq; // start freq, if less than band min freq, then will use band min freq - uint8_t scandir; - uint16_t ScanTBL[TX_SCAN_MAX]; //need no less than the chip - uint16_t ScanTBLSize; //IN: desired size, OUT: scan result size -}; - -struct fm_gps_rtc_info{ - int err; //error number, 0: success, other: err code - int retryCnt; //GPS mnl can decide retry times - int ageThd; //GPS 3D fix time diff threshold - int driftThd; //GPS RTC drift threshold - struct timeval tvThd; //time value diff threshold - int age; //GPS 3D fix time diff - int drift; //GPS RTC drift - union{ - unsigned long stamp; //time stamp in jiffies - struct timeval tv; //time stamp value in RTC - }; - int flag; //rw flag -}; - -typedef enum -{ - FM_I2S_ON = 0, - FM_I2S_OFF -}fm_i2s_state; - -typedef enum -{ - FM_I2S_MASTER = 0, - FM_I2S_SLAVE -}fm_i2s_mode; - -typedef enum -{ - FM_I2S_32K = 0, - FM_I2S_44K, - FM_I2S_48K -}fm_i2s_sample; - -struct fm_i2s_setting{ - int onoff; - int mode; - int sample; -}; - -typedef enum{ - FM_RX = 0, - FM_TX = 1 -}FM_PWR_T; - -#define FM_IOCTL_POWERUP _IOWR(FM_IOC_MAGIC, 0, struct fm_tune_parm*) -#define FM_IOCTL_POWERDOWN _IOWR(FM_IOC_MAGIC, 1, int32_t*) -#define FM_IOCTL_TUNE _IOWR(FM_IOC_MAGIC, 2, struct fm_tune_parm*) -#define FM_IOCTL_SEEK _IOWR(FM_IOC_MAGIC, 3, struct fm_seek_parm*) -#define FM_IOCTL_SETVOL _IOWR(FM_IOC_MAGIC, 4, uint32_t*) -#define FM_IOCTL_GETVOL _IOWR(FM_IOC_MAGIC, 5, uint32_t*) -#define FM_IOCTL_MUTE _IOWR(FM_IOC_MAGIC, 6, uint32_t*) -#define FM_IOCTL_GETRSSI _IOWR(FM_IOC_MAGIC, 7, int32_t*) -#define FM_IOCTL_SCAN _IOWR(FM_IOC_MAGIC, 8, struct fm_scan_parm*) -#define FM_IOCTL_STOP_SCAN _IO(FM_IOC_MAGIC, 9) -#define FM_IOCTL_POWERUP_TX _IOWR(FM_IOC_MAGIC, 20, struct fm_tune_parm*) -#define FM_IOCTL_TUNE_TX _IOWR(FM_IOC_MAGIC, 21, struct fm_tune_parm*) -#define FM_IOCTL_RDS_TX _IOWR(FM_IOC_MAGIC, 22, struct fm_rds_tx_parm*) - -//IOCTL and struct for test -#define FM_IOCTL_GETCHIPID _IOWR(FM_IOC_MAGIC, 10, uint16_t*) -#define FM_IOCTL_EM_TEST _IOWR(FM_IOC_MAGIC, 11, struct fm_em_parm*) -#define FM_IOCTL_RW_REG _IOWR(FM_IOC_MAGIC, 12, struct fm_ctl_parm*) -#define FM_IOCTL_GETMONOSTERO _IOWR(FM_IOC_MAGIC, 13, uint16_t*) -#define FM_IOCTL_GETCURPAMD _IOWR(FM_IOC_MAGIC, 14, uint16_t*) -#define FM_IOCTL_GETGOODBCNT _IOWR(FM_IOC_MAGIC, 15, uint16_t*) -#define FM_IOCTL_GETBADBNT _IOWR(FM_IOC_MAGIC, 16, uint16_t*) -#define FM_IOCTL_GETBLERRATIO _IOWR(FM_IOC_MAGIC, 17, uint16_t*) - - -//IOCTL for RDS -#define FM_IOCTL_RDS_ONOFF _IOWR(FM_IOC_MAGIC, 18, uint16_t*) -#define FM_IOCTL_RDS_SUPPORT _IOWR(FM_IOC_MAGIC, 19, int32_t*) - -#define FM_IOCTL_RDS_SIM_DATA _IOWR(FM_IOC_MAGIC, 23, uint32_t*) -#define FM_IOCTL_IS_FM_POWERED_UP _IOWR(FM_IOC_MAGIC, 24, uint32_t*) - -//IOCTL for FM Tx -#define FM_IOCTL_TX_SUPPORT _IOWR(FM_IOC_MAGIC, 25, int32_t*) -#define FM_IOCTL_RDSTX_SUPPORT _IOWR(FM_IOC_MAGIC, 26, int32_t*) -#define FM_IOCTL_RDSTX_ENABLE _IOWR(FM_IOC_MAGIC, 27, int32_t*) -#define FM_IOCTL_TX_SCAN _IOWR(FM_IOC_MAGIC, 28, struct fm_tx_scan_parm*) - -//IOCTL for FM over BT -#define FM_IOCTL_OVER_BT_ENABLE _IOWR(FM_IOC_MAGIC, 29, int32_t*) - -//IOCTL for FM ANTENNA SWITCH -#define FM_IOCTL_ANA_SWITCH _IOWR(FM_IOC_MAGIC, 30, int32_t*) -#define FM_IOCTL_GETCAPARRAY _IOWR(FM_IOC_MAGIC, 31, int32_t*) - -//IOCTL for FM compensation by GPS RTC -#define FM_IOCTL_GPS_RTC_DRIFT _IOWR(FM_IOC_MAGIC, 32, struct fm_gps_rtc_info*) - -//IOCTL for FM I2S Setting -#define FM_IOCTL_I2S_SETTING _IOWR(FM_IOC_MAGIC, 33, struct fm_i2s_setting*) - -#define FM_IOCTL_RDS_GROUPCNT _IOWR(FM_IOC_MAGIC, 34, struct rds_group_cnt_req*) -#define FM_IOCTL_RDS_GET_LOG _IOWR(FM_IOC_MAGIC, 35, struct rds_raw_data*) - -#define FM_IOCTL_SCAN_GETRSSI _IOWR(FM_IOC_MAGIC, 36, struct fm_rssi_req*) -#define FM_IOCTL_SETMONOSTERO _IOWR(FM_IOC_MAGIC, 37, int32_t) - -#define FM_IOCTL_RDS_BC_RST _IOWR(FM_IOC_MAGIC, 38, int32_t*) - -#define FM_IOCTL_DUMP_REG _IO(FM_IOC_MAGIC, 0xFF) - -enum group_idx { - mono=0, - stereo, - RSSI_threshold, - HCC_Enable, - PAMD_threshold, - Softmute_Enable, - De_emphasis, - HL_Side, - Demod_BW, - Dynamic_Limiter, - Softmute_Rate, - AFC_Enable, - Softmute_Level, - Analog_Volume, - GROUP_TOTAL_NUMS -}; - -enum item_idx { - Sblend_OFF=0, - Sblend_ON, - ITEM_TOTAL_NUMS -}; - -struct fm_ctl_parm { - uint8_t err; - uint8_t addr; - uint16_t val; - uint16_t rw_flag;//0:write, 1:read -}; - -struct fm_em_parm { - uint16_t group_idx; - uint16_t item_idx; - uint32_t item_value; -}; -#endif // __FM_H__ diff --git a/ANDROID_3.4.5/drivers/net/wireless/rda/rda_fm/fm_drv.c b/ANDROID_3.4.5/drivers/net/wireless/rda/rda_fm/fm_drv.c deleted file mode 100755 index cc44d8f3..00000000 --- a/ANDROID_3.4.5/drivers/net/wireless/rda/rda_fm/fm_drv.c +++ /dev/null @@ -1,2257 +0,0 @@ -#include -#include -#include -#include // udelay() -#include // device_create() -#include -#include -#include -#include -#include /* constant of kernel version */ -#include // get_user() -#include - -//#include -#include "fm.h" -//#include -//#include -#include -#include -#include -#define FMDEBUG 1 -#define MTK_MT6515 1 -#define RDA599X_FM_SUPPORT 1 -#define FM_ALERT(f, s...) \ - do { \ - printk(KERN_ALERT "RDAFM " f, ## s); \ - } while(0) - -#ifdef FMDEBUG -#define FM_DEBUG(f, s...) \ - do { \ - printk("RDAFM " f, ## s); \ - } while(0) -#else -#define FM_DEBUG(f, s...) -#endif -#define RDA599X_SCANTBL_SIZE 16 //16*uinit16_t -#define RDA599X_FM_SCAN_UP 0x0 -#define RDA599X_FM_SCAN_DOWN 0x01 - - -typedef signed char int8; -typedef unsigned char uint8; -typedef signed short int16; -typedef unsigned short uint16; -typedef signed int int32; -typedef unsigned int uint32; - -extern int rda_fm_power_off(); -extern int rda_fm_power_on(); - -/****************************************************************************** - * CONSTANT DEFINITIONS - *****************************************************************************/ -#define RDAFM_SLAVE_ADDR (0x11) //RDA FM Chip address - -#define RDAFM_MASK_RSSI 0X7F // RSSI -#define RDAFM_DEV "RDA_FM" - -//customer need customize the I2C port -#define RDAFM_I2C_PORT 0 - - -#define ID_RDA5802E 0x5804 -#define ID_RDA5802H 0x5801 -#define ID_RDA5802N 0x5808 -#define ID_RDA5820 0x5805 -#define ID_RDA5820NS 0x5820 - - -static struct proc_dir_entry *g_fm_proc = NULL; -static struct fm *g_fm_struct = NULL; -static atomic_t scan_complete_flag; - -#define FM_PROC_FILE "fm" - -/****************************************************************************** - * STRUCTURE DEFINITIONS - *****************************************************************************/ - -enum RDAFM_CHIP_TYPE { - CHIP_TYPE_RDA5802E = 0, - CHIP_TYPE_RDA5802H, - CHIP_TYPE_RDA5802N, - CHIP_TYPE_RDA5820, - CHIP_TYPE_RDA5820NS, -}; - - - -typedef struct -{ - uint8_t address; - uint16_t value; -}RDA_FM_REG_T; - -typedef struct -{ - bool byPowerUp; - struct fm_tune_parm parm -}FM_TUNE_T; -static FM_TUNE_T fm_tune_data = {false, {}}; - -typedef enum -{ - FM_RECEIVER, //5800,5802,5804 - FM_TRANSMITTER, //5820 -}RDA_RADIO_WORK_E; - -typedef enum -{ - OFF, - ON, -}RDA_FM_POWER_STATE_T; - -struct fm { - uint32_t ref; - bool powerup; - uint16_t chip_id; - uint16_t device_id; - dev_t dev_t; - uint16_t min_freq; // KHz - uint16_t max_freq; // KHz - uint8_t band; // TODO - struct class *cls; - struct device *dev; - struct cdev cdev; - struct i2c_client *i2c_client; -}; - - -/****************************************************************************** - * FUNCTION PROTOTYPES - *****************************************************************************/ -//extern void fm_low_power_wa(int fmon); - -static int RDAFM_clear_hmute(struct i2c_client *client); -static int RDAFM_enable_hmute(struct i2c_client *client); -static int RDAFM_clear_tune(struct i2c_client *client); -static int RDAFM_enable_tune(struct i2c_client *client); -static int RDAFM_clear_seek(struct i2c_client *client); -static int RDAFM_enable_seek(struct i2c_client *client); -static int RDAFM_SetStereo(struct i2c_client *client,uint8_t b); -static int RDAFM_SetRSSI_Threshold(struct i2c_client *client,uint8_t RssiThreshold); -static int RDAFM_SetDe_Emphasis(struct i2c_client *client,uint8_t index); -static bool RDAFM_Scan(struct i2c_client *client, - uint16_t min_freq, uint16_t max_freq, - uint16_t *pFreq, //get the valid freq after scan - uint16_t *pScanTBL, - uint16_t *ScanTBLsize, - uint16_t scandir, - uint16_t space); - - -static int RDAFM_read(struct i2c_client *client, uint8_t addr, uint16_t *val); -static int RDAFM_write(struct i2c_client *client, uint8_t addr, uint16_t val); -static void RDAFM_em_test(struct i2c_client *client, uint16_t group_idx, uint16_t item_idx, uint32_t item_value); -static int fm_setup_cdev(struct fm *fm); -static int fm_ops_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); -static loff_t fm_ops_lseek(struct file *filp, loff_t off, int whence); -static int fm_ops_open(struct inode *inode, struct file *filp); -static int fm_ops_release(struct inode *inode, struct file *filp); - -static int fm_init(struct i2c_client *client); -static int fm_destroy(struct fm *fm); -static int fm_powerup(struct fm *fm, struct fm_tune_parm *parm); -static int fm_powerdown(struct fm *fm); - -static int fm_tune(struct fm *fm, struct fm_tune_parm *parm); -static int fm_seek(struct fm *fm, struct fm_seek_parm *parm); -static int fm_scan(struct fm *fm, struct fm_scan_parm *parm); -static int fm_setvol(struct fm *fm, uint32_t vol); -static int fm_getvol(struct fm *fm, uint32_t *vol); -static int fm_getrssi(struct fm *fm, uint32_t *rssi); -static int fm_proc_read(char *page, char **start, off_t off, int count, int *eof, void *data); - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,31)) -static int fm_i2c_attach_adapter(struct i2c_adapter *adapter); -static int fm_i2c_detect(struct i2c_adapter *adapter, int addr, int kind); -static int fm_i2c_detach_client(struct i2c_client *client); -#else -static int fm_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id); -static int fm_i2c_detect(struct i2c_client *client, struct i2c_board_info *info); -static int fm_i2c_remove(struct i2c_client *client); -#endif - -/****************************************************************************** - * GLOBAL DATA - *****************************************************************************/ -/* Addresses to scan */ -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,31)) -static unsigned short normal_i2c[] = {RDAFM_SLAVE_ADDR, I2C_CLIENT_END}; -static unsigned short ignore = I2C_CLIENT_END; - -static struct i2c_client_address_data RDAFM_addr_data = { - .normal_i2c = normal_i2c, - .probe = &ignore, - .ignore = &ignore, -}; -#else -static const struct i2c_device_id fm_i2c_id = {RDAFM_DEV, 0}; -static unsigned short force[] = {RDAFM_I2C_PORT, RDAFM_SLAVE_ADDR, I2C_CLIENT_END, I2C_CLIENT_END}; -static const unsigned short * const forces[] = {force, NULL}; -//static struct i2c_client_address_data addr_data = {.forces = forces}; -static unsigned short addr_data[] = {/*RDAFM_I2C_PORT,*/ RDAFM_SLAVE_ADDR, I2C_CLIENT_END, I2C_CLIENT_END}; - -#endif - -static struct i2c_driver RDAFM_driver = { -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,31)) - .driver = { - .owner = THIS_MODULE, - .name = RDAFM_DEV, - }, - .attach_adapter = fm_i2c_attach_adapter, - .detach_client = fm_i2c_detach_client, -#else - .class = I2C_CLASS_HWMON, - .probe = fm_i2c_probe, - .remove = fm_i2c_remove, - .detect = fm_i2c_detect, - .driver.name = RDAFM_DEV, - .driver.owner = THIS_MODULE, - .id_table = &fm_i2c_id, - //.address_data = &addr_data, - .address_list = (const unsigned short*) addr_data, -#endif -}; - -static uint16_t RDAFM_CHIP_ID = 0x5808; -static RDA_RADIO_WORK_E RDA_RADIO_WorkType = FM_RECEIVER; - - - -#if 1 -static uint16_t RDA5802N_initialization_reg[]={ - 0xC005, //02h - 0x0000, - 0x0400, - 0xC6ED, //0x86AD, //05h - 0x6000, - 0x721A, - 0x0000, - 0x0000, - 0x0000, //0x0ah - 0x0000, - 0x0000, - 0x0000, - 0x0000, - 0x0000, - 0x0000, //0x10h - 0x0019, - 0x2A11, - 0xB042, - 0x2A11, - 0xB831, //0x15h - 0xC000, - 0x2A91, - 0x9400, - 0x00A8, - 0xc400, //0x1ah - 0xF7CF, //提高远端噪声抑制 - 0x2414, //0x2ADC, //0x1ch 提升VIO VDD之间压差引起的不良 - 0x806F, - 0x4608, - 0x0086, - 0x0661, //0x20H - 0x0000, - 0x109E, - 0x23C8, - 0x0406, - 0x0E1C, //0x25H -}; -#else -static uint16_t RDA5802N_initialization_reg[]={ - 0xc401, //02h - 0x0000, - 0x0400, - 0x86ad, //05h// - 0x0000, - 0x42c6, - 0x0000, - 0x0000, - 0x0000, //0x0ah - 0x0000, - 0x0000, - 0x0000, - 0x0000, - 0x0000, - 0x0000, //0x10h - 0x0019, - 0x2a11, - 0xa053,//0x80,0x53, - 0x3e11,//0x22,0x11, - 0xfc7d, //0x15h - 0xc000, - 0x2a91, - 0x9400, - 0x00a8, - 0xc400, //0x1ah - 0xe000, - 0x2b1d, //0x23,0x14 - 0x816a, - 0x4608, - 0x0086, - 0x0661, //0x20h - 0x0000, - 0x109e, - 0x2244, - 0x0408, //0x24 - 0x0408, //0x25 -}; -#endif - -static RDA_FM_REG_T RDA5820NS_TX_initialization_reg[]={ - {0x02, 0xE003}, - {0xFF, 100}, // if address is 0xFF, sleep value ms - {0x02, 0xE001}, - {0x19, 0x88A8}, - {0x1A, 0x4290}, - {0x68, 0x0AF0}, - {0x40, 0x0001}, - {0x41, 0x41FF}, - {0xFF, 500}, - {0x03, 0x1B90}, -}; - -static RDA_FM_REG_T RDA5820NS_RX_initialization_reg[]={ - {0x02, 0x0002}, //Soft reset - {0xFF, 100}, // wait - {0x02, 0xC001}, //Power Up - {0x05, 0x888F}, //LNAP 0x884F --LNAN - {0x06, 0x6000}, - {0x13, 0x80E1}, - {0x14, 0x2A11}, - {0x1C, 0x22DE}, - {0x21, 0x0020}, - {0x03, 0x1B90}, -}; - - - -static struct file_operations fm_ops = { - .owner = THIS_MODULE, - .unlocked_ioctl = fm_ops_ioctl, - .llseek = fm_ops_lseek, - .open = fm_ops_open, - .release = fm_ops_release, -}; - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36) -static DECLARE_MUTEX(fm_ops_mutex); -#else -DEFINE_SEMAPHORE(fm_ops_mutex); -#endif - -/****************************************************************************** - *****************************************************************************/ - -/****************************************************************************** - *****************************************************************************/ - - - -static int RDAFM_GetChipID(struct i2c_client *client, uint16_t *pChipID) -{ - int err; - int ret = -1; - uint16_t val = 0x0002; - - //Reset RDA FM - err = RDAFM_write(client, 0x02, val); - if(err < 0){ -#ifdef FMDEBUG - FM_DEBUG("RDAFM_GetChipID: reset FM chip failed!\n"); -#endif - ret = -1; - return ret; - } - msleep(80); - - val = 0; - err = RDAFM_read(client, 0x0C, &val); - if (err == 0) - { - if ((0x5802 == val) || (0x5803 == val)) - { - err = RDAFM_read(client, 0x0E, &val); - - if (err == 0) - *pChipID = val; - else - *pChipID = 0x5802; - -#ifdef FMDEBUG - FM_DEBUG("RDAFM_GetChipID: Chip ID = %04X\n", val); -#endif - - ret = 0; - - } - else if ((0x5805 == val) || (0x5820 == val)) - { - *pChipID = val; - ret = 0; - } - else - { -#ifdef FMDEBUG - FM_DEBUG("RDAFM_GetChipID: get chip ID failed! get value = %04X\n", val); -#endif - ret = -1; - } - - } - else - { -#ifdef FMDEBUG - FM_DEBUG("RDAFM_GetChipID: get chip ID failed!\n"); -#endif - ret = -1; - } - - return ret; -} - - -/* - * RDAFM_read - */ -static int RDAFM_read(struct i2c_client *client, uint8_t addr, uint16_t *val) -{ - int n; - char b[2] = {0}; - - // first, send addr to RDAFM - n = i2c_master_send(client, (char*)&addr, 1); - if (n < 0) - { - FM_ALERT("RDAFM_read send:0x%X err:%d\n", addr, n); - return -1; - } - - // second, receive two byte from RDAFM - n = i2c_master_recv(client, b, 2); - if (n < 0) - { - FM_ALERT("RDAFM_read recv:0x%X err:%d\n", addr, n); - return -1; - } - - *val = (uint16_t)(b[0] << 8 | b[1]); - - return 0; -} - -/* - * RDAFM_write - */ -static int RDAFM_write(struct i2c_client *client, uint8_t addr, uint16_t val) -{ - int n; - char b[3]; - - b[0] = addr; - b[1] = (char)(val >> 8); - b[2] = (char)(val & 0xFF); - - n = i2c_master_send(client, b, 3); - if (n < 0) - { - FM_ALERT("RDAFM_write send:0x%X err:%d\n", addr, n); - return -1; - } - - return 0; -} - - -static int RDAFM_clear_hmute(struct i2c_client *client) -{ - int ret = 0; - uint16_t tRegValue = 0; - - FM_DEBUG("RDAFM_clear_hmute\n"); - - ret = RDAFM_read(client, 0x02, &tRegValue); - if (ret < 0) - { - FM_ALERT("RDAFM_clear_hmute read register failed!\n"); - return -1; - } - - tRegValue |= (1 << 14); - - ret = RDAFM_write(client, 0x02, tRegValue); - - if (ret < 0) - { - FM_ALERT("RDAFM_clear_hmute write register failed!\n"); - return -1; - } - - if(fm_tune_data.byPowerUp){ - if (fm_tune(g_fm_struct, &(fm_tune_data.parm)) < 0) - { - fm_tune_data.byPowerUp = false; - memset(&fm_tune_data.parm, 0, sizeof(fm_tune_data.parm)); - return -EPERM; - } - fm_tune_data.byPowerUp = false; - memset(&fm_tune_data.parm, 0, sizeof(fm_tune_data.parm)); - } - - return 0; -} - - - -static int RDAFM_enable_hmute(struct i2c_client *client) -{ - int ret = 0; - uint16_t tRegValue = 0; - - FM_DEBUG("RDAFM_enable_hmute\n"); - - ret = RDAFM_read(client, 0x02, &tRegValue); - if (ret < 0) - { - FM_ALERT("RDAFM_enable_hmute read register failed!\n"); - return -1; - } - - tRegValue &= (~(1 << 14)); - - ret = RDAFM_write(client, 0x02, tRegValue); - - if (ret < 0) - { - FM_ALERT("RDAFM_enable_hmute write register failed!\n"); - return -1; - } - - return 0; -} - - - -static int RDAFM_clear_tune(struct i2c_client *client) -{ - //Don't need it - return 0; -} - - - -static int RDAFM_enable_tune(struct i2c_client *client) -{ - //Don't need it - return 0; -} - - - -static int RDAFM_clear_seek(struct i2c_client *client) -{ - //Don't need it - return 0; -} - - - -static int RDAFM_enable_seek(struct i2c_client *client) -{ - //Don't need it - return 0; -} - - -//b=true set stereo else set mono -static int RDAFM_SetStereo(struct i2c_client *client, uint8_t b) -{ - int ret = 0; - uint16_t tRegValue = 0; - - FM_DEBUG("RDAFM_SetStereo\n"); - - ret = RDAFM_read(client, 0x02, &tRegValue); - if (ret < 0) - { - FM_ALERT("RDAFM_SetStereo read register failed!\n"); - return -1; - } - if (b) - tRegValue &= (~(1 << 13));//set stereo - else - tRegValue |= (1 << 13); //set mono - - ret = RDAFM_write(client, 0x02, tRegValue); - - if (ret < 0) - { - FM_ALERT("RDAFM_SetStereo write register failed!\n"); - return -1; - } - - - return 0; - -} - - - -static int RDAFM_SetRSSI_Threshold(struct i2c_client *client, uint8_t RssiThreshold) -{ - int ret = 0; - uint16_t tRegValue = 0; - - FM_DEBUG("RDAFM_SetRSSI_Threshold\n"); - - ret = RDAFM_read(client, 0x05, &tRegValue); - if (ret < 0) - { - FM_ALERT("RDAFM_SetRSSI_Threshold read register failed!\n"); - return -1; - } - - tRegValue &= 0x80FF;//clear valume - tRegValue |= ((RssiThreshold & 0x7f) << 8); //set valume - - ret = RDAFM_write(client, 0x05, tRegValue); - - if (ret < 0) - { - FM_ALERT("RDAFM_SetRSSI_Threshold write register failed!\n"); - return -1; - } - - - return 0; - -} - - - -static int RDAFM_SetDe_Emphasis(struct i2c_client *client, uint8_t index) -{ - int ret = 0; - uint16_t tRegValue = 0; - - FM_DEBUG("RDAFM_SetRSSI_Threshold\n"); - - ret = RDAFM_read(client, 0x04, &tRegValue); - if (ret < 0) - { - FM_ALERT("RDAFM_SetRSSI_Threshold read register failed!\n"); - return -1; - } - - if (0 == index) - { - tRegValue &= (~(1 << 11));//De_Emphasis=75us - } - else if (1 == index) - { - tRegValue |= (1 << 11);//De_Emphasis=50us - } - - - ret = RDAFM_write(client, 0x04, tRegValue); - - if (ret < 0) - { - FM_ALERT("RDAFM_SetRSSI_Threshold write register failed!\n"); - return -1; - } - - - return 0; - - -} - -static void RDAFM_em_test(struct i2c_client *client, uint16_t group_idx, uint16_t item_idx, uint32_t item_value) -{ - FM_ALERT("RDAFM_em_test %d:%d:%d\n", group_idx, item_idx, item_value); - switch (group_idx) - { - case mono: - if(item_value == 1) - { - RDAFM_SetStereo(client, 0); //force mono - } - else - { - RDAFM_SetStereo(client, 1); //stereo - - } - - break; - case stereo: - if(item_value == 0) - { - RDAFM_SetStereo(client, 1); //stereo - } - else - { - RDAFM_SetStereo(client, 0); //force mono - } - break; - case RSSI_threshold: - item_value &= 0x7F; - RDAFM_SetRSSI_Threshold(client, item_value); - break; - case Softmute_Enable: - if (item_idx) - { - RDAFM_enable_hmute(client); - } - else - { - RDAFM_clear_hmute(client); - } - break; - case De_emphasis: - if(item_idx >= 2) //0us - { - FM_ALERT("RDAFM not support De_emphasis 0\n"); - } - else - { - RDAFM_SetDe_Emphasis(client,item_idx);//0=75us,1=50us - } - break; - - case HL_Side: - - break; - default: - FM_ALERT("RDAFM not support this setting\n"); - break; - } -} - -static bool RDAFM_Scan(struct i2c_client *client, - uint16_t min_freq, uint16_t max_freq, - uint16_t *pFreq, - uint16_t *pScanTBL, - uint16_t *ScanTBLsize, - uint16_t scandir, - uint16_t space) -{ - uint16_t tFreq, tRegValue = 0; - uint16_t tmp_scanTBLsize = *ScanTBLsize; - int ret = -1; - bool isTrueStation = false; - uint16_t oldValue = 0; - int channel = 0; - if((!pScanTBL) || (tmp_scanTBLsize == 0)) { - return false; - } - - //clear the old value of pScanTBL - memset(pScanTBL, 0, sizeof(uint16_t)*RDA599X_SCANTBL_SIZE); - - if(tmp_scanTBLsize > RDA599X_SCANTBL_SIZE) - { - tmp_scanTBLsize = RDA599X_SCANTBL_SIZE; - } - - //scan up - if(scandir == RDA599X_FM_SCAN_UP){ // now, only support scan up - tFreq = min_freq; - }else{ //scan down - tFreq = max_freq;//max_freq compare need or not - } - - //mute FM - RDAFM_enable_hmute(client); -#if 0 - //set seekth - tRegValue = 0; - RDAFM_read(client, 0x05, &tRegValue); - tRegValue &= (~(0x7f<<8)); - tRegValue |= ((0x8 & 0x7f) << 8); - RDAFM_write(client, 0x05, tRegValue); - msleep(50); -#endif - atomic_set(&scan_complete_flag, 1); - do { - if(atomic_read(&scan_complete_flag) == 0) - break; - isTrueStation = false; - - //set channel and enable TUNE - tRegValue = 0; - RDAFM_read(client, 0x03, &tRegValue); - tRegValue &= (~(0x03ff<<6)); //clear bit[15:6] - channel = tFreq - min_freq; - tRegValue |= ((channel << 6) | (1 << 4)); //set bit[15:6] and bit[4] - ret = RDAFM_write(client, 0x03, tRegValue); - msleep(40); - - //read 0x0B and check FM_TRUE(bit[8]) - tRegValue = 0; - ret = RDAFM_read(client, 0x0B, &tRegValue); - if(!ret){ - if((tRegValue & 0x0100) == 0x0100){ - isTrueStation = true; - } - } - - //if this freq is a true station, read the channel - if(isTrueStation){ - //tRegValue = 0; - //RDAFM_read(client, 0x03, &tRegValue); - //channel = ((tRegValue>>6) & 0x03ff) - 5; - channel = channel - 5; - if((channel >= 0) && (channel != 85)){ - oldValue = *(pScanTBL+(channel/16)); - oldValue |= (1<<(channel%16)); - *(pScanTBL+(channel/16)) = oldValue; - } - } - - //increase freq - tFreq += space; - }while( tFreq <= max_freq ); - -#if defined(MTK_MT6515) && defined(MT6626) - *(pScanTBL+13) = 0xb2d4; - *(pScanTBL+14) = 0xb2d4; - *(pScanTBL+15) = 0xb2d4; -#endif - - *ScanTBLsize = tmp_scanTBLsize; - *pFreq = 0; - - //clear FM mute - RDAFM_clear_hmute(client); - - return true; -} - - -static int fm_setup_cdev(struct fm *fm) -{ - int err; - - err = alloc_chrdev_region(&fm->dev_t, 0, 1, FM_NAME); - if (err) { - FM_ALERT("alloc dev_t failed\n"); - return -1; - } - - FM_ALERT("alloc %s:%d:%d\n", FM_NAME, - MAJOR(fm->dev_t), MINOR(fm->dev_t)); - - cdev_init(&fm->cdev, &fm_ops); - - fm->cdev.owner = THIS_MODULE; - fm->cdev.ops = &fm_ops; - - err = cdev_add(&fm->cdev, fm->dev_t, 1); - if (err) { - FM_ALERT("alloc dev_t failed\n"); - return -1; - } - - fm->cls = class_create(THIS_MODULE, FM_NAME); - if (IS_ERR(fm->cls)) { - err = PTR_ERR(fm->cls); - FM_ALERT("class_create err:%d\n", err); - return err; - } - fm->dev = device_create(fm->cls, NULL, fm->dev_t, NULL, FM_NAME); - - return 0; -} - - - -static int fm_ops_ioctl(struct file *filp, - unsigned int cmd, unsigned long arg) -{ - int ret = 0; - struct fm *fm = container_of(filp->f_dentry->d_inode->i_cdev, struct fm, cdev); - - FM_DEBUG("%s cmd(%x)\n", __func__, cmd); - - switch(cmd) - { - case FM_IOCTL_POWERUP: - { - struct fm_tune_parm parm; - FM_DEBUG("FM_IOCTL_POWERUP\n"); - - // FIXME!! - // if (!capable(CAP_SYS_ADMIN)) - // return -EPERM; - - if (copy_from_user(&parm, (void*)arg, sizeof(struct fm_tune_parm))) - return -EFAULT; - - if (down_interruptible(&fm_ops_mutex)) - return -EFAULT; - ret = fm_powerup(fm, &parm); - up(&fm_ops_mutex); - if (copy_to_user((void*)arg, &parm, sizeof(struct fm_tune_parm))) - return -EFAULT; - // fm_low_power_wa(1); - break; - } - - case FM_IOCTL_POWERDOWN: - { - FM_DEBUG("FM_IOCTL_POWERDOWN\n"); - // FIXME!! - // if (!capable(CAP_SYS_ADMIN)) - // return -EPERM; - if (down_interruptible(&fm_ops_mutex)) - return -EFAULT; - ret = fm_powerdown(fm); - up(&fm_ops_mutex); -// fm_low_power_wa(0); - break; - } - - // tune (frequency, auto Hi/Lo ON/OFF ) - case FM_IOCTL_TUNE: - { - struct fm_tune_parm parm; - FM_DEBUG("FM_IOCTL_TUNE\n"); -// FIXME! -// if (!capable(CAP_SYS_ADMIN)) -// return -EPERM; - - if (copy_from_user(&parm, (void*)arg, sizeof(struct fm_tune_parm))) - return -EFAULT; - - if (down_interruptible(&fm_ops_mutex)) - return -EFAULT; - ret = fm_tune(fm, &parm); - up(&fm_ops_mutex); - - if (copy_to_user((void*)arg, &parm, sizeof(struct fm_tune_parm))) - return -EFAULT; - - break; - } - - case FM_IOCTL_SEEK: - { - struct fm_seek_parm parm; - FM_DEBUG("FM_IOCTL_SEEK\n"); - -// FIXME!! -// if (!capable(CAP_SYS_ADMIN)) -// return -EPERM; - - if (copy_from_user(&parm, (void*)arg, sizeof(struct fm_seek_parm))) - return -EFAULT; - - if (down_interruptible(&fm_ops_mutex)) - return -EFAULT; - ret = fm_seek(fm, &parm); - up(&fm_ops_mutex); - - if (copy_to_user((void*)arg, &parm, sizeof(struct fm_seek_parm))) - return -EFAULT; - - break; - } - - case FM_IOCTL_SETVOL: - { - uint32_t vol; - FM_DEBUG("FM_IOCTL_SETVOL\n"); - -// FIXME!! -// if (!capable(CAP_SYS_ADMIN)) -// return -EPERM; - - if(copy_from_user(&vol, (void*)arg, sizeof(uint32_t))) { - FM_ALERT("copy_from_user failed\n"); - return -EFAULT; - } - - if (down_interruptible(&fm_ops_mutex)) - return -EFAULT; - ret = fm_setvol(fm, vol); - up(&fm_ops_mutex); - - break; - } - - case FM_IOCTL_GETVOL: - { - uint32_t vol; - FM_DEBUG("FM_IOCTL_GETVOL\n"); - -// FIXME!! -// if (!capable(CAP_SYS_ADMIN)) -// return -EPERM; - - if (down_interruptible(&fm_ops_mutex)) - return -EFAULT; - ret = fm_getvol(fm, &vol); - up(&fm_ops_mutex); - - if (copy_to_user((void*)arg, &vol, sizeof(uint32_t))) - return -EFAULT; - - break; - } - - case FM_IOCTL_MUTE: - { - uint32_t bmute; - FM_DEBUG("FM_IOCTL_MUTE\n"); - - // FIXME!! - // if (!capable(CAP_SYS_ADMIN)) - // return -EPERM; - if (copy_from_user(&bmute, (void*)arg, sizeof(uint32_t))) - { - FM_DEBUG("copy_from_user mute failed!\n"); - return -EFAULT; - } - - FM_DEBUG("FM_IOCTL_MUTE:%d\n", bmute); - if (down_interruptible(&fm_ops_mutex)) - return -EFAULT; - - if (bmute){ - ret = RDAFM_enable_hmute(fm->i2c_client); - }else{ - ret = RDAFM_clear_hmute(fm->i2c_client); - } - - up(&fm_ops_mutex); - - break; - } - - case FM_IOCTL_GETRSSI: - { - uint32_t rssi; - FM_DEBUG("FM_IOCTL_GETRSSI\n"); - -// FIXME!! -// if (!capable(CAP_SYS_ADMIN)) -// return -EPERM; - - if (down_interruptible(&fm_ops_mutex)) - return -EFAULT; - - ret = fm_getrssi(fm, &rssi); - up(&fm_ops_mutex); - - if (copy_to_user((void*)arg, &rssi, sizeof(uint32_t))) - return -EFAULT; - - break; - } - - case FM_IOCTL_RW_REG: - { - struct fm_ctl_parm parm_ctl; - FM_DEBUG("FM_IOCTL_RW_REG\n"); - -// FIXME!! -// if (!capable(CAP_SYS_ADMIN)) -// return -EPERM; - - if (copy_from_user(&parm_ctl, (void*)arg, sizeof(struct fm_ctl_parm))) - return -EFAULT; - - if (down_interruptible(&fm_ops_mutex)) - return -EFAULT; - - if(parm_ctl.rw_flag == 0) //write - { - ret = RDAFM_write(fm->i2c_client, parm_ctl.addr, parm_ctl.val); - } - else - { - ret = RDAFM_read(fm->i2c_client, parm_ctl.addr, &parm_ctl.val); - } - - up(&fm_ops_mutex); - if ((parm_ctl.rw_flag == 0x01) && (!ret)) // Read success. - { - if (copy_to_user((void*)arg, &parm_ctl, sizeof(struct fm_ctl_parm))) - return -EFAULT; - } - break; - } - - case FM_IOCTL_GETCHIPID: - { - uint16_t chipid; - - if (down_interruptible(&fm_ops_mutex)) - return -EFAULT; - - RDAFM_GetChipID(fm->i2c_client, &chipid); - //chipid = fm->chip_id; - chipid = 0x6620; - FM_DEBUG("FM_IOCTL_GETCHIPID:%04x\n", chipid); - up(&fm_ops_mutex); - - if (copy_to_user((void*)arg, &chipid, sizeof(uint16_t))) - return -EFAULT; - - break; - } - - case FM_IOCTL_EM_TEST: - { - struct fm_em_parm parm_em; - FM_DEBUG("FM_IOCTL_EM_TEST\n"); - -// FIXME!! -// if (!capable(CAP_SYS_ADMIN)) -// return -EPERM; - - if (copy_from_user(&parm_em, (void*)arg, sizeof(struct fm_em_parm))) - return -EFAULT; - - if (down_interruptible(&fm_ops_mutex)) - return -EFAULT; - - RDAFM_em_test(fm->i2c_client, parm_em.group_idx, parm_em.item_idx, parm_em.item_value); - - up(&fm_ops_mutex); - - break; - } - case FM_IOCTL_IS_FM_POWERED_UP: - { - uint32_t powerup; - FM_DEBUG("FM_IOCTL_IS_FM_POWERED_UP"); - if (fm->powerup) { - powerup = 1; - } else { - powerup = 0; - } - if (copy_to_user((void*)arg, &powerup, sizeof(uint32_t))) - return -EFAULT; - break; - } - -#ifdef FMDEBUG - case FM_IOCTL_DUMP_REG: - { - uint16_t chipid = 0; - if (down_interruptible(&fm_ops_mutex)) - return -EFAULT; - RDAFM_GetChipID(fm->i2c_client, &chipid); - up(&fm_ops_mutex); - - break; - } -#endif - - case FM_IOCTL_SCAN: - { - struct fm_scan_parm parm; - FM_DEBUG("FM_IOCTL_SCAN\n"); - if (false == fm->powerup){ - return -EFAULT; - } - if(copy_from_user(&parm, (void*)arg, sizeof(struct fm_scan_parm))){ - return -EFAULT; - } - if (down_interruptible(&fm_ops_mutex)){ - return -EFAULT; - } - fm_scan(fm, &parm); - up(&fm_ops_mutex); - - if(copy_to_user((void*)arg, &parm, sizeof(struct fm_scan_parm))){ - return -EFAULT; - } - - break; - } - - case FM_IOCTL_STOP_SCAN: - { - FM_DEBUG("FM_IOCTL_STOP_SCAN\n"); - break; - } - - default: - { - FM_DEBUG("default\n"); - break; - } - } - - return ret; -} -static loff_t fm_ops_lseek(struct file *filp, loff_t off, int whence) -{ -// struct fm *fm = filp->private_data; - - if(whence == SEEK_END){ - //fm_hwscan_stop(fm); - atomic_set(&scan_complete_flag, 0); - }else if(whence == SEEK_SET){ - //FM_EVENT_SEND(fm->rds_event, FM_RDS_DATA_READY); - } - return off; -} - -static int fm_ops_open(struct inode *inode, struct file *filp) -{ - struct fm *fm = container_of(inode->i_cdev, struct fm, cdev); - - FM_DEBUG("%s\n", __func__); - - if (down_interruptible(&fm_ops_mutex)) - return -EFAULT; - - // TODO: only have to set in the first time? - // YES!!!! - - fm->ref++; - - up(&fm_ops_mutex); - - filp->private_data = fm; - - // TODO: check open flags - - return 0; -} - -static int fm_ops_release(struct inode *inode, struct file *filp) -{ - int err = 0; - struct fm *fm = container_of(inode->i_cdev, struct fm, cdev); - - FM_DEBUG("%s\n", __func__); - - if (down_interruptible(&fm_ops_mutex)) - return -EFAULT; - fm->ref--; - if(fm->ref < 1) { - if(fm->powerup == true) { - fm_powerdown(fm); - } - } - - up(&fm_ops_mutex); - - return err; -} - -//#define WMT_TEST_ORI 1 - -static int fm_init(struct i2c_client *client) -{ - int err; - struct fm *fm = NULL; - int ret = -1; - - - FM_DEBUG("%s()\n", __func__); - if (!(fm = kzalloc(sizeof(struct fm), GFP_KERNEL))) - { - FM_ALERT("-ENOMEM\n"); - err = -ENOMEM; - goto ERR_EXIT; - } - - fm->ref = 0; - fm->powerup = false; - atomic_set(&scan_complete_flag, 0); - -#ifdef RDA599X_FM_SUPPORT - - ret = rda_fm_power_on(); - if(ret < 0){ - err = -ENOMEM; - goto ERR_EXIT; - } - msleep(100); -#endif - - // First, read 5802NM chip ID - FM_DEBUG("%s()First, read 5802NM chip ID\n", __func__); - ret = RDAFM_GetChipID(client, &RDAFM_CHIP_ID); - if(ret < 0){ - FM_DEBUG("%s() read RDA chip ID failed\n", __func__); - err = -ENOMEM; - goto ERR_EXIT; - } - else{ - fm->chip_id = RDAFM_CHIP_ID; - } - - FM_DEBUG("%s() 5802NM chip ID = 0x%04x\n", __func__, RDAFM_CHIP_ID); - -#ifdef RDA599X_FM_SUPPORT - ret = rda_fm_power_off(); - if(ret < 0){ - err = -ENOMEM; - goto ERR_EXIT; - } -#endif - - -#if WMT_TEST_ORI - printk("ori code\n"); - // if failed, means use FM in 5990P_E - if(ret < 0){ - // enable the FM chip in combo - FM_DEBUG("%s() enable the FM chip in combo\n", __func__); - ret = rda_fm_power_on(); - if(ret < 0){ - err = -ENOMEM; - goto ERR_EXIT; - } - msleep(100); - ret = RDAFM_GetChipID(client, &RDAFM_CHIP_ID); - FM_DEBUG("%s() the FM in combo chip ID = 0x%04x\n", __func__, RDAFM_CHIP_ID); - if(ret < 0){ - err = -ENOMEM; - goto ERR_EXIT; - }else{ - fm->chip_id = RDAFM_CHIP_ID; - } - - // disable the FM chip for power saving - ret = rda_fm_power_off(); - if(ret < 0){ - err = -ENOMEM; - goto ERR_EXIT; - } - }else{ - fm->chip_id = RDAFM_CHIP_ID; - } - - -#endif - - - if ((err = fm_setup_cdev(fm))) - { - goto ERR_EXIT; - } - - g_fm_struct = fm; - fm->i2c_client = client; - i2c_set_clientdata(client, fm); - - - /***********Add porc file system*************/ - - g_fm_proc = create_proc_entry(FM_PROC_FILE, 0444, NULL); - if (g_fm_proc == NULL) { - FM_ALERT("create_proc_entry failed\n"); - err = -ENOMEM; - goto ERR_EXIT; - } else { - g_fm_proc->read_proc = fm_proc_read; - g_fm_proc->write_proc = NULL; - //g_fm_proc->owner = THIS_MODULE; - FM_ALERT("create_proc_entry success\n"); - } - - /********************************************/ - - FM_DEBUG("fm_init is ok!\n"); - - return 0; - -ERR_EXIT: - kfree(fm); -#ifdef RDA599X_FM_SUPPORT - rda_fm_power_off(); -#endif - - return err; -} - -static int fm_proc_read(char *page, char **start, off_t off, int count, int *eof, void *data) -{ - int cnt= 0; - struct fm *fm = g_fm_struct; - FM_ALERT("Enter fm_proc_read.\n"); - if(off != 0) - return 0; - if (fm != NULL && fm->powerup) { - cnt = sprintf(page, "1\n"); - } else { - cnt = sprintf(page, "0\n"); - } - *eof = 1; - FM_ALERT("Leave fm_proc_read. cnt = %d\n", cnt); - return cnt; -} - - -static int fm_destroy(struct fm *fm) -{ - int err = 0; - - FM_DEBUG("%s\n", __func__); - - device_destroy(fm->cls, fm->dev_t); - class_destroy(fm->cls); - - cdev_del(&fm->cdev); - unregister_chrdev_region(fm->dev_t, 1); - - fm_powerdown(fm); - - /***********************************/ - remove_proc_entry(FM_PROC_FILE, NULL); - - /**********************************/ - - // FIXME: any other hardware configuration ? - - // free all memory - kfree(fm); - - return err; -} - -/* - * fm_powerup - */ -static int fm_powerup(struct fm *fm, struct fm_tune_parm *parm) -{ - int i; - uint16_t tRegValue = 0x0002; - int ret = -1; - - struct i2c_client *client = fm->i2c_client; - - if (fm->powerup) - { - parm->err = FM_BADSTATUS; - return -EPERM; - } - - // if chip_id is ID_RDA5820NS, enable the FM chip in combo -#ifdef RDA599X_FM_SUPPORT - ret = rda_fm_power_on(); - if(ret < 0){ - return -EPERM; - } - msleep(100); -#endif - - - //Reset RDA FM - tRegValue = 0x0002; - RDAFM_write(client, 0x02, tRegValue); - msleep(100); - - if ((ID_RDA5802N == RDAFM_CHIP_ID) || (ID_RDA5802H == RDAFM_CHIP_ID)){ - //if (ID_RDA5802N == RDAFM_CHIP_ID){ - - for (i=0; i<((sizeof(RDA5802N_initialization_reg)) / (sizeof(uint16_t))); i++) - { - ret = RDAFM_write(client, i+2, RDA5802N_initialization_reg[i]); - - if (ret < 0) - { - FM_DEBUG("fm_powerup init failed!\n"); - FM_ALERT("fm_powerup init failed!\n"); - parm->err = FM_FAILED; - - return -EPERM; - } - } - - }else if (ID_RDA5820NS == RDAFM_CHIP_ID){ - if(RDA_RADIO_WorkType == FM_RECEIVER){ - for (i = 0; i < ((sizeof(RDA5820NS_RX_initialization_reg)) / (sizeof(RDA_FM_REG_T))); i++) - { - if(RDA5820NS_RX_initialization_reg[i].address == 0xFF){ - msleep(RDA5820NS_RX_initialization_reg[i].value); - }else{ - ret = RDAFM_write(client, RDA5820NS_RX_initialization_reg[i].address, RDA5820NS_RX_initialization_reg[i].value); - if (ret < 0) - { - FM_DEBUG("fm_powerup init failed!\n"); - parm->err = FM_FAILED; - return -EPERM; - } - } - } - }else{ - for (i = 0; i < ((sizeof(RDA5820NS_TX_initialization_reg)) / (sizeof(RDA_FM_REG_T))); i++) - { - if(RDA5820NS_TX_initialization_reg[i].address == 0xFF){ - msleep(RDA5820NS_TX_initialization_reg[i].value); - }else{ - ret = RDAFM_write(client, RDA5820NS_TX_initialization_reg[i].address, RDA5820NS_TX_initialization_reg[i].value); - if (ret < 0) - { - FM_DEBUG("fm_powerup init failed!\n"); - parm->err = FM_FAILED; - return -EPERM; - } - } - } - } - - } - - - FM_DEBUG("pwron ok\n"); - fm->powerup = true; - - if (fm_tune(fm, parm) < 0) - { - return -EPERM; - } - fm_tune_data.byPowerUp = true; - memcpy(&fm_tune_data.parm, parm, sizeof(fm_tune_data.parm)); - - parm->err = FM_SUCCESS; - - return 0; - -} - -/* - * fm_powerdown - */ -static int fm_powerdown(struct fm *fm) -{ - uint16_t tRegValue = 0; - int ret = -1; - struct i2c_client *client = fm->i2c_client; - - RDAFM_read(client, 0x02, &tRegValue); - tRegValue &= (~(1 << 0)); - RDAFM_write(client, 0x02, tRegValue); -/* - if((fm->chip_id == ID_RDA5820NS) || (fm->chip_id == ID_RDA5991_FM){ - ret = rda_fm_power_off(); - if(ret < 0){ - return -EPERM; - } - } -*/ - -#ifdef RDA599X_FM_SUPPORT - ret = rda_fm_power_off(); - if(ret < 0){ - return -EPERM; - } -#endif - - - fm->powerup = false; - FM_ALERT("pwrdown ok\n"); - - return 0; -} - -/* - * fm_seek - */ -static int fm_seek(struct fm *fm, struct fm_seek_parm *parm) -{ - int ret = 0; - uint16_t val = 0; - uint8_t spaec = 1; - uint16_t tFreq = 875; - uint16_t tRegValue = 0; - uint16_t bottomOfBand = 875; - int falseStation = -1; - - - struct i2c_client *client = fm->i2c_client; - - if (!fm->powerup) - { - parm->err = FM_BADSTATUS; - return -EPERM; - } - - if (parm->space == FM_SPACE_100K) - { - spaec = 1; - val &= (~((1<<0) | (1<<1))); - } - else if (parm->space == FM_SPACE_200K) - { - spaec = 2; - val &= (~(1<<1)); - val |= (1<<0); - } - else - { - parm->err = FM_EPARM; - return -EPERM; - } - - if (parm->band == FM_BAND_UE) - { - val &= (~((1<<2) | (1<<3))); - bottomOfBand = 875; - fm->min_freq = 875; - fm->max_freq = 1080; - } - else if (parm->band == FM_BAND_JAPAN) - { - val &= (~(1<<3)); - val |= (1 << 2); - bottomOfBand = 760; - fm->min_freq = 760; - fm->max_freq = 910; - } - else if (parm->band == FM_BAND_JAPANW) { - val &= (~(1<<2)); - val |= (1 << 3); - bottomOfBand = 760; - fm->min_freq = 760; - fm->max_freq = 1080; - } - else - { - FM_ALERT("band:%d out of range\n", parm->band); - parm->err = FM_EPARM; - return -EPERM; - } - - if (parm->freq < fm->min_freq || parm->freq > fm->max_freq) { - FM_ALERT("freq:%d out of range\n", parm->freq); - parm->err = FM_EPARM; - return -EPERM; - } - - if (parm->seekth > 0x0B) { - FM_ALERT("seekth:%d out of range\n", parm->seekth); - parm->err = FM_EPARM; - return -EPERM; - } -#if 0 - RDAFM_read(client, 0x05, &tRegValue); - tRegValue &= (~(0x7f<<8)); - //tRegValue |= ((parm->seekth & 0x7f) << 8); - tRegValue |= ((0x8 & 0x7f) << 8); - RDAFM_write(client, 0x05, tRegValue); -#endif - -#ifdef FMDEBUG - if (parm->seekdir == FM_SEEK_UP) - FM_DEBUG("seek %d up\n", parm->freq); - else - FM_DEBUG("seek %d down\n", parm->freq); -#endif - - // (1) set hmute bit - RDAFM_enable_hmute(client); - - tFreq = parm->freq; - - do { - if (parm->seekdir == FM_SEEK_UP) - tFreq += spaec; - else - tFreq -= spaec; - - if (tFreq > fm->max_freq) - tFreq = fm->min_freq; - if (tFreq < fm->min_freq) - tFreq = fm->max_freq; - - val = (((tFreq - bottomOfBand+5) << 6) | (1 << 4) | (val & 0x0f)); - RDAFM_write(client, 0x03, val); - msleep(40); - ret = RDAFM_read(client, 0x0B, &tRegValue); - if (ret < 0) - { - FM_DEBUG("fm_seek: read register failed tunning freq = %4X\n", tFreq); - falseStation = -1; - } - else - { - if ((tRegValue & 0x0100) == 0x0100) - falseStation = 0; - else - falseStation = -1; - } - - if(falseStation == 0) - break; - }while(tFreq != parm->freq); - - - //clear hmute - RDAFM_clear_hmute(client); - - if (falseStation == 0) // seek successfully - { - parm->freq = tFreq; - FM_ALERT("fm_seek success, freq:%d\n", parm->freq); - parm->err = FM_SUCCESS; - } - else - { - FM_ALERT("fm_seek failed, invalid freq\n"); - parm->err = FM_SEEK_FAILED; - ret = -1; - } - - return ret; -} -static int fm_scan(struct fm *fm, struct fm_scan_parm *parm) -{ - int ret = 0; - uint16_t tRegValue = 0; - uint16_t scandir = RDA599X_FM_SCAN_UP; //scandir 搜索方向 - uint8_t space = 1; - struct i2c_client *client = fm->i2c_client; - - if (!fm->powerup){ - parm->err = FM_BADSTATUS; - return -EPERM; - } - - RDAFM_read(client, 0x03, &tRegValue); - - if (parm->space == FM_SPACE_100K){ - space = 1; - tRegValue &= (~((1<<0) | (1<<1))); //set 03H's bit[1:0] to 00 - }else if (parm->space == FM_SPACE_200K) { - space = 2; - tRegValue &= (~(1<<1)); //clear bit[1] - tRegValue |= (1<<0); //set bit[0] - }else{ - //default - space = 1; - tRegValue &= (~((1<<0) | (1<<1))); //set 03H's bit[1:0] to 00 - } - - if(parm->band == FM_BAND_UE){ - tRegValue &= (~((1<<2) | (1<<3))); - fm->min_freq = 875; - fm->max_freq = 1080; - }else if(parm->band == FM_BAND_JAPAN){ - tRegValue &= (~(1<<3)); - tRegValue |= (1 << 2); - fm->min_freq = 760; - fm->max_freq = 900; - }else if(parm->band == FM_BAND_JAPANW){ - tRegValue &= (~(1<<2)); - tRegValue |= (1 << 3); - fm->min_freq = 760; - fm->max_freq = 1080; - }else{ - parm->err = FM_EPARM; - return -EPERM; - } - - //set space and band - RDAFM_write(client, 0x03, tRegValue); - msleep(40); - - - if(RDAFM_Scan(client, fm->min_freq, fm->max_freq, &(parm->freq), parm->ScanTBL, &(parm->ScanTBLSize), scandir, space)){ - parm->err = FM_SUCCESS; - }else{ - parm->err = FM_SEEK_FAILED; - } - - return ret; -} - - -static int fm_setvol(struct fm *fm, uint32_t vol) -{ - int ret = 0; - uint16_t tRegValue = 0; - struct i2c_client *client = fm->i2c_client; - - if (vol > 15) - vol = 15; - - FM_DEBUG("fm_setvol:%d\n", vol); - - ret = RDAFM_read(client, 0x05, &tRegValue); - if (ret) - return -EPERM; - tRegValue &= ~(0x000f); - tRegValue |= vol; - - ret = RDAFM_write(client, 0x05, tRegValue); - if (ret) - return -EPERM; - - return 0; -} - -static int fm_getvol(struct fm *fm, uint32_t *vol) -{ - int ret = 0; - uint16_t tRegValue; - struct i2c_client *client = fm->i2c_client; - - ret = RDAFM_read(client, 0x05, &tRegValue); - if (ret) - return -EPERM; - - - *vol = (tRegValue & 0x000F); - - return 0; -} - -static int fm_getrssi(struct fm *fm, uint32_t *rssi) -{ - int ret = 0; - uint16_t tRegValue; - struct i2c_client *client = fm->i2c_client; - - ret = RDAFM_read(client, 0x0B, &tRegValue); - if (ret) - return -EPERM; - - - *rssi = (uint32_t)((tRegValue >> 9) & RDAFM_MASK_RSSI); - - FM_DEBUG("rssi value:%d\n", *rssi); - - return 0; -} - -/* - * fm_tune - */ -static int fm_tune(struct fm *fm, struct fm_tune_parm *parm) -{ - int ret; - uint16_t val = 0; - uint8_t space = 1; - uint16_t bottomOfBand = 875; - - struct i2c_client *client = fm->i2c_client; - - FM_DEBUG("%s\n", __func__); - - if (!fm->powerup) - { - parm->err = FM_BADSTATUS; - return -EPERM; - } - - if (parm->space == FM_SPACE_100K) - { - space = 1; - val &= (~((1<<0) | (1<<1))); - } - else if (parm->space == FM_SPACE_200K) - { - space = 2; - val |= (1<<0); - val &= (~(1<<1)); - } - else - { - parm->err = FM_EPARM; - return -EPERM; - } - - if (parm->band == FM_BAND_UE) - { - val &= (~((1<<2) | (1<<3))); - bottomOfBand = 875; - fm->min_freq = 875; - fm->max_freq = 1080; - } - else if (parm->band == FM_BAND_JAPAN) - { - val &= (~(1<<3)); - val |= (1 << 2); - bottomOfBand = 760; - fm->min_freq = 760; - fm->max_freq = 910; - } - else if (parm->band == FM_BAND_JAPANW) { - val &= (~(1<<2)); - val |= (1 << 3); - bottomOfBand = 760; - fm->min_freq = 760; - fm->max_freq = 1080; - } - else - { - FM_ALERT("band:%d out of range\n", parm->band); - parm->err = FM_EPARM; - return -EPERM; - } - - if (parm->freq < fm->min_freq || parm->freq > fm->max_freq) { - FM_ALERT("freq:%d out of range\n", parm->freq); - parm->err = FM_EPARM; - return -EPERM; - } - - FM_DEBUG("fm_tune, freq:%d\n", parm->freq); - - //RDAFM_enable_hmute(client); - - val = (((parm->freq - bottomOfBand + 5) << 6) | (1 << 4) | (val & 0x0f)); - - ret = RDAFM_write(client, 0x03, val); - if (ret < 0) - { - FM_ALERT("fm_tune write freq failed\n"); - parm->err = FM_SEEK_FAILED; - return ret; - } - msleep(40); - -#ifdef FM_DEBUG - RDAFM_read(client, 0x0A, &val); - FM_DEBUG("%s() read freq reg value = 0x%04x\n", __func__, val); -#endif - - return ret; -} - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,31)) -/* - * fm_i2c_attach_adapter - */ -static int fm_i2c_attach_adapter(struct i2c_adapter *adapter) -{ - int err = 0; - - if (adapter->id == RDAFM_I2C_PORT) - { - return i2c_probe(adapter, &RDAFM_addr_data, fm_i2c_detect); - } - - return err; -} - -/* - * fm_i2c_detect - * This function is called by i2c_detect - */ -static int fm_i2c_detect(struct i2c_adapter *adapter, int addr, int kind) -{ - int err; - struct i2c_client *client = NULL; - - /* skip this since MT6516 shall support all the needed functionalities - if (!i2c_check_functionality(adapter, xxx)) - { - FM_DEBUG("i2c_check_functionality failed\n"); - return -ENOTSUPP; - } - */ - - /* initial i2c client */ - if (!(client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL))) - { - FM_ALERT("kzalloc failed\n"); - err = -ENOMEM; - goto ERR_EXIT; - } - - client->addr = addr; - client->adapter = adapter; - client->driver = &RDAFM_driver; - client->flags = 0; - strncpy(client->name, "RDA FM RADIO", I2C_NAME_SIZE); - - if ((err = fm_init(client))) - { - FM_ALERT("fm_init ERR:%d\n", err); - goto ERR_EXIT; - } - - if (err = i2c_attach_client(client)) - { - FM_ALERT("i2c_attach_client ERR:%d\n", err); - goto ERR_EXIT; - } - - return 0; - -ERR_EXIT: - kfree(client); - - return err; -} -static int fm_i2c_detach_client(struct i2c_client *client) -{ - int err = 0; - struct fm *fm = i2c_get_clientdata(client); - - FM_DEBUG("fm_i2c_detach_client\n"); - - err = i2c_detach_client(client); - if (err) - { - dev_err(&client->dev, "fm_i2c_detach_client failed\n"); - return err; - } - - fm_destroy(fm); - kfree(client); - - return err; -} -#else -static int fm_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) -{ - int err = -1; - FM_DEBUG("fm_i2c_probe\n"); - //client->timing = 50; - //client->timing = 200; - if ((err = fm_init(client))) - { - FM_ALERT("fm_init ERR:%d\n", err); - goto ERR_EXIT; - } - - return 0; - -ERR_EXIT: - return err; -} -/* -static int fm_for_read_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) -{ - client_for_read = client; - return 0; -} -*/ - -static int fm_i2c_detect(struct i2c_client *client, struct i2c_board_info *info) -{ - struct i2c_adapter *adapter = client->adapter; - if(adapter->nr == 1) - { - FM_DEBUG("fm_i2c_detect\n"); - strcpy(info->type, RDAFM_DEV); - return 0; - } - else - { - return -ENODEV; - } -} -/* -static int fm_for_read_i2c_detect(struct i2c_client *client, int kind, struct i2c_board_info *info) -{ - FM_DEBUG("fm_wifi_i2c_detect\n"); - printk(KERN_DEBUG "####[%s(): %d]\n", __func__, __LINE__); - strcpy(info->type, RDAFM_READ_DEV); - return 0; -} -*/ - -static int fm_i2c_remove(struct i2c_client *client) -{ - int err = 0; - struct fm *fm = i2c_get_clientdata(client); - - FM_DEBUG("fm_i2c_remove\n"); - if(fm) - { - fm_destroy(fm); - fm = NULL; - } - - return err; -} -/* -static int fm_for_read_i2c_remove(struct i2c_client *client) -{ - return 0; -} -*/ -#endif - -static int mt_fm_probe(struct platform_device *pdev) -{ - int err = -1; - FM_ALERT("mt_fm_probe\n"); - - /* - printk(KERN_DEBUG "####[%s(): %d]\n", __func__, __LINE__); - err = i2c_add_driver(&RDAFM_for_read_driver); - if (err) - { - FM_ALERT("i2c err\n"); - } - */ - - // Open I2C driver - err = i2c_add_driver(&RDAFM_driver); - if (err) - { - FM_ALERT("i2c err\n"); - } - - return err; -} - -static int mt_fm_remove(struct platform_device *pdev) -{ - FM_ALERT("mt_fm_remove\n"); - i2c_del_driver(&RDAFM_driver); - - return 0; -} - - -static struct platform_driver mt_fm_dev_drv = -{ - .probe = mt_fm_probe, - .remove = mt_fm_remove, -#if 0//def CONFIG_PM //Not need now - .suspend = mt_fm_suspend, - .resume = mt_fm_resume, -#endif - .driver = { - .name = FM_NAME, - .owner = THIS_MODULE, - } -}; - - - -#if defined(MTK_MT6515) -static void fm_release(struct device * dev) {} - -static struct platform_device mt_fm_device = { - .name = FM_NAME, - .id = 0, - .dev = { - .release = fm_release, - }, - -}; -#endif - -static void fm_test_tune() -{ - struct fm *fm; - struct fm_tune_parm parm; - - fm_powerup(fm, &parm); -} - -static struct i2c_client *rda_fm=NULL; - -#define RDA_FM_ADDR (0x11) -#define RDA_FM_I2C_DEVNAME "RDA_FM" -struct i2c_board_info rda_fm_i2c_board_info = { - .type = RDA_FM_I2C_DEVNAME, - .flags = 0x00, - .addr = RDA_FM_ADDR, - .platform_data = NULL, - .archdata = NULL, - .irq = -1, -}; - -static int rda_i2c_register_device (struct i2c_board_info *ts_i2c_bi,struct i2c_client **l_client) -{ - struct i2c_adapter *adapter = NULL; - - adapter = i2c_get_adapter(4); - - if (NULL == adapter) { - printk("can not get i2c adapter, client address error\n"); - return -1; - } - *l_client = i2c_new_device(adapter, ts_i2c_bi); - if (*l_client == NULL) { - printk("allocate i2c client failed\n"); - return -1; - } - i2c_put_adapter(adapter); - return 0; -} - -static void rda_i2c_unregister_device(struct i2c_client *l_client) -{ - if (l_client != NULL) - { - i2c_unregister_device(l_client); - l_client = NULL; - } -} - - - -/* - * mt_fm_init - */ -static int __init mt_fm_init(void) -{ - int err = 0; - rda_i2c_register_device(&rda_fm_i2c_board_info,&rda_fm); - - FM_ALERT("mt_fm_init\n"); -#if defined(MTK_MT6515) - err = platform_device_register(&mt_fm_device); - if(err){ - FM_ALERT("platform_device_register fail\n"); - return err; - }else{ - FM_ALERT("platform_device_register success\n"); - } -#endif - err = platform_driver_register(&mt_fm_dev_drv); - if (err) - { - FM_ALERT("platform_driver_register failed\n"); - }else{ - FM_ALERT("platform_driver_register success\n"); - } - - return err; -} - -/* - * mt_fm_exit - */ -static void __exit mt_fm_exit(void) -{ - FM_ALERT("mt_fm_exit\n"); - platform_driver_unregister(&mt_fm_dev_drv); -#if defined(MTK_MT6515) - platform_device_unregister(&mt_fm_device); -#endif - - rda_i2c_unregister_device(rda_fm); - -} - -module_init(mt_fm_init); -module_exit(mt_fm_exit); - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("MediaTek FM Driver"); -MODULE_AUTHOR("William Chung "); - - -- cgit