static int s5p_hdp_irq_eint(int irq) { HPDIFPRINTK("\n"); if (hpd_struct.read_gpio()) { HPDIFPRINTK("gpio is high\n"); set_irq_type(hpd_struct.irq_n, IRQ_TYPE_LEVEL_LOW); if (atomic_read(&hpd_struct.state) == HPD_HI) return IRQ_HANDLED; atomic_set(&hpd_struct.state, HPD_HI); atomic_set(&poll_state, 1); last_hpd_state = HPD_HI; wake_up_interruptible(&hpd_struct.waitq); } else { HPDIFPRINTK("gpio is low\n"); set_irq_type(hpd_struct.irq_n, IRQ_TYPE_LEVEL_HIGH); if (atomic_read(&hpd_struct.state) == HPD_LO) return IRQ_HANDLED; atomic_set(&hpd_struct.state, HPD_LO); atomic_set(&poll_state, 1); last_hpd_state = HPD_LO; wake_up_interruptible(&hpd_struct.waitq); } schedule_work(&hpd_work); HPDIFPRINTK("%s\n", atomic_read(&hpd_struct.state) == HPD_HI ? "HPD HI" : "HPD LO"); return IRQ_HANDLED; }
irqreturn_t s5p_hpd_irq_handler(int irq) { int ret = IRQ_HANDLED; unsigned long flags; spin_lock_irqsave(&hpd_struct.lock, flags); if (gpio_get_value(S5PV210_GPH1(5))) { if (irq_event == EVENT_FALLING) { mod_timer(&hpd_irq_check_timer, jiffies + HZ/20); } irq_event = EVENT_RISING; } else { irq_event = EVENT_FALLING; del_timer(&hpd_irq_check_timer); } /* check HDMI status */ if (atomic_read(&hdmi_status)) { /* HDMI on */ ret = irq_hdmi(irq); HPDIFPRINTK("HDMI HPD interrupt\n"); } else { /* HDMI off */ ret = irq_eint(irq); HPDIFPRINTK("EINT HPD interrupt\n"); } spin_unlock_irqrestore(&hpd_struct.lock, flags); return ret; }
static long s5p_hpd_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { switch (cmd) { case HPD_GET_STATE: { unsigned int *status = (unsigned int *)arg; *status = atomic_read(&hpd_struct.state); if (last_uevent_state == -1) last_uevent_state = *status; if (last_uevent_state != *status) { on_start_process = false; on_stop_process = false; HPDIFPRINTK("%s() on_start_process, " "on_stop_process = false" , __func__); } HPDIFPRINTK("HPD status is %s\n", (*status) ? "plugged" : "unplugged"); return 0; } #ifdef CONFIG_LSI_HDMI_AUDIO_CH_EVENT case AUDIO_CH_SET_STATE: { int supported_ch_num; if (copy_from_user(&supported_ch_num, (void __user *)arg, sizeof(supported_ch_num))) { printk(KERN_ERR "%s() -copy_from_user error\n", __func__); return -EFAULT; } printk(KERN_INFO "%s() - AUDIO_CH_SET_STATE = 0x%x\n", __func__, supported_ch_num); hdmi_send_audio_ch_num(supported_ch_num, &g_audio_ch_switch); return 0; } #endif default: printk(KERN_ERR "(%d) unknown ioctl, HPD_GET_STATE(%d)\n", (unsigned int)cmd, (unsigned int)HPD_GET_STATE); return -EFAULT; } }
int s5p_hpd_set_hdmiint(void) { /* EINT -> HDMI */ HPDIFPRINTK("\n"); set_irq_type(hpd_struct.irq_n, IRQ_TYPE_NONE); if (last_hpd_state) s5p_hdmi_reg_intc_enable(HDMI_IRQ_HPD_UNPLUG, 0); else s5p_hdmi_reg_intc_enable(HDMI_IRQ_HPD_PLUG, 0); atomic_set(&hdmi_status, HDMI_ON); hpd_struct.int_src_hdmi_hpd(); s5p_hdmi_reg_hpd_gen(); if (s5p_hdmi_reg_get_hpd_status()) s5p_hdmi_reg_intc_enable(HDMI_IRQ_HPD_UNPLUG, 1); else s5p_hdmi_reg_intc_enable(HDMI_IRQ_HPD_PLUG, 1); return 0; }
static int irq_eint(int irq) { if (gpio_get_value(S5PV210_GPH1(5))) { if (g_last_hpd_state == HPD_HI) return IRQ_HANDLED; atomic_set(&g_hpd_struct.state, HPD_HI); atomic_set(&g_poll_state, 1); g_last_hpd_state = HPD_HI; wake_up_interruptible(&g_hpd_struct.waitq); } else { if (g_last_hpd_state == HPD_LO) return IRQ_HANDLED; atomic_set(&g_hpd_struct.state, HPD_LO); atomic_set(&g_poll_state, 1); g_last_hpd_state = HPD_LO; wake_up_interruptible(&g_hpd_struct.waitq); } schedule_work(&g_hpd_work); HPDIFPRINTK("%s\n", atomic_read(&g_hpd_struct.state) == HPD_HI ? "HPD HI" : "HPD LO"); return IRQ_HANDLED; }
int irq_eint(int irq) { if (gpio_get_value(S5PV210_GPH1(5))) { atomic_set(&hpd_struct.state, HPD_HI); atomic_set(&poll_state, 1); last_hpd_state = HPD_HI; wake_up_interruptible(&hpd_struct.waitq); } else { atomic_set(&hpd_struct.state, HPD_LO); atomic_set(&poll_state, 1); last_hpd_state = HPD_LO; wake_up_interruptible(&hpd_struct.waitq); } if (atomic_read(&hpd_struct.state)) set_irq_type(IRQ_EINT13, IRQ_TYPE_EDGE_FALLING); else set_irq_type(IRQ_EINT13, IRQ_TYPE_EDGE_RISING); schedule_work(&hpd_work); HPDIFPRINTK("%s\n", atomic_read(&hpd_struct.state) == HPD_HI ? "HPD HI" : "HPD LO"); return IRQ_HANDLED; }
static int s5p_hpd_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { switch (cmd) { case HPD_GET_STATE: { unsigned int *status = (unsigned int *)arg; #ifdef CONFIG_VIDEO_MHL_V1 if (!gpio_get_value(GPIO_MHL_SEL)) *status = HPD_LO; else #endif *status = atomic_read(&hpd_struct.state); if (last_uevent_state == -1) last_uevent_state = *status; if (last_uevent_state != *status) { on_start_process = false; on_stop_process = false; } HPDIFPRINTK("HPD status is %s\n", (*status) ? "plugged" : "unplugged"); return 0; } default: printk(KERN_ERR "(%d) unknown ioctl, HPD_GET_STATE(%d)\n", (unsigned int)cmd, (unsigned int)HPD_GET_STATE); return -EFAULT; } }
static int s5p_hpd_irq_eint(int irq) { HPDIFPRINTK("\n"); if (hpd_struct.read_gpio()) { HPDIFPRINTK("gpio is high\n"); irq_set_irq_type(hpd_struct.irq_n, IRQ_TYPE_LEVEL_LOW); if (atomic_read(&hpd_struct.state) == HPD_HI) return IRQ_HANDLED; atomic_set(&hpd_struct.state, HPD_HI); atomic_set(&poll_state, 1); last_hpd_state = HPD_HI; wake_up_interruptible(&hpd_struct.waitq); } else { HPDIFPRINTK("gpio is low\n"); irq_set_irq_type(hpd_struct.irq_n, IRQ_TYPE_LEVEL_HIGH); if (atomic_read(&hpd_struct.state) == HPD_LO) return IRQ_HANDLED; atomic_set(&hpd_struct.state, HPD_LO); atomic_set(&poll_state, 1); last_hpd_state = HPD_LO; #ifdef CONFIG_SAMSUNG_WORKAROUND_HPD_GLANCE if (is_mhl_power_state_on != NULL) if (!is_mhl_power_state_on()) mhl_hpd_handler(false); #endif #ifdef CONFIG_HDMI_CONTROLLED_BY_EXT_IC schedule_delayed_work(&ext_ic_control_dwork , msecs_to_jiffies(1000)); #endif wake_up_interruptible(&hpd_struct.waitq); } schedule_work(&hpd_work); HPDIFPRINTK("%s\n", atomic_read(&hpd_struct.state) == HPD_HI ? "HPD HI" : "HPD LO"); return IRQ_HANDLED; }
/* * HPD interrupt handler * * Handles interrupt requests from HPD hardware. * Handler changes value of internal variable and notifies waiting thread. */ static irqreturn_t s5p_hpd_irq_handler(int irq, void *dev_id) { irqreturn_t ret = IRQ_HANDLED; HPDIFPRINTK("\n"); /* check HDMI status */ if (atomic_read(&hdmi_status)) { /* HDMI on */ ret = s5p_hpd_irq_hdmi(irq); HPDIFPRINTK("HDMI HPD interrupt\n"); } else { /* HDMI off */ ret = s5p_hdp_irq_eint(irq); HPDIFPRINTK("EINT HPD interrupt\n"); } return ret; }
/* * HPD interrupt handler * * Handles interrupt requests from HPD hardware. * Handler changes value of internal variable and notifies waiting thread. */ irqreturn_t s5p_hpd_irq_handler(int irq) { int ret = IRQ_HANDLED; spin_lock_irq(&hpd_struct.lock); /* check HDMI status */ if (atomic_read(&hdmi_status)) { /* HDMI on */ ret = irq_hdmi(irq); HPDIFPRINTK("HDMI HPD interrupt\n"); } else { /* HDMI off */ ret = irq_eint(irq); HPDIFPRINTK("EINT HPD interrupt\n"); } spin_unlock_irq(&hpd_struct.lock); return ret; }
static irqreturn_t s5p_hpd_irq_default_handler(int irq, void *dev_id) { u8 flag; flag = s5p_hdmi_reg_intc_status(); if (s5p_hdmi_reg_get_hpd_status()) s5p_hdmi_reg_intc_clear_pending(HDMI_IRQ_HPD_PLUG); else s5p_hdmi_reg_intc_clear_pending(HDMI_IRQ_HPD_UNPLUG); s5p_hdmi_reg_intc_enable(HDMI_IRQ_HPD_UNPLUG, 0); s5p_hdmi_reg_intc_enable(HDMI_IRQ_HPD_PLUG, 0); if (flag & (1 << HDMI_IRQ_HPD_PLUG)) HPDIFPRINTK("HPD_HI\n"); else if (flag & (1 << HDMI_IRQ_HPD_UNPLUG)) HPDIFPRINTK("HPD_LO\n"); else HPDIFPRINTK("UNKNOWN EVENT\n"); return IRQ_HANDLED; }
int s5p_hpd_set_eint(void) { HPDIFPRINTK("\n"); /* HDMI -> EINT */ atomic_set(&hdmi_status, HDMI_OFF); s5p_hdmi_reg_intc_clear_pending(HDMI_IRQ_HPD_PLUG); s5p_hdmi_reg_intc_clear_pending(HDMI_IRQ_HPD_UNPLUG); s5p_hdmi_reg_intc_enable(HDMI_IRQ_HPD_PLUG, 0); s5p_hdmi_reg_intc_enable(HDMI_IRQ_HPD_UNPLUG, 0); hpd_struct.int_src_ext_hpd(); return 0; }
int irq_eint(int irq) { // by pjlee : Interrupt Signal Change #ifdef CONFIG_MACH_MANGO210_EVT0 if (!gpio_get_value(S5PV210_GPH1(5))) { #else if (gpio_get_value(S5PV210_GPH1(5))) { #endif if(last_hpd_state == HPD_HI) return; atomic_set(&hpd_struct.state, HPD_HI); atomic_set(&poll_state, 1); last_hpd_state = HPD_HI; wake_up_interruptible(&hpd_struct.waitq); } else { if(last_hpd_state == HPD_LO) return; atomic_set(&hpd_struct.state, HPD_LO); atomic_set(&poll_state, 1); last_hpd_state = HPD_LO; wake_up_interruptible(&hpd_struct.waitq); } schedule_work(&hpd_work); HPDIFPRINTK("%s\n", atomic_read(&hpd_struct.state) == HPD_HI ? "HPD HI" : "HPD LO"); return IRQ_HANDLED; } int irq_hdmi(int irq) { u8 flag; int ret = IRQ_HANDLED; /* read flag register */ flag = s5p_hdmi_get_interrupts(); #ifdef CONFIG_MACH_MANGO210_EVT0 if (!s5p_hdmi_get_hpd_status()) #else if (s5p_hdmi_get_hpd_status()) #endif s5p_hdmi_clear_pending(HDMI_IRQ_HPD_PLUG); else s5p_hdmi_clear_pending(HDMI_IRQ_HPD_UNPLUG); s5p_hdmi_disable_interrupts(HDMI_IRQ_HPD_UNPLUG); s5p_hdmi_disable_interrupts(HDMI_IRQ_HPD_PLUG); /* is this our interrupt? */ if (!(flag & (1 << HDMI_IRQ_HPD_PLUG | 1 << HDMI_IRQ_HPD_UNPLUG))) { ret = IRQ_NONE; goto out; } if (flag == (1 << HDMI_IRQ_HPD_PLUG | 1 << HDMI_IRQ_HPD_UNPLUG)) { HPDIFPRINTK("HPD_HI && HPD_LO\n"); #ifdef CONFIG_MACH_MANGO210_EVT0 if (last_hpd_state == HPD_HI && !s5p_hdmi_get_hpd_status()) #else if (last_hpd_state == HPD_HI && s5p_hdmi_get_hpd_status()) #endif flag = 1 << HDMI_IRQ_HPD_UNPLUG; else flag = 1 << HDMI_IRQ_HPD_PLUG; } if (flag & (1 << HDMI_IRQ_HPD_PLUG)) { s5p_hdmi_enable_interrupts(HDMI_IRQ_HPD_UNPLUG); atomic_set(&hpd_struct.state, HPD_HI); atomic_set(&poll_state, 1); last_hpd_state = HPD_HI; wake_up_interruptible(&hpd_struct.waitq); s5p_hdcp_encrypt_stop(true); HPDIFPRINTK("HPD_HI\n"); } else if (flag & (1 << HDMI_IRQ_HPD_UNPLUG)) { s5p_hdcp_encrypt_stop(false); s5p_hdmi_enable_interrupts(HDMI_IRQ_HPD_PLUG); atomic_set(&hpd_struct.state, HPD_LO); atomic_set(&poll_state, 1); last_hpd_state = HPD_LO; wake_up_interruptible(&hpd_struct.waitq); HPDIFPRINTK("HPD_LO\n"); } schedule_work(&hpd_work); out: return IRQ_HANDLED; }
/* * HPD interrupt handler * * Handles interrupt requests from HPD hardware. * Handler changes value of internal variable and notifies waiting thread. */ irqreturn_t s5p_hpd_irq_handler(int irq, void *pw) { #ifdef USEEXTINT spin_lock_irq(&hpd_struct.lock); if (gpio_get_value(S5PV210_GPH1(5))) { if (atomic_read(&hpd_struct.state) == HPD_HI) goto out; atomic_set(&hpd_struct.state, HPD_HI); } else { if (atomic_read(&hpd_struct.state) == HPD_LO) goto out; atomic_set(&hpd_struct.state, HPD_LO); } if(atomic_read(&hpd_struct.state)){ set_irq_type(IRQ_EINT13, IRQ_TYPE_LEVEL_LOW); }else{ set_irq_type(IRQ_EINT13, IRQ_TYPE_LEVEL_HIGH); } /* Send UEvent for HPD - added by jyg1004 */ schedule_work(&hpd_work); spin_unlock_irq(&hpd_struct.lock); HPDIFPRINTK("hpd_status = %d\n", atomic_read(&hpd_struct.state)); return IRQ_HANDLED; out: spin_unlock_irq(&hpd_struct.lock); return IRQ_HANDLED; #else u8 flag; int ret = IRQ_HANDLED; /* read flag register */ flag = s5p_hdmi_get_interrupts(); /* is this our interrupt? */ if (!(flag & (1 << HDMI_IRQ_HPD_PLUG | 1 << HDMI_IRQ_HPD_UNPLUG))) { ret = IRQ_NONE; goto out; } /* workaround: ignore HPD IRQ caused by reseting HDCP engine */ if (s5p_hdmi_get_swhpd_status()) { s5p_hdmi_swhpd_disable(); /* clear pending bit */ s5p_hdmi_clear_pending(HDMI_IRQ_HPD_UNPLUG); s5p_hdmi_clear_pending(HDMI_IRQ_HPD_PLUG); ret = IRQ_HANDLED; goto out; } if (flag == (1 << HDMI_IRQ_HPD_PLUG | 1 << HDMI_IRQ_HPD_UNPLUG)) { HPDIFPRINTK("HPD_HI && HPD_LO\n"); if (last_hpd_state == HPD_HI && s5p_hdmi_get_hpd_status()) //if ( last_hpd_state == HPD_HI ) flag = 1 << HDMI_IRQ_HPD_UNPLUG; else flag = 1 << HDMI_IRQ_HPD_PLUG; } if (flag & (1 << HDMI_IRQ_HPD_PLUG)) { HPDIFPRINTK("HPD_HI\n"); /* clear pending bit */ s5p_hdmi_clear_pending(HDMI_IRQ_HPD_PLUG); s5p_hdmi_clear_pending(HDMI_IRQ_HPD_UNPLUG); atomic_set(&hpd_struct.state, HPD_HI); // workaround: enable HDMI_IRQ_HPD_UNPLUG interrupt s5p_hdmi_disable_interrupts(HDMI_IRQ_HPD_PLUG); s5p_hdmi_enable_interrupts(HDMI_IRQ_HPD_UNPLUG); last_hpd_state = HPD_HI; wake_up_interruptible(&hpd_struct.waitq); } else if (flag & (1 << HDMI_IRQ_HPD_UNPLUG)) { HPDIFPRINTK("HPD_LO\n"); /* clear pending bit */ s5p_hdmi_clear_pending(HDMI_IRQ_HPD_PLUG); s5p_hdmi_clear_pending(HDMI_IRQ_HPD_UNPLUG); atomic_set(&hpd_struct.state, HPD_LO); // workaround: disable HDMI_IRQ_HPD_UNPLUG interrupt last_hpd_state = HPD_LO; s5p_hdmi_disable_interrupts(HDMI_IRQ_HPD_UNPLUG); s5p_hdmi_enable_interrupts(HDMI_IRQ_HPD_PLUG); wake_up_interruptible(&hpd_struct.waitq); } out: return IRQ_HANDLED; #endif }
static void s5p_hpd_kobject_uevent(void) { char env_buf[120]; char *envp[2]; int env_offset = 0; int i = 0; int hpd_state = atomic_read(&hpd_struct.state); HPDIFPRINTK("++\n"); if (hpd_tvout_kobj == NULL || hpd_video_kobj == NULL) return; memset(env_buf, 0, sizeof(env_buf)); if (hpd_state) { while(on_stop_process && (i < RETRY_COUNT)) { HPDIFPRINTK("on_stop_process\n"); msleep(5); i++; }; } else { while(on_start_process && (i < RETRY_COUNT)) { HPDIFPRINTK("on_start_process\n"); msleep(5); i++; }; } if (i == RETRY_COUNT) { on_stop_process = false; on_start_process = false; } hpd_state = atomic_read(&hpd_struct.state); if (hpd_state) { if (last_uevent_state == -1 || last_uevent_state == HPD_LO) { sprintf(env_buf, "HDMI_STATE=online"); envp[env_offset++] = env_buf; envp[env_offset] = NULL; HPDIFPRINTK("online event\n"); kobject_uevent_env(hpd_tvout_kobj, KOBJ_CHANGE, envp); on_start_process = true; } last_uevent_state = HPD_HI; } else { if (last_uevent_state == -1 || last_uevent_state == HPD_HI) { sprintf(env_buf, "HDMI_STATE=offline"); envp[env_offset++] = env_buf; envp[env_offset] = NULL; HPDIFPRINTK("offline event\n"); kobject_uevent_env(hpd_tvout_kobj, KOBJ_CHANGE, envp); on_stop_process = true; } last_uevent_state = HPD_LO; } printk("[HDMI] s5p_hpd_kobject_uevent : hpd_state= %d\n",hpd_state); }
static int s5p_hpd_irq_hdmi(int irq) { u8 flag; int ret = IRQ_HANDLED; HPDIFPRINTK("\n"); /* read flag register */ flag = s5p_hdmi_reg_intc_status(); if (s5p_hdmi_reg_get_hpd_status()) s5p_hdmi_reg_intc_clear_pending(HDMI_IRQ_HPD_PLUG); else s5p_hdmi_reg_intc_clear_pending(HDMI_IRQ_HPD_UNPLUG); s5p_hdmi_reg_intc_enable(HDMI_IRQ_HPD_UNPLUG, 0); s5p_hdmi_reg_intc_enable(HDMI_IRQ_HPD_PLUG, 0); /* is this our interrupt? */ if (!(flag & (1 << HDMI_IRQ_HPD_PLUG | 1 << HDMI_IRQ_HPD_UNPLUG))) { ret = IRQ_NONE; goto out; } if (flag == (1 << HDMI_IRQ_HPD_PLUG | 1 << HDMI_IRQ_HPD_UNPLUG)) { HPDIFPRINTK("HPD_HI && HPD_LO\n"); if (last_hpd_state == HPD_HI && s5p_hdmi_reg_get_hpd_status()) flag = 1 << HDMI_IRQ_HPD_UNPLUG; else flag = 1 << HDMI_IRQ_HPD_PLUG; } if (flag & (1 << HDMI_IRQ_HPD_PLUG)) { s5p_hdmi_reg_intc_enable(HDMI_IRQ_HPD_UNPLUG, 1); if (atomic_read(&hpd_struct.state) == HPD_HI) return IRQ_HANDLED; atomic_set(&hpd_struct.state, HPD_HI); atomic_set(&poll_state, 1); last_hpd_state = HPD_HI; wake_up_interruptible(&hpd_struct.waitq); //s5p_hdcp_encrypt_stop(true); HPDIFPRINTK("HPD_HI\n"); } else if (flag & (1 << HDMI_IRQ_HPD_UNPLUG)) { //s5p_hdcp_encrypt_stop(false); s5p_hdcp_stop(); s5p_hdmi_reg_intc_enable(HDMI_IRQ_HPD_PLUG, 1); if (atomic_read(&hpd_struct.state) == HPD_LO) return IRQ_HANDLED; atomic_set(&hpd_struct.state, HPD_LO); atomic_set(&poll_state, 1); last_hpd_state = HPD_LO; wake_up_interruptible(&hpd_struct.waitq); HPDIFPRINTK("HPD_LO\n"); } schedule_work(&hpd_work); out: return IRQ_HANDLED; }
static void s5p_hpd_kobject_uevent(void) { char env_buf[120]; #ifndef CONFIG_HDMI_SWITCH_HPD char *envp[2]; int env_offset = 0; #endif int i = 0; int hpd_state = atomic_read(&hpd_struct.state); HPDIFPRINTK("++\n"); memset(env_buf, 0, sizeof(env_buf)); if (hpd_state) { while (on_stop_process && (i < RETRY_COUNT)) { HPDIFPRINTK("waiting on_stop_process\n"); usleep_range(5000, 5000); i++; }; } else { while (on_start_process && (i < RETRY_COUNT)) { HPDIFPRINTK("waiting on_start_process\n"); usleep_range(5000, 5000); i++; }; } if (i == RETRY_COUNT) { on_stop_process = false; on_start_process = false; printk(KERN_ERR "[ERROR] %s() %s fail !!\n", __func__, hpd_state ? "on_stop_process" : "on_start_process"); } hpd_state = atomic_read(&hpd_struct.state); if (hpd_state) { if (last_uevent_state == -1 || last_uevent_state == HPD_LO) { #ifdef CONFIG_HDMI_CONTROLLED_BY_EXT_IC HPDPRINTK("ext_ic power ON\n"); hpd_struct.ext_ic_control(true); msleep(20); #endif #ifdef CONFIG_HDMI_SWITCH_HPD hpd_struct.hpd_switch.state = 0; switch_set_state(&hpd_struct.hpd_switch, 1); #else sprintf(env_buf, "HDMI_STATE=online"); envp[env_offset++] = env_buf; envp[env_offset] = NULL; HPDIFPRINTK("online event\n"); kobject_uevent_env(&(hpd_misc_device.this_device->kobj), KOBJ_CHANGE, envp); #endif HPDPRINTK("[HDMI] HPD event -connect!!!\n"); if (atomic_read(&hdmi_status) == HDMI_OFF) { on_start_process = true; } else { on_start_process = false; } HPDIFPRINTK("%s() on_start_process(%d)\n", __func__, on_start_process); } last_uevent_state = HPD_HI; } else { if (last_uevent_state == -1 || last_uevent_state == HPD_HI) { #ifdef CONFIG_LSI_HDMI_AUDIO_CH_EVENT switch_set_state(&g_audio_ch_switch, (int)-1); #endif #ifdef CONFIG_HDMI_SWITCH_HPD hpd_struct.hpd_switch.state = 1; switch_set_state(&hpd_struct.hpd_switch, 0); #else sprintf(env_buf, "HDMI_STATE=offline"); envp[env_offset++] = env_buf; envp[env_offset] = NULL; HPDIFPRINTK("offline event\n"); kobject_uevent_env(&(hpd_misc_device.this_device->kobj), KOBJ_CHANGE, envp); #endif HPDPRINTK("[HDMI] HPD event -disconnet!!!\n"); if (atomic_read(&hdmi_status) == HDMI_ON) { on_stop_process = true; } else { on_stop_process = false; } HPDIFPRINTK("%s() on_stop_process(%d)\n", __func__, on_stop_process); } last_uevent_state = HPD_LO; } }
static int s5p_hpd_irq_hdmi(int irq) { u8 flag; int ret = IRQ_HANDLED; HPDIFPRINTK("\n"); /* read flag register */ flag = s5p_hdmi_reg_intc_status(); if (s5p_hdmi_reg_get_hpd_status()) s5p_hdmi_reg_intc_clear_pending(HDMI_IRQ_HPD_PLUG); else s5p_hdmi_reg_intc_clear_pending(HDMI_IRQ_HPD_UNPLUG); s5p_hdmi_reg_intc_enable(HDMI_IRQ_HPD_UNPLUG, 0); s5p_hdmi_reg_intc_enable(HDMI_IRQ_HPD_PLUG, 0); /* is this our interrupt? */ if (!(flag & (1 << HDMI_IRQ_HPD_PLUG | 1 << HDMI_IRQ_HPD_UNPLUG))) { printk(KERN_WARNING "%s() flag is wrong : 0x%x\n", __func__, flag); ret = IRQ_NONE; goto out; } if (flag == (1 << HDMI_IRQ_HPD_PLUG | 1 << HDMI_IRQ_HPD_UNPLUG)) { HPDIFPRINTK("HPD_HI && HPD_LO\n"); if (last_hpd_state == HPD_HI && s5p_hdmi_reg_get_hpd_status()) flag = 1 << HDMI_IRQ_HPD_UNPLUG; else flag = 1 << HDMI_IRQ_HPD_PLUG; } if (flag & (1 << HDMI_IRQ_HPD_PLUG)) { HPDIFPRINTK("HPD_HI\n"); s5p_hdmi_reg_intc_enable(HDMI_IRQ_HPD_UNPLUG, 1); if (atomic_read(&hpd_struct.state) == HPD_HI) return IRQ_HANDLED; atomic_set(&hpd_struct.state, HPD_HI); atomic_set(&poll_state, 1); last_hpd_state = HPD_HI; wake_up_interruptible(&hpd_struct.waitq); } else if (flag & (1 << HDMI_IRQ_HPD_UNPLUG)) { HPDIFPRINTK("HPD_LO\n"); s5p_hdcp_stop(); s5p_hdmi_reg_intc_enable(HDMI_IRQ_HPD_PLUG, 1); if (atomic_read(&hpd_struct.state) == HPD_LO) return IRQ_HANDLED; atomic_set(&hpd_struct.state, HPD_LO); atomic_set(&poll_state, 1); last_hpd_state = HPD_LO; #ifdef CONFIG_SAMSUNG_WORKAROUND_HPD_GLANCE if (is_mhl_power_state_on != NULL) if (!is_mhl_power_state_on()) mhl_hpd_handler(false); #endif #ifdef CONFIG_HDMI_CONTROLLED_BY_EXT_IC schedule_delayed_work(&ext_ic_control_dwork , msecs_to_jiffies(1000)); #endif wake_up_interruptible(&hpd_struct.waitq); } schedule_work(&hpd_work); out: return IRQ_HANDLED; }