diff options
Diffstat (limited to 'drivers/media')
-rw-r--r-- | drivers/media/i2c/imx219.c | 134 |
1 files changed, 36 insertions, 98 deletions
diff --git a/drivers/media/i2c/imx219.c b/drivers/media/i2c/imx219.c index cf55c59cbb7f..927ab106cea6 100644 --- a/drivers/media/i2c/imx219.c +++ b/drivers/media/i2c/imx219.c @@ -149,11 +149,6 @@ #define IMX219_PIXEL_ARRAY_WIDTH 3280U #define IMX219_PIXEL_ARRAY_HEIGHT 2464U -struct imx219_reg_list { - unsigned int num_of_regs; - const struct cci_reg_sequence *regs; -}; - /* Mode : resolution and related config&values */ struct imx219_mode { /* Frame width */ @@ -167,9 +162,6 @@ struct imx219_mode { /* V-timing */ unsigned int vts_def; - /* Default register values */ - struct imx219_reg_list reg_list; - /* 2x2 binning is used */ bool binning; }; @@ -218,65 +210,6 @@ static const struct cci_reg_sequence imx219_common_regs[] = { { IMX219_REG_EXCK_FREQ, IMX219_EXCK_FREQ(IMX219_XCLK_FREQ / 1000000) }, }; -/* - * Register sets lifted off the i2C interface from the Raspberry Pi firmware - * driver. - * 3280x2464 = mode 2, 1920x1080 = mode 1, 1640x1232 = mode 4, 640x480 = mode 7. - */ -static const struct cci_reg_sequence mode_3280x2464_regs[] = { - { IMX219_REG_X_ADD_STA_A, 0 }, - { IMX219_REG_X_ADD_END_A, 3279 }, - { IMX219_REG_Y_ADD_STA_A, 0 }, - { IMX219_REG_Y_ADD_END_A, 2463 }, - { IMX219_REG_X_OUTPUT_SIZE, 3280 }, - { IMX219_REG_Y_OUTPUT_SIZE, 2464 }, - { IMX219_REG_TP_WINDOW_WIDTH, 3280 }, - { IMX219_REG_TP_WINDOW_HEIGHT, 2464 }, -}; - -static const struct cci_reg_sequence mode_1920_1080_regs[] = { - { IMX219_REG_X_ADD_STA_A, 680 }, - { IMX219_REG_X_ADD_END_A, 2599 }, - { IMX219_REG_Y_ADD_STA_A, 692 }, - { IMX219_REG_Y_ADD_END_A, 1771 }, - { IMX219_REG_X_OUTPUT_SIZE, 1920 }, - { IMX219_REG_Y_OUTPUT_SIZE, 1080 }, - { IMX219_REG_TP_WINDOW_WIDTH, 1920 }, - { IMX219_REG_TP_WINDOW_HEIGHT, 1080 }, -}; - -static const struct cci_reg_sequence mode_1640_1232_regs[] = { - { IMX219_REG_X_ADD_STA_A, 0 }, - { IMX219_REG_X_ADD_END_A, 3279 }, - { IMX219_REG_Y_ADD_STA_A, 0 }, - { IMX219_REG_Y_ADD_END_A, 2463 }, - { IMX219_REG_X_OUTPUT_SIZE, 1640 }, - { IMX219_REG_Y_OUTPUT_SIZE, 1232 }, - { IMX219_REG_TP_WINDOW_WIDTH, 1640 }, - { IMX219_REG_TP_WINDOW_HEIGHT, 1232 }, -}; - -static const struct cci_reg_sequence mode_640_480_regs[] = { - { IMX219_REG_X_ADD_STA_A, 1000 }, - { IMX219_REG_X_ADD_END_A, 2279 }, - { IMX219_REG_Y_ADD_STA_A, 752 }, - { IMX219_REG_Y_ADD_END_A, 1711 }, - { IMX219_REG_X_OUTPUT_SIZE, 640 }, - { IMX219_REG_Y_OUTPUT_SIZE, 480 }, - { IMX219_REG_TP_WINDOW_WIDTH, 640 }, - { IMX219_REG_TP_WINDOW_HEIGHT, 480 }, -}; - -static const struct cci_reg_sequence raw8_framefmt_regs[] = { - { IMX219_REG_CSI_DATA_FORMAT_A, 0x0808 }, - { IMX219_REG_OPPXCK_DIV, 8 }, -}; - -static const struct cci_reg_sequence raw10_framefmt_regs[] = { - { IMX219_REG_CSI_DATA_FORMAT_A, 0x0a0a }, - { IMX219_REG_OPPXCK_DIV, 10 }, -}; - static const s64 imx219_link_freq_menu[] = { IMX219_DEFAULT_LINK_FREQ, }; @@ -372,10 +305,6 @@ static const struct imx219_mode supported_modes[] = { .height = 2464 }, .vts_def = IMX219_VTS_15FPS, - .reg_list = { - .num_of_regs = ARRAY_SIZE(mode_3280x2464_regs), - .regs = mode_3280x2464_regs, - }, .binning = false, }, { @@ -389,10 +318,6 @@ static const struct imx219_mode supported_modes[] = { .height = 1080 }, .vts_def = IMX219_VTS_30FPS_1080P, - .reg_list = { - .num_of_regs = ARRAY_SIZE(mode_1920_1080_regs), - .regs = mode_1920_1080_regs, - }, .binning = false, }, { @@ -406,10 +331,6 @@ static const struct imx219_mode supported_modes[] = { .height = 2464 }, .vts_def = IMX219_VTS_30FPS_BINNED, - .reg_list = { - .num_of_regs = ARRAY_SIZE(mode_1640_1232_regs), - .regs = mode_1640_1232_regs, - }, .binning = true, }, { @@ -423,10 +344,6 @@ static const struct imx219_mode supported_modes[] = { .height = 960 }, .vts_def = IMX219_VTS_30FPS_640x480, - .reg_list = { - .num_of_regs = ARRAY_SIZE(mode_640_480_regs), - .regs = mode_640_480_regs, - }, .binning = true, }, }; @@ -695,23 +612,53 @@ static int imx219_set_pad_format(struct v4l2_subdev *sd, static int imx219_set_framefmt(struct imx219 *imx219, const struct v4l2_mbus_framefmt *format) { + const struct imx219_mode *mode = imx219->mode; + unsigned int bpp; + int ret = 0; + switch (format->code) { case MEDIA_BUS_FMT_SRGGB8_1X8: case MEDIA_BUS_FMT_SGRBG8_1X8: case MEDIA_BUS_FMT_SGBRG8_1X8: case MEDIA_BUS_FMT_SBGGR8_1X8: - return cci_multi_reg_write(imx219->regmap, raw8_framefmt_regs, - ARRAY_SIZE(raw8_framefmt_regs), NULL); + bpp = 8; + break; case MEDIA_BUS_FMT_SRGGB10_1X10: case MEDIA_BUS_FMT_SGRBG10_1X10: case MEDIA_BUS_FMT_SGBRG10_1X10: case MEDIA_BUS_FMT_SBGGR10_1X10: - return cci_multi_reg_write(imx219->regmap, raw10_framefmt_regs, - ARRAY_SIZE(raw10_framefmt_regs), NULL); + default: + bpp = 10; + break; } - return -EINVAL; + cci_write(imx219->regmap, IMX219_REG_X_ADD_STA_A, + mode->crop.left - IMX219_PIXEL_ARRAY_LEFT, &ret); + cci_write(imx219->regmap, IMX219_REG_X_ADD_END_A, + mode->crop.left - IMX219_PIXEL_ARRAY_LEFT + mode->crop.width - 1, + &ret); + cci_write(imx219->regmap, IMX219_REG_Y_ADD_STA_A, + mode->crop.top - IMX219_PIXEL_ARRAY_TOP, &ret); + cci_write(imx219->regmap, IMX219_REG_Y_ADD_END_A, + mode->crop.top - IMX219_PIXEL_ARRAY_TOP + mode->crop.height - 1, + &ret); + + cci_write(imx219->regmap, IMX219_REG_X_OUTPUT_SIZE, + format->width, &ret); + cci_write(imx219->regmap, IMX219_REG_Y_OUTPUT_SIZE, + format->height, &ret); + + cci_write(imx219->regmap, IMX219_REG_TP_WINDOW_WIDTH, + format->width, &ret); + cci_write(imx219->regmap, IMX219_REG_TP_WINDOW_HEIGHT, + format->height, &ret); + + cci_write(imx219->regmap, IMX219_REG_CSI_DATA_FORMAT_A, + (bpp << 8) | bpp, &ret); + cci_write(imx219->regmap, IMX219_REG_OPPXCK_DIV, bpp, &ret); + + return ret; } static int imx219_set_binning(struct imx219 *imx219, @@ -783,7 +730,6 @@ static int imx219_start_streaming(struct imx219 *imx219, { struct i2c_client *client = v4l2_get_subdevdata(&imx219->sd); const struct v4l2_mbus_framefmt *format; - const struct imx219_reg_list *reg_list; int ret; ret = pm_runtime_resume_and_get(&client->dev); @@ -805,15 +751,7 @@ static int imx219_start_streaming(struct imx219 *imx219, goto err_rpm_put; } - /* Apply default values of current mode */ - reg_list = &imx219->mode->reg_list; - ret = cci_multi_reg_write(imx219->regmap, reg_list->regs, - reg_list->num_of_regs, NULL); - if (ret) { - dev_err(&client->dev, "%s failed to set mode\n", __func__); - goto err_rpm_put; - } - + /* Apply format and crop settings. */ format = v4l2_subdev_get_pad_format(&imx219->sd, state, 0); ret = imx219_set_framefmt(imx219, format); if (ret) { |