f07e572f64
bcm2708: boot tested on RPi B+ v1.2 bcm2709: boot tested on RPi 3B v1.2 and RPi 4B v1.1 4G bcm2710: boot tested on RPi 3B v1.2 bcm2711: boot tested on RPi 4B v1.1 4G Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
189 lines
5.6 KiB
Diff
189 lines
5.6 KiB
Diff
From c673ce1338b69c5c8c6572e361be02356af93a72 Mon Sep 17 00:00:00 2001
|
|
From: Dave Stevenson <dave.stevenson@raspberrypi.com>
|
|
Date: Tue, 7 Jul 2020 18:29:10 +0100
|
|
Subject: [PATCH] media: i2c: ov9281: Add support for 8 bit readout
|
|
|
|
The sensor supports 8 bit mode as well as 10bit, so add the
|
|
relevant code to allow selection of this.
|
|
|
|
Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
|
|
---
|
|
drivers/media/i2c/ov9281.c | 66 ++++++++++++++++++++++++++++++--------
|
|
1 file changed, 52 insertions(+), 14 deletions(-)
|
|
|
|
--- a/drivers/media/i2c/ov9281.c
|
|
+++ b/drivers/media/i2c/ov9281.c
|
|
@@ -29,11 +29,12 @@
|
|
|
|
#define OV9281_LINK_FREQ_400MHZ 400000000
|
|
#define OV9281_LANES 2
|
|
-#define OV9281_BITS_PER_SAMPLE 10
|
|
|
|
/* pixel rate = link frequency * 2 * lanes / BITS_PER_SAMPLE */
|
|
-#define OV9281_PIXEL_RATE (OV9281_LINK_FREQ_400MHZ * 2 * \
|
|
- OV9281_LANES / OV9281_BITS_PER_SAMPLE)
|
|
+#define OV9281_PIXEL_RATE_10BIT (OV9281_LINK_FREQ_400MHZ * 2 * \
|
|
+ OV9281_LANES / 10)
|
|
+#define OV9281_PIXEL_RATE_8BIT (OV9281_LINK_FREQ_400MHZ * 2 * \
|
|
+ OV9281_LANES / 8)
|
|
#define OV9281_XVCLK_FREQ 24000000
|
|
|
|
#define CHIP_ID 0x9281
|
|
@@ -122,24 +123,25 @@ struct ov9281 {
|
|
struct v4l2_ctrl *digi_gain;
|
|
struct v4l2_ctrl *hblank;
|
|
struct v4l2_ctrl *vblank;
|
|
+ struct v4l2_ctrl *pixel_rate;
|
|
struct v4l2_ctrl *test_pattern;
|
|
struct mutex mutex;
|
|
bool streaming;
|
|
bool power_on;
|
|
const struct ov9281_mode *cur_mode;
|
|
+ u32 code;
|
|
};
|
|
|
|
#define to_ov9281(sd) container_of(sd, struct ov9281, subdev)
|
|
|
|
/*
|
|
* Xclk 24Mhz
|
|
- * max_framerate 120fps
|
|
+ * max_framerate 120fps for 10 bit, 144fps for 8 bit.
|
|
* mipi_datarate per lane 800Mbps
|
|
*/
|
|
static const struct regval ov9281_1280x800_regs[] = {
|
|
{0x0103, 0x01},
|
|
{0x0302, 0x32},
|
|
- {0x030d, 0x50},
|
|
{0x030e, 0x02},
|
|
{0x3001, 0x00},
|
|
{0x3004, 0x00},
|
|
@@ -168,7 +170,6 @@ static const struct regval ov9281_1280x8
|
|
{0x3620, 0x6f},
|
|
{0x3632, 0x56},
|
|
{0x3633, 0x78},
|
|
- {0x3662, 0x05},
|
|
{0x3666, 0x00},
|
|
{0x366f, 0x5a},
|
|
{0x3680, 0x84},
|
|
@@ -235,6 +236,18 @@ static const struct regval ov9281_1280x8
|
|
{REG_NULL, 0x00},
|
|
};
|
|
|
|
+static const struct regval op_10bit[] = {
|
|
+ {0x030d, 0x50},
|
|
+ {0x3662, 0x05},
|
|
+ {REG_NULL, 0x00},
|
|
+};
|
|
+
|
|
+static const struct regval op_8bit[] = {
|
|
+ {0x030d, 0x60},
|
|
+ {0x3662, 0x07},
|
|
+ {REG_NULL, 0x00},
|
|
+};
|
|
+
|
|
static const struct ov9281_mode supported_modes[] = {
|
|
{
|
|
.width = 1280,
|
|
@@ -374,12 +387,13 @@ static int ov9281_set_fmt(struct v4l2_su
|
|
{
|
|
struct ov9281 *ov9281 = to_ov9281(sd);
|
|
const struct ov9281_mode *mode;
|
|
- s64 h_blank, vblank_def;
|
|
+ s64 h_blank, vblank_def, pixel_rate;
|
|
|
|
mutex_lock(&ov9281->mutex);
|
|
|
|
mode = ov9281_find_best_fit(fmt);
|
|
- fmt->format.code = MEDIA_BUS_FMT_Y10_1X10;
|
|
+ if (fmt->format.code != MEDIA_BUS_FMT_Y8_1X8)
|
|
+ fmt->format.code = MEDIA_BUS_FMT_Y10_1X10;
|
|
fmt->format.width = mode->width;
|
|
fmt->format.height = mode->height;
|
|
fmt->format.field = V4L2_FIELD_NONE;
|
|
@@ -396,6 +410,7 @@ static int ov9281_set_fmt(struct v4l2_su
|
|
*v4l2_subdev_get_try_format(sd, cfg, fmt->pad) = fmt->format;
|
|
} else {
|
|
ov9281->cur_mode = mode;
|
|
+ ov9281->code = fmt->format.code;
|
|
h_blank = mode->hts_def - mode->width;
|
|
__v4l2_ctrl_modify_range(ov9281->hblank, h_blank,
|
|
h_blank, 1, h_blank);
|
|
@@ -405,6 +420,11 @@ static int ov9281_set_fmt(struct v4l2_su
|
|
OV9281_VTS_MAX - mode->height,
|
|
1, vblank_def);
|
|
__v4l2_ctrl_s_ctrl(ov9281->vblank, vblank_def);
|
|
+
|
|
+ pixel_rate = (fmt->format.code == MEDIA_BUS_FMT_Y10_1X10) ?
|
|
+ OV9281_PIXEL_RATE_10BIT : OV9281_PIXEL_RATE_8BIT;
|
|
+ __v4l2_ctrl_modify_range(ov9281->pixel_rate, pixel_rate,
|
|
+ pixel_rate, 1, pixel_rate);
|
|
}
|
|
|
|
mutex_unlock(&ov9281->mutex);
|
|
@@ -425,7 +445,7 @@ static int ov9281_get_fmt(struct v4l2_su
|
|
} else {
|
|
fmt->format.width = mode->width;
|
|
fmt->format.height = mode->height;
|
|
- fmt->format.code = MEDIA_BUS_FMT_Y10_1X10;
|
|
+ fmt->format.code = ov9281->code;
|
|
fmt->format.field = V4L2_FIELD_NONE;
|
|
fmt->format.colorspace = V4L2_COLORSPACE_SRGB;
|
|
fmt->format.ycbcr_enc =
|
|
@@ -446,9 +466,16 @@ static int ov9281_enum_mbus_code(struct
|
|
struct v4l2_subdev_pad_config *cfg,
|
|
struct v4l2_subdev_mbus_code_enum *code)
|
|
{
|
|
- if (code->index)
|
|
+ switch (code->index) {
|
|
+ default:
|
|
return -EINVAL;
|
|
- code->code = MEDIA_BUS_FMT_Y10_1X10;
|
|
+ case 0:
|
|
+ code->code = MEDIA_BUS_FMT_Y10_1X10;
|
|
+ break;
|
|
+ case 1:
|
|
+ code->code = MEDIA_BUS_FMT_Y8_1X8;
|
|
+ break;
|
|
+ }
|
|
|
|
return 0;
|
|
}
|
|
@@ -460,7 +487,8 @@ static int ov9281_enum_frame_sizes(struc
|
|
if (fse->index >= ARRAY_SIZE(supported_modes))
|
|
return -EINVAL;
|
|
|
|
- if (fse->code != MEDIA_BUS_FMT_Y10_1X10)
|
|
+ if (fse->code != MEDIA_BUS_FMT_Y10_1X10 &&
|
|
+ fse->code != MEDIA_BUS_FMT_Y8_1X8)
|
|
return -EINVAL;
|
|
|
|
fse->min_width = supported_modes[fse->index].width;
|
|
@@ -543,6 +571,13 @@ static int __ov9281_start_stream(struct
|
|
if (ret)
|
|
return ret;
|
|
|
|
+ if (ov9281->code == MEDIA_BUS_FMT_Y10_1X10)
|
|
+ ret = ov9281_write_array(ov9281->client, op_10bit);
|
|
+ else
|
|
+ ret = ov9281_write_array(ov9281->client, op_8bit);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
/* In case these controls are set before streaming */
|
|
mutex_unlock(&ov9281->mutex);
|
|
ret = v4l2_ctrl_handler_setup(&ov9281->ctrl_handler);
|
|
@@ -849,8 +884,11 @@ static int ov9281_initialize_controls(st
|
|
if (ctrl)
|
|
ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;
|
|
|
|
- v4l2_ctrl_new_std(handler, NULL, V4L2_CID_PIXEL_RATE,
|
|
- 0, OV9281_PIXEL_RATE, 1, OV9281_PIXEL_RATE);
|
|
+ ov9281->pixel_rate = v4l2_ctrl_new_std(handler, NULL,
|
|
+ V4L2_CID_PIXEL_RATE,
|
|
+ OV9281_PIXEL_RATE_10BIT,
|
|
+ OV9281_PIXEL_RATE_10BIT, 1,
|
|
+ OV9281_PIXEL_RATE_10BIT);
|
|
|
|
h_blank = mode->hts_def - mode->width;
|
|
ov9281->hblank = v4l2_ctrl_new_std(handler, NULL, V4L2_CID_HBLANK,
|