Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris...
[sfrench/cifs-2.6.git] / drivers / media / platform / s5p-fimc / mipi-csis.c
1 /*
2  * Samsung S5P/EXYNOS4 SoC series MIPI-CSI receiver driver
3  *
4  * Copyright (C) 2011 - 2012 Samsung Electronics Co., Ltd.
5  * Sylwester Nawrocki, <s.nawrocki@samsung.com>
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License version 2 as
9  * published by the Free Software Foundation.
10  */
11
12 #include <linux/clk.h>
13 #include <linux/delay.h>
14 #include <linux/device.h>
15 #include <linux/errno.h>
16 #include <linux/interrupt.h>
17 #include <linux/io.h>
18 #include <linux/irq.h>
19 #include <linux/kernel.h>
20 #include <linux/memory.h>
21 #include <linux/module.h>
22 #include <linux/platform_device.h>
23 #include <linux/pm_runtime.h>
24 #include <linux/regulator/consumer.h>
25 #include <linux/slab.h>
26 #include <linux/spinlock.h>
27 #include <linux/videodev2.h>
28 #include <media/v4l2-subdev.h>
29 #include <linux/platform_data/mipi-csis.h>
30 #include "mipi-csis.h"
31
32 static int debug;
33 module_param(debug, int, 0644);
34 MODULE_PARM_DESC(debug, "Debug level (0-2)");
35
36 /* Register map definition */
37
38 /* CSIS global control */
39 #define S5PCSIS_CTRL                    0x00
40 #define S5PCSIS_CTRL_DPDN_DEFAULT       (0 << 31)
41 #define S5PCSIS_CTRL_DPDN_SWAP          (1 << 31)
42 #define S5PCSIS_CTRL_ALIGN_32BIT        (1 << 20)
43 #define S5PCSIS_CTRL_UPDATE_SHADOW      (1 << 16)
44 #define S5PCSIS_CTRL_WCLK_EXTCLK        (1 << 8)
45 #define S5PCSIS_CTRL_RESET              (1 << 4)
46 #define S5PCSIS_CTRL_ENABLE             (1 << 0)
47
48 /* D-PHY control */
49 #define S5PCSIS_DPHYCTRL                0x04
50 #define S5PCSIS_DPHYCTRL_HSS_MASK       (0x1f << 27)
51 #define S5PCSIS_DPHYCTRL_ENABLE         (0x1f << 0)
52
53 #define S5PCSIS_CONFIG                  0x08
54 #define S5PCSIS_CFG_FMT_YCBCR422_8BIT   (0x1e << 2)
55 #define S5PCSIS_CFG_FMT_RAW8            (0x2a << 2)
56 #define S5PCSIS_CFG_FMT_RAW10           (0x2b << 2)
57 #define S5PCSIS_CFG_FMT_RAW12           (0x2c << 2)
58 /* User defined formats, x = 1...4 */
59 #define S5PCSIS_CFG_FMT_USER(x)         ((0x30 + x - 1) << 2)
60 #define S5PCSIS_CFG_FMT_MASK            (0x3f << 2)
61 #define S5PCSIS_CFG_NR_LANE_MASK        3
62
63 /* Interrupt mask */
64 #define S5PCSIS_INTMSK                  0x10
65 #define S5PCSIS_INTMSK_EN_ALL           0xf000103f
66 #define S5PCSIS_INTMSK_EVEN_BEFORE      (1 << 31)
67 #define S5PCSIS_INTMSK_EVEN_AFTER       (1 << 30)
68 #define S5PCSIS_INTMSK_ODD_BEFORE       (1 << 29)
69 #define S5PCSIS_INTMSK_ODD_AFTER        (1 << 28)
70 #define S5PCSIS_INTMSK_ERR_SOT_HS       (1 << 12)
71 #define S5PCSIS_INTMSK_ERR_LOST_FS      (1 << 5)
72 #define S5PCSIS_INTMSK_ERR_LOST_FE      (1 << 4)
73 #define S5PCSIS_INTMSK_ERR_OVER         (1 << 3)
74 #define S5PCSIS_INTMSK_ERR_ECC          (1 << 2)
75 #define S5PCSIS_INTMSK_ERR_CRC          (1 << 1)
76 #define S5PCSIS_INTMSK_ERR_UNKNOWN      (1 << 0)
77
78 /* Interrupt source */
79 #define S5PCSIS_INTSRC                  0x14
80 #define S5PCSIS_INTSRC_EVEN_BEFORE      (1 << 31)
81 #define S5PCSIS_INTSRC_EVEN_AFTER       (1 << 30)
82 #define S5PCSIS_INTSRC_EVEN             (0x3 << 30)
83 #define S5PCSIS_INTSRC_ODD_BEFORE       (1 << 29)
84 #define S5PCSIS_INTSRC_ODD_AFTER        (1 << 28)
85 #define S5PCSIS_INTSRC_ODD              (0x3 << 28)
86 #define S5PCSIS_INTSRC_NON_IMAGE_DATA   (0xff << 28)
87 #define S5PCSIS_INTSRC_ERR_SOT_HS       (0xf << 12)
88 #define S5PCSIS_INTSRC_ERR_LOST_FS      (1 << 5)
89 #define S5PCSIS_INTSRC_ERR_LOST_FE      (1 << 4)
90 #define S5PCSIS_INTSRC_ERR_OVER         (1 << 3)
91 #define S5PCSIS_INTSRC_ERR_ECC          (1 << 2)
92 #define S5PCSIS_INTSRC_ERR_CRC          (1 << 1)
93 #define S5PCSIS_INTSRC_ERR_UNKNOWN      (1 << 0)
94 #define S5PCSIS_INTSRC_ERRORS           0xf03f
95
96 /* Pixel resolution */
97 #define S5PCSIS_RESOL                   0x2c
98 #define CSIS_MAX_PIX_WIDTH              0xffff
99 #define CSIS_MAX_PIX_HEIGHT             0xffff
100
101 enum {
102         CSIS_CLK_MUX,
103         CSIS_CLK_GATE,
104 };
105
106 static char *csi_clock_name[] = {
107         [CSIS_CLK_MUX]  = "sclk_csis",
108         [CSIS_CLK_GATE] = "csis",
109 };
110 #define NUM_CSIS_CLOCKS ARRAY_SIZE(csi_clock_name)
111
112 static const char * const csis_supply_name[] = {
113         "vdd11", /* 1.1V or 1.2V (s5pc100) MIPI CSI suppply */
114         "vdd18", /* VDD 1.8V and MIPI CSI PLL supply */
115 };
116 #define CSIS_NUM_SUPPLIES ARRAY_SIZE(csis_supply_name)
117
118 enum {
119         ST_POWERED      = 1,
120         ST_STREAMING    = 2,
121         ST_SUSPENDED    = 4,
122 };
123
124 struct s5pcsis_event {
125         u32 mask;
126         const char * const name;
127         unsigned int counter;
128 };
129
130 static const struct s5pcsis_event s5pcsis_events[] = {
131         /* Errors */
132         { S5PCSIS_INTSRC_ERR_SOT_HS,    "SOT Error" },
133         { S5PCSIS_INTSRC_ERR_LOST_FS,   "Lost Frame Start Error" },
134         { S5PCSIS_INTSRC_ERR_LOST_FE,   "Lost Frame End Error" },
135         { S5PCSIS_INTSRC_ERR_OVER,      "FIFO Overflow Error" },
136         { S5PCSIS_INTSRC_ERR_ECC,       "ECC Error" },
137         { S5PCSIS_INTSRC_ERR_CRC,       "CRC Error" },
138         { S5PCSIS_INTSRC_ERR_UNKNOWN,   "Unknown Error" },
139         /* Non-image data receive events */
140         { S5PCSIS_INTSRC_EVEN_BEFORE,   "Non-image data before even frame" },
141         { S5PCSIS_INTSRC_EVEN_AFTER,    "Non-image data after even frame" },
142         { S5PCSIS_INTSRC_ODD_BEFORE,    "Non-image data before odd frame" },
143         { S5PCSIS_INTSRC_ODD_AFTER,     "Non-image data after odd frame" },
144 };
145 #define S5PCSIS_NUM_EVENTS ARRAY_SIZE(s5pcsis_events)
146
147 /**
148  * struct csis_state - the driver's internal state data structure
149  * @lock: mutex serializing the subdev and power management operations,
150  *        protecting @format and @flags members
151  * @pads: CSIS pads array
152  * @sd: v4l2_subdev associated with CSIS device instance
153  * @pdev: CSIS platform device
154  * @regs: mmaped I/O registers memory
155  * @supplies: CSIS regulator supplies
156  * @clock: CSIS clocks
157  * @irq: requested s5p-mipi-csis irq number
158  * @flags: the state variable for power and streaming control
159  * @csis_fmt: current CSIS pixel format
160  * @format: common media bus format for the source and sink pad
161  * @slock: spinlock protecting structure members below
162  * @events: MIPI-CSIS event (error) counters
163  */
164 struct csis_state {
165         struct mutex lock;
166         struct media_pad pads[CSIS_PADS_NUM];
167         struct v4l2_subdev sd;
168         struct platform_device *pdev;
169         void __iomem *regs;
170         struct regulator_bulk_data supplies[CSIS_NUM_SUPPLIES];
171         struct clk *clock[NUM_CSIS_CLOCKS];
172         int irq;
173         u32 flags;
174         const struct csis_pix_format *csis_fmt;
175         struct v4l2_mbus_framefmt format;
176
177         struct spinlock slock;
178         struct s5pcsis_event events[S5PCSIS_NUM_EVENTS];
179 };
180
181 /**
182  * struct csis_pix_format - CSIS pixel format description
183  * @pix_width_alignment: horizontal pixel alignment, width will be
184  *                       multiple of 2^pix_width_alignment
185  * @code: corresponding media bus code
186  * @fmt_reg: S5PCSIS_CONFIG register value
187  * @data_alignment: MIPI-CSI data alignment in bits
188  */
189 struct csis_pix_format {
190         unsigned int pix_width_alignment;
191         enum v4l2_mbus_pixelcode code;
192         u32 fmt_reg;
193         u8 data_alignment;
194 };
195
196 static const struct csis_pix_format s5pcsis_formats[] = {
197         {
198                 .code = V4L2_MBUS_FMT_VYUY8_2X8,
199                 .fmt_reg = S5PCSIS_CFG_FMT_YCBCR422_8BIT,
200                 .data_alignment = 32,
201         }, {
202                 .code = V4L2_MBUS_FMT_JPEG_1X8,
203                 .fmt_reg = S5PCSIS_CFG_FMT_USER(1),
204                 .data_alignment = 32,
205         },
206 };
207
208 #define s5pcsis_write(__csis, __r, __v) writel(__v, __csis->regs + __r)
209 #define s5pcsis_read(__csis, __r) readl(__csis->regs + __r)
210
211 static struct csis_state *sd_to_csis_state(struct v4l2_subdev *sdev)
212 {
213         return container_of(sdev, struct csis_state, sd);
214 }
215
216 static const struct csis_pix_format *find_csis_format(
217         struct v4l2_mbus_framefmt *mf)
218 {
219         int i;
220
221         for (i = 0; i < ARRAY_SIZE(s5pcsis_formats); i++)
222                 if (mf->code == s5pcsis_formats[i].code)
223                         return &s5pcsis_formats[i];
224         return NULL;
225 }
226
227 static void s5pcsis_enable_interrupts(struct csis_state *state, bool on)
228 {
229         u32 val = s5pcsis_read(state, S5PCSIS_INTMSK);
230
231         val = on ? val | S5PCSIS_INTMSK_EN_ALL :
232                    val & ~S5PCSIS_INTMSK_EN_ALL;
233         s5pcsis_write(state, S5PCSIS_INTMSK, val);
234 }
235
236 static void s5pcsis_reset(struct csis_state *state)
237 {
238         u32 val = s5pcsis_read(state, S5PCSIS_CTRL);
239
240         s5pcsis_write(state, S5PCSIS_CTRL, val | S5PCSIS_CTRL_RESET);
241         udelay(10);
242 }
243
244 static void s5pcsis_system_enable(struct csis_state *state, int on)
245 {
246         u32 val;
247
248         val = s5pcsis_read(state, S5PCSIS_CTRL);
249         if (on)
250                 val |= S5PCSIS_CTRL_ENABLE;
251         else
252                 val &= ~S5PCSIS_CTRL_ENABLE;
253         s5pcsis_write(state, S5PCSIS_CTRL, val);
254
255         val = s5pcsis_read(state, S5PCSIS_DPHYCTRL);
256         if (on)
257                 val |= S5PCSIS_DPHYCTRL_ENABLE;
258         else
259                 val &= ~S5PCSIS_DPHYCTRL_ENABLE;
260         s5pcsis_write(state, S5PCSIS_DPHYCTRL, val);
261 }
262
263 /* Called with the state.lock mutex held */
264 static void __s5pcsis_set_format(struct csis_state *state)
265 {
266         struct v4l2_mbus_framefmt *mf = &state->format;
267         u32 val;
268
269         v4l2_dbg(1, debug, &state->sd, "fmt: %d, %d x %d\n",
270                  mf->code, mf->width, mf->height);
271
272         /* Color format */
273         val = s5pcsis_read(state, S5PCSIS_CONFIG);
274         val = (val & ~S5PCSIS_CFG_FMT_MASK) | state->csis_fmt->fmt_reg;
275         s5pcsis_write(state, S5PCSIS_CONFIG, val);
276
277         /* Pixel resolution */
278         val = (mf->width << 16) | mf->height;
279         s5pcsis_write(state, S5PCSIS_RESOL, val);
280 }
281
282 static void s5pcsis_set_hsync_settle(struct csis_state *state, int settle)
283 {
284         u32 val = s5pcsis_read(state, S5PCSIS_DPHYCTRL);
285
286         val = (val & ~S5PCSIS_DPHYCTRL_HSS_MASK) | (settle << 27);
287         s5pcsis_write(state, S5PCSIS_DPHYCTRL, val);
288 }
289
290 static void s5pcsis_set_params(struct csis_state *state)
291 {
292         struct s5p_platform_mipi_csis *pdata = state->pdev->dev.platform_data;
293         u32 val;
294
295         val = s5pcsis_read(state, S5PCSIS_CONFIG);
296         val = (val & ~S5PCSIS_CFG_NR_LANE_MASK) | (pdata->lanes - 1);
297         s5pcsis_write(state, S5PCSIS_CONFIG, val);
298
299         __s5pcsis_set_format(state);
300         s5pcsis_set_hsync_settle(state, pdata->hs_settle);
301
302         val = s5pcsis_read(state, S5PCSIS_CTRL);
303         if (state->csis_fmt->data_alignment == 32)
304                 val |= S5PCSIS_CTRL_ALIGN_32BIT;
305         else /* 24-bits */
306                 val &= ~S5PCSIS_CTRL_ALIGN_32BIT;
307         /* Not using external clock. */
308         val &= ~S5PCSIS_CTRL_WCLK_EXTCLK;
309         s5pcsis_write(state, S5PCSIS_CTRL, val);
310
311         /* Update the shadow register. */
312         val = s5pcsis_read(state, S5PCSIS_CTRL);
313         s5pcsis_write(state, S5PCSIS_CTRL, val | S5PCSIS_CTRL_UPDATE_SHADOW);
314 }
315
316 static void s5pcsis_clk_put(struct csis_state *state)
317 {
318         int i;
319
320         for (i = 0; i < NUM_CSIS_CLOCKS; i++) {
321                 if (IS_ERR_OR_NULL(state->clock[i]))
322                         continue;
323                 clk_unprepare(state->clock[i]);
324                 clk_put(state->clock[i]);
325                 state->clock[i] = NULL;
326         }
327 }
328
329 static int s5pcsis_clk_get(struct csis_state *state)
330 {
331         struct device *dev = &state->pdev->dev;
332         int i, ret;
333
334         for (i = 0; i < NUM_CSIS_CLOCKS; i++) {
335                 state->clock[i] = clk_get(dev, csi_clock_name[i]);
336                 if (IS_ERR(state->clock[i]))
337                         goto err;
338                 ret = clk_prepare(state->clock[i]);
339                 if (ret < 0) {
340                         clk_put(state->clock[i]);
341                         state->clock[i] = NULL;
342                         goto err;
343                 }
344         }
345         return 0;
346 err:
347         s5pcsis_clk_put(state);
348         dev_err(dev, "failed to get clock: %s\n", csi_clock_name[i]);
349         return -ENXIO;
350 }
351
352 static void s5pcsis_start_stream(struct csis_state *state)
353 {
354         s5pcsis_reset(state);
355         s5pcsis_set_params(state);
356         s5pcsis_system_enable(state, true);
357         s5pcsis_enable_interrupts(state, true);
358 }
359
360 static void s5pcsis_stop_stream(struct csis_state *state)
361 {
362         s5pcsis_enable_interrupts(state, false);
363         s5pcsis_system_enable(state, false);
364 }
365
366 static void s5pcsis_clear_counters(struct csis_state *state)
367 {
368         unsigned long flags;
369         int i;
370
371         spin_lock_irqsave(&state->slock, flags);
372         for (i = 0; i < S5PCSIS_NUM_EVENTS; i++)
373                 state->events[i].counter = 0;
374         spin_unlock_irqrestore(&state->slock, flags);
375 }
376
377 static void s5pcsis_log_counters(struct csis_state *state, bool non_errors)
378 {
379         int i = non_errors ? S5PCSIS_NUM_EVENTS : S5PCSIS_NUM_EVENTS - 4;
380         unsigned long flags;
381
382         spin_lock_irqsave(&state->slock, flags);
383
384         for (i--; i >= 0; i--)
385                 if (state->events[i].counter >= 0)
386                         v4l2_info(&state->sd, "%s events: %d\n",
387                                   state->events[i].name,
388                                   state->events[i].counter);
389
390         spin_unlock_irqrestore(&state->slock, flags);
391 }
392
393 /*
394  * V4L2 subdev operations
395  */
396 static int s5pcsis_s_power(struct v4l2_subdev *sd, int on)
397 {
398         struct csis_state *state = sd_to_csis_state(sd);
399         struct device *dev = &state->pdev->dev;
400
401         if (on)
402                 return pm_runtime_get_sync(dev);
403
404         return pm_runtime_put_sync(dev);
405 }
406
407 static int s5pcsis_s_stream(struct v4l2_subdev *sd, int enable)
408 {
409         struct csis_state *state = sd_to_csis_state(sd);
410         int ret = 0;
411
412         v4l2_dbg(1, debug, sd, "%s: %d, state: 0x%x\n",
413                  __func__, enable, state->flags);
414
415         if (enable) {
416                 s5pcsis_clear_counters(state);
417                 ret = pm_runtime_get_sync(&state->pdev->dev);
418                 if (ret && ret != 1)
419                         return ret;
420         }
421
422         mutex_lock(&state->lock);
423         if (enable) {
424                 if (state->flags & ST_SUSPENDED) {
425                         ret = -EBUSY;
426                         goto unlock;
427                 }
428                 s5pcsis_start_stream(state);
429                 state->flags |= ST_STREAMING;
430         } else {
431                 s5pcsis_stop_stream(state);
432                 state->flags &= ~ST_STREAMING;
433                 if (debug > 0)
434                         s5pcsis_log_counters(state, true);
435         }
436 unlock:
437         mutex_unlock(&state->lock);
438         if (!enable)
439                 pm_runtime_put(&state->pdev->dev);
440
441         return ret == 1 ? 0 : ret;
442 }
443
444 static int s5pcsis_enum_mbus_code(struct v4l2_subdev *sd,
445                                   struct v4l2_subdev_fh *fh,
446                                   struct v4l2_subdev_mbus_code_enum *code)
447 {
448         if (code->index >= ARRAY_SIZE(s5pcsis_formats))
449                 return -EINVAL;
450
451         code->code = s5pcsis_formats[code->index].code;
452         return 0;
453 }
454
455 static struct csis_pix_format const *s5pcsis_try_format(
456         struct v4l2_mbus_framefmt *mf)
457 {
458         struct csis_pix_format const *csis_fmt;
459
460         csis_fmt = find_csis_format(mf);
461         if (csis_fmt == NULL)
462                 csis_fmt = &s5pcsis_formats[0];
463
464         mf->code = csis_fmt->code;
465         v4l_bound_align_image(&mf->width, 1, CSIS_MAX_PIX_WIDTH,
466                               csis_fmt->pix_width_alignment,
467                               &mf->height, 1, CSIS_MAX_PIX_HEIGHT, 1,
468                               0);
469         return csis_fmt;
470 }
471
472 static struct v4l2_mbus_framefmt *__s5pcsis_get_format(
473                 struct csis_state *state, struct v4l2_subdev_fh *fh,
474                 u32 pad, enum v4l2_subdev_format_whence which)
475 {
476         if (which == V4L2_SUBDEV_FORMAT_TRY)
477                 return fh ? v4l2_subdev_get_try_format(fh, pad) : NULL;
478
479         return &state->format;
480 }
481
482 static int s5pcsis_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
483                            struct v4l2_subdev_format *fmt)
484 {
485         struct csis_state *state = sd_to_csis_state(sd);
486         struct csis_pix_format const *csis_fmt;
487         struct v4l2_mbus_framefmt *mf;
488
489         if (fmt->pad != CSIS_PAD_SOURCE && fmt->pad != CSIS_PAD_SINK)
490                 return -EINVAL;
491
492         mf = __s5pcsis_get_format(state, fh, fmt->pad, fmt->which);
493
494         if (fmt->pad == CSIS_PAD_SOURCE) {
495                 if (mf) {
496                         mutex_lock(&state->lock);
497                         fmt->format = *mf;
498                         mutex_unlock(&state->lock);
499                 }
500                 return 0;
501         }
502         csis_fmt = s5pcsis_try_format(&fmt->format);
503         if (mf) {
504                 mutex_lock(&state->lock);
505                 *mf = fmt->format;
506                 if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE)
507                         state->csis_fmt = csis_fmt;
508                 mutex_unlock(&state->lock);
509         }
510         return 0;
511 }
512
513 static int s5pcsis_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
514                            struct v4l2_subdev_format *fmt)
515 {
516         struct csis_state *state = sd_to_csis_state(sd);
517         struct v4l2_mbus_framefmt *mf;
518
519         if (fmt->pad != CSIS_PAD_SOURCE && fmt->pad != CSIS_PAD_SINK)
520                 return -EINVAL;
521
522         mf = __s5pcsis_get_format(state, fh, fmt->pad, fmt->which);
523         if (!mf)
524                 return -EINVAL;
525
526         mutex_lock(&state->lock);
527         fmt->format = *mf;
528         mutex_unlock(&state->lock);
529         return 0;
530 }
531
532 static int s5pcsis_log_status(struct v4l2_subdev *sd)
533 {
534         struct csis_state *state = sd_to_csis_state(sd);
535
536         s5pcsis_log_counters(state, true);
537         return 0;
538 }
539
540 static int s5pcsis_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
541 {
542         struct v4l2_mbus_framefmt *format = v4l2_subdev_get_try_format(fh, 0);
543
544         format->colorspace = V4L2_COLORSPACE_JPEG;
545         format->code = s5pcsis_formats[0].code;
546         format->width = S5PCSIS_DEF_PIX_WIDTH;
547         format->height = S5PCSIS_DEF_PIX_HEIGHT;
548         format->field = V4L2_FIELD_NONE;
549
550         return 0;
551 }
552
553 static const struct v4l2_subdev_internal_ops s5pcsis_sd_internal_ops = {
554         .open = s5pcsis_open,
555 };
556
557 static struct v4l2_subdev_core_ops s5pcsis_core_ops = {
558         .s_power = s5pcsis_s_power,
559         .log_status = s5pcsis_log_status,
560 };
561
562 static struct v4l2_subdev_pad_ops s5pcsis_pad_ops = {
563         .enum_mbus_code = s5pcsis_enum_mbus_code,
564         .get_fmt = s5pcsis_get_fmt,
565         .set_fmt = s5pcsis_set_fmt,
566 };
567
568 static struct v4l2_subdev_video_ops s5pcsis_video_ops = {
569         .s_stream = s5pcsis_s_stream,
570 };
571
572 static struct v4l2_subdev_ops s5pcsis_subdev_ops = {
573         .core = &s5pcsis_core_ops,
574         .pad = &s5pcsis_pad_ops,
575         .video = &s5pcsis_video_ops,
576 };
577
578 static irqreturn_t s5pcsis_irq_handler(int irq, void *dev_id)
579 {
580         struct csis_state *state = dev_id;
581         unsigned long flags;
582         u32 status;
583
584         status = s5pcsis_read(state, S5PCSIS_INTSRC);
585
586         spin_lock_irqsave(&state->slock, flags);
587
588         /* Update the event/error counters */
589         if ((status & S5PCSIS_INTSRC_ERRORS) || debug) {
590                 int i;
591                 for (i = 0; i < S5PCSIS_NUM_EVENTS; i++) {
592                         if (!(status & state->events[i].mask))
593                                 continue;
594                         state->events[i].counter++;
595                         v4l2_dbg(2, debug, &state->sd, "%s: %d\n",
596                                  state->events[i].name,
597                                  state->events[i].counter);
598                 }
599                 v4l2_dbg(2, debug, &state->sd, "status: %08x\n", status);
600         }
601         spin_unlock_irqrestore(&state->slock, flags);
602
603         s5pcsis_write(state, S5PCSIS_INTSRC, status);
604         return IRQ_HANDLED;
605 }
606
607 static int __devinit s5pcsis_probe(struct platform_device *pdev)
608 {
609         struct s5p_platform_mipi_csis *pdata;
610         struct resource *mem_res;
611         struct csis_state *state;
612         int ret = -ENOMEM;
613         int i;
614
615         state = devm_kzalloc(&pdev->dev, sizeof(*state), GFP_KERNEL);
616         if (!state)
617                 return -ENOMEM;
618
619         mutex_init(&state->lock);
620         spin_lock_init(&state->slock);
621
622         state->pdev = pdev;
623
624         pdata = pdev->dev.platform_data;
625         if (pdata == NULL || pdata->phy_enable == NULL) {
626                 dev_err(&pdev->dev, "Platform data not fully specified\n");
627                 return -EINVAL;
628         }
629
630         if ((pdev->id == 1 && pdata->lanes > CSIS1_MAX_LANES) ||
631             pdata->lanes > CSIS0_MAX_LANES) {
632                 dev_err(&pdev->dev, "Unsupported number of data lanes: %d\n",
633                         pdata->lanes);
634                 return -EINVAL;
635         }
636
637         mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
638         state->regs = devm_request_and_ioremap(&pdev->dev, mem_res);
639         if (state->regs == NULL) {
640                 dev_err(&pdev->dev, "Failed to request and remap io memory\n");
641                 return -ENXIO;
642         }
643
644         state->irq = platform_get_irq(pdev, 0);
645         if (state->irq < 0) {
646                 dev_err(&pdev->dev, "Failed to get irq\n");
647                 return state->irq;
648         }
649
650         for (i = 0; i < CSIS_NUM_SUPPLIES; i++)
651                 state->supplies[i].supply = csis_supply_name[i];
652
653         ret = regulator_bulk_get(&pdev->dev, CSIS_NUM_SUPPLIES,
654                                  state->supplies);
655         if (ret)
656                 return ret;
657
658         ret = s5pcsis_clk_get(state);
659         if (ret)
660                 goto e_clkput;
661
662         clk_enable(state->clock[CSIS_CLK_MUX]);
663         if (pdata->clk_rate)
664                 clk_set_rate(state->clock[CSIS_CLK_MUX], pdata->clk_rate);
665         else
666                 dev_WARN(&pdev->dev, "No clock frequency specified!\n");
667
668         ret = devm_request_irq(&pdev->dev, state->irq, s5pcsis_irq_handler,
669                                0, dev_name(&pdev->dev), state);
670         if (ret) {
671                 dev_err(&pdev->dev, "Interrupt request failed\n");
672                 goto e_regput;
673         }
674
675         v4l2_subdev_init(&state->sd, &s5pcsis_subdev_ops);
676         state->sd.owner = THIS_MODULE;
677         strlcpy(state->sd.name, dev_name(&pdev->dev), sizeof(state->sd.name));
678         state->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
679         state->csis_fmt = &s5pcsis_formats[0];
680
681         state->format.code = s5pcsis_formats[0].code;
682         state->format.width = S5PCSIS_DEF_PIX_WIDTH;
683         state->format.height = S5PCSIS_DEF_PIX_HEIGHT;
684
685         state->pads[CSIS_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
686         state->pads[CSIS_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
687         ret = media_entity_init(&state->sd.entity,
688                                 CSIS_PADS_NUM, state->pads, 0);
689         if (ret < 0)
690                 goto e_clkput;
691
692         /* This allows to retrieve the platform device id by the host driver */
693         v4l2_set_subdevdata(&state->sd, pdev);
694
695         /* .. and a pointer to the subdev. */
696         platform_set_drvdata(pdev, &state->sd);
697
698         memcpy(state->events, s5pcsis_events, sizeof(state->events));
699
700         pm_runtime_enable(&pdev->dev);
701         return 0;
702
703 e_regput:
704         regulator_bulk_free(CSIS_NUM_SUPPLIES, state->supplies);
705 e_clkput:
706         clk_disable(state->clock[CSIS_CLK_MUX]);
707         s5pcsis_clk_put(state);
708         return ret;
709 }
710
711 static int s5pcsis_pm_suspend(struct device *dev, bool runtime)
712 {
713         struct s5p_platform_mipi_csis *pdata = dev->platform_data;
714         struct platform_device *pdev = to_platform_device(dev);
715         struct v4l2_subdev *sd = platform_get_drvdata(pdev);
716         struct csis_state *state = sd_to_csis_state(sd);
717         int ret = 0;
718
719         v4l2_dbg(1, debug, sd, "%s: flags: 0x%x\n",
720                  __func__, state->flags);
721
722         mutex_lock(&state->lock);
723         if (state->flags & ST_POWERED) {
724                 s5pcsis_stop_stream(state);
725                 ret = pdata->phy_enable(state->pdev, false);
726                 if (ret)
727                         goto unlock;
728                 ret = regulator_bulk_disable(CSIS_NUM_SUPPLIES,
729                                              state->supplies);
730                 if (ret)
731                         goto unlock;
732                 clk_disable(state->clock[CSIS_CLK_GATE]);
733                 state->flags &= ~ST_POWERED;
734                 if (!runtime)
735                         state->flags |= ST_SUSPENDED;
736         }
737  unlock:
738         mutex_unlock(&state->lock);
739         return ret ? -EAGAIN : 0;
740 }
741
742 static int s5pcsis_pm_resume(struct device *dev, bool runtime)
743 {
744         struct s5p_platform_mipi_csis *pdata = dev->platform_data;
745         struct platform_device *pdev = to_platform_device(dev);
746         struct v4l2_subdev *sd = platform_get_drvdata(pdev);
747         struct csis_state *state = sd_to_csis_state(sd);
748         int ret = 0;
749
750         v4l2_dbg(1, debug, sd, "%s: flags: 0x%x\n",
751                  __func__, state->flags);
752
753         mutex_lock(&state->lock);
754         if (!runtime && !(state->flags & ST_SUSPENDED))
755                 goto unlock;
756
757         if (!(state->flags & ST_POWERED)) {
758                 ret = regulator_bulk_enable(CSIS_NUM_SUPPLIES,
759                                             state->supplies);
760                 if (ret)
761                         goto unlock;
762                 ret = pdata->phy_enable(state->pdev, true);
763                 if (!ret) {
764                         state->flags |= ST_POWERED;
765                 } else {
766                         regulator_bulk_disable(CSIS_NUM_SUPPLIES,
767                                                state->supplies);
768                         goto unlock;
769                 }
770                 clk_enable(state->clock[CSIS_CLK_GATE]);
771         }
772         if (state->flags & ST_STREAMING)
773                 s5pcsis_start_stream(state);
774
775         state->flags &= ~ST_SUSPENDED;
776  unlock:
777         mutex_unlock(&state->lock);
778         return ret ? -EAGAIN : 0;
779 }
780
781 #ifdef CONFIG_PM_SLEEP
782 static int s5pcsis_suspend(struct device *dev)
783 {
784         return s5pcsis_pm_suspend(dev, false);
785 }
786
787 static int s5pcsis_resume(struct device *dev)
788 {
789         return s5pcsis_pm_resume(dev, false);
790 }
791 #endif
792
793 #ifdef CONFIG_PM_RUNTIME
794 static int s5pcsis_runtime_suspend(struct device *dev)
795 {
796         return s5pcsis_pm_suspend(dev, true);
797 }
798
799 static int s5pcsis_runtime_resume(struct device *dev)
800 {
801         return s5pcsis_pm_resume(dev, true);
802 }
803 #endif
804
805 static int __devexit s5pcsis_remove(struct platform_device *pdev)
806 {
807         struct v4l2_subdev *sd = platform_get_drvdata(pdev);
808         struct csis_state *state = sd_to_csis_state(sd);
809
810         pm_runtime_disable(&pdev->dev);
811         s5pcsis_pm_suspend(&pdev->dev, false);
812         clk_disable(state->clock[CSIS_CLK_MUX]);
813         pm_runtime_set_suspended(&pdev->dev);
814         s5pcsis_clk_put(state);
815         regulator_bulk_free(CSIS_NUM_SUPPLIES, state->supplies);
816
817         media_entity_cleanup(&state->sd.entity);
818
819         return 0;
820 }
821
822 static const struct dev_pm_ops s5pcsis_pm_ops = {
823         SET_RUNTIME_PM_OPS(s5pcsis_runtime_suspend, s5pcsis_runtime_resume,
824                            NULL)
825         SET_SYSTEM_SLEEP_PM_OPS(s5pcsis_suspend, s5pcsis_resume)
826 };
827
828 static struct platform_driver s5pcsis_driver = {
829         .probe          = s5pcsis_probe,
830         .remove         = __devexit_p(s5pcsis_remove),
831         .driver         = {
832                 .name   = CSIS_DRIVER_NAME,
833                 .owner  = THIS_MODULE,
834                 .pm     = &s5pcsis_pm_ops,
835         },
836 };
837
838 module_platform_driver(s5pcsis_driver);
839
840 MODULE_AUTHOR("Sylwester Nawrocki <s.nawrocki@samsung.com>");
841 MODULE_DESCRIPTION("Samsung S5P/EXYNOS SoC MIPI-CSI2 receiver driver");
842 MODULE_LICENSE("GPL");