diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-02-22 01:58:32 +0100 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-02-22 01:58:32 +0100 |
commit | ff58d005cd10fcd372787cceac547e11cf706ff6 (patch) | |
tree | 7e7af56aa1a38731af1ec5f3cf09f13050bb0ff4 /drivers/media/rc/nuvoton-cir.c | |
parent | Merge tag 'pinctrl-v4.11-1' of git://git.kernel.org/pub/scm/linux/kernel/git/... (diff) | |
parent | [media] mtk-vcodec: fix build warnings without DEBUG (diff) | |
download | linux-ff58d005cd10fcd372787cceac547e11cf706ff6.tar.xz linux-ff58d005cd10fcd372787cceac547e11cf706ff6.zip |
Merge tag 'media/v4.11-1' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media
Pull media updates from Mauro Carvalho Chehab:
- new drivers:
- i.MX6 Video Data Order Adapter's (VDOA)
- Toshiba et8ek8 5MP sensor
- STM DELTA multi-format video decoder V4L2 driver
- SPI connected IR LED
- Mediatek IR remote receiver
- ZyDAS ZD1301 DVB USB interface driver
- new RC keymaps
- some very old LIRC drivers got removed from staging
- RC core gained support encoding IR scan codes
- DVB si2168 gained support for DVBv5 statistics
- lirc_sir driver ported to rc-core and promoted from staging
- other bug fixes, board additions and driver improvements
* tag 'media/v4.11-1' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (230 commits)
[media] mtk-vcodec: fix build warnings without DEBUG
[media] zd1301: fix building interface driver without demodulator
[media] usbtv: add sharpness control
[media] cxusb: Use a dma capable buffer also for reading
[media] ttpci: address stringop overflow warning
[media] dvb-usb-v2: avoid use-after-free
[media] add Hama Hybrid DVB-T Stick support
[media] et8ek8: Fix compiler / Coccinelle warnings
[media] media: fix semicolon.cocci warnings
[media] media: exynos4-is: add flags to dummy Exynos IS i2c adapter
[media] v4l: of: check for unique lanes in data-lanes and clock-lanes
[media] coda/imx-vdoa: constify structs
[media] st-delta: debug: trace stream/frame information & summary
[media] st-delta: add mjpeg support
[media] st-delta: EOS (End Of Stream) support
[media] st-delta: rpmsg ipc support
[media] st-delta: add memory allocator helper functions
[media] st-delta: STiH4xx multi-format video decoder v4l2 driver
[media] MAINTAINERS: add st-delta driver
[media] ARM: multi_v7_defconfig: enable STMicroelectronics DELTA Support
...
Diffstat (limited to 'drivers/media/rc/nuvoton-cir.c')
-rw-r--r-- | drivers/media/rc/nuvoton-cir.c | 130 |
1 files changed, 98 insertions, 32 deletions
diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c index 4b78c891eb77..b109f8246b96 100644 --- a/drivers/media/rc/nuvoton-cir.c +++ b/drivers/media/rc/nuvoton-cir.c @@ -18,11 +18,6 @@ * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt @@ -176,6 +171,41 @@ static void nvt_set_ioaddr(struct nvt_dev *nvt, unsigned long *ioaddr) } } +static void nvt_write_wakeup_codes(struct rc_dev *dev, + const u8 *wbuf, int count) +{ + u8 tolerance, config; + struct nvt_dev *nvt = dev->priv; + int i; + + /* hardcode the tolerance to 10% */ + tolerance = DIV_ROUND_UP(count, 10); + + spin_lock(&nvt->lock); + + nvt_clear_cir_wake_fifo(nvt); + nvt_cir_wake_reg_write(nvt, count, CIR_WAKE_FIFO_CMP_DEEP); + nvt_cir_wake_reg_write(nvt, tolerance, CIR_WAKE_FIFO_CMP_TOL); + + config = nvt_cir_wake_reg_read(nvt, CIR_WAKE_IRCON); + + /* enable writes to wake fifo */ + nvt_cir_wake_reg_write(nvt, config | CIR_WAKE_IRCON_MODE1, + CIR_WAKE_IRCON); + + if (count) + pr_info("Wake samples (%d) =", count); + else + pr_info("Wake sample fifo cleared"); + + for (i = 0; i < count; i++) + nvt_cir_wake_reg_write(nvt, wbuf[i], CIR_WAKE_WR_FIFO_DATA); + + nvt_cir_wake_reg_write(nvt, config, CIR_WAKE_IRCON); + + spin_unlock(&nvt->lock); +} + static ssize_t wakeup_data_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -214,9 +244,7 @@ static ssize_t wakeup_data_store(struct device *dev, const char *buf, size_t len) { struct rc_dev *rc_dev = to_rc_dev(dev); - struct nvt_dev *nvt = rc_dev->priv; - unsigned long flags; - u8 tolerance, config, wake_buf[WAKEUP_MAX_SIZE]; + u8 wake_buf[WAKEUP_MAX_SIZE]; char **argv; int i, count; unsigned int val; @@ -245,27 +273,7 @@ static ssize_t wakeup_data_store(struct device *dev, wake_buf[i] |= BUF_PULSE_BIT; } - /* hardcode the tolerance to 10% */ - tolerance = DIV_ROUND_UP(count, 10); - - spin_lock_irqsave(&nvt->lock, flags); - - nvt_clear_cir_wake_fifo(nvt); - nvt_cir_wake_reg_write(nvt, count, CIR_WAKE_FIFO_CMP_DEEP); - nvt_cir_wake_reg_write(nvt, tolerance, CIR_WAKE_FIFO_CMP_TOL); - - config = nvt_cir_wake_reg_read(nvt, CIR_WAKE_IRCON); - - /* enable writes to wake fifo */ - nvt_cir_wake_reg_write(nvt, config | CIR_WAKE_IRCON_MODE1, - CIR_WAKE_IRCON); - - for (i = 0; i < count; i++) - nvt_cir_wake_reg_write(nvt, wake_buf[i], CIR_WAKE_WR_FIFO_DATA); - - nvt_cir_wake_reg_write(nvt, config, CIR_WAKE_IRCON); - - spin_unlock_irqrestore(&nvt->lock, flags); + nvt_write_wakeup_codes(rc_dev, wake_buf, count); ret = len; out: @@ -662,6 +670,62 @@ static int nvt_set_tx_carrier(struct rc_dev *dev, u32 carrier) return 0; } +static int nvt_ir_raw_set_wakeup_filter(struct rc_dev *dev, + struct rc_scancode_filter *sc_filter) +{ + u8 buf_val; + int i, ret, count; + unsigned int val; + struct ir_raw_event *raw; + u8 wake_buf[WAKEUP_MAX_SIZE]; + bool complete; + + /* Require mask to be set */ + if (!sc_filter->mask) + return 0; + + raw = kmalloc_array(WAKEUP_MAX_SIZE, sizeof(*raw), GFP_KERNEL); + if (!raw) + return -ENOMEM; + + ret = ir_raw_encode_scancode(dev->wakeup_protocol, sc_filter->data, + raw, WAKEUP_MAX_SIZE); + complete = (ret != -ENOBUFS); + if (!complete) + ret = WAKEUP_MAX_SIZE; + else if (ret < 0) + goto out_raw; + + /* Inspect the ir samples */ + for (i = 0, count = 0; i < ret && count < WAKEUP_MAX_SIZE; ++i) { + /* NS to US */ + val = DIV_ROUND_UP(raw[i].duration, 1000L) / SAMPLE_PERIOD; + + /* Split too large values into several smaller ones */ + while (val > 0 && count < WAKEUP_MAX_SIZE) { + /* Skip last value for better comparison tolerance */ + if (complete && i == ret - 1 && val < BUF_LEN_MASK) + break; + + /* Clamp values to BUF_LEN_MASK at most */ + buf_val = (val > BUF_LEN_MASK) ? BUF_LEN_MASK : val; + + wake_buf[count] = buf_val; + val -= buf_val; + if ((raw[i]).pulse) + wake_buf[count] |= BUF_PULSE_BIT; + count++; + } + } + + nvt_write_wakeup_codes(dev, wake_buf, count); + ret = 0; +out_raw: + kfree(raw); + + return ret; +} + /* * nvt_tx_ir * @@ -998,7 +1062,7 @@ static int nvt_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id) return -ENOMEM; /* input device for IR remote (and tx) */ - nvt->rdev = devm_rc_allocate_device(&pdev->dev); + nvt->rdev = devm_rc_allocate_device(&pdev->dev, RC_DRIVER_IR_RAW); if (!nvt->rdev) return -ENOMEM; rdev = nvt->rdev; @@ -1061,12 +1125,14 @@ static int nvt_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id) /* Set up the rc device */ rdev->priv = nvt; - rdev->driver_type = RC_DRIVER_IR_RAW; - rdev->allowed_protocols = RC_BIT_ALL; + rdev->allowed_protocols = RC_BIT_ALL_IR_DECODER; + rdev->allowed_wakeup_protocols = RC_BIT_ALL_IR_ENCODER; + rdev->encode_wakeup = true; rdev->open = nvt_open; rdev->close = nvt_close; rdev->tx_ir = nvt_tx_ir; rdev->s_tx_carrier = nvt_set_tx_carrier; + rdev->s_wakeup_filter = nvt_ir_raw_set_wakeup_filter; rdev->input_name = "Nuvoton w836x7hg Infrared Remote Transceiver"; rdev->input_phys = "nuvoton/cir0"; rdev->input_id.bustype = BUS_HOST; |