media: mt9m001: introduce multi_reg_write()
Introduce multi_reg_write() to write multiple registers to the device and use it where possible. Cc: Guennadi Liakhovetski <g.liakhovetski@gmx.de> Signed-off-by: Akinobu Mita <akinobu.mita@gmail.com> Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com> Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
This commit is contained in:

committed by
Mauro Carvalho Chehab

parent
1e57e4ce90
commit
a5826484d4
@@ -47,6 +47,8 @@
|
|||||||
#define MT9M001_MIN_HEIGHT 32
|
#define MT9M001_MIN_HEIGHT 32
|
||||||
#define MT9M001_COLUMN_SKIP 20
|
#define MT9M001_COLUMN_SKIP 20
|
||||||
#define MT9M001_ROW_SKIP 12
|
#define MT9M001_ROW_SKIP 12
|
||||||
|
#define MT9M001_DEFAULT_HBLANK 9
|
||||||
|
#define MT9M001_DEFAULT_VBLANK 25
|
||||||
|
|
||||||
/* MT9M001 has only one fixed colorspace per pixelcode */
|
/* MT9M001 has only one fixed colorspace per pixelcode */
|
||||||
struct mt9m001_datafmt {
|
struct mt9m001_datafmt {
|
||||||
@@ -137,25 +139,65 @@ static int reg_clear(struct i2c_client *client, const u8 reg,
|
|||||||
return reg_write(client, reg, ret & ~data);
|
return reg_write(client, reg, ret & ~data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct mt9m001_reg {
|
||||||
|
u8 reg;
|
||||||
|
u16 data;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int multi_reg_write(struct i2c_client *client,
|
||||||
|
const struct mt9m001_reg *regs, int num)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < num; i++) {
|
||||||
|
int ret = reg_write(client, regs[i].reg, regs[i].data);
|
||||||
|
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int mt9m001_init(struct i2c_client *client)
|
static int mt9m001_init(struct i2c_client *client)
|
||||||
{
|
{
|
||||||
int ret;
|
const struct mt9m001_reg init_regs[] = {
|
||||||
|
/*
|
||||||
|
* Issue a soft reset. This returns all registers to their
|
||||||
|
* default values.
|
||||||
|
*/
|
||||||
|
{ MT9M001_RESET, 1 },
|
||||||
|
{ MT9M001_RESET, 0 },
|
||||||
|
/* Disable chip, synchronous option update */
|
||||||
|
{ MT9M001_OUTPUT_CONTROL, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
dev_dbg(&client->dev, "%s\n", __func__);
|
dev_dbg(&client->dev, "%s\n", __func__);
|
||||||
|
|
||||||
|
return multi_reg_write(client, init_regs, ARRAY_SIZE(init_regs));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mt9m001_apply_selection(struct v4l2_subdev *sd,
|
||||||
|
struct v4l2_rect *rect)
|
||||||
|
{
|
||||||
|
struct i2c_client *client = v4l2_get_subdevdata(sd);
|
||||||
|
struct mt9m001 *mt9m001 = to_mt9m001(client);
|
||||||
|
const struct mt9m001_reg regs[] = {
|
||||||
|
/* Blanking and start values - default... */
|
||||||
|
{ MT9M001_HORIZONTAL_BLANKING, MT9M001_DEFAULT_HBLANK },
|
||||||
|
{ MT9M001_VERTICAL_BLANKING, MT9M001_DEFAULT_VBLANK },
|
||||||
/*
|
/*
|
||||||
* We don't know, whether platform provides reset, issue a soft reset
|
* The caller provides a supported format, as verified per
|
||||||
* too. This returns all registers to their default values.
|
* call to .set_fmt(FORMAT_TRY).
|
||||||
*/
|
*/
|
||||||
ret = reg_write(client, MT9M001_RESET, 1);
|
{ MT9M001_COLUMN_START, rect->left },
|
||||||
if (!ret)
|
{ MT9M001_ROW_START, rect->top },
|
||||||
ret = reg_write(client, MT9M001_RESET, 0);
|
{ MT9M001_WINDOW_WIDTH, rect->width - 1 },
|
||||||
|
{ MT9M001_WINDOW_HEIGHT,
|
||||||
|
rect->height + mt9m001->y_skip_top - 1 },
|
||||||
|
};
|
||||||
|
|
||||||
/* Disable chip, synchronous option update */
|
return multi_reg_write(client, regs, ARRAY_SIZE(regs));
|
||||||
if (!ret)
|
|
||||||
ret = reg_write(client, MT9M001_OUTPUT_CONTROL, 0);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mt9m001_s_stream(struct v4l2_subdev *sd, int enable)
|
static int mt9m001_s_stream(struct v4l2_subdev *sd, int enable)
|
||||||
@@ -175,7 +217,6 @@ static int mt9m001_set_selection(struct v4l2_subdev *sd,
|
|||||||
struct i2c_client *client = v4l2_get_subdevdata(sd);
|
struct i2c_client *client = v4l2_get_subdevdata(sd);
|
||||||
struct mt9m001 *mt9m001 = to_mt9m001(client);
|
struct mt9m001 *mt9m001 = to_mt9m001(client);
|
||||||
struct v4l2_rect rect = sel->r;
|
struct v4l2_rect rect = sel->r;
|
||||||
const u16 hblank = 9, vblank = 25;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE ||
|
if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE ||
|
||||||
@@ -199,26 +240,11 @@ static int mt9m001_set_selection(struct v4l2_subdev *sd,
|
|||||||
soc_camera_limit_side(&rect.top, &rect.height,
|
soc_camera_limit_side(&rect.top, &rect.height,
|
||||||
MT9M001_ROW_SKIP, MT9M001_MIN_HEIGHT, MT9M001_MAX_HEIGHT);
|
MT9M001_ROW_SKIP, MT9M001_MIN_HEIGHT, MT9M001_MAX_HEIGHT);
|
||||||
|
|
||||||
mt9m001->total_h = rect.height + mt9m001->y_skip_top + vblank;
|
mt9m001->total_h = rect.height + mt9m001->y_skip_top +
|
||||||
|
MT9M001_DEFAULT_VBLANK;
|
||||||
|
|
||||||
/* Blanking and start values - default... */
|
|
||||||
ret = reg_write(client, MT9M001_HORIZONTAL_BLANKING, hblank);
|
|
||||||
if (!ret)
|
|
||||||
ret = reg_write(client, MT9M001_VERTICAL_BLANKING, vblank);
|
|
||||||
|
|
||||||
/*
|
ret = mt9m001_apply_selection(sd, &rect);
|
||||||
* The caller provides a supported format, as verified per
|
|
||||||
* call to .set_fmt(FORMAT_TRY).
|
|
||||||
*/
|
|
||||||
if (!ret)
|
|
||||||
ret = reg_write(client, MT9M001_COLUMN_START, rect.left);
|
|
||||||
if (!ret)
|
|
||||||
ret = reg_write(client, MT9M001_ROW_START, rect.top);
|
|
||||||
if (!ret)
|
|
||||||
ret = reg_write(client, MT9M001_WINDOW_WIDTH, rect.width - 1);
|
|
||||||
if (!ret)
|
|
||||||
ret = reg_write(client, MT9M001_WINDOW_HEIGHT,
|
|
||||||
rect.height + mt9m001->y_skip_top - 1);
|
|
||||||
if (!ret && v4l2_ctrl_g_ctrl(mt9m001->autoexposure) == V4L2_EXPOSURE_AUTO)
|
if (!ret && v4l2_ctrl_g_ctrl(mt9m001->autoexposure) == V4L2_EXPOSURE_AUTO)
|
||||||
ret = reg_write(client, MT9M001_SHUTTER_WIDTH, mt9m001->total_h);
|
ret = reg_write(client, MT9M001_SHUTTER_WIDTH, mt9m001->total_h);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user