1cb33db2bSLaurent Pinchart // SPDX-License-Identifier: GPL-2.0
2cb33db2bSLaurent Pinchart /*
3cb33db2bSLaurent Pinchart * Driver for IMX296 CMOS Image Sensor from Sony
4cb33db2bSLaurent Pinchart *
5cb33db2bSLaurent Pinchart * Copyright 2019 Laurent Pinchart <laurent.pinchart@ideasonboard.com>
6cb33db2bSLaurent Pinchart */
7cb33db2bSLaurent Pinchart
8cb33db2bSLaurent Pinchart #include <linux/clk.h>
9cb33db2bSLaurent Pinchart #include <linux/gpio/consumer.h>
10cb33db2bSLaurent Pinchart #include <linux/i2c.h>
11cb33db2bSLaurent Pinchart #include <linux/module.h>
127c7e33b7SRob Herring #include <linux/of.h>
13cb33db2bSLaurent Pinchart #include <linux/pm_runtime.h>
14cb33db2bSLaurent Pinchart #include <linux/regmap.h>
15cb33db2bSLaurent Pinchart #include <linux/regulator/consumer.h>
16cb33db2bSLaurent Pinchart #include <linux/slab.h>
17cb33db2bSLaurent Pinchart #include <linux/videodev2.h>
18cb33db2bSLaurent Pinchart
19cb33db2bSLaurent Pinchart #include <media/v4l2-ctrls.h>
20cb33db2bSLaurent Pinchart #include <media/v4l2-fwnode.h>
21cb33db2bSLaurent Pinchart #include <media/v4l2-subdev.h>
22cb33db2bSLaurent Pinchart
23cb33db2bSLaurent Pinchart #define IMX296_PIXEL_ARRAY_WIDTH 1456
24cb33db2bSLaurent Pinchart #define IMX296_PIXEL_ARRAY_HEIGHT 1088
25cb33db2bSLaurent Pinchart
26cb33db2bSLaurent Pinchart #define IMX296_REG_8BIT(n) ((1 << 16) | (n))
27cb33db2bSLaurent Pinchart #define IMX296_REG_16BIT(n) ((2 << 16) | (n))
28cb33db2bSLaurent Pinchart #define IMX296_REG_24BIT(n) ((3 << 16) | (n))
29cb33db2bSLaurent Pinchart #define IMX296_REG_SIZE_SHIFT 16
30cb33db2bSLaurent Pinchart #define IMX296_REG_ADDR_MASK 0xffff
31cb33db2bSLaurent Pinchart
32cb33db2bSLaurent Pinchart #define IMX296_CTRL00 IMX296_REG_8BIT(0x3000)
33cb33db2bSLaurent Pinchart #define IMX296_CTRL00_STANDBY BIT(0)
34cb33db2bSLaurent Pinchart #define IMX296_CTRL08 IMX296_REG_8BIT(0x3008)
35cb33db2bSLaurent Pinchart #define IMX296_CTRL08_REGHOLD BIT(0)
36cb33db2bSLaurent Pinchart #define IMX296_CTRL0A IMX296_REG_8BIT(0x300a)
37cb33db2bSLaurent Pinchart #define IMX296_CTRL0A_XMSTA BIT(0)
38cb33db2bSLaurent Pinchart #define IMX296_CTRL0B IMX296_REG_8BIT(0x300b)
39cb33db2bSLaurent Pinchart #define IMX296_CTRL0B_TRIGEN BIT(0)
40cb33db2bSLaurent Pinchart #define IMX296_CTRL0D IMX296_REG_8BIT(0x300d)
41cb33db2bSLaurent Pinchart #define IMX296_CTRL0D_WINMODE_ALL (0 << 0)
42cb33db2bSLaurent Pinchart #define IMX296_CTRL0D_WINMODE_FD_BINNING (2 << 0)
43cb33db2bSLaurent Pinchart #define IMX296_CTRL0D_HADD_ON_BINNING BIT(5)
44cb33db2bSLaurent Pinchart #define IMX296_CTRL0D_SAT_CNT BIT(6)
45cb33db2bSLaurent Pinchart #define IMX296_CTRL0E IMX296_REG_8BIT(0x300e)
46cb33db2bSLaurent Pinchart #define IMX296_CTRL0E_VREVERSE BIT(0)
47cb33db2bSLaurent Pinchart #define IMX296_CTRL0E_HREVERSE BIT(1)
48cb33db2bSLaurent Pinchart #define IMX296_VMAX IMX296_REG_24BIT(0x3010)
49cb33db2bSLaurent Pinchart #define IMX296_HMAX IMX296_REG_16BIT(0x3014)
50cb33db2bSLaurent Pinchart #define IMX296_TMDCTRL IMX296_REG_8BIT(0x301d)
51cb33db2bSLaurent Pinchart #define IMX296_TMDCTRL_LATCH BIT(0)
52cb33db2bSLaurent Pinchart #define IMX296_TMDOUT IMX296_REG_16BIT(0x301e)
53cb33db2bSLaurent Pinchart #define IMX296_TMDOUT_MASK 0x3ff
54cb33db2bSLaurent Pinchart #define IMX296_WDSEL IMX296_REG_8BIT(0x3021)
55cb33db2bSLaurent Pinchart #define IMX296_WDSEL_NORMAL (0 << 0)
56cb33db2bSLaurent Pinchart #define IMX296_WDSEL_MULTI_2 (1 << 0)
57cb33db2bSLaurent Pinchart #define IMX296_WDSEL_MULTI_4 (3 << 0)
58cb33db2bSLaurent Pinchart #define IMX296_BLKLEVELAUTO IMX296_REG_8BIT(0x3022)
59cb33db2bSLaurent Pinchart #define IMX296_BLKLEVELAUTO_ON 0x01
60cb33db2bSLaurent Pinchart #define IMX296_BLKLEVELAUTO_OFF 0xf0
61cb33db2bSLaurent Pinchart #define IMX296_SST IMX296_REG_8BIT(0x3024)
62cb33db2bSLaurent Pinchart #define IMX296_SST_EN BIT(0)
63cb33db2bSLaurent Pinchart #define IMX296_CTRLTOUT IMX296_REG_8BIT(0x3026)
64cb33db2bSLaurent Pinchart #define IMX296_CTRLTOUT_TOUT1SEL_LOW (0 << 0)
65cb33db2bSLaurent Pinchart #define IMX296_CTRLTOUT_TOUT1SEL_PULSE (3 << 0)
66cb33db2bSLaurent Pinchart #define IMX296_CTRLTOUT_TOUT2SEL_LOW (0 << 2)
67cb33db2bSLaurent Pinchart #define IMX296_CTRLTOUT_TOUT2SEL_PULSE (3 << 2)
68cb33db2bSLaurent Pinchart #define IMX296_CTRLTRIG IMX296_REG_8BIT(0x3029)
69cb33db2bSLaurent Pinchart #define IMX296_CTRLTRIG_TOUT1_SEL_LOW (0 << 0)
70cb33db2bSLaurent Pinchart #define IMX296_CTRLTRIG_TOUT1_SEL_PULSE1 (1 << 0)
71cb33db2bSLaurent Pinchart #define IMX296_CTRLTRIG_TOUT2_SEL_LOW (0 << 4)
72cb33db2bSLaurent Pinchart #define IMX296_CTRLTRIG_TOUT2_SEL_PULSE2 (2 << 4)
73cb33db2bSLaurent Pinchart #define IMX296_SYNCSEL IMX296_REG_8BIT(0x3036)
74cb33db2bSLaurent Pinchart #define IMX296_SYNCSEL_NORMAL 0xc0
75cb33db2bSLaurent Pinchart #define IMX296_SYNCSEL_HIZ 0xf0
76cb33db2bSLaurent Pinchart #define IMX296_PULSE1 IMX296_REG_8BIT(0x306d)
77cb33db2bSLaurent Pinchart #define IMX296_PULSE1_EN_NOR BIT(0)
78cb33db2bSLaurent Pinchart #define IMX296_PULSE1_EN_TRIG BIT(1)
79cb33db2bSLaurent Pinchart #define IMX296_PULSE1_POL_HIGH (0 << 2)
80cb33db2bSLaurent Pinchart #define IMX296_PULSE1_POL_LOW (1 << 2)
81cb33db2bSLaurent Pinchart #define IMX296_PULSE1_UP IMX296_REG_24BIT(0x3070)
82cb33db2bSLaurent Pinchart #define IMX296_PULSE1_DN IMX296_REG_24BIT(0x3074)
83cb33db2bSLaurent Pinchart #define IMX296_PULSE2 IMX296_REG_8BIT(0x3079)
84cb33db2bSLaurent Pinchart #define IMX296_PULSE2_EN_NOR BIT(0)
85cb33db2bSLaurent Pinchart #define IMX296_PULSE2_EN_TRIG BIT(1)
86cb33db2bSLaurent Pinchart #define IMX296_PULSE2_POL_HIGH (0 << 2)
87cb33db2bSLaurent Pinchart #define IMX296_PULSE2_POL_LOW (1 << 2)
88cb33db2bSLaurent Pinchart #define IMX296_PULSE2_UP IMX296_REG_24BIT(0x307c)
89cb33db2bSLaurent Pinchart #define IMX296_PULSE2_DN IMX296_REG_24BIT(0x3080)
90cb33db2bSLaurent Pinchart #define IMX296_INCKSEL(n) IMX296_REG_8BIT(0x3089 + (n))
91cb33db2bSLaurent Pinchart #define IMX296_SHS1 IMX296_REG_24BIT(0x308d)
92cb33db2bSLaurent Pinchart #define IMX296_SHS2 IMX296_REG_24BIT(0x3090)
93cb33db2bSLaurent Pinchart #define IMX296_SHS3 IMX296_REG_24BIT(0x3094)
94cb33db2bSLaurent Pinchart #define IMX296_SHS4 IMX296_REG_24BIT(0x3098)
95cb33db2bSLaurent Pinchart #define IMX296_VBLANKLP IMX296_REG_8BIT(0x309c)
96cb33db2bSLaurent Pinchart #define IMX296_VBLANKLP_NORMAL 0x04
97cb33db2bSLaurent Pinchart #define IMX296_VBLANKLP_LOW_POWER 0x2c
98cb33db2bSLaurent Pinchart #define IMX296_EXP_CNT IMX296_REG_8BIT(0x30a3)
99cb33db2bSLaurent Pinchart #define IMX296_EXP_CNT_RESET BIT(0)
100cb33db2bSLaurent Pinchart #define IMX296_EXP_MAX IMX296_REG_16BIT(0x30a6)
101cb33db2bSLaurent Pinchart #define IMX296_VINT IMX296_REG_8BIT(0x30aa)
102cb33db2bSLaurent Pinchart #define IMX296_VINT_EN BIT(0)
103cb33db2bSLaurent Pinchart #define IMX296_LOWLAGTRG IMX296_REG_8BIT(0x30ae)
104cb33db2bSLaurent Pinchart #define IMX296_LOWLAGTRG_FAST BIT(0)
105cb33db2bSLaurent Pinchart #define IMX296_I2CCTRL IMX296_REG_8BIT(0x30ef)
106cb33db2bSLaurent Pinchart #define IMX296_I2CCTRL_I2CACKEN BIT(0)
107cb33db2bSLaurent Pinchart
108cb33db2bSLaurent Pinchart #define IMX296_SENSOR_INFO IMX296_REG_16BIT(0x3148)
109cb33db2bSLaurent Pinchart #define IMX296_SENSOR_INFO_MONO BIT(15)
110cb33db2bSLaurent Pinchart #define IMX296_SENSOR_INFO_IMX296LQ 0x4a00
111cb33db2bSLaurent Pinchart #define IMX296_SENSOR_INFO_IMX296LL 0xca00
112cb33db2bSLaurent Pinchart #define IMX296_S_SHSA IMX296_REG_16BIT(0x31ca)
113cb33db2bSLaurent Pinchart #define IMX296_S_SHSB IMX296_REG_16BIT(0x31d2)
114cb33db2bSLaurent Pinchart /*
115cb33db2bSLaurent Pinchart * Registers 0x31c8 to 0x31cd, 0x31d0 to 0x31d5, 0x31e2, 0x31e3, 0x31ea and
116cb33db2bSLaurent Pinchart * 0x31eb are related to exposure mode but otherwise not documented.
117cb33db2bSLaurent Pinchart */
118cb33db2bSLaurent Pinchart
119cb33db2bSLaurent Pinchart #define IMX296_GAINCTRL IMX296_REG_8BIT(0x3200)
120cb33db2bSLaurent Pinchart #define IMX296_GAINCTRL_WD_GAIN_MODE_NORMAL 0x01
121cb33db2bSLaurent Pinchart #define IMX296_GAINCTRL_WD_GAIN_MODE_MULTI 0x41
122cb33db2bSLaurent Pinchart #define IMX296_GAIN IMX296_REG_16BIT(0x3204)
123cb33db2bSLaurent Pinchart #define IMX296_GAIN_MIN 0
124cb33db2bSLaurent Pinchart #define IMX296_GAIN_MAX 480
125cb33db2bSLaurent Pinchart #define IMX296_GAIN1 IMX296_REG_16BIT(0x3208)
126cb33db2bSLaurent Pinchart #define IMX296_GAIN2 IMX296_REG_16BIT(0x320c)
127cb33db2bSLaurent Pinchart #define IMX296_GAIN3 IMX296_REG_16BIT(0x3210)
128cb33db2bSLaurent Pinchart #define IMX296_GAINDLY IMX296_REG_8BIT(0x3212)
129cb33db2bSLaurent Pinchart #define IMX296_GAINDLY_NONE 0x08
130cb33db2bSLaurent Pinchart #define IMX296_GAINDLY_1FRAME 0x09
131cb33db2bSLaurent Pinchart #define IMX296_PGCTRL IMX296_REG_8BIT(0x3238)
132cb33db2bSLaurent Pinchart #define IMX296_PGCTRL_REGEN BIT(0)
133cb33db2bSLaurent Pinchart #define IMX296_PGCTRL_THRU BIT(1)
134cb33db2bSLaurent Pinchart #define IMX296_PGCTRL_CLKEN BIT(2)
135cb33db2bSLaurent Pinchart #define IMX296_PGCTRL_MODE(n) ((n) << 3)
136cb33db2bSLaurent Pinchart #define IMX296_PGHPOS IMX296_REG_16BIT(0x3239)
137cb33db2bSLaurent Pinchart #define IMX296_PGVPOS IMX296_REG_16BIT(0x323c)
138cb33db2bSLaurent Pinchart #define IMX296_PGHPSTEP IMX296_REG_8BIT(0x323e)
139cb33db2bSLaurent Pinchart #define IMX296_PGVPSTEP IMX296_REG_8BIT(0x323f)
140cb33db2bSLaurent Pinchart #define IMX296_PGHPNUM IMX296_REG_8BIT(0x3240)
141cb33db2bSLaurent Pinchart #define IMX296_PGVPNUM IMX296_REG_8BIT(0x3241)
142cb33db2bSLaurent Pinchart #define IMX296_PGDATA1 IMX296_REG_16BIT(0x3244)
143cb33db2bSLaurent Pinchart #define IMX296_PGDATA2 IMX296_REG_16BIT(0x3246)
144cb33db2bSLaurent Pinchart #define IMX296_PGHGSTEP IMX296_REG_8BIT(0x3249)
145cb33db2bSLaurent Pinchart #define IMX296_BLKLEVEL IMX296_REG_16BIT(0x3254)
146cb33db2bSLaurent Pinchart
147cb33db2bSLaurent Pinchart #define IMX296_FID0_ROI IMX296_REG_8BIT(0x3300)
148cb33db2bSLaurent Pinchart #define IMX296_FID0_ROIH1ON BIT(0)
149cb33db2bSLaurent Pinchart #define IMX296_FID0_ROIV1ON BIT(1)
150cb33db2bSLaurent Pinchart #define IMX296_FID0_ROIPH1 IMX296_REG_16BIT(0x3310)
151cb33db2bSLaurent Pinchart #define IMX296_FID0_ROIPV1 IMX296_REG_16BIT(0x3312)
152cb33db2bSLaurent Pinchart #define IMX296_FID0_ROIWH1 IMX296_REG_16BIT(0x3314)
153cb33db2bSLaurent Pinchart #define IMX296_FID0_ROIWH1_MIN 80
154cb33db2bSLaurent Pinchart #define IMX296_FID0_ROIWV1 IMX296_REG_16BIT(0x3316)
155cb33db2bSLaurent Pinchart #define IMX296_FID0_ROIWV1_MIN 4
156cb33db2bSLaurent Pinchart
157cb33db2bSLaurent Pinchart #define IMX296_CM_HSST_STARTTMG IMX296_REG_16BIT(0x4018)
158cb33db2bSLaurent Pinchart #define IMX296_CM_HSST_ENDTMG IMX296_REG_16BIT(0x401a)
159cb33db2bSLaurent Pinchart #define IMX296_DA_HSST_STARTTMG IMX296_REG_16BIT(0x404d)
160cb33db2bSLaurent Pinchart #define IMX296_DA_HSST_ENDTMG IMX296_REG_16BIT(0x4050)
161cb33db2bSLaurent Pinchart #define IMX296_LM_HSST_STARTTMG IMX296_REG_16BIT(0x4094)
162cb33db2bSLaurent Pinchart #define IMX296_LM_HSST_ENDTMG IMX296_REG_16BIT(0x4096)
163cb33db2bSLaurent Pinchart #define IMX296_SST_SIEASTA1_SET IMX296_REG_8BIT(0x40c9)
164cb33db2bSLaurent Pinchart #define IMX296_SST_SIEASTA1PRE_1U IMX296_REG_16BIT(0x40cc)
165cb33db2bSLaurent Pinchart #define IMX296_SST_SIEASTA1PRE_1D IMX296_REG_16BIT(0x40ce)
166cb33db2bSLaurent Pinchart #define IMX296_SST_SIEASTA1PRE_2U IMX296_REG_16BIT(0x40d0)
167cb33db2bSLaurent Pinchart #define IMX296_SST_SIEASTA1PRE_2D IMX296_REG_16BIT(0x40d2)
168cb33db2bSLaurent Pinchart #define IMX296_HSST IMX296_REG_8BIT(0x40dc)
169cb33db2bSLaurent Pinchart #define IMX296_HSST_EN BIT(2)
170cb33db2bSLaurent Pinchart
171cb33db2bSLaurent Pinchart #define IMX296_CKREQSEL IMX296_REG_8BIT(0x4101)
172cb33db2bSLaurent Pinchart #define IMX296_CKREQSEL_HS BIT(2)
173cb33db2bSLaurent Pinchart #define IMX296_GTTABLENUM IMX296_REG_8BIT(0x4114)
174cb33db2bSLaurent Pinchart #define IMX296_CTRL418C IMX296_REG_8BIT(0x418c)
175cb33db2bSLaurent Pinchart
176cb33db2bSLaurent Pinchart struct imx296_clk_params {
177cb33db2bSLaurent Pinchart unsigned int freq;
178cb33db2bSLaurent Pinchart u8 incksel[4];
179cb33db2bSLaurent Pinchart u8 ctrl418c;
180cb33db2bSLaurent Pinchart };
181cb33db2bSLaurent Pinchart
182cb33db2bSLaurent Pinchart static const struct imx296_clk_params imx296_clk_params[] = {
183cb33db2bSLaurent Pinchart { 37125000, { 0x80, 0x0b, 0x80, 0x08 }, 116 },
184cb33db2bSLaurent Pinchart { 54000000, { 0xb0, 0x0f, 0xb0, 0x0c }, 168 },
185cb33db2bSLaurent Pinchart { 74250000, { 0x80, 0x0f, 0x80, 0x0c }, 232 },
186cb33db2bSLaurent Pinchart };
187cb33db2bSLaurent Pinchart
188cb33db2bSLaurent Pinchart static const char * const imx296_supply_names[] = {
189cb33db2bSLaurent Pinchart "dvdd",
190cb33db2bSLaurent Pinchart "ovdd",
191cb33db2bSLaurent Pinchart "avdd",
192cb33db2bSLaurent Pinchart };
193cb33db2bSLaurent Pinchart
194cb33db2bSLaurent Pinchart struct imx296 {
195cb33db2bSLaurent Pinchart struct device *dev;
196cb33db2bSLaurent Pinchart struct clk *clk;
197cb33db2bSLaurent Pinchart struct regulator_bulk_data supplies[ARRAY_SIZE(imx296_supply_names)];
198cb33db2bSLaurent Pinchart struct gpio_desc *reset;
199cb33db2bSLaurent Pinchart struct regmap *regmap;
200cb33db2bSLaurent Pinchart
201cb33db2bSLaurent Pinchart const struct imx296_clk_params *clk_params;
202cb33db2bSLaurent Pinchart bool mono;
203cb33db2bSLaurent Pinchart
204cb33db2bSLaurent Pinchart bool streaming;
205cb33db2bSLaurent Pinchart
206cb33db2bSLaurent Pinchart struct v4l2_subdev subdev;
207cb33db2bSLaurent Pinchart struct media_pad pad;
208cb33db2bSLaurent Pinchart
209cb33db2bSLaurent Pinchart struct v4l2_ctrl_handler ctrls;
210cb33db2bSLaurent Pinchart struct v4l2_ctrl *hblank;
211cb33db2bSLaurent Pinchart struct v4l2_ctrl *vblank;
212cb33db2bSLaurent Pinchart };
213cb33db2bSLaurent Pinchart
to_imx296(struct v4l2_subdev * sd)214cb33db2bSLaurent Pinchart static inline struct imx296 *to_imx296(struct v4l2_subdev *sd)
215cb33db2bSLaurent Pinchart {
216cb33db2bSLaurent Pinchart return container_of(sd, struct imx296, subdev);
217cb33db2bSLaurent Pinchart }
218cb33db2bSLaurent Pinchart
imx296_read(struct imx296 * sensor,u32 addr)219cb33db2bSLaurent Pinchart static int imx296_read(struct imx296 *sensor, u32 addr)
220cb33db2bSLaurent Pinchart {
221cb33db2bSLaurent Pinchart u8 data[3] = { 0, 0, 0 };
222cb33db2bSLaurent Pinchart int ret;
223cb33db2bSLaurent Pinchart
224cb33db2bSLaurent Pinchart ret = regmap_raw_read(sensor->regmap, addr & IMX296_REG_ADDR_MASK, data,
225cb33db2bSLaurent Pinchart (addr >> IMX296_REG_SIZE_SHIFT) & 3);
226cb33db2bSLaurent Pinchart if (ret < 0)
227cb33db2bSLaurent Pinchart return ret;
228cb33db2bSLaurent Pinchart
229cb33db2bSLaurent Pinchart return (data[2] << 16) | (data[1] << 8) | data[0];
230cb33db2bSLaurent Pinchart }
231cb33db2bSLaurent Pinchart
imx296_write(struct imx296 * sensor,u32 addr,u32 value,int * err)232cb33db2bSLaurent Pinchart static int imx296_write(struct imx296 *sensor, u32 addr, u32 value, int *err)
233cb33db2bSLaurent Pinchart {
234cb33db2bSLaurent Pinchart u8 data[3] = { value & 0xff, (value >> 8) & 0xff, value >> 16 };
235cb33db2bSLaurent Pinchart int ret;
236cb33db2bSLaurent Pinchart
237cb33db2bSLaurent Pinchart if (err && *err)
238cb33db2bSLaurent Pinchart return *err;
239cb33db2bSLaurent Pinchart
240cb33db2bSLaurent Pinchart ret = regmap_raw_write(sensor->regmap, addr & IMX296_REG_ADDR_MASK,
241cb33db2bSLaurent Pinchart data, (addr >> IMX296_REG_SIZE_SHIFT) & 3);
242cb33db2bSLaurent Pinchart if (ret < 0) {
243cb33db2bSLaurent Pinchart dev_err(sensor->dev, "%u-bit write to 0x%04x failed: %d\n",
244cb33db2bSLaurent Pinchart ((addr >> IMX296_REG_SIZE_SHIFT) & 3) * 8,
245cb33db2bSLaurent Pinchart addr & IMX296_REG_ADDR_MASK, ret);
246cb33db2bSLaurent Pinchart if (err)
247cb33db2bSLaurent Pinchart *err = ret;
248cb33db2bSLaurent Pinchart }
249cb33db2bSLaurent Pinchart
250cb33db2bSLaurent Pinchart return ret;
251cb33db2bSLaurent Pinchart }
252cb33db2bSLaurent Pinchart
imx296_power_on(struct imx296 * sensor)253cb33db2bSLaurent Pinchart static int imx296_power_on(struct imx296 *sensor)
254cb33db2bSLaurent Pinchart {
255cb33db2bSLaurent Pinchart int ret;
256cb33db2bSLaurent Pinchart
257cb33db2bSLaurent Pinchart ret = regulator_bulk_enable(ARRAY_SIZE(sensor->supplies),
258cb33db2bSLaurent Pinchart sensor->supplies);
259cb33db2bSLaurent Pinchart if (ret < 0)
260cb33db2bSLaurent Pinchart return ret;
261cb33db2bSLaurent Pinchart
262cb33db2bSLaurent Pinchart udelay(1);
263cb33db2bSLaurent Pinchart
264cb33db2bSLaurent Pinchart ret = gpiod_direction_output(sensor->reset, 0);
265cb33db2bSLaurent Pinchart if (ret < 0)
266cb33db2bSLaurent Pinchart goto err_supply;
267cb33db2bSLaurent Pinchart
268cb33db2bSLaurent Pinchart udelay(1);
269cb33db2bSLaurent Pinchart
270cb33db2bSLaurent Pinchart ret = clk_prepare_enable(sensor->clk);
271cb33db2bSLaurent Pinchart if (ret < 0)
272cb33db2bSLaurent Pinchart goto err_reset;
273cb33db2bSLaurent Pinchart
274cb33db2bSLaurent Pinchart /*
275cb33db2bSLaurent Pinchart * The documentation doesn't explicitly say how much time is required
276cb33db2bSLaurent Pinchart * after providing a clock and before starting I2C communication. It
277cb33db2bSLaurent Pinchart * mentions a delay of 20µs in 4-wire mode, but tests showed that a
278cb33db2bSLaurent Pinchart * delay of 100µs resulted in I2C communication failures, while 500µs
279cb33db2bSLaurent Pinchart * seems to be enough. Be conservative.
280cb33db2bSLaurent Pinchart */
281cb33db2bSLaurent Pinchart usleep_range(1000, 2000);
282cb33db2bSLaurent Pinchart
283cb33db2bSLaurent Pinchart return 0;
284cb33db2bSLaurent Pinchart
285cb33db2bSLaurent Pinchart err_reset:
286cb33db2bSLaurent Pinchart gpiod_direction_output(sensor->reset, 1);
287cb33db2bSLaurent Pinchart err_supply:
288cb33db2bSLaurent Pinchart regulator_bulk_disable(ARRAY_SIZE(sensor->supplies), sensor->supplies);
289cb33db2bSLaurent Pinchart return ret;
290cb33db2bSLaurent Pinchart }
291cb33db2bSLaurent Pinchart
imx296_power_off(struct imx296 * sensor)292cb33db2bSLaurent Pinchart static void imx296_power_off(struct imx296 *sensor)
293cb33db2bSLaurent Pinchart {
294cb33db2bSLaurent Pinchart clk_disable_unprepare(sensor->clk);
295cb33db2bSLaurent Pinchart gpiod_direction_output(sensor->reset, 1);
296cb33db2bSLaurent Pinchart regulator_bulk_disable(ARRAY_SIZE(sensor->supplies), sensor->supplies);
297cb33db2bSLaurent Pinchart }
298cb33db2bSLaurent Pinchart
299cb33db2bSLaurent Pinchart /* -----------------------------------------------------------------------------
300cb33db2bSLaurent Pinchart * Controls
301cb33db2bSLaurent Pinchart */
302cb33db2bSLaurent Pinchart
303cb33db2bSLaurent Pinchart static const char * const imx296_test_pattern_menu[] = {
304cb33db2bSLaurent Pinchart "Disabled",
305cb33db2bSLaurent Pinchart "Multiple Pixels",
306cb33db2bSLaurent Pinchart "Sequence 1",
307cb33db2bSLaurent Pinchart "Sequence 2",
308cb33db2bSLaurent Pinchart "Gradient",
309cb33db2bSLaurent Pinchart "Row",
310cb33db2bSLaurent Pinchart "Column",
311cb33db2bSLaurent Pinchart "Cross",
312cb33db2bSLaurent Pinchart "Stripe",
313cb33db2bSLaurent Pinchart "Checks",
314cb33db2bSLaurent Pinchart };
315cb33db2bSLaurent Pinchart
imx296_s_ctrl(struct v4l2_ctrl * ctrl)316cb33db2bSLaurent Pinchart static int imx296_s_ctrl(struct v4l2_ctrl *ctrl)
317cb33db2bSLaurent Pinchart {
318cb33db2bSLaurent Pinchart struct imx296 *sensor = container_of(ctrl->handler, struct imx296, ctrls);
319cb33db2bSLaurent Pinchart const struct v4l2_mbus_framefmt *format;
320cb33db2bSLaurent Pinchart struct v4l2_subdev_state *state;
321cb33db2bSLaurent Pinchart unsigned int vmax;
322cb33db2bSLaurent Pinchart int ret = 0;
323cb33db2bSLaurent Pinchart
324cb33db2bSLaurent Pinchart if (!sensor->streaming)
325cb33db2bSLaurent Pinchart return 0;
326cb33db2bSLaurent Pinchart
327cb33db2bSLaurent Pinchart state = v4l2_subdev_get_locked_active_state(&sensor->subdev);
328cb33db2bSLaurent Pinchart format = v4l2_subdev_get_pad_format(&sensor->subdev, state, 0);
329cb33db2bSLaurent Pinchart
330cb33db2bSLaurent Pinchart switch (ctrl->id) {
331cb33db2bSLaurent Pinchart case V4L2_CID_EXPOSURE:
332cb33db2bSLaurent Pinchart /* Clamp the exposure value to VMAX. */
333cb33db2bSLaurent Pinchart vmax = format->height + sensor->vblank->cur.val;
334cb33db2bSLaurent Pinchart ctrl->val = min_t(int, ctrl->val, vmax);
335cb33db2bSLaurent Pinchart imx296_write(sensor, IMX296_SHS1, vmax - ctrl->val, &ret);
336cb33db2bSLaurent Pinchart break;
337cb33db2bSLaurent Pinchart
338cb33db2bSLaurent Pinchart case V4L2_CID_ANALOGUE_GAIN:
339cb33db2bSLaurent Pinchart imx296_write(sensor, IMX296_GAIN, ctrl->val, &ret);
340cb33db2bSLaurent Pinchart break;
341cb33db2bSLaurent Pinchart
342cb33db2bSLaurent Pinchart case V4L2_CID_VBLANK:
343cb33db2bSLaurent Pinchart imx296_write(sensor, IMX296_VMAX, format->height + ctrl->val,
344cb33db2bSLaurent Pinchart &ret);
345cb33db2bSLaurent Pinchart break;
346cb33db2bSLaurent Pinchart
347cb33db2bSLaurent Pinchart case V4L2_CID_TEST_PATTERN:
348cb33db2bSLaurent Pinchart if (ctrl->val) {
349cb33db2bSLaurent Pinchart imx296_write(sensor, IMX296_PGHPOS, 8, &ret);
350cb33db2bSLaurent Pinchart imx296_write(sensor, IMX296_PGVPOS, 8, &ret);
351cb33db2bSLaurent Pinchart imx296_write(sensor, IMX296_PGHPSTEP, 8, &ret);
352cb33db2bSLaurent Pinchart imx296_write(sensor, IMX296_PGVPSTEP, 8, &ret);
353cb33db2bSLaurent Pinchart imx296_write(sensor, IMX296_PGHPNUM, 100, &ret);
354cb33db2bSLaurent Pinchart imx296_write(sensor, IMX296_PGVPNUM, 100, &ret);
355cb33db2bSLaurent Pinchart imx296_write(sensor, IMX296_PGDATA1, 0x300, &ret);
356cb33db2bSLaurent Pinchart imx296_write(sensor, IMX296_PGDATA2, 0x100, &ret);
357cb33db2bSLaurent Pinchart imx296_write(sensor, IMX296_PGHGSTEP, 0, &ret);
358cb33db2bSLaurent Pinchart imx296_write(sensor, IMX296_BLKLEVEL, 0, &ret);
359cb33db2bSLaurent Pinchart imx296_write(sensor, IMX296_BLKLEVELAUTO,
360cb33db2bSLaurent Pinchart IMX296_BLKLEVELAUTO_OFF, &ret);
361cb33db2bSLaurent Pinchart imx296_write(sensor, IMX296_PGCTRL,
362cb33db2bSLaurent Pinchart IMX296_PGCTRL_REGEN |
363cb33db2bSLaurent Pinchart IMX296_PGCTRL_CLKEN |
364cb33db2bSLaurent Pinchart IMX296_PGCTRL_MODE(ctrl->val - 1), &ret);
365cb33db2bSLaurent Pinchart } else {
366cb33db2bSLaurent Pinchart imx296_write(sensor, IMX296_PGCTRL,
367cb33db2bSLaurent Pinchart IMX296_PGCTRL_CLKEN, &ret);
368cb33db2bSLaurent Pinchart imx296_write(sensor, IMX296_BLKLEVEL, 0x3c, &ret);
369cb33db2bSLaurent Pinchart imx296_write(sensor, IMX296_BLKLEVELAUTO,
370cb33db2bSLaurent Pinchart IMX296_BLKLEVELAUTO_ON, &ret);
371cb33db2bSLaurent Pinchart }
372cb33db2bSLaurent Pinchart break;
373cb33db2bSLaurent Pinchart
374cb33db2bSLaurent Pinchart default:
375cb33db2bSLaurent Pinchart ret = -EINVAL;
376cb33db2bSLaurent Pinchart break;
377cb33db2bSLaurent Pinchart }
378cb33db2bSLaurent Pinchart
379cb33db2bSLaurent Pinchart return ret;
380cb33db2bSLaurent Pinchart }
381cb33db2bSLaurent Pinchart
382cb33db2bSLaurent Pinchart static const struct v4l2_ctrl_ops imx296_ctrl_ops = {
383cb33db2bSLaurent Pinchart .s_ctrl = imx296_s_ctrl,
384cb33db2bSLaurent Pinchart };
385cb33db2bSLaurent Pinchart
imx296_ctrls_init(struct imx296 * sensor)386cb33db2bSLaurent Pinchart static int imx296_ctrls_init(struct imx296 *sensor)
387cb33db2bSLaurent Pinchart {
388cb33db2bSLaurent Pinchart struct v4l2_fwnode_device_properties props;
389cb33db2bSLaurent Pinchart unsigned int hblank;
390cb33db2bSLaurent Pinchart int ret;
391cb33db2bSLaurent Pinchart
392cb33db2bSLaurent Pinchart ret = v4l2_fwnode_device_parse(sensor->dev, &props);
393cb33db2bSLaurent Pinchart if (ret < 0)
394cb33db2bSLaurent Pinchart return ret;
395cb33db2bSLaurent Pinchart
396cb33db2bSLaurent Pinchart v4l2_ctrl_handler_init(&sensor->ctrls, 9);
397cb33db2bSLaurent Pinchart
398cb33db2bSLaurent Pinchart v4l2_ctrl_new_std(&sensor->ctrls, &imx296_ctrl_ops,
399cb33db2bSLaurent Pinchart V4L2_CID_EXPOSURE, 1, 1048575, 1, 1104);
400cb33db2bSLaurent Pinchart v4l2_ctrl_new_std(&sensor->ctrls, &imx296_ctrl_ops,
401cb33db2bSLaurent Pinchart V4L2_CID_ANALOGUE_GAIN, IMX296_GAIN_MIN,
402cb33db2bSLaurent Pinchart IMX296_GAIN_MAX, 1, IMX296_GAIN_MIN);
403cb33db2bSLaurent Pinchart
404cb33db2bSLaurent Pinchart /*
405cb33db2bSLaurent Pinchart * Horizontal blanking is controlled through the HMAX register, which
406cb33db2bSLaurent Pinchart * contains a line length in INCK clock units. The INCK frequency is
407cb33db2bSLaurent Pinchart * fixed to 74.25 MHz. The HMAX value is currently fixed to 1100,
408cb33db2bSLaurent Pinchart * convert it to a number of pixels based on the nominal pixel rate.
409cb33db2bSLaurent Pinchart */
410cb33db2bSLaurent Pinchart hblank = 1100 * 1188000000ULL / 10 / 74250000
411cb33db2bSLaurent Pinchart - IMX296_PIXEL_ARRAY_WIDTH;
412cb33db2bSLaurent Pinchart sensor->hblank = v4l2_ctrl_new_std(&sensor->ctrls, &imx296_ctrl_ops,
413cb33db2bSLaurent Pinchart V4L2_CID_HBLANK, hblank, hblank, 1,
414cb33db2bSLaurent Pinchart hblank);
415cb33db2bSLaurent Pinchart if (sensor->hblank)
416cb33db2bSLaurent Pinchart sensor->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;
417cb33db2bSLaurent Pinchart
418cb33db2bSLaurent Pinchart sensor->vblank = v4l2_ctrl_new_std(&sensor->ctrls, &imx296_ctrl_ops,
419cb33db2bSLaurent Pinchart V4L2_CID_VBLANK, 30,
420cb33db2bSLaurent Pinchart 1048575 - IMX296_PIXEL_ARRAY_HEIGHT,
421cb33db2bSLaurent Pinchart 1, 30);
422cb33db2bSLaurent Pinchart /*
423cb33db2bSLaurent Pinchart * The sensor calculates the MIPI timings internally to achieve a bit
424cb33db2bSLaurent Pinchart * rate between 1122 and 1198 Mbps. The exact value is unfortunately not
425cb33db2bSLaurent Pinchart * reported, at least according to the documentation. Report a nominal
426cb33db2bSLaurent Pinchart * rate of 1188 Mbps as that is used by the datasheet in multiple
427cb33db2bSLaurent Pinchart * examples.
428cb33db2bSLaurent Pinchart */
429cb33db2bSLaurent Pinchart v4l2_ctrl_new_std(&sensor->ctrls, NULL, V4L2_CID_PIXEL_RATE,
430cb33db2bSLaurent Pinchart 1122000000 / 10, 1198000000 / 10, 1, 1188000000 / 10);
431cb33db2bSLaurent Pinchart v4l2_ctrl_new_std_menu_items(&sensor->ctrls, &imx296_ctrl_ops,
432cb33db2bSLaurent Pinchart V4L2_CID_TEST_PATTERN,
433cb33db2bSLaurent Pinchart ARRAY_SIZE(imx296_test_pattern_menu) - 1,
434cb33db2bSLaurent Pinchart 0, 0, imx296_test_pattern_menu);
435cb33db2bSLaurent Pinchart
436cb33db2bSLaurent Pinchart v4l2_ctrl_new_fwnode_properties(&sensor->ctrls, &imx296_ctrl_ops,
437cb33db2bSLaurent Pinchart &props);
438cb33db2bSLaurent Pinchart
439cb33db2bSLaurent Pinchart if (sensor->ctrls.error) {
440cb33db2bSLaurent Pinchart dev_err(sensor->dev, "failed to add controls (%d)\n",
441cb33db2bSLaurent Pinchart sensor->ctrls.error);
442cb33db2bSLaurent Pinchart v4l2_ctrl_handler_free(&sensor->ctrls);
443cb33db2bSLaurent Pinchart return sensor->ctrls.error;
444cb33db2bSLaurent Pinchart }
445cb33db2bSLaurent Pinchart
446cb33db2bSLaurent Pinchart sensor->subdev.ctrl_handler = &sensor->ctrls;
447cb33db2bSLaurent Pinchart
448cb33db2bSLaurent Pinchart return 0;
449cb33db2bSLaurent Pinchart }
450cb33db2bSLaurent Pinchart
451cb33db2bSLaurent Pinchart /* -----------------------------------------------------------------------------
452cb33db2bSLaurent Pinchart * V4L2 Subdev Operations
453cb33db2bSLaurent Pinchart */
454cb33db2bSLaurent Pinchart
455cb33db2bSLaurent Pinchart /*
456cb33db2bSLaurent Pinchart * This table is extracted from vendor data that is entirely undocumented. The
457cb33db2bSLaurent Pinchart * first register write is required to activate the CSI-2 output. The other
458cb33db2bSLaurent Pinchart * entries may or may not be optional?
459cb33db2bSLaurent Pinchart */
460cb33db2bSLaurent Pinchart static const struct {
461cb33db2bSLaurent Pinchart unsigned int reg;
462cb33db2bSLaurent Pinchart unsigned int value;
463cb33db2bSLaurent Pinchart } imx296_init_table[] = {
464cb33db2bSLaurent Pinchart { IMX296_REG_8BIT(0x3005), 0xf0 },
465cb33db2bSLaurent Pinchart { IMX296_REG_8BIT(0x309e), 0x04 },
466cb33db2bSLaurent Pinchart { IMX296_REG_8BIT(0x30a0), 0x04 },
467cb33db2bSLaurent Pinchart { IMX296_REG_8BIT(0x30a1), 0x3c },
468cb33db2bSLaurent Pinchart { IMX296_REG_8BIT(0x30a4), 0x5f },
469cb33db2bSLaurent Pinchart { IMX296_REG_8BIT(0x30a8), 0x91 },
470cb33db2bSLaurent Pinchart { IMX296_REG_8BIT(0x30ac), 0x28 },
471cb33db2bSLaurent Pinchart { IMX296_REG_8BIT(0x30af), 0x09 },
472cb33db2bSLaurent Pinchart { IMX296_REG_8BIT(0x30df), 0x00 },
473cb33db2bSLaurent Pinchart { IMX296_REG_8BIT(0x3165), 0x00 },
474cb33db2bSLaurent Pinchart { IMX296_REG_8BIT(0x3169), 0x10 },
475cb33db2bSLaurent Pinchart { IMX296_REG_8BIT(0x316a), 0x02 },
476cb33db2bSLaurent Pinchart { IMX296_REG_8BIT(0x31c8), 0xf3 }, /* Exposure-related */
477cb33db2bSLaurent Pinchart { IMX296_REG_8BIT(0x31d0), 0xf4 }, /* Exposure-related */
478cb33db2bSLaurent Pinchart { IMX296_REG_8BIT(0x321a), 0x00 },
479cb33db2bSLaurent Pinchart { IMX296_REG_8BIT(0x3226), 0x02 },
480cb33db2bSLaurent Pinchart { IMX296_REG_8BIT(0x3256), 0x01 },
481cb33db2bSLaurent Pinchart { IMX296_REG_8BIT(0x3541), 0x72 },
482cb33db2bSLaurent Pinchart { IMX296_REG_8BIT(0x3516), 0x77 },
483cb33db2bSLaurent Pinchart { IMX296_REG_8BIT(0x350b), 0x7f },
484cb33db2bSLaurent Pinchart { IMX296_REG_8BIT(0x3758), 0xa3 },
485cb33db2bSLaurent Pinchart { IMX296_REG_8BIT(0x3759), 0x00 },
486cb33db2bSLaurent Pinchart { IMX296_REG_8BIT(0x375a), 0x85 },
487cb33db2bSLaurent Pinchart { IMX296_REG_8BIT(0x375b), 0x00 },
488cb33db2bSLaurent Pinchart { IMX296_REG_8BIT(0x3832), 0xf5 },
489cb33db2bSLaurent Pinchart { IMX296_REG_8BIT(0x3833), 0x00 },
490cb33db2bSLaurent Pinchart { IMX296_REG_8BIT(0x38a2), 0xf6 },
491cb33db2bSLaurent Pinchart { IMX296_REG_8BIT(0x38a3), 0x00 },
492cb33db2bSLaurent Pinchart { IMX296_REG_8BIT(0x3a00), 0x80 },
493cb33db2bSLaurent Pinchart { IMX296_REG_8BIT(0x3d48), 0xa3 },
494cb33db2bSLaurent Pinchart { IMX296_REG_8BIT(0x3d49), 0x00 },
495cb33db2bSLaurent Pinchart { IMX296_REG_8BIT(0x3d4a), 0x85 },
496cb33db2bSLaurent Pinchart { IMX296_REG_8BIT(0x3d4b), 0x00 },
497cb33db2bSLaurent Pinchart { IMX296_REG_8BIT(0x400e), 0x58 },
498cb33db2bSLaurent Pinchart { IMX296_REG_8BIT(0x4014), 0x1c },
499cb33db2bSLaurent Pinchart { IMX296_REG_8BIT(0x4041), 0x2a },
500cb33db2bSLaurent Pinchart { IMX296_REG_8BIT(0x40a2), 0x06 },
501cb33db2bSLaurent Pinchart { IMX296_REG_8BIT(0x40c1), 0xf6 },
502cb33db2bSLaurent Pinchart { IMX296_REG_8BIT(0x40c7), 0x0f },
503cb33db2bSLaurent Pinchart { IMX296_REG_8BIT(0x40c8), 0x00 },
504cb33db2bSLaurent Pinchart { IMX296_REG_8BIT(0x4174), 0x00 },
505cb33db2bSLaurent Pinchart };
506cb33db2bSLaurent Pinchart
imx296_setup(struct imx296 * sensor,struct v4l2_subdev_state * state)507cb33db2bSLaurent Pinchart static int imx296_setup(struct imx296 *sensor, struct v4l2_subdev_state *state)
508cb33db2bSLaurent Pinchart {
509cb33db2bSLaurent Pinchart const struct v4l2_mbus_framefmt *format;
510cb33db2bSLaurent Pinchart const struct v4l2_rect *crop;
511cb33db2bSLaurent Pinchart unsigned int i;
512cb33db2bSLaurent Pinchart int ret = 0;
513cb33db2bSLaurent Pinchart
514cb33db2bSLaurent Pinchart format = v4l2_subdev_get_pad_format(&sensor->subdev, state, 0);
515cb33db2bSLaurent Pinchart crop = v4l2_subdev_get_pad_crop(&sensor->subdev, state, 0);
516cb33db2bSLaurent Pinchart
517cb33db2bSLaurent Pinchart for (i = 0; i < ARRAY_SIZE(imx296_init_table); ++i)
518cb33db2bSLaurent Pinchart imx296_write(sensor, imx296_init_table[i].reg,
519cb33db2bSLaurent Pinchart imx296_init_table[i].value, &ret);
520cb33db2bSLaurent Pinchart
521cb33db2bSLaurent Pinchart if (crop->width != IMX296_PIXEL_ARRAY_WIDTH ||
522cb33db2bSLaurent Pinchart crop->height != IMX296_PIXEL_ARRAY_HEIGHT) {
523cb33db2bSLaurent Pinchart imx296_write(sensor, IMX296_FID0_ROI,
524cb33db2bSLaurent Pinchart IMX296_FID0_ROIH1ON | IMX296_FID0_ROIV1ON, &ret);
525cb33db2bSLaurent Pinchart imx296_write(sensor, IMX296_FID0_ROIPH1, crop->left, &ret);
526cb33db2bSLaurent Pinchart imx296_write(sensor, IMX296_FID0_ROIPV1, crop->top, &ret);
527cb33db2bSLaurent Pinchart imx296_write(sensor, IMX296_FID0_ROIWH1, crop->width, &ret);
528cb33db2bSLaurent Pinchart imx296_write(sensor, IMX296_FID0_ROIWV1, crop->height, &ret);
529cb33db2bSLaurent Pinchart } else {
530cb33db2bSLaurent Pinchart imx296_write(sensor, IMX296_FID0_ROI, 0, &ret);
531cb33db2bSLaurent Pinchart }
532cb33db2bSLaurent Pinchart
533cb33db2bSLaurent Pinchart imx296_write(sensor, IMX296_CTRL0D,
534cb33db2bSLaurent Pinchart (crop->width != format->width ?
535cb33db2bSLaurent Pinchart IMX296_CTRL0D_HADD_ON_BINNING : 0) |
536cb33db2bSLaurent Pinchart (crop->height != format->height ?
537cb33db2bSLaurent Pinchart IMX296_CTRL0D_WINMODE_FD_BINNING : 0),
538cb33db2bSLaurent Pinchart &ret);
539cb33db2bSLaurent Pinchart
540cb33db2bSLaurent Pinchart /*
541cb33db2bSLaurent Pinchart * HMAX and VMAX configure horizontal and vertical blanking by
542cb33db2bSLaurent Pinchart * specifying the total line time and frame time respectively. The line
543cb33db2bSLaurent Pinchart * time is specified in operational clock units (which appears to be the
544cb33db2bSLaurent Pinchart * output of an internal PLL, fixed at 74.25 MHz regardless of the
545cb33db2bSLaurent Pinchart * exernal clock frequency), while the frame time is specified as a
546cb33db2bSLaurent Pinchart * number of lines.
547cb33db2bSLaurent Pinchart *
548cb33db2bSLaurent Pinchart * In the vertical direction the sensor outputs the following:
549cb33db2bSLaurent Pinchart *
550cb33db2bSLaurent Pinchart * - one line for the FS packet
551cb33db2bSLaurent Pinchart * - two lines of embedded data (DT 0x12)
552cb33db2bSLaurent Pinchart * - six null lines (DT 0x10)
553cb33db2bSLaurent Pinchart * - four lines of vertical effective optical black (DT 0x37)
554cb33db2bSLaurent Pinchart * - 8 to 1088 lines of active image data (RAW10, DT 0x2b)
555cb33db2bSLaurent Pinchart * - one line for the FE packet
556cb33db2bSLaurent Pinchart * - 16 or more lines of vertical blanking
557cb33db2bSLaurent Pinchart */
558cb33db2bSLaurent Pinchart imx296_write(sensor, IMX296_HMAX, 1100, &ret);
559cb33db2bSLaurent Pinchart imx296_write(sensor, IMX296_VMAX,
560cb33db2bSLaurent Pinchart format->height + sensor->vblank->cur.val, &ret);
561cb33db2bSLaurent Pinchart
562cb33db2bSLaurent Pinchart for (i = 0; i < ARRAY_SIZE(sensor->clk_params->incksel); ++i)
563cb33db2bSLaurent Pinchart imx296_write(sensor, IMX296_INCKSEL(i),
564cb33db2bSLaurent Pinchart sensor->clk_params->incksel[i], &ret);
565cb33db2bSLaurent Pinchart imx296_write(sensor, IMX296_GTTABLENUM, 0xc5, &ret);
566cb33db2bSLaurent Pinchart imx296_write(sensor, IMX296_CTRL418C, sensor->clk_params->ctrl418c,
567cb33db2bSLaurent Pinchart &ret);
568cb33db2bSLaurent Pinchart
569cb33db2bSLaurent Pinchart imx296_write(sensor, IMX296_GAINDLY, IMX296_GAINDLY_NONE, &ret);
570cb33db2bSLaurent Pinchart imx296_write(sensor, IMX296_BLKLEVEL, 0x03c, &ret);
571cb33db2bSLaurent Pinchart
572cb33db2bSLaurent Pinchart return ret;
573cb33db2bSLaurent Pinchart }
574cb33db2bSLaurent Pinchart
imx296_stream_on(struct imx296 * sensor)575cb33db2bSLaurent Pinchart static int imx296_stream_on(struct imx296 *sensor)
576cb33db2bSLaurent Pinchart {
577cb33db2bSLaurent Pinchart int ret = 0;
578cb33db2bSLaurent Pinchart
579cb33db2bSLaurent Pinchart imx296_write(sensor, IMX296_CTRL00, 0, &ret);
580cb33db2bSLaurent Pinchart usleep_range(2000, 5000);
581cb33db2bSLaurent Pinchart imx296_write(sensor, IMX296_CTRL0A, 0, &ret);
582cb33db2bSLaurent Pinchart
583cb33db2bSLaurent Pinchart return ret;
584cb33db2bSLaurent Pinchart }
585cb33db2bSLaurent Pinchart
imx296_stream_off(struct imx296 * sensor)586cb33db2bSLaurent Pinchart static int imx296_stream_off(struct imx296 *sensor)
587cb33db2bSLaurent Pinchart {
588cb33db2bSLaurent Pinchart int ret = 0;
589cb33db2bSLaurent Pinchart
590cb33db2bSLaurent Pinchart imx296_write(sensor, IMX296_CTRL0A, IMX296_CTRL0A_XMSTA, &ret);
591cb33db2bSLaurent Pinchart imx296_write(sensor, IMX296_CTRL00, IMX296_CTRL00_STANDBY, &ret);
592cb33db2bSLaurent Pinchart
593cb33db2bSLaurent Pinchart return ret;
594cb33db2bSLaurent Pinchart }
595cb33db2bSLaurent Pinchart
imx296_s_stream(struct v4l2_subdev * sd,int enable)596cb33db2bSLaurent Pinchart static int imx296_s_stream(struct v4l2_subdev *sd, int enable)
597cb33db2bSLaurent Pinchart {
598cb33db2bSLaurent Pinchart struct imx296 *sensor = to_imx296(sd);
599cb33db2bSLaurent Pinchart struct v4l2_subdev_state *state;
600cb33db2bSLaurent Pinchart int ret;
601cb33db2bSLaurent Pinchart
602cb33db2bSLaurent Pinchart state = v4l2_subdev_lock_and_get_active_state(sd);
603cb33db2bSLaurent Pinchart
604cb33db2bSLaurent Pinchart if (!enable) {
605cb33db2bSLaurent Pinchart ret = imx296_stream_off(sensor);
606cb33db2bSLaurent Pinchart
607cb33db2bSLaurent Pinchart pm_runtime_mark_last_busy(sensor->dev);
608cb33db2bSLaurent Pinchart pm_runtime_put_autosuspend(sensor->dev);
609cb33db2bSLaurent Pinchart
610cb33db2bSLaurent Pinchart sensor->streaming = false;
611cb33db2bSLaurent Pinchart
612cb33db2bSLaurent Pinchart goto unlock;
613cb33db2bSLaurent Pinchart }
614cb33db2bSLaurent Pinchart
615cb33db2bSLaurent Pinchart ret = pm_runtime_resume_and_get(sensor->dev);
616cb33db2bSLaurent Pinchart if (ret < 0)
617cb33db2bSLaurent Pinchart goto unlock;
618cb33db2bSLaurent Pinchart
619cb33db2bSLaurent Pinchart ret = imx296_setup(sensor, state);
620cb33db2bSLaurent Pinchart if (ret < 0)
621cb33db2bSLaurent Pinchart goto err_pm;
622cb33db2bSLaurent Pinchart
623cb33db2bSLaurent Pinchart /*
624cb33db2bSLaurent Pinchart * Set streaming to true to ensure __v4l2_ctrl_handler_setup() will set
625cb33db2bSLaurent Pinchart * the controls. The flag is reset to false further down if an error
626cb33db2bSLaurent Pinchart * occurs.
627cb33db2bSLaurent Pinchart */
628cb33db2bSLaurent Pinchart sensor->streaming = true;
629cb33db2bSLaurent Pinchart
630cb33db2bSLaurent Pinchart ret = __v4l2_ctrl_handler_setup(&sensor->ctrls);
631cb33db2bSLaurent Pinchart if (ret < 0)
632cb33db2bSLaurent Pinchart goto err_pm;
633cb33db2bSLaurent Pinchart
634cb33db2bSLaurent Pinchart ret = imx296_stream_on(sensor);
635cb33db2bSLaurent Pinchart if (ret)
636cb33db2bSLaurent Pinchart goto err_pm;
637cb33db2bSLaurent Pinchart
638cb33db2bSLaurent Pinchart unlock:
639cb33db2bSLaurent Pinchart v4l2_subdev_unlock_state(state);
640cb33db2bSLaurent Pinchart
641cb33db2bSLaurent Pinchart return ret;
642cb33db2bSLaurent Pinchart
643cb33db2bSLaurent Pinchart err_pm:
644cb33db2bSLaurent Pinchart /*
645cb33db2bSLaurent Pinchart * In case of error, turn the power off synchronously as the device
646cb33db2bSLaurent Pinchart * likely has no other chance to recover.
647cb33db2bSLaurent Pinchart */
648cb33db2bSLaurent Pinchart pm_runtime_put_sync(sensor->dev);
649cb33db2bSLaurent Pinchart sensor->streaming = false;
650cb33db2bSLaurent Pinchart
651cb33db2bSLaurent Pinchart goto unlock;
652cb33db2bSLaurent Pinchart }
653cb33db2bSLaurent Pinchart
imx296_enum_mbus_code(struct v4l2_subdev * sd,struct v4l2_subdev_state * state,struct v4l2_subdev_mbus_code_enum * code)654cb33db2bSLaurent Pinchart static int imx296_enum_mbus_code(struct v4l2_subdev *sd,
655cb33db2bSLaurent Pinchart struct v4l2_subdev_state *state,
656cb33db2bSLaurent Pinchart struct v4l2_subdev_mbus_code_enum *code)
657cb33db2bSLaurent Pinchart {
658cb33db2bSLaurent Pinchart struct imx296 *sensor = to_imx296(sd);
659cb33db2bSLaurent Pinchart
660cb33db2bSLaurent Pinchart if (code->index != 0)
661cb33db2bSLaurent Pinchart return -EINVAL;
662cb33db2bSLaurent Pinchart
663cb33db2bSLaurent Pinchart code->code = sensor->mono ? MEDIA_BUS_FMT_Y10_1X10
664cb33db2bSLaurent Pinchart : MEDIA_BUS_FMT_SBGGR10_1X10;
665cb33db2bSLaurent Pinchart
666cb33db2bSLaurent Pinchart return 0;
667cb33db2bSLaurent Pinchart }
668cb33db2bSLaurent Pinchart
imx296_enum_frame_size(struct v4l2_subdev * sd,struct v4l2_subdev_state * state,struct v4l2_subdev_frame_size_enum * fse)669cb33db2bSLaurent Pinchart static int imx296_enum_frame_size(struct v4l2_subdev *sd,
670cb33db2bSLaurent Pinchart struct v4l2_subdev_state *state,
671cb33db2bSLaurent Pinchart struct v4l2_subdev_frame_size_enum *fse)
672cb33db2bSLaurent Pinchart {
673cb33db2bSLaurent Pinchart const struct v4l2_mbus_framefmt *format;
674cb33db2bSLaurent Pinchart
675cb33db2bSLaurent Pinchart format = v4l2_subdev_get_pad_format(sd, state, fse->pad);
676cb33db2bSLaurent Pinchart
677cb33db2bSLaurent Pinchart if (fse->index >= 2 || fse->code != format->code)
678cb33db2bSLaurent Pinchart return -EINVAL;
679cb33db2bSLaurent Pinchart
680cb33db2bSLaurent Pinchart fse->min_width = IMX296_PIXEL_ARRAY_WIDTH / (fse->index + 1);
681cb33db2bSLaurent Pinchart fse->max_width = fse->min_width;
682cb33db2bSLaurent Pinchart fse->min_height = IMX296_PIXEL_ARRAY_HEIGHT / (fse->index + 1);
683cb33db2bSLaurent Pinchart fse->max_height = fse->min_height;
684cb33db2bSLaurent Pinchart
685cb33db2bSLaurent Pinchart return 0;
686cb33db2bSLaurent Pinchart }
687cb33db2bSLaurent Pinchart
imx296_set_format(struct v4l2_subdev * sd,struct v4l2_subdev_state * state,struct v4l2_subdev_format * fmt)688cb33db2bSLaurent Pinchart static int imx296_set_format(struct v4l2_subdev *sd,
689cb33db2bSLaurent Pinchart struct v4l2_subdev_state *state,
690cb33db2bSLaurent Pinchart struct v4l2_subdev_format *fmt)
691cb33db2bSLaurent Pinchart {
692cb33db2bSLaurent Pinchart struct imx296 *sensor = to_imx296(sd);
693cb33db2bSLaurent Pinchart struct v4l2_mbus_framefmt *format;
694cb33db2bSLaurent Pinchart struct v4l2_rect *crop;
695cb33db2bSLaurent Pinchart
696cb33db2bSLaurent Pinchart crop = v4l2_subdev_get_pad_crop(sd, state, fmt->pad);
697cb33db2bSLaurent Pinchart format = v4l2_subdev_get_pad_format(sd, state, fmt->pad);
698cb33db2bSLaurent Pinchart
699cb33db2bSLaurent Pinchart /*
700cb33db2bSLaurent Pinchart * Binning is only allowed when cropping is disabled according to the
701cb33db2bSLaurent Pinchart * documentation. This should be double-checked.
702cb33db2bSLaurent Pinchart */
703cb33db2bSLaurent Pinchart if (crop->width == IMX296_PIXEL_ARRAY_WIDTH &&
704cb33db2bSLaurent Pinchart crop->height == IMX296_PIXEL_ARRAY_HEIGHT) {
705cb33db2bSLaurent Pinchart unsigned int width;
706cb33db2bSLaurent Pinchart unsigned int height;
707cb33db2bSLaurent Pinchart unsigned int hratio;
708cb33db2bSLaurent Pinchart unsigned int vratio;
709cb33db2bSLaurent Pinchart
710cb33db2bSLaurent Pinchart /* Clamp the width and height to avoid dividing by zero. */
711cb33db2bSLaurent Pinchart width = clamp_t(unsigned int, fmt->format.width,
712cb33db2bSLaurent Pinchart crop->width / 2, crop->width);
713cb33db2bSLaurent Pinchart height = clamp_t(unsigned int, fmt->format.height,
714cb33db2bSLaurent Pinchart crop->height / 2, crop->height);
715cb33db2bSLaurent Pinchart
716cb33db2bSLaurent Pinchart hratio = DIV_ROUND_CLOSEST(crop->width, width);
717cb33db2bSLaurent Pinchart vratio = DIV_ROUND_CLOSEST(crop->height, height);
718cb33db2bSLaurent Pinchart
719cb33db2bSLaurent Pinchart format->width = crop->width / hratio;
720cb33db2bSLaurent Pinchart format->height = crop->height / vratio;
721cb33db2bSLaurent Pinchart } else {
722cb33db2bSLaurent Pinchart format->width = crop->width;
723cb33db2bSLaurent Pinchart format->height = crop->height;
724cb33db2bSLaurent Pinchart }
725cb33db2bSLaurent Pinchart
726cb33db2bSLaurent Pinchart format->code = sensor->mono ? MEDIA_BUS_FMT_Y10_1X10
727cb33db2bSLaurent Pinchart : MEDIA_BUS_FMT_SBGGR10_1X10;
728cb33db2bSLaurent Pinchart format->field = V4L2_FIELD_NONE;
729cb33db2bSLaurent Pinchart format->colorspace = V4L2_COLORSPACE_RAW;
730cb33db2bSLaurent Pinchart format->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
731cb33db2bSLaurent Pinchart format->quantization = V4L2_QUANTIZATION_FULL_RANGE;
732cb33db2bSLaurent Pinchart format->xfer_func = V4L2_XFER_FUNC_NONE;
733cb33db2bSLaurent Pinchart
734cb33db2bSLaurent Pinchart fmt->format = *format;
735cb33db2bSLaurent Pinchart
736cb33db2bSLaurent Pinchart return 0;
737cb33db2bSLaurent Pinchart }
738cb33db2bSLaurent Pinchart
imx296_get_selection(struct v4l2_subdev * sd,struct v4l2_subdev_state * state,struct v4l2_subdev_selection * sel)739cb33db2bSLaurent Pinchart static int imx296_get_selection(struct v4l2_subdev *sd,
740cb33db2bSLaurent Pinchart struct v4l2_subdev_state *state,
741cb33db2bSLaurent Pinchart struct v4l2_subdev_selection *sel)
742cb33db2bSLaurent Pinchart {
743cb33db2bSLaurent Pinchart switch (sel->target) {
744cb33db2bSLaurent Pinchart case V4L2_SEL_TGT_CROP:
745cb33db2bSLaurent Pinchart sel->r = *v4l2_subdev_get_pad_crop(sd, state, sel->pad);
746cb33db2bSLaurent Pinchart break;
747cb33db2bSLaurent Pinchart
748cb33db2bSLaurent Pinchart case V4L2_SEL_TGT_CROP_DEFAULT:
749cb33db2bSLaurent Pinchart case V4L2_SEL_TGT_CROP_BOUNDS:
750cb33db2bSLaurent Pinchart case V4L2_SEL_TGT_NATIVE_SIZE:
751cb33db2bSLaurent Pinchart sel->r.left = 0;
752cb33db2bSLaurent Pinchart sel->r.top = 0;
753cb33db2bSLaurent Pinchart sel->r.width = IMX296_PIXEL_ARRAY_WIDTH;
754cb33db2bSLaurent Pinchart sel->r.height = IMX296_PIXEL_ARRAY_HEIGHT;
755cb33db2bSLaurent Pinchart break;
756cb33db2bSLaurent Pinchart
757cb33db2bSLaurent Pinchart default:
758cb33db2bSLaurent Pinchart return -EINVAL;
759cb33db2bSLaurent Pinchart }
760cb33db2bSLaurent Pinchart
761cb33db2bSLaurent Pinchart return 0;
762cb33db2bSLaurent Pinchart }
763cb33db2bSLaurent Pinchart
imx296_set_selection(struct v4l2_subdev * sd,struct v4l2_subdev_state * state,struct v4l2_subdev_selection * sel)764cb33db2bSLaurent Pinchart static int imx296_set_selection(struct v4l2_subdev *sd,
765cb33db2bSLaurent Pinchart struct v4l2_subdev_state *state,
766cb33db2bSLaurent Pinchart struct v4l2_subdev_selection *sel)
767cb33db2bSLaurent Pinchart {
768cb33db2bSLaurent Pinchart struct v4l2_mbus_framefmt *format;
769cb33db2bSLaurent Pinchart struct v4l2_rect *crop;
770cb33db2bSLaurent Pinchart struct v4l2_rect rect;
771cb33db2bSLaurent Pinchart
772cb33db2bSLaurent Pinchart if (sel->target != V4L2_SEL_TGT_CROP)
773cb33db2bSLaurent Pinchart return -EINVAL;
774cb33db2bSLaurent Pinchart
775cb33db2bSLaurent Pinchart /*
776cb33db2bSLaurent Pinchart * Clamp the crop rectangle boundaries and align them to a multiple of 4
777cb33db2bSLaurent Pinchart * pixels to satisfy hardware requirements.
778cb33db2bSLaurent Pinchart */
779cb33db2bSLaurent Pinchart rect.left = clamp(ALIGN(sel->r.left, 4), 0,
780cb33db2bSLaurent Pinchart IMX296_PIXEL_ARRAY_WIDTH - IMX296_FID0_ROIWH1_MIN);
781cb33db2bSLaurent Pinchart rect.top = clamp(ALIGN(sel->r.top, 4), 0,
782cb33db2bSLaurent Pinchart IMX296_PIXEL_ARRAY_HEIGHT - IMX296_FID0_ROIWV1_MIN);
783cb33db2bSLaurent Pinchart rect.width = clamp_t(unsigned int, ALIGN(sel->r.width, 4),
784cb33db2bSLaurent Pinchart IMX296_FID0_ROIWH1_MIN, IMX296_PIXEL_ARRAY_WIDTH);
785cb33db2bSLaurent Pinchart rect.height = clamp_t(unsigned int, ALIGN(sel->r.height, 4),
786cb33db2bSLaurent Pinchart IMX296_FID0_ROIWV1_MIN, IMX296_PIXEL_ARRAY_HEIGHT);
787cb33db2bSLaurent Pinchart
788cb33db2bSLaurent Pinchart rect.width = min_t(unsigned int, rect.width,
789cb33db2bSLaurent Pinchart IMX296_PIXEL_ARRAY_WIDTH - rect.left);
790cb33db2bSLaurent Pinchart rect.height = min_t(unsigned int, rect.height,
791cb33db2bSLaurent Pinchart IMX296_PIXEL_ARRAY_HEIGHT - rect.top);
792cb33db2bSLaurent Pinchart
793cb33db2bSLaurent Pinchart crop = v4l2_subdev_get_pad_crop(sd, state, sel->pad);
794cb33db2bSLaurent Pinchart
795cb33db2bSLaurent Pinchart if (rect.width != crop->width || rect.height != crop->height) {
796cb33db2bSLaurent Pinchart /*
797cb33db2bSLaurent Pinchart * Reset the output image size if the crop rectangle size has
798cb33db2bSLaurent Pinchart * been modified.
799cb33db2bSLaurent Pinchart */
800cb33db2bSLaurent Pinchart format = v4l2_subdev_get_pad_format(sd, state, sel->pad);
801cb33db2bSLaurent Pinchart format->width = rect.width;
802cb33db2bSLaurent Pinchart format->height = rect.height;
803cb33db2bSLaurent Pinchart }
804cb33db2bSLaurent Pinchart
805cb33db2bSLaurent Pinchart *crop = rect;
806cb33db2bSLaurent Pinchart sel->r = rect;
807cb33db2bSLaurent Pinchart
808cb33db2bSLaurent Pinchart return 0;
809cb33db2bSLaurent Pinchart }
810cb33db2bSLaurent Pinchart
imx296_init_cfg(struct v4l2_subdev * sd,struct v4l2_subdev_state * state)811cb33db2bSLaurent Pinchart static int imx296_init_cfg(struct v4l2_subdev *sd,
812cb33db2bSLaurent Pinchart struct v4l2_subdev_state *state)
813cb33db2bSLaurent Pinchart {
814cb33db2bSLaurent Pinchart struct v4l2_subdev_selection sel = {
815cb33db2bSLaurent Pinchart .target = V4L2_SEL_TGT_CROP,
816cb33db2bSLaurent Pinchart .r.width = IMX296_PIXEL_ARRAY_WIDTH,
817cb33db2bSLaurent Pinchart .r.height = IMX296_PIXEL_ARRAY_HEIGHT,
818cb33db2bSLaurent Pinchart };
819cb33db2bSLaurent Pinchart struct v4l2_subdev_format format = {
820cb33db2bSLaurent Pinchart .format = {
821cb33db2bSLaurent Pinchart .width = IMX296_PIXEL_ARRAY_WIDTH,
822cb33db2bSLaurent Pinchart .height = IMX296_PIXEL_ARRAY_HEIGHT,
823cb33db2bSLaurent Pinchart },
824cb33db2bSLaurent Pinchart };
825cb33db2bSLaurent Pinchart
826cb33db2bSLaurent Pinchart imx296_set_selection(sd, state, &sel);
827cb33db2bSLaurent Pinchart imx296_set_format(sd, state, &format);
828cb33db2bSLaurent Pinchart
829cb33db2bSLaurent Pinchart return 0;
830cb33db2bSLaurent Pinchart }
831cb33db2bSLaurent Pinchart
832cb33db2bSLaurent Pinchart static const struct v4l2_subdev_video_ops imx296_subdev_video_ops = {
833cb33db2bSLaurent Pinchart .s_stream = imx296_s_stream,
834cb33db2bSLaurent Pinchart };
835cb33db2bSLaurent Pinchart
836cb33db2bSLaurent Pinchart static const struct v4l2_subdev_pad_ops imx296_subdev_pad_ops = {
837cb33db2bSLaurent Pinchart .enum_mbus_code = imx296_enum_mbus_code,
838cb33db2bSLaurent Pinchart .enum_frame_size = imx296_enum_frame_size,
839ef586f26SLaurent Pinchart .get_fmt = v4l2_subdev_get_fmt,
840cb33db2bSLaurent Pinchart .set_fmt = imx296_set_format,
841cb33db2bSLaurent Pinchart .get_selection = imx296_get_selection,
842cb33db2bSLaurent Pinchart .set_selection = imx296_set_selection,
843cb33db2bSLaurent Pinchart .init_cfg = imx296_init_cfg,
844cb33db2bSLaurent Pinchart };
845cb33db2bSLaurent Pinchart
846cb33db2bSLaurent Pinchart static const struct v4l2_subdev_ops imx296_subdev_ops = {
847cb33db2bSLaurent Pinchart .video = &imx296_subdev_video_ops,
848cb33db2bSLaurent Pinchart .pad = &imx296_subdev_pad_ops,
849cb33db2bSLaurent Pinchart };
850cb33db2bSLaurent Pinchart
imx296_subdev_init(struct imx296 * sensor)851cb33db2bSLaurent Pinchart static int imx296_subdev_init(struct imx296 *sensor)
852cb33db2bSLaurent Pinchart {
853cb33db2bSLaurent Pinchart struct i2c_client *client = to_i2c_client(sensor->dev);
854cb33db2bSLaurent Pinchart int ret;
855cb33db2bSLaurent Pinchart
856cb33db2bSLaurent Pinchart v4l2_i2c_subdev_init(&sensor->subdev, client, &imx296_subdev_ops);
857cb33db2bSLaurent Pinchart
858cb33db2bSLaurent Pinchart ret = imx296_ctrls_init(sensor);
859cb33db2bSLaurent Pinchart if (ret < 0)
860cb33db2bSLaurent Pinchart return ret;
861cb33db2bSLaurent Pinchart
862cb33db2bSLaurent Pinchart sensor->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
863cb33db2bSLaurent Pinchart sensor->pad.flags = MEDIA_PAD_FL_SOURCE;
864cb33db2bSLaurent Pinchart sensor->subdev.entity.function = MEDIA_ENT_F_CAM_SENSOR;
865cb33db2bSLaurent Pinchart ret = media_entity_pads_init(&sensor->subdev.entity, 1, &sensor->pad);
866cb33db2bSLaurent Pinchart if (ret < 0) {
867cb33db2bSLaurent Pinchart v4l2_ctrl_handler_free(&sensor->ctrls);
868cb33db2bSLaurent Pinchart return ret;
869cb33db2bSLaurent Pinchart }
870cb33db2bSLaurent Pinchart
871cb33db2bSLaurent Pinchart sensor->subdev.state_lock = sensor->subdev.ctrl_handler->lock;
872cb33db2bSLaurent Pinchart
873cb33db2bSLaurent Pinchart v4l2_subdev_init_finalize(&sensor->subdev);
874cb33db2bSLaurent Pinchart
875cb33db2bSLaurent Pinchart return ret;
876cb33db2bSLaurent Pinchart }
877cb33db2bSLaurent Pinchart
imx296_subdev_cleanup(struct imx296 * sensor)878cb33db2bSLaurent Pinchart static void imx296_subdev_cleanup(struct imx296 *sensor)
879cb33db2bSLaurent Pinchart {
880cb33db2bSLaurent Pinchart media_entity_cleanup(&sensor->subdev.entity);
881cb33db2bSLaurent Pinchart v4l2_ctrl_handler_free(&sensor->ctrls);
882cb33db2bSLaurent Pinchart }
883cb33db2bSLaurent Pinchart
884cb33db2bSLaurent Pinchart /* -----------------------------------------------------------------------------
885cb33db2bSLaurent Pinchart * Power management
886cb33db2bSLaurent Pinchart */
887cb33db2bSLaurent Pinchart
imx296_runtime_resume(struct device * dev)888cb33db2bSLaurent Pinchart static int __maybe_unused imx296_runtime_resume(struct device *dev)
889cb33db2bSLaurent Pinchart {
890cb33db2bSLaurent Pinchart struct i2c_client *client = to_i2c_client(dev);
891cb33db2bSLaurent Pinchart struct v4l2_subdev *subdev = i2c_get_clientdata(client);
892cb33db2bSLaurent Pinchart struct imx296 *sensor = to_imx296(subdev);
893cb33db2bSLaurent Pinchart
894cb33db2bSLaurent Pinchart return imx296_power_on(sensor);
895cb33db2bSLaurent Pinchart }
896cb33db2bSLaurent Pinchart
imx296_runtime_suspend(struct device * dev)897cb33db2bSLaurent Pinchart static int __maybe_unused imx296_runtime_suspend(struct device *dev)
898cb33db2bSLaurent Pinchart {
899cb33db2bSLaurent Pinchart struct i2c_client *client = to_i2c_client(dev);
900cb33db2bSLaurent Pinchart struct v4l2_subdev *subdev = i2c_get_clientdata(client);
901cb33db2bSLaurent Pinchart struct imx296 *sensor = to_imx296(subdev);
902cb33db2bSLaurent Pinchart
903cb33db2bSLaurent Pinchart imx296_power_off(sensor);
904cb33db2bSLaurent Pinchart
905cb33db2bSLaurent Pinchart return 0;
906cb33db2bSLaurent Pinchart }
907cb33db2bSLaurent Pinchart
908cb33db2bSLaurent Pinchart static const struct dev_pm_ops imx296_pm_ops = {
909cb33db2bSLaurent Pinchart SET_RUNTIME_PM_OPS(imx296_runtime_suspend, imx296_runtime_resume, NULL)
910cb33db2bSLaurent Pinchart };
911cb33db2bSLaurent Pinchart
912cb33db2bSLaurent Pinchart /* -----------------------------------------------------------------------------
913cb33db2bSLaurent Pinchart * Probe & Remove
914cb33db2bSLaurent Pinchart */
915cb33db2bSLaurent Pinchart
imx296_read_temperature(struct imx296 * sensor,int * temp)916cb33db2bSLaurent Pinchart static int imx296_read_temperature(struct imx296 *sensor, int *temp)
917cb33db2bSLaurent Pinchart {
918cb33db2bSLaurent Pinchart int tmdout;
919cb33db2bSLaurent Pinchart int ret;
920cb33db2bSLaurent Pinchart
921cb33db2bSLaurent Pinchart ret = imx296_write(sensor, IMX296_TMDCTRL, IMX296_TMDCTRL_LATCH, NULL);
922cb33db2bSLaurent Pinchart if (ret < 0)
923cb33db2bSLaurent Pinchart return ret;
924cb33db2bSLaurent Pinchart
9251b3565dbSDan Carpenter tmdout = imx296_read(sensor, IMX296_TMDOUT);
926cb33db2bSLaurent Pinchart if (tmdout < 0)
927cb33db2bSLaurent Pinchart return tmdout;
928cb33db2bSLaurent Pinchart
9291b3565dbSDan Carpenter tmdout &= IMX296_TMDOUT_MASK;
9301b3565dbSDan Carpenter
931cb33db2bSLaurent Pinchart /* T(°C) = 246.312 - 0.304 * TMDOUT */;
932cb33db2bSLaurent Pinchart *temp = 246312 - 304 * tmdout;
933cb33db2bSLaurent Pinchart
934cb33db2bSLaurent Pinchart return imx296_write(sensor, IMX296_TMDCTRL, 0, NULL);
935cb33db2bSLaurent Pinchart }
936cb33db2bSLaurent Pinchart
imx296_identify_model(struct imx296 * sensor)937cb33db2bSLaurent Pinchart static int imx296_identify_model(struct imx296 *sensor)
938cb33db2bSLaurent Pinchart {
939cb33db2bSLaurent Pinchart unsigned int model;
940cb33db2bSLaurent Pinchart int temp = 0;
941cb33db2bSLaurent Pinchart int ret;
942cb33db2bSLaurent Pinchart
943cb33db2bSLaurent Pinchart model = (uintptr_t)of_device_get_match_data(sensor->dev);
944cb33db2bSLaurent Pinchart if (model) {
945cb33db2bSLaurent Pinchart dev_dbg(sensor->dev,
946cb33db2bSLaurent Pinchart "sensor model auto-detection disabled, forcing 0x%04x\n",
947cb33db2bSLaurent Pinchart model);
948cb33db2bSLaurent Pinchart sensor->mono = model & IMX296_SENSOR_INFO_MONO;
949cb33db2bSLaurent Pinchart return 0;
950cb33db2bSLaurent Pinchart }
951cb33db2bSLaurent Pinchart
952cb33db2bSLaurent Pinchart /*
953cb33db2bSLaurent Pinchart * While most registers can be read when the sensor is in standby, this
954cb33db2bSLaurent Pinchart * is not the case of the sensor info register :-(
955cb33db2bSLaurent Pinchart */
956cb33db2bSLaurent Pinchart ret = imx296_write(sensor, IMX296_CTRL00, 0, NULL);
957cb33db2bSLaurent Pinchart if (ret < 0) {
958cb33db2bSLaurent Pinchart dev_err(sensor->dev,
959cb33db2bSLaurent Pinchart "failed to get sensor out of standby (%d)\n", ret);
960cb33db2bSLaurent Pinchart return ret;
961cb33db2bSLaurent Pinchart }
962cb33db2bSLaurent Pinchart
963*25abffeeSNaushir Patuck usleep_range(2000, 5000);
964*25abffeeSNaushir Patuck
965cb33db2bSLaurent Pinchart ret = imx296_read(sensor, IMX296_SENSOR_INFO);
966cb33db2bSLaurent Pinchart if (ret < 0) {
967cb33db2bSLaurent Pinchart dev_err(sensor->dev, "failed to read sensor information (%d)\n",
968cb33db2bSLaurent Pinchart ret);
969cb33db2bSLaurent Pinchart goto done;
970cb33db2bSLaurent Pinchart }
971cb33db2bSLaurent Pinchart
972cb33db2bSLaurent Pinchart model = (ret >> 6) & 0x1ff;
973cb33db2bSLaurent Pinchart
974cb33db2bSLaurent Pinchart switch (model) {
975cb33db2bSLaurent Pinchart case 296:
976cb33db2bSLaurent Pinchart sensor->mono = ret & IMX296_SENSOR_INFO_MONO;
977cb33db2bSLaurent Pinchart break;
978cb33db2bSLaurent Pinchart /*
979cb33db2bSLaurent Pinchart * The IMX297 seems to share features with the IMX296, it may be
980cb33db2bSLaurent Pinchart * possible to support it in the same driver.
981cb33db2bSLaurent Pinchart */
982cb33db2bSLaurent Pinchart case 297:
983cb33db2bSLaurent Pinchart default:
984cb33db2bSLaurent Pinchart dev_err(sensor->dev, "invalid device model 0x%04x\n", ret);
985cb33db2bSLaurent Pinchart ret = -ENODEV;
986cb33db2bSLaurent Pinchart goto done;
987cb33db2bSLaurent Pinchart }
988cb33db2bSLaurent Pinchart
989cb33db2bSLaurent Pinchart ret = imx296_read_temperature(sensor, &temp);
990cb33db2bSLaurent Pinchart if (ret < 0)
991cb33db2bSLaurent Pinchart goto done;
992cb33db2bSLaurent Pinchart
993cb33db2bSLaurent Pinchart dev_info(sensor->dev, "found IMX%u%s (%u.%uC)\n", model,
994cb33db2bSLaurent Pinchart sensor->mono ? "LL" : "LQ", temp / 1000, (temp / 100) % 10);
995cb33db2bSLaurent Pinchart
996cb33db2bSLaurent Pinchart done:
997cb33db2bSLaurent Pinchart imx296_write(sensor, IMX296_CTRL00, IMX296_CTRL00_STANDBY, NULL);
998cb33db2bSLaurent Pinchart return ret;
999cb33db2bSLaurent Pinchart }
1000cb33db2bSLaurent Pinchart
1001cb33db2bSLaurent Pinchart static const struct regmap_config imx296_regmap_config = {
1002cb33db2bSLaurent Pinchart .reg_bits = 16,
1003cb33db2bSLaurent Pinchart .val_bits = 8,
1004cb33db2bSLaurent Pinchart
1005cb33db2bSLaurent Pinchart .wr_table = &(const struct regmap_access_table) {
1006cb33db2bSLaurent Pinchart .no_ranges = (const struct regmap_range[]) {
1007cb33db2bSLaurent Pinchart {
1008cb33db2bSLaurent Pinchart .range_min = IMX296_SENSOR_INFO & 0xffff,
1009cb33db2bSLaurent Pinchart .range_max = (IMX296_SENSOR_INFO & 0xffff) + 1,
1010cb33db2bSLaurent Pinchart },
1011cb33db2bSLaurent Pinchart },
1012cb33db2bSLaurent Pinchart .n_no_ranges = 1,
1013cb33db2bSLaurent Pinchart },
1014cb33db2bSLaurent Pinchart };
1015cb33db2bSLaurent Pinchart
imx296_probe(struct i2c_client * client)1016cb33db2bSLaurent Pinchart static int imx296_probe(struct i2c_client *client)
1017cb33db2bSLaurent Pinchart {
1018cb33db2bSLaurent Pinchart struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
1019cb33db2bSLaurent Pinchart unsigned long clk_rate;
1020cb33db2bSLaurent Pinchart struct imx296 *sensor;
1021cb33db2bSLaurent Pinchart unsigned int i;
1022cb33db2bSLaurent Pinchart int ret;
1023cb33db2bSLaurent Pinchart
1024cb33db2bSLaurent Pinchart if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
1025cb33db2bSLaurent Pinchart dev_warn(&adapter->dev,
1026cb33db2bSLaurent Pinchart "I2C-Adapter doesn't support I2C_FUNC_SMBUS_BYTE\n");
1027cb33db2bSLaurent Pinchart return -EIO;
1028cb33db2bSLaurent Pinchart }
1029cb33db2bSLaurent Pinchart
1030cb33db2bSLaurent Pinchart sensor = devm_kzalloc(&client->dev, sizeof(*sensor), GFP_KERNEL);
1031cb33db2bSLaurent Pinchart if (!sensor)
1032cb33db2bSLaurent Pinchart return -ENOMEM;
1033cb33db2bSLaurent Pinchart
1034cb33db2bSLaurent Pinchart sensor->dev = &client->dev;
1035cb33db2bSLaurent Pinchart
1036cb33db2bSLaurent Pinchart /* Acquire resources. */
1037cb33db2bSLaurent Pinchart for (i = 0; i < ARRAY_SIZE(sensor->supplies); ++i)
1038cb33db2bSLaurent Pinchart sensor->supplies[i].supply = imx296_supply_names[i];
1039cb33db2bSLaurent Pinchart
1040cb33db2bSLaurent Pinchart ret = devm_regulator_bulk_get(sensor->dev, ARRAY_SIZE(sensor->supplies),
1041cb33db2bSLaurent Pinchart sensor->supplies);
1042cb33db2bSLaurent Pinchart if (ret) {
1043cb33db2bSLaurent Pinchart dev_err_probe(sensor->dev, ret, "failed to get supplies\n");
1044cb33db2bSLaurent Pinchart return ret;
1045cb33db2bSLaurent Pinchart }
1046cb33db2bSLaurent Pinchart
1047cb33db2bSLaurent Pinchart sensor->reset = devm_gpiod_get_optional(sensor->dev, "reset",
1048cb33db2bSLaurent Pinchart GPIOD_OUT_HIGH);
1049cb33db2bSLaurent Pinchart if (IS_ERR(sensor->reset))
1050cb33db2bSLaurent Pinchart return dev_err_probe(sensor->dev, PTR_ERR(sensor->reset),
1051cb33db2bSLaurent Pinchart "failed to get reset GPIO\n");
1052cb33db2bSLaurent Pinchart
1053cb33db2bSLaurent Pinchart sensor->clk = devm_clk_get(sensor->dev, "inck");
1054cb33db2bSLaurent Pinchart if (IS_ERR(sensor->clk))
1055cb33db2bSLaurent Pinchart return dev_err_probe(sensor->dev, PTR_ERR(sensor->clk),
1056cb33db2bSLaurent Pinchart "failed to get clock\n");
1057cb33db2bSLaurent Pinchart
1058cb33db2bSLaurent Pinchart clk_rate = clk_get_rate(sensor->clk);
1059cb33db2bSLaurent Pinchart for (i = 0; i < ARRAY_SIZE(imx296_clk_params); ++i) {
1060cb33db2bSLaurent Pinchart if (clk_rate == imx296_clk_params[i].freq) {
1061cb33db2bSLaurent Pinchart sensor->clk_params = &imx296_clk_params[i];
1062cb33db2bSLaurent Pinchart break;
1063cb33db2bSLaurent Pinchart }
1064cb33db2bSLaurent Pinchart }
1065cb33db2bSLaurent Pinchart
1066cb33db2bSLaurent Pinchart if (!sensor->clk_params) {
1067cb33db2bSLaurent Pinchart dev_err(sensor->dev, "unsupported clock rate %lu\n", clk_rate);
1068cb33db2bSLaurent Pinchart return -EINVAL;
1069cb33db2bSLaurent Pinchart }
1070cb33db2bSLaurent Pinchart
1071cb33db2bSLaurent Pinchart sensor->regmap = devm_regmap_init_i2c(client, &imx296_regmap_config);
1072cb33db2bSLaurent Pinchart if (IS_ERR(sensor->regmap))
1073cb33db2bSLaurent Pinchart return PTR_ERR(sensor->regmap);
1074cb33db2bSLaurent Pinchart
1075cb33db2bSLaurent Pinchart /*
1076cb33db2bSLaurent Pinchart * Enable power management. The driver supports runtime PM, but needs to
1077cb33db2bSLaurent Pinchart * work when runtime PM is disabled in the kernel. To that end, power
1078cb33db2bSLaurent Pinchart * the sensor on manually here, identify it, and fully initialize it.
1079cb33db2bSLaurent Pinchart */
1080cb33db2bSLaurent Pinchart ret = imx296_power_on(sensor);
1081cb33db2bSLaurent Pinchart if (ret < 0)
1082cb33db2bSLaurent Pinchart return ret;
1083cb33db2bSLaurent Pinchart
1084cb33db2bSLaurent Pinchart ret = imx296_identify_model(sensor);
1085cb33db2bSLaurent Pinchart if (ret < 0)
1086cb33db2bSLaurent Pinchart goto err_power;
1087cb33db2bSLaurent Pinchart
1088cb33db2bSLaurent Pinchart /* Initialize the V4L2 subdev. */
1089cb33db2bSLaurent Pinchart ret = imx296_subdev_init(sensor);
1090cb33db2bSLaurent Pinchart if (ret < 0)
1091cb33db2bSLaurent Pinchart goto err_power;
1092cb33db2bSLaurent Pinchart
1093cb33db2bSLaurent Pinchart /*
1094cb33db2bSLaurent Pinchart * Enable runtime PM. As the device has been powered manually, mark it
1095cb33db2bSLaurent Pinchart * as active, and increase the usage count without resuming the device.
1096cb33db2bSLaurent Pinchart */
1097cb33db2bSLaurent Pinchart pm_runtime_set_active(sensor->dev);
1098cb33db2bSLaurent Pinchart pm_runtime_get_noresume(sensor->dev);
1099cb33db2bSLaurent Pinchart pm_runtime_enable(sensor->dev);
1100cb33db2bSLaurent Pinchart
1101cb33db2bSLaurent Pinchart /* Register the V4L2 subdev. */
1102cb33db2bSLaurent Pinchart ret = v4l2_async_register_subdev(&sensor->subdev);
1103cb33db2bSLaurent Pinchart if (ret < 0)
1104cb33db2bSLaurent Pinchart goto err_pm;
1105cb33db2bSLaurent Pinchart
1106cb33db2bSLaurent Pinchart /*
1107cb33db2bSLaurent Pinchart * Finally, enable autosuspend and decrease the usage count. The device
1108cb33db2bSLaurent Pinchart * will get suspended after the autosuspend delay, turning the power
1109cb33db2bSLaurent Pinchart * off.
1110cb33db2bSLaurent Pinchart */
1111cb33db2bSLaurent Pinchart pm_runtime_set_autosuspend_delay(sensor->dev, 1000);
1112cb33db2bSLaurent Pinchart pm_runtime_use_autosuspend(sensor->dev);
1113cb33db2bSLaurent Pinchart pm_runtime_put_autosuspend(sensor->dev);
1114cb33db2bSLaurent Pinchart
1115cb33db2bSLaurent Pinchart return 0;
1116cb33db2bSLaurent Pinchart
1117cb33db2bSLaurent Pinchart err_pm:
1118cb33db2bSLaurent Pinchart pm_runtime_disable(sensor->dev);
1119cb33db2bSLaurent Pinchart pm_runtime_put_noidle(sensor->dev);
1120cb33db2bSLaurent Pinchart imx296_subdev_cleanup(sensor);
1121cb33db2bSLaurent Pinchart err_power:
1122cb33db2bSLaurent Pinchart imx296_power_off(sensor);
1123cb33db2bSLaurent Pinchart return ret;
1124cb33db2bSLaurent Pinchart }
1125cb33db2bSLaurent Pinchart
imx296_remove(struct i2c_client * client)1126cb33db2bSLaurent Pinchart static void imx296_remove(struct i2c_client *client)
1127cb33db2bSLaurent Pinchart {
1128cb33db2bSLaurent Pinchart struct v4l2_subdev *subdev = i2c_get_clientdata(client);
1129cb33db2bSLaurent Pinchart struct imx296 *sensor = to_imx296(subdev);
1130cb33db2bSLaurent Pinchart
1131cb33db2bSLaurent Pinchart v4l2_async_unregister_subdev(subdev);
1132cb33db2bSLaurent Pinchart
1133cb33db2bSLaurent Pinchart imx296_subdev_cleanup(sensor);
1134cb33db2bSLaurent Pinchart
1135cb33db2bSLaurent Pinchart /*
1136cb33db2bSLaurent Pinchart * Disable runtime PM. In case runtime PM is disabled in the kernel,
1137cb33db2bSLaurent Pinchart * make sure to turn power off manually.
1138cb33db2bSLaurent Pinchart */
1139cb33db2bSLaurent Pinchart pm_runtime_disable(sensor->dev);
1140cb33db2bSLaurent Pinchart if (!pm_runtime_status_suspended(sensor->dev))
1141cb33db2bSLaurent Pinchart imx296_power_off(sensor);
1142cb33db2bSLaurent Pinchart pm_runtime_set_suspended(sensor->dev);
1143cb33db2bSLaurent Pinchart }
1144cb33db2bSLaurent Pinchart
1145cb33db2bSLaurent Pinchart static const struct of_device_id imx296_of_match[] = {
1146cb33db2bSLaurent Pinchart { .compatible = "sony,imx296", .data = NULL },
1147cb33db2bSLaurent Pinchart { .compatible = "sony,imx296ll", .data = (void *)IMX296_SENSOR_INFO_IMX296LL },
1148cb33db2bSLaurent Pinchart { .compatible = "sony,imx296lq", .data = (void *)IMX296_SENSOR_INFO_IMX296LQ },
1149cb33db2bSLaurent Pinchart { /* sentinel */ },
1150cb33db2bSLaurent Pinchart };
1151cb33db2bSLaurent Pinchart MODULE_DEVICE_TABLE(of, imx296_of_match);
1152cb33db2bSLaurent Pinchart
1153cb33db2bSLaurent Pinchart static struct i2c_driver imx296_i2c_driver = {
1154cb33db2bSLaurent Pinchart .driver = {
1155cb33db2bSLaurent Pinchart .of_match_table = imx296_of_match,
1156cb33db2bSLaurent Pinchart .name = "imx296",
1157cb33db2bSLaurent Pinchart .pm = &imx296_pm_ops
1158cb33db2bSLaurent Pinchart },
1159aaeb31c0SUwe Kleine-König .probe = imx296_probe,
1160cb33db2bSLaurent Pinchart .remove = imx296_remove,
1161cb33db2bSLaurent Pinchart };
1162cb33db2bSLaurent Pinchart
1163cb33db2bSLaurent Pinchart module_i2c_driver(imx296_i2c_driver);
1164cb33db2bSLaurent Pinchart
1165cb33db2bSLaurent Pinchart MODULE_DESCRIPTION("Sony IMX296 Camera driver");
1166cb33db2bSLaurent Pinchart MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>");
1167cb33db2bSLaurent Pinchart MODULE_LICENSE("GPL");
1168