完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
|
|
相关推荐
1个回答
|
|
之前在做车机相关项目,有FM发射需求,8027这颗芯片,之前大部分都是在单片机使用,很少在linux系统使用,我把他移植成了linux驱动,以下为参考: #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "QN8027.h" #define QN8027_I2C_NAME "QN8027" #define QN8027_I2C_ADDR 0x58 #define QN8027_DEV_NAME "QN8027" static int qn8027_fm_write(struct i2c_client *client, u8 addr, u8 *pdata, int datalen); static int qn8027_fm_read(struct i2c_client *client, u8 addr, u8 *pdata, unsigned int datalen); void QNF_SetRegBit(struct i2c_client *client,u8 reg, u8 bitMask, u8 data_val) ; u16 QNF_GetCh(struct i2c_client *client) ; void QN_ChipInitialization(struct i2c_client *client); UINT8 QNF_SetCh(struct i2c_client *client,u16 freq) ; void QN_ChipInitialization(struct i2c_client *client); static struct i2c_client *Gol_client; struct proc_dir_entry *qn8027_extend_dir; extern void es8316_spk_ctrl(int level); static int qn8027_fm_write(struct i2c_client *client, u8 addr, u8 *pdata, int datalen) { int ret = 0; u8 tmp_buf[128]; unsigned int bytelen = 0; if (datalen > 125) { printk("%s too big datalen = %d!n", __func__, datalen); return -1; } tmp_buf[0] = addr; bytelen++; if (datalen != 0 && pdata != NULL) { memcpy(&tmp_buf[bytelen], pdata, datalen); bytelen += datalen; } ret = i2c_master_send(client, tmp_buf, bytelen); return ret; } static int qn8027_fm_read(struct i2c_client *client, u8 addr, u8 *pdata, unsigned int datalen) { int ret = 0; if (datalen > 126) { printk("%s too big datalen = %d!n", __func__, datalen); return -1; } ret = qn8027_fm_write(client, addr, NULL, 0); if (ret < 0) { printk("%s set data address fail!n", __func__); return ret; } return i2c_master_recv(client, pdata, datalen); } void QNF_SetRegBit(struct i2c_client *client,u8 reg, u8 bitMask, u8 data_val) { u8 temp; int ret; ret= qn8027_fm_read(client,reg,&temp,sizeof(temp)); temp &= (u8)(~bitMask); temp |= data_val & bitMask; qn8027_fm_write(client, reg, &temp, 1); } UINT8 QNF_SetCh(struct i2c_client *client,u16 freq) { // calculate ch parameter used for register setting UINT8 tStep; UINT8 tCh; UINT16 f; f = FREQ2CHREG(freq); // set to reg: CH tCh = (UINT8) f; qn8027_fm_write(client,CH, &tCh,1); // set to reg: CH_STEP qn8027_fm_read(client,CH_STEP,&tStep,1); tStep &= ~CH_CH; tStep |= ((UINT8) (f >> 8) & CH_CH); qn8027_fm_write(client,CH_STEP, &tStep,1); return 1; } u16 QNF_GetCh(struct i2c_client *client) { u8 tCh; u8 tStep; u16 ch = 0; // set to reg: CH_STEP qn8027_fm_read(client,CH_STEP,&tStep,1); tStep &= CH_CH; printk("Step &= CH_CH; ==== %dn",tStep); ch = tStep ; printk(" ch = tStep ; ==== %dn",ch); qn8027_fm_read(client,CH,&tCh,1); printk(" ch = tCh ; ==== %dn",tCh); ch = (ch<<8)+tCh; printk("(ch<<8)+tCh; ==== %dn",ch); return CHREG2FREQ(ch); } void QN_ChipInitialization(struct i2c_client *client) { u8 write_buf; u8 read_buf; int ret = 0; //write_buf = 0x81; //ret = qn8027_fm_write(client, 0x00, &write_buf, 1); //msleep(200); write_buf = 0x20; ret = qn8027_fm_write(client, 0x03, &write_buf, 1); msleep(200); write_buf = 0x21; ret = qn8027_fm_write(client, 0x04, &write_buf, 1); msleep(200); QNF_SetRegBit(client,0x00,0x40,0x40); msleep(200); //delay 20 ms write_buf = 0xe4; ret = qn8027_fm_write(client, 0x18, &write_buf, 1); msleep(200); write_buf = 0xf0; qn8027_fm_write(client, 0x1b, &write_buf, 1); msleep(200); write_buf = 0xB9; ret = qn8027_fm_write(client, 0x02, &write_buf, 1); msleep(200); write_buf = 0x20; ret = qn8027_fm_write(client, 0x00, &write_buf, 1); ret= qn8027_fm_read(client,0x00,&read_buf,sizeof(read_buf)); printk("intqn8027_fm_read ===================== %xn",read_buf); } static int qn8027_fm_probe(struct i2c_client *client, const struct i2c_device_id *id) { int ch; int ret = 0; u8 write_buf; QN_ChipInitialization(client); ch = QNF_GetCh(client); Gol_client = client; printk("qn8027 ch ========================= %dn",ch); return 0; } static int qn8027_fm_remove(struct i2c_client *client) { printk("qn8027_fm_remove ========================= n"); return 0; } static int qn8027_open(struct inode *inode, struct file *file) { return nonseekable_open(inode, file); } static int qn8027_release(struct inode *inode, struct file *file) { return 0; } static ssize_t qn8027_read(struct file *file, char __user * usr_buf, size_t len, loff_t * f_pos) { int ch = 0; ch = QNF_GetCh(Gol_client); copy_to_user(usr_buf,&ch,1); printk("qn8027_read =================== %dn",ch); return 0; } static ssize_t qn8027_write(struct file *file, const char __user * usr_buf, size_t len, loff_t * f_pos){ char fm_buf[40]; copy_from_user(&fm_buf,usr_buf,len); QNF_SetCh(Gol_client,10000); printk("qn8027_write ===================n"); return len; } static ssize_t qn8027_proc_write(struct file *file, const char __user *usr_buf, size_t count, loff_t *pos){ char fm_buf[40]; int value; char write_buf; copy_from_user(&fm_buf,usr_buf,count); fm_buf[count] = ' |