void img_ir_setup_raw(struct img_ir_priv *priv) { u32 irq_en; if (!priv->raw.rdev) return; /* clear and enable edge interrupts */ spin_lock_irq(&priv->lock); irq_en = img_ir_read(priv, IMG_IR_IRQ_ENABLE); irq_en |= IMG_IR_IRQ_EDGE; img_ir_write(priv, IMG_IR_IRQ_CLEAR, IMG_IR_IRQ_EDGE); img_ir_write(priv, IMG_IR_IRQ_ENABLE, irq_en); spin_unlock_irq(&priv->lock); }
static irqreturn_t img_ir_isr(int irq, void *dev_id) { struct img_ir_priv *priv = dev_id; u32 irq_status; spin_lock(&priv->lock); /* we have to clear irqs before reading */ irq_status = img_ir_read(priv, IMG_IR_IRQ_STATUS); img_ir_write(priv, IMG_IR_IRQ_CLEAR, irq_status); /* don't handle valid data irqs if we're only interested in matches */ irq_status &= img_ir_read(priv, IMG_IR_IRQ_ENABLE); /* hand off edge interrupts to raw decode handler */ if (irq_status & IMG_IR_IRQ_EDGE && img_ir_raw_enabled(&priv->raw)) img_ir_isr_raw(priv, irq_status); /* hand off hardware match interrupts to hardware decode handler */ if (irq_status & (IMG_IR_IRQ_DATA_MATCH | IMG_IR_IRQ_DATA_VALID | IMG_IR_IRQ_DATA2_VALID) && img_ir_hw_enabled(&priv->hw)) img_ir_isr_hw(priv, irq_status); spin_unlock(&priv->lock); return IRQ_HANDLED; }
static void img_ir_setup(struct img_ir_priv *priv) { /* start off with interrupts disabled */ img_ir_write(priv, IMG_IR_IRQ_ENABLE, 0); img_ir_setup_raw(priv); img_ir_setup_hw(priv); if (!IS_ERR(priv->clk)) clk_prepare_enable(priv->clk); }
void img_ir_remove_raw(struct img_ir_priv *priv) { struct img_ir_priv_raw *raw = &priv->raw; struct rc_dev *rdev = raw->rdev; u32 irq_en; if (!rdev) return; /* switch off and disable raw (edge) interrupts */ spin_lock_irq(&priv->lock); raw->rdev = NULL; irq_en = img_ir_read(priv, IMG_IR_IRQ_ENABLE); irq_en &= ~IMG_IR_IRQ_EDGE; img_ir_write(priv, IMG_IR_IRQ_ENABLE, irq_en); img_ir_write(priv, IMG_IR_IRQ_CLEAR, IMG_IR_IRQ_EDGE); spin_unlock_irq(&priv->lock); rc_unregister_device(rdev); del_timer_sync(&raw->timer); }