^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * winbond-cir.c - Driver for the Consumer IR functionality of Winbond
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * SuperI/O chips.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Currently supports the Winbond WPCD376i chip (PNP id WEC1022), but
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * could probably support others (Winbond WEC102X, NatSemi, etc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * with minor modifications.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * Original Author: David Härdeman <david@hardeman.nu>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * Copyright (C) 2012 Sean Young <sean@mess.org>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * Copyright (C) 2009 - 2011 David Härdeman <david@hardeman.nu>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * Dedicated to my daughter Matilda, without whose loving attention this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * driver would have been finished in half the time and with a fraction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * of the bugs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * Written using:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * o Winbond WPCD376I datasheet helpfully provided by Jesse Barnes at Intel
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * o NatSemi PC87338/PC97338 datasheet (for the serial port stuff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * o DSDT dumps
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * Supported features:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * o IR Receive
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * o IR Transmit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * o Wake-On-CIR functionality
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) * o Carrier detection
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #include <linux/pnp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #include <linux/timer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #include <linux/leds.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #include <linux/spinlock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #include <linux/pci_ids.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #include <linux/bitrev.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #include <linux/wait.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #include <linux/sched.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #include <media/rc-core.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #define DRVNAME "winbond-cir"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) /* CEIR Wake-Up Registers, relative to data->wbase */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #define WBCIR_REG_WCEIR_CTL 0x03 /* CEIR Receiver Control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #define WBCIR_REG_WCEIR_STS 0x04 /* CEIR Receiver Status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #define WBCIR_REG_WCEIR_EV_EN 0x05 /* CEIR Receiver Event Enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #define WBCIR_REG_WCEIR_CNTL 0x06 /* CEIR Receiver Counter Low */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #define WBCIR_REG_WCEIR_CNTH 0x07 /* CEIR Receiver Counter High */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #define WBCIR_REG_WCEIR_INDEX 0x08 /* CEIR Receiver Index */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #define WBCIR_REG_WCEIR_DATA 0x09 /* CEIR Receiver Data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #define WBCIR_REG_WCEIR_CSL 0x0A /* CEIR Re. Compare Strlen */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #define WBCIR_REG_WCEIR_CFG1 0x0B /* CEIR Re. Configuration 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #define WBCIR_REG_WCEIR_CFG2 0x0C /* CEIR Re. Configuration 2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) /* CEIR Enhanced Functionality Registers, relative to data->ebase */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #define WBCIR_REG_ECEIR_CTS 0x00 /* Enhanced IR Control Status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) #define WBCIR_REG_ECEIR_CCTL 0x01 /* Infrared Counter Control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) #define WBCIR_REG_ECEIR_CNT_LO 0x02 /* Infrared Counter LSB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) #define WBCIR_REG_ECEIR_CNT_HI 0x03 /* Infrared Counter MSB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) #define WBCIR_REG_ECEIR_IREM 0x04 /* Infrared Emitter Status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) /* SP3 Banked Registers, relative to data->sbase */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) #define WBCIR_REG_SP3_BSR 0x03 /* Bank Select, all banks */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) /* Bank 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) #define WBCIR_REG_SP3_RXDATA 0x00 /* FIFO RX data (r) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) #define WBCIR_REG_SP3_TXDATA 0x00 /* FIFO TX data (w) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) #define WBCIR_REG_SP3_IER 0x01 /* Interrupt Enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) #define WBCIR_REG_SP3_EIR 0x02 /* Event Identification (r) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) #define WBCIR_REG_SP3_FCR 0x02 /* FIFO Control (w) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) #define WBCIR_REG_SP3_MCR 0x04 /* Mode Control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) #define WBCIR_REG_SP3_LSR 0x05 /* Link Status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) #define WBCIR_REG_SP3_MSR 0x06 /* Modem Status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) #define WBCIR_REG_SP3_ASCR 0x07 /* Aux Status and Control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) /* Bank 2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) #define WBCIR_REG_SP3_BGDL 0x00 /* Baud Divisor LSB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) #define WBCIR_REG_SP3_BGDH 0x01 /* Baud Divisor MSB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) #define WBCIR_REG_SP3_EXCR1 0x02 /* Extended Control 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) #define WBCIR_REG_SP3_EXCR2 0x04 /* Extended Control 2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) #define WBCIR_REG_SP3_TXFLV 0x06 /* TX FIFO Level */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) #define WBCIR_REG_SP3_RXFLV 0x07 /* RX FIFO Level */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) /* Bank 3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) #define WBCIR_REG_SP3_MRID 0x00 /* Module Identification */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) #define WBCIR_REG_SP3_SH_LCR 0x01 /* LCR Shadow */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) #define WBCIR_REG_SP3_SH_FCR 0x02 /* FCR Shadow */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) /* Bank 4 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) #define WBCIR_REG_SP3_IRCR1 0x02 /* Infrared Control 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) /* Bank 5 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) #define WBCIR_REG_SP3_IRCR2 0x04 /* Infrared Control 2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) /* Bank 6 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) #define WBCIR_REG_SP3_IRCR3 0x00 /* Infrared Control 3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) #define WBCIR_REG_SP3_SIR_PW 0x02 /* SIR Pulse Width */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) /* Bank 7 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) #define WBCIR_REG_SP3_IRRXDC 0x00 /* IR RX Demod Control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) #define WBCIR_REG_SP3_IRTXMC 0x01 /* IR TX Mod Control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) #define WBCIR_REG_SP3_RCCFG 0x02 /* CEIR Config */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) #define WBCIR_REG_SP3_IRCFG1 0x04 /* Infrared Config 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) #define WBCIR_REG_SP3_IRCFG4 0x07 /* Infrared Config 4 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) * Magic values follow
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) /* No interrupts for WBCIR_REG_SP3_IER and WBCIR_REG_SP3_EIR */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) #define WBCIR_IRQ_NONE 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) /* RX data bit for WBCIR_REG_SP3_IER and WBCIR_REG_SP3_EIR */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) #define WBCIR_IRQ_RX 0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) /* TX data low bit for WBCIR_REG_SP3_IER and WBCIR_REG_SP3_EIR */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) #define WBCIR_IRQ_TX_LOW 0x02
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) /* Over/Under-flow bit for WBCIR_REG_SP3_IER and WBCIR_REG_SP3_EIR */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) #define WBCIR_IRQ_ERR 0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) /* TX data empty bit for WBCEIR_REG_SP3_IER and WBCIR_REG_SP3_EIR */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) #define WBCIR_IRQ_TX_EMPTY 0x20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) /* Led enable/disable bit for WBCIR_REG_ECEIR_CTS */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) #define WBCIR_LED_ENABLE 0x80
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) /* RX data available bit for WBCIR_REG_SP3_LSR */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) #define WBCIR_RX_AVAIL 0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) /* RX data overrun error bit for WBCIR_REG_SP3_LSR */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) #define WBCIR_RX_OVERRUN 0x02
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) /* TX End-Of-Transmission bit for WBCIR_REG_SP3_ASCR */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) #define WBCIR_TX_EOT 0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) /* RX disable bit for WBCIR_REG_SP3_ASCR */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) #define WBCIR_RX_DISABLE 0x20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) /* TX data underrun error bit for WBCIR_REG_SP3_ASCR */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) #define WBCIR_TX_UNDERRUN 0x40
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) /* Extended mode enable bit for WBCIR_REG_SP3_EXCR1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) #define WBCIR_EXT_ENABLE 0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) /* Select compare register in WBCIR_REG_WCEIR_INDEX (bits 5 & 6) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) #define WBCIR_REGSEL_COMPARE 0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) /* Select mask register in WBCIR_REG_WCEIR_INDEX (bits 5 & 6) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) #define WBCIR_REGSEL_MASK 0x20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) /* Starting address of selected register in WBCIR_REG_WCEIR_INDEX */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) #define WBCIR_REG_ADDR0 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) /* Enable carrier counter */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) #define WBCIR_CNTR_EN 0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) /* Reset carrier counter */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) #define WBCIR_CNTR_R 0x02
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) /* Invert TX */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) #define WBCIR_IRTX_INV 0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) /* Receiver oversampling */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) #define WBCIR_RX_T_OV 0x40
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) /* Valid banks for the SP3 UART */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) enum wbcir_bank {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) WBCIR_BANK_0 = 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) WBCIR_BANK_1 = 0x80,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) WBCIR_BANK_2 = 0xE0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) WBCIR_BANK_3 = 0xE4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) WBCIR_BANK_4 = 0xE8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) WBCIR_BANK_5 = 0xEC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) WBCIR_BANK_6 = 0xF0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) WBCIR_BANK_7 = 0xF4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) /* Supported power-on IR Protocols */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) enum wbcir_protocol {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) IR_PROTOCOL_RC5 = 0x0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) IR_PROTOCOL_NEC = 0x1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) IR_PROTOCOL_RC6 = 0x2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) /* Possible states for IR reception */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) enum wbcir_rxstate {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) WBCIR_RXSTATE_INACTIVE = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) WBCIR_RXSTATE_ACTIVE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) WBCIR_RXSTATE_ERROR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) /* Possible states for IR transmission */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) enum wbcir_txstate {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) WBCIR_TXSTATE_INACTIVE = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) WBCIR_TXSTATE_ACTIVE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) WBCIR_TXSTATE_ERROR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) /* Misc */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) #define WBCIR_NAME "Winbond CIR"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) #define WBCIR_ID_FAMILY 0xF1 /* Family ID for the WPCD376I */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) #define WBCIR_ID_CHIP 0x04 /* Chip ID for the WPCD376I */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) #define WAKEUP_IOMEM_LEN 0x10 /* Wake-Up I/O Reg Len */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) #define EHFUNC_IOMEM_LEN 0x10 /* Enhanced Func I/O Reg Len */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) #define SP_IOMEM_LEN 0x08 /* Serial Port 3 (IR) Reg Len */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) /* Per-device data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) struct wbcir_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) spinlock_t spinlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) struct rc_dev *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) struct led_classdev led;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) unsigned long wbase; /* Wake-Up Baseaddr */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) unsigned long ebase; /* Enhanced Func. Baseaddr */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) unsigned long sbase; /* Serial Port Baseaddr */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) unsigned int irq; /* Serial Port IRQ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) u8 irqmask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) /* RX state */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) enum wbcir_rxstate rxstate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) int carrier_report_enabled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) u32 pulse_duration;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) /* TX state */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) enum wbcir_txstate txstate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) u32 txlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) u32 txoff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) u32 *txbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) u8 txmask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) u32 txcarrier;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) static bool invert; /* default = 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) module_param(invert, bool, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) MODULE_PARM_DESC(invert, "Invert the signal from the IR receiver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) static bool txandrx; /* default = 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) module_param(txandrx, bool, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) MODULE_PARM_DESC(txandrx, "Allow simultaneous TX and RX");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) /*****************************************************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) * UTILITY FUNCTIONS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) *****************************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) /* Caller needs to hold wbcir_lock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) wbcir_set_bits(unsigned long addr, u8 bits, u8 mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) u8 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) val = inb(addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) val = ((val & ~mask) | (bits & mask));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) outb(val, addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) /* Selects the register bank for the serial port */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) static inline void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) wbcir_select_bank(struct wbcir_data *data, enum wbcir_bank bank)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) outb(bank, data->sbase + WBCIR_REG_SP3_BSR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) static inline void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) wbcir_set_irqmask(struct wbcir_data *data, u8 irqmask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) if (data->irqmask == irqmask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) wbcir_select_bank(data, WBCIR_BANK_0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) outb(irqmask, data->sbase + WBCIR_REG_SP3_IER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) data->irqmask = irqmask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) static enum led_brightness
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) wbcir_led_brightness_get(struct led_classdev *led_cdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) struct wbcir_data *data = container_of(led_cdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) struct wbcir_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) led);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) if (inb(data->ebase + WBCIR_REG_ECEIR_CTS) & WBCIR_LED_ENABLE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) return LED_FULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) return LED_OFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) wbcir_led_brightness_set(struct led_classdev *led_cdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) enum led_brightness brightness)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) struct wbcir_data *data = container_of(led_cdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) struct wbcir_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) led);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) wbcir_set_bits(data->ebase + WBCIR_REG_ECEIR_CTS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) brightness == LED_OFF ? 0x00 : WBCIR_LED_ENABLE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) WBCIR_LED_ENABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) /* Manchester encodes bits to RC6 message cells (see wbcir_shutdown) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) static u8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) wbcir_to_rc6cells(u8 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) u8 coded = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) val &= 0x0F;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) for (i = 0; i < 4; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) if (val & 0x01)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) coded |= 0x02 << (i * 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) coded |= 0x01 << (i * 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) val >>= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) return coded;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) /*****************************************************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) * INTERRUPT FUNCTIONS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) *****************************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) wbcir_carrier_report(struct wbcir_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) unsigned counter = inb(data->ebase + WBCIR_REG_ECEIR_CNT_LO) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) inb(data->ebase + WBCIR_REG_ECEIR_CNT_HI) << 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) if (counter > 0 && counter < 0xffff) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) struct ir_raw_event ev = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) .carrier_report = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) .carrier = DIV_ROUND_CLOSEST(counter * 1000000u,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) data->pulse_duration)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) ir_raw_event_store(data->dev, &ev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) /* reset and restart the counter */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) data->pulse_duration = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) wbcir_set_bits(data->ebase + WBCIR_REG_ECEIR_CCTL, WBCIR_CNTR_R,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) WBCIR_CNTR_EN | WBCIR_CNTR_R);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) wbcir_set_bits(data->ebase + WBCIR_REG_ECEIR_CCTL, WBCIR_CNTR_EN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) WBCIR_CNTR_EN | WBCIR_CNTR_R);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) wbcir_idle_rx(struct rc_dev *dev, bool idle)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) struct wbcir_data *data = dev->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) if (!idle && data->rxstate == WBCIR_RXSTATE_INACTIVE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) data->rxstate = WBCIR_RXSTATE_ACTIVE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) if (idle && data->rxstate != WBCIR_RXSTATE_INACTIVE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) data->rxstate = WBCIR_RXSTATE_INACTIVE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) if (data->carrier_report_enabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) wbcir_carrier_report(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) /* Tell hardware to go idle by setting RXINACTIVE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) outb(WBCIR_RX_DISABLE, data->sbase + WBCIR_REG_SP3_ASCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) wbcir_irq_rx(struct wbcir_data *data, struct pnp_dev *device)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) u8 irdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) struct ir_raw_event rawir = {};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) /* Since RXHDLEV is set, at least 8 bytes are in the FIFO */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) while (inb(data->sbase + WBCIR_REG_SP3_LSR) & WBCIR_RX_AVAIL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) irdata = inb(data->sbase + WBCIR_REG_SP3_RXDATA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) if (data->rxstate == WBCIR_RXSTATE_ERROR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) rawir.duration = ((irdata & 0x7F) + 1) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) (data->carrier_report_enabled ? 2 : 10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) rawir.pulse = irdata & 0x80 ? false : true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) if (rawir.pulse)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) data->pulse_duration += rawir.duration;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) ir_raw_event_store_with_filter(data->dev, &rawir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) ir_raw_event_handle(data->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) wbcir_irq_tx(struct wbcir_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) unsigned int space;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) unsigned int used;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) u8 bytes[16];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) u8 byte;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) if (!data->txbuf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) switch (data->txstate) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) case WBCIR_TXSTATE_INACTIVE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) /* TX FIFO empty */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) space = 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) case WBCIR_TXSTATE_ACTIVE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) /* TX FIFO low (3 bytes or less) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) space = 13;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) case WBCIR_TXSTATE_ERROR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) space = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) * TX data is run-length coded in bytes: YXXXXXXX
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) * Y = space (1) or pulse (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) * X = duration, encoded as (X + 1) * 10us (i.e 10 to 1280 us)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) for (used = 0; used < space && data->txoff != data->txlen; used++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) if (data->txbuf[data->txoff] == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) data->txoff++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) byte = min((u32)0x80, data->txbuf[data->txoff]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) data->txbuf[data->txoff] -= byte;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) byte--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) byte |= (data->txoff % 2 ? 0x80 : 0x00); /* pulse/space */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) bytes[used] = byte;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) while (data->txoff != data->txlen && data->txbuf[data->txoff] == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) data->txoff++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) if (used == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) /* Finished */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) if (data->txstate == WBCIR_TXSTATE_ERROR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) /* Clear TX underrun bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) outb(WBCIR_TX_UNDERRUN, data->sbase + WBCIR_REG_SP3_ASCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) wbcir_set_irqmask(data, WBCIR_IRQ_RX | WBCIR_IRQ_ERR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) kfree(data->txbuf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) data->txbuf = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) data->txstate = WBCIR_TXSTATE_INACTIVE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) } else if (data->txoff == data->txlen) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) /* At the end of transmission, tell the hw before last byte */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) outsb(data->sbase + WBCIR_REG_SP3_TXDATA, bytes, used - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) outb(WBCIR_TX_EOT, data->sbase + WBCIR_REG_SP3_ASCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) outb(bytes[used - 1], data->sbase + WBCIR_REG_SP3_TXDATA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) wbcir_set_irqmask(data, WBCIR_IRQ_RX | WBCIR_IRQ_ERR |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) WBCIR_IRQ_TX_EMPTY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) /* More data to follow... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) outsb(data->sbase + WBCIR_REG_SP3_RXDATA, bytes, used);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) if (data->txstate == WBCIR_TXSTATE_INACTIVE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) wbcir_set_irqmask(data, WBCIR_IRQ_RX | WBCIR_IRQ_ERR |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) WBCIR_IRQ_TX_LOW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) data->txstate = WBCIR_TXSTATE_ACTIVE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) static irqreturn_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) wbcir_irq_handler(int irqno, void *cookie)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) struct pnp_dev *device = cookie;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) struct wbcir_data *data = pnp_get_drvdata(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) u8 status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) spin_lock_irqsave(&data->spinlock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) wbcir_select_bank(data, WBCIR_BANK_0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) status = inb(data->sbase + WBCIR_REG_SP3_EIR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) status &= data->irqmask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) if (!status) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) spin_unlock_irqrestore(&data->spinlock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) return IRQ_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) if (status & WBCIR_IRQ_ERR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) /* RX overflow? (read clears bit) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) if (inb(data->sbase + WBCIR_REG_SP3_LSR) & WBCIR_RX_OVERRUN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) data->rxstate = WBCIR_RXSTATE_ERROR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) ir_raw_event_reset(data->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) /* TX underflow? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) if (inb(data->sbase + WBCIR_REG_SP3_ASCR) & WBCIR_TX_UNDERRUN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) data->txstate = WBCIR_TXSTATE_ERROR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) if (status & WBCIR_IRQ_RX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) wbcir_irq_rx(data, device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) if (status & (WBCIR_IRQ_TX_LOW | WBCIR_IRQ_TX_EMPTY))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) wbcir_irq_tx(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) spin_unlock_irqrestore(&data->spinlock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) /*****************************************************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) * RC-CORE INTERFACE FUNCTIONS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) *****************************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) wbcir_set_carrier_report(struct rc_dev *dev, int enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) struct wbcir_data *data = dev->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) spin_lock_irqsave(&data->spinlock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) if (data->carrier_report_enabled == enable) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) spin_unlock_irqrestore(&data->spinlock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) data->pulse_duration = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) wbcir_set_bits(data->ebase + WBCIR_REG_ECEIR_CCTL, WBCIR_CNTR_R,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) WBCIR_CNTR_EN | WBCIR_CNTR_R);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) if (enable && data->dev->idle)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) wbcir_set_bits(data->ebase + WBCIR_REG_ECEIR_CCTL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) WBCIR_CNTR_EN, WBCIR_CNTR_EN | WBCIR_CNTR_R);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) /* Set a higher sampling resolution if carrier reports are enabled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) wbcir_select_bank(data, WBCIR_BANK_2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) data->dev->rx_resolution = enable ? 2 : 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) outb(enable ? 0x03 : 0x0f, data->sbase + WBCIR_REG_SP3_BGDL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) outb(0x00, data->sbase + WBCIR_REG_SP3_BGDH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) /* Enable oversampling if carrier reports are enabled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) wbcir_select_bank(data, WBCIR_BANK_7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) wbcir_set_bits(data->sbase + WBCIR_REG_SP3_RCCFG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) enable ? WBCIR_RX_T_OV : 0, WBCIR_RX_T_OV);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) data->carrier_report_enabled = enable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) spin_unlock_irqrestore(&data->spinlock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) wbcir_txcarrier(struct rc_dev *dev, u32 carrier)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) struct wbcir_data *data = dev->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) u8 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) u32 freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) freq = DIV_ROUND_CLOSEST(carrier, 1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) if (freq < 30 || freq > 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) switch (freq) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) case 58:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) case 59:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) case 60:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) val = freq - 58;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) freq *= 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) case 57:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) val = freq - 27;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) freq = 56900;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) val = freq - 27;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) freq *= 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) spin_lock_irqsave(&data->spinlock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) if (data->txstate != WBCIR_TXSTATE_INACTIVE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) spin_unlock_irqrestore(&data->spinlock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) if (data->txcarrier != freq) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) wbcir_select_bank(data, WBCIR_BANK_7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) wbcir_set_bits(data->sbase + WBCIR_REG_SP3_IRTXMC, val, 0x1F);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) data->txcarrier = freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) spin_unlock_irqrestore(&data->spinlock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) wbcir_txmask(struct rc_dev *dev, u32 mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) struct wbcir_data *data = dev->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) u8 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) /* return the number of transmitters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) if (mask > 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) return 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) /* Four outputs, only one output can be enabled at a time */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) switch (mask) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) case 0x1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) val = 0x0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) case 0x2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) val = 0x1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) case 0x4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) val = 0x2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) case 0x8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) val = 0x3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) spin_lock_irqsave(&data->spinlock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) if (data->txstate != WBCIR_TXSTATE_INACTIVE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) spin_unlock_irqrestore(&data->spinlock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) if (data->txmask != mask) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) wbcir_set_bits(data->ebase + WBCIR_REG_ECEIR_CTS, val, 0x0c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) data->txmask = mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) spin_unlock_irqrestore(&data->spinlock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) wbcir_tx(struct rc_dev *dev, unsigned *b, unsigned count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) struct wbcir_data *data = dev->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) unsigned *buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) unsigned i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) buf = kmalloc_array(count, sizeof(*b), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) if (!buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) /* Convert values to multiples of 10us */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) for (i = 0; i < count; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) buf[i] = DIV_ROUND_CLOSEST(b[i], 10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) /* Not sure if this is possible, but better safe than sorry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) spin_lock_irqsave(&data->spinlock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) if (data->txstate != WBCIR_TXSTATE_INACTIVE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) spin_unlock_irqrestore(&data->spinlock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) kfree(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) /* Fill the TX fifo once, the irq handler will do the rest */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) data->txbuf = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) data->txlen = count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) data->txoff = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) wbcir_irq_tx(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) /* We're done */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) spin_unlock_irqrestore(&data->spinlock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) /*****************************************************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) * SETUP/INIT/SUSPEND/RESUME FUNCTIONS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) *****************************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) wbcir_shutdown(struct pnp_dev *device)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) struct device *dev = &device->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) struct wbcir_data *data = pnp_get_drvdata(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) struct rc_dev *rc = data->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) bool do_wake = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) u8 match[11];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) u8 mask[11];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) u8 rc6_csl = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) u8 proto;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) u32 wake_sc = rc->scancode_wakeup_filter.data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) u32 mask_sc = rc->scancode_wakeup_filter.mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) memset(match, 0, sizeof(match));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) memset(mask, 0, sizeof(mask));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) if (!mask_sc || !device_may_wakeup(dev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) do_wake = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) goto finish;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) switch (rc->wakeup_protocol) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) case RC_PROTO_RC5:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) /* Mask = 13 bits, ex toggle */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) mask[0] = (mask_sc & 0x003f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) mask[0] |= (mask_sc & 0x0300) >> 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) mask[1] = (mask_sc & 0x1c00) >> 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) if (mask_sc & 0x0040) /* 2nd start bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) match[1] |= 0x10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) match[0] = (wake_sc & 0x003F); /* 6 command bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) match[0] |= (wake_sc & 0x0300) >> 2; /* 2 address bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) match[1] = (wake_sc & 0x1c00) >> 10; /* 3 address bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) if (!(wake_sc & 0x0040)) /* 2nd start bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) match[1] |= 0x10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) proto = IR_PROTOCOL_RC5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) case RC_PROTO_NEC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) mask[1] = bitrev8(mask_sc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) mask[0] = mask[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) mask[3] = bitrev8(mask_sc >> 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) mask[2] = mask[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) match[1] = bitrev8(wake_sc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) match[0] = ~match[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) match[3] = bitrev8(wake_sc >> 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) match[2] = ~match[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) proto = IR_PROTOCOL_NEC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) case RC_PROTO_NECX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) mask[1] = bitrev8(mask_sc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) mask[0] = mask[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) mask[2] = bitrev8(mask_sc >> 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) mask[3] = bitrev8(mask_sc >> 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) match[1] = bitrev8(wake_sc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) match[0] = ~match[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) match[2] = bitrev8(wake_sc >> 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) match[3] = bitrev8(wake_sc >> 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) proto = IR_PROTOCOL_NEC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) case RC_PROTO_NEC32:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) mask[0] = bitrev8(mask_sc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) mask[1] = bitrev8(mask_sc >> 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) mask[2] = bitrev8(mask_sc >> 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) mask[3] = bitrev8(mask_sc >> 24);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) match[0] = bitrev8(wake_sc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) match[1] = bitrev8(wake_sc >> 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) match[2] = bitrev8(wake_sc >> 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) match[3] = bitrev8(wake_sc >> 24);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) proto = IR_PROTOCOL_NEC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) case RC_PROTO_RC6_0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) /* Command */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) match[0] = wbcir_to_rc6cells(wake_sc >> 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) mask[0] = wbcir_to_rc6cells(mask_sc >> 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) match[1] = wbcir_to_rc6cells(wake_sc >> 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) mask[1] = wbcir_to_rc6cells(mask_sc >> 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) /* Address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) match[2] = wbcir_to_rc6cells(wake_sc >> 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) mask[2] = wbcir_to_rc6cells(mask_sc >> 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) match[3] = wbcir_to_rc6cells(wake_sc >> 12);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) mask[3] = wbcir_to_rc6cells(mask_sc >> 12);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) /* Header */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) match[4] = 0x50; /* mode1 = mode0 = 0, ignore toggle */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) mask[4] = 0xF0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) match[5] = 0x09; /* start bit = 1, mode2 = 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) mask[5] = 0x0F;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) rc6_csl = 44;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) proto = IR_PROTOCOL_RC6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) case RC_PROTO_RC6_6A_24:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) case RC_PROTO_RC6_6A_32:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) case RC_PROTO_RC6_MCE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) /* Command */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) match[i] = wbcir_to_rc6cells(wake_sc >> 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) mask[i++] = wbcir_to_rc6cells(mask_sc >> 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) match[i] = wbcir_to_rc6cells(wake_sc >> 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) mask[i++] = wbcir_to_rc6cells(mask_sc >> 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) /* Address + Toggle */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) match[i] = wbcir_to_rc6cells(wake_sc >> 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) mask[i++] = wbcir_to_rc6cells(mask_sc >> 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) match[i] = wbcir_to_rc6cells(wake_sc >> 12);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) mask[i++] = wbcir_to_rc6cells(mask_sc >> 12);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) /* Customer bits 7 - 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) match[i] = wbcir_to_rc6cells(wake_sc >> 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) mask[i++] = wbcir_to_rc6cells(mask_sc >> 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) if (rc->wakeup_protocol == RC_PROTO_RC6_6A_20) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) rc6_csl = 52;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) match[i] = wbcir_to_rc6cells(wake_sc >> 20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) mask[i++] = wbcir_to_rc6cells(mask_sc >> 20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) if (rc->wakeup_protocol == RC_PROTO_RC6_6A_24) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) rc6_csl = 60;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) /* Customer range bit and bits 15 - 8 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) match[i] = wbcir_to_rc6cells(wake_sc >> 24);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) mask[i++] = wbcir_to_rc6cells(mask_sc >> 24);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) match[i] = wbcir_to_rc6cells(wake_sc >> 28);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) mask[i++] = wbcir_to_rc6cells(mask_sc >> 28);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) rc6_csl = 76;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) /* Header */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) match[i] = 0x93; /* mode1 = mode0 = 1, submode = 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) mask[i++] = 0xFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) match[i] = 0x0A; /* start bit = 1, mode2 = 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) mask[i++] = 0x0F;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) proto = IR_PROTOCOL_RC6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) do_wake = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) finish:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) if (do_wake) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) /* Set compare and compare mask */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_INDEX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) WBCIR_REGSEL_COMPARE | WBCIR_REG_ADDR0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) 0x3F);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) outsb(data->wbase + WBCIR_REG_WCEIR_DATA, match, 11);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_INDEX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) WBCIR_REGSEL_MASK | WBCIR_REG_ADDR0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) 0x3F);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) outsb(data->wbase + WBCIR_REG_WCEIR_DATA, mask, 11);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) /* RC6 Compare String Len */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) outb(rc6_csl, data->wbase + WBCIR_REG_WCEIR_CSL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) /* Clear status bits NEC_REP, BUFF, MSG_END, MATCH */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_STS, 0x17, 0x17);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) /* Clear BUFF_EN, Clear END_EN, Set MATCH_EN */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_EV_EN, 0x01, 0x07);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) /* Set CEIR_EN */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_CTL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) (proto << 4) | 0x01, 0x31);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) /* Clear BUFF_EN, Clear END_EN, Clear MATCH_EN */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_EV_EN, 0x00, 0x07);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) /* Clear CEIR_EN */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_CTL, 0x00, 0x01);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) * ACPI will set the HW disable bit for SP3 which means that the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) * output signals are left in an undefined state which may cause
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) * spurious interrupts which we need to ignore until the hardware
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) * is reinitialized.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) wbcir_set_irqmask(data, WBCIR_IRQ_NONE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) disable_irq(data->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) * Wakeup handling is done on shutdown.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) wbcir_set_wakeup_filter(struct rc_dev *rc, struct rc_scancode_filter *filter)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) wbcir_suspend(struct pnp_dev *device, pm_message_t state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) struct wbcir_data *data = pnp_get_drvdata(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) led_classdev_suspend(&data->led);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) wbcir_shutdown(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) wbcir_init_hw(struct wbcir_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) /* Disable interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) wbcir_set_irqmask(data, WBCIR_IRQ_NONE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) /* Set RX_INV, Clear CEIR_EN (needed for the led) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_CTL, invert ? 8 : 0, 0x09);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) /* Clear status bits NEC_REP, BUFF, MSG_END, MATCH */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_STS, 0x17, 0x17);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) /* Clear BUFF_EN, Clear END_EN, Clear MATCH_EN */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_EV_EN, 0x00, 0x07);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) /* Set RC5 cell time to correspond to 36 kHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_CFG1, 0x4A, 0x7F);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) /* Set IRTX_INV */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) if (invert)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) outb(WBCIR_IRTX_INV, data->ebase + WBCIR_REG_ECEIR_CCTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) outb(0x00, data->ebase + WBCIR_REG_ECEIR_CCTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) * Clear IR LED, set SP3 clock to 24Mhz, set TX mask to IRTX1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) * set SP3_IRRX_SW to binary 01, helpfully not documented
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) outb(0x10, data->ebase + WBCIR_REG_ECEIR_CTS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) data->txmask = 0x1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) /* Enable extended mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) wbcir_select_bank(data, WBCIR_BANK_2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) outb(WBCIR_EXT_ENABLE, data->sbase + WBCIR_REG_SP3_EXCR1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) * Configure baud generator, IR data will be sampled at
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) * a bitrate of: (24Mhz * prescaler) / (divisor * 16).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) * The ECIR registers include a flag to change the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) * 24Mhz clock freq to 48Mhz.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) * It's not documented in the specs, but fifo levels
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) * other than 16 seems to be unsupported.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) /* prescaler 1.0, tx/rx fifo lvl 16 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) outb(0x30, data->sbase + WBCIR_REG_SP3_EXCR2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) /* Set baud divisor to sample every 10 us */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) outb(0x0f, data->sbase + WBCIR_REG_SP3_BGDL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) outb(0x00, data->sbase + WBCIR_REG_SP3_BGDH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) /* Set CEIR mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) wbcir_select_bank(data, WBCIR_BANK_0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) outb(0xC0, data->sbase + WBCIR_REG_SP3_MCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) inb(data->sbase + WBCIR_REG_SP3_LSR); /* Clear LSR */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) inb(data->sbase + WBCIR_REG_SP3_MSR); /* Clear MSR */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) /* Disable RX demod, enable run-length enc/dec, set freq span */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) wbcir_select_bank(data, WBCIR_BANK_7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) outb(0x90, data->sbase + WBCIR_REG_SP3_RCCFG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) /* Disable timer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) wbcir_select_bank(data, WBCIR_BANK_4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) outb(0x00, data->sbase + WBCIR_REG_SP3_IRCR1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) /* Disable MSR interrupt, clear AUX_IRX, mask RX during TX? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) wbcir_select_bank(data, WBCIR_BANK_5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) outb(txandrx ? 0x03 : 0x02, data->sbase + WBCIR_REG_SP3_IRCR2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) /* Disable CRC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) wbcir_select_bank(data, WBCIR_BANK_6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) outb(0x20, data->sbase + WBCIR_REG_SP3_IRCR3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) /* Set RX demodulation freq, not really used */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) wbcir_select_bank(data, WBCIR_BANK_7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) outb(0xF2, data->sbase + WBCIR_REG_SP3_IRRXDC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) /* Set TX modulation, 36kHz, 7us pulse width */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) outb(0x69, data->sbase + WBCIR_REG_SP3_IRTXMC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) data->txcarrier = 36000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) /* Set invert and pin direction */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) if (invert)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) outb(0x10, data->sbase + WBCIR_REG_SP3_IRCFG4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) outb(0x00, data->sbase + WBCIR_REG_SP3_IRCFG4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) /* Set FIFO thresholds (RX = 8, TX = 3), reset RX/TX */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) wbcir_select_bank(data, WBCIR_BANK_0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) outb(0x97, data->sbase + WBCIR_REG_SP3_FCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) /* Clear AUX status bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) outb(0xE0, data->sbase + WBCIR_REG_SP3_ASCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) /* Clear RX state */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) data->rxstate = WBCIR_RXSTATE_INACTIVE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) wbcir_idle_rx(data->dev, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) /* Clear TX state */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) if (data->txstate == WBCIR_TXSTATE_ACTIVE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) kfree(data->txbuf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) data->txbuf = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) data->txstate = WBCIR_TXSTATE_INACTIVE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) /* Enable interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) wbcir_set_irqmask(data, WBCIR_IRQ_RX | WBCIR_IRQ_ERR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) wbcir_resume(struct pnp_dev *device)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) struct wbcir_data *data = pnp_get_drvdata(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) wbcir_init_hw(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) ir_raw_event_reset(data->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) enable_irq(data->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) led_classdev_resume(&data->led);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) wbcir_probe(struct pnp_dev *device, const struct pnp_device_id *dev_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) struct device *dev = &device->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) struct wbcir_data *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) if (!(pnp_port_len(device, 0) == EHFUNC_IOMEM_LEN &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) pnp_port_len(device, 1) == WAKEUP_IOMEM_LEN &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) pnp_port_len(device, 2) == SP_IOMEM_LEN)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) dev_err(dev, "Invalid resources\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) data = kzalloc(sizeof(*data), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) if (!data) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) pnp_set_drvdata(device, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) spin_lock_init(&data->spinlock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) data->ebase = pnp_port_start(device, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) data->wbase = pnp_port_start(device, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) data->sbase = pnp_port_start(device, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) data->irq = pnp_irq(device, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) if (data->wbase == 0 || data->ebase == 0 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) data->sbase == 0 || data->irq == -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) err = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) dev_err(dev, "Invalid resources\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) goto exit_free_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) dev_dbg(&device->dev, "Found device (w: 0x%lX, e: 0x%lX, s: 0x%lX, i: %u)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) data->wbase, data->ebase, data->sbase, data->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) data->led.name = "cir::activity";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) data->led.default_trigger = "rc-feedback";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) data->led.brightness_set = wbcir_led_brightness_set;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) data->led.brightness_get = wbcir_led_brightness_get;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) err = led_classdev_register(&device->dev, &data->led);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) goto exit_free_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) data->dev = rc_allocate_device(RC_DRIVER_IR_RAW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) if (!data->dev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) goto exit_unregister_led;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) data->dev->driver_name = DRVNAME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) data->dev->device_name = WBCIR_NAME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) data->dev->input_phys = "wbcir/cir0";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) data->dev->input_id.bustype = BUS_HOST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) data->dev->input_id.vendor = PCI_VENDOR_ID_WINBOND;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) data->dev->input_id.product = WBCIR_ID_FAMILY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) data->dev->input_id.version = WBCIR_ID_CHIP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) data->dev->map_name = RC_MAP_RC6_MCE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) data->dev->s_idle = wbcir_idle_rx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) data->dev->s_carrier_report = wbcir_set_carrier_report;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) data->dev->s_tx_mask = wbcir_txmask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) data->dev->s_tx_carrier = wbcir_txcarrier;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) data->dev->tx_ir = wbcir_tx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) data->dev->priv = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) data->dev->dev.parent = &device->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) data->dev->min_timeout = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) data->dev->timeout = IR_DEFAULT_TIMEOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) data->dev->max_timeout = 10 * IR_DEFAULT_TIMEOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) data->dev->rx_resolution = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) data->dev->allowed_protocols = RC_PROTO_BIT_ALL_IR_DECODER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) data->dev->allowed_wakeup_protocols = RC_PROTO_BIT_NEC |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) RC_PROTO_BIT_NECX | RC_PROTO_BIT_NEC32 | RC_PROTO_BIT_RC5 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) RC_PROTO_BIT_RC6_0 | RC_PROTO_BIT_RC6_6A_20 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) RC_PROTO_BIT_RC6_6A_24 | RC_PROTO_BIT_RC6_6A_32 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) RC_PROTO_BIT_RC6_MCE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) data->dev->wakeup_protocol = RC_PROTO_RC6_MCE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) data->dev->scancode_wakeup_filter.data = 0x800f040c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) data->dev->scancode_wakeup_filter.mask = 0xffff7fff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) data->dev->s_wakeup_filter = wbcir_set_wakeup_filter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) err = rc_register_device(data->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) goto exit_free_rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) if (!request_region(data->wbase, WAKEUP_IOMEM_LEN, DRVNAME)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) dev_err(dev, "Region 0x%lx-0x%lx already in use!\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) data->wbase, data->wbase + WAKEUP_IOMEM_LEN - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) err = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) goto exit_unregister_device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) if (!request_region(data->ebase, EHFUNC_IOMEM_LEN, DRVNAME)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) dev_err(dev, "Region 0x%lx-0x%lx already in use!\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) data->ebase, data->ebase + EHFUNC_IOMEM_LEN - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) err = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) goto exit_release_wbase;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) if (!request_region(data->sbase, SP_IOMEM_LEN, DRVNAME)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) dev_err(dev, "Region 0x%lx-0x%lx already in use!\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) data->sbase, data->sbase + SP_IOMEM_LEN - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) err = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) goto exit_release_ebase;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) err = request_irq(data->irq, wbcir_irq_handler,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) 0, DRVNAME, device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) dev_err(dev, "Failed to claim IRQ %u\n", data->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) err = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) goto exit_release_sbase;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) device_init_wakeup(&device->dev, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) wbcir_init_hw(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) exit_release_sbase:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) release_region(data->sbase, SP_IOMEM_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) exit_release_ebase:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) release_region(data->ebase, EHFUNC_IOMEM_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) exit_release_wbase:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) release_region(data->wbase, WAKEUP_IOMEM_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) exit_unregister_device:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) rc_unregister_device(data->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) data->dev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) exit_free_rc:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) rc_free_device(data->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) exit_unregister_led:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) led_classdev_unregister(&data->led);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) exit_free_data:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) kfree(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) pnp_set_drvdata(device, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) wbcir_remove(struct pnp_dev *device)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) struct wbcir_data *data = pnp_get_drvdata(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) /* Disable interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) wbcir_set_irqmask(data, WBCIR_IRQ_NONE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) free_irq(data->irq, device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) /* Clear status bits NEC_REP, BUFF, MSG_END, MATCH */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_STS, 0x17, 0x17);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) /* Clear CEIR_EN */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_CTL, 0x00, 0x01);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) /* Clear BUFF_EN, END_EN, MATCH_EN */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_EV_EN, 0x00, 0x07);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) rc_unregister_device(data->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) led_classdev_unregister(&data->led);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) /* This is ok since &data->led isn't actually used */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) wbcir_led_brightness_set(&data->led, LED_OFF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) release_region(data->wbase, WAKEUP_IOMEM_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) release_region(data->ebase, EHFUNC_IOMEM_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) release_region(data->sbase, SP_IOMEM_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) kfree(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) pnp_set_drvdata(device, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) static const struct pnp_device_id wbcir_ids[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) { "WEC1022", 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) { "", 0 }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) MODULE_DEVICE_TABLE(pnp, wbcir_ids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) static struct pnp_driver wbcir_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) .name = DRVNAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) .id_table = wbcir_ids,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) .probe = wbcir_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) .remove = wbcir_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) .suspend = wbcir_suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) .resume = wbcir_resume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) .shutdown = wbcir_shutdown
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) static int __init
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) wbcir_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) ret = pnp_register_driver(&wbcir_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) pr_err("Unable to register driver\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) static void __exit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) wbcir_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) pnp_unregister_driver(&wbcir_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) module_init(wbcir_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) module_exit(wbcir_exit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) MODULE_AUTHOR("David Härdeman <david@hardeman.nu>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) MODULE_DESCRIPTION("Winbond SuperI/O Consumer IR Driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) MODULE_LICENSE("GPL");