/* * 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 }
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; }
int irq_hdmi(int irq) { u8 flag; int ret = IRQ_HANDLED; /* read flag register */ flag = s5p_hdmi_get_interrupts(); if (s5p_hdmi_get_hpd_status()) s5p_hdmi_disable_interrupts(HDMI_IRQ_HPD_UNPLUG); else s5p_hdmi_disable_interrupts(HDMI_IRQ_HPD_PLUG); s5p_hdmi_clear_pending(HDMI_IRQ_HPD_PLUG); s5p_hdmi_clear_pending(HDMI_IRQ_HPD_UNPLUG); /* 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_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_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; }