• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/of.h>
23 #include <linux/platform_data/mipi-csis.h>
24 #include <linux/platform_device.h>
25 #include <linux/pm_runtime.h>
26 #include <linux/regulator/consumer.h>
27 #include <linux/slab.h>
28 #include <linux/spinlock.h>
29 #include <linux/videodev2.h>
30 #include <media/s5p_fimc.h>
31 #include <media/v4l2-of.h>
32 #include <media/v4l2-subdev.h>
33 
34 #include "mipi-csis.h"
35 
36 static int debug;
37 module_param(debug, int, 0644);
38 MODULE_PARM_DESC(debug, "Debug level (0-2)");
39 
40 /* Register map definition */
41 
42 /* CSIS global control */
43 #define S5PCSIS_CTRL			0x00
44 #define S5PCSIS_CTRL_DPDN_DEFAULT	(0 << 31)
45 #define S5PCSIS_CTRL_DPDN_SWAP		(1 << 31)
46 #define S5PCSIS_CTRL_ALIGN_32BIT	(1 << 20)
47 #define S5PCSIS_CTRL_UPDATE_SHADOW	(1 << 16)
48 #define S5PCSIS_CTRL_WCLK_EXTCLK	(1 << 8)
49 #define S5PCSIS_CTRL_RESET		(1 << 4)
50 #define S5PCSIS_CTRL_ENABLE		(1 << 0)
51 
52 /* D-PHY control */
53 #define S5PCSIS_DPHYCTRL		0x04
54 #define S5PCSIS_DPHYCTRL_HSS_MASK	(0x1f << 27)
55 #define S5PCSIS_DPHYCTRL_ENABLE		(0x1f << 0)
56 
57 #define S5PCSIS_CONFIG			0x08
58 #define S5PCSIS_CFG_FMT_YCBCR422_8BIT	(0x1e << 2)
59 #define S5PCSIS_CFG_FMT_RAW8		(0x2a << 2)
60 #define S5PCSIS_CFG_FMT_RAW10		(0x2b << 2)
61 #define S5PCSIS_CFG_FMT_RAW12		(0x2c << 2)
62 /* User defined formats, x = 1...4 */
63 #define S5PCSIS_CFG_FMT_USER(x)		((0x30 + x - 1) << 2)
64 #define S5PCSIS_CFG_FMT_MASK		(0x3f << 2)
65 #define S5PCSIS_CFG_NR_LANE_MASK	3
66 
67 /* Interrupt mask */
68 #define S5PCSIS_INTMSK			0x10
69 #define S5PCSIS_INTMSK_EN_ALL		0xf000103f
70 #define S5PCSIS_INTMSK_EVEN_BEFORE	(1 << 31)
71 #define S5PCSIS_INTMSK_EVEN_AFTER	(1 << 30)
72 #define S5PCSIS_INTMSK_ODD_BEFORE	(1 << 29)
73 #define S5PCSIS_INTMSK_ODD_AFTER	(1 << 28)
74 #define S5PCSIS_INTMSK_ERR_SOT_HS	(1 << 12)
75 #define S5PCSIS_INTMSK_ERR_LOST_FS	(1 << 5)
76 #define S5PCSIS_INTMSK_ERR_LOST_FE	(1 << 4)
77 #define S5PCSIS_INTMSK_ERR_OVER		(1 << 3)
78 #define S5PCSIS_INTMSK_ERR_ECC		(1 << 2)
79 #define S5PCSIS_INTMSK_ERR_CRC		(1 << 1)
80 #define S5PCSIS_INTMSK_ERR_UNKNOWN	(1 << 0)
81 
82 /* Interrupt source */
83 #define S5PCSIS_INTSRC			0x14
84 #define S5PCSIS_INTSRC_EVEN_BEFORE	(1 << 31)
85 #define S5PCSIS_INTSRC_EVEN_AFTER	(1 << 30)
86 #define S5PCSIS_INTSRC_EVEN		(0x3 << 30)
87 #define S5PCSIS_INTSRC_ODD_BEFORE	(1 << 29)
88 #define S5PCSIS_INTSRC_ODD_AFTER	(1 << 28)
89 #define S5PCSIS_INTSRC_ODD		(0x3 << 28)
90 #define S5PCSIS_INTSRC_NON_IMAGE_DATA	(0xff << 28)
91 #define S5PCSIS_INTSRC_ERR_SOT_HS	(0xf << 12)
92 #define S5PCSIS_INTSRC_ERR_LOST_FS	(1 << 5)
93 #define S5PCSIS_INTSRC_ERR_LOST_FE	(1 << 4)
94 #define S5PCSIS_INTSRC_ERR_OVER		(1 << 3)
95 #define S5PCSIS_INTSRC_ERR_ECC		(1 << 2)
96 #define S5PCSIS_INTSRC_ERR_CRC		(1 << 1)
97 #define S5PCSIS_INTSRC_ERR_UNKNOWN	(1 << 0)
98 #define S5PCSIS_INTSRC_ERRORS		0xf03f
99 
100 /* Pixel resolution */
101 #define S5PCSIS_RESOL			0x2c
102 #define CSIS_MAX_PIX_WIDTH		0xffff
103 #define CSIS_MAX_PIX_HEIGHT		0xffff
104 
105 /* Non-image packet data buffers */
106 #define S5PCSIS_PKTDATA_ODD		0x2000
107 #define S5PCSIS_PKTDATA_EVEN		0x3000
108 #define S5PCSIS_PKTDATA_SIZE		SZ_4K
109 
110 enum {
111 	CSIS_CLK_MUX,
112 	CSIS_CLK_GATE,
113 };
114 
115 static char *csi_clock_name[] = {
116 	[CSIS_CLK_MUX]  = "sclk_csis",
117 	[CSIS_CLK_GATE] = "csis",
118 };
119 #define NUM_CSIS_CLOCKS	ARRAY_SIZE(csi_clock_name)
120 #define DEFAULT_SCLK_CSIS_FREQ	166000000UL
121 
122 static const char * const csis_supply_name[] = {
123 	"vddcore",  /* CSIS Core (1.0V, 1.1V or 1.2V) suppply */
124 	"vddio",    /* CSIS I/O and PLL (1.8V) supply */
125 };
126 #define CSIS_NUM_SUPPLIES ARRAY_SIZE(csis_supply_name)
127 
128 enum {
129 	ST_POWERED	= 1,
130 	ST_STREAMING	= 2,
131 	ST_SUSPENDED	= 4,
132 };
133 
134 struct s5pcsis_event {
135 	u32 mask;
136 	const char * const name;
137 	unsigned int counter;
138 };
139 
140 static const struct s5pcsis_event s5pcsis_events[] = {
141 	/* Errors */
142 	{ S5PCSIS_INTSRC_ERR_SOT_HS,	"SOT Error" },
143 	{ S5PCSIS_INTSRC_ERR_LOST_FS,	"Lost Frame Start Error" },
144 	{ S5PCSIS_INTSRC_ERR_LOST_FE,	"Lost Frame End Error" },
145 	{ S5PCSIS_INTSRC_ERR_OVER,	"FIFO Overflow Error" },
146 	{ S5PCSIS_INTSRC_ERR_ECC,	"ECC Error" },
147 	{ S5PCSIS_INTSRC_ERR_CRC,	"CRC Error" },
148 	{ S5PCSIS_INTSRC_ERR_UNKNOWN,	"Unknown Error" },
149 	/* Non-image data receive events */
150 	{ S5PCSIS_INTSRC_EVEN_BEFORE,	"Non-image data before even frame" },
151 	{ S5PCSIS_INTSRC_EVEN_AFTER,	"Non-image data after even frame" },
152 	{ S5PCSIS_INTSRC_ODD_BEFORE,	"Non-image data before odd frame" },
153 	{ S5PCSIS_INTSRC_ODD_AFTER,	"Non-image data after odd frame" },
154 };
155 #define S5PCSIS_NUM_EVENTS ARRAY_SIZE(s5pcsis_events)
156 
157 struct csis_pktbuf {
158 	u32 *data;
159 	unsigned int len;
160 };
161 
162 /**
163  * struct csis_state - the driver's internal state data structure
164  * @lock: mutex serializing the subdev and power management operations,
165  *        protecting @format and @flags members
166  * @pads: CSIS pads array
167  * @sd: v4l2_subdev associated with CSIS device instance
168  * @index: the hardware instance index
169  * @pdev: CSIS platform device
170  * @regs: mmaped I/O registers memory
171  * @supplies: CSIS regulator supplies
172  * @clock: CSIS clocks
173  * @irq: requested s5p-mipi-csis irq number
174  * @flags: the state variable for power and streaming control
175  * @clock_frequency: device bus clock frequency
176  * @hs_settle: HS-RX settle time
177  * @num_lanes: number of MIPI-CSI data lanes used
178  * @max_num_lanes: maximum number of MIPI-CSI data lanes supported
179  * @wclk_ext: CSI wrapper clock: 0 - bus clock, 1 - external SCLK_CAM
180  * @csis_fmt: current CSIS pixel format
181  * @format: common media bus format for the source and sink pad
182  * @slock: spinlock protecting structure members below
183  * @pkt_buf: the frame embedded (non-image) data buffer
184  * @events: MIPI-CSIS event (error) counters
185  */
186 struct csis_state {
187 	struct mutex lock;
188 	struct media_pad pads[CSIS_PADS_NUM];
189 	struct v4l2_subdev sd;
190 	u8 index;
191 	struct platform_device *pdev;
192 	void __iomem *regs;
193 	struct regulator_bulk_data supplies[CSIS_NUM_SUPPLIES];
194 	struct clk *clock[NUM_CSIS_CLOCKS];
195 	int irq;
196 	u32 flags;
197 
198 	u32 clk_frequency;
199 	u32 hs_settle;
200 	u32 num_lanes;
201 	u32 max_num_lanes;
202 	u8 wclk_ext;
203 
204 	const struct csis_pix_format *csis_fmt;
205 	struct v4l2_mbus_framefmt format;
206 
207 	spinlock_t slock;
208 	struct csis_pktbuf pkt_buf;
209 	struct s5pcsis_event events[S5PCSIS_NUM_EVENTS];
210 };
211 
212 /**
213  * struct csis_pix_format - CSIS pixel format description
214  * @pix_width_alignment: horizontal pixel alignment, width will be
215  *                       multiple of 2^pix_width_alignment
216  * @code: corresponding media bus code
217  * @fmt_reg: S5PCSIS_CONFIG register value
218  * @data_alignment: MIPI-CSI data alignment in bits
219  */
220 struct csis_pix_format {
221 	unsigned int pix_width_alignment;
222 	enum v4l2_mbus_pixelcode code;
223 	u32 fmt_reg;
224 	u8 data_alignment;
225 };
226 
227 static const struct csis_pix_format s5pcsis_formats[] = {
228 	{
229 		.code = V4L2_MBUS_FMT_VYUY8_2X8,
230 		.fmt_reg = S5PCSIS_CFG_FMT_YCBCR422_8BIT,
231 		.data_alignment = 32,
232 	}, {
233 		.code = V4L2_MBUS_FMT_JPEG_1X8,
234 		.fmt_reg = S5PCSIS_CFG_FMT_USER(1),
235 		.data_alignment = 32,
236 	}, {
237 		.code = V4L2_MBUS_FMT_S5C_UYVY_JPEG_1X8,
238 		.fmt_reg = S5PCSIS_CFG_FMT_USER(1),
239 		.data_alignment = 32,
240 	}, {
241 		.code = V4L2_MBUS_FMT_SGRBG8_1X8,
242 		.fmt_reg = S5PCSIS_CFG_FMT_RAW8,
243 		.data_alignment = 24,
244 	}, {
245 		.code = V4L2_MBUS_FMT_SGRBG10_1X10,
246 		.fmt_reg = S5PCSIS_CFG_FMT_RAW10,
247 		.data_alignment = 24,
248 	}, {
249 		.code = V4L2_MBUS_FMT_SGRBG12_1X12,
250 		.fmt_reg = S5PCSIS_CFG_FMT_RAW12,
251 		.data_alignment = 24,
252 	}
253 };
254 
255 #define s5pcsis_write(__csis, __r, __v) writel(__v, __csis->regs + __r)
256 #define s5pcsis_read(__csis, __r) readl(__csis->regs + __r)
257 
sd_to_csis_state(struct v4l2_subdev * sdev)258 static struct csis_state *sd_to_csis_state(struct v4l2_subdev *sdev)
259 {
260 	return container_of(sdev, struct csis_state, sd);
261 }
262 
find_csis_format(struct v4l2_mbus_framefmt * mf)263 static const struct csis_pix_format *find_csis_format(
264 	struct v4l2_mbus_framefmt *mf)
265 {
266 	int i;
267 
268 	for (i = 0; i < ARRAY_SIZE(s5pcsis_formats); i++)
269 		if (mf->code == s5pcsis_formats[i].code)
270 			return &s5pcsis_formats[i];
271 	return NULL;
272 }
273 
s5pcsis_enable_interrupts(struct csis_state * state,bool on)274 static void s5pcsis_enable_interrupts(struct csis_state *state, bool on)
275 {
276 	u32 val = s5pcsis_read(state, S5PCSIS_INTMSK);
277 
278 	val = on ? val | S5PCSIS_INTMSK_EN_ALL :
279 		   val & ~S5PCSIS_INTMSK_EN_ALL;
280 	s5pcsis_write(state, S5PCSIS_INTMSK, val);
281 }
282 
s5pcsis_reset(struct csis_state * state)283 static void s5pcsis_reset(struct csis_state *state)
284 {
285 	u32 val = s5pcsis_read(state, S5PCSIS_CTRL);
286 
287 	s5pcsis_write(state, S5PCSIS_CTRL, val | S5PCSIS_CTRL_RESET);
288 	udelay(10);
289 }
290 
s5pcsis_system_enable(struct csis_state * state,int on)291 static void s5pcsis_system_enable(struct csis_state *state, int on)
292 {
293 	u32 val, mask;
294 
295 	val = s5pcsis_read(state, S5PCSIS_CTRL);
296 	if (on)
297 		val |= S5PCSIS_CTRL_ENABLE;
298 	else
299 		val &= ~S5PCSIS_CTRL_ENABLE;
300 	s5pcsis_write(state, S5PCSIS_CTRL, val);
301 
302 	val = s5pcsis_read(state, S5PCSIS_DPHYCTRL);
303 	val &= ~S5PCSIS_DPHYCTRL_ENABLE;
304 	if (on) {
305 		mask = (1 << (state->num_lanes + 1)) - 1;
306 		val |= (mask & S5PCSIS_DPHYCTRL_ENABLE);
307 	}
308 	s5pcsis_write(state, S5PCSIS_DPHYCTRL, val);
309 }
310 
311 /* Called with the state.lock mutex held */
__s5pcsis_set_format(struct csis_state * state)312 static void __s5pcsis_set_format(struct csis_state *state)
313 {
314 	struct v4l2_mbus_framefmt *mf = &state->format;
315 	u32 val;
316 
317 	v4l2_dbg(1, debug, &state->sd, "fmt: %#x, %d x %d\n",
318 		 mf->code, mf->width, mf->height);
319 
320 	/* Color format */
321 	val = s5pcsis_read(state, S5PCSIS_CONFIG);
322 	val = (val & ~S5PCSIS_CFG_FMT_MASK) | state->csis_fmt->fmt_reg;
323 	s5pcsis_write(state, S5PCSIS_CONFIG, val);
324 
325 	/* Pixel resolution */
326 	val = (mf->width << 16) | mf->height;
327 	s5pcsis_write(state, S5PCSIS_RESOL, val);
328 }
329 
s5pcsis_set_hsync_settle(struct csis_state * state,int settle)330 static void s5pcsis_set_hsync_settle(struct csis_state *state, int settle)
331 {
332 	u32 val = s5pcsis_read(state, S5PCSIS_DPHYCTRL);
333 
334 	val = (val & ~S5PCSIS_DPHYCTRL_HSS_MASK) | (settle << 27);
335 	s5pcsis_write(state, S5PCSIS_DPHYCTRL, val);
336 }
337 
s5pcsis_set_params(struct csis_state * state)338 static void s5pcsis_set_params(struct csis_state *state)
339 {
340 	u32 val;
341 
342 	val = s5pcsis_read(state, S5PCSIS_CONFIG);
343 	val = (val & ~S5PCSIS_CFG_NR_LANE_MASK) | (state->num_lanes - 1);
344 	s5pcsis_write(state, S5PCSIS_CONFIG, val);
345 
346 	__s5pcsis_set_format(state);
347 	s5pcsis_set_hsync_settle(state, state->hs_settle);
348 
349 	val = s5pcsis_read(state, S5PCSIS_CTRL);
350 	if (state->csis_fmt->data_alignment == 32)
351 		val |= S5PCSIS_CTRL_ALIGN_32BIT;
352 	else /* 24-bits */
353 		val &= ~S5PCSIS_CTRL_ALIGN_32BIT;
354 
355 	val &= ~S5PCSIS_CTRL_WCLK_EXTCLK;
356 	if (state->wclk_ext)
357 		val |= S5PCSIS_CTRL_WCLK_EXTCLK;
358 	s5pcsis_write(state, S5PCSIS_CTRL, val);
359 
360 	/* Update the shadow register. */
361 	val = s5pcsis_read(state, S5PCSIS_CTRL);
362 	s5pcsis_write(state, S5PCSIS_CTRL, val | S5PCSIS_CTRL_UPDATE_SHADOW);
363 }
364 
s5pcsis_clk_put(struct csis_state * state)365 static void s5pcsis_clk_put(struct csis_state *state)
366 {
367 	int i;
368 
369 	for (i = 0; i < NUM_CSIS_CLOCKS; i++) {
370 		if (IS_ERR(state->clock[i]))
371 			continue;
372 		clk_unprepare(state->clock[i]);
373 		clk_put(state->clock[i]);
374 		state->clock[i] = ERR_PTR(-EINVAL);
375 	}
376 }
377 
s5pcsis_clk_get(struct csis_state * state)378 static int s5pcsis_clk_get(struct csis_state *state)
379 {
380 	struct device *dev = &state->pdev->dev;
381 	int i, ret;
382 
383 	for (i = 0; i < NUM_CSIS_CLOCKS; i++)
384 		state->clock[i] = ERR_PTR(-EINVAL);
385 
386 	for (i = 0; i < NUM_CSIS_CLOCKS; i++) {
387 		state->clock[i] = clk_get(dev, csi_clock_name[i]);
388 		if (IS_ERR(state->clock[i])) {
389 			ret = PTR_ERR(state->clock[i]);
390 			goto err;
391 		}
392 		ret = clk_prepare(state->clock[i]);
393 		if (ret < 0) {
394 			clk_put(state->clock[i]);
395 			state->clock[i] = ERR_PTR(-EINVAL);
396 			goto err;
397 		}
398 	}
399 	return 0;
400 err:
401 	s5pcsis_clk_put(state);
402 	dev_err(dev, "failed to get clock: %s\n", csi_clock_name[i]);
403 	return ret;
404 }
405 
dump_regs(struct csis_state * state,const char * label)406 static void dump_regs(struct csis_state *state, const char *label)
407 {
408 	struct {
409 		u32 offset;
410 		const char * const name;
411 	} registers[] = {
412 		{ 0x00, "CTRL" },
413 		{ 0x04, "DPHYCTRL" },
414 		{ 0x08, "CONFIG" },
415 		{ 0x0c, "DPHYSTS" },
416 		{ 0x10, "INTMSK" },
417 		{ 0x2c, "RESOL" },
418 		{ 0x38, "SDW_CONFIG" },
419 	};
420 	u32 i;
421 
422 	v4l2_info(&state->sd, "--- %s ---\n", label);
423 
424 	for (i = 0; i < ARRAY_SIZE(registers); i++) {
425 		u32 cfg = s5pcsis_read(state, registers[i].offset);
426 		v4l2_info(&state->sd, "%10s: 0x%08x\n", registers[i].name, cfg);
427 	}
428 }
429 
s5pcsis_start_stream(struct csis_state * state)430 static void s5pcsis_start_stream(struct csis_state *state)
431 {
432 	s5pcsis_reset(state);
433 	s5pcsis_set_params(state);
434 	s5pcsis_system_enable(state, true);
435 	s5pcsis_enable_interrupts(state, true);
436 }
437 
s5pcsis_stop_stream(struct csis_state * state)438 static void s5pcsis_stop_stream(struct csis_state *state)
439 {
440 	s5pcsis_enable_interrupts(state, false);
441 	s5pcsis_system_enable(state, false);
442 }
443 
s5pcsis_clear_counters(struct csis_state * state)444 static void s5pcsis_clear_counters(struct csis_state *state)
445 {
446 	unsigned long flags;
447 	int i;
448 
449 	spin_lock_irqsave(&state->slock, flags);
450 	for (i = 0; i < S5PCSIS_NUM_EVENTS; i++)
451 		state->events[i].counter = 0;
452 	spin_unlock_irqrestore(&state->slock, flags);
453 }
454 
s5pcsis_log_counters(struct csis_state * state,bool non_errors)455 static void s5pcsis_log_counters(struct csis_state *state, bool non_errors)
456 {
457 	int i = non_errors ? S5PCSIS_NUM_EVENTS : S5PCSIS_NUM_EVENTS - 4;
458 	unsigned long flags;
459 
460 	spin_lock_irqsave(&state->slock, flags);
461 
462 	for (i--; i >= 0; i--) {
463 		if (state->events[i].counter > 0 || debug)
464 			v4l2_info(&state->sd, "%s events: %d\n",
465 				  state->events[i].name,
466 				  state->events[i].counter);
467 	}
468 	spin_unlock_irqrestore(&state->slock, flags);
469 }
470 
471 /*
472  * V4L2 subdev operations
473  */
s5pcsis_s_power(struct v4l2_subdev * sd,int on)474 static int s5pcsis_s_power(struct v4l2_subdev *sd, int on)
475 {
476 	struct csis_state *state = sd_to_csis_state(sd);
477 	struct device *dev = &state->pdev->dev;
478 
479 	if (on)
480 		return pm_runtime_get_sync(dev);
481 
482 	return pm_runtime_put_sync(dev);
483 }
484 
s5pcsis_s_stream(struct v4l2_subdev * sd,int enable)485 static int s5pcsis_s_stream(struct v4l2_subdev *sd, int enable)
486 {
487 	struct csis_state *state = sd_to_csis_state(sd);
488 	int ret = 0;
489 
490 	v4l2_dbg(1, debug, sd, "%s: %d, state: 0x%x\n",
491 		 __func__, enable, state->flags);
492 
493 	if (enable) {
494 		s5pcsis_clear_counters(state);
495 		ret = pm_runtime_get_sync(&state->pdev->dev);
496 		if (ret && ret != 1)
497 			return ret;
498 	}
499 
500 	mutex_lock(&state->lock);
501 	if (enable) {
502 		if (state->flags & ST_SUSPENDED) {
503 			ret = -EBUSY;
504 			goto unlock;
505 		}
506 		s5pcsis_start_stream(state);
507 		state->flags |= ST_STREAMING;
508 	} else {
509 		s5pcsis_stop_stream(state);
510 		state->flags &= ~ST_STREAMING;
511 		if (debug > 0)
512 			s5pcsis_log_counters(state, true);
513 	}
514 unlock:
515 	mutex_unlock(&state->lock);
516 	if (!enable)
517 		pm_runtime_put(&state->pdev->dev);
518 
519 	return ret == 1 ? 0 : ret;
520 }
521 
s5pcsis_enum_mbus_code(struct v4l2_subdev * sd,struct v4l2_subdev_fh * fh,struct v4l2_subdev_mbus_code_enum * code)522 static int s5pcsis_enum_mbus_code(struct v4l2_subdev *sd,
523 				  struct v4l2_subdev_fh *fh,
524 				  struct v4l2_subdev_mbus_code_enum *code)
525 {
526 	if (code->index >= ARRAY_SIZE(s5pcsis_formats))
527 		return -EINVAL;
528 
529 	code->code = s5pcsis_formats[code->index].code;
530 	return 0;
531 }
532 
s5pcsis_try_format(struct v4l2_mbus_framefmt * mf)533 static struct csis_pix_format const *s5pcsis_try_format(
534 	struct v4l2_mbus_framefmt *mf)
535 {
536 	struct csis_pix_format const *csis_fmt;
537 
538 	csis_fmt = find_csis_format(mf);
539 	if (csis_fmt == NULL)
540 		csis_fmt = &s5pcsis_formats[0];
541 
542 	mf->code = csis_fmt->code;
543 	v4l_bound_align_image(&mf->width, 1, CSIS_MAX_PIX_WIDTH,
544 			      csis_fmt->pix_width_alignment,
545 			      &mf->height, 1, CSIS_MAX_PIX_HEIGHT, 1,
546 			      0);
547 	return csis_fmt;
548 }
549 
__s5pcsis_get_format(struct csis_state * state,struct v4l2_subdev_fh * fh,enum v4l2_subdev_format_whence which)550 static struct v4l2_mbus_framefmt *__s5pcsis_get_format(
551 		struct csis_state *state, struct v4l2_subdev_fh *fh,
552 		enum v4l2_subdev_format_whence which)
553 {
554 	if (which == V4L2_SUBDEV_FORMAT_TRY)
555 		return fh ? v4l2_subdev_get_try_format(fh, 0) : NULL;
556 
557 	return &state->format;
558 }
559 
s5pcsis_set_fmt(struct v4l2_subdev * sd,struct v4l2_subdev_fh * fh,struct v4l2_subdev_format * fmt)560 static int s5pcsis_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
561 			   struct v4l2_subdev_format *fmt)
562 {
563 	struct csis_state *state = sd_to_csis_state(sd);
564 	struct csis_pix_format const *csis_fmt;
565 	struct v4l2_mbus_framefmt *mf;
566 
567 	mf = __s5pcsis_get_format(state, fh, fmt->which);
568 
569 	if (fmt->pad == CSIS_PAD_SOURCE) {
570 		if (mf) {
571 			mutex_lock(&state->lock);
572 			fmt->format = *mf;
573 			mutex_unlock(&state->lock);
574 		}
575 		return 0;
576 	}
577 	csis_fmt = s5pcsis_try_format(&fmt->format);
578 	if (mf) {
579 		mutex_lock(&state->lock);
580 		*mf = fmt->format;
581 		if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE)
582 			state->csis_fmt = csis_fmt;
583 		mutex_unlock(&state->lock);
584 	}
585 	return 0;
586 }
587 
s5pcsis_get_fmt(struct v4l2_subdev * sd,struct v4l2_subdev_fh * fh,struct v4l2_subdev_format * fmt)588 static int s5pcsis_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
589 			   struct v4l2_subdev_format *fmt)
590 {
591 	struct csis_state *state = sd_to_csis_state(sd);
592 	struct v4l2_mbus_framefmt *mf;
593 
594 	mf = __s5pcsis_get_format(state, fh, fmt->which);
595 	if (!mf)
596 		return -EINVAL;
597 
598 	mutex_lock(&state->lock);
599 	fmt->format = *mf;
600 	mutex_unlock(&state->lock);
601 	return 0;
602 }
603 
s5pcsis_s_rx_buffer(struct v4l2_subdev * sd,void * buf,unsigned int * size)604 static int s5pcsis_s_rx_buffer(struct v4l2_subdev *sd, void *buf,
605 			       unsigned int *size)
606 {
607 	struct csis_state *state = sd_to_csis_state(sd);
608 	unsigned long flags;
609 
610 	*size = min_t(unsigned int, *size, S5PCSIS_PKTDATA_SIZE);
611 
612 	spin_lock_irqsave(&state->slock, flags);
613 	state->pkt_buf.data = buf;
614 	state->pkt_buf.len = *size;
615 	spin_unlock_irqrestore(&state->slock, flags);
616 
617 	return 0;
618 }
619 
s5pcsis_log_status(struct v4l2_subdev * sd)620 static int s5pcsis_log_status(struct v4l2_subdev *sd)
621 {
622 	struct csis_state *state = sd_to_csis_state(sd);
623 
624 	mutex_lock(&state->lock);
625 	s5pcsis_log_counters(state, true);
626 	if (debug && (state->flags & ST_POWERED))
627 		dump_regs(state, __func__);
628 	mutex_unlock(&state->lock);
629 	return 0;
630 }
631 
s5pcsis_open(struct v4l2_subdev * sd,struct v4l2_subdev_fh * fh)632 static int s5pcsis_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
633 {
634 	struct v4l2_mbus_framefmt *format = v4l2_subdev_get_try_format(fh, 0);
635 
636 	format->colorspace = V4L2_COLORSPACE_JPEG;
637 	format->code = s5pcsis_formats[0].code;
638 	format->width = S5PCSIS_DEF_PIX_WIDTH;
639 	format->height = S5PCSIS_DEF_PIX_HEIGHT;
640 	format->field = V4L2_FIELD_NONE;
641 
642 	return 0;
643 }
644 
645 static const struct v4l2_subdev_internal_ops s5pcsis_sd_internal_ops = {
646 	.open = s5pcsis_open,
647 };
648 
649 static struct v4l2_subdev_core_ops s5pcsis_core_ops = {
650 	.s_power = s5pcsis_s_power,
651 	.log_status = s5pcsis_log_status,
652 };
653 
654 static struct v4l2_subdev_pad_ops s5pcsis_pad_ops = {
655 	.enum_mbus_code = s5pcsis_enum_mbus_code,
656 	.get_fmt = s5pcsis_get_fmt,
657 	.set_fmt = s5pcsis_set_fmt,
658 };
659 
660 static struct v4l2_subdev_video_ops s5pcsis_video_ops = {
661 	.s_rx_buffer = s5pcsis_s_rx_buffer,
662 	.s_stream = s5pcsis_s_stream,
663 };
664 
665 static struct v4l2_subdev_ops s5pcsis_subdev_ops = {
666 	.core = &s5pcsis_core_ops,
667 	.pad = &s5pcsis_pad_ops,
668 	.video = &s5pcsis_video_ops,
669 };
670 
s5pcsis_irq_handler(int irq,void * dev_id)671 static irqreturn_t s5pcsis_irq_handler(int irq, void *dev_id)
672 {
673 	struct csis_state *state = dev_id;
674 	struct csis_pktbuf *pktbuf = &state->pkt_buf;
675 	unsigned long flags;
676 	u32 status;
677 
678 	status = s5pcsis_read(state, S5PCSIS_INTSRC);
679 	spin_lock_irqsave(&state->slock, flags);
680 
681 	if ((status & S5PCSIS_INTSRC_NON_IMAGE_DATA) && pktbuf->data) {
682 		u32 offset;
683 
684 		if (status & S5PCSIS_INTSRC_EVEN)
685 			offset = S5PCSIS_PKTDATA_EVEN;
686 		else
687 			offset = S5PCSIS_PKTDATA_ODD;
688 
689 		memcpy(pktbuf->data, state->regs + offset, pktbuf->len);
690 		pktbuf->data = NULL;
691 		rmb();
692 	}
693 
694 	/* Update the event/error counters */
695 	if ((status & S5PCSIS_INTSRC_ERRORS) || debug) {
696 		int i;
697 		for (i = 0; i < S5PCSIS_NUM_EVENTS; i++) {
698 			if (!(status & state->events[i].mask))
699 				continue;
700 			state->events[i].counter++;
701 			v4l2_dbg(2, debug, &state->sd, "%s: %d\n",
702 				 state->events[i].name,
703 				 state->events[i].counter);
704 		}
705 		v4l2_dbg(2, debug, &state->sd, "status: %08x\n", status);
706 	}
707 	spin_unlock_irqrestore(&state->slock, flags);
708 
709 	s5pcsis_write(state, S5PCSIS_INTSRC, status);
710 	return IRQ_HANDLED;
711 }
712 
s5pcsis_get_platform_data(struct platform_device * pdev,struct csis_state * state)713 static int s5pcsis_get_platform_data(struct platform_device *pdev,
714 				     struct csis_state *state)
715 {
716 	struct s5p_platform_mipi_csis *pdata = pdev->dev.platform_data;
717 
718 	if (pdata == NULL) {
719 		dev_err(&pdev->dev, "Platform data not specified\n");
720 		return -EINVAL;
721 	}
722 
723 	state->clk_frequency = pdata->clk_rate;
724 	state->num_lanes = pdata->lanes;
725 	state->hs_settle = pdata->hs_settle;
726 	state->index = max(0, pdev->id);
727 	state->max_num_lanes = state->index ? CSIS1_MAX_LANES :
728 					      CSIS0_MAX_LANES;
729 	return 0;
730 }
731 
732 #ifdef CONFIG_OF
s5pcsis_parse_dt(struct platform_device * pdev,struct csis_state * state)733 static int s5pcsis_parse_dt(struct platform_device *pdev,
734 			    struct csis_state *state)
735 {
736 	struct device_node *node = pdev->dev.of_node;
737 	struct v4l2_of_endpoint endpoint;
738 
739 	if (of_property_read_u32(node, "clock-frequency",
740 				 &state->clk_frequency))
741 		state->clk_frequency = DEFAULT_SCLK_CSIS_FREQ;
742 	if (of_property_read_u32(node, "bus-width",
743 				 &state->max_num_lanes))
744 		return -EINVAL;
745 
746 	node = v4l2_of_get_next_endpoint(node, NULL);
747 	if (!node) {
748 		dev_err(&pdev->dev, "No port node at %s\n",
749 				pdev->dev.of_node->full_name);
750 		return -EINVAL;
751 	}
752 	/* Get port node and validate MIPI-CSI channel id. */
753 	v4l2_of_parse_endpoint(node, &endpoint);
754 
755 	state->index = endpoint.port - FIMC_INPUT_MIPI_CSI2_0;
756 	if (state->index < 0 || state->index >= CSIS_MAX_ENTITIES)
757 		return -ENXIO;
758 
759 	/* Get MIPI CSI-2 bus configration from the endpoint node. */
760 	of_property_read_u32(node, "samsung,csis-hs-settle",
761 					&state->hs_settle);
762 	state->wclk_ext = of_property_read_bool(node,
763 					"samsung,csis-wclk");
764 
765 	state->num_lanes = endpoint.bus.mipi_csi2.num_data_lanes;
766 
767 	of_node_put(node);
768 	return 0;
769 }
770 #else
771 #define s5pcsis_parse_dt(pdev, state) (-ENOSYS)
772 #endif
773 
s5pcsis_probe(struct platform_device * pdev)774 static int s5pcsis_probe(struct platform_device *pdev)
775 {
776 	struct device *dev = &pdev->dev;
777 	struct resource *mem_res;
778 	struct csis_state *state;
779 	int ret = -ENOMEM;
780 	int i;
781 
782 	state = devm_kzalloc(dev, sizeof(*state), GFP_KERNEL);
783 	if (!state)
784 		return -ENOMEM;
785 
786 	mutex_init(&state->lock);
787 	spin_lock_init(&state->slock);
788 	state->pdev = pdev;
789 
790 	if (dev->of_node)
791 		ret = s5pcsis_parse_dt(pdev, state);
792 	else
793 		ret = s5pcsis_get_platform_data(pdev, state);
794 	if (ret < 0)
795 		return ret;
796 
797 	if (state->num_lanes == 0 || state->num_lanes > state->max_num_lanes) {
798 		dev_err(dev, "Unsupported number of data lanes: %d (max. %d)\n",
799 			state->num_lanes, state->max_num_lanes);
800 		return -EINVAL;
801 	}
802 
803 	mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
804 	state->regs = devm_ioremap_resource(dev, mem_res);
805 	if (IS_ERR(state->regs))
806 		return PTR_ERR(state->regs);
807 
808 	state->irq = platform_get_irq(pdev, 0);
809 	if (state->irq < 0) {
810 		dev_err(dev, "Failed to get irq\n");
811 		return state->irq;
812 	}
813 
814 	for (i = 0; i < CSIS_NUM_SUPPLIES; i++)
815 		state->supplies[i].supply = csis_supply_name[i];
816 
817 	ret = devm_regulator_bulk_get(dev, CSIS_NUM_SUPPLIES,
818 				 state->supplies);
819 	if (ret)
820 		return ret;
821 
822 	ret = s5pcsis_clk_get(state);
823 	if (ret < 0)
824 		return ret;
825 
826 	if (state->clk_frequency)
827 		ret = clk_set_rate(state->clock[CSIS_CLK_MUX],
828 				   state->clk_frequency);
829 	else
830 		dev_WARN(dev, "No clock frequency specified!\n");
831 	if (ret < 0)
832 		goto e_clkput;
833 
834 	ret = clk_enable(state->clock[CSIS_CLK_MUX]);
835 	if (ret < 0)
836 		goto e_clkput;
837 
838 	ret = devm_request_irq(dev, state->irq, s5pcsis_irq_handler,
839 			       0, dev_name(dev), state);
840 	if (ret) {
841 		dev_err(dev, "Interrupt request failed\n");
842 		goto e_clkdis;
843 	}
844 
845 	v4l2_subdev_init(&state->sd, &s5pcsis_subdev_ops);
846 	state->sd.owner = THIS_MODULE;
847 	snprintf(state->sd.name, sizeof(state->sd.name), "%s.%d",
848 		 CSIS_SUBDEV_NAME, state->index);
849 	state->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
850 	state->csis_fmt = &s5pcsis_formats[0];
851 
852 	state->format.code = s5pcsis_formats[0].code;
853 	state->format.width = S5PCSIS_DEF_PIX_WIDTH;
854 	state->format.height = S5PCSIS_DEF_PIX_HEIGHT;
855 
856 	state->pads[CSIS_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
857 	state->pads[CSIS_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
858 	ret = media_entity_init(&state->sd.entity,
859 				CSIS_PADS_NUM, state->pads, 0);
860 	if (ret < 0)
861 		goto e_clkdis;
862 
863 	/* This allows to retrieve the platform device id by the host driver */
864 	v4l2_set_subdevdata(&state->sd, pdev);
865 
866 	/* .. and a pointer to the subdev. */
867 	platform_set_drvdata(pdev, &state->sd);
868 	memcpy(state->events, s5pcsis_events, sizeof(state->events));
869 	pm_runtime_enable(dev);
870 
871 	dev_info(&pdev->dev, "lanes: %d, hs_settle: %d, wclk: %d, freq: %u\n",
872 		 state->num_lanes, state->hs_settle, state->wclk_ext,
873 		 state->clk_frequency);
874 	return 0;
875 
876 e_clkdis:
877 	clk_disable(state->clock[CSIS_CLK_MUX]);
878 e_clkput:
879 	s5pcsis_clk_put(state);
880 	return ret;
881 }
882 
s5pcsis_pm_suspend(struct device * dev,bool runtime)883 static int s5pcsis_pm_suspend(struct device *dev, bool runtime)
884 {
885 	struct platform_device *pdev = to_platform_device(dev);
886 	struct v4l2_subdev *sd = platform_get_drvdata(pdev);
887 	struct csis_state *state = sd_to_csis_state(sd);
888 	int ret = 0;
889 
890 	v4l2_dbg(1, debug, sd, "%s: flags: 0x%x\n",
891 		 __func__, state->flags);
892 
893 	mutex_lock(&state->lock);
894 	if (state->flags & ST_POWERED) {
895 		s5pcsis_stop_stream(state);
896 		ret = s5p_csis_phy_enable(state->index, false);
897 		if (ret)
898 			goto unlock;
899 		ret = regulator_bulk_disable(CSIS_NUM_SUPPLIES,
900 					     state->supplies);
901 		if (ret)
902 			goto unlock;
903 		clk_disable(state->clock[CSIS_CLK_GATE]);
904 		state->flags &= ~ST_POWERED;
905 		if (!runtime)
906 			state->flags |= ST_SUSPENDED;
907 	}
908  unlock:
909 	mutex_unlock(&state->lock);
910 	return ret ? -EAGAIN : 0;
911 }
912 
s5pcsis_pm_resume(struct device * dev,bool runtime)913 static int s5pcsis_pm_resume(struct device *dev, bool runtime)
914 {
915 	struct platform_device *pdev = to_platform_device(dev);
916 	struct v4l2_subdev *sd = platform_get_drvdata(pdev);
917 	struct csis_state *state = sd_to_csis_state(sd);
918 	int ret = 0;
919 
920 	v4l2_dbg(1, debug, sd, "%s: flags: 0x%x\n",
921 		 __func__, state->flags);
922 
923 	mutex_lock(&state->lock);
924 	if (!runtime && !(state->flags & ST_SUSPENDED))
925 		goto unlock;
926 
927 	if (!(state->flags & ST_POWERED)) {
928 		ret = regulator_bulk_enable(CSIS_NUM_SUPPLIES,
929 					    state->supplies);
930 		if (ret)
931 			goto unlock;
932 		ret = s5p_csis_phy_enable(state->index, true);
933 		if (!ret) {
934 			state->flags |= ST_POWERED;
935 		} else {
936 			regulator_bulk_disable(CSIS_NUM_SUPPLIES,
937 					       state->supplies);
938 			goto unlock;
939 		}
940 		clk_enable(state->clock[CSIS_CLK_GATE]);
941 	}
942 	if (state->flags & ST_STREAMING)
943 		s5pcsis_start_stream(state);
944 
945 	state->flags &= ~ST_SUSPENDED;
946  unlock:
947 	mutex_unlock(&state->lock);
948 	return ret ? -EAGAIN : 0;
949 }
950 
951 #ifdef CONFIG_PM_SLEEP
s5pcsis_suspend(struct device * dev)952 static int s5pcsis_suspend(struct device *dev)
953 {
954 	return s5pcsis_pm_suspend(dev, false);
955 }
956 
s5pcsis_resume(struct device * dev)957 static int s5pcsis_resume(struct device *dev)
958 {
959 	return s5pcsis_pm_resume(dev, false);
960 }
961 #endif
962 
963 #ifdef CONFIG_PM_RUNTIME
s5pcsis_runtime_suspend(struct device * dev)964 static int s5pcsis_runtime_suspend(struct device *dev)
965 {
966 	return s5pcsis_pm_suspend(dev, true);
967 }
968 
s5pcsis_runtime_resume(struct device * dev)969 static int s5pcsis_runtime_resume(struct device *dev)
970 {
971 	return s5pcsis_pm_resume(dev, true);
972 }
973 #endif
974 
s5pcsis_remove(struct platform_device * pdev)975 static int s5pcsis_remove(struct platform_device *pdev)
976 {
977 	struct v4l2_subdev *sd = platform_get_drvdata(pdev);
978 	struct csis_state *state = sd_to_csis_state(sd);
979 
980 	pm_runtime_disable(&pdev->dev);
981 	s5pcsis_pm_suspend(&pdev->dev, false);
982 	clk_disable(state->clock[CSIS_CLK_MUX]);
983 	pm_runtime_set_suspended(&pdev->dev);
984 	s5pcsis_clk_put(state);
985 
986 	media_entity_cleanup(&state->sd.entity);
987 
988 	return 0;
989 }
990 
991 static const struct dev_pm_ops s5pcsis_pm_ops = {
992 	SET_RUNTIME_PM_OPS(s5pcsis_runtime_suspend, s5pcsis_runtime_resume,
993 			   NULL)
994 	SET_SYSTEM_SLEEP_PM_OPS(s5pcsis_suspend, s5pcsis_resume)
995 };
996 
997 static const struct of_device_id s5pcsis_of_match[] = {
998 	{ .compatible = "samsung,s5pv210-csis" },
999 	{ .compatible = "samsung,exynos4210-csis" },
1000 	{ /* sentinel */ },
1001 };
1002 MODULE_DEVICE_TABLE(of, s5pcsis_of_match);
1003 
1004 static struct platform_driver s5pcsis_driver = {
1005 	.probe		= s5pcsis_probe,
1006 	.remove		= s5pcsis_remove,
1007 	.driver		= {
1008 		.of_match_table = s5pcsis_of_match,
1009 		.name		= CSIS_DRIVER_NAME,
1010 		.owner		= THIS_MODULE,
1011 		.pm		= &s5pcsis_pm_ops,
1012 	},
1013 };
1014 
1015 module_platform_driver(s5pcsis_driver);
1016 
1017 MODULE_AUTHOR("Sylwester Nawrocki <s.nawrocki@samsung.com>");
1018 MODULE_DESCRIPTION("Samsung S5P/EXYNOS SoC MIPI-CSI2 receiver driver");
1019 MODULE_LICENSE("GPL");
1020