4 * MediaTek <www.MediaTek.com>
5 * Hongcheng <hongcheng.xia@MediaTek.com>
7 * MT6626 FM Radio Driver -- setup data link
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #include <linux/slab.h>
24 #include <linux/version.h>
25 #include <linux/interrupt.h>
26 #include <linux/cdev.h>
27 #include <asm/uaccess.h>
28 #include <linux/i2c.h>
30 #include "fm_typedef.h"
33 #include "fm_stdlib.h"
35 #include "mt6626_fm.h"
36 #include "mt6626_fm_link.h"
37 #include "mt6626_fm_reg.h"
39 //these functions are defined after Linux2.6.32
40 static int fm_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id);
41 static int fm_i2c_detect(struct i2c_client *client, int kind, struct i2c_board_info *info);
42 static int fm_i2c_remove(struct i2c_client *client);
45 static const struct i2c_device_id fm_i2c_id = {MT6626_DEV, 0};
46 static unsigned short force[] = {MT6626_I2C_PORT, MT6626_SLAVE_ADDR, I2C_CLIENT_END, I2C_CLIENT_END};
47 static const unsigned short * const forces[] = {force, NULL};
48 static struct i2c_client_address_data addr_data = {
52 struct i2c_driver MT6626_driver = {
53 .probe = fm_i2c_probe,
54 .remove = fm_i2c_remove,
55 .detect = fm_i2c_detect,
56 .driver.name = MT6626_DEV,
57 .id_table = &fm_i2c_id,
58 .address_data = &addr_data,
61 static struct i2c_client *g_client;
63 static int fm_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
67 WCN_DBG(FM_NTC | LINK, "%s\n", __func__);
73 static int fm_i2c_detect(struct i2c_client *client, int kind, struct i2c_board_info *info)
75 WCN_DBG(FM_NTC | LINK, "%s\n", __func__);
76 strcpy(info->type, MT6626_DEV);
80 static int fm_i2c_remove(struct i2c_client *client)
82 WCN_DBG(FM_NTC | LINK, "%s\n", __func__);
86 static struct fm_link_event *link_event;
88 fm_s32 fm_link_setup(void* data)
90 if (!(link_event = kzalloc(sizeof(struct fm_link_event), GFP_KERNEL))) {
91 WCN_DBG(FM_ALT | LINK, "kzalloc(fm_link_event) -ENOMEM\n");
95 link_event->ln_event = fm_flag_event_create("ln_evt");
97 if (!link_event->ln_event) {
98 WCN_DBG(FM_ALT | LINK, "create mt6626_ln_event failed\n");
103 fm_flag_event_get(link_event->ln_event);
105 WCN_DBG(FM_NTC | LINK, "fm link setup\n");
106 return i2c_add_driver(&MT6626_driver);
109 fm_s32 fm_link_release(void)
111 fm_flag_event_put(link_event->ln_event);
116 WCN_DBG(FM_NTC | LINK, "fm link release\n");
117 i2c_del_driver(&MT6626_driver);
123 * the low level func to read a rigister
124 * @addr - rigister address
125 * @val - the pointer of target buf
126 * If success, return 0; else error code
128 fm_s32 fm_ctrl_rx(fm_u8 addr, fm_u16 *val)
133 // first, send addr to MT6626
134 n = i2c_master_send(g_client, (fm_u8*) & addr, 1);
137 WCN_DBG(FM_ALT | LINK, "rx 1, [addr=0x%02X] [err=%d]\n", addr, n);
141 // second, receive two byte from MT6626
142 n = i2c_master_recv(g_client, b, 2);
145 WCN_DBG(FM_ALT | LINK, "rx 2, [addr=0x%02X] [err=%d]\n", addr, n);
149 *val = ((fm_u16)b[0] << 8 | (fm_u16)b[1]);
156 * the low level func to write a rigister
157 * @addr - rigister address
158 * @val - value will be writed in the rigister
159 * If success, return 0; else error code
161 fm_s32 fm_ctrl_tx(fm_u8 addr, fm_u16 val)
167 b[1] = (fm_u8)(val >> 8);
168 b[2] = (fm_u8)(val & 0xFF);
170 n = i2c_master_send(g_client, b, 3);
173 WCN_DBG(FM_ALT | LINK, "tx, [addr=0x%02X] [err=%d]\n", addr, n);
181 * fm_cmd_tx() - send cmd to FM firmware and wait event
183 * @len - the length of cmd
184 * @mask - the event flag mask
185 * @ cnt - the retry conter
186 * @timeout - timeout per cmd
187 * Return 0, if success; error code, if failed
189 fm_s32 fm_cmd_tx(fm_u8* buf, fm_u16 len, fm_s32 mask, fm_s32 cnt, fm_s32 timeout, fm_s32(*callback)(struct fm_res_ctx* result))
194 fm_bool fm_wait_stc_done(fm_u32 sec)
198 ret_time = FM_EVENT_WAIT_TIMEOUT(link_event->ln_event, FLAG_TEST, sec);
200 WCN_DBG(FM_WAR | LINK, "wait stc done fail\n");
203 WCN_DBG(FM_DBG | LINK, "wait stc done ok\n");
206 FM_EVENT_CLR(link_event->ln_event, FLAG_TEST);
210 fm_s32 fm_event_parser(fm_s32(*rds_parser)(struct rds_rx_t*, fm_s32))
214 fm_ctrl_rx(FM_MAIN_INTR, &tmp_reg);
216 if (tmp_reg&FM_INTR_STC_DONE) {
218 fm_ctrl_tx(FM_MAIN_INTR, tmp_reg | FM_INTR_STC_DONE);
219 FM_EVENT_SEND(link_event->ln_event, FLAG_TEST);
222 if (tmp_reg&FM_INTR_RDS) {
224 fm_ctrl_tx(FM_MAIN_INTR, tmp_reg | FM_INTR_RDS);
226 /*Handle the RDS data that we get*/
228 rds_parser(NULL, 0); //mt6626 rds lib will get rds raw data by itself
230 WCN_DBG(FM_WAR | LINK, "no method to parse RDS data\n");
237 fm_s32 fm_force_active_event(fm_u32 mask)
239 FM_EVENT_SEND(link_event->ln_event, FLAG_TEST);