Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / drivers / staging / media / omap4iss / iss_ipipe.c
1 /*
2  * TI OMAP4 ISS V4L2 Driver - ISP IPIPE module
3  *
4  * Copyright (C) 2012 Texas Instruments, Inc.
5  *
6  * Author: Sergio Aguirre <sergio.a.aguirre@gmail.com>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  */
13
14 #include <linux/module.h>
15 #include <linux/uaccess.h>
16 #include <linux/delay.h>
17 #include <linux/device.h>
18 #include <linux/dma-mapping.h>
19 #include <linux/mm.h>
20 #include <linux/sched.h>
21
22 #include "iss.h"
23 #include "iss_regs.h"
24 #include "iss_ipipe.h"
25
26 static struct v4l2_mbus_framefmt *
27 __ipipe_get_format(struct iss_ipipe_device *ipipe, struct v4l2_subdev_pad_config *cfg,
28                   unsigned int pad, enum v4l2_subdev_format_whence which);
29
30 static const unsigned int ipipe_fmts[] = {
31         MEDIA_BUS_FMT_SGRBG10_1X10,
32         MEDIA_BUS_FMT_SRGGB10_1X10,
33         MEDIA_BUS_FMT_SBGGR10_1X10,
34         MEDIA_BUS_FMT_SGBRG10_1X10,
35 };
36
37 /*
38  * ipipe_print_status - Print current IPIPE Module register values.
39  * @ipipe: Pointer to ISS ISP IPIPE device.
40  *
41  * Also prints other debug information stored in the IPIPE module.
42  */
43 #define IPIPE_PRINT_REGISTER(iss, name)\
44         dev_dbg(iss->dev, "###IPIPE " #name "=0x%08x\n", \
45                 iss_reg_read(iss, OMAP4_ISS_MEM_ISP_IPIPE, IPIPE_##name))
46
47 static void ipipe_print_status(struct iss_ipipe_device *ipipe)
48 {
49         struct iss_device *iss = to_iss_device(ipipe);
50
51         dev_dbg(iss->dev, "-------------IPIPE Register dump-------------\n");
52
53         IPIPE_PRINT_REGISTER(iss, SRC_EN);
54         IPIPE_PRINT_REGISTER(iss, SRC_MODE);
55         IPIPE_PRINT_REGISTER(iss, SRC_FMT);
56         IPIPE_PRINT_REGISTER(iss, SRC_COL);
57         IPIPE_PRINT_REGISTER(iss, SRC_VPS);
58         IPIPE_PRINT_REGISTER(iss, SRC_VSZ);
59         IPIPE_PRINT_REGISTER(iss, SRC_HPS);
60         IPIPE_PRINT_REGISTER(iss, SRC_HSZ);
61         IPIPE_PRINT_REGISTER(iss, GCK_MMR);
62         IPIPE_PRINT_REGISTER(iss, YUV_PHS);
63
64         dev_dbg(iss->dev, "-----------------------------------------------\n");
65 }
66
67 /*
68  * ipipe_enable - Enable/Disable IPIPE.
69  * @enable: enable flag
70  *
71  */
72 static void ipipe_enable(struct iss_ipipe_device *ipipe, u8 enable)
73 {
74         struct iss_device *iss = to_iss_device(ipipe);
75
76         iss_reg_update(iss, OMAP4_ISS_MEM_ISP_IPIPE, IPIPE_SRC_EN,
77                        IPIPE_SRC_EN_EN, enable ? IPIPE_SRC_EN_EN : 0);
78 }
79
80 /* -----------------------------------------------------------------------------
81  * Format- and pipeline-related configuration helpers
82  */
83
84 static void ipipe_configure(struct iss_ipipe_device *ipipe)
85 {
86         struct iss_device *iss = to_iss_device(ipipe);
87         struct v4l2_mbus_framefmt *format;
88
89         /* IPIPE_PAD_SINK */
90         format = &ipipe->formats[IPIPE_PAD_SINK];
91
92         /* NOTE: Currently just supporting pipeline IN: RGB, OUT: YUV422 */
93         iss_reg_write(iss, OMAP4_ISS_MEM_ISP_IPIPE, IPIPE_SRC_FMT,
94                       IPIPE_SRC_FMT_RAW2YUV);
95
96         /* Enable YUV444 -> YUV422 conversion */
97         iss_reg_write(iss, OMAP4_ISS_MEM_ISP_IPIPE, IPIPE_YUV_PHS,
98                       IPIPE_YUV_PHS_LPF);
99
100         iss_reg_write(iss, OMAP4_ISS_MEM_ISP_IPIPE, IPIPE_SRC_VPS, 0);
101         iss_reg_write(iss, OMAP4_ISS_MEM_ISP_IPIPE, IPIPE_SRC_HPS, 0);
102         iss_reg_write(iss, OMAP4_ISS_MEM_ISP_IPIPE, IPIPE_SRC_VSZ,
103                       (format->height - 2) & IPIPE_SRC_VSZ_MASK);
104         iss_reg_write(iss, OMAP4_ISS_MEM_ISP_IPIPE, IPIPE_SRC_HSZ,
105                       (format->width - 1) & IPIPE_SRC_HSZ_MASK);
106
107         /* Ignore ipipeif_wrt signal, and operate on-the-fly.  */
108         iss_reg_clr(iss, OMAP4_ISS_MEM_ISP_IPIPE, IPIPE_SRC_MODE,
109                     IPIPE_SRC_MODE_WRT | IPIPE_SRC_MODE_OST);
110
111         /* HACK: Values tuned for Ducati SW (OV) */
112         iss_reg_write(iss, OMAP4_ISS_MEM_ISP_IPIPE, IPIPE_SRC_COL,
113                       IPIPE_SRC_COL_EE_B | IPIPE_SRC_COL_EO_GB |
114                       IPIPE_SRC_COL_OE_GR | IPIPE_SRC_COL_OO_R);
115
116         /* IPIPE_PAD_SOURCE_VP */
117         format = &ipipe->formats[IPIPE_PAD_SOURCE_VP];
118         /* Do nothing? */
119 }
120
121 /* -----------------------------------------------------------------------------
122  * V4L2 subdev operations
123  */
124
125 /*
126  * ipipe_set_stream - Enable/Disable streaming on the IPIPE module
127  * @sd: ISP IPIPE V4L2 subdevice
128  * @enable: Enable/disable stream
129  */
130 static int ipipe_set_stream(struct v4l2_subdev *sd, int enable)
131 {
132         struct iss_ipipe_device *ipipe = v4l2_get_subdevdata(sd);
133         struct iss_device *iss = to_iss_device(ipipe);
134         int ret = 0;
135
136         if (ipipe->state == ISS_PIPELINE_STREAM_STOPPED) {
137                 if (enable == ISS_PIPELINE_STREAM_STOPPED)
138                         return 0;
139
140                 omap4iss_isp_subclk_enable(iss, OMAP4_ISS_ISP_SUBCLK_IPIPE);
141
142                 /* Enable clk_arm_g0 */
143                 iss_reg_write(iss, OMAP4_ISS_MEM_ISP_IPIPE, IPIPE_GCK_MMR,
144                               IPIPE_GCK_MMR_REG);
145
146                 /* Enable clk_pix_g[3:0] */
147                 iss_reg_write(iss, OMAP4_ISS_MEM_ISP_IPIPE, IPIPE_GCK_PIX,
148                               IPIPE_GCK_PIX_G3 | IPIPE_GCK_PIX_G2 |
149                               IPIPE_GCK_PIX_G1 | IPIPE_GCK_PIX_G0);
150         }
151
152         switch (enable) {
153         case ISS_PIPELINE_STREAM_CONTINUOUS:
154
155                 ipipe_configure(ipipe);
156                 ipipe_print_status(ipipe);
157
158                 atomic_set(&ipipe->stopping, 0);
159                 ipipe_enable(ipipe, 1);
160                 break;
161
162         case ISS_PIPELINE_STREAM_STOPPED:
163                 if (ipipe->state == ISS_PIPELINE_STREAM_STOPPED)
164                         return 0;
165                 if (omap4iss_module_sync_idle(&sd->entity, &ipipe->wait,
166                                               &ipipe->stopping))
167                         ret = -ETIMEDOUT;
168
169                 ipipe_enable(ipipe, 0);
170                 omap4iss_isp_subclk_disable(iss, OMAP4_ISS_ISP_SUBCLK_IPIPE);
171                 break;
172         }
173
174         ipipe->state = enable;
175         return ret;
176 }
177
178 static struct v4l2_mbus_framefmt *
179 __ipipe_get_format(struct iss_ipipe_device *ipipe, struct v4l2_subdev_pad_config *cfg,
180                   unsigned int pad, enum v4l2_subdev_format_whence which)
181 {
182         if (which == V4L2_SUBDEV_FORMAT_TRY)
183                 return v4l2_subdev_get_try_format(&ipipe->subdev, cfg, pad);
184
185         return &ipipe->formats[pad];
186 }
187
188 /*
189  * ipipe_try_format - Try video format on a pad
190  * @ipipe: ISS IPIPE device
191  * @cfg: V4L2 subdev pad config
192  * @pad: Pad number
193  * @fmt: Format
194  */
195 static void
196 ipipe_try_format(struct iss_ipipe_device *ipipe, struct v4l2_subdev_pad_config *cfg,
197                 unsigned int pad, struct v4l2_mbus_framefmt *fmt,
198                 enum v4l2_subdev_format_whence which)
199 {
200         struct v4l2_mbus_framefmt *format;
201         unsigned int width = fmt->width;
202         unsigned int height = fmt->height;
203         unsigned int i;
204
205         switch (pad) {
206         case IPIPE_PAD_SINK:
207                 for (i = 0; i < ARRAY_SIZE(ipipe_fmts); i++) {
208                         if (fmt->code == ipipe_fmts[i])
209                                 break;
210                 }
211
212                 /* If not found, use SGRBG10 as default */
213                 if (i >= ARRAY_SIZE(ipipe_fmts))
214                         fmt->code = MEDIA_BUS_FMT_SGRBG10_1X10;
215
216                 /* Clamp the input size. */
217                 fmt->width = clamp_t(u32, width, 1, 8192);
218                 fmt->height = clamp_t(u32, height, 1, 8192);
219                 fmt->colorspace = V4L2_COLORSPACE_SRGB;
220                 break;
221
222         case IPIPE_PAD_SOURCE_VP:
223                 format = __ipipe_get_format(ipipe, cfg, IPIPE_PAD_SINK, which);
224                 memcpy(fmt, format, sizeof(*fmt));
225
226                 fmt->code = MEDIA_BUS_FMT_UYVY8_1X16;
227                 fmt->width = clamp_t(u32, width, 32, fmt->width);
228                 fmt->height = clamp_t(u32, height, 32, fmt->height);
229                 fmt->colorspace = V4L2_COLORSPACE_JPEG;
230                 break;
231         }
232
233         fmt->field = V4L2_FIELD_NONE;
234 }
235
236 /*
237  * ipipe_enum_mbus_code - Handle pixel format enumeration
238  * @sd     : pointer to v4l2 subdev structure
239  * @cfg    : V4L2 subdev pad config
240  * @code   : pointer to v4l2_subdev_mbus_code_enum structure
241  * return -EINVAL or zero on success
242  */
243 static int ipipe_enum_mbus_code(struct v4l2_subdev *sd,
244                                struct v4l2_subdev_pad_config *cfg,
245                                struct v4l2_subdev_mbus_code_enum *code)
246 {
247         switch (code->pad) {
248         case IPIPE_PAD_SINK:
249                 if (code->index >= ARRAY_SIZE(ipipe_fmts))
250                         return -EINVAL;
251
252                 code->code = ipipe_fmts[code->index];
253                 break;
254
255         case IPIPE_PAD_SOURCE_VP:
256                 /* FIXME: Forced format conversion inside IPIPE ? */
257                 if (code->index != 0)
258                         return -EINVAL;
259
260                 code->code = MEDIA_BUS_FMT_UYVY8_1X16;
261                 break;
262
263         default:
264                 return -EINVAL;
265         }
266
267         return 0;
268 }
269
270 static int ipipe_enum_frame_size(struct v4l2_subdev *sd,
271                                 struct v4l2_subdev_pad_config *cfg,
272                                 struct v4l2_subdev_frame_size_enum *fse)
273 {
274         struct iss_ipipe_device *ipipe = v4l2_get_subdevdata(sd);
275         struct v4l2_mbus_framefmt format;
276
277         if (fse->index != 0)
278                 return -EINVAL;
279
280         format.code = fse->code;
281         format.width = 1;
282         format.height = 1;
283         ipipe_try_format(ipipe, cfg, fse->pad, &format, fse->which);
284         fse->min_width = format.width;
285         fse->min_height = format.height;
286
287         if (format.code != fse->code)
288                 return -EINVAL;
289
290         format.code = fse->code;
291         format.width = -1;
292         format.height = -1;
293         ipipe_try_format(ipipe, cfg, fse->pad, &format, fse->which);
294         fse->max_width = format.width;
295         fse->max_height = format.height;
296
297         return 0;
298 }
299
300 /*
301  * ipipe_get_format - Retrieve the video format on a pad
302  * @sd : ISP IPIPE V4L2 subdevice
303  * @cfg: V4L2 subdev pad config
304  * @fmt: Format
305  *
306  * Return 0 on success or -EINVAL if the pad is invalid or doesn't correspond
307  * to the format type.
308  */
309 static int ipipe_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg,
310                            struct v4l2_subdev_format *fmt)
311 {
312         struct iss_ipipe_device *ipipe = v4l2_get_subdevdata(sd);
313         struct v4l2_mbus_framefmt *format;
314
315         format = __ipipe_get_format(ipipe, cfg, fmt->pad, fmt->which);
316         if (format == NULL)
317                 return -EINVAL;
318
319         fmt->format = *format;
320         return 0;
321 }
322
323 /*
324  * ipipe_set_format - Set the video format on a pad
325  * @sd : ISP IPIPE V4L2 subdevice
326  * @cfg: V4L2 subdev pad config
327  * @fmt: Format
328  *
329  * Return 0 on success or -EINVAL if the pad is invalid or doesn't correspond
330  * to the format type.
331  */
332 static int ipipe_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg,
333                            struct v4l2_subdev_format *fmt)
334 {
335         struct iss_ipipe_device *ipipe = v4l2_get_subdevdata(sd);
336         struct v4l2_mbus_framefmt *format;
337
338         format = __ipipe_get_format(ipipe, cfg, fmt->pad, fmt->which);
339         if (format == NULL)
340                 return -EINVAL;
341
342         ipipe_try_format(ipipe, cfg, fmt->pad, &fmt->format, fmt->which);
343         *format = fmt->format;
344
345         /* Propagate the format from sink to source */
346         if (fmt->pad == IPIPE_PAD_SINK) {
347                 format = __ipipe_get_format(ipipe, cfg, IPIPE_PAD_SOURCE_VP,
348                                            fmt->which);
349                 *format = fmt->format;
350                 ipipe_try_format(ipipe, cfg, IPIPE_PAD_SOURCE_VP, format,
351                                 fmt->which);
352         }
353
354         return 0;
355 }
356
357 static int ipipe_link_validate(struct v4l2_subdev *sd, struct media_link *link,
358                                  struct v4l2_subdev_format *source_fmt,
359                                  struct v4l2_subdev_format *sink_fmt)
360 {
361         /* Check if the two ends match */
362         if (source_fmt->format.width != sink_fmt->format.width ||
363             source_fmt->format.height != sink_fmt->format.height)
364                 return -EPIPE;
365
366         if (source_fmt->format.code != sink_fmt->format.code)
367                 return -EPIPE;
368
369         return 0;
370 }
371
372 /*
373  * ipipe_init_formats - Initialize formats on all pads
374  * @sd: ISP IPIPE V4L2 subdevice
375  * @fh: V4L2 subdev file handle
376  *
377  * Initialize all pad formats with default values. If fh is not NULL, try
378  * formats are initialized on the file handle. Otherwise active formats are
379  * initialized on the device.
380  */
381 static int ipipe_init_formats(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
382 {
383         struct v4l2_subdev_format format;
384
385         memset(&format, 0, sizeof(format));
386         format.pad = IPIPE_PAD_SINK;
387         format.which = fh ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
388         format.format.code = MEDIA_BUS_FMT_SGRBG10_1X10;
389         format.format.width = 4096;
390         format.format.height = 4096;
391         ipipe_set_format(sd, fh ? fh->pad : NULL, &format);
392
393         return 0;
394 }
395
396 /* V4L2 subdev video operations */
397 static const struct v4l2_subdev_video_ops ipipe_v4l2_video_ops = {
398         .s_stream = ipipe_set_stream,
399 };
400
401 /* V4L2 subdev pad operations */
402 static const struct v4l2_subdev_pad_ops ipipe_v4l2_pad_ops = {
403         .enum_mbus_code = ipipe_enum_mbus_code,
404         .enum_frame_size = ipipe_enum_frame_size,
405         .get_fmt = ipipe_get_format,
406         .set_fmt = ipipe_set_format,
407         .link_validate = ipipe_link_validate,
408 };
409
410 /* V4L2 subdev operations */
411 static const struct v4l2_subdev_ops ipipe_v4l2_ops = {
412         .video = &ipipe_v4l2_video_ops,
413         .pad = &ipipe_v4l2_pad_ops,
414 };
415
416 /* V4L2 subdev internal operations */
417 static const struct v4l2_subdev_internal_ops ipipe_v4l2_internal_ops = {
418         .open = ipipe_init_formats,
419 };
420
421 /* -----------------------------------------------------------------------------
422  * Media entity operations
423  */
424
425 /*
426  * ipipe_link_setup - Setup IPIPE connections
427  * @entity: IPIPE media entity
428  * @local: Pad at the local end of the link
429  * @remote: Pad at the remote end of the link
430  * @flags: Link flags
431  *
432  * return -EINVAL or zero on success
433  */
434 static int ipipe_link_setup(struct media_entity *entity,
435                            const struct media_pad *local,
436                            const struct media_pad *remote, u32 flags)
437 {
438         struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
439         struct iss_ipipe_device *ipipe = v4l2_get_subdevdata(sd);
440         struct iss_device *iss = to_iss_device(ipipe);
441
442         switch (local->index | media_entity_type(remote->entity)) {
443         case IPIPE_PAD_SINK | MEDIA_ENT_T_V4L2_SUBDEV:
444                 /* Read from IPIPEIF. */
445                 if (!(flags & MEDIA_LNK_FL_ENABLED)) {
446                         ipipe->input = IPIPE_INPUT_NONE;
447                         break;
448                 }
449
450                 if (ipipe->input != IPIPE_INPUT_NONE)
451                         return -EBUSY;
452
453                 if (remote->entity == &iss->ipipeif.subdev.entity)
454                         ipipe->input = IPIPE_INPUT_IPIPEIF;
455
456                 break;
457
458         case IPIPE_PAD_SOURCE_VP | MEDIA_ENT_T_V4L2_SUBDEV:
459                 /* Send to RESIZER */
460                 if (flags & MEDIA_LNK_FL_ENABLED) {
461                         if (ipipe->output & ~IPIPE_OUTPUT_VP)
462                                 return -EBUSY;
463                         ipipe->output |= IPIPE_OUTPUT_VP;
464                 } else {
465                         ipipe->output &= ~IPIPE_OUTPUT_VP;
466                 }
467                 break;
468
469         default:
470                 return -EINVAL;
471         }
472
473         return 0;
474 }
475
476 /* media operations */
477 static const struct media_entity_operations ipipe_media_ops = {
478         .link_setup = ipipe_link_setup,
479         .link_validate = v4l2_subdev_link_validate,
480 };
481
482 /*
483  * ipipe_init_entities - Initialize V4L2 subdev and media entity
484  * @ipipe: ISS ISP IPIPE module
485  *
486  * Return 0 on success and a negative error code on failure.
487  */
488 static int ipipe_init_entities(struct iss_ipipe_device *ipipe)
489 {
490         struct v4l2_subdev *sd = &ipipe->subdev;
491         struct media_pad *pads = ipipe->pads;
492         struct media_entity *me = &sd->entity;
493         int ret;
494
495         ipipe->input = IPIPE_INPUT_NONE;
496
497         v4l2_subdev_init(sd, &ipipe_v4l2_ops);
498         sd->internal_ops = &ipipe_v4l2_internal_ops;
499         strlcpy(sd->name, "OMAP4 ISS ISP IPIPE", sizeof(sd->name));
500         sd->grp_id = 1 << 16;   /* group ID for iss subdevs */
501         v4l2_set_subdevdata(sd, ipipe);
502         sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
503
504         pads[IPIPE_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
505         pads[IPIPE_PAD_SOURCE_VP].flags = MEDIA_PAD_FL_SOURCE;
506
507         me->ops = &ipipe_media_ops;
508         ret = media_entity_init(me, IPIPE_PADS_NUM, pads, 0);
509         if (ret < 0)
510                 return ret;
511
512         ipipe_init_formats(sd, NULL);
513
514         return 0;
515 }
516
517 void omap4iss_ipipe_unregister_entities(struct iss_ipipe_device *ipipe)
518 {
519         v4l2_device_unregister_subdev(&ipipe->subdev);
520 }
521
522 int omap4iss_ipipe_register_entities(struct iss_ipipe_device *ipipe,
523         struct v4l2_device *vdev)
524 {
525         int ret;
526
527         /* Register the subdev and video node. */
528         ret = v4l2_device_register_subdev(vdev, &ipipe->subdev);
529         if (ret < 0)
530                 goto error;
531
532         return 0;
533
534 error:
535         omap4iss_ipipe_unregister_entities(ipipe);
536         return ret;
537 }
538
539 /* -----------------------------------------------------------------------------
540  * ISP IPIPE initialisation and cleanup
541  */
542
543 /*
544  * omap4iss_ipipe_init - IPIPE module initialization.
545  * @iss: Device pointer specific to the OMAP4 ISS.
546  *
547  * TODO: Get the initialisation values from platform data.
548  *
549  * Return 0 on success or a negative error code otherwise.
550  */
551 int omap4iss_ipipe_init(struct iss_device *iss)
552 {
553         struct iss_ipipe_device *ipipe = &iss->ipipe;
554
555         ipipe->state = ISS_PIPELINE_STREAM_STOPPED;
556         init_waitqueue_head(&ipipe->wait);
557
558         return ipipe_init_entities(ipipe);
559 }
560
561 /*
562  * omap4iss_ipipe_cleanup - IPIPE module cleanup.
563  * @iss: Device pointer specific to the OMAP4 ISS.
564  */
565 void omap4iss_ipipe_cleanup(struct iss_device *iss)
566 {
567         struct iss_ipipe_device *ipipe = &iss->ipipe;
568
569         media_entity_cleanup(&ipipe->subdev.entity);
570 }