ce0ac0d6934d189a40a397c7c2a09299f8cc6c96
[openwrt/staging/neocturne.git] /
1 From 1cec09c2c2f4c65350d29a0c597da6c7df5ef3bc Mon Sep 17 00:00:00 2001
2 From: Dave Stevenson <dave.stevenson@raspberrypi.com>
3 Date: Thu, 25 Jun 2020 17:03:11 +0100
4 Subject: [PATCH] media : i2c: imx290: Add support for the mono sensor
5 variant.
6
7 The IMX290 module is available as either mono or colour (Bayer).
8
9 Update the driver so that it can advertise the correct mono
10 formats instead of the colour ones.
11
12 Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
13 ---
14 drivers/media/i2c/imx290.c | 58 +++++++++++++++++++++++++++-----------
15 1 file changed, 41 insertions(+), 17 deletions(-)
16
17 --- a/drivers/media/i2c/imx290.c
18 +++ b/drivers/media/i2c/imx290.c
19 @@ -1,10 +1,12 @@
20 // SPDX-License-Identifier: GPL-2.0
21 /*
22 - * Sony IMX290/327 CMOS Image Sensor Driver
23 + * Sony IMX290 & IMX327 CMOS Image Sensor Driver
24 *
25 * The IMX290 and IMX327 are very similar 1920x1080 1/2.8 CMOS image sensors.
26 - * IMX327 can support up to 60fps, whilst IMX290 support up to 120fps (only
27 - * 10bit and when connected over 4 CSI-2 lanes).
28 + * IMX327 can support up to 60fps, whilst IMX290 can support up to 120fps, but
29 + * only 10bit and when connected over 4 CSI-2 lanes.
30 + * The modules don't appear to have a mechanism to identify whether the mono or
31 + * colour variant is connected, therefore it is done via compatible string.
32 *
33 * Copyright (C) 2019 FRAMOS GmbH.
34 *
35 @@ -17,6 +19,7 @@
36 #include <linux/gpio/consumer.h>
37 #include <linux/i2c.h>
38 #include <linux/module.h>
39 +#include <linux/of_device.h>
40 #include <linux/pm_runtime.h>
41 #include <linux/regmap.h>
42 #include <linux/regulator/consumer.h>
43 @@ -95,6 +98,8 @@ struct imx290 {
44 u8 bpp;
45 u16 hmax_min;
46
47 + const struct imx290_pixfmt *formats;
48 +
49 struct v4l2_subdev sd;
50 struct media_pad pad;
51 struct v4l2_mbus_framefmt current_format;
52 @@ -120,11 +125,18 @@ struct imx290_pixfmt {
53 u8 bpp;
54 };
55
56 -static const struct imx290_pixfmt imx290_formats[] = {
57 +#define IMX290_NUM_FORMATS 2
58 +
59 +static const struct imx290_pixfmt imx290_colour_formats[IMX290_NUM_FORMATS] = {
60 { MEDIA_BUS_FMT_SRGGB10_1X10, 10 },
61 { MEDIA_BUS_FMT_SRGGB12_1X12, 12 },
62 };
63
64 +static const struct imx290_pixfmt imx290_mono_formats[IMX290_NUM_FORMATS] = {
65 + { MEDIA_BUS_FMT_Y10_1X10, 10 },
66 + { MEDIA_BUS_FMT_Y12_1X12, 12 },
67 +};
68 +
69 static const struct regmap_config imx290_regmap_config = {
70 .reg_bits = 16,
71 .val_bits = 8,
72 @@ -671,10 +683,12 @@ static int imx290_enum_mbus_code(struct
73 struct v4l2_subdev_state *sd_state,
74 struct v4l2_subdev_mbus_code_enum *code)
75 {
76 - if (code->index >= ARRAY_SIZE(imx290_formats))
77 + const struct imx290 *imx290 = to_imx290(sd);
78 +
79 + if (code->index >= IMX290_NUM_FORMATS)
80 return -EINVAL;
81
82 - code->code = imx290_formats[code->index].code;
83 + code->code = imx290->formats[code->index].code;
84
85 return 0;
86 }
87 @@ -686,8 +700,8 @@ static int imx290_enum_frame_size(struct
88 const struct imx290 *imx290 = to_imx290(sd);
89 const struct imx290_mode *imx290_modes = imx290_modes_ptr(imx290);
90
91 - if ((fse->code != imx290_formats[0].code) &&
92 - (fse->code != imx290_formats[1].code))
93 + if (fse->code != imx290->formats[0].code &&
94 + fse->code != imx290->formats[1].code)
95 return -EINVAL;
96
97 if (fse->index >= imx290_modes_num(imx290))
98 @@ -765,14 +779,14 @@ static int imx290_set_fmt(struct v4l2_su
99 fmt->format.width = mode->width;
100 fmt->format.height = mode->height;
101
102 - for (i = 0; i < ARRAY_SIZE(imx290_formats); i++)
103 - if (imx290_formats[i].code == fmt->format.code)
104 + for (i = 0; i < IMX290_NUM_FORMATS; i++)
105 + if (imx290->formats[i].code == fmt->format.code)
106 break;
107
108 - if (i >= ARRAY_SIZE(imx290_formats))
109 + if (i >= IMX290_NUM_FORMATS)
110 i = 0;
111
112 - fmt->format.code = imx290_formats[i].code;
113 + fmt->format.code = imx290->formats[i].code;
114 fmt->format.field = V4L2_FIELD_NONE;
115
116 if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
117 @@ -780,7 +794,7 @@ static int imx290_set_fmt(struct v4l2_su
118 } else {
119 format = &imx290->current_format;
120 imx290->current_mode = mode;
121 - imx290->bpp = imx290_formats[i].bpp;
122 + imx290->bpp = imx290->formats[i].bpp;
123
124 if (imx290->link_freq)
125 __v4l2_ctrl_s_ctrl(imx290->link_freq,
126 @@ -835,6 +849,7 @@ static int imx290_write_current_format(s
127
128 switch (imx290->current_format.code) {
129 case MEDIA_BUS_FMT_SRGGB10_1X10:
130 + case MEDIA_BUS_FMT_Y10_1X10:
131 ret = imx290_set_register_array(imx290, imx290_10bit_settings,
132 ARRAY_SIZE(
133 imx290_10bit_settings));
134 @@ -844,6 +859,7 @@ static int imx290_write_current_format(s
135 }
136 break;
137 case MEDIA_BUS_FMT_SRGGB12_1X12:
138 + case MEDIA_BUS_FMT_Y12_1X12:
139 ret = imx290_set_register_array(imx290, imx290_12bit_settings,
140 ARRAY_SIZE(
141 imx290_12bit_settings));
142 @@ -1087,6 +1103,12 @@ static s64 imx290_check_link_freqs(const
143 return 0;
144 }
145
146 +static const struct of_device_id imx290_of_match[] = {
147 + { .compatible = "sony,imx290", .data = imx290_colour_formats },
148 + { .compatible = "sony,imx290-mono", .data = imx290_mono_formats },
149 + { /* sentinel */ }
150 +};
151 +
152 static int imx290_probe(struct i2c_client *client)
153 {
154 struct device *dev = &client->dev;
155 @@ -1095,6 +1117,7 @@ static int imx290_probe(struct i2c_clien
156 struct v4l2_fwnode_endpoint ep = {
157 .bus_type = V4L2_MBUS_CSI2_DPHY
158 };
159 + const struct of_device_id *match;
160 const struct imx290_mode *mode;
161 struct imx290 *imx290;
162 s64 fq;
163 @@ -1111,6 +1134,11 @@ static int imx290_probe(struct i2c_clien
164 return -ENODEV;
165 }
166
167 + match = of_match_device(imx290_of_match, dev);
168 + if (!match)
169 + return -ENODEV;
170 + imx290->formats = (const struct imx290_pixfmt *)match->data;
171 +
172 endpoint = fwnode_graph_get_next_endpoint(dev_fwnode(dev), NULL);
173 if (!endpoint) {
174 dev_err(dev, "Endpoint node not found\n");
175 @@ -1329,10 +1357,6 @@ static int imx290_remove(struct i2c_clie
176 return 0;
177 }
178
179 -static const struct of_device_id imx290_of_match[] = {
180 - { .compatible = "sony,imx290" },
181 - { /* sentinel */ }
182 -};
183 MODULE_DEVICE_TABLE(of, imx290_of_match);
184
185 static struct i2c_driver imx290_i2c_driver = {