[media] omap3/omap4/davinci: get rid of MEDIA_ENT_T_V4L2_SUBDEV abuse
[deliverable/linux.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 *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 == 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 *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
314 case IPIPEIF_SDRAM_YUV:
315 /* Set clock divider */
316 if (params.clock_select == IPIPEIF_SDRAM_CLK) {
317 val = ipipeif_read(ipipeif_base_addr, IPIPEIF_CLKDIV);
318 val |= (params.if_5_1.clk_div.m - 1) <<
319 IPIPEIF_CLKDIV_M_SHIFT;
320 val |= (params.if_5_1.clk_div.n - 1);
321 ipipeif_write(val, ipipeif_base_addr, IPIPEIF_CLKDIV);
322 }
323 break;
324
325 case IPIPEIF_CCDC:
326 case IPIPEIF_CCDC_DARKFM:
327 /* set DPC */
328 ipipeif_config_dpc(ipipeif_base_addr, &params.if_5_1.dpc);
329
330 /* Set DF gain & threshold control */
331 val = 0;
332 if (params.if_5_1.df_gain_en) {
333 val = params.if_5_1.df_gain_thr &
334 IPIPEIF_DF_GAIN_THR_MASK;
335 ipipeif_write(val, ipipeif_base_addr, IPIPEIF_DFSGTH);
336 val = (params.if_5_1.df_gain_en & 1) <<
337 IPIPEIF_DF_GAIN_EN_SHIFT;
338 val |= params.if_5_1.df_gain &
339 IPIPEIF_DF_GAIN_MASK;
340 }
341 ipipeif_write(val, ipipeif_base_addr, IPIPEIF_DFSGVL);
342 /* configure CFG2 */
343 val = VPFE_PINPOL_POSITIVE << IPIPEIF_CFG2_HDPOL_SHIFT;
344 val |= VPFE_PINPOL_POSITIVE << IPIPEIF_CFG2_VDPOL_SHIFT;
345
346 switch (isif_port_if) {
347 case MEDIA_BUS_FMT_YUYV8_1X16:
348 case MEDIA_BUS_FMT_YUYV10_1X20:
349 RESETBIT(val, IPIPEIF_CFG2_YUV8_SHIFT);
350 SETBIT(val, IPIPEIF_CFG2_YUV16_SHIFT);
351 break;
352
353 case MEDIA_BUS_FMT_YUYV8_2X8:
354 case MEDIA_BUS_FMT_UYVY8_2X8:
355 case MEDIA_BUS_FMT_Y8_1X8:
356 case MEDIA_BUS_FMT_YUYV10_2X10:
357 SETBIT(val, IPIPEIF_CFG2_YUV8_SHIFT);
358 SETBIT(val, IPIPEIF_CFG2_YUV16_SHIFT);
359 val |= IPIPEIF_CBCR_Y << IPIPEIF_CFG2_YUV8P_SHIFT;
360 break;
361
362 default:
363 /* Bayer */
364 ipipeif_write(params.if_5_1.clip, ipipeif_base_addr,
365 IPIPEIF_OCLIP);
366 }
367 ipipeif_write(val, ipipeif_base_addr, IPIPEIF_CFG2);
368 break;
369
370 default:
371 return -EINVAL;
372 }
373
374 return 0;
375 }
376
377 static int
378 ipipeif_set_config(struct v4l2_subdev *sd, struct ipipeif_params *config)
379 {
380 struct vpfe_ipipeif_device *ipipeif = v4l2_get_subdevdata(sd);
381 struct device *dev = ipipeif->subdev.v4l2_dev->dev;
382
383 if (!config) {
384 dev_err(dev, "Invalid configuration pointer\n");
385 return -EINVAL;
386 }
387
388 ipipeif->config.clock_select = config->clock_select;
389 ipipeif->config.ppln = config->ppln;
390 ipipeif->config.lpfr = config->lpfr;
391 ipipeif->config.rsz = config->rsz;
392 ipipeif->config.decimation = config->decimation;
393 if (ipipeif->config.decimation &&
394 (ipipeif->config.rsz < IPIPEIF_RSZ_MIN ||
395 ipipeif->config.rsz > IPIPEIF_RSZ_MAX)) {
396 dev_err(dev, "rsz range is %d to %d\n",
397 IPIPEIF_RSZ_MIN, IPIPEIF_RSZ_MAX);
398 return -EINVAL;
399 }
400
401 ipipeif->config.avg_filter = config->avg_filter;
402
403 ipipeif->config.if_5_1.df_gain_thr = config->if_5_1.df_gain_thr;
404 ipipeif->config.if_5_1.df_gain = config->if_5_1.df_gain;
405 ipipeif->config.if_5_1.df_gain_en = config->if_5_1.df_gain_en;
406
407 ipipeif->config.if_5_1.rsz_start = config->if_5_1.rsz_start;
408 ipipeif->config.if_5_1.align_sync = config->if_5_1.align_sync;
409 ipipeif->config.if_5_1.clip = config->if_5_1.clip;
410
411 ipipeif->config.if_5_1.dpc.en = config->if_5_1.dpc.en;
412 ipipeif->config.if_5_1.dpc.thr = config->if_5_1.dpc.thr;
413
414 ipipeif->config.if_5_1.clk_div.m = config->if_5_1.clk_div.m;
415 ipipeif->config.if_5_1.clk_div.n = config->if_5_1.clk_div.n;
416
417 return 0;
418 }
419
420 static int
421 ipipeif_get_config(struct v4l2_subdev *sd, void __user *arg)
422 {
423 struct vpfe_ipipeif_device *ipipeif = v4l2_get_subdevdata(sd);
424 struct ipipeif_params *config = arg;
425 struct device *dev = ipipeif->subdev.v4l2_dev->dev;
426
427 if (!arg) {
428 dev_err(dev, "Invalid configuration pointer\n");
429 return -EINVAL;
430 }
431
432 config->clock_select = ipipeif->config.clock_select;
433 config->ppln = ipipeif->config.ppln;
434 config->lpfr = ipipeif->config.lpfr;
435 config->rsz = ipipeif->config.rsz;
436 config->decimation = ipipeif->config.decimation;
437 config->avg_filter = ipipeif->config.avg_filter;
438
439 config->if_5_1.df_gain_thr = ipipeif->config.if_5_1.df_gain_thr;
440 config->if_5_1.df_gain = ipipeif->config.if_5_1.df_gain;
441 config->if_5_1.df_gain_en = ipipeif->config.if_5_1.df_gain_en;
442
443 config->if_5_1.rsz_start = ipipeif->config.if_5_1.rsz_start;
444 config->if_5_1.align_sync = ipipeif->config.if_5_1.align_sync;
445 config->if_5_1.clip = ipipeif->config.if_5_1.clip;
446
447 config->if_5_1.dpc.en = ipipeif->config.if_5_1.dpc.en;
448 config->if_5_1.dpc.thr = ipipeif->config.if_5_1.dpc.thr;
449
450 config->if_5_1.clk_div.m = ipipeif->config.if_5_1.clk_div.m;
451 config->if_5_1.clk_div.n = ipipeif->config.if_5_1.clk_div.n;
452
453 return 0;
454 }
455
456 /*
457 * ipipeif_ioctl() - Handle ipipeif module private ioctl's
458 * @sd: pointer to v4l2 subdev structure
459 * @cmd: configuration command
460 * @arg: configuration argument
461 */
462 static long ipipeif_ioctl(struct v4l2_subdev *sd,
463 unsigned int cmd, void *arg)
464 {
465 struct ipipeif_params *config = arg;
466 int ret = -ENOIOCTLCMD;
467
468 switch (cmd) {
469 case VIDIOC_VPFE_IPIPEIF_S_CONFIG:
470 ret = ipipeif_set_config(sd, config);
471 break;
472
473 case VIDIOC_VPFE_IPIPEIF_G_CONFIG:
474 ret = ipipeif_get_config(sd, arg);
475 break;
476 }
477 return ret;
478 }
479
480 /*
481 * ipipeif_s_ctrl() - Handle set control subdev method
482 * @ctrl: pointer to v4l2 control structure
483 */
484 static int ipipeif_s_ctrl(struct v4l2_ctrl *ctrl)
485 {
486 struct vpfe_ipipeif_device *ipipeif =
487 container_of(ctrl->handler, struct vpfe_ipipeif_device, ctrls);
488
489 switch (ctrl->id) {
490 case VPFE_CID_DPCM_PREDICTOR:
491 ipipeif->dpcm_predictor = ctrl->val;
492 break;
493
494 case V4L2_CID_GAIN:
495 ipipeif->gain = ctrl->val;
496 break;
497
498 default:
499 return -EINVAL;
500 }
501
502 return 0;
503 }
504
505 #define ENABLE_IPIPEIF 0x1
506
507 void vpfe_ipipeif_enable(struct vpfe_device *vpfe_dev)
508 {
509 struct vpfe_ipipeif_device *ipipeif = &vpfe_dev->vpfe_ipipeif;
510 void *ipipeif_base_addr = ipipeif->ipipeif_base_addr;
511 unsigned char val;
512
513 if (ipipeif->input != IPIPEIF_INPUT_MEMORY)
514 return;
515
516 do {
517 val = ipipeif_read(ipipeif_base_addr, IPIPEIF_ENABLE);
518 } while (val & 0x1);
519
520 ipipeif_write(ENABLE_IPIPEIF, ipipeif_base_addr, IPIPEIF_ENABLE);
521 }
522
523 /*
524 * ipipeif_set_stream() - Enable/Disable streaming on ipipeif subdev
525 * @sd: pointer to v4l2 subdev structure
526 * @enable: 1 == Enable, 0 == Disable
527 */
528 static int ipipeif_set_stream(struct v4l2_subdev *sd, int enable)
529 {
530 struct vpfe_ipipeif_device *ipipeif = v4l2_get_subdevdata(sd);
531 struct vpfe_device *vpfe_dev = to_vpfe_device(ipipeif);
532 int ret = 0;
533
534 if (!enable)
535 return ret;
536
537 ret = ipipeif_hw_setup(sd);
538 if (!ret)
539 vpfe_ipipeif_enable(vpfe_dev);
540
541 return ret;
542 }
543
544 /*
545 * ipipeif_enum_mbus_code() - Handle pixel format enumeration
546 * @sd: pointer to v4l2 subdev structure
547 * @cfg: V4L2 subdev pad config
548 * @code: pointer to v4l2_subdev_mbus_code_enum structure
549 * return -EINVAL or zero on success
550 */
551 static int ipipeif_enum_mbus_code(struct v4l2_subdev *sd,
552 struct v4l2_subdev_pad_config *cfg,
553 struct v4l2_subdev_mbus_code_enum *code)
554 {
555 switch (code->pad) {
556 case IPIPEIF_PAD_SINK:
557 if (code->index >= ARRAY_SIZE(ipipeif_input_fmts))
558 return -EINVAL;
559
560 code->code = ipipeif_input_fmts[code->index];
561 break;
562
563 case IPIPEIF_PAD_SOURCE:
564 if (code->index >= ARRAY_SIZE(ipipeif_output_fmts))
565 return -EINVAL;
566
567 code->code = ipipeif_output_fmts[code->index];
568 break;
569
570 default:
571 return -EINVAL;
572 }
573
574 return 0;
575 }
576
577 /*
578 * ipipeif_get_format() - Handle get format by pads subdev method
579 * @sd: pointer to v4l2 subdev structure
580 * @cfg: V4L2 subdev pad config
581 * @fmt: pointer to v4l2 subdev format structure
582 */
583 static int
584 ipipeif_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg,
585 struct v4l2_subdev_format *fmt)
586 {
587 struct vpfe_ipipeif_device *ipipeif = v4l2_get_subdevdata(sd);
588
589 if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE)
590 fmt->format = ipipeif->formats[fmt->pad];
591 else
592 fmt->format = *(v4l2_subdev_get_try_format(sd, cfg, fmt->pad));
593
594 return 0;
595 }
596
597 #define MIN_OUT_WIDTH 32
598 #define MIN_OUT_HEIGHT 32
599
600 /*
601 * ipipeif_try_format() - Handle try format by pad subdev method
602 * @ipipeif: VPFE ipipeif device.
603 * @cfg: V4L2 subdev pad config
604 * @pad: pad num.
605 * @fmt: pointer to v4l2 format structure.
606 * @which : wanted subdev format
607 */
608 static void
609 ipipeif_try_format(struct vpfe_ipipeif_device *ipipeif,
610 struct v4l2_subdev_pad_config *cfg, unsigned int pad,
611 struct v4l2_mbus_framefmt *fmt,
612 enum v4l2_subdev_format_whence which)
613 {
614 unsigned int max_out_height;
615 unsigned int max_out_width;
616 unsigned int i;
617
618 max_out_width = IPIPE_MAX_OUTPUT_WIDTH_A;
619 max_out_height = IPIPE_MAX_OUTPUT_HEIGHT_A;
620
621 if (pad == IPIPEIF_PAD_SINK) {
622 for (i = 0; i < ARRAY_SIZE(ipipeif_input_fmts); i++)
623 if (fmt->code == ipipeif_input_fmts[i])
624 break;
625
626 /* If not found, use SBGGR10 as default */
627 if (i >= ARRAY_SIZE(ipipeif_input_fmts))
628 fmt->code = MEDIA_BUS_FMT_SGRBG12_1X12;
629 } else if (pad == IPIPEIF_PAD_SOURCE) {
630 for (i = 0; i < ARRAY_SIZE(ipipeif_output_fmts); i++)
631 if (fmt->code == ipipeif_output_fmts[i])
632 break;
633
634 /* If not found, use UYVY as default */
635 if (i >= ARRAY_SIZE(ipipeif_output_fmts))
636 fmt->code = MEDIA_BUS_FMT_UYVY8_2X8;
637 }
638
639 fmt->width = clamp_t(u32, fmt->width, MIN_OUT_HEIGHT, max_out_width);
640 fmt->height = clamp_t(u32, fmt->height, MIN_OUT_WIDTH, max_out_height);
641 }
642
643 static int
644 ipipeif_enum_frame_size(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg,
645 struct v4l2_subdev_frame_size_enum *fse)
646 {
647 struct vpfe_ipipeif_device *ipipeif = v4l2_get_subdevdata(sd);
648 struct v4l2_mbus_framefmt format;
649
650 if (fse->index != 0)
651 return -EINVAL;
652
653 format.code = fse->code;
654 format.width = 1;
655 format.height = 1;
656 ipipeif_try_format(ipipeif, cfg, fse->pad, &format, fse->which);
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, cfg, fse->pad, &format, fse->which);
667 fse->max_width = format.width;
668 fse->max_height = format.height;
669
670 return 0;
671 }
672
673 /*
674 * __ipipeif_get_format() - helper function for getting ipipeif format
675 * @ipipeif: pointer to ipipeif private structure.
676 * @cfg: V4L2 subdev pad config
677 * @pad: pad number.
678 * @which: wanted subdev format.
679 *
680 */
681 static struct v4l2_mbus_framefmt *
682 __ipipeif_get_format(struct vpfe_ipipeif_device *ipipeif,
683 struct v4l2_subdev_pad_config *cfg, unsigned int pad,
684 enum v4l2_subdev_format_whence which)
685 {
686 if (which == V4L2_SUBDEV_FORMAT_TRY)
687 return v4l2_subdev_get_try_format(&ipipeif->subdev, cfg, pad);
688
689 return &ipipeif->formats[pad];
690 }
691
692 /*
693 * ipipeif_set_format() - Handle set format by pads subdev method
694 * @sd: pointer to v4l2 subdev structure
695 * @cfg: V4L2 subdev pad config
696 * @fmt: pointer to v4l2 subdev format structure
697 * return -EINVAL or zero on success
698 */
699 static int
700 ipipeif_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg,
701 struct v4l2_subdev_format *fmt)
702 {
703 struct vpfe_ipipeif_device *ipipeif = v4l2_get_subdevdata(sd);
704 struct v4l2_mbus_framefmt *format;
705
706 format = __ipipeif_get_format(ipipeif, cfg, fmt->pad, fmt->which);
707 if (format == NULL)
708 return -EINVAL;
709
710 ipipeif_try_format(ipipeif, cfg, fmt->pad, &fmt->format, fmt->which);
711 *format = fmt->format;
712
713 if (fmt->which == V4L2_SUBDEV_FORMAT_TRY)
714 return 0;
715
716 if (fmt->pad == IPIPEIF_PAD_SINK &&
717 ipipeif->input != IPIPEIF_INPUT_NONE)
718 ipipeif->formats[fmt->pad] = fmt->format;
719 else if (fmt->pad == IPIPEIF_PAD_SOURCE &&
720 ipipeif->output != IPIPEIF_OUTPUT_NONE)
721 ipipeif->formats[fmt->pad] = fmt->format;
722 else
723 return -EINVAL;
724
725 return 0;
726 }
727
728 static void ipipeif_set_default_config(struct vpfe_ipipeif_device *ipipeif)
729 {
730 #define WIDTH_I 640
731 #define HEIGHT_I 480
732
733 const struct ipipeif_params ipipeif_defaults = {
734 .clock_select = IPIPEIF_SDRAM_CLK,
735 .ppln = WIDTH_I + 8,
736 .lpfr = HEIGHT_I + 10,
737 .rsz = 16, /* resize ratio 16/rsz */
738 .decimation = IPIPEIF_DECIMATION_OFF,
739 .avg_filter = IPIPEIF_AVG_OFF,
740 .if_5_1 = {
741 .clk_div = {
742 .m = 1, /* clock = sdram clock * (m/n) */
743 .n = 6
744 },
745 .clip = 4095,
746 },
747 };
748 memcpy(&ipipeif->config, &ipipeif_defaults,
749 sizeof(struct ipipeif_params));
750 }
751
752 /*
753 * ipipeif_init_formats() - Initialize formats on all pads
754 * @sd: VPFE ipipeif V4L2 subdevice
755 * @fh: V4L2 subdev file handle
756 *
757 * Initialize all pad formats with default values. Try formats are initialized
758 * on the file handle.
759 */
760 static int
761 ipipeif_init_formats(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
762 {
763 struct vpfe_ipipeif_device *ipipeif = v4l2_get_subdevdata(sd);
764 struct v4l2_subdev_format format;
765
766 memset(&format, 0, sizeof(format));
767 format.pad = IPIPEIF_PAD_SINK;
768 format.which = V4L2_SUBDEV_FORMAT_TRY;
769 format.format.code = MEDIA_BUS_FMT_SGRBG12_1X12;
770 format.format.width = IPIPE_MAX_OUTPUT_WIDTH_A;
771 format.format.height = IPIPE_MAX_OUTPUT_HEIGHT_A;
772 ipipeif_set_format(sd, fh->pad, &format);
773
774 memset(&format, 0, sizeof(format));
775 format.pad = IPIPEIF_PAD_SOURCE;
776 format.which = V4L2_SUBDEV_FORMAT_TRY;
777 format.format.code = MEDIA_BUS_FMT_UYVY8_2X8;
778 format.format.width = IPIPE_MAX_OUTPUT_WIDTH_A;
779 format.format.height = IPIPE_MAX_OUTPUT_HEIGHT_A;
780 ipipeif_set_format(sd, fh->pad, &format);
781
782 ipipeif_set_default_config(ipipeif);
783
784 return 0;
785 }
786
787 /*
788 * ipipeif_video_in_queue() - ipipeif video in queue
789 * @vpfe_dev: vpfe device pointer
790 * @addr: buffer address
791 */
792 static int
793 ipipeif_video_in_queue(struct vpfe_device *vpfe_dev, unsigned long addr)
794 {
795 struct vpfe_ipipeif_device *ipipeif = &vpfe_dev->vpfe_ipipeif;
796 void *ipipeif_base_addr = ipipeif->ipipeif_base_addr;
797 unsigned int adofs;
798 u32 val;
799
800 if (ipipeif->input != IPIPEIF_INPUT_MEMORY)
801 return -EINVAL;
802
803 switch (ipipeif->formats[IPIPEIF_PAD_SINK].code) {
804 case MEDIA_BUS_FMT_Y8_1X8:
805 case MEDIA_BUS_FMT_UV8_1X8:
806 case MEDIA_BUS_FMT_YDYUYDYV8_1X16:
807 adofs = ipipeif->formats[IPIPEIF_PAD_SINK].width;
808 break;
809
810 default:
811 adofs = ipipeif->formats[IPIPEIF_PAD_SINK].width << 1;
812 break;
813 }
814
815 /* adjust the line len to be a multiple of 32 */
816 adofs += 31;
817 adofs &= ~0x1f;
818 val = (adofs >> 5) & IPIPEIF_ADOFS_LSB_MASK;
819 ipipeif_write(val, ipipeif_base_addr, IPIPEIF_ADOFS);
820
821 /* lower sixteen bit */
822 val = (addr >> IPIPEIF_ADDRL_SHIFT) & IPIPEIF_ADDRL_MASK;
823 ipipeif_write(val, ipipeif_base_addr, IPIPEIF_ADDRL);
824
825 /* upper next seven bit */
826 val = (addr >> IPIPEIF_ADDRU_SHIFT) & IPIPEIF_ADDRU_MASK;
827 ipipeif_write(val, ipipeif_base_addr, IPIPEIF_ADDRU);
828
829 return 0;
830 }
831
832 /* subdev core operations */
833 static const struct v4l2_subdev_core_ops ipipeif_v4l2_core_ops = {
834 .ioctl = ipipeif_ioctl,
835 };
836
837 static const struct v4l2_ctrl_ops ipipeif_ctrl_ops = {
838 .s_ctrl = ipipeif_s_ctrl,
839 };
840
841 static const struct v4l2_ctrl_config vpfe_ipipeif_dpcm_pred = {
842 .ops = &ipipeif_ctrl_ops,
843 .id = VPFE_CID_DPCM_PREDICTOR,
844 .name = "DPCM Predictor",
845 .type = V4L2_CTRL_TYPE_INTEGER,
846 .min = 0,
847 .max = 1,
848 .step = 1,
849 .def = 0,
850 };
851
852 /* subdev file operations */
853 static const struct v4l2_subdev_internal_ops ipipeif_v4l2_internal_ops = {
854 .open = ipipeif_init_formats,
855 };
856
857 /* subdev video operations */
858 static const struct v4l2_subdev_video_ops ipipeif_v4l2_video_ops = {
859 .s_stream = ipipeif_set_stream,
860 };
861
862 /* subdev pad operations */
863 static const struct v4l2_subdev_pad_ops ipipeif_v4l2_pad_ops = {
864 .enum_mbus_code = ipipeif_enum_mbus_code,
865 .enum_frame_size = ipipeif_enum_frame_size,
866 .get_fmt = ipipeif_get_format,
867 .set_fmt = ipipeif_set_format,
868 };
869
870 /* subdev operations */
871 static const struct v4l2_subdev_ops ipipeif_v4l2_ops = {
872 .core = &ipipeif_v4l2_core_ops,
873 .video = &ipipeif_v4l2_video_ops,
874 .pad = &ipipeif_v4l2_pad_ops,
875 };
876
877 static const struct vpfe_video_operations video_in_ops = {
878 .queue = ipipeif_video_in_queue,
879 };
880
881 static int
882 ipipeif_link_setup(struct media_entity *entity, const struct media_pad *local,
883 const struct media_pad *remote, u32 flags)
884 {
885 struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
886 struct vpfe_ipipeif_device *ipipeif = v4l2_get_subdevdata(sd);
887 struct vpfe_device *vpfe = to_vpfe_device(ipipeif);
888 int index = local->index;
889
890 /* FIXME: this is actually a hack! */
891 if (is_media_entity_v4l2_subdev(remote->entity))
892 index |= 2 << 16;
893
894 switch (index) {
895 case IPIPEIF_PAD_SINK:
896 /* Single shot mode */
897 if (!(flags & MEDIA_LNK_FL_ENABLED)) {
898 ipipeif->input = IPIPEIF_INPUT_NONE;
899 break;
900 }
901 ipipeif->input = IPIPEIF_INPUT_MEMORY;
902 break;
903
904 case IPIPEIF_PAD_SINK | 2 << 16:
905 /* read from isif */
906 if (!(flags & MEDIA_LNK_FL_ENABLED)) {
907 ipipeif->input = IPIPEIF_INPUT_NONE;
908 break;
909 }
910 if (ipipeif->input != IPIPEIF_INPUT_NONE)
911 return -EBUSY;
912
913 ipipeif->input = IPIPEIF_INPUT_ISIF;
914 break;
915
916 case IPIPEIF_PAD_SOURCE | 2 << 16:
917 if (!(flags & MEDIA_LNK_FL_ENABLED)) {
918 ipipeif->output = IPIPEIF_OUTPUT_NONE;
919 break;
920 }
921 if (remote->entity == &vpfe->vpfe_ipipe.subdev.entity)
922 /* connencted to ipipe */
923 ipipeif->output = IPIPEIF_OUTPUT_IPIPE;
924 else if (remote->entity == &vpfe->vpfe_resizer.
925 crop_resizer.subdev.entity)
926 /* connected to resizer */
927 ipipeif->output = IPIPEIF_OUTPUT_RESIZER;
928 else
929 return -EINVAL;
930 break;
931
932 default:
933 return -EINVAL;
934 }
935
936 return 0;
937 }
938
939 static const struct media_entity_operations ipipeif_media_ops = {
940 .link_setup = ipipeif_link_setup,
941 };
942
943 /*
944 * vpfe_ipipeif_unregister_entities() - Unregister entity
945 * @ipipeif - pointer to ipipeif subdevice structure.
946 */
947 void vpfe_ipipeif_unregister_entities(struct vpfe_ipipeif_device *ipipeif)
948 {
949 /* unregister video device */
950 vpfe_video_unregister(&ipipeif->video_in);
951
952 /* unregister subdev */
953 v4l2_device_unregister_subdev(&ipipeif->subdev);
954 /* cleanup entity */
955 media_entity_cleanup(&ipipeif->subdev.entity);
956 }
957
958 int
959 vpfe_ipipeif_register_entities(struct vpfe_ipipeif_device *ipipeif,
960 struct v4l2_device *vdev)
961 {
962 struct vpfe_device *vpfe_dev = to_vpfe_device(ipipeif);
963 unsigned int flags;
964 int ret;
965
966 /* Register the subdev */
967 ret = v4l2_device_register_subdev(vdev, &ipipeif->subdev);
968 if (ret < 0)
969 return ret;
970
971 ret = vpfe_video_register(&ipipeif->video_in, vdev);
972 if (ret) {
973 pr_err("Failed to register ipipeif video-in device\n");
974 goto fail;
975 }
976 ipipeif->video_in.vpfe_dev = vpfe_dev;
977
978 flags = 0;
979 ret = media_create_pad_link(&ipipeif->video_in.video_dev.entity, 0,
980 &ipipeif->subdev.entity, 0, flags);
981 if (ret < 0)
982 goto fail;
983
984 return 0;
985 fail:
986 v4l2_device_unregister_subdev(&ipipeif->subdev);
987
988 return ret;
989 }
990
991 #define IPIPEIF_GAIN_HIGH 0x3ff
992 #define IPIPEIF_DEFAULT_GAIN 0x200
993
994 int vpfe_ipipeif_init(struct vpfe_ipipeif_device *ipipeif,
995 struct platform_device *pdev)
996 {
997 struct v4l2_subdev *sd = &ipipeif->subdev;
998 struct media_pad *pads = &ipipeif->pads[0];
999 struct media_entity *me = &sd->entity;
1000 static resource_size_t res_len;
1001 struct resource *res;
1002 int ret;
1003
1004 res = platform_get_resource(pdev, IORESOURCE_MEM, 3);
1005 if (!res)
1006 return -ENOENT;
1007
1008 res_len = resource_size(res);
1009 res = request_mem_region(res->start, res_len, res->name);
1010 if (!res)
1011 return -EBUSY;
1012
1013 ipipeif->ipipeif_base_addr = ioremap_nocache(res->start, res_len);
1014 if (!ipipeif->ipipeif_base_addr) {
1015 ret = -EBUSY;
1016 goto fail;
1017 }
1018
1019 v4l2_subdev_init(sd, &ipipeif_v4l2_ops);
1020
1021 sd->internal_ops = &ipipeif_v4l2_internal_ops;
1022 strlcpy(sd->name, "DAVINCI IPIPEIF", sizeof(sd->name));
1023 sd->grp_id = 1 << 16; /* group ID for davinci subdevs */
1024
1025 v4l2_set_subdevdata(sd, ipipeif);
1026
1027 sd->flags |= V4L2_SUBDEV_FL_HAS_EVENTS | V4L2_SUBDEV_FL_HAS_DEVNODE;
1028 pads[IPIPEIF_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
1029 pads[IPIPEIF_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
1030 ipipeif->input = IPIPEIF_INPUT_NONE;
1031 ipipeif->output = IPIPEIF_OUTPUT_NONE;
1032 me->ops = &ipipeif_media_ops;
1033
1034 ret = media_entity_init(me, IPIPEIF_NUM_PADS, pads);
1035 if (ret)
1036 goto fail;
1037
1038 v4l2_ctrl_handler_init(&ipipeif->ctrls, 2);
1039 v4l2_ctrl_new_std(&ipipeif->ctrls, &ipipeif_ctrl_ops,
1040 V4L2_CID_GAIN, 0,
1041 IPIPEIF_GAIN_HIGH, 1, IPIPEIF_DEFAULT_GAIN);
1042 v4l2_ctrl_new_custom(&ipipeif->ctrls, &vpfe_ipipeif_dpcm_pred, NULL);
1043 v4l2_ctrl_handler_setup(&ipipeif->ctrls);
1044 sd->ctrl_handler = &ipipeif->ctrls;
1045
1046 ipipeif->video_in.ops = &video_in_ops;
1047 ipipeif->video_in.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
1048 ret = vpfe_video_init(&ipipeif->video_in, "IPIPEIF");
1049 if (ret) {
1050 pr_err("Failed to init IPIPEIF video-in device\n");
1051 goto fail;
1052 }
1053 ipipeif_set_default_config(ipipeif);
1054 return 0;
1055 fail:
1056 release_mem_region(res->start, res_len);
1057 return ret;
1058 }
1059
1060 void
1061 vpfe_ipipeif_cleanup(struct vpfe_ipipeif_device *ipipeif,
1062 struct platform_device *pdev)
1063 {
1064 struct resource *res;
1065
1066 v4l2_ctrl_handler_free(&ipipeif->ctrls);
1067 iounmap(ipipeif->ipipeif_base_addr);
1068 res = platform_get_resource(pdev, IORESOURCE_MEM, 3);
1069 if (res)
1070 release_mem_region(res->start, resource_size(res));
1071
1072 }
This page took 0.073669 seconds and 5 git commands to generate.