blob: 9522990383915d093dee0c832f2c055d9ecae171 [file] [log] [blame]
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* ImgTec IR Hardware Decoder found in PowerDown Controller.
*
* Copyright 2010-2014 Imagination Technologies Ltd.
*/
#ifndef _IMG_IR_HW_H_
#define _IMG_IR_HW_H_
#include <linux/kernel.h>
#include <media/rc-core.h>
/* constants */
#define IMG_IR_CODETYPE_PULSELEN 0x0 /* Sony */
#define IMG_IR_CODETYPE_PULSEDIST 0x1 /* NEC, Toshiba, Micom, Sharp */
#define IMG_IR_CODETYPE_BIPHASE 0x2 /* RC-5/6 */
#define IMG_IR_CODETYPE_2BITPULSEPOS 0x3 /* RC-MM */
/* Timing information */
/**
* struct img_ir_control - Decoder control settings
* @decoden: Primary decoder enable
* @code_type: Decode type (see IMG_IR_CODETYPE_*)
* @hdrtog: Detect header toggle symbol after leader symbol
* @ldrdec: Don't discard leader if maximum width reached
* @decodinpol: Decoder input polarity (1=active high)
* @bitorien: Bit orientation (1=MSB first)
* @d1validsel: Decoder 2 takes over if it detects valid data
* @bitinv: Bit inversion switch (1=don't invert)
* @decodend2: Secondary decoder enable (no leader symbol)
* @bitoriend2: Bit orientation (1=MSB first)
* @bitinvd2: Secondary decoder bit inversion switch (1=don't invert)
*/
struct img_ir_control {
unsigned decoden:1;
unsigned code_type:2;
unsigned hdrtog:1;
unsigned ldrdec:1;
unsigned decodinpol:1;
unsigned bitorien:1;
unsigned d1validsel:1;
unsigned bitinv:1;
unsigned decodend2:1;
unsigned bitoriend2:1;
unsigned bitinvd2:1;
};
/**
* struct img_ir_timing_range - range of timing values
* @min: Minimum timing value
* @max: Maximum timing value (if < @min, this will be set to @min during
* preprocessing step, so it is normally not explicitly initialised
* and is taken care of by the tolerance)
*/
struct img_ir_timing_range {
u16 min;
u16 max;
};
/**
* struct img_ir_symbol_timing - timing data for a symbol
* @pulse: Timing range for the length of the pulse in this symbol
* @space: Timing range for the length of the space in this symbol
*/
struct img_ir_symbol_timing {
struct img_ir_timing_range pulse;
struct img_ir_timing_range space;
};
/**
* struct img_ir_free_timing - timing data for free time symbol
* @minlen: Minimum number of bits of data
* @maxlen: Maximum number of bits of data
* @ft_min: Minimum free time after message
*/
struct img_ir_free_timing {
/* measured in bits */
u8 minlen;
u8 maxlen;
u16 ft_min;
};
/**
* struct img_ir_timings - Timing values.
* @ldr: Leader symbol timing data
* @s00: Zero symbol timing data for primary decoder
* @s01: One symbol timing data for primary decoder
* @s10: Zero symbol timing data for secondary (no leader symbol) decoder
* @s11: One symbol timing data for secondary (no leader symbol) decoder
* @ft: Free time symbol timing data
*/
struct img_ir_timings {
struct img_ir_symbol_timing ldr, s00, s01, s10, s11;
struct img_ir_free_timing ft;
};
/**
* struct img_ir_filter - Filter IR events.
* @data: Data to match.
* @mask: Mask of bits to compare.
* @minlen: Additional minimum number of bits.
* @maxlen: Additional maximum number of bits.
*/
struct img_ir_filter {
u64 data;
u64 mask;
u8 minlen;
u8 maxlen;
};
/**
* struct img_ir_timing_regvals - Calculated timing register values.
* @ldr: Leader symbol timing register value
* @s00: Zero symbol timing register value for primary decoder
* @s01: One symbol timing register value for primary decoder
* @s10: Zero symbol timing register value for secondary decoder
* @s11: One symbol timing register value for secondary decoder
* @ft: Free time symbol timing register value
*/
struct img_ir_timing_regvals {
u32 ldr, s00, s01, s10, s11, ft;
};
#define IMG_IR_SCANCODE 0 /* new scancode */
#define IMG_IR_REPEATCODE 1 /* repeat the previous code */
/**
* struct img_ir_scancode_req - Scancode request data.
* @protocol: Protocol code of received message (defaults to
* RC_PROTO_UNKNOWN).
* @scancode: Scan code of received message (must be written by
* handler if IMG_IR_SCANCODE is returned).
* @toggle: Toggle bit (defaults to 0).
*/
struct img_ir_scancode_req {
enum rc_proto protocol;
u32 scancode;
u8 toggle;
};
/**
* struct img_ir_decoder - Decoder settings for an IR protocol.
* @type: Protocol types bitmap.
* @tolerance: Timing tolerance as a percentage (default 10%).
* @unit: Unit of timings in nanoseconds (default 1 us).
* @timings: Primary timings
* @rtimings: Additional override timings while waiting for repeats.
* @repeat: Maximum repeat interval (always in milliseconds).
* @control: Control flags.
*
* @scancode: Pointer to function to convert the IR data into a scancode (it
* must be safe to execute in interrupt context).
* Returns IMG_IR_SCANCODE to emit new scancode.
* Returns IMG_IR_REPEATCODE to repeat previous code.
* Returns -errno (e.g. -EINVAL) on error.
* @filter: Pointer to function to convert scancode filter to raw hardware
* filter. The minlen and maxlen fields will have been initialised
* to the maximum range.
*/
struct img_ir_decoder {
/* core description */
u64 type;
unsigned int tolerance;
unsigned int unit;
struct img_ir_timings timings;
struct img_ir_timings rtimings;
unsigned int repeat;
struct img_ir_control control;
/* scancode logic */
int (*scancode)(int len, u64 raw, u64 enabled_protocols,
struct img_ir_scancode_req *request);
int (*filter)(const struct rc_scancode_filter *in,
struct img_ir_filter *out, u64 protocols);
};
extern struct img_ir_decoder img_ir_nec;
extern struct img_ir_decoder img_ir_jvc;
extern struct img_ir_decoder img_ir_sony;
extern struct img_ir_decoder img_ir_sharp;
extern struct img_ir_decoder img_ir_sanyo;
extern struct img_ir_decoder img_ir_rc5;
extern struct img_ir_decoder img_ir_rc6;
/**
* struct img_ir_reg_timings - Reg values for decoder timings at clock rate.
* @ctrl: Processed control register value.
* @timings: Processed primary timings.
* @rtimings: Processed repeat timings.
*/
struct img_ir_reg_timings {
u32 ctrl;
struct img_ir_timing_regvals timings;
struct img_ir_timing_regvals rtimings;
};
struct img_ir_priv;
#ifdef CONFIG_IR_IMG_HW
enum img_ir_mode {
IMG_IR_M_NORMAL,
IMG_IR_M_REPEATING,
#ifdef CONFIG_PM_SLEEP
IMG_IR_M_WAKE,
#endif
};
/**
* struct img_ir_priv_hw - Private driver data for hardware decoder.
* @ct_quirks: Quirk bits for each code type.
* @rdev: Remote control device
* @clk_nb: Notifier block for clock notify events.
* @end_timer: Timer until repeat timeout.
* @suspend_timer: Timer to re-enable protocol.
* @decoder: Current decoder settings.
* @enabled_protocols: Currently enabled protocols.
* @clk_hz: Current core clock rate in Hz.
* @reg_timings: Timing reg values for decoder at clock rate.
* @flags: IMG_IR_F_*.
* @filters: HW filters (derived from scancode filters).
* @mode: Current decode mode.
* @stopping: Indicates that decoder is being taken down and timers
* should not be restarted.
* @suspend_irqen: Saved IRQ enable mask over suspend.
* @quirk_suspend_irq: Saved IRQ enable mask over quirk suspend timer.
*/
struct img_ir_priv_hw {
unsigned int ct_quirks[4];
struct rc_dev *rdev;
struct notifier_block clk_nb;
struct timer_list end_timer;
struct timer_list suspend_timer;
const struct img_ir_decoder *decoder;
u64 enabled_protocols;
unsigned long clk_hz;
struct img_ir_reg_timings reg_timings;
unsigned int flags;
struct img_ir_filter filters[RC_FILTER_MAX];
enum img_ir_mode mode;
bool stopping;
u32 suspend_irqen;
u32 quirk_suspend_irq;
};
static inline bool img_ir_hw_enabled(struct img_ir_priv_hw *hw)
{
return hw->rdev;
};
void img_ir_isr_hw(struct img_ir_priv *priv, u32 irq_status);
void img_ir_setup_hw(struct img_ir_priv *priv);
int img_ir_probe_hw(struct img_ir_priv *priv);
void img_ir_remove_hw(struct img_ir_priv *priv);
#ifdef CONFIG_PM_SLEEP
int img_ir_suspend(struct device *dev);
int img_ir_resume(struct device *dev);
#else
#define img_ir_suspend NULL
#define img_ir_resume NULL
#endif
#else
struct img_ir_priv_hw {
};
static inline bool img_ir_hw_enabled(struct img_ir_priv_hw *hw)
{
return false;
};
static inline void img_ir_isr_hw(struct img_ir_priv *priv, u32 irq_status)
{
}
static inline void img_ir_setup_hw(struct img_ir_priv *priv)
{
}
static inline int img_ir_probe_hw(struct img_ir_priv *priv)
{
return -ENODEV;
}
static inline void img_ir_remove_hw(struct img_ir_priv *priv)
{
}
#define img_ir_suspend NULL
#define img_ir_resume NULL
#endif /* CONFIG_IR_IMG_HW */
#endif /* _IMG_IR_HW_H_ */