1// SPDX-License-Identifier: GPL-2.0
2/*
3 * camss-csid-4-7.c
4 *
5 * Qualcomm MSM Camera Subsystem - CSID (CSI Decoder) Module
6 *
7 * Copyright (C) 2020 Linaro Ltd.
8 */
9#include <linux/completion.h>
10#include <linux/interrupt.h>
11#include <linux/io.h>
12#include <linux/kernel.h>
13#include <linux/of.h>
14
15#include "camss-csid.h"
16#include "camss-csid-gen1.h"
17#include "camss.h"
18
19#define CAMSS_CSID_HW_VERSION		0x0
20#define CAMSS_CSID_CORE_CTRL_0		0x004
21#define CAMSS_CSID_CORE_CTRL_1		0x008
22#define CAMSS_CSID_RST_CMD		0x010
23#define CAMSS_CSID_CID_LUT_VC_n(n)	(0x014 + 0x4 * (n))
24#define CAMSS_CSID_CID_n_CFG(n)		(0x024 + 0x4 * (n))
25#define CAMSS_CSID_CID_n_CFG_ISPIF_EN	BIT(0)
26#define CAMSS_CSID_CID_n_CFG_RDI_EN	BIT(1)
27#define CAMSS_CSID_CID_n_CFG_DECODE_FORMAT_SHIFT	4
28#define CAMSS_CSID_CID_n_CFG_PLAIN_FORMAT_8		(PLAIN_FORMAT_PLAIN8 << 8)
29#define CAMSS_CSID_CID_n_CFG_PLAIN_FORMAT_16		(PLAIN_FORMAT_PLAIN16 << 8)
30#define CAMSS_CSID_CID_n_CFG_PLAIN_ALIGNMENT_LSB	(0 << 9)
31#define CAMSS_CSID_CID_n_CFG_PLAIN_ALIGNMENT_MSB	(1 << 9)
32#define CAMSS_CSID_CID_n_CFG_RDI_MODE_RAW_DUMP		(0 << 10)
33#define CAMSS_CSID_CID_n_CFG_RDI_MODE_PLAIN_PACKING	(1 << 10)
34#define CAMSS_CSID_IRQ_CLEAR_CMD	0x064
35#define CAMSS_CSID_IRQ_MASK		0x068
36#define CAMSS_CSID_IRQ_STATUS		0x06c
37#define CAMSS_CSID_TG_CTRL		0x0a8
38#define CAMSS_CSID_TG_CTRL_DISABLE	0xa06436
39#define CAMSS_CSID_TG_CTRL_ENABLE	0xa06437
40#define CAMSS_CSID_TG_VC_CFG		0x0ac
41#define CAMSS_CSID_TG_VC_CFG_H_BLANKING		0x3ff
42#define CAMSS_CSID_TG_VC_CFG_V_BLANKING		0x7f
43#define CAMSS_CSID_TG_DT_n_CGG_0(n)	(0x0b4 + 0xc * (n))
44#define CAMSS_CSID_TG_DT_n_CGG_1(n)	(0x0b8 + 0xc * (n))
45#define CAMSS_CSID_TG_DT_n_CGG_2(n)	(0x0bc + 0xc * (n))
46
47static const struct csid_format csid_formats[] = {
48	{
49		MEDIA_BUS_FMT_UYVY8_2X8,
50		DATA_TYPE_YUV422_8BIT,
51		DECODE_FORMAT_UNCOMPRESSED_8_BIT,
52		8,
53		2,
54	},
55	{
56		MEDIA_BUS_FMT_VYUY8_2X8,
57		DATA_TYPE_YUV422_8BIT,
58		DECODE_FORMAT_UNCOMPRESSED_8_BIT,
59		8,
60		2,
61	},
62	{
63		MEDIA_BUS_FMT_YUYV8_2X8,
64		DATA_TYPE_YUV422_8BIT,
65		DECODE_FORMAT_UNCOMPRESSED_8_BIT,
66		8,
67		2,
68	},
69	{
70		MEDIA_BUS_FMT_YVYU8_2X8,
71		DATA_TYPE_YUV422_8BIT,
72		DECODE_FORMAT_UNCOMPRESSED_8_BIT,
73		8,
74		2,
75	},
76	{
77		MEDIA_BUS_FMT_SBGGR8_1X8,
78		DATA_TYPE_RAW_8BIT,
79		DECODE_FORMAT_UNCOMPRESSED_8_BIT,
80		8,
81		1,
82	},
83	{
84		MEDIA_BUS_FMT_SGBRG8_1X8,
85		DATA_TYPE_RAW_8BIT,
86		DECODE_FORMAT_UNCOMPRESSED_8_BIT,
87		8,
88		1,
89	},
90	{
91		MEDIA_BUS_FMT_SGRBG8_1X8,
92		DATA_TYPE_RAW_8BIT,
93		DECODE_FORMAT_UNCOMPRESSED_8_BIT,
94		8,
95		1,
96	},
97	{
98		MEDIA_BUS_FMT_SRGGB8_1X8,
99		DATA_TYPE_RAW_8BIT,
100		DECODE_FORMAT_UNCOMPRESSED_8_BIT,
101		8,
102		1,
103	},
104	{
105		MEDIA_BUS_FMT_SBGGR10_1X10,
106		DATA_TYPE_RAW_10BIT,
107		DECODE_FORMAT_UNCOMPRESSED_10_BIT,
108		10,
109		1,
110	},
111	{
112		MEDIA_BUS_FMT_SGBRG10_1X10,
113		DATA_TYPE_RAW_10BIT,
114		DECODE_FORMAT_UNCOMPRESSED_10_BIT,
115		10,
116		1,
117	},
118	{
119		MEDIA_BUS_FMT_SGRBG10_1X10,
120		DATA_TYPE_RAW_10BIT,
121		DECODE_FORMAT_UNCOMPRESSED_10_BIT,
122		10,
123		1,
124	},
125	{
126		MEDIA_BUS_FMT_SRGGB10_1X10,
127		DATA_TYPE_RAW_10BIT,
128		DECODE_FORMAT_UNCOMPRESSED_10_BIT,
129		10,
130		1,
131	},
132	{
133		MEDIA_BUS_FMT_SBGGR12_1X12,
134		DATA_TYPE_RAW_12BIT,
135		DECODE_FORMAT_UNCOMPRESSED_12_BIT,
136		12,
137		1,
138	},
139	{
140		MEDIA_BUS_FMT_SGBRG12_1X12,
141		DATA_TYPE_RAW_12BIT,
142		DECODE_FORMAT_UNCOMPRESSED_12_BIT,
143		12,
144		1,
145	},
146	{
147		MEDIA_BUS_FMT_SGRBG12_1X12,
148		DATA_TYPE_RAW_12BIT,
149		DECODE_FORMAT_UNCOMPRESSED_12_BIT,
150		12,
151		1,
152	},
153	{
154		MEDIA_BUS_FMT_SRGGB12_1X12,
155		DATA_TYPE_RAW_12BIT,
156		DECODE_FORMAT_UNCOMPRESSED_12_BIT,
157		12,
158		1,
159	},
160	{
161		MEDIA_BUS_FMT_SBGGR14_1X14,
162		DATA_TYPE_RAW_14BIT,
163		DECODE_FORMAT_UNCOMPRESSED_14_BIT,
164		14,
165		1,
166	},
167	{
168		MEDIA_BUS_FMT_SGBRG14_1X14,
169		DATA_TYPE_RAW_14BIT,
170		DECODE_FORMAT_UNCOMPRESSED_14_BIT,
171		14,
172		1,
173	},
174	{
175		MEDIA_BUS_FMT_SGRBG14_1X14,
176		DATA_TYPE_RAW_14BIT,
177		DECODE_FORMAT_UNCOMPRESSED_14_BIT,
178		14,
179		1,
180	},
181	{
182		MEDIA_BUS_FMT_SRGGB14_1X14,
183		DATA_TYPE_RAW_14BIT,
184		DECODE_FORMAT_UNCOMPRESSED_14_BIT,
185		14,
186		1,
187	},
188	{
189		MEDIA_BUS_FMT_Y10_1X10,
190		DATA_TYPE_RAW_10BIT,
191		DECODE_FORMAT_UNCOMPRESSED_10_BIT,
192		10,
193		1,
194	},
195};
196
197static void csid_configure_stream(struct csid_device *csid, u8 enable)
198{
199	struct csid_testgen_config *tg = &csid->testgen;
200	u32 sink_code = csid->fmt[MSM_CSID_PAD_SINK].code;
201	u32 src_code = csid->fmt[MSM_CSID_PAD_SRC].code;
202	u32 val;
203
204	if (enable) {
205		struct v4l2_mbus_framefmt *input_format;
206		const struct csid_format *format;
207		u8 vc = 0; /* Virtual Channel 0 */
208		u8 cid = vc * 4; /* id of Virtual Channel and Data Type set */
209		u8 dt_shift;
210
211		if (tg->enabled) {
212			/* Config Test Generator */
213			u32 num_bytes_per_line, num_lines;
214
215			input_format = &csid->fmt[MSM_CSID_PAD_SRC];
216			format = csid_get_fmt_entry(csid->formats, csid->nformats,
217						    input_format->code);
218			num_bytes_per_line = input_format->width * format->bpp * format->spp / 8;
219			num_lines = input_format->height;
220
221			/* 31:24 V blank, 23:13 H blank, 3:2 num of active DT */
222			/* 1:0 VC */
223			val = ((CAMSS_CSID_TG_VC_CFG_V_BLANKING & 0xff) << 24) |
224				  ((CAMSS_CSID_TG_VC_CFG_H_BLANKING & 0x7ff) << 13);
225			writel_relaxed(val, csid->base + CAMSS_CSID_TG_VC_CFG);
226
227			/* 28:16 bytes per lines, 12:0 num of lines */
228			val = ((num_bytes_per_line & 0x1fff) << 16) |
229				  (num_lines & 0x1fff);
230			writel_relaxed(val, csid->base + CAMSS_CSID_TG_DT_n_CGG_0(0));
231
232			/* 5:0 data type */
233			val = format->data_type;
234			writel_relaxed(val, csid->base + CAMSS_CSID_TG_DT_n_CGG_1(0));
235
236			/* 2:0 output test pattern */
237			val = tg->mode - 1;
238			writel_relaxed(val, csid->base + CAMSS_CSID_TG_DT_n_CGG_2(0));
239		} else {
240			struct csid_phy_config *phy = &csid->phy;
241
242			input_format = &csid->fmt[MSM_CSID_PAD_SINK];
243			format = csid_get_fmt_entry(csid->formats, csid->nformats,
244						    input_format->code);
245
246			val = phy->lane_cnt - 1;
247			val |= phy->lane_assign << 4;
248
249			writel_relaxed(val, csid->base + CAMSS_CSID_CORE_CTRL_0);
250
251			val = phy->csiphy_id << 17;
252			val |= 0x9;
253
254			writel_relaxed(val, csid->base + CAMSS_CSID_CORE_CTRL_1);
255		}
256
257		/* Config LUT */
258
259		dt_shift = (cid % 4) * 8;
260
261		val = readl_relaxed(csid->base + CAMSS_CSID_CID_LUT_VC_n(vc));
262		val &= ~(0xff << dt_shift);
263		val |= format->data_type << dt_shift;
264		writel_relaxed(val, csid->base + CAMSS_CSID_CID_LUT_VC_n(vc));
265
266		val = CAMSS_CSID_CID_n_CFG_ISPIF_EN;
267		val |= CAMSS_CSID_CID_n_CFG_RDI_EN;
268		val |= format->decode_format << CAMSS_CSID_CID_n_CFG_DECODE_FORMAT_SHIFT;
269		val |= CAMSS_CSID_CID_n_CFG_RDI_MODE_RAW_DUMP;
270
271		if ((sink_code == MEDIA_BUS_FMT_SBGGR10_1X10 &&
272		     src_code == MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_LE) ||
273		    (sink_code == MEDIA_BUS_FMT_Y10_1X10 &&
274		     src_code == MEDIA_BUS_FMT_Y10_2X8_PADHI_LE)) {
275			val |= CAMSS_CSID_CID_n_CFG_RDI_MODE_PLAIN_PACKING;
276			val |= CAMSS_CSID_CID_n_CFG_PLAIN_FORMAT_16;
277			val |= CAMSS_CSID_CID_n_CFG_PLAIN_ALIGNMENT_LSB;
278		}
279
280		writel_relaxed(val, csid->base + CAMSS_CSID_CID_n_CFG(cid));
281
282		if (tg->enabled) {
283			val = CAMSS_CSID_TG_CTRL_ENABLE;
284			writel_relaxed(val, csid->base + CAMSS_CSID_TG_CTRL);
285		}
286	} else {
287		if (tg->enabled) {
288			val = CAMSS_CSID_TG_CTRL_DISABLE;
289			writel_relaxed(val, csid->base + CAMSS_CSID_TG_CTRL);
290		}
291	}
292}
293
294static int csid_configure_testgen_pattern(struct csid_device *csid, s32 val)
295{
296	if (val > 0 && val <= csid->testgen.nmodes)
297		csid->testgen.mode = val;
298
299	return 0;
300}
301
302static u32 csid_hw_version(struct csid_device *csid)
303{
304	u32 hw_version = readl_relaxed(csid->base + CAMSS_CSID_HW_VERSION);
305
306	dev_dbg(csid->camss->dev, "CSID HW Version = 0x%08x\n", hw_version);
307
308	return hw_version;
309}
310
311/*
312 * isr - CSID module interrupt service routine
313 * @irq: Interrupt line
314 * @dev: CSID device
315 *
316 * Return IRQ_HANDLED on success
317 */
318static irqreturn_t csid_isr(int irq, void *dev)
319{
320	struct csid_device *csid = dev;
321	u32 value;
322
323	value = readl_relaxed(csid->base + CAMSS_CSID_IRQ_STATUS);
324	writel_relaxed(value, csid->base + CAMSS_CSID_IRQ_CLEAR_CMD);
325
326	if ((value >> 11) & 0x1)
327		complete(&csid->reset_complete);
328
329	return IRQ_HANDLED;
330}
331
332/*
333 * csid_reset - Trigger reset on CSID module and wait to complete
334 * @csid: CSID device
335 *
336 * Return 0 on success or a negative error code otherwise
337 */
338static int csid_reset(struct csid_device *csid)
339{
340	unsigned long time;
341
342	reinit_completion(&csid->reset_complete);
343
344	writel_relaxed(0x7fff, csid->base + CAMSS_CSID_RST_CMD);
345
346	time = wait_for_completion_timeout(&csid->reset_complete,
347					   msecs_to_jiffies(CSID_RESET_TIMEOUT_MS));
348	if (!time) {
349		dev_err(csid->camss->dev, "CSID reset timeout\n");
350		return -EIO;
351	}
352
353	return 0;
354}
355
356static u32 csid_src_pad_code(struct csid_device *csid, u32 sink_code,
357			     unsigned int match_format_idx, u32 match_code)
358{
359	switch (sink_code) {
360	case MEDIA_BUS_FMT_SBGGR10_1X10:
361	{
362		u32 src_code[] = {
363			MEDIA_BUS_FMT_SBGGR10_1X10,
364			MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_LE,
365		};
366
367		return csid_find_code(src_code, ARRAY_SIZE(src_code),
368				      match_format_idx, match_code);
369	}
370	case MEDIA_BUS_FMT_Y10_1X10:
371	{
372		u32 src_code[] = {
373			MEDIA_BUS_FMT_Y10_1X10,
374			MEDIA_BUS_FMT_Y10_2X8_PADHI_LE,
375		};
376
377		return csid_find_code(src_code, ARRAY_SIZE(src_code),
378				      match_format_idx, match_code);
379	}
380	default:
381		if (match_format_idx > 0)
382			return 0;
383
384		return sink_code;
385	}
386}
387
388static void csid_subdev_init(struct csid_device *csid)
389{
390	csid->formats = csid_formats;
391	csid->nformats = ARRAY_SIZE(csid_formats);
392	csid->testgen.modes = csid_testgen_modes;
393	csid->testgen.nmodes = CSID_PAYLOAD_MODE_NUM_SUPPORTED_GEN1;
394}
395
396const struct csid_hw_ops csid_ops_4_7 = {
397	.configure_stream = csid_configure_stream,
398	.configure_testgen_pattern = csid_configure_testgen_pattern,
399	.hw_version = csid_hw_version,
400	.isr = csid_isr,
401	.reset = csid_reset,
402	.src_pad_code = csid_src_pad_code,
403	.subdev_init = csid_subdev_init,
404};
405