1 #include <linux/kernel.h>
\r
2 #include <linux/delay.h>
\r
3 #include <linux/module.h>
\r
4 #include <linux/err.h>
\r
6 #include <linux/hdmi.h>
\r
7 #include <linux/input.h>
\r
10 struct class *hdmi_class;
\r
11 struct hdmi_id_ref_info {
\r
15 }ref_info[HDMI_MAX_ID];
\r
18 extern int hdmi_create_attrs(struct hdmi *hdmi);
\r
19 extern void hdmi_remove_attrs(struct hdmi *hdmi);
\r
23 static inline int hdmi_create_attrs(struct hdmi *hdmi)
\r
25 static inline void hdmi_remove_attrs(struct hdmi *hdmi) {}
\r
27 #endif /* CONFIG_SYSFS */
\r
28 static void __hdmi_changed(struct hdmi *hdmi)
\r
32 mutex_lock(&hdmi->lock);
\r
33 precent = hdmi->ops->hdmi_precent(hdmi);
\r
35 if(precent && hdmi->mode == DISP_ON_LCD && hdmi->display_on){
\r
36 if(hdmi->ops->insert(hdmi) == 0){
\r
37 hdmi->mode = DISP_ON_HDMI;
\r
38 kobject_uevent(&hdmi->dev->kobj, KOBJ_CHANGE);
\r
41 hdmi_dbg(hdmi->dev, "insert error\n");
\r
43 else if((!precent || !hdmi->display_on) && hdmi->mode == DISP_ON_HDMI){
\r
44 if(hdmi->ops->remove(hdmi) == 0){
\r
45 hdmi->mode = DISP_ON_LCD;
\r
46 kobject_uevent(&hdmi->dev->kobj, KOBJ_CHANGE);
\r
49 hdmi_dbg(hdmi->dev, "remove error\n");
\r
51 mutex_unlock(&hdmi->lock);
\r
55 void hdmi_changed(struct hdmi *hdmi, int msec)
\r
57 schedule_delayed_work(&hdmi->work, msecs_to_jiffies(msec));
\r
60 void hdmi_suspend(struct hdmi *hdmi)
\r
62 del_timer(&hdmi->timer);
\r
63 flush_delayed_work(&hdmi->work);
\r
64 if(hdmi->mode == DISP_ON_HDMI){
\r
65 hdmi->ops->remove(hdmi);
\r
66 hdmi->mode = DISP_ON_LCD;
\r
70 void hdmi_resume(struct hdmi *hdmi)
\r
72 mod_timer(&hdmi->timer, jiffies + msecs_to_jiffies(10));
\r
76 static void hdmi_changed_work(struct work_struct *work)
\r
78 struct hdmi *hdmi = container_of(work, struct hdmi,
\r
81 __hdmi_changed(hdmi);
\r
85 void *hdmi_priv(struct hdmi *hdmi)
\r
87 return (void *)hdmi->priv;
\r
89 static void hdmi_detect_timer(unsigned long data)
\r
91 struct hdmi *hdmi = (struct hdmi*)data;
\r
93 int precent = hdmi->ops->hdmi_precent(hdmi);
\r
95 if((precent && hdmi->mode == DISP_ON_LCD) ||
\r
96 (!precent && hdmi->mode == DISP_ON_HDMI))
\r
97 hdmi_changed(hdmi, 100);
\r
98 mod_timer(&hdmi->timer, jiffies + msecs_to_jiffies(200));
\r
100 struct hdmi *hdmi_register(int extra, struct device *parent)
\r
104 struct hdmi *hdmi = kzalloc(sizeof(struct hdmi)+ extra, GFP_KERNEL);
\r
108 for(i = 0; i < HDMI_MAX_ID; i++)
\r
110 if(ref_info[i].ref == 0)
\r
112 ref_info[i].ref = 1;
\r
117 if(i == HDMI_MAX_ID)
\r
122 sprintf(name, "hdmi-%d", hdmi->id);
\r
124 hdmi->dev = device_create(hdmi_class, parent, 0,
\r
126 if (IS_ERR(hdmi->dev)) {
\r
127 rc = PTR_ERR(hdmi->dev);
\r
128 goto dev_create_failed;
\r
131 dev_set_drvdata(hdmi->dev, hdmi);
\r
132 ref_info[i].hdmi = hdmi;
\r
134 INIT_DELAYED_WORK(&hdmi->work, hdmi_changed_work);
\r
136 rc = hdmi_create_attrs(hdmi);
\r
138 goto create_attrs_failed;
\r
142 create_attrs_failed:
\r
143 device_unregister(hdmi->dev);
\r
145 hdmi_remove_attrs(hdmi);
\r
149 mutex_init(&hdmi->lock);
\r
150 setup_timer(&hdmi->timer, hdmi_detect_timer,(unsigned long)hdmi);
\r
151 mod_timer(&hdmi->timer, jiffies + msecs_to_jiffies(200));
\r
154 void hdmi_unregister(struct hdmi *hdmi)
\r
161 del_timer(&hdmi->timer);
\r
162 flush_scheduled_work();
\r
163 hdmi_remove_attrs(hdmi);
\r
164 device_unregister(hdmi->dev);
\r
168 ref_info[id].ref = 0;
\r
169 ref_info[id].hdmi = NULL;
\r
171 struct hdmi *get_hdmi_struct(int nr)
\r
173 if(ref_info[nr].ref == 0)
\r
176 return ref_info[nr].hdmi;
\r
178 int hdmi_is_insert(void)
\r
180 struct hdmi *hdmi = get_hdmi_struct(0);
\r
182 if(hdmi && hdmi->ops && hdmi->ops->hdmi_precent)
\r
183 return hdmi->ops->hdmi_precent(hdmi);
\r
187 int hdmi_get_scale(void)
\r
189 struct hdmi* hdmi = get_hdmi_struct(0);
\r
193 return hdmi->scale;
\r
196 int hdmi_set_scale(int event, char *data, int len)
\r
199 struct hdmi* hdmi = get_hdmi_struct(0);
\r
205 if(fb_get_video_mode() || hdmi->mode == DISP_ON_LCD)
\r
208 result = data[0] | data[1]<<1 | data[2]<<2;
\r
209 if(event != MOUSE_NONE && (result & event) != event)
\r
212 hdmi->scale += data[3];
\r
214 hdmi->scale = (hdmi->scale>100)?100:hdmi->scale;
\r
215 hdmi->scale = (hdmi->scale<MIN_SCALE)?MIN_SCALE:hdmi->scale;
\r
219 static int __init hdmi_class_init(void)
\r
223 hdmi_class = class_create(THIS_MODULE, "hdmi");
\r
225 if (IS_ERR(hdmi_class))
\r
226 return PTR_ERR(hdmi_class);
\r
227 for(i = 0; i < HDMI_MAX_ID; i++) {
\r
228 ref_info[i].id = i;
\r
229 ref_info[i].ref = 0;
\r
230 ref_info[i].hdmi = NULL;
\r
235 static void __exit hdmi_class_exit(void)
\r
237 class_destroy(hdmi_class);
\r
239 EXPORT_SYMBOL(hdmi_changed);
\r
240 EXPORT_SYMBOL(hdmi_register);
\r
241 EXPORT_SYMBOL(hdmi_unregister);
\r
242 EXPORT_SYMBOL(get_hdmi_struct);
\r
244 subsys_initcall(hdmi_class_init);
\r
245 module_exit(hdmi_class_exit);
\r