mipi-csis.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722
  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. #include <linux/clk.h>
  12. #include <linux/delay.h>
  13. #include <linux/device.h>
  14. #include <linux/errno.h>
  15. #include <linux/interrupt.h>
  16. #include <linux/io.h>
  17. #include <linux/irq.h>
  18. #include <linux/kernel.h>
  19. #include <linux/memory.h>
  20. #include <linux/module.h>
  21. #include <linux/platform_device.h>
  22. #include <linux/pm_runtime.h>
  23. #include <linux/regulator/consumer.h>
  24. #include <linux/slab.h>
  25. #include <linux/spinlock.h>
  26. #include <linux/videodev2.h>
  27. #include <media/v4l2-subdev.h>
  28. #include <linux/platform_data/mipi-csis.h>
  29. #include "mipi-csis.h"
  30. static int debug;
  31. module_param(debug, int, 0644);
  32. MODULE_PARM_DESC(debug, "Debug level (0-1)");
  33. /* Register map definition */
  34. /* CSIS global control */
  35. #define S5PCSIS_CTRL 0x00
  36. #define S5PCSIS_CTRL_DPDN_DEFAULT (0 << 31)
  37. #define S5PCSIS_CTRL_DPDN_SWAP (1 << 31)
  38. #define S5PCSIS_CTRL_ALIGN_32BIT (1 << 20)
  39. #define S5PCSIS_CTRL_UPDATE_SHADOW (1 << 16)
  40. #define S5PCSIS_CTRL_WCLK_EXTCLK (1 << 8)
  41. #define S5PCSIS_CTRL_RESET (1 << 4)
  42. #define S5PCSIS_CTRL_ENABLE (1 << 0)
  43. /* D-PHY control */
  44. #define S5PCSIS_DPHYCTRL 0x04
  45. #define S5PCSIS_DPHYCTRL_HSS_MASK (0x1f << 27)
  46. #define S5PCSIS_DPHYCTRL_ENABLE (0x1f << 0)
  47. #define S5PCSIS_CONFIG 0x08
  48. #define S5PCSIS_CFG_FMT_YCBCR422_8BIT (0x1e << 2)
  49. #define S5PCSIS_CFG_FMT_RAW8 (0x2a << 2)
  50. #define S5PCSIS_CFG_FMT_RAW10 (0x2b << 2)
  51. #define S5PCSIS_CFG_FMT_RAW12 (0x2c << 2)
  52. /* User defined formats, x = 1...4 */
  53. #define S5PCSIS_CFG_FMT_USER(x) ((0x30 + x - 1) << 2)
  54. #define S5PCSIS_CFG_FMT_MASK (0x3f << 2)
  55. #define S5PCSIS_CFG_NR_LANE_MASK 3
  56. /* Interrupt mask. */
  57. #define S5PCSIS_INTMSK 0x10
  58. #define S5PCSIS_INTMSK_EN_ALL 0xf000003f
  59. #define S5PCSIS_INTSRC 0x14
  60. /* Pixel resolution */
  61. #define S5PCSIS_RESOL 0x2c
  62. #define CSIS_MAX_PIX_WIDTH 0xffff
  63. #define CSIS_MAX_PIX_HEIGHT 0xffff
  64. enum {
  65. CSIS_CLK_MUX,
  66. CSIS_CLK_GATE,
  67. };
  68. static char *csi_clock_name[] = {
  69. [CSIS_CLK_MUX] = "sclk_csis",
  70. [CSIS_CLK_GATE] = "csis",
  71. };
  72. #define NUM_CSIS_CLOCKS ARRAY_SIZE(csi_clock_name)
  73. static const char * const csis_supply_name[] = {
  74. "vdd11", /* 1.1V or 1.2V (s5pc100) MIPI CSI suppply */
  75. "vdd18", /* VDD 1.8V and MIPI CSI PLL supply */
  76. };
  77. #define CSIS_NUM_SUPPLIES ARRAY_SIZE(csis_supply_name)
  78. enum {
  79. ST_POWERED = 1,
  80. ST_STREAMING = 2,
  81. ST_SUSPENDED = 4,
  82. };
  83. /**
  84. * struct csis_state - the driver's internal state data structure
  85. * @lock: mutex serializing the subdev and power management operations,
  86. * protecting @format and @flags members
  87. * @pads: CSIS pads array
  88. * @sd: v4l2_subdev associated with CSIS device instance
  89. * @pdev: CSIS platform device
  90. * @regs: mmaped I/O registers memory
  91. * @clock: CSIS clocks
  92. * @irq: requested s5p-mipi-csis irq number
  93. * @flags: the state variable for power and streaming control
  94. * @csis_fmt: current CSIS pixel format
  95. * @format: common media bus format for the source and sink pad
  96. */
  97. struct csis_state {
  98. struct mutex lock;
  99. struct media_pad pads[CSIS_PADS_NUM];
  100. struct v4l2_subdev sd;
  101. struct platform_device *pdev;
  102. void __iomem *regs;
  103. struct regulator_bulk_data supplies[CSIS_NUM_SUPPLIES];
  104. struct clk *clock[NUM_CSIS_CLOCKS];
  105. int irq;
  106. u32 flags;
  107. const struct csis_pix_format *csis_fmt;
  108. struct v4l2_mbus_framefmt format;
  109. };
  110. /**
  111. * struct csis_pix_format - CSIS pixel format description
  112. * @pix_width_alignment: horizontal pixel alignment, width will be
  113. * multiple of 2^pix_width_alignment
  114. * @code: corresponding media bus code
  115. * @fmt_reg: S5PCSIS_CONFIG register value
  116. * @data_alignment: MIPI-CSI data alignment in bits
  117. */
  118. struct csis_pix_format {
  119. unsigned int pix_width_alignment;
  120. enum v4l2_mbus_pixelcode code;
  121. u32 fmt_reg;
  122. u8 data_alignment;
  123. };
  124. static const struct csis_pix_format s5pcsis_formats[] = {
  125. {
  126. .code = V4L2_MBUS_FMT_VYUY8_2X8,
  127. .fmt_reg = S5PCSIS_CFG_FMT_YCBCR422_8BIT,
  128. .data_alignment = 32,
  129. }, {
  130. .code = V4L2_MBUS_FMT_JPEG_1X8,
  131. .fmt_reg = S5PCSIS_CFG_FMT_USER(1),
  132. .data_alignment = 32,
  133. },
  134. };
  135. #define s5pcsis_write(__csis, __r, __v) writel(__v, __csis->regs + __r)
  136. #define s5pcsis_read(__csis, __r) readl(__csis->regs + __r)
  137. static struct csis_state *sd_to_csis_state(struct v4l2_subdev *sdev)
  138. {
  139. return container_of(sdev, struct csis_state, sd);
  140. }
  141. static const struct csis_pix_format *find_csis_format(
  142. struct v4l2_mbus_framefmt *mf)
  143. {
  144. int i;
  145. for (i = 0; i < ARRAY_SIZE(s5pcsis_formats); i++)
  146. if (mf->code == s5pcsis_formats[i].code)
  147. return &s5pcsis_formats[i];
  148. return NULL;
  149. }
  150. static void s5pcsis_enable_interrupts(struct csis_state *state, bool on)
  151. {
  152. u32 val = s5pcsis_read(state, S5PCSIS_INTMSK);
  153. val = on ? val | S5PCSIS_INTMSK_EN_ALL :
  154. val & ~S5PCSIS_INTMSK_EN_ALL;
  155. s5pcsis_write(state, S5PCSIS_INTMSK, val);
  156. }
  157. static void s5pcsis_reset(struct csis_state *state)
  158. {
  159. u32 val = s5pcsis_read(state, S5PCSIS_CTRL);
  160. s5pcsis_write(state, S5PCSIS_CTRL, val | S5PCSIS_CTRL_RESET);
  161. udelay(10);
  162. }
  163. static void s5pcsis_system_enable(struct csis_state *state, int on)
  164. {
  165. u32 val;
  166. val = s5pcsis_read(state, S5PCSIS_CTRL);
  167. if (on)
  168. val |= S5PCSIS_CTRL_ENABLE;
  169. else
  170. val &= ~S5PCSIS_CTRL_ENABLE;
  171. s5pcsis_write(state, S5PCSIS_CTRL, val);
  172. val = s5pcsis_read(state, S5PCSIS_DPHYCTRL);
  173. if (on)
  174. val |= S5PCSIS_DPHYCTRL_ENABLE;
  175. else
  176. val &= ~S5PCSIS_DPHYCTRL_ENABLE;
  177. s5pcsis_write(state, S5PCSIS_DPHYCTRL, val);
  178. }
  179. /* Called with the state.lock mutex held */
  180. static void __s5pcsis_set_format(struct csis_state *state)
  181. {
  182. struct v4l2_mbus_framefmt *mf = &state->format;
  183. u32 val;
  184. v4l2_dbg(1, debug, &state->sd, "fmt: %d, %d x %d\n",
  185. mf->code, mf->width, mf->height);
  186. /* Color format */
  187. val = s5pcsis_read(state, S5PCSIS_CONFIG);
  188. val = (val & ~S5PCSIS_CFG_FMT_MASK) | state->csis_fmt->fmt_reg;
  189. s5pcsis_write(state, S5PCSIS_CONFIG, val);
  190. /* Pixel resolution */
  191. val = (mf->width << 16) | mf->height;
  192. s5pcsis_write(state, S5PCSIS_RESOL, val);
  193. }
  194. static void s5pcsis_set_hsync_settle(struct csis_state *state, int settle)
  195. {
  196. u32 val = s5pcsis_read(state, S5PCSIS_DPHYCTRL);
  197. val = (val & ~S5PCSIS_DPHYCTRL_HSS_MASK) | (settle << 27);
  198. s5pcsis_write(state, S5PCSIS_DPHYCTRL, val);
  199. }
  200. static void s5pcsis_set_params(struct csis_state *state)
  201. {
  202. struct s5p_platform_mipi_csis *pdata = state->pdev->dev.platform_data;
  203. u32 val;
  204. val = s5pcsis_read(state, S5PCSIS_CONFIG);
  205. val = (val & ~S5PCSIS_CFG_NR_LANE_MASK) | (pdata->lanes - 1);
  206. s5pcsis_write(state, S5PCSIS_CONFIG, val);
  207. __s5pcsis_set_format(state);
  208. s5pcsis_set_hsync_settle(state, pdata->hs_settle);
  209. val = s5pcsis_read(state, S5PCSIS_CTRL);
  210. if (state->csis_fmt->data_alignment == 32)
  211. val |= S5PCSIS_CTRL_ALIGN_32BIT;
  212. else /* 24-bits */
  213. val &= ~S5PCSIS_CTRL_ALIGN_32BIT;
  214. /* Not using external clock. */
  215. val &= ~S5PCSIS_CTRL_WCLK_EXTCLK;
  216. s5pcsis_write(state, S5PCSIS_CTRL, val);
  217. /* Update the shadow register. */
  218. val = s5pcsis_read(state, S5PCSIS_CTRL);
  219. s5pcsis_write(state, S5PCSIS_CTRL, val | S5PCSIS_CTRL_UPDATE_SHADOW);
  220. }
  221. static void s5pcsis_clk_put(struct csis_state *state)
  222. {
  223. int i;
  224. for (i = 0; i < NUM_CSIS_CLOCKS; i++) {
  225. if (IS_ERR_OR_NULL(state->clock[i]))
  226. continue;
  227. clk_unprepare(state->clock[i]);
  228. clk_put(state->clock[i]);
  229. state->clock[i] = NULL;
  230. }
  231. }
  232. static int s5pcsis_clk_get(struct csis_state *state)
  233. {
  234. struct device *dev = &state->pdev->dev;
  235. int i, ret;
  236. for (i = 0; i < NUM_CSIS_CLOCKS; i++) {
  237. state->clock[i] = clk_get(dev, csi_clock_name[i]);
  238. if (IS_ERR(state->clock[i]))
  239. goto err;
  240. ret = clk_prepare(state->clock[i]);
  241. if (ret < 0) {
  242. clk_put(state->clock[i]);
  243. state->clock[i] = NULL;
  244. goto err;
  245. }
  246. }
  247. return 0;
  248. err:
  249. s5pcsis_clk_put(state);
  250. dev_err(dev, "failed to get clock: %s\n", csi_clock_name[i]);
  251. return -ENXIO;
  252. }
  253. static int s5pcsis_s_power(struct v4l2_subdev *sd, int on)
  254. {
  255. struct csis_state *state = sd_to_csis_state(sd);
  256. struct device *dev = &state->pdev->dev;
  257. if (on)
  258. return pm_runtime_get_sync(dev);
  259. return pm_runtime_put_sync(dev);
  260. }
  261. static void s5pcsis_start_stream(struct csis_state *state)
  262. {
  263. s5pcsis_reset(state);
  264. s5pcsis_set_params(state);
  265. s5pcsis_system_enable(state, true);
  266. s5pcsis_enable_interrupts(state, true);
  267. }
  268. static void s5pcsis_stop_stream(struct csis_state *state)
  269. {
  270. s5pcsis_enable_interrupts(state, false);
  271. s5pcsis_system_enable(state, false);
  272. }
  273. /* v4l2_subdev operations */
  274. static int s5pcsis_s_stream(struct v4l2_subdev *sd, int enable)
  275. {
  276. struct csis_state *state = sd_to_csis_state(sd);
  277. int ret = 0;
  278. v4l2_dbg(1, debug, sd, "%s: %d, state: 0x%x\n",
  279. __func__, enable, state->flags);
  280. if (enable) {
  281. ret = pm_runtime_get_sync(&state->pdev->dev);
  282. if (ret && ret != 1)
  283. return ret;
  284. }
  285. mutex_lock(&state->lock);
  286. if (enable) {
  287. if (state->flags & ST_SUSPENDED) {
  288. ret = -EBUSY;
  289. goto unlock;
  290. }
  291. s5pcsis_start_stream(state);
  292. state->flags |= ST_STREAMING;
  293. } else {
  294. s5pcsis_stop_stream(state);
  295. state->flags &= ~ST_STREAMING;
  296. }
  297. unlock:
  298. mutex_unlock(&state->lock);
  299. if (!enable)
  300. pm_runtime_put(&state->pdev->dev);
  301. return ret == 1 ? 0 : ret;
  302. }
  303. static int s5pcsis_enum_mbus_code(struct v4l2_subdev *sd,
  304. struct v4l2_subdev_fh *fh,
  305. struct v4l2_subdev_mbus_code_enum *code)
  306. {
  307. if (code->index >= ARRAY_SIZE(s5pcsis_formats))
  308. return -EINVAL;
  309. code->code = s5pcsis_formats[code->index].code;
  310. return 0;
  311. }
  312. static struct csis_pix_format const *s5pcsis_try_format(
  313. struct v4l2_mbus_framefmt *mf)
  314. {
  315. struct csis_pix_format const *csis_fmt;
  316. csis_fmt = find_csis_format(mf);
  317. if (csis_fmt == NULL)
  318. csis_fmt = &s5pcsis_formats[0];
  319. mf->code = csis_fmt->code;
  320. v4l_bound_align_image(&mf->width, 1, CSIS_MAX_PIX_WIDTH,
  321. csis_fmt->pix_width_alignment,
  322. &mf->height, 1, CSIS_MAX_PIX_HEIGHT, 1,
  323. 0);
  324. return csis_fmt;
  325. }
  326. static struct v4l2_mbus_framefmt *__s5pcsis_get_format(
  327. struct csis_state *state, struct v4l2_subdev_fh *fh,
  328. u32 pad, enum v4l2_subdev_format_whence which)
  329. {
  330. if (which == V4L2_SUBDEV_FORMAT_TRY)
  331. return fh ? v4l2_subdev_get_try_format(fh, pad) : NULL;
  332. return &state->format;
  333. }
  334. static int s5pcsis_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
  335. struct v4l2_subdev_format *fmt)
  336. {
  337. struct csis_state *state = sd_to_csis_state(sd);
  338. struct csis_pix_format const *csis_fmt;
  339. struct v4l2_mbus_framefmt *mf;
  340. if (fmt->pad != CSIS_PAD_SOURCE && fmt->pad != CSIS_PAD_SINK)
  341. return -EINVAL;
  342. mf = __s5pcsis_get_format(state, fh, fmt->pad, fmt->which);
  343. if (fmt->pad == CSIS_PAD_SOURCE) {
  344. if (mf) {
  345. mutex_lock(&state->lock);
  346. fmt->format = *mf;
  347. mutex_unlock(&state->lock);
  348. }
  349. return 0;
  350. }
  351. csis_fmt = s5pcsis_try_format(&fmt->format);
  352. if (mf) {
  353. mutex_lock(&state->lock);
  354. *mf = fmt->format;
  355. if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE)
  356. state->csis_fmt = csis_fmt;
  357. mutex_unlock(&state->lock);
  358. }
  359. return 0;
  360. }
  361. static int s5pcsis_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
  362. struct v4l2_subdev_format *fmt)
  363. {
  364. struct csis_state *state = sd_to_csis_state(sd);
  365. struct v4l2_mbus_framefmt *mf;
  366. if (fmt->pad != CSIS_PAD_SOURCE && fmt->pad != CSIS_PAD_SINK)
  367. return -EINVAL;
  368. mf = __s5pcsis_get_format(state, fh, fmt->pad, fmt->which);
  369. if (!mf)
  370. return -EINVAL;
  371. mutex_lock(&state->lock);
  372. fmt->format = *mf;
  373. mutex_unlock(&state->lock);
  374. return 0;
  375. }
  376. static int s5pcsis_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
  377. {
  378. struct v4l2_mbus_framefmt *format = v4l2_subdev_get_try_format(fh, 0);
  379. format->colorspace = V4L2_COLORSPACE_JPEG;
  380. format->code = s5pcsis_formats[0].code;
  381. format->width = S5PCSIS_DEF_PIX_WIDTH;
  382. format->height = S5PCSIS_DEF_PIX_HEIGHT;
  383. format->field = V4L2_FIELD_NONE;
  384. return 0;
  385. }
  386. static const struct v4l2_subdev_internal_ops s5pcsis_sd_internal_ops = {
  387. .open = s5pcsis_open,
  388. };
  389. static struct v4l2_subdev_core_ops s5pcsis_core_ops = {
  390. .s_power = s5pcsis_s_power,
  391. };
  392. static struct v4l2_subdev_pad_ops s5pcsis_pad_ops = {
  393. .enum_mbus_code = s5pcsis_enum_mbus_code,
  394. .get_fmt = s5pcsis_get_fmt,
  395. .set_fmt = s5pcsis_set_fmt,
  396. };
  397. static struct v4l2_subdev_video_ops s5pcsis_video_ops = {
  398. .s_stream = s5pcsis_s_stream,
  399. };
  400. static struct v4l2_subdev_ops s5pcsis_subdev_ops = {
  401. .core = &s5pcsis_core_ops,
  402. .pad = &s5pcsis_pad_ops,
  403. .video = &s5pcsis_video_ops,
  404. };
  405. static irqreturn_t s5pcsis_irq_handler(int irq, void *dev_id)
  406. {
  407. struct csis_state *state = dev_id;
  408. u32 val;
  409. /* Just clear the interrupt pending bits. */
  410. val = s5pcsis_read(state, S5PCSIS_INTSRC);
  411. s5pcsis_write(state, S5PCSIS_INTSRC, val);
  412. return IRQ_HANDLED;
  413. }
  414. static int __devinit s5pcsis_probe(struct platform_device *pdev)
  415. {
  416. struct s5p_platform_mipi_csis *pdata;
  417. struct resource *mem_res;
  418. struct csis_state *state;
  419. int ret = -ENOMEM;
  420. int i;
  421. state = devm_kzalloc(&pdev->dev, sizeof(*state), GFP_KERNEL);
  422. if (!state)
  423. return -ENOMEM;
  424. mutex_init(&state->lock);
  425. state->pdev = pdev;
  426. pdata = pdev->dev.platform_data;
  427. if (pdata == NULL || pdata->phy_enable == NULL) {
  428. dev_err(&pdev->dev, "Platform data not fully specified\n");
  429. return -EINVAL;
  430. }
  431. if ((pdev->id == 1 && pdata->lanes > CSIS1_MAX_LANES) ||
  432. pdata->lanes > CSIS0_MAX_LANES) {
  433. dev_err(&pdev->dev, "Unsupported number of data lanes: %d\n",
  434. pdata->lanes);
  435. return -EINVAL;
  436. }
  437. mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  438. state->regs = devm_request_and_ioremap(&pdev->dev, mem_res);
  439. if (state->regs == NULL) {
  440. dev_err(&pdev->dev, "Failed to request and remap io memory\n");
  441. return -ENXIO;
  442. }
  443. state->irq = platform_get_irq(pdev, 0);
  444. if (state->irq < 0) {
  445. dev_err(&pdev->dev, "Failed to get irq\n");
  446. return state->irq;
  447. }
  448. for (i = 0; i < CSIS_NUM_SUPPLIES; i++)
  449. state->supplies[i].supply = csis_supply_name[i];
  450. ret = regulator_bulk_get(&pdev->dev, CSIS_NUM_SUPPLIES,
  451. state->supplies);
  452. if (ret)
  453. return ret;
  454. ret = s5pcsis_clk_get(state);
  455. if (ret)
  456. goto e_clkput;
  457. clk_enable(state->clock[CSIS_CLK_MUX]);
  458. if (pdata->clk_rate)
  459. clk_set_rate(state->clock[CSIS_CLK_MUX], pdata->clk_rate);
  460. else
  461. dev_WARN(&pdev->dev, "No clock frequency specified!\n");
  462. ret = devm_request_irq(&pdev->dev, state->irq, s5pcsis_irq_handler,
  463. 0, dev_name(&pdev->dev), state);
  464. if (ret) {
  465. dev_err(&pdev->dev, "Interrupt request failed\n");
  466. goto e_regput;
  467. }
  468. v4l2_subdev_init(&state->sd, &s5pcsis_subdev_ops);
  469. state->sd.owner = THIS_MODULE;
  470. strlcpy(state->sd.name, dev_name(&pdev->dev), sizeof(state->sd.name));
  471. state->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
  472. state->csis_fmt = &s5pcsis_formats[0];
  473. state->format.code = s5pcsis_formats[0].code;
  474. state->format.width = S5PCSIS_DEF_PIX_WIDTH;
  475. state->format.height = S5PCSIS_DEF_PIX_HEIGHT;
  476. state->pads[CSIS_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
  477. state->pads[CSIS_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
  478. ret = media_entity_init(&state->sd.entity,
  479. CSIS_PADS_NUM, state->pads, 0);
  480. if (ret < 0)
  481. goto e_clkput;
  482. /* This allows to retrieve the platform device id by the host driver */
  483. v4l2_set_subdevdata(&state->sd, pdev);
  484. /* .. and a pointer to the subdev. */
  485. platform_set_drvdata(pdev, &state->sd);
  486. pm_runtime_enable(&pdev->dev);
  487. return 0;
  488. e_regput:
  489. regulator_bulk_free(CSIS_NUM_SUPPLIES, state->supplies);
  490. e_clkput:
  491. clk_disable(state->clock[CSIS_CLK_MUX]);
  492. s5pcsis_clk_put(state);
  493. return ret;
  494. }
  495. static int s5pcsis_pm_suspend(struct device *dev, bool runtime)
  496. {
  497. struct s5p_platform_mipi_csis *pdata = dev->platform_data;
  498. struct platform_device *pdev = to_platform_device(dev);
  499. struct v4l2_subdev *sd = platform_get_drvdata(pdev);
  500. struct csis_state *state = sd_to_csis_state(sd);
  501. int ret = 0;
  502. v4l2_dbg(1, debug, sd, "%s: flags: 0x%x\n",
  503. __func__, state->flags);
  504. mutex_lock(&state->lock);
  505. if (state->flags & ST_POWERED) {
  506. s5pcsis_stop_stream(state);
  507. ret = pdata->phy_enable(state->pdev, false);
  508. if (ret)
  509. goto unlock;
  510. ret = regulator_bulk_disable(CSIS_NUM_SUPPLIES,
  511. state->supplies);
  512. if (ret)
  513. goto unlock;
  514. clk_disable(state->clock[CSIS_CLK_GATE]);
  515. state->flags &= ~ST_POWERED;
  516. if (!runtime)
  517. state->flags |= ST_SUSPENDED;
  518. }
  519. unlock:
  520. mutex_unlock(&state->lock);
  521. return ret ? -EAGAIN : 0;
  522. }
  523. static int s5pcsis_pm_resume(struct device *dev, bool runtime)
  524. {
  525. struct s5p_platform_mipi_csis *pdata = dev->platform_data;
  526. struct platform_device *pdev = to_platform_device(dev);
  527. struct v4l2_subdev *sd = platform_get_drvdata(pdev);
  528. struct csis_state *state = sd_to_csis_state(sd);
  529. int ret = 0;
  530. v4l2_dbg(1, debug, sd, "%s: flags: 0x%x\n",
  531. __func__, state->flags);
  532. mutex_lock(&state->lock);
  533. if (!runtime && !(state->flags & ST_SUSPENDED))
  534. goto unlock;
  535. if (!(state->flags & ST_POWERED)) {
  536. ret = regulator_bulk_enable(CSIS_NUM_SUPPLIES,
  537. state->supplies);
  538. if (ret)
  539. goto unlock;
  540. ret = pdata->phy_enable(state->pdev, true);
  541. if (!ret) {
  542. state->flags |= ST_POWERED;
  543. } else {
  544. regulator_bulk_disable(CSIS_NUM_SUPPLIES,
  545. state->supplies);
  546. goto unlock;
  547. }
  548. clk_enable(state->clock[CSIS_CLK_GATE]);
  549. }
  550. if (state->flags & ST_STREAMING)
  551. s5pcsis_start_stream(state);
  552. state->flags &= ~ST_SUSPENDED;
  553. unlock:
  554. mutex_unlock(&state->lock);
  555. return ret ? -EAGAIN : 0;
  556. }
  557. #ifdef CONFIG_PM_SLEEP
  558. static int s5pcsis_suspend(struct device *dev)
  559. {
  560. return s5pcsis_pm_suspend(dev, false);
  561. }
  562. static int s5pcsis_resume(struct device *dev)
  563. {
  564. return s5pcsis_pm_resume(dev, false);
  565. }
  566. #endif
  567. #ifdef CONFIG_PM_RUNTIME
  568. static int s5pcsis_runtime_suspend(struct device *dev)
  569. {
  570. return s5pcsis_pm_suspend(dev, true);
  571. }
  572. static int s5pcsis_runtime_resume(struct device *dev)
  573. {
  574. return s5pcsis_pm_resume(dev, true);
  575. }
  576. #endif
  577. static int __devexit s5pcsis_remove(struct platform_device *pdev)
  578. {
  579. struct v4l2_subdev *sd = platform_get_drvdata(pdev);
  580. struct csis_state *state = sd_to_csis_state(sd);
  581. pm_runtime_disable(&pdev->dev);
  582. s5pcsis_pm_suspend(&pdev->dev, false);
  583. clk_disable(state->clock[CSIS_CLK_MUX]);
  584. pm_runtime_set_suspended(&pdev->dev);
  585. s5pcsis_clk_put(state);
  586. regulator_bulk_free(CSIS_NUM_SUPPLIES, state->supplies);
  587. media_entity_cleanup(&state->sd.entity);
  588. return 0;
  589. }
  590. static const struct dev_pm_ops s5pcsis_pm_ops = {
  591. SET_RUNTIME_PM_OPS(s5pcsis_runtime_suspend, s5pcsis_runtime_resume,
  592. NULL)
  593. SET_SYSTEM_SLEEP_PM_OPS(s5pcsis_suspend, s5pcsis_resume)
  594. };
  595. static struct platform_driver s5pcsis_driver = {
  596. .probe = s5pcsis_probe,
  597. .remove = __devexit_p(s5pcsis_remove),
  598. .driver = {
  599. .name = CSIS_DRIVER_NAME,
  600. .owner = THIS_MODULE,
  601. .pm = &s5pcsis_pm_ops,
  602. },
  603. };
  604. module_platform_driver(s5pcsis_driver);
  605. MODULE_AUTHOR("Sylwester Nawrocki <s.nawrocki@samsung.com>");
  606. MODULE_DESCRIPTION("Samsung S5P/EXYNOS SoC MIPI-CSI2 receiver driver");
  607. MODULE_LICENSE("GPL");