Commit 47921932 authored by Guennadi Liakhovetski's avatar Guennadi Liakhovetski Committed by Mauro Carvalho Chehab

[media] mt9m111: cleanly separate register contexts

Cleanly separating register contexts A and B will allow us to configure
the contexts independently.
Signed-off-by: default avatarGuennadi Liakhovetski <g.liakhovetski@gmx.de>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent 8843d119
...@@ -139,6 +139,46 @@ ...@@ -139,6 +139,46 @@
#define MT9M111_MAX_HEIGHT 1024 #define MT9M111_MAX_HEIGHT 1024
#define MT9M111_MAX_WIDTH 1280 #define MT9M111_MAX_WIDTH 1280
struct mt9m111_context {
u16 read_mode;
u16 blanking_h;
u16 blanking_v;
u16 reducer_xzoom;
u16 reducer_yzoom;
u16 reducer_xsize;
u16 reducer_ysize;
u16 output_fmt_ctrl2;
u16 control;
};
static struct mt9m111_context context_a = {
.read_mode = MT9M111_READ_MODE_A,
.blanking_h = MT9M111_HORIZONTAL_BLANKING_A,
.blanking_v = MT9M111_VERTICAL_BLANKING_A,
.reducer_xzoom = MT9M111_REDUCER_XZOOM_A,
.reducer_yzoom = MT9M111_REDUCER_YZOOM_A,
.reducer_xsize = MT9M111_REDUCER_XSIZE_A,
.reducer_ysize = MT9M111_REDUCER_YSIZE_A,
.output_fmt_ctrl2 = MT9M111_OUTPUT_FORMAT_CTRL2_A,
.control = MT9M111_CTXT_CTRL_RESTART,
};
static struct mt9m111_context context_b = {
.read_mode = MT9M111_READ_MODE_B,
.blanking_h = MT9M111_HORIZONTAL_BLANKING_B,
.blanking_v = MT9M111_VERTICAL_BLANKING_B,
.reducer_xzoom = MT9M111_REDUCER_XZOOM_B,
.reducer_yzoom = MT9M111_REDUCER_YZOOM_B,
.reducer_xsize = MT9M111_REDUCER_XSIZE_B,
.reducer_ysize = MT9M111_REDUCER_YSIZE_B,
.output_fmt_ctrl2 = MT9M111_OUTPUT_FORMAT_CTRL2_B,
.control = MT9M111_CTXT_CTRL_RESTART |
MT9M111_CTXT_CTRL_DEFECTCOR_B | MT9M111_CTXT_CTRL_RESIZE_B |
MT9M111_CTXT_CTRL_CTRL2_B | MT9M111_CTXT_CTRL_GAMMA_B |
MT9M111_CTXT_CTRL_READ_MODE_B | MT9M111_CTXT_CTRL_VBLANK_SEL_B |
MT9M111_CTXT_CTRL_HBLANK_SEL_B,
};
/* MT9M111 has only one fixed colorspace per pixelcode */ /* MT9M111 has only one fixed colorspace per pixelcode */
struct mt9m111_datafmt { struct mt9m111_datafmt {
enum v4l2_mbus_pixelcode code; enum v4l2_mbus_pixelcode code;
...@@ -173,18 +213,13 @@ static const struct mt9m111_datafmt mt9m111_colour_fmts[] = { ...@@ -173,18 +213,13 @@ static const struct mt9m111_datafmt mt9m111_colour_fmts[] = {
{V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE, V4L2_COLORSPACE_SRGB}, {V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE, V4L2_COLORSPACE_SRGB},
}; };
enum mt9m111_context {
HIGHPOWER = 0,
LOWPOWER,
};
struct mt9m111 { struct mt9m111 {
struct v4l2_subdev subdev; struct v4l2_subdev subdev;
struct v4l2_ctrl_handler hdl; struct v4l2_ctrl_handler hdl;
struct v4l2_ctrl *gain; struct v4l2_ctrl *gain;
int model; /* V4L2_IDENT_MT9M111 or V4L2_IDENT_MT9M112 code int model; /* V4L2_IDENT_MT9M111 or V4L2_IDENT_MT9M112 code
* from v4l2-chip-ident.h */ * from v4l2-chip-ident.h */
enum mt9m111_context context; struct mt9m111_context *ctx;
struct v4l2_rect rect; struct v4l2_rect rect;
struct mutex power_lock; /* lock to protect power_count */ struct mutex power_lock; /* lock to protect power_count */
int power_count; int power_count;
...@@ -275,35 +310,33 @@ static int mt9m111_reg_mask(struct i2c_client *client, const u16 reg, ...@@ -275,35 +310,33 @@ static int mt9m111_reg_mask(struct i2c_client *client, const u16 reg,
} }
static int mt9m111_set_context(struct mt9m111 *mt9m111, static int mt9m111_set_context(struct mt9m111 *mt9m111,
enum mt9m111_context ctxt) struct mt9m111_context *ctx)
{ {
struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev); struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev);
int valB = MT9M111_CTXT_CTRL_RESTART | MT9M111_CTXT_CTRL_DEFECTCOR_B return reg_write(CONTEXT_CONTROL, ctx->control);
| MT9M111_CTXT_CTRL_RESIZE_B | MT9M111_CTXT_CTRL_CTRL2_B }
| MT9M111_CTXT_CTRL_GAMMA_B | MT9M111_CTXT_CTRL_READ_MODE_B
| MT9M111_CTXT_CTRL_VBLANK_SEL_B static int mt9m111_setup_rect_ctx(struct mt9m111 *mt9m111,
| MT9M111_CTXT_CTRL_HBLANK_SEL_B; struct v4l2_rect *rect, struct mt9m111_context *ctx)
int valA = MT9M111_CTXT_CTRL_RESTART; {
struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev);
if (ctxt == HIGHPOWER) int ret = mt9m111_reg_write(client, ctx->reducer_xzoom, MT9M111_MAX_WIDTH);
return reg_write(CONTEXT_CONTROL, valB); if (!ret)
else ret = mt9m111_reg_write(client, ctx->reducer_yzoom, MT9M111_MAX_HEIGHT);
return reg_write(CONTEXT_CONTROL, valA); if (!ret)
ret = mt9m111_reg_write(client, ctx->reducer_xsize, rect->width);
if (!ret)
ret = mt9m111_reg_write(client, ctx->reducer_ysize, rect->height);
return ret;
} }
static int mt9m111_setup_rect(struct mt9m111 *mt9m111, static int mt9m111_setup_rect(struct mt9m111 *mt9m111,
struct v4l2_rect *rect) struct v4l2_rect *rect)
{ {
struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev); struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev);
int ret, is_raw_format; int ret;
int width = rect->width; bool is_raw_format = mt9m111->fmt->code == V4L2_MBUS_FMT_SBGGR8_1X8 ||
int height = rect->height; mt9m111->fmt->code == V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE;
if (mt9m111->fmt->code == V4L2_MBUS_FMT_SBGGR8_1X8 ||
mt9m111->fmt->code == V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE)
is_raw_format = 1;
else
is_raw_format = 0;
ret = reg_write(COLUMN_START, rect->left); ret = reg_write(COLUMN_START, rect->left);
if (!ret) if (!ret)
...@@ -311,26 +344,14 @@ static int mt9m111_setup_rect(struct mt9m111 *mt9m111, ...@@ -311,26 +344,14 @@ static int mt9m111_setup_rect(struct mt9m111 *mt9m111,
if (is_raw_format) { if (is_raw_format) {
if (!ret) if (!ret)
ret = reg_write(WINDOW_WIDTH, width); ret = reg_write(WINDOW_WIDTH, rect->width);
if (!ret) if (!ret)
ret = reg_write(WINDOW_HEIGHT, height); ret = reg_write(WINDOW_HEIGHT, rect->height);
} else { } else {
if (!ret) if (!ret)
ret = reg_write(REDUCER_XZOOM_B, MT9M111_MAX_WIDTH); ret = mt9m111_setup_rect_ctx(mt9m111, rect, &context_b);
if (!ret)
ret = reg_write(REDUCER_YZOOM_B, MT9M111_MAX_HEIGHT);
if (!ret)
ret = reg_write(REDUCER_XSIZE_B, width);
if (!ret) if (!ret)
ret = reg_write(REDUCER_YSIZE_B, height); ret = mt9m111_setup_rect_ctx(mt9m111, rect, &context_a);
if (!ret)
ret = reg_write(REDUCER_XZOOM_A, MT9M111_MAX_WIDTH);
if (!ret)
ret = reg_write(REDUCER_YZOOM_A, MT9M111_MAX_HEIGHT);
if (!ret)
ret = reg_write(REDUCER_XSIZE_A, width);
if (!ret)
ret = reg_write(REDUCER_YSIZE_A, height);
} }
return ret; return ret;
...@@ -503,11 +524,11 @@ static int mt9m111_set_pixfmt(struct mt9m111 *mt9m111, ...@@ -503,11 +524,11 @@ static int mt9m111_set_pixfmt(struct mt9m111 *mt9m111,
return -EINVAL; return -EINVAL;
} }
ret = reg_mask(OUTPUT_FORMAT_CTRL2_A, data_outfmt2, ret = mt9m111_reg_mask(client, context_a.output_fmt_ctrl2,
mask_outfmt2); data_outfmt2, mask_outfmt2);
if (!ret) if (!ret)
ret = reg_mask(OUTPUT_FORMAT_CTRL2_B, data_outfmt2, ret = mt9m111_reg_mask(client, context_b.output_fmt_ctrl2,
mask_outfmt2); data_outfmt2, mask_outfmt2);
return ret; return ret;
} }
...@@ -649,17 +670,10 @@ static int mt9m111_set_flip(struct mt9m111 *mt9m111, int flip, int mask) ...@@ -649,17 +670,10 @@ static int mt9m111_set_flip(struct mt9m111 *mt9m111, int flip, int mask)
struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev); struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev);
int ret; int ret;
if (mt9m111->context == HIGHPOWER) { if (flip)
if (flip) ret = mt9m111_reg_set(client, mt9m111->ctx->read_mode, mask);
ret = reg_set(READ_MODE_B, mask); else
else ret = mt9m111_reg_clear(client, mt9m111->ctx->read_mode, mask);
ret = reg_clear(READ_MODE_B, mask);
} else {
if (flip)
ret = reg_set(READ_MODE_A, mask);
else
ret = reg_clear(READ_MODE_A, mask);
}
return ret; return ret;
} }
...@@ -744,7 +758,7 @@ static int mt9m111_suspend(struct mt9m111 *mt9m111) ...@@ -744,7 +758,7 @@ static int mt9m111_suspend(struct mt9m111 *mt9m111)
static void mt9m111_restore_state(struct mt9m111 *mt9m111) static void mt9m111_restore_state(struct mt9m111 *mt9m111)
{ {
mt9m111_set_context(mt9m111, mt9m111->context); mt9m111_set_context(mt9m111, mt9m111->ctx);
mt9m111_set_pixfmt(mt9m111, mt9m111->fmt->code); mt9m111_set_pixfmt(mt9m111, mt9m111->fmt->code);
mt9m111_setup_rect(mt9m111, &mt9m111->rect); mt9m111_setup_rect(mt9m111, &mt9m111->rect);
v4l2_ctrl_handler_setup(&mt9m111->hdl); v4l2_ctrl_handler_setup(&mt9m111->hdl);
...@@ -769,12 +783,13 @@ static int mt9m111_init(struct mt9m111 *mt9m111) ...@@ -769,12 +783,13 @@ static int mt9m111_init(struct mt9m111 *mt9m111)
struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev); struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev);
int ret; int ret;
mt9m111->context = HIGHPOWER; /* Default HIGHPOWER context */
mt9m111->ctx = &context_b;
ret = mt9m111_enable(mt9m111); ret = mt9m111_enable(mt9m111);
if (!ret) if (!ret)
ret = mt9m111_reset(mt9m111); ret = mt9m111_reset(mt9m111);
if (!ret) if (!ret)
ret = mt9m111_set_context(mt9m111, mt9m111->context); ret = mt9m111_set_context(mt9m111, mt9m111->ctx);
if (ret) if (ret)
dev_err(&client->dev, "mt9m111 init failed: %d\n", ret); dev_err(&client->dev, "mt9m111 init failed: %d\n", ret);
return ret; return ret;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment