diff options
Diffstat (limited to 'drivers/media/rc/nuvoton-cir.c')
-rw-r--r-- | drivers/media/rc/nuvoton-cir.c | 143 |
1 files changed, 58 insertions, 85 deletions
diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c index 04fedaa75612..4b78c891eb77 100644 --- a/drivers/media/rc/nuvoton-cir.c +++ b/drivers/media/rc/nuvoton-cir.c @@ -48,6 +48,11 @@ static const struct nvt_chip nvt_chips[] = { { "NCT6779D", NVT_6779D }, }; +static inline struct device *nvt_get_dev(const struct nvt_dev *nvt) +{ + return nvt->rdev->dev.parent; +} + static inline bool is_w83667hg(struct nvt_dev *nvt) { return nvt->chip_ver == NVT_W83667HG; @@ -182,7 +187,7 @@ static ssize_t wakeup_data_show(struct device *dev, ssize_t buf_len = 0; int i; - spin_lock_irqsave(&nvt->nvt_lock, flags); + spin_lock_irqsave(&nvt->lock, flags); fifo_len = nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFO_COUNT); fifo_len = min(fifo_len, WAKEUP_MAX_SIZE); @@ -199,7 +204,7 @@ static ssize_t wakeup_data_show(struct device *dev, } buf_len += snprintf(buf + buf_len, PAGE_SIZE - buf_len, "\n"); - spin_unlock_irqrestore(&nvt->nvt_lock, flags); + spin_unlock_irqrestore(&nvt->lock, flags); return buf_len; } @@ -243,7 +248,7 @@ static ssize_t wakeup_data_store(struct device *dev, /* hardcode the tolerance to 10% */ tolerance = DIV_ROUND_UP(count, 10); - spin_lock_irqsave(&nvt->nvt_lock, flags); + spin_lock_irqsave(&nvt->lock, flags); nvt_clear_cir_wake_fifo(nvt); nvt_cir_wake_reg_write(nvt, count, CIR_WAKE_FIFO_CMP_DEEP); @@ -260,7 +265,7 @@ static ssize_t wakeup_data_store(struct device *dev, nvt_cir_wake_reg_write(nvt, config, CIR_WAKE_IRCON); - spin_unlock_irqrestore(&nvt->nvt_lock, flags); + spin_unlock_irqrestore(&nvt->lock, flags); ret = len; out: @@ -385,6 +390,7 @@ static inline const char *nvt_find_chip(struct nvt_dev *nvt, int id) /* detect hardware features */ static int nvt_hw_detect(struct nvt_dev *nvt) { + struct device *dev = nvt_get_dev(nvt); const char *chip_name; int chip_id; @@ -405,8 +411,7 @@ static int nvt_hw_detect(struct nvt_dev *nvt) chip_id = nvt->chip_major << 8 | nvt->chip_minor; if (chip_id == NVT_INVALID) { - dev_err(&nvt->pdev->dev, - "No device found on either EFM port\n"); + dev_err(dev, "No device found on either EFM port\n"); return -ENODEV; } @@ -414,12 +419,11 @@ static int nvt_hw_detect(struct nvt_dev *nvt) /* warn, but still let the driver load, if we don't know this chip */ if (!chip_name) - dev_warn(&nvt->pdev->dev, + dev_warn(dev, "unknown chip, id: 0x%02x 0x%02x, it may not work...", nvt->chip_major, nvt->chip_minor); else - dev_info(&nvt->pdev->dev, - "found %s or compatible: chip id: 0x%02x 0x%02x", + dev_info(dev, "found %s or compatible: chip id: 0x%02x 0x%02x", chip_name, nvt->chip_major, nvt->chip_minor); return 0; @@ -586,7 +590,7 @@ static void nvt_enable_wake(struct nvt_dev *nvt) nvt_efm_disable(nvt); - spin_lock_irqsave(&nvt->nvt_lock, flags); + spin_lock_irqsave(&nvt->lock, flags); nvt_cir_wake_reg_write(nvt, CIR_WAKE_IRCON_MODE0 | CIR_WAKE_IRCON_RXEN | CIR_WAKE_IRCON_R | CIR_WAKE_IRCON_RXINV | @@ -595,11 +599,11 @@ static void nvt_enable_wake(struct nvt_dev *nvt) nvt_cir_wake_reg_write(nvt, 0xff, CIR_WAKE_IRSTS); nvt_cir_wake_reg_write(nvt, 0, CIR_WAKE_IREN); - spin_unlock_irqrestore(&nvt->nvt_lock, flags); + spin_unlock_irqrestore(&nvt->lock, flags); } #if 0 /* Currently unused */ -/* rx carrier detect only works in learning mode, must be called w/nvt_lock */ +/* rx carrier detect only works in learning mode, must be called w/lock */ static u32 nvt_rx_carrier_detect(struct nvt_dev *nvt) { u32 count, carrier, duration = 0; @@ -616,7 +620,7 @@ static u32 nvt_rx_carrier_detect(struct nvt_dev *nvt) duration *= SAMPLE_PERIOD; if (!count || !duration) { - dev_notice(&nvt->pdev->dev, + dev_notice(nvt_get_dev(nvt), "Unable to determine carrier! (c:%u, d:%u)", count, duration); return 0; @@ -684,7 +688,7 @@ static int nvt_tx_ir(struct rc_dev *dev, unsigned *txbuf, unsigned n) u8 iren; int ret; - spin_lock_irqsave(&nvt->tx.lock, flags); + spin_lock_irqsave(&nvt->lock, flags); ret = min((unsigned)(TX_BUF_LEN / sizeof(unsigned)), n); nvt->tx.buf_count = (ret * sizeof(unsigned)); @@ -708,13 +712,13 @@ static int nvt_tx_ir(struct rc_dev *dev, unsigned *txbuf, unsigned n) for (i = 0; i < 9; i++) nvt_cir_reg_write(nvt, 0x01, CIR_STXFIFO); - spin_unlock_irqrestore(&nvt->tx.lock, flags); + spin_unlock_irqrestore(&nvt->lock, flags); wait_event(nvt->tx.queue, nvt->tx.tx_state == ST_TX_REQUEST); - spin_lock_irqsave(&nvt->tx.lock, flags); + spin_lock_irqsave(&nvt->lock, flags); nvt->tx.tx_state = ST_TX_NONE; - spin_unlock_irqrestore(&nvt->tx.lock, flags); + spin_unlock_irqrestore(&nvt->lock, flags); /* restore enabled interrupts to prior state */ nvt_cir_reg_write(nvt, iren, CIR_IREN); @@ -781,7 +785,7 @@ static void nvt_process_rx_ir_data(struct nvt_dev *nvt) static void nvt_handle_rx_fifo_overrun(struct nvt_dev *nvt) { - dev_warn(&nvt->pdev->dev, "RX FIFO overrun detected, flushing data!"); + dev_warn(nvt_get_dev(nvt), "RX FIFO overrun detected, flushing data!"); nvt->pkts = 0; nvt_clear_cir_fifo(nvt); @@ -828,14 +832,7 @@ static void nvt_cir_log_irqs(u8 status, u8 iren) static bool nvt_cir_tx_inactive(struct nvt_dev *nvt) { - unsigned long flags; - u8 tx_state; - - spin_lock_irqsave(&nvt->tx.lock, flags); - tx_state = nvt->tx.tx_state; - spin_unlock_irqrestore(&nvt->tx.lock, flags); - - return tx_state == ST_TX_NONE; + return nvt->tx.tx_state == ST_TX_NONE; } /* interrupt service routine for incoming and outgoing CIR data */ @@ -843,11 +840,10 @@ static irqreturn_t nvt_cir_isr(int irq, void *data) { struct nvt_dev *nvt = data; u8 status, iren; - unsigned long flags; nvt_dbg_verbose("%s firing", __func__); - spin_lock_irqsave(&nvt->nvt_lock, flags); + spin_lock(&nvt->lock); /* * Get IR Status register contents. Write 1 to ack/clear @@ -869,7 +865,7 @@ static irqreturn_t nvt_cir_isr(int irq, void *data) * logical device is being disabled. */ if (status == 0xff && iren == 0xff) { - spin_unlock_irqrestore(&nvt->nvt_lock, flags); + spin_unlock(&nvt->lock); nvt_dbg_verbose("Spurious interrupt detected"); return IRQ_HANDLED; } @@ -878,7 +874,7 @@ static irqreturn_t nvt_cir_isr(int irq, void *data) * status bit whether the related interrupt source is enabled */ if (!(status & iren)) { - spin_unlock_irqrestore(&nvt->nvt_lock, flags); + spin_unlock(&nvt->lock); nvt_dbg_verbose("%s exiting, IRSTS 0x0", __func__); return IRQ_NONE; } @@ -898,8 +894,6 @@ static irqreturn_t nvt_cir_isr(int irq, void *data) nvt_get_rx_ir_data(nvt); } - spin_unlock_irqrestore(&nvt->nvt_lock, flags); - if (status & CIR_IRSTS_TE) nvt_clear_tx_fifo(nvt); @@ -907,8 +901,6 @@ static irqreturn_t nvt_cir_isr(int irq, void *data) unsigned int pos, count; u8 tmp; - spin_lock_irqsave(&nvt->tx.lock, flags); - pos = nvt->tx.cur_buf_num; count = nvt->tx.buf_count; @@ -921,20 +913,17 @@ static irqreturn_t nvt_cir_isr(int irq, void *data) tmp = nvt_cir_reg_read(nvt, CIR_IREN); nvt_cir_reg_write(nvt, tmp & ~CIR_IREN_TTR, CIR_IREN); } - - spin_unlock_irqrestore(&nvt->tx.lock, flags); - } if (status & CIR_IRSTS_TFU) { - spin_lock_irqsave(&nvt->tx.lock, flags); if (nvt->tx.tx_state == ST_TX_REPLY) { nvt->tx.tx_state = ST_TX_REQUEST; wake_up(&nvt->tx.queue); } - spin_unlock_irqrestore(&nvt->tx.lock, flags); } + spin_unlock(&nvt->lock); + nvt_dbg_verbose("%s done", __func__); return IRQ_HANDLED; } @@ -943,7 +932,7 @@ static void nvt_disable_cir(struct nvt_dev *nvt) { unsigned long flags; - spin_lock_irqsave(&nvt->nvt_lock, flags); + spin_lock_irqsave(&nvt->lock, flags); /* disable CIR interrupts */ nvt_cir_reg_write(nvt, 0, CIR_IREN); @@ -958,7 +947,7 @@ static void nvt_disable_cir(struct nvt_dev *nvt) nvt_clear_cir_fifo(nvt); nvt_clear_tx_fifo(nvt); - spin_unlock_irqrestore(&nvt->nvt_lock, flags); + spin_unlock_irqrestore(&nvt->lock, flags); /* disable the CIR logical device */ nvt_disable_logical_dev(nvt, LOGICAL_DEV_CIR); @@ -969,7 +958,7 @@ static int nvt_open(struct rc_dev *dev) struct nvt_dev *nvt = dev->priv; unsigned long flags; - spin_lock_irqsave(&nvt->nvt_lock, flags); + spin_lock_irqsave(&nvt->lock, flags); /* set function enable flags */ nvt_cir_reg_write(nvt, CIR_IRCON_TXEN | CIR_IRCON_RXEN | @@ -982,7 +971,7 @@ static int nvt_open(struct rc_dev *dev) /* enable interrupts */ nvt_set_cir_iren(nvt); - spin_unlock_irqrestore(&nvt->nvt_lock, flags); + spin_unlock_irqrestore(&nvt->lock, flags); /* enable the CIR logical device */ nvt_enable_logical_dev(nvt, LOGICAL_DEV_CIR); @@ -1002,40 +991,41 @@ static int nvt_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id) { struct nvt_dev *nvt; struct rc_dev *rdev; - int ret = -ENOMEM; + int ret; nvt = devm_kzalloc(&pdev->dev, sizeof(struct nvt_dev), GFP_KERNEL); if (!nvt) - return ret; + return -ENOMEM; /* input device for IR remote (and tx) */ - rdev = rc_allocate_device(); - if (!rdev) - goto exit_free_dev_rdev; + nvt->rdev = devm_rc_allocate_device(&pdev->dev); + if (!nvt->rdev) + return -ENOMEM; + rdev = nvt->rdev; - ret = -ENODEV; /* activate pnp device */ - if (pnp_activate_dev(pdev) < 0) { + ret = pnp_activate_dev(pdev); + if (ret) { dev_err(&pdev->dev, "Could not activate PNP device!\n"); - goto exit_free_dev_rdev; + return ret; } /* validate pnp resources */ if (!pnp_port_valid(pdev, 0) || pnp_port_len(pdev, 0) < CIR_IOREG_LENGTH) { dev_err(&pdev->dev, "IR PNP Port not valid!\n"); - goto exit_free_dev_rdev; + return -EINVAL; } if (!pnp_irq_valid(pdev, 0)) { dev_err(&pdev->dev, "PNP IRQ not valid!\n"); - goto exit_free_dev_rdev; + return -EINVAL; } if (!pnp_port_valid(pdev, 1) || pnp_port_len(pdev, 1) < CIR_IOREG_LENGTH) { dev_err(&pdev->dev, "Wake PNP Port not valid!\n"); - goto exit_free_dev_rdev; + return -EINVAL; } nvt->cir_addr = pnp_port_start(pdev, 0); @@ -1046,17 +1036,15 @@ static int nvt_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id) nvt->cr_efir = CR_EFIR; nvt->cr_efdr = CR_EFDR; - spin_lock_init(&nvt->nvt_lock); - spin_lock_init(&nvt->tx.lock); + spin_lock_init(&nvt->lock); pnp_set_drvdata(pdev, nvt); - nvt->pdev = pdev; init_waitqueue_head(&nvt->tx.queue); ret = nvt_hw_detect(nvt); if (ret) - goto exit_free_dev_rdev; + return ret; /* Initialize CIR & CIR Wake Logical Devices */ nvt_efm_enable(nvt); @@ -1085,7 +1073,6 @@ static int nvt_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id) rdev->input_id.vendor = PCI_VENDOR_ID_WINBOND2; rdev->input_id.product = nvt->chip_major; rdev->input_id.version = nvt->chip_minor; - rdev->dev.parent = &pdev->dev; rdev->driver_name = NVT_DRIVER_NAME; rdev->map_name = RC_MAP_RC6_MCE; rdev->timeout = MS_TO_NS(100); @@ -1097,29 +1084,27 @@ static int nvt_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id) /* tx bits */ rdev->tx_resolution = XYZ; #endif - nvt->rdev = rdev; - - ret = rc_register_device(rdev); + ret = devm_rc_register_device(&pdev->dev, rdev); if (ret) - goto exit_free_dev_rdev; + return ret; - ret = -EBUSY; /* now claim resources */ if (!devm_request_region(&pdev->dev, nvt->cir_addr, CIR_IOREG_LENGTH, NVT_DRIVER_NAME)) - goto exit_unregister_device; + return -EBUSY; - if (devm_request_irq(&pdev->dev, nvt->cir_irq, nvt_cir_isr, - IRQF_SHARED, NVT_DRIVER_NAME, (void *)nvt)) - goto exit_unregister_device; + ret = devm_request_irq(&pdev->dev, nvt->cir_irq, nvt_cir_isr, + IRQF_SHARED, NVT_DRIVER_NAME, nvt); + if (ret) + return ret; if (!devm_request_region(&pdev->dev, nvt->cir_wake_addr, CIR_IOREG_LENGTH, NVT_DRIVER_NAME "-wake")) - goto exit_unregister_device; + return -EBUSY; ret = device_create_file(&rdev->dev, &dev_attr_wakeup_data); if (ret) - goto exit_unregister_device; + return ret; device_init_wakeup(&pdev->dev, true); @@ -1130,14 +1115,6 @@ static int nvt_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id) } return 0; - -exit_unregister_device: - rc_unregister_device(rdev); - rdev = NULL; -exit_free_dev_rdev: - rc_free_device(rdev); - - return ret; } static void nvt_remove(struct pnp_dev *pdev) @@ -1150,8 +1127,6 @@ static void nvt_remove(struct pnp_dev *pdev) /* enable CIR Wake (for IR power-on) */ nvt_enable_wake(nvt); - - rc_unregister_device(nvt->rdev); } static int nvt_suspend(struct pnp_dev *pdev, pm_message_t state) @@ -1161,16 +1136,14 @@ static int nvt_suspend(struct pnp_dev *pdev, pm_message_t state) nvt_dbg("%s called", __func__); - spin_lock_irqsave(&nvt->tx.lock, flags); - nvt->tx.tx_state = ST_TX_NONE; - spin_unlock_irqrestore(&nvt->tx.lock, flags); + spin_lock_irqsave(&nvt->lock, flags); - spin_lock_irqsave(&nvt->nvt_lock, flags); + nvt->tx.tx_state = ST_TX_NONE; /* disable all CIR interrupts */ nvt_cir_reg_write(nvt, 0, CIR_IREN); - spin_unlock_irqrestore(&nvt->nvt_lock, flags); + spin_unlock_irqrestore(&nvt->lock, flags); /* disable cir logical dev */ nvt_disable_logical_dev(nvt, LOGICAL_DEV_CIR); |