upload tizen1.0 source
[kernel/linux-2.6.36.git] / drivers / misc / jack.c
1 /*
2  *  Jack Monitoring Interface
3  *
4  *  Copyright (C) 2009 Samsung Electronics
5  *  Minkyu Kang <mk7.kang@samsung.com>
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License version 2 as
9  * published by the Free Software Foundation.
10  */
11
12 #include <linux/kernel.h>
13 #include <linux/module.h>
14 #include <linux/init.h>
15 #include <linux/platform_device.h>
16 #include <linux/jack.h>
17 #include <linux/slab.h>
18
19 struct jack_data {
20         struct jack_platform_data       *pdata;
21 };
22
23 static struct platform_device *jack_dev;
24
25 static void jack_set_data(struct jack_platform_data *pdata,
26                 const char *name, int value)
27 {
28         if (!strcmp(name, "usb"))
29                 pdata->usb_online = value;
30         else if (!strcmp(name, "charger"))
31                 pdata->charger_online = value;
32         else if (!strcmp(name, "hdmi"))
33                 pdata->hdmi_online = value;
34         else if (!strcmp(name, "earjack"))
35                 pdata->earjack_online = value;
36         else if (!strcmp(name, "earkey"))
37                 pdata->earkey_online = value;
38         else if (!strcmp(name, "ums"))
39                 pdata->ums_online = value;
40         else if (!strcmp(name, "cdrom"))
41                 pdata->cdrom_online = value;
42         else if (!strcmp(name, "jig"))
43                 pdata->jig_online = value;
44         else if (!strcmp(name, "host"))
45                 pdata->host_online = value;
46 }
47
48 int jack_get_data(const char *name)
49 {
50         struct jack_data *jack = platform_get_drvdata(jack_dev);
51
52         if (!strcmp(name, "usb"))
53                 return jack->pdata->usb_online;
54         else if (!strcmp(name, "charger"))
55                 return jack->pdata->charger_online;
56         else if (!strcmp(name, "hdmi"))
57                 return jack->pdata->hdmi_online;
58         else if (!strcmp(name, "earjack"))
59                 return jack->pdata->earjack_online;
60         else if (!strcmp(name, "earkey"))
61                 return jack->pdata->earkey_online;
62         else if (!strcmp(name, "ums"))
63                 return jack->pdata->ums_online;
64         else if (!strcmp(name, "cdrom"))
65                 return jack->pdata->cdrom_online;
66         else if (!strcmp(name, "jig"))
67                 return jack->pdata->jig_online;
68         else if (!strcmp(name, "host"))
69                 return jack->pdata->host_online;
70
71
72         return -EINVAL;
73 }
74 EXPORT_SYMBOL_GPL(jack_get_data);
75
76 void jack_event_handler(const char *name, int value)
77 {
78         struct jack_data *jack = platform_get_drvdata(jack_dev);
79         char env_str[16];
80         char *envp[] = { env_str, NULL };
81
82         jack_set_data(jack->pdata, name, value);
83
84         sprintf(env_str, "CHGDET=%s", name);
85         dev_info(&jack_dev->dev, "jack event %s\n", env_str);
86         kobject_uevent_env(&jack_dev->dev.kobj, KOBJ_CHANGE, envp);
87 }
88 EXPORT_SYMBOL_GPL(jack_event_handler);
89
90 #define JACK_OUTPUT(name)                                               \
91 static ssize_t jack_show_##name(struct device *dev,                     \
92                 struct device_attribute *attr, char *buf)               \
93 {                                                                       \
94         struct jack_data *chip = dev_get_drvdata(dev);                  \
95         return sprintf(buf, "%d\n", chip->pdata->name);                 \
96 }                                                                       \
97 static DEVICE_ATTR(name, S_IRUGO, jack_show_##name, NULL);
98
99 JACK_OUTPUT(usb_online);
100 JACK_OUTPUT(charger_online);
101 JACK_OUTPUT(hdmi_online);
102 JACK_OUTPUT(earjack_online);
103 JACK_OUTPUT(earkey_online);
104 JACK_OUTPUT(jig_online);
105 JACK_OUTPUT(host_online);
106
107 static int jack_device_init(struct jack_data *jack)
108 {
109         struct jack_platform_data *pdata = jack->pdata;
110         int ret;
111
112         if (pdata->usb_online != -1)
113                 ret = device_create_file(&jack_dev->dev,
114                                 &dev_attr_usb_online);
115         if (pdata->charger_online != -1)
116                 ret = device_create_file(&jack_dev->dev,
117                                 &dev_attr_charger_online);
118         if (pdata->hdmi_online != -1)
119                 ret = device_create_file(&jack_dev->dev,
120                                 &dev_attr_hdmi_online);
121         if (pdata->earjack_online != -1)
122                 ret = device_create_file(&jack_dev->dev,
123                                 &dev_attr_earjack_online);
124         if (pdata->earkey_online != -1)
125                 ret = device_create_file(&jack_dev->dev,
126                                 &dev_attr_earkey_online);
127         if (pdata->jig_online != -1)
128                 ret = device_create_file(&jack_dev->dev,
129                                 &dev_attr_jig_online);
130         if (pdata->host_online != -1)
131                 ret = device_create_file(&jack_dev->dev,
132                                 &dev_attr_host_online);
133
134         return 0;
135 }
136
137 static int __devinit jack_probe(struct platform_device *pdev)
138 {
139         struct jack_platform_data *pdata = pdev->dev.platform_data;
140         struct jack_data *jack;
141
142         jack = kzalloc(sizeof(struct jack_data), GFP_KERNEL);
143         if (!jack) {
144                 dev_err(&pdev->dev, "failed to allocate driver data\n");
145                 return -ENOMEM;
146         }
147
148         platform_set_drvdata(pdev, jack);
149         jack_dev = pdev;
150         jack->pdata = pdata;
151
152         jack_device_init(jack);
153
154         return 0;
155 }
156
157 static int __devexit jack_remove(struct platform_device *pdev)
158 {
159         struct jack_platform_data *pdata = pdev->dev.platform_data;
160
161         if (pdata->usb_online != -1)
162                 device_remove_file(&jack_dev->dev, &dev_attr_usb_online);
163         if (pdata->charger_online != -1)
164                 device_remove_file(&jack_dev->dev, &dev_attr_charger_online);
165         if (pdata->hdmi_online != -1)
166                 device_remove_file(&jack_dev->dev, &dev_attr_hdmi_online);
167         if (pdata->earjack_online != -1)
168                 device_remove_file(&jack_dev->dev, &dev_attr_earjack_online);
169         if (pdata->earkey_online != -1)
170                 device_remove_file(&jack_dev->dev, &dev_attr_earkey_online);
171         if (pdata->jig_online != -1)
172                 device_remove_file(&jack_dev->dev, &dev_attr_jig_online);
173         if (pdata->host_online != -1)
174                 device_remove_file(&jack_dev->dev, &dev_attr_host_online);
175
176
177         platform_set_drvdata(pdev, NULL);
178
179         return 0;
180 }
181
182 static struct platform_driver jack_driver = {
183         .probe          = jack_probe,
184         .remove         = __devexit_p(jack_remove),
185         .driver         = {
186                 .name   = "jack",
187                 .owner  = THIS_MODULE,
188         },
189 };
190
191 static int __init jack_init(void)
192 {
193         return platform_driver_register(&jack_driver);
194 }
195 module_init(jack_init);
196
197 static void __exit jack_exit(void)
198 {
199         platform_driver_unregister(&jack_driver);
200 }
201 module_exit(jack_exit);
202
203 MODULE_AUTHOR("Minkyu Kang <mk7.kang@samsung.com>");
204 MODULE_DESCRIPTION("Jack Monitoring Interface");
205 MODULE_LICENSE("GPL");