1 #include <linux/kernel.h>
2 #include <linux/delay.h>
3 #include <linux/module.h>
4 #include <linux/platform_device.h>
5 #include <linux/interrupt.h>
7 #include <mach/iomux.h>
9 #include "cat66121_hdmi.h"
11 struct cat66121_hdmi_pdata *cat66121_hdmi = NULL;
12 struct hdmi *hdmi=NULL;
14 extern struct rk_lcdc_device_driver * rk_get_lcdc_drv(char *name);
15 extern void hdmi_register_display_sysfs(struct hdmi *hdmi, struct device *parent);
16 extern void hdmi_unregister_display_sysfs(struct hdmi *hdmi);
18 int cat66121_hdmi_register_hdcp_callbacks(void (*hdcp_cb)(void),
19 void (*hdcp_irq_cb)(int status),
20 int (*hdcp_power_on_cb)(void),
21 void (*hdcp_power_off_cb)(void))
23 hdmi->hdcp_cb = hdcp_cb;
24 hdmi->hdcp_irq_cb = hdcp_irq_cb;
25 hdmi->hdcp_power_on_cb = hdcp_power_on_cb;
26 hdmi->hdcp_power_off_cb = hdcp_power_off_cb;
28 return HDMI_ERROR_SUCESS;
31 #ifdef CONFIG_HAS_EARLYSUSPEND
32 static void hdmi_early_suspend(struct early_suspend *h)
34 hdmi_dbg(hdmi->dev, "hdmi enter early suspend pwr %d state %d\n", hdmi->pwr_mode, hdmi->state);
35 flush_delayed_work(&hdmi->delay_work);
36 mutex_lock(&hdmi->enable_mutex);
39 mutex_unlock(&hdmi->enable_mutex);
45 disable_irq(hdmi->irq);
48 mutex_unlock(&hdmi->enable_mutex);
49 hdmi->command = HDMI_CONFIG_ENABLE;
50 init_completion(&hdmi->complete);
52 queue_delayed_work(hdmi->workqueue, &hdmi->delay_work, 0);
53 wait_for_completion_interruptible_timeout(&hdmi->complete,
54 msecs_to_jiffies(5000));
55 flush_delayed_work(&hdmi->delay_work);
59 static void hdmi_early_resume(struct early_suspend *h)
61 hdmi_dbg(hdmi->dev, "hdmi exit early resume\n");
62 mutex_lock(&hdmi->enable_mutex);
66 if(hdmi->enable && hdmi->irq) {
67 enable_irq(hdmi->irq);
70 queue_delayed_work(cat66121_hdmi->workqueue, &cat66121_hdmi->delay_work, 100);
72 queue_delayed_work(hdmi->workqueue, &hdmi->delay_work, msecs_to_jiffies(10));
73 mutex_unlock(&hdmi->enable_mutex);
78 static void cat66121_irq_work_func(struct work_struct *work)
80 if(hdmi->suspend == 0) {
81 if(hdmi->enable == 1) {
82 cat66121_hdmi_interrupt();
87 queue_delayed_work(cat66121_hdmi->workqueue, &cat66121_hdmi->delay_work, 100);
93 static irqreturn_t cat66121_irq(int irq, void *dev_id)
95 printk(KERN_INFO "cat66121 irq triggered.\n");
96 schedule_work(&cat66121_hdmi->irq_work);
101 static int hdmi_read_p0_reg(struct i2c_client *client, char reg, char *val)
103 return i2c_master_reg8_recv(client, reg, val, 1, 100*1000) > 0? 0: -EINVAL;
106 static int hdmi_write_p0_reg(struct i2c_client *client, char reg, char *val)
108 return i2c_master_reg8_send(client, reg, val, 1, 100*1000) > 0? 0: -EINVAL;
110 static ssize_t hdmi_show_reg_attrs(struct device *dev,
111 struct device_attribute *attr,
117 struct i2c_client *client=cat66121_hdmi->client;
121 hdmi_read_p0_reg(client, i, &val);
123 size += sprintf(buf+size,"\n>>>hdmi_hdmi %x:",i);
124 size += sprintf(buf+size," %2x",val);
129 static ssize_t hdmi_store_reg_attrs(struct device *dev,
130 struct device_attribute *attr,
131 const char *buf, size_t size)
133 struct i2c_client *client=NULL;
134 static char val=0,reg=0;
135 client = cat66121_hdmi->client;
136 printk("/**********hdmi reg config******/");
138 sscanf(buf, "%x%x", &val,®);
139 hdmi_write_p0_reg(client, reg, &val);
143 static struct device_attribute hdmi_attrs[] = {
144 __ATTR(reg_ctl, 0777,hdmi_show_reg_attrs,hdmi_store_reg_attrs),
147 static int cat66121_hdmi_i2c_probe(struct i2c_client *client,const struct i2c_device_id *id)
150 struct rk_hdmi_platform_data *pdata = client->dev.platform_data;
152 cat66121_hdmi = kzalloc(sizeof(struct cat66121_hdmi_pdata), GFP_KERNEL);
155 dev_err(&client->dev, "no memory for state\n");
158 cat66121_hdmi->client = client;
159 i2c_set_clientdata(client, cat66121_hdmi);
161 hdmi = kmalloc(sizeof(struct hdmi), GFP_KERNEL);
164 dev_err(&client->dev, "cat66121 hdmi kmalloc fail!");
165 goto err_kzalloc_hdmi;
167 memset(hdmi, 0, sizeof(struct hdmi));
168 hdmi->dev = &client->dev;
170 if(HDMI_SOURCE_DEFAULT == HDMI_SOURCE_LCDC0)
171 hdmi->lcdc = rk_get_lcdc_drv("lcdc0");
173 hdmi->lcdc = rk_get_lcdc_drv("lcdc1");
174 if(hdmi->lcdc == NULL)
176 dev_err(hdmi->dev, "can not connect to video source lcdc\n");
178 goto err_request_lcdc;
180 if(cat66121_detect_device()!=1){
181 dev_err(hdmi->dev, "can't find it6610 device \n");
183 goto err_request_lcdc;
188 hdmi->insert = cat66121_hdmi_sys_insert;
189 hdmi->remove = cat66121_hdmi_sys_remove;
190 hdmi->control_output = cat66121_hdmi_sys_enalbe_output;
191 hdmi->config_video = cat66121_hdmi_sys_config_video;
192 hdmi->config_audio = cat66121_hdmi_sys_config_audio;
193 hdmi->detect_hotplug = cat66121_hdmi_sys_detect_hpd;
194 hdmi->read_edid = cat66121_hdmi_sys_read_edid;
197 hdmi->workqueue = create_singlethread_workqueue("hdmi");
198 INIT_DELAYED_WORK(&(hdmi->delay_work), hdmi_work);
200 #ifdef CONFIG_HAS_EARLYSUSPEND
201 hdmi->early_suspend.suspend = hdmi_early_suspend;
202 hdmi->early_suspend.resume = hdmi_early_resume;
203 hdmi->early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB - 10;
204 register_early_suspend(&hdmi->early_suspend);
207 hdmi_register_display_sysfs(hdmi, NULL);
209 hdmi->switch_hdmi.name="hdmi";
210 switch_dev_register(&(hdmi->switch_hdmi));
213 spin_lock_init(&hdmi->irq_lock);
214 mutex_init(&hdmi->enable_mutex);
217 if(pdata->io_init()<0){
218 dev_err(&client->dev, "fail to rst chip\n");
219 goto err_request_lcdc;
222 cat66121_hdmi_sys_init();
224 if(client->irq != INVALID_GPIO) {
225 INIT_WORK(&cat66121_hdmi->irq_work, cat66121_irq_work_func);
226 schedule_work(&cat66121_hdmi->irq_work);
227 if((rc = gpio_request(client->irq, "hdmi gpio")) < 0)
229 dev_err(&client->dev, "fail to request gpio %d\n", client->irq);
230 goto err_request_lcdc;
232 hdmi->irq = gpio_to_irq(client->irq);
233 cat66121_hdmi->gpio = client->irq;
234 gpio_pull_updown(client->irq, GPIOPullUp);
235 gpio_direction_input(client->irq);
236 if((rc = request_irq(hdmi->irq, cat66121_irq, IRQF_TRIGGER_RISING, NULL, hdmi)) < 0)
238 dev_err(&client->dev, "fail to request hdmi irq\n");
239 goto err_request_irq;
245 cat66121_hdmi->workqueue = create_singlethread_workqueue("cat66121 irq");
246 INIT_DELAYED_WORK(&(cat66121_hdmi->delay_work), cat66121_irq_work_func);
247 cat66121_irq_work_func(NULL);
252 device_create_file(&(client->dev), &hdmi_attrs[0]);
254 dev_info(&client->dev, "cat66121 hdmi i2c probe ok\n");
259 gpio_free(client->irq);
264 kfree(cat66121_hdmi);
265 cat66121_hdmi = NULL;
266 dev_err(&client->dev, "cat66121 hdmi probe error\n");
271 static int __devexit cat66121_hdmi_i2c_remove(struct i2c_client *client)
273 hdmi_dbg(hdmi->dev, "%s\n", __func__);
275 mutex_lock(&hdmi->enable_mutex);
276 if(!hdmi->suspend && hdmi->enable && hdmi->irq)
277 disable_irq(hdmi->irq);
278 mutex_unlock(&hdmi->enable_mutex);
280 free_irq(hdmi->irq, NULL);
281 flush_workqueue(hdmi->workqueue);
282 destroy_workqueue(hdmi->workqueue);
284 switch_dev_unregister(&(hdmi->switch_hdmi));
286 hdmi_unregister_display_sysfs(hdmi);
287 #ifdef CONFIG_HAS_EARLYSUSPEND
288 unregister_early_suspend(&hdmi->early_suspend);
290 fb_destroy_modelist(&hdmi->edid.modelist);
292 kfree(hdmi->edid.audio);
295 if(hdmi->edid.specs->modedb)
296 kfree(hdmi->edid.specs->modedb);
297 kfree(hdmi->edid.specs);
305 static void cat66121_hdmi_i2c_shutdown(struct i2c_client *client)
308 #ifdef CONFIG_HAS_EARLYSUSPEND
309 unregister_early_suspend(&hdmi->early_suspend);
312 printk(KERN_INFO "cat66121 hdmi shut down.\n");
315 static const struct i2c_device_id cat66121_hdmi_id[] = {
316 { "cat66121_hdmi", 0 },
320 static struct i2c_driver cat66121_hdmi_i2c_driver = {
322 .name = "cat66121_hdmi",
323 .owner = THIS_MODULE,
325 .probe = cat66121_hdmi_i2c_probe,
326 .remove = cat66121_hdmi_i2c_remove,
327 .shutdown = cat66121_hdmi_i2c_shutdown,
328 .id_table = cat66121_hdmi_id,
331 static int __init cat66121_hdmi_init(void)
333 return i2c_add_driver(&cat66121_hdmi_i2c_driver);
336 static void __exit cat66121_hdmi_exit(void)
338 i2c_del_driver(&cat66121_hdmi_i2c_driver);
341 //module_init(cat66121_hdmi_init);
342 device_initcall_sync(cat66121_hdmi_init);
343 module_exit(cat66121_hdmi_exit);