Re: [PATCH v2 9/9] rc: nuvoton-cir: Add support for writing wakeup samples via sysfs filter callback

2014-03-16 Thread James Hogan
On Sunday 16 March 2014 10:39:39 Antti Seppälä wrote:
> > +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.

Yep, good point

Thanks
James

signature.asc
Description: This is a digitally signed message part.


Re: [PATCH v2 9/9] rc: nuvoton-cir: Add support for writing wakeup samples via sysfs filter callback

2014-03-16 Thread Antti Seppälä
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) {
>