diff options
author | Jacob Chen <jacob2.chen@rock-chips.com> | 2017-11-20 09:51:13 +0800 |
---|---|---|
committer | Tao Huang <huangtao@rock-chips.com> | 2017-11-28 14:30:07 +0800 |
commit | c10f2c465a24693068286cb8f67f4ec453d58527 (patch) | |
tree | c8e1ebabeaae86829356b3a5a483760c5f1f9972 /drivers/media/i2c/imx219.c | |
parent | 76a28bb1b9cb0566e1523a79daa69b0a7f574796 (diff) |
media: i2c: imx219: add some controls for 3A
Change-Id: I2157b98f9c00e303dd50470247ca794381db727e
Signed-off-by: Jacob Chen <jacob2.chen@rock-chips.com>
Diffstat (limited to 'drivers/media/i2c/imx219.c')
-rw-r--r-- | drivers/media/i2c/imx219.c | 106 |
1 files changed, 52 insertions, 54 deletions
diff --git a/drivers/media/i2c/imx219.c b/drivers/media/i2c/imx219.c index 4990efc148d5..d03b086dbe34 100644 --- a/drivers/media/i2c/imx219.c +++ b/drivers/media/i2c/imx219.c @@ -21,19 +21,32 @@ #include <media/v4l2-fwnode.h> #include <media/v4l2-image-sizes.h> #include <media/v4l2-mediabus.h> -#include <media/v4l2-of.h> /* IMX219 supported geometry */ -#define IMX219_WIDTH 3280 //3280 +#define IMX219_WIDTH 3280 #define IMX219_HEIGHT 2464 +#define IMX219_HTS 3448 +#define IMX219_VTS 2500 + #define IMX219_TABLE_END 0xffff #define IMX219_ANALOGUE_GAIN_MULTIPLIER 256 #define IMX219_ANALOGUE_GAIN_MIN (1 * IMX219_ANALOGUE_GAIN_MULTIPLIER) #define IMX219_ANALOGUE_GAIN_MAX (8 * IMX219_ANALOGUE_GAIN_MULTIPLIER) + /* In dB*256 */ #define IMX219_DIGITAL_GAIN_MIN 256 #define IMX219_DIGITAL_GAIN_MAX 4095 +#define IMX219_DIGITAL_EXPOSURE_MIN 0 +#define IMX219_DIGITAL_EXPOSURE_MAX 4095 + +#define IMX219_LANES 2 +#define IMX219_BITS_PER_SAMPLE 10 + +static const s64 link_freq_menu_items[] = { + 456000000, +}; + struct imx219_reg { u16 addr; u8 val; @@ -143,6 +156,7 @@ struct imx219 { int vflip; u8 analogue_gain; u16 digital_gain; /* bits 11:0 */ + u16 exposure_time; u16 test_pattern; u16 test_pattern_solid_color_r; u16 test_pattern_solid_color_gr; @@ -287,6 +301,12 @@ static int imx219_s_stream(struct v4l2_subdev *sd, int enable) if (ret) return ret; + /* Handle exposure time */ + ret = reg_write(client, 0x015a, priv->exposure_time >> 8); + ret |= reg_write(client, 0x015b, priv->exposure_time & 0xff); + if (ret) + return ret; + /* Handle test pattern */ if (priv->test_pattern) { ret = reg_write(client, 0x0600, priv->test_pattern >> 8); @@ -326,54 +346,6 @@ static int imx219_s_stream(struct v4l2_subdev *sd, int enable) return reg_write_table(client, start); } -static int imx219_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *crop) -{ - if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - - crop->bounds.left = 0; - crop->bounds.top = 0; - crop->bounds.width = IMX219_WIDTH; - crop->bounds.height = IMX219_HEIGHT; - crop->defrect = crop->bounds; - crop->pixelaspect.numerator = 1; - crop->pixelaspect.denominator = 1; - - return 0; -} - -static int imx219_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *crop) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - struct imx219 *priv = to_imx219(client); - - crop->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - crop->c = priv->crop_rect; - - return 0; -} - -static int imx219_s_crop(struct v4l2_subdev *sd, const struct v4l2_crop *crop) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - struct imx219 *priv = to_imx219(client); - struct v4l2_rect rect = crop->c; - u8 reg; - - rect.left = ALIGN(rect.left, 2); - rect.width = ALIGN(rect.width, 2); - rect.top = ALIGN(rect.top, 2); - rect.height = ALIGN(rect.height, 2); - priv->crop_rect = rect; - - /* If enabled, apply settings immediately */ - reg = reg_read(client, 0x0100); - if ((reg & 0x1f) == 0x01) - imx219_s_stream(sd, 1); - - return 0; -} - static int imx219_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned int index, u32 *code) { @@ -558,6 +530,9 @@ static int imx219_s_ctrl(struct v4l2_ctrl *ctrl) */ priv->digital_gain = ctrl->val; break; + case V4L2_CID_EXPOSURE: + priv->exposure_time = ctrl->val; + break; case V4L2_CID_TEST_PATTERN: return imx219_s_ctrl_test_pattern(ctrl); default: @@ -598,9 +573,6 @@ static int imx219_get_fmt(struct v4l2_subdev *sd, /* Various V4L2 operations tables */ static struct v4l2_subdev_video_ops imx219_subdev_video_ops = { .s_stream = imx219_s_stream, - .cropcap = imx219_cropcap, - .g_crop = imx219_g_crop, - .s_crop = imx219_s_crop, }; static struct v4l2_subdev_core_ops imx219_subdev_core_ops = { @@ -703,6 +675,7 @@ static int imx219_ctrls_init(struct v4l2_subdev *sd) { struct i2c_client *client = v4l2_get_subdevdata(sd); struct imx219 *priv = to_imx219(client); + u32 pixel_rate, h_blank, v_blank; int ret; v4l2_ctrl_handler_init(&priv->ctrl_handler, 10); @@ -710,6 +683,8 @@ static int imx219_ctrls_init(struct v4l2_subdev *sd) V4L2_CID_HFLIP, 0, 1, 1, 0); v4l2_ctrl_new_std(&priv->ctrl_handler, &imx219_ctrl_ops, V4L2_CID_VFLIP, 0, 1, 1, 0); + + /* exposure */ v4l2_ctrl_new_std(&priv->ctrl_handler, &imx219_ctrl_ops, V4L2_CID_ANALOGUE_GAIN, IMX219_ANALOGUE_GAIN_MIN, @@ -718,7 +693,30 @@ static int imx219_ctrls_init(struct v4l2_subdev *sd) v4l2_ctrl_new_std(&priv->ctrl_handler, &imx219_ctrl_ops, V4L2_CID_GAIN, IMX219_DIGITAL_GAIN_MIN, - IMX219_DIGITAL_GAIN_MAX, 1, IMX219_DIGITAL_GAIN_MIN); + IMX219_DIGITAL_GAIN_MAX, 1, + IMX219_DIGITAL_GAIN_MIN); + v4l2_ctrl_new_std(&priv->ctrl_handler, &imx219_ctrl_ops, + V4L2_CID_EXPOSURE, + IMX219_DIGITAL_EXPOSURE_MIN, + IMX219_DIGITAL_EXPOSURE_MAX, 1, + IMX219_DIGITAL_EXPOSURE_MIN); + + /* blank */ + h_blank = IMX219_HTS - IMX219_WIDTH; + v4l2_ctrl_new_std(&priv->ctrl_handler, NULL, V4L2_CID_HBLANK, + h_blank, h_blank, 1, h_blank); + v_blank = IMX219_VTS - IMX219_HEIGHT; + v4l2_ctrl_new_std(&priv->ctrl_handler, NULL, V4L2_CID_VBLANK, + v_blank, v_blank, 1, v_blank); + + /* freq */ + v4l2_ctrl_new_int_menu(&priv->ctrl_handler, NULL, V4L2_CID_LINK_FREQ, + 0, 0, link_freq_menu_items); + pixel_rate = (link_freq_menu_items[0] * 2 * IMX219_LANES) / + IMX219_BITS_PER_SAMPLE; + v4l2_ctrl_new_std(&priv->ctrl_handler, NULL, V4L2_CID_PIXEL_RATE, + 0, pixel_rate, 1, pixel_rate); + v4l2_ctrl_new_std_menu_items(&priv->ctrl_handler, &imx219_ctrl_ops, V4L2_CID_TEST_PATTERN, ARRAY_SIZE(tp_qmenu) - 1, 0, 0, tp_qmenu); |