1 #include <linux/kernel.h>
\r
2 #include <linux/delay.h>
\r
3 #include <linux/module.h>
\r
4 #include <linux/err.h>
\r
5 #include <linux/slab.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
34 if(precent && (hdmi->mode == DISP_ON_LCD) && hdmi->display_on){
\r
35 if(hdmi->ops->insert(hdmi) == 0){
\r
36 hdmi->mode = hdmi->display_on;
\r
37 kobject_uevent(&hdmi->dev->kobj, KOBJ_CHANGE);
\r
40 hdmi_dbg(hdmi->dev, "insert error\n");
\r
41 hdmi_set_backlight(hdmi->display_on==DISP_ON_HDMI?HDMI_DISABLE: HDMI_ENABLE);
\r
44 else if(precent &&(hdmi->mode != hdmi->display_on)&& hdmi->display_on){
\r
45 hdmi->mode = hdmi->display_on;
\r
46 hdmi_set_backlight(hdmi->display_on==DISP_ON_HDMI?HDMI_DISABLE: HDMI_ENABLE);
\r
48 else if((!precent || !hdmi->display_on) && hdmi->mode != DISP_ON_LCD){
\r
49 if(hdmi->ops->remove(hdmi) == 0){
\r
50 hdmi->mode = DISP_ON_LCD;
\r
51 hdmi_set_backlight(HDMI_ENABLE);
\r
52 kobject_uevent(&hdmi->dev->kobj, KOBJ_CHANGE);
\r
55 hdmi_dbg(hdmi->dev, "remove error\n");
\r
57 mutex_unlock(&hdmi->lock);
\r
61 void hdmi_changed(struct hdmi *hdmi, int msec)
\r
63 schedule_delayed_work(&hdmi->work, msecs_to_jiffies(msec));
\r
66 void hdmi_suspend(struct hdmi *hdmi)
\r
68 del_timer(&hdmi->timer);
\r
69 flush_delayed_work(&hdmi->work);
\r
70 if(hdmi->mode != DISP_ON_LCD){
\r
71 hdmi->ops->remove(hdmi);
\r
72 hdmi->mode = DISP_ON_LCD;
\r
76 void hdmi_resume(struct hdmi *hdmi)
\r
78 mod_timer(&hdmi->timer, jiffies + msecs_to_jiffies(10));
\r
82 static void hdmi_changed_work(struct work_struct *work)
\r
84 struct hdmi *hdmi = container_of(work, struct hdmi,
\r
87 __hdmi_changed(hdmi);
\r
91 void *hdmi_priv(struct hdmi *hdmi)
\r
93 return (void *)hdmi->priv;
\r
95 static void hdmi_detect_timer(unsigned long data)
\r
97 struct hdmi *hdmi = (struct hdmi*)data;
\r
99 int precent = hdmi->ops->hdmi_precent(hdmi);
\r
101 if((precent && hdmi->mode == DISP_ON_LCD) ||
\r
102 (!precent && hdmi->mode != DISP_ON_LCD))
\r
103 hdmi_changed(hdmi, 100);
\r
104 mod_timer(&hdmi->timer, jiffies + msecs_to_jiffies(200));
\r
106 struct hdmi *hdmi_register(int extra, struct device *parent)
\r
110 struct hdmi *hdmi = kzalloc(sizeof(struct hdmi)+ extra, GFP_KERNEL);
\r
114 for(i = 0; i < HDMI_MAX_ID; i++)
\r
116 if(ref_info[i].ref == 0)
\r
118 ref_info[i].ref = 1;
\r
123 if(i == HDMI_MAX_ID)
\r
128 sprintf(name, "hdmi-%d", hdmi->id);
\r
130 hdmi->dev = device_create(hdmi_class, parent, 0,
\r
132 if (IS_ERR(hdmi->dev)) {
\r
133 rc = PTR_ERR(hdmi->dev);
\r
134 goto dev_create_failed;
\r
137 dev_set_drvdata(hdmi->dev, hdmi);
\r
138 ref_info[i].hdmi = hdmi;
\r
140 INIT_DELAYED_WORK(&hdmi->work, hdmi_changed_work);
\r
142 rc = hdmi_create_attrs(hdmi);
\r
144 goto create_attrs_failed;
\r
148 create_attrs_failed:
\r
149 device_unregister(hdmi->dev);
\r
151 hdmi_remove_attrs(hdmi);
\r
155 mutex_init(&hdmi->lock);
\r
156 setup_timer(&hdmi->timer, hdmi_detect_timer,(unsigned long)hdmi);
\r
157 mod_timer(&hdmi->timer, jiffies + msecs_to_jiffies(200));
\r
160 void hdmi_unregister(struct hdmi *hdmi)
\r
167 del_timer(&hdmi->timer);
\r
168 flush_scheduled_work();
\r
169 hdmi_remove_attrs(hdmi);
\r
170 device_unregister(hdmi->dev);
\r
174 ref_info[id].ref = 0;
\r
175 ref_info[id].hdmi = NULL;
\r
177 struct hdmi *get_hdmi_struct(int nr)
\r
179 if(ref_info[nr].ref == 0)
\r
182 return ref_info[nr].hdmi;
\r
184 int hdmi_is_insert(void)
\r
186 struct hdmi *hdmi = get_hdmi_struct(0);
\r
188 if(hdmi && hdmi->ops && hdmi->ops->hdmi_precent)
\r
189 return hdmi->ops->hdmi_precent(hdmi);
\r
193 int hdmi_get_scale(void)
\r
195 struct hdmi* hdmi = get_hdmi_struct(0);
\r
198 else if(hdmi->mode != DISP_ON_LCD)
\r
199 return hdmi->scale;
\r
204 int hdmi_set_scale(int event, char *data, int len)
\r
207 struct hdmi* hdmi = get_hdmi_struct(0);
\r
213 if(fb_get_video_mode() || hdmi->mode == DISP_ON_LCD)
\r
216 result = data[0] | data[1]<<1 | data[2]<<2;
\r
217 if(event != MOUSE_NONE && (result & event) != event)
\r
220 hdmi->scale += data[3];
\r
222 hdmi->scale = (hdmi->scale>100)?100:hdmi->scale;
\r
223 hdmi->scale = (hdmi->scale<MIN_SCALE)?MIN_SCALE:hdmi->scale;
\r
227 static int __init hdmi_class_init(void)
\r
231 hdmi_class = class_create(THIS_MODULE, "hdmi");
\r
233 if (IS_ERR(hdmi_class))
\r
234 return PTR_ERR(hdmi_class);
\r
235 for(i = 0; i < HDMI_MAX_ID; i++) {
\r
236 ref_info[i].id = i;
\r
237 ref_info[i].ref = 0;
\r
238 ref_info[i].hdmi = NULL;
\r
243 static void __exit hdmi_class_exit(void)
\r
245 class_destroy(hdmi_class);
\r
247 EXPORT_SYMBOL(hdmi_changed);
\r
248 EXPORT_SYMBOL(hdmi_register);
\r
249 EXPORT_SYMBOL(hdmi_unregister);
\r
250 EXPORT_SYMBOL(get_hdmi_struct);
\r
252 subsys_initcall(hdmi_class_init);
\r
253 module_exit(hdmi_class_exit);
\r