diff options
author | Álvaro Fernández Rojas <noltari@gmail.com> | 2022-05-16 23:40:32 +0200 |
---|---|---|
committer | Álvaro Fernández Rojas <noltari@gmail.com> | 2022-05-17 15:11:22 +0200 |
commit | 20ea6adbf199097c4f5f591ffee088340630dae4 (patch) | |
tree | d6719d95e136611a1c25bbf7789652d6d402779d /target/linux/bcm27xx/patches-5.15/950-0812-media-i2c-imx258-Implement-HFLIP-and-VFLIP-controls.patch | |
parent | bca05bd072180dc38ef740b37ded9572a6db1981 (diff) | |
download | upstream-20ea6adbf199097c4f5f591ffee088340630dae4.tar.gz upstream-20ea6adbf199097c4f5f591ffee088340630dae4.tar.bz2 upstream-20ea6adbf199097c4f5f591ffee088340630dae4.zip |
bcm27xx: add support for linux v5.15
Build system: x86_64
Build-tested: bcm2708, bcm2709, bcm2710, bcm2711
Run-tested: bcm2708/RPiB+, bcm2709/RPi3B, bcm2710/RPi3B, bcm2711/RPi4B
Signed-off-by: Marty Jones <mj8263788@gmail.com>
Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Diffstat (limited to 'target/linux/bcm27xx/patches-5.15/950-0812-media-i2c-imx258-Implement-HFLIP-and-VFLIP-controls.patch')
-rw-r--r-- | target/linux/bcm27xx/patches-5.15/950-0812-media-i2c-imx258-Implement-HFLIP-and-VFLIP-controls.patch | 269 |
1 files changed, 269 insertions, 0 deletions
diff --git a/target/linux/bcm27xx/patches-5.15/950-0812-media-i2c-imx258-Implement-HFLIP-and-VFLIP-controls.patch b/target/linux/bcm27xx/patches-5.15/950-0812-media-i2c-imx258-Implement-HFLIP-and-VFLIP-controls.patch new file mode 100644 index 0000000000..49cb5c1d7f --- /dev/null +++ b/target/linux/bcm27xx/patches-5.15/950-0812-media-i2c-imx258-Implement-HFLIP-and-VFLIP-controls.patch @@ -0,0 +1,269 @@ +From c9d976e455b911c977ffeb000b4342cd65c79dbc Mon Sep 17 00:00:00 2001 +From: Dave Stevenson <dave.stevenson@raspberrypi.com> +Date: Tue, 15 Jun 2021 18:29:52 +0100 +Subject: [PATCH] media: i2c: imx258: Implement HFLIP and VFLIP + controls. + +The sensor supports H & V flips, so implement the relevant controls. +Note that the Bayer order changes with these flips, therefore +they set the V4L2_CTRL_FLAG_MODIFY_LAYOUT property. + +As we now support flips, remove the restriction of the sensor only +probing if rotated 180 degrees, but do take that value and initialise +VFLIP and HFLIP based on it. + +Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com> +--- + drivers/media/i2c/imx258.c | 106 +++++++++++++++++++++++++------------ + 1 file changed, 73 insertions(+), 33 deletions(-) + +--- a/drivers/media/i2c/imx258.c ++++ b/drivers/media/i2c/imx258.c +@@ -9,6 +9,7 @@ + #include <linux/pm_runtime.h> + #include <media/v4l2-ctrls.h> + #include <media/v4l2-device.h> ++#include <media/v4l2-fwnode.h> + #include <asm/unaligned.h> + + #define IMX258_REG_VALUE_08BIT 1 +@@ -69,7 +70,8 @@ + + /* Orientation */ + #define REG_MIRROR_FLIP_CONTROL 0x0101 +-#define REG_CONFIG_MIRROR_FLIP 0x03 ++#define REG_CONFIG_MIRROR_HFLIP 0x01 ++#define REG_CONFIG_MIRROR_VFLIP 0x02 + #define REG_CONFIG_FLIP_TEST_PATTERN 0x02 + + /* Input clock frequency in Hz */ +@@ -504,6 +506,22 @@ static const struct imx258_reg mode_1048 + { 0x0220, 0x00 }, + }; + ++/* ++ * The supported formats. ++ * This table MUST contain 4 entries per format, to cover the various flip ++ * combinations in the order ++ * - no flip ++ * - h flip ++ * - v flip ++ * - h&v flips ++ */ ++static const u32 codes[] = { ++ /* 10-bit modes. */ ++ MEDIA_BUS_FMT_SRGGB10_1X10, ++ MEDIA_BUS_FMT_SGRBG10_1X10, ++ MEDIA_BUS_FMT_SGBRG10_1X10, ++ MEDIA_BUS_FMT_SBGGR10_1X10 ++}; + static const char * const imx258_test_pattern_menu[] = { + "Disabled", + "Solid Colour", +@@ -605,6 +623,8 @@ struct imx258 { + struct v4l2_ctrl *vblank; + struct v4l2_ctrl *hblank; + struct v4l2_ctrl *exposure; ++ struct v4l2_ctrl *hflip; ++ struct v4l2_ctrl *vflip; + + /* Current mode */ + const struct imx258_mode *cur_mode; +@@ -700,16 +720,29 @@ static int imx258_write_regs(struct imx2 + return 0; + } + ++/* Get bayer order based on flip setting. */ ++static u32 imx258_get_format_code(struct imx258 *imx258) ++{ ++ unsigned int i; ++ ++ lockdep_assert_held(&imx258->mutex); ++ ++ i = (imx258->vflip->val ? 2 : 0) | ++ (imx258->hflip->val ? 1 : 0); ++ ++ return codes[i]; ++} + /* Open sub-device */ + static int imx258_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) + { ++ struct imx258 *imx258 = to_imx258(sd); + struct v4l2_mbus_framefmt *try_fmt = + v4l2_subdev_get_try_format(sd, fh->state, 0); + + /* Initialize try_fmt */ + try_fmt->width = supported_modes[0].width; + try_fmt->height = supported_modes[0].height; +- try_fmt->code = MEDIA_BUS_FMT_SBGGR10_1X10; ++ try_fmt->code = imx258_get_format_code(imx258); + try_fmt->field = V4L2_FIELD_NONE; + + return 0; +@@ -775,10 +808,6 @@ static int imx258_set_ctrl(struct v4l2_c + ret = imx258_write_reg(imx258, IMX258_REG_TEST_PATTERN, + IMX258_REG_VALUE_16BIT, + ctrl->val); +- ret = imx258_write_reg(imx258, REG_MIRROR_FLIP_CONTROL, +- IMX258_REG_VALUE_08BIT, +- !ctrl->val ? REG_CONFIG_MIRROR_FLIP : +- REG_CONFIG_FLIP_TEST_PATTERN); + break; + case V4L2_CID_WIDE_DYNAMIC_RANGE: + if (!ctrl->val) { +@@ -796,6 +825,15 @@ static int imx258_set_ctrl(struct v4l2_c + BIT(IMX258_HDR_RATIO_MAX)); + } + break; ++ case V4L2_CID_VFLIP: ++ case V4L2_CID_HFLIP: ++ ret = imx258_write_reg(imx258, REG_MIRROR_FLIP_CONTROL, ++ IMX258_REG_VALUE_08BIT, ++ (imx258->hflip->val ? ++ REG_CONFIG_MIRROR_HFLIP : 0) | ++ (imx258->vflip->val ? ++ REG_CONFIG_MIRROR_VFLIP : 0)); ++ break; + default: + dev_info(&client->dev, + "ctrl(id:0x%x,val:0x%x) is not handled\n", +@@ -817,11 +855,13 @@ static int imx258_enum_mbus_code(struct + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_mbus_code_enum *code) + { +- /* Only one bayer order(GRBG) is supported */ ++ struct imx258 *imx258 = to_imx258(sd); ++ ++ /* Only one bayer format (10 bit) is supported */ + if (code->index > 0) + return -EINVAL; + +- code->code = MEDIA_BUS_FMT_SBGGR10_1X10; ++ code->code = imx258_get_format_code(imx258); + + return 0; + } +@@ -830,10 +870,11 @@ static int imx258_enum_frame_size(struct + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_frame_size_enum *fse) + { ++ struct imx258 *imx258 = to_imx258(sd); + if (fse->index >= ARRAY_SIZE(supported_modes)) + return -EINVAL; + +- if (fse->code != MEDIA_BUS_FMT_SBGGR10_1X10) ++ if (fse->code != imx258_get_format_code(imx258)) + return -EINVAL; + + fse->min_width = supported_modes[fse->index].width; +@@ -844,12 +885,13 @@ static int imx258_enum_frame_size(struct + return 0; + } + +-static void imx258_update_pad_format(const struct imx258_mode *mode, ++static void imx258_update_pad_format(struct imx258 *imx258, ++ const struct imx258_mode *mode, + struct v4l2_subdev_format *fmt) + { + fmt->format.width = mode->width; + fmt->format.height = mode->height; +- fmt->format.code = MEDIA_BUS_FMT_SBGGR10_1X10; ++ fmt->format.code = imx258_get_format_code(imx258); + fmt->format.field = V4L2_FIELD_NONE; + } + +@@ -862,7 +904,7 @@ static int __imx258_get_pad_format(struc + sd_state, + fmt->pad); + else +- imx258_update_pad_format(imx258->cur_mode, fmt); ++ imx258_update_pad_format(imx258, imx258->cur_mode, fmt); + + return 0; + } +@@ -896,13 +938,12 @@ static int imx258_set_pad_format(struct + + mutex_lock(&imx258->mutex); + +- /* Only one raw bayer(GBRG) order is supported */ +- fmt->format.code = MEDIA_BUS_FMT_SBGGR10_1X10; ++ fmt->format.code = imx258_get_format_code(imx258); + + mode = v4l2_find_nearest_size(supported_modes, + ARRAY_SIZE(supported_modes), width, height, + fmt->format.width, fmt->format.height); +- imx258_update_pad_format(mode, fmt); ++ imx258_update_pad_format(imx258, mode, fmt); + if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { + framefmt = v4l2_subdev_get_try_format(sd, sd_state, fmt->pad); + *framefmt = fmt->format; +@@ -959,15 +1000,6 @@ static int imx258_start_streaming(struct + return ret; + } + +- /* Set Orientation be 180 degree */ +- ret = imx258_write_reg(imx258, REG_MIRROR_FLIP_CONTROL, +- IMX258_REG_VALUE_08BIT, REG_CONFIG_MIRROR_FLIP); +- if (ret) { +- dev_err(&client->dev, "%s failed to set orientation\n", +- __func__); +- return ret; +- } +- + /* Apply customized values from user */ + ret = __v4l2_ctrl_handler_setup(imx258->sd.ctrl_handler); + if (ret) +@@ -1142,6 +1174,7 @@ static const struct v4l2_subdev_internal + static int imx258_init_controls(struct imx258 *imx258) + { + struct i2c_client *client = v4l2_get_subdevdata(&imx258->sd); ++ struct v4l2_fwnode_device_properties props; + struct v4l2_ctrl_handler *ctrl_hdlr; + s64 vblank_def; + s64 vblank_min; +@@ -1150,7 +1183,7 @@ static int imx258_init_controls(struct i + int ret; + + ctrl_hdlr = &imx258->ctrl_handler; +- ret = v4l2_ctrl_handler_init(ctrl_hdlr, 8); ++ ret = v4l2_ctrl_handler_init(ctrl_hdlr, 10); + if (ret) + return ret; + +@@ -1219,6 +1252,21 @@ static int imx258_init_controls(struct i + ARRAY_SIZE(imx258_test_pattern_menu) - 1, + 0, 0, imx258_test_pattern_menu); + ++ ret = v4l2_fwnode_device_parse(&client->dev, &props); ++ if (ret) ++ goto error; ++ ++ imx258->hflip = v4l2_ctrl_new_std(ctrl_hdlr, &imx258_ctrl_ops, ++ V4L2_CID_HFLIP, 0, 1, 1, ++ props.rotation == 180 ? 1 : 0); ++ if (imx258->hflip) ++ imx258->hflip->flags |= V4L2_CTRL_FLAG_MODIFY_LAYOUT; ++ ++ imx258->vflip = v4l2_ctrl_new_std(ctrl_hdlr, &imx258_ctrl_ops, ++ V4L2_CID_VFLIP, 0, 1, 1, ++ props.rotation == 180 ? 1 : 0); ++ if (imx258->vflip) ++ imx258->vflip->flags |= V4L2_CTRL_FLAG_MODIFY_LAYOUT; + if (ctrl_hdlr->error) { + ret = ctrl_hdlr->error; + dev_err(&client->dev, "%s control init failed (%d)\n", +@@ -1270,14 +1318,6 @@ static int imx258_probe(struct i2c_clien + return -EINVAL; + } + +- /* +- * Check that the device is mounted upside down. The driver only +- * supports a single pixel order right now. +- */ +- ret = device_property_read_u32(&client->dev, "rotation", &val); +- if (ret || val != 180) +- return -EINVAL; +- + /* Initialize subdev */ + v4l2_i2c_subdev_init(&imx258->sd, client, &imx258_subdev_ops); + |