Unverified Commit cec9d64c authored by Mark Brown's avatar Mark Brown
Browse files

ASoC: Correct bug parsing DisCo booleans

Charles Keepax <ckeepax@opensource.cirrus.com> says:

MIPI DisCo uses the unfortunate convention of allowing boolean
properties to be present but having a zero value. Opposed to the
normal convention of simply not specifying the property. Fix an
issue in the SDCA code where mipi-sdca-control-deferrable is not
parsed correctly.

However, we also have some shipping ACPIs where these properties
are not specified correctly. Update the MBQ regmap to attempt defers
albeit with a warning in the case where a control attempts to defer
but is not marked at such. There is little down side to this as if
defer is genuinely not supported then the control will just return
the same error again.
parents c15bc168 956c032b
Loading
Loading
Loading
Loading
+18 −18
Original line number Diff line number Diff line
@@ -74,7 +74,7 @@ static int regmap_sdw_mbq_poll_busy(struct sdw_slave *slave, unsigned int reg,

static int regmap_sdw_mbq_write_impl(struct sdw_slave *slave,
				     unsigned int reg, unsigned int val,
				     int mbq_size, bool deferrable)
				     int mbq_size)
{
	int shift = mbq_size * BITS_PER_BYTE;
	int ret;
@@ -88,17 +88,14 @@ static int regmap_sdw_mbq_write_impl(struct sdw_slave *slave,
			return ret;
	}

	ret = sdw_write_no_pm(slave, reg, val & 0xff);
	if (deferrable && ret == -ENODATA)
		return -EAGAIN;

	return ret;
	return sdw_write_no_pm(slave, reg, val & 0xff);
}

static int regmap_sdw_mbq_write(void *context, unsigned int reg, unsigned int val)
{
	struct regmap_mbq_context *ctx = context;
	struct sdw_slave *slave = ctx->sdw;
	struct device *dev = ctx->dev;
	bool deferrable = regmap_sdw_mbq_deferrable(ctx, reg);
	int mbq_size = regmap_sdw_mbq_size(ctx, reg);
	int ret;
@@ -113,13 +110,16 @@ static int regmap_sdw_mbq_write(void *context, unsigned int reg, unsigned int va
	 * process a single wait/timeout on function busy and a single retry
	 * of the transaction.
	 */
	ret = regmap_sdw_mbq_write_impl(slave, reg, val, mbq_size, deferrable);
	if (ret == -EAGAIN) {
	ret = regmap_sdw_mbq_write_impl(slave, reg, val, mbq_size);
	if (ret == -ENODATA) {
		if (!deferrable)
			dev_warn(dev, "Defer on undeferrable control: %x\n", reg);

		ret = regmap_sdw_mbq_poll_busy(slave, reg, ctx);
		if (ret)
			return ret;

		ret = regmap_sdw_mbq_write_impl(slave, reg, val, mbq_size, false);
		ret = regmap_sdw_mbq_write_impl(slave, reg, val, mbq_size);
	}

	return ret;
@@ -127,18 +127,14 @@ static int regmap_sdw_mbq_write(void *context, unsigned int reg, unsigned int va

static int regmap_sdw_mbq_read_impl(struct sdw_slave *slave,
				    unsigned int reg, unsigned int *val,
				    int mbq_size, bool deferrable)
				    int mbq_size)
{
	int shift = BITS_PER_BYTE;
	int read;

	read = sdw_read_no_pm(slave, reg);
	if (read < 0) {
		if (deferrable && read == -ENODATA)
			return -EAGAIN;

	if (read < 0)
		return read;
	}

	*val = read;

@@ -158,6 +154,7 @@ static int regmap_sdw_mbq_read(void *context, unsigned int reg, unsigned int *va
{
	struct regmap_mbq_context *ctx = context;
	struct sdw_slave *slave = ctx->sdw;
	struct device *dev = ctx->dev;
	bool deferrable = regmap_sdw_mbq_deferrable(ctx, reg);
	int mbq_size = regmap_sdw_mbq_size(ctx, reg);
	int ret;
@@ -172,13 +169,16 @@ static int regmap_sdw_mbq_read(void *context, unsigned int reg, unsigned int *va
	 * process a single wait/timeout on function busy and a single retry
	 * of the transaction.
	 */
	ret = regmap_sdw_mbq_read_impl(slave, reg, val, mbq_size, deferrable);
	if (ret == -EAGAIN) {
	ret = regmap_sdw_mbq_read_impl(slave, reg, val, mbq_size);
	if (ret == -ENODATA) {
		if (!deferrable)
			dev_warn(dev, "Defer on undeferable control: %x\n", reg);

		ret = regmap_sdw_mbq_poll_busy(slave, reg, ctx);
		if (ret)
			return ret;

		ret = regmap_sdw_mbq_read_impl(slave, reg, val, mbq_size, false);
		ret = regmap_sdw_mbq_read_impl(slave, reg, val, mbq_size);
	}

	return ret;
+5 −2
Original line number Diff line number Diff line
@@ -1006,8 +1006,11 @@ static int find_sdca_entity_control(struct device *dev, struct sdca_entity *enti
			control->has_fixed = true;
		fallthrough;
	case SDCA_ACCESS_MODE_RO:
		control->deferrable = fwnode_property_read_bool(control_node,
								"mipi-sdca-control-deferrable");
		ret = fwnode_property_read_u32(control_node,
					       "mipi-sdca-control-deferrable",
					       &tmp);
		if (ret == 0)
			control->deferrable = !!tmp;
		break;
	default:
		break;