429 lines
15 KiB
C
429 lines
15 KiB
C
|
#include <asm/io.h>
|
||
|
#include <asm/uaccess.h>
|
||
|
#include <linux/cdev.h>
|
||
|
#include <linux/device.h>
|
||
|
#include <linux/fs.h>
|
||
|
#include <linux/gpio.h>
|
||
|
#include <linux/init.h>
|
||
|
#include <linux/kernel.h>
|
||
|
#include <linux/module.h>
|
||
|
#include <linux/sched.h>
|
||
|
#include <linux/sysfs.h>
|
||
|
#include <linux/timer.h>
|
||
|
#include <linux/workqueue.h>
|
||
|
//#include <linux/stdlib.h>
|
||
|
#include <linux/stat.h>
|
||
|
#include <linux/string.h>
|
||
|
|
||
|
// unsigned char toupad_get_key(void);
|
||
|
// void tipa_set_vol(unsigned char abs_vol);
|
||
|
int at_8740_write(unsigned char *pbuf, unsigned int len);
|
||
|
int at_8740_read(unsigned char *pbuf, unsigned int len);
|
||
|
void at_8740_wakeup(void);
|
||
|
|
||
|
static unsigned int map_io_base;
|
||
|
#define D_IO_BASE map_io_base
|
||
|
#define D_IO_BASE_PHY (0x01c20800)
|
||
|
#define D_IO_LEN (0x400)
|
||
|
#define D_IO_A (0)
|
||
|
#define D_IO_B (1)
|
||
|
#define D_IO_C (2)
|
||
|
#define D_IO_D (3)
|
||
|
#define D_IO_E (4)
|
||
|
#define D_IO_F (5)
|
||
|
#define D_IO_G (6)
|
||
|
#define D_IO_H (7)
|
||
|
#define D_IO_I (8)
|
||
|
#define D_IO_CFG0(x) (D_IO_BASE + (x * 0x24) + 0x00)
|
||
|
#define D_IO_CFG1(x) (D_IO_BASE + (x * 0x24) + 0x04)
|
||
|
#define D_IO_CFG2(x) (D_IO_BASE + (x * 0x24) + 0x08)
|
||
|
#define D_IO_CFG3(x) (D_IO_BASE + (x * 0x24) + 0x0c)
|
||
|
#define D_IO_DAT(x) (D_IO_BASE + (x * 0x24) + 0x10)
|
||
|
#define D_IO_DRV0(x) (D_IO_BASE + (x * 0x24) + 0x14)
|
||
|
#define D_IO_DRV1(x) (D_IO_BASE + (x * 0x24) + 0x18)
|
||
|
#define D_IO_PUL0(x) (D_IO_BASE + (x * 0x24) + 0x1c)
|
||
|
#define D_IO_PUL1(x) (D_IO_BASE + (x * 0x24) + 0x20)
|
||
|
|
||
|
int cx20810_set_mode(int mode, int index);
|
||
|
|
||
|
typedef struct {
|
||
|
unsigned int opcode;
|
||
|
unsigned int param[3];
|
||
|
} t_data_unit;
|
||
|
|
||
|
enum {
|
||
|
eDU_RESVER = 0,
|
||
|
eDU_IVW_PRESET_TIME,
|
||
|
eDU_REC_TYPE,
|
||
|
eDU_IVW_POS_INFO,
|
||
|
eDU_MAX
|
||
|
};
|
||
|
|
||
|
t_data_unit database[eDU_MAX];
|
||
|
|
||
|
static int major_num;
|
||
|
static struct class *p_class;
|
||
|
static struct device *p_fpga;
|
||
|
static struct device *p_reg_debug;
|
||
|
static struct device *p_dsp_settings;
|
||
|
static struct device *p_au;
|
||
|
static struct device *p_tk;
|
||
|
static struct device *p_vol;
|
||
|
static struct device *p_vol2;
|
||
|
static struct device *p_8740;
|
||
|
static struct device *p_8740_wakeup;
|
||
|
|
||
|
static unsigned int param_config;
|
||
|
|
||
|
static struct kset *kset_vendor;
|
||
|
static struct kobject kobj_pa;
|
||
|
|
||
|
static ssize_t gen_attr_show(struct kobject *kobj, struct attribute *attr,
|
||
|
char *buf) {
|
||
|
strcpy(buf, "wocao");
|
||
|
return strlen(buf);
|
||
|
}
|
||
|
|
||
|
static ssize_t gen_attr_store(struct kobject *kobj, struct attribute *attr,
|
||
|
const char *buf, size_t count) {
|
||
|
int i = simple_strtol(buf, (char **)(buf + strlen(buf) - 1), 0);
|
||
|
printk("vol=%ddb", i);
|
||
|
// tipa_set_vol(2 * (24-i));
|
||
|
return count;
|
||
|
}
|
||
|
|
||
|
struct attribute gen_vol_set = {
|
||
|
.name = "vol_set",
|
||
|
.mode = S_IRWXUGO,
|
||
|
};
|
||
|
|
||
|
struct attribute *gen_attr_group[] = {
|
||
|
&gen_vol_set,
|
||
|
NULL,
|
||
|
};
|
||
|
|
||
|
static const struct sysfs_ops gen_ops = {
|
||
|
.show = gen_attr_show,
|
||
|
.store = gen_attr_store,
|
||
|
};
|
||
|
|
||
|
static void gen_release(struct kobject *k) {
|
||
|
// nothing to do
|
||
|
}
|
||
|
|
||
|
static struct kobj_type gen_ktype = {
|
||
|
.sysfs_ops = &gen_ops,
|
||
|
.default_attrs = gen_attr_group,
|
||
|
.release = gen_release,
|
||
|
};
|
||
|
|
||
|
static int gp_open(struct inode *pnode, struct file *pfile) {
|
||
|
int major = MAJOR(pnode->i_rdev);
|
||
|
int minor = MINOR(pnode->i_rdev);
|
||
|
|
||
|
if (minor == 0) {
|
||
|
pfile->private_data = (void *)p_fpga;
|
||
|
} else if (minor == 1) {
|
||
|
pfile->private_data = (void *)p_reg_debug;
|
||
|
} else if (minor == 2) {
|
||
|
pfile->private_data = (void *)p_dsp_settings;
|
||
|
} else if (minor == 3) {
|
||
|
pfile->private_data = (void *)p_au;
|
||
|
} else if (minor == 4) {
|
||
|
pfile->private_data = (void *)p_tk;
|
||
|
} else if (minor == 5) {
|
||
|
pfile->private_data = (void *)p_vol;
|
||
|
}
|
||
|
// else if(minor == 6)
|
||
|
// {
|
||
|
// pfile->private_data = (void*)p_8740;
|
||
|
// }
|
||
|
// else if(minor == 7)
|
||
|
// {
|
||
|
// pfile->private_data = (void*)p_8740_wakeup;
|
||
|
// }
|
||
|
else {
|
||
|
pfile->private_data = NULL;
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static int gp_close(struct inode *pnode, struct file *pfile) { return 0; }
|
||
|
|
||
|
static ssize_t gp_read(struct file *pfile, char __user *puser, size_t len,
|
||
|
loff_t *poff) {
|
||
|
if (pfile->private_data == p_fpga) {
|
||
|
return 0;
|
||
|
} else if (pfile->private_data == p_reg_debug) {
|
||
|
unsigned int base_addr = (unsigned int)ioremap(0x1C22400, 0x100);
|
||
|
unsigned int i;
|
||
|
for (i = 0; i <= 0x3C; i += 4) {
|
||
|
printk("[i2s1] addr:0x%x val:0x%x\r\n", base_addr + i,
|
||
|
*((unsigned int *)(base_addr + i)));
|
||
|
}
|
||
|
return len;
|
||
|
} else if (pfile->private_data == p_au) {
|
||
|
t_data_unit tmp_data;
|
||
|
copy_from_user((void *)&tmp_data, puser, len);
|
||
|
if (tmp_data.opcode < eDU_MAX) {
|
||
|
copy_to_user(puser, &database[tmp_data.opcode],
|
||
|
sizeof(t_data_unit));
|
||
|
return len;
|
||
|
} else {
|
||
|
return 0;
|
||
|
}
|
||
|
}
|
||
|
// else if(pfile->private_data == p_tk)
|
||
|
// {
|
||
|
// unsigned char tmp = toupad_get_key();
|
||
|
// copy_to_user(puser, &tmp, sizeof(unsigned char));
|
||
|
// return len;
|
||
|
// }
|
||
|
// else if(pfile->private_data == p_8740)
|
||
|
// {
|
||
|
// unsigned char * pbuf;
|
||
|
// pbuf = kmalloc(len, GFP_KERNEL);
|
||
|
// printk("8740 nread:%d\r\n", at_8740_read(pbuf, len));
|
||
|
// copy_to_user(puser, pbuf, len);
|
||
|
// kfree(pbuf);
|
||
|
// return len;
|
||
|
// }
|
||
|
// else if(pfile->private_data == p_8740_wakeup)
|
||
|
// {
|
||
|
// return len;
|
||
|
// }
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
enum {
|
||
|
CX20810_NORMAL_MODE = 0,
|
||
|
CX20810_NORMAL_MODE_SIMPLE,
|
||
|
CX20810_NIRMAL_MODE_CODEC3,
|
||
|
CX20810_NIRMAL_MODE_CODEC3_SIMPLE,
|
||
|
CX20810_96K_16BIT_MODE,
|
||
|
CX20810_48K_16BIT_MODE,
|
||
|
};
|
||
|
|
||
|
static ssize_t gp_write(struct file *pfile, const char __user *puser,
|
||
|
size_t len, loff_t *poff) {
|
||
|
if (pfile->private_data == p_fpga) {
|
||
|
copy_from_user((void *)¶m_config, puser, len);
|
||
|
switch (param_config) {
|
||
|
case 0:
|
||
|
printk("fpga_config:mode0\r\n");
|
||
|
// cx20810_set_mode(CX20810_NORMAL_MODE, 0);
|
||
|
// cx20810_set_mode(CX20810_NORMAL_MODE, 1);
|
||
|
// cx20810_set_mode(CX20810_NORMAL_MODE, 2);
|
||
|
// writel((readl(D_IO_CFG0(D_IO_D)) & ~0x7000000) |
|
||
|
// 0x1000000, D_IO_CFG0(D_IO_D));
|
||
|
// writel((readl(D_IO_DAT(D_IO_D)) & ~(1 << 6)),
|
||
|
// D_IO_DAT(D_IO_D));
|
||
|
// writel((readl(D_IO_CFG0(D_IO_D)) & ~0x7000) |
|
||
|
// 0x1000, D_IO_CFG0(D_IO_D));
|
||
|
// writel((readl(D_IO_DAT(D_IO_D)) & ~(1 << 3)),
|
||
|
// D_IO_DAT(D_IO_D));
|
||
|
// writel((readl(D_IO_CFG0(D_IO_D)) & ~0x70000) |
|
||
|
// 0x10000, D_IO_CFG0(D_IO_D));
|
||
|
// writel((readl(D_IO_DAT(D_IO_D)) & ~(1 << 4)),
|
||
|
// D_IO_DAT(D_IO_D));
|
||
|
writel((readl(D_IO_CFG0(D_IO_E)) & ~0x70000) | 0x10000,
|
||
|
D_IO_CFG0(D_IO_E));
|
||
|
writel((readl(D_IO_DAT(D_IO_E)) & ~(1 << 4)), D_IO_DAT(D_IO_E));
|
||
|
writel((readl(D_IO_CFG0(D_IO_H)) & ~0x70000000) | 0x10000000,
|
||
|
D_IO_CFG0(D_IO_H));
|
||
|
writel((readl(D_IO_DAT(D_IO_H)) & ~(1 << 7)), D_IO_DAT(D_IO_H));
|
||
|
writel((readl(D_IO_CFG0(D_IO_E)) & ~0x7000) | 0x1000,
|
||
|
D_IO_CFG0(D_IO_E));
|
||
|
writel((readl(D_IO_DAT(D_IO_E)) & ~(1 << 3)), D_IO_DAT(D_IO_E));
|
||
|
break;
|
||
|
case 1:
|
||
|
printk("fpga_config:mode1\r\n");
|
||
|
cx20810_set_mode(CX20810_96K_16BIT_MODE, 1);
|
||
|
// writel((readl(D_IO_CFG0(D_IO_D)) & ~0x7000000) |
|
||
|
// 0x1000000, D_IO_CFG0(D_IO_D));
|
||
|
// writel((readl(D_IO_DAT(D_IO_D)) & ~(1 << 6)),
|
||
|
// D_IO_DAT(D_IO_D));
|
||
|
// writel((readl(D_IO_CFG0(D_IO_D)) & ~0x7000) |
|
||
|
// 0x1000, D_IO_CFG0(D_IO_D));
|
||
|
// writel((readl(D_IO_DAT(D_IO_D)) | (1 << 3)),
|
||
|
// D_IO_DAT(D_IO_D));
|
||
|
// writel((readl(D_IO_CFG0(D_IO_D)) & ~0x70000) |
|
||
|
// 0x10000, D_IO_CFG0(D_IO_D));
|
||
|
// writel((readl(D_IO_DAT(D_IO_D)) & ~(1 << 4)),
|
||
|
// D_IO_DAT(D_IO_D));
|
||
|
writel((readl(D_IO_CFG0(D_IO_E)) & ~0x70000) | 0x10000,
|
||
|
D_IO_CFG0(D_IO_E));
|
||
|
writel((readl(D_IO_DAT(D_IO_E)) & ~(1 << 4)), D_IO_DAT(D_IO_E));
|
||
|
writel((readl(D_IO_CFG0(D_IO_H)) & ~0x70000000) | 0x10000000,
|
||
|
D_IO_CFG0(D_IO_H));
|
||
|
writel((readl(D_IO_DAT(D_IO_H)) & ~(1 << 7)), D_IO_DAT(D_IO_H));
|
||
|
writel((readl(D_IO_CFG0(D_IO_E)) & ~0x7000) | 0x1000,
|
||
|
D_IO_CFG0(D_IO_E));
|
||
|
writel((readl(D_IO_DAT(D_IO_E)) | (1 << 3)), D_IO_DAT(D_IO_E));
|
||
|
break;
|
||
|
case 2:
|
||
|
printk("fpga_config:mode2\r\n");
|
||
|
cx20810_set_mode(CX20810_48K_16BIT_MODE, 0);
|
||
|
// writel((readl(D_IO_CFG0(D_IO_D)) & ~0x7000000) |
|
||
|
// 0x1000000, D_IO_CFG0(D_IO_D));
|
||
|
// writel((readl(D_IO_DAT(D_IO_D)) & ~(1 << 6)),
|
||
|
// D_IO_DAT(D_IO_D));
|
||
|
// writel((readl(D_IO_CFG0(D_IO_D)) & ~0x7000) |
|
||
|
// 0x1000, D_IO_CFG0(D_IO_D));
|
||
|
// writel((readl(D_IO_DAT(D_IO_D)) & ~(1 << 3)),
|
||
|
// D_IO_DAT(D_IO_D));
|
||
|
// writel((readl(D_IO_CFG0(D_IO_D)) & ~0x70000) |
|
||
|
// 0x10000, D_IO_CFG0(D_IO_D));
|
||
|
// writel((readl(D_IO_DAT(D_IO_D)) | (1 << 4)),
|
||
|
// D_IO_DAT(D_IO_D));
|
||
|
writel((readl(D_IO_CFG0(D_IO_E)) & ~0x70000) | 0x10000,
|
||
|
D_IO_CFG0(D_IO_E));
|
||
|
writel((readl(D_IO_DAT(D_IO_E)) & ~(1 << 4)), D_IO_DAT(D_IO_E));
|
||
|
writel((readl(D_IO_CFG0(D_IO_H)) & ~0x70000000) | 0x10000000,
|
||
|
D_IO_CFG0(D_IO_H));
|
||
|
writel((readl(D_IO_DAT(D_IO_H)) | (1 << 7)), D_IO_DAT(D_IO_H));
|
||
|
writel((readl(D_IO_CFG0(D_IO_E)) & ~0x7000) | 0x1000,
|
||
|
D_IO_CFG0(D_IO_E));
|
||
|
writel((readl(D_IO_DAT(D_IO_E)) & ~(1 << 3)), D_IO_DAT(D_IO_E));
|
||
|
break;
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
return len;
|
||
|
} else if (pfile->private_data == p_reg_debug) {
|
||
|
return len;
|
||
|
} else if (pfile->private_data == p_dsp_settings) {
|
||
|
return len;
|
||
|
} else if (pfile->private_data == p_au) {
|
||
|
t_data_unit tmp_data;
|
||
|
copy_from_user((void *)&tmp_data, puser, len);
|
||
|
if (tmp_data.opcode < eDU_MAX) {
|
||
|
memcpy(&database[tmp_data.opcode], &tmp_data, sizeof(t_data_unit));
|
||
|
return len;
|
||
|
} else {
|
||
|
return 0;
|
||
|
}
|
||
|
} else if (pfile->private_data == p_vol) {
|
||
|
unsigned char tmp;
|
||
|
copy_from_user((void *)&tmp, puser, len);
|
||
|
// tipa_set_vol(tmp);
|
||
|
return len;
|
||
|
}
|
||
|
// else if(pfile->private_data == p_8740)
|
||
|
// {
|
||
|
// unsigned char * pbuf;
|
||
|
// pbuf = kmalloc(len, GFP_KERNEL);
|
||
|
// copy_from_user((void*)pbuf, puser, len);
|
||
|
// printk("8740 nwrite:%d\r\n", at_8740_write(pbuf, len));
|
||
|
// kfree(pbuf);
|
||
|
// return len;
|
||
|
// }
|
||
|
// else if(pfile->private_data == p_8740_wakeup)
|
||
|
// {
|
||
|
// printk("8740 wakeup\r\n");
|
||
|
// at_8740_wakeup();
|
||
|
// return len;
|
||
|
// }
|
||
|
else {
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static struct file_operations gp_fops = {
|
||
|
.owner = THIS_MODULE,
|
||
|
.open = gp_open,
|
||
|
.release = gp_close,
|
||
|
.read = gp_read,
|
||
|
.write = gp_write,
|
||
|
};
|
||
|
|
||
|
static int __init fpga_config_init(void) {
|
||
|
D_IO_BASE = (unsigned int)ioremap(D_IO_BASE_PHY, D_IO_LEN);
|
||
|
if (!D_IO_BASE) {
|
||
|
printk("[gen_prov] init gpio err\r\n");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
kset_vendor = kset_create_and_add("vendor", NULL, NULL);
|
||
|
kobj_pa.kset = kset_vendor;
|
||
|
kobject_init_and_add(&kobj_pa, &gen_ktype, NULL, "pa");
|
||
|
|
||
|
major_num = register_chrdev(0, "fpga_chr", &gp_fops);
|
||
|
if (major_num < 0) {
|
||
|
printk("reg_chr_err\n");
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
p_class = class_create(THIS_MODULE, "fpga_class");
|
||
|
if (p_class == NULL) {
|
||
|
printk("class create err\n");
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
p_fpga =
|
||
|
device_create(p_class, NULL, MKDEV(major_num, 0), NULL, "fpga_config");
|
||
|
if (p_fpga == NULL) {
|
||
|
printk("device_create err:fpga\n");
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
p_reg_debug =
|
||
|
device_create(p_class, NULL, MKDEV(major_num, 1), NULL, "reg_debug");
|
||
|
if (p_reg_debug == NULL) {
|
||
|
printk("device_create err:reg_debug\n");
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
p_dsp_settings =
|
||
|
device_create(p_class, NULL, MKDEV(major_num, 2), NULL, "dsp_settings");
|
||
|
if (p_dsp_settings == NULL) {
|
||
|
printk("device_create err:p_dsp_settings\n");
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
p_au = device_create(p_class, NULL, MKDEV(major_num, 3), NULL, "au_base");
|
||
|
if (p_au == NULL) {
|
||
|
printk("device_create err:au_base\n");
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
p_tk = device_create(p_class, NULL, MKDEV(major_num, 4), NULL, "touch_key");
|
||
|
if (p_tk == NULL) {
|
||
|
printk("device_create err:touch_key\n");
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
p_vol = device_create(p_class, NULL, MKDEV(major_num, 5), NULL, "vbox_vol");
|
||
|
if (p_vol == NULL) {
|
||
|
printk("device_create err:vbox_vol\n");
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
// p_8740 = device_create(p_class, NULL, MKDEV(major_num, 6), NULL,
|
||
|
// "atml_sec"); if(p_8740 == NULL)
|
||
|
// {
|
||
|
// printk("device_create err:p_8740\n");
|
||
|
// return 1;
|
||
|
// }
|
||
|
|
||
|
// p_8740_wakeup = device_create(p_class, NULL, MKDEV(major_num, 7),
|
||
|
// NULL, "atml_sec_wake"); if(p_8740_wakeup == NULL)
|
||
|
// {
|
||
|
// printk("device_create err:p_8740\n");
|
||
|
// return 1;
|
||
|
// }
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
//module_init(fpga_config_init);
|
||
|
|
||
|
static void __exit fpga_config_exit(void) {}
|
||
|
module_exit(fpga_config_exit);
|
||
|
|
||
|
/* Module information */
|
||
|
MODULE_AUTHOR("feitao");
|
||
|
MODULE_DESCRIPTION("fpga config");
|
||
|
MODULE_LICENSE("GPL");
|
||
|
MODULE_ALIAS("platform:fpga");
|