Lines Matching +full:hardware +full:- +full:fifo

2  * Driver for Nuvoton Technology Corporation w83667hg/w83677hg-i CIR
7 * Special thanks to Nuvoton for providing hardware, spec sheets and
32 #include <media/rc-core.h>
35 #include "nuvoton-cir.h"
48 return nvt->rdev->dev.parent; in nvt_get_dev()
53 return nvt->chip_ver == NVT_W83667HG; in is_w83667hg()
59 outb(reg, nvt->cr_efir); in nvt_cr_write()
60 outb(val, nvt->cr_efdr); in nvt_cr_write()
66 outb(reg, nvt->cr_efir); in nvt_cr_read()
67 return inb(nvt->cr_efdr); in nvt_cr_read()
80 if (!request_muxed_region(nvt->cr_efir, 2, NVT_DRIVER_NAME)) in nvt_efm_enable()
81 return -EBUSY; in nvt_efm_enable()
84 outb(EFER_EFM_ENABLE, nvt->cr_efir); in nvt_efm_enable()
85 outb(EFER_EFM_ENABLE, nvt->cr_efir); in nvt_efm_enable()
93 outb(EFER_EFM_DISABLE, nvt->cr_efir); in nvt_efm_disable()
95 release_region(nvt->cr_efir, 2); in nvt_efm_disable()
129 outb(val, nvt->cir_addr + offset); in nvt_cir_reg_write()
135 return inb(nvt->cir_addr + offset); in nvt_cir_reg_read()
142 outb(val, nvt->cir_wake_addr + offset); in nvt_cir_wake_reg_write()
148 return inb(nvt->cir_wake_addr + offset); in nvt_cir_wake_reg_read()
171 struct nvt_dev *nvt = dev->priv; in nvt_write_wakeup_codes()
178 spin_lock_irqsave(&nvt->lock, flags); in nvt_write_wakeup_codes()
186 /* enable writes to wake fifo */ in nvt_write_wakeup_codes()
193 pr_info("Wake sample fifo cleared"); in nvt_write_wakeup_codes()
200 spin_unlock_irqrestore(&nvt->lock, flags); in nvt_write_wakeup_codes()
208 struct nvt_dev *nvt = rc_dev->priv; in wakeup_data_show()
214 spin_lock_irqsave(&nvt->lock, flags); in wakeup_data_show()
226 buf_len += scnprintf(buf + buf_len, PAGE_SIZE - buf_len, in wakeup_data_show()
229 buf_len += scnprintf(buf + buf_len, PAGE_SIZE - buf_len, "\n"); in wakeup_data_show()
231 spin_unlock_irqrestore(&nvt->lock, flags); in wakeup_data_show()
249 return -ENOMEM; in wakeup_data_store()
251 ret = -EINVAL; in wakeup_data_store()
261 ret = -EINVAL; in wakeup_data_store()
342 pr_info(" * FIFO CMP DEEP: 0x%x\n", in cir_wake_dump_regs()
344 pr_info(" * FIFO CMP TOL: 0x%x\n", in cir_wake_dump_regs()
346 pr_info(" * FIFO COUNT: 0x%x\n", in cir_wake_dump_regs()
356 pr_info(" * SAMPLE RX FIFO: 0x%x\n", in cir_wake_dump_regs()
358 pr_info(" * WR FIFO DATA: 0x%x\n", in cir_wake_dump_regs()
360 pr_info(" * RD FIFO ONLY: 0x%x\n", in cir_wake_dump_regs()
362 pr_info(" * RD FIFO ONLY IDX: 0x%x\n", in cir_wake_dump_regs()
364 pr_info(" * FIFO IGNORE: 0x%x\n", in cir_wake_dump_regs()
370 pr_info("%s: Dump CIR WAKE FIFO (len %d)\n", NVT_DRIVER_NAME, fifo_len); in cir_wake_dump_regs()
384 nvt->chip_ver = nvt_chips[i].chip_ver; in nvt_find_chip()
392 /* detect hardware features */
402 nvt->chip_major = nvt_cr_read(nvt, CR_CHIP_ID_HI); in nvt_hw_detect()
403 if (nvt->chip_major == 0xff) { in nvt_hw_detect()
405 nvt->cr_efir = CR_EFIR2; in nvt_hw_detect()
406 nvt->cr_efdr = CR_EFDR2; in nvt_hw_detect()
408 nvt->chip_major = nvt_cr_read(nvt, CR_CHIP_ID_HI); in nvt_hw_detect()
410 nvt->chip_minor = nvt_cr_read(nvt, CR_CHIP_ID_LO); in nvt_hw_detect()
414 chip_id = nvt->chip_major << 8 | nvt->chip_minor; in nvt_hw_detect()
417 return -ENODEV; in nvt_hw_detect()
426 nvt->chip_major, nvt->chip_minor); in nvt_hw_detect()
429 chip_name, nvt->chip_major, nvt->chip_minor); in nvt_hw_detect()
457 nvt_set_ioaddr(nvt, &nvt->cir_addr); in nvt_cir_ldev_init()
459 nvt_cr_write(nvt, nvt->cir_irq, CR_CIR_IRQ_RSRC); in nvt_cir_ldev_init()
462 nvt->cir_addr, nvt->cir_irq); in nvt_cir_ldev_init()
480 nvt_set_ioaddr(nvt, &nvt->cir_wake_addr); in nvt_cir_wake_ldev_init()
483 nvt->cir_wake_addr); in nvt_cir_wake_ldev_init()
486 /* clear out the hardware's cir rx fifo */
493 /* clear out the hardware's cir wake rx fifo */
500 /* clearing wake fifo works in learning mode only */ in nvt_clear_cir_wake_fifo()
511 /* clear out the hardware's cir tx fifo */
537 /* set fifo irq trigger levels */ in nvt_cir_regs_init()
541 /* clear hardware rx and tx fifos */ in nvt_cir_regs_init()
580 spin_lock_irqsave(&nvt->lock, flags); in nvt_enable_wake()
589 spin_unlock_irqrestore(&nvt->lock, flags); in nvt_enable_wake()
602 for (i = 0; i < nvt->pkts; i++) {
603 if (nvt->buf[i] & BUF_PULSE_BIT)
604 duration += nvt->buf[i] & BUF_LEN_MASK;
639 if (!sc_filter->mask) in nvt_ir_raw_set_wakeup_filter()
644 return -ENOMEM; in nvt_ir_raw_set_wakeup_filter()
646 ret = ir_raw_encode_scancode(dev->wakeup_protocol, sc_filter->data, in nvt_ir_raw_set_wakeup_filter()
648 complete = (ret != -ENOBUFS); in nvt_ir_raw_set_wakeup_filter()
661 if (complete && i == ret - 1 && val < BUF_LEN_MASK) in nvt_ir_raw_set_wakeup_filter()
668 val -= buf_val; in nvt_ir_raw_set_wakeup_filter()
683 /* dump contents of the last rx buffer we got from the hw rx fifo */
688 printk(KERN_DEBUG "%s (len %d): ", __func__, nvt->pkts); in nvt_dump_rx_buf()
689 for (i = 0; (i < nvt->pkts) && (i < RX_BUF_LEN); i++) in nvt_dump_rx_buf()
690 printk(KERN_CONT "0x%02x ", nvt->buf[i]); in nvt_dump_rx_buf()
717 nvt_dbg_verbose("Processing buffer of len %d", nvt->pkts); in nvt_process_rx_ir_data()
719 for (i = 0; i < nvt->pkts; i++) { in nvt_process_rx_ir_data()
720 sample = nvt->buf[i]; in nvt_process_rx_ir_data()
728 ir_raw_event_store_with_filter(nvt->rdev, &rawir); in nvt_process_rx_ir_data()
731 nvt->pkts = 0; in nvt_process_rx_ir_data()
734 ir_raw_event_handle(nvt->rdev); in nvt_process_rx_ir_data()
741 dev_warn(nvt_get_dev(nvt), "RX FIFO overrun detected, flushing data!"); in nvt_handle_rx_fifo_overrun()
743 nvt->pkts = 0; in nvt_handle_rx_fifo_overrun()
745 ir_raw_event_overflow(nvt->rdev); in nvt_handle_rx_fifo_overrun()
748 /* copy data from hardware rx fifo into driver buffer */
754 /* Get count of how many bytes to read from RX FIFO */ in nvt_get_rx_ir_data()
757 nvt_dbg("attempting to fetch %u bytes from hw rx fifo", fifocount); in nvt_get_rx_ir_data()
759 /* Read fifocount bytes from CIR Sample RX FIFO register */ in nvt_get_rx_ir_data()
761 nvt->buf[i] = nvt_cir_reg_read(nvt, CIR_SRXFIFO); in nvt_get_rx_ir_data()
763 nvt->pkts = fifocount; in nvt_get_rx_ir_data()
764 nvt_dbg("%s: pkts now %d", __func__, nvt->pkts); in nvt_get_rx_ir_data()
794 spin_lock(&nvt->lock); in nvt_cir_isr()
799 * bit: reg name - description in nvt_cir_isr()
800 * 7: CIR_IRSTS_RDR - RX Data Ready in nvt_cir_isr()
801 * 6: CIR_IRSTS_RTR - RX FIFO Trigger Level Reach in nvt_cir_isr()
802 * 5: CIR_IRSTS_PE - Packet End in nvt_cir_isr()
803 * 4: CIR_IRSTS_RFO - RX FIFO Overrun (RDR will also be set) in nvt_cir_isr()
804 * 3: CIR_IRSTS_TE - TX FIFO Empty in nvt_cir_isr()
805 * 2: CIR_IRSTS_TTR - TX FIFO Trigger Level Reach in nvt_cir_isr()
806 * 1: CIR_IRSTS_TFU - TX FIFO Underrun in nvt_cir_isr()
807 * 0: CIR_IRSTS_GH - Min Length Detected in nvt_cir_isr()
816 spin_unlock(&nvt->lock); in nvt_cir_isr()
825 spin_unlock(&nvt->lock); in nvt_cir_isr()
841 spin_unlock(&nvt->lock); in nvt_cir_isr()
854 spin_lock_irqsave(&nvt->lock, flags); in nvt_enable_cir()
870 spin_unlock_irqrestore(&nvt->lock, flags); in nvt_enable_cir()
877 spin_lock_irqsave(&nvt->lock, flags); in nvt_disable_cir()
888 /* clear hardware rx and tx fifos */ in nvt_disable_cir()
892 spin_unlock_irqrestore(&nvt->lock, flags); in nvt_disable_cir()
900 struct nvt_dev *nvt = dev->priv; in nvt_open()
909 struct nvt_dev *nvt = dev->priv; in nvt_close()
914 /* Allocate memory, probe hardware, and initialize everything */
921 nvt = devm_kzalloc(&pdev->dev, sizeof(struct nvt_dev), GFP_KERNEL); in nvt_probe()
923 return -ENOMEM; in nvt_probe()
926 nvt->rdev = devm_rc_allocate_device(&pdev->dev, RC_DRIVER_IR_RAW); in nvt_probe()
927 if (!nvt->rdev) in nvt_probe()
928 return -ENOMEM; in nvt_probe()
929 rdev = nvt->rdev; in nvt_probe()
934 dev_err(&pdev->dev, "Could not activate PNP device!\n"); in nvt_probe()
941 dev_err(&pdev->dev, "IR PNP Port not valid!\n"); in nvt_probe()
942 return -EINVAL; in nvt_probe()
946 dev_err(&pdev->dev, "PNP IRQ not valid!\n"); in nvt_probe()
947 return -EINVAL; in nvt_probe()
952 dev_err(&pdev->dev, "Wake PNP Port not valid!\n"); in nvt_probe()
953 return -EINVAL; in nvt_probe()
956 nvt->cir_addr = pnp_port_start(pdev, 0); in nvt_probe()
957 nvt->cir_irq = pnp_irq(pdev, 0); in nvt_probe()
959 nvt->cir_wake_addr = pnp_port_start(pdev, 1); in nvt_probe()
961 nvt->cr_efir = CR_EFIR; in nvt_probe()
962 nvt->cr_efdr = CR_EFDR; in nvt_probe()
964 spin_lock_init(&nvt->lock); in nvt_probe()
986 rdev->priv = nvt; in nvt_probe()
987 rdev->allowed_protocols = RC_PROTO_BIT_ALL_IR_DECODER; in nvt_probe()
988 rdev->allowed_wakeup_protocols = RC_PROTO_BIT_ALL_IR_ENCODER; in nvt_probe()
989 rdev->encode_wakeup = true; in nvt_probe()
990 rdev->open = nvt_open; in nvt_probe()
991 rdev->close = nvt_close; in nvt_probe()
992 rdev->s_wakeup_filter = nvt_ir_raw_set_wakeup_filter; in nvt_probe()
993 rdev->device_name = "Nuvoton w836x7hg Infrared Remote Transceiver"; in nvt_probe()
994 rdev->input_phys = "nuvoton/cir0"; in nvt_probe()
995 rdev->input_id.bustype = BUS_HOST; in nvt_probe()
996 rdev->input_id.vendor = PCI_VENDOR_ID_WINBOND2; in nvt_probe()
997 rdev->input_id.product = nvt->chip_major; in nvt_probe()
998 rdev->input_id.version = nvt->chip_minor; in nvt_probe()
999 rdev->driver_name = NVT_DRIVER_NAME; in nvt_probe()
1000 rdev->map_name = RC_MAP_RC6_MCE; in nvt_probe()
1001 rdev->timeout = MS_TO_US(100); in nvt_probe()
1003 rdev->rx_resolution = CIR_SAMPLE_PERIOD; in nvt_probe()
1005 rdev->min_timeout = XYZ; in nvt_probe()
1006 rdev->max_timeout = XYZ; in nvt_probe()
1008 ret = devm_rc_register_device(&pdev->dev, rdev); in nvt_probe()
1013 if (!devm_request_region(&pdev->dev, nvt->cir_addr, in nvt_probe()
1015 return -EBUSY; in nvt_probe()
1017 ret = devm_request_irq(&pdev->dev, nvt->cir_irq, nvt_cir_isr, in nvt_probe()
1022 if (!devm_request_region(&pdev->dev, nvt->cir_wake_addr, in nvt_probe()
1023 CIR_IOREG_LENGTH, NVT_DRIVER_NAME "-wake")) in nvt_probe()
1024 return -EBUSY; in nvt_probe()
1026 ret = device_create_file(&rdev->dev, &dev_attr_wakeup_data); in nvt_probe()
1030 device_init_wakeup(&pdev->dev, true); in nvt_probe()
1032 dev_notice(&pdev->dev, "driver has been successfully loaded\n"); in nvt_probe()
1045 device_remove_file(&nvt->rdev->dev, &dev_attr_wakeup_data); in nvt_remove()
1049 /* enable CIR Wake (for IR power-on) */ in nvt_remove()
1059 mutex_lock(&nvt->rdev->lock); in nvt_suspend()
1060 if (nvt->rdev->users) in nvt_suspend()
1062 mutex_unlock(&nvt->rdev->lock); in nvt_suspend()
1079 mutex_lock(&nvt->rdev->lock); in nvt_resume()
1080 if (nvt->rdev->users) in nvt_resume()
1082 mutex_unlock(&nvt->rdev->lock); in nvt_resume()
1115 MODULE_DESCRIPTION("Nuvoton W83667HG-A & W83677HG-I CIR driver");