Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]
Version: [ 2.6.11.8 ] [ 2.6.25 ] [ 2.6.25.8 ] [ 2.6.31.13 ] Architecture: [ i386 ]
  1 #include <linux/module.h>
  2 #include <linux/slab.h>
  3 #include <linux/proc_fs.h>
  4 #include <linux/ioport.h>
  5 #include <linux/sysctl.h>
  6 #include <linux/types.h>
  7 #include <linux/i2c.h>
  8 #include <linux/init.h>
  9 #include <linux/soundcard.h>
 10 #include <asm/uaccess.h>
 11 #include <asm/errno.h>
 12 #include <asm/io.h>
 13 #include <asm/prom.h>
 14 
 15 #include "tas_common.h"
 16 
 17 #define CALL0(proc)                                                             \
 18         do {                                                                    \
 19                 struct tas_data_t *self;                                        \
 20                 if (!tas_client || driver_hooks == NULL)                        \
 21                         return -1;                                              \
 22                 self = dev_get_drvdata(&tas_client->dev);                       \
 23                 if (driver_hooks->proc)                                         \
 24                         return driver_hooks->proc(self);                        \
 25                 else                                                            \
 26                         return -EINVAL;                                         \
 27         } while (0)
 28 
 29 #define CALL(proc,arg...)                                                       \
 30         do {                                                                    \
 31                 struct tas_data_t *self;                                        \
 32                 if (!tas_client || driver_hooks == NULL)                        \
 33                         return -1;                                              \
 34                 self = dev_get_drvdata(&tas_client->dev);                       \
 35                 if (driver_hooks->proc)                                         \
 36                         return driver_hooks->proc(self, ## arg);                \
 37                 else                                                            \
 38                         return -EINVAL;                                         \
 39         } while (0)
 40 
 41 
 42 static u8 tas_i2c_address = 0x34;
 43 static struct i2c_client *tas_client;
 44 static struct device_node* tas_node;
 45 
 46 static int tas_attach_adapter(struct i2c_adapter *);
 47 static int tas_detach_client(struct i2c_client *);
 48 
 49 struct i2c_driver tas_driver = {
 50         .owner          = THIS_MODULE,
 51         .name           = "tas",
 52         .flags          = I2C_DF_NOTIFY,
 53         .attach_adapter = tas_attach_adapter,
 54         .detach_client  = tas_detach_client,
 55 };
 56 
 57 struct tas_driver_hooks_t *driver_hooks;
 58 
 59 int
 60 tas_register_driver(struct tas_driver_hooks_t *hooks)
 61 {
 62         driver_hooks = hooks;
 63         return 0;
 64 }
 65 
 66 int
 67 tas_get_mixer_level(int mixer, uint *level)
 68 {
 69         CALL(get_mixer_level,mixer,level);
 70 }
 71 
 72 int
 73 tas_set_mixer_level(int mixer,uint level)
 74 {
 75         CALL(set_mixer_level,mixer,level);
 76 }
 77 
 78 int
 79 tas_enter_sleep(void)
 80 {
 81         CALL0(enter_sleep);
 82 }
 83 
 84 int
 85 tas_leave_sleep(void)
 86 {
 87         CALL0(leave_sleep);
 88 }
 89 
 90 int
 91 tas_supported_mixers(void)
 92 {
 93         CALL0(supported_mixers);
 94 }
 95 
 96 int
 97 tas_mixer_is_stereo(int mixer)
 98 {
 99         CALL(mixer_is_stereo,mixer);
100 }
101 
102 int
103 tas_stereo_mixers(void)
104 {
105         CALL0(stereo_mixers);
106 }
107 
108 int
109 tas_output_device_change(int device_id,int layout_id,int speaker_id)
110 {
111         CALL(output_device_change,device_id,layout_id,speaker_id);
112 }
113 
114 int
115 tas_device_ioctl(u_int cmd, u_long arg)
116 {
117         CALL(device_ioctl,cmd,arg);
118 }
119 
120 int
121 tas_post_init(void)
122 {
123         CALL0(post_init);
124 }
125 
126 static int
127 tas_detect_client(struct i2c_adapter *adapter, int address)
128 {
129         static const char *client_name = "tas Digital Equalizer";
130         struct i2c_client *new_client;
131         int rc = -ENODEV;
132 
133         if (!driver_hooks) {
134                 printk(KERN_ERR "tas_detect_client called with no hooks !\n");
135                 return -ENODEV;
136         }
137         
138         new_client = kmalloc(sizeof(*new_client), GFP_KERNEL);
139         if (!new_client)
140                 return -ENOMEM;
141         memset(new_client, 0, sizeof(*new_client));
142 
143         new_client->addr = address;
144         new_client->adapter = adapter;
145         new_client->driver = &tas_driver;
146         strlcpy(new_client->name, client_name, DEVICE_NAME_SIZE);
147 
148         if (driver_hooks->init(new_client))
149                 goto bail;
150 
151         /* Tell the i2c layer a new client has arrived */
152         if (i2c_attach_client(new_client)) {
153                 driver_hooks->uninit(dev_get_drvdata(&new_client->dev));
154                 goto bail;
155         }
156 
157         tas_client = new_client;
158         return 0;
159  bail:
160         tas_client = NULL;
161         kfree(new_client);
162         return rc;
163 }
164 
165 static int
166 tas_attach_adapter(struct i2c_adapter *adapter)
167 {
168         if (!strncmp(adapter->name, "mac-io", 6))
169                 return tas_detect_client(adapter, tas_i2c_address);
170         return 0;
171 }
172 
173 static int
174 tas_detach_client(struct i2c_client *client)
175 {
176         if (client == tas_client) {
177                 driver_hooks->uninit(dev_get_drvdata(&client->dev));
178 
179                 i2c_detach_client(client);
180                 kfree(client);
181         }
182         return 0;
183 }
184 
185 void
186 tas_cleanup(void)
187 {
188         i2c_del_driver(&tas_driver);
189 }
190 
191 int __init
192 tas_init(int driver_id, const char *driver_name)
193 {
194         u32* paddr;
195 
196         printk(KERN_INFO "tas driver [%s])\n", driver_name);
197 
198 #ifndef CONFIG_I2C_KEYWEST
199         request_module("i2c-keywest");
200 #endif
201         tas_node = find_devices("deq");
202         if (tas_node == NULL)
203                 return -ENODEV;
204         paddr = (u32 *)get_property(tas_node, "i2c-address", NULL);
205         if (paddr) {
206                 tas_i2c_address = (*paddr) >> 1;
207                 printk(KERN_INFO "using i2c address: 0x%x from device-tree\n",
208                                 tas_i2c_address);
209         } else    
210                 printk(KERN_INFO "using i2c address: 0x%x (default)\n",
211                                 tas_i2c_address);
212 
213         return i2c_add_driver(&tas_driver);
214 }
215 
  This page was automatically generated by the LXR engine.