mipi-csis.c 26.7 KB
Newer Older
1
// SPDX-License-Identifier: GPL-2.0-only
2
/*
3
 * Samsung S5P/EXYNOS SoC series MIPI-CSI receiver driver
4
 *
5 6
 * Copyright (C) 2011 - 2013 Samsung Electronics Co., Ltd.
 * Author: Sylwester Nawrocki <s.nawrocki@samsung.com>
7 8 9 10 11 12 13 14 15 16 17 18
 */

#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>
19
#include <linux/of.h>
20
#include <linux/of_graph.h>
21
#include <linux/phy/phy.h>
22 23 24
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/regulator/consumer.h>
25
#include <linux/sizes.h>
26 27 28
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/videodev2.h>
29
#include <media/drv-intf/exynos-fimc.h>
30
#include <media/v4l2-fwnode.h>
31
#include <media/v4l2-subdev.h>
32

33 34 35 36
#include "mipi-csis.h"

static int debug;
module_param(debug, int, 0644);
37
MODULE_PARM_DESC(debug, "Debug level (0-2)");
38 39 40 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

/* 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

66
/* Interrupt mask */
67
#define S5PCSIS_INTMSK			0x10
68 69 70 71
#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)
72 73
#define S5PCSIS_INTMSK_FRAME_START	(1 << 27)
#define S5PCSIS_INTMSK_FRAME_END	(1 << 26)
74 75 76 77 78 79 80
#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)
81 82
#define S5PCSIS_INTMSK_EXYNOS4_EN_ALL	0xf000103f
#define S5PCSIS_INTMSK_EXYNOS5_EN_ALL	0xfc00103f
83 84

/* Interrupt source */
85
#define S5PCSIS_INTSRC			0x14
86 87 88 89 90 91
#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)
92
#define S5PCSIS_INTSRC_NON_IMAGE_DATA	(0xf << 28)
93 94
#define S5PCSIS_INTSRC_FRAME_START	(1 << 27)
#define S5PCSIS_INTSRC_FRAME_END	(1 << 26)
95 96 97 98 99 100 101 102
#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
103 104 105 106 107 108

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

109 110 111 112 113
/* Non-image packet data buffers */
#define S5PCSIS_PKTDATA_ODD		0x2000
#define S5PCSIS_PKTDATA_EVEN		0x3000
#define S5PCSIS_PKTDATA_SIZE		SZ_4K

114 115 116 117 118 119 120 121 122 123
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)
124
#define DEFAULT_SCLK_CSIS_FREQ	166000000UL
125

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

132 133 134 135 136 137
enum {
	ST_POWERED	= 1,
	ST_STREAMING	= 2,
	ST_SUSPENDED	= 4,
};

138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157
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" },
158 159 160
	/* Frame start/end */
	{ S5PCSIS_INTSRC_FRAME_START,	"Frame Start" },
	{ S5PCSIS_INTSRC_FRAME_END,	"Frame End" },
161 162 163
};
#define S5PCSIS_NUM_EVENTS ARRAY_SIZE(s5pcsis_events)

164 165 166 167 168
struct csis_pktbuf {
	u32 *data;
	unsigned int len;
};

169 170 171 172 173
struct csis_drvdata {
	/* Mask of all used interrupts in S5PCSIS_INTMSK register */
	u32 interrupt_mask;
};

174 175 176 177 178 179
/**
 * 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
180
 * @index: the hardware instance index
181
 * @pdev: CSIS platform device
182
 * @phy: pointer to the CSIS generic PHY
183
 * @regs: mmapped I/O registers memory
184
 * @supplies: CSIS regulator supplies
185 186
 * @clock: CSIS clocks
 * @irq: requested s5p-mipi-csis irq number
187
 * @interrupt_mask: interrupt mask of the all used interrupts
188
 * @flags: the state variable for power and streaming control
189
 * @clk_frequency: device bus clock frequency
190 191 192 193
 * @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
194 195
 * @csis_fmt: current CSIS pixel format
 * @format: common media bus format for the source and sink pad
196
 * @slock: spinlock protecting structure members below
197
 * @pkt_buf: the frame embedded (non-image) data buffer
198
 * @events: MIPI-CSIS event (error) counters
199 200 201 202 203
 */
struct csis_state {
	struct mutex lock;
	struct media_pad pads[CSIS_PADS_NUM];
	struct v4l2_subdev sd;
204
	u8 index;
205
	struct platform_device *pdev;
206
	struct phy *phy;
207
	void __iomem *regs;
208
	struct regulator_bulk_data supplies[CSIS_NUM_SUPPLIES];
209 210
	struct clk *clock[NUM_CSIS_CLOCKS];
	int irq;
211
	u32 interrupt_mask;
212
	u32 flags;
213 214 215 216 217 218 219

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

220 221
	const struct csis_pix_format *csis_fmt;
	struct v4l2_mbus_framefmt format;
222

223
	spinlock_t slock;
224
	struct csis_pktbuf pkt_buf;
225
	struct s5pcsis_event events[S5PCSIS_NUM_EVENTS];
226 227 228 229 230 231 232 233
};

/**
 * 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
234
 * @data_alignment: MIPI-CSI data alignment in bits
235 236 237
 */
struct csis_pix_format {
	unsigned int pix_width_alignment;
238
	u32 code;
239
	u32 fmt_reg;
240
	u8 data_alignment;
241 242 243 244
};

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

#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);
293 294 295 296
	if (on)
		val |= state->interrupt_mask;
	else
		val &= ~state->interrupt_mask;
297 298 299 300 301 302 303 304 305 306 307 308 309
	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)
{
310
	u32 val, mask;
311 312 313 314 315 316 317 318 319

	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);
320 321
	val &= ~S5PCSIS_DPHYCTRL_ENABLE;
	if (on) {
322
		mask = (1 << (state->num_lanes + 1)) - 1;
323 324
		val |= (mask & S5PCSIS_DPHYCTRL_ENABLE);
	}
325 326 327 328 329 330 331 332 333
	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;

334
	v4l2_dbg(1, debug, &state->sd, "fmt: %#x, %d x %d\n",
335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359
		 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);
360
	val = (val & ~S5PCSIS_CFG_NR_LANE_MASK) | (state->num_lanes - 1);
361 362 363
	s5pcsis_write(state, S5PCSIS_CONFIG, val);

	__s5pcsis_set_format(state);
364
	s5pcsis_set_hsync_settle(state, state->hs_settle);
365 366

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

372
	val &= ~S5PCSIS_CTRL_WCLK_EXTCLK;
373
	if (state->wclk_ext)
374
		val |= S5PCSIS_CTRL_WCLK_EXTCLK;
375 376 377 378 379 380 381 382 383 384 385
	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;

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

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

400 401 402
	for (i = 0; i < NUM_CSIS_CLOCKS; i++)
		state->clock[i] = ERR_PTR(-EINVAL);

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

423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446
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);
	}
}

447 448 449 450 451 452 453 454 455 456 457 458 459 460
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);
}

461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478
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);

479 480
	for (i--; i >= 0; i--) {
		if (state->events[i].counter > 0 || debug)
481 482 483
			v4l2_info(&state->sd, "%s events: %d\n",
				  state->events[i].name,
				  state->events[i].counter);
484
	}
485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501
	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);
}

502 503 504 505 506 507 508 509 510
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) {
511
		s5pcsis_clear_counters(state);
512 513 514 515
		ret = pm_runtime_get_sync(&state->pdev->dev);
		if (ret && ret != 1)
			return ret;
	}
516

517 518 519 520 521 522 523 524 525 526 527
	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;
528 529
		if (debug > 0)
			s5pcsis_log_counters(state, true);
530 531 532 533 534 535 536 537 538 539
	}
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,
540
				  struct v4l2_subdev_pad_config *cfg,
541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567
				  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(
568
		struct csis_state *state, struct v4l2_subdev_pad_config *cfg,
569
		enum v4l2_subdev_format_whence which)
570 571
{
	if (which == V4L2_SUBDEV_FORMAT_TRY)
572
		return cfg ? v4l2_subdev_get_try_format(&state->sd, cfg, 0) : NULL;
573 574 575 576

	return &state->format;
}

577
static int s5pcsis_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg,
578 579 580 581 582 583
			   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;

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

	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;
}

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

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

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

621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636
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;
}

637 638 639 640
static int s5pcsis_log_status(struct v4l2_subdev *sd)
{
	struct csis_state *state = sd_to_csis_state(sd);

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

649
static const struct v4l2_subdev_core_ops s5pcsis_core_ops = {
650
	.s_power = s5pcsis_s_power,
651
	.log_status = s5pcsis_log_status,
652 653
};

654
static const struct v4l2_subdev_pad_ops s5pcsis_pad_ops = {
655 656 657 658 659
	.enum_mbus_code = s5pcsis_enum_mbus_code,
	.get_fmt = s5pcsis_get_fmt,
	.set_fmt = s5pcsis_set_fmt,
};

660
static const struct v4l2_subdev_video_ops s5pcsis_video_ops = {
661
	.s_rx_buffer = s5pcsis_s_rx_buffer,
662 663 664
	.s_stream = s5pcsis_s_stream,
};

665
static const struct v4l2_subdev_ops s5pcsis_subdev_ops = {
666 667 668 669 670 671 672 673
	.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;
674
	struct csis_pktbuf *pktbuf = &state->pkt_buf;
675 676 677 678 679 680
	unsigned long flags;
	u32 status;

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

681 682 683 684 685 686 687 688
	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;

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

695 696 697 698 699 700 701 702 703 704 705 706 707 708
	/* 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);
709

710
	s5pcsis_write(state, S5PCSIS_INTSRC, status);
711 712 713
	return IRQ_HANDLED;
}

714 715 716 717
static int s5pcsis_parse_dt(struct platform_device *pdev,
			    struct csis_state *state)
{
	struct device_node *node = pdev->dev.of_node;
718
	struct v4l2_fwnode_endpoint endpoint = { .bus_type = 0 };
719
	int ret;
720 721 722 723 724 725 726 727

	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;

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

739
	state->index = endpoint.base.port - FIMC_INPUT_MIPI_CSI2_0;
740 741 742 743
	if (state->index >= CSIS_MAX_ENTITIES) {
		ret = -ENXIO;
		goto err;
	}
744

745
	/* Get MIPI CSI-2 bus configuration from the endpoint node. */
746 747 748 749 750 751
	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;
752

753 754 755
err:
	of_node_put(node);
	return ret;
756 757
}

758
static int s5pcsis_pm_resume(struct device *dev, bool runtime);
759 760
static const struct of_device_id s5pcsis_of_match[];

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

771
	state = devm_kzalloc(dev, sizeof(*state), GFP_KERNEL);
772 773 774 775
	if (!state)
		return -ENOMEM;

	mutex_init(&state->lock);
776
	spin_lock_init(&state->slock);
777 778
	state->pdev = pdev;

779 780 781
	of_id = of_match_node(s5pcsis_of_match, dev->of_node);
	if (WARN_ON(of_id == NULL))
		return -EINVAL;
782

783 784
	drv_data = of_id->data;
	state->interrupt_mask = drv_data->interrupt_mask;
785

786
	ret = s5pcsis_parse_dt(pdev, state);
787 788
	if (ret < 0)
		return ret;
789

790 791 792
	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);
793
		return -EINVAL;
794 795
	}

796 797 798 799
	state->phy = devm_phy_get(dev, "csis");
	if (IS_ERR(state->phy))
		return PTR_ERR(state->phy);

800
	mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
801
	state->regs = devm_ioremap_resource(dev, mem_res);
802 803
	if (IS_ERR(state->regs))
		return PTR_ERR(state->regs);
804 805

	state->irq = platform_get_irq(pdev, 0);
806
	if (state->irq < 0)
807
		return state->irq;
808

809 810 811
	for (i = 0; i < CSIS_NUM_SUPPLIES; i++)
		state->supplies[i].supply = csis_supply_name[i];

812
	ret = devm_regulator_bulk_get(dev, CSIS_NUM_SUPPLIES,
813
				 state->supplies);
814 815 816 817
	if (ret)
		return ret;

	ret = s5pcsis_clk_get(state);
818 819
	if (ret < 0)
		return ret;
820

821
	if (state->clk_frequency)
822
		ret = clk_set_rate(state->clock[CSIS_CLK_MUX],
823
				   state->clk_frequency);
824
	else
825
		dev_WARN(dev, "No clock frequency specified!\n");
826 827 828 829 830 831
	if (ret < 0)
		goto e_clkput;

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

833 834
	ret = devm_request_irq(dev, state->irq, s5pcsis_irq_handler,
			       0, dev_name(dev), state);
835
	if (ret) {
836
		dev_err(dev, "Interrupt request failed\n");
837
		goto e_clkdis;
838 839 840 841
	}

	v4l2_subdev_init(&state->sd, &s5pcsis_subdev_ops);
	state->sd.owner = THIS_MODULE;
842 843
	snprintf(state->sd.name, sizeof(state->sd.name), "%s.%d",
		 CSIS_SUBDEV_NAME, state->index);
844
	state->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
845 846
	state->csis_fmt = &s5pcsis_formats[0];

847 848 849 850
	state->format.code = s5pcsis_formats[0].code;
	state->format.width = S5PCSIS_DEF_PIX_WIDTH;
	state->format.height = S5PCSIS_DEF_PIX_HEIGHT;

851
	state->sd.entity.function = MEDIA_ENT_F_IO_V4L;
852 853
	state->pads[CSIS_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
	state->pads[CSIS_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
854
	ret = media_entity_pads_init(&state->sd.entity,
855
				CSIS_PADS_NUM, state->pads);
856
	if (ret < 0)
857
		goto e_clkdis;
858 859 860 861 862 863

	/* 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);
864
	memcpy(state->events, s5pcsis_events, sizeof(state->events));
865

866
	pm_runtime_enable(dev);
867 868 869 870 871
	if (!pm_runtime_enabled(dev)) {
		ret = s5pcsis_pm_resume(dev, true);
		if (ret < 0)
			goto e_m_ent;
	}
872

873 874 875
	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);
876 877
	return 0;

878 879
e_m_ent:
	media_entity_cleanup(&state->sd.entity);
880
e_clkdis:
881
	clk_disable(state->clock[CSIS_CLK_MUX]);
882
e_clkput:
883 884 885 886
	s5pcsis_clk_put(state);
	return ret;
}

887
static int s5pcsis_pm_suspend(struct device *dev, bool runtime)
888
{
889
	struct v4l2_subdev *sd = dev_get_drvdata(dev);
890
	struct csis_state *state = sd_to_csis_state(sd);
891
	int ret = 0;
892 893 894 895 896 897 898

	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);
899
		ret = phy_power_off(state->phy);
900 901
		if (ret)
			goto unlock;
902 903 904 905
		ret = regulator_bulk_disable(CSIS_NUM_SUPPLIES,
					     state->supplies);
		if (ret)
			goto unlock;
906 907
		clk_disable(state->clock[CSIS_CLK_GATE]);
		state->flags &= ~ST_POWERED;
908 909
		if (!runtime)
			state->flags |= ST_SUSPENDED;
910 911 912 913 914 915
	}
 unlock:
	mutex_unlock(&state->lock);
	return ret ? -EAGAIN : 0;
}

916
static int s5pcsis_pm_resume(struct device *dev, bool runtime)
917
{
918
	struct v4l2_subdev *sd = dev_get_drvdata(dev);
919 920 921 922 923 924 925
	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);
926
	if (!runtime && !(state->flags & ST_SUSPENDED))
927 928 929
		goto unlock;

	if (!(state->flags & ST_POWERED)) {
930 931
		ret = regulator_bulk_enable(CSIS_NUM_SUPPLIES,
					    state->supplies);
932 933
		if (ret)
			goto unlock;
934
		ret = phy_power_on(state->phy);
935 936
		if (!ret) {
			state->flags |= ST_POWERED;
937 938 939
		} else {
			regulator_bulk_disable(CSIS_NUM_SUPPLIES,
					       state->supplies);
940 941 942 943 944 945 946 947 948 949 950 951 952 953
			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
954
static int s5pcsis_suspend(struct device *dev)
955
{
956
	return s5pcsis_pm_suspend(dev, false);
957 958
}

959
static int s5pcsis_resume(struct device *dev)
960
{
961 962 963
	return s5pcsis_pm_resume(dev, false);
}
#endif
964

965
#ifdef CONFIG_PM
966 967 968 969
static int s5pcsis_runtime_suspend(struct device *dev)
{
	return s5pcsis_pm_suspend(dev, true);
}
970

971 972 973
static int s5pcsis_runtime_resume(struct device *dev)
{
	return s5pcsis_pm_resume(dev, true);
974 975 976
}
#endif

977
static int s5pcsis_remove(struct platform_device *pdev)
978 979 980 981 982
{
	struct v4l2_subdev *sd = platform_get_drvdata(pdev);
	struct csis_state *state = sd_to_csis_state(sd);

	pm_runtime_disable(&pdev->dev);
983
	s5pcsis_pm_suspend(&pdev->dev, true);
984 985 986 987 988 989 990 991 992 993
	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 = {
994 995 996
	SET_RUNTIME_PM_OPS(s5pcsis_runtime_suspend, s5pcsis_runtime_resume,
			   NULL)
	SET_SYSTEM_SLEEP_PM_OPS(s5pcsis_suspend, s5pcsis_resume)
997 998
};

999 1000 1001 1002 1003 1004 1005 1006
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,
};

1007
static const struct of_device_id s5pcsis_of_match[] = {
1008 1009 1010 1011 1012 1013 1014 1015 1016 1017
	{
		.compatible = "samsung,s5pv210-csis",
		.data = &exynos4_csis_drvdata,
	}, {
		.compatible = "samsung,exynos4210-csis",
		.data = &exynos4_csis_drvdata,
	}, {
		.compatible = "samsung,exynos5250-csis",
		.data = &exynos5_csis_drvdata,
	},
1018 1019 1020 1021
	{ /* sentinel */ },
};
MODULE_DEVICE_TABLE(of, s5pcsis_of_match);

1022 1023
static struct platform_driver s5pcsis_driver = {
	.probe		= s5pcsis_probe,
1024
	.remove		= s5pcsis_remove,
1025
	.driver		= {
1026 1027 1028
		.of_match_table = s5pcsis_of_match,
		.name		= CSIS_DRIVER_NAME,
		.pm		= &s5pcsis_pm_ops,
1029 1030 1031
	},
};

1032
module_platform_driver(s5pcsis_driver);
1033 1034

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