]> Pileus Git - ~andy/linux/blob - drivers/staging/media/davinci_vpfe/dm365_ipipeif.c
Merge tag 'boards-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/arm...
[~andy/linux] / drivers / staging / media / davinci_vpfe / dm365_ipipeif.c
1 /*
2  * Copyright (C) 2012 Texas Instruments Inc
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation version 2.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16  *
17  * Contributors:
18  *      Manjunath Hadli <manjunath.hadli@ti.com>
19  *      Prabhakar Lad <prabhakar.lad@ti.com>
20  */
21
22 #include "dm365_ipipeif.h"
23 #include "vpfe_mc_capture.h"
24
25 static const unsigned int ipipeif_input_fmts[] = {
26         V4L2_MBUS_FMT_UYVY8_2X8,
27         V4L2_MBUS_FMT_SGRBG12_1X12,
28         V4L2_MBUS_FMT_Y8_1X8,
29         V4L2_MBUS_FMT_UV8_1X8,
30         V4L2_MBUS_FMT_YDYUYDYV8_1X16,
31         V4L2_MBUS_FMT_SBGGR8_1X8,
32 };
33
34 static const unsigned int ipipeif_output_fmts[] = {
35         V4L2_MBUS_FMT_UYVY8_2X8,
36         V4L2_MBUS_FMT_SGRBG12_1X12,
37         V4L2_MBUS_FMT_Y8_1X8,
38         V4L2_MBUS_FMT_UV8_1X8,
39         V4L2_MBUS_FMT_YDYUYDYV8_1X16,
40         V4L2_MBUS_FMT_SBGGR8_1X8,
41         V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8,
42         V4L2_MBUS_FMT_SGRBG10_ALAW8_1X8,
43 };
44
45 static int
46 ipipeif_get_pack_mode(enum v4l2_mbus_pixelcode in_pix_fmt)
47 {
48         switch (in_pix_fmt) {
49         case V4L2_MBUS_FMT_SBGGR8_1X8:
50         case V4L2_MBUS_FMT_Y8_1X8:
51         case V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8:
52         case V4L2_MBUS_FMT_UV8_1X8:
53                 return IPIPEIF_5_1_PACK_8_BIT;
54
55         case V4L2_MBUS_FMT_SGRBG10_ALAW8_1X8:
56                 return IPIPEIF_5_1_PACK_8_BIT_A_LAW;
57
58         case V4L2_MBUS_FMT_SGRBG12_1X12:
59                 return IPIPEIF_5_1_PACK_16_BIT;
60
61         case V4L2_MBUS_FMT_SBGGR12_1X12:
62                 return IPIPEIF_5_1_PACK_12_BIT;
63
64         default:
65                 return IPIPEIF_5_1_PACK_16_BIT;
66         }
67 }
68
69 static inline u32 ipipeif_read(void *addr, u32 offset)
70 {
71         return readl(addr + offset);
72 }
73
74 static inline void ipipeif_write(u32 val, void *addr, u32 offset)
75 {
76         writel(val, addr + offset);
77 }
78
79 static void ipipeif_config_dpc(void *addr, struct ipipeif_dpc *dpc)
80 {
81         u32 val = 0;
82
83         if (dpc->en) {
84                 val = (dpc->en & 1) << IPIPEIF_DPC2_EN_SHIFT;
85                 val |= dpc->thr & IPIPEIF_DPC2_THR_MASK;
86         }
87         ipipeif_write(val, addr, IPIPEIF_DPC2);
88 }
89
90 #define IPIPEIF_MODE_CONTINUOUS                 0
91 #define IPIPEIF_MODE_ONE_SHOT                   1
92
93 static int get_oneshot_mode(enum ipipeif_input_entity input)
94 {
95         if (input == IPIPEIF_INPUT_MEMORY)
96                 return IPIPEIF_MODE_ONE_SHOT;
97         else if (input == IPIPEIF_INPUT_ISIF)
98                 return IPIPEIF_MODE_CONTINUOUS;
99
100         return -EINVAL;
101 }
102
103 static int
104 ipipeif_get_cfg_src1(struct vpfe_ipipeif_device *ipipeif)
105 {
106         struct v4l2_mbus_framefmt *informat;
107
108         informat = &ipipeif->formats[IPIPEIF_PAD_SINK];
109         if (ipipeif->input == IPIPEIF_INPUT_MEMORY &&
110            (informat->code == V4L2_MBUS_FMT_Y8_1X8 ||
111             informat->code == V4L2_MBUS_FMT_UV8_1X8))
112                 return IPIPEIF_CCDC;
113
114         return IPIPEIF_SRC1_PARALLEL_PORT;
115 }
116
117 static int
118 ipipeif_get_data_shift(struct vpfe_ipipeif_device *ipipeif)
119 {
120         struct v4l2_mbus_framefmt *informat;
121
122         informat = &ipipeif->formats[IPIPEIF_PAD_SINK];
123
124         switch (informat->code) {
125         case V4L2_MBUS_FMT_SGRBG12_1X12:
126                 return IPIPEIF_5_1_BITS11_0;
127
128         case V4L2_MBUS_FMT_Y8_1X8:
129         case V4L2_MBUS_FMT_UV8_1X8:
130                 return IPIPEIF_5_1_BITS11_0;
131
132         default:
133                 return IPIPEIF_5_1_BITS7_0;
134         }
135 }
136
137 static enum ipipeif_input_source
138 ipipeif_get_source(struct vpfe_ipipeif_device *ipipeif)
139 {
140         struct v4l2_mbus_framefmt *informat;
141
142         informat = &ipipeif->formats[IPIPEIF_PAD_SINK];
143         if (ipipeif->input == IPIPEIF_INPUT_ISIF)
144                 return IPIPEIF_CCDC;
145
146         if (informat->code == V4L2_MBUS_FMT_UYVY8_2X8)
147                 return IPIPEIF_SDRAM_YUV;
148
149         return IPIPEIF_SDRAM_RAW;
150 }
151
152 void vpfe_ipipeif_ss_buffer_isr(struct vpfe_ipipeif_device *ipipeif)
153 {
154         struct vpfe_video_device *video_in = &ipipeif->video_in;
155
156         if (ipipeif->input != IPIPEIF_INPUT_MEMORY)
157                 return;
158
159         spin_lock(&video_in->dma_queue_lock);
160         vpfe_video_process_buffer_complete(video_in);
161         video_in->state = VPFE_VIDEO_BUFFER_NOT_QUEUED;
162         vpfe_video_schedule_next_buffer(video_in);
163         spin_unlock(&video_in->dma_queue_lock);
164 }
165
166 int vpfe_ipipeif_decimation_enabled(struct vpfe_device *vpfe_dev)
167 {
168         struct vpfe_ipipeif_device *ipipeif = &vpfe_dev->vpfe_ipipeif;
169
170         return ipipeif->config.decimation;
171 }
172
173 int vpfe_ipipeif_get_rsz(struct vpfe_device *vpfe_dev)
174 {
175         struct vpfe_ipipeif_device *ipipeif = &vpfe_dev->vpfe_ipipeif;
176
177         return ipipeif->config.rsz;
178 }
179
180 #define RD_DATA_15_2            0x7
181
182 /*
183  * ipipeif_hw_setup() - This function sets up IPIPEIF
184  * @sd: pointer to v4l2 subdev structure
185  * return -EINVAL or zero on success
186  */
187 static int ipipeif_hw_setup(struct v4l2_subdev *sd)
188 {
189         struct vpfe_ipipeif_device *ipipeif = v4l2_get_subdevdata(sd);
190         struct v4l2_mbus_framefmt *informat, *outformat;
191         struct ipipeif_params params = ipipeif->config;
192         enum ipipeif_input_source ipipeif_source;
193         enum v4l2_mbus_pixelcode isif_port_if;
194         void *ipipeif_base_addr;
195         unsigned int val;
196         int data_shift;
197         int pack_mode;
198         int source1;
199
200         ipipeif_base_addr = ipipeif->ipipeif_base_addr;
201
202         /* Enable clock to IPIPEIF and IPIPE */
203         vpss_enable_clock(VPSS_IPIPEIF_CLOCK, 1);
204
205         informat = &ipipeif->formats[IPIPEIF_PAD_SINK];
206         outformat = &ipipeif->formats[IPIPEIF_PAD_SOURCE];
207
208         /* Combine all the fields to make CFG1 register of IPIPEIF */
209         val = get_oneshot_mode(ipipeif->input);
210         if (val < 0) {
211                 pr_err("ipipeif: links setup required");
212                 return -EINVAL;
213         }
214         val = val << ONESHOT_SHIFT;
215
216         ipipeif_source = ipipeif_get_source(ipipeif);
217         val |= ipipeif_source << INPSRC_SHIFT;
218
219         val |= params.clock_select << CLKSEL_SHIFT;
220         val |= params.avg_filter << AVGFILT_SHIFT;
221         val |= params.decimation << DECIM_SHIFT;
222
223         pack_mode = ipipeif_get_pack_mode(informat->code);
224         val |= pack_mode << PACK8IN_SHIFT;
225
226         source1 = ipipeif_get_cfg_src1(ipipeif);
227         val |= source1 << INPSRC1_SHIFT;
228
229         data_shift = ipipeif_get_data_shift(ipipeif);
230         if (ipipeif_source != IPIPEIF_SDRAM_YUV)
231                 val |= data_shift << DATASFT_SHIFT;
232         else
233                 val &= ~(RD_DATA_15_2 << DATASFT_SHIFT);
234
235         ipipeif_write(val, ipipeif_base_addr, IPIPEIF_CFG1);
236
237         switch (ipipeif_source) {
238         case IPIPEIF_CCDC:
239                 ipipeif_write(ipipeif->gain, ipipeif_base_addr, IPIPEIF_GAIN);
240                 break;
241
242         case IPIPEIF_SDRAM_RAW:
243         case IPIPEIF_CCDC_DARKFM:
244                 ipipeif_write(ipipeif->gain, ipipeif_base_addr, IPIPEIF_GAIN);
245                 /* fall through */
246         case IPIPEIF_SDRAM_YUV:
247                 val |= data_shift << DATASFT_SHIFT;
248                 ipipeif_write(params.ppln, ipipeif_base_addr, IPIPEIF_PPLN);
249                 ipipeif_write(params.lpfr, ipipeif_base_addr, IPIPEIF_LPFR);
250                 ipipeif_write(informat->width, ipipeif_base_addr, IPIPEIF_HNUM);
251                 ipipeif_write(informat->height,
252                               ipipeif_base_addr, IPIPEIF_VNUM);
253                 break;
254
255         default:
256                 return -EINVAL;
257         }
258
259         /*check if decimation is enable or not */
260         if (params.decimation)
261                 ipipeif_write(params.rsz, ipipeif_base_addr, IPIPEIF_RSZ);
262
263         /* Setup sync alignment and initial rsz position */
264         val = params.if_5_1.align_sync & 1;
265         val <<= IPIPEIF_INIRSZ_ALNSYNC_SHIFT;
266         val |= params.if_5_1.rsz_start & IPIPEIF_INIRSZ_MASK;
267         ipipeif_write(val, ipipeif_base_addr, IPIPEIF_INIRSZ);
268         isif_port_if = informat->code;
269
270         if (isif_port_if == V4L2_MBUS_FMT_Y8_1X8)
271                 isif_port_if = V4L2_MBUS_FMT_YUYV8_1X16;
272         else if (isif_port_if == V4L2_MBUS_FMT_UV8_1X8)
273                 isif_port_if = V4L2_MBUS_FMT_SGRBG12_1X12;
274
275         /* Enable DPCM decompression */
276         switch (ipipeif_source) {
277         case IPIPEIF_SDRAM_RAW:
278                 val = 0;
279                 if (outformat->code == V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8) {
280                         val = 1;
281                         val |= (IPIPEIF_DPCM_8BIT_10BIT & 1) <<
282                                 IPIPEIF_DPCM_BITS_SHIFT;
283                         val |= (ipipeif->dpcm_predictor & 1) <<
284                                 IPIPEIF_DPCM_PRED_SHIFT;
285                 }
286                 ipipeif_write(val, ipipeif_base_addr, IPIPEIF_DPCM);
287
288                 /* set DPC */
289                 ipipeif_config_dpc(ipipeif_base_addr, &params.if_5_1.dpc);
290
291                 ipipeif_write(params.if_5_1.clip,
292                               ipipeif_base_addr, IPIPEIF_OCLIP);
293
294                 /* fall through for SDRAM YUV mode */
295                 /* configure CFG2 */
296                 val = ipipeif_read(ipipeif_base_addr, IPIPEIF_CFG2);
297                 switch (isif_port_if) {
298                 case V4L2_MBUS_FMT_YUYV8_1X16:
299                 case V4L2_MBUS_FMT_UYVY8_2X8:
300                 case V4L2_MBUS_FMT_Y8_1X8:
301                         RESETBIT(val, IPIPEIF_CFG2_YUV8_SHIFT);
302                         SETBIT(val, IPIPEIF_CFG2_YUV16_SHIFT);
303                         ipipeif_write(val, ipipeif_base_addr, IPIPEIF_CFG2);
304                         break;
305
306                 default:
307                         RESETBIT(val, IPIPEIF_CFG2_YUV8_SHIFT);
308                         RESETBIT(val, IPIPEIF_CFG2_YUV16_SHIFT);
309                         ipipeif_write(val, ipipeif_base_addr, IPIPEIF_CFG2);
310                         break;
311                 }
312
313         case IPIPEIF_SDRAM_YUV:
314                 /* Set clock divider */
315                 if (params.clock_select == IPIPEIF_SDRAM_CLK) {
316                         val = ipipeif_read(ipipeif_base_addr, IPIPEIF_CLKDIV);
317                         val |= (params.if_5_1.clk_div.m - 1) <<
318                                 IPIPEIF_CLKDIV_M_SHIFT;
319                         val |= (params.if_5_1.clk_div.n - 1);
320                         ipipeif_write(val, ipipeif_base_addr, IPIPEIF_CLKDIV);
321                 }
322                 break;
323
324         case IPIPEIF_CCDC:
325         case IPIPEIF_CCDC_DARKFM:
326                 /* set DPC */
327                 ipipeif_config_dpc(ipipeif_base_addr, &params.if_5_1.dpc);
328
329                 /* Set DF gain & threshold control */
330                 val = 0;
331                 if (params.if_5_1.df_gain_en) {
332                         val = params.if_5_1.df_gain_thr &
333                                 IPIPEIF_DF_GAIN_THR_MASK;
334                         ipipeif_write(val, ipipeif_base_addr, IPIPEIF_DFSGTH);
335                         val = (params.if_5_1.df_gain_en & 1) <<
336                                 IPIPEIF_DF_GAIN_EN_SHIFT;
337                         val |= params.if_5_1.df_gain &
338                                 IPIPEIF_DF_GAIN_MASK;
339                 }
340                 ipipeif_write(val, ipipeif_base_addr, IPIPEIF_DFSGVL);
341                 /* configure CFG2 */
342                 val = VPFE_PINPOL_POSITIVE << IPIPEIF_CFG2_HDPOL_SHIFT;
343                 val |= VPFE_PINPOL_POSITIVE << IPIPEIF_CFG2_VDPOL_SHIFT;
344
345                 switch (isif_port_if) {
346                 case V4L2_MBUS_FMT_YUYV8_1X16:
347                 case V4L2_MBUS_FMT_YUYV10_1X20:
348                         RESETBIT(val, IPIPEIF_CFG2_YUV8_SHIFT);
349                         SETBIT(val, IPIPEIF_CFG2_YUV16_SHIFT);
350                         break;
351
352                 case V4L2_MBUS_FMT_YUYV8_2X8:
353                 case V4L2_MBUS_FMT_UYVY8_2X8:
354                 case V4L2_MBUS_FMT_Y8_1X8:
355                 case V4L2_MBUS_FMT_YUYV10_2X10:
356                         SETBIT(val, IPIPEIF_CFG2_YUV8_SHIFT);
357                         SETBIT(val, IPIPEIF_CFG2_YUV16_SHIFT);
358                         val |= IPIPEIF_CBCR_Y << IPIPEIF_CFG2_YUV8P_SHIFT;
359                         break;
360
361                 default:
362                         /* Bayer */
363                         ipipeif_write(params.if_5_1.clip, ipipeif_base_addr,
364                                 IPIPEIF_OCLIP);
365                 }
366                 ipipeif_write(val, ipipeif_base_addr, IPIPEIF_CFG2);
367                 break;
368
369         default:
370                 return -EINVAL;
371         }
372
373         return 0;
374 }
375
376 static int
377 ipipeif_set_config(struct v4l2_subdev *sd, struct ipipeif_params *config)
378 {
379         struct vpfe_ipipeif_device *ipipeif = v4l2_get_subdevdata(sd);
380         struct device *dev = ipipeif->subdev.v4l2_dev->dev;
381
382         if (!config) {
383                 dev_err(dev, "Invalid configuration pointer\n");
384                 return -EINVAL;
385         }
386
387         ipipeif->config.clock_select = config->clock_select;
388         ipipeif->config.ppln = config->ppln;
389         ipipeif->config.lpfr = config->lpfr;
390         ipipeif->config.rsz = config->rsz;
391         ipipeif->config.decimation = config->decimation;
392         if (ipipeif->config.decimation &&
393            (ipipeif->config.rsz < IPIPEIF_RSZ_MIN ||
394             ipipeif->config.rsz > IPIPEIF_RSZ_MAX)) {
395                 dev_err(dev, "rsz range is %d to %d\n",
396                         IPIPEIF_RSZ_MIN, IPIPEIF_RSZ_MAX);
397                 return -EINVAL;
398         }
399
400         ipipeif->config.avg_filter = config->avg_filter;
401
402         ipipeif->config.if_5_1.df_gain_thr = config->if_5_1.df_gain_thr;
403         ipipeif->config.if_5_1.df_gain = config->if_5_1.df_gain;
404         ipipeif->config.if_5_1.df_gain_en = config->if_5_1.df_gain_en;
405
406         ipipeif->config.if_5_1.rsz_start = config->if_5_1.rsz_start;
407         ipipeif->config.if_5_1.align_sync = config->if_5_1.align_sync;
408         ipipeif->config.if_5_1.clip = config->if_5_1.clip;
409
410         ipipeif->config.if_5_1.dpc.en = config->if_5_1.dpc.en;
411         ipipeif->config.if_5_1.dpc.thr = config->if_5_1.dpc.thr;
412
413         ipipeif->config.if_5_1.clk_div.m = config->if_5_1.clk_div.m;
414         ipipeif->config.if_5_1.clk_div.n = config->if_5_1.clk_div.n;
415
416         return 0;
417 }
418
419 static int
420 ipipeif_get_config(struct v4l2_subdev *sd, void __user *arg)
421 {
422         struct vpfe_ipipeif_device *ipipeif = v4l2_get_subdevdata(sd);
423         struct ipipeif_params *config = (struct ipipeif_params *)arg;
424         struct device *dev = ipipeif->subdev.v4l2_dev->dev;
425
426         if (!arg) {
427                 dev_err(dev, "Invalid configuration pointer\n");
428                 return -EINVAL;
429         }
430
431         config->clock_select = ipipeif->config.clock_select;
432         config->ppln = ipipeif->config.ppln;
433         config->lpfr = ipipeif->config.lpfr;
434         config->rsz = ipipeif->config.rsz;
435         config->decimation = ipipeif->config.decimation;
436         config->avg_filter = ipipeif->config.avg_filter;
437
438         config->if_5_1.df_gain_thr = ipipeif->config.if_5_1.df_gain_thr;
439         config->if_5_1.df_gain = ipipeif->config.if_5_1.df_gain;
440         config->if_5_1.df_gain_en = ipipeif->config.if_5_1.df_gain_en;
441
442         config->if_5_1.rsz_start = ipipeif->config.if_5_1.rsz_start;
443         config->if_5_1.align_sync = ipipeif->config.if_5_1.align_sync;
444         config->if_5_1.clip = ipipeif->config.if_5_1.clip;
445
446         config->if_5_1.dpc.en = ipipeif->config.if_5_1.dpc.en;
447         config->if_5_1.dpc.thr = ipipeif->config.if_5_1.dpc.thr;
448
449         config->if_5_1.clk_div.m = ipipeif->config.if_5_1.clk_div.m;
450         config->if_5_1.clk_div.n = ipipeif->config.if_5_1.clk_div.n;
451
452         return 0;
453 }
454
455 /*
456  * ipipeif_ioctl() - Handle ipipeif module private ioctl's
457  * @sd: pointer to v4l2 subdev structure
458  * @cmd: configuration command
459  * @arg: configuration argument
460  */
461 static long ipipeif_ioctl(struct v4l2_subdev *sd,
462                           unsigned int cmd, void *arg)
463 {
464         struct ipipeif_params *config = (struct ipipeif_params *)arg;
465         int ret = -ENOIOCTLCMD;
466
467         switch (cmd) {
468         case VIDIOC_VPFE_IPIPEIF_S_CONFIG:
469                 ret = ipipeif_set_config(sd, config);
470                 break;
471
472         case VIDIOC_VPFE_IPIPEIF_G_CONFIG:
473                 ret = ipipeif_get_config(sd, arg);
474                 break;
475         }
476         return ret;
477 }
478
479 /*
480  * ipipeif_s_ctrl() - Handle set control subdev method
481  * @ctrl: pointer to v4l2 control structure
482  */
483 static int ipipeif_s_ctrl(struct v4l2_ctrl *ctrl)
484 {
485         struct vpfe_ipipeif_device *ipipeif =
486                 container_of(ctrl->handler, struct vpfe_ipipeif_device, ctrls);
487
488         switch (ctrl->id) {
489         case VPFE_CID_DPCM_PREDICTOR:
490                 ipipeif->dpcm_predictor = ctrl->val;
491                 break;
492
493         case V4L2_CID_GAIN:
494                 ipipeif->gain = ctrl->val;
495                 break;
496
497         default:
498                 return -EINVAL;
499         }
500
501         return 0;
502 }
503
504 #define ENABLE_IPIPEIF          0x1
505
506 void vpfe_ipipeif_enable(struct vpfe_device *vpfe_dev)
507 {
508         struct vpfe_ipipeif_device *ipipeif = &vpfe_dev->vpfe_ipipeif;
509         void *ipipeif_base_addr = ipipeif->ipipeif_base_addr;
510         unsigned char val;
511
512         if (ipipeif->input != IPIPEIF_INPUT_MEMORY)
513                 return;
514
515         do {
516                 val = ipipeif_read(ipipeif_base_addr, IPIPEIF_ENABLE);
517         } while (val & 0x1);
518
519         ipipeif_write(ENABLE_IPIPEIF, ipipeif_base_addr, IPIPEIF_ENABLE);
520 }
521
522 /*
523  * ipipeif_set_stream() - Enable/Disable streaming on ipipeif subdev
524  * @sd: pointer to v4l2 subdev structure
525  * @enable: 1 == Enable, 0 == Disable
526  */
527 static int ipipeif_set_stream(struct v4l2_subdev *sd, int enable)
528 {
529         struct vpfe_ipipeif_device *ipipeif = v4l2_get_subdevdata(sd);
530         struct vpfe_device *vpfe_dev = to_vpfe_device(ipipeif);
531         int ret = 0;
532
533         if (!enable)
534                 return ret;
535
536         ret = ipipeif_hw_setup(sd);
537         if (!ret)
538                 vpfe_ipipeif_enable(vpfe_dev);
539
540         return ret;
541 }
542
543 /*
544  * ipipeif_enum_mbus_code() - Handle pixel format enumeration
545  * @sd: pointer to v4l2 subdev structure
546  * @fh: V4L2 subdev file handle
547  * @code: pointer to v4l2_subdev_mbus_code_enum structure
548  * return -EINVAL or zero on success
549  */
550 static int ipipeif_enum_mbus_code(struct v4l2_subdev *sd,
551                                   struct v4l2_subdev_fh *fh,
552                         struct v4l2_subdev_mbus_code_enum *code)
553 {
554         switch (code->pad) {
555         case IPIPEIF_PAD_SINK:
556                 if (code->index >= ARRAY_SIZE(ipipeif_input_fmts))
557                         return -EINVAL;
558
559                 code->code = ipipeif_input_fmts[code->index];
560                 break;
561
562         case IPIPEIF_PAD_SOURCE:
563                 if (code->index >= ARRAY_SIZE(ipipeif_output_fmts))
564                         return -EINVAL;
565
566                 code->code = ipipeif_output_fmts[code->index];
567                 break;
568
569         default:
570                 return -EINVAL;
571         }
572
573         return 0;
574 }
575
576 /*
577  * ipipeif_get_format() - Handle get format by pads subdev method
578  * @sd: pointer to v4l2 subdev structure
579  * @fh: V4L2 subdev file handle
580  * @fmt: pointer to v4l2 subdev format structure
581  */
582 static int
583 ipipeif_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
584                 struct v4l2_subdev_format *fmt)
585 {
586         struct vpfe_ipipeif_device *ipipeif = v4l2_get_subdevdata(sd);
587
588         if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE)
589                 fmt->format = ipipeif->formats[fmt->pad];
590         else
591                 fmt->format = *(v4l2_subdev_get_try_format(fh, fmt->pad));
592
593         return 0;
594 }
595
596 #define MIN_OUT_WIDTH                   32
597 #define MIN_OUT_HEIGHT                  32
598
599 /*
600  * ipipeif_try_format() - Handle try format by pad subdev method
601  * @ipipeif: VPFE ipipeif device.
602  * @fh: V4L2 subdev file handle.
603  * @pad: pad num.
604  * @fmt: pointer to v4l2 format structure.
605  * @which : wanted subdev format
606  */
607 static void
608 ipipeif_try_format(struct vpfe_ipipeif_device *ipipeif,
609                    struct v4l2_subdev_fh *fh, unsigned int pad,
610                    struct v4l2_mbus_framefmt *fmt,
611                    enum v4l2_subdev_format_whence which)
612 {
613         unsigned int max_out_height;
614         unsigned int max_out_width;
615         unsigned int i;
616
617         max_out_width = IPIPE_MAX_OUTPUT_WIDTH_A;
618         max_out_height = IPIPE_MAX_OUTPUT_HEIGHT_A;
619
620         if (pad == IPIPEIF_PAD_SINK) {
621                 for (i = 0; i < ARRAY_SIZE(ipipeif_input_fmts); i++)
622                         if (fmt->code == ipipeif_input_fmts[i])
623                                 break;
624
625                 /* If not found, use SBGGR10 as default */
626                 if (i >= ARRAY_SIZE(ipipeif_input_fmts))
627                         fmt->code = V4L2_MBUS_FMT_SGRBG12_1X12;
628         } else if (pad == IPIPEIF_PAD_SOURCE) {
629                 for (i = 0; i < ARRAY_SIZE(ipipeif_output_fmts); i++)
630                         if (fmt->code == ipipeif_output_fmts[i])
631                                 break;
632
633                 /* If not found, use UYVY as default */
634                 if (i >= ARRAY_SIZE(ipipeif_output_fmts))
635                         fmt->code = V4L2_MBUS_FMT_UYVY8_2X8;
636         }
637
638         fmt->width = clamp_t(u32, fmt->width, MIN_OUT_HEIGHT, max_out_width);
639         fmt->height = clamp_t(u32, fmt->height, MIN_OUT_WIDTH, max_out_height);
640 }
641
642 static int
643 ipipeif_enum_frame_size(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
644                      struct v4l2_subdev_frame_size_enum *fse)
645 {
646         struct vpfe_ipipeif_device *ipipeif = v4l2_get_subdevdata(sd);
647         struct v4l2_mbus_framefmt format;
648
649         if (fse->index != 0)
650                 return -EINVAL;
651
652         format.code = fse->code;
653         format.width = 1;
654         format.height = 1;
655         ipipeif_try_format(ipipeif, fh, fse->pad, &format,
656                            V4L2_SUBDEV_FORMAT_TRY);
657         fse->min_width = format.width;
658         fse->min_height = format.height;
659
660         if (format.code != fse->code)
661                 return -EINVAL;
662
663         format.code = fse->code;
664         format.width = -1;
665         format.height = -1;
666         ipipeif_try_format(ipipeif, fh, fse->pad, &format,
667                            V4L2_SUBDEV_FORMAT_TRY);
668         fse->max_width = format.width;
669         fse->max_height = format.height;
670
671         return 0;
672 }
673
674 /*
675  * __ipipeif_get_format() - helper function for getting ipipeif format
676  * @ipipeif: pointer to ipipeif private structure.
677  * @pad: pad number.
678  * @fh: V4L2 subdev file handle.
679  * @which: wanted subdev format.
680  *
681  */
682 static struct v4l2_mbus_framefmt *
683 __ipipeif_get_format(struct vpfe_ipipeif_device *ipipeif,
684                        struct v4l2_subdev_fh *fh, unsigned int pad,
685                        enum v4l2_subdev_format_whence which)
686 {
687         if (which == V4L2_SUBDEV_FORMAT_TRY)
688                 return v4l2_subdev_get_try_format(fh, pad);
689
690         return &ipipeif->formats[pad];
691 }
692
693 /*
694  * ipipeif_set_format() - Handle set format by pads subdev method
695  * @sd: pointer to v4l2 subdev structure
696  * @fh: V4L2 subdev file handle
697  * @fmt: pointer to v4l2 subdev format structure
698  * return -EINVAL or zero on success
699  */
700 static int
701 ipipeif_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
702                 struct v4l2_subdev_format *fmt)
703 {
704         struct vpfe_ipipeif_device *ipipeif = v4l2_get_subdevdata(sd);
705         struct v4l2_mbus_framefmt *format;
706
707         format = __ipipeif_get_format(ipipeif, fh, fmt->pad, fmt->which);
708         if (format == NULL)
709                 return -EINVAL;
710
711         ipipeif_try_format(ipipeif, fh, fmt->pad, &fmt->format, fmt->which);
712         *format = fmt->format;
713
714         if (fmt->which == V4L2_SUBDEV_FORMAT_TRY)
715                 return 0;
716
717         if (fmt->pad == IPIPEIF_PAD_SINK &&
718             ipipeif->input != IPIPEIF_INPUT_NONE)
719                 ipipeif->formats[fmt->pad] = fmt->format;
720         else if (fmt->pad == IPIPEIF_PAD_SOURCE &&
721                  ipipeif->output != IPIPEIF_OUTPUT_NONE)
722                 ipipeif->formats[fmt->pad] = fmt->format;
723         else
724                 return -EINVAL;
725
726         return 0;
727 }
728
729 static void ipipeif_set_default_config(struct vpfe_ipipeif_device *ipipeif)
730 {
731 #define WIDTH_I                 640
732 #define HEIGHT_I                480
733
734         const struct ipipeif_params ipipeif_defaults = {
735                 .clock_select = IPIPEIF_SDRAM_CLK,
736                 .ppln = WIDTH_I + 8,
737                 .lpfr = HEIGHT_I + 10,
738                 .rsz = 16,      /* resize ratio 16/rsz */
739                 .decimation = IPIPEIF_DECIMATION_OFF,
740                 .avg_filter = IPIPEIF_AVG_OFF,
741                 .if_5_1 = {
742                         .clk_div = {
743                                 .m = 1, /* clock = sdram clock * (m/n) */
744                                 .n = 6
745                         },
746                         .clip = 4095,
747                 },
748         };
749         memset(&ipipeif->config, 0, sizeof(struct ipipeif_params));
750         memcpy(&ipipeif->config, &ipipeif_defaults,
751                sizeof(struct ipipeif_params));
752 }
753
754 /*
755  * ipipeif_init_formats() - Initialize formats on all pads
756  * @sd: VPFE ipipeif V4L2 subdevice
757  * @fh: V4L2 subdev file handle
758  *
759  * Initialize all pad formats with default values. If fh is not NULL, try
760  * formats are initialized on the file handle. Otherwise active formats are
761  * initialized on the device.
762  */
763 static int
764 ipipeif_init_formats(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
765 {
766         struct vpfe_ipipeif_device *ipipeif = v4l2_get_subdevdata(sd);
767         struct v4l2_subdev_format format;
768
769         memset(&format, 0, sizeof(format));
770         format.pad = IPIPEIF_PAD_SINK;
771         format.which = fh ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
772         format.format.code = V4L2_MBUS_FMT_SGRBG12_1X12;
773         format.format.width = IPIPE_MAX_OUTPUT_WIDTH_A;
774         format.format.height = IPIPE_MAX_OUTPUT_HEIGHT_A;
775         ipipeif_set_format(sd, fh, &format);
776
777         memset(&format, 0, sizeof(format));
778         format.pad = IPIPEIF_PAD_SOURCE;
779         format.which = fh ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
780         format.format.code = V4L2_MBUS_FMT_UYVY8_2X8;
781         format.format.width = IPIPE_MAX_OUTPUT_WIDTH_A;
782         format.format.height = IPIPE_MAX_OUTPUT_HEIGHT_A;
783         ipipeif_set_format(sd, fh, &format);
784
785         ipipeif_set_default_config(ipipeif);
786
787         return 0;
788 }
789
790 /*
791  * ipipeif_video_in_queue() - ipipeif video in queue
792  * @vpfe_dev: vpfe device pointer
793  * @addr: buffer address
794  */
795 static int
796 ipipeif_video_in_queue(struct vpfe_device *vpfe_dev, unsigned long addr)
797 {
798         struct vpfe_ipipeif_device *ipipeif = &vpfe_dev->vpfe_ipipeif;
799         void *ipipeif_base_addr = ipipeif->ipipeif_base_addr;
800         unsigned int adofs;
801         u32 val;
802
803         if (ipipeif->input != IPIPEIF_INPUT_MEMORY)
804                 return -EINVAL;
805
806         switch (ipipeif->formats[IPIPEIF_PAD_SINK].code) {
807         case V4L2_MBUS_FMT_Y8_1X8:
808         case V4L2_MBUS_FMT_UV8_1X8:
809         case V4L2_MBUS_FMT_YDYUYDYV8_1X16:
810                 adofs = ipipeif->formats[IPIPEIF_PAD_SINK].width;
811                 break;
812
813         default:
814                 adofs = ipipeif->formats[IPIPEIF_PAD_SINK].width << 1;
815                 break;
816         }
817
818         /* adjust the line len to be a multiple of 32 */
819         adofs += 31;
820         adofs &= ~0x1f;
821         val = (adofs >> 5) & IPIPEIF_ADOFS_LSB_MASK;
822         ipipeif_write(val, ipipeif_base_addr, IPIPEIF_ADOFS);
823
824         /* lower sixteen bit */
825         val = (addr >> IPIPEIF_ADDRL_SHIFT) & IPIPEIF_ADDRL_MASK;
826         ipipeif_write(val, ipipeif_base_addr, IPIPEIF_ADDRL);
827
828         /* upper next seven bit */
829         val = (addr >> IPIPEIF_ADDRU_SHIFT) & IPIPEIF_ADDRU_MASK;
830         ipipeif_write(val, ipipeif_base_addr, IPIPEIF_ADDRU);
831
832         return 0;
833 }
834
835 /* subdev core operations */
836 static const struct v4l2_subdev_core_ops ipipeif_v4l2_core_ops = {
837         .ioctl = ipipeif_ioctl,
838 };
839
840 static const struct v4l2_ctrl_ops ipipeif_ctrl_ops = {
841         .s_ctrl = ipipeif_s_ctrl,
842 };
843
844 static const struct v4l2_ctrl_config vpfe_ipipeif_dpcm_pred = {
845         .ops = &ipipeif_ctrl_ops,
846         .id = VPFE_CID_DPCM_PREDICTOR,
847         .name = "DPCM Predictor",
848         .type = V4L2_CTRL_TYPE_INTEGER,
849         .min = 0,
850         .max = 1,
851         .step = 1,
852         .def = 0,
853 };
854
855 /* subdev file operations */
856 static const struct v4l2_subdev_internal_ops ipipeif_v4l2_internal_ops = {
857         .open = ipipeif_init_formats,
858 };
859
860 /* subdev video operations */
861 static const struct v4l2_subdev_video_ops ipipeif_v4l2_video_ops = {
862         .s_stream = ipipeif_set_stream,
863 };
864
865 /* subdev pad operations */
866 static const struct v4l2_subdev_pad_ops ipipeif_v4l2_pad_ops = {
867         .enum_mbus_code = ipipeif_enum_mbus_code,
868         .enum_frame_size = ipipeif_enum_frame_size,
869         .get_fmt = ipipeif_get_format,
870         .set_fmt = ipipeif_set_format,
871 };
872
873 /* subdev operations */
874 static const struct v4l2_subdev_ops ipipeif_v4l2_ops = {
875         .core = &ipipeif_v4l2_core_ops,
876         .video = &ipipeif_v4l2_video_ops,
877         .pad = &ipipeif_v4l2_pad_ops,
878 };
879
880 static const struct vpfe_video_operations video_in_ops = {
881         .queue = ipipeif_video_in_queue,
882 };
883
884 static int
885 ipipeif_link_setup(struct media_entity *entity, const struct media_pad *local,
886                 const struct media_pad *remote, u32 flags)
887 {
888         struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
889         struct vpfe_ipipeif_device *ipipeif = v4l2_get_subdevdata(sd);
890         struct vpfe_device *vpfe = to_vpfe_device(ipipeif);
891
892         switch (local->index | media_entity_type(remote->entity)) {
893         case IPIPEIF_PAD_SINK | MEDIA_ENT_T_DEVNODE:
894                 /* Single shot mode */
895                 if (!(flags & MEDIA_LNK_FL_ENABLED)) {
896                         ipipeif->input = IPIPEIF_INPUT_NONE;
897                         break;
898                 }
899                 ipipeif->input = IPIPEIF_INPUT_MEMORY;
900                 break;
901
902         case IPIPEIF_PAD_SINK | MEDIA_ENT_T_V4L2_SUBDEV:
903                 /* read from isif */
904                 if (!(flags & MEDIA_LNK_FL_ENABLED)) {
905                         ipipeif->input = IPIPEIF_INPUT_NONE;
906                         break;
907                 }
908                 if (ipipeif->input != IPIPEIF_INPUT_NONE)
909                         return -EBUSY;
910
911                 ipipeif->input = IPIPEIF_INPUT_ISIF;
912                 break;
913
914         case IPIPEIF_PAD_SOURCE | MEDIA_ENT_T_V4L2_SUBDEV:
915                 if (!(flags & MEDIA_LNK_FL_ENABLED)) {
916                         ipipeif->output = IPIPEIF_OUTPUT_NONE;
917                         break;
918                 }
919                 if (remote->entity == &vpfe->vpfe_ipipe.subdev.entity)
920                         /* connencted to ipipe */
921                         ipipeif->output = IPIPEIF_OUTPUT_IPIPE;
922                 else if (remote->entity == &vpfe->vpfe_resizer.
923                         crop_resizer.subdev.entity)
924                         /* connected to resizer */
925                         ipipeif->output = IPIPEIF_OUTPUT_RESIZER;
926                 else
927                         return -EINVAL;
928                 break;
929
930         default:
931                 return -EINVAL;
932         }
933
934         return 0;
935 }
936
937 static const struct media_entity_operations ipipeif_media_ops = {
938         .link_setup = ipipeif_link_setup,
939 };
940
941 /*
942  * vpfe_ipipeif_unregister_entities() - Unregister entity
943  * @ipipeif - pointer to ipipeif subdevice structure.
944  */
945 void vpfe_ipipeif_unregister_entities(struct vpfe_ipipeif_device *ipipeif)
946 {
947         /* unregister video device */
948         vpfe_video_unregister(&ipipeif->video_in);
949
950         /* cleanup entity */
951         media_entity_cleanup(&ipipeif->subdev.entity);
952         /* unregister subdev */
953         v4l2_device_unregister_subdev(&ipipeif->subdev);
954 }
955
956 int
957 vpfe_ipipeif_register_entities(struct vpfe_ipipeif_device *ipipeif,
958                                struct v4l2_device *vdev)
959 {
960         struct vpfe_device *vpfe_dev = to_vpfe_device(ipipeif);
961         unsigned int flags;
962         int ret;
963
964         /* Register the subdev */
965         ret = v4l2_device_register_subdev(vdev, &ipipeif->subdev);
966         if (ret < 0)
967                 return ret;
968
969         ret = vpfe_video_register(&ipipeif->video_in, vdev);
970         if (ret) {
971                 pr_err("Failed to register ipipeif video-in device\n");
972                 goto fail;
973         }
974         ipipeif->video_in.vpfe_dev = vpfe_dev;
975
976         flags = 0;
977         ret = media_entity_create_link(&ipipeif->video_in.video_dev.entity, 0,
978                                         &ipipeif->subdev.entity, 0, flags);
979         if (ret < 0)
980                 goto fail;
981
982         return 0;
983 fail:
984         v4l2_device_unregister_subdev(&ipipeif->subdev);
985
986         return ret;
987 }
988
989 #define IPIPEIF_GAIN_HIGH               0x3ff
990 #define IPIPEIF_DEFAULT_GAIN            0x200
991
992 int vpfe_ipipeif_init(struct vpfe_ipipeif_device *ipipeif,
993                       struct platform_device *pdev)
994 {
995         struct v4l2_subdev *sd = &ipipeif->subdev;
996         struct media_pad *pads = &ipipeif->pads[0];
997         struct media_entity *me = &sd->entity;
998         static resource_size_t  res_len;
999         struct resource *res;
1000         int ret;
1001
1002         res = platform_get_resource(pdev, IORESOURCE_MEM, 3);
1003         if (!res)
1004                 return -ENOENT;
1005
1006         res_len = resource_size(res);
1007         res = request_mem_region(res->start, res_len, res->name);
1008         if (!res)
1009                 return -EBUSY;
1010
1011         ipipeif->ipipeif_base_addr = ioremap_nocache(res->start, res_len);
1012         if (!ipipeif->ipipeif_base_addr) {
1013                 ret =  -EBUSY;
1014                 goto fail;
1015         }
1016
1017         v4l2_subdev_init(sd, &ipipeif_v4l2_ops);
1018
1019         sd->internal_ops = &ipipeif_v4l2_internal_ops;
1020         strlcpy(sd->name, "DAVINCI IPIPEIF", sizeof(sd->name));
1021         sd->grp_id = 1 << 16;   /* group ID for davinci subdevs */
1022
1023         v4l2_set_subdevdata(sd, ipipeif);
1024
1025         sd->flags |= V4L2_SUBDEV_FL_HAS_EVENTS | V4L2_SUBDEV_FL_HAS_DEVNODE;
1026         pads[IPIPEIF_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
1027         pads[IPIPEIF_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
1028         ipipeif->input = IPIPEIF_INPUT_NONE;
1029         ipipeif->output = IPIPEIF_OUTPUT_NONE;
1030         me->ops = &ipipeif_media_ops;
1031
1032         ret = media_entity_init(me, IPIPEIF_NUM_PADS, pads, 0);
1033         if (ret)
1034                 goto fail;
1035
1036         v4l2_ctrl_handler_init(&ipipeif->ctrls, 2);
1037         v4l2_ctrl_new_std(&ipipeif->ctrls, &ipipeif_ctrl_ops,
1038                           V4L2_CID_GAIN, 0,
1039                           IPIPEIF_GAIN_HIGH, 1, IPIPEIF_DEFAULT_GAIN);
1040         v4l2_ctrl_new_custom(&ipipeif->ctrls, &vpfe_ipipeif_dpcm_pred, NULL);
1041         v4l2_ctrl_handler_setup(&ipipeif->ctrls);
1042         sd->ctrl_handler = &ipipeif->ctrls;
1043
1044         ipipeif->video_in.ops = &video_in_ops;
1045         ipipeif->video_in.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
1046         ret = vpfe_video_init(&ipipeif->video_in, "IPIPEIF");
1047         if (ret) {
1048                 pr_err("Failed to init IPIPEIF video-in device\n");
1049                 goto fail;
1050         }
1051         ipipeif_set_default_config(ipipeif);
1052         return 0;
1053 fail:
1054         release_mem_region(res->start, res_len);
1055         return ret;
1056 }
1057
1058 void
1059 vpfe_ipipeif_cleanup(struct vpfe_ipipeif_device *ipipeif,
1060                      struct platform_device *pdev)
1061 {
1062         struct resource *res;
1063
1064         v4l2_ctrl_handler_free(&ipipeif->ctrls);
1065         iounmap(ipipeif->ipipeif_base_addr);
1066         res = platform_get_resource(pdev, IORESOURCE_MEM, 3);
1067         if (res)
1068                 release_mem_region(res->start, resource_size(res));
1069
1070 }