summaryrefslogtreecommitdiffstats
path: root/drivers/media/i2c/mt9v032.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-07-27 03:59:59 +0200
committerLinus Torvalds <torvalds@linux-foundation.org>2016-07-27 03:59:59 +0200
commit9c1958fc326a0a0a533ec8e86ea6fa30977207de (patch)
tree9d76e6a146c2622fad0eefbb8ff0503caefe33cc /drivers/media/i2c/mt9v032.c
parentMerge tag 'pstore-v4.8' of git://git.kernel.org/pub/scm/linux/kernel/git/kees... (diff)
parent[media] cec: always check all_device_types and features (diff)
downloadlinux-9c1958fc326a0a0a533ec8e86ea6fa30977207de.tar.xz
linux-9c1958fc326a0a0a533ec8e86ea6fa30977207de.zip
Merge tag 'media/v4.8-1' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media
Pull media updates from Mauro Carvalho Chehab: - new framework support for HDMI CEC and remote control support - new encoding codec driver for Mediatek SoC - new frontend driver: helene tuner - added support for NetUp almost universal devices, with supports DVB-C/S/S2/T/T2 and ISDB-T - the mn88472 frontend driver got promoted from staging - a new driver for RCar video input - some soc_camera legacy drivers got removed: timb, omap1, mx2, mx3 - lots of driver cleanups, improvements and fixups * tag 'media/v4.8-1' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (377 commits) [media] cec: always check all_device_types and features [media] cec: poll should check if there is room in the tx queue [media] vivid: support monitor all mode [media] cec: fix test for unconfigured adapter in main message loop [media] cec: limit the size of the transmit queue [media] cec: zero unused msg part after msg->len [media] cec: don't set fh to NULL in CEC_TRANSMIT [media] cec: clear all status fields before transmit and always fill in sequence [media] cec: CEC_RECEIVE overwrote the timeout field [media] cxd2841er: Reading SNR for DVB-C added [media] cxd2841er: Reading BER and UCB for DVB-C added [media] cxd2841er: fix switch-case for DVB-C [media] cxd2841er: fix signal strength scale for ISDB-T [media] cxd2841er: adjust the dB scale for DVB-C [media] cxd2841er: provide signal strength for DVB-C [media] cxd2841er: fix BER report via DVBv5 stats API [media] mb86a20s: apply mask to val after checking for read failure [media] airspy: fix error logic during device register [media] s5p-cec/TODO: add TODO item [media] cec/TODO: drop comment about sphinx documentation ...
Diffstat (limited to 'drivers/media/i2c/mt9v032.c')
-rw-r--r--drivers/media/i2c/mt9v032.c279
1 files changed, 210 insertions, 69 deletions
diff --git a/drivers/media/i2c/mt9v032.c b/drivers/media/i2c/mt9v032.c
index 501b37039449..58eb62f1ba21 100644
--- a/drivers/media/i2c/mt9v032.c
+++ b/drivers/media/i2c/mt9v032.c
@@ -19,7 +19,6 @@
#include <linux/log2.h>
#include <linux/mutex.h>
#include <linux/of.h>
-#include <linux/of_gpio.h>
#include <linux/regmap.h>
#include <linux/slab.h>
#include <linux/videodev2.h>
@@ -133,9 +132,16 @@
#define MT9V032_TEST_PATTERN_GRAY_DIAGONAL (3 << 11)
#define MT9V032_TEST_PATTERN_ENABLE (1 << 13)
#define MT9V032_TEST_PATTERN_FLIP (1 << 14)
+#define MT9V032_AEGC_DESIRED_BIN 0xa5
+#define MT9V032_AEC_UPDATE_FREQUENCY 0xa6
+#define MT9V032_AEC_LPF 0xa8
+#define MT9V032_AGC_UPDATE_FREQUENCY 0xa9
+#define MT9V032_AGC_LPF 0xaa
#define MT9V032_AEC_AGC_ENABLE 0xaf
#define MT9V032_AEC_ENABLE (1 << 0)
#define MT9V032_AGC_ENABLE (1 << 1)
+#define MT9V034_AEC_MAX_SHUTTER_WIDTH 0xad
+#define MT9V032_AEC_MAX_SHUTTER_WIDTH 0xbd
#define MT9V032_THERMAL_INFO 0xc1
enum mt9v032_model {
@@ -162,6 +168,8 @@ struct mt9v032_model_data {
unsigned int min_shutter;
unsigned int max_shutter;
unsigned int pclk_reg;
+ unsigned int aec_max_shutter_reg;
+ const struct v4l2_ctrl_config * const aec_max_shutter_v4l2_ctrl;
};
struct mt9v032_model_info {
@@ -175,63 +183,6 @@ static const struct mt9v032_model_version mt9v032_versions[] = {
{ MT9V034_CHIP_ID_REV1, "MT9V024/MT9V034 rev1" },
};
-static const struct mt9v032_model_data mt9v032_model_data[] = {
- {
- /* MT9V022, MT9V032 revisions 1/2/3 */
- .min_row_time = 660,
- .min_hblank = MT9V032_HORIZONTAL_BLANKING_MIN,
- .min_vblank = MT9V032_VERTICAL_BLANKING_MIN,
- .max_vblank = MT9V032_VERTICAL_BLANKING_MAX,
- .min_shutter = MT9V032_TOTAL_SHUTTER_WIDTH_MIN,
- .max_shutter = MT9V032_TOTAL_SHUTTER_WIDTH_MAX,
- .pclk_reg = MT9V032_PIXEL_CLOCK,
- }, {
- /* MT9V024, MT9V034 */
- .min_row_time = 690,
- .min_hblank = MT9V034_HORIZONTAL_BLANKING_MIN,
- .min_vblank = MT9V034_VERTICAL_BLANKING_MIN,
- .max_vblank = MT9V034_VERTICAL_BLANKING_MAX,
- .min_shutter = MT9V034_TOTAL_SHUTTER_WIDTH_MIN,
- .max_shutter = MT9V034_TOTAL_SHUTTER_WIDTH_MAX,
- .pclk_reg = MT9V034_PIXEL_CLOCK,
- },
-};
-
-static const struct mt9v032_model_info mt9v032_models[] = {
- [MT9V032_MODEL_V022_COLOR] = {
- .data = &mt9v032_model_data[0],
- .color = true,
- },
- [MT9V032_MODEL_V022_MONO] = {
- .data = &mt9v032_model_data[0],
- .color = false,
- },
- [MT9V032_MODEL_V024_COLOR] = {
- .data = &mt9v032_model_data[1],
- .color = true,
- },
- [MT9V032_MODEL_V024_MONO] = {
- .data = &mt9v032_model_data[1],
- .color = false,
- },
- [MT9V032_MODEL_V032_COLOR] = {
- .data = &mt9v032_model_data[0],
- .color = true,
- },
- [MT9V032_MODEL_V032_MONO] = {
- .data = &mt9v032_model_data[0],
- .color = false,
- },
- [MT9V032_MODEL_V034_COLOR] = {
- .data = &mt9v032_model_data[1],
- .color = true,
- },
- [MT9V032_MODEL_V034_MONO] = {
- .data = &mt9v032_model_data[1],
- .color = false,
- },
-};
-
struct mt9v032 {
struct v4l2_subdev subdev;
struct media_pad pad;
@@ -349,7 +300,8 @@ static int mt9v032_power_on(struct mt9v032 *mt9v032)
if (ret < 0)
return ret;
- return regmap_write(map, MT9V032_CHIP_CONTROL, 0);
+ return regmap_write(map, MT9V032_CHIP_CONTROL,
+ MT9V032_CHIP_CONTROL_MASTER_MODE);
}
static void mt9v032_power_off(struct mt9v032 *mt9v032)
@@ -421,8 +373,7 @@ __mt9v032_get_pad_crop(struct mt9v032 *mt9v032, struct v4l2_subdev_pad_config *c
static int mt9v032_s_stream(struct v4l2_subdev *subdev, int enable)
{
- const u16 mode = MT9V032_CHIP_CONTROL_MASTER_MODE
- | MT9V032_CHIP_CONTROL_DOUT_ENABLE
+ const u16 mode = MT9V032_CHIP_CONTROL_DOUT_ENABLE
| MT9V032_CHIP_CONTROL_SEQUENTIAL;
struct mt9v032 *mt9v032 = to_mt9v032(subdev);
struct v4l2_rect *crop = &mt9v032->crop;
@@ -647,6 +598,34 @@ static int mt9v032_set_selection(struct v4l2_subdev *subdev,
*/
#define V4L2_CID_TEST_PATTERN_COLOR (V4L2_CID_USER_BASE | 0x1001)
+/*
+ * Value between 1 and 64 to set the desired bin. This is effectively a measure
+ * of how bright the image is supposed to be. Both AGC and AEC try to reach
+ * this.
+ */
+#define V4L2_CID_AEGC_DESIRED_BIN (V4L2_CID_USER_BASE | 0x1002)
+/*
+ * LPF is the low pass filter capability of the chip. Both AEC and AGC have
+ * this setting. This limits the speed in which AGC/AEC adjust their settings.
+ * Possible values are 0-2. 0 means no LPF. For 1 and 2 this equation is used:
+ *
+ * if |(calculated new exp - current exp)| > (current exp / 4)
+ * next exp = calculated new exp
+ * else
+ * next exp = current exp + ((calculated new exp - current exp) / 2^LPF)
+ */
+#define V4L2_CID_AEC_LPF (V4L2_CID_USER_BASE | 0x1003)
+#define V4L2_CID_AGC_LPF (V4L2_CID_USER_BASE | 0x1004)
+/*
+ * Value between 0 and 15. This is the number of frames being skipped before
+ * updating the auto exposure/gain.
+ */
+#define V4L2_CID_AEC_UPDATE_INTERVAL (V4L2_CID_USER_BASE | 0x1005)
+#define V4L2_CID_AGC_UPDATE_INTERVAL (V4L2_CID_USER_BASE | 0x1006)
+/*
+ * Maximum shutter width used for AEC.
+ */
+#define V4L2_CID_AEC_MAX_SHUTTER_WIDTH (V4L2_CID_USER_BASE | 0x1007)
static int mt9v032_s_ctrl(struct v4l2_ctrl *ctrl)
{
@@ -716,6 +695,28 @@ static int mt9v032_s_ctrl(struct v4l2_ctrl *ctrl)
break;
}
return regmap_write(map, MT9V032_TEST_PATTERN, data);
+
+ case V4L2_CID_AEGC_DESIRED_BIN:
+ return regmap_write(map, MT9V032_AEGC_DESIRED_BIN, ctrl->val);
+
+ case V4L2_CID_AEC_LPF:
+ return regmap_write(map, MT9V032_AEC_LPF, ctrl->val);
+
+ case V4L2_CID_AGC_LPF:
+ return regmap_write(map, MT9V032_AGC_LPF, ctrl->val);
+
+ case V4L2_CID_AEC_UPDATE_INTERVAL:
+ return regmap_write(map, MT9V032_AEC_UPDATE_FREQUENCY,
+ ctrl->val);
+
+ case V4L2_CID_AGC_UPDATE_INTERVAL:
+ return regmap_write(map, MT9V032_AGC_UPDATE_FREQUENCY,
+ ctrl->val);
+
+ case V4L2_CID_AEC_MAX_SHUTTER_WIDTH:
+ return regmap_write(map,
+ mt9v032->model->data->aec_max_shutter_reg,
+ ctrl->val);
}
return 0;
@@ -745,6 +746,84 @@ static const struct v4l2_ctrl_config mt9v032_test_pattern_color = {
.flags = 0,
};
+static const struct v4l2_ctrl_config mt9v032_aegc_controls[] = {
+ {
+ .ops = &mt9v032_ctrl_ops,
+ .id = V4L2_CID_AEGC_DESIRED_BIN,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "AEC/AGC Desired Bin",
+ .min = 1,
+ .max = 64,
+ .step = 1,
+ .def = 58,
+ .flags = 0,
+ }, {
+ .ops = &mt9v032_ctrl_ops,
+ .id = V4L2_CID_AEC_LPF,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "AEC Low Pass Filter",
+ .min = 0,
+ .max = 2,
+ .step = 1,
+ .def = 0,
+ .flags = 0,
+ }, {
+ .ops = &mt9v032_ctrl_ops,
+ .id = V4L2_CID_AGC_LPF,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "AGC Low Pass Filter",
+ .min = 0,
+ .max = 2,
+ .step = 1,
+ .def = 2,
+ .flags = 0,
+ }, {
+ .ops = &mt9v032_ctrl_ops,
+ .id = V4L2_CID_AEC_UPDATE_INTERVAL,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "AEC Update Interval",
+ .min = 0,
+ .max = 16,
+ .step = 1,
+ .def = 2,
+ .flags = 0,
+ }, {
+ .ops = &mt9v032_ctrl_ops,
+ .id = V4L2_CID_AGC_UPDATE_INTERVAL,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "AGC Update Interval",
+ .min = 0,
+ .max = 16,
+ .step = 1,
+ .def = 2,
+ .flags = 0,
+ }
+};
+
+static const struct v4l2_ctrl_config mt9v032_aec_max_shutter_width = {
+ .ops = &mt9v032_ctrl_ops,
+ .id = V4L2_CID_AEC_MAX_SHUTTER_WIDTH,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "AEC Max Shutter Width",
+ .min = 1,
+ .max = 2047,
+ .step = 1,
+ .def = 480,
+ .flags = 0,
+};
+
+static const struct v4l2_ctrl_config mt9v034_aec_max_shutter_width = {
+ .ops = &mt9v032_ctrl_ops,
+ .id = V4L2_CID_AEC_MAX_SHUTTER_WIDTH,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "AEC Max Shutter Width",
+ .min = 1,
+ .max = 32765,
+ .step = 1,
+ .def = 480,
+ .flags = 0,
+};
+
/* -----------------------------------------------------------------------------
* V4L2 subdev core operations
*/
@@ -953,13 +1032,6 @@ static int mt9v032_probe(struct i2c_client *client,
unsigned int i;
int ret;
- if (!i2c_check_functionality(client->adapter,
- I2C_FUNC_SMBUS_WORD_DATA)) {
- dev_warn(&client->adapter->dev,
- "I2C-Adapter doesn't support I2C_FUNC_SMBUS_WORD\n");
- return -EIO;
- }
-
mt9v032 = devm_kzalloc(&client->dev, sizeof(*mt9v032), GFP_KERNEL);
if (!mt9v032)
return -ENOMEM;
@@ -986,7 +1058,8 @@ static int mt9v032_probe(struct i2c_client *client,
mt9v032->pdata = pdata;
mt9v032->model = (const void *)did->driver_data;
- v4l2_ctrl_handler_init(&mt9v032->ctrls, 10);
+ v4l2_ctrl_handler_init(&mt9v032->ctrls, 11 +
+ ARRAY_SIZE(mt9v032_aegc_controls));
v4l2_ctrl_new_std(&mt9v032->ctrls, &mt9v032_ctrl_ops,
V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
@@ -1015,6 +1088,13 @@ static int mt9v032_probe(struct i2c_client *client,
mt9v032->test_pattern_color = v4l2_ctrl_new_custom(&mt9v032->ctrls,
&mt9v032_test_pattern_color, NULL);
+ v4l2_ctrl_new_custom(&mt9v032->ctrls,
+ mt9v032->model->data->aec_max_shutter_v4l2_ctrl,
+ NULL);
+ for (i = 0; i < ARRAY_SIZE(mt9v032_aegc_controls); ++i)
+ v4l2_ctrl_new_custom(&mt9v032->ctrls, &mt9v032_aegc_controls[i],
+ NULL);
+
v4l2_ctrl_cluster(2, &mt9v032->test_pattern);
mt9v032->pixel_rate =
@@ -1103,6 +1183,67 @@ static int mt9v032_remove(struct i2c_client *client)
return 0;
}
+static const struct mt9v032_model_data mt9v032_model_data[] = {
+ {
+ /* MT9V022, MT9V032 revisions 1/2/3 */
+ .min_row_time = 660,
+ .min_hblank = MT9V032_HORIZONTAL_BLANKING_MIN,
+ .min_vblank = MT9V032_VERTICAL_BLANKING_MIN,
+ .max_vblank = MT9V032_VERTICAL_BLANKING_MAX,
+ .min_shutter = MT9V032_TOTAL_SHUTTER_WIDTH_MIN,
+ .max_shutter = MT9V032_TOTAL_SHUTTER_WIDTH_MAX,
+ .pclk_reg = MT9V032_PIXEL_CLOCK,
+ .aec_max_shutter_reg = MT9V032_AEC_MAX_SHUTTER_WIDTH,
+ .aec_max_shutter_v4l2_ctrl = &mt9v032_aec_max_shutter_width,
+ }, {
+ /* MT9V024, MT9V034 */
+ .min_row_time = 690,
+ .min_hblank = MT9V034_HORIZONTAL_BLANKING_MIN,
+ .min_vblank = MT9V034_VERTICAL_BLANKING_MIN,
+ .max_vblank = MT9V034_VERTICAL_BLANKING_MAX,
+ .min_shutter = MT9V034_TOTAL_SHUTTER_WIDTH_MIN,
+ .max_shutter = MT9V034_TOTAL_SHUTTER_WIDTH_MAX,
+ .pclk_reg = MT9V034_PIXEL_CLOCK,
+ .aec_max_shutter_reg = MT9V034_AEC_MAX_SHUTTER_WIDTH,
+ .aec_max_shutter_v4l2_ctrl = &mt9v034_aec_max_shutter_width,
+ },
+};
+
+static const struct mt9v032_model_info mt9v032_models[] = {
+ [MT9V032_MODEL_V022_COLOR] = {
+ .data = &mt9v032_model_data[0],
+ .color = true,
+ },
+ [MT9V032_MODEL_V022_MONO] = {
+ .data = &mt9v032_model_data[0],
+ .color = false,
+ },
+ [MT9V032_MODEL_V024_COLOR] = {
+ .data = &mt9v032_model_data[1],
+ .color = true,
+ },
+ [MT9V032_MODEL_V024_MONO] = {
+ .data = &mt9v032_model_data[1],
+ .color = false,
+ },
+ [MT9V032_MODEL_V032_COLOR] = {
+ .data = &mt9v032_model_data[0],
+ .color = true,
+ },
+ [MT9V032_MODEL_V032_MONO] = {
+ .data = &mt9v032_model_data[0],
+ .color = false,
+ },
+ [MT9V032_MODEL_V034_COLOR] = {
+ .data = &mt9v032_model_data[1],
+ .color = true,
+ },
+ [MT9V032_MODEL_V034_MONO] = {
+ .data = &mt9v032_model_data[1],
+ .color = false,
+ },
+};
+
static const struct i2c_device_id mt9v032_id[] = {
{ "mt9v022", (kernel_ulong_t)&mt9v032_models[MT9V032_MODEL_V022_COLOR] },
{ "mt9v022m", (kernel_ulong_t)&mt9v032_models[MT9V032_MODEL_V022_MONO] },