aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@osg.samsung.com>2015-02-04 04:07:30 -0500
committerMauro Carvalho Chehab <mchehab@osg.samsung.com>2015-03-02 12:50:06 -0500
commit559addc25b00ff3a40eff03a0b3873c2b6d726f8 (patch)
tree1bad1442f4bd55fe063f6b04ce00573927fc9517 /drivers/input
parent96df988bb935959e6380c2333e03911839079ee1 (diff)
[media] fixp-arith: replace sin/cos table by a better precision one
The cos table used at fixp-arith.h has only 8 bits of precision. That causes problems if it is reused on other drivers. As some media drivers require a higher precision sin/cos implementation, replace the current implementation by one that will provide 32 bits precision. The values generated by the new implementation matches the 32 bit precision of glibc's sin for an angle measured in integer degrees. It also provides support for fractional angles via linear interpolation. On experimental calculus, when used a table with a 0.001 degree angle, the maximum error for sin is 0.000038, which is likely good enough for practical purposes. There are some logic there that seems to be specific to the usage inside ff-memless.c. Move those logic to there, as they're not needed elsewhere. Cc: Hans de Goede <hdegoede@redhat.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com> Signed-off-by: Prashant Laddha <prladdha@cisco.com> Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Acked-by: Dmitry Torokhov <dmitry.torokhov@gmail.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
Diffstat (limited to 'drivers/input')
-rw-r--r--drivers/input/ff-memless.c18
1 files changed, 15 insertions, 3 deletions
diff --git a/drivers/input/ff-memless.c b/drivers/input/ff-memless.c
index 74c0d8c6002a..fcc6c3368182 100644
--- a/drivers/input/ff-memless.c
+++ b/drivers/input/ff-memless.c
@@ -237,6 +237,18 @@ static u16 ml_calculate_direction(u16 direction, u16 force,
237 (force + new_force)) << 1; 237 (force + new_force)) << 1;
238} 238}
239 239
240#define FRAC_N 8
241static inline s16 fixp_new16(s16 a)
242{
243 return ((s32)a) >> (16 - FRAC_N);
244}
245
246static inline s16 fixp_mult(s16 a, s16 b)
247{
248 a = ((s32)a * 0x100) / 0x7fff;
249 return ((s32)(a * b)) >> FRAC_N;
250}
251
240/* 252/*
241 * Combine two effects and apply gain. 253 * Combine two effects and apply gain.
242 */ 254 */
@@ -247,7 +259,7 @@ static void ml_combine_effects(struct ff_effect *effect,
247 struct ff_effect *new = state->effect; 259 struct ff_effect *new = state->effect;
248 unsigned int strong, weak, i; 260 unsigned int strong, weak, i;
249 int x, y; 261 int x, y;
250 fixp_t level; 262 s16 level;
251 263
252 switch (new->type) { 264 switch (new->type) {
253 case FF_CONSTANT: 265 case FF_CONSTANT:
@@ -255,8 +267,8 @@ static void ml_combine_effects(struct ff_effect *effect,
255 level = fixp_new16(apply_envelope(state, 267 level = fixp_new16(apply_envelope(state,
256 new->u.constant.level, 268 new->u.constant.level,
257 &new->u.constant.envelope)); 269 &new->u.constant.envelope));
258 x = fixp_mult(fixp_sin(i), level) * gain / 0xffff; 270 x = fixp_mult(fixp_sin16(i), level) * gain / 0xffff;
259 y = fixp_mult(-fixp_cos(i), level) * gain / 0xffff; 271 y = fixp_mult(-fixp_cos16(i), level) * gain / 0xffff;
260 /* 272 /*
261 * here we abuse ff_ramp to hold x and y of constant force 273 * here we abuse ff_ramp to hold x and y of constant force
262 * If in future any driver wants something else than x and y 274 * If in future any driver wants something else than x and y