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

V4L/DVB (12536): soc-camera: remove .gain and .exposure struct soc_camera_device members

This makes the soc-camera interface for V4L2 subdevices thinner yet. Handle
gain and exposure internally in each driver just like all other controls.
Signed-off-by: default avatarGuennadi Liakhovetski <g.liakhovetski@gmx.de>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent a4c56fd8
...@@ -80,6 +80,8 @@ struct mt9m001 { ...@@ -80,6 +80,8 @@ struct mt9m001 {
struct v4l2_rect rect; /* Sensor window */ struct v4l2_rect rect; /* Sensor window */
__u32 fourcc; __u32 fourcc;
int model; /* V4L2_IDENT_MT9M001* codes from v4l2-chip-ident.h */ int model; /* V4L2_IDENT_MT9M001* codes from v4l2-chip-ident.h */
unsigned int gain;
unsigned int exposure;
unsigned char autoexposure; unsigned char autoexposure;
}; };
...@@ -129,8 +131,8 @@ static int mt9m001_init(struct i2c_client *client) ...@@ -129,8 +131,8 @@ static int mt9m001_init(struct i2c_client *client)
dev_dbg(&client->dev, "%s\n", __func__); dev_dbg(&client->dev, "%s\n", __func__);
/* /*
* We don't know, whether platform provides reset, * We don't know, whether platform provides reset, issue a soft reset
* issue a soft reset too * too. This returns all registers to their default values.
*/ */
ret = reg_write(client, MT9M001_RESET, 1); ret = reg_write(client, MT9M001_RESET, 1);
if (!ret) if (!ret)
...@@ -200,6 +202,7 @@ static int mt9m001_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) ...@@ -200,6 +202,7 @@ static int mt9m001_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
struct soc_camera_device *icd = client->dev.platform_data; struct soc_camera_device *icd = client->dev.platform_data;
int ret; int ret;
const u16 hblank = 9, vblank = 25; const u16 hblank = 9, vblank = 25;
unsigned int total_h;
if (mt9m001->fourcc == V4L2_PIX_FMT_SBGGR8 || if (mt9m001->fourcc == V4L2_PIX_FMT_SBGGR8 ||
mt9m001->fourcc == V4L2_PIX_FMT_SBGGR16) mt9m001->fourcc == V4L2_PIX_FMT_SBGGR16)
...@@ -219,6 +222,8 @@ static int mt9m001_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) ...@@ -219,6 +222,8 @@ static int mt9m001_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
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);
total_h = rect.height + icd->y_skip_top + vblank;
/* Blanking and start values - default... */ /* Blanking and start values - default... */
ret = reg_write(client, MT9M001_HORIZONTAL_BLANKING, hblank); ret = reg_write(client, MT9M001_HORIZONTAL_BLANKING, hblank);
if (!ret) if (!ret)
...@@ -236,15 +241,13 @@ static int mt9m001_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) ...@@ -236,15 +241,13 @@ static int mt9m001_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
ret = reg_write(client, MT9M001_WINDOW_HEIGHT, ret = reg_write(client, MT9M001_WINDOW_HEIGHT,
rect.height + icd->y_skip_top - 1); rect.height + icd->y_skip_top - 1);
if (!ret && mt9m001->autoexposure) { if (!ret && mt9m001->autoexposure) {
ret = reg_write(client, MT9M001_SHUTTER_WIDTH, ret = reg_write(client, MT9M001_SHUTTER_WIDTH, total_h);
rect.height + icd->y_skip_top + vblank);
if (!ret) { if (!ret) {
const struct v4l2_queryctrl *qctrl = const struct v4l2_queryctrl *qctrl =
soc_camera_find_qctrl(icd->ops, soc_camera_find_qctrl(icd->ops,
V4L2_CID_EXPOSURE); V4L2_CID_EXPOSURE);
icd->exposure = (524 + (rect.height + icd->y_skip_top + mt9m001->exposure = (524 + (total_h - 1) *
vblank - 1) * (qctrl->maximum - qctrl->minimum)) /
(qctrl->maximum - qctrl->minimum)) /
1048 + qctrl->minimum; 1048 + qctrl->minimum;
} }
} }
...@@ -457,6 +460,12 @@ static int mt9m001_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) ...@@ -457,6 +460,12 @@ static int mt9m001_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
case V4L2_CID_EXPOSURE_AUTO: case V4L2_CID_EXPOSURE_AUTO:
ctrl->value = mt9m001->autoexposure; ctrl->value = mt9m001->autoexposure;
break; break;
case V4L2_CID_GAIN:
ctrl->value = mt9m001->gain;
break;
case V4L2_CID_EXPOSURE:
ctrl->value = mt9m001->exposure;
break;
} }
return 0; return 0;
} }
...@@ -518,7 +527,7 @@ static int mt9m001_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) ...@@ -518,7 +527,7 @@ static int mt9m001_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
} }
/* Success */ /* Success */
icd->gain = ctrl->value; mt9m001->gain = ctrl->value;
break; break;
case V4L2_CID_EXPOSURE: case V4L2_CID_EXPOSURE:
/* mt9m001 has maximum == default */ /* mt9m001 has maximum == default */
...@@ -535,21 +544,21 @@ static int mt9m001_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) ...@@ -535,21 +544,21 @@ static int mt9m001_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
shutter); shutter);
if (reg_write(client, MT9M001_SHUTTER_WIDTH, shutter) < 0) if (reg_write(client, MT9M001_SHUTTER_WIDTH, shutter) < 0)
return -EIO; return -EIO;
icd->exposure = ctrl->value; mt9m001->exposure = ctrl->value;
mt9m001->autoexposure = 0; mt9m001->autoexposure = 0;
} }
break; break;
case V4L2_CID_EXPOSURE_AUTO: case V4L2_CID_EXPOSURE_AUTO:
if (ctrl->value) { if (ctrl->value) {
const u16 vblank = 25; const u16 vblank = 25;
unsigned int total_h = mt9m001->rect.height +
icd->y_skip_top + vblank;
if (reg_write(client, MT9M001_SHUTTER_WIDTH, if (reg_write(client, MT9M001_SHUTTER_WIDTH,
mt9m001->rect.height + total_h) < 0)
icd->y_skip_top + vblank) < 0)
return -EIO; return -EIO;
qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_EXPOSURE); qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_EXPOSURE);
icd->exposure = (524 + (mt9m001->rect.height + mt9m001->exposure = (524 + (total_h - 1) *
icd->y_skip_top + vblank - 1) * (qctrl->maximum - qctrl->minimum)) /
(qctrl->maximum - qctrl->minimum)) /
1048 + qctrl->minimum; 1048 + qctrl->minimum;
mt9m001->autoexposure = 1; mt9m001->autoexposure = 1;
} else } else
...@@ -629,6 +638,10 @@ static int mt9m001_video_probe(struct soc_camera_device *icd, ...@@ -629,6 +638,10 @@ static int mt9m001_video_probe(struct soc_camera_device *icd,
if (ret < 0) if (ret < 0)
dev_err(&client->dev, "Failed to initialise the camera\n"); dev_err(&client->dev, "Failed to initialise the camera\n");
/* mt9m001_init() has reset the chip, returning registers to defaults */
mt9m001->gain = 64;
mt9m001->exposure = 255;
return ret; return ret;
} }
...@@ -701,7 +714,7 @@ static int mt9m001_probe(struct i2c_client *client, ...@@ -701,7 +714,7 @@ static int mt9m001_probe(struct i2c_client *client,
/* Second stage probe - when a capture adapter is there */ /* Second stage probe - when a capture adapter is there */
icd->ops = &mt9m001_ops; icd->ops = &mt9m001_ops;
icd->y_skip_top = 1; icd->y_skip_top = 0;
mt9m001->rect.left = MT9M001_COLUMN_SKIP; mt9m001->rect.left = MT9M001_COLUMN_SKIP;
mt9m001->rect.top = MT9M001_ROW_SKIP; mt9m001->rect.top = MT9M001_ROW_SKIP;
......
...@@ -153,6 +153,7 @@ struct mt9m111 { ...@@ -153,6 +153,7 @@ struct mt9m111 {
enum mt9m111_context context; enum mt9m111_context context;
struct v4l2_rect rect; struct v4l2_rect rect;
u32 pixfmt; u32 pixfmt;
unsigned int gain;
unsigned char autoexposure; unsigned char autoexposure;
unsigned char datawidth; unsigned char datawidth;
unsigned int powered:1; unsigned int powered:1;
...@@ -513,7 +514,8 @@ static int mt9m111_set_pixfmt(struct i2c_client *client, u32 pixfmt) ...@@ -513,7 +514,8 @@ static int mt9m111_set_pixfmt(struct i2c_client *client, u32 pixfmt)
ret = mt9m111_setfmt_yuv(client); ret = mt9m111_setfmt_yuv(client);
break; break;
default: default:
dev_err(&client->dev, "Pixel format not handled : %x\n", pixfmt); dev_err(&client->dev, "Pixel format not handled : %x\n",
pixfmt);
ret = -EINVAL; ret = -EINVAL;
} }
...@@ -536,9 +538,9 @@ static int mt9m111_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) ...@@ -536,9 +538,9 @@ static int mt9m111_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f)
}; };
int ret; int ret;
dev_dbg(&client->dev, "%s fmt=%x left=%d, top=%d, width=%d, height=%d\n", dev_dbg(&client->dev,
__func__, pix->pixelformat, rect.left, rect.top, rect.width, "%s fmt=%x left=%d, top=%d, width=%d, height=%d\n", __func__,
rect.height); pix->pixelformat, rect.left, rect.top, rect.width, rect.height);
ret = mt9m111_make_rect(client, &rect); ret = mt9m111_make_rect(client, &rect);
if (!ret) if (!ret)
...@@ -672,8 +674,10 @@ static const struct v4l2_queryctrl mt9m111_controls[] = { ...@@ -672,8 +674,10 @@ static const struct v4l2_queryctrl mt9m111_controls[] = {
}; };
static int mt9m111_resume(struct soc_camera_device *icd); static int mt9m111_resume(struct soc_camera_device *icd);
static int mt9m111_suspend(struct soc_camera_device *icd, pm_message_t state);
static struct soc_camera_ops mt9m111_ops = { static struct soc_camera_ops mt9m111_ops = {
.suspend = mt9m111_suspend,
.resume = mt9m111_resume, .resume = mt9m111_resume,
.query_bus_param = mt9m111_query_bus_param, .query_bus_param = mt9m111_query_bus_param,
.set_bus_param = mt9m111_set_bus_param, .set_bus_param = mt9m111_set_bus_param,
...@@ -714,13 +718,13 @@ static int mt9m111_get_global_gain(struct i2c_client *client) ...@@ -714,13 +718,13 @@ static int mt9m111_get_global_gain(struct i2c_client *client)
static int mt9m111_set_global_gain(struct i2c_client *client, int gain) static int mt9m111_set_global_gain(struct i2c_client *client, int gain)
{ {
struct soc_camera_device *icd = client->dev.platform_data; struct mt9m111 *mt9m111 = to_mt9m111(client);
u16 val; u16 val;
if (gain > 63 * 2 * 2) if (gain > 63 * 2 * 2)
return -EINVAL; return -EINVAL;
icd->gain = gain; mt9m111->gain = gain;
if ((gain >= 64 * 2) && (gain < 63 * 2 * 2)) if ((gain >= 64 * 2) && (gain < 63 * 2 * 2))
val = (1 << 10) | (1 << 9) | (gain / 4); val = (1 << 10) | (1 << 9) | (gain / 4);
else if ((gain >= 64) && (gain < 64 * 2)) else if ((gain >= 64) && (gain < 64 * 2))
...@@ -844,17 +848,26 @@ static int mt9m111_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) ...@@ -844,17 +848,26 @@ static int mt9m111_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
return ret; return ret;
} }
static int mt9m111_suspend(struct soc_camera_device *icd, pm_message_t state)
{
struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
struct mt9m111 *mt9m111 = to_mt9m111(client);
mt9m111->gain = mt9m111_get_global_gain(client);
return 0;
}
static int mt9m111_restore_state(struct i2c_client *client) static int mt9m111_restore_state(struct i2c_client *client)
{ {
struct mt9m111 *mt9m111 = to_mt9m111(client); struct mt9m111 *mt9m111 = to_mt9m111(client);
struct soc_camera_device *icd = client->dev.platform_data;
mt9m111_set_context(client, mt9m111->context); mt9m111_set_context(client, mt9m111->context);
mt9m111_set_pixfmt(client, mt9m111->pixfmt); mt9m111_set_pixfmt(client, mt9m111->pixfmt);
mt9m111_setup_rect(client, &mt9m111->rect); mt9m111_setup_rect(client, &mt9m111->rect);
mt9m111_set_flip(client, mt9m111->hflip, MT9M111_RMB_MIRROR_COLS); mt9m111_set_flip(client, mt9m111->hflip, MT9M111_RMB_MIRROR_COLS);
mt9m111_set_flip(client, mt9m111->vflip, MT9M111_RMB_MIRROR_ROWS); mt9m111_set_flip(client, mt9m111->vflip, MT9M111_RMB_MIRROR_ROWS);
mt9m111_set_global_gain(client, icd->gain); mt9m111_set_global_gain(client, mt9m111->gain);
mt9m111_set_autoexposure(client, mt9m111->autoexposure); mt9m111_set_autoexposure(client, mt9m111->autoexposure);
mt9m111_set_autowhitebalance(client, mt9m111->autowhitebalance); mt9m111_set_autowhitebalance(client, mt9m111->autowhitebalance);
return 0; return 0;
......
...@@ -73,6 +73,8 @@ struct mt9t031 { ...@@ -73,6 +73,8 @@ struct mt9t031 {
int model; /* V4L2_IDENT_MT9T031* codes from v4l2-chip-ident.h */ int model; /* V4L2_IDENT_MT9T031* codes from v4l2-chip-ident.h */
u16 xskip; u16 xskip;
u16 yskip; u16 yskip;
unsigned int gain;
unsigned int exposure;
unsigned char autoexposure; unsigned char autoexposure;
}; };
...@@ -301,16 +303,15 @@ static int mt9t031_set_params(struct soc_camera_device *icd, ...@@ -301,16 +303,15 @@ static int mt9t031_set_params(struct soc_camera_device *icd,
ret = reg_write(client, MT9T031_WINDOW_HEIGHT, ret = reg_write(client, MT9T031_WINDOW_HEIGHT,
rect->height + icd->y_skip_top - 1); rect->height + icd->y_skip_top - 1);
if (ret >= 0 && mt9t031->autoexposure) { if (ret >= 0 && mt9t031->autoexposure) {
ret = set_shutter(client, unsigned int total_h = rect->height + icd->y_skip_top + vblank;
rect->height + icd->y_skip_top + vblank); ret = set_shutter(client, total_h);
if (ret >= 0) { if (ret >= 0) {
const u32 shutter_max = MT9T031_MAX_HEIGHT + vblank; const u32 shutter_max = MT9T031_MAX_HEIGHT + vblank;
const struct v4l2_queryctrl *qctrl = const struct v4l2_queryctrl *qctrl =
soc_camera_find_qctrl(icd->ops, soc_camera_find_qctrl(icd->ops,
V4L2_CID_EXPOSURE); V4L2_CID_EXPOSURE);
icd->exposure = (shutter_max / 2 + (rect->height + mt9t031->exposure = (shutter_max / 2 + (total_h - 1) *
icd->y_skip_top + vblank - 1) * (qctrl->maximum - qctrl->minimum)) /
(qctrl->maximum - qctrl->minimum)) /
shutter_max + qctrl->minimum; shutter_max + qctrl->minimum;
} }
} }
...@@ -553,6 +554,12 @@ static int mt9t031_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) ...@@ -553,6 +554,12 @@ static int mt9t031_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
case V4L2_CID_EXPOSURE_AUTO: case V4L2_CID_EXPOSURE_AUTO:
ctrl->value = mt9t031->autoexposure; ctrl->value = mt9t031->autoexposure;
break; break;
case V4L2_CID_GAIN:
ctrl->value = mt9t031->gain;
break;
case V4L2_CID_EXPOSURE:
ctrl->value = mt9t031->exposure;
break;
} }
return 0; return 0;
} }
...@@ -624,7 +631,7 @@ static int mt9t031_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) ...@@ -624,7 +631,7 @@ static int mt9t031_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
} }
/* Success */ /* Success */
icd->gain = ctrl->value; mt9t031->gain = ctrl->value;
break; break;
case V4L2_CID_EXPOSURE: case V4L2_CID_EXPOSURE:
/* mt9t031 has maximum == default */ /* mt9t031 has maximum == default */
...@@ -641,7 +648,7 @@ static int mt9t031_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) ...@@ -641,7 +648,7 @@ static int mt9t031_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
old, shutter); old, shutter);
if (set_shutter(client, shutter) < 0) if (set_shutter(client, shutter) < 0)
return -EIO; return -EIO;
icd->exposure = ctrl->value; mt9t031->exposure = ctrl->value;
mt9t031->autoexposure = 0; mt9t031->autoexposure = 0;
} }
break; break;
...@@ -649,14 +656,14 @@ static int mt9t031_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) ...@@ -649,14 +656,14 @@ static int mt9t031_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
if (ctrl->value) { if (ctrl->value) {
const u16 vblank = MT9T031_VERTICAL_BLANK; const u16 vblank = MT9T031_VERTICAL_BLANK;
const u32 shutter_max = MT9T031_MAX_HEIGHT + vblank; const u32 shutter_max = MT9T031_MAX_HEIGHT + vblank;
if (set_shutter(client, mt9t031->rect.height + unsigned int total_h = mt9t031->rect.height +
icd->y_skip_top + vblank) < 0) icd->y_skip_top + vblank;
if (set_shutter(client, total_h) < 0)
return -EIO; return -EIO;
qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_EXPOSURE); qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_EXPOSURE);
icd->exposure = (shutter_max / 2 + mt9t031->exposure = (shutter_max / 2 + (total_h - 1) *
(mt9t031->rect.height + (qctrl->maximum - qctrl->minimum)) /
icd->y_skip_top + vblank - 1) *
(qctrl->maximum - qctrl->minimum)) /
shutter_max + qctrl->minimum; shutter_max + qctrl->minimum;
mt9t031->autoexposure = 1; mt9t031->autoexposure = 1;
} else } else
...@@ -700,6 +707,10 @@ static int mt9t031_video_probe(struct i2c_client *client) ...@@ -700,6 +707,10 @@ static int mt9t031_video_probe(struct i2c_client *client)
if (ret < 0) if (ret < 0)
dev_err(&client->dev, "Failed to initialise the camera\n"); dev_err(&client->dev, "Failed to initialise the camera\n");
/* mt9t031_idle() has reset the chip to default. */
mt9t031->exposure = 255;
mt9t031->gain = 64;
return ret; return ret;
} }
......
...@@ -45,7 +45,7 @@ MODULE_PARM_DESC(sensor_type, "Sensor type: \"colour\" or \"monochrome\""); ...@@ -45,7 +45,7 @@ MODULE_PARM_DESC(sensor_type, "Sensor type: \"colour\" or \"monochrome\"");
#define MT9V022_PIXEL_OPERATION_MODE 0x0f #define MT9V022_PIXEL_OPERATION_MODE 0x0f
#define MT9V022_LED_OUT_CONTROL 0x1b #define MT9V022_LED_OUT_CONTROL 0x1b
#define MT9V022_ADC_MODE_CONTROL 0x1c #define MT9V022_ADC_MODE_CONTROL 0x1c
#define MT9V022_ANALOG_GAIN 0x34 #define MT9V022_ANALOG_GAIN 0x35
#define MT9V022_BLACK_LEVEL_CALIB_CTRL 0x47 #define MT9V022_BLACK_LEVEL_CALIB_CTRL 0x47
#define MT9V022_PIXCLK_FV_LV 0x74 #define MT9V022_PIXCLK_FV_LV 0x74
#define MT9V022_DIGITAL_TEST_PATTERN 0x7f #define MT9V022_DIGITAL_TEST_PATTERN 0x7f
...@@ -155,6 +155,10 @@ static int mt9v022_init(struct i2c_client *client) ...@@ -155,6 +155,10 @@ static int mt9v022_init(struct i2c_client *client)
if (!ret) if (!ret)
/* AEC, AGC on */ /* AEC, AGC on */
ret = reg_set(client, MT9V022_AEC_AGC_ENABLE, 0x3); ret = reg_set(client, MT9V022_AEC_AGC_ENABLE, 0x3);
if (!ret)
ret = reg_write(client, MT9V022_ANALOG_GAIN, 16);
if (!ret)
ret = reg_write(client, MT9V022_TOTAL_SHUTTER_WIDTH, 480);
if (!ret) if (!ret)
ret = reg_write(client, MT9V022_MAX_TOTAL_SHUTTER_WIDTH, 480); ret = reg_write(client, MT9V022_MAX_TOTAL_SHUTTER_WIDTH, 480);
if (!ret) if (!ret)
...@@ -540,8 +544,12 @@ static struct soc_camera_ops mt9v022_ops = { ...@@ -540,8 +544,12 @@ static struct soc_camera_ops mt9v022_ops = {
static int mt9v022_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) static int mt9v022_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
{ {
struct i2c_client *client = sd->priv; struct i2c_client *client = sd->priv;
const struct v4l2_queryctrl *qctrl;
unsigned long range;
int data; int data;
qctrl = soc_camera_find_qctrl(&mt9v022_ops, ctrl->id);
switch (ctrl->id) { switch (ctrl->id) {
case V4L2_CID_VFLIP: case V4L2_CID_VFLIP:
data = reg_read(client, MT9V022_READ_MODE); data = reg_read(client, MT9V022_READ_MODE);
...@@ -566,6 +574,24 @@ static int mt9v022_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) ...@@ -566,6 +574,24 @@ static int mt9v022_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
if (data < 0) if (data < 0)
return -EIO; return -EIO;
ctrl->value = !!(data & 0x2); ctrl->value = !!(data & 0x2);
break;
case V4L2_CID_GAIN:
data = reg_read(client, MT9V022_ANALOG_GAIN);
if (data < 0)
return -EIO;
range = qctrl->maximum - qctrl->minimum;
ctrl->value = ((data - 16) * range + 24) / 48 + qctrl->minimum;
break;
case V4L2_CID_EXPOSURE:
data = reg_read(client, MT9V022_TOTAL_SHUTTER_WIDTH);
if (data < 0)
return -EIO;
range = qctrl->maximum - qctrl->minimum;
ctrl->value = ((data - 1) * range + 239) / 479 + qctrl->minimum;
break; break;
} }
return 0; return 0;
...@@ -575,7 +601,6 @@ static int mt9v022_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) ...@@ -575,7 +601,6 @@ static int mt9v022_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
{ {
int data; int data;
struct i2c_client *client = sd->priv; struct i2c_client *client = sd->priv;
struct soc_camera_device *icd = client->dev.platform_data;
const struct v4l2_queryctrl *qctrl; const struct v4l2_queryctrl *qctrl;
qctrl = soc_camera_find_qctrl(&mt9v022_ops, ctrl->id); qctrl = soc_camera_find_qctrl(&mt9v022_ops, ctrl->id);
...@@ -605,12 +630,9 @@ static int mt9v022_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) ...@@ -605,12 +630,9 @@ static int mt9v022_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
return -EINVAL; return -EINVAL;
else { else {
unsigned long range = qctrl->maximum - qctrl->minimum; unsigned long range = qctrl->maximum - qctrl->minimum;
/* Datasheet says 16 to 64. autogain only works properly /* Valid values 16 to 64, 32 to 64 must be even. */
* after setting gain to maximum 14. Larger values
* produce "white fly" noise effect. On the whole,
* manually setting analog gain does no good. */
unsigned long gain = ((ctrl->value - qctrl->minimum) * unsigned long gain = ((ctrl->value - qctrl->minimum) *
10 + range / 2) / range + 4; 48 + range / 2) / range + 16;
if (gain >= 32) if (gain >= 32)
gain &= ~1; gain &= ~1;
/* The user wants to set gain manually, hope, she /* The user wants to set gain manually, hope, she
...@@ -619,11 +641,10 @@ static int mt9v022_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) ...@@ -619,11 +641,10 @@ static int mt9v022_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
if (reg_clear(client, MT9V022_AEC_AGC_ENABLE, 0x2) < 0) if (reg_clear(client, MT9V022_AEC_AGC_ENABLE, 0x2) < 0)
return -EIO; return -EIO;
dev_info(&client->dev, "Setting gain from %d to %lu\n", dev_dbg(&client->dev, "Setting gain from %d to %lu\n",
reg_read(client, MT9V022_ANALOG_GAIN), gain); reg_read(client, MT9V022_ANALOG_GAIN), gain);
if (reg_write(client, MT9V022_ANALOG_GAIN, gain) < 0) if (reg_write(client, MT9V022_ANALOG_GAIN, gain) < 0)
return -EIO; return -EIO;
icd->gain = ctrl->value;
} }
break; break;
case V4L2_CID_EXPOSURE: case V4L2_CID_EXPOSURE:
...@@ -646,7 +667,6 @@ static int mt9v022_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) ...@@ -646,7 +667,6 @@ static int mt9v022_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
if (reg_write(client, MT9V022_TOTAL_SHUTTER_WIDTH, if (reg_write(client, MT9V022_TOTAL_SHUTTER_WIDTH,
shutter) < 0) shutter) < 0)
return -EIO; return -EIO;
icd->exposure = ctrl->value;
} }
break; break;
case V4L2_CID_AUTOGAIN: case V4L2_CID_AUTOGAIN:
...@@ -827,6 +847,10 @@ static int mt9v022_probe(struct i2c_client *client, ...@@ -827,6 +847,10 @@ static int mt9v022_probe(struct i2c_client *client,
mt9v022->chip_control = MT9V022_CHIP_CONTROL_DEFAULT; mt9v022->chip_control = MT9V022_CHIP_CONTROL_DEFAULT;
icd->ops = &mt9v022_ops; icd->ops = &mt9v022_ops;
/*
* MT9V022 _really_ corrupts the first read out line.
* TODO: verify on i.MX31
*/
icd->y_skip_top = 1; icd->y_skip_top = 1;
mt9v022->rect.left = MT9V022_COLUMN_SKIP; mt9v022->rect.left = MT9V022_COLUMN_SKIP;
......
...@@ -548,7 +548,8 @@ static int mx1_camera_set_fmt(struct soc_camera_device *icd, ...@@ -548,7 +548,8 @@ static int mx1_camera_set_fmt(struct soc_camera_device *icd,
xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat); xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat);
if (!xlate) { if (!xlate) {
dev_warn(icd->dev.parent, "Format %x not found\n", pix->pixelformat); dev_warn(icd->dev.parent, "Format %x not found\n",
pix->pixelformat);
return -EINVAL; return -EINVAL;
} }
......
...@@ -404,7 +404,8 @@ struct ov772x_priv { ...@@ -404,7 +404,8 @@ struct ov772x_priv {
int model; int model;
unsigned short flag_vflip:1; unsigned short flag_vflip:1;
unsigned short flag_hflip:1; unsigned short flag_hflip:1;
unsigned short band_filter; /* 256 - BDBASE, 0 if (!COM8[5]) */ /* band_filter = COM8[5] ? 256 - BDBASE : 0 */
unsigned short band_filter;
}; };
#define ENDMARKER { 0xff, 0xff } #define ENDMARKER { 0xff, 0xff }
...@@ -587,7 +588,8 @@ static const struct v4l2_queryctrl ov772x_controls[] = { ...@@ -587,7 +588,8 @@ static const struct v4l2_queryctrl ov772x_controls[] = {
static struct ov772x_priv *to_ov772x(const struct i2c_client *client) static struct ov772x_priv *to_ov772x(const struct i2c_client *client)
{ {
return container_of(i2c_get_clientdata(client), struct ov772x_priv, subdev); return container_of(i2c_get_clientdata(client), struct ov772x_priv,
subdev);
} }
static int ov772x_write_array(struct i2c_client *client, static int ov772x_write_array(struct i2c_client *client,
......
...@@ -274,7 +274,8 @@ static void free_buffer(struct videobuf_queue *vq, struct pxa_buffer *buf) ...@@ -274,7 +274,8 @@ static void free_buffer(struct videobuf_queue *vq, struct pxa_buffer *buf)
for (i = 0; i < ARRAY_SIZE(buf->dmas); i++) { for (i = 0; i < ARRAY_SIZE(buf->dmas); i++) {
if (buf->dmas[i].sg_cpu) if (buf->dmas[i].sg_cpu)
dma_free_coherent(ici->v4l2_dev.dev, buf->dmas[i].sg_size, dma_free_coherent(ici->v4l2_dev.dev,
buf->dmas[i].sg_size,
buf->dmas[i].sg_cpu, buf->dmas[i].sg_cpu,
buf->dmas[i].sg_dma); buf->dmas[i].sg_dma);
buf->dmas[i].sg_cpu = NULL; buf->dmas[i].sg_cpu = NULL;
......
...@@ -327,7 +327,9 @@ static int soc_camera_set_fmt(struct soc_camera_file *icf, ...@@ -327,7 +327,9 @@ static int soc_camera_set_fmt(struct soc_camera_file *icf,
static int soc_camera_open(struct file *file) static int soc_camera_open(struct file *file)
{ {
struct video_device *vdev = video_devdata(file); struct video_device *vdev = video_devdata(file);
struct soc_camera_device *icd = container_of(vdev->parent, struct soc_camera_device, dev); struct soc_camera_device *icd = container_of(vdev->parent,
struct soc_camera_device,
dev);
struct soc_camera_link *icl = to_soc_camera_link(icd); struct soc_camera_link *icl = to_soc_camera_link(icd);
struct soc_camera_host *ici; struct soc_camera_host *ici;
struct soc_camera_file *icf; struct soc_camera_file *icf;
...@@ -349,7 +351,10 @@ static int soc_camera_open(struct file *file) ...@@ -349,7 +351,10 @@ static int soc_camera_open(struct file *file)
goto emgi; goto emgi;
} }
/* Protect against icd->ops->remove() until we module_get() both drivers. */ /*
* Protect against icd->ops->remove() until we module_get() both
* drivers.
*/
mutex_lock(&icd->video_lock); mutex_lock(&icd->video_lock);
icf->icd = icd; icf->icd = icd;
...@@ -670,19 +675,6 @@ static int soc_camera_g_ctrl(struct file *file, void *priv, ...@@ -670,19 +675,6 @@ static int soc_camera_g_ctrl(struct file *file, void *priv,
WARN_ON(priv != file->private_data); WARN_ON(priv != file->private_data);
switch (ctrl->id) {
case V4L2_CID_GAIN:
if (icd->gain == (unsigned short)~0)
return -EINVAL;
ctrl->value = icd->gain;
return 0;
case V4L2_CID_EXPOSURE:
if (icd->exposure == (unsigned short)~0)
return -EINVAL;
ctrl->value = icd->exposure;
return 0;
}
if (ici->ops->get_ctrl) { if (ici->ops->get_ctrl) {
ret = ici->ops->get_ctrl(icd, ctrl); ret = ici->ops->get_ctrl(icd, ctrl);
if (ret != -ENOIOCTLCMD) if (ret != -ENOIOCTLCMD)
...@@ -944,7 +936,10 @@ static int soc_camera_probe(struct device *dev) ...@@ -944,7 +936,10 @@ static int soc_camera_probe(struct device *dev)
if (ret < 0) if (ret < 0)
goto eadddev; goto eadddev;
/* FIXME: this is racy, have to use driver-binding notification */ /*
* FIXME: this is racy, have to use driver-binding notification,
* when it is available
*/
control = to_soc_camera_control(icd); control = to_soc_camera_control(icd);
if (!control || !control->driver || !dev_get_drvdata(control) || if (!control || !control->driver || !dev_get_drvdata(control) ||
!try_module_get(control->driver->owner)) { !try_module_get(control->driver->owner)) {
...@@ -1279,7 +1274,6 @@ static int video_dev_create(struct soc_camera_device *icd) ...@@ -1279,7 +1274,6 @@ static int video_dev_create(struct soc_camera_device *icd)
*/ */
static int soc_camera_video_start(struct soc_camera_device *icd) static int soc_camera_video_start(struct soc_camera_device *icd)
{ {
const struct v4l2_queryctrl *qctrl;
int ret; int ret;
if (!icd->dev.parent) if (!icd->dev.parent)
...@@ -1297,11 +1291,6 @@ static int soc_camera_video_start(struct soc_camera_device *icd) ...@@ -1297,11 +1291,6 @@ static int soc_camera_video_start(struct soc_camera_device *icd)
return ret; return ret;
} }
qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_GAIN);
icd->gain = qctrl ? qctrl->default_value : (unsigned short)~0;
qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_EXPOSURE);
icd->exposure = qctrl ? qctrl->default_value : (unsigned short)~0;
return 0; return 0;
} }
......
...@@ -33,7 +33,8 @@ static struct soc_camera_platform_priv *get_priv(struct platform_device *pdev) ...@@ -33,7 +33,8 @@ static struct soc_camera_platform_priv *get_priv(struct platform_device *pdev)
static struct soc_camera_platform_info *get_info(struct soc_camera_device *icd) static struct soc_camera_platform_info *get_info(struct soc_camera_device *icd)
{ {
struct platform_device *pdev = to_platform_device(to_soc_camera_control(icd)); struct platform_device *pdev =
to_platform_device(to_soc_camera_control(icd));
return pdev->dev.platform_data; return pdev->dev.platform_data;
} }
......
...@@ -357,7 +357,8 @@ static const struct tw9910_hsync_ctrl tw9910_hsync_ctrl = { ...@@ -357,7 +357,8 @@ static const struct tw9910_hsync_ctrl tw9910_hsync_ctrl = {
*/ */
static struct tw9910_priv *to_tw9910(const struct i2c_client *client) static struct tw9910_priv *to_tw9910(const struct i2c_client *client)
{ {
return container_of(i2c_get_clientdata(client), struct tw9910_priv, subdev); return container_of(i2c_get_clientdata(client), struct tw9910_priv,
subdev);
} }
static int tw9910_set_scale(struct i2c_client *client, static int tw9910_set_scale(struct i2c_client *client,
......
...@@ -27,8 +27,6 @@ struct soc_camera_device { ...@@ -27,8 +27,6 @@ struct soc_camera_device {
unsigned short width_min; unsigned short width_min;
unsigned short height_min; unsigned short height_min;
unsigned short y_skip_top; /* Lines to skip at the top */ unsigned short y_skip_top; /* Lines to skip at the top */
unsigned short gain;
unsigned short exposure;
unsigned char iface; /* Host number */ unsigned char iface; /* Host number */
unsigned char devnum; /* Device number per host */ unsigned char devnum; /* Device number per host */
unsigned char buswidth; /* See comment in .c */ unsigned char buswidth; /* See comment in .c */
...@@ -128,29 +126,34 @@ struct soc_camera_link { ...@@ -128,29 +126,34 @@ struct soc_camera_link {
void (*free_bus)(struct soc_camera_link *); void (*free_bus)(struct soc_camera_link *);
}; };
static inline struct soc_camera_device *to_soc_camera_dev(const struct device *dev) static inline struct soc_camera_device *to_soc_camera_dev(
const struct device *dev)
{ {
return container_of(dev, struct soc_camera_device, dev); return container_of(dev, struct soc_camera_device, dev);
} }
static inline struct soc_camera_host *to_soc_camera_host(const struct device *dev) static inline struct soc_camera_host *to_soc_camera_host(
const struct device *dev)
{ {
struct v4l2_device *v4l2_dev = dev_get_drvdata(dev); struct v4l2_device *v4l2_dev = dev_get_drvdata(dev);
return container_of(v4l2_dev, struct soc_camera_host, v4l2_dev); return container_of(v4l2_dev, struct soc_camera_host, v4l2_dev);
} }
static inline struct soc_camera_link *to_soc_camera_link(const struct soc_camera_device *icd) static inline struct soc_camera_link *to_soc_camera_link(
const struct soc_camera_device *icd)
{ {
return icd->dev.platform_data; return icd->dev.platform_data;
} }
static inline struct device *to_soc_camera_control(const struct soc_camera_device *icd) static inline struct device *to_soc_camera_control(
const struct soc_camera_device *icd)
{ {
return dev_get_drvdata(&icd->dev); return dev_get_drvdata(&icd->dev);
} }
static inline struct v4l2_subdev *soc_camera_to_subdev(const struct soc_camera_device *icd) static inline struct v4l2_subdev *soc_camera_to_subdev(
const struct soc_camera_device *icd)
{ {
struct device *control = to_soc_camera_control(icd); struct device *control = to_soc_camera_control(icd);
return dev_get_drvdata(control); return dev_get_drvdata(control);
......
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