aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2010-10-01 17:14:25 -0400
committerGuenter Roeck <guenter.roeck@ericsson.com>2010-10-25 17:11:20 -0400
commit2ee321440e3a594dcdd9981e68e5e302447047a2 (patch)
treec2dde23d160339ff713f9fd12f7922cca0c8c6d3
parent37394050b5be0fe87f96ed8848f11c3c2cd4d556 (diff)
hwmon: (lis3) add axes module parameter for custom axis-mapping
The axis-mapping of lis3dev device on many (rather most) HP machines doesn't follow the standard. When each new model appears, users need to adjust again. Testing this requires the rebuild of kernel, thus it's not trivial for end-users. This patch adds a module parameter "axes" to allow a custom axis-mapping without patching and recompiling the kernel driver. User can pass the parameter such as axes=3,2,1. Also it can be changed via sysfs. Signed-off-by: Takashi Iwai <tiwai@suse.de> Acked-by: Eric Piel <eric.piel@tremplin-utc.net> Cc: Jean Delvare <khali@linux-fr.org> Cc: Guenter Roeck <guenter.roeck@ericsson.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Guenter Roeck <guenter.roeck@ericsson.com>
-rw-r--r--drivers/hwmon/hp_accel.c30
-rw-r--r--drivers/hwmon/lis3lv02d.c24
-rw-r--r--drivers/hwmon/lis3lv02d.h11
-rw-r--r--drivers/hwmon/lis3lv02d_i2c.c5
-rw-r--r--drivers/hwmon/lis3lv02d_spi.c3
5 files changed, 52 insertions, 21 deletions
diff --git a/drivers/hwmon/hp_accel.c b/drivers/hwmon/hp_accel.c
index c5cd3db78c94..a56a78412fcb 100644
--- a/drivers/hwmon/hp_accel.c
+++ b/drivers/hwmon/hp_accel.c
@@ -146,7 +146,7 @@ int lis3lv02d_acpi_write(struct lis3lv02d *lis3, int reg, u8 val)
146 146
147static int lis3lv02d_dmi_matched(const struct dmi_system_id *dmi) 147static int lis3lv02d_dmi_matched(const struct dmi_system_id *dmi)
148{ 148{
149 lis3_dev.ac = *((struct axis_conversion *)dmi->driver_data); 149 lis3_dev.ac = *((union axis_conversion *)dmi->driver_data);
150 printk(KERN_INFO DRIVER_NAME ": hardware type %s found.\n", dmi->ident); 150 printk(KERN_INFO DRIVER_NAME ": hardware type %s found.\n", dmi->ident);
151 151
152 return 1; 152 return 1;
@@ -154,16 +154,19 @@ static int lis3lv02d_dmi_matched(const struct dmi_system_id *dmi)
154 154
155/* Represents, for each axis seen by userspace, the corresponding hw axis (+1). 155/* Represents, for each axis seen by userspace, the corresponding hw axis (+1).
156 * If the value is negative, the opposite of the hw value is used. */ 156 * If the value is negative, the opposite of the hw value is used. */
157static struct axis_conversion lis3lv02d_axis_normal = {1, 2, 3}; 157#define DEFINE_CONV(name, x, y, z) \
158static struct axis_conversion lis3lv02d_axis_y_inverted = {1, -2, 3}; 158 static union axis_conversion lis3lv02d_axis_##name = \
159static struct axis_conversion lis3lv02d_axis_x_inverted = {-1, 2, 3}; 159 { .as_array = { x, y, z } }
160static struct axis_conversion lis3lv02d_axis_z_inverted = {1, 2, -3}; 160DEFINE_CONV(normal, 1, 2, 3);
161static struct axis_conversion lis3lv02d_axis_xy_swap = {2, 1, 3}; 161DEFINE_CONV(y_inverted, 1, -2, 3);
162static struct axis_conversion lis3lv02d_axis_xy_rotated_left = {-2, 1, 3}; 162DEFINE_CONV(x_inverted, -1, 2, 3);
163static struct axis_conversion lis3lv02d_axis_xy_rotated_left_usd = {-2, 1, -3}; 163DEFINE_CONV(z_inverted, 1, 2, -3);
164static struct axis_conversion lis3lv02d_axis_xy_swap_inverted = {-2, -1, 3}; 164DEFINE_CONV(xy_swap, 2, 1, 3);
165static struct axis_conversion lis3lv02d_axis_xy_rotated_right = {2, -1, 3}; 165DEFINE_CONV(xy_rotated_left, -2, 1, 3);
166static struct axis_conversion lis3lv02d_axis_xy_swap_yz_inverted = {2, -1, -3}; 166DEFINE_CONV(xy_rotated_left_usd, -2, 1, -3);
167DEFINE_CONV(xy_swap_inverted, -2, -1, 3);
168DEFINE_CONV(xy_rotated_right, 2, -1, 3);
169DEFINE_CONV(xy_swap_yz_inverted, 2, -1, -3);
167 170
168#define AXIS_DMI_MATCH(_ident, _name, _axis) { \ 171#define AXIS_DMI_MATCH(_ident, _name, _axis) { \
169 .ident = _ident, \ 172 .ident = _ident, \
@@ -299,7 +302,10 @@ static int lis3lv02d_add(struct acpi_device *device)
299 lis3lv02d_enum_resources(device); 302 lis3lv02d_enum_resources(device);
300 303
301 /* If possible use a "standard" axes order */ 304 /* If possible use a "standard" axes order */
302 if (dmi_check_system(lis3lv02d_dmi_ids) == 0) { 305 if (lis3_dev.ac.x && lis3_dev.ac.y && lis3_dev.ac.z) {
306 printk(KERN_INFO DRIVER_NAME ": Using custom axes %d,%d,%d\n",
307 lis3_dev.ac.x, lis3_dev.ac.y, lis3_dev.ac.z);
308 } else if (dmi_check_system(lis3lv02d_dmi_ids) == 0) {
303 printk(KERN_INFO DRIVER_NAME ": laptop model unknown, " 309 printk(KERN_INFO DRIVER_NAME ": laptop model unknown, "
304 "using default axes configuration\n"); 310 "using default axes configuration\n");
305 lis3_dev.ac = lis3lv02d_axis_normal; 311 lis3_dev.ac = lis3lv02d_axis_normal;
diff --git a/drivers/hwmon/lis3lv02d.c b/drivers/hwmon/lis3lv02d.c
index ef7510d83603..25f385010953 100644
--- a/drivers/hwmon/lis3lv02d.c
+++ b/drivers/hwmon/lis3lv02d.c
@@ -75,6 +75,30 @@ struct lis3lv02d lis3_dev = {
75 75
76EXPORT_SYMBOL_GPL(lis3_dev); 76EXPORT_SYMBOL_GPL(lis3_dev);
77 77
78/* just like param_set_int() but does sanity-check so that it won't point
79 * over the axis array size
80 */
81static int param_set_axis(const char *val, const struct kernel_param *kp)
82{
83 int ret = param_set_int(val, kp);
84 if (!ret) {
85 int val = *(int *)kp->arg;
86 if (val < 0)
87 val = -val;
88 if (!val || val > 3)
89 return -EINVAL;
90 }
91 return ret;
92}
93
94static struct kernel_param_ops param_ops_axis = {
95 .set = param_set_axis,
96 .get = param_get_int,
97};
98
99module_param_array_named(axes, lis3_dev.ac.as_array, axis, NULL, 0644);
100MODULE_PARM_DESC(axes, "Axis-mapping for x,y,z directions");
101
78static s16 lis3lv02d_read_8(struct lis3lv02d *lis3, int reg) 102static s16 lis3lv02d_read_8(struct lis3lv02d *lis3, int reg)
79{ 103{
80 s8 lo; 104 s8 lo;
diff --git a/drivers/hwmon/lis3lv02d.h b/drivers/hwmon/lis3lv02d.h
index 62c6652eb9d5..eb5db584eb0e 100644
--- a/drivers/hwmon/lis3lv02d.h
+++ b/drivers/hwmon/lis3lv02d.h
@@ -223,10 +223,11 @@ enum lis3lv02d_click_src_8b {
223 CLICK_IA = 0x40, 223 CLICK_IA = 0x40,
224}; 224};
225 225
226struct axis_conversion { 226union axis_conversion {
227 s8 x; 227 struct {
228 s8 y; 228 int x, y, z;
229 s8 z; 229 };
230 int as_array[3];
230}; 231};
231 232
232struct lis3lv02d { 233struct lis3lv02d {
@@ -249,7 +250,7 @@ struct lis3lv02d {
249 struct input_polled_dev *idev; /* input device */ 250 struct input_polled_dev *idev; /* input device */
250 struct platform_device *pdev; /* platform device */ 251 struct platform_device *pdev; /* platform device */
251 atomic_t count; /* interrupt count after last read */ 252 atomic_t count; /* interrupt count after last read */
252 struct axis_conversion ac; /* hw -> logical axis */ 253 union axis_conversion ac; /* hw -> logical axis */
253 int mapped_btns[3]; 254 int mapped_btns[3];
254 255
255 u32 irq; /* IRQ number */ 256 u32 irq; /* IRQ number */
diff --git a/drivers/hwmon/lis3lv02d_i2c.c b/drivers/hwmon/lis3lv02d_i2c.c
index 8e5933b72d19..c6f3f3411276 100644
--- a/drivers/hwmon/lis3lv02d_i2c.c
+++ b/drivers/hwmon/lis3lv02d_i2c.c
@@ -61,9 +61,8 @@ static int lis3_i2c_init(struct lis3lv02d *lis3)
61} 61}
62 62
63/* Default axis mapping but it can be overwritten by platform data */ 63/* Default axis mapping but it can be overwritten by platform data */
64static struct axis_conversion lis3lv02d_axis_map = { LIS3_DEV_X, 64static union axis_conversion lis3lv02d_axis_map =
65 LIS3_DEV_Y, 65 { .as_array = { LIS3_DEV_X, LIS3_DEV_Y, LIS3_DEV_Z } };
66 LIS3_DEV_Z };
67 66
68static int __devinit lis3lv02d_i2c_probe(struct i2c_client *client, 67static int __devinit lis3lv02d_i2c_probe(struct i2c_client *client,
69 const struct i2c_device_id *id) 68 const struct i2c_device_id *id)
diff --git a/drivers/hwmon/lis3lv02d_spi.c b/drivers/hwmon/lis3lv02d_spi.c
index b9be5e3a22b3..955544b1c71e 100644
--- a/drivers/hwmon/lis3lv02d_spi.c
+++ b/drivers/hwmon/lis3lv02d_spi.c
@@ -54,7 +54,8 @@ static int lis3_spi_init(struct lis3lv02d *lis3)
54 return lis3->write(lis3, CTRL_REG1, reg); 54 return lis3->write(lis3, CTRL_REG1, reg);
55} 55}
56 56
57static struct axis_conversion lis3lv02d_axis_normal = { 1, 2, 3 }; 57static union axis_conversion lis3lv02d_axis_normal =
58 { .as_array = { 1, 2, 3 } };
58 59
59static int __devinit lis302dl_spi_probe(struct spi_device *spi) 60static int __devinit lis302dl_spi_probe(struct spi_device *spi)
60{ 61{