2 * Samsung S5P/EXYNOS4 SoC series MIPI-CSI receiver driver
4 * Copyright (C) 2011 - 2012 Samsung Electronics Co., Ltd.
5 * Sylwester Nawrocki, <s.nawrocki@samsung.com>
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.
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>
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"
33 module_param(debug
, int, 0644);
34 MODULE_PARM_DESC(debug
, "Debug level (0-1)");
36 /* Register map definition */
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)
49 #define S5PCSIS_DPHYCTRL 0x04
50 #define S5PCSIS_DPHYCTRL_HSS_MASK (0x1f << 27)
51 #define S5PCSIS_DPHYCTRL_ENABLE (0x1f << 0)
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
64 #define S5PCSIS_INTMSK 0x10
65 #define S5PCSIS_INTMSK_EN_ALL 0xf000003f
66 #define S5PCSIS_INTSRC 0x14
68 /* Pixel resolution */
69 #define S5PCSIS_RESOL 0x2c
70 #define CSIS_MAX_PIX_WIDTH 0xffff
71 #define CSIS_MAX_PIX_HEIGHT 0xffff
78 static char *csi_clock_name
[] = {
79 [CSIS_CLK_MUX
] = "sclk_csis",
80 [CSIS_CLK_GATE
] = "csis",
82 #define NUM_CSIS_CLOCKS ARRAY_SIZE(csi_clock_name)
84 static const char * const csis_supply_name
[] = {
85 "vdd11", /* 1.1V or 1.2V (s5pc100) MIPI CSI suppply */
86 "vdd18", /* VDD 1.8V and MIPI CSI PLL supply */
88 #define CSIS_NUM_SUPPLIES ARRAY_SIZE(csis_supply_name)
97 * struct csis_state - the driver's internal state data structure
98 * @lock: mutex serializing the subdev and power management operations,
99 * protecting @format and @flags members
100 * @pads: CSIS pads array
101 * @sd: v4l2_subdev associated with CSIS device instance
102 * @pdev: CSIS platform device
103 * @regs: mmaped I/O registers memory
104 * @clock: CSIS clocks
105 * @irq: requested s5p-mipi-csis irq number
106 * @flags: the state variable for power and streaming control
107 * @csis_fmt: current CSIS pixel format
108 * @format: common media bus format for the source and sink pad
112 struct media_pad pads
[CSIS_PADS_NUM
];
113 struct v4l2_subdev sd
;
114 struct platform_device
*pdev
;
116 struct regulator_bulk_data supplies
[CSIS_NUM_SUPPLIES
];
117 struct clk
*clock
[NUM_CSIS_CLOCKS
];
120 const struct csis_pix_format
*csis_fmt
;
121 struct v4l2_mbus_framefmt format
;
125 * struct csis_pix_format - CSIS pixel format description
126 * @pix_width_alignment: horizontal pixel alignment, width will be
127 * multiple of 2^pix_width_alignment
128 * @code: corresponding media bus code
129 * @fmt_reg: S5PCSIS_CONFIG register value
130 * @data_alignment: MIPI-CSI data alignment in bits
132 struct csis_pix_format
{
133 unsigned int pix_width_alignment
;
134 enum v4l2_mbus_pixelcode code
;
139 static const struct csis_pix_format s5pcsis_formats
[] = {
141 .code
= V4L2_MBUS_FMT_VYUY8_2X8
,
142 .fmt_reg
= S5PCSIS_CFG_FMT_YCBCR422_8BIT
,
143 .data_alignment
= 32,
145 .code
= V4L2_MBUS_FMT_JPEG_1X8
,
146 .fmt_reg
= S5PCSIS_CFG_FMT_USER(1),
147 .data_alignment
= 32,
151 #define s5pcsis_write(__csis, __r, __v) writel(__v, __csis->regs + __r)
152 #define s5pcsis_read(__csis, __r) readl(__csis->regs + __r)
154 static struct csis_state
*sd_to_csis_state(struct v4l2_subdev
*sdev
)
156 return container_of(sdev
, struct csis_state
, sd
);
159 static const struct csis_pix_format
*find_csis_format(
160 struct v4l2_mbus_framefmt
*mf
)
164 for (i
= 0; i
< ARRAY_SIZE(s5pcsis_formats
); i
++)
165 if (mf
->code
== s5pcsis_formats
[i
].code
)
166 return &s5pcsis_formats
[i
];
170 static void s5pcsis_enable_interrupts(struct csis_state
*state
, bool on
)
172 u32 val
= s5pcsis_read(state
, S5PCSIS_INTMSK
);
174 val
= on
? val
| S5PCSIS_INTMSK_EN_ALL
:
175 val
& ~S5PCSIS_INTMSK_EN_ALL
;
176 s5pcsis_write(state
, S5PCSIS_INTMSK
, val
);
179 static void s5pcsis_reset(struct csis_state
*state
)
181 u32 val
= s5pcsis_read(state
, S5PCSIS_CTRL
);
183 s5pcsis_write(state
, S5PCSIS_CTRL
, val
| S5PCSIS_CTRL_RESET
);
187 static void s5pcsis_system_enable(struct csis_state
*state
, int on
)
191 val
= s5pcsis_read(state
, S5PCSIS_CTRL
);
193 val
|= S5PCSIS_CTRL_ENABLE
;
195 val
&= ~S5PCSIS_CTRL_ENABLE
;
196 s5pcsis_write(state
, S5PCSIS_CTRL
, val
);
198 val
= s5pcsis_read(state
, S5PCSIS_DPHYCTRL
);
200 val
|= S5PCSIS_DPHYCTRL_ENABLE
;
202 val
&= ~S5PCSIS_DPHYCTRL_ENABLE
;
203 s5pcsis_write(state
, S5PCSIS_DPHYCTRL
, val
);
206 /* Called with the state.lock mutex held */
207 static void __s5pcsis_set_format(struct csis_state
*state
)
209 struct v4l2_mbus_framefmt
*mf
= &state
->format
;
212 v4l2_dbg(1, debug
, &state
->sd
, "fmt: %d, %d x %d\n",
213 mf
->code
, mf
->width
, mf
->height
);
216 val
= s5pcsis_read(state
, S5PCSIS_CONFIG
);
217 val
= (val
& ~S5PCSIS_CFG_FMT_MASK
) | state
->csis_fmt
->fmt_reg
;
218 s5pcsis_write(state
, S5PCSIS_CONFIG
, val
);
220 /* Pixel resolution */
221 val
= (mf
->width
<< 16) | mf
->height
;
222 s5pcsis_write(state
, S5PCSIS_RESOL
, val
);
225 static void s5pcsis_set_hsync_settle(struct csis_state
*state
, int settle
)
227 u32 val
= s5pcsis_read(state
, S5PCSIS_DPHYCTRL
);
229 val
= (val
& ~S5PCSIS_DPHYCTRL_HSS_MASK
) | (settle
<< 27);
230 s5pcsis_write(state
, S5PCSIS_DPHYCTRL
, val
);
233 static void s5pcsis_set_params(struct csis_state
*state
)
235 struct s5p_platform_mipi_csis
*pdata
= state
->pdev
->dev
.platform_data
;
238 val
= s5pcsis_read(state
, S5PCSIS_CONFIG
);
239 val
= (val
& ~S5PCSIS_CFG_NR_LANE_MASK
) | (pdata
->lanes
- 1);
240 s5pcsis_write(state
, S5PCSIS_CONFIG
, val
);
242 __s5pcsis_set_format(state
);
243 s5pcsis_set_hsync_settle(state
, pdata
->hs_settle
);
245 val
= s5pcsis_read(state
, S5PCSIS_CTRL
);
246 if (state
->csis_fmt
->data_alignment
== 32)
247 val
|= S5PCSIS_CTRL_ALIGN_32BIT
;
249 val
&= ~S5PCSIS_CTRL_ALIGN_32BIT
;
250 /* Not using external clock. */
251 val
&= ~S5PCSIS_CTRL_WCLK_EXTCLK
;
252 s5pcsis_write(state
, S5PCSIS_CTRL
, val
);
254 /* Update the shadow register. */
255 val
= s5pcsis_read(state
, S5PCSIS_CTRL
);
256 s5pcsis_write(state
, S5PCSIS_CTRL
, val
| S5PCSIS_CTRL_UPDATE_SHADOW
);
259 static void s5pcsis_clk_put(struct csis_state
*state
)
263 for (i
= 0; i
< NUM_CSIS_CLOCKS
; i
++) {
264 if (IS_ERR_OR_NULL(state
->clock
[i
]))
266 clk_unprepare(state
->clock
[i
]);
267 clk_put(state
->clock
[i
]);
268 state
->clock
[i
] = NULL
;
272 static int s5pcsis_clk_get(struct csis_state
*state
)
274 struct device
*dev
= &state
->pdev
->dev
;
277 for (i
= 0; i
< NUM_CSIS_CLOCKS
; i
++) {
278 state
->clock
[i
] = clk_get(dev
, csi_clock_name
[i
]);
279 if (IS_ERR(state
->clock
[i
]))
281 ret
= clk_prepare(state
->clock
[i
]);
283 clk_put(state
->clock
[i
]);
284 state
->clock
[i
] = NULL
;
290 s5pcsis_clk_put(state
);
291 dev_err(dev
, "failed to get clock: %s\n", csi_clock_name
[i
]);
295 static int s5pcsis_s_power(struct v4l2_subdev
*sd
, int on
)
297 struct csis_state
*state
= sd_to_csis_state(sd
);
298 struct device
*dev
= &state
->pdev
->dev
;
301 return pm_runtime_get_sync(dev
);
303 return pm_runtime_put_sync(dev
);
306 static void s5pcsis_start_stream(struct csis_state
*state
)
308 s5pcsis_reset(state
);
309 s5pcsis_set_params(state
);
310 s5pcsis_system_enable(state
, true);
311 s5pcsis_enable_interrupts(state
, true);
314 static void s5pcsis_stop_stream(struct csis_state
*state
)
316 s5pcsis_enable_interrupts(state
, false);
317 s5pcsis_system_enable(state
, false);
320 /* v4l2_subdev operations */
321 static int s5pcsis_s_stream(struct v4l2_subdev
*sd
, int enable
)
323 struct csis_state
*state
= sd_to_csis_state(sd
);
326 v4l2_dbg(1, debug
, sd
, "%s: %d, state: 0x%x\n",
327 __func__
, enable
, state
->flags
);
330 ret
= pm_runtime_get_sync(&state
->pdev
->dev
);
334 mutex_lock(&state
->lock
);
336 if (state
->flags
& ST_SUSPENDED
) {
340 s5pcsis_start_stream(state
);
341 state
->flags
|= ST_STREAMING
;
343 s5pcsis_stop_stream(state
);
344 state
->flags
&= ~ST_STREAMING
;
347 mutex_unlock(&state
->lock
);
349 pm_runtime_put(&state
->pdev
->dev
);
351 return ret
== 1 ? 0 : ret
;
354 static int s5pcsis_enum_mbus_code(struct v4l2_subdev
*sd
,
355 struct v4l2_subdev_fh
*fh
,
356 struct v4l2_subdev_mbus_code_enum
*code
)
358 if (code
->index
>= ARRAY_SIZE(s5pcsis_formats
))
361 code
->code
= s5pcsis_formats
[code
->index
].code
;
365 static struct csis_pix_format
const *s5pcsis_try_format(
366 struct v4l2_mbus_framefmt
*mf
)
368 struct csis_pix_format
const *csis_fmt
;
370 csis_fmt
= find_csis_format(mf
);
371 if (csis_fmt
== NULL
)
372 csis_fmt
= &s5pcsis_formats
[0];
374 mf
->code
= csis_fmt
->code
;
375 v4l_bound_align_image(&mf
->width
, 1, CSIS_MAX_PIX_WIDTH
,
376 csis_fmt
->pix_width_alignment
,
377 &mf
->height
, 1, CSIS_MAX_PIX_HEIGHT
, 1,
382 static struct v4l2_mbus_framefmt
*__s5pcsis_get_format(
383 struct csis_state
*state
, struct v4l2_subdev_fh
*fh
,
384 u32 pad
, enum v4l2_subdev_format_whence which
)
386 if (which
== V4L2_SUBDEV_FORMAT_TRY
)
387 return fh
? v4l2_subdev_get_try_format(fh
, pad
) : NULL
;
389 return &state
->format
;
392 static int s5pcsis_set_fmt(struct v4l2_subdev
*sd
, struct v4l2_subdev_fh
*fh
,
393 struct v4l2_subdev_format
*fmt
)
395 struct csis_state
*state
= sd_to_csis_state(sd
);
396 struct csis_pix_format
const *csis_fmt
;
397 struct v4l2_mbus_framefmt
*mf
;
399 if (fmt
->pad
!= CSIS_PAD_SOURCE
&& fmt
->pad
!= CSIS_PAD_SINK
)
402 mf
= __s5pcsis_get_format(state
, fh
, fmt
->pad
, fmt
->which
);
404 if (fmt
->pad
== CSIS_PAD_SOURCE
) {
406 mutex_lock(&state
->lock
);
408 mutex_unlock(&state
->lock
);
412 csis_fmt
= s5pcsis_try_format(&fmt
->format
);
414 mutex_lock(&state
->lock
);
416 if (fmt
->which
== V4L2_SUBDEV_FORMAT_ACTIVE
)
417 state
->csis_fmt
= csis_fmt
;
418 mutex_unlock(&state
->lock
);
423 static int s5pcsis_get_fmt(struct v4l2_subdev
*sd
, struct v4l2_subdev_fh
*fh
,
424 struct v4l2_subdev_format
*fmt
)
426 struct csis_state
*state
= sd_to_csis_state(sd
);
427 struct v4l2_mbus_framefmt
*mf
;
429 if (fmt
->pad
!= CSIS_PAD_SOURCE
&& fmt
->pad
!= CSIS_PAD_SINK
)
432 mf
= __s5pcsis_get_format(state
, fh
, fmt
->pad
, fmt
->which
);
436 mutex_lock(&state
->lock
);
438 mutex_unlock(&state
->lock
);
442 static int s5pcsis_open(struct v4l2_subdev
*sd
, struct v4l2_subdev_fh
*fh
)
444 struct v4l2_mbus_framefmt
*format
= v4l2_subdev_get_try_format(fh
, 0);
446 format
->colorspace
= V4L2_COLORSPACE_JPEG
;
447 format
->code
= s5pcsis_formats
[0].code
;
448 format
->width
= S5PCSIS_DEF_PIX_WIDTH
;
449 format
->height
= S5PCSIS_DEF_PIX_HEIGHT
;
450 format
->field
= V4L2_FIELD_NONE
;
455 static const struct v4l2_subdev_internal_ops s5pcsis_sd_internal_ops
= {
456 .open
= s5pcsis_open
,
459 static struct v4l2_subdev_core_ops s5pcsis_core_ops
= {
460 .s_power
= s5pcsis_s_power
,
463 static struct v4l2_subdev_pad_ops s5pcsis_pad_ops
= {
464 .enum_mbus_code
= s5pcsis_enum_mbus_code
,
465 .get_fmt
= s5pcsis_get_fmt
,
466 .set_fmt
= s5pcsis_set_fmt
,
469 static struct v4l2_subdev_video_ops s5pcsis_video_ops
= {
470 .s_stream
= s5pcsis_s_stream
,
473 static struct v4l2_subdev_ops s5pcsis_subdev_ops
= {
474 .core
= &s5pcsis_core_ops
,
475 .pad
= &s5pcsis_pad_ops
,
476 .video
= &s5pcsis_video_ops
,
479 static irqreturn_t
s5pcsis_irq_handler(int irq
, void *dev_id
)
481 struct csis_state
*state
= dev_id
;
484 /* Just clear the interrupt pending bits. */
485 val
= s5pcsis_read(state
, S5PCSIS_INTSRC
);
486 s5pcsis_write(state
, S5PCSIS_INTSRC
, val
);
491 static int __devinit
s5pcsis_probe(struct platform_device
*pdev
)
493 struct s5p_platform_mipi_csis
*pdata
;
494 struct resource
*mem_res
;
495 struct csis_state
*state
;
499 state
= devm_kzalloc(&pdev
->dev
, sizeof(*state
), GFP_KERNEL
);
503 mutex_init(&state
->lock
);
506 pdata
= pdev
->dev
.platform_data
;
507 if (pdata
== NULL
|| pdata
->phy_enable
== NULL
) {
508 dev_err(&pdev
->dev
, "Platform data not fully specified\n");
512 if ((pdev
->id
== 1 && pdata
->lanes
> CSIS1_MAX_LANES
) ||
513 pdata
->lanes
> CSIS0_MAX_LANES
) {
514 dev_err(&pdev
->dev
, "Unsupported number of data lanes: %d\n",
519 mem_res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
520 state
->regs
= devm_request_and_ioremap(&pdev
->dev
, mem_res
);
521 if (state
->regs
== NULL
) {
522 dev_err(&pdev
->dev
, "Failed to request and remap io memory\n");
526 state
->irq
= platform_get_irq(pdev
, 0);
527 if (state
->irq
< 0) {
528 dev_err(&pdev
->dev
, "Failed to get irq\n");
532 for (i
= 0; i
< CSIS_NUM_SUPPLIES
; i
++)
533 state
->supplies
[i
].supply
= csis_supply_name
[i
];
535 ret
= regulator_bulk_get(&pdev
->dev
, CSIS_NUM_SUPPLIES
,
540 ret
= s5pcsis_clk_get(state
);
544 clk_enable(state
->clock
[CSIS_CLK_MUX
]);
546 clk_set_rate(state
->clock
[CSIS_CLK_MUX
], pdata
->clk_rate
);
548 dev_WARN(&pdev
->dev
, "No clock frequency specified!\n");
550 ret
= devm_request_irq(&pdev
->dev
, state
->irq
, s5pcsis_irq_handler
,
551 0, dev_name(&pdev
->dev
), state
);
553 dev_err(&pdev
->dev
, "Interrupt request failed\n");
557 v4l2_subdev_init(&state
->sd
, &s5pcsis_subdev_ops
);
558 state
->sd
.owner
= THIS_MODULE
;
559 strlcpy(state
->sd
.name
, dev_name(&pdev
->dev
), sizeof(state
->sd
.name
));
560 state
->sd
.flags
|= V4L2_SUBDEV_FL_HAS_DEVNODE
;
561 state
->csis_fmt
= &s5pcsis_formats
[0];
563 state
->format
.code
= s5pcsis_formats
[0].code
;
564 state
->format
.width
= S5PCSIS_DEF_PIX_WIDTH
;
565 state
->format
.height
= S5PCSIS_DEF_PIX_HEIGHT
;
567 state
->pads
[CSIS_PAD_SINK
].flags
= MEDIA_PAD_FL_SINK
;
568 state
->pads
[CSIS_PAD_SOURCE
].flags
= MEDIA_PAD_FL_SOURCE
;
569 ret
= media_entity_init(&state
->sd
.entity
,
570 CSIS_PADS_NUM
, state
->pads
, 0);
574 /* This allows to retrieve the platform device id by the host driver */
575 v4l2_set_subdevdata(&state
->sd
, pdev
);
577 /* .. and a pointer to the subdev. */
578 platform_set_drvdata(pdev
, &state
->sd
);
580 pm_runtime_enable(&pdev
->dev
);
584 regulator_bulk_free(CSIS_NUM_SUPPLIES
, state
->supplies
);
586 clk_disable(state
->clock
[CSIS_CLK_MUX
]);
587 s5pcsis_clk_put(state
);
591 static int s5pcsis_pm_suspend(struct device
*dev
, bool runtime
)
593 struct s5p_platform_mipi_csis
*pdata
= dev
->platform_data
;
594 struct platform_device
*pdev
= to_platform_device(dev
);
595 struct v4l2_subdev
*sd
= platform_get_drvdata(pdev
);
596 struct csis_state
*state
= sd_to_csis_state(sd
);
599 v4l2_dbg(1, debug
, sd
, "%s: flags: 0x%x\n",
600 __func__
, state
->flags
);
602 mutex_lock(&state
->lock
);
603 if (state
->flags
& ST_POWERED
) {
604 s5pcsis_stop_stream(state
);
605 ret
= pdata
->phy_enable(state
->pdev
, false);
608 ret
= regulator_bulk_disable(CSIS_NUM_SUPPLIES
,
612 clk_disable(state
->clock
[CSIS_CLK_GATE
]);
613 state
->flags
&= ~ST_POWERED
;
615 state
->flags
|= ST_SUSPENDED
;
618 mutex_unlock(&state
->lock
);
619 return ret
? -EAGAIN
: 0;
622 static int s5pcsis_pm_resume(struct device
*dev
, bool runtime
)
624 struct s5p_platform_mipi_csis
*pdata
= dev
->platform_data
;
625 struct platform_device
*pdev
= to_platform_device(dev
);
626 struct v4l2_subdev
*sd
= platform_get_drvdata(pdev
);
627 struct csis_state
*state
= sd_to_csis_state(sd
);
630 v4l2_dbg(1, debug
, sd
, "%s: flags: 0x%x\n",
631 __func__
, state
->flags
);
633 mutex_lock(&state
->lock
);
634 if (!runtime
&& !(state
->flags
& ST_SUSPENDED
))
637 if (!(state
->flags
& ST_POWERED
)) {
638 ret
= regulator_bulk_enable(CSIS_NUM_SUPPLIES
,
642 ret
= pdata
->phy_enable(state
->pdev
, true);
644 state
->flags
|= ST_POWERED
;
646 regulator_bulk_disable(CSIS_NUM_SUPPLIES
,
650 clk_enable(state
->clock
[CSIS_CLK_GATE
]);
652 if (state
->flags
& ST_STREAMING
)
653 s5pcsis_start_stream(state
);
655 state
->flags
&= ~ST_SUSPENDED
;
657 mutex_unlock(&state
->lock
);
658 return ret
? -EAGAIN
: 0;
661 #ifdef CONFIG_PM_SLEEP
662 static int s5pcsis_suspend(struct device
*dev
)
664 return s5pcsis_pm_suspend(dev
, false);
667 static int s5pcsis_resume(struct device
*dev
)
669 return s5pcsis_pm_resume(dev
, false);
673 #ifdef CONFIG_PM_RUNTIME
674 static int s5pcsis_runtime_suspend(struct device
*dev
)
676 return s5pcsis_pm_suspend(dev
, true);
679 static int s5pcsis_runtime_resume(struct device
*dev
)
681 return s5pcsis_pm_resume(dev
, true);
685 static int __devexit
s5pcsis_remove(struct platform_device
*pdev
)
687 struct v4l2_subdev
*sd
= platform_get_drvdata(pdev
);
688 struct csis_state
*state
= sd_to_csis_state(sd
);
690 pm_runtime_disable(&pdev
->dev
);
691 s5pcsis_pm_suspend(&pdev
->dev
, false);
692 clk_disable(state
->clock
[CSIS_CLK_MUX
]);
693 pm_runtime_set_suspended(&pdev
->dev
);
694 s5pcsis_clk_put(state
);
695 regulator_bulk_free(CSIS_NUM_SUPPLIES
, state
->supplies
);
697 media_entity_cleanup(&state
->sd
.entity
);
702 static const struct dev_pm_ops s5pcsis_pm_ops
= {
703 SET_RUNTIME_PM_OPS(s5pcsis_runtime_suspend
, s5pcsis_runtime_resume
,
705 SET_SYSTEM_SLEEP_PM_OPS(s5pcsis_suspend
, s5pcsis_resume
)
708 static struct platform_driver s5pcsis_driver
= {
709 .probe
= s5pcsis_probe
,
710 .remove
= __devexit_p(s5pcsis_remove
),
712 .name
= CSIS_DRIVER_NAME
,
713 .owner
= THIS_MODULE
,
714 .pm
= &s5pcsis_pm_ops
,
718 module_platform_driver(s5pcsis_driver
);
720 MODULE_AUTHOR("Sylwester Nawrocki <s.nawrocki@samsung.com>");
721 MODULE_DESCRIPTION("Samsung S5P/EXYNOS SoC MIPI-CSI2 receiver driver");
722 MODULE_LICENSE("GPL");