2 /***************************************************************************
6 * SiI9244 - MHL Transmitter Driver
10 * Copyright (C) (2011, Silicon Image Inc)
14 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation version 2.
22 * This program is distributed ¡°as is¡± WITHOUT ANY WARRANTY of any
24 * kind, whether express or implied; without even the implied warranty
26 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 * GNU General Public License for more details.
32 *****************************************************************************/
34 #include <linux/interrupt.h>
35 #include <linux/irq.h>
36 #include <linux/i2c.h>
37 #include <linux/gpio.h>
40 #include <linux/delay.h>
41 #include <plat/gpio-cfg.h>
42 #include <plat/gpio-core.h>
43 #include <mach/regs-gpio.h>
44 #include <mach/regs-clock.h>
45 #include <linux/miscdevice.h>
46 #include <linux/slab.h>
47 #include <linux/syscalls.h>
48 #include <linux/fcntl.h>
49 #include <asm/uaccess.h>
50 #include <linux/regulator/consumer.h>
51 #include <linux/mfd/max8998.h>
52 #include <linux/mfd/max8997.h>
55 #include "sii9234_driver.h"
56 #include "Common_Def.h"
57 #include "u1hd_gpio.h"
59 #define SUBJECT "MHL_DRIVER"
61 #define SII_DEV_DBG(format,...)\
62 printk ("[ "SUBJECT " (%s,%d) ] " format "\n", __func__, __LINE__, ## __VA_ARGS__);
64 struct work_struct sii9234_int_work;
65 struct workqueue_struct *sii9234_wq = NULL;
67 struct i2c_driver sii9234_i2c_driver;
68 struct i2c_client *sii9234_i2c_client = NULL;
70 struct i2c_driver sii9234a_i2c_driver;
71 struct i2c_client *sii9234a_i2c_client = NULL;
73 struct i2c_driver sii9234b_i2c_driver;
74 struct i2c_client *sii9234b_i2c_client = NULL;
76 struct i2c_driver sii9234c_i2c_driver;
77 struct i2c_client *sii9234c_i2c_client = NULL;
79 extern bool sii9234_init(void);
81 static struct i2c_device_id sii9234_id[] = {
86 static struct i2c_device_id sii9234a_id[] = {
91 static struct i2c_device_id sii9234b_id[] = {
96 static struct i2c_device_id sii9234c_id[] = {
101 int MHL_i2c_init = 0;
104 struct sii9234_state {
105 struct i2c_client *client;
108 void sii9234_cfg_power(bool on);
110 static void sii9234_cfg_gpio(void);
112 irqreturn_t mhl_int_irq_handler(int irq, void *dev_id);
114 irqreturn_t mhl_wake_up_irq_handler(int irq, void *dev_id);
116 void sii9234_interrupt_event_work(struct work_struct *p);
118 #define MHL_SWITCH_TEST 1
120 #ifdef MHL_SWITCH_TEST
121 struct class *sec_mhl;
122 EXPORT_SYMBOL(sec_mhl);
124 struct device *mhl_switch;
125 EXPORT_SYMBOL(mhl_switch);
127 static ssize_t check_MHL_command(struct device *dev, struct device_attribute *attr, char *buf)
132 printk(KERN_ERR "[MHL]: check_MHL_command\n");
133 sii9234_cfg_power(1);
134 res = SiI9234_startTPI();
135 count = sprintf(buf,"%d\n", res );
136 sii9234_cfg_power(0);
141 static ssize_t change_switch_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
144 unsigned long value = simple_strtoul(buf, &after, 10);
146 printk(KERN_ERR "[MHL_SWITCH] Change the switch: %ld\n", value);
149 for (i = 0; i <20; i++) {
150 printk(KERN_ERR "[MHL] try %d\n", i+1);
153 s3c_gpio_cfgpin(GPIO_MHL_INT, GPIO_MHL_INT_AF);
154 s3c_gpio_setpull(GPIO_MHL_SEL, S3C_GPIO_PULL_UP);
155 gpio_set_value(GPIO_MHL_SEL, GPIO_LEVEL_HIGH);
156 sii9234_cfg_power(1);
159 sii9234_cfg_power(0);
160 s3c_gpio_setpull(GPIO_MHL_SEL, S3C_GPIO_PULL_NONE);
161 gpio_set_value(GPIO_MHL_SEL, GPIO_LEVEL_LOW);
166 static BLOCKING_NOTIFIER_HEAD(mhl_notifier_client_list);
168 int mhl_register_client(struct notifier_block *nb)
170 return blocking_notifier_chain_register(
171 &mhl_notifier_client_list, nb);
173 EXPORT_SYMBOL(mhl_register_client);
175 int mhl_unregister_client(struct notifier_block *nb)
177 return blocking_notifier_chain_unregister(
178 &mhl_notifier_client_list, nb);
180 EXPORT_SYMBOL(mhl_unregister_client);
182 static int mhl_send_event(unsigned long val, void *v)
184 return blocking_notifier_call_chain(
185 &mhl_notifier_client_list, val, v);
190 printk("[MHL] USB path change : %d\n", on);
192 mhl_send_event(1, NULL);
193 if(gpio_get_value(GPIO_MHL_SEL))
194 printk("[MHL] GPIO_MHL_SEL : already 1\n");
196 gpio_set_value(GPIO_MHL_SEL, GPIO_LEVEL_HIGH);
197 sii9234_cfg_power(1);
201 if(!gpio_get_value(GPIO_MHL_SEL))
202 printk("[MHL] GPIO_MHL_SEL : already 0\n");
204 sii9234_cfg_power(0);
205 gpio_set_value(GPIO_MHL_SEL, GPIO_LEVEL_LOW);
210 EXPORT_SYMBOL(MHL_On);
213 static DEVICE_ATTR(mhl_sel, S_IRUGO | S_IWUSR | S_IXOTH, check_MHL_command, change_switch_store);
216 static ssize_t MHD_check_read(struct device *dev, struct device_attribute *attr, char *buf)
222 s3c_gpio_setpull(GPIO_MHL_SEL, S3C_GPIO_PULL_UP); //MHL_SEL
224 gpio_set_value(GPIO_MHL_SEL, GPIO_LEVEL_HIGH);
227 //TVout_LDO_ctrl(true);
232 res = MHD_Read_deviceID();
238 res = MHD_Read_deviceID();
241 I2C_WriteByte(0x72, 0xA5, 0xE1);
243 res = I2C_ReadByte(0x72, 0xA5);
245 printk(KERN_ERR "A5 res %x",res);
248 res = I2C_ReadByte(0x72, 0x1B);
250 printk(KERN_ERR "Device ID res %x",res);
253 res = I2C_ReadByte(0x72, 0x1C);
255 printk(KERN_ERR "Device Rev ID res %x",res);
258 res = I2C_ReadByte(0x72, 0x1D);
260 printk(KERN_ERR "Device Reserved ID res %x",res);
262 printk(KERN_ERR "\n####HDMI_EN1 %x MHL_RST %x GPIO_MHL_SEL %x\n",gpio_get_value(GPIO_HDMI_EN),gpio_get_value(GPIO_MHL_RST),gpio_get_value(GPIO_MHL_SEL));
264 res = I2C_ReadByte(0x7A, 0x3D);
266 res = I2C_ReadByte(0x7A, 0xFF);
268 s3c_gpio_setpull(GPIO_MHL_SEL, S3C_GPIO_PULL_NONE); //MHL_SEL
270 gpio_set_value(GPIO_MHL_SEL, GPIO_LEVEL_LOW);
272 count = sprintf(buf,"%d\n", res );
273 //TVout_LDO_ctrl(false);
277 static ssize_t MHD_check_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
279 printk(KERN_ERR "input data --> %s\n", buf);
284 static DEVICE_ATTR(MHD_file, S_IRUGO , MHD_check_read, MHD_check_write);
287 struct i2c_client* get_sii9234_client(u8 device_id)
290 struct i2c_client* client_ptr;
292 if(device_id == 0x72)
293 client_ptr = sii9234_i2c_client;
294 else if(device_id == 0x7A)
295 client_ptr = sii9234a_i2c_client;
296 else if(device_id == 0x92)
297 client_ptr = sii9234b_i2c_client;
298 else if(device_id == 0xC8)
299 client_ptr = sii9234c_i2c_client;
305 EXPORT_SYMBOL(get_sii9234_client);
307 u8 sii9234_i2c_read(struct i2c_client *client, u8 reg)
313 SII_DEV_DBG("I2C not ready");
317 i2c_smbus_write_byte(client, reg);
320 ret = i2c_smbus_read_byte(client);
322 //printk(KERN_ERR "#######Read reg %x data %x\n", reg, ret);
326 SII_DEV_DBG("i2c read fail");
332 EXPORT_SYMBOL(sii9234_i2c_read);
335 int sii9234_i2c_write(struct i2c_client *client, u8 reg, u8 data)
339 SII_DEV_DBG("I2C not ready");
343 //printk(KERN_ERR "#######Write reg %x data %x\n", reg, data);
344 return i2c_smbus_write_byte_data(client, reg, data);
346 EXPORT_SYMBOL(sii9234_i2c_write);
349 void sii9234_interrupt_event_work(struct work_struct *p)
352 printk(KERN_ERR "[MHL]sii9234_interrupt_event_work() is called\n");
353 sii9234_interrupt_event();
357 void mhl_int_irq_handler_sched(void)
359 //printk(KERN_ERR "mhl_int_irq_handler_sched() is called\n");
360 queue_work(sii9234_wq, &sii9234_int_work);
364 irqreturn_t mhl_int_irq_handler(int irq, void *dev_id)
366 printk(KERN_ERR "[MHL]mhl_int_irq_handler() is called\n");
368 if (gpio_get_value(GPIO_MHL_SEL))
369 mhl_int_irq_handler_sched();
375 irqreturn_t mhl_wake_up_irq_handler(int irq, void *dev_id)
378 printk(KERN_ERR "mhl_wake_up_irq_handler() is called\n");
380 if (gpio_get_value(GPIO_MHL_SEL))
381 mhl_int_irq_handler_sched();
386 static int sii9234_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
390 struct sii9234_state *state;
392 struct class *mhl_class;
393 struct device *mhl_dev;
395 state = kzalloc(sizeof(struct sii9234_state), GFP_KERNEL);
397 printk(KERN_ERR "failed to allocate memory \n");
401 state->client = client;
402 i2c_set_clientdata(client, state);
406 /* rest of the initialisation goes here. */
408 printk(KERN_ERR "SII9234 attach success!!!\n");
410 sii9234_i2c_client = client;
414 mhl_class = class_create(THIS_MODULE, "mhl");
415 if (IS_ERR(mhl_class))
417 pr_err("Failed to create class(mhl)!\n");
420 mhl_dev = device_create(mhl_class, NULL, 0, NULL, "mhl_dev");
423 pr_err("Failed to create device(mhl_dev)!\n");
426 if (device_create_file(mhl_dev, &dev_attr_MHD_file) < 0)
427 printk(KERN_ERR "Failed to create device file(%s)!\n", dev_attr_MHD_file.attr.name);
435 static int __devexit sii9234_remove(struct i2c_client *client)
437 struct sii9234_state *state = i2c_get_clientdata(client);
443 static int sii9234a_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
445 struct sii9234_state *state;
447 state = kzalloc(sizeof(struct sii9234_state), GFP_KERNEL);
449 printk(KERN_ERR "failed to allocate memory \n");
453 state->client = client;
454 i2c_set_clientdata(client, state);
456 /* rest of the initialisation goes here. */
458 printk(KERN_ERR "SII9234A attach success!!!\n");
460 sii9234a_i2c_client = client;
468 static int __devexit sii9234a_remove(struct i2c_client *client)
470 struct sii9234_state *state = i2c_get_clientdata(client);
475 static int sii9234b_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
477 struct sii9234_state *state;
479 state = kzalloc(sizeof(struct sii9234_state), GFP_KERNEL);
481 printk(KERN_ERR "failed to allocate memory \n");
485 state->client = client;
486 i2c_set_clientdata(client, state);
488 /* rest of the initialisation goes here. */
490 printk(KERN_ERR "SII9234B attach success!!!\n");
492 sii9234b_i2c_client = client;
501 static int __devexit sii9234b_remove(struct i2c_client *client)
503 struct sii9234_state *state = i2c_get_clientdata(client);
509 static int sii9234c_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
511 struct sii9234_state *state;
514 state = kzalloc(sizeof(struct sii9234_state), GFP_KERNEL);
516 printk(KERN_ERR "failed to allocate memory \n");
520 state->client = client;
521 i2c_set_clientdata(client, state);
523 /* rest of the initialisation goes here. */
525 printk(KERN_ERR "SII9234C attach success!!!\n");
527 sii9234c_i2c_client = client;
531 sii9234_wq = create_singlethread_workqueue("sii9234_wq");
532 INIT_WORK(&sii9234_int_work, sii9234_interrupt_event_work);
534 ret = request_threaded_irq(MHL_INT_IRQ, NULL, mhl_int_irq_handler,
535 IRQF_SHARED , "mhl_int", (void *) state);
537 printk(KERN_ERR "unable to request irq mhl_int"
541 printk(KERN_ERR "MHL int reques successful %d\n", ret);
543 ret = request_threaded_irq(MHL_WAKEUP_IRQ, NULL,
544 mhl_wake_up_irq_handler, IRQF_SHARED,
545 "mhl_wake_up", (void *) state);
547 printk(KERN_ERR "unable to request irq mhl_wake_up"
558 static int __devexit sii9234c_remove(struct i2c_client *client)
560 struct sii9234_state *state = i2c_get_clientdata(client);
565 struct i2c_driver sii9234_i2c_driver = {
567 .owner = THIS_MODULE,
570 .id_table = sii9234_id,
571 .probe = sii9234_i2c_probe,
572 .remove = __devexit_p(sii9234_remove),
576 struct i2c_driver sii9234a_i2c_driver = {
578 .owner = THIS_MODULE,
581 .id_table = sii9234a_id,
582 .probe = sii9234a_i2c_probe,
583 .remove = __devexit_p(sii9234a_remove),
587 struct i2c_driver sii9234b_i2c_driver = {
589 .owner = THIS_MODULE,
592 .id_table = sii9234b_id,
593 .probe = sii9234b_i2c_probe,
594 .remove = __devexit_p(sii9234b_remove),
598 struct i2c_driver sii9234c_i2c_driver = {
600 .owner = THIS_MODULE,
603 .id_table = sii9234c_id,
604 .probe = sii9234c_i2c_probe,
605 .remove = __devexit_p(sii9234c_remove),
610 extern struct device * fimc_get_active_device(void);
613 void sii9234_cfg_power(bool on)
618 // s3c_gpio_cfgpin(GPIO_HDMI_EN,S3C_GPIO_OUTPUT); //HDMI_EN
619 #ifdef CONFIG_TARGET_LOCALE_KOR
620 gpio_set_value(GPIO_HDMI_EN,GPIO_LEVEL_HIGH);
622 gpio_set_value(GPIO_HDMI_EN,GPIO_LEVEL_HIGH);
625 s3c_gpio_cfgpin(GPIO_MHL_RST,S3C_GPIO_OUTPUT); //MHL_RST
626 s3c_gpio_setpull(GPIO_MHL_RST, S3C_GPIO_PULL_NONE);
629 s3c_gpio_setpull(GPIO_AP_SCL_18V, S3C_GPIO_PULL_DOWN);
630 gpio_set_value(GPIO_MHL_RST, GPIO_LEVEL_LOW);
632 gpio_set_value(GPIO_MHL_RST, GPIO_LEVEL_HIGH);
633 s3c_gpio_setpull(GPIO_AP_SCL_18V, S3C_GPIO_PULL_NONE);
635 sii9234_unmaks_interrupt();
639 gpio_set_value(GPIO_MHL_RST, GPIO_LEVEL_LOW);
641 gpio_set_value(GPIO_MHL_RST, GPIO_LEVEL_HIGH);
642 #ifdef CONFIG_TARGET_LOCALE_KOR
643 gpio_set_value(GPIO_HDMI_EN,GPIO_LEVEL_HIGH);
645 gpio_set_value(GPIO_HDMI_EN,GPIO_LEVEL_LOW);
647 gpio_set_value(GPIO_MHL_RST, GPIO_LEVEL_LOW);
649 printk(KERN_ERR "[MHL]%s : %d \n",__func__,on);
656 static void sii9234_cfg_gpio()
658 s3c_gpio_cfgpin(GPIO_AP_SDA_18V, S3C_GPIO_SFN(0x0)); //AP_MHL_SDA
659 s3c_gpio_setpull(GPIO_AP_SDA_18V, S3C_GPIO_PULL_NONE);
661 s3c_gpio_cfgpin(GPIO_AP_SCL_18V,S3C_GPIO_SFN(0x1)); //AP_MHL_SCL
662 s3c_gpio_setpull(GPIO_AP_SCL_18V, S3C_GPIO_PULL_NONE);
664 s3c_gpio_cfgpin(GPIO_MHL_WAKE_UP,S3C_GPIO_INPUT);//GPH1(6) XEINT 14
665 set_irq_type(MHL_WAKEUP_IRQ, IRQ_TYPE_EDGE_RISING);
666 s3c_gpio_setpull(GPIO_MHL_WAKE_UP, S3C_GPIO_PULL_DOWN);
668 s3c_gpio_setpull(GPIO_MHL_INT, S3C_GPIO_PULL_DOWN);
669 set_irq_type(MHL_INT_IRQ, IRQ_TYPE_EDGE_RISING);
670 s3c_gpio_cfgpin(GPIO_MHL_INT, GPIO_MHL_INT_AF);
672 #ifdef CONFIG_TARGET_LOCALE_KOR
673 s3c_gpio_cfgpin(GPIO_HDMI_EN,S3C_GPIO_OUTPUT); //HDMI_EN
674 gpio_set_value(GPIO_HDMI_EN,GPIO_LEVEL_LOW);
675 s3c_gpio_setpull(GPIO_HDMI_EN, S3C_GPIO_PULL_NONE);
677 s3c_gpio_cfgpin(GPIO_HDMI_EN,S3C_GPIO_OUTPUT); //HDMI_EN
678 gpio_set_value(GPIO_HDMI_EN,GPIO_LEVEL_LOW);
679 s3c_gpio_setpull(GPIO_HDMI_EN, S3C_GPIO_PULL_NONE);
682 s3c_gpio_cfgpin(GPIO_MHL_RST,S3C_GPIO_OUTPUT);
683 s3c_gpio_setpull(GPIO_MHL_RST, S3C_GPIO_PULL_NONE);
684 gpio_set_value(GPIO_MHL_RST, GPIO_LEVEL_LOW);
686 s3c_gpio_cfgpin(GPIO_MHL_SEL,S3C_GPIO_OUTPUT);
687 s3c_gpio_setpull(GPIO_MHL_SEL, S3C_GPIO_PULL_NONE);
688 gpio_set_value(GPIO_MHL_SEL, GPIO_LEVEL_LOW);
692 static int mhl_open(struct inode *ip, struct file *fp)
694 printk(KERN_ERR "[%s] \n",__func__);
699 static int mhl_release(struct inode *ip, struct file *fp)
702 printk(KERN_ERR "[%s] \n",__func__);
707 static int mhl_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
709 printk(KERN_ERR "[%s] \n",__func__);
716 case MHL_READ_RCP_DATA:
717 data = GetCbusRcpData();
719 put_user(data,(byte *)arg);
720 printk(KERN_ERR "MHL_READ_RCP_DATA read");
730 static struct file_operations mhl_fops = {
731 .owner = THIS_MODULE,
733 .release = mhl_release,
736 static struct miscdevice mhl_device = {
737 .minor = MISC_DYNAMIC_MINOR,
742 static int __init sii9234_module_init(void)
748 /* sii9234_cfg_power(1); //Turn On power to sii9234
751 #ifdef MHL_SWITCH_TEST
752 sec_mhl = class_create(THIS_MODULE, "sec_mhl");
754 printk(KERN_ERR "[MHL] Failed to create class (sec_mhl)\n");
756 mhl_switch = device_create(sec_mhl, NULL, 0, NULL, "switch");
757 if (IS_ERR(mhl_switch))
758 printk(KERN_ERR "[MHL] Failed to create device (mhl_switch)\n");
759 if (device_create_file(mhl_switch, &dev_attr_mhl_sel) < 0)
760 printk(KERN_ERR "[MHL] Failed to create file (mhl_sel)");
763 ret = misc_register(&mhl_device);
765 pr_err(KERN_ERR "misc_register failed - mhl \n");
768 ret = i2c_add_driver(&sii9234_i2c_driver);
770 printk(KERN_ERR "[MHL SII9234] can't add i2c driver\n");
772 printk(KERN_ERR "[MHL SII9234] add i2c driver\n");
773 ret = i2c_add_driver(&sii9234a_i2c_driver);
775 printk(KERN_ERR "[MHL SII9234A] can't add i2c driver\n");
777 printk(KERN_ERR "[MHL SII9234A] add i2c driver\n");
778 ret = i2c_add_driver(&sii9234b_i2c_driver);
780 printk(KERN_ERR "[MHL SII9234B] can't add i2c driver\n");
782 printk(KERN_ERR "[MHL SII9234B] add i2c driver\n");
784 ret = i2c_add_driver(&sii9234c_i2c_driver);
786 printk(KERN_ERR "[MHL SII9234C] can't add i2c driver\n");
788 printk(KERN_ERR "[MHL SII9234C] add i2c driver\n");
792 module_init(sii9234_module_init);
793 static void __exit sii9234_exit(void)
795 i2c_del_driver(&sii9234_i2c_driver);
796 i2c_del_driver(&sii9234a_i2c_driver);
797 i2c_del_driver(&sii9234b_i2c_driver);
798 i2c_del_driver(&sii9234c_i2c_driver);
801 module_exit(sii9234_exit);
803 MODULE_DESCRIPTION("Sii9234 MHL driver");
804 MODULE_AUTHOR("Aakash Manik");
805 MODULE_LICENSE("GPL");