diff options
-rw-r--r-- | drivers/media/IR/nuvoton-cir.c | 37 |
1 files changed, 29 insertions, 8 deletions
diff --git a/drivers/media/IR/nuvoton-cir.c b/drivers/media/IR/nuvoton-cir.c index 1ce93599ff56..fdb280ed01ce 100644 --- a/drivers/media/IR/nuvoton-cir.c +++ b/drivers/media/IR/nuvoton-cir.c | |||
@@ -339,6 +339,15 @@ static void nvt_clear_tx_fifo(struct nvt_dev *nvt) | |||
339 | nvt_cir_reg_write(nvt, val | CIR_FIFOCON_TXFIFOCLR, CIR_FIFOCON); | 339 | nvt_cir_reg_write(nvt, val | CIR_FIFOCON_TXFIFOCLR, CIR_FIFOCON); |
340 | } | 340 | } |
341 | 341 | ||
342 | /* enable RX Trigger Level Reach and Packet End interrupts */ | ||
343 | static void nvt_set_cir_iren(struct nvt_dev *nvt) | ||
344 | { | ||
345 | u8 iren; | ||
346 | |||
347 | iren = CIR_IREN_RTR | CIR_IREN_PE; | ||
348 | nvt_cir_reg_write(nvt, iren, CIR_IREN); | ||
349 | } | ||
350 | |||
342 | static void nvt_cir_regs_init(struct nvt_dev *nvt) | 351 | static void nvt_cir_regs_init(struct nvt_dev *nvt) |
343 | { | 352 | { |
344 | /* set sample limit count (PE interrupt raised when reached) */ | 353 | /* set sample limit count (PE interrupt raised when reached) */ |
@@ -363,8 +372,8 @@ static void nvt_cir_regs_init(struct nvt_dev *nvt) | |||
363 | /* clear any and all stray interrupts */ | 372 | /* clear any and all stray interrupts */ |
364 | nvt_cir_reg_write(nvt, 0xff, CIR_IRSTS); | 373 | nvt_cir_reg_write(nvt, 0xff, CIR_IRSTS); |
365 | 374 | ||
366 | /* and finally, enable RX Trigger Level Read and Packet End interrupts */ | 375 | /* and finally, enable interrupts */ |
367 | nvt_cir_reg_write(nvt, CIR_IREN_RTR | CIR_IREN_PE, CIR_IREN); | 376 | nvt_set_cir_iren(nvt); |
368 | } | 377 | } |
369 | 378 | ||
370 | static void nvt_cir_wake_regs_init(struct nvt_dev *nvt) | 379 | static void nvt_cir_wake_regs_init(struct nvt_dev *nvt) |
@@ -639,12 +648,22 @@ static void nvt_process_rx_ir_data(struct nvt_dev *nvt) | |||
639 | nvt_dbg_verbose("%s done", __func__); | 648 | nvt_dbg_verbose("%s done", __func__); |
640 | } | 649 | } |
641 | 650 | ||
651 | static void nvt_handle_rx_fifo_overrun(struct nvt_dev *nvt) | ||
652 | { | ||
653 | nvt_pr(KERN_WARNING, "RX FIFO overrun detected, flushing data!"); | ||
654 | |||
655 | nvt->pkts = 0; | ||
656 | nvt_clear_cir_fifo(nvt); | ||
657 | ir_raw_event_reset(nvt->rdev); | ||
658 | } | ||
659 | |||
642 | /* copy data from hardware rx fifo into driver buffer */ | 660 | /* copy data from hardware rx fifo into driver buffer */ |
643 | static void nvt_get_rx_ir_data(struct nvt_dev *nvt) | 661 | static void nvt_get_rx_ir_data(struct nvt_dev *nvt) |
644 | { | 662 | { |
645 | unsigned long flags; | 663 | unsigned long flags; |
646 | u8 fifocount, val; | 664 | u8 fifocount, val; |
647 | unsigned int b_idx; | 665 | unsigned int b_idx; |
666 | bool overrun = false; | ||
648 | int i; | 667 | int i; |
649 | 668 | ||
650 | /* Get count of how many bytes to read from RX FIFO */ | 669 | /* Get count of how many bytes to read from RX FIFO */ |
@@ -652,11 +671,10 @@ static void nvt_get_rx_ir_data(struct nvt_dev *nvt) | |||
652 | /* if we get 0xff, probably means the logical dev is disabled */ | 671 | /* if we get 0xff, probably means the logical dev is disabled */ |
653 | if (fifocount == 0xff) | 672 | if (fifocount == 0xff) |
654 | return; | 673 | return; |
655 | /* this would suggest a fifo overrun, not good... */ | 674 | /* watch out for a fifo overrun condition */ |
656 | else if (fifocount > RX_BUF_LEN) { | 675 | else if (fifocount > RX_BUF_LEN) { |
657 | nvt_pr(KERN_WARNING, "fifocount %d over fifo len (%d)!", | 676 | overrun = true; |
658 | fifocount, RX_BUF_LEN); | 677 | fifocount = RX_BUF_LEN; |
659 | return; | ||
660 | } | 678 | } |
661 | 679 | ||
662 | nvt_dbg("attempting to fetch %u bytes from hw rx fifo", fifocount); | 680 | nvt_dbg("attempting to fetch %u bytes from hw rx fifo", fifocount); |
@@ -682,6 +700,9 @@ static void nvt_get_rx_ir_data(struct nvt_dev *nvt) | |||
682 | 700 | ||
683 | nvt_process_rx_ir_data(nvt); | 701 | nvt_process_rx_ir_data(nvt); |
684 | 702 | ||
703 | if (overrun) | ||
704 | nvt_handle_rx_fifo_overrun(nvt); | ||
705 | |||
685 | spin_unlock_irqrestore(&nvt->nvt_lock, flags); | 706 | spin_unlock_irqrestore(&nvt->nvt_lock, flags); |
686 | } | 707 | } |
687 | 708 | ||
@@ -886,7 +907,7 @@ static void nvt_enable_cir(struct nvt_dev *nvt) | |||
886 | nvt_cir_reg_write(nvt, 0xff, CIR_IRSTS); | 907 | nvt_cir_reg_write(nvt, 0xff, CIR_IRSTS); |
887 | 908 | ||
888 | /* enable interrupts */ | 909 | /* enable interrupts */ |
889 | nvt_cir_reg_write(nvt, CIR_IREN_RTR | CIR_IREN_PE, CIR_IREN); | 910 | nvt_set_cir_iren(nvt); |
890 | } | 911 | } |
891 | 912 | ||
892 | static void nvt_disable_cir(struct nvt_dev *nvt) | 913 | static void nvt_disable_cir(struct nvt_dev *nvt) |
@@ -1155,7 +1176,7 @@ static int nvt_resume(struct pnp_dev *pdev) | |||
1155 | nvt_dbg("%s called", __func__); | 1176 | nvt_dbg("%s called", __func__); |
1156 | 1177 | ||
1157 | /* open interrupt */ | 1178 | /* open interrupt */ |
1158 | nvt_cir_reg_write(nvt, CIR_IREN_RTR | CIR_IREN_PE, CIR_IREN); | 1179 | nvt_set_cir_iren(nvt); |
1159 | 1180 | ||
1160 | /* Enable CIR logical device */ | 1181 | /* Enable CIR logical device */ |
1161 | nvt_efm_enable(nvt); | 1182 | nvt_efm_enable(nvt); |