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