Commit e1a4b3a7 authored by Hans de Goede's avatar Hans de Goede Committed by Mauro Carvalho Chehab
Browse files

media: atomisp: gc0310: Simplify gc0310_write_reg_array()



Remove the complex optimization to send multiple registers in
one i2c-transfer. None of the other sensor drivers are doing this
and the reg-lists are only used once at stream-start time, so
this does not need to be highly optimized.

Reviewed-by: default avatarAndy Shevchenko <andy.shevchenko@gmail.com>
Signed-off-by: default avatarHans de Goede <hdegoede@redhat.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@kernel.org>
parent bfe06aee
Loading
Loading
Loading
Loading
+3 −84
Original line number Diff line number Diff line
@@ -135,100 +135,19 @@ static int gc0310_write_reg(struct i2c_client *client, u16 data_length,
 * @client: i2c driver client structure
 * @reglist: list of registers to be written
 * @count: number of register, value pairs in the list
 *
 * This function initializes a list of registers. When consecutive addresses
 * are found in a row on the list, this function creates a buffer and sends
 * consecutive data in a single i2c_transfer().
 *
 * __gc0310_flush_reg_array, __gc0310_buf_reg_array() and
 * __gc0310_write_reg_is_consecutive() are internal functions to
 * gc0310_write_reg_array_fast() and should be not used anywhere else.
 *
 */

static int __gc0310_flush_reg_array(struct i2c_client *client,
				    struct gc0310_write_ctrl *ctrl)
{
	u16 size;

	if (ctrl->index == 0)
		return 0;

	size = sizeof(u8) + ctrl->index; /* 8-bit address + data */
	ctrl->buffer.addr = (u8)(ctrl->buffer.addr);
	ctrl->index = 0;

	return gc0310_i2c_write(client, size, (u8 *)&ctrl->buffer);
}

static int __gc0310_buf_reg_array(struct i2c_client *client,
				  struct gc0310_write_ctrl *ctrl,
				  const struct gc0310_reg *next)
{
	int size;

	switch (next->type) {
	case GC0310_8BIT:
		size = 1;
		ctrl->buffer.data[ctrl->index] = (u8)next->val;
		break;
	default:
		return -EINVAL;
	}

	/* When first item is added, we need to store its starting address */
	if (ctrl->index == 0)
		ctrl->buffer.addr = next->reg;

	ctrl->index += size;

	/*
	 * Buffer cannot guarantee free space for u32? Better flush it to avoid
	 * possible lack of memory for next item.
	 */
	if (ctrl->index + sizeof(u8) >= GC0310_MAX_WRITE_BUF_SIZE)
		return __gc0310_flush_reg_array(client, ctrl);

	return 0;
}

static int __gc0310_write_reg_is_consecutive(struct i2c_client *client,
					     struct gc0310_write_ctrl *ctrl,
					     const struct gc0310_reg *next)
{
	if (ctrl->index == 0)
		return 1;

	return ctrl->buffer.addr + ctrl->index == next->reg;
}

static int gc0310_write_reg_array(struct i2c_client *client,
				  const struct gc0310_reg *reglist, int count)
{
	struct gc0310_write_ctrl ctrl;
	int i, err;

	ctrl.index = 0;
	for (i = 0; i < count; i++) {
		/*
		 * If next address is not consecutive, data needs to be
		 * flushed before proceed.
		 */
		if (!__gc0310_write_reg_is_consecutive(client, &ctrl,
						       &reglist[i])) {
			err = __gc0310_flush_reg_array(client, &ctrl);
		err = gc0310_write_reg(client, GC0310_8BIT, reglist[i].reg, reglist[i].val);
		if (err)
			return err;
	}
		err = __gc0310_buf_reg_array(client, &ctrl, &reglist[i]);
		if (err) {
			dev_err(&client->dev, "%s: write error, aborted\n",
				__func__);
			return err;
		}
	}

	return __gc0310_flush_reg_array(client, &ctrl);
	return 0;
}

static int gc0310_set_gain(struct v4l2_subdev *sd, int gain)
+0 −12
Original line number Diff line number Diff line
@@ -158,18 +158,6 @@ struct gc0310_reg {

#define to_gc0310_sensor(x) container_of(x, struct gc0310_device, sd)

#define GC0310_MAX_WRITE_BUF_SIZE	30

struct gc0310_write_buffer {
	u8 addr;
	u8 data[GC0310_MAX_WRITE_BUF_SIZE];
};

struct gc0310_write_ctrl {
	int index;
	struct gc0310_write_buffer buffer;
};

/*
 * Register settings for various resolution
 */