summaryrefslogtreecommitdiffstats
path: root/drivers/media/rc/nuvoton-cir.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2015-06-25 17:55:48 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2015-06-25 17:55:48 -0700
commit5b4ca4447757019f11a601b0009534ef84bed801 (patch)
tree09bc8445e61aea621580d7587c21ac3f2b0cafb4 /drivers/media/rc/nuvoton-cir.c
parent0db9723cacf4d62bc3685fb15179b39ee4e17679 (diff)
parentfaebbd8f134f0c054f372982c8ddd1bbcc41b440 (diff)
downloadop-kernel-dev-5b4ca4447757019f11a601b0009534ef84bed801.zip
op-kernel-dev-5b4ca4447757019f11a601b0009534ef84bed801.tar.gz
Merge tag 'media/v4.2-1' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media
Pull media updates from Mauro Carvalho Chehab: - Lots of improvements at the DVB API DocBook documentation. Now, the frontend and the network APIs are fully in sync with the Kernel and looks more like the rest of the media documentation; - New frontend driver: cx24120 - New driver for a PCI device: cobalt. This driver is actually not sold in the market, but it is a good example of a multi-HDMI input device; - The dt3155 driver were promoted from staging; - The mantis driver got remote controller support; - New V4L2 driver for ST bdisp SoC chipsets; - Make sparse and smatch happier: several bugs were solved by fixing the issues reported by those static code analyzers. - Lots of new device additions, new features, improvements and cleanups at the existing drivers. * tag 'media/v4.2-1' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (553 commits) [media] lmedm04: fix the range for relative measurements [media] lmedm04: use u32 instead of u64 for relative stats [media] omap3isp: remove unused var [media] saa7134: fix page size on some archs [media] use CONFIG_PM_SLEEP for suspend/resume [media] tuner-i2c: be consistent with I2C declaration [media] si470x: cleanup define namespace [media] bdisp: prevent compiling on random arch [media] vb2: Don't WARN when v4l2_buffer.bytesused is 0 for multiplanar buffers [media] MAINTAINERS: Add entry for the Renesas VSP1 driver [media] videodev2.h: fix copy-and-paste error in V4L2_MAP_XFER_FUNC_DEFAULT [media] Revert "[media] vb2: Push mmap_sem down to memops" [media] mantis: cleanup a warning [media] bdisp-debug: don't try to divide by s64 [media] cx88: don't declare restart_video_queue if not used [media] au0828: move dev->boards atribuition to happen earlier [media] lmedm04: implement dvb v5 statistics [media] bdisp: remove unused var [media] bdisp: remove needless check ts2020: fix compilation on i386 ...
Diffstat (limited to 'drivers/media/rc/nuvoton-cir.c')
-rw-r--r--drivers/media/rc/nuvoton-cir.c127
1 files changed, 127 insertions, 0 deletions
diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c
index 85af7a8..baeb597 100644
--- a/drivers/media/rc/nuvoton-cir.c
+++ b/drivers/media/rc/nuvoton-cir.c
@@ -526,6 +526,130 @@ static int nvt_set_tx_carrier(struct rc_dev *dev, u32 carrier)
return 0;
}
+static int nvt_write_wakeup_codes(struct rc_dev *dev,
+ const u8 *wakeup_sample_buf, int count)
+{
+ int i = 0;
+ u8 reg, reg_learn_mode;
+ unsigned long flags;
+ struct nvt_dev *nvt = dev->priv;
+
+ nvt_dbg_wake("writing wakeup samples");
+
+ reg = nvt_cir_wake_reg_read(nvt, CIR_WAKE_IRCON);
+ reg_learn_mode = reg & ~CIR_WAKE_IRCON_MODE0;
+ reg_learn_mode |= CIR_WAKE_IRCON_MODE1;
+
+ /* Lock the learn area to prevent racing with wake-isr */
+ spin_lock_irqsave(&nvt->nvt_lock, flags);
+
+ /* Enable fifo writes */
+ nvt_cir_wake_reg_write(nvt, reg_learn_mode, CIR_WAKE_IRCON);
+
+ /* Clear cir wake rx fifo */
+ nvt_clear_cir_wake_fifo(nvt);
+
+ if (count > WAKE_FIFO_LEN) {
+ nvt_dbg_wake("HW FIFO too small for all wake samples");
+ count = WAKE_FIFO_LEN;
+ }
+
+ if (count)
+ pr_info("Wake samples (%d) =", count);
+ else
+ pr_info("Wake sample fifo cleared");
+
+ /* Write wake samples to fifo */
+ for (i = 0; i < count; i++) {
+ pr_cont(" %02x", wakeup_sample_buf[i]);
+ nvt_cir_wake_reg_write(nvt, wakeup_sample_buf[i],
+ CIR_WAKE_WR_FIFO_DATA);
+ }
+ pr_cont("\n");
+
+ /* Switch cir to wakeup mode and disable fifo writing */
+ nvt_cir_wake_reg_write(nvt, reg, CIR_WAKE_IRCON);
+
+ /* Set number of bytes needed for wake */
+ nvt_cir_wake_reg_write(nvt, count ? count :
+ CIR_WAKE_FIFO_CMP_BYTES,
+ CIR_WAKE_FIFO_CMP_DEEP);
+
+ spin_unlock_irqrestore(&nvt->nvt_lock, flags);
+
+ return 0;
+}
+
+static int nvt_ir_raw_set_wakeup_filter(struct rc_dev *dev,
+ struct rc_scancode_filter *sc_filter)
+{
+ u8 *reg_buf;
+ u8 buf_val;
+ int i, ret, count;
+ unsigned int val;
+ struct ir_raw_event *raw;
+ bool complete;
+
+ /* Require both mask and data to be set before actually committing */
+ if (!sc_filter->mask || !sc_filter->data)
+ return 0;
+
+ raw = kmalloc_array(WAKE_FIFO_LEN, sizeof(*raw), GFP_KERNEL);
+ if (!raw)
+ return -ENOMEM;
+
+ ret = ir_raw_encode_scancode(dev->enabled_wakeup_protocols, sc_filter,
+ raw, WAKE_FIFO_LEN);
+ complete = (ret != -ENOBUFS);
+ if (!complete)
+ ret = WAKE_FIFO_LEN;
+ else if (ret < 0)
+ goto out_raw;
+
+ reg_buf = kmalloc_array(WAKE_FIFO_LEN, sizeof(*reg_buf), GFP_KERNEL);
+ if (!reg_buf) {
+ ret = -ENOMEM;
+ goto out_raw;
+ }
+
+ /* Inspect the ir samples */
+ for (i = 0, count = 0; i < ret && count < WAKE_FIFO_LEN; ++i) {
+ val = NS_TO_US((raw[i]).duration) / SAMPLE_PERIOD;
+
+ /* Split too large values into several smaller ones */
+ while (val > 0 && count < WAKE_FIFO_LEN) {
+
+ /* 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;
+
+ reg_buf[count] = buf_val;
+ val -= buf_val;
+ if ((raw[i]).pulse)
+ reg_buf[count] |= BUF_PULSE_BIT;
+ count++;
+ }
+ }
+
+ ret = nvt_write_wakeup_codes(dev, reg_buf, count);
+
+ kfree(reg_buf);
+out_raw:
+ kfree(raw);
+
+ return ret;
+}
+
+/* Dummy implementation. nuvoton is agnostic to the protocol used */
+static int nvt_ir_raw_change_wakeup_protocol(struct rc_dev *dev,
+ u64 *rc_type)
+{
+ return 0;
+}
+
/*
* nvt_tx_ir
*
@@ -1043,11 +1167,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->encode_wakeup = true;
rdev->allowed_protocols = RC_BIT_ALL;
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->change_wakeup_protocol = nvt_ir_raw_change_wakeup_protocol;
rdev->input_name = "Nuvoton w836x7hg Infrared Remote Transceiver";
rdev->input_phys = "nuvoton/cir0";
rdev->input_id.bustype = BUS_HOST;
OpenPOWER on IntegriCloud