Commit 1a67448f authored by Hans de Goede's avatar Hans de Goede Committed by Dmitry Torokhov
Browse files

Input: goodix - make goodix_send_cfg() take a raw buffer as argument

Make goodix_send_cfg() take a raw buffer as argument instead of a
struct firmware *cfg, so that it can also be used to restore the config
on resume if necessary.

BugLink: https://bugzilla.redhat.com/show_bug.cgi?id=1786317
BugLink: https://github.com/nexus511/gpd-ubuntu-packages/issues/10
BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=199207


Reviewed-by: default avatarBastien Nocera <hadess@hadess.net>
Signed-off-by: default avatarHans de Goede <hdegoede@redhat.com>
Link: https://lore.kernel.org/r/20200307121505.3707-10-hdegoede@redhat.com


Signed-off-by: default avatarDmitry Torokhov <dmitry.torokhov@gmail.com>
parent 686e8a24
Loading
Loading
Loading
Loading
+22 −26
Original line number Original line Diff line number Diff line
@@ -73,7 +73,7 @@ enum goodix_irq_pin_access_method {
struct goodix_chip_data {
struct goodix_chip_data {
	u16 config_addr;
	u16 config_addr;
	int config_len;
	int config_len;
	int (*check_config)(struct goodix_ts_data *, const struct firmware *);
	int (*check_config)(struct goodix_ts_data *ts, const u8 *cfg, int len);
	void (*calc_config_checksum)(struct goodix_ts_data *ts);
	void (*calc_config_checksum)(struct goodix_ts_data *ts);
};
};


@@ -103,9 +103,9 @@ struct goodix_ts_data {
};
};


static int goodix_check_cfg_8(struct goodix_ts_data *ts,
static int goodix_check_cfg_8(struct goodix_ts_data *ts,
			const struct firmware *cfg);
			      const u8 *cfg, int len);
static int goodix_check_cfg_16(struct goodix_ts_data *ts,
static int goodix_check_cfg_16(struct goodix_ts_data *ts,
			const struct firmware *cfg);
			       const u8 *cfg, int len);
static void goodix_calc_cfg_checksum_8(struct goodix_ts_data *ts);
static void goodix_calc_cfg_checksum_8(struct goodix_ts_data *ts);
static void goodix_calc_cfg_checksum_16(struct goodix_ts_data *ts);
static void goodix_calc_cfg_checksum_16(struct goodix_ts_data *ts);


@@ -444,22 +444,21 @@ static int goodix_request_irq(struct goodix_ts_data *ts)
					 ts->irq_flags, ts->client->name, ts);
					 ts->irq_flags, ts->client->name, ts);
}
}


static int goodix_check_cfg_8(struct goodix_ts_data *ts,
static int goodix_check_cfg_8(struct goodix_ts_data *ts, const u8 *cfg, int len)
			const struct firmware *cfg)
{
{
	int i, raw_cfg_len = cfg->size - 2;
	int i, raw_cfg_len = len - 2;
	u8 check_sum = 0;
	u8 check_sum = 0;


	for (i = 0; i < raw_cfg_len; i++)
	for (i = 0; i < raw_cfg_len; i++)
		check_sum += cfg->data[i];
		check_sum += cfg[i];
	check_sum = (~check_sum) + 1;
	check_sum = (~check_sum) + 1;
	if (check_sum != cfg->data[raw_cfg_len]) {
	if (check_sum != cfg[raw_cfg_len]) {
		dev_err(&ts->client->dev,
		dev_err(&ts->client->dev,
			"The checksum of the config fw is not correct");
			"The checksum of the config fw is not correct");
		return -EINVAL;
		return -EINVAL;
	}
	}


	if (cfg->data[raw_cfg_len + 1] != 1) {
	if (cfg[raw_cfg_len + 1] != 1) {
		dev_err(&ts->client->dev,
		dev_err(&ts->client->dev,
			"Config fw must have Config_Fresh register set");
			"Config fw must have Config_Fresh register set");
		return -EINVAL;
		return -EINVAL;
@@ -481,22 +480,22 @@ static void goodix_calc_cfg_checksum_8(struct goodix_ts_data *ts)
	ts->config[raw_cfg_len + 1] = 1; /* Set "config_fresh" bit */
	ts->config[raw_cfg_len + 1] = 1; /* Set "config_fresh" bit */
}
}


static int goodix_check_cfg_16(struct goodix_ts_data *ts,
static int goodix_check_cfg_16(struct goodix_ts_data *ts, const u8 *cfg,
			const struct firmware *cfg)
			       int len)
{
{
	int i, raw_cfg_len = cfg->size - 3;
	int i, raw_cfg_len = len - 3;
	u16 check_sum = 0;
	u16 check_sum = 0;


	for (i = 0; i < raw_cfg_len; i += 2)
	for (i = 0; i < raw_cfg_len; i += 2)
		check_sum += get_unaligned_be16(&cfg->data[i]);
		check_sum += get_unaligned_be16(&cfg[i]);
	check_sum = (~check_sum) + 1;
	check_sum = (~check_sum) + 1;
	if (check_sum != get_unaligned_be16(&cfg->data[raw_cfg_len])) {
	if (check_sum != get_unaligned_be16(&cfg[raw_cfg_len])) {
		dev_err(&ts->client->dev,
		dev_err(&ts->client->dev,
			"The checksum of the config fw is not correct");
			"The checksum of the config fw is not correct");
		return -EINVAL;
		return -EINVAL;
	}
	}


	if (cfg->data[raw_cfg_len + 2] != 1) {
	if (cfg[raw_cfg_len + 2] != 1) {
		dev_err(&ts->client->dev,
		dev_err(&ts->client->dev,
			"Config fw must have Config_Fresh register set");
			"Config fw must have Config_Fresh register set");
		return -EINVAL;
		return -EINVAL;
@@ -524,17 +523,16 @@ static void goodix_calc_cfg_checksum_16(struct goodix_ts_data *ts)
 * @ts: goodix_ts_data pointer
 * @ts: goodix_ts_data pointer
 * @cfg: firmware config data
 * @cfg: firmware config data
 */
 */
static int goodix_check_cfg(struct goodix_ts_data *ts,
static int goodix_check_cfg(struct goodix_ts_data *ts, const u8 *cfg, int len)
			    const struct firmware *cfg)
{
{
	if (cfg->size < GOODIX_CONFIG_MIN_LENGTH ||
	if (len < GOODIX_CONFIG_MIN_LENGTH ||
	    cfg->size > GOODIX_CONFIG_MAX_LENGTH) {
	    len > GOODIX_CONFIG_MAX_LENGTH) {
		dev_err(&ts->client->dev,
		dev_err(&ts->client->dev,
			"The length of the config fw is not correct");
			"The length of the config fw is not correct");
		return -EINVAL;
		return -EINVAL;
	}
	}


	return ts->chip->check_config(ts, cfg);
	return ts->chip->check_config(ts, cfg, len);
}
}


/**
/**
@@ -543,17 +541,15 @@ static int goodix_check_cfg(struct goodix_ts_data *ts,
 * @ts: goodix_ts_data pointer
 * @ts: goodix_ts_data pointer
 * @cfg: config firmware to write to device
 * @cfg: config firmware to write to device
 */
 */
static int goodix_send_cfg(struct goodix_ts_data *ts,
static int goodix_send_cfg(struct goodix_ts_data *ts, const u8 *cfg, int len)
			   const struct firmware *cfg)
{
{
	int error;
	int error;


	error = goodix_check_cfg(ts, cfg);
	error = goodix_check_cfg(ts, cfg, len);
	if (error)
	if (error)
		return error;
		return error;


	error = goodix_i2c_write(ts->client, ts->chip->config_addr, cfg->data,
	error = goodix_i2c_write(ts->client, ts->chip->config_addr, cfg, len);
				 cfg->size);
	if (error) {
	if (error) {
		dev_err(&ts->client->dev, "Failed to write config data: %d",
		dev_err(&ts->client->dev, "Failed to write config data: %d",
			error);
			error);
@@ -1094,7 +1090,7 @@ static void goodix_config_cb(const struct firmware *cfg, void *ctx)


	if (cfg) {
	if (cfg) {
		/* send device configuration to the firmware */
		/* send device configuration to the firmware */
		error = goodix_send_cfg(ts, cfg);
		error = goodix_send_cfg(ts, cfg->data, cfg->size);
		if (error)
		if (error)
			goto err_release_cfg;
			goto err_release_cfg;
	}
	}