aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video')
-rw-r--r--drivers/media/video/Kconfig2
-rw-r--r--drivers/media/video/Makefile1
-rw-r--r--drivers/media/video/smiapp-pll.c2
-rw-r--r--drivers/media/video/smiapp/Kconfig13
-rw-r--r--drivers/media/video/smiapp/Makefile3
-rw-r--r--drivers/media/video/smiapp/smiapp-core.c2832
-rw-r--r--drivers/media/video/smiapp/smiapp-debug.h32
-rw-r--r--drivers/media/video/smiapp/smiapp-limits.c132
-rw-r--r--drivers/media/video/smiapp/smiapp-limits.h128
-rw-r--r--drivers/media/video/smiapp/smiapp-quirk.c264
-rw-r--r--drivers/media/video/smiapp/smiapp-quirk.h72
-rw-r--r--drivers/media/video/smiapp/smiapp-reg-defs.h503
-rw-r--r--drivers/media/video/smiapp/smiapp-reg.h122
-rw-r--r--drivers/media/video/smiapp/smiapp-regs.c213
-rw-r--r--drivers/media/video/smiapp/smiapp-regs.h46
-rw-r--r--drivers/media/video/smiapp/smiapp.h251
16 files changed, 4616 insertions, 0 deletions
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
index d3e879f64310..9fc7c5224ac8 100644
--- a/drivers/media/video/Kconfig
+++ b/drivers/media/video/Kconfig
@@ -559,6 +559,8 @@ config VIDEO_S5K6AA
559 This is a V4L2 sensor-level driver for Samsung S5K6AA(FX) 1.3M 559 This is a V4L2 sensor-level driver for Samsung S5K6AA(FX) 1.3M
560 camera sensor with an embedded SoC image signal processor. 560 camera sensor with an embedded SoC image signal processor.
561 561
562source "drivers/media/video/smiapp/Kconfig"
563
562comment "Flash devices" 564comment "Flash devices"
563 565
564config VIDEO_ADP1653 566config VIDEO_ADP1653
diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile
index 4e6c100cf583..5a97da2ae33b 100644
--- a/drivers/media/video/Makefile
+++ b/drivers/media/video/Makefile
@@ -79,6 +79,7 @@ obj-$(CONFIG_VIDEO_SR030PC30) += sr030pc30.o
79obj-$(CONFIG_VIDEO_NOON010PC30) += noon010pc30.o 79obj-$(CONFIG_VIDEO_NOON010PC30) += noon010pc30.o
80obj-$(CONFIG_VIDEO_M5MOLS) += m5mols/ 80obj-$(CONFIG_VIDEO_M5MOLS) += m5mols/
81obj-$(CONFIG_VIDEO_S5K6AA) += s5k6aa.o 81obj-$(CONFIG_VIDEO_S5K6AA) += s5k6aa.o
82obj-$(CONFIG_VIDEO_SMIAPP) += smiapp/
82obj-$(CONFIG_VIDEO_ADP1653) += adp1653.o 83obj-$(CONFIG_VIDEO_ADP1653) += adp1653.o
83obj-$(CONFIG_VIDEO_AS3645A) += as3645a.o 84obj-$(CONFIG_VIDEO_AS3645A) += as3645a.o
84 85
diff --git a/drivers/media/video/smiapp-pll.c b/drivers/media/video/smiapp-pll.c
index a416e27a4282..501da413dfad 100644
--- a/drivers/media/video/smiapp-pll.c
+++ b/drivers/media/video/smiapp-pll.c
@@ -22,6 +22,8 @@
22 * 22 *
23 */ 23 */
24 24
25#include "smiapp/smiapp-debug.h"
26
25#include <linux/gcd.h> 27#include <linux/gcd.h>
26#include <linux/lcm.h> 28#include <linux/lcm.h>
27#include <linux/module.h> 29#include <linux/module.h>
diff --git a/drivers/media/video/smiapp/Kconfig b/drivers/media/video/smiapp/Kconfig
new file mode 100644
index 000000000000..9504c436a5ca
--- /dev/null
+++ b/drivers/media/video/smiapp/Kconfig
@@ -0,0 +1,13 @@
1config VIDEO_SMIAPP
2 tristate "SMIA++/SMIA sensor support"
3 depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
4 select VIDEO_SMIAPP_PLL
5 ---help---
6 This is a generic driver for SMIA++/SMIA camera modules.
7
8config VIDEO_SMIAPP_DEBUG
9 bool "Enable debugging for the generic SMIA++/SMIA driver"
10 depends on VIDEO_SMIAPP
11 ---help---
12 Enable debugging output in the generic SMIA++/SMIA driver. If you
13 are developing the driver you might want to enable this.
diff --git a/drivers/media/video/smiapp/Makefile b/drivers/media/video/smiapp/Makefile
new file mode 100644
index 000000000000..5a207eecd357
--- /dev/null
+++ b/drivers/media/video/smiapp/Makefile
@@ -0,0 +1,3 @@
1smiapp-objs += smiapp-core.o smiapp-regs.o \
2 smiapp-quirk.o smiapp-limits.o
3obj-$(CONFIG_VIDEO_SMIAPP) += smiapp.o
diff --git a/drivers/media/video/smiapp/smiapp-core.c b/drivers/media/video/smiapp/smiapp-core.c
new file mode 100644
index 000000000000..3991c452acb2
--- /dev/null
+++ b/drivers/media/video/smiapp/smiapp-core.c
@@ -0,0 +1,2832 @@
1/*
2 * drivers/media/video/smiapp/smiapp-core.c
3 *
4 * Generic driver for SMIA/SMIA++ compliant camera modules
5 *
6 * Copyright (C) 2010--2012 Nokia Corporation
7 * Contact: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
8 *
9 * Based on smiapp driver by Vimarsh Zutshi
10 * Based on jt8ev1.c by Vimarsh Zutshi
11 * Based on smia-sensor.c by Tuukka Toivonen <tuukkat76@gmail.com>
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * version 2 as published by the Free Software Foundation.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
25 * 02110-1301 USA
26 *
27 */
28
29#include "smiapp-debug.h"
30
31#include <linux/delay.h>
32#include <linux/device.h>
33#include <linux/gpio.h>
34#include <linux/module.h>
35#include <linux/regulator/consumer.h>
36#include <linux/v4l2-mediabus.h>
37#include <media/v4l2-device.h>
38
39#include "smiapp.h"
40
41#define SMIAPP_ALIGN_DIM(dim, flags) \
42 ((flags) & V4L2_SUBDEV_SEL_FLAG_SIZE_GE \
43 ? ALIGN((dim), 2) \
44 : (dim) & ~1)
45
46/*
47 * smiapp_module_idents - supported camera modules
48 */
49static const struct smiapp_module_ident smiapp_module_idents[] = {
50 SMIAPP_IDENT_L(0x01, 0x022b, -1, "vs6555"),
51 SMIAPP_IDENT_L(0x01, 0x022e, -1, "vw6558"),
52 SMIAPP_IDENT_L(0x07, 0x7698, -1, "ovm7698"),
53 SMIAPP_IDENT_L(0x0b, 0x4242, -1, "smiapp-003"),
54 SMIAPP_IDENT_L(0x0c, 0x208a, -1, "tcm8330md"),
55 SMIAPP_IDENT_LQ(0x0c, 0x2134, -1, "tcm8500md", &smiapp_tcm8500md_quirk),
56 SMIAPP_IDENT_L(0x0c, 0x213e, -1, "et8en2"),
57 SMIAPP_IDENT_L(0x0c, 0x2184, -1, "tcm8580md"),
58 SMIAPP_IDENT_LQ(0x0c, 0x560f, -1, "jt8ew9", &smiapp_jt8ew9_quirk),
59 SMIAPP_IDENT_LQ(0x10, 0x4141, -1, "jt8ev1", &smiapp_jt8ev1_quirk),
60 SMIAPP_IDENT_LQ(0x10, 0x4241, -1, "imx125es", &smiapp_imx125es_quirk),
61};
62
63/*
64 *
65 * Dynamic Capability Identification
66 *
67 */
68
69static int smiapp_read_frame_fmt(struct smiapp_sensor *sensor)
70{
71 struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
72 u32 fmt_model_type, fmt_model_subtype, ncol_desc, nrow_desc;
73 unsigned int i;
74 int rval;
75 int line_count = 0;
76 int embedded_start = -1, embedded_end = -1;
77 int image_start = 0;
78
79 rval = smiapp_read(client, SMIAPP_REG_U8_FRAME_FORMAT_MODEL_TYPE,
80 &fmt_model_type);
81 if (rval)
82 return rval;
83
84 rval = smiapp_read(client, SMIAPP_REG_U8_FRAME_FORMAT_MODEL_SUBTYPE,
85 &fmt_model_subtype);
86 if (rval)
87 return rval;
88
89 ncol_desc = (fmt_model_subtype
90 & SMIAPP_FRAME_FORMAT_MODEL_SUBTYPE_NCOLS_MASK)
91 >> SMIAPP_FRAME_FORMAT_MODEL_SUBTYPE_NCOLS_SHIFT;
92 nrow_desc = fmt_model_subtype
93 & SMIAPP_FRAME_FORMAT_MODEL_SUBTYPE_NROWS_MASK;
94
95 dev_dbg(&client->dev, "format_model_type %s\n",
96 fmt_model_type == SMIAPP_FRAME_FORMAT_MODEL_TYPE_2BYTE
97 ? "2 byte" :
98 fmt_model_type == SMIAPP_FRAME_FORMAT_MODEL_TYPE_4BYTE
99 ? "4 byte" : "is simply bad");
100
101 for (i = 0; i < ncol_desc + nrow_desc; i++) {
102 u32 desc;
103 u32 pixelcode;
104 u32 pixels;
105 char *which;
106 char *what;
107
108 if (fmt_model_type == SMIAPP_FRAME_FORMAT_MODEL_TYPE_2BYTE) {
109 rval = smiapp_read(
110 client,
111 SMIAPP_REG_U16_FRAME_FORMAT_DESCRIPTOR_2(i),
112 &desc);
113 if (rval)
114 return rval;
115
116 pixelcode =
117 (desc
118 & SMIAPP_FRAME_FORMAT_DESC_2_PIXELCODE_MASK)
119 >> SMIAPP_FRAME_FORMAT_DESC_2_PIXELCODE_SHIFT;
120 pixels = desc & SMIAPP_FRAME_FORMAT_DESC_2_PIXELS_MASK;
121 } else if (fmt_model_type
122 == SMIAPP_FRAME_FORMAT_MODEL_TYPE_4BYTE) {
123 rval = smiapp_read(
124 client,
125 SMIAPP_REG_U32_FRAME_FORMAT_DESCRIPTOR_4(i),
126 &desc);
127 if (rval)
128 return rval;
129
130 pixelcode =
131 (desc
132 & SMIAPP_FRAME_FORMAT_DESC_4_PIXELCODE_MASK)
133 >> SMIAPP_FRAME_FORMAT_DESC_4_PIXELCODE_SHIFT;
134 pixels = desc & SMIAPP_FRAME_FORMAT_DESC_4_PIXELS_MASK;
135 } else {
136 dev_dbg(&client->dev,
137 "invalid frame format model type %d\n",
138 fmt_model_type);
139 return -EINVAL;
140 }
141
142 if (i < ncol_desc)
143 which = "columns";
144 else
145 which = "rows";
146
147 switch (pixelcode) {
148 case SMIAPP_FRAME_FORMAT_DESC_PIXELCODE_EMBEDDED:
149 what = "embedded";
150 break;
151 case SMIAPP_FRAME_FORMAT_DESC_PIXELCODE_DUMMY:
152 what = "dummy";
153 break;
154 case SMIAPP_FRAME_FORMAT_DESC_PIXELCODE_BLACK:
155 what = "black";
156 break;
157 case SMIAPP_FRAME_FORMAT_DESC_PIXELCODE_DARK:
158 what = "dark";
159 break;
160 case SMIAPP_FRAME_FORMAT_DESC_PIXELCODE_VISIBLE:
161 what = "visible";
162 break;
163 default:
164 what = "invalid";
165 dev_dbg(&client->dev, "pixelcode %d\n", pixelcode);
166 break;
167 }
168
169 dev_dbg(&client->dev, "%s pixels: %d %s\n",
170 what, pixels, which);
171
172 if (i < ncol_desc)
173 continue;
174
175 /* Handle row descriptors */
176 if (pixelcode
177 == SMIAPP_FRAME_FORMAT_DESC_PIXELCODE_EMBEDDED) {
178 embedded_start = line_count;
179 } else {
180 if (pixelcode == SMIAPP_FRAME_FORMAT_DESC_PIXELCODE_VISIBLE
181 || pixels >= sensor->limits[SMIAPP_LIMIT_MIN_FRAME_LENGTH_LINES] / 2)
182 image_start = line_count;
183 if (embedded_start != -1 && embedded_end == -1)
184 embedded_end = line_count;
185 }
186 line_count += pixels;
187 }
188
189 if (embedded_start == -1 || embedded_end == -1) {
190 embedded_start = 0;
191 embedded_end = 0;
192 }
193
194 dev_dbg(&client->dev, "embedded data from lines %d to %d\n",
195 embedded_start, embedded_end);
196 dev_dbg(&client->dev, "image data starts at line %d\n", image_start);
197
198 return 0;
199}
200
201static int smiapp_pll_configure(struct smiapp_sensor *sensor)
202{
203 struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
204 struct smiapp_pll *pll = &sensor->pll;
205 int rval;
206
207 rval = smiapp_write(
208 client, SMIAPP_REG_U16_VT_PIX_CLK_DIV, pll->vt_pix_clk_div);
209 if (rval < 0)
210 return rval;
211
212 rval = smiapp_write(
213 client, SMIAPP_REG_U16_VT_SYS_CLK_DIV, pll->vt_sys_clk_div);
214 if (rval < 0)
215 return rval;
216
217 rval = smiapp_write(
218 client, SMIAPP_REG_U16_PRE_PLL_CLK_DIV, pll->pre_pll_clk_div);
219 if (rval < 0)
220 return rval;
221
222 rval = smiapp_write(
223 client, SMIAPP_REG_U16_PLL_MULTIPLIER, pll->pll_multiplier);
224 if (rval < 0)
225 return rval;
226
227 /* Lane op clock ratio does not apply here. */
228 rval = smiapp_write(
229 client, SMIAPP_REG_U32_REQUESTED_LINK_BIT_RATE_MBPS,
230 DIV_ROUND_UP(pll->op_sys_clk_freq_hz, 1000000 / 256 / 256));
231 if (rval < 0 || sensor->minfo.smiapp_profile == SMIAPP_PROFILE_0)
232 return rval;
233
234 rval = smiapp_write(
235 client, SMIAPP_REG_U16_OP_PIX_CLK_DIV, pll->op_pix_clk_div);
236 if (rval < 0)
237 return rval;
238
239 return smiapp_write(
240 client, SMIAPP_REG_U16_OP_SYS_CLK_DIV, pll->op_sys_clk_div);
241}
242
243static int smiapp_pll_update(struct smiapp_sensor *sensor)
244{
245 struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
246 struct smiapp_pll_limits lim = {
247 .min_pre_pll_clk_div = sensor->limits[SMIAPP_LIMIT_MIN_PRE_PLL_CLK_DIV],
248 .max_pre_pll_clk_div = sensor->limits[SMIAPP_LIMIT_MAX_PRE_PLL_CLK_DIV],
249 .min_pll_ip_freq_hz = sensor->limits[SMIAPP_LIMIT_MIN_PLL_IP_FREQ_HZ],
250 .max_pll_ip_freq_hz = sensor->limits[SMIAPP_LIMIT_MAX_PLL_IP_FREQ_HZ],
251 .min_pll_multiplier = sensor->limits[SMIAPP_LIMIT_MIN_PLL_MULTIPLIER],
252 .max_pll_multiplier = sensor->limits[SMIAPP_LIMIT_MAX_PLL_MULTIPLIER],
253 .min_pll_op_freq_hz = sensor->limits[SMIAPP_LIMIT_MIN_PLL_OP_FREQ_HZ],
254 .max_pll_op_freq_hz = sensor->limits[SMIAPP_LIMIT_MAX_PLL_OP_FREQ_HZ],
255
256 .min_op_sys_clk_div = sensor->limits[SMIAPP_LIMIT_MIN_OP_SYS_CLK_DIV],
257 .max_op_sys_clk_div = sensor->limits[SMIAPP_LIMIT_MAX_OP_SYS_CLK_DIV],
258 .min_op_pix_clk_div = sensor->limits[SMIAPP_LIMIT_MIN_OP_PIX_CLK_DIV],
259 .max_op_pix_clk_div = sensor->limits[SMIAPP_LIMIT_MAX_OP_PIX_CLK_DIV],
260 .min_op_sys_clk_freq_hz = sensor->limits[SMIAPP_LIMIT_MIN_OP_SYS_CLK_FREQ_HZ],
261 .max_op_sys_clk_freq_hz = sensor->limits[SMIAPP_LIMIT_MAX_OP_SYS_CLK_FREQ_HZ],
262 .min_op_pix_clk_freq_hz = sensor->limits[SMIAPP_LIMIT_MIN_OP_PIX_CLK_FREQ_HZ],
263 .max_op_pix_clk_freq_hz = sensor->limits[SMIAPP_LIMIT_MAX_OP_PIX_CLK_FREQ_HZ],
264
265 .min_vt_sys_clk_div = sensor->limits[SMIAPP_LIMIT_MIN_VT_SYS_CLK_DIV],
266 .max_vt_sys_clk_div = sensor->limits[SMIAPP_LIMIT_MAX_VT_SYS_CLK_DIV],
267 .min_vt_pix_clk_div = sensor->limits[SMIAPP_LIMIT_MIN_VT_PIX_CLK_DIV],
268 .max_vt_pix_clk_div = sensor->limits[SMIAPP_LIMIT_MAX_VT_PIX_CLK_DIV],
269 .min_vt_sys_clk_freq_hz = sensor->limits[SMIAPP_LIMIT_MIN_VT_SYS_CLK_FREQ_HZ],
270 .max_vt_sys_clk_freq_hz = sensor->limits[SMIAPP_LIMIT_MAX_VT_SYS_CLK_FREQ_HZ],
271 .min_vt_pix_clk_freq_hz = sensor->limits[SMIAPP_LIMIT_MIN_VT_PIX_CLK_FREQ_HZ],
272 .max_vt_pix_clk_freq_hz = sensor->limits[SMIAPP_LIMIT_MAX_VT_PIX_CLK_FREQ_HZ],
273
274 .min_line_length_pck_bin = sensor->limits[SMIAPP_LIMIT_MIN_LINE_LENGTH_PCK_BIN],
275 .min_line_length_pck = sensor->limits[SMIAPP_LIMIT_MIN_LINE_LENGTH_PCK],
276 };
277 struct smiapp_pll *pll = &sensor->pll;
278 int rval;
279
280 memset(&sensor->pll, 0, sizeof(sensor->pll));
281
282 pll->lanes = sensor->platform_data->lanes;
283 pll->ext_clk_freq_hz = sensor->platform_data->ext_clk;
284
285 if (sensor->minfo.smiapp_profile == SMIAPP_PROFILE_0) {
286 /*
287 * Fill in operational clock divisors limits from the
288 * video timing ones. On profile 0 sensors the
289 * requirements regarding them are essentially the
290 * same as on VT ones.
291 */
292 lim.min_op_sys_clk_div = lim.min_vt_sys_clk_div;
293 lim.max_op_sys_clk_div = lim.max_vt_sys_clk_div;
294 lim.min_op_pix_clk_div = lim.min_vt_pix_clk_div;
295 lim.max_op_pix_clk_div = lim.max_vt_pix_clk_div;
296 lim.min_op_sys_clk_freq_hz = lim.min_vt_sys_clk_freq_hz;
297 lim.max_op_sys_clk_freq_hz = lim.max_vt_sys_clk_freq_hz;
298 lim.min_op_pix_clk_freq_hz = lim.min_vt_pix_clk_freq_hz;
299 lim.max_op_pix_clk_freq_hz = lim.max_vt_pix_clk_freq_hz;
300 /* Profile 0 sensors have no separate OP clock branch. */
301 pll->flags |= SMIAPP_PLL_FLAG_NO_OP_CLOCKS;
302 }
303
304 if (smiapp_needs_quirk(sensor,
305 SMIAPP_QUIRK_FLAG_OP_PIX_CLOCK_PER_LANE))
306 pll->flags |= SMIAPP_PLL_FLAG_OP_PIX_CLOCK_PER_LANE;
307
308 pll->binning_horizontal = sensor->binning_horizontal;
309 pll->binning_vertical = sensor->binning_vertical;
310 pll->link_freq =
311 sensor->link_freq->qmenu_int[sensor->link_freq->val];
312 pll->scale_m = sensor->scale_m;
313 pll->scale_n = sensor->limits[SMIAPP_LIMIT_SCALER_N_MIN];
314 pll->bits_per_pixel = sensor->csi_format->compressed;
315
316 rval = smiapp_pll_calculate(&client->dev, &lim, pll);
317 if (rval < 0)
318 return rval;
319
320 sensor->pixel_rate_parray->cur.val64 = pll->vt_pix_clk_freq_hz;
321 sensor->pixel_rate_csi->cur.val64 = pll->pixel_rate_csi;
322
323 return 0;
324}
325
326
327/*
328 *
329 * V4L2 Controls handling
330 *
331 */
332
333static void __smiapp_update_exposure_limits(struct smiapp_sensor *sensor)
334{
335 struct v4l2_ctrl *ctrl = sensor->exposure;
336 int max;
337
338 max = sensor->pixel_array->crop[SMIAPP_PA_PAD_SRC].height
339 + sensor->vblank->val
340 - sensor->limits[SMIAPP_LIMIT_COARSE_INTEGRATION_TIME_MAX_MARGIN];
341
342 ctrl->maximum = max;
343 if (ctrl->default_value > max)
344 ctrl->default_value = max;
345 if (ctrl->val > max)
346 ctrl->val = max;
347 if (ctrl->cur.val > max)
348 ctrl->cur.val = max;
349}
350
351/*
352 * Order matters.
353 *
354 * 1. Bits-per-pixel, descending.
355 * 2. Bits-per-pixel compressed, descending.
356 * 3. Pixel order, same as in pixel_order_str. Formats for all four pixel
357 * orders must be defined.
358 */
359static const struct smiapp_csi_data_format smiapp_csi_data_formats[] = {
360 { V4L2_MBUS_FMT_SGRBG12_1X12, 12, 12, SMIAPP_PIXEL_ORDER_GRBG, },
361 { V4L2_MBUS_FMT_SRGGB12_1X12, 12, 12, SMIAPP_PIXEL_ORDER_RGGB, },
362 { V4L2_MBUS_FMT_SBGGR12_1X12, 12, 12, SMIAPP_PIXEL_ORDER_BGGR, },
363 { V4L2_MBUS_FMT_SGBRG12_1X12, 12, 12, SMIAPP_PIXEL_ORDER_GBRG, },
364 { V4L2_MBUS_FMT_SGRBG10_1X10, 10, 10, SMIAPP_PIXEL_ORDER_GRBG, },
365 { V4L2_MBUS_FMT_SRGGB10_1X10, 10, 10, SMIAPP_PIXEL_ORDER_RGGB, },
366 { V4L2_MBUS_FMT_SBGGR10_1X10, 10, 10, SMIAPP_PIXEL_ORDER_BGGR, },
367 { V4L2_MBUS_FMT_SGBRG10_1X10, 10, 10, SMIAPP_PIXEL_ORDER_GBRG, },
368 { V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8, 10, 8, SMIAPP_PIXEL_ORDER_GRBG, },
369 { V4L2_MBUS_FMT_SRGGB10_DPCM8_1X8, 10, 8, SMIAPP_PIXEL_ORDER_RGGB, },
370 { V4L2_MBUS_FMT_SBGGR10_DPCM8_1X8, 10, 8, SMIAPP_PIXEL_ORDER_BGGR, },
371 { V4L2_MBUS_FMT_SGBRG10_DPCM8_1X8, 10, 8, SMIAPP_PIXEL_ORDER_GBRG, },
372};
373
374const char *pixel_order_str[] = { "GRBG", "RGGB", "BGGR", "GBRG" };
375
376#define to_csi_format_idx(fmt) (((unsigned long)(fmt) \
377 - (unsigned long)smiapp_csi_data_formats) \
378 / sizeof(*smiapp_csi_data_formats))
379
380static u32 smiapp_pixel_order(struct smiapp_sensor *sensor)
381{
382 struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
383 int flip = 0;
384
385 if (sensor->hflip) {
386 if (sensor->hflip->val)
387 flip |= SMIAPP_IMAGE_ORIENTATION_HFLIP;
388
389 if (sensor->vflip->val)
390 flip |= SMIAPP_IMAGE_ORIENTATION_VFLIP;
391 }
392
393 flip ^= sensor->hvflip_inv_mask;
394
395 dev_dbg(&client->dev, "flip %d\n", flip);
396 return sensor->default_pixel_order ^ flip;
397}
398
399static void smiapp_update_mbus_formats(struct smiapp_sensor *sensor)
400{
401 struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
402 unsigned int csi_format_idx =
403 to_csi_format_idx(sensor->csi_format) & ~3;
404 unsigned int internal_csi_format_idx =
405 to_csi_format_idx(sensor->internal_csi_format) & ~3;
406 unsigned int pixel_order = smiapp_pixel_order(sensor);
407
408 sensor->mbus_frame_fmts =
409 sensor->default_mbus_frame_fmts << pixel_order;
410 sensor->csi_format =
411 &smiapp_csi_data_formats[csi_format_idx + pixel_order];
412 sensor->internal_csi_format =
413 &smiapp_csi_data_formats[internal_csi_format_idx
414 + pixel_order];
415
416 BUG_ON(max(internal_csi_format_idx, csi_format_idx) + pixel_order
417 >= ARRAY_SIZE(smiapp_csi_data_formats));
418 BUG_ON(min(internal_csi_format_idx, csi_format_idx) < 0);
419
420 dev_dbg(&client->dev, "new pixel order %s\n",
421 pixel_order_str[pixel_order]);
422}
423
424static int smiapp_set_ctrl(struct v4l2_ctrl *ctrl)
425{
426 struct smiapp_sensor *sensor =
427 container_of(ctrl->handler, struct smiapp_subdev, ctrl_handler)
428 ->sensor;
429 struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
430 u32 orient = 0;
431 int exposure;
432 int rval;
433
434 switch (ctrl->id) {
435 case V4L2_CID_ANALOGUE_GAIN:
436 return smiapp_write(
437 client,
438 SMIAPP_REG_U16_ANALOGUE_GAIN_CODE_GLOBAL, ctrl->val);
439
440 case V4L2_CID_EXPOSURE:
441 return smiapp_write(
442 client,
443 SMIAPP_REG_U16_COARSE_INTEGRATION_TIME, ctrl->val);
444
445 case V4L2_CID_HFLIP:
446 case V4L2_CID_VFLIP:
447 if (sensor->streaming)
448 return -EBUSY;
449
450 if (sensor->hflip->val)
451 orient |= SMIAPP_IMAGE_ORIENTATION_HFLIP;
452
453 if (sensor->vflip->val)
454 orient |= SMIAPP_IMAGE_ORIENTATION_VFLIP;
455
456 orient ^= sensor->hvflip_inv_mask;
457 rval = smiapp_write(client,
458 SMIAPP_REG_U8_IMAGE_ORIENTATION,
459 orient);
460 if (rval < 0)
461 return rval;
462
463 smiapp_update_mbus_formats(sensor);
464
465 return 0;
466
467 case V4L2_CID_VBLANK:
468 exposure = sensor->exposure->val;
469
470 __smiapp_update_exposure_limits(sensor);
471
472 if (exposure > sensor->exposure->maximum) {
473 sensor->exposure->val =
474 sensor->exposure->maximum;
475 rval = smiapp_set_ctrl(
476 sensor->exposure);
477 if (rval < 0)
478 return rval;
479 }
480
481 return smiapp_write(
482 client, SMIAPP_REG_U16_FRAME_LENGTH_LINES,
483 sensor->pixel_array->crop[SMIAPP_PA_PAD_SRC].height
484 + ctrl->val);
485
486 case V4L2_CID_HBLANK:
487 return smiapp_write(
488 client, SMIAPP_REG_U16_LINE_LENGTH_PCK,
489 sensor->pixel_array->crop[SMIAPP_PA_PAD_SRC].width
490 + ctrl->val);
491
492 case V4L2_CID_LINK_FREQ:
493 if (sensor->streaming)
494 return -EBUSY;
495
496 return smiapp_pll_update(sensor);
497
498 default:
499 return -EINVAL;
500 }
501}
502
503static const struct v4l2_ctrl_ops smiapp_ctrl_ops = {
504 .s_ctrl = smiapp_set_ctrl,
505};
506
507static int smiapp_init_controls(struct smiapp_sensor *sensor)
508{
509 struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
510 struct v4l2_ctrl_config cfg;
511 int rval;
512
513 rval = v4l2_ctrl_handler_init(&sensor->pixel_array->ctrl_handler, 7);
514 if (rval)
515 return rval;
516 sensor->pixel_array->ctrl_handler.lock = &sensor->mutex;
517
518 sensor->analog_gain = v4l2_ctrl_new_std(
519 &sensor->pixel_array->ctrl_handler, &smiapp_ctrl_ops,
520 V4L2_CID_ANALOGUE_GAIN,
521 sensor->limits[SMIAPP_LIMIT_ANALOGUE_GAIN_CODE_MIN],
522 sensor->limits[SMIAPP_LIMIT_ANALOGUE_GAIN_CODE_MAX],
523 max(sensor->limits[SMIAPP_LIMIT_ANALOGUE_GAIN_CODE_STEP], 1U),
524 sensor->limits[SMIAPP_LIMIT_ANALOGUE_GAIN_CODE_MIN]);
525
526 /* Exposure limits will be updated soon, use just something here. */
527 sensor->exposure = v4l2_ctrl_new_std(
528 &sensor->pixel_array->ctrl_handler, &smiapp_ctrl_ops,
529 V4L2_CID_EXPOSURE, 0, 0, 1, 0);
530
531 sensor->hflip = v4l2_ctrl_new_std(
532 &sensor->pixel_array->ctrl_handler, &smiapp_ctrl_ops,
533 V4L2_CID_HFLIP, 0, 1, 1, 0);
534 sensor->vflip = v4l2_ctrl_new_std(
535 &sensor->pixel_array->ctrl_handler, &smiapp_ctrl_ops,
536 V4L2_CID_VFLIP, 0, 1, 1, 0);
537
538 sensor->vblank = v4l2_ctrl_new_std(
539 &sensor->pixel_array->ctrl_handler, &smiapp_ctrl_ops,
540 V4L2_CID_VBLANK, 0, 1, 1, 0);
541
542 if (sensor->vblank)
543 sensor->vblank->flags |= V4L2_CTRL_FLAG_UPDATE;
544
545 sensor->hblank = v4l2_ctrl_new_std(
546 &sensor->pixel_array->ctrl_handler, &smiapp_ctrl_ops,
547 V4L2_CID_HBLANK, 0, 1, 1, 0);
548
549 if (sensor->hblank)
550 sensor->hblank->flags |= V4L2_CTRL_FLAG_UPDATE;
551
552 sensor->pixel_rate_parray = v4l2_ctrl_new_std(
553 &sensor->pixel_array->ctrl_handler, &smiapp_ctrl_ops,
554 V4L2_CID_PIXEL_RATE, 0, 0, 1, 0);
555
556 if (sensor->pixel_array->ctrl_handler.error) {
557 dev_err(&client->dev,
558 "pixel array controls initialization failed (%d)\n",
559 sensor->pixel_array->ctrl_handler.error);
560 rval = sensor->pixel_array->ctrl_handler.error;
561 goto error;
562 }
563
564 sensor->pixel_array->sd.ctrl_handler =
565 &sensor->pixel_array->ctrl_handler;
566
567 v4l2_ctrl_cluster(2, &sensor->hflip);
568
569 rval = v4l2_ctrl_handler_init(&sensor->src->ctrl_handler, 0);
570 if (rval)
571 goto error;
572 sensor->src->ctrl_handler.lock = &sensor->mutex;
573
574 memset(&cfg, 0, sizeof(cfg));
575
576 cfg.ops = &smiapp_ctrl_ops;
577 cfg.id = V4L2_CID_LINK_FREQ;
578 cfg.type = V4L2_CTRL_TYPE_INTEGER_MENU;
579 while (sensor->platform_data->op_sys_clock[cfg.max + 1])
580 cfg.max++;
581 cfg.qmenu_int = sensor->platform_data->op_sys_clock;
582
583 sensor->link_freq = v4l2_ctrl_new_custom(
584 &sensor->src->ctrl_handler, &cfg, NULL);
585
586 sensor->pixel_rate_csi = v4l2_ctrl_new_std(
587 &sensor->src->ctrl_handler, &smiapp_ctrl_ops,
588 V4L2_CID_PIXEL_RATE, 0, 0, 1, 0);
589
590 if (sensor->src->ctrl_handler.error) {
591 dev_err(&client->dev,
592 "src controls initialization failed (%d)\n",
593 sensor->src->ctrl_handler.error);
594 rval = sensor->src->ctrl_handler.error;
595 goto error;
596 }
597
598 sensor->src->sd.ctrl_handler =
599 &sensor->src->ctrl_handler;
600
601 return 0;
602
603error:
604 v4l2_ctrl_handler_free(&sensor->pixel_array->ctrl_handler);
605 v4l2_ctrl_handler_free(&sensor->src->ctrl_handler);
606
607 return rval;
608}
609
610static void smiapp_free_controls(struct smiapp_sensor *sensor)
611{
612 unsigned int i;
613
614 for (i = 0; i < sensor->ssds_used; i++)
615 v4l2_ctrl_handler_free(&sensor->ssds[i].ctrl_handler);
616}
617
618static int smiapp_get_limits(struct smiapp_sensor *sensor, int const *limit,
619 unsigned int n)
620{
621 struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
622 unsigned int i;
623 u32 val;
624 int rval;
625
626 for (i = 0; i < n; i++) {
627 rval = smiapp_read(
628 client, smiapp_reg_limits[limit[i]].addr, &val);
629 if (rval)
630 return rval;
631 sensor->limits[limit[i]] = val;
632 dev_dbg(&client->dev, "0x%8.8x \"%s\" = %d, 0x%x\n",
633 smiapp_reg_limits[limit[i]].addr,
634 smiapp_reg_limits[limit[i]].what, val, val);
635 }
636
637 return 0;
638}
639
640static int smiapp_get_all_limits(struct smiapp_sensor *sensor)
641{
642 unsigned int i;
643 int rval;
644
645 for (i = 0; i < SMIAPP_LIMIT_LAST; i++) {
646 rval = smiapp_get_limits(sensor, &i, 1);
647 if (rval < 0)
648 return rval;
649 }
650
651 if (sensor->limits[SMIAPP_LIMIT_SCALER_N_MIN] == 0)
652 smiapp_replace_limit(sensor, SMIAPP_LIMIT_SCALER_N_MIN, 16);
653
654 return 0;
655}
656
657static int smiapp_get_limits_binning(struct smiapp_sensor *sensor)
658{
659 static u32 const limits[] = {
660 SMIAPP_LIMIT_MIN_FRAME_LENGTH_LINES_BIN,
661 SMIAPP_LIMIT_MAX_FRAME_LENGTH_LINES_BIN,
662 SMIAPP_LIMIT_MIN_LINE_LENGTH_PCK_BIN,
663 SMIAPP_LIMIT_MAX_LINE_LENGTH_PCK_BIN,
664 SMIAPP_LIMIT_MIN_LINE_BLANKING_PCK_BIN,
665 SMIAPP_LIMIT_FINE_INTEGRATION_TIME_MIN_BIN,
666 SMIAPP_LIMIT_FINE_INTEGRATION_TIME_MAX_MARGIN_BIN,
667 };
668 static u32 const limits_replace[] = {
669 SMIAPP_LIMIT_MIN_FRAME_LENGTH_LINES,
670 SMIAPP_LIMIT_MAX_FRAME_LENGTH_LINES,
671 SMIAPP_LIMIT_MIN_LINE_LENGTH_PCK,
672 SMIAPP_LIMIT_MAX_LINE_LENGTH_PCK,
673 SMIAPP_LIMIT_MIN_LINE_BLANKING_PCK,
674 SMIAPP_LIMIT_FINE_INTEGRATION_TIME_MIN,
675 SMIAPP_LIMIT_FINE_INTEGRATION_TIME_MAX_MARGIN,
676 };
677
678 if (sensor->limits[SMIAPP_LIMIT_BINNING_CAPABILITY] ==
679 SMIAPP_BINNING_CAPABILITY_NO) {
680 unsigned int i;
681
682 for (i = 0; i < ARRAY_SIZE(limits); i++)
683 sensor->limits[limits[i]] =
684 sensor->limits[limits_replace[i]];
685
686 return 0;
687 }
688
689 return smiapp_get_limits(sensor, limits, ARRAY_SIZE(limits));
690}
691
692static int smiapp_get_mbus_formats(struct smiapp_sensor *sensor)
693{
694 struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
695 unsigned int type, n;
696 unsigned int i, pixel_order;
697 int rval;
698
699 rval = smiapp_read(
700 client, SMIAPP_REG_U8_DATA_FORMAT_MODEL_TYPE, &type);
701 if (rval)
702 return rval;
703
704 dev_dbg(&client->dev, "data_format_model_type %d\n", type);
705
706 rval = smiapp_read(client, SMIAPP_REG_U8_PIXEL_ORDER,
707 &pixel_order);
708 if (rval)
709 return rval;
710
711 if (pixel_order >= ARRAY_SIZE(pixel_order_str)) {
712 dev_dbg(&client->dev, "bad pixel order %d\n", pixel_order);
713 return -EINVAL;
714 }
715
716 dev_dbg(&client->dev, "pixel order %d (%s)\n", pixel_order,
717 pixel_order_str[pixel_order]);
718
719 switch (type) {
720 case SMIAPP_DATA_FORMAT_MODEL_TYPE_NORMAL:
721 n = SMIAPP_DATA_FORMAT_MODEL_TYPE_NORMAL_N;
722 break;
723 case SMIAPP_DATA_FORMAT_MODEL_TYPE_EXTENDED:
724 n = SMIAPP_DATA_FORMAT_MODEL_TYPE_EXTENDED_N;
725 break;
726 default:
727 return -EINVAL;
728 }
729
730 sensor->default_pixel_order = pixel_order;
731 sensor->mbus_frame_fmts = 0;
732
733 for (i = 0; i < n; i++) {
734 unsigned int fmt, j;
735
736 rval = smiapp_read(
737 client,
738 SMIAPP_REG_U16_DATA_FORMAT_DESCRIPTOR(i), &fmt);
739 if (rval)
740 return rval;
741
742 dev_dbg(&client->dev, "bpp %d, compressed %d\n",
743 fmt >> 8, (u8)fmt);
744
745 for (j = 0; j < ARRAY_SIZE(smiapp_csi_data_formats); j++) {
746 const struct smiapp_csi_data_format *f =
747 &smiapp_csi_data_formats[j];
748
749 if (f->pixel_order != SMIAPP_PIXEL_ORDER_GRBG)
750 continue;
751
752 if (f->width != fmt >> 8 || f->compressed != (u8)fmt)
753 continue;
754
755 dev_dbg(&client->dev, "jolly good! %d\n", j);
756
757 sensor->default_mbus_frame_fmts |= 1 << j;
758 if (!sensor->csi_format) {
759 sensor->csi_format = f;
760 sensor->internal_csi_format = f;
761 }
762 }
763 }
764
765 if (!sensor->csi_format) {
766 dev_err(&client->dev, "no supported mbus code found\n");
767 return -EINVAL;
768 }
769
770 smiapp_update_mbus_formats(sensor);
771
772 return 0;
773}
774
775static void smiapp_update_blanking(struct smiapp_sensor *sensor)
776{
777 struct v4l2_ctrl *vblank = sensor->vblank;
778 struct v4l2_ctrl *hblank = sensor->hblank;
779
780 vblank->minimum =
781 max_t(int,
782 sensor->limits[SMIAPP_LIMIT_MIN_FRAME_BLANKING_LINES],
783 sensor->limits[SMIAPP_LIMIT_MIN_FRAME_LENGTH_LINES_BIN] -
784 sensor->pixel_array->crop[SMIAPP_PA_PAD_SRC].height);
785 vblank->maximum =
786 sensor->limits[SMIAPP_LIMIT_MAX_FRAME_LENGTH_LINES_BIN] -
787 sensor->pixel_array->crop[SMIAPP_PA_PAD_SRC].height;
788
789 vblank->val = clamp_t(int, vblank->val,
790 vblank->minimum, vblank->maximum);
791 vblank->default_value = vblank->minimum;
792 vblank->val = vblank->val;
793 vblank->cur.val = vblank->val;
794
795 hblank->minimum =
796 max_t(int,
797 sensor->limits[SMIAPP_LIMIT_MIN_LINE_LENGTH_PCK_BIN] -
798 sensor->pixel_array->crop[SMIAPP_PA_PAD_SRC].width,
799 sensor->limits[SMIAPP_LIMIT_MIN_LINE_BLANKING_PCK_BIN]);
800 hblank->maximum =
801 sensor->limits[SMIAPP_LIMIT_MAX_LINE_LENGTH_PCK_BIN] -
802 sensor->pixel_array->crop[SMIAPP_PA_PAD_SRC].width;
803
804 hblank->val = clamp_t(int, hblank->val,
805 hblank->minimum, hblank->maximum);
806 hblank->default_value = hblank->minimum;
807 hblank->val = hblank->val;
808 hblank->cur.val = hblank->val;
809
810 __smiapp_update_exposure_limits(sensor);
811}
812
813static int smiapp_update_mode(struct smiapp_sensor *sensor)
814{
815 struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
816 unsigned int binning_mode;
817 int rval;
818
819 dev_dbg(&client->dev, "frame size: %dx%d\n",
820 sensor->src->crop[SMIAPP_PAD_SRC].width,
821 sensor->src->crop[SMIAPP_PAD_SRC].height);
822 dev_dbg(&client->dev, "csi format width: %d\n",
823 sensor->csi_format->width);
824
825 /* Binning has to be set up here; it affects limits */
826 if (sensor->binning_horizontal == 1 &&
827 sensor->binning_vertical == 1) {
828 binning_mode = 0;
829 } else {
830 u8 binning_type =
831 (sensor->binning_horizontal << 4)
832 | sensor->binning_vertical;
833
834 rval = smiapp_write(
835 client, SMIAPP_REG_U8_BINNING_TYPE, binning_type);
836 if (rval < 0)
837 return rval;
838
839 binning_mode = 1;
840 }
841 rval = smiapp_write(client, SMIAPP_REG_U8_BINNING_MODE, binning_mode);
842 if (rval < 0)
843 return rval;
844
845 /* Get updated limits due to binning */
846 rval = smiapp_get_limits_binning(sensor);
847 if (rval < 0)
848 return rval;
849
850 rval = smiapp_pll_update(sensor);
851 if (rval < 0)
852 return rval;
853
854 /* Output from pixel array, including blanking */
855 smiapp_update_blanking(sensor);
856
857 dev_dbg(&client->dev, "vblank\t\t%d\n", sensor->vblank->val);
858 dev_dbg(&client->dev, "hblank\t\t%d\n", sensor->hblank->val);
859
860 dev_dbg(&client->dev, "real timeperframe\t100/%d\n",
861 sensor->pll.vt_pix_clk_freq_hz /
862 ((sensor->pixel_array->crop[SMIAPP_PA_PAD_SRC].width
863 + sensor->hblank->val) *
864 (sensor->pixel_array->crop[SMIAPP_PA_PAD_SRC].height
865 + sensor->vblank->val) / 100));
866
867 return 0;
868}
869
870/*
871 *
872 * SMIA++ NVM handling
873 *
874 */
875static int smiapp_read_nvm(struct smiapp_sensor *sensor,
876 unsigned char *nvm)
877{
878 struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
879 u32 i, s, p, np, v;
880 int rval, rval2;
881
882 np = sensor->nvm_size / SMIAPP_NVM_PAGE_SIZE;
883 for (p = 0; p < np; p++) {
884 rval = smiapp_write(
885 client,
886 SMIAPP_REG_U8_DATA_TRANSFER_IF_1_PAGE_SELECT, p);
887 if (rval)
888 goto out;
889
890 rval = smiapp_write(client,
891 SMIAPP_REG_U8_DATA_TRANSFER_IF_1_CTRL,
892 SMIAPP_DATA_TRANSFER_IF_1_CTRL_EN |
893 SMIAPP_DATA_TRANSFER_IF_1_CTRL_RD_EN);
894 if (rval)
895 goto out;
896
897 for (i = 0; i < 1000; i++) {
898 rval = smiapp_read(
899 client,
900 SMIAPP_REG_U8_DATA_TRANSFER_IF_1_STATUS, &s);
901
902 if (rval)
903 goto out;
904
905 if (s & SMIAPP_DATA_TRANSFER_IF_1_STATUS_RD_READY)
906 break;
907
908 if (--i == 0) {
909 rval = -ETIMEDOUT;
910 goto out;
911 }
912
913 }
914
915 for (i = 0; i < SMIAPP_NVM_PAGE_SIZE; i++) {
916 rval = smiapp_read(
917 client,
918 SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_0 + i,
919 &v);
920 if (rval)
921 goto out;
922
923 *nvm++ = v;
924 }
925 }
926
927out:
928 rval2 = smiapp_write(client, SMIAPP_REG_U8_DATA_TRANSFER_IF_1_CTRL, 0);
929 if (rval < 0)
930 return rval;
931 else
932 return rval2;
933}
934
935/*
936 *
937 * SMIA++ CCI address control
938 *
939 */
940static int smiapp_change_cci_addr(struct smiapp_sensor *sensor)
941{
942 struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
943 int rval;
944 u32 val;
945
946 client->addr = sensor->platform_data->i2c_addr_dfl;
947
948 rval = smiapp_write(client,
949 SMIAPP_REG_U8_CCI_ADDRESS_CONTROL,
950 sensor->platform_data->i2c_addr_alt << 1);
951 if (rval)
952 return rval;
953
954 client->addr = sensor->platform_data->i2c_addr_alt;
955
956 /* verify addr change went ok */
957 rval = smiapp_read(client, SMIAPP_REG_U8_CCI_ADDRESS_CONTROL, &val);
958 if (rval)
959 return rval;
960
961 if (val != sensor->platform_data->i2c_addr_alt << 1)
962 return -ENODEV;
963
964 return 0;
965}
966
967/*
968 *
969 * SMIA++ Mode Control
970 *
971 */
972static int smiapp_setup_flash_strobe(struct smiapp_sensor *sensor)
973{
974 struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
975 struct smiapp_flash_strobe_parms *strobe_setup;
976 unsigned int ext_freq = sensor->platform_data->ext_clk;
977 u32 tmp;
978 u32 strobe_adjustment;
979 u32 strobe_width_high_rs;
980 int rval;
981
982 strobe_setup = sensor->platform_data->strobe_setup;
983
984 /*
985 * How to calculate registers related to strobe length. Please
986 * do not change, or if you do at least know what you're
987 * doing. :-)
988 *
989 * Sakari Ailus <sakari.ailus@maxwell.research.nokia.com> 2010-10-25
990 *
991 * flash_strobe_length [us] / 10^6 = (tFlash_strobe_width_ctrl
992 * / EXTCLK freq [Hz]) * flash_strobe_adjustment
993 *
994 * tFlash_strobe_width_ctrl E N, [1 - 0xffff]
995 * flash_strobe_adjustment E N, [1 - 0xff]
996 *
997 * The formula above is written as below to keep it on one
998 * line:
999 *
1000 * l / 10^6 = w / e * a
1001 *
1002 * Let's mark w * a by x:
1003 *
1004 * x = w * a
1005 *
1006 * Thus, we get:
1007 *
1008 * x = l * e / 10^6
1009 *
1010 * The strobe width must be at least as long as requested,
1011 * thus rounding upwards is needed.
1012 *
1013 * x = (l * e + 10^6 - 1) / 10^6
1014 * -----------------------------
1015 *
1016 * Maximum possible accuracy is wanted at all times. Thus keep
1017 * a as small as possible.
1018 *
1019 * Calculate a, assuming maximum w, with rounding upwards:
1020 *
1021 * a = (x + (2^16 - 1) - 1) / (2^16 - 1)
1022 * -------------------------------------
1023 *
1024 * Thus, we also get w, with that a, with rounding upwards:
1025 *
1026 * w = (x + a - 1) / a
1027 * -------------------
1028 *
1029 * To get limits:
1030 *
1031 * x E [1, (2^16 - 1) * (2^8 - 1)]
1032 *
1033 * Substituting maximum x to the original formula (with rounding),
1034 * the maximum l is thus
1035 *
1036 * (2^16 - 1) * (2^8 - 1) * 10^6 = l * e + 10^6 - 1
1037 *
1038 * l = (10^6 * (2^16 - 1) * (2^8 - 1) - 10^6 + 1) / e
1039 * --------------------------------------------------
1040 *
1041 * flash_strobe_length must be clamped between 1 and
1042 * (10^6 * (2^16 - 1) * (2^8 - 1) - 10^6 + 1) / EXTCLK freq.
1043 *
1044 * Then,
1045 *
1046 * flash_strobe_adjustment = ((flash_strobe_length *
1047 * EXTCLK freq + 10^6 - 1) / 10^6 + (2^16 - 1) - 1) / (2^16 - 1)
1048 *
1049 * tFlash_strobe_width_ctrl = ((flash_strobe_length *
1050 * EXTCLK freq + 10^6 - 1) / 10^6 +
1051 * flash_strobe_adjustment - 1) / flash_strobe_adjustment
1052 */
1053 tmp = div_u64(1000000ULL * ((1 << 16) - 1) * ((1 << 8) - 1) -
1054 1000000 + 1, ext_freq);
1055 strobe_setup->strobe_width_high_us =
1056 clamp_t(u32, strobe_setup->strobe_width_high_us, 1, tmp);
1057
1058 tmp = div_u64(((u64)strobe_setup->strobe_width_high_us * (u64)ext_freq +
1059 1000000 - 1), 1000000ULL);
1060 strobe_adjustment = (tmp + (1 << 16) - 1 - 1) / ((1 << 16) - 1);
1061 strobe_width_high_rs = (tmp + strobe_adjustment - 1) /
1062 strobe_adjustment;
1063
1064 rval = smiapp_write(client, SMIAPP_REG_U8_FLASH_MODE_RS,
1065 strobe_setup->mode);
1066 if (rval < 0)
1067 goto out;
1068
1069 rval = smiapp_write(client, SMIAPP_REG_U8_FLASH_STROBE_ADJUSTMENT,
1070 strobe_adjustment);
1071 if (rval < 0)
1072 goto out;
1073
1074 rval = smiapp_write(
1075 client, SMIAPP_REG_U16_TFLASH_STROBE_WIDTH_HIGH_RS_CTRL,
1076 strobe_width_high_rs);
1077 if (rval < 0)
1078 goto out;
1079
1080 rval = smiapp_write(client, SMIAPP_REG_U16_TFLASH_STROBE_DELAY_RS_CTRL,
1081 strobe_setup->strobe_delay);
1082 if (rval < 0)
1083 goto out;
1084
1085 rval = smiapp_write(client, SMIAPP_REG_U16_FLASH_STROBE_START_POINT,
1086 strobe_setup->stobe_start_point);
1087 if (rval < 0)
1088 goto out;
1089
1090 rval = smiapp_write(client, SMIAPP_REG_U8_FLASH_TRIGGER_RS,
1091 strobe_setup->trigger);
1092
1093out:
1094 sensor->platform_data->strobe_setup->trigger = 0;
1095
1096 return rval;
1097}
1098
1099/* -----------------------------------------------------------------------------
1100 * Power management
1101 */
1102
1103static int smiapp_power_on(struct smiapp_sensor *sensor)
1104{
1105 struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
1106 unsigned int sleep;
1107 int rval;
1108
1109 rval = regulator_enable(sensor->vana);
1110 if (rval) {
1111 dev_err(&client->dev, "failed to enable vana regulator\n");
1112 return rval;
1113 }
1114 usleep_range(1000, 1000);
1115
1116 rval = sensor->platform_data->set_xclk(&sensor->src->sd,
1117 sensor->platform_data->ext_clk);
1118 if (rval < 0) {
1119 dev_dbg(&client->dev, "failed to set xclk\n");
1120 goto out_xclk_fail;
1121 }
1122 usleep_range(1000, 1000);
1123
1124 if (sensor->platform_data->xshutdown != SMIAPP_NO_XSHUTDOWN)
1125 gpio_set_value(sensor->platform_data->xshutdown, 1);
1126
1127 sleep = SMIAPP_RESET_DELAY(sensor->platform_data->ext_clk);
1128 usleep_range(sleep, sleep);
1129
1130 /*
1131 * Failures to respond to the address change command have been noticed.
1132 * Those failures seem to be caused by the sensor requiring a longer
1133 * boot time than advertised. An additional 10ms delay seems to work
1134 * around the issue, but the SMIA++ I2C write retry hack makes the delay
1135 * unnecessary. The failures need to be investigated to find a proper
1136 * fix, and a delay will likely need to be added here if the I2C write
1137 * retry hack is reverted before the root cause of the boot time issue
1138 * is found.
1139 */
1140
1141 if (sensor->platform_data->i2c_addr_alt) {
1142 rval = smiapp_change_cci_addr(sensor);
1143 if (rval) {
1144 dev_err(&client->dev, "cci address change error\n");
1145 goto out_cci_addr_fail;
1146 }
1147 }
1148
1149 rval = smiapp_write(client, SMIAPP_REG_U8_SOFTWARE_RESET,
1150 SMIAPP_SOFTWARE_RESET);
1151 if (rval < 0) {
1152 dev_err(&client->dev, "software reset failed\n");
1153 goto out_cci_addr_fail;
1154 }
1155
1156 if (sensor->platform_data->i2c_addr_alt) {
1157 rval = smiapp_change_cci_addr(sensor);
1158 if (rval) {
1159 dev_err(&client->dev, "cci address change error\n");
1160 goto out_cci_addr_fail;
1161 }
1162 }
1163
1164 rval = smiapp_write(client, SMIAPP_REG_U16_COMPRESSION_MODE,
1165 SMIAPP_COMPRESSION_MODE_SIMPLE_PREDICTOR);
1166 if (rval) {
1167 dev_err(&client->dev, "compression mode set failed\n");
1168 goto out_cci_addr_fail;
1169 }
1170
1171 rval = smiapp_write(
1172 client, SMIAPP_REG_U16_EXTCLK_FREQUENCY_MHZ,
1173 sensor->platform_data->ext_clk / (1000000 / (1 << 8)));
1174 if (rval) {
1175 dev_err(&client->dev, "extclk frequency set failed\n");
1176 goto out_cci_addr_fail;
1177 }
1178
1179 rval = smiapp_write(client, SMIAPP_REG_U8_CSI_LANE_MODE,
1180 sensor->platform_data->lanes - 1);
1181 if (rval) {
1182 dev_err(&client->dev, "csi lane mode set failed\n");
1183 goto out_cci_addr_fail;
1184 }
1185
1186 rval = smiapp_write(client, SMIAPP_REG_U8_FAST_STANDBY_CTRL,
1187 SMIAPP_FAST_STANDBY_CTRL_IMMEDIATE);
1188 if (rval) {
1189 dev_err(&client->dev, "fast standby set failed\n");
1190 goto out_cci_addr_fail;
1191 }
1192
1193 rval = smiapp_write(client, SMIAPP_REG_U8_CSI_SIGNALLING_MODE,
1194 sensor->platform_data->csi_signalling_mode);
1195 if (rval) {
1196 dev_err(&client->dev, "csi signalling mode set failed\n");
1197 goto out_cci_addr_fail;
1198 }
1199
1200 /* DPHY control done by sensor based on requested link rate */
1201 rval = smiapp_write(client, SMIAPP_REG_U8_DPHY_CTRL,
1202 SMIAPP_DPHY_CTRL_UI);
1203 if (rval < 0)
1204 return rval;
1205
1206 rval = smiapp_call_quirk(sensor, post_poweron);
1207 if (rval) {
1208 dev_err(&client->dev, "post_poweron quirks failed\n");
1209 goto out_cci_addr_fail;
1210 }
1211
1212 /* Are we still initialising...? If yes, return here. */
1213 if (!sensor->pixel_array)
1214 return 0;
1215
1216 rval = v4l2_ctrl_handler_setup(
1217 &sensor->pixel_array->ctrl_handler);
1218 if (rval)
1219 goto out_cci_addr_fail;
1220
1221 rval = v4l2_ctrl_handler_setup(&sensor->src->ctrl_handler);
1222 if (rval)
1223 goto out_cci_addr_fail;
1224
1225 mutex_lock(&sensor->mutex);
1226 rval = smiapp_update_mode(sensor);
1227 mutex_unlock(&sensor->mutex);
1228 if (rval < 0)
1229 goto out_cci_addr_fail;
1230
1231 return 0;
1232
1233out_cci_addr_fail:
1234 if (sensor->platform_data->xshutdown != SMIAPP_NO_XSHUTDOWN)
1235 gpio_set_value(sensor->platform_data->xshutdown, 0);
1236 sensor->platform_data->set_xclk(&sensor->src->sd, 0);
1237
1238out_xclk_fail:
1239 regulator_disable(sensor->vana);
1240 return rval;
1241}
1242
1243static void smiapp_power_off(struct smiapp_sensor *sensor)
1244{
1245 struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
1246
1247 /*
1248 * Currently power/clock to lens are enable/disabled separately
1249 * but they are essentially the same signals. So if the sensor is
1250 * powered off while the lens is powered on the sensor does not
1251 * really see a power off and next time the cci address change
1252 * will fail. So do a soft reset explicitly here.
1253 */
1254 if (sensor->platform_data->i2c_addr_alt)
1255 smiapp_write(client,
1256 SMIAPP_REG_U8_SOFTWARE_RESET,
1257 SMIAPP_SOFTWARE_RESET);
1258
1259 if (sensor->platform_data->xshutdown != SMIAPP_NO_XSHUTDOWN)
1260 gpio_set_value(sensor->platform_data->xshutdown, 0);
1261 sensor->platform_data->set_xclk(&sensor->src->sd, 0);
1262 usleep_range(5000, 5000);
1263 regulator_disable(sensor->vana);
1264 sensor->streaming = 0;
1265}
1266
1267static int smiapp_set_power(struct v4l2_subdev *subdev, int on)
1268{
1269 struct smiapp_sensor *sensor = to_smiapp_sensor(subdev);
1270 int ret = 0;
1271
1272 mutex_lock(&sensor->power_mutex);
1273
1274 /*
1275 * If the power count is modified from 0 to != 0 or from != 0
1276 * to 0, update the power state.
1277 */
1278 if (!sensor->power_count == !on)
1279 goto out;
1280
1281 if (on) {
1282 /* Power on and perform initialisation. */
1283 ret = smiapp_power_on(sensor);
1284 if (ret < 0)
1285 goto out;
1286 } else {
1287 smiapp_power_off(sensor);
1288 }
1289
1290 /* Update the power count. */
1291 sensor->power_count += on ? 1 : -1;
1292 WARN_ON(sensor->power_count < 0);
1293
1294out:
1295 mutex_unlock(&sensor->power_mutex);
1296 return ret;
1297}
1298
1299/* -----------------------------------------------------------------------------
1300 * Video stream management
1301 */
1302
1303static int smiapp_start_streaming(struct smiapp_sensor *sensor)
1304{
1305 struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
1306 int rval;
1307
1308 mutex_lock(&sensor->mutex);
1309
1310 rval = smiapp_write(client, SMIAPP_REG_U16_CSI_DATA_FORMAT,
1311 (sensor->csi_format->width << 8) |
1312 sensor->csi_format->compressed);
1313 if (rval)
1314 goto out;
1315
1316 rval = smiapp_pll_configure(sensor);
1317 if (rval)
1318 goto out;
1319
1320 /* Analog crop start coordinates */
1321 rval = smiapp_write(client, SMIAPP_REG_U16_X_ADDR_START,
1322 sensor->pixel_array->crop[SMIAPP_PA_PAD_SRC].left);
1323 if (rval < 0)
1324 goto out;
1325
1326 rval = smiapp_write(client, SMIAPP_REG_U16_Y_ADDR_START,
1327 sensor->pixel_array->crop[SMIAPP_PA_PAD_SRC].top);
1328 if (rval < 0)
1329 goto out;
1330
1331 /* Analog crop end coordinates */
1332 rval = smiapp_write(
1333 client, SMIAPP_REG_U16_X_ADDR_END,
1334 sensor->pixel_array->crop[SMIAPP_PA_PAD_SRC].left
1335 + sensor->pixel_array->crop[SMIAPP_PA_PAD_SRC].width - 1);
1336 if (rval < 0)
1337 goto out;
1338
1339 rval = smiapp_write(
1340 client, SMIAPP_REG_U16_Y_ADDR_END,
1341 sensor->pixel_array->crop[SMIAPP_PA_PAD_SRC].top
1342 + sensor->pixel_array->crop[SMIAPP_PA_PAD_SRC].height - 1);
1343 if (rval < 0)
1344 goto out;
1345
1346 /*
1347 * Output from pixel array, including blanking, is set using
1348 * controls below. No need to set here.
1349 */
1350
1351 /* Digital crop */
1352 if (sensor->limits[SMIAPP_LIMIT_DIGITAL_CROP_CAPABILITY]
1353 == SMIAPP_DIGITAL_CROP_CAPABILITY_INPUT_CROP) {
1354 rval = smiapp_write(
1355 client, SMIAPP_REG_U16_DIGITAL_CROP_X_OFFSET,
1356 sensor->scaler->crop[SMIAPP_PAD_SINK].left);
1357 if (rval < 0)
1358 goto out;
1359
1360 rval = smiapp_write(
1361 client, SMIAPP_REG_U16_DIGITAL_CROP_Y_OFFSET,
1362 sensor->scaler->crop[SMIAPP_PAD_SINK].top);
1363 if (rval < 0)
1364 goto out;
1365
1366 rval = smiapp_write(
1367 client, SMIAPP_REG_U16_DIGITAL_CROP_IMAGE_WIDTH,
1368 sensor->scaler->crop[SMIAPP_PAD_SINK].width);
1369 if (rval < 0)
1370 goto out;
1371
1372 rval = smiapp_write(
1373 client, SMIAPP_REG_U16_DIGITAL_CROP_IMAGE_HEIGHT,
1374 sensor->scaler->crop[SMIAPP_PAD_SINK].height);
1375 if (rval < 0)
1376 goto out;
1377 }
1378
1379 /* Scaling */
1380 if (sensor->limits[SMIAPP_LIMIT_SCALING_CAPABILITY]
1381 != SMIAPP_SCALING_CAPABILITY_NONE) {
1382 rval = smiapp_write(client, SMIAPP_REG_U16_SCALING_MODE,
1383 sensor->scaling_mode);
1384 if (rval < 0)
1385 goto out;
1386
1387 rval = smiapp_write(client, SMIAPP_REG_U16_SCALE_M,
1388 sensor->scale_m);
1389 if (rval < 0)
1390 goto out;
1391 }
1392
1393 /* Output size from sensor */
1394 rval = smiapp_write(client, SMIAPP_REG_U16_X_OUTPUT_SIZE,
1395 sensor->src->crop[SMIAPP_PAD_SRC].width);
1396 if (rval < 0)
1397 goto out;
1398 rval = smiapp_write(client, SMIAPP_REG_U16_Y_OUTPUT_SIZE,
1399 sensor->src->crop[SMIAPP_PAD_SRC].height);
1400 if (rval < 0)
1401 goto out;
1402
1403 if ((sensor->flash_capability &
1404 (SMIAPP_FLASH_MODE_CAPABILITY_SINGLE_STROBE |
1405 SMIAPP_FLASH_MODE_CAPABILITY_MULTIPLE_STROBE)) &&
1406 sensor->platform_data->strobe_setup != NULL &&
1407 sensor->platform_data->strobe_setup->trigger != 0) {
1408 rval = smiapp_setup_flash_strobe(sensor);
1409 if (rval)
1410 goto out;
1411 }
1412
1413 rval = smiapp_call_quirk(sensor, pre_streamon);
1414 if (rval) {
1415 dev_err(&client->dev, "pre_streamon quirks failed\n");
1416 goto out;
1417 }
1418
1419 rval = smiapp_write(client, SMIAPP_REG_U8_MODE_SELECT,
1420 SMIAPP_MODE_SELECT_STREAMING);
1421
1422out:
1423 mutex_unlock(&sensor->mutex);
1424
1425 return rval;
1426}
1427
1428static int smiapp_stop_streaming(struct smiapp_sensor *sensor)
1429{
1430 struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
1431 int rval;
1432
1433 mutex_lock(&sensor->mutex);
1434 rval = smiapp_write(client, SMIAPP_REG_U8_MODE_SELECT,
1435 SMIAPP_MODE_SELECT_SOFTWARE_STANDBY);
1436 if (rval)
1437 goto out;
1438
1439 rval = smiapp_call_quirk(sensor, post_streamoff);
1440 if (rval)
1441 dev_err(&client->dev, "post_streamoff quirks failed\n");
1442
1443out:
1444 mutex_unlock(&sensor->mutex);
1445 return rval;
1446}
1447
1448/* -----------------------------------------------------------------------------
1449 * V4L2 subdev video operations
1450 */
1451
1452static int smiapp_set_stream(struct v4l2_subdev *subdev, int enable)
1453{
1454 struct smiapp_sensor *sensor = to_smiapp_sensor(subdev);
1455 int rval;
1456
1457 if (sensor->streaming == enable)
1458 return 0;
1459
1460 if (enable) {
1461 sensor->streaming = 1;
1462 rval = smiapp_start_streaming(sensor);
1463 if (rval < 0)
1464 sensor->streaming = 0;
1465 } else {
1466 rval = smiapp_stop_streaming(sensor);
1467 sensor->streaming = 0;
1468 }
1469
1470 return rval;
1471}
1472
1473static int smiapp_enum_mbus_code(struct v4l2_subdev *subdev,
1474 struct v4l2_subdev_fh *fh,
1475 struct v4l2_subdev_mbus_code_enum *code)
1476{
1477 struct i2c_client *client = v4l2_get_subdevdata(subdev);
1478 struct smiapp_sensor *sensor = to_smiapp_sensor(subdev);
1479 unsigned int i;
1480 int idx = -1;
1481 int rval = -EINVAL;
1482
1483 mutex_lock(&sensor->mutex);
1484
1485 dev_err(&client->dev, "subdev %s, pad %d, index %d\n",
1486 subdev->name, code->pad, code->index);
1487
1488 if (subdev != &sensor->src->sd || code->pad != SMIAPP_PAD_SRC) {
1489 if (code->index)
1490 goto out;
1491
1492 code->code = sensor->internal_csi_format->code;
1493 rval = 0;
1494 goto out;
1495 }
1496
1497 for (i = 0; i < ARRAY_SIZE(smiapp_csi_data_formats); i++) {
1498 if (sensor->mbus_frame_fmts & (1 << i))
1499 idx++;
1500
1501 if (idx == code->index) {
1502 code->code = smiapp_csi_data_formats[i].code;
1503 dev_err(&client->dev, "found index %d, i %d, code %x\n",
1504 code->index, i, code->code);
1505 rval = 0;
1506 break;
1507 }
1508 }
1509
1510out:
1511 mutex_unlock(&sensor->mutex);
1512
1513 return rval;
1514}
1515
1516static u32 __smiapp_get_mbus_code(struct v4l2_subdev *subdev,
1517 unsigned int pad)
1518{
1519 struct smiapp_sensor *sensor = to_smiapp_sensor(subdev);
1520
1521 if (subdev == &sensor->src->sd && pad == SMIAPP_PAD_SRC)
1522 return sensor->csi_format->code;
1523 else
1524 return sensor->internal_csi_format->code;
1525}
1526
1527static int __smiapp_get_format(struct v4l2_subdev *subdev,
1528 struct v4l2_subdev_fh *fh,
1529 struct v4l2_subdev_format *fmt)
1530{
1531 struct smiapp_subdev *ssd = to_smiapp_subdev(subdev);
1532
1533 if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
1534 fmt->format = *v4l2_subdev_get_try_format(fh, fmt->pad);
1535 } else {
1536 struct v4l2_rect *r;
1537
1538 if (fmt->pad == ssd->source_pad)
1539 r = &ssd->crop[ssd->source_pad];
1540 else
1541 r = &ssd->sink_fmt;
1542
1543 fmt->format.code = __smiapp_get_mbus_code(subdev, fmt->pad);
1544 fmt->format.width = r->width;
1545 fmt->format.height = r->height;
1546 }
1547
1548 return 0;
1549}
1550
1551static int smiapp_get_format(struct v4l2_subdev *subdev,
1552 struct v4l2_subdev_fh *fh,
1553 struct v4l2_subdev_format *fmt)
1554{
1555 struct smiapp_sensor *sensor = to_smiapp_sensor(subdev);
1556 int rval;
1557
1558 mutex_lock(&sensor->mutex);
1559 rval = __smiapp_get_format(subdev, fh, fmt);
1560 mutex_unlock(&sensor->mutex);
1561
1562 return rval;
1563}
1564
1565static void smiapp_get_crop_compose(struct v4l2_subdev *subdev,
1566 struct v4l2_subdev_fh *fh,
1567 struct v4l2_rect **crops,
1568 struct v4l2_rect **comps, int which)
1569{
1570 struct smiapp_subdev *ssd = to_smiapp_subdev(subdev);
1571 unsigned int i;
1572
1573 if (which == V4L2_SUBDEV_FORMAT_ACTIVE) {
1574 if (crops)
1575 for (i = 0; i < subdev->entity.num_pads; i++)
1576 crops[i] = &ssd->crop[i];
1577 if (comps)
1578 *comps = &ssd->compose;
1579 } else {
1580 if (crops) {
1581 for (i = 0; i < subdev->entity.num_pads; i++) {
1582 crops[i] = v4l2_subdev_get_try_crop(fh, i);
1583 BUG_ON(!crops[i]);
1584 }
1585 }
1586 if (comps) {
1587 *comps = v4l2_subdev_get_try_compose(fh,
1588 SMIAPP_PAD_SINK);
1589 BUG_ON(!*comps);
1590 }
1591 }
1592}
1593
1594/* Changes require propagation only on sink pad. */
1595static void smiapp_propagate(struct v4l2_subdev *subdev,
1596 struct v4l2_subdev_fh *fh, int which,
1597 int target)
1598{
1599 struct smiapp_sensor *sensor = to_smiapp_sensor(subdev);
1600 struct smiapp_subdev *ssd = to_smiapp_subdev(subdev);
1601 struct v4l2_rect *comp, *crops[SMIAPP_PADS];
1602
1603 smiapp_get_crop_compose(subdev, fh, crops, &comp, which);
1604
1605 switch (target) {
1606 case V4L2_SUBDEV_SEL_TGT_CROP_ACTUAL:
1607 comp->width = crops[SMIAPP_PAD_SINK]->width;
1608 comp->height = crops[SMIAPP_PAD_SINK]->height;
1609 if (which == V4L2_SUBDEV_FORMAT_ACTIVE) {
1610 if (ssd == sensor->scaler) {
1611 sensor->scale_m =
1612 sensor->limits[
1613 SMIAPP_LIMIT_SCALER_N_MIN];
1614 sensor->scaling_mode =
1615 SMIAPP_SCALING_MODE_NONE;
1616 } else if (ssd == sensor->binner) {
1617 sensor->binning_horizontal = 1;
1618 sensor->binning_vertical = 1;
1619 }
1620 }
1621 /* Fall through */
1622 case V4L2_SUBDEV_SEL_TGT_COMPOSE_ACTUAL:
1623 *crops[SMIAPP_PAD_SRC] = *comp;
1624 break;
1625 default:
1626 BUG();
1627 }
1628}
1629
1630static const struct smiapp_csi_data_format
1631*smiapp_validate_csi_data_format(struct smiapp_sensor *sensor, u32 code)
1632{
1633 const struct smiapp_csi_data_format *csi_format = sensor->csi_format;
1634 unsigned int i;
1635
1636 for (i = 0; i < ARRAY_SIZE(smiapp_csi_data_formats); i++) {
1637 if (sensor->mbus_frame_fmts & (1 << i)
1638 && smiapp_csi_data_formats[i].code == code)
1639 return &smiapp_csi_data_formats[i];
1640 }
1641
1642 return csi_format;
1643}
1644
1645static int smiapp_set_format(struct v4l2_subdev *subdev,
1646 struct v4l2_subdev_fh *fh,
1647 struct v4l2_subdev_format *fmt)
1648{
1649 struct smiapp_sensor *sensor = to_smiapp_sensor(subdev);
1650 struct smiapp_subdev *ssd = to_smiapp_subdev(subdev);
1651 struct v4l2_rect *crops[SMIAPP_PADS];
1652
1653 mutex_lock(&sensor->mutex);
1654
1655 /*
1656 * Media bus code is changeable on src subdev's source pad. On
1657 * other source pads we just get format here.
1658 */
1659 if (fmt->pad == ssd->source_pad) {
1660 u32 code = fmt->format.code;
1661 int rval = __smiapp_get_format(subdev, fh, fmt);
1662
1663 if (!rval && subdev == &sensor->src->sd) {
1664 const struct smiapp_csi_data_format *csi_format =
1665 smiapp_validate_csi_data_format(sensor, code);
1666 if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE)
1667 sensor->csi_format = csi_format;
1668 fmt->format.code = csi_format->code;
1669 }
1670
1671 mutex_unlock(&sensor->mutex);
1672 return rval;
1673 }
1674
1675 /* Sink pad. Width and height are changeable here. */
1676 fmt->format.code = __smiapp_get_mbus_code(subdev, fmt->pad);
1677 fmt->format.width &= ~1;
1678 fmt->format.height &= ~1;
1679
1680 fmt->format.width =
1681 clamp(fmt->format.width,
1682 sensor->limits[SMIAPP_LIMIT_MIN_X_OUTPUT_SIZE],
1683 sensor->limits[SMIAPP_LIMIT_MAX_X_OUTPUT_SIZE]);
1684 fmt->format.height =
1685 clamp(fmt->format.height,
1686 sensor->limits[SMIAPP_LIMIT_MIN_Y_OUTPUT_SIZE],
1687 sensor->limits[SMIAPP_LIMIT_MAX_Y_OUTPUT_SIZE]);
1688
1689 smiapp_get_crop_compose(subdev, fh, crops, NULL, fmt->which);
1690
1691 crops[ssd->sink_pad]->left = 0;
1692 crops[ssd->sink_pad]->top = 0;
1693 crops[ssd->sink_pad]->width = fmt->format.width;
1694 crops[ssd->sink_pad]->height = fmt->format.height;
1695 if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE)
1696 ssd->sink_fmt = *crops[ssd->sink_pad];
1697 smiapp_propagate(subdev, fh, fmt->which,
1698 V4L2_SUBDEV_SEL_TGT_CROP_ACTUAL);
1699
1700 mutex_unlock(&sensor->mutex);
1701
1702 return 0;
1703}
1704
1705/*
1706 * Calculate goodness of scaled image size compared to expected image
1707 * size and flags provided.
1708 */
1709#define SCALING_GOODNESS 100000
1710#define SCALING_GOODNESS_EXTREME 100000000
1711static int scaling_goodness(struct v4l2_subdev *subdev, int w, int ask_w,
1712 int h, int ask_h, u32 flags)
1713{
1714 struct smiapp_sensor *sensor = to_smiapp_sensor(subdev);
1715 struct i2c_client *client = v4l2_get_subdevdata(subdev);
1716 int val = 0;
1717
1718 w &= ~1;
1719 ask_w &= ~1;
1720 h &= ~1;
1721 ask_h &= ~1;
1722
1723 if (flags & V4L2_SUBDEV_SEL_FLAG_SIZE_GE) {
1724 if (w < ask_w)
1725 val -= SCALING_GOODNESS;
1726 if (h < ask_h)
1727 val -= SCALING_GOODNESS;
1728 }
1729
1730 if (flags & V4L2_SUBDEV_SEL_FLAG_SIZE_LE) {
1731 if (w > ask_w)
1732 val -= SCALING_GOODNESS;
1733 if (h > ask_h)
1734 val -= SCALING_GOODNESS;
1735 }
1736
1737 val -= abs(w - ask_w);
1738 val -= abs(h - ask_h);
1739
1740 if (w < sensor->limits[SMIAPP_LIMIT_MIN_X_OUTPUT_SIZE])
1741 val -= SCALING_GOODNESS_EXTREME;
1742
1743 dev_dbg(&client->dev, "w %d ask_w %d h %d ask_h %d goodness %d\n",
1744 w, ask_h, h, ask_h, val);
1745
1746 return val;
1747}
1748
1749static void smiapp_set_compose_binner(struct v4l2_subdev *subdev,
1750 struct v4l2_subdev_fh *fh,
1751 struct v4l2_subdev_selection *sel,
1752 struct v4l2_rect **crops,
1753 struct v4l2_rect *comp)
1754{
1755 struct smiapp_sensor *sensor = to_smiapp_sensor(subdev);
1756 unsigned int i;
1757 unsigned int binh = 1, binv = 1;
1758 unsigned int best = scaling_goodness(
1759 subdev,
1760 crops[SMIAPP_PAD_SINK]->width, sel->r.width,
1761 crops[SMIAPP_PAD_SINK]->height, sel->r.height, sel->flags);
1762
1763 for (i = 0; i < sensor->nbinning_subtypes; i++) {
1764 int this = scaling_goodness(
1765 subdev,
1766 crops[SMIAPP_PAD_SINK]->width
1767 / sensor->binning_subtypes[i].horizontal,
1768 sel->r.width,
1769 crops[SMIAPP_PAD_SINK]->height
1770 / sensor->binning_subtypes[i].vertical,
1771 sel->r.height, sel->flags);
1772
1773 if (this > best) {
1774 binh = sensor->binning_subtypes[i].horizontal;
1775 binv = sensor->binning_subtypes[i].vertical;
1776 best = this;
1777 }
1778 }
1779 if (sel->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
1780 sensor->binning_vertical = binv;
1781 sensor->binning_horizontal = binh;
1782 }
1783
1784 sel->r.width = (crops[SMIAPP_PAD_SINK]->width / binh) & ~1;
1785 sel->r.height = (crops[SMIAPP_PAD_SINK]->height / binv) & ~1;
1786}
1787
1788/*
1789 * Calculate best scaling ratio and mode for given output resolution.
1790 *
1791 * Try all of these: horizontal ratio, vertical ratio and smallest
1792 * size possible (horizontally).
1793 *
1794 * Also try whether horizontal scaler or full scaler gives a better
1795 * result.
1796 */
1797static void smiapp_set_compose_scaler(struct v4l2_subdev *subdev,
1798 struct v4l2_subdev_fh *fh,
1799 struct v4l2_subdev_selection *sel,
1800 struct v4l2_rect **crops,
1801 struct v4l2_rect *comp)
1802{
1803 struct i2c_client *client = v4l2_get_subdevdata(subdev);
1804 struct smiapp_sensor *sensor = to_smiapp_sensor(subdev);
1805 u32 min, max, a, b, max_m;
1806 u32 scale_m = sensor->limits[SMIAPP_LIMIT_SCALER_N_MIN];
1807 int mode = SMIAPP_SCALING_MODE_HORIZONTAL;
1808 u32 try[4];
1809 u32 ntry = 0;
1810 unsigned int i;
1811 int best = INT_MIN;
1812
1813 sel->r.width = min_t(unsigned int, sel->r.width,
1814 crops[SMIAPP_PAD_SINK]->width);
1815 sel->r.height = min_t(unsigned int, sel->r.height,
1816 crops[SMIAPP_PAD_SINK]->height);
1817
1818 a = crops[SMIAPP_PAD_SINK]->width
1819 * sensor->limits[SMIAPP_LIMIT_SCALER_N_MIN] / sel->r.width;
1820 b = crops[SMIAPP_PAD_SINK]->height
1821 * sensor->limits[SMIAPP_LIMIT_SCALER_N_MIN] / sel->r.height;
1822 max_m = crops[SMIAPP_PAD_SINK]->width
1823 * sensor->limits[SMIAPP_LIMIT_SCALER_N_MIN]
1824 / sensor->limits[SMIAPP_LIMIT_MIN_X_OUTPUT_SIZE];
1825
1826 a = min(sensor->limits[SMIAPP_LIMIT_SCALER_M_MAX],
1827 max(a, sensor->limits[SMIAPP_LIMIT_SCALER_M_MIN]));
1828 b = min(sensor->limits[SMIAPP_LIMIT_SCALER_M_MAX],
1829 max(b, sensor->limits[SMIAPP_LIMIT_SCALER_M_MIN]));
1830 max_m = min(sensor->limits[SMIAPP_LIMIT_SCALER_M_MAX],
1831 max(max_m, sensor->limits[SMIAPP_LIMIT_SCALER_M_MIN]));
1832
1833 dev_dbg(&client->dev, "scaling: a %d b %d max_m %d\n", a, b, max_m);
1834
1835 min = min(max_m, min(a, b));
1836 max = min(max_m, max(a, b));
1837
1838 try[ntry] = min;
1839 ntry++;
1840 if (min != max) {
1841 try[ntry] = max;
1842 ntry++;
1843 }
1844 if (max != max_m) {
1845 try[ntry] = min + 1;
1846 ntry++;
1847 if (min != max) {
1848 try[ntry] = max + 1;
1849 ntry++;
1850 }
1851 }
1852
1853 for (i = 0; i < ntry; i++) {
1854 int this = scaling_goodness(
1855 subdev,
1856 crops[SMIAPP_PAD_SINK]->width
1857 / try[i]
1858 * sensor->limits[SMIAPP_LIMIT_SCALER_N_MIN],
1859 sel->r.width,
1860 crops[SMIAPP_PAD_SINK]->height,
1861 sel->r.height,
1862 sel->flags);
1863
1864 dev_dbg(&client->dev, "trying factor %d (%d)\n", try[i], i);
1865
1866 if (this > best) {
1867 scale_m = try[i];
1868 mode = SMIAPP_SCALING_MODE_HORIZONTAL;
1869 best = this;
1870 }
1871
1872 if (sensor->limits[SMIAPP_LIMIT_SCALING_CAPABILITY]
1873 == SMIAPP_SCALING_CAPABILITY_HORIZONTAL)
1874 continue;
1875
1876 this = scaling_goodness(
1877 subdev, crops[SMIAPP_PAD_SINK]->width
1878 / try[i]
1879 * sensor->limits[SMIAPP_LIMIT_SCALER_N_MIN],
1880 sel->r.width,
1881 crops[SMIAPP_PAD_SINK]->height
1882 / try[i]
1883 * sensor->limits[SMIAPP_LIMIT_SCALER_N_MIN],
1884 sel->r.height,
1885 sel->flags);
1886
1887 if (this > best) {
1888 scale_m = try[i];
1889 mode = SMIAPP_SCALING_MODE_BOTH;
1890 best = this;
1891 }
1892 }
1893
1894 sel->r.width =
1895 (crops[SMIAPP_PAD_SINK]->width
1896 / scale_m
1897 * sensor->limits[SMIAPP_LIMIT_SCALER_N_MIN]) & ~1;
1898 if (mode == SMIAPP_SCALING_MODE_BOTH)
1899 sel->r.height =
1900 (crops[SMIAPP_PAD_SINK]->height
1901 / scale_m
1902 * sensor->limits[SMIAPP_LIMIT_SCALER_N_MIN])
1903 & ~1;
1904 else
1905 sel->r.height = crops[SMIAPP_PAD_SINK]->height;
1906
1907 if (sel->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
1908 sensor->scale_m = scale_m;
1909 sensor->scaling_mode = mode;
1910 }
1911}
1912/* We're only called on source pads. This function sets scaling. */
1913static int smiapp_set_compose(struct v4l2_subdev *subdev,
1914 struct v4l2_subdev_fh *fh,
1915 struct v4l2_subdev_selection *sel)
1916{
1917 struct smiapp_sensor *sensor = to_smiapp_sensor(subdev);
1918 struct smiapp_subdev *ssd = to_smiapp_subdev(subdev);
1919 struct v4l2_rect *comp, *crops[SMIAPP_PADS];
1920
1921 smiapp_get_crop_compose(subdev, fh, crops, &comp, sel->which);
1922
1923 sel->r.top = 0;
1924 sel->r.left = 0;
1925
1926 if (ssd == sensor->binner)
1927 smiapp_set_compose_binner(subdev, fh, sel, crops, comp);
1928 else
1929 smiapp_set_compose_scaler(subdev, fh, sel, crops, comp);
1930
1931 *comp = sel->r;
1932 smiapp_propagate(subdev, fh, sel->which,
1933 V4L2_SUBDEV_SEL_TGT_COMPOSE_ACTUAL);
1934
1935 if (sel->which == V4L2_SUBDEV_FORMAT_ACTIVE)
1936 return smiapp_update_mode(sensor);
1937
1938 return 0;
1939}
1940
1941static int __smiapp_sel_supported(struct v4l2_subdev *subdev,
1942 struct v4l2_subdev_selection *sel)
1943{
1944 struct smiapp_sensor *sensor = to_smiapp_sensor(subdev);
1945 struct smiapp_subdev *ssd = to_smiapp_subdev(subdev);
1946
1947 /* We only implement crop in three places. */
1948 switch (sel->target) {
1949 case V4L2_SUBDEV_SEL_TGT_CROP_ACTUAL:
1950 case V4L2_SUBDEV_SEL_TGT_CROP_BOUNDS:
1951 if (ssd == sensor->pixel_array
1952 && sel->pad == SMIAPP_PA_PAD_SRC)
1953 return 0;
1954 if (ssd == sensor->src
1955 && sel->pad == SMIAPP_PAD_SRC)
1956 return 0;
1957 if (ssd == sensor->scaler
1958 && sel->pad == SMIAPP_PAD_SINK
1959 && sensor->limits[SMIAPP_LIMIT_DIGITAL_CROP_CAPABILITY]
1960 == SMIAPP_DIGITAL_CROP_CAPABILITY_INPUT_CROP)
1961 return 0;
1962 return -EINVAL;
1963 case V4L2_SUBDEV_SEL_TGT_COMPOSE_ACTUAL:
1964 case V4L2_SUBDEV_SEL_TGT_COMPOSE_BOUNDS:
1965 if (sel->pad == ssd->source_pad)
1966 return -EINVAL;
1967 if (ssd == sensor->binner)
1968 return 0;
1969 if (ssd == sensor->scaler
1970 && sensor->limits[SMIAPP_LIMIT_SCALING_CAPABILITY]
1971 != SMIAPP_SCALING_CAPABILITY_NONE)
1972 return 0;
1973 /* Fall through */
1974 default:
1975 return -EINVAL;
1976 }
1977}
1978
1979static int smiapp_set_crop(struct v4l2_subdev *subdev,
1980 struct v4l2_subdev_fh *fh,
1981 struct v4l2_subdev_selection *sel)
1982{
1983 struct smiapp_sensor *sensor = to_smiapp_sensor(subdev);
1984 struct smiapp_subdev *ssd = to_smiapp_subdev(subdev);
1985 struct v4l2_rect *src_size, *crops[SMIAPP_PADS];
1986 struct v4l2_rect _r;
1987
1988 smiapp_get_crop_compose(subdev, fh, crops, NULL, sel->which);
1989
1990 if (sel->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
1991 if (sel->pad == ssd->sink_pad)
1992 src_size = &ssd->sink_fmt;
1993 else
1994 src_size = &ssd->compose;
1995 } else {
1996 if (sel->pad == ssd->sink_pad) {
1997 _r.left = 0;
1998 _r.top = 0;
1999 _r.width = v4l2_subdev_get_try_format(fh, sel->pad)
2000 ->width;
2001 _r.height = v4l2_subdev_get_try_format(fh, sel->pad)
2002 ->height;
2003 src_size = &_r;
2004 } else {
2005 src_size =
2006 v4l2_subdev_get_try_compose(
2007 fh, ssd->sink_pad);
2008 }
2009 }
2010
2011 if (ssd == sensor->src && sel->pad == SMIAPP_PAD_SRC) {
2012 sel->r.left = 0;
2013 sel->r.top = 0;
2014 }
2015
2016 sel->r.width = min(sel->r.width, src_size->width);
2017 sel->r.height = min(sel->r.height, src_size->height);
2018
2019 sel->r.left = min(sel->r.left, src_size->width - sel->r.width);
2020 sel->r.top = min(sel->r.top, src_size->height - sel->r.height);
2021
2022 *crops[sel->pad] = sel->r;
2023
2024 if (ssd != sensor->pixel_array && sel->pad == SMIAPP_PAD_SINK)
2025 smiapp_propagate(subdev, fh, sel->which,
2026 V4L2_SUBDEV_SEL_TGT_CROP_ACTUAL);
2027
2028 return 0;
2029}
2030
2031static int __smiapp_get_selection(struct v4l2_subdev *subdev,
2032 struct v4l2_subdev_fh *fh,
2033 struct v4l2_subdev_selection *sel)
2034{
2035 struct smiapp_sensor *sensor = to_smiapp_sensor(subdev);
2036 struct smiapp_subdev *ssd = to_smiapp_subdev(subdev);
2037 struct v4l2_rect *comp, *crops[SMIAPP_PADS];
2038 struct v4l2_rect sink_fmt;
2039 int ret;
2040
2041 ret = __smiapp_sel_supported(subdev, sel);
2042 if (ret)
2043 return ret;
2044
2045 smiapp_get_crop_compose(subdev, fh, crops, &comp, sel->which);
2046
2047 if (sel->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
2048 sink_fmt = ssd->sink_fmt;
2049 } else {
2050 struct v4l2_mbus_framefmt *fmt =
2051 v4l2_subdev_get_try_format(fh, ssd->sink_pad);
2052
2053 sink_fmt.left = 0;
2054 sink_fmt.top = 0;
2055 sink_fmt.width = fmt->width;
2056 sink_fmt.height = fmt->height;
2057 }
2058
2059 switch (sel->target) {
2060 case V4L2_SUBDEV_SEL_TGT_CROP_BOUNDS:
2061 if (ssd == sensor->pixel_array) {
2062 sel->r.width =
2063 sensor->limits[SMIAPP_LIMIT_X_ADDR_MAX] + 1;
2064 sel->r.height =
2065 sensor->limits[SMIAPP_LIMIT_Y_ADDR_MAX] + 1;
2066 } else if (sel->pad == ssd->sink_pad) {
2067 sel->r = sink_fmt;
2068 } else {
2069 sel->r = *comp;
2070 }
2071 break;
2072 case V4L2_SUBDEV_SEL_TGT_CROP_ACTUAL:
2073 case V4L2_SUBDEV_SEL_TGT_COMPOSE_BOUNDS:
2074 sel->r = *crops[sel->pad];
2075 break;
2076 case V4L2_SUBDEV_SEL_TGT_COMPOSE_ACTUAL:
2077 sel->r = *comp;
2078 break;
2079 }
2080
2081 return 0;
2082}
2083
2084static int smiapp_get_selection(struct v4l2_subdev *subdev,
2085 struct v4l2_subdev_fh *fh,
2086 struct v4l2_subdev_selection *sel)
2087{
2088 struct smiapp_sensor *sensor = to_smiapp_sensor(subdev);
2089 int rval;
2090
2091 mutex_lock(&sensor->mutex);
2092 rval = __smiapp_get_selection(subdev, fh, sel);
2093 mutex_unlock(&sensor->mutex);
2094
2095 return rval;
2096}
2097static int smiapp_set_selection(struct v4l2_subdev *subdev,
2098 struct v4l2_subdev_fh *fh,
2099 struct v4l2_subdev_selection *sel)
2100{
2101 struct smiapp_sensor *sensor = to_smiapp_sensor(subdev);
2102 int ret;
2103
2104 ret = __smiapp_sel_supported(subdev, sel);
2105 if (ret)
2106 return ret;
2107
2108 mutex_lock(&sensor->mutex);
2109
2110 sel->r.left = max(0, sel->r.left & ~1);
2111 sel->r.top = max(0, sel->r.top & ~1);
2112 sel->r.width = max(0, SMIAPP_ALIGN_DIM(sel->r.width, sel->flags));
2113 sel->r.height = max(0, SMIAPP_ALIGN_DIM(sel->r.height, sel->flags));
2114
2115 sel->r.width = max_t(unsigned int,
2116 sensor->limits[SMIAPP_LIMIT_MIN_X_OUTPUT_SIZE],
2117 sel->r.width);
2118 sel->r.height = max_t(unsigned int,
2119 sensor->limits[SMIAPP_LIMIT_MIN_Y_OUTPUT_SIZE],
2120 sel->r.height);
2121
2122 switch (sel->target) {
2123 case V4L2_SUBDEV_SEL_TGT_CROP_ACTUAL:
2124 ret = smiapp_set_crop(subdev, fh, sel);
2125 break;
2126 case V4L2_SUBDEV_SEL_TGT_COMPOSE_ACTUAL:
2127 ret = smiapp_set_compose(subdev, fh, sel);
2128 break;
2129 default:
2130 BUG();
2131 }
2132
2133 mutex_unlock(&sensor->mutex);
2134 return ret;
2135}
2136
2137static int smiapp_get_skip_frames(struct v4l2_subdev *subdev, u32 *frames)
2138{
2139 struct smiapp_sensor *sensor = to_smiapp_sensor(subdev);
2140
2141 *frames = sensor->frame_skip;
2142 return 0;
2143}
2144
2145/* -----------------------------------------------------------------------------
2146 * sysfs attributes
2147 */
2148
2149static ssize_t
2150smiapp_sysfs_nvm_read(struct device *dev, struct device_attribute *attr,
2151 char *buf)
2152{
2153 struct v4l2_subdev *subdev = i2c_get_clientdata(to_i2c_client(dev));
2154 struct i2c_client *client = v4l2_get_subdevdata(subdev);
2155 struct smiapp_sensor *sensor = to_smiapp_sensor(subdev);
2156 unsigned int nbytes;
2157
2158 if (!sensor->dev_init_done)
2159 return -EBUSY;
2160
2161 if (!sensor->nvm_size) {
2162 /* NVM not read yet - read it now */
2163 sensor->nvm_size = sensor->platform_data->nvm_size;
2164 if (smiapp_set_power(subdev, 1) < 0)
2165 return -ENODEV;
2166 if (smiapp_read_nvm(sensor, sensor->nvm)) {
2167 dev_err(&client->dev, "nvm read failed\n");
2168 return -ENODEV;
2169 }
2170 smiapp_set_power(subdev, 0);
2171 }
2172 /*
2173 * NVM is still way below a PAGE_SIZE, so we can safely
2174 * assume this for now.
2175 */
2176 nbytes = min_t(unsigned int, sensor->nvm_size, PAGE_SIZE);
2177 memcpy(buf, sensor->nvm, nbytes);
2178
2179 return nbytes;
2180}
2181static DEVICE_ATTR(nvm, S_IRUGO, smiapp_sysfs_nvm_read, NULL);
2182
2183/* -----------------------------------------------------------------------------
2184 * V4L2 subdev core operations
2185 */
2186
2187static int smiapp_identify_module(struct v4l2_subdev *subdev)
2188{
2189 struct smiapp_sensor *sensor = to_smiapp_sensor(subdev);
2190 struct i2c_client *client = v4l2_get_subdevdata(subdev);
2191 struct smiapp_module_info *minfo = &sensor->minfo;
2192 unsigned int i;
2193 int rval = 0;
2194
2195 minfo->name = SMIAPP_NAME;
2196
2197 /* Module info */
2198 rval = smiapp_read(client, SMIAPP_REG_U8_MANUFACTURER_ID,
2199 &minfo->manufacturer_id);
2200 if (!rval)
2201 rval = smiapp_read(client, SMIAPP_REG_U16_MODEL_ID,
2202 &minfo->model_id);
2203 if (!rval)
2204 rval = smiapp_read(client, SMIAPP_REG_U8_REVISION_NUMBER_MAJOR,
2205 &minfo->revision_number_major);
2206 if (!rval)
2207 rval = smiapp_read(client, SMIAPP_REG_U8_REVISION_NUMBER_MINOR,
2208 &minfo->revision_number_minor);
2209 if (!rval)
2210 rval = smiapp_read(client, SMIAPP_REG_U8_MODULE_DATE_YEAR,
2211 &minfo->module_year);
2212 if (!rval)
2213 rval = smiapp_read(client, SMIAPP_REG_U8_MODULE_DATE_MONTH,
2214 &minfo->module_month);
2215 if (!rval)
2216 rval = smiapp_read(client, SMIAPP_REG_U8_MODULE_DATE_DAY,
2217 &minfo->module_day);
2218
2219 /* Sensor info */
2220 if (!rval)
2221 rval = smiapp_read(client,
2222 SMIAPP_REG_U8_SENSOR_MANUFACTURER_ID,
2223 &minfo->sensor_manufacturer_id);
2224 if (!rval)
2225 rval = smiapp_read(client, SMIAPP_REG_U16_SENSOR_MODEL_ID,
2226 &minfo->sensor_model_id);
2227 if (!rval)
2228 rval = smiapp_read(client,
2229 SMIAPP_REG_U8_SENSOR_REVISION_NUMBER,
2230 &minfo->sensor_revision_number);
2231 if (!rval)
2232 rval = smiapp_read(client,
2233 SMIAPP_REG_U8_SENSOR_FIRMWARE_VERSION,
2234 &minfo->sensor_firmware_version);
2235
2236 /* SMIA */
2237 if (!rval)
2238 rval = smiapp_read(client, SMIAPP_REG_U8_SMIA_VERSION,
2239 &minfo->smia_version);
2240 if (!rval)
2241 rval = smiapp_read(client, SMIAPP_REG_U8_SMIAPP_VERSION,
2242 &minfo->smiapp_version);
2243
2244 if (rval) {
2245 dev_err(&client->dev, "sensor detection failed\n");
2246 return -ENODEV;
2247 }
2248
2249 dev_dbg(&client->dev, "module 0x%2.2x-0x%4.4x\n",
2250 minfo->manufacturer_id, minfo->model_id);
2251
2252 dev_dbg(&client->dev,
2253 "module revision 0x%2.2x-0x%2.2x date %2.2d-%2.2d-%2.2d\n",
2254 minfo->revision_number_major, minfo->revision_number_minor,
2255 minfo->module_year, minfo->module_month, minfo->module_day);
2256
2257 dev_dbg(&client->dev, "sensor 0x%2.2x-0x%4.4x\n",
2258 minfo->sensor_manufacturer_id, minfo->sensor_model_id);
2259
2260 dev_dbg(&client->dev,
2261 "sensor revision 0x%2.2x firmware version 0x%2.2x\n",
2262 minfo->sensor_revision_number, minfo->sensor_firmware_version);
2263
2264 dev_dbg(&client->dev, "smia version %2.2d smiapp version %2.2d\n",
2265 minfo->smia_version, minfo->smiapp_version);
2266
2267 /*
2268 * Some modules have bad data in the lvalues below. Hope the
2269 * rvalues have better stuff. The lvalues are module
2270 * parameters whereas the rvalues are sensor parameters.
2271 */
2272 if (!minfo->manufacturer_id && !minfo->model_id) {
2273 minfo->manufacturer_id = minfo->sensor_manufacturer_id;
2274 minfo->model_id = minfo->sensor_model_id;
2275 minfo->revision_number_major = minfo->sensor_revision_number;
2276 }
2277
2278 for (i = 0; i < ARRAY_SIZE(smiapp_module_idents); i++) {
2279 if (smiapp_module_idents[i].manufacturer_id
2280 != minfo->manufacturer_id)
2281 continue;
2282 if (smiapp_module_idents[i].model_id != minfo->model_id)
2283 continue;
2284 if (smiapp_module_idents[i].flags
2285 & SMIAPP_MODULE_IDENT_FLAG_REV_LE) {
2286 if (smiapp_module_idents[i].revision_number_major
2287 < minfo->revision_number_major)
2288 continue;
2289 } else {
2290 if (smiapp_module_idents[i].revision_number_major
2291 != minfo->revision_number_major)
2292 continue;
2293 }
2294
2295 minfo->name = smiapp_module_idents[i].name;
2296 minfo->quirk = smiapp_module_idents[i].quirk;
2297 break;
2298 }
2299
2300 if (i >= ARRAY_SIZE(smiapp_module_idents))
2301 dev_warn(&client->dev,
2302 "no quirks for this module; let's hope it's fully compliant\n");
2303
2304 dev_dbg(&client->dev, "the sensor is called %s, ident %2.2x%4.4x%2.2x\n",
2305 minfo->name, minfo->manufacturer_id, minfo->model_id,
2306 minfo->revision_number_major);
2307
2308 strlcpy(subdev->name, sensor->minfo.name, sizeof(subdev->name));
2309
2310 return 0;
2311}
2312
2313static const struct v4l2_subdev_ops smiapp_ops;
2314static const struct v4l2_subdev_internal_ops smiapp_internal_ops;
2315static const struct media_entity_operations smiapp_entity_ops;
2316
2317static int smiapp_registered(struct v4l2_subdev *subdev)
2318{
2319 struct smiapp_sensor *sensor = to_smiapp_sensor(subdev);
2320 struct i2c_client *client = v4l2_get_subdevdata(subdev);
2321 struct smiapp_subdev *last = NULL;
2322 u32 tmp;
2323 unsigned int i;
2324 int rval;
2325
2326 sensor->vana = regulator_get(&client->dev, "VANA");
2327 if (IS_ERR(sensor->vana)) {
2328 dev_err(&client->dev, "could not get regulator for vana\n");
2329 return -ENODEV;
2330 }
2331
2332 if (sensor->platform_data->xshutdown != SMIAPP_NO_XSHUTDOWN) {
2333 if (gpio_request_one(sensor->platform_data->xshutdown, 0,
2334 "SMIA++ xshutdown") != 0) {
2335 dev_err(&client->dev,
2336 "unable to acquire reset gpio %d\n",
2337 sensor->platform_data->xshutdown);
2338 rval = -ENODEV;
2339 goto out_gpio_request;
2340 }
2341 }
2342
2343 rval = smiapp_power_on(sensor);
2344 if (rval) {
2345 rval = -ENODEV;
2346 goto out_smiapp_power_on;
2347 }
2348
2349 rval = smiapp_identify_module(subdev);
2350 if (rval) {
2351 rval = -ENODEV;
2352 goto out_power_off;
2353 }
2354
2355 rval = smiapp_get_all_limits(sensor);
2356 if (rval) {
2357 rval = -ENODEV;
2358 goto out_power_off;
2359 }
2360
2361 /*
2362 * Handle Sensor Module orientation on the board.
2363 *
2364 * The application of H-FLIP and V-FLIP on the sensor is modified by
2365 * the sensor orientation on the board.
2366 *
2367 * For SMIAPP_BOARD_SENSOR_ORIENT_180 the default behaviour is to set
2368 * both H-FLIP and V-FLIP for normal operation which also implies
2369 * that a set/unset operation for user space HFLIP and VFLIP v4l2
2370 * controls will need to be internally inverted.
2371 *
2372 * Rotation also changes the bayer pattern.
2373 */
2374 if (sensor->platform_data->module_board_orient ==
2375 SMIAPP_MODULE_BOARD_ORIENT_180)
2376 sensor->hvflip_inv_mask = SMIAPP_IMAGE_ORIENTATION_HFLIP |
2377 SMIAPP_IMAGE_ORIENTATION_VFLIP;
2378
2379 rval = smiapp_get_mbus_formats(sensor);
2380 if (rval) {
2381 rval = -ENODEV;
2382 goto out_power_off;
2383 }
2384
2385 if (sensor->limits[SMIAPP_LIMIT_BINNING_CAPABILITY]) {
2386 u32 val;
2387
2388 rval = smiapp_read(client,
2389 SMIAPP_REG_U8_BINNING_SUBTYPES, &val);
2390 if (rval < 0) {
2391 rval = -ENODEV;
2392 goto out_power_off;
2393 }
2394 sensor->nbinning_subtypes = min_t(u8, val,
2395 SMIAPP_BINNING_SUBTYPES);
2396
2397 for (i = 0; i < sensor->nbinning_subtypes; i++) {
2398 rval = smiapp_read(
2399 client, SMIAPP_REG_U8_BINNING_TYPE_n(i), &val);
2400 if (rval < 0) {
2401 rval = -ENODEV;
2402 goto out_power_off;
2403 }
2404 sensor->binning_subtypes[i] =
2405 *(struct smiapp_binning_subtype *)&val;
2406
2407 dev_dbg(&client->dev, "binning %xx%x\n",
2408 sensor->binning_subtypes[i].horizontal,
2409 sensor->binning_subtypes[i].vertical);
2410 }
2411 }
2412 sensor->binning_horizontal = 1;
2413 sensor->binning_vertical = 1;
2414
2415 /* SMIA++ NVM initialization - it will be read from the sensor
2416 * when it is first requested by userspace.
2417 */
2418 if (sensor->minfo.smiapp_version && sensor->platform_data->nvm_size) {
2419 sensor->nvm = kzalloc(sensor->platform_data->nvm_size,
2420 GFP_KERNEL);
2421 if (sensor->nvm == NULL) {
2422 dev_err(&client->dev, "nvm buf allocation failed\n");
2423 rval = -ENOMEM;
2424 goto out_power_off;
2425 }
2426
2427 if (device_create_file(&client->dev, &dev_attr_nvm) != 0) {
2428 dev_err(&client->dev, "sysfs nvm entry failed\n");
2429 rval = -EBUSY;
2430 goto out_power_off;
2431 }
2432 }
2433
2434 rval = smiapp_call_quirk(sensor, limits);
2435 if (rval) {
2436 dev_err(&client->dev, "limits quirks failed\n");
2437 goto out_nvm_release;
2438 }
2439
2440 /* We consider this as profile 0 sensor if any of these are zero. */
2441 if (!sensor->limits[SMIAPP_LIMIT_MIN_OP_SYS_CLK_DIV] ||
2442 !sensor->limits[SMIAPP_LIMIT_MAX_OP_SYS_CLK_DIV] ||
2443 !sensor->limits[SMIAPP_LIMIT_MIN_OP_PIX_CLK_DIV] ||
2444 !sensor->limits[SMIAPP_LIMIT_MAX_OP_PIX_CLK_DIV]) {
2445 sensor->minfo.smiapp_profile = SMIAPP_PROFILE_0;
2446 } else if (sensor->limits[SMIAPP_LIMIT_SCALING_CAPABILITY]
2447 != SMIAPP_SCALING_CAPABILITY_NONE) {
2448 if (sensor->limits[SMIAPP_LIMIT_SCALING_CAPABILITY]
2449 == SMIAPP_SCALING_CAPABILITY_HORIZONTAL)
2450 sensor->minfo.smiapp_profile = SMIAPP_PROFILE_1;
2451 else
2452 sensor->minfo.smiapp_profile = SMIAPP_PROFILE_2;
2453 sensor->scaler = &sensor->ssds[sensor->ssds_used];
2454 sensor->ssds_used++;
2455 } else if (sensor->limits[SMIAPP_LIMIT_DIGITAL_CROP_CAPABILITY]
2456 == SMIAPP_DIGITAL_CROP_CAPABILITY_INPUT_CROP) {
2457 sensor->scaler = &sensor->ssds[sensor->ssds_used];
2458 sensor->ssds_used++;
2459 }
2460 sensor->binner = &sensor->ssds[sensor->ssds_used];
2461 sensor->ssds_used++;
2462 sensor->pixel_array = &sensor->ssds[sensor->ssds_used];
2463 sensor->ssds_used++;
2464
2465 sensor->scale_m = sensor->limits[SMIAPP_LIMIT_SCALER_N_MIN];
2466
2467 for (i = 0; i < SMIAPP_SUBDEVS; i++) {
2468 struct {
2469 struct smiapp_subdev *ssd;
2470 char *name;
2471 } const __this[] = {
2472 { sensor->scaler, "scaler", },
2473 { sensor->binner, "binner", },
2474 { sensor->pixel_array, "pixel array", },
2475 }, *_this = &__this[i];
2476 struct smiapp_subdev *this = _this->ssd;
2477
2478 if (!this)
2479 continue;
2480
2481 if (this != sensor->src)
2482 v4l2_subdev_init(&this->sd, &smiapp_ops);
2483
2484 this->sensor = sensor;
2485
2486 if (this == sensor->pixel_array) {
2487 this->npads = 1;
2488 } else {
2489 this->npads = 2;
2490 this->source_pad = 1;
2491 }
2492
2493 snprintf(this->sd.name,
2494 sizeof(this->sd.name), "%s %s",
2495 sensor->minfo.name, _this->name);
2496
2497 this->sink_fmt.width =
2498 sensor->limits[SMIAPP_LIMIT_X_ADDR_MAX] + 1;
2499 this->sink_fmt.height =
2500 sensor->limits[SMIAPP_LIMIT_Y_ADDR_MAX] + 1;
2501 this->compose.width = this->sink_fmt.width;
2502 this->compose.height = this->sink_fmt.height;
2503 this->crop[this->source_pad] = this->compose;
2504 this->pads[this->source_pad].flags = MEDIA_PAD_FL_SOURCE;
2505 if (this != sensor->pixel_array) {
2506 this->crop[this->sink_pad] = this->compose;
2507 this->pads[this->sink_pad].flags = MEDIA_PAD_FL_SINK;
2508 }
2509
2510 this->sd.entity.ops = &smiapp_entity_ops;
2511
2512 if (last == NULL) {
2513 last = this;
2514 continue;
2515 }
2516
2517 this->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
2518 this->sd.internal_ops = &smiapp_internal_ops;
2519 this->sd.owner = NULL;
2520 v4l2_set_subdevdata(&this->sd, client);
2521
2522 rval = media_entity_init(&this->sd.entity,
2523 this->npads, this->pads, 0);
2524 if (rval) {
2525 dev_err(&client->dev,
2526 "media_entity_init failed\n");
2527 goto out_nvm_release;
2528 }
2529
2530 rval = media_entity_create_link(&this->sd.entity,
2531 this->source_pad,
2532 &last->sd.entity,
2533 last->sink_pad,
2534 MEDIA_LNK_FL_ENABLED |
2535 MEDIA_LNK_FL_IMMUTABLE);
2536 if (rval) {
2537 dev_err(&client->dev,
2538 "media_entity_create_link failed\n");
2539 goto out_nvm_release;
2540 }
2541
2542 rval = v4l2_device_register_subdev(sensor->src->sd.v4l2_dev,
2543 &this->sd);
2544 if (rval) {
2545 dev_err(&client->dev,
2546 "v4l2_device_register_subdev failed\n");
2547 goto out_nvm_release;
2548 }
2549
2550 last = this;
2551 }
2552
2553 dev_dbg(&client->dev, "profile %d\n", sensor->minfo.smiapp_profile);
2554
2555 sensor->pixel_array->sd.entity.type = MEDIA_ENT_T_V4L2_SUBDEV_SENSOR;
2556
2557 /* final steps */
2558 smiapp_read_frame_fmt(sensor);
2559 rval = smiapp_init_controls(sensor);
2560 if (rval < 0)
2561 goto out_nvm_release;
2562
2563 rval = smiapp_update_mode(sensor);
2564 if (rval) {
2565 dev_err(&client->dev, "update mode failed\n");
2566 goto out_nvm_release;
2567 }
2568
2569 sensor->streaming = false;
2570 sensor->dev_init_done = true;
2571
2572 /* check flash capability */
2573 rval = smiapp_read(client, SMIAPP_REG_U8_FLASH_MODE_CAPABILITY, &tmp);
2574 sensor->flash_capability = tmp;
2575 if (rval)
2576 goto out_nvm_release;
2577
2578 smiapp_power_off(sensor);
2579
2580 return 0;
2581
2582out_nvm_release:
2583 device_remove_file(&client->dev, &dev_attr_nvm);
2584
2585out_power_off:
2586 kfree(sensor->nvm);
2587 sensor->nvm = NULL;
2588 smiapp_power_off(sensor);
2589
2590out_smiapp_power_on:
2591 if (sensor->platform_data->xshutdown != SMIAPP_NO_XSHUTDOWN)
2592 gpio_free(sensor->platform_data->xshutdown);
2593
2594out_gpio_request:
2595 regulator_put(sensor->vana);
2596 sensor->vana = NULL;
2597 return rval;
2598}
2599
2600static int smiapp_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
2601{
2602 struct smiapp_subdev *ssd = to_smiapp_subdev(sd);
2603 struct smiapp_sensor *sensor = ssd->sensor;
2604 u32 mbus_code =
2605 smiapp_csi_data_formats[smiapp_pixel_order(sensor)].code;
2606 unsigned int i;
2607
2608 mutex_lock(&sensor->mutex);
2609
2610 for (i = 0; i < ssd->npads; i++) {
2611 struct v4l2_mbus_framefmt *try_fmt =
2612 v4l2_subdev_get_try_format(fh, i);
2613 struct v4l2_rect *try_crop = v4l2_subdev_get_try_crop(fh, i);
2614 struct v4l2_rect *try_comp;
2615
2616 try_fmt->width = sensor->limits[SMIAPP_LIMIT_X_ADDR_MAX] + 1;
2617 try_fmt->height = sensor->limits[SMIAPP_LIMIT_Y_ADDR_MAX] + 1;
2618 try_fmt->code = mbus_code;
2619
2620 try_crop->top = 0;
2621 try_crop->left = 0;
2622 try_crop->width = try_fmt->width;
2623 try_crop->height = try_fmt->height;
2624
2625 if (ssd != sensor->pixel_array)
2626 continue;
2627
2628 try_comp = v4l2_subdev_get_try_compose(fh, i);
2629 *try_comp = *try_crop;
2630 }
2631
2632 mutex_unlock(&sensor->mutex);
2633
2634 return smiapp_set_power(sd, 1);
2635}
2636
2637static int smiapp_close(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
2638{
2639 return smiapp_set_power(sd, 0);
2640}
2641
2642static const struct v4l2_subdev_video_ops smiapp_video_ops = {
2643 .s_stream = smiapp_set_stream,
2644};
2645
2646static const struct v4l2_subdev_core_ops smiapp_core_ops = {
2647 .s_power = smiapp_set_power,
2648};
2649
2650static const struct v4l2_subdev_pad_ops smiapp_pad_ops = {
2651 .enum_mbus_code = smiapp_enum_mbus_code,
2652 .get_fmt = smiapp_get_format,
2653 .set_fmt = smiapp_set_format,
2654 .get_selection = smiapp_get_selection,
2655 .set_selection = smiapp_set_selection,
2656};
2657
2658static const struct v4l2_subdev_sensor_ops smiapp_sensor_ops = {
2659 .g_skip_frames = smiapp_get_skip_frames,
2660};
2661
2662static const struct v4l2_subdev_ops smiapp_ops = {
2663 .core = &smiapp_core_ops,
2664 .video = &smiapp_video_ops,
2665 .pad = &smiapp_pad_ops,
2666 .sensor = &smiapp_sensor_ops,
2667};
2668
2669static const struct media_entity_operations smiapp_entity_ops = {
2670 .link_validate = v4l2_subdev_link_validate,
2671};
2672
2673static const struct v4l2_subdev_internal_ops smiapp_internal_src_ops = {
2674 .registered = smiapp_registered,
2675 .open = smiapp_open,
2676 .close = smiapp_close,
2677};
2678
2679static const struct v4l2_subdev_internal_ops smiapp_internal_ops = {
2680 .open = smiapp_open,
2681 .close = smiapp_close,
2682};
2683
2684/* -----------------------------------------------------------------------------
2685 * I2C Driver
2686 */
2687
2688#ifdef CONFIG_PM
2689
2690static int smiapp_suspend(struct device *dev)
2691{
2692 struct i2c_client *client = to_i2c_client(dev);
2693 struct v4l2_subdev *subdev = i2c_get_clientdata(client);
2694 struct smiapp_sensor *sensor = to_smiapp_sensor(subdev);
2695 bool streaming;
2696
2697 BUG_ON(mutex_is_locked(&sensor->mutex));
2698
2699 if (sensor->power_count == 0)
2700 return 0;
2701
2702 if (sensor->streaming)
2703 smiapp_stop_streaming(sensor);
2704
2705 streaming = sensor->streaming;
2706
2707 smiapp_power_off(sensor);
2708
2709 /* save state for resume */
2710 sensor->streaming = streaming;
2711
2712 return 0;
2713}
2714
2715static int smiapp_resume(struct device *dev)
2716{
2717 struct i2c_client *client = to_i2c_client(dev);
2718 struct v4l2_subdev *subdev = i2c_get_clientdata(client);
2719 struct smiapp_sensor *sensor = to_smiapp_sensor(subdev);
2720 int rval;
2721
2722 if (sensor->power_count == 0)
2723 return 0;
2724
2725 rval = smiapp_power_on(sensor);
2726 if (rval)
2727 return rval;
2728
2729 if (sensor->streaming)
2730 rval = smiapp_start_streaming(sensor);
2731
2732 return rval;
2733}
2734
2735#else
2736
2737#define smiapp_suspend NULL
2738#define smiapp_resume NULL
2739
2740#endif /* CONFIG_PM */
2741
2742static int smiapp_probe(struct i2c_client *client,
2743 const struct i2c_device_id *devid)
2744{
2745 struct smiapp_sensor *sensor;
2746 int rval;
2747
2748 if (client->dev.platform_data == NULL)
2749 return -ENODEV;
2750
2751 sensor = kzalloc(sizeof(*sensor), GFP_KERNEL);
2752 if (sensor == NULL)
2753 return -ENOMEM;
2754
2755 sensor->platform_data = client->dev.platform_data;
2756 mutex_init(&sensor->mutex);
2757 mutex_init(&sensor->power_mutex);
2758 sensor->src = &sensor->ssds[sensor->ssds_used];
2759
2760 v4l2_i2c_subdev_init(&sensor->src->sd, client, &smiapp_ops);
2761 sensor->src->sd.internal_ops = &smiapp_internal_src_ops;
2762 sensor->src->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
2763 sensor->src->sensor = sensor;
2764
2765 sensor->src->pads[0].flags = MEDIA_PAD_FL_SOURCE;
2766 rval = media_entity_init(&sensor->src->sd.entity, 2,
2767 sensor->src->pads, 0);
2768 if (rval < 0)
2769 kfree(sensor);
2770
2771 return rval;
2772}
2773
2774static int __exit smiapp_remove(struct i2c_client *client)
2775{
2776 struct v4l2_subdev *subdev = i2c_get_clientdata(client);
2777 struct smiapp_sensor *sensor = to_smiapp_sensor(subdev);
2778 unsigned int i;
2779
2780 if (sensor->power_count) {
2781 if (sensor->platform_data->xshutdown != SMIAPP_NO_XSHUTDOWN)
2782 gpio_set_value(sensor->platform_data->xshutdown, 0);
2783 sensor->platform_data->set_xclk(&sensor->src->sd, 0);
2784 sensor->power_count = 0;
2785 }
2786
2787 if (sensor->nvm) {
2788 device_remove_file(&client->dev, &dev_attr_nvm);
2789 kfree(sensor->nvm);
2790 }
2791
2792 for (i = 0; i < sensor->ssds_used; i++) {
2793 media_entity_cleanup(&sensor->ssds[i].sd.entity);
2794 v4l2_device_unregister_subdev(&sensor->ssds[i].sd);
2795 }
2796 smiapp_free_controls(sensor);
2797 if (sensor->platform_data->xshutdown != SMIAPP_NO_XSHUTDOWN)
2798 gpio_free(sensor->platform_data->xshutdown);
2799 if (sensor->vana)
2800 regulator_put(sensor->vana);
2801
2802 kfree(sensor);
2803
2804 return 0;
2805}
2806
2807static const struct i2c_device_id smiapp_id_table[] = {
2808 { SMIAPP_NAME, 0 },
2809 { },
2810};
2811MODULE_DEVICE_TABLE(i2c, smiapp_id_table);
2812
2813static const struct dev_pm_ops smiapp_pm_ops = {
2814 .suspend = smiapp_suspend,
2815 .resume = smiapp_resume,
2816};
2817
2818static struct i2c_driver smiapp_i2c_driver = {
2819 .driver = {
2820 .name = SMIAPP_NAME,
2821 .pm = &smiapp_pm_ops,
2822 },
2823 .probe = smiapp_probe,
2824 .remove = __exit_p(smiapp_remove),
2825 .id_table = smiapp_id_table,
2826};
2827
2828module_i2c_driver(smiapp_i2c_driver);
2829
2830MODULE_AUTHOR("Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>");
2831MODULE_DESCRIPTION("Generic SMIA/SMIA++ camera module driver");
2832MODULE_LICENSE("GPL");
diff --git a/drivers/media/video/smiapp/smiapp-debug.h b/drivers/media/video/smiapp/smiapp-debug.h
new file mode 100644
index 000000000000..627809eed1d9
--- /dev/null
+++ b/drivers/media/video/smiapp/smiapp-debug.h
@@ -0,0 +1,32 @@
1/*
2 * drivers/media/video/smiapp/smiapp-debug.h
3 *
4 * Generic driver for SMIA/SMIA++ compliant camera modules
5 *
6 * Copyright (C) 2011--2012 Nokia Corporation
7 * Contact: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * version 2 as published by the Free Software Foundation.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
21 * 02110-1301 USA
22 *
23 */
24
25#ifndef SMIAPP_DEBUG_H
26#define SMIAPP_DEBUG_H
27
28#ifdef CONFIG_VIDEO_SMIAPP_DEBUG
29#define DEBUG
30#endif
31
32#endif
diff --git a/drivers/media/video/smiapp/smiapp-limits.c b/drivers/media/video/smiapp/smiapp-limits.c
new file mode 100644
index 000000000000..0800e095724e
--- /dev/null
+++ b/drivers/media/video/smiapp/smiapp-limits.c
@@ -0,0 +1,132 @@
1/*
2 * drivers/media/video/smiapp/smiapp-limits.c
3 *
4 * Generic driver for SMIA/SMIA++ compliant camera modules
5 *
6 * Copyright (C) 2011--2012 Nokia Corporation
7 * Contact: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * version 2 as published by the Free Software Foundation.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
21 * 02110-1301 USA
22 *
23 */
24
25#include "smiapp.h"
26
27struct smiapp_reg_limits smiapp_reg_limits[] = {
28 { SMIAPP_REG_U16_ANALOGUE_GAIN_CAPABILITY, "analogue_gain_capability" }, /* 0 */
29 { SMIAPP_REG_U16_ANALOGUE_GAIN_CODE_MIN, "analogue_gain_code_min" },
30 { SMIAPP_REG_U16_ANALOGUE_GAIN_CODE_MAX, "analogue_gain_code_max" },
31 { SMIAPP_REG_U8_THS_ZERO_MIN, "ths_zero_min" },
32 { SMIAPP_REG_U8_TCLK_TRAIL_MIN, "tclk_trail_min" },
33 { SMIAPP_REG_U16_INTEGRATION_TIME_CAPABILITY, "integration_time_capability" }, /* 5 */
34 { SMIAPP_REG_U16_COARSE_INTEGRATION_TIME_MIN, "coarse_integration_time_min" },
35 { SMIAPP_REG_U16_COARSE_INTEGRATION_TIME_MAX_MARGIN, "coarse_integration_time_max_margin" },
36 { SMIAPP_REG_U16_FINE_INTEGRATION_TIME_MIN, "fine_integration_time_min" },
37 { SMIAPP_REG_U16_FINE_INTEGRATION_TIME_MAX_MARGIN, "fine_integration_time_max_margin" },
38 { SMIAPP_REG_U16_DIGITAL_GAIN_CAPABILITY, "digital_gain_capability" }, /* 10 */
39 { SMIAPP_REG_U16_DIGITAL_GAIN_MIN, "digital_gain_min" },
40 { SMIAPP_REG_U16_DIGITAL_GAIN_MAX, "digital_gain_max" },
41 { SMIAPP_REG_F32_MIN_EXT_CLK_FREQ_HZ, "min_ext_clk_freq_hz" },
42 { SMIAPP_REG_F32_MAX_EXT_CLK_FREQ_HZ, "max_ext_clk_freq_hz" },
43 { SMIAPP_REG_U16_MIN_PRE_PLL_CLK_DIV, "min_pre_pll_clk_div" }, /* 15 */
44 { SMIAPP_REG_U16_MAX_PRE_PLL_CLK_DIV, "max_pre_pll_clk_div" },
45 { SMIAPP_REG_F32_MIN_PLL_IP_FREQ_HZ, "min_pll_ip_freq_hz" },
46 { SMIAPP_REG_F32_MAX_PLL_IP_FREQ_HZ, "max_pll_ip_freq_hz" },
47 { SMIAPP_REG_U16_MIN_PLL_MULTIPLIER, "min_pll_multiplier" },
48 { SMIAPP_REG_U16_MAX_PLL_MULTIPLIER, "max_pll_multiplier" }, /* 20 */
49 { SMIAPP_REG_F32_MIN_PLL_OP_FREQ_HZ, "min_pll_op_freq_hz" },
50 { SMIAPP_REG_F32_MAX_PLL_OP_FREQ_HZ, "max_pll_op_freq_hz" },
51 { SMIAPP_REG_U16_MIN_VT_SYS_CLK_DIV, "min_vt_sys_clk_div" },
52 { SMIAPP_REG_U16_MAX_VT_SYS_CLK_DIV, "max_vt_sys_clk_div" },
53 { SMIAPP_REG_F32_MIN_VT_SYS_CLK_FREQ_HZ, "min_vt_sys_clk_freq_hz" }, /* 25 */
54 { SMIAPP_REG_F32_MAX_VT_SYS_CLK_FREQ_HZ, "max_vt_sys_clk_freq_hz" },
55 { SMIAPP_REG_F32_MIN_VT_PIX_CLK_FREQ_HZ, "min_vt_pix_clk_freq_hz" },
56 { SMIAPP_REG_F32_MAX_VT_PIX_CLK_FREQ_HZ, "max_vt_pix_clk_freq_hz" },
57 { SMIAPP_REG_U16_MIN_VT_PIX_CLK_DIV, "min_vt_pix_clk_div" },
58 { SMIAPP_REG_U16_MAX_VT_PIX_CLK_DIV, "max_vt_pix_clk_div" }, /* 30 */
59 { SMIAPP_REG_U16_MIN_FRAME_LENGTH_LINES, "min_frame_length_lines" },
60 { SMIAPP_REG_U16_MAX_FRAME_LENGTH_LINES, "max_frame_length_lines" },
61 { SMIAPP_REG_U16_MIN_LINE_LENGTH_PCK, "min_line_length_pck" },
62 { SMIAPP_REG_U16_MAX_LINE_LENGTH_PCK, "max_line_length_pck" },
63 { SMIAPP_REG_U16_MIN_LINE_BLANKING_PCK, "min_line_blanking_pck" }, /* 35 */
64 { SMIAPP_REG_U16_MIN_FRAME_BLANKING_LINES, "min_frame_blanking_lines" },
65 { SMIAPP_REG_U8_MIN_LINE_LENGTH_PCK_STEP_SIZE, "min_line_length_pck_step_size" },
66 { SMIAPP_REG_U16_MIN_OP_SYS_CLK_DIV, "min_op_sys_clk_div" },
67 { SMIAPP_REG_U16_MAX_OP_SYS_CLK_DIV, "max_op_sys_clk_div" },
68 { SMIAPP_REG_F32_MIN_OP_SYS_CLK_FREQ_HZ, "min_op_sys_clk_freq_hz" }, /* 40 */
69 { SMIAPP_REG_F32_MAX_OP_SYS_CLK_FREQ_HZ, "max_op_sys_clk_freq_hz" },
70 { SMIAPP_REG_U16_MIN_OP_PIX_CLK_DIV, "min_op_pix_clk_div" },
71 { SMIAPP_REG_U16_MAX_OP_PIX_CLK_DIV, "max_op_pix_clk_div" },
72 { SMIAPP_REG_F32_MIN_OP_PIX_CLK_FREQ_HZ, "min_op_pix_clk_freq_hz" },
73 { SMIAPP_REG_F32_MAX_OP_PIX_CLK_FREQ_HZ, "max_op_pix_clk_freq_hz" }, /* 45 */
74 { SMIAPP_REG_U16_X_ADDR_MIN, "x_addr_min" },
75 { SMIAPP_REG_U16_Y_ADDR_MIN, "y_addr_min" },
76 { SMIAPP_REG_U16_X_ADDR_MAX, "x_addr_max" },
77 { SMIAPP_REG_U16_Y_ADDR_MAX, "y_addr_max" },
78 { SMIAPP_REG_U16_MIN_X_OUTPUT_SIZE, "min_x_output_size" }, /* 50 */
79 { SMIAPP_REG_U16_MIN_Y_OUTPUT_SIZE, "min_y_output_size" },
80 { SMIAPP_REG_U16_MAX_X_OUTPUT_SIZE, "max_x_output_size" },
81 { SMIAPP_REG_U16_MAX_Y_OUTPUT_SIZE, "max_y_output_size" },
82 { SMIAPP_REG_U16_MIN_EVEN_INC, "min_even_inc" },
83 { SMIAPP_REG_U16_MAX_EVEN_INC, "max_even_inc" }, /* 55 */
84 { SMIAPP_REG_U16_MIN_ODD_INC, "min_odd_inc" },
85 { SMIAPP_REG_U16_MAX_ODD_INC, "max_odd_inc" },
86 { SMIAPP_REG_U16_SCALING_CAPABILITY, "scaling_capability" },
87 { SMIAPP_REG_U16_SCALER_M_MIN, "scaler_m_min" },
88 { SMIAPP_REG_U16_SCALER_M_MAX, "scaler_m_max" }, /* 60 */
89 { SMIAPP_REG_U16_SCALER_N_MIN, "scaler_n_min" },
90 { SMIAPP_REG_U16_SCALER_N_MAX, "scaler_n_max" },
91 { SMIAPP_REG_U16_SPATIAL_SAMPLING_CAPABILITY, "spatial_sampling_capability" },
92 { SMIAPP_REG_U8_DIGITAL_CROP_CAPABILITY, "digital_crop_capability" },
93 { SMIAPP_REG_U16_COMPRESSION_CAPABILITY, "compression_capability" }, /* 65 */
94 { SMIAPP_REG_U8_FIFO_SUPPORT_CAPABILITY, "fifo_support_capability" },
95 { SMIAPP_REG_U8_DPHY_CTRL_CAPABILITY, "dphy_ctrl_capability" },
96 { SMIAPP_REG_U8_CSI_LANE_MODE_CAPABILITY, "csi_lane_mode_capability" },
97 { SMIAPP_REG_U8_CSI_SIGNALLING_MODE_CAPABILITY, "csi_signalling_mode_capability" },
98 { SMIAPP_REG_U8_FAST_STANDBY_CAPABILITY, "fast_standby_capability" }, /* 70 */
99 { SMIAPP_REG_U8_CCI_ADDRESS_CONTROL_CAPABILITY, "cci_address_control_capability" },
100 { SMIAPP_REG_U32_MAX_PER_LANE_BITRATE_1_LANE_MODE_MBPS, "max_per_lane_bitrate_1_lane_mode_mbps" },
101 { SMIAPP_REG_U32_MAX_PER_LANE_BITRATE_2_LANE_MODE_MBPS, "max_per_lane_bitrate_2_lane_mode_mbps" },
102 { SMIAPP_REG_U32_MAX_PER_LANE_BITRATE_3_LANE_MODE_MBPS, "max_per_lane_bitrate_3_lane_mode_mbps" },
103 { SMIAPP_REG_U32_MAX_PER_LANE_BITRATE_4_LANE_MODE_MBPS, "max_per_lane_bitrate_4_lane_mode_mbps" }, /* 75 */
104 { SMIAPP_REG_U8_TEMP_SENSOR_CAPABILITY, "temp_sensor_capability" },
105 { SMIAPP_REG_U16_MIN_FRAME_LENGTH_LINES_BIN, "min_frame_length_lines_bin" },
106 { SMIAPP_REG_U16_MAX_FRAME_LENGTH_LINES_BIN, "max_frame_length_lines_bin" },
107 { SMIAPP_REG_U16_MIN_LINE_LENGTH_PCK_BIN, "min_line_length_pck_bin" },
108 { SMIAPP_REG_U16_MAX_LINE_LENGTH_PCK_BIN, "max_line_length_pck_bin" }, /* 80 */
109 { SMIAPP_REG_U16_MIN_LINE_BLANKING_PCK_BIN, "min_line_blanking_pck_bin" },
110 { SMIAPP_REG_U16_FINE_INTEGRATION_TIME_MIN_BIN, "fine_integration_time_min_bin" },
111 { SMIAPP_REG_U16_FINE_INTEGRATION_TIME_MAX_MARGIN_BIN, "fine_integration_time_max_margin_bin" },
112 { SMIAPP_REG_U8_BINNING_CAPABILITY, "binning_capability" },
113 { SMIAPP_REG_U8_BINNING_WEIGHTING_CAPABILITY, "binning_weighting_capability" }, /* 85 */
114 { SMIAPP_REG_U8_DATA_TRANSFER_IF_CAPABILITY, "data_transfer_if_capability" },
115 { SMIAPP_REG_U8_SHADING_CORRECTION_CAPABILITY, "shading_correction_capability" },
116 { SMIAPP_REG_U8_GREEN_IMBALANCE_CAPABILITY, "green_imbalance_capability" },
117 { SMIAPP_REG_U8_BLACK_LEVEL_CAPABILITY, "black_level_capability" },
118 { SMIAPP_REG_U8_MODULE_SPECIFIC_CORRECTION_CAPABILITY, "module_specific_correction_capability" }, /* 90 */
119 { SMIAPP_REG_U16_DEFECT_CORRECTION_CAPABILITY, "defect_correction_capability" },
120 { SMIAPP_REG_U16_DEFECT_CORRECTION_CAPABILITY_2, "defect_correction_capability_2" },
121 { SMIAPP_REG_U8_EDOF_CAPABILITY, "edof_capability" },
122 { SMIAPP_REG_U8_COLOUR_FEEDBACK_CAPABILITY, "colour_feedback_capability" },
123 { SMIAPP_REG_U8_ESTIMATION_MODE_CAPABILITY, "estimation_mode_capability" }, /* 95 */
124 { SMIAPP_REG_U8_ESTIMATION_ZONE_CAPABILITY, "estimation_zone_capability" },
125 { SMIAPP_REG_U16_CAPABILITY_TRDY_MIN, "capability_trdy_min" },
126 { SMIAPP_REG_U8_FLASH_MODE_CAPABILITY, "flash_mode_capability" },
127 { SMIAPP_REG_U8_ACTUATOR_CAPABILITY, "actuator_capability" },
128 { SMIAPP_REG_U8_BRACKETING_LUT_CAPABILITY_1, "bracketing_lut_capability_1" }, /* 100 */
129 { SMIAPP_REG_U8_BRACKETING_LUT_CAPABILITY_2, "bracketing_lut_capability_2" },
130 { SMIAPP_REG_U16_ANALOGUE_GAIN_CODE_STEP, "analogue_gain_code_step" },
131 { 0, NULL },
132};
diff --git a/drivers/media/video/smiapp/smiapp-limits.h b/drivers/media/video/smiapp/smiapp-limits.h
new file mode 100644
index 000000000000..7f4836bb78db
--- /dev/null
+++ b/drivers/media/video/smiapp/smiapp-limits.h
@@ -0,0 +1,128 @@
1/*
2 * drivers/media/video/smiapp/smiapp-limits.h
3 *
4 * Generic driver for SMIA/SMIA++ compliant camera modules
5 *
6 * Copyright (C) 2011--2012 Nokia Corporation
7 * Contact: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * version 2 as published by the Free Software Foundation.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
21 * 02110-1301 USA
22 *
23 */
24
25#define SMIAPP_LIMIT_ANALOGUE_GAIN_CAPABILITY 0
26#define SMIAPP_LIMIT_ANALOGUE_GAIN_CODE_MIN 1
27#define SMIAPP_LIMIT_ANALOGUE_GAIN_CODE_MAX 2
28#define SMIAPP_LIMIT_THS_ZERO_MIN 3
29#define SMIAPP_LIMIT_TCLK_TRAIL_MIN 4
30#define SMIAPP_LIMIT_INTEGRATION_TIME_CAPABILITY 5
31#define SMIAPP_LIMIT_COARSE_INTEGRATION_TIME_MIN 6
32#define SMIAPP_LIMIT_COARSE_INTEGRATION_TIME_MAX_MARGIN 7
33#define SMIAPP_LIMIT_FINE_INTEGRATION_TIME_MIN 8
34#define SMIAPP_LIMIT_FINE_INTEGRATION_TIME_MAX_MARGIN 9
35#define SMIAPP_LIMIT_DIGITAL_GAIN_CAPABILITY 10
36#define SMIAPP_LIMIT_DIGITAL_GAIN_MIN 11
37#define SMIAPP_LIMIT_DIGITAL_GAIN_MAX 12
38#define SMIAPP_LIMIT_MIN_EXT_CLK_FREQ_HZ 13
39#define SMIAPP_LIMIT_MAX_EXT_CLK_FREQ_HZ 14
40#define SMIAPP_LIMIT_MIN_PRE_PLL_CLK_DIV 15
41#define SMIAPP_LIMIT_MAX_PRE_PLL_CLK_DIV 16
42#define SMIAPP_LIMIT_MIN_PLL_IP_FREQ_HZ 17
43#define SMIAPP_LIMIT_MAX_PLL_IP_FREQ_HZ 18
44#define SMIAPP_LIMIT_MIN_PLL_MULTIPLIER 19
45#define SMIAPP_LIMIT_MAX_PLL_MULTIPLIER 20
46#define SMIAPP_LIMIT_MIN_PLL_OP_FREQ_HZ 21
47#define SMIAPP_LIMIT_MAX_PLL_OP_FREQ_HZ 22
48#define SMIAPP_LIMIT_MIN_VT_SYS_CLK_DIV 23
49#define SMIAPP_LIMIT_MAX_VT_SYS_CLK_DIV 24
50#define SMIAPP_LIMIT_MIN_VT_SYS_CLK_FREQ_HZ 25
51#define SMIAPP_LIMIT_MAX_VT_SYS_CLK_FREQ_HZ 26
52#define SMIAPP_LIMIT_MIN_VT_PIX_CLK_FREQ_HZ 27
53#define SMIAPP_LIMIT_MAX_VT_PIX_CLK_FREQ_HZ 28
54#define SMIAPP_LIMIT_MIN_VT_PIX_CLK_DIV 29
55#define SMIAPP_LIMIT_MAX_VT_PIX_CLK_DIV 30
56#define SMIAPP_LIMIT_MIN_FRAME_LENGTH_LINES 31
57#define SMIAPP_LIMIT_MAX_FRAME_LENGTH_LINES 32
58#define SMIAPP_LIMIT_MIN_LINE_LENGTH_PCK 33
59#define SMIAPP_LIMIT_MAX_LINE_LENGTH_PCK 34
60#define SMIAPP_LIMIT_MIN_LINE_BLANKING_PCK 35
61#define SMIAPP_LIMIT_MIN_FRAME_BLANKING_LINES 36
62#define SMIAPP_LIMIT_MIN_LINE_LENGTH_PCK_STEP_SIZE 37
63#define SMIAPP_LIMIT_MIN_OP_SYS_CLK_DIV 38
64#define SMIAPP_LIMIT_MAX_OP_SYS_CLK_DIV 39
65#define SMIAPP_LIMIT_MIN_OP_SYS_CLK_FREQ_HZ 40
66#define SMIAPP_LIMIT_MAX_OP_SYS_CLK_FREQ_HZ 41
67#define SMIAPP_LIMIT_MIN_OP_PIX_CLK_DIV 42
68#define SMIAPP_LIMIT_MAX_OP_PIX_CLK_DIV 43
69#define SMIAPP_LIMIT_MIN_OP_PIX_CLK_FREQ_HZ 44
70#define SMIAPP_LIMIT_MAX_OP_PIX_CLK_FREQ_HZ 45
71#define SMIAPP_LIMIT_X_ADDR_MIN 46
72#define SMIAPP_LIMIT_Y_ADDR_MIN 47
73#define SMIAPP_LIMIT_X_ADDR_MAX 48
74#define SMIAPP_LIMIT_Y_ADDR_MAX 49
75#define SMIAPP_LIMIT_MIN_X_OUTPUT_SIZE 50
76#define SMIAPP_LIMIT_MIN_Y_OUTPUT_SIZE 51
77#define SMIAPP_LIMIT_MAX_X_OUTPUT_SIZE 52
78#define SMIAPP_LIMIT_MAX_Y_OUTPUT_SIZE 53
79#define SMIAPP_LIMIT_MIN_EVEN_INC 54
80#define SMIAPP_LIMIT_MAX_EVEN_INC 55
81#define SMIAPP_LIMIT_MIN_ODD_INC 56
82#define SMIAPP_LIMIT_MAX_ODD_INC 57
83#define SMIAPP_LIMIT_SCALING_CAPABILITY 58
84#define SMIAPP_LIMIT_SCALER_M_MIN 59
85#define SMIAPP_LIMIT_SCALER_M_MAX 60
86#define SMIAPP_LIMIT_SCALER_N_MIN 61
87#define SMIAPP_LIMIT_SCALER_N_MAX 62
88#define SMIAPP_LIMIT_SPATIAL_SAMPLING_CAPABILITY 63
89#define SMIAPP_LIMIT_DIGITAL_CROP_CAPABILITY 64
90#define SMIAPP_LIMIT_COMPRESSION_CAPABILITY 65
91#define SMIAPP_LIMIT_FIFO_SUPPORT_CAPABILITY 66
92#define SMIAPP_LIMIT_DPHY_CTRL_CAPABILITY 67
93#define SMIAPP_LIMIT_CSI_LANE_MODE_CAPABILITY 68
94#define SMIAPP_LIMIT_CSI_SIGNALLING_MODE_CAPABILITY 69
95#define SMIAPP_LIMIT_FAST_STANDBY_CAPABILITY 70
96#define SMIAPP_LIMIT_CCI_ADDRESS_CONTROL_CAPABILITY 71
97#define SMIAPP_LIMIT_MAX_PER_LANE_BITRATE_1_LANE_MODE_MBPS 72
98#define SMIAPP_LIMIT_MAX_PER_LANE_BITRATE_2_LANE_MODE_MBPS 73
99#define SMIAPP_LIMIT_MAX_PER_LANE_BITRATE_3_LANE_MODE_MBPS 74
100#define SMIAPP_LIMIT_MAX_PER_LANE_BITRATE_4_LANE_MODE_MBPS 75
101#define SMIAPP_LIMIT_TEMP_SENSOR_CAPABILITY 76
102#define SMIAPP_LIMIT_MIN_FRAME_LENGTH_LINES_BIN 77
103#define SMIAPP_LIMIT_MAX_FRAME_LENGTH_LINES_BIN 78
104#define SMIAPP_LIMIT_MIN_LINE_LENGTH_PCK_BIN 79
105#define SMIAPP_LIMIT_MAX_LINE_LENGTH_PCK_BIN 80
106#define SMIAPP_LIMIT_MIN_LINE_BLANKING_PCK_BIN 81
107#define SMIAPP_LIMIT_FINE_INTEGRATION_TIME_MIN_BIN 82
108#define SMIAPP_LIMIT_FINE_INTEGRATION_TIME_MAX_MARGIN_BIN 83
109#define SMIAPP_LIMIT_BINNING_CAPABILITY 84
110#define SMIAPP_LIMIT_BINNING_WEIGHTING_CAPABILITY 85
111#define SMIAPP_LIMIT_DATA_TRANSFER_IF_CAPABILITY 86
112#define SMIAPP_LIMIT_SHADING_CORRECTION_CAPABILITY 87
113#define SMIAPP_LIMIT_GREEN_IMBALANCE_CAPABILITY 88
114#define SMIAPP_LIMIT_BLACK_LEVEL_CAPABILITY 89
115#define SMIAPP_LIMIT_MODULE_SPECIFIC_CORRECTION_CAPABILITY 90
116#define SMIAPP_LIMIT_DEFECT_CORRECTION_CAPABILITY 91
117#define SMIAPP_LIMIT_DEFECT_CORRECTION_CAPABILITY_2 92
118#define SMIAPP_LIMIT_EDOF_CAPABILITY 93
119#define SMIAPP_LIMIT_COLOUR_FEEDBACK_CAPABILITY 94
120#define SMIAPP_LIMIT_ESTIMATION_MODE_CAPABILITY 95
121#define SMIAPP_LIMIT_ESTIMATION_ZONE_CAPABILITY 96
122#define SMIAPP_LIMIT_CAPABILITY_TRDY_MIN 97
123#define SMIAPP_LIMIT_FLASH_MODE_CAPABILITY 98
124#define SMIAPP_LIMIT_ACTUATOR_CAPABILITY 99
125#define SMIAPP_LIMIT_BRACKETING_LUT_CAPABILITY_1 100
126#define SMIAPP_LIMIT_BRACKETING_LUT_CAPABILITY_2 101
127#define SMIAPP_LIMIT_ANALOGUE_GAIN_CODE_STEP 102
128#define SMIAPP_LIMIT_LAST 103
diff --git a/drivers/media/video/smiapp/smiapp-quirk.c b/drivers/media/video/smiapp/smiapp-quirk.c
new file mode 100644
index 000000000000..dae85a12f7ec
--- /dev/null
+++ b/drivers/media/video/smiapp/smiapp-quirk.c
@@ -0,0 +1,264 @@
1/*
2 * drivers/media/video/smiapp/smiapp-quirk.c
3 *
4 * Generic driver for SMIA/SMIA++ compliant camera modules
5 *
6 * Copyright (C) 2011--2012 Nokia Corporation
7 * Contact: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * version 2 as published by the Free Software Foundation.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
21 * 02110-1301 USA
22 *
23 */
24
25#include "smiapp-debug.h"
26
27#include <linux/delay.h>
28
29#include "smiapp.h"
30
31static int smiapp_write_8(struct smiapp_sensor *sensor, u16 reg, u8 val)
32{
33 struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
34
35 return smiapp_write(client, (SMIA_REG_8BIT << 16) | reg, val);
36}
37
38static int smiapp_write_8s(struct smiapp_sensor *sensor,
39 struct smiapp_reg_8 *regs, int len)
40{
41 struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
42 int rval;
43
44 for (; len > 0; len--, regs++) {
45 rval = smiapp_write_8(sensor, regs->reg, regs->val);
46 if (rval < 0) {
47 dev_err(&client->dev,
48 "error %d writing reg 0x%4.4x, val 0x%2.2x",
49 rval, regs->reg, regs->val);
50 return rval;
51 }
52 }
53
54 return 0;
55}
56
57void smiapp_replace_limit(struct smiapp_sensor *sensor,
58 u32 limit, u32 val)
59{
60 struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
61
62 dev_dbg(&client->dev, "quirk: 0x%8.8x \"%s\" = %d, 0x%x\n",
63 smiapp_reg_limits[limit].addr,
64 smiapp_reg_limits[limit].what, val, val);
65 sensor->limits[limit] = val;
66}
67
68int smiapp_replace_limit_at(struct smiapp_sensor *sensor,
69 u32 reg, u32 val)
70{
71 struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
72 int i;
73
74 for (i = 0; smiapp_reg_limits[i].addr; i++) {
75 if ((smiapp_reg_limits[i].addr & 0xffff) != reg)
76 continue;
77
78 smiapp_replace_limit(sensor, i, val);
79
80 return 0;
81 }
82
83 dev_dbg(&client->dev, "quirk: bad register 0x%4.4x\n", reg);
84
85 return -EINVAL;
86}
87
88static int jt8ew9_limits(struct smiapp_sensor *sensor)
89{
90 if (sensor->minfo.revision_number_major < 0x03)
91 sensor->frame_skip = 1;
92
93 /* Below 24 gain doesn't have effect at all, */
94 /* but ~59 is needed for full dynamic range */
95 smiapp_replace_limit(sensor, SMIAPP_LIMIT_ANALOGUE_GAIN_CODE_MIN, 59);
96 smiapp_replace_limit(
97 sensor, SMIAPP_LIMIT_ANALOGUE_GAIN_CODE_MAX, 6000);
98
99 return 0;
100}
101
102static int jt8ew9_post_poweron(struct smiapp_sensor *sensor)
103{
104 struct smiapp_reg_8 regs[] = {
105 { 0x30a3, 0xd8 }, /* Output port control : LVDS ports only */
106 { 0x30ae, 0x00 }, /* 0x0307 pll_multiplier maximum value on PLL input 9.6MHz ( 19.2MHz is divided on pre_pll_div) */
107 { 0x30af, 0xd0 }, /* 0x0307 pll_multiplier maximum value on PLL input 9.6MHz ( 19.2MHz is divided on pre_pll_div) */
108 { 0x322d, 0x04 }, /* Adjusting Processing Image Size to Scaler Toshiba Recommendation Setting */
109 { 0x3255, 0x0f }, /* Horizontal Noise Reduction Control Toshiba Recommendation Setting */
110 { 0x3256, 0x15 }, /* Horizontal Noise Reduction Control Toshiba Recommendation Setting */
111 { 0x3258, 0x70 }, /* Analog Gain Control Toshiba Recommendation Setting */
112 { 0x3259, 0x70 }, /* Analog Gain Control Toshiba Recommendation Setting */
113 { 0x325f, 0x7c }, /* Analog Gain Control Toshiba Recommendation Setting */
114 { 0x3302, 0x06 }, /* Pixel Reference Voltage Control Toshiba Recommendation Setting */
115 { 0x3304, 0x00 }, /* Pixel Reference Voltage Control Toshiba Recommendation Setting */
116 { 0x3307, 0x22 }, /* Pixel Reference Voltage Control Toshiba Recommendation Setting */
117 { 0x3308, 0x8d }, /* Pixel Reference Voltage Control Toshiba Recommendation Setting */
118 { 0x331e, 0x0f }, /* Black Hole Sun Correction Control Toshiba Recommendation Setting */
119 { 0x3320, 0x30 }, /* Black Hole Sun Correction Control Toshiba Recommendation Setting */
120 { 0x3321, 0x11 }, /* Black Hole Sun Correction Control Toshiba Recommendation Setting */
121 { 0x3322, 0x98 }, /* Black Hole Sun Correction Control Toshiba Recommendation Setting */
122 { 0x3323, 0x64 }, /* Black Hole Sun Correction Control Toshiba Recommendation Setting */
123 { 0x3325, 0x83 }, /* Read Out Timing Control Toshiba Recommendation Setting */
124 { 0x3330, 0x18 }, /* Read Out Timing Control Toshiba Recommendation Setting */
125 { 0x333c, 0x01 }, /* Read Out Timing Control Toshiba Recommendation Setting */
126 { 0x3345, 0x2f }, /* Black Hole Sun Correction Control Toshiba Recommendation Setting */
127 { 0x33de, 0x38 }, /* Horizontal Noise Reduction Control Toshiba Recommendation Setting */
128 /* Taken from v03. No idea what the rest are. */
129 { 0x32e0, 0x05 },
130 { 0x32e1, 0x05 },
131 { 0x32e2, 0x04 },
132 { 0x32e5, 0x04 },
133 { 0x32e6, 0x04 },
134
135 };
136
137 return smiapp_write_8s(sensor, regs, ARRAY_SIZE(regs));
138}
139
140const struct smiapp_quirk smiapp_jt8ew9_quirk = {
141 .limits = jt8ew9_limits,
142 .post_poweron = jt8ew9_post_poweron,
143};
144
145static int imx125es_post_poweron(struct smiapp_sensor *sensor)
146{
147 /* Taken from v02. No idea what the other two are. */
148 struct smiapp_reg_8 regs[] = {
149 /*
150 * 0x3302: clk during frame blanking:
151 * 0x00 - HS mode, 0x01 - LP11
152 */
153 { 0x3302, 0x01 },
154 { 0x302d, 0x00 },
155 { 0x3b08, 0x8c },
156 };
157
158 return smiapp_write_8s(sensor, regs, ARRAY_SIZE(regs));
159}
160
161const struct smiapp_quirk smiapp_imx125es_quirk = {
162 .post_poweron = imx125es_post_poweron,
163};
164
165static int jt8ev1_limits(struct smiapp_sensor *sensor)
166{
167 smiapp_replace_limit(sensor, SMIAPP_LIMIT_X_ADDR_MAX, 4271);
168 smiapp_replace_limit(sensor,
169 SMIAPP_LIMIT_MIN_LINE_BLANKING_PCK_BIN, 184);
170
171 return 0;
172}
173
174static int jt8ev1_post_poweron(struct smiapp_sensor *sensor)
175{
176 struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
177 int rval;
178
179 struct smiapp_reg_8 regs[] = {
180 { 0x3031, 0xcd }, /* For digital binning (EQ_MONI) */
181 { 0x30a3, 0xd0 }, /* FLASH STROBE enable */
182 { 0x3237, 0x00 }, /* For control of pulse timing for ADC */
183 { 0x3238, 0x43 },
184 { 0x3301, 0x06 }, /* For analog bias for sensor */
185 { 0x3302, 0x06 },
186 { 0x3304, 0x00 },
187 { 0x3305, 0x88 },
188 { 0x332a, 0x14 },
189 { 0x332c, 0x6b },
190 { 0x3336, 0x01 },
191 { 0x333f, 0x1f },
192 { 0x3355, 0x00 },
193 { 0x3356, 0x20 },
194 { 0x33bf, 0x20 }, /* Adjust the FBC speed */
195 { 0x33c9, 0x20 },
196 { 0x33ce, 0x30 }, /* Adjust the parameter for logic function */
197 { 0x33cf, 0xec }, /* For Black sun */
198 { 0x3328, 0x80 }, /* Ugh. No idea what's this. */
199 };
200
201 struct smiapp_reg_8 regs_96[] = {
202 { 0x30ae, 0x00 }, /* For control of ADC clock */
203 { 0x30af, 0xd0 },
204 { 0x30b0, 0x01 },
205 };
206
207 rval = smiapp_write_8s(sensor, regs, ARRAY_SIZE(regs));
208 if (rval < 0)
209 return rval;
210
211 switch (sensor->platform_data->ext_clk) {
212 case 9600000:
213 return smiapp_write_8s(sensor, regs_96,
214 ARRAY_SIZE(regs_96));
215 default:
216 dev_warn(&client->dev, "no MSRs for %d Hz ext_clk\n",
217 sensor->platform_data->ext_clk);
218 return 0;
219 }
220}
221
222static int jt8ev1_pre_streamon(struct smiapp_sensor *sensor)
223{
224 return smiapp_write_8(sensor, 0x3328, 0x00);
225}
226
227static int jt8ev1_post_streamoff(struct smiapp_sensor *sensor)
228{
229 int rval;
230
231 /* Workaround: allows fast standby to work properly */
232 rval = smiapp_write_8(sensor, 0x3205, 0x04);
233 if (rval < 0)
234 return rval;
235
236 /* Wait for 1 ms + one line => 2 ms is likely enough */
237 usleep_range(2000, 2000);
238
239 /* Restore it */
240 rval = smiapp_write_8(sensor, 0x3205, 0x00);
241 if (rval < 0)
242 return rval;
243
244 return smiapp_write_8(sensor, 0x3328, 0x80);
245}
246
247const struct smiapp_quirk smiapp_jt8ev1_quirk = {
248 .limits = jt8ev1_limits,
249 .post_poweron = jt8ev1_post_poweron,
250 .pre_streamon = jt8ev1_pre_streamon,
251 .post_streamoff = jt8ev1_post_streamoff,
252 .flags = SMIAPP_QUIRK_FLAG_OP_PIX_CLOCK_PER_LANE,
253};
254
255static int tcm8500md_limits(struct smiapp_sensor *sensor)
256{
257 smiapp_replace_limit(sensor, SMIAPP_LIMIT_MIN_PLL_IP_FREQ_HZ, 2700000);
258
259 return 0;
260}
261
262const struct smiapp_quirk smiapp_tcm8500md_quirk = {
263 .limits = tcm8500md_limits,
264};
diff --git a/drivers/media/video/smiapp/smiapp-quirk.h b/drivers/media/video/smiapp/smiapp-quirk.h
new file mode 100644
index 000000000000..7a1b3a02a7bd
--- /dev/null
+++ b/drivers/media/video/smiapp/smiapp-quirk.h
@@ -0,0 +1,72 @@
1/*
2 * drivers/media/video/smiapp/smiapp-quirk.h
3 *
4 * Generic driver for SMIA/SMIA++ compliant camera modules
5 *
6 * Copyright (C) 2011--2012 Nokia Corporation
7 * Contact: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * version 2 as published by the Free Software Foundation.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
21 * 02110-1301 USA
22 *
23 */
24
25#ifndef __SMIAPP_QUIRK__
26#define __SMIAPP_QUIRK__
27
28struct smiapp_sensor;
29
30/**
31 * struct smiapp_quirk - quirks for sensors that deviate from SMIA++ standard
32 *
33 * @limits: Replace sensor->limits with values which can't be read from
34 * sensor registers. Called the first time the sensor is powered up.
35 * @post_poweron: Called always after the sensor has been fully powered on.
36 * @pre_streamon: Called just before streaming is enabled.
37 * @post_streamon: Called right after stopping streaming.
38 */
39struct smiapp_quirk {
40 int (*limits)(struct smiapp_sensor *sensor);
41 int (*post_poweron)(struct smiapp_sensor *sensor);
42 int (*pre_streamon)(struct smiapp_sensor *sensor);
43 int (*post_streamoff)(struct smiapp_sensor *sensor);
44 unsigned long flags;
45};
46
47/* op pix clock is for all lanes in total normally */
48#define SMIAPP_QUIRK_FLAG_OP_PIX_CLOCK_PER_LANE (1 << 0)
49
50struct smiapp_reg_8 {
51 u16 reg;
52 u8 val;
53};
54
55void smiapp_replace_limit(struct smiapp_sensor *sensor,
56 u32 limit, u32 val);
57
58#define smiapp_call_quirk(_sensor, _quirk, ...) \
59 (_sensor->minfo.quirk && \
60 _sensor->minfo.quirk->_quirk ? \
61 _sensor->minfo.quirk->_quirk(_sensor, ##__VA_ARGS__) : 0)
62
63#define smiapp_needs_quirk(_sensor, _quirk) \
64 (_sensor->minfo.quirk ? \
65 _sensor->minfo.quirk->flags & _quirk : 0)
66
67extern const struct smiapp_quirk smiapp_jt8ev1_quirk;
68extern const struct smiapp_quirk smiapp_imx125es_quirk;
69extern const struct smiapp_quirk smiapp_jt8ew9_quirk;
70extern const struct smiapp_quirk smiapp_tcm8500md_quirk;
71
72#endif /* __SMIAPP_QUIRK__ */
diff --git a/drivers/media/video/smiapp/smiapp-reg-defs.h b/drivers/media/video/smiapp/smiapp-reg-defs.h
new file mode 100644
index 000000000000..a089eb8161e1
--- /dev/null
+++ b/drivers/media/video/smiapp/smiapp-reg-defs.h
@@ -0,0 +1,503 @@
1/*
2 * drivers/media/video/smiapp/smiapp-reg-defs.h
3 *
4 * Generic driver for SMIA/SMIA++ compliant camera modules
5 *
6 * Copyright (C) 2011--2012 Nokia Corporation
7 * Contact: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * version 2 as published by the Free Software Foundation.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
21 * 02110-1301 USA
22 *
23 */
24#define SMIAPP_REG_MK_U8(r) ((SMIA_REG_8BIT << 16) | (r))
25#define SMIAPP_REG_MK_U16(r) ((SMIA_REG_16BIT << 16) | (r))
26#define SMIAPP_REG_MK_U32(r) ((SMIA_REG_32BIT << 16) | (r))
27
28#define SMIAPP_REG_MK_F32(r) (SMIA_REG_FLAG_FLOAT | (SMIA_REG_32BIT << 16) | (r))
29
30#define SMIAPP_REG_U16_MODEL_ID SMIAPP_REG_MK_U16(0x0000)
31#define SMIAPP_REG_U8_REVISION_NUMBER_MAJOR SMIAPP_REG_MK_U8(0x0002)
32#define SMIAPP_REG_U8_MANUFACTURER_ID SMIAPP_REG_MK_U8(0x0003)
33#define SMIAPP_REG_U8_SMIA_VERSION SMIAPP_REG_MK_U8(0x0004)
34#define SMIAPP_REG_U8_FRAME_COUNT SMIAPP_REG_MK_U8(0x0005)
35#define SMIAPP_REG_U8_PIXEL_ORDER SMIAPP_REG_MK_U8(0x0006)
36#define SMIAPP_REG_U16_DATA_PEDESTAL SMIAPP_REG_MK_U16(0x0008)
37#define SMIAPP_REG_U8_PIXEL_DEPTH SMIAPP_REG_MK_U8(0x000c)
38#define SMIAPP_REG_U8_REVISION_NUMBER_MINOR SMIAPP_REG_MK_U8(0x0010)
39#define SMIAPP_REG_U8_SMIAPP_VERSION SMIAPP_REG_MK_U8(0x0011)
40#define SMIAPP_REG_U8_MODULE_DATE_YEAR SMIAPP_REG_MK_U8(0x0012)
41#define SMIAPP_REG_U8_MODULE_DATE_MONTH SMIAPP_REG_MK_U8(0x0013)
42#define SMIAPP_REG_U8_MODULE_DATE_DAY SMIAPP_REG_MK_U8(0x0014)
43#define SMIAPP_REG_U8_MODULE_DATE_PHASE SMIAPP_REG_MK_U8(0x0015)
44#define SMIAPP_REG_U16_SENSOR_MODEL_ID SMIAPP_REG_MK_U16(0x0016)
45#define SMIAPP_REG_U8_SENSOR_REVISION_NUMBER SMIAPP_REG_MK_U8(0x0018)
46#define SMIAPP_REG_U8_SENSOR_MANUFACTURER_ID SMIAPP_REG_MK_U8(0x0019)
47#define SMIAPP_REG_U8_SENSOR_FIRMWARE_VERSION SMIAPP_REG_MK_U8(0x001a)
48#define SMIAPP_REG_U32_SERIAL_NUMBER SMIAPP_REG_MK_U32(0x001c)
49#define SMIAPP_REG_U8_FRAME_FORMAT_MODEL_TYPE SMIAPP_REG_MK_U8(0x0040)
50#define SMIAPP_REG_U8_FRAME_FORMAT_MODEL_SUBTYPE SMIAPP_REG_MK_U8(0x0041)
51#define SMIAPP_REG_U16_FRAME_FORMAT_DESCRIPTOR_2(n) SMIAPP_REG_MK_U16(0x0042 + ((n) << 1)) /* 0 <= n <= 14 */
52#define SMIAPP_REG_U32_FRAME_FORMAT_DESCRIPTOR_4(n) SMIAPP_REG_MK_U32(0x0060 + ((n) << 2)) /* 0 <= n <= 7 */
53#define SMIAPP_REG_U16_ANALOGUE_GAIN_CAPABILITY SMIAPP_REG_MK_U16(0x0080)
54#define SMIAPP_REG_U16_ANALOGUE_GAIN_CODE_MIN SMIAPP_REG_MK_U16(0x0084)
55#define SMIAPP_REG_U16_ANALOGUE_GAIN_CODE_MAX SMIAPP_REG_MK_U16(0x0086)
56#define SMIAPP_REG_U16_ANALOGUE_GAIN_CODE_STEP SMIAPP_REG_MK_U16(0x0088)
57#define SMIAPP_REG_U16_ANALOGUE_GAIN_TYPE SMIAPP_REG_MK_U16(0x008a)
58#define SMIAPP_REG_U16_ANALOGUE_GAIN_M0 SMIAPP_REG_MK_U16(0x008c)
59#define SMIAPP_REG_U16_ANALOGUE_GAIN_C0 SMIAPP_REG_MK_U16(0x008e)
60#define SMIAPP_REG_U16_ANALOGUE_GAIN_M1 SMIAPP_REG_MK_U16(0x0090)
61#define SMIAPP_REG_U16_ANALOGUE_GAIN_C1 SMIAPP_REG_MK_U16(0x0092)
62#define SMIAPP_REG_U8_DATA_FORMAT_MODEL_TYPE SMIAPP_REG_MK_U8(0x00c0)
63#define SMIAPP_REG_U8_DATA_FORMAT_MODEL_SUBTYPE SMIAPP_REG_MK_U8(0x00c1)
64#define SMIAPP_REG_U16_DATA_FORMAT_DESCRIPTOR(n) SMIAPP_REG_MK_U16(0x00c2 + ((n) << 1))
65#define SMIAPP_REG_U8_MODE_SELECT SMIAPP_REG_MK_U8(0x0100)
66#define SMIAPP_REG_U8_IMAGE_ORIENTATION SMIAPP_REG_MK_U8(0x0101)
67#define SMIAPP_REG_U8_SOFTWARE_RESET SMIAPP_REG_MK_U8(0x0103)
68#define SMIAPP_REG_U8_GROUPED_PARAMETER_HOLD SMIAPP_REG_MK_U8(0x0104)
69#define SMIAPP_REG_U8_MASK_CORRUPTED_FRAMES SMIAPP_REG_MK_U8(0x0105)
70#define SMIAPP_REG_U8_FAST_STANDBY_CTRL SMIAPP_REG_MK_U8(0x0106)
71#define SMIAPP_REG_U8_CCI_ADDRESS_CONTROL SMIAPP_REG_MK_U8(0x0107)
72#define SMIAPP_REG_U8_2ND_CCI_IF_CONTROL SMIAPP_REG_MK_U8(0x0108)
73#define SMIAPP_REG_U8_2ND_CCI_ADDRESS_CONTROL SMIAPP_REG_MK_U8(0x0109)
74#define SMIAPP_REG_U8_CSI_CHANNEL_IDENTIFIER SMIAPP_REG_MK_U8(0x0110)
75#define SMIAPP_REG_U8_CSI_SIGNALLING_MODE SMIAPP_REG_MK_U8(0x0111)
76#define SMIAPP_REG_U16_CSI_DATA_FORMAT SMIAPP_REG_MK_U16(0x0112)
77#define SMIAPP_REG_U8_CSI_LANE_MODE SMIAPP_REG_MK_U8(0x0114)
78#define SMIAPP_REG_U8_CSI2_10_TO_8_DT SMIAPP_REG_MK_U8(0x0115)
79#define SMIAPP_REG_U8_CSI2_10_TO_7_DT SMIAPP_REG_MK_U8(0x0116)
80#define SMIAPP_REG_U8_CSI2_10_TO_6_DT SMIAPP_REG_MK_U8(0x0117)
81#define SMIAPP_REG_U8_CSI2_12_TO_8_DT SMIAPP_REG_MK_U8(0x0118)
82#define SMIAPP_REG_U8_CSI2_12_TO_7_DT SMIAPP_REG_MK_U8(0x0119)
83#define SMIAPP_REG_U8_CSI2_12_TO_6_DT SMIAPP_REG_MK_U8(0x011a)
84#define SMIAPP_REG_U8_CSI2_14_TO_10_DT SMIAPP_REG_MK_U8(0x011b)
85#define SMIAPP_REG_U8_CSI2_14_TO_8_DT SMIAPP_REG_MK_U8(0x011c)
86#define SMIAPP_REG_U8_CSI2_16_TO_10_DT SMIAPP_REG_MK_U8(0x011d)
87#define SMIAPP_REG_U8_CSI2_16_TO_8_DT SMIAPP_REG_MK_U8(0x011e)
88#define SMIAPP_REG_U8_GAIN_MODE SMIAPP_REG_MK_U8(0x0120)
89#define SMIAPP_REG_U16_VANA_VOLTAGE SMIAPP_REG_MK_U16(0x0130)
90#define SMIAPP_REG_U16_VDIG_VOLTAGE SMIAPP_REG_MK_U16(0x0132)
91#define SMIAPP_REG_U16_VIO_VOLTAGE SMIAPP_REG_MK_U16(0x0134)
92#define SMIAPP_REG_U16_EXTCLK_FREQUENCY_MHZ SMIAPP_REG_MK_U16(0x0136)
93#define SMIAPP_REG_U8_TEMP_SENSOR_CONTROL SMIAPP_REG_MK_U8(0x0138)
94#define SMIAPP_REG_U8_TEMP_SENSOR_MODE SMIAPP_REG_MK_U8(0x0139)
95#define SMIAPP_REG_U8_TEMP_SENSOR_OUTPUT SMIAPP_REG_MK_U8(0x013a)
96#define SMIAPP_REG_U16_FINE_INTEGRATION_TIME SMIAPP_REG_MK_U16(0x0200)
97#define SMIAPP_REG_U16_COARSE_INTEGRATION_TIME SMIAPP_REG_MK_U16(0x0202)
98#define SMIAPP_REG_U16_ANALOGUE_GAIN_CODE_GLOBAL SMIAPP_REG_MK_U16(0x0204)
99#define SMIAPP_REG_U16_ANALOGUE_GAIN_CODE_GREENR SMIAPP_REG_MK_U16(0x0206)
100#define SMIAPP_REG_U16_ANALOGUE_GAIN_CODE_RED SMIAPP_REG_MK_U16(0x0208)
101#define SMIAPP_REG_U16_ANALOGUE_GAIN_CODE_BLUE SMIAPP_REG_MK_U16(0x020a)
102#define SMIAPP_REG_U16_ANALOGUE_GAIN_CODE_GREENB SMIAPP_REG_MK_U16(0x020c)
103#define SMIAPP_REG_U16_DIGITAL_GAIN_GREENR SMIAPP_REG_MK_U16(0x020e)
104#define SMIAPP_REG_U16_DIGITAL_GAIN_RED SMIAPP_REG_MK_U16(0x0210)
105#define SMIAPP_REG_U16_DIGITAL_GAIN_BLUE SMIAPP_REG_MK_U16(0x0212)
106#define SMIAPP_REG_U16_DIGITAL_GAIN_GREENB SMIAPP_REG_MK_U16(0x0214)
107#define SMIAPP_REG_U16_VT_PIX_CLK_DIV SMIAPP_REG_MK_U16(0x0300)
108#define SMIAPP_REG_U16_VT_SYS_CLK_DIV SMIAPP_REG_MK_U16(0x0302)
109#define SMIAPP_REG_U16_PRE_PLL_CLK_DIV SMIAPP_REG_MK_U16(0x0304)
110#define SMIAPP_REG_U16_PLL_MULTIPLIER SMIAPP_REG_MK_U16(0x0306)
111#define SMIAPP_REG_U16_OP_PIX_CLK_DIV SMIAPP_REG_MK_U16(0x0308)
112#define SMIAPP_REG_U16_OP_SYS_CLK_DIV SMIAPP_REG_MK_U16(0x030a)
113#define SMIAPP_REG_U16_FRAME_LENGTH_LINES SMIAPP_REG_MK_U16(0x0340)
114#define SMIAPP_REG_U16_LINE_LENGTH_PCK SMIAPP_REG_MK_U16(0x0342)
115#define SMIAPP_REG_U16_X_ADDR_START SMIAPP_REG_MK_U16(0x0344)
116#define SMIAPP_REG_U16_Y_ADDR_START SMIAPP_REG_MK_U16(0x0346)
117#define SMIAPP_REG_U16_X_ADDR_END SMIAPP_REG_MK_U16(0x0348)
118#define SMIAPP_REG_U16_Y_ADDR_END SMIAPP_REG_MK_U16(0x034a)
119#define SMIAPP_REG_U16_X_OUTPUT_SIZE SMIAPP_REG_MK_U16(0x034c)
120#define SMIAPP_REG_U16_Y_OUTPUT_SIZE SMIAPP_REG_MK_U16(0x034e)
121#define SMIAPP_REG_U16_X_EVEN_INC SMIAPP_REG_MK_U16(0x0380)
122#define SMIAPP_REG_U16_X_ODD_INC SMIAPP_REG_MK_U16(0x0382)
123#define SMIAPP_REG_U16_Y_EVEN_INC SMIAPP_REG_MK_U16(0x0384)
124#define SMIAPP_REG_U16_Y_ODD_INC SMIAPP_REG_MK_U16(0x0386)
125#define SMIAPP_REG_U16_SCALING_MODE SMIAPP_REG_MK_U16(0x0400)
126#define SMIAPP_REG_U16_SPATIAL_SAMPLING SMIAPP_REG_MK_U16(0x0402)
127#define SMIAPP_REG_U16_SCALE_M SMIAPP_REG_MK_U16(0x0404)
128#define SMIAPP_REG_U16_SCALE_N SMIAPP_REG_MK_U16(0x0406)
129#define SMIAPP_REG_U16_DIGITAL_CROP_X_OFFSET SMIAPP_REG_MK_U16(0x0408)
130#define SMIAPP_REG_U16_DIGITAL_CROP_Y_OFFSET SMIAPP_REG_MK_U16(0x040a)
131#define SMIAPP_REG_U16_DIGITAL_CROP_IMAGE_WIDTH SMIAPP_REG_MK_U16(0x040c)
132#define SMIAPP_REG_U16_DIGITAL_CROP_IMAGE_HEIGHT SMIAPP_REG_MK_U16(0x040e)
133#define SMIAPP_REG_U16_COMPRESSION_MODE SMIAPP_REG_MK_U16(0x0500)
134#define SMIAPP_REG_U16_TEST_PATTERN_MODE SMIAPP_REG_MK_U16(0x0600)
135#define SMIAPP_REG_U16_TEST_DATA_RED SMIAPP_REG_MK_U16(0x0602)
136#define SMIAPP_REG_U16_TEST_DATA_GREENR SMIAPP_REG_MK_U16(0x0604)
137#define SMIAPP_REG_U16_TEST_DATA_BLUE SMIAPP_REG_MK_U16(0x0606)
138#define SMIAPP_REG_U16_TEST_DATA_GREENB SMIAPP_REG_MK_U16(0x0608)
139#define SMIAPP_REG_U16_HORIZONTAL_CURSOR_WIDTH SMIAPP_REG_MK_U16(0x060a)
140#define SMIAPP_REG_U16_HORIZONTAL_CURSOR_POSITION SMIAPP_REG_MK_U16(0x060c)
141#define SMIAPP_REG_U16_VERTICAL_CURSOR_WIDTH SMIAPP_REG_MK_U16(0x060e)
142#define SMIAPP_REG_U16_VERTICAL_CURSOR_POSITION SMIAPP_REG_MK_U16(0x0610)
143#define SMIAPP_REG_U16_FIFO_WATER_MARK_PIXELS SMIAPP_REG_MK_U16(0x0700)
144#define SMIAPP_REG_U8_TCLK_POST SMIAPP_REG_MK_U8(0x0800)
145#define SMIAPP_REG_U8_THS_PREPARE SMIAPP_REG_MK_U8(0x0801)
146#define SMIAPP_REG_U8_THS_ZERO_MIN SMIAPP_REG_MK_U8(0x0802)
147#define SMIAPP_REG_U8_THS_TRAIL SMIAPP_REG_MK_U8(0x0803)
148#define SMIAPP_REG_U8_TCLK_TRAIL_MIN SMIAPP_REG_MK_U8(0x0804)
149#define SMIAPP_REG_U8_TCLK_PREPARE SMIAPP_REG_MK_U8(0x0805)
150#define SMIAPP_REG_U8_TCLK_ZERO SMIAPP_REG_MK_U8(0x0806)
151#define SMIAPP_REG_U8_TLPX SMIAPP_REG_MK_U8(0x0807)
152#define SMIAPP_REG_U8_DPHY_CTRL SMIAPP_REG_MK_U8(0x0808)
153#define SMIAPP_REG_U32_REQUESTED_LINK_BIT_RATE_MBPS SMIAPP_REG_MK_U32(0x0820)
154#define SMIAPP_REG_U8_BINNING_MODE SMIAPP_REG_MK_U8(0x0900)
155#define SMIAPP_REG_U8_BINNING_TYPE SMIAPP_REG_MK_U8(0x0901)
156#define SMIAPP_REG_U8_BINNING_WEIGHTING SMIAPP_REG_MK_U8(0x0902)
157#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_CTRL SMIAPP_REG_MK_U8(0x0a00)
158#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_STATUS SMIAPP_REG_MK_U8(0x0a01)
159#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_PAGE_SELECT SMIAPP_REG_MK_U8(0x0a02)
160#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_0 SMIAPP_REG_MK_U8(0x0a04)
161#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_1 SMIAPP_REG_MK_U8(0x0a05)
162#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_2 SMIAPP_REG_MK_U8(0x0a06)
163#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_3 SMIAPP_REG_MK_U8(0x0a07)
164#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_4 SMIAPP_REG_MK_U8(0x0a08)
165#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_5 SMIAPP_REG_MK_U8(0x0a09)
166#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_12 SMIAPP_REG_MK_U8(0x0a10)
167#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_13 SMIAPP_REG_MK_U8(0x0a11)
168#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_14 SMIAPP_REG_MK_U8(0x0a12)
169#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_15 SMIAPP_REG_MK_U8(0x0a13)
170#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_16 SMIAPP_REG_MK_U8(0x0a14)
171#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_17 SMIAPP_REG_MK_U8(0x0a15)
172#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_18 SMIAPP_REG_MK_U8(0x0a16)
173#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_19 SMIAPP_REG_MK_U8(0x0a17)
174#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_20 SMIAPP_REG_MK_U8(0x0a18)
175#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_21 SMIAPP_REG_MK_U8(0x0a19)
176#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_22 SMIAPP_REG_MK_U8(0x0a1a)
177#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_23 SMIAPP_REG_MK_U8(0x0a1b)
178#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_24 SMIAPP_REG_MK_U8(0x0a1c)
179#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_25 SMIAPP_REG_MK_U8(0x0a1d)
180#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_26 SMIAPP_REG_MK_U8(0x0a1e)
181#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_27 SMIAPP_REG_MK_U8(0x0a1f)
182#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_28 SMIAPP_REG_MK_U8(0x0a20)
183#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_29 SMIAPP_REG_MK_U8(0x0a21)
184#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_30 SMIAPP_REG_MK_U8(0x0a22)
185#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_31 SMIAPP_REG_MK_U8(0x0a23)
186#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_32 SMIAPP_REG_MK_U8(0x0a24)
187#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_33 SMIAPP_REG_MK_U8(0x0a25)
188#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_34 SMIAPP_REG_MK_U8(0x0a26)
189#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_35 SMIAPP_REG_MK_U8(0x0a27)
190#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_36 SMIAPP_REG_MK_U8(0x0a28)
191#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_37 SMIAPP_REG_MK_U8(0x0a29)
192#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_38 SMIAPP_REG_MK_U8(0x0a2a)
193#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_39 SMIAPP_REG_MK_U8(0x0a2b)
194#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_40 SMIAPP_REG_MK_U8(0x0a2c)
195#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_41 SMIAPP_REG_MK_U8(0x0a2d)
196#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_42 SMIAPP_REG_MK_U8(0x0a2e)
197#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_43 SMIAPP_REG_MK_U8(0x0a2f)
198#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_44 SMIAPP_REG_MK_U8(0x0a30)
199#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_45 SMIAPP_REG_MK_U8(0x0a31)
200#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_46 SMIAPP_REG_MK_U8(0x0a32)
201#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_47 SMIAPP_REG_MK_U8(0x0a33)
202#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_48 SMIAPP_REG_MK_U8(0x0a34)
203#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_49 SMIAPP_REG_MK_U8(0x0a35)
204#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_50 SMIAPP_REG_MK_U8(0x0a36)
205#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_51 SMIAPP_REG_MK_U8(0x0a37)
206#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_52 SMIAPP_REG_MK_U8(0x0a38)
207#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_53 SMIAPP_REG_MK_U8(0x0a39)
208#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_54 SMIAPP_REG_MK_U8(0x0a3a)
209#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_55 SMIAPP_REG_MK_U8(0x0a3b)
210#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_56 SMIAPP_REG_MK_U8(0x0a3c)
211#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_57 SMIAPP_REG_MK_U8(0x0a3d)
212#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_58 SMIAPP_REG_MK_U8(0x0a3e)
213#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_59 SMIAPP_REG_MK_U8(0x0a3f)
214#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_60 SMIAPP_REG_MK_U8(0x0a40)
215#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_61 SMIAPP_REG_MK_U8(0x0a41)
216#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_62 SMIAPP_REG_MK_U8(0x0a42)
217#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_63 SMIAPP_REG_MK_U8(0x0a43)
218#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_CTRL SMIAPP_REG_MK_U8(0x0a44)
219#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_STATUS SMIAPP_REG_MK_U8(0x0a45)
220#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_PAGE_SELECT SMIAPP_REG_MK_U8(0x0a46)
221#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_0 SMIAPP_REG_MK_U8(0x0a48)
222#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_1 SMIAPP_REG_MK_U8(0x0a49)
223#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_2 SMIAPP_REG_MK_U8(0x0a4a)
224#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_3 SMIAPP_REG_MK_U8(0x0a4b)
225#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_4 SMIAPP_REG_MK_U8(0x0a4c)
226#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_5 SMIAPP_REG_MK_U8(0x0a4d)
227#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_6 SMIAPP_REG_MK_U8(0x0a4e)
228#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_7 SMIAPP_REG_MK_U8(0x0a4f)
229#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_8 SMIAPP_REG_MK_U8(0x0a50)
230#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_9 SMIAPP_REG_MK_U8(0x0a51)
231#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_10 SMIAPP_REG_MK_U8(0x0a52)
232#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_11 SMIAPP_REG_MK_U8(0x0a53)
233#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_12 SMIAPP_REG_MK_U8(0x0a54)
234#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_13 SMIAPP_REG_MK_U8(0x0a55)
235#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_14 SMIAPP_REG_MK_U8(0x0a56)
236#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_15 SMIAPP_REG_MK_U8(0x0a57)
237#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_16 SMIAPP_REG_MK_U8(0x0a58)
238#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_17 SMIAPP_REG_MK_U8(0x0a59)
239#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_18 SMIAPP_REG_MK_U8(0x0a5a)
240#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_19 SMIAPP_REG_MK_U8(0x0a5b)
241#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_20 SMIAPP_REG_MK_U8(0x0a5c)
242#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_21 SMIAPP_REG_MK_U8(0x0a5d)
243#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_22 SMIAPP_REG_MK_U8(0x0a5e)
244#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_23 SMIAPP_REG_MK_U8(0x0a5f)
245#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_24 SMIAPP_REG_MK_U8(0x0a60)
246#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_25 SMIAPP_REG_MK_U8(0x0a61)
247#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_26 SMIAPP_REG_MK_U8(0x0a62)
248#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_27 SMIAPP_REG_MK_U8(0x0a63)
249#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_28 SMIAPP_REG_MK_U8(0x0a64)
250#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_29 SMIAPP_REG_MK_U8(0x0a65)
251#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_30 SMIAPP_REG_MK_U8(0x0a66)
252#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_31 SMIAPP_REG_MK_U8(0x0a67)
253#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_32 SMIAPP_REG_MK_U8(0x0a68)
254#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_33 SMIAPP_REG_MK_U8(0x0a69)
255#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_34 SMIAPP_REG_MK_U8(0x0a6a)
256#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_35 SMIAPP_REG_MK_U8(0x0a6b)
257#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_36 SMIAPP_REG_MK_U8(0x0a6c)
258#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_37 SMIAPP_REG_MK_U8(0x0a6d)
259#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_38 SMIAPP_REG_MK_U8(0x0a6e)
260#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_39 SMIAPP_REG_MK_U8(0x0a6f)
261#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_40 SMIAPP_REG_MK_U8(0x0a70)
262#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_41 SMIAPP_REG_MK_U8(0x0a71)
263#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_42 SMIAPP_REG_MK_U8(0x0a72)
264#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_43 SMIAPP_REG_MK_U8(0x0a73)
265#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_44 SMIAPP_REG_MK_U8(0x0a74)
266#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_45 SMIAPP_REG_MK_U8(0x0a75)
267#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_46 SMIAPP_REG_MK_U8(0x0a76)
268#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_47 SMIAPP_REG_MK_U8(0x0a77)
269#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_48 SMIAPP_REG_MK_U8(0x0a78)
270#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_49 SMIAPP_REG_MK_U8(0x0a79)
271#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_50 SMIAPP_REG_MK_U8(0x0a7a)
272#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_51 SMIAPP_REG_MK_U8(0x0a7b)
273#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_52 SMIAPP_REG_MK_U8(0x0a7c)
274#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_53 SMIAPP_REG_MK_U8(0x0a7d)
275#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_54 SMIAPP_REG_MK_U8(0x0a7e)
276#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_55 SMIAPP_REG_MK_U8(0x0a7f)
277#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_56 SMIAPP_REG_MK_U8(0x0a80)
278#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_57 SMIAPP_REG_MK_U8(0x0a81)
279#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_58 SMIAPP_REG_MK_U8(0x0a82)
280#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_59 SMIAPP_REG_MK_U8(0x0a83)
281#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_60 SMIAPP_REG_MK_U8(0x0a84)
282#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_61 SMIAPP_REG_MK_U8(0x0a85)
283#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_62 SMIAPP_REG_MK_U8(0x0a86)
284#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_63 SMIAPP_REG_MK_U8(0x0a87)
285#define SMIAPP_REG_U8_SHADING_CORRECTION_ENABLE SMIAPP_REG_MK_U8(0x0b00)
286#define SMIAPP_REG_U8_LUMINANCE_CORRECTION_LEVEL SMIAPP_REG_MK_U8(0x0b01)
287#define SMIAPP_REG_U8_GREEN_IMBALANCE_FILTER_ENABLE SMIAPP_REG_MK_U8(0x0b02)
288#define SMIAPP_REG_U8_GREEN_IMBALANCE_FILTER_WEIGHT SMIAPP_REG_MK_U8(0x0b03)
289#define SMIAPP_REG_U8_BLACK_LEVEL_CORRECTION_ENABLE SMIAPP_REG_MK_U8(0x0b04)
290#define SMIAPP_REG_U8_MAPPED_COUPLET_CORRECT_ENABLE SMIAPP_REG_MK_U8(0x0b05)
291#define SMIAPP_REG_U8_SINGLE_DEFECT_CORRECT_ENABLE SMIAPP_REG_MK_U8(0x0b06)
292#define SMIAPP_REG_U8_SINGLE_DEFECT_CORRECT_WEIGHT SMIAPP_REG_MK_U8(0x0b07)
293#define SMIAPP_REG_U8_DYNAMIC_COUPLET_CORRECT_ENABLE SMIAPP_REG_MK_U8(0x0b08)
294#define SMIAPP_REG_U8_DYNAMIC_COUPLET_CORRECT_WEIGHT SMIAPP_REG_MK_U8(0x0b09)
295#define SMIAPP_REG_U8_COMBINED_DEFECT_CORRECT_ENABLE SMIAPP_REG_MK_U8(0x0b0a)
296#define SMIAPP_REG_U8_COMBINED_DEFECT_CORRECT_WEIGHT SMIAPP_REG_MK_U8(0x0b0b)
297#define SMIAPP_REG_U8_MODULE_SPECIFIC_CORRECTION_ENABLE SMIAPP_REG_MK_U8(0x0b0c)
298#define SMIAPP_REG_U8_MODULE_SPECIFIC_CORRECTION_WEIGHT SMIAPP_REG_MK_U8(0x0b0d)
299#define SMIAPP_REG_U8_MAPPED_LINE_DEFECT_CORRECT_ENABLE SMIAPP_REG_MK_U8(0x0b0e)
300#define SMIAPP_REG_U8_MAPPED_LINE_DEFECT_CORRECT_ADJUST SMIAPP_REG_MK_U8(0x0b0f)
301#define SMIAPP_REG_U8_MAPPED_COUPLET_CORRECT_ADJUST SMIAPP_REG_MK_U8(0x0b10)
302#define SMIAPP_REG_U8_MAPPED_TRIPLET_DEFECT_CORRECT_ENABLE SMIAPP_REG_MK_U8(0x0b11)
303#define SMIAPP_REG_U8_MAPPED_TRIPLET_DEFECT_CORRECT_ADJUST SMIAPP_REG_MK_U8(0x0b12)
304#define SMIAPP_REG_U8_DYNAMIC_TRIPLET_DEFECT_CORRECT_ENABLE SMIAPP_REG_MK_U8(0x0b13)
305#define SMIAPP_REG_U8_DYNAMIC_TRIPLET_DEFECT_CORRECT_ADJUST SMIAPP_REG_MK_U8(0x0b14)
306#define SMIAPP_REG_U8_DYNAMIC_LINE_DEFECT_CORRECT_ENABLE SMIAPP_REG_MK_U8(0x0b15)
307#define SMIAPP_REG_U8_DYNAMIC_LINE_DEFECT_CORRECT_ADJUST SMIAPP_REG_MK_U8(0x0b16)
308#define SMIAPP_REG_U8_EDOF_MODE SMIAPP_REG_MK_U8(0x0b80)
309#define SMIAPP_REG_U8_SHARPNESS SMIAPP_REG_MK_U8(0x0b83)
310#define SMIAPP_REG_U8_DENOISING SMIAPP_REG_MK_U8(0x0b84)
311#define SMIAPP_REG_U8_MODULE_SPECIFIC SMIAPP_REG_MK_U8(0x0b85)
312#define SMIAPP_REG_U16_DEPTH_OF_FIELD SMIAPP_REG_MK_U16(0x0b86)
313#define SMIAPP_REG_U16_FOCUS_DISTANCE SMIAPP_REG_MK_U16(0x0b88)
314#define SMIAPP_REG_U8_ESTIMATION_MODE_CTRL SMIAPP_REG_MK_U8(0x0b8a)
315#define SMIAPP_REG_U16_COLOUR_TEMPERATURE SMIAPP_REG_MK_U16(0x0b8c)
316#define SMIAPP_REG_U16_ABSOLUTE_GAIN_GREENR SMIAPP_REG_MK_U16(0x0b8e)
317#define SMIAPP_REG_U16_ABSOLUTE_GAIN_RED SMIAPP_REG_MK_U16(0x0b90)
318#define SMIAPP_REG_U16_ABSOLUTE_GAIN_BLUE SMIAPP_REG_MK_U16(0x0b92)
319#define SMIAPP_REG_U16_ABSOLUTE_GAIN_GREENB SMIAPP_REG_MK_U16(0x0b94)
320#define SMIAPP_REG_U8_ESTIMATION_ZONE_MODE SMIAPP_REG_MK_U8(0x0bc0)
321#define SMIAPP_REG_U16_FIXED_ZONE_WEIGHTING SMIAPP_REG_MK_U16(0x0bc2)
322#define SMIAPP_REG_U16_CUSTOM_ZONE_X_START SMIAPP_REG_MK_U16(0x0bc4)
323#define SMIAPP_REG_U16_CUSTOM_ZONE_Y_START SMIAPP_REG_MK_U16(0x0bc6)
324#define SMIAPP_REG_U16_CUSTOM_ZONE_WIDTH SMIAPP_REG_MK_U16(0x0bc8)
325#define SMIAPP_REG_U16_CUSTOM_ZONE_HEIGHT SMIAPP_REG_MK_U16(0x0bca)
326#define SMIAPP_REG_U8_GLOBAL_RESET_CTRL1 SMIAPP_REG_MK_U8(0x0c00)
327#define SMIAPP_REG_U8_GLOBAL_RESET_CTRL2 SMIAPP_REG_MK_U8(0x0c01)
328#define SMIAPP_REG_U8_GLOBAL_RESET_MODE_CONFIG_1 SMIAPP_REG_MK_U8(0x0c02)
329#define SMIAPP_REG_U8_GLOBAL_RESET_MODE_CONFIG_2 SMIAPP_REG_MK_U8(0x0c03)
330#define SMIAPP_REG_U16_TRDY_CTRL SMIAPP_REG_MK_U16(0x0c04)
331#define SMIAPP_REG_U16_TRDOUT_CTRL SMIAPP_REG_MK_U16(0x0c06)
332#define SMIAPP_REG_U16_TSHUTTER_STROBE_DELAY_CTRL SMIAPP_REG_MK_U16(0x0c08)
333#define SMIAPP_REG_U16_TSHUTTER_STROBE_WIDTH_CTRL SMIAPP_REG_MK_U16(0x0c0a)
334#define SMIAPP_REG_U16_TFLASH_STROBE_DELAY_CTRL SMIAPP_REG_MK_U16(0x0c0c)
335#define SMIAPP_REG_U16_TFLASH_STROBE_WIDTH_HIGH_CTRL SMIAPP_REG_MK_U16(0x0c0e)
336#define SMIAPP_REG_U16_TGRST_INTERVAL_CTRL SMIAPP_REG_MK_U16(0x0c10)
337#define SMIAPP_REG_U8_FLASH_STROBE_ADJUSTMENT SMIAPP_REG_MK_U8(0x0c12)
338#define SMIAPP_REG_U16_FLASH_STROBE_START_POINT SMIAPP_REG_MK_U16(0x0c14)
339#define SMIAPP_REG_U16_TFLASH_STROBE_DELAY_RS_CTRL SMIAPP_REG_MK_U16(0x0c16)
340#define SMIAPP_REG_U16_TFLASH_STROBE_WIDTH_HIGH_RS_CTRL SMIAPP_REG_MK_U16(0x0c18)
341#define SMIAPP_REG_U8_FLASH_MODE_RS SMIAPP_REG_MK_U8(0x0c1a)
342#define SMIAPP_REG_U8_FLASH_TRIGGER_RS SMIAPP_REG_MK_U8(0x0c1b)
343#define SMIAPP_REG_U8_FLASH_STATUS SMIAPP_REG_MK_U8(0x0c1c)
344#define SMIAPP_REG_U8_SA_STROBE_MODE SMIAPP_REG_MK_U8(0x0c1d)
345#define SMIAPP_REG_U16_SA_STROBE_START_POINT SMIAPP_REG_MK_U16(0x0c1e)
346#define SMIAPP_REG_U16_TSA_STROBE_DELAY_CTRL SMIAPP_REG_MK_U16(0x0c20)
347#define SMIAPP_REG_U16_TSA_STROBE_WIDTH_CTRL SMIAPP_REG_MK_U16(0x0c22)
348#define SMIAPP_REG_U8_SA_STROBE_TRIGGER SMIAPP_REG_MK_U8(0x0c24)
349#define SMIAPP_REG_U8_SPECIAL_ACTUATOR_STATUS SMIAPP_REG_MK_U8(0x0c25)
350#define SMIAPP_REG_U16_TFLASH_STROBE_WIDTH2_HIGH_RS_CTRL SMIAPP_REG_MK_U16(0x0c26)
351#define SMIAPP_REG_U16_TFLASH_STROBE_WIDTH_LOW_RS_CTRL SMIAPP_REG_MK_U16(0x0c28)
352#define SMIAPP_REG_U8_TFLASH_STROBE_COUNT_RS_CTRL SMIAPP_REG_MK_U8(0x0c2a)
353#define SMIAPP_REG_U8_TFLASH_STROBE_COUNT_CTRL SMIAPP_REG_MK_U8(0x0c2b)
354#define SMIAPP_REG_U16_TFLASH_STROBE_WIDTH2_HIGH_CTRL SMIAPP_REG_MK_U16(0x0c2c)
355#define SMIAPP_REG_U16_TFLASH_STROBE_WIDTH_LOW_CTRL SMIAPP_REG_MK_U16(0x0c2e)
356#define SMIAPP_REG_U8_LOW_LEVEL_CTRL SMIAPP_REG_MK_U8(0x0c80)
357#define SMIAPP_REG_U16_MAIN_TRIGGER_REF_POINT SMIAPP_REG_MK_U16(0x0c82)
358#define SMIAPP_REG_U16_MAIN_TRIGGER_T3 SMIAPP_REG_MK_U16(0x0c84)
359#define SMIAPP_REG_U8_MAIN_TRIGGER_COUNT SMIAPP_REG_MK_U8(0x0c86)
360#define SMIAPP_REG_U16_PHASE1_TRIGGER_T3 SMIAPP_REG_MK_U16(0x0c88)
361#define SMIAPP_REG_U8_PHASE1_TRIGGER_COUNT SMIAPP_REG_MK_U8(0x0c8a)
362#define SMIAPP_REG_U16_PHASE2_TRIGGER_T3 SMIAPP_REG_MK_U16(0x0c8c)
363#define SMIAPP_REG_U8_PHASE2_TRIGGER_COUNT SMIAPP_REG_MK_U8(0x0c8e)
364#define SMIAPP_REG_U8_MECH_SHUTTER_CTRL SMIAPP_REG_MK_U8(0x0d00)
365#define SMIAPP_REG_U8_OPERATION_MODE SMIAPP_REG_MK_U8(0x0d01)
366#define SMIAPP_REG_U8_ACT_STATE1 SMIAPP_REG_MK_U8(0x0d02)
367#define SMIAPP_REG_U8_ACT_STATE2 SMIAPP_REG_MK_U8(0x0d03)
368#define SMIAPP_REG_U16_FOCUS_CHANGE SMIAPP_REG_MK_U16(0x0d80)
369#define SMIAPP_REG_U16_FOCUS_CHANGE_CONTROL SMIAPP_REG_MK_U16(0x0d82)
370#define SMIAPP_REG_U16_FOCUS_CHANGE_NUMBER_PHASE1 SMIAPP_REG_MK_U16(0x0d84)
371#define SMIAPP_REG_U16_FOCUS_CHANGE_NUMBER_PHASE2 SMIAPP_REG_MK_U16(0x0d86)
372#define SMIAPP_REG_U8_STROBE_COUNT_PHASE1 SMIAPP_REG_MK_U8(0x0d88)
373#define SMIAPP_REG_U8_STROBE_COUNT_PHASE2 SMIAPP_REG_MK_U8(0x0d89)
374#define SMIAPP_REG_U8_POSITION SMIAPP_REG_MK_U8(0x0d8a)
375#define SMIAPP_REG_U8_BRACKETING_LUT_CONTROL SMIAPP_REG_MK_U8(0x0e00)
376#define SMIAPP_REG_U8_BRACKETING_LUT_MODE SMIAPP_REG_MK_U8(0x0e01)
377#define SMIAPP_REG_U8_BRACKETING_LUT_ENTRY_CONTROL SMIAPP_REG_MK_U8(0x0e02)
378#define SMIAPP_REG_U8_LUT_PARAMETERS_START SMIAPP_REG_MK_U8(0x0e10)
379#define SMIAPP_REG_U8_LUT_PARAMETERS_END SMIAPP_REG_MK_U8(0x0eff)
380#define SMIAPP_REG_U16_INTEGRATION_TIME_CAPABILITY SMIAPP_REG_MK_U16(0x1000)
381#define SMIAPP_REG_U16_COARSE_INTEGRATION_TIME_MIN SMIAPP_REG_MK_U16(0x1004)
382#define SMIAPP_REG_U16_COARSE_INTEGRATION_TIME_MAX_MARGIN SMIAPP_REG_MK_U16(0x1006)
383#define SMIAPP_REG_U16_FINE_INTEGRATION_TIME_MIN SMIAPP_REG_MK_U16(0x1008)
384#define SMIAPP_REG_U16_FINE_INTEGRATION_TIME_MAX_MARGIN SMIAPP_REG_MK_U16(0x100a)
385#define SMIAPP_REG_U16_DIGITAL_GAIN_CAPABILITY SMIAPP_REG_MK_U16(0x1080)
386#define SMIAPP_REG_U16_DIGITAL_GAIN_MIN SMIAPP_REG_MK_U16(0x1084)
387#define SMIAPP_REG_U16_DIGITAL_GAIN_MAX SMIAPP_REG_MK_U16(0x1086)
388#define SMIAPP_REG_U16_DIGITAL_GAIN_STEP_SIZE SMIAPP_REG_MK_U16(0x1088)
389#define SMIAPP_REG_F32_MIN_EXT_CLK_FREQ_HZ SMIAPP_REG_MK_F32(0x1100)
390#define SMIAPP_REG_F32_MAX_EXT_CLK_FREQ_HZ SMIAPP_REG_MK_F32(0x1104)
391#define SMIAPP_REG_U16_MIN_PRE_PLL_CLK_DIV SMIAPP_REG_MK_U16(0x1108)
392#define SMIAPP_REG_U16_MAX_PRE_PLL_CLK_DIV SMIAPP_REG_MK_U16(0x110a)
393#define SMIAPP_REG_F32_MIN_PLL_IP_FREQ_HZ SMIAPP_REG_MK_F32(0x110c)
394#define SMIAPP_REG_F32_MAX_PLL_IP_FREQ_HZ SMIAPP_REG_MK_F32(0x1110)
395#define SMIAPP_REG_U16_MIN_PLL_MULTIPLIER SMIAPP_REG_MK_U16(0x1114)
396#define SMIAPP_REG_U16_MAX_PLL_MULTIPLIER SMIAPP_REG_MK_U16(0x1116)
397#define SMIAPP_REG_F32_MIN_PLL_OP_FREQ_HZ SMIAPP_REG_MK_F32(0x1118)
398#define SMIAPP_REG_F32_MAX_PLL_OP_FREQ_HZ SMIAPP_REG_MK_F32(0x111c)
399#define SMIAPP_REG_U16_MIN_VT_SYS_CLK_DIV SMIAPP_REG_MK_U16(0x1120)
400#define SMIAPP_REG_U16_MAX_VT_SYS_CLK_DIV SMIAPP_REG_MK_U16(0x1122)
401#define SMIAPP_REG_F32_MIN_VT_SYS_CLK_FREQ_HZ SMIAPP_REG_MK_F32(0x1124)
402#define SMIAPP_REG_F32_MAX_VT_SYS_CLK_FREQ_HZ SMIAPP_REG_MK_F32(0x1128)
403#define SMIAPP_REG_F32_MIN_VT_PIX_CLK_FREQ_HZ SMIAPP_REG_MK_F32(0x112c)
404#define SMIAPP_REG_F32_MAX_VT_PIX_CLK_FREQ_HZ SMIAPP_REG_MK_F32(0x1130)
405#define SMIAPP_REG_U16_MIN_VT_PIX_CLK_DIV SMIAPP_REG_MK_U16(0x1134)
406#define SMIAPP_REG_U16_MAX_VT_PIX_CLK_DIV SMIAPP_REG_MK_U16(0x1136)
407#define SMIAPP_REG_U16_MIN_FRAME_LENGTH_LINES SMIAPP_REG_MK_U16(0x1140)
408#define SMIAPP_REG_U16_MAX_FRAME_LENGTH_LINES SMIAPP_REG_MK_U16(0x1142)
409#define SMIAPP_REG_U16_MIN_LINE_LENGTH_PCK SMIAPP_REG_MK_U16(0x1144)
410#define SMIAPP_REG_U16_MAX_LINE_LENGTH_PCK SMIAPP_REG_MK_U16(0x1146)
411#define SMIAPP_REG_U16_MIN_LINE_BLANKING_PCK SMIAPP_REG_MK_U16(0x1148)
412#define SMIAPP_REG_U16_MIN_FRAME_BLANKING_LINES SMIAPP_REG_MK_U16(0x114a)
413#define SMIAPP_REG_U8_MIN_LINE_LENGTH_PCK_STEP_SIZE SMIAPP_REG_MK_U8(0x114c)
414#define SMIAPP_REG_U16_MIN_OP_SYS_CLK_DIV SMIAPP_REG_MK_U16(0x1160)
415#define SMIAPP_REG_U16_MAX_OP_SYS_CLK_DIV SMIAPP_REG_MK_U16(0x1162)
416#define SMIAPP_REG_F32_MIN_OP_SYS_CLK_FREQ_HZ SMIAPP_REG_MK_F32(0x1164)
417#define SMIAPP_REG_F32_MAX_OP_SYS_CLK_FREQ_HZ SMIAPP_REG_MK_F32(0x1168)
418#define SMIAPP_REG_U16_MIN_OP_PIX_CLK_DIV SMIAPP_REG_MK_U16(0x116c)
419#define SMIAPP_REG_U16_MAX_OP_PIX_CLK_DIV SMIAPP_REG_MK_U16(0x116e)
420#define SMIAPP_REG_F32_MIN_OP_PIX_CLK_FREQ_HZ SMIAPP_REG_MK_F32(0x1170)
421#define SMIAPP_REG_F32_MAX_OP_PIX_CLK_FREQ_HZ SMIAPP_REG_MK_F32(0x1174)
422#define SMIAPP_REG_U16_X_ADDR_MIN SMIAPP_REG_MK_U16(0x1180)
423#define SMIAPP_REG_U16_Y_ADDR_MIN SMIAPP_REG_MK_U16(0x1182)
424#define SMIAPP_REG_U16_X_ADDR_MAX SMIAPP_REG_MK_U16(0x1184)
425#define SMIAPP_REG_U16_Y_ADDR_MAX SMIAPP_REG_MK_U16(0x1186)
426#define SMIAPP_REG_U16_MIN_X_OUTPUT_SIZE SMIAPP_REG_MK_U16(0x1188)
427#define SMIAPP_REG_U16_MIN_Y_OUTPUT_SIZE SMIAPP_REG_MK_U16(0x118a)
428#define SMIAPP_REG_U16_MAX_X_OUTPUT_SIZE SMIAPP_REG_MK_U16(0x118c)
429#define SMIAPP_REG_U16_MAX_Y_OUTPUT_SIZE SMIAPP_REG_MK_U16(0x118e)
430#define SMIAPP_REG_U16_MIN_EVEN_INC SMIAPP_REG_MK_U16(0x11c0)
431#define SMIAPP_REG_U16_MAX_EVEN_INC SMIAPP_REG_MK_U16(0x11c2)
432#define SMIAPP_REG_U16_MIN_ODD_INC SMIAPP_REG_MK_U16(0x11c4)
433#define SMIAPP_REG_U16_MAX_ODD_INC SMIAPP_REG_MK_U16(0x11c6)
434#define SMIAPP_REG_U16_SCALING_CAPABILITY SMIAPP_REG_MK_U16(0x1200)
435#define SMIAPP_REG_U16_SCALER_M_MIN SMIAPP_REG_MK_U16(0x1204)
436#define SMIAPP_REG_U16_SCALER_M_MAX SMIAPP_REG_MK_U16(0x1206)
437#define SMIAPP_REG_U16_SCALER_N_MIN SMIAPP_REG_MK_U16(0x1208)
438#define SMIAPP_REG_U16_SCALER_N_MAX SMIAPP_REG_MK_U16(0x120a)
439#define SMIAPP_REG_U16_SPATIAL_SAMPLING_CAPABILITY SMIAPP_REG_MK_U16(0x120c)
440#define SMIAPP_REG_U8_DIGITAL_CROP_CAPABILITY SMIAPP_REG_MK_U8(0x120e)
441#define SMIAPP_REG_U16_COMPRESSION_CAPABILITY SMIAPP_REG_MK_U16(0x1300)
442#define SMIAPP_REG_U16_MATRIX_ELEMENT_REDINRED SMIAPP_REG_MK_U16(0x1400)
443#define SMIAPP_REG_U16_MATRIX_ELEMENT_GREENINRED SMIAPP_REG_MK_U16(0x1402)
444#define SMIAPP_REG_U16_MATRIX_ELEMENT_BLUEINRED SMIAPP_REG_MK_U16(0x1404)
445#define SMIAPP_REG_U16_MATRIX_ELEMENT_REDINGREEN SMIAPP_REG_MK_U16(0x1406)
446#define SMIAPP_REG_U16_MATRIX_ELEMENT_GREENINGREEN SMIAPP_REG_MK_U16(0x1408)
447#define SMIAPP_REG_U16_MATRIX_ELEMENT_BLUEINGREEN SMIAPP_REG_MK_U16(0x140a)
448#define SMIAPP_REG_U16_MATRIX_ELEMENT_REDINBLUE SMIAPP_REG_MK_U16(0x140c)
449#define SMIAPP_REG_U16_MATRIX_ELEMENT_GREENINBLUE SMIAPP_REG_MK_U16(0x140e)
450#define SMIAPP_REG_U16_MATRIX_ELEMENT_BLUEINBLUE SMIAPP_REG_MK_U16(0x1410)
451#define SMIAPP_REG_U16_FIFO_SIZE_PIXELS SMIAPP_REG_MK_U16(0x1500)
452#define SMIAPP_REG_U8_FIFO_SUPPORT_CAPABILITY SMIAPP_REG_MK_U8(0x1502)
453#define SMIAPP_REG_U8_DPHY_CTRL_CAPABILITY SMIAPP_REG_MK_U8(0x1600)
454#define SMIAPP_REG_U8_CSI_LANE_MODE_CAPABILITY SMIAPP_REG_MK_U8(0x1601)
455#define SMIAPP_REG_U8_CSI_SIGNALLING_MODE_CAPABILITY SMIAPP_REG_MK_U8(0x1602)
456#define SMIAPP_REG_U8_FAST_STANDBY_CAPABILITY SMIAPP_REG_MK_U8(0x1603)
457#define SMIAPP_REG_U8_CCI_ADDRESS_CONTROL_CAPABILITY SMIAPP_REG_MK_U8(0x1604)
458#define SMIAPP_REG_U32_MAX_PER_LANE_BITRATE_1_LANE_MODE_MBPS SMIAPP_REG_MK_U32(0x1608)
459#define SMIAPP_REG_U32_MAX_PER_LANE_BITRATE_2_LANE_MODE_MBPS SMIAPP_REG_MK_U32(0x160c)
460#define SMIAPP_REG_U32_MAX_PER_LANE_BITRATE_3_LANE_MODE_MBPS SMIAPP_REG_MK_U32(0x1610)
461#define SMIAPP_REG_U32_MAX_PER_LANE_BITRATE_4_LANE_MODE_MBPS SMIAPP_REG_MK_U32(0x1614)
462#define SMIAPP_REG_U8_TEMP_SENSOR_CAPABILITY SMIAPP_REG_MK_U8(0x1618)
463#define SMIAPP_REG_U16_MIN_FRAME_LENGTH_LINES_BIN SMIAPP_REG_MK_U16(0x1700)
464#define SMIAPP_REG_U16_MAX_FRAME_LENGTH_LINES_BIN SMIAPP_REG_MK_U16(0x1702)
465#define SMIAPP_REG_U16_MIN_LINE_LENGTH_PCK_BIN SMIAPP_REG_MK_U16(0x1704)
466#define SMIAPP_REG_U16_MAX_LINE_LENGTH_PCK_BIN SMIAPP_REG_MK_U16(0x1706)
467#define SMIAPP_REG_U16_MIN_LINE_BLANKING_PCK_BIN SMIAPP_REG_MK_U16(0x1708)
468#define SMIAPP_REG_U16_FINE_INTEGRATION_TIME_MIN_BIN SMIAPP_REG_MK_U16(0x170a)
469#define SMIAPP_REG_U16_FINE_INTEGRATION_TIME_MAX_MARGIN_BIN SMIAPP_REG_MK_U16(0x170c)
470#define SMIAPP_REG_U8_BINNING_CAPABILITY SMIAPP_REG_MK_U8(0x1710)
471#define SMIAPP_REG_U8_BINNING_WEIGHTING_CAPABILITY SMIAPP_REG_MK_U8(0x1711)
472#define SMIAPP_REG_U8_BINNING_SUBTYPES SMIAPP_REG_MK_U8(0x1712)
473#define SMIAPP_REG_U8_BINNING_TYPE_n(n) SMIAPP_REG_MK_U8(0x1713 + (n)) /* 1 <= n <= 237 */
474#define SMIAPP_REG_U8_DATA_TRANSFER_IF_CAPABILITY SMIAPP_REG_MK_U8(0x1800)
475#define SMIAPP_REG_U8_SHADING_CORRECTION_CAPABILITY SMIAPP_REG_MK_U8(0x1900)
476#define SMIAPP_REG_U8_GREEN_IMBALANCE_CAPABILITY SMIAPP_REG_MK_U8(0x1901)
477#define SMIAPP_REG_U8_BLACK_LEVEL_CAPABILITY SMIAPP_REG_MK_U8(0x1902)
478#define SMIAPP_REG_U8_MODULE_SPECIFIC_CORRECTION_CAPABILITY SMIAPP_REG_MK_U8(0x1903)
479#define SMIAPP_REG_U16_DEFECT_CORRECTION_CAPABILITY SMIAPP_REG_MK_U16(0x1904)
480#define SMIAPP_REG_U16_DEFECT_CORRECTION_CAPABILITY_2 SMIAPP_REG_MK_U16(0x1906)
481#define SMIAPP_REG_U8_EDOF_CAPABILITY SMIAPP_REG_MK_U8(0x1980)
482#define SMIAPP_REG_U8_ESTIMATION_FRAMES SMIAPP_REG_MK_U8(0x1981)
483#define SMIAPP_REG_U8_SUPPORTS_SHARPNESS_ADJ SMIAPP_REG_MK_U8(0x1982)
484#define SMIAPP_REG_U8_SUPPORTS_DENOISING_ADJ SMIAPP_REG_MK_U8(0x1983)
485#define SMIAPP_REG_U8_SUPPORTS_MODULE_SPECIFIC_ADJ SMIAPP_REG_MK_U8(0x1984)
486#define SMIAPP_REG_U8_SUPPORTS_DEPTH_OF_FIELD_ADJ SMIAPP_REG_MK_U8(0x1985)
487#define SMIAPP_REG_U8_SUPPORTS_FOCUS_DISTANCE_ADJ SMIAPP_REG_MK_U8(0x1986)
488#define SMIAPP_REG_U8_COLOUR_FEEDBACK_CAPABILITY SMIAPP_REG_MK_U8(0x1987)
489#define SMIAPP_REG_U8_EDOF_SUPPORT_AB_NXM SMIAPP_REG_MK_U8(0x1988)
490#define SMIAPP_REG_U8_ESTIMATION_MODE_CAPABILITY SMIAPP_REG_MK_U8(0x19c0)
491#define SMIAPP_REG_U8_ESTIMATION_ZONE_CAPABILITY SMIAPP_REG_MK_U8(0x19c1)
492#define SMIAPP_REG_U16_EST_DEPTH_OF_FIELD SMIAPP_REG_MK_U16(0x19c2)
493#define SMIAPP_REG_U16_EST_FOCUS_DISTANCE SMIAPP_REG_MK_U16(0x19c4)
494#define SMIAPP_REG_U16_CAPABILITY_TRDY_MIN SMIAPP_REG_MK_U16(0x1a00)
495#define SMIAPP_REG_U8_FLASH_MODE_CAPABILITY SMIAPP_REG_MK_U8(0x1a02)
496#define SMIAPP_REG_U16_MECH_SHUT_AND_ACT_START_ADDR SMIAPP_REG_MK_U16(0x1b02)
497#define SMIAPP_REG_U8_ACTUATOR_CAPABILITY SMIAPP_REG_MK_U8(0x1b04)
498#define SMIAPP_REG_U16_ACTUATOR_TYPE SMIAPP_REG_MK_U16(0x1b40)
499#define SMIAPP_REG_U8_AF_DEVICE_ADDRESS SMIAPP_REG_MK_U8(0x1b42)
500#define SMIAPP_REG_U16_FOCUS_CHANGE_ADDRESS SMIAPP_REG_MK_U16(0x1b44)
501#define SMIAPP_REG_U8_BRACKETING_LUT_CAPABILITY_1 SMIAPP_REG_MK_U8(0x1c00)
502#define SMIAPP_REG_U8_BRACKETING_LUT_CAPABILITY_2 SMIAPP_REG_MK_U8(0x1c01)
503#define SMIAPP_REG_U8_BRACKETING_LUT_SIZE SMIAPP_REG_MK_U8(0x1c02)
diff --git a/drivers/media/video/smiapp/smiapp-reg.h b/drivers/media/video/smiapp/smiapp-reg.h
new file mode 100644
index 000000000000..d0167aa17534
--- /dev/null
+++ b/drivers/media/video/smiapp/smiapp-reg.h
@@ -0,0 +1,122 @@
1/*
2 * drivers/media/video/smiapp/smiapp-reg.h
3 *
4 * Generic driver for SMIA/SMIA++ compliant camera modules
5 *
6 * Copyright (C) 2011--2012 Nokia Corporation
7 * Contact: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * version 2 as published by the Free Software Foundation.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
21 * 02110-1301 USA
22 *
23 */
24
25#ifndef __SMIAPP_REG_H_
26#define __SMIAPP_REG_H_
27
28#include "smiapp-reg-defs.h"
29
30/* Bits for above register */
31#define SMIAPP_IMAGE_ORIENTATION_HFLIP (1 << 0)
32#define SMIAPP_IMAGE_ORIENTATION_VFLIP (1 << 1)
33
34#define SMIAPP_DATA_TRANSFER_IF_1_CTRL_EN (1 << 0)
35#define SMIAPP_DATA_TRANSFER_IF_1_CTRL_RD_EN (0 << 1)
36#define SMIAPP_DATA_TRANSFER_IF_1_CTRL_WR_EN (1 << 1)
37#define SMIAPP_DATA_TRANSFER_IF_1_CTRL_ERR_CLEAR (1 << 2)
38#define SMIAPP_DATA_TRANSFER_IF_1_STATUS_RD_READY (1 << 0)
39#define SMIAPP_DATA_TRANSFER_IF_1_STATUS_WR_READY (1 << 1)
40#define SMIAPP_DATA_TRANSFER_IF_1_STATUS_EDATA (1 << 2)
41#define SMIAPP_DATA_TRANSFER_IF_1_STATUS_EUSAGE (1 << 3)
42
43#define SMIAPP_SOFTWARE_RESET (1 << 0)
44
45#define SMIAPP_FLASH_MODE_CAPABILITY_SINGLE_STROBE (1 << 0)
46#define SMIAPP_FLASH_MODE_CAPABILITY_MULTIPLE_STROBE (1 << 1)
47
48#define SMIAPP_DPHY_CTRL_AUTOMATIC 0
49/* DPHY control based on REQUESTED_LINK_BIT_RATE_MBPS */
50#define SMIAPP_DPHY_CTRL_UI 1
51#define SMIAPP_DPHY_CTRL_REGISTER 2
52
53#define SMIAPP_COMPRESSION_MODE_SIMPLE_PREDICTOR 1
54#define SMIAPP_COMPRESSION_MODE_ADVANCED_PREDICTOR 2
55
56#define SMIAPP_MODE_SELECT_SOFTWARE_STANDBY 0
57#define SMIAPP_MODE_SELECT_STREAMING 1
58
59#define SMIAPP_SCALING_MODE_NONE 0
60#define SMIAPP_SCALING_MODE_HORIZONTAL 1
61#define SMIAPP_SCALING_MODE_BOTH 2
62
63#define SMIAPP_SCALING_CAPABILITY_NONE 0
64#define SMIAPP_SCALING_CAPABILITY_HORIZONTAL 1
65#define SMIAPP_SCALING_CAPABILITY_BOTH 2 /* horizontal/both */
66
67/* digital crop right before scaler */
68#define SMIAPP_DIGITAL_CROP_CAPABILITY_NONE 0
69#define SMIAPP_DIGITAL_CROP_CAPABILITY_INPUT_CROP 1
70
71#define SMIAPP_BINNING_CAPABILITY_NO 0
72#define SMIAPP_BINNING_CAPABILITY_YES 1
73
74/* Maximum number of binning subtypes */
75#define SMIAPP_BINNING_SUBTYPES 253
76
77#define SMIAPP_PIXEL_ORDER_GRBG 0
78#define SMIAPP_PIXEL_ORDER_RGGB 1
79#define SMIAPP_PIXEL_ORDER_BGGR 2
80#define SMIAPP_PIXEL_ORDER_GBRG 3
81
82#define SMIAPP_DATA_FORMAT_MODEL_TYPE_NORMAL 1
83#define SMIAPP_DATA_FORMAT_MODEL_TYPE_EXTENDED 2
84#define SMIAPP_DATA_FORMAT_MODEL_TYPE_NORMAL_N 8
85#define SMIAPP_DATA_FORMAT_MODEL_TYPE_EXTENDED_N 16
86
87#define SMIAPP_FRAME_FORMAT_MODEL_TYPE_2BYTE 0x01
88#define SMIAPP_FRAME_FORMAT_MODEL_TYPE_4BYTE 0x02
89#define SMIAPP_FRAME_FORMAT_MODEL_SUBTYPE_NROWS_MASK 0x0f
90#define SMIAPP_FRAME_FORMAT_MODEL_SUBTYPE_NCOLS_MASK 0xf0
91#define SMIAPP_FRAME_FORMAT_MODEL_SUBTYPE_NCOLS_SHIFT 4
92
93#define SMIAPP_FRAME_FORMAT_DESC_2_PIXELCODE_MASK 0xf000
94#define SMIAPP_FRAME_FORMAT_DESC_2_PIXELCODE_SHIFT 12
95#define SMIAPP_FRAME_FORMAT_DESC_2_PIXELS_MASK 0x0fff
96
97#define SMIAPP_FRAME_FORMAT_DESC_4_PIXELCODE_MASK 0xf0000000
98#define SMIAPP_FRAME_FORMAT_DESC_4_PIXELCODE_SHIFT 28
99#define SMIAPP_FRAME_FORMAT_DESC_4_PIXELS_MASK 0x0000ffff
100
101#define SMIAPP_FRAME_FORMAT_DESC_PIXELCODE_EMBEDDED 1
102#define SMIAPP_FRAME_FORMAT_DESC_PIXELCODE_DUMMY 2
103#define SMIAPP_FRAME_FORMAT_DESC_PIXELCODE_BLACK 3
104#define SMIAPP_FRAME_FORMAT_DESC_PIXELCODE_DARK 4
105#define SMIAPP_FRAME_FORMAT_DESC_PIXELCODE_VISIBLE 5
106
107#define SMIAPP_FAST_STANDBY_CTRL_COMPLETE_FRAMES 0
108#define SMIAPP_FAST_STANDBY_CTRL_IMMEDIATE 1
109
110/* Scaling N factor */
111#define SMIAPP_SCALE_N 16
112
113/* Image statistics registers */
114/* Registers 0x2000 to 0x2fff are reserved for future
115 * use for statistics features.
116 */
117
118/* Manufacturer Specific Registers: 0x3000 to 0x3fff
119 * The manufacturer specifies these as a black box.
120 */
121
122#endif /* __SMIAPP_REG_H_ */
diff --git a/drivers/media/video/smiapp/smiapp-regs.c b/drivers/media/video/smiapp/smiapp-regs.c
new file mode 100644
index 000000000000..4851ff710779
--- /dev/null
+++ b/drivers/media/video/smiapp/smiapp-regs.c
@@ -0,0 +1,213 @@
1/*
2 * drivers/media/video/smiapp/smiapp-regs.c
3 *
4 * Generic driver for SMIA/SMIA++ compliant camera modules
5 *
6 * Copyright (C) 2011--2012 Nokia Corporation
7 * Contact: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * version 2 as published by the Free Software Foundation.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
21 * 02110-1301 USA
22 *
23 */
24
25#include "smiapp-debug.h"
26
27#include <linux/delay.h>
28#include <linux/i2c.h>
29
30#include "smiapp-regs.h"
31
32static uint32_t float_to_u32_mul_1000000(struct i2c_client *client,
33 uint32_t phloat)
34{
35 int32_t exp;
36 uint64_t man;
37
38 if (phloat >= 0x80000000) {
39 dev_err(&client->dev, "this is a negative number\n");
40 return 0;
41 }
42
43 if (phloat == 0x7f800000)
44 return ~0; /* Inf. */
45
46 if ((phloat & 0x7f800000) == 0x7f800000) {
47 dev_err(&client->dev, "NaN or other special number\n");
48 return 0;
49 }
50
51 /* Valid cases begin here */
52 if (phloat == 0)
53 return 0; /* Valid zero */
54
55 if (phloat > 0x4f800000)
56 return ~0; /* larger than 4294967295 */
57
58 /*
59 * Unbias exponent (note how phloat is now guaranteed to
60 * have 0 in the high bit)
61 */
62 exp = ((int32_t)phloat >> 23) - 127;
63
64 /* Extract mantissa, add missing '1' bit and it's in MHz */
65 man = ((phloat & 0x7fffff) | 0x800000) * 1000000ULL;
66
67 if (exp < 0)
68 man >>= -exp;
69 else
70 man <<= exp;
71
72 man >>= 23; /* Remove mantissa bias */
73
74 return man & 0xffffffff;
75}
76
77
78/*
79 * Read a 8/16/32-bit i2c register. The value is returned in 'val'.
80 * Returns zero if successful, or non-zero otherwise.
81 */
82int smiapp_read(struct i2c_client *client, u32 reg, u32 *val)
83{
84 struct i2c_msg msg;
85 unsigned char data[4];
86 unsigned int len = (u8)(reg >> 16);
87 u16 offset = reg;
88 int r;
89
90 if (len != SMIA_REG_8BIT && len != SMIA_REG_16BIT
91 && len != SMIA_REG_32BIT)
92 return -EINVAL;
93
94 msg.addr = client->addr;
95 msg.flags = 0;
96 msg.len = 2;
97 msg.buf = data;
98
99 /* high byte goes out first */
100 data[0] = (u8) (offset >> 8);
101 data[1] = (u8) offset;
102 r = i2c_transfer(client->adapter, &msg, 1);
103 if (r != 1) {
104 if (r >= 0)
105 r = -EBUSY;
106 goto err;
107 }
108
109 msg.len = len;
110 msg.flags = I2C_M_RD;
111 r = i2c_transfer(client->adapter, &msg, 1);
112 if (r != 1) {
113 if (r >= 0)
114 r = -EBUSY;
115 goto err;
116 }
117
118 *val = 0;
119 /* high byte comes first */
120 switch (len) {
121 case SMIA_REG_32BIT:
122 *val = (data[0] << 24) + (data[1] << 16) + (data[2] << 8) +
123 data[3];
124 break;
125 case SMIA_REG_16BIT:
126 *val = (data[0] << 8) + data[1];
127 break;
128 case SMIA_REG_8BIT:
129 *val = data[0];
130 break;
131 default:
132 BUG();
133 }
134
135 if (reg & SMIA_REG_FLAG_FLOAT)
136 *val = float_to_u32_mul_1000000(client, *val);
137
138 return 0;
139
140err:
141 dev_err(&client->dev, "read from offset 0x%x error %d\n", offset, r);
142
143 return r;
144}
145
146/*
147 * Write to a 8/16-bit register.
148 * Returns zero if successful, or non-zero otherwise.
149 */
150int smiapp_write(struct i2c_client *client, u32 reg, u32 val)
151{
152 struct i2c_msg msg;
153 unsigned char data[6];
154 unsigned int retries;
155 unsigned int flags = reg >> 24;
156 unsigned int len = (u8)(reg >> 16);
157 u16 offset = reg;
158 int r;
159
160 if ((len != SMIA_REG_8BIT && len != SMIA_REG_16BIT &&
161 len != SMIA_REG_32BIT) || flags)
162 return -EINVAL;
163
164 msg.addr = client->addr;
165 msg.flags = 0; /* Write */
166 msg.len = 2 + len;
167 msg.buf = data;
168
169 /* high byte goes out first */
170 data[0] = (u8) (reg >> 8);
171 data[1] = (u8) (reg & 0xff);
172
173 switch (len) {
174 case SMIA_REG_8BIT:
175 data[2] = val;
176 break;
177 case SMIA_REG_16BIT:
178 data[2] = val >> 8;
179 data[3] = val;
180 break;
181 case SMIA_REG_32BIT:
182 data[2] = val >> 24;
183 data[3] = val >> 16;
184 data[4] = val >> 8;
185 data[5] = val;
186 break;
187 default:
188 BUG();
189 }
190
191 for (retries = 0; retries < 5; retries++) {
192 /*
193 * Due to unknown reason sensor stops responding. This
194 * loop is a temporaty solution until the root cause
195 * is found.
196 */
197 r = i2c_transfer(client->adapter, &msg, 1);
198 if (r == 1) {
199 if (retries)
200 dev_err(&client->dev,
201 "sensor i2c stall encountered. "
202 "retries: %d\n", retries);
203 return 0;
204 }
205
206 usleep_range(2000, 2000);
207 }
208
209 dev_err(&client->dev,
210 "wrote 0x%x to offset 0x%x error %d\n", val, offset, r);
211
212 return r;
213}
diff --git a/drivers/media/video/smiapp/smiapp-regs.h b/drivers/media/video/smiapp/smiapp-regs.h
new file mode 100644
index 000000000000..58e8009d4aa5
--- /dev/null
+++ b/drivers/media/video/smiapp/smiapp-regs.h
@@ -0,0 +1,46 @@
1/*
2 * include/media/smiapp/smiapp-regs.h
3 *
4 * Generic driver for SMIA/SMIA++ compliant camera modules
5 *
6 * Copyright (C) 2011--2012 Nokia Corporation
7 * Contact: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * version 2 as published by the Free Software Foundation.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
21 * 02110-1301 USA
22 *
23 */
24
25#ifndef SMIAPP_REGS_H
26#define SMIAPP_REGS_H
27
28#include <linux/i2c.h>
29#include <linux/types.h>
30
31/* Use upper 8 bits of the type field for flags */
32#define SMIA_REG_FLAG_FLOAT (1 << 24)
33
34#define SMIA_REG_8BIT 1
35#define SMIA_REG_16BIT 2
36#define SMIA_REG_32BIT 4
37struct smia_reg {
38 u16 type;
39 u16 reg; /* 16-bit offset */
40 u32 val; /* 8/16/32-bit value */
41};
42
43int smiapp_read(struct i2c_client *client, u32 reg, u32 *val);
44int smiapp_write(struct i2c_client *client, u32 reg, u32 val);
45
46#endif
diff --git a/drivers/media/video/smiapp/smiapp.h b/drivers/media/video/smiapp/smiapp.h
new file mode 100644
index 000000000000..805d8c8a3c18
--- /dev/null
+++ b/drivers/media/video/smiapp/smiapp.h
@@ -0,0 +1,251 @@
1/*
2 * drivers/media/video/smiapp/smiapp.h
3 *
4 * Generic driver for SMIA/SMIA++ compliant camera modules
5 *
6 * Copyright (C) 2010--2012 Nokia Corporation
7 * Contact: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * version 2 as published by the Free Software Foundation.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
21 * 02110-1301 USA
22 *
23 */
24
25#ifndef __SMIAPP_PRIV_H_
26#define __SMIAPP_PRIV_H_
27
28#include <linux/mutex.h>
29#include <media/v4l2-ctrls.h>
30#include <media/v4l2-subdev.h>
31#include <media/smiapp.h>
32
33#include "../smiapp-pll.h"
34#include "smiapp-reg.h"
35#include "smiapp-regs.h"
36#include "smiapp-quirk.h"
37
38/*
39 * Standard SMIA++ constants
40 */
41#define SMIA_VERSION_1 10
42#define SMIAPP_VERSION_0_8 8 /* Draft 0.8 */
43#define SMIAPP_VERSION_0_9 9 /* Draft 0.9 */
44#define SMIAPP_VERSION_1 10
45
46#define SMIAPP_PROFILE_0 0
47#define SMIAPP_PROFILE_1 1
48#define SMIAPP_PROFILE_2 2
49
50#define SMIAPP_NVM_PAGE_SIZE 64 /* bytes */
51
52#define SMIAPP_RESET_DELAY_CLOCKS 2400
53#define SMIAPP_RESET_DELAY(clk) \
54 (1000 + (SMIAPP_RESET_DELAY_CLOCKS * 1000 \
55 + (clk) / 1000 - 1) / ((clk) / 1000))
56
57#include "smiapp-limits.h"
58
59struct smiapp_quirk;
60
61#define SMIAPP_MODULE_IDENT_FLAG_REV_LE (1 << 0)
62
63struct smiapp_module_ident {
64 u8 manufacturer_id;
65 u16 model_id;
66 u8 revision_number_major;
67
68 u8 flags;
69
70 char *name;
71 const struct smiapp_quirk *quirk;
72};
73
74struct smiapp_module_info {
75 u32 manufacturer_id;
76 u32 model_id;
77 u32 revision_number_major;
78 u32 revision_number_minor;
79
80 u32 module_year;
81 u32 module_month;
82 u32 module_day;
83
84 u32 sensor_manufacturer_id;
85 u32 sensor_model_id;
86 u32 sensor_revision_number;
87 u32 sensor_firmware_version;
88
89 u32 smia_version;
90 u32 smiapp_version;
91
92 u32 smiapp_profile;
93
94 char *name;
95 const struct smiapp_quirk *quirk;
96};
97
98#define SMIAPP_IDENT_FQ(manufacturer, model, rev, fl, _name, _quirk) \
99 { .manufacturer_id = manufacturer, \
100 .model_id = model, \
101 .revision_number_major = rev, \
102 .flags = fl, \
103 .name = _name, \
104 .quirk = _quirk, }
105
106#define SMIAPP_IDENT_LQ(manufacturer, model, rev, _name, _quirk) \
107 { .manufacturer_id = manufacturer, \
108 .model_id = model, \
109 .revision_number_major = rev, \
110 .flags = SMIAPP_MODULE_IDENT_FLAG_REV_LE, \
111 .name = _name, \
112 .quirk = _quirk, }
113
114#define SMIAPP_IDENT_L(manufacturer, model, rev, _name) \
115 { .manufacturer_id = manufacturer, \
116 .model_id = model, \
117 .revision_number_major = rev, \
118 .flags = SMIAPP_MODULE_IDENT_FLAG_REV_LE, \
119 .name = _name, }
120
121#define SMIAPP_IDENT_Q(manufacturer, model, rev, _name, _quirk) \
122 { .manufacturer_id = manufacturer, \
123 .model_id = model, \
124 .revision_number_major = rev, \
125 .flags = 0, \
126 .name = _name, \
127 .quirk = _quirk, }
128
129#define SMIAPP_IDENT(manufacturer, model, rev, _name) \
130 { .manufacturer_id = manufacturer, \
131 .model_id = model, \
132 .revision_number_major = rev, \
133 .flags = 0, \
134 .name = _name, }
135
136struct smiapp_reg_limits {
137 u32 addr;
138 char *what;
139};
140
141extern struct smiapp_reg_limits smiapp_reg_limits[];
142
143struct smiapp_csi_data_format {
144 u32 code;
145 u8 width;
146 u8 compressed;
147 u8 pixel_order;
148};
149
150#define SMIAPP_SUBDEVS 3
151
152#define SMIAPP_PA_PAD_SRC 0
153#define SMIAPP_PAD_SINK 0
154#define SMIAPP_PAD_SRC 1
155#define SMIAPP_PADS 2
156
157struct smiapp_binning_subtype {
158 u8 horizontal:4;
159 u8 vertical:4;
160} __packed;
161
162struct smiapp_subdev {
163 struct v4l2_subdev sd;
164 struct media_pad pads[2];
165 struct v4l2_rect sink_fmt;
166 struct v4l2_rect crop[2];
167 struct v4l2_rect compose; /* compose on sink */
168 unsigned short sink_pad;
169 unsigned short source_pad;
170 int npads;
171 struct smiapp_sensor *sensor;
172 struct v4l2_ctrl_handler ctrl_handler;
173};
174
175/*
176 * struct smiapp_sensor - Main device structure
177 */
178struct smiapp_sensor {
179 /*
180 * "mutex" is used to serialise access to all fields here
181 * except v4l2_ctrls at the end of the struct. "mutex" is also
182 * used to serialise access to file handle specific
183 * information. The exception to this rule is the power_mutex
184 * below.
185 */
186 struct mutex mutex;
187 /*
188 * power_mutex is used to serialise power management related
189 * activities. Acquiring "mutex" at that time isn't necessary
190 * since there are no other users anyway.
191 */
192 struct mutex power_mutex;
193 struct smiapp_subdev ssds[SMIAPP_SUBDEVS];
194 u32 ssds_used;
195 struct smiapp_subdev *src;
196 struct smiapp_subdev *binner;
197 struct smiapp_subdev *scaler;
198 struct smiapp_subdev *pixel_array;
199 struct smiapp_platform_data *platform_data;
200 struct regulator *vana;
201 u32 limits[SMIAPP_LIMIT_LAST];
202 u8 nbinning_subtypes;
203 struct smiapp_binning_subtype binning_subtypes[SMIAPP_BINNING_SUBTYPES];
204 u32 mbus_frame_fmts;
205 const struct smiapp_csi_data_format *csi_format;
206 const struct smiapp_csi_data_format *internal_csi_format;
207 u32 default_mbus_frame_fmts;
208 int default_pixel_order;
209
210 u8 binning_horizontal;
211 u8 binning_vertical;
212
213 u8 scale_m;
214 u8 scaling_mode;
215
216 u8 hvflip_inv_mask; /* H/VFLIP inversion due to sensor orientation */
217 u8 flash_capability;
218 u8 frame_skip;
219
220 int power_count;
221
222 bool streaming;
223 bool dev_init_done;
224
225 u8 *nvm; /* nvm memory buffer */
226 unsigned int nvm_size; /* bytes */
227
228 struct smiapp_module_info minfo;
229
230 struct smiapp_pll pll;
231
232 /* Pixel array controls */
233 struct v4l2_ctrl *analog_gain;
234 struct v4l2_ctrl *exposure;
235 struct v4l2_ctrl *hflip;
236 struct v4l2_ctrl *vflip;
237 struct v4l2_ctrl *vblank;
238 struct v4l2_ctrl *hblank;
239 struct v4l2_ctrl *pixel_rate_parray;
240 /* src controls */
241 struct v4l2_ctrl *link_freq;
242 struct v4l2_ctrl *pixel_rate_csi;
243};
244
245#define to_smiapp_subdev(_sd) \
246 container_of(_sd, struct smiapp_subdev, sd)
247
248#define to_smiapp_sensor(_sd) \
249 (to_smiapp_subdev(_sd)->sensor)
250
251#endif /* __SMIAPP_PRIV_H_ */