Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
Pull second round of input updates from Dmitry Torokhov: "An update to Elantech driver to support hardware v7, fix to the new cyttsp4 driver to use proper addressing, ads7846 device tree support and nspire-keypad got a small cleanup." * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input: Input: nspire-keypad - replace magic offset with define Input: elantech - fix for newer hardware versions (v7) Input: cyttsp4 - use 16bit address for I2C/SPI communication Input: ads7846 - add device tree bindings Input: ads7846 - make sure we do not change platform data
This commit is contained in:
Коммит
18fb38e2f5
|
@ -0,0 +1,91 @@
|
|||
Device tree bindings for TI's ADS7843, ADS7845, ADS7846, ADS7873, TSC2046
|
||||
SPI driven touch screen controllers.
|
||||
|
||||
The node for this driver must be a child node of a SPI controller, hence
|
||||
all mandatory properties described in
|
||||
|
||||
Documentation/devicetree/bindings/spi/spi-bus.txt
|
||||
|
||||
must be specified.
|
||||
|
||||
Additional required properties:
|
||||
|
||||
compatible Must be one of the following, depending on the
|
||||
model:
|
||||
"ti,tsc2046"
|
||||
"ti,ads7843"
|
||||
"ti,ads7845"
|
||||
"ti,ads7846"
|
||||
"ti,ads7873"
|
||||
|
||||
interrupt-parent
|
||||
interrupts An interrupt node describing the IRQ line the chip's
|
||||
!PENIRQ pin is connected to.
|
||||
vcc-supply A regulator node for the supply voltage.
|
||||
|
||||
|
||||
Optional properties:
|
||||
|
||||
ti,vref-delay-usecs vref supply delay in usecs, 0 for
|
||||
external vref (u16).
|
||||
ti,vref-mv The VREF voltage, in millivolts (u16).
|
||||
ti,keep-vref-on set to keep vref on for differential
|
||||
measurements as well
|
||||
ti,swap-xy swap x and y axis
|
||||
ti,settle-delay-usec Settling time of the analog signals;
|
||||
a function of Vcc and the capacitance
|
||||
on the X/Y drivers. If set to non-zero,
|
||||
two samples are taken with settle_delay
|
||||
us apart, and the second one is used.
|
||||
~150 uSec with 0.01uF caps (u16).
|
||||
ti,penirq-recheck-delay-usecs If set to non-zero, after samples are
|
||||
taken this delay is applied and penirq
|
||||
is rechecked, to help avoid false
|
||||
events. This value is affected by the
|
||||
material used to build the touch layer
|
||||
(u16).
|
||||
ti,x-plate-ohms Resistance of the X-plate,
|
||||
in Ohms (u16).
|
||||
ti,y-plate-ohms Resistance of the Y-plate,
|
||||
in Ohms (u16).
|
||||
ti,x-min Minimum value on the X axis (u16).
|
||||
ti,y-min Minimum value on the Y axis (u16).
|
||||
ti,x-max Maximum value on the X axis (u16).
|
||||
ti,y-max Minimum value on the Y axis (u16).
|
||||
ti,pressure-min Minimum reported pressure value
|
||||
(threshold) - u16.
|
||||
ti,pressure-max Maximum reported pressure value (u16).
|
||||
ti,debounce-max Max number of additional readings per
|
||||
sample (u16).
|
||||
ti,debounce-tol Tolerance used for filtering (u16).
|
||||
ti,debounce-rep Additional consecutive good readings
|
||||
required after the first two (u16).
|
||||
ti,pendown-gpio-debounce Platform specific debounce time for the
|
||||
pendown-gpio (u32).
|
||||
pendown-gpio GPIO handle describing the pin the !PENIRQ
|
||||
line is connected to.
|
||||
linux,wakeup use any event on touchscreen as wakeup event.
|
||||
|
||||
|
||||
Example for a TSC2046 chip connected to an McSPI controller of an OMAP SoC::
|
||||
|
||||
spi_controller {
|
||||
tsc2046@0 {
|
||||
reg = <0>; /* CS0 */
|
||||
compatible = "ti,tsc2046";
|
||||
interrupt-parent = <&gpio1>;
|
||||
interrupts = <8 0>; /* BOOT6 / GPIO 8 */
|
||||
spi-max-frequency = <1000000>;
|
||||
pendown-gpio = <&gpio1 8 0>;
|
||||
vcc-supply = <®_vcc3>;
|
||||
|
||||
ti,x-min = /bits/ 16 <0>;
|
||||
ti,x-max = /bits/ 16 <8000>;
|
||||
ti,y-min = /bits/ 16 <0>;
|
||||
ti,y-max = /bits/ 16 <4800>;
|
||||
ti,x-plate-ohms = /bits/ 16 <40>;
|
||||
ti,pressure-max = /bits/ 16 <255>;
|
||||
|
||||
linux,wakeup;
|
||||
};
|
||||
};
|
|
@ -122,7 +122,7 @@ static int nspire_keypad_chip_init(struct nspire_keypad *keypad)
|
|||
|
||||
/* Enable interrupts */
|
||||
keypad->int_mask = 1 << 1;
|
||||
writel(keypad->int_mask, keypad->reg_base + 0xc);
|
||||
writel(keypad->int_mask, keypad->reg_base + KEYPAD_INTMSK);
|
||||
|
||||
/* Disable GPIO interrupts to prevent hanging on touchpad */
|
||||
/* Possibly used to detect touchpad events */
|
||||
|
|
|
@ -694,18 +694,18 @@ static int elantech_packet_check_v3(struct psmouse *psmouse)
|
|||
static int elantech_packet_check_v4(struct psmouse *psmouse)
|
||||
{
|
||||
unsigned char *packet = psmouse->packet;
|
||||
unsigned char packet_type = packet[3] & 0x03;
|
||||
|
||||
if ((packet[0] & 0x0c) == 0x04 &&
|
||||
(packet[3] & 0x1f) == 0x11)
|
||||
switch (packet_type) {
|
||||
case 0:
|
||||
return PACKET_V4_STATUS;
|
||||
|
||||
case 1:
|
||||
return PACKET_V4_HEAD;
|
||||
|
||||
if ((packet[0] & 0x0c) == 0x04 &&
|
||||
(packet[3] & 0x1f) == 0x12)
|
||||
case 2:
|
||||
return PACKET_V4_MOTION;
|
||||
|
||||
if ((packet[0] & 0x0c) == 0x04 &&
|
||||
(packet[3] & 0x1f) == 0x10)
|
||||
return PACKET_V4_STATUS;
|
||||
}
|
||||
|
||||
return PACKET_UNKNOWN;
|
||||
}
|
||||
|
@ -1282,6 +1282,7 @@ static int elantech_set_properties(struct elantech_data *etd)
|
|||
etd->hw_version = 3;
|
||||
break;
|
||||
case 6:
|
||||
case 7:
|
||||
etd->hw_version = 4;
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -27,6 +27,9 @@
|
|||
#include <linux/interrupt.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/pm.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/spi/ads7846.h>
|
||||
|
@ -961,9 +964,9 @@ static int ads7846_resume(struct device *dev)
|
|||
static SIMPLE_DEV_PM_OPS(ads7846_pm, ads7846_suspend, ads7846_resume);
|
||||
|
||||
static int ads7846_setup_pendown(struct spi_device *spi,
|
||||
struct ads7846 *ts)
|
||||
struct ads7846 *ts,
|
||||
const struct ads7846_platform_data *pdata)
|
||||
{
|
||||
struct ads7846_platform_data *pdata = spi->dev.platform_data;
|
||||
int err;
|
||||
|
||||
/*
|
||||
|
@ -1003,7 +1006,7 @@ static int ads7846_setup_pendown(struct spi_device *spi,
|
|||
* use formula #2 for pressure, not #3.
|
||||
*/
|
||||
static void ads7846_setup_spi_msg(struct ads7846 *ts,
|
||||
const struct ads7846_platform_data *pdata)
|
||||
const struct ads7846_platform_data *pdata)
|
||||
{
|
||||
struct spi_message *m = &ts->msg[0];
|
||||
struct spi_transfer *x = ts->xfer;
|
||||
|
@ -1201,33 +1204,107 @@ static void ads7846_setup_spi_msg(struct ads7846 *ts,
|
|||
spi_message_add_tail(x, m);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static const struct of_device_id ads7846_dt_ids[] = {
|
||||
{ .compatible = "ti,tsc2046", .data = (void *) 7846 },
|
||||
{ .compatible = "ti,ads7843", .data = (void *) 7843 },
|
||||
{ .compatible = "ti,ads7845", .data = (void *) 7845 },
|
||||
{ .compatible = "ti,ads7846", .data = (void *) 7846 },
|
||||
{ .compatible = "ti,ads7873", .data = (void *) 7873 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, ads7846_dt_ids);
|
||||
|
||||
static const struct ads7846_platform_data *ads7846_probe_dt(struct device *dev)
|
||||
{
|
||||
struct ads7846_platform_data *pdata;
|
||||
struct device_node *node = dev->of_node;
|
||||
const struct of_device_id *match;
|
||||
|
||||
if (!node) {
|
||||
dev_err(dev, "Device does not have associated DT data\n");
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
match = of_match_device(ads7846_dt_ids, dev);
|
||||
if (!match) {
|
||||
dev_err(dev, "Unknown device model\n");
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
|
||||
if (!pdata)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
pdata->model = (unsigned long)match->data;
|
||||
|
||||
of_property_read_u16(node, "ti,vref-delay-usecs",
|
||||
&pdata->vref_delay_usecs);
|
||||
of_property_read_u16(node, "ti,vref-mv", &pdata->vref_mv);
|
||||
pdata->keep_vref_on = of_property_read_bool(node, "ti,keep-vref-on");
|
||||
|
||||
pdata->swap_xy = of_property_read_bool(node, "ti,swap-xy");
|
||||
|
||||
of_property_read_u16(node, "ti,settle-delay-usec",
|
||||
&pdata->settle_delay_usecs);
|
||||
of_property_read_u16(node, "ti,penirq-recheck-delay-usecs",
|
||||
&pdata->penirq_recheck_delay_usecs);
|
||||
|
||||
of_property_read_u16(node, "ti,x-plate-ohms", &pdata->x_plate_ohms);
|
||||
of_property_read_u16(node, "ti,y-plate-ohms", &pdata->y_plate_ohms);
|
||||
|
||||
of_property_read_u16(node, "ti,x-min", &pdata->x_min);
|
||||
of_property_read_u16(node, "ti,y-min", &pdata->y_min);
|
||||
of_property_read_u16(node, "ti,x-max", &pdata->x_max);
|
||||
of_property_read_u16(node, "ti,y-max", &pdata->y_max);
|
||||
|
||||
of_property_read_u16(node, "ti,pressure-min", &pdata->pressure_min);
|
||||
of_property_read_u16(node, "ti,pressure-max", &pdata->pressure_max);
|
||||
|
||||
of_property_read_u16(node, "ti,debounce-max", &pdata->debounce_max);
|
||||
of_property_read_u16(node, "ti,debounce-tol", &pdata->debounce_tol);
|
||||
of_property_read_u16(node, "ti,debounce-rep", &pdata->debounce_rep);
|
||||
|
||||
of_property_read_u32(node, "ti,pendown-gpio-debounce",
|
||||
&pdata->gpio_pendown_debounce);
|
||||
|
||||
pdata->wakeup = of_property_read_bool(node, "linux,wakeup");
|
||||
|
||||
pdata->gpio_pendown = of_get_named_gpio(dev->of_node, "pendown-gpio", 0);
|
||||
|
||||
return pdata;
|
||||
}
|
||||
#else
|
||||
static const struct ads7846_platform_data *ads7846_probe_dt(struct device *dev)
|
||||
{
|
||||
dev_err(dev, "no platform data defined\n");
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int ads7846_probe(struct spi_device *spi)
|
||||
{
|
||||
const struct ads7846_platform_data *pdata;
|
||||
struct ads7846 *ts;
|
||||
struct ads7846_packet *packet;
|
||||
struct input_dev *input_dev;
|
||||
struct ads7846_platform_data *pdata = spi->dev.platform_data;
|
||||
unsigned long irq_flags;
|
||||
int err;
|
||||
|
||||
if (!spi->irq) {
|
||||
dev_dbg(&spi->dev, "no IRQ?\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (!pdata) {
|
||||
dev_dbg(&spi->dev, "no platform data?\n");
|
||||
return -ENODEV;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* don't exceed max specified sample rate */
|
||||
if (spi->max_speed_hz > (125000 * SAMPLE_BITS)) {
|
||||
dev_dbg(&spi->dev, "f(sample) %d KHz?\n",
|
||||
dev_err(&spi->dev, "f(sample) %d KHz?\n",
|
||||
(spi->max_speed_hz/SAMPLE_BITS)/1000);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* We'd set TX word size 8 bits and RX word size to 13 bits ... except
|
||||
/*
|
||||
* We'd set TX word size 8 bits and RX word size to 13 bits ... except
|
||||
* that even if the hardware can do that, the SPI controller driver
|
||||
* may not. So we stick to very-portable 8 bit words, both RX and TX.
|
||||
*/
|
||||
|
@ -1250,17 +1327,25 @@ static int ads7846_probe(struct spi_device *spi)
|
|||
ts->packet = packet;
|
||||
ts->spi = spi;
|
||||
ts->input = input_dev;
|
||||
ts->vref_mv = pdata->vref_mv;
|
||||
ts->swap_xy = pdata->swap_xy;
|
||||
|
||||
mutex_init(&ts->lock);
|
||||
init_waitqueue_head(&ts->wait);
|
||||
|
||||
pdata = dev_get_platdata(&spi->dev);
|
||||
if (!pdata) {
|
||||
pdata = ads7846_probe_dt(&spi->dev);
|
||||
if (IS_ERR(pdata))
|
||||
return PTR_ERR(pdata);
|
||||
}
|
||||
|
||||
ts->model = pdata->model ? : 7846;
|
||||
ts->vref_delay_usecs = pdata->vref_delay_usecs ? : 100;
|
||||
ts->x_plate_ohms = pdata->x_plate_ohms ? : 400;
|
||||
ts->pressure_max = pdata->pressure_max ? : ~0;
|
||||
|
||||
ts->vref_mv = pdata->vref_mv;
|
||||
ts->swap_xy = pdata->swap_xy;
|
||||
|
||||
if (pdata->filter != NULL) {
|
||||
if (pdata->filter_init != NULL) {
|
||||
err = pdata->filter_init(pdata, &ts->filter_data);
|
||||
|
@ -1281,7 +1366,7 @@ static int ads7846_probe(struct spi_device *spi)
|
|||
ts->filter = ads7846_no_filter;
|
||||
}
|
||||
|
||||
err = ads7846_setup_pendown(spi, ts);
|
||||
err = ads7846_setup_pendown(spi, ts, pdata);
|
||||
if (err)
|
||||
goto err_cleanup_filter;
|
||||
|
||||
|
@ -1370,6 +1455,13 @@ static int ads7846_probe(struct spi_device *spi)
|
|||
|
||||
device_init_wakeup(&spi->dev, pdata->wakeup);
|
||||
|
||||
/*
|
||||
* If device does not carry platform data we must have allocated it
|
||||
* when parsing DT data.
|
||||
*/
|
||||
if (!dev_get_platdata(&spi->dev))
|
||||
devm_kfree(&spi->dev, (void *)pdata);
|
||||
|
||||
return 0;
|
||||
|
||||
err_remove_attr_group:
|
||||
|
@ -1437,6 +1529,7 @@ static struct spi_driver ads7846_driver = {
|
|||
.name = "ads7846",
|
||||
.owner = THIS_MODULE,
|
||||
.pm = &ads7846_pm,
|
||||
.of_match_table = of_match_ptr(ads7846_dt_ids),
|
||||
},
|
||||
.probe = ads7846_probe,
|
||||
.remove = ads7846_remove,
|
||||
|
|
|
@ -369,9 +369,9 @@ struct cyttsp4 {
|
|||
|
||||
struct cyttsp4_bus_ops {
|
||||
u16 bustype;
|
||||
int (*write)(struct device *dev, u8 *xfer_buf, u8 addr, u8 length,
|
||||
int (*write)(struct device *dev, u8 *xfer_buf, u16 addr, u8 length,
|
||||
const void *values);
|
||||
int (*read)(struct device *dev, u8 *xfer_buf, u8 addr, u8 length,
|
||||
int (*read)(struct device *dev, u8 *xfer_buf, u16 addr, u8 length,
|
||||
void *values);
|
||||
};
|
||||
|
||||
|
@ -448,13 +448,13 @@ enum cyttsp4_event_id {
|
|||
/* y-axis, 0:origin is on top side of panel, 1: bottom */
|
||||
#define CY_PCFG_ORIGIN_Y_MASK 0x80
|
||||
|
||||
static inline int cyttsp4_adap_read(struct cyttsp4 *ts, u8 addr, int size,
|
||||
static inline int cyttsp4_adap_read(struct cyttsp4 *ts, u16 addr, int size,
|
||||
void *buf)
|
||||
{
|
||||
return ts->bus_ops->read(ts->dev, ts->xfer_buf, addr, size, buf);
|
||||
}
|
||||
|
||||
static inline int cyttsp4_adap_write(struct cyttsp4 *ts, u8 addr, int size,
|
||||
static inline int cyttsp4_adap_write(struct cyttsp4 *ts, u16 addr, int size,
|
||||
const void *buf)
|
||||
{
|
||||
return ts->bus_ops->write(ts->dev, ts->xfer_buf, addr, size, buf);
|
||||
|
@ -463,9 +463,9 @@ static inline int cyttsp4_adap_write(struct cyttsp4 *ts, u8 addr, int size,
|
|||
extern struct cyttsp4 *cyttsp4_probe(const struct cyttsp4_bus_ops *ops,
|
||||
struct device *dev, u16 irq, size_t xfer_buf_size);
|
||||
extern int cyttsp4_remove(struct cyttsp4 *ts);
|
||||
int cyttsp_i2c_write_block_data(struct device *dev, u8 *xfer_buf, u8 addr,
|
||||
int cyttsp_i2c_write_block_data(struct device *dev, u8 *xfer_buf, u16 addr,
|
||||
u8 length, const void *values);
|
||||
int cyttsp_i2c_read_block_data(struct device *dev, u8 *xfer_buf, u8 addr,
|
||||
int cyttsp_i2c_read_block_data(struct device *dev, u8 *xfer_buf, u16 addr,
|
||||
u8 length, void *values);
|
||||
extern const struct dev_pm_ops cyttsp4_pm_ops;
|
||||
|
||||
|
|
|
@ -44,7 +44,7 @@
|
|||
#define CY_SPI_DATA_BUF_SIZE (CY_SPI_CMD_BYTES + CY_SPI_DATA_SIZE)
|
||||
|
||||
static int cyttsp_spi_xfer(struct device *dev, u8 *xfer_buf,
|
||||
u8 op, u8 reg, u8 *buf, int length)
|
||||
u8 op, u16 reg, u8 *buf, int length)
|
||||
{
|
||||
struct spi_device *spi = to_spi_device(dev);
|
||||
struct spi_message msg;
|
||||
|
@ -63,14 +63,12 @@ static int cyttsp_spi_xfer(struct device *dev, u8 *xfer_buf,
|
|||
memset(wr_buf, 0, CY_SPI_DATA_BUF_SIZE);
|
||||
memset(rd_buf, 0, CY_SPI_CMD_BYTES);
|
||||
|
||||
if (reg > 255)
|
||||
wr_buf[0] = op + CY_SPI_A8_BIT;
|
||||
else
|
||||
wr_buf[0] = op;
|
||||
if (op == CY_SPI_WR_OP)
|
||||
wr_buf[1] = reg % 256;
|
||||
if (op == CY_SPI_WR_OP && length > 0)
|
||||
memcpy(wr_buf + CY_SPI_CMD_BYTES, buf, length);
|
||||
wr_buf[0] = op + (((reg >> 8) & 0x1) ? CY_SPI_A8_BIT : 0);
|
||||
if (op == CY_SPI_WR_OP) {
|
||||
wr_buf[1] = reg & 0xFF;
|
||||
if (length > 0)
|
||||
memcpy(wr_buf + CY_SPI_CMD_BYTES, buf, length);
|
||||
}
|
||||
|
||||
memset(xfer, 0, sizeof(xfer));
|
||||
spi_message_init(&msg);
|
||||
|
@ -130,7 +128,7 @@ static int cyttsp_spi_xfer(struct device *dev, u8 *xfer_buf,
|
|||
}
|
||||
|
||||
static int cyttsp_spi_read_block_data(struct device *dev, u8 *xfer_buf,
|
||||
u8 addr, u8 length, void *data)
|
||||
u16 addr, u8 length, void *data)
|
||||
{
|
||||
int rc;
|
||||
|
||||
|
@ -143,7 +141,7 @@ static int cyttsp_spi_read_block_data(struct device *dev, u8 *xfer_buf,
|
|||
}
|
||||
|
||||
static int cyttsp_spi_write_block_data(struct device *dev, u8 *xfer_buf,
|
||||
u8 addr, u8 length, const void *data)
|
||||
u16 addr, u8 length, const void *data)
|
||||
{
|
||||
return cyttsp_spi_xfer(dev, xfer_buf, CY_SPI_WR_OP, addr, (void *)data,
|
||||
length);
|
||||
|
|
|
@ -112,9 +112,9 @@ struct cyttsp;
|
|||
|
||||
struct cyttsp_bus_ops {
|
||||
u16 bustype;
|
||||
int (*write)(struct device *dev, u8 *xfer_buf, u8 addr, u8 length,
|
||||
int (*write)(struct device *dev, u8 *xfer_buf, u16 addr, u8 length,
|
||||
const void *values);
|
||||
int (*read)(struct device *dev, u8 *xfer_buf, u8 addr, u8 length,
|
||||
int (*read)(struct device *dev, u8 *xfer_buf, u16 addr, u8 length,
|
||||
void *values);
|
||||
};
|
||||
|
||||
|
@ -145,9 +145,9 @@ struct cyttsp *cyttsp_probe(const struct cyttsp_bus_ops *bus_ops,
|
|||
struct device *dev, int irq, size_t xfer_buf_size);
|
||||
void cyttsp_remove(struct cyttsp *ts);
|
||||
|
||||
int cyttsp_i2c_write_block_data(struct device *dev, u8 *xfer_buf, u8 addr,
|
||||
int cyttsp_i2c_write_block_data(struct device *dev, u8 *xfer_buf, u16 addr,
|
||||
u8 length, const void *values);
|
||||
int cyttsp_i2c_read_block_data(struct device *dev, u8 *xfer_buf, u8 addr,
|
||||
int cyttsp_i2c_read_block_data(struct device *dev, u8 *xfer_buf, u16 addr,
|
||||
u8 length, void *values);
|
||||
extern const struct dev_pm_ops cyttsp_pm_ops;
|
||||
|
||||
|
|
|
@ -32,18 +32,20 @@
|
|||
#include <linux/types.h>
|
||||
|
||||
int cyttsp_i2c_read_block_data(struct device *dev, u8 *xfer_buf,
|
||||
u8 addr, u8 length, void *values)
|
||||
u16 addr, u8 length, void *values)
|
||||
{
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
u8 client_addr = client->addr | ((addr >> 8) & 0x1);
|
||||
u8 addr_lo = addr & 0xFF;
|
||||
struct i2c_msg msgs[] = {
|
||||
{
|
||||
.addr = client->addr,
|
||||
.addr = client_addr,
|
||||
.flags = 0,
|
||||
.len = 1,
|
||||
.buf = &addr,
|
||||
.buf = &addr_lo,
|
||||
},
|
||||
{
|
||||
.addr = client->addr,
|
||||
.addr = client_addr,
|
||||
.flags = I2C_M_RD,
|
||||
.len = length,
|
||||
.buf = values,
|
||||
|
@ -60,17 +62,29 @@ int cyttsp_i2c_read_block_data(struct device *dev, u8 *xfer_buf,
|
|||
EXPORT_SYMBOL_GPL(cyttsp_i2c_read_block_data);
|
||||
|
||||
int cyttsp_i2c_write_block_data(struct device *dev, u8 *xfer_buf,
|
||||
u8 addr, u8 length, const void *values)
|
||||
u16 addr, u8 length, const void *values)
|
||||
{
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
u8 client_addr = client->addr | ((addr >> 8) & 0x1);
|
||||
u8 addr_lo = addr & 0xFF;
|
||||
struct i2c_msg msgs[] = {
|
||||
{
|
||||
.addr = client_addr,
|
||||
.flags = 0,
|
||||
.len = length + 1,
|
||||
.buf = xfer_buf,
|
||||
},
|
||||
};
|
||||
int retval;
|
||||
|
||||
xfer_buf[0] = addr;
|
||||
xfer_buf[0] = addr_lo;
|
||||
memcpy(&xfer_buf[1], values, length);
|
||||
|
||||
retval = i2c_master_send(client, xfer_buf, length + 1);
|
||||
retval = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
|
||||
if (retval < 0)
|
||||
return retval;
|
||||
|
||||
return retval < 0 ? retval : 0;
|
||||
return retval != ARRAY_SIZE(msgs) ? -EIO : 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(cyttsp_i2c_write_block_data);
|
||||
|
||||
|
|
|
@ -41,7 +41,7 @@
|
|||
#define CY_SPI_BITS_PER_WORD 8
|
||||
|
||||
static int cyttsp_spi_xfer(struct device *dev, u8 *xfer_buf,
|
||||
u8 op, u8 reg, u8 *buf, int length)
|
||||
u8 op, u16 reg, u8 *buf, int length)
|
||||
{
|
||||
struct spi_device *spi = to_spi_device(dev);
|
||||
struct spi_message msg;
|
||||
|
@ -126,14 +126,14 @@ static int cyttsp_spi_xfer(struct device *dev, u8 *xfer_buf,
|
|||
}
|
||||
|
||||
static int cyttsp_spi_read_block_data(struct device *dev, u8 *xfer_buf,
|
||||
u8 addr, u8 length, void *data)
|
||||
u16 addr, u8 length, void *data)
|
||||
{
|
||||
return cyttsp_spi_xfer(dev, xfer_buf, CY_SPI_RD_OP, addr, data,
|
||||
length);
|
||||
}
|
||||
|
||||
static int cyttsp_spi_write_block_data(struct device *dev, u8 *xfer_buf,
|
||||
u8 addr, u8 length, const void *data)
|
||||
u16 addr, u8 length, const void *data)
|
||||
{
|
||||
return cyttsp_spi_xfer(dev, xfer_buf, CY_SPI_WR_OP, addr, (void *)data,
|
||||
length);
|
||||
|
|
Загрузка…
Ссылка в новой задаче