cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

mipi-csis.c (27328B)


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