mipi-csis.c 27.0 KB
Newer Older
1
/*
2
 * Samsung S5P/EXYNOS SoC series MIPI-CSI receiver driver
3
 *
4 5
 * Copyright (C) 2011 - 2013 Samsung Electronics Co., Ltd.
 * Author: Sylwester Nawrocki <s.nawrocki@samsung.com>
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/errno.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/irq.h>
#include <linux/kernel.h>
#include <linux/memory.h>
#include <linux/module.h>
22
#include <linux/of.h>
23
#include <linux/of_graph.h>
24
#include <linux/phy/phy.h>
25 26 27
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/regulator/consumer.h>
28
#include <linux/sizes.h>
29 30 31
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/videodev2.h>
32
#include <media/drv-intf/exynos-fimc.h>
33
#include <media/v4l2-of.h>
34
#include <media/v4l2-subdev.h>
35

36 37 38 39
#include "mipi-csis.h"

static int debug;
module_param(debug, int, 0644);
40
MODULE_PARM_DESC(debug, "Debug level (0-2)");
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68

/* Register map definition */

/* CSIS global control */
#define S5PCSIS_CTRL			0x00
#define S5PCSIS_CTRL_DPDN_DEFAULT	(0 << 31)
#define S5PCSIS_CTRL_DPDN_SWAP		(1 << 31)
#define S5PCSIS_CTRL_ALIGN_32BIT	(1 << 20)
#define S5PCSIS_CTRL_UPDATE_SHADOW	(1 << 16)
#define S5PCSIS_CTRL_WCLK_EXTCLK	(1 << 8)
#define S5PCSIS_CTRL_RESET		(1 << 4)
#define S5PCSIS_CTRL_ENABLE		(1 << 0)

/* D-PHY control */
#define S5PCSIS_DPHYCTRL		0x04
#define S5PCSIS_DPHYCTRL_HSS_MASK	(0x1f << 27)
#define S5PCSIS_DPHYCTRL_ENABLE		(0x1f << 0)

#define S5PCSIS_CONFIG			0x08
#define S5PCSIS_CFG_FMT_YCBCR422_8BIT	(0x1e << 2)
#define S5PCSIS_CFG_FMT_RAW8		(0x2a << 2)
#define S5PCSIS_CFG_FMT_RAW10		(0x2b << 2)
#define S5PCSIS_CFG_FMT_RAW12		(0x2c << 2)
/* User defined formats, x = 1...4 */
#define S5PCSIS_CFG_FMT_USER(x)		((0x30 + x - 1) << 2)
#define S5PCSIS_CFG_FMT_MASK		(0x3f << 2)
#define S5PCSIS_CFG_NR_LANE_MASK	3

69
/* Interrupt mask */
70
#define S5PCSIS_INTMSK			0x10
71 72 73 74
#define S5PCSIS_INTMSK_EVEN_BEFORE	(1 << 31)
#define S5PCSIS_INTMSK_EVEN_AFTER	(1 << 30)
#define S5PCSIS_INTMSK_ODD_BEFORE	(1 << 29)
#define S5PCSIS_INTMSK_ODD_AFTER	(1 << 28)
75 76
#define S5PCSIS_INTMSK_FRAME_START	(1 << 27)
#define S5PCSIS_INTMSK_FRAME_END	(1 << 26)
77 78 79 80 81 82 83
#define S5PCSIS_INTMSK_ERR_SOT_HS	(1 << 12)
#define S5PCSIS_INTMSK_ERR_LOST_FS	(1 << 5)
#define S5PCSIS_INTMSK_ERR_LOST_FE	(1 << 4)
#define S5PCSIS_INTMSK_ERR_OVER		(1 << 3)
#define S5PCSIS_INTMSK_ERR_ECC		(1 << 2)
#define S5PCSIS_INTMSK_ERR_CRC		(1 << 1)
#define S5PCSIS_INTMSK_ERR_UNKNOWN	(1 << 0)
84 85
#define S5PCSIS_INTMSK_EXYNOS4_EN_ALL	0xf000103f
#define S5PCSIS_INTMSK_EXYNOS5_EN_ALL	0xfc00103f
86 87

/* Interrupt source */
88
#define S5PCSIS_INTSRC			0x14
89 90 91 92 93 94
#define S5PCSIS_INTSRC_EVEN_BEFORE	(1 << 31)
#define S5PCSIS_INTSRC_EVEN_AFTER	(1 << 30)
#define S5PCSIS_INTSRC_EVEN		(0x3 << 30)
#define S5PCSIS_INTSRC_ODD_BEFORE	(1 << 29)
#define S5PCSIS_INTSRC_ODD_AFTER	(1 << 28)
#define S5PCSIS_INTSRC_ODD		(0x3 << 28)
95
#define S5PCSIS_INTSRC_NON_IMAGE_DATA	(0xf << 28)
96 97
#define S5PCSIS_INTSRC_FRAME_START	(1 << 27)
#define S5PCSIS_INTSRC_FRAME_END	(1 << 26)
98 99 100 101 102 103 104 105
#define S5PCSIS_INTSRC_ERR_SOT_HS	(0xf << 12)
#define S5PCSIS_INTSRC_ERR_LOST_FS	(1 << 5)
#define S5PCSIS_INTSRC_ERR_LOST_FE	(1 << 4)
#define S5PCSIS_INTSRC_ERR_OVER		(1 << 3)
#define S5PCSIS_INTSRC_ERR_ECC		(1 << 2)
#define S5PCSIS_INTSRC_ERR_CRC		(1 << 1)
#define S5PCSIS_INTSRC_ERR_UNKNOWN	(1 << 0)
#define S5PCSIS_INTSRC_ERRORS		0xf03f
106 107 108 109 110 111

/* Pixel resolution */
#define S5PCSIS_RESOL			0x2c
#define CSIS_MAX_PIX_WIDTH		0xffff
#define CSIS_MAX_PIX_HEIGHT		0xffff

112 113 114 115 116
/* Non-image packet data buffers */
#define S5PCSIS_PKTDATA_ODD		0x2000
#define S5PCSIS_PKTDATA_EVEN		0x3000
#define S5PCSIS_PKTDATA_SIZE		SZ_4K

117 118 119 120 121 122 123 124 125 126
enum {
	CSIS_CLK_MUX,
	CSIS_CLK_GATE,
};

static char *csi_clock_name[] = {
	[CSIS_CLK_MUX]  = "sclk_csis",
	[CSIS_CLK_GATE] = "csis",
};
#define NUM_CSIS_CLOCKS	ARRAY_SIZE(csi_clock_name)
127
#define DEFAULT_SCLK_CSIS_FREQ	166000000UL
128

129
static const char * const csis_supply_name[] = {
130 131
	"vddcore",  /* CSIS Core (1.0V, 1.1V or 1.2V) suppply */
	"vddio",    /* CSIS I/O and PLL (1.8V) supply */
132 133 134
};
#define CSIS_NUM_SUPPLIES ARRAY_SIZE(csis_supply_name)

135 136 137 138 139 140
enum {
	ST_POWERED	= 1,
	ST_STREAMING	= 2,
	ST_SUSPENDED	= 4,
};

141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
struct s5pcsis_event {
	u32 mask;
	const char * const name;
	unsigned int counter;
};

static const struct s5pcsis_event s5pcsis_events[] = {
	/* Errors */
	{ S5PCSIS_INTSRC_ERR_SOT_HS,	"SOT Error" },
	{ S5PCSIS_INTSRC_ERR_LOST_FS,	"Lost Frame Start Error" },
	{ S5PCSIS_INTSRC_ERR_LOST_FE,	"Lost Frame End Error" },
	{ S5PCSIS_INTSRC_ERR_OVER,	"FIFO Overflow Error" },
	{ S5PCSIS_INTSRC_ERR_ECC,	"ECC Error" },
	{ S5PCSIS_INTSRC_ERR_CRC,	"CRC Error" },
	{ S5PCSIS_INTSRC_ERR_UNKNOWN,	"Unknown Error" },
	/* Non-image data receive events */
	{ S5PCSIS_INTSRC_EVEN_BEFORE,	"Non-image data before even frame" },
	{ S5PCSIS_INTSRC_EVEN_AFTER,	"Non-image data after even frame" },
	{ S5PCSIS_INTSRC_ODD_BEFORE,	"Non-image data before odd frame" },
	{ S5PCSIS_INTSRC_ODD_AFTER,	"Non-image data after odd frame" },
161 162 163
	/* Frame start/end */
	{ S5PCSIS_INTSRC_FRAME_START,	"Frame Start" },
	{ S5PCSIS_INTSRC_FRAME_END,	"Frame End" },
164 165 166
};
#define S5PCSIS_NUM_EVENTS ARRAY_SIZE(s5pcsis_events)

167 168 169 170 171
struct csis_pktbuf {
	u32 *data;
	unsigned int len;
};

172 173 174 175 176
struct csis_drvdata {
	/* Mask of all used interrupts in S5PCSIS_INTMSK register */
	u32 interrupt_mask;
};

177 178 179 180 181 182
/**
 * struct csis_state - the driver's internal state data structure
 * @lock: mutex serializing the subdev and power management operations,
 *        protecting @format and @flags members
 * @pads: CSIS pads array
 * @sd: v4l2_subdev associated with CSIS device instance
183
 * @index: the hardware instance index
184
 * @pdev: CSIS platform device
185
 * @phy: pointer to the CSIS generic PHY
186
 * @regs: mmaped I/O registers memory
187
 * @supplies: CSIS regulator supplies
188 189
 * @clock: CSIS clocks
 * @irq: requested s5p-mipi-csis irq number
190
 * @interrupt_mask: interrupt mask of the all used interrupts
191
 * @flags: the state variable for power and streaming control
192 193 194 195 196
 * @clock_frequency: device bus clock frequency
 * @hs_settle: HS-RX settle time
 * @num_lanes: number of MIPI-CSI data lanes used
 * @max_num_lanes: maximum number of MIPI-CSI data lanes supported
 * @wclk_ext: CSI wrapper clock: 0 - bus clock, 1 - external SCLK_CAM
197 198
 * @csis_fmt: current CSIS pixel format
 * @format: common media bus format for the source and sink pad
199
 * @slock: spinlock protecting structure members below
200
 * @pkt_buf: the frame embedded (non-image) data buffer
201
 * @events: MIPI-CSIS event (error) counters
202 203 204 205 206
 */
struct csis_state {
	struct mutex lock;
	struct media_pad pads[CSIS_PADS_NUM];
	struct v4l2_subdev sd;
207
	u8 index;
208
	struct platform_device *pdev;
209
	struct phy *phy;
210
	void __iomem *regs;
211
	struct regulator_bulk_data supplies[CSIS_NUM_SUPPLIES];
212 213
	struct clk *clock[NUM_CSIS_CLOCKS];
	int irq;
214
	u32 interrupt_mask;
215
	u32 flags;
216 217 218 219 220 221 222

	u32 clk_frequency;
	u32 hs_settle;
	u32 num_lanes;
	u32 max_num_lanes;
	u8 wclk_ext;

223 224
	const struct csis_pix_format *csis_fmt;
	struct v4l2_mbus_framefmt format;
225

226
	spinlock_t slock;
227
	struct csis_pktbuf pkt_buf;
228
	struct s5pcsis_event events[S5PCSIS_NUM_EVENTS];
229 230 231 232 233 234 235 236
};

/**
 * struct csis_pix_format - CSIS pixel format description
 * @pix_width_alignment: horizontal pixel alignment, width will be
 *                       multiple of 2^pix_width_alignment
 * @code: corresponding media bus code
 * @fmt_reg: S5PCSIS_CONFIG register value
237
 * @data_alignment: MIPI-CSI data alignment in bits
238 239 240
 */
struct csis_pix_format {
	unsigned int pix_width_alignment;
241
	u32 code;
242
	u32 fmt_reg;
243
	u8 data_alignment;
244 245 246 247
};

static const struct csis_pix_format s5pcsis_formats[] = {
	{
248
		.code = MEDIA_BUS_FMT_VYUY8_2X8,
249
		.fmt_reg = S5PCSIS_CFG_FMT_YCBCR422_8BIT,
250
		.data_alignment = 32,
251
	}, {
252
		.code = MEDIA_BUS_FMT_JPEG_1X8,
253
		.fmt_reg = S5PCSIS_CFG_FMT_USER(1),
254
		.data_alignment = 32,
255
	}, {
256
		.code = MEDIA_BUS_FMT_S5C_UYVY_JPEG_1X8,
257 258
		.fmt_reg = S5PCSIS_CFG_FMT_USER(1),
		.data_alignment = 32,
259
	}, {
260
		.code = MEDIA_BUS_FMT_SGRBG8_1X8,
261 262 263
		.fmt_reg = S5PCSIS_CFG_FMT_RAW8,
		.data_alignment = 24,
	}, {
264
		.code = MEDIA_BUS_FMT_SGRBG10_1X10,
265 266 267
		.fmt_reg = S5PCSIS_CFG_FMT_RAW10,
		.data_alignment = 24,
	}, {
268
		.code = MEDIA_BUS_FMT_SGRBG12_1X12,
269 270
		.fmt_reg = S5PCSIS_CFG_FMT_RAW12,
		.data_alignment = 24,
271
	}
272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295
};

#define s5pcsis_write(__csis, __r, __v) writel(__v, __csis->regs + __r)
#define s5pcsis_read(__csis, __r) readl(__csis->regs + __r)

static struct csis_state *sd_to_csis_state(struct v4l2_subdev *sdev)
{
	return container_of(sdev, struct csis_state, sd);
}

static const struct csis_pix_format *find_csis_format(
	struct v4l2_mbus_framefmt *mf)
{
	int i;

	for (i = 0; i < ARRAY_SIZE(s5pcsis_formats); i++)
		if (mf->code == s5pcsis_formats[i].code)
			return &s5pcsis_formats[i];
	return NULL;
}

static void s5pcsis_enable_interrupts(struct csis_state *state, bool on)
{
	u32 val = s5pcsis_read(state, S5PCSIS_INTMSK);
296 297 298 299
	if (on)
		val |= state->interrupt_mask;
	else
		val &= ~state->interrupt_mask;
300 301 302 303 304 305 306 307 308 309 310 311 312
	s5pcsis_write(state, S5PCSIS_INTMSK, val);
}

static void s5pcsis_reset(struct csis_state *state)
{
	u32 val = s5pcsis_read(state, S5PCSIS_CTRL);

	s5pcsis_write(state, S5PCSIS_CTRL, val | S5PCSIS_CTRL_RESET);
	udelay(10);
}

static void s5pcsis_system_enable(struct csis_state *state, int on)
{
313
	u32 val, mask;
314 315 316 317 318 319 320 321 322

	val = s5pcsis_read(state, S5PCSIS_CTRL);
	if (on)
		val |= S5PCSIS_CTRL_ENABLE;
	else
		val &= ~S5PCSIS_CTRL_ENABLE;
	s5pcsis_write(state, S5PCSIS_CTRL, val);

	val = s5pcsis_read(state, S5PCSIS_DPHYCTRL);
323 324
	val &= ~S5PCSIS_DPHYCTRL_ENABLE;
	if (on) {
325
		mask = (1 << (state->num_lanes + 1)) - 1;
326 327
		val |= (mask & S5PCSIS_DPHYCTRL_ENABLE);
	}
328 329 330 331 332 333 334 335 336
	s5pcsis_write(state, S5PCSIS_DPHYCTRL, val);
}

/* Called with the state.lock mutex held */
static void __s5pcsis_set_format(struct csis_state *state)
{
	struct v4l2_mbus_framefmt *mf = &state->format;
	u32 val;

337
	v4l2_dbg(1, debug, &state->sd, "fmt: %#x, %d x %d\n",
338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362
		 mf->code, mf->width, mf->height);

	/* Color format */
	val = s5pcsis_read(state, S5PCSIS_CONFIG);
	val = (val & ~S5PCSIS_CFG_FMT_MASK) | state->csis_fmt->fmt_reg;
	s5pcsis_write(state, S5PCSIS_CONFIG, val);

	/* Pixel resolution */
	val = (mf->width << 16) | mf->height;
	s5pcsis_write(state, S5PCSIS_RESOL, val);
}

static void s5pcsis_set_hsync_settle(struct csis_state *state, int settle)
{
	u32 val = s5pcsis_read(state, S5PCSIS_DPHYCTRL);

	val = (val & ~S5PCSIS_DPHYCTRL_HSS_MASK) | (settle << 27);
	s5pcsis_write(state, S5PCSIS_DPHYCTRL, val);
}

static void s5pcsis_set_params(struct csis_state *state)
{
	u32 val;

	val = s5pcsis_read(state, S5PCSIS_CONFIG);
363
	val = (val & ~S5PCSIS_CFG_NR_LANE_MASK) | (state->num_lanes - 1);
364 365 366
	s5pcsis_write(state, S5PCSIS_CONFIG, val);

	__s5pcsis_set_format(state);
367
	s5pcsis_set_hsync_settle(state, state->hs_settle);
368 369

	val = s5pcsis_read(state, S5PCSIS_CTRL);
370
	if (state->csis_fmt->data_alignment == 32)
371 372 373
		val |= S5PCSIS_CTRL_ALIGN_32BIT;
	else /* 24-bits */
		val &= ~S5PCSIS_CTRL_ALIGN_32BIT;
374

375
	val &= ~S5PCSIS_CTRL_WCLK_EXTCLK;
376
	if (state->wclk_ext)
377
		val |= S5PCSIS_CTRL_WCLK_EXTCLK;
378 379 380 381 382 383 384 385 386 387 388
	s5pcsis_write(state, S5PCSIS_CTRL, val);

	/* Update the shadow register. */
	val = s5pcsis_read(state, S5PCSIS_CTRL);
	s5pcsis_write(state, S5PCSIS_CTRL, val | S5PCSIS_CTRL_UPDATE_SHADOW);
}

static void s5pcsis_clk_put(struct csis_state *state)
{
	int i;

389
	for (i = 0; i < NUM_CSIS_CLOCKS; i++) {
390
		if (IS_ERR(state->clock[i]))
391 392 393
			continue;
		clk_unprepare(state->clock[i]);
		clk_put(state->clock[i]);
394
		state->clock[i] = ERR_PTR(-EINVAL);
395
	}
396 397 398 399 400
}

static int s5pcsis_clk_get(struct csis_state *state)
{
	struct device *dev = &state->pdev->dev;
401
	int i, ret;
402

403 404 405
	for (i = 0; i < NUM_CSIS_CLOCKS; i++)
		state->clock[i] = ERR_PTR(-EINVAL);

406 407
	for (i = 0; i < NUM_CSIS_CLOCKS; i++) {
		state->clock[i] = clk_get(dev, csi_clock_name[i]);
408 409
		if (IS_ERR(state->clock[i])) {
			ret = PTR_ERR(state->clock[i]);
410
			goto err;
411
		}
412 413 414
		ret = clk_prepare(state->clock[i]);
		if (ret < 0) {
			clk_put(state->clock[i]);
415
			state->clock[i] = ERR_PTR(-EINVAL);
416
			goto err;
417 418 419
		}
	}
	return 0;
420 421 422
err:
	s5pcsis_clk_put(state);
	dev_err(dev, "failed to get clock: %s\n", csi_clock_name[i]);
423
	return ret;
424 425
}

426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449
static void dump_regs(struct csis_state *state, const char *label)
{
	struct {
		u32 offset;
		const char * const name;
	} registers[] = {
		{ 0x00, "CTRL" },
		{ 0x04, "DPHYCTRL" },
		{ 0x08, "CONFIG" },
		{ 0x0c, "DPHYSTS" },
		{ 0x10, "INTMSK" },
		{ 0x2c, "RESOL" },
		{ 0x38, "SDW_CONFIG" },
	};
	u32 i;

	v4l2_info(&state->sd, "--- %s ---\n", label);

	for (i = 0; i < ARRAY_SIZE(registers); i++) {
		u32 cfg = s5pcsis_read(state, registers[i].offset);
		v4l2_info(&state->sd, "%10s: 0x%08x\n", registers[i].name, cfg);
	}
}

450 451 452 453 454 455 456 457 458 459 460 461 462 463
static void s5pcsis_start_stream(struct csis_state *state)
{
	s5pcsis_reset(state);
	s5pcsis_set_params(state);
	s5pcsis_system_enable(state, true);
	s5pcsis_enable_interrupts(state, true);
}

static void s5pcsis_stop_stream(struct csis_state *state)
{
	s5pcsis_enable_interrupts(state, false);
	s5pcsis_system_enable(state, false);
}

464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481
static void s5pcsis_clear_counters(struct csis_state *state)
{
	unsigned long flags;
	int i;

	spin_lock_irqsave(&state->slock, flags);
	for (i = 0; i < S5PCSIS_NUM_EVENTS; i++)
		state->events[i].counter = 0;
	spin_unlock_irqrestore(&state->slock, flags);
}

static void s5pcsis_log_counters(struct csis_state *state, bool non_errors)
{
	int i = non_errors ? S5PCSIS_NUM_EVENTS : S5PCSIS_NUM_EVENTS - 4;
	unsigned long flags;

	spin_lock_irqsave(&state->slock, flags);

482 483
	for (i--; i >= 0; i--) {
		if (state->events[i].counter > 0 || debug)
484 485 486
			v4l2_info(&state->sd, "%s events: %d\n",
				  state->events[i].name,
				  state->events[i].counter);
487
	}
488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504
	spin_unlock_irqrestore(&state->slock, flags);
}

/*
 * V4L2 subdev operations
 */
static int s5pcsis_s_power(struct v4l2_subdev *sd, int on)
{
	struct csis_state *state = sd_to_csis_state(sd);
	struct device *dev = &state->pdev->dev;

	if (on)
		return pm_runtime_get_sync(dev);

	return pm_runtime_put_sync(dev);
}

505 506 507 508 509 510 511 512 513
static int s5pcsis_s_stream(struct v4l2_subdev *sd, int enable)
{
	struct csis_state *state = sd_to_csis_state(sd);
	int ret = 0;

	v4l2_dbg(1, debug, sd, "%s: %d, state: 0x%x\n",
		 __func__, enable, state->flags);

	if (enable) {
514
		s5pcsis_clear_counters(state);
515 516 517 518
		ret = pm_runtime_get_sync(&state->pdev->dev);
		if (ret && ret != 1)
			return ret;
	}
519

520 521 522 523 524 525 526 527 528 529 530
	mutex_lock(&state->lock);
	if (enable) {
		if (state->flags & ST_SUSPENDED) {
			ret = -EBUSY;
			goto unlock;
		}
		s5pcsis_start_stream(state);
		state->flags |= ST_STREAMING;
	} else {
		s5pcsis_stop_stream(state);
		state->flags &= ~ST_STREAMING;
531 532
		if (debug > 0)
			s5pcsis_log_counters(state, true);
533 534 535 536 537 538 539 540 541 542
	}
unlock:
	mutex_unlock(&state->lock);
	if (!enable)
		pm_runtime_put(&state->pdev->dev);

	return ret == 1 ? 0 : ret;
}

static int s5pcsis_enum_mbus_code(struct v4l2_subdev *sd,
543
				  struct v4l2_subdev_pad_config *cfg,
544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570
				  struct v4l2_subdev_mbus_code_enum *code)
{
	if (code->index >= ARRAY_SIZE(s5pcsis_formats))
		return -EINVAL;

	code->code = s5pcsis_formats[code->index].code;
	return 0;
}

static struct csis_pix_format const *s5pcsis_try_format(
	struct v4l2_mbus_framefmt *mf)
{
	struct csis_pix_format const *csis_fmt;

	csis_fmt = find_csis_format(mf);
	if (csis_fmt == NULL)
		csis_fmt = &s5pcsis_formats[0];

	mf->code = csis_fmt->code;
	v4l_bound_align_image(&mf->width, 1, CSIS_MAX_PIX_WIDTH,
			      csis_fmt->pix_width_alignment,
			      &mf->height, 1, CSIS_MAX_PIX_HEIGHT, 1,
			      0);
	return csis_fmt;
}

static struct v4l2_mbus_framefmt *__s5pcsis_get_format(
571
		struct csis_state *state, struct v4l2_subdev_pad_config *cfg,
572
		enum v4l2_subdev_format_whence which)
573 574
{
	if (which == V4L2_SUBDEV_FORMAT_TRY)
575
		return cfg ? v4l2_subdev_get_try_format(&state->sd, cfg, 0) : NULL;
576 577 578 579

	return &state->format;
}

580
static int s5pcsis_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg,
581 582 583 584 585 586
			   struct v4l2_subdev_format *fmt)
{
	struct csis_state *state = sd_to_csis_state(sd);
	struct csis_pix_format const *csis_fmt;
	struct v4l2_mbus_framefmt *mf;

587
	mf = __s5pcsis_get_format(state, cfg, fmt->which);
588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607

	if (fmt->pad == CSIS_PAD_SOURCE) {
		if (mf) {
			mutex_lock(&state->lock);
			fmt->format = *mf;
			mutex_unlock(&state->lock);
		}
		return 0;
	}
	csis_fmt = s5pcsis_try_format(&fmt->format);
	if (mf) {
		mutex_lock(&state->lock);
		*mf = fmt->format;
		if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE)
			state->csis_fmt = csis_fmt;
		mutex_unlock(&state->lock);
	}
	return 0;
}

608
static int s5pcsis_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg,
609 610 611 612 613
			   struct v4l2_subdev_format *fmt)
{
	struct csis_state *state = sd_to_csis_state(sd);
	struct v4l2_mbus_framefmt *mf;

614
	mf = __s5pcsis_get_format(state, cfg, fmt->which);
615 616 617 618 619 620 621 622 623
	if (!mf)
		return -EINVAL;

	mutex_lock(&state->lock);
	fmt->format = *mf;
	mutex_unlock(&state->lock);
	return 0;
}

624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639
static int s5pcsis_s_rx_buffer(struct v4l2_subdev *sd, void *buf,
			       unsigned int *size)
{
	struct csis_state *state = sd_to_csis_state(sd);
	unsigned long flags;

	*size = min_t(unsigned int, *size, S5PCSIS_PKTDATA_SIZE);

	spin_lock_irqsave(&state->slock, flags);
	state->pkt_buf.data = buf;
	state->pkt_buf.len = *size;
	spin_unlock_irqrestore(&state->slock, flags);

	return 0;
}

640 641 642 643
static int s5pcsis_log_status(struct v4l2_subdev *sd)
{
	struct csis_state *state = sd_to_csis_state(sd);

644
	mutex_lock(&state->lock);
645
	s5pcsis_log_counters(state, true);
646 647 648
	if (debug && (state->flags & ST_POWERED))
		dump_regs(state, __func__);
	mutex_unlock(&state->lock);
649 650 651
	return 0;
}

652 653
static struct v4l2_subdev_core_ops s5pcsis_core_ops = {
	.s_power = s5pcsis_s_power,
654
	.log_status = s5pcsis_log_status,
655 656 657 658 659 660 661 662 663
};

static struct v4l2_subdev_pad_ops s5pcsis_pad_ops = {
	.enum_mbus_code = s5pcsis_enum_mbus_code,
	.get_fmt = s5pcsis_get_fmt,
	.set_fmt = s5pcsis_set_fmt,
};

static struct v4l2_subdev_video_ops s5pcsis_video_ops = {
664
	.s_rx_buffer = s5pcsis_s_rx_buffer,
665 666 667 668 669 670 671 672 673 674 675 676
	.s_stream = s5pcsis_s_stream,
};

static struct v4l2_subdev_ops s5pcsis_subdev_ops = {
	.core = &s5pcsis_core_ops,
	.pad = &s5pcsis_pad_ops,
	.video = &s5pcsis_video_ops,
};

static irqreturn_t s5pcsis_irq_handler(int irq, void *dev_id)
{
	struct csis_state *state = dev_id;
677
	struct csis_pktbuf *pktbuf = &state->pkt_buf;
678 679 680 681 682 683
	unsigned long flags;
	u32 status;

	status = s5pcsis_read(state, S5PCSIS_INTSRC);
	spin_lock_irqsave(&state->slock, flags);

684 685 686 687 688 689 690 691
	if ((status & S5PCSIS_INTSRC_NON_IMAGE_DATA) && pktbuf->data) {
		u32 offset;

		if (status & S5PCSIS_INTSRC_EVEN)
			offset = S5PCSIS_PKTDATA_EVEN;
		else
			offset = S5PCSIS_PKTDATA_ODD;

692 693
		memcpy(pktbuf->data, (u8 __force *)state->regs + offset,
		       pktbuf->len);
694 695 696 697
		pktbuf->data = NULL;
		rmb();
	}

698 699 700 701 702 703 704 705 706 707 708 709 710 711
	/* Update the event/error counters */
	if ((status & S5PCSIS_INTSRC_ERRORS) || debug) {
		int i;
		for (i = 0; i < S5PCSIS_NUM_EVENTS; i++) {
			if (!(status & state->events[i].mask))
				continue;
			state->events[i].counter++;
			v4l2_dbg(2, debug, &state->sd, "%s: %d\n",
				 state->events[i].name,
				 state->events[i].counter);
		}
		v4l2_dbg(2, debug, &state->sd, "status: %08x\n", status);
	}
	spin_unlock_irqrestore(&state->slock, flags);
712

713
	s5pcsis_write(state, S5PCSIS_INTSRC, status);
714 715 716
	return IRQ_HANDLED;
}

717 718 719 720 721
static int s5pcsis_parse_dt(struct platform_device *pdev,
			    struct csis_state *state)
{
	struct device_node *node = pdev->dev.of_node;
	struct v4l2_of_endpoint endpoint;
722
	int ret;
723 724 725 726 727 728 729 730

	if (of_property_read_u32(node, "clock-frequency",
				 &state->clk_frequency))
		state->clk_frequency = DEFAULT_SCLK_CSIS_FREQ;
	if (of_property_read_u32(node, "bus-width",
				 &state->max_num_lanes))
		return -EINVAL;

731
	node = of_graph_get_next_endpoint(node, NULL);
732 733
	if (!node) {
		dev_err(&pdev->dev, "No port node at %s\n",
734
				pdev->dev.of_node->full_name);
735 736 737
		return -EINVAL;
	}
	/* Get port node and validate MIPI-CSI channel id. */
738 739 740
	ret = v4l2_of_parse_endpoint(node, &endpoint);
	if (ret)
		goto err;
741

742
	state->index = endpoint.base.port - FIMC_INPUT_MIPI_CSI2_0;
743 744 745 746
	if (state->index >= CSIS_MAX_ENTITIES) {
		ret = -ENXIO;
		goto err;
	}
747 748 749 750 751 752 753 754

	/* Get MIPI CSI-2 bus configration from the endpoint node. */
	of_property_read_u32(node, "samsung,csis-hs-settle",
					&state->hs_settle);
	state->wclk_ext = of_property_read_bool(node,
					"samsung,csis-wclk");

	state->num_lanes = endpoint.bus.mipi_csi2.num_data_lanes;
755

756 757 758
err:
	of_node_put(node);
	return ret;
759 760
}

761
static int s5pcsis_pm_resume(struct device *dev, bool runtime);
762 763
static const struct of_device_id s5pcsis_of_match[];

764
static int s5pcsis_probe(struct platform_device *pdev)
765
{
766 767
	const struct of_device_id *of_id;
	const struct csis_drvdata *drv_data;
768
	struct device *dev = &pdev->dev;
769 770 771
	struct resource *mem_res;
	struct csis_state *state;
	int ret = -ENOMEM;
772
	int i;
773

774
	state = devm_kzalloc(dev, sizeof(*state), GFP_KERNEL);
775 776 777 778
	if (!state)
		return -ENOMEM;

	mutex_init(&state->lock);
779
	spin_lock_init(&state->slock);
780 781
	state->pdev = pdev;

782 783 784
	of_id = of_match_node(s5pcsis_of_match, dev->of_node);
	if (WARN_ON(of_id == NULL))
		return -EINVAL;
785

786 787
	drv_data = of_id->data;
	state->interrupt_mask = drv_data->interrupt_mask;
788

789
	ret = s5pcsis_parse_dt(pdev, state);
790 791
	if (ret < 0)
		return ret;
792

793 794 795
	if (state->num_lanes == 0 || state->num_lanes > state->max_num_lanes) {
		dev_err(dev, "Unsupported number of data lanes: %d (max. %d)\n",
			state->num_lanes, state->max_num_lanes);
796
		return -EINVAL;
797 798
	}

799 800 801 802
	state->phy = devm_phy_get(dev, "csis");
	if (IS_ERR(state->phy))
		return PTR_ERR(state->phy);

803
	mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
804
	state->regs = devm_ioremap_resource(dev, mem_res);
805 806
	if (IS_ERR(state->regs))
		return PTR_ERR(state->regs);
807 808 809

	state->irq = platform_get_irq(pdev, 0);
	if (state->irq < 0) {
810
		dev_err(dev, "Failed to get irq\n");
811
		return state->irq;
812 813
	}

814 815 816
	for (i = 0; i < CSIS_NUM_SUPPLIES; i++)
		state->supplies[i].supply = csis_supply_name[i];

817
	ret = devm_regulator_bulk_get(dev, CSIS_NUM_SUPPLIES,
818
				 state->supplies);
819 820 821 822
	if (ret)
		return ret;

	ret = s5pcsis_clk_get(state);
823 824
	if (ret < 0)
		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 832 833 834 835 836
	if (ret < 0)
		goto e_clkput;

	ret = clk_enable(state->clock[CSIS_CLK_MUX]);
	if (ret < 0)
		goto e_clkput;
837

838 839
	ret = devm_request_irq(dev, state->irq, s5pcsis_irq_handler,
			       0, dev_name(dev), state);
840
	if (ret) {
841
		dev_err(dev, "Interrupt request failed\n");
842
		goto e_clkdis;
843 844 845 846
	}

	v4l2_subdev_init(&state->sd, &s5pcsis_subdev_ops);
	state->sd.owner = THIS_MODULE;
847 848
	snprintf(state->sd.name, sizeof(state->sd.name), "%s.%d",
		 CSIS_SUBDEV_NAME, state->index);
849
	state->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
850 851
	state->csis_fmt = &s5pcsis_formats[0];

852 853 854 855
	state->format.code = s5pcsis_formats[0].code;
	state->format.width = S5PCSIS_DEF_PIX_WIDTH;
	state->format.height = S5PCSIS_DEF_PIX_HEIGHT;

856
	state->sd.entity.function = MEDIA_ENT_F_IO_V4L;
857 858
	state->pads[CSIS_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
	state->pads[CSIS_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
859
	ret = media_entity_pads_init(&state->sd.entity,
860
				CSIS_PADS_NUM, state->pads);
861
	if (ret < 0)
862
		goto e_clkdis;
863 864 865 866 867 868

	/* This allows to retrieve the platform device id by the host driver */
	v4l2_set_subdevdata(&state->sd, pdev);

	/* .. and a pointer to the subdev. */
	platform_set_drvdata(pdev, &state->sd);
869
	memcpy(state->events, s5pcsis_events, sizeof(state->events));
870

871
	pm_runtime_enable(dev);
872 873 874 875 876
	if (!pm_runtime_enabled(dev)) {
		ret = s5pcsis_pm_resume(dev, true);
		if (ret < 0)
			goto e_m_ent;
	}
877

878 879 880
	dev_info(&pdev->dev, "lanes: %d, hs_settle: %d, wclk: %d, freq: %u\n",
		 state->num_lanes, state->hs_settle, state->wclk_ext,
		 state->clk_frequency);
881 882
	return 0;

883 884
e_m_ent:
	media_entity_cleanup(&state->sd.entity);
885
e_clkdis:
886
	clk_disable(state->clock[CSIS_CLK_MUX]);
887
e_clkput:
888 889 890 891
	s5pcsis_clk_put(state);
	return ret;
}

892
static int s5pcsis_pm_suspend(struct device *dev, bool runtime)
893 894 895 896
{
	struct platform_device *pdev = to_platform_device(dev);
	struct v4l2_subdev *sd = platform_get_drvdata(pdev);
	struct csis_state *state = sd_to_csis_state(sd);
897
	int ret = 0;
898 899 900 901 902 903 904

	v4l2_dbg(1, debug, sd, "%s: flags: 0x%x\n",
		 __func__, state->flags);

	mutex_lock(&state->lock);
	if (state->flags & ST_POWERED) {
		s5pcsis_stop_stream(state);
905
		ret = phy_power_off(state->phy);
906 907
		if (ret)
			goto unlock;
908 909 910 911
		ret = regulator_bulk_disable(CSIS_NUM_SUPPLIES,
					     state->supplies);
		if (ret)
			goto unlock;
912 913
		clk_disable(state->clock[CSIS_CLK_GATE]);
		state->flags &= ~ST_POWERED;
914 915
		if (!runtime)
			state->flags |= ST_SUSPENDED;
916 917 918 919 920 921
	}
 unlock:
	mutex_unlock(&state->lock);
	return ret ? -EAGAIN : 0;
}

922
static int s5pcsis_pm_resume(struct device *dev, bool runtime)
923 924 925 926 927 928 929 930 931 932
{
	struct platform_device *pdev = to_platform_device(dev);
	struct v4l2_subdev *sd = platform_get_drvdata(pdev);
	struct csis_state *state = sd_to_csis_state(sd);
	int ret = 0;

	v4l2_dbg(1, debug, sd, "%s: flags: 0x%x\n",
		 __func__, state->flags);

	mutex_lock(&state->lock);
933
	if (!runtime && !(state->flags & ST_SUSPENDED))
934 935 936
		goto unlock;

	if (!(state->flags & ST_POWERED)) {
937 938
		ret = regulator_bulk_enable(CSIS_NUM_SUPPLIES,
					    state->supplies);
939 940
		if (ret)
			goto unlock;
941
		ret = phy_power_on(state->phy);
942 943
		if (!ret) {
			state->flags |= ST_POWERED;
944 945 946
		} else {
			regulator_bulk_disable(CSIS_NUM_SUPPLIES,
					       state->supplies);
947 948 949 950 951 952 953 954 955 956 957 958 959 960
			goto unlock;
		}
		clk_enable(state->clock[CSIS_CLK_GATE]);
	}
	if (state->flags & ST_STREAMING)
		s5pcsis_start_stream(state);

	state->flags &= ~ST_SUSPENDED;
 unlock:
	mutex_unlock(&state->lock);
	return ret ? -EAGAIN : 0;
}

#ifdef CONFIG_PM_SLEEP
961
static int s5pcsis_suspend(struct device *dev)
962
{
963
	return s5pcsis_pm_suspend(dev, false);
964 965
}

966
static int s5pcsis_resume(struct device *dev)
967
{
968 969 970
	return s5pcsis_pm_resume(dev, false);
}
#endif
971

972
#ifdef CONFIG_PM
973 974 975 976
static int s5pcsis_runtime_suspend(struct device *dev)
{
	return s5pcsis_pm_suspend(dev, true);
}
977

978 979 980
static int s5pcsis_runtime_resume(struct device *dev)
{
	return s5pcsis_pm_resume(dev, true);
981 982 983
}
#endif

984
static int s5pcsis_remove(struct platform_device *pdev)
985 986 987 988 989
{
	struct v4l2_subdev *sd = platform_get_drvdata(pdev);
	struct csis_state *state = sd_to_csis_state(sd);

	pm_runtime_disable(&pdev->dev);
990
	s5pcsis_pm_suspend(&pdev->dev, true);
991 992 993 994 995 996 997 998 999 1000
	clk_disable(state->clock[CSIS_CLK_MUX]);
	pm_runtime_set_suspended(&pdev->dev);
	s5pcsis_clk_put(state);

	media_entity_cleanup(&state->sd.entity);

	return 0;
}

static const struct dev_pm_ops s5pcsis_pm_ops = {
1001 1002 1003
	SET_RUNTIME_PM_OPS(s5pcsis_runtime_suspend, s5pcsis_runtime_resume,
			   NULL)
	SET_SYSTEM_SLEEP_PM_OPS(s5pcsis_suspend, s5pcsis_resume)
1004 1005
};

1006 1007 1008 1009 1010 1011 1012 1013
static const struct csis_drvdata exynos4_csis_drvdata = {
	.interrupt_mask = S5PCSIS_INTMSK_EXYNOS4_EN_ALL,
};

static const struct csis_drvdata exynos5_csis_drvdata = {
	.interrupt_mask = S5PCSIS_INTMSK_EXYNOS5_EN_ALL,
};

1014
static const struct of_device_id s5pcsis_of_match[] = {
1015 1016 1017 1018 1019 1020 1021 1022 1023 1024
	{
		.compatible = "samsung,s5pv210-csis",
		.data = &exynos4_csis_drvdata,
	}, {
		.compatible = "samsung,exynos4210-csis",
		.data = &exynos4_csis_drvdata,
	}, {
		.compatible = "samsung,exynos5250-csis",
		.data = &exynos5_csis_drvdata,
	},
1025 1026 1027 1028
	{ /* sentinel */ },
};
MODULE_DEVICE_TABLE(of, s5pcsis_of_match);

1029 1030
static struct platform_driver s5pcsis_driver = {
	.probe		= s5pcsis_probe,
1031
	.remove		= s5pcsis_remove,
1032
	.driver		= {
1033 1034 1035
		.of_match_table = s5pcsis_of_match,
		.name		= CSIS_DRIVER_NAME,
		.pm		= &s5pcsis_pm_ops,
1036 1037 1038
	},
};

1039
module_platform_driver(s5pcsis_driver);
1040 1041

MODULE_AUTHOR("Sylwester Nawrocki <s.nawrocki@samsung.com>");
1042
MODULE_DESCRIPTION("Samsung S5P/EXYNOS SoC MIPI-CSI2 receiver driver");
1043
MODULE_LICENSE("GPL");