diff options
Diffstat (limited to 'target/linux/bcm27xx/patches-5.4/950-0456-media-ov5647-Add-basic-support-for-multiple-sensor-m.patch')
-rw-r--r-- | target/linux/bcm27xx/patches-5.4/950-0456-media-ov5647-Add-basic-support-for-multiple-sensor-m.patch | 407 |
1 files changed, 0 insertions, 407 deletions
diff --git a/target/linux/bcm27xx/patches-5.4/950-0456-media-ov5647-Add-basic-support-for-multiple-sensor-m.patch b/target/linux/bcm27xx/patches-5.4/950-0456-media-ov5647-Add-basic-support-for-multiple-sensor-m.patch deleted file mode 100644 index 5846e96af8..0000000000 --- a/target/linux/bcm27xx/patches-5.4/950-0456-media-ov5647-Add-basic-support-for-multiple-sensor-m.patch +++ /dev/null @@ -1,407 +0,0 @@ -From 9e584d9de3387588bf455d3c45ec6a092bfa4266 Mon Sep 17 00:00:00 2001 -From: David Plowman <david.plowman@raspberrypi.com> -Date: Wed, 29 Jan 2020 15:30:53 +0000 -Subject: [PATCH] media: ov5647: Add basic support for multiple sensor - modes. - -Specifically: - -Added a structure ov5647_mode and a list of supported_modes (though no -actual new modes as yet). The state object points to the "current mode". - -ov5647_enum_mbus_code, ov5647_enum_frame_size, ov5647_set_fmt and -ov5647_get_fmt all needed upgrading to cope with multiple modes. - -__sensor_init (which writes all the registers) is now called by -ov5647_stream_on (once the mode is known) rather than by -ov5647_sensor_power. - -Signed-off-by: David Plowman <david.plowman@raspberrypi.com> -Signed-off-by: Naushir Patuck <naush@raspberrypi.com> ---- - drivers/media/i2c/ov5647.c | 268 ++++++++++++++++++++++++++++--------- - 1 file changed, 202 insertions(+), 66 deletions(-) - ---- a/drivers/media/i2c/ov5647.c -+++ b/drivers/media/i2c/ov5647.c -@@ -86,13 +86,17 @@ struct regval_list { - u8 data; - }; - -+struct ov5647_mode { -+ struct v4l2_mbus_framefmt format; -+ struct regval_list *reg_list; -+ unsigned int num_regs; -+}; -+ - struct ov5647 { - struct v4l2_subdev sd; - struct media_pad pad; - struct mutex lock; -- struct v4l2_mbus_framefmt format; -- unsigned int width; -- unsigned int height; -+ const struct ov5647_mode *mode; - int power_count; - struct clk *xclk; - struct gpio_desc *pwdn; -@@ -207,6 +211,32 @@ static struct regval_list ov5647_640x480 - {0x0100, 0x01}, - }; - -+static struct ov5647_mode supported_modes_8bit[] = { -+ /* -+ * Original 8-bit VGA mode -+ * Uncentred crop (top left quarter) from 2x2 binned 1296x972 image. -+ */ -+ { -+ { -+ .code = MEDIA_BUS_FMT_SBGGR8_1X8, -+ .colorspace = V4L2_COLORSPACE_SRGB, -+ .field = V4L2_FIELD_NONE, -+ .width = 640, -+ .height = 480 -+ }, -+ ov5647_640x480, -+ ARRAY_SIZE(ov5647_640x480) -+ }, -+ /* more modes below here... */ -+}; -+ -+static struct ov5647_mode supported_modes_10bit[] = { -+ /* no 10-bit modes yet */ -+}; -+ -+/* Use original 8-bit VGA mode as default. */ -+#define OV5647_DEFAULT_MODE (&supported_modes_8bit[0]) -+ - static int ov5647_write(struct v4l2_subdev *sd, u16 reg, u8 val) - { - int ret; -@@ -293,12 +323,55 @@ static int ov5647_set_virtual_channel(st - return ov5647_write(sd, OV5647_REG_MIPI_CTRL14, channel_id | (channel << 6)); - } - -+static int __sensor_init(struct v4l2_subdev *sd) -+{ -+ int ret; -+ u8 resetval, rdval; -+ struct i2c_client *client = v4l2_get_subdevdata(sd); -+ struct ov5647 *state = to_state(sd); -+ -+ ret = ov5647_read(sd, OV5647_SW_STANDBY, &rdval); -+ if (ret < 0) -+ return ret; -+ -+ ret = ov5647_write_array(sd, state->mode->reg_list, -+ state->mode->num_regs); -+ if (ret < 0) { -+ dev_err(&client->dev, "write sensor default regs error\n"); -+ return ret; -+ } -+ -+ ret = ov5647_set_virtual_channel(sd, 0); -+ if (ret < 0) -+ return ret; -+ -+ ret = ov5647_read(sd, OV5647_SW_STANDBY, &resetval); -+ if (ret < 0) -+ return ret; -+ -+ if (!(resetval & 0x01)) { -+ dev_err(&client->dev, "Device was in SW standby"); -+ ret = ov5647_write(sd, OV5647_SW_STANDBY, 0x01); -+ if (ret < 0) -+ return ret; -+ } -+ -+ return 0; -+} -+ - static int ov5647_stream_on(struct v4l2_subdev *sd) - { -+ struct i2c_client *client = v4l2_get_subdevdata(sd); - struct ov5647 *ov5647 = to_state(sd); - u8 val = MIPI_CTRL00_BUS_IDLE; - int ret; - -+ ret = __sensor_init(sd); -+ if (ret < 0) { -+ dev_err(&client->dev, "sensor_init failed\n"); -+ return ret; -+ } -+ - if (ov5647->flags & V4L2_MBUS_CSI2_NONCONTINUOUS_CLOCK) - val |= MIPI_CTRL00_CLOCK_LANE_GATE | - MIPI_CTRL00_LINE_SYNC_ENABLE; -@@ -347,44 +420,6 @@ static int set_sw_standby(struct v4l2_su - return ov5647_write(sd, OV5647_SW_STANDBY, rdval); - } - --static int __sensor_init(struct v4l2_subdev *sd) --{ -- int ret; -- u8 resetval, rdval; -- struct i2c_client *client = v4l2_get_subdevdata(sd); -- -- ret = ov5647_read(sd, OV5647_SW_STANDBY, &rdval); -- if (ret < 0) -- return ret; -- -- ret = ov5647_write_array(sd, ov5647_640x480, -- ARRAY_SIZE(ov5647_640x480)); -- if (ret < 0) { -- dev_err(&client->dev, "write sensor default regs error\n"); -- return ret; -- } -- -- ret = ov5647_set_virtual_channel(sd, 0); -- if (ret < 0) -- return ret; -- -- ret = ov5647_read(sd, OV5647_SW_STANDBY, &resetval); -- if (ret < 0) -- return ret; -- -- if (!(resetval & 0x01)) { -- dev_err(&client->dev, "Device was in SW standby"); -- ret = ov5647_write(sd, OV5647_SW_STANDBY, 0x01); -- if (ret < 0) -- return ret; -- } -- -- /* -- * stream off to make the clock lane into LP-11 state. -- */ -- return ov5647_stream_off(sd); --} -- - static int ov5647_sensor_power(struct v4l2_subdev *sd, int on) - { - int ret = 0; -@@ -408,7 +443,7 @@ static int ov5647_sensor_power(struct v4 - } - - ret = ov5647_write_array(sd, sensor_oe_enable_regs, -- ARRAY_SIZE(sensor_oe_enable_regs)); -+ ARRAY_SIZE(sensor_oe_enable_regs)); - if (ret < 0) { - clk_disable_unprepare(ov5647->xclk); - dev_err(&client->dev, -@@ -416,7 +451,10 @@ static int ov5647_sensor_power(struct v4 - goto out; - } - -- ret = __sensor_init(sd); -+ /* -+ * Ensure streaming off to make clock lane go into LP-11 state. -+ */ -+ ret = ov5647_stream_off(sd); - if (ret < 0) { - clk_disable_unprepare(ov5647->xclk); - dev_err(&client->dev, -@@ -427,7 +465,7 @@ static int ov5647_sensor_power(struct v4 - dev_dbg(&client->dev, "OV5647 power off\n"); - - ret = ov5647_write_array(sd, sensor_oe_disable_regs, -- ARRAY_SIZE(sensor_oe_disable_regs)); -+ ARRAY_SIZE(sensor_oe_disable_regs)); - - if (ret < 0) - dev_dbg(&client->dev, "disable oe failed\n"); -@@ -489,10 +527,19 @@ static const struct v4l2_subdev_core_ops - - static int ov5647_s_stream(struct v4l2_subdev *sd, int enable) - { -+ struct ov5647 *state = to_state(sd); -+ int ret = 0; -+ -+ mutex_lock(&state->lock); -+ - if (enable) -- return ov5647_stream_on(sd); -+ ret = ov5647_stream_on(sd); - else -- return ov5647_stream_off(sd); -+ ret = ov5647_stream_off(sd); -+ -+ mutex_unlock(&state->lock); -+ -+ return ret; - } - - static const struct v4l2_subdev_video_ops ov5647_subdev_video_ops = { -@@ -503,38 +550,127 @@ static int ov5647_enum_mbus_code(struct - struct v4l2_subdev_pad_config *cfg, - struct v4l2_subdev_mbus_code_enum *code) - { -- if (code->index > 0) -+ if (code->index == 0 && ARRAY_SIZE(supported_modes_8bit)) -+ code->code = MEDIA_BUS_FMT_SBGGR8_1X8; -+ else if (code->index == 0 && ARRAY_SIZE(supported_modes_8bit) == 0 && -+ ARRAY_SIZE(supported_modes_10bit)) -+ code->code = MEDIA_BUS_FMT_SBGGR10_1X10; -+ else if (code->index == 1 && ARRAY_SIZE(supported_modes_8bit) && -+ ARRAY_SIZE(supported_modes_10bit)) -+ code->code = MEDIA_BUS_FMT_SBGGR10_1X10; -+ else - return -EINVAL; - -- code->code = MEDIA_BUS_FMT_SBGGR8_1X8; -+ return 0; -+} -+ -+static int ov5647_enum_frame_size(struct v4l2_subdev *sd, -+ struct v4l2_subdev_pad_config *cfg, -+ struct v4l2_subdev_frame_size_enum *fse) -+{ -+ struct ov5647_mode *mode = NULL; -+ -+ if (fse->code == MEDIA_BUS_FMT_SBGGR8_1X8) { -+ if (fse->index >= ARRAY_SIZE(supported_modes_8bit)) -+ return -EINVAL; -+ mode = &supported_modes_8bit[fse->index]; -+ } else if (fse->code == MEDIA_BUS_FMT_SBGGR10_1X10) { -+ if (fse->index >= ARRAY_SIZE(supported_modes_10bit)) -+ return -EINVAL; -+ mode = &supported_modes_10bit[fse->index]; -+ } else { -+ return -EINVAL; -+ } -+ -+ fse->min_width = mode->format.width; -+ fse->max_width = fse->min_width; -+ fse->min_height = mode->format.height; -+ fse->max_height = fse->min_height; -+ -+ return 0; -+} -+ -+static int ov5647_set_fmt(struct v4l2_subdev *sd, -+ struct v4l2_subdev_pad_config *cfg, -+ struct v4l2_subdev_format *format) -+{ -+ struct v4l2_mbus_framefmt *fmt = &format->format; -+ struct ov5647 *state = to_state(sd); -+ struct v4l2_mbus_framefmt *framefmt; -+ const struct ov5647_mode *mode_8bit, *mode_10bit, *mode = NULL; -+ -+ if (format->pad != 0) -+ return -EINVAL; -+ -+ mutex_lock(&state->lock); -+ -+ /* -+ * Try to respect any given pixel format, otherwise try for a 10-bit -+ * mode. -+ */ -+ mode_8bit = v4l2_find_nearest_size(supported_modes_8bit, -+ ARRAY_SIZE(supported_modes_8bit), -+ format.width, format.height, -+ format->format.width, -+ format->format.height); -+ mode_10bit = v4l2_find_nearest_size(supported_modes_10bit, -+ ARRAY_SIZE(supported_modes_10bit), -+ format.width, format.height, -+ format->format.width, -+ format->format.height); -+ if (format->format.code == MEDIA_BUS_FMT_SBGGR8_1X8 && mode_8bit) -+ mode = mode_8bit; -+ else if (format->format.code == MEDIA_BUS_FMT_SBGGR10_1X10 && -+ mode_10bit) -+ mode = mode_10bit; -+ else if (mode_10bit) -+ mode = mode_10bit; -+ else -+ mode = mode_8bit; -+ -+ if (!mode) -+ return -EINVAL; -+ -+ *fmt = mode->format; -+ if (format->which == V4L2_SUBDEV_FORMAT_TRY) { -+ framefmt = v4l2_subdev_get_try_format(sd, cfg, format->pad); -+ *framefmt = format->format; -+ } else { -+ state->mode = mode; -+ } -+ -+ mutex_unlock(&state->lock); - - return 0; - } - --static int ov5647_set_get_fmt(struct v4l2_subdev *sd, -- struct v4l2_subdev_pad_config *cfg, -- struct v4l2_subdev_format *format) -+static int ov5647_get_fmt(struct v4l2_subdev *sd, -+ struct v4l2_subdev_pad_config *cfg, -+ struct v4l2_subdev_format *format) - { - struct v4l2_mbus_framefmt *fmt = &format->format; -+ struct ov5647 *state = to_state(sd); - - if (format->pad != 0) - return -EINVAL; - -- /* Only one format is supported, so return that */ -- memset(fmt, 0, sizeof(*fmt)); -- fmt->code = MEDIA_BUS_FMT_SBGGR8_1X8; -- fmt->colorspace = V4L2_COLORSPACE_SRGB; -- fmt->field = V4L2_FIELD_NONE; -- fmt->width = 640; -- fmt->height = 480; -+ mutex_lock(&state->lock); -+ -+ if (format->which == V4L2_SUBDEV_FORMAT_TRY) -+ *fmt = *v4l2_subdev_get_try_format(sd, cfg, format->pad); -+ else -+ *fmt = state->mode->format; -+ -+ mutex_unlock(&state->lock); - - return 0; - } - - static const struct v4l2_subdev_pad_ops ov5647_subdev_pad_ops = { - .enum_mbus_code = ov5647_enum_mbus_code, -- .set_fmt = ov5647_set_get_fmt, -- .get_fmt = ov5647_set_get_fmt, -+ .set_fmt = ov5647_set_fmt, -+ .get_fmt = ov5647_get_fmt, -+ .enum_frame_size = ov5647_enum_frame_size, - }; - - static const struct v4l2_subdev_ops ov5647_subdev_ops = { -@@ -580,18 +716,15 @@ static int ov5647_open(struct v4l2_subde - v4l2_subdev_get_try_format(sd, fh->pad, 0); - struct v4l2_rect *crop = - v4l2_subdev_get_try_crop(sd, fh->pad, 0); -+ struct ov5647 *state = to_state(sd); - - crop->left = OV5647_COLUMN_START_DEF; - crop->top = OV5647_ROW_START_DEF; - crop->width = OV5647_WINDOW_WIDTH_DEF; - crop->height = OV5647_WINDOW_HEIGHT_DEF; - -- format->code = MEDIA_BUS_FMT_SBGGR8_1X8; -- -- format->width = OV5647_WINDOW_WIDTH_DEF; -- format->height = OV5647_WINDOW_HEIGHT_DEF; -- format->field = V4L2_FIELD_NONE; -- format->colorspace = V4L2_COLORSPACE_SRGB; -+ /* Set the default format to the same as the sensor. */ -+ *format = state->mode->format; - - return 0; - } -@@ -660,6 +793,9 @@ static int ov5647_probe(struct i2c_clien - - mutex_init(&sensor->lock); - -+ /* Set the default mode before we init the subdev */ -+ sensor->mode = OV5647_DEFAULT_MODE; -+ - sd = &sensor->sd; - v4l2_i2c_subdev_init(sd, client, &ov5647_subdev_ops); - sensor->sd.internal_ops = &ov5647_subdev_internal_ops; |