298 lines
8.4 KiB
C
298 lines
8.4 KiB
C
/* 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_ */
|