Commit 152fcb27 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input

Pull input updates from Dmitry Torokhov:
 "Except for the largish change to the ALPS driver adding "Dolphin V1"
  support and Wacom getting a new signature of yet another device, the
  rest are straightforward driver fixes."

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input:
  Input: mms114 - Fix regulator enable and disable paths
  Input: ads7864 - check return value of regulator enable
  Input: tc3589x-keypad - fix keymap size
  Input: wacom - add support for 0x10d
  Input: ALPS - update documentation for recent touchpad driver mods
  Input: ALPS - add "Dolphin V1" touchpad support
  Input: ALPS - remove unused argument to alps_enter_command_mode()
  Input: cypress_ps2 - fix trackpadi found in Dell XPS12
parents f6161aa1 4b7d293c
...@@ -3,10 +3,26 @@ ALPS Touchpad Protocol ...@@ -3,10 +3,26 @@ ALPS Touchpad Protocol
Introduction Introduction
------------ ------------
Currently the ALPS touchpad driver supports five protocol versions in use by
Currently the ALPS touchpad driver supports four protocol versions in use by ALPS touchpads, called versions 1, 2, 3, 4 and 5.
ALPS touchpads, called versions 1, 2, 3, and 4. Information about the various
protocol versions is contained in the following sections. Since roughly mid-2010 several new ALPS touchpads have been released and
integrated into a variety of laptops and netbooks. These new touchpads
have enough behavior differences that the alps_model_data definition
table, describing the properties of the different versions, is no longer
adequate. The design choices were to re-define the alps_model_data
table, with the risk of regression testing existing devices, or isolate
the new devices outside of the alps_model_data table. The latter design
choice was made. The new touchpad signatures are named: "Rushmore",
"Pinnacle", and "Dolphin", which you will see in the alps.c code.
For the purposes of this document, this group of ALPS touchpads will
generically be called "new ALPS touchpads".
We experimented with probing the ACPI interface _HID (Hardware ID)/_CID
(Compatibility ID) definition as a way to uniquely identify the
different ALPS variants but there did not appear to be a 1:1 mapping.
In fact, it appeared to be an m:n mapping between the _HID and actual
hardware type.
Detection Detection
--------- ---------
...@@ -20,9 +36,13 @@ If the E6 report is successful, the touchpad model is identified using the "E7 ...@@ -20,9 +36,13 @@ If the E6 report is successful, the touchpad model is identified using the "E7
report" sequence: E8-E7-E7-E7-E9. The response is the model signature and is report" sequence: E8-E7-E7-E7-E9. The response is the model signature and is
matched against known models in the alps_model_data_array. matched against known models in the alps_model_data_array.
With protocol versions 3 and 4, the E7 report model signature is always For older touchpads supporting protocol versions 3 and 4, the E7 report
73-02-64. To differentiate between these versions, the response from the model signature is always 73-02-64. To differentiate between these
"Enter Command Mode" sequence must be inspected as described below. versions, the response from the "Enter Command Mode" sequence must be
inspected as described below.
The new ALPS touchpads have an E7 signature of 73-03-50 or 73-03-0A but
seem to be better differentiated by the EC Command Mode response.
Command Mode Command Mode
------------ ------------
...@@ -47,6 +67,14 @@ address of the register being read, and the third contains the value of the ...@@ -47,6 +67,14 @@ address of the register being read, and the third contains the value of the
register. Registers are written by writing the value one nibble at a time register. Registers are written by writing the value one nibble at a time
using the same encoding used for addresses. using the same encoding used for addresses.
For the new ALPS touchpads, the EC command is used to enter command
mode. The response in the new ALPS touchpads is significantly different,
and more important in determining the behavior. This code has been
separated from the original alps_model_data table and put in the
alps_identify function. For example, there seem to be two hardware init
sequences for the "Dolphin" touchpads as determined by the second byte
of the EC response.
Packet Format Packet Format
------------- -------------
...@@ -187,3 +215,28 @@ There are several things worth noting here. ...@@ -187,3 +215,28 @@ There are several things worth noting here.
well. well.
So far no v4 devices with tracksticks have been encountered. So far no v4 devices with tracksticks have been encountered.
ALPS Absolute Mode - Protocol Version 5
---------------------------------------
This is basically Protocol Version 3 but with different logic for packet
decode. It uses the same alps_process_touchpad_packet_v3 call with a
specialized decode_fields function pointer to correctly interpret the
packets. This appears to only be used by the Dolphin devices.
For single-touch, the 6-byte packet format is:
byte 0: 1 1 0 0 1 0 0 0
byte 1: 0 x6 x5 x4 x3 x2 x1 x0
byte 2: 0 y6 y5 y4 y3 y2 y1 y0
byte 3: 0 M R L 1 m r l
byte 4: y10 y9 y8 y7 x10 x9 x8 x7
byte 5: 0 z6 z5 z4 z3 z2 z1 z0
For mt, the format is:
byte 0: 1 1 1 n3 1 n2 n1 x24
byte 1: 1 y7 y6 y5 y4 y3 y2 y1
byte 2: ? x2 x1 y12 y11 y10 y9 y8
byte 3: 0 x23 x22 x21 x20 x19 x18 x17
byte 4: 0 x9 x8 x7 x6 x5 x4 x3
byte 5: 0 x16 x15 x14 x13 x12 x11 x10
...@@ -70,8 +70,6 @@ ...@@ -70,8 +70,6 @@
#define TC3589x_EVT_INT_CLR 0x2 #define TC3589x_EVT_INT_CLR 0x2
#define TC3589x_KBD_INT_CLR 0x1 #define TC3589x_KBD_INT_CLR 0x1
#define TC3589x_KBD_KEYMAP_SIZE 64
/** /**
* struct tc_keypad - data structure used by keypad driver * struct tc_keypad - data structure used by keypad driver
* @tc3589x: pointer to tc35893 * @tc3589x: pointer to tc35893
...@@ -88,7 +86,7 @@ struct tc_keypad { ...@@ -88,7 +86,7 @@ struct tc_keypad {
const struct tc3589x_keypad_platform_data *board; const struct tc3589x_keypad_platform_data *board;
unsigned int krow; unsigned int krow;
unsigned int kcol; unsigned int kcol;
unsigned short keymap[TC3589x_KBD_KEYMAP_SIZE]; unsigned short *keymap;
bool keypad_stopped; bool keypad_stopped;
}; };
...@@ -338,12 +336,14 @@ static int tc3589x_keypad_probe(struct platform_device *pdev) ...@@ -338,12 +336,14 @@ static int tc3589x_keypad_probe(struct platform_device *pdev)
error = matrix_keypad_build_keymap(plat->keymap_data, NULL, error = matrix_keypad_build_keymap(plat->keymap_data, NULL,
TC3589x_MAX_KPROW, TC3589x_MAX_KPCOL, TC3589x_MAX_KPROW, TC3589x_MAX_KPCOL,
keypad->keymap, input); NULL, input);
if (error) { if (error) {
dev_err(&pdev->dev, "Failed to build keymap\n"); dev_err(&pdev->dev, "Failed to build keymap\n");
goto err_free_mem; goto err_free_mem;
} }
keypad->keymap = input->keycode;
input_set_capability(input, EV_MSC, MSC_SCAN); input_set_capability(input, EV_MSC, MSC_SCAN);
if (!plat->no_autorepeat) if (!plat->no_autorepeat)
__set_bit(EV_REP, input->evbit); __set_bit(EV_REP, input->evbit);
......
...@@ -490,6 +490,29 @@ static void alps_decode_rushmore(struct alps_fields *f, unsigned char *p) ...@@ -490,6 +490,29 @@ static void alps_decode_rushmore(struct alps_fields *f, unsigned char *p)
f->y_map |= (p[5] & 0x20) << 6; f->y_map |= (p[5] & 0x20) << 6;
} }
static void alps_decode_dolphin(struct alps_fields *f, unsigned char *p)
{
f->first_mp = !!(p[0] & 0x02);
f->is_mp = !!(p[0] & 0x20);
f->fingers = ((p[0] & 0x6) >> 1 |
(p[0] & 0x10) >> 2);
f->x_map = ((p[2] & 0x60) >> 5) |
((p[4] & 0x7f) << 2) |
((p[5] & 0x7f) << 9) |
((p[3] & 0x07) << 16) |
((p[3] & 0x70) << 15) |
((p[0] & 0x01) << 22);
f->y_map = (p[1] & 0x7f) |
((p[2] & 0x1f) << 7);
f->x = ((p[1] & 0x7f) | ((p[4] & 0x0f) << 7));
f->y = ((p[2] & 0x7f) | ((p[4] & 0xf0) << 3));
f->z = (p[0] & 4) ? 0 : p[5] & 0x7f;
alps_decode_buttons_v3(f, p);
}
static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) static void alps_process_touchpad_packet_v3(struct psmouse *psmouse)
{ {
struct alps_data *priv = psmouse->private; struct alps_data *priv = psmouse->private;
...@@ -874,7 +897,8 @@ static psmouse_ret_t alps_process_byte(struct psmouse *psmouse) ...@@ -874,7 +897,8 @@ static psmouse_ret_t alps_process_byte(struct psmouse *psmouse)
} }
/* Bytes 2 - pktsize should have 0 in the highest bit */ /* Bytes 2 - pktsize should have 0 in the highest bit */
if (psmouse->pktcnt >= 2 && psmouse->pktcnt <= psmouse->pktsize && if (priv->proto_version != ALPS_PROTO_V5 &&
psmouse->pktcnt >= 2 && psmouse->pktcnt <= psmouse->pktsize &&
(psmouse->packet[psmouse->pktcnt - 1] & 0x80)) { (psmouse->packet[psmouse->pktcnt - 1] & 0x80)) {
psmouse_dbg(psmouse, "refusing packet[%i] = %x\n", psmouse_dbg(psmouse, "refusing packet[%i] = %x\n",
psmouse->pktcnt - 1, psmouse->pktcnt - 1,
...@@ -994,8 +1018,7 @@ static int alps_rpt_cmd(struct psmouse *psmouse, int init_command, ...@@ -994,8 +1018,7 @@ static int alps_rpt_cmd(struct psmouse *psmouse, int init_command,
return 0; return 0;
} }
static int alps_enter_command_mode(struct psmouse *psmouse, static int alps_enter_command_mode(struct psmouse *psmouse)
unsigned char *resp)
{ {
unsigned char param[4]; unsigned char param[4];
...@@ -1004,14 +1027,12 @@ static int alps_enter_command_mode(struct psmouse *psmouse, ...@@ -1004,14 +1027,12 @@ static int alps_enter_command_mode(struct psmouse *psmouse,
return -1; return -1;
} }
if (param[0] != 0x88 || (param[1] != 0x07 && param[1] != 0x08)) { if ((param[0] != 0x88 || (param[1] != 0x07 && param[1] != 0x08)) &&
param[0] != 0x73) {
psmouse_dbg(psmouse, psmouse_dbg(psmouse,
"unknown response while entering command mode\n"); "unknown response while entering command mode\n");
return -1; return -1;
} }
if (resp)
*resp = param[2];
return 0; return 0;
} }
...@@ -1176,7 +1197,7 @@ static int alps_passthrough_mode_v3(struct psmouse *psmouse, ...@@ -1176,7 +1197,7 @@ static int alps_passthrough_mode_v3(struct psmouse *psmouse,
{ {
int reg_val, ret = -1; int reg_val, ret = -1;
if (alps_enter_command_mode(psmouse, NULL)) if (alps_enter_command_mode(psmouse))
return -1; return -1;
reg_val = alps_command_mode_read_reg(psmouse, reg_base + 0x0008); reg_val = alps_command_mode_read_reg(psmouse, reg_base + 0x0008);
...@@ -1216,7 +1237,7 @@ static int alps_probe_trackstick_v3(struct psmouse *psmouse, int reg_base) ...@@ -1216,7 +1237,7 @@ static int alps_probe_trackstick_v3(struct psmouse *psmouse, int reg_base)
{ {
int ret = -EIO, reg_val; int ret = -EIO, reg_val;
if (alps_enter_command_mode(psmouse, NULL)) if (alps_enter_command_mode(psmouse))
goto error; goto error;
reg_val = alps_command_mode_read_reg(psmouse, reg_base + 0x08); reg_val = alps_command_mode_read_reg(psmouse, reg_base + 0x08);
...@@ -1279,7 +1300,7 @@ static int alps_setup_trackstick_v3(struct psmouse *psmouse, int reg_base) ...@@ -1279,7 +1300,7 @@ static int alps_setup_trackstick_v3(struct psmouse *psmouse, int reg_base)
* supported by this driver. If bit 1 isn't set the packet * supported by this driver. If bit 1 isn't set the packet
* format is different. * format is different.
*/ */
if (alps_enter_command_mode(psmouse, NULL) || if (alps_enter_command_mode(psmouse) ||
alps_command_mode_write_reg(psmouse, alps_command_mode_write_reg(psmouse,
reg_base + 0x08, 0x82) || reg_base + 0x08, 0x82) ||
alps_exit_command_mode(psmouse)) alps_exit_command_mode(psmouse))
...@@ -1306,7 +1327,7 @@ static int alps_hw_init_v3(struct psmouse *psmouse) ...@@ -1306,7 +1327,7 @@ static int alps_hw_init_v3(struct psmouse *psmouse)
alps_setup_trackstick_v3(psmouse, ALPS_REG_BASE_PINNACLE) == -EIO) alps_setup_trackstick_v3(psmouse, ALPS_REG_BASE_PINNACLE) == -EIO)
goto error; goto error;
if (alps_enter_command_mode(psmouse, NULL) || if (alps_enter_command_mode(psmouse) ||
alps_absolute_mode_v3(psmouse)) { alps_absolute_mode_v3(psmouse)) {
psmouse_err(psmouse, "Failed to enter absolute mode\n"); psmouse_err(psmouse, "Failed to enter absolute mode\n");
goto error; goto error;
...@@ -1381,7 +1402,7 @@ static int alps_hw_init_rushmore_v3(struct psmouse *psmouse) ...@@ -1381,7 +1402,7 @@ static int alps_hw_init_rushmore_v3(struct psmouse *psmouse)
priv->flags &= ~ALPS_DUALPOINT; priv->flags &= ~ALPS_DUALPOINT;
} }
if (alps_enter_command_mode(psmouse, NULL) || if (alps_enter_command_mode(psmouse) ||
alps_command_mode_read_reg(psmouse, 0xc2d9) == -1 || alps_command_mode_read_reg(psmouse, 0xc2d9) == -1 ||
alps_command_mode_write_reg(psmouse, 0xc2cb, 0x00)) alps_command_mode_write_reg(psmouse, 0xc2cb, 0x00))
goto error; goto error;
...@@ -1431,7 +1452,7 @@ static int alps_hw_init_v4(struct psmouse *psmouse) ...@@ -1431,7 +1452,7 @@ static int alps_hw_init_v4(struct psmouse *psmouse)
struct ps2dev *ps2dev = &psmouse->ps2dev; struct ps2dev *ps2dev = &psmouse->ps2dev;
unsigned char param[4]; unsigned char param[4];
if (alps_enter_command_mode(psmouse, NULL)) if (alps_enter_command_mode(psmouse))
goto error; goto error;
if (alps_absolute_mode_v4(psmouse)) { if (alps_absolute_mode_v4(psmouse)) {
...@@ -1499,6 +1520,23 @@ static int alps_hw_init_v4(struct psmouse *psmouse) ...@@ -1499,6 +1520,23 @@ static int alps_hw_init_v4(struct psmouse *psmouse)
return -1; return -1;
} }
static int alps_hw_init_dolphin_v1(struct psmouse *psmouse)
{
struct ps2dev *ps2dev = &psmouse->ps2dev;
unsigned char param[2];
/* This is dolphin "v1" as empirically defined by florin9doi */
param[0] = 0x64;
param[1] = 0x28;
if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSTREAM) ||
ps2_command(ps2dev, &param[0], PSMOUSE_CMD_SETRATE) ||
ps2_command(ps2dev, &param[1], PSMOUSE_CMD_SETRATE))
return -1;
return 0;
}
static void alps_set_defaults(struct alps_data *priv) static void alps_set_defaults(struct alps_data *priv)
{ {
priv->byte0 = 0x8f; priv->byte0 = 0x8f;
...@@ -1532,6 +1570,21 @@ static void alps_set_defaults(struct alps_data *priv) ...@@ -1532,6 +1570,21 @@ static void alps_set_defaults(struct alps_data *priv)
priv->nibble_commands = alps_v4_nibble_commands; priv->nibble_commands = alps_v4_nibble_commands;
priv->addr_command = PSMOUSE_CMD_DISABLE; priv->addr_command = PSMOUSE_CMD_DISABLE;
break; break;
case ALPS_PROTO_V5:
priv->hw_init = alps_hw_init_dolphin_v1;
priv->process_packet = alps_process_packet_v3;
priv->decode_fields = alps_decode_dolphin;
priv->set_abs_params = alps_set_abs_params_mt;
priv->nibble_commands = alps_v3_nibble_commands;
priv->addr_command = PSMOUSE_CMD_RESET_WRAP;
priv->byte0 = 0xc8;
priv->mask0 = 0xc8;
priv->flags = 0;
priv->x_max = 1360;
priv->y_max = 660;
priv->x_bits = 23;
priv->y_bits = 12;
break;
} }
} }
...@@ -1591,6 +1644,12 @@ static int alps_identify(struct psmouse *psmouse, struct alps_data *priv) ...@@ -1591,6 +1644,12 @@ static int alps_identify(struct psmouse *psmouse, struct alps_data *priv)
return -EIO; return -EIO;
if (alps_match_table(psmouse, priv, e7, ec) == 0) { if (alps_match_table(psmouse, priv, e7, ec) == 0) {
return 0;
} else if (e7[0] == 0x73 && e7[1] == 0x03 && e7[2] == 0x50 &&
ec[0] == 0x73 && ec[1] == 0x01) {
priv->proto_version = ALPS_PROTO_V5;
alps_set_defaults(priv);
return 0; return 0;
} else if (ec[0] == 0x88 && ec[1] == 0x08) { } else if (ec[0] == 0x88 && ec[1] == 0x08) {
priv->proto_version = ALPS_PROTO_V3; priv->proto_version = ALPS_PROTO_V3;
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#define ALPS_PROTO_V2 2 #define ALPS_PROTO_V2 2
#define ALPS_PROTO_V3 3 #define ALPS_PROTO_V3 3
#define ALPS_PROTO_V4 4 #define ALPS_PROTO_V4 4
#define ALPS_PROTO_V5 5
/** /**
* struct alps_model_info - touchpad ID table * struct alps_model_info - touchpad ID table
......
...@@ -236,6 +236,13 @@ static int cypress_read_fw_version(struct psmouse *psmouse) ...@@ -236,6 +236,13 @@ static int cypress_read_fw_version(struct psmouse *psmouse)
cytp->fw_version = param[2] & FW_VERSION_MASX; cytp->fw_version = param[2] & FW_VERSION_MASX;
cytp->tp_metrics_supported = (param[2] & TP_METRICS_MASK) ? 1 : 0; cytp->tp_metrics_supported = (param[2] & TP_METRICS_MASK) ? 1 : 0;
/*
* Trackpad fw_version 11 (in Dell XPS12) yields a bogus response to
* CYTP_CMD_READ_TP_METRICS so do not try to use it. LP: #1103594.
*/
if (cytp->fw_version >= 11)
cytp->tp_metrics_supported = 0;
psmouse_dbg(psmouse, "cytp->fw_version = %d\n", cytp->fw_version); psmouse_dbg(psmouse, "cytp->fw_version = %d\n", cytp->fw_version);
psmouse_dbg(psmouse, "cytp->tp_metrics_supported = %d\n", psmouse_dbg(psmouse, "cytp->tp_metrics_supported = %d\n",
cytp->tp_metrics_supported); cytp->tp_metrics_supported);
...@@ -258,6 +265,9 @@ static int cypress_read_tp_metrics(struct psmouse *psmouse) ...@@ -258,6 +265,9 @@ static int cypress_read_tp_metrics(struct psmouse *psmouse)
cytp->tp_res_x = cytp->tp_max_abs_x / cytp->tp_width; cytp->tp_res_x = cytp->tp_max_abs_x / cytp->tp_width;
cytp->tp_res_y = cytp->tp_max_abs_y / cytp->tp_high; cytp->tp_res_y = cytp->tp_max_abs_y / cytp->tp_high;
if (!cytp->tp_metrics_supported)
return 0;
memset(param, 0, sizeof(param)); memset(param, 0, sizeof(param));
if (cypress_send_ext_cmd(psmouse, CYTP_CMD_READ_TP_METRICS, param) == 0) { if (cypress_send_ext_cmd(psmouse, CYTP_CMD_READ_TP_METRICS, param) == 0) {
/* Update trackpad parameters. */ /* Update trackpad parameters. */
...@@ -315,18 +325,15 @@ static int cypress_read_tp_metrics(struct psmouse *psmouse) ...@@ -315,18 +325,15 @@ static int cypress_read_tp_metrics(struct psmouse *psmouse)
static int cypress_query_hardware(struct psmouse *psmouse) static int cypress_query_hardware(struct psmouse *psmouse)
{ {
struct cytp_data *cytp = psmouse->private;
int ret; int ret;
ret = cypress_read_fw_version(psmouse); ret = cypress_read_fw_version(psmouse);
if (ret) if (ret)
return ret; return ret;
if (cytp->tp_metrics_supported) { ret = cypress_read_tp_metrics(psmouse);
ret = cypress_read_tp_metrics(psmouse); if (ret)
if (ret) return ret;
return ret;
}
return 0; return 0;
} }
......
...@@ -2017,6 +2017,9 @@ static const struct wacom_features wacom_features_0x100 = ...@@ -2017,6 +2017,9 @@ static const struct wacom_features wacom_features_0x100 =
static const struct wacom_features wacom_features_0x101 = static const struct wacom_features wacom_features_0x101 =
{ "Wacom ISDv4 101", WACOM_PKGLEN_MTTPC, 26202, 16325, 255, { "Wacom ISDv4 101", WACOM_PKGLEN_MTTPC, 26202, 16325, 255,
0, MTTPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; 0, MTTPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
static const struct wacom_features wacom_features_0x10D =
{ "Wacom ISDv4 10D", WACOM_PKGLEN_MTTPC, 26202, 16325, 255,
0, MTTPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
static const struct wacom_features wacom_features_0x4001 = static const struct wacom_features wacom_features_0x4001 =
{ "Wacom ISDv4 4001", WACOM_PKGLEN_MTTPC, 26202, 16325, 255, { "Wacom ISDv4 4001", WACOM_PKGLEN_MTTPC, 26202, 16325, 255,
0, MTTPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; 0, MTTPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
...@@ -2201,6 +2204,7 @@ const struct usb_device_id wacom_ids[] = { ...@@ -2201,6 +2204,7 @@ const struct usb_device_id wacom_ids[] = {
{ USB_DEVICE_WACOM(0xEF) }, { USB_DEVICE_WACOM(0xEF) },
{ USB_DEVICE_WACOM(0x100) }, { USB_DEVICE_WACOM(0x100) },
{ USB_DEVICE_WACOM(0x101) }, { USB_DEVICE_WACOM(0x101) },
{ USB_DEVICE_WACOM(0x10D) },
{ USB_DEVICE_WACOM(0x4001) }, { USB_DEVICE_WACOM(0x4001) },
{ USB_DEVICE_WACOM(0x47) }, { USB_DEVICE_WACOM(0x47) },
{ USB_DEVICE_WACOM(0xF4) }, { USB_DEVICE_WACOM(0xF4) },
......
...@@ -236,7 +236,12 @@ static void __ads7846_disable(struct ads7846 *ts) ...@@ -236,7 +236,12 @@ static void __ads7846_disable(struct ads7846 *ts)
/* Must be called with ts->lock held */ /* Must be called with ts->lock held */
static void __ads7846_enable(struct ads7846 *ts) static void __ads7846_enable(struct ads7846 *ts)
{ {
regulator_enable(ts->reg); int error;
error = regulator_enable(ts->reg);
if (error != 0)
dev_err(&ts->spi->dev, "Failed to enable supply: %d\n", error);
ads7846_restart(ts); ads7846_restart(ts);
} }
......
...@@ -314,15 +314,27 @@ static int mms114_start(struct mms114_data *data) ...@@ -314,15 +314,27 @@ static int mms114_start(struct mms114_data *data)
struct i2c_client *client = data->client; struct i2c_client *client = data->client;
int error; int error;
if (data->core_reg) error = regulator_enable(data->core_reg);
regulator_enable(data->core_reg); if (error) {
if (data->io_reg) dev_err(&client->dev, "Failed to enable avdd: %d\n", error);
regulator_enable(data->io_reg); return error;
}
error = regulator_enable(data->io_reg);
if (error) {
dev_err(&client->dev, "Failed to enable vdd: %d\n", error);
regulator_disable(data->core_reg);
return error;
}
mdelay(MMS114_POWERON_DELAY); mdelay(MMS114_POWERON_DELAY);
error = mms114_setup_regs(data); error = mms114_setup_regs(data);
if (error < 0) if (error < 0) {
regulator_disable(data->io_reg);
regulator_disable(data->core_reg);
return error; return error;
}
if (data->pdata->cfg_pin) if (data->pdata->cfg_pin)
data->pdata->cfg_pin(true); data->pdata->cfg_pin(true);
...@@ -335,16 +347,20 @@ static int mms114_start(struct mms114_data *data) ...@@ -335,16 +347,20 @@ static int mms114_start(struct mms114_data *data)
static void mms114_stop(struct mms114_data *data) static void mms114_stop(struct mms114_data *data)
{ {
struct i2c_client *client = data->client; struct i2c_client *client = data->client;
int error;
disable_irq(client->irq); disable_irq(client->irq);
if (data->pdata->cfg_pin) if (data->pdata->cfg_pin)
data->pdata->cfg_pin(false); data->pdata->cfg_pin(false);
if (data->io_reg) error = regulator_disable(data->io_reg);
regulator_disable(data->io_reg); if (error)
if (data->core_reg) dev_warn(&client->dev, "Failed to disable vdd: %d\n", error);
regulator_disable(data->core_reg);
error = regulator_disable(data->core_reg);
if (error)
dev_warn(&client->dev, "Failed to disable avdd: %d\n", error);
} }
static int mms114_input_open(struct input_dev *dev) static int mms114_input_open(struct input_dev *dev)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment