blob: c4b2115559a54349b9d080372adb9e9fabac6eb4 [file] [log] [blame]
Songjun Wu10626742016-08-17 03:05:27 -03001/*
2 * Atmel Image Sensor Controller (ISC) driver
3 *
4 * Copyright (C) 2016 Atmel
5 *
6 * Author: Songjun Wu <songjun.wu@microchip.com>
7 *
8 * This program is free software; you may redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; version 2 of the License.
11 *
12 * Sensor-->PFE-->WB-->CFA-->CC-->GAM-->CSC-->CBC-->SUB-->RLP-->DMA
13 *
14 * ISC video pipeline integrates the following submodules:
15 * PFE: Parallel Front End to sample the camera sensor input stream
16 * WB: Programmable white balance in the Bayer domain
17 * CFA: Color filter array interpolation module
18 * CC: Programmable color correction
19 * GAM: Gamma correction
20 * CSC: Programmable color space conversion
21 * CBC: Contrast and Brightness control
22 * SUB: This module performs YCbCr444 to YCbCr420 chrominance subsampling
23 * RLP: This module performs rounding, range limiting
24 * and packing of the incoming data
25 */
26
27#include <linux/clk.h>
28#include <linux/clkdev.h>
29#include <linux/clk-provider.h>
30#include <linux/delay.h>
31#include <linux/interrupt.h>
Songjun Wu93d4a262017-01-24 06:05:57 -020032#include <linux/math64.h>
Songjun Wu10626742016-08-17 03:05:27 -030033#include <linux/module.h>
34#include <linux/of.h>
35#include <linux/platform_device.h>
36#include <linux/pm_runtime.h>
37#include <linux/regmap.h>
38#include <linux/videodev2.h>
39
Songjun Wu93d4a262017-01-24 06:05:57 -020040#include <media/v4l2-ctrls.h>
Songjun Wu10626742016-08-17 03:05:27 -030041#include <media/v4l2-device.h>
Songjun Wu93d4a262017-01-24 06:05:57 -020042#include <media/v4l2-event.h>
Songjun Wu10626742016-08-17 03:05:27 -030043#include <media/v4l2-image-sizes.h>
44#include <media/v4l2-ioctl.h>
45#include <media/v4l2-of.h>
46#include <media/v4l2-subdev.h>
47#include <media/videobuf2-dma-contig.h>
48
49#include "atmel-isc-regs.h"
50
51#define ATMEL_ISC_NAME "atmel_isc"
52
53#define ISC_MAX_SUPPORT_WIDTH 2592
54#define ISC_MAX_SUPPORT_HEIGHT 1944
55
56#define ISC_CLK_MAX_DIV 255
57
58enum isc_clk_id {
59 ISC_ISPCK = 0,
60 ISC_MCK = 1,
61};
62
63struct isc_clk {
64 struct clk_hw hw;
65 struct clk *clk;
66 struct regmap *regmap;
67 u8 id;
68 u8 parent_id;
69 u32 div;
70 struct device *dev;
71};
72
73#define to_isc_clk(hw) container_of(hw, struct isc_clk, hw)
74
75struct isc_buffer {
76 struct vb2_v4l2_buffer vb;
77 struct list_head list;
78};
79
80struct isc_subdev_entity {
81 struct v4l2_subdev *sd;
82 struct v4l2_async_subdev *asd;
83 struct v4l2_async_notifier notifier;
84 struct v4l2_subdev_pad_config *config;
85
86 u32 pfe_cfg0;
87
88 struct list_head list;
89};
90
91/*
92 * struct isc_format - ISC media bus format information
93 * @fourcc: Fourcc code for this format
94 * @mbus_code: V4L2 media bus format code.
Songjun Wu93d4a262017-01-24 06:05:57 -020095 * @bpp: Bits per pixel (when stored in memory)
Songjun Wu10626742016-08-17 03:05:27 -030096 * @reg_bps: reg value for bits per sample
97 * (when transferred over a bus)
Songjun Wu93d4a262017-01-24 06:05:57 -020098 * @pipeline: pipeline switch
99 * @sd_support: Subdev supports this format
100 * @isc_support: ISC can convert raw format to this format
Songjun Wu10626742016-08-17 03:05:27 -0300101 */
102struct isc_format {
103 u32 fourcc;
104 u32 mbus_code;
105 u8 bpp;
106
107 u32 reg_bps;
Songjun Wu93d4a262017-01-24 06:05:57 -0200108 u32 reg_bay_cfg;
Songjun Wu10626742016-08-17 03:05:27 -0300109 u32 reg_rlp_mode;
110 u32 reg_dcfg_imode;
111 u32 reg_dctrl_dview;
112
Songjun Wu93d4a262017-01-24 06:05:57 -0200113 u32 pipeline;
114
115 bool sd_support;
116 bool isc_support;
117};
118
119
120#define HIST_ENTRIES 512
121#define HIST_BAYER (ISC_HIS_CFG_MODE_B + 1)
122
123enum{
124 HIST_INIT = 0,
125 HIST_ENABLED,
126 HIST_DISABLED,
127};
128
129struct isc_ctrls {
130 struct v4l2_ctrl_handler handler;
131
132 u32 brightness;
133 u32 contrast;
134 u8 gamma_index;
135 u8 awb;
136
137 u32 r_gain;
138 u32 b_gain;
139
140 u32 hist_entry[HIST_ENTRIES];
141 u32 hist_count[HIST_BAYER];
142 u8 hist_id;
143 u8 hist_stat;
Songjun Wu10626742016-08-17 03:05:27 -0300144};
145
146#define ISC_PIPE_LINE_NODE_NUM 11
147
148struct isc_device {
149 struct regmap *regmap;
150 struct clk *hclock;
151 struct clk *ispck;
152 struct isc_clk isc_clks[2];
153
154 struct device *dev;
155 struct v4l2_device v4l2_dev;
156 struct video_device video_dev;
157
158 struct vb2_queue vb2_vidq;
159 spinlock_t dma_queue_lock;
160 struct list_head dma_queue;
161 struct isc_buffer *cur_frm;
162 unsigned int sequence;
163 bool stop;
164 struct completion comp;
165
166 struct v4l2_format fmt;
167 struct isc_format **user_formats;
168 unsigned int num_user_formats;
169 const struct isc_format *current_fmt;
Songjun Wu93d4a262017-01-24 06:05:57 -0200170 const struct isc_format *raw_fmt;
171
172 struct isc_ctrls ctrls;
173 struct work_struct awb_work;
Songjun Wu10626742016-08-17 03:05:27 -0300174
175 struct mutex lock;
176
177 struct regmap_field *pipeline[ISC_PIPE_LINE_NODE_NUM];
178
179 struct isc_subdev_entity *current_subdev;
180 struct list_head subdev_entities;
181};
182
Songjun Wu93d4a262017-01-24 06:05:57 -0200183#define RAW_FMT_IND_START 0
184#define RAW_FMT_IND_END 11
185#define ISC_FMT_IND_START 12
186#define ISC_FMT_IND_END 14
187
Songjun Wu10626742016-08-17 03:05:27 -0300188static struct isc_format isc_formats[] = {
Songjun Wu93d4a262017-01-24 06:05:57 -0200189 { V4L2_PIX_FMT_SBGGR8, MEDIA_BUS_FMT_SBGGR8_1X8, 8,
190 ISC_PFE_CFG0_BPS_EIGHT, ISC_BAY_CFG_BGBG, ISC_RLP_CFG_MODE_DAT8,
191 ISC_DCFG_IMODE_PACKED8, ISC_DCTRL_DVIEW_PACKED, 0x0,
192 false, false },
193 { V4L2_PIX_FMT_SGBRG8, MEDIA_BUS_FMT_SGBRG8_1X8, 8,
194 ISC_PFE_CFG0_BPS_EIGHT, ISC_BAY_CFG_GBGB, ISC_RLP_CFG_MODE_DAT8,
195 ISC_DCFG_IMODE_PACKED8, ISC_DCTRL_DVIEW_PACKED, 0x0,
196 false, false },
197 { V4L2_PIX_FMT_SGRBG8, MEDIA_BUS_FMT_SGRBG8_1X8, 8,
198 ISC_PFE_CFG0_BPS_EIGHT, ISC_BAY_CFG_GRGR, ISC_RLP_CFG_MODE_DAT8,
199 ISC_DCFG_IMODE_PACKED8, ISC_DCTRL_DVIEW_PACKED, 0x0,
200 false, false },
201 { V4L2_PIX_FMT_SRGGB8, MEDIA_BUS_FMT_SRGGB8_1X8, 8,
202 ISC_PFE_CFG0_BPS_EIGHT, ISC_BAY_CFG_RGRG, ISC_RLP_CFG_MODE_DAT8,
203 ISC_DCFG_IMODE_PACKED8, ISC_DCTRL_DVIEW_PACKED, 0x0,
204 false, false },
Songjun Wu10626742016-08-17 03:05:27 -0300205
Songjun Wu93d4a262017-01-24 06:05:57 -0200206 { V4L2_PIX_FMT_SBGGR10, MEDIA_BUS_FMT_SBGGR10_1X10, 16,
207 ISC_PFG_CFG0_BPS_TEN, ISC_BAY_CFG_BGBG, ISC_RLP_CFG_MODE_DAT10,
208 ISC_DCFG_IMODE_PACKED16, ISC_DCTRL_DVIEW_PACKED, 0x0,
209 false, false },
210 { V4L2_PIX_FMT_SGBRG10, MEDIA_BUS_FMT_SGBRG10_1X10, 16,
211 ISC_PFG_CFG0_BPS_TEN, ISC_BAY_CFG_GBGB, ISC_RLP_CFG_MODE_DAT10,
212 ISC_DCFG_IMODE_PACKED16, ISC_DCTRL_DVIEW_PACKED, 0x0,
213 false, false },
214 { V4L2_PIX_FMT_SGRBG10, MEDIA_BUS_FMT_SGRBG10_1X10, 16,
215 ISC_PFG_CFG0_BPS_TEN, ISC_BAY_CFG_GRGR, ISC_RLP_CFG_MODE_DAT10,
216 ISC_DCFG_IMODE_PACKED16, ISC_DCTRL_DVIEW_PACKED, 0x0,
217 false, false },
218 { V4L2_PIX_FMT_SRGGB10, MEDIA_BUS_FMT_SRGGB10_1X10, 16,
219 ISC_PFG_CFG0_BPS_TEN, ISC_BAY_CFG_RGRG, ISC_RLP_CFG_MODE_DAT10,
220 ISC_DCFG_IMODE_PACKED16, ISC_DCTRL_DVIEW_PACKED, 0x0,
221 false, false },
Songjun Wu10626742016-08-17 03:05:27 -0300222
Songjun Wu93d4a262017-01-24 06:05:57 -0200223 { V4L2_PIX_FMT_SBGGR12, MEDIA_BUS_FMT_SBGGR12_1X12, 16,
224 ISC_PFG_CFG0_BPS_TWELVE, ISC_BAY_CFG_BGBG, ISC_RLP_CFG_MODE_DAT12,
225 ISC_DCFG_IMODE_PACKED16, ISC_DCTRL_DVIEW_PACKED, 0x0,
226 false, false },
227 { V4L2_PIX_FMT_SGBRG12, MEDIA_BUS_FMT_SGBRG12_1X12, 16,
228 ISC_PFG_CFG0_BPS_TWELVE, ISC_BAY_CFG_GBGB, ISC_RLP_CFG_MODE_DAT12,
229 ISC_DCFG_IMODE_PACKED16, ISC_DCTRL_DVIEW_PACKED, 0x0,
230 false, false },
231 { V4L2_PIX_FMT_SGRBG12, MEDIA_BUS_FMT_SGRBG12_1X12, 16,
232 ISC_PFG_CFG0_BPS_TWELVE, ISC_BAY_CFG_GRGR, ISC_RLP_CFG_MODE_DAT12,
233 ISC_DCFG_IMODE_PACKED16, ISC_DCTRL_DVIEW_PACKED, 0x0,
234 false, false },
235 { V4L2_PIX_FMT_SRGGB12, MEDIA_BUS_FMT_SRGGB12_1X12, 16,
236 ISC_PFG_CFG0_BPS_TWELVE, ISC_BAY_CFG_RGRG, ISC_RLP_CFG_MODE_DAT12,
237 ISC_DCFG_IMODE_PACKED16, ISC_DCTRL_DVIEW_PACKED, 0x0,
238 false, false },
Songjun Wu10626742016-08-17 03:05:27 -0300239
Songjun Wu93d4a262017-01-24 06:05:57 -0200240 { V4L2_PIX_FMT_YUV420, 0x0, 12,
241 ISC_PFE_CFG0_BPS_EIGHT, ISC_BAY_CFG_BGBG, ISC_RLP_CFG_MODE_YYCC,
242 ISC_DCFG_IMODE_YC420P | ISC_DCFG_YMBSIZE_BEATS8 |
243 ISC_DCFG_CMBSIZE_BEATS8, ISC_DCTRL_DVIEW_PLANAR, 0x7fb,
244 false, false },
245 { V4L2_PIX_FMT_YUV422P, 0x0, 16,
246 ISC_PFE_CFG0_BPS_EIGHT, ISC_BAY_CFG_BGBG, ISC_RLP_CFG_MODE_YYCC,
247 ISC_DCFG_IMODE_YC422P | ISC_DCFG_YMBSIZE_BEATS8 |
248 ISC_DCFG_CMBSIZE_BEATS8, ISC_DCTRL_DVIEW_PLANAR, 0x3fb,
249 false, false },
250 { V4L2_PIX_FMT_RGB565, MEDIA_BUS_FMT_RGB565_2X8_LE, 16,
251 ISC_PFE_CFG0_BPS_EIGHT, ISC_BAY_CFG_BGBG, ISC_RLP_CFG_MODE_RGB565,
252 ISC_DCFG_IMODE_PACKED16, ISC_DCTRL_DVIEW_PACKED, 0x7b,
253 false, false },
254
255 { V4L2_PIX_FMT_YUYV, MEDIA_BUS_FMT_YUYV8_2X8, 16,
256 ISC_PFE_CFG0_BPS_EIGHT, ISC_BAY_CFG_BGBG, ISC_RLP_CFG_MODE_DAT8,
257 ISC_DCFG_IMODE_PACKED8, ISC_DCTRL_DVIEW_PACKED, 0x0,
258 false, false },
Songjun Wu10626742016-08-17 03:05:27 -0300259};
260
Songjun Wu93d4a262017-01-24 06:05:57 -0200261#define GAMMA_MAX 2
262#define GAMMA_ENTRIES 64
263
264/* Gamma table with gamma 1/2.2 */
265static const u32 isc_gamma_table[GAMMA_MAX + 1][GAMMA_ENTRIES] = {
266 /* 0 --> gamma 1/1.8 */
267 { 0x65, 0x66002F, 0x950025, 0xBB0020, 0xDB001D, 0xF8001A,
268 0x1130018, 0x12B0017, 0x1420016, 0x1580014, 0x16D0013, 0x1810012,
269 0x1940012, 0x1A60012, 0x1B80011, 0x1C90010, 0x1DA0010, 0x1EA000F,
270 0x1FA000F, 0x209000F, 0x218000F, 0x227000E, 0x235000E, 0x243000E,
271 0x251000E, 0x25F000D, 0x26C000D, 0x279000D, 0x286000D, 0x293000C,
272 0x2A0000C, 0x2AC000C, 0x2B8000C, 0x2C4000C, 0x2D0000B, 0x2DC000B,
273 0x2E7000B, 0x2F3000B, 0x2FE000B, 0x309000B, 0x314000B, 0x31F000A,
274 0x32A000A, 0x334000B, 0x33F000A, 0x349000A, 0x354000A, 0x35E000A,
275 0x368000A, 0x372000A, 0x37C000A, 0x386000A, 0x3900009, 0x399000A,
276 0x3A30009, 0x3AD0009, 0x3B60009, 0x3BF000A, 0x3C90009, 0x3D20009,
277 0x3DB0009, 0x3E40009, 0x3ED0009, 0x3F60009 },
278
279 /* 1 --> gamma 1/2 */
280 { 0x7F, 0x800034, 0xB50028, 0xDE0021, 0x100001E, 0x11E001B,
281 0x1390019, 0x1520017, 0x16A0015, 0x1800014, 0x1940014, 0x1A80013,
282 0x1BB0012, 0x1CD0011, 0x1DF0010, 0x1EF0010, 0x200000F, 0x20F000F,
283 0x21F000E, 0x22D000F, 0x23C000E, 0x24A000E, 0x258000D, 0x265000D,
284 0x273000C, 0x27F000D, 0x28C000C, 0x299000C, 0x2A5000C, 0x2B1000B,
285 0x2BC000C, 0x2C8000B, 0x2D3000C, 0x2DF000B, 0x2EA000A, 0x2F5000A,
286 0x2FF000B, 0x30A000A, 0x314000B, 0x31F000A, 0x329000A, 0x333000A,
287 0x33D0009, 0x3470009, 0x350000A, 0x35A0009, 0x363000A, 0x36D0009,
288 0x3760009, 0x37F0009, 0x3880009, 0x3910009, 0x39A0009, 0x3A30009,
289 0x3AC0008, 0x3B40009, 0x3BD0008, 0x3C60008, 0x3CE0008, 0x3D60009,
290 0x3DF0008, 0x3E70008, 0x3EF0008, 0x3F70008 },
291
292 /* 2 --> gamma 1/2.2 */
293 { 0x99, 0x9B0038, 0xD4002A, 0xFF0023, 0x122001F, 0x141001B,
294 0x15D0019, 0x1760017, 0x18E0015, 0x1A30015, 0x1B80013, 0x1CC0012,
295 0x1DE0011, 0x1F00010, 0x2010010, 0x2110010, 0x221000F, 0x230000F,
296 0x23F000E, 0x24D000E, 0x25B000D, 0x269000C, 0x276000C, 0x283000C,
297 0x28F000C, 0x29B000C, 0x2A7000C, 0x2B3000B, 0x2BF000B, 0x2CA000B,
298 0x2D5000B, 0x2E0000A, 0x2EB000A, 0x2F5000A, 0x2FF000A, 0x30A000A,
299 0x3140009, 0x31E0009, 0x327000A, 0x3310009, 0x33A0009, 0x3440009,
300 0x34D0009, 0x3560009, 0x35F0009, 0x3680008, 0x3710008, 0x3790009,
301 0x3820008, 0x38A0008, 0x3930008, 0x39B0008, 0x3A30008, 0x3AB0008,
302 0x3B30008, 0x3BB0008, 0x3C30008, 0x3CB0007, 0x3D20008, 0x3DA0007,
303 0x3E20007, 0x3E90007, 0x3F00008, 0x3F80007 },
304};
305
306static unsigned int sensor_preferred = 1;
307module_param(sensor_preferred, uint, 0644);
308MODULE_PARM_DESC(sensor_preferred,
309 "Sensor is preferred to output the specified format (1-on 0-off), default 1");
310
Songjun Wu10626742016-08-17 03:05:27 -0300311static int isc_clk_enable(struct clk_hw *hw)
312{
313 struct isc_clk *isc_clk = to_isc_clk(hw);
314 u32 id = isc_clk->id;
315 struct regmap *regmap = isc_clk->regmap;
316
317 dev_dbg(isc_clk->dev, "ISC CLK: %s, div = %d, parent id = %d\n",
318 __func__, isc_clk->div, isc_clk->parent_id);
319
320 regmap_update_bits(regmap, ISC_CLKCFG,
321 ISC_CLKCFG_DIV_MASK(id) | ISC_CLKCFG_SEL_MASK(id),
322 (isc_clk->div << ISC_CLKCFG_DIV_SHIFT(id)) |
323 (isc_clk->parent_id << ISC_CLKCFG_SEL_SHIFT(id)));
324
325 regmap_write(regmap, ISC_CLKEN, ISC_CLK(id));
326
327 return 0;
328}
329
330static void isc_clk_disable(struct clk_hw *hw)
331{
332 struct isc_clk *isc_clk = to_isc_clk(hw);
333 u32 id = isc_clk->id;
334
335 regmap_write(isc_clk->regmap, ISC_CLKDIS, ISC_CLK(id));
336}
337
338static int isc_clk_is_enabled(struct clk_hw *hw)
339{
340 struct isc_clk *isc_clk = to_isc_clk(hw);
341 u32 status;
342
343 regmap_read(isc_clk->regmap, ISC_CLKSR, &status);
344
345 return status & ISC_CLK(isc_clk->id) ? 1 : 0;
346}
347
348static unsigned long
349isc_clk_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
350{
351 struct isc_clk *isc_clk = to_isc_clk(hw);
352
353 return DIV_ROUND_CLOSEST(parent_rate, isc_clk->div + 1);
354}
355
356static int isc_clk_determine_rate(struct clk_hw *hw,
357 struct clk_rate_request *req)
358{
359 struct isc_clk *isc_clk = to_isc_clk(hw);
360 long best_rate = -EINVAL;
361 int best_diff = -1;
362 unsigned int i, div;
363
364 for (i = 0; i < clk_hw_get_num_parents(hw); i++) {
365 struct clk_hw *parent;
366 unsigned long parent_rate;
367
368 parent = clk_hw_get_parent_by_index(hw, i);
369 if (!parent)
370 continue;
371
372 parent_rate = clk_hw_get_rate(parent);
373 if (!parent_rate)
374 continue;
375
376 for (div = 1; div < ISC_CLK_MAX_DIV + 2; div++) {
377 unsigned long rate;
378 int diff;
379
380 rate = DIV_ROUND_CLOSEST(parent_rate, div);
381 diff = abs(req->rate - rate);
382
383 if (best_diff < 0 || best_diff > diff) {
384 best_rate = rate;
385 best_diff = diff;
386 req->best_parent_rate = parent_rate;
387 req->best_parent_hw = parent;
388 }
389
390 if (!best_diff || rate < req->rate)
391 break;
392 }
393
394 if (!best_diff)
395 break;
396 }
397
398 dev_dbg(isc_clk->dev,
399 "ISC CLK: %s, best_rate = %ld, parent clk: %s @ %ld\n",
400 __func__, best_rate,
401 __clk_get_name((req->best_parent_hw)->clk),
402 req->best_parent_rate);
403
404 if (best_rate < 0)
405 return best_rate;
406
407 req->rate = best_rate;
408
409 return 0;
410}
411
412static int isc_clk_set_parent(struct clk_hw *hw, u8 index)
413{
414 struct isc_clk *isc_clk = to_isc_clk(hw);
415
416 if (index >= clk_hw_get_num_parents(hw))
417 return -EINVAL;
418
419 isc_clk->parent_id = index;
420
421 return 0;
422}
423
424static u8 isc_clk_get_parent(struct clk_hw *hw)
425{
426 struct isc_clk *isc_clk = to_isc_clk(hw);
427
428 return isc_clk->parent_id;
429}
430
431static int isc_clk_set_rate(struct clk_hw *hw,
432 unsigned long rate,
433 unsigned long parent_rate)
434{
435 struct isc_clk *isc_clk = to_isc_clk(hw);
436 u32 div;
437
438 if (!rate)
439 return -EINVAL;
440
441 div = DIV_ROUND_CLOSEST(parent_rate, rate);
442 if (div > (ISC_CLK_MAX_DIV + 1) || !div)
443 return -EINVAL;
444
445 isc_clk->div = div - 1;
446
447 return 0;
448}
449
450static const struct clk_ops isc_clk_ops = {
451 .enable = isc_clk_enable,
452 .disable = isc_clk_disable,
453 .is_enabled = isc_clk_is_enabled,
454 .recalc_rate = isc_clk_recalc_rate,
455 .determine_rate = isc_clk_determine_rate,
456 .set_parent = isc_clk_set_parent,
457 .get_parent = isc_clk_get_parent,
458 .set_rate = isc_clk_set_rate,
459};
460
461static int isc_clk_register(struct isc_device *isc, unsigned int id)
462{
463 struct regmap *regmap = isc->regmap;
464 struct device_node *np = isc->dev->of_node;
465 struct isc_clk *isc_clk;
466 struct clk_init_data init;
467 const char *clk_name = np->name;
468 const char *parent_names[3];
469 int num_parents;
470
471 num_parents = of_clk_get_parent_count(np);
472 if (num_parents < 1 || num_parents > 3)
473 return -EINVAL;
474
475 if (num_parents > 2 && id == ISC_ISPCK)
476 num_parents = 2;
477
478 of_clk_parent_fill(np, parent_names, num_parents);
479
480 if (id == ISC_MCK)
481 of_property_read_string(np, "clock-output-names", &clk_name);
482 else
483 clk_name = "isc-ispck";
484
485 init.parent_names = parent_names;
486 init.num_parents = num_parents;
487 init.name = clk_name;
488 init.ops = &isc_clk_ops;
489 init.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE;
490
491 isc_clk = &isc->isc_clks[id];
492 isc_clk->hw.init = &init;
493 isc_clk->regmap = regmap;
494 isc_clk->id = id;
495 isc_clk->dev = isc->dev;
496
497 isc_clk->clk = clk_register(isc->dev, &isc_clk->hw);
498 if (IS_ERR(isc_clk->clk)) {
499 dev_err(isc->dev, "%s: clock register fail\n", clk_name);
500 return PTR_ERR(isc_clk->clk);
501 } else if (id == ISC_MCK)
502 of_clk_add_provider(np, of_clk_src_simple_get, isc_clk->clk);
503
504 return 0;
505}
506
507static int isc_clk_init(struct isc_device *isc)
508{
509 unsigned int i;
510 int ret;
511
512 for (i = 0; i < ARRAY_SIZE(isc->isc_clks); i++)
513 isc->isc_clks[i].clk = ERR_PTR(-EINVAL);
514
515 for (i = 0; i < ARRAY_SIZE(isc->isc_clks); i++) {
516 ret = isc_clk_register(isc, i);
517 if (ret)
518 return ret;
519 }
520
521 return 0;
522}
523
524static void isc_clk_cleanup(struct isc_device *isc)
525{
526 unsigned int i;
527
528 of_clk_del_provider(isc->dev->of_node);
529
530 for (i = 0; i < ARRAY_SIZE(isc->isc_clks); i++) {
531 struct isc_clk *isc_clk = &isc->isc_clks[i];
532
533 if (!IS_ERR(isc_clk->clk))
534 clk_unregister(isc_clk->clk);
535 }
536}
537
538static int isc_queue_setup(struct vb2_queue *vq,
539 unsigned int *nbuffers, unsigned int *nplanes,
540 unsigned int sizes[], struct device *alloc_devs[])
541{
542 struct isc_device *isc = vb2_get_drv_priv(vq);
543 unsigned int size = isc->fmt.fmt.pix.sizeimage;
544
545 if (*nplanes)
546 return sizes[0] < size ? -EINVAL : 0;
547
548 *nplanes = 1;
549 sizes[0] = size;
550
551 return 0;
552}
553
554static int isc_buffer_prepare(struct vb2_buffer *vb)
555{
556 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
557 struct isc_device *isc = vb2_get_drv_priv(vb->vb2_queue);
558 unsigned long size = isc->fmt.fmt.pix.sizeimage;
559
560 if (vb2_plane_size(vb, 0) < size) {
561 v4l2_err(&isc->v4l2_dev, "buffer too small (%lu < %lu)\n",
562 vb2_plane_size(vb, 0), size);
563 return -EINVAL;
564 }
565
566 vb2_set_plane_payload(vb, 0, size);
567
568 vbuf->field = isc->fmt.fmt.pix.field;
569
570 return 0;
571}
572
Songjun Wu93d4a262017-01-24 06:05:57 -0200573static inline bool sensor_is_preferred(const struct isc_format *isc_fmt)
Songjun Wu10626742016-08-17 03:05:27 -0300574{
Songjun Wu93d4a262017-01-24 06:05:57 -0200575 return (sensor_preferred && isc_fmt->sd_support) ||
576 !isc_fmt->isc_support;
577}
Songjun Wu10626742016-08-17 03:05:27 -0300578
Songjun Wu93d4a262017-01-24 06:05:57 -0200579static void isc_start_dma(struct isc_device *isc)
580{
581 struct regmap *regmap = isc->regmap;
582 struct v4l2_pix_format *pixfmt = &isc->fmt.fmt.pix;
583 u32 sizeimage = pixfmt->sizeimage;
584 u32 dctrl_dview;
585 dma_addr_t addr0;
Songjun Wu10626742016-08-17 03:05:27 -0300586
Songjun Wu93d4a262017-01-24 06:05:57 -0200587 addr0 = vb2_dma_contig_plane_dma_addr(&isc->cur_frm->vb.vb2_buf, 0);
588 regmap_write(regmap, ISC_DAD0, addr0);
589
590 switch (pixfmt->pixelformat) {
591 case V4L2_PIX_FMT_YUV420:
592 regmap_write(regmap, ISC_DAD1, addr0 + (sizeimage * 2) / 3);
593 regmap_write(regmap, ISC_DAD2, addr0 + (sizeimage * 5) / 6);
594 break;
595 case V4L2_PIX_FMT_YUV422P:
596 regmap_write(regmap, ISC_DAD1, addr0 + sizeimage / 2);
597 regmap_write(regmap, ISC_DAD2, addr0 + (sizeimage * 3) / 4);
598 break;
599 default:
600 break;
601 }
602
603 if (sensor_is_preferred(isc->current_fmt))
604 dctrl_dview = ISC_DCTRL_DVIEW_PACKED;
605 else
606 dctrl_dview = isc->current_fmt->reg_dctrl_dview;
607
608 regmap_write(regmap, ISC_DCTRL, dctrl_dview | ISC_DCTRL_IE_IS);
Songjun Wu10626742016-08-17 03:05:27 -0300609 regmap_write(regmap, ISC_CTRLEN, ISC_CTRL_CAPTURE);
610}
611
612static void isc_set_pipeline(struct isc_device *isc, u32 pipeline)
613{
Songjun Wu93d4a262017-01-24 06:05:57 -0200614 struct regmap *regmap = isc->regmap;
615 struct isc_ctrls *ctrls = &isc->ctrls;
616 u32 val, bay_cfg;
617 const u32 *gamma;
Songjun Wu10626742016-08-17 03:05:27 -0300618 unsigned int i;
619
Songjun Wu93d4a262017-01-24 06:05:57 -0200620 /* WB-->CFA-->CC-->GAM-->CSC-->CBC-->SUB422-->SUB420 */
Songjun Wu10626742016-08-17 03:05:27 -0300621 for (i = 0; i < ISC_PIPE_LINE_NODE_NUM; i++) {
622 val = pipeline & BIT(i) ? 1 : 0;
623 regmap_field_write(isc->pipeline[i], val);
624 }
Songjun Wu93d4a262017-01-24 06:05:57 -0200625
626 if (!pipeline)
627 return;
628
629 bay_cfg = isc->raw_fmt->reg_bay_cfg;
630
631 regmap_write(regmap, ISC_WB_CFG, bay_cfg);
632 regmap_write(regmap, ISC_WB_O_RGR, 0x0);
633 regmap_write(regmap, ISC_WB_O_BGR, 0x0);
634 regmap_write(regmap, ISC_WB_G_RGR, ctrls->r_gain | (0x1 << 25));
635 regmap_write(regmap, ISC_WB_G_BGR, ctrls->b_gain | (0x1 << 25));
636
637 regmap_write(regmap, ISC_CFA_CFG, bay_cfg | ISC_CFA_CFG_EITPOL);
638
639 gamma = &isc_gamma_table[ctrls->gamma_index][0];
640 regmap_bulk_write(regmap, ISC_GAM_BENTRY, gamma, GAMMA_ENTRIES);
641 regmap_bulk_write(regmap, ISC_GAM_GENTRY, gamma, GAMMA_ENTRIES);
642 regmap_bulk_write(regmap, ISC_GAM_RENTRY, gamma, GAMMA_ENTRIES);
643
644 /* Convert RGB to YUV */
645 regmap_write(regmap, ISC_CSC_YR_YG, 0x42 | (0x81 << 16));
646 regmap_write(regmap, ISC_CSC_YB_OY, 0x19 | (0x10 << 16));
647 regmap_write(regmap, ISC_CSC_CBR_CBG, 0xFDA | (0xFB6 << 16));
648 regmap_write(regmap, ISC_CSC_CBB_OCB, 0x70 | (0x80 << 16));
649 regmap_write(regmap, ISC_CSC_CRR_CRG, 0x70 | (0xFA2 << 16));
650 regmap_write(regmap, ISC_CSC_CRB_OCR, 0xFEE | (0x80 << 16));
651
652 regmap_write(regmap, ISC_CBC_BRIGHT, ctrls->brightness);
653 regmap_write(regmap, ISC_CBC_CONTRAST, ctrls->contrast);
654}
655
656static int isc_update_profile(struct isc_device *isc)
657{
658 struct regmap *regmap = isc->regmap;
659 u32 sr;
660 int counter = 100;
661
662 regmap_write(regmap, ISC_CTRLEN, ISC_CTRL_UPPRO);
663
664 regmap_read(regmap, ISC_CTRLSR, &sr);
665 while ((sr & ISC_CTRL_UPPRO) && counter--) {
666 usleep_range(1000, 2000);
667 regmap_read(regmap, ISC_CTRLSR, &sr);
668 }
669
670 if (counter < 0) {
671 v4l2_warn(&isc->v4l2_dev, "Time out to update profie\n");
672 return -ETIMEDOUT;
673 }
674
675 return 0;
676}
677
678static void isc_set_histogram(struct isc_device *isc)
679{
680 struct regmap *regmap = isc->regmap;
681 struct isc_ctrls *ctrls = &isc->ctrls;
682
683 if (ctrls->awb && (ctrls->hist_stat != HIST_ENABLED)) {
684 regmap_write(regmap, ISC_HIS_CFG, ISC_HIS_CFG_MODE_R |
685 (isc->raw_fmt->reg_bay_cfg << ISC_HIS_CFG_BAYSEL_SHIFT) |
686 ISC_HIS_CFG_RAR);
687 regmap_write(regmap, ISC_HIS_CTRL, ISC_HIS_CTRL_EN);
688 regmap_write(regmap, ISC_INTEN, ISC_INT_HISDONE);
689 ctrls->hist_id = ISC_HIS_CFG_MODE_R;
690 isc_update_profile(isc);
691 regmap_write(regmap, ISC_CTRLEN, ISC_CTRL_HISREQ);
692
693 ctrls->hist_stat = HIST_ENABLED;
694 } else if (!ctrls->awb && (ctrls->hist_stat != HIST_DISABLED)) {
695 regmap_write(regmap, ISC_INTDIS, ISC_INT_HISDONE);
696 regmap_write(regmap, ISC_HIS_CTRL, ISC_HIS_CTRL_DIS);
697
698 ctrls->hist_stat = HIST_DISABLED;
699 }
700}
701
702static inline void isc_get_param(const struct isc_format *fmt,
703 u32 *rlp_mode, u32 *dcfg_imode)
704{
705 switch (fmt->fourcc) {
706 case V4L2_PIX_FMT_SBGGR10:
707 case V4L2_PIX_FMT_SGBRG10:
708 case V4L2_PIX_FMT_SGRBG10:
709 case V4L2_PIX_FMT_SRGGB10:
710 case V4L2_PIX_FMT_SBGGR12:
711 case V4L2_PIX_FMT_SGBRG12:
712 case V4L2_PIX_FMT_SGRBG12:
713 case V4L2_PIX_FMT_SRGGB12:
714 *rlp_mode = fmt->reg_rlp_mode;
715 *dcfg_imode = fmt->reg_dcfg_imode;
716 break;
717 default:
718 *rlp_mode = ISC_RLP_CFG_MODE_DAT8;
719 *dcfg_imode = ISC_DCFG_IMODE_PACKED8;
720 break;
721 }
Songjun Wu10626742016-08-17 03:05:27 -0300722}
723
724static int isc_configure(struct isc_device *isc)
725{
726 struct regmap *regmap = isc->regmap;
727 const struct isc_format *current_fmt = isc->current_fmt;
728 struct isc_subdev_entity *subdev = isc->current_subdev;
Songjun Wu93d4a262017-01-24 06:05:57 -0200729 u32 pfe_cfg0, rlp_mode, dcfg_imode, mask, pipeline;
Songjun Wu10626742016-08-17 03:05:27 -0300730
Songjun Wu93d4a262017-01-24 06:05:57 -0200731 if (sensor_is_preferred(current_fmt)) {
732 pfe_cfg0 = current_fmt->reg_bps;
733 pipeline = 0x0;
734 isc_get_param(current_fmt, &rlp_mode, &dcfg_imode);
735 isc->ctrls.hist_stat = HIST_INIT;
736 } else {
737 pfe_cfg0 = isc->raw_fmt->reg_bps;
738 pipeline = current_fmt->pipeline;
739 rlp_mode = current_fmt->reg_rlp_mode;
740 dcfg_imode = current_fmt->reg_dcfg_imode;
741 }
742
743 pfe_cfg0 |= subdev->pfe_cfg0 | ISC_PFE_CFG0_MODE_PROGRESSIVE;
Songjun Wu10626742016-08-17 03:05:27 -0300744 mask = ISC_PFE_CFG0_BPS_MASK | ISC_PFE_CFG0_HPOL_LOW |
745 ISC_PFE_CFG0_VPOL_LOW | ISC_PFE_CFG0_PPOL_LOW |
746 ISC_PFE_CFG0_MODE_MASK;
747
Songjun Wu93d4a262017-01-24 06:05:57 -0200748 regmap_update_bits(regmap, ISC_PFE_CFG0, mask, pfe_cfg0);
Songjun Wu10626742016-08-17 03:05:27 -0300749
750 regmap_update_bits(regmap, ISC_RLP_CFG, ISC_RLP_CFG_MODE_MASK,
Songjun Wu93d4a262017-01-24 06:05:57 -0200751 rlp_mode);
Songjun Wu10626742016-08-17 03:05:27 -0300752
Songjun Wu93d4a262017-01-24 06:05:57 -0200753 regmap_update_bits(regmap, ISC_DCFG, ISC_DCFG_IMODE_MASK, dcfg_imode);
Songjun Wu10626742016-08-17 03:05:27 -0300754
Songjun Wu93d4a262017-01-24 06:05:57 -0200755 /* Set the pipeline */
756 isc_set_pipeline(isc, pipeline);
757
758 if (pipeline)
759 isc_set_histogram(isc);
Songjun Wu10626742016-08-17 03:05:27 -0300760
761 /* Update profile */
Songjun Wu93d4a262017-01-24 06:05:57 -0200762 return isc_update_profile(isc);
Songjun Wu10626742016-08-17 03:05:27 -0300763}
764
765static int isc_start_streaming(struct vb2_queue *vq, unsigned int count)
766{
767 struct isc_device *isc = vb2_get_drv_priv(vq);
768 struct regmap *regmap = isc->regmap;
769 struct isc_buffer *buf;
770 unsigned long flags;
771 int ret;
Songjun Wu10626742016-08-17 03:05:27 -0300772
773 /* Enable stream on the sub device */
774 ret = v4l2_subdev_call(isc->current_subdev->sd, video, s_stream, 1);
775 if (ret && ret != -ENOIOCTLCMD) {
776 v4l2_err(&isc->v4l2_dev, "stream on failed in subdev\n");
777 goto err_start_stream;
778 }
779
780 pm_runtime_get_sync(isc->dev);
781
Songjun Wu10626742016-08-17 03:05:27 -0300782 ret = isc_configure(isc);
783 if (unlikely(ret))
784 goto err_configure;
785
786 /* Enable DMA interrupt */
787 regmap_write(regmap, ISC_INTEN, ISC_INT_DDONE);
788
789 spin_lock_irqsave(&isc->dma_queue_lock, flags);
790
791 isc->sequence = 0;
792 isc->stop = false;
793 reinit_completion(&isc->comp);
794
795 isc->cur_frm = list_first_entry(&isc->dma_queue,
796 struct isc_buffer, list);
797 list_del(&isc->cur_frm->list);
798
Songjun Wu93d4a262017-01-24 06:05:57 -0200799 isc_start_dma(isc);
Songjun Wu10626742016-08-17 03:05:27 -0300800
801 spin_unlock_irqrestore(&isc->dma_queue_lock, flags);
802
803 return 0;
804
805err_configure:
806 pm_runtime_put_sync(isc->dev);
807
808 v4l2_subdev_call(isc->current_subdev->sd, video, s_stream, 0);
809
810err_start_stream:
811 spin_lock_irqsave(&isc->dma_queue_lock, flags);
812 list_for_each_entry(buf, &isc->dma_queue, list)
813 vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_QUEUED);
814 INIT_LIST_HEAD(&isc->dma_queue);
815 spin_unlock_irqrestore(&isc->dma_queue_lock, flags);
816
817 return ret;
818}
819
820static void isc_stop_streaming(struct vb2_queue *vq)
821{
822 struct isc_device *isc = vb2_get_drv_priv(vq);
823 unsigned long flags;
824 struct isc_buffer *buf;
825 int ret;
826
827 isc->stop = true;
828
829 /* Wait until the end of the current frame */
830 if (isc->cur_frm && !wait_for_completion_timeout(&isc->comp, 5 * HZ))
831 v4l2_err(&isc->v4l2_dev,
832 "Timeout waiting for end of the capture\n");
833
834 /* Disable DMA interrupt */
835 regmap_write(isc->regmap, ISC_INTDIS, ISC_INT_DDONE);
836
837 pm_runtime_put_sync(isc->dev);
838
839 /* Disable stream on the sub device */
840 ret = v4l2_subdev_call(isc->current_subdev->sd, video, s_stream, 0);
841 if (ret && ret != -ENOIOCTLCMD)
842 v4l2_err(&isc->v4l2_dev, "stream off failed in subdev\n");
843
844 /* Release all active buffers */
845 spin_lock_irqsave(&isc->dma_queue_lock, flags);
846 if (unlikely(isc->cur_frm)) {
847 vb2_buffer_done(&isc->cur_frm->vb.vb2_buf,
848 VB2_BUF_STATE_ERROR);
849 isc->cur_frm = NULL;
850 }
851 list_for_each_entry(buf, &isc->dma_queue, list)
852 vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
853 INIT_LIST_HEAD(&isc->dma_queue);
854 spin_unlock_irqrestore(&isc->dma_queue_lock, flags);
855}
856
857static void isc_buffer_queue(struct vb2_buffer *vb)
858{
859 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
860 struct isc_buffer *buf = container_of(vbuf, struct isc_buffer, vb);
861 struct isc_device *isc = vb2_get_drv_priv(vb->vb2_queue);
862 unsigned long flags;
863
864 spin_lock_irqsave(&isc->dma_queue_lock, flags);
Songjun Wufa8bbe02016-09-28 02:28:57 -0300865 if (!isc->cur_frm && list_empty(&isc->dma_queue) &&
866 vb2_is_streaming(vb->vb2_queue)) {
867 isc->cur_frm = buf;
Songjun Wu93d4a262017-01-24 06:05:57 -0200868 isc_start_dma(isc);
Songjun Wufa8bbe02016-09-28 02:28:57 -0300869 } else
870 list_add_tail(&buf->list, &isc->dma_queue);
Songjun Wu10626742016-08-17 03:05:27 -0300871 spin_unlock_irqrestore(&isc->dma_queue_lock, flags);
872}
873
874static struct vb2_ops isc_vb2_ops = {
875 .queue_setup = isc_queue_setup,
876 .wait_prepare = vb2_ops_wait_prepare,
877 .wait_finish = vb2_ops_wait_finish,
878 .buf_prepare = isc_buffer_prepare,
879 .start_streaming = isc_start_streaming,
880 .stop_streaming = isc_stop_streaming,
881 .buf_queue = isc_buffer_queue,
882};
883
884static int isc_querycap(struct file *file, void *priv,
885 struct v4l2_capability *cap)
886{
887 struct isc_device *isc = video_drvdata(file);
888
889 strcpy(cap->driver, ATMEL_ISC_NAME);
890 strcpy(cap->card, "Atmel Image Sensor Controller");
891 snprintf(cap->bus_info, sizeof(cap->bus_info),
892 "platform:%s", isc->v4l2_dev.name);
893
894 return 0;
895}
896
897static int isc_enum_fmt_vid_cap(struct file *file, void *priv,
898 struct v4l2_fmtdesc *f)
899{
900 struct isc_device *isc = video_drvdata(file);
901 u32 index = f->index;
902
903 if (index >= isc->num_user_formats)
904 return -EINVAL;
905
906 f->pixelformat = isc->user_formats[index]->fourcc;
907
908 return 0;
909}
910
911static int isc_g_fmt_vid_cap(struct file *file, void *priv,
912 struct v4l2_format *fmt)
913{
914 struct isc_device *isc = video_drvdata(file);
915
916 *fmt = isc->fmt;
917
918 return 0;
919}
920
921static struct isc_format *find_format_by_fourcc(struct isc_device *isc,
922 unsigned int fourcc)
923{
924 unsigned int num_formats = isc->num_user_formats;
925 struct isc_format *fmt;
926 unsigned int i;
927
928 for (i = 0; i < num_formats; i++) {
929 fmt = isc->user_formats[i];
930 if (fmt->fourcc == fourcc)
931 return fmt;
932 }
933
934 return NULL;
935}
936
937static int isc_try_fmt(struct isc_device *isc, struct v4l2_format *f,
Songjun Wu93d4a262017-01-24 06:05:57 -0200938 struct isc_format **current_fmt, u32 *code)
Songjun Wu10626742016-08-17 03:05:27 -0300939{
940 struct isc_format *isc_fmt;
941 struct v4l2_pix_format *pixfmt = &f->fmt.pix;
942 struct v4l2_subdev_format format = {
943 .which = V4L2_SUBDEV_FORMAT_TRY,
944 };
Songjun Wu93d4a262017-01-24 06:05:57 -0200945 u32 mbus_code;
Songjun Wu10626742016-08-17 03:05:27 -0300946 int ret;
947
948 if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
949 return -EINVAL;
950
951 isc_fmt = find_format_by_fourcc(isc, pixfmt->pixelformat);
952 if (!isc_fmt) {
953 v4l2_warn(&isc->v4l2_dev, "Format 0x%x not found\n",
954 pixfmt->pixelformat);
955 isc_fmt = isc->user_formats[isc->num_user_formats - 1];
956 pixfmt->pixelformat = isc_fmt->fourcc;
957 }
958
959 /* Limit to Atmel ISC hardware capabilities */
960 if (pixfmt->width > ISC_MAX_SUPPORT_WIDTH)
961 pixfmt->width = ISC_MAX_SUPPORT_WIDTH;
962 if (pixfmt->height > ISC_MAX_SUPPORT_HEIGHT)
963 pixfmt->height = ISC_MAX_SUPPORT_HEIGHT;
964
Songjun Wu93d4a262017-01-24 06:05:57 -0200965 if (sensor_is_preferred(isc_fmt))
966 mbus_code = isc_fmt->mbus_code;
967 else
968 mbus_code = isc->raw_fmt->mbus_code;
969
970 v4l2_fill_mbus_format(&format.format, pixfmt, mbus_code);
Songjun Wu10626742016-08-17 03:05:27 -0300971 ret = v4l2_subdev_call(isc->current_subdev->sd, pad, set_fmt,
972 isc->current_subdev->config, &format);
973 if (ret < 0)
974 return ret;
975
976 v4l2_fill_pix_format(pixfmt, &format.format);
977
978 pixfmt->field = V4L2_FIELD_NONE;
Songjun Wu93d4a262017-01-24 06:05:57 -0200979 pixfmt->bytesperline = (pixfmt->width * isc_fmt->bpp) >> 3;
Songjun Wu10626742016-08-17 03:05:27 -0300980 pixfmt->sizeimage = pixfmt->bytesperline * pixfmt->height;
981
982 if (current_fmt)
983 *current_fmt = isc_fmt;
984
Songjun Wu93d4a262017-01-24 06:05:57 -0200985 if (code)
986 *code = mbus_code;
987
Songjun Wu10626742016-08-17 03:05:27 -0300988 return 0;
989}
990
991static int isc_set_fmt(struct isc_device *isc, struct v4l2_format *f)
992{
993 struct v4l2_subdev_format format = {
994 .which = V4L2_SUBDEV_FORMAT_ACTIVE,
995 };
996 struct isc_format *current_fmt;
Songjun Wu93d4a262017-01-24 06:05:57 -0200997 u32 mbus_code;
Songjun Wu10626742016-08-17 03:05:27 -0300998 int ret;
999
Songjun Wu93d4a262017-01-24 06:05:57 -02001000 ret = isc_try_fmt(isc, f, &current_fmt, &mbus_code);
Songjun Wu10626742016-08-17 03:05:27 -03001001 if (ret)
1002 return ret;
1003
Songjun Wu93d4a262017-01-24 06:05:57 -02001004 v4l2_fill_mbus_format(&format.format, &f->fmt.pix, mbus_code);
Songjun Wu10626742016-08-17 03:05:27 -03001005 ret = v4l2_subdev_call(isc->current_subdev->sd, pad,
1006 set_fmt, NULL, &format);
1007 if (ret < 0)
1008 return ret;
1009
1010 isc->fmt = *f;
1011 isc->current_fmt = current_fmt;
1012
1013 return 0;
1014}
1015
1016static int isc_s_fmt_vid_cap(struct file *file, void *priv,
1017 struct v4l2_format *f)
1018{
1019 struct isc_device *isc = video_drvdata(file);
1020
1021 if (vb2_is_streaming(&isc->vb2_vidq))
1022 return -EBUSY;
1023
1024 return isc_set_fmt(isc, f);
1025}
1026
1027static int isc_try_fmt_vid_cap(struct file *file, void *priv,
1028 struct v4l2_format *f)
1029{
1030 struct isc_device *isc = video_drvdata(file);
1031
Songjun Wu93d4a262017-01-24 06:05:57 -02001032 return isc_try_fmt(isc, f, NULL, NULL);
Songjun Wu10626742016-08-17 03:05:27 -03001033}
1034
1035static int isc_enum_input(struct file *file, void *priv,
1036 struct v4l2_input *inp)
1037{
1038 if (inp->index != 0)
1039 return -EINVAL;
1040
1041 inp->type = V4L2_INPUT_TYPE_CAMERA;
1042 inp->std = 0;
1043 strcpy(inp->name, "Camera");
1044
1045 return 0;
1046}
1047
1048static int isc_g_input(struct file *file, void *priv, unsigned int *i)
1049{
1050 *i = 0;
1051
1052 return 0;
1053}
1054
1055static int isc_s_input(struct file *file, void *priv, unsigned int i)
1056{
1057 if (i > 0)
1058 return -EINVAL;
1059
1060 return 0;
1061}
1062
1063static int isc_g_parm(struct file *file, void *fh, struct v4l2_streamparm *a)
1064{
1065 struct isc_device *isc = video_drvdata(file);
1066
1067 if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1068 return -EINVAL;
1069
1070 return v4l2_subdev_call(isc->current_subdev->sd, video, g_parm, a);
1071}
1072
1073static int isc_s_parm(struct file *file, void *fh, struct v4l2_streamparm *a)
1074{
1075 struct isc_device *isc = video_drvdata(file);
1076
1077 if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1078 return -EINVAL;
1079
1080 return v4l2_subdev_call(isc->current_subdev->sd, video, s_parm, a);
1081}
1082
1083static int isc_enum_framesizes(struct file *file, void *fh,
1084 struct v4l2_frmsizeenum *fsize)
1085{
1086 struct isc_device *isc = video_drvdata(file);
1087 const struct isc_format *isc_fmt;
1088 struct v4l2_subdev_frame_size_enum fse = {
1089 .index = fsize->index,
1090 .which = V4L2_SUBDEV_FORMAT_ACTIVE,
1091 };
1092 int ret;
1093
1094 isc_fmt = find_format_by_fourcc(isc, fsize->pixel_format);
1095 if (!isc_fmt)
1096 return -EINVAL;
1097
Songjun Wu93d4a262017-01-24 06:05:57 -02001098 if (sensor_is_preferred(isc_fmt))
1099 fse.code = isc_fmt->mbus_code;
1100 else
1101 fse.code = isc->raw_fmt->mbus_code;
Songjun Wu10626742016-08-17 03:05:27 -03001102
1103 ret = v4l2_subdev_call(isc->current_subdev->sd, pad, enum_frame_size,
1104 NULL, &fse);
1105 if (ret)
1106 return ret;
1107
1108 fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
1109 fsize->discrete.width = fse.max_width;
1110 fsize->discrete.height = fse.max_height;
1111
1112 return 0;
1113}
1114
1115static int isc_enum_frameintervals(struct file *file, void *fh,
1116 struct v4l2_frmivalenum *fival)
1117{
1118 struct isc_device *isc = video_drvdata(file);
1119 const struct isc_format *isc_fmt;
1120 struct v4l2_subdev_frame_interval_enum fie = {
1121 .index = fival->index,
1122 .width = fival->width,
1123 .height = fival->height,
1124 .which = V4L2_SUBDEV_FORMAT_ACTIVE,
1125 };
1126 int ret;
1127
1128 isc_fmt = find_format_by_fourcc(isc, fival->pixel_format);
1129 if (!isc_fmt)
1130 return -EINVAL;
1131
Songjun Wu93d4a262017-01-24 06:05:57 -02001132 if (sensor_is_preferred(isc_fmt))
1133 fie.code = isc_fmt->mbus_code;
1134 else
1135 fie.code = isc->raw_fmt->mbus_code;
Songjun Wu10626742016-08-17 03:05:27 -03001136
1137 ret = v4l2_subdev_call(isc->current_subdev->sd, pad,
1138 enum_frame_interval, NULL, &fie);
1139 if (ret)
1140 return ret;
1141
1142 fival->type = V4L2_FRMIVAL_TYPE_DISCRETE;
1143 fival->discrete = fie.interval;
1144
1145 return 0;
1146}
1147
1148static const struct v4l2_ioctl_ops isc_ioctl_ops = {
1149 .vidioc_querycap = isc_querycap,
1150 .vidioc_enum_fmt_vid_cap = isc_enum_fmt_vid_cap,
1151 .vidioc_g_fmt_vid_cap = isc_g_fmt_vid_cap,
1152 .vidioc_s_fmt_vid_cap = isc_s_fmt_vid_cap,
1153 .vidioc_try_fmt_vid_cap = isc_try_fmt_vid_cap,
1154
1155 .vidioc_enum_input = isc_enum_input,
1156 .vidioc_g_input = isc_g_input,
1157 .vidioc_s_input = isc_s_input,
1158
1159 .vidioc_reqbufs = vb2_ioctl_reqbufs,
1160 .vidioc_querybuf = vb2_ioctl_querybuf,
1161 .vidioc_qbuf = vb2_ioctl_qbuf,
1162 .vidioc_expbuf = vb2_ioctl_expbuf,
1163 .vidioc_dqbuf = vb2_ioctl_dqbuf,
1164 .vidioc_create_bufs = vb2_ioctl_create_bufs,
1165 .vidioc_prepare_buf = vb2_ioctl_prepare_buf,
1166 .vidioc_streamon = vb2_ioctl_streamon,
1167 .vidioc_streamoff = vb2_ioctl_streamoff,
1168
1169 .vidioc_g_parm = isc_g_parm,
1170 .vidioc_s_parm = isc_s_parm,
1171 .vidioc_enum_framesizes = isc_enum_framesizes,
1172 .vidioc_enum_frameintervals = isc_enum_frameintervals,
Songjun Wu93d4a262017-01-24 06:05:57 -02001173
1174 .vidioc_log_status = v4l2_ctrl_log_status,
1175 .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
1176 .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
Songjun Wu10626742016-08-17 03:05:27 -03001177};
1178
1179static int isc_open(struct file *file)
1180{
1181 struct isc_device *isc = video_drvdata(file);
1182 struct v4l2_subdev *sd = isc->current_subdev->sd;
1183 int ret;
1184
1185 if (mutex_lock_interruptible(&isc->lock))
1186 return -ERESTARTSYS;
1187
1188 ret = v4l2_fh_open(file);
1189 if (ret < 0)
1190 goto unlock;
1191
1192 if (!v4l2_fh_is_singular_file(file))
1193 goto unlock;
1194
1195 ret = v4l2_subdev_call(sd, core, s_power, 1);
Songjun Wu4540e0a2016-09-12 04:47:24 -03001196 if (ret < 0 && ret != -ENOIOCTLCMD) {
Songjun Wu10626742016-08-17 03:05:27 -03001197 v4l2_fh_release(file);
Songjun Wu4540e0a2016-09-12 04:47:24 -03001198 goto unlock;
1199 }
1200
1201 ret = isc_set_fmt(isc, &isc->fmt);
1202 if (ret) {
1203 v4l2_subdev_call(sd, core, s_power, 0);
1204 v4l2_fh_release(file);
1205 }
Songjun Wu10626742016-08-17 03:05:27 -03001206
1207unlock:
1208 mutex_unlock(&isc->lock);
1209 return ret;
1210}
1211
1212static int isc_release(struct file *file)
1213{
1214 struct isc_device *isc = video_drvdata(file);
1215 struct v4l2_subdev *sd = isc->current_subdev->sd;
1216 bool fh_singular;
1217 int ret;
1218
1219 mutex_lock(&isc->lock);
1220
1221 fh_singular = v4l2_fh_is_singular_file(file);
1222
1223 ret = _vb2_fop_release(file, NULL);
1224
1225 if (fh_singular)
1226 v4l2_subdev_call(sd, core, s_power, 0);
1227
1228 mutex_unlock(&isc->lock);
1229
1230 return ret;
1231}
1232
1233static const struct v4l2_file_operations isc_fops = {
1234 .owner = THIS_MODULE,
1235 .open = isc_open,
1236 .release = isc_release,
1237 .unlocked_ioctl = video_ioctl2,
1238 .read = vb2_fop_read,
1239 .mmap = vb2_fop_mmap,
1240 .poll = vb2_fop_poll,
1241};
1242
1243static irqreturn_t isc_interrupt(int irq, void *dev_id)
1244{
1245 struct isc_device *isc = (struct isc_device *)dev_id;
1246 struct regmap *regmap = isc->regmap;
1247 u32 isc_intsr, isc_intmask, pending;
1248 irqreturn_t ret = IRQ_NONE;
1249
Songjun Wu10626742016-08-17 03:05:27 -03001250 regmap_read(regmap, ISC_INTSR, &isc_intsr);
1251 regmap_read(regmap, ISC_INTMASK, &isc_intmask);
1252
1253 pending = isc_intsr & isc_intmask;
1254
1255 if (likely(pending & ISC_INT_DDONE)) {
Songjun Wu93d4a262017-01-24 06:05:57 -02001256 spin_lock(&isc->dma_queue_lock);
Songjun Wu10626742016-08-17 03:05:27 -03001257 if (isc->cur_frm) {
1258 struct vb2_v4l2_buffer *vbuf = &isc->cur_frm->vb;
1259 struct vb2_buffer *vb = &vbuf->vb2_buf;
1260
1261 vb->timestamp = ktime_get_ns();
1262 vbuf->sequence = isc->sequence++;
1263 vb2_buffer_done(vb, VB2_BUF_STATE_DONE);
1264 isc->cur_frm = NULL;
1265 }
1266
1267 if (!list_empty(&isc->dma_queue) && !isc->stop) {
1268 isc->cur_frm = list_first_entry(&isc->dma_queue,
1269 struct isc_buffer, list);
1270 list_del(&isc->cur_frm->list);
1271
Songjun Wu93d4a262017-01-24 06:05:57 -02001272 isc_start_dma(isc);
Songjun Wu10626742016-08-17 03:05:27 -03001273 }
1274
1275 if (isc->stop)
1276 complete(&isc->comp);
1277
1278 ret = IRQ_HANDLED;
Songjun Wu93d4a262017-01-24 06:05:57 -02001279 spin_unlock(&isc->dma_queue_lock);
Songjun Wu10626742016-08-17 03:05:27 -03001280 }
1281
Songjun Wu93d4a262017-01-24 06:05:57 -02001282 if (pending & ISC_INT_HISDONE) {
1283 schedule_work(&isc->awb_work);
1284 ret = IRQ_HANDLED;
1285 }
Songjun Wu10626742016-08-17 03:05:27 -03001286
1287 return ret;
1288}
1289
Songjun Wu93d4a262017-01-24 06:05:57 -02001290static void isc_hist_count(struct isc_device *isc)
1291{
1292 struct regmap *regmap = isc->regmap;
1293 struct isc_ctrls *ctrls = &isc->ctrls;
1294 u32 *hist_count = &ctrls->hist_count[ctrls->hist_id];
1295 u32 *hist_entry = &ctrls->hist_entry[0];
1296 u32 i;
1297
1298 regmap_bulk_read(regmap, ISC_HIS_ENTRY, hist_entry, HIST_ENTRIES);
1299
1300 *hist_count = 0;
Colin Ian King6ea87862017-03-07 11:30:47 -03001301 for (i = 0; i < HIST_ENTRIES; i++)
Songjun Wu93d4a262017-01-24 06:05:57 -02001302 *hist_count += i * (*hist_entry++);
1303}
1304
1305static void isc_wb_update(struct isc_ctrls *ctrls)
1306{
1307 u32 *hist_count = &ctrls->hist_count[0];
1308 u64 g_count = (u64)hist_count[ISC_HIS_CFG_MODE_GB] << 9;
1309 u32 hist_r = hist_count[ISC_HIS_CFG_MODE_R];
1310 u32 hist_b = hist_count[ISC_HIS_CFG_MODE_B];
1311
1312 if (hist_r)
1313 ctrls->r_gain = div_u64(g_count, hist_r);
1314
1315 if (hist_b)
1316 ctrls->b_gain = div_u64(g_count, hist_b);
1317}
1318
1319static void isc_awb_work(struct work_struct *w)
1320{
1321 struct isc_device *isc =
1322 container_of(w, struct isc_device, awb_work);
1323 struct regmap *regmap = isc->regmap;
1324 struct isc_ctrls *ctrls = &isc->ctrls;
1325 u32 hist_id = ctrls->hist_id;
1326 u32 baysel;
1327
1328 if (ctrls->hist_stat != HIST_ENABLED)
1329 return;
1330
1331 isc_hist_count(isc);
1332
1333 if (hist_id != ISC_HIS_CFG_MODE_B) {
1334 hist_id++;
1335 } else {
1336 isc_wb_update(ctrls);
1337 hist_id = ISC_HIS_CFG_MODE_R;
1338 }
1339
1340 ctrls->hist_id = hist_id;
1341 baysel = isc->raw_fmt->reg_bay_cfg << ISC_HIS_CFG_BAYSEL_SHIFT;
1342
1343 pm_runtime_get_sync(isc->dev);
1344
1345 regmap_write(regmap, ISC_HIS_CFG, hist_id | baysel | ISC_HIS_CFG_RAR);
1346 isc_update_profile(isc);
1347 regmap_write(regmap, ISC_CTRLEN, ISC_CTRL_HISREQ);
1348
1349 pm_runtime_put_sync(isc->dev);
1350}
1351
1352static int isc_s_ctrl(struct v4l2_ctrl *ctrl)
1353{
1354 struct isc_device *isc = container_of(ctrl->handler,
1355 struct isc_device, ctrls.handler);
1356 struct isc_ctrls *ctrls = &isc->ctrls;
1357
1358 switch (ctrl->id) {
1359 case V4L2_CID_BRIGHTNESS:
1360 ctrls->brightness = ctrl->val & ISC_CBC_BRIGHT_MASK;
1361 break;
1362 case V4L2_CID_CONTRAST:
1363 ctrls->contrast = ctrl->val & ISC_CBC_CONTRAST_MASK;
1364 break;
1365 case V4L2_CID_GAMMA:
1366 ctrls->gamma_index = ctrl->val;
1367 break;
1368 case V4L2_CID_AUTO_WHITE_BALANCE:
1369 ctrls->awb = ctrl->val;
1370 if (ctrls->hist_stat != HIST_ENABLED) {
1371 ctrls->r_gain = 0x1 << 9;
1372 ctrls->b_gain = 0x1 << 9;
1373 }
1374 break;
1375 default:
1376 return -EINVAL;
1377 }
1378
1379 return 0;
1380}
1381
1382static const struct v4l2_ctrl_ops isc_ctrl_ops = {
1383 .s_ctrl = isc_s_ctrl,
1384};
1385
1386static int isc_ctrl_init(struct isc_device *isc)
1387{
1388 const struct v4l2_ctrl_ops *ops = &isc_ctrl_ops;
1389 struct isc_ctrls *ctrls = &isc->ctrls;
1390 struct v4l2_ctrl_handler *hdl = &ctrls->handler;
1391 int ret;
1392
1393 ctrls->hist_stat = HIST_INIT;
1394
1395 ret = v4l2_ctrl_handler_init(hdl, 4);
1396 if (ret < 0)
1397 return ret;
1398
1399 v4l2_ctrl_new_std(hdl, ops, V4L2_CID_BRIGHTNESS, -1024, 1023, 1, 0);
1400 v4l2_ctrl_new_std(hdl, ops, V4L2_CID_CONTRAST, -2048, 2047, 1, 256);
1401 v4l2_ctrl_new_std(hdl, ops, V4L2_CID_GAMMA, 0, GAMMA_MAX, 1, 2);
1402 v4l2_ctrl_new_std(hdl, ops, V4L2_CID_AUTO_WHITE_BALANCE, 0, 1, 1, 1);
1403
1404 v4l2_ctrl_handler_setup(hdl);
1405
1406 return 0;
1407}
1408
1409
Songjun Wu10626742016-08-17 03:05:27 -03001410static int isc_async_bound(struct v4l2_async_notifier *notifier,
1411 struct v4l2_subdev *subdev,
1412 struct v4l2_async_subdev *asd)
1413{
1414 struct isc_device *isc = container_of(notifier->v4l2_dev,
1415 struct isc_device, v4l2_dev);
1416 struct isc_subdev_entity *subdev_entity =
1417 container_of(notifier, struct isc_subdev_entity, notifier);
1418
1419 if (video_is_registered(&isc->video_dev)) {
1420 v4l2_err(&isc->v4l2_dev, "only supports one sub-device.\n");
1421 return -EBUSY;
1422 }
1423
1424 subdev_entity->sd = subdev;
1425
1426 return 0;
1427}
1428
1429static void isc_async_unbind(struct v4l2_async_notifier *notifier,
1430 struct v4l2_subdev *subdev,
1431 struct v4l2_async_subdev *asd)
1432{
1433 struct isc_device *isc = container_of(notifier->v4l2_dev,
1434 struct isc_device, v4l2_dev);
Songjun Wu93d4a262017-01-24 06:05:57 -02001435 cancel_work_sync(&isc->awb_work);
Songjun Wu10626742016-08-17 03:05:27 -03001436 video_unregister_device(&isc->video_dev);
1437 if (isc->current_subdev->config)
1438 v4l2_subdev_free_pad_config(isc->current_subdev->config);
Songjun Wu93d4a262017-01-24 06:05:57 -02001439 v4l2_ctrl_handler_free(&isc->ctrls.handler);
Songjun Wu10626742016-08-17 03:05:27 -03001440}
1441
1442static struct isc_format *find_format_by_code(unsigned int code, int *index)
1443{
1444 struct isc_format *fmt = &isc_formats[0];
1445 unsigned int i;
1446
1447 for (i = 0; i < ARRAY_SIZE(isc_formats); i++) {
1448 if (fmt->mbus_code == code) {
1449 *index = i;
1450 return fmt;
1451 }
1452
1453 fmt++;
1454 }
1455
1456 return NULL;
1457}
1458
1459static int isc_formats_init(struct isc_device *isc)
1460{
1461 struct isc_format *fmt;
1462 struct v4l2_subdev *subdev = isc->current_subdev->sd;
Songjun Wu93d4a262017-01-24 06:05:57 -02001463 unsigned int num_fmts, i, j;
Songjun Wu10626742016-08-17 03:05:27 -03001464 struct v4l2_subdev_mbus_code_enum mbus_code = {
1465 .which = V4L2_SUBDEV_FORMAT_ACTIVE,
1466 };
1467
1468 fmt = &isc_formats[0];
1469 for (i = 0; i < ARRAY_SIZE(isc_formats); i++) {
Songjun Wu93d4a262017-01-24 06:05:57 -02001470 fmt->isc_support = false;
1471 fmt->sd_support = false;
1472
Songjun Wu10626742016-08-17 03:05:27 -03001473 fmt++;
1474 }
1475
1476 while (!v4l2_subdev_call(subdev, pad, enum_mbus_code,
1477 NULL, &mbus_code)) {
1478 mbus_code.index++;
1479 fmt = find_format_by_code(mbus_code.code, &i);
1480 if (!fmt)
1481 continue;
1482
Songjun Wu93d4a262017-01-24 06:05:57 -02001483 fmt->sd_support = true;
1484
1485 if (i <= RAW_FMT_IND_END) {
1486 for (j = ISC_FMT_IND_START; j <= ISC_FMT_IND_END; j++)
1487 isc_formats[j].isc_support = true;
1488
1489 isc->raw_fmt = fmt;
1490 }
1491 }
1492
Songjun Wu9eb9db3a2017-04-17 06:07:57 -03001493 fmt = &isc_formats[0];
Songjun Wu93d4a262017-01-24 06:05:57 -02001494 for (i = 0, num_fmts = 0; i < ARRAY_SIZE(isc_formats); i++) {
1495 if (fmt->isc_support || fmt->sd_support)
1496 num_fmts++;
1497
1498 fmt++;
Songjun Wu10626742016-08-17 03:05:27 -03001499 }
1500
1501 if (!num_fmts)
1502 return -ENXIO;
1503
1504 isc->num_user_formats = num_fmts;
1505 isc->user_formats = devm_kcalloc(isc->dev,
1506 num_fmts, sizeof(struct isc_format *),
1507 GFP_KERNEL);
1508 if (!isc->user_formats) {
1509 v4l2_err(&isc->v4l2_dev, "could not allocate memory\n");
1510 return -ENOMEM;
1511 }
1512
1513 fmt = &isc_formats[0];
1514 for (i = 0, j = 0; i < ARRAY_SIZE(isc_formats); i++) {
Songjun Wu93d4a262017-01-24 06:05:57 -02001515 if (fmt->isc_support || fmt->sd_support)
Songjun Wu10626742016-08-17 03:05:27 -03001516 isc->user_formats[j++] = fmt;
1517
1518 fmt++;
1519 }
1520
1521 return 0;
1522}
1523
1524static int isc_set_default_fmt(struct isc_device *isc)
1525{
1526 struct v4l2_format f = {
1527 .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
1528 .fmt.pix = {
1529 .width = VGA_WIDTH,
1530 .height = VGA_HEIGHT,
1531 .field = V4L2_FIELD_NONE,
1532 .pixelformat = isc->user_formats[0]->fourcc,
1533 },
1534 };
Songjun Wu4540e0a2016-09-12 04:47:24 -03001535 int ret;
Songjun Wu10626742016-08-17 03:05:27 -03001536
Songjun Wu93d4a262017-01-24 06:05:57 -02001537 ret = isc_try_fmt(isc, &f, NULL, NULL);
Songjun Wu4540e0a2016-09-12 04:47:24 -03001538 if (ret)
1539 return ret;
1540
1541 isc->current_fmt = isc->user_formats[0];
1542 isc->fmt = f;
1543
1544 return 0;
Songjun Wu10626742016-08-17 03:05:27 -03001545}
1546
1547static int isc_async_complete(struct v4l2_async_notifier *notifier)
1548{
1549 struct isc_device *isc = container_of(notifier->v4l2_dev,
1550 struct isc_device, v4l2_dev);
1551 struct isc_subdev_entity *sd_entity;
1552 struct video_device *vdev = &isc->video_dev;
1553 struct vb2_queue *q = &isc->vb2_vidq;
1554 int ret;
1555
Songjun Wu93d4a262017-01-24 06:05:57 -02001556 ret = v4l2_device_register_subdev_nodes(&isc->v4l2_dev);
1557 if (ret < 0) {
1558 v4l2_err(&isc->v4l2_dev, "Failed to register subdev nodes\n");
1559 return ret;
1560 }
1561
Songjun Wu10626742016-08-17 03:05:27 -03001562 isc->current_subdev = container_of(notifier,
1563 struct isc_subdev_entity, notifier);
1564 sd_entity = isc->current_subdev;
1565
1566 mutex_init(&isc->lock);
1567 init_completion(&isc->comp);
1568
1569 /* Initialize videobuf2 queue */
1570 q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1571 q->io_modes = VB2_MMAP | VB2_DMABUF | VB2_READ;
1572 q->drv_priv = isc;
1573 q->buf_struct_size = sizeof(struct isc_buffer);
1574 q->ops = &isc_vb2_ops;
1575 q->mem_ops = &vb2_dma_contig_memops;
1576 q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
1577 q->lock = &isc->lock;
1578 q->min_buffers_needed = 1;
1579 q->dev = isc->dev;
1580
1581 ret = vb2_queue_init(q);
1582 if (ret < 0) {
1583 v4l2_err(&isc->v4l2_dev,
1584 "vb2_queue_init() failed: %d\n", ret);
1585 return ret;
1586 }
1587
1588 /* Init video dma queues */
1589 INIT_LIST_HEAD(&isc->dma_queue);
1590 spin_lock_init(&isc->dma_queue_lock);
1591
1592 sd_entity->config = v4l2_subdev_alloc_pad_config(sd_entity->sd);
1593 if (sd_entity->config == NULL)
1594 return -ENOMEM;
1595
1596 ret = isc_formats_init(isc);
1597 if (ret < 0) {
1598 v4l2_err(&isc->v4l2_dev,
1599 "Init format failed: %d\n", ret);
1600 return ret;
1601 }
1602
Songjun Wu10626742016-08-17 03:05:27 -03001603 ret = isc_set_default_fmt(isc);
1604 if (ret) {
1605 v4l2_err(&isc->v4l2_dev, "Could not set default format\n");
1606 return ret;
1607 }
1608
Songjun Wu93d4a262017-01-24 06:05:57 -02001609 ret = isc_ctrl_init(isc);
1610 if (ret) {
1611 v4l2_err(&isc->v4l2_dev, "Init isc ctrols failed: %d\n", ret);
1612 return ret;
1613 }
1614
1615 INIT_WORK(&isc->awb_work, isc_awb_work);
1616
Songjun Wu10626742016-08-17 03:05:27 -03001617 /* Register video device */
1618 strlcpy(vdev->name, ATMEL_ISC_NAME, sizeof(vdev->name));
1619 vdev->release = video_device_release_empty;
1620 vdev->fops = &isc_fops;
1621 vdev->ioctl_ops = &isc_ioctl_ops;
1622 vdev->v4l2_dev = &isc->v4l2_dev;
1623 vdev->vfl_dir = VFL_DIR_RX;
1624 vdev->queue = q;
1625 vdev->lock = &isc->lock;
Songjun Wu93d4a262017-01-24 06:05:57 -02001626 vdev->ctrl_handler = &isc->ctrls.handler;
Songjun Wu10626742016-08-17 03:05:27 -03001627 vdev->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_CAPTURE;
1628 video_set_drvdata(vdev, isc);
1629
1630 ret = video_register_device(vdev, VFL_TYPE_GRABBER, -1);
1631 if (ret < 0) {
1632 v4l2_err(&isc->v4l2_dev,
1633 "video_register_device failed: %d\n", ret);
1634 return ret;
1635 }
1636
1637 return 0;
1638}
1639
1640static void isc_subdev_cleanup(struct isc_device *isc)
1641{
1642 struct isc_subdev_entity *subdev_entity;
1643
1644 list_for_each_entry(subdev_entity, &isc->subdev_entities, list)
1645 v4l2_async_notifier_unregister(&subdev_entity->notifier);
1646
1647 INIT_LIST_HEAD(&isc->subdev_entities);
1648}
1649
1650static int isc_pipeline_init(struct isc_device *isc)
1651{
1652 struct device *dev = isc->dev;
1653 struct regmap *regmap = isc->regmap;
1654 struct regmap_field *regs;
1655 unsigned int i;
1656
1657 /* WB-->CFA-->CC-->GAM-->CSC-->CBC-->SUB422-->SUB420 */
1658 const struct reg_field regfields[ISC_PIPE_LINE_NODE_NUM] = {
1659 REG_FIELD(ISC_WB_CTRL, 0, 0),
1660 REG_FIELD(ISC_CFA_CTRL, 0, 0),
1661 REG_FIELD(ISC_CC_CTRL, 0, 0),
1662 REG_FIELD(ISC_GAM_CTRL, 0, 0),
1663 REG_FIELD(ISC_GAM_CTRL, 1, 1),
1664 REG_FIELD(ISC_GAM_CTRL, 2, 2),
1665 REG_FIELD(ISC_GAM_CTRL, 3, 3),
1666 REG_FIELD(ISC_CSC_CTRL, 0, 0),
1667 REG_FIELD(ISC_CBC_CTRL, 0, 0),
1668 REG_FIELD(ISC_SUB422_CTRL, 0, 0),
1669 REG_FIELD(ISC_SUB420_CTRL, 0, 0),
1670 };
1671
1672 for (i = 0; i < ISC_PIPE_LINE_NODE_NUM; i++) {
1673 regs = devm_regmap_field_alloc(dev, regmap, regfields[i]);
1674 if (IS_ERR(regs))
1675 return PTR_ERR(regs);
1676
1677 isc->pipeline[i] = regs;
1678 }
1679
1680 return 0;
1681}
1682
1683static int isc_parse_dt(struct device *dev, struct isc_device *isc)
1684{
1685 struct device_node *np = dev->of_node;
1686 struct device_node *epn = NULL, *rem;
1687 struct v4l2_of_endpoint v4l2_epn;
1688 struct isc_subdev_entity *subdev_entity;
1689 unsigned int flags;
1690 int ret;
1691
1692 INIT_LIST_HEAD(&isc->subdev_entities);
1693
1694 for (; ;) {
1695 epn = of_graph_get_next_endpoint(np, epn);
1696 if (!epn)
1697 break;
1698
1699 rem = of_graph_get_remote_port_parent(epn);
1700 if (!rem) {
1701 dev_notice(dev, "Remote device at %s not found\n",
1702 of_node_full_name(epn));
1703 continue;
1704 }
1705
1706 ret = v4l2_of_parse_endpoint(epn, &v4l2_epn);
1707 if (ret) {
1708 of_node_put(rem);
1709 ret = -EINVAL;
1710 dev_err(dev, "Could not parse the endpoint\n");
1711 break;
1712 }
1713
1714 subdev_entity = devm_kzalloc(dev,
1715 sizeof(*subdev_entity), GFP_KERNEL);
1716 if (subdev_entity == NULL) {
1717 of_node_put(rem);
1718 ret = -ENOMEM;
1719 break;
1720 }
1721
1722 subdev_entity->asd = devm_kzalloc(dev,
1723 sizeof(*subdev_entity->asd), GFP_KERNEL);
1724 if (subdev_entity->asd == NULL) {
1725 of_node_put(rem);
1726 ret = -ENOMEM;
1727 break;
1728 }
1729
1730 flags = v4l2_epn.bus.parallel.flags;
1731
1732 if (flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)
1733 subdev_entity->pfe_cfg0 = ISC_PFE_CFG0_HPOL_LOW;
1734
1735 if (flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)
1736 subdev_entity->pfe_cfg0 |= ISC_PFE_CFG0_VPOL_LOW;
1737
1738 if (flags & V4L2_MBUS_PCLK_SAMPLE_FALLING)
1739 subdev_entity->pfe_cfg0 |= ISC_PFE_CFG0_PPOL_LOW;
1740
1741 subdev_entity->asd->match_type = V4L2_ASYNC_MATCH_OF;
1742 subdev_entity->asd->match.of.node = rem;
1743 list_add_tail(&subdev_entity->list, &isc->subdev_entities);
1744 }
1745
1746 of_node_put(epn);
1747 return ret;
1748}
1749
1750/* regmap configuration */
1751#define ATMEL_ISC_REG_MAX 0xbfc
1752static const struct regmap_config isc_regmap_config = {
1753 .reg_bits = 32,
1754 .reg_stride = 4,
1755 .val_bits = 32,
1756 .max_register = ATMEL_ISC_REG_MAX,
1757};
1758
1759static int atmel_isc_probe(struct platform_device *pdev)
1760{
1761 struct device *dev = &pdev->dev;
1762 struct isc_device *isc;
1763 struct resource *res;
1764 void __iomem *io_base;
1765 struct isc_subdev_entity *subdev_entity;
1766 int irq;
1767 int ret;
1768
1769 isc = devm_kzalloc(dev, sizeof(*isc), GFP_KERNEL);
1770 if (!isc)
1771 return -ENOMEM;
1772
1773 platform_set_drvdata(pdev, isc);
1774 isc->dev = dev;
1775
1776 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1777 io_base = devm_ioremap_resource(dev, res);
1778 if (IS_ERR(io_base))
1779 return PTR_ERR(io_base);
1780
1781 isc->regmap = devm_regmap_init_mmio(dev, io_base, &isc_regmap_config);
1782 if (IS_ERR(isc->regmap)) {
1783 ret = PTR_ERR(isc->regmap);
1784 dev_err(dev, "failed to init register map: %d\n", ret);
1785 return ret;
1786 }
1787
1788 irq = platform_get_irq(pdev, 0);
Songjun Wu846c4a72016-08-24 05:49:28 -03001789 if (irq < 0) {
Songjun Wu10626742016-08-17 03:05:27 -03001790 ret = irq;
1791 dev_err(dev, "failed to get irq: %d\n", ret);
1792 return ret;
1793 }
1794
1795 ret = devm_request_irq(dev, irq, isc_interrupt, 0,
1796 ATMEL_ISC_NAME, isc);
1797 if (ret < 0) {
1798 dev_err(dev, "can't register ISR for IRQ %u (ret=%i)\n",
1799 irq, ret);
1800 return ret;
1801 }
1802
1803 ret = isc_pipeline_init(isc);
1804 if (ret)
1805 return ret;
1806
1807 isc->hclock = devm_clk_get(dev, "hclock");
1808 if (IS_ERR(isc->hclock)) {
1809 ret = PTR_ERR(isc->hclock);
1810 dev_err(dev, "failed to get hclock: %d\n", ret);
1811 return ret;
1812 }
1813
1814 ret = isc_clk_init(isc);
1815 if (ret) {
1816 dev_err(dev, "failed to init isc clock: %d\n", ret);
1817 goto clean_isc_clk;
1818 }
1819
1820 isc->ispck = isc->isc_clks[ISC_ISPCK].clk;
1821
1822 /* ispck should be greater or equal to hclock */
1823 ret = clk_set_rate(isc->ispck, clk_get_rate(isc->hclock));
1824 if (ret) {
1825 dev_err(dev, "failed to set ispck rate: %d\n", ret);
1826 goto clean_isc_clk;
1827 }
1828
1829 ret = v4l2_device_register(dev, &isc->v4l2_dev);
1830 if (ret) {
1831 dev_err(dev, "unable to register v4l2 device.\n");
1832 goto clean_isc_clk;
1833 }
1834
1835 ret = isc_parse_dt(dev, isc);
1836 if (ret) {
1837 dev_err(dev, "fail to parse device tree\n");
1838 goto unregister_v4l2_device;
1839 }
1840
1841 if (list_empty(&isc->subdev_entities)) {
1842 dev_err(dev, "no subdev found\n");
Wei Yongjune04e5812016-11-11 11:40:20 -02001843 ret = -ENODEV;
Songjun Wu10626742016-08-17 03:05:27 -03001844 goto unregister_v4l2_device;
1845 }
1846
1847 list_for_each_entry(subdev_entity, &isc->subdev_entities, list) {
1848 subdev_entity->notifier.subdevs = &subdev_entity->asd;
1849 subdev_entity->notifier.num_subdevs = 1;
1850 subdev_entity->notifier.bound = isc_async_bound;
1851 subdev_entity->notifier.unbind = isc_async_unbind;
1852 subdev_entity->notifier.complete = isc_async_complete;
1853
1854 ret = v4l2_async_notifier_register(&isc->v4l2_dev,
1855 &subdev_entity->notifier);
1856 if (ret) {
1857 dev_err(dev, "fail to register async notifier\n");
1858 goto cleanup_subdev;
1859 }
1860
1861 if (video_is_registered(&isc->video_dev))
1862 break;
1863 }
1864
1865 pm_runtime_enable(dev);
1866
1867 return 0;
1868
1869cleanup_subdev:
1870 isc_subdev_cleanup(isc);
1871
1872unregister_v4l2_device:
1873 v4l2_device_unregister(&isc->v4l2_dev);
1874
1875clean_isc_clk:
1876 isc_clk_cleanup(isc);
1877
1878 return ret;
1879}
1880
1881static int atmel_isc_remove(struct platform_device *pdev)
1882{
1883 struct isc_device *isc = platform_get_drvdata(pdev);
1884
1885 pm_runtime_disable(&pdev->dev);
1886
1887 isc_subdev_cleanup(isc);
1888
1889 v4l2_device_unregister(&isc->v4l2_dev);
1890
1891 isc_clk_cleanup(isc);
1892
1893 return 0;
1894}
1895
Arnd Bergmannb7e50632016-09-12 12:32:58 -03001896static int __maybe_unused isc_runtime_suspend(struct device *dev)
Songjun Wu10626742016-08-17 03:05:27 -03001897{
1898 struct isc_device *isc = dev_get_drvdata(dev);
1899
1900 clk_disable_unprepare(isc->ispck);
1901 clk_disable_unprepare(isc->hclock);
1902
1903 return 0;
1904}
1905
Arnd Bergmannb7e50632016-09-12 12:32:58 -03001906static int __maybe_unused isc_runtime_resume(struct device *dev)
Songjun Wu10626742016-08-17 03:05:27 -03001907{
1908 struct isc_device *isc = dev_get_drvdata(dev);
1909 int ret;
1910
1911 ret = clk_prepare_enable(isc->hclock);
1912 if (ret)
1913 return ret;
1914
1915 return clk_prepare_enable(isc->ispck);
1916}
1917
1918static const struct dev_pm_ops atmel_isc_dev_pm_ops = {
1919 SET_RUNTIME_PM_OPS(isc_runtime_suspend, isc_runtime_resume, NULL)
1920};
1921
1922static const struct of_device_id atmel_isc_of_match[] = {
1923 { .compatible = "atmel,sama5d2-isc" },
1924 { }
1925};
1926MODULE_DEVICE_TABLE(of, atmel_isc_of_match);
1927
1928static struct platform_driver atmel_isc_driver = {
1929 .probe = atmel_isc_probe,
1930 .remove = atmel_isc_remove,
1931 .driver = {
1932 .name = ATMEL_ISC_NAME,
1933 .pm = &atmel_isc_dev_pm_ops,
1934 .of_match_table = of_match_ptr(atmel_isc_of_match),
1935 },
1936};
1937
1938module_platform_driver(atmel_isc_driver);
1939
1940MODULE_AUTHOR("Songjun Wu <songjun.wu@microchip.com>");
1941MODULE_DESCRIPTION("The V4L2 driver for Atmel-ISC");
1942MODULE_LICENSE("GPL v2");
1943MODULE_SUPPORTED_DEVICE("video");