On 15 March 2014 01:04, James Hogan wrote:
> From: Antti Seppälä
>
> Nuvoton-cir utilizes the encoding capabilities of rc-core to convert
> scancodes from user space to pulse/space format understood by the
> underlying hardware.
>
> Converted samples are then written to the wakeup fifo along with other
> necessary configuration to enable wake up functionality.
>
> Signed-off-by: Antti Seppälä
> Signed-off-by: James Hogan
> Cc: Mauro Carvalho Chehab
> Cc: Jarod Wilson
> Cc: Wei Yongjun
> Cc: Hans Verkuil
> ---
> Please note this patch is only build tested.
>
> Changes in v2 (James Hogan):
> - Handle new -ENOBUFS when IR encoding buffer isn't long enough and
>reduce buffer size to the size of the wake fifo so that time isn't
>wasted processing encoded IR events that will be discarded. Also only
>discard the last event if the encoded data is complete.
> - Change reference to rc_dev::enabled_protocols to
>enabled_protocols[type] since it has been converted to an array.
> - Fix IR encoding buffer loop condition to be i < ret rather than i <=
>ret. The return value of ir_raw_encode_scancode is the number of
>events rather than the last event.
> - Set encode_wakeup so that the set of allowed wakeup protocols matches
>the set of raw IR encoders.
> ---
> drivers/media/rc/nuvoton-cir.c | 123
> +
> drivers/media/rc/nuvoton-cir.h | 1 +
> include/media/rc-core.h| 1 +
> 3 files changed, 125 insertions(+)
>
> diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c
> index d244e1a..ec8f4fc 100644
> --- a/drivers/media/rc/nuvoton-cir.c
> +++ b/drivers/media/rc/nuvoton-cir.c
> @@ -527,6 +527,127 @@ 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;
> + }
Now that the encoders support partial encoding the above check against
WAKE_FIFO_LEN never triggers and can be removed.
> +
> + 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_filter(struct rc_dev *dev, enum rc_filter_type
> type,
> +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;
> +
> + /* Other types are not valid for nuvoton */
> + if (type != RC_FILTER_WAKEUP)
> + return -EINVAL;
> +
> + /* Require both mask and data to be set before actually committing */
> + if (!sc_filter->mask || !sc_filter->data)
> + return 0;
> +
> + raw = kmalloc(WAKE_FIFO_LEN * sizeof(*raw), GFP_KERNEL);
> + if (!raw)
> + return -ENOMEM;
> +
> + ret = ir_raw_encode_scancode(dev->enabled_protocols[type], 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(sizeof(*reg_buf) * WAKE_FIFO_LEN, GFP_KERNEL);
> + if (!reg_buf) {
>