summaryrefslogtreecommitdiffstats
path: root/drivers/media/rc/img-ir/img-ir-hw.h
blob: 5c2b216c5fe3eb3723177d6c2e7145e1d9cba75b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
/*
 * ImgTec IR Hardware Decoder found in PowerDown Controller.
 *
 * Copyright 2010-2014 Imagination Technologies Ltd.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by the
 * Free Software Foundation; either version 2 of the License, or (at your
 * option) any later version.
 */

#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_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, enum rc_type *protocol,
			u32 *scancode, u64 enabled_protocols);
	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;

/**
 * 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.
 * @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.
 */
struct img_ir_priv_hw {
	unsigned int			ct_quirks[4];
	struct rc_dev			*rdev;
	struct notifier_block		clk_nb;
	struct timer_list		end_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;
};

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_ */