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