📄 tas_common.c
字号:
#include <linux/module.h>#include <linux/slab.h>#include <linux/proc_fs.h>#include <linux/ioport.h>#include <linux/sysctl.h>#include <linux/types.h>#include <linux/i2c.h>#include <linux/init.h>#include <linux/soundcard.h>#include <asm/uaccess.h>#include <asm/errno.h>#include <asm/io.h>#include <asm/prom.h>#include "tas_common.h"#define CALL0(proc) \ do { \ struct tas_data_t *self; \ if (!tas_client || driver_hooks == NULL) \ return -1; \ self = dev_get_drvdata(&tas_client->dev); \ if (driver_hooks->proc) \ return driver_hooks->proc(self); \ else \ return -EINVAL; \ } while (0)#define CALL(proc,arg...) \ do { \ struct tas_data_t *self; \ if (!tas_client || driver_hooks == NULL) \ return -1; \ self = dev_get_drvdata(&tas_client->dev); \ if (driver_hooks->proc) \ return driver_hooks->proc(self, ## arg); \ else \ return -EINVAL; \ } while (0)static u8 tas_i2c_address = 0x34;static struct i2c_client *tas_client;static struct device_node* tas_node;static int tas_attach_adapter(struct i2c_adapter *);static int tas_detach_client(struct i2c_client *);struct i2c_driver tas_driver = { .owner = THIS_MODULE, .name = "tas", .flags = I2C_DF_NOTIFY, .attach_adapter = tas_attach_adapter, .detach_client = tas_detach_client,};struct tas_driver_hooks_t *driver_hooks;inttas_register_driver(struct tas_driver_hooks_t *hooks){ driver_hooks = hooks; return 0;}inttas_get_mixer_level(int mixer, uint *level){ CALL(get_mixer_level,mixer,level);}inttas_set_mixer_level(int mixer,uint level){ CALL(set_mixer_level,mixer,level);}inttas_enter_sleep(void){ CALL0(enter_sleep);}inttas_leave_sleep(void){ CALL0(leave_sleep);}inttas_supported_mixers(void){ CALL0(supported_mixers);}inttas_mixer_is_stereo(int mixer){ CALL(mixer_is_stereo,mixer);}inttas_stereo_mixers(void){ CALL0(stereo_mixers);}inttas_output_device_change(int device_id,int layout_id,int speaker_id){ CALL(output_device_change,device_id,layout_id,speaker_id);}inttas_device_ioctl(u_int cmd, u_long arg){ CALL(device_ioctl,cmd,arg);}inttas_post_init(void){ CALL0(post_init);}static inttas_detect_client(struct i2c_adapter *adapter, int address){ static const char *client_name = "tas Digital Equalizer"; struct i2c_client *new_client; int rc = -ENODEV; if (!driver_hooks) { printk(KERN_ERR "tas_detect_client called with no hooks !\n"); return -ENODEV; } new_client = kmalloc(sizeof(*new_client), GFP_KERNEL); if (!new_client) return -ENOMEM; memset(new_client, 0, sizeof(*new_client)); new_client->addr = address; new_client->adapter = adapter; new_client->driver = &tas_driver; strlcpy(new_client->name, client_name, DEVICE_NAME_SIZE); if (driver_hooks->init(new_client)) goto bail; /* Tell the i2c layer a new client has arrived */ if (i2c_attach_client(new_client)) { driver_hooks->uninit(dev_get_drvdata(&new_client->dev)); goto bail; } tas_client = new_client; return 0; bail: tas_client = NULL; kfree(new_client); return rc;}static inttas_attach_adapter(struct i2c_adapter *adapter){ if (!strncmp(adapter->name, "mac-io", 6)) return tas_detect_client(adapter, tas_i2c_address); return 0;}static inttas_detach_client(struct i2c_client *client){ if (client == tas_client) { driver_hooks->uninit(dev_get_drvdata(&client->dev)); i2c_detach_client(client); kfree(client); } return 0;}voidtas_cleanup(void){ i2c_del_driver(&tas_driver);}int __inittas_init(int driver_id, const char *driver_name){ u32* paddr; printk(KERN_INFO "tas driver [%s])\n", driver_name);#ifndef CONFIG_I2C_KEYWEST request_module("i2c-keywest");#endif tas_node = find_devices("deq"); if (tas_node == NULL) return -ENODEV; paddr = (u32 *)get_property(tas_node, "i2c-address", NULL); if (paddr) { tas_i2c_address = (*paddr) >> 1; printk(KERN_INFO "using i2c address: 0x%x from device-tree\n", tas_i2c_address); } else printk(KERN_INFO "using i2c address: 0x%x (default)\n", tas_i2c_address); return i2c_add_driver(&tas_driver);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -