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-gen2.h"
17 #include "camss.h"
18
19 /* The CSID 2 IP-block is different from the others,
20 * and is of a bare-bones Lite version, with no PIX
21 * interface support. As a result of that it has an
22 * alternate register layout.
23 */
24
25 #define CSID_RST_STROBES 0x10
26 #define RST_STROBES 0
27
28 #define CSID_CSI2_RX_IRQ_STATUS 0x20
29 #define CSID_CSI2_RX_IRQ_MASK 0x24
30 #define CSID_CSI2_RX_IRQ_CLEAR 0x28
31
32 #define CSID_CSI2_RDIN_IRQ_STATUS(rdi) ((csid_is_lite(csid) ? 0x30 : 0x40) \
33 + 0x10 * (rdi))
34 #define CSID_CSI2_RDIN_IRQ_MASK(rdi) ((csid_is_lite(csid) ? 0x34 : 0x44) \
35 + 0x10 * (rdi))
36 #define CSID_CSI2_RDIN_IRQ_CLEAR(rdi) ((csid_is_lite(csid) ? 0x38 : 0x48) \
37 + 0x10 * (rdi))
38 #define CSID_CSI2_RDIN_IRQ_SET(rdi) ((csid_is_lite(csid) ? 0x3C : 0x4C) \
39 + 0x10 * (rdi))
40
41 #define CSID_TOP_IRQ_STATUS 0x70
42 #define TOP_IRQ_STATUS_RESET_DONE 0
43 #define CSID_TOP_IRQ_MASK 0x74
44 #define CSID_TOP_IRQ_CLEAR 0x78
45 #define CSID_TOP_IRQ_SET 0x7C
46 #define CSID_IRQ_CMD 0x80
47 #define IRQ_CMD_CLEAR 0
48 #define IRQ_CMD_SET 4
49
50 #define CSID_CSI2_RX_CFG0 0x100
51 #define CSI2_RX_CFG0_NUM_ACTIVE_LANES 0
52 #define CSI2_RX_CFG0_DL0_INPUT_SEL 4
53 #define CSI2_RX_CFG0_DL1_INPUT_SEL 8
54 #define CSI2_RX_CFG0_DL2_INPUT_SEL 12
55 #define CSI2_RX_CFG0_DL3_INPUT_SEL 16
56 #define CSI2_RX_CFG0_PHY_NUM_SEL 20
57 #define CSI2_RX_CFG0_PHY_TYPE_SEL 24
58
59 #define CSID_CSI2_RX_CFG1 0x104
60 #define CSI2_RX_CFG1_PACKET_ECC_CORRECTION_EN 0
61 #define CSI2_RX_CFG1_DE_SCRAMBLE_EN 1
62 #define CSI2_RX_CFG1_VC_MODE 2
63 #define CSI2_RX_CFG1_COMPLETE_STREAM_EN 4
64 #define CSI2_RX_CFG1_COMPLETE_STREAM_FRAME_TIMING 5
65 #define CSI2_RX_CFG1_MISR_EN 6
66 #define CSI2_RX_CFG1_CGC_MODE 7
67 #define CGC_MODE_DYNAMIC_GATING 0
68 #define CGC_MODE_ALWAYS_ON 1
69
70 #define CSID_RDI_CFG0(rdi) ((csid_is_lite(csid) ? 0x200 : 0x300) \
71 + 0x100 * (rdi))
72 #define RDI_CFG0_BYTE_CNTR_EN 0
73 #define RDI_CFG0_FORMAT_MEASURE_EN 1
74 #define RDI_CFG0_TIMESTAMP_EN 2
75 #define RDI_CFG0_DROP_H_EN 3
76 #define RDI_CFG0_DROP_V_EN 4
77 #define RDI_CFG0_CROP_H_EN 5
78 #define RDI_CFG0_CROP_V_EN 6
79 #define RDI_CFG0_MISR_EN 7
80 #define RDI_CFG0_CGC_MODE 8
81 #define CGC_MODE_DYNAMIC 0
82 #define CGC_MODE_ALWAYS_ON 1
83 #define RDI_CFG0_PLAIN_ALIGNMENT 9
84 #define PLAIN_ALIGNMENT_LSB 0
85 #define PLAIN_ALIGNMENT_MSB 1
86 #define RDI_CFG0_PLAIN_FORMAT 10
87 #define RDI_CFG0_DECODE_FORMAT 12
88 #define RDI_CFG0_DATA_TYPE 16
89 #define RDI_CFG0_VIRTUAL_CHANNEL 22
90 #define RDI_CFG0_DT_ID 27
91 #define RDI_CFG0_EARLY_EOF_EN 29
92 #define RDI_CFG0_PACKING_FORMAT 30
93 #define RDI_CFG0_ENABLE 31
94
95 #define CSID_RDI_CFG1(rdi) ((csid_is_lite(csid) ? 0x204 : 0x304)\
96 + 0x100 * (rdi))
97 #define RDI_CFG1_TIMESTAMP_STB_SEL 0
98
99 #define CSID_RDI_CTRL(rdi) ((csid_is_lite(csid) ? 0x208 : 0x308)\
100 + 0x100 * (rdi))
101 #define RDI_CTRL_HALT_CMD 0
102 #define HALT_CMD_HALT_AT_FRAME_BOUNDARY 0
103 #define HALT_CMD_RESUME_AT_FRAME_BOUNDARY 1
104 #define RDI_CTRL_HALT_MODE 2
105
106 #define CSID_RDI_FRM_DROP_PATTERN(rdi) ((csid_is_lite(csid) ? 0x20C : 0x30C)\
107 + 0x100 * (rdi))
108 #define CSID_RDI_FRM_DROP_PERIOD(rdi) ((csid_is_lite(csid) ? 0x210 : 0x310)\
109 + 0x100 * (rdi))
110 #define CSID_RDI_IRQ_SUBSAMPLE_PATTERN(rdi) ((csid_is_lite(csid) ? 0x214 : 0x314)\
111 + 0x100 * (rdi))
112 #define CSID_RDI_IRQ_SUBSAMPLE_PERIOD(rdi) ((csid_is_lite(csid) ? 0x218 : 0x318)\
113 + 0x100 * (rdi))
114 #define CSID_RDI_RPP_PIX_DROP_PATTERN(rdi) ((csid_is_lite(csid) ? 0x224 : 0x324)\
115 + 0x100 * (rdi))
116 #define CSID_RDI_RPP_PIX_DROP_PERIOD(rdi) ((csid_is_lite(csid) ? 0x228 : 0x328)\
117 + 0x100 * (rdi))
118 #define CSID_RDI_RPP_LINE_DROP_PATTERN(rdi) ((csid_is_lite(csid) ? 0x22C : 0x32C)\
119 + 0x100 * (rdi))
120 #define CSID_RDI_RPP_LINE_DROP_PERIOD(rdi) ((csid_is_lite(csid) ? 0x230 : 0x330)\
121 + 0x100 * (rdi))
122
123 #define CSID_TPG_CTRL 0x600
124 #define TPG_CTRL_TEST_EN 0
125 #define TPG_CTRL_FS_PKT_EN 1
126 #define TPG_CTRL_FE_PKT_EN 2
127 #define TPG_CTRL_NUM_ACTIVE_LANES 4
128 #define TPG_CTRL_CYCLES_BETWEEN_PKTS 8
129 #define TPG_CTRL_NUM_TRAIL_BYTES 20
130
131 #define CSID_TPG_VC_CFG0 0x604
132 #define TPG_VC_CFG0_VC_NUM 0
133 #define TPG_VC_CFG0_NUM_ACTIVE_SLOTS 8
134 #define NUM_ACTIVE_SLOTS_0_ENABLED 0
135 #define NUM_ACTIVE_SLOTS_0_1_ENABLED 1
136 #define NUM_ACTIVE_SLOTS_0_1_2_ENABLED 2
137 #define NUM_ACTIVE_SLOTS_0_1_3_ENABLED 3
138 #define TPG_VC_CFG0_LINE_INTERLEAVING_MODE 10
139 #define INTELEAVING_MODE_INTERLEAVED 0
140 #define INTELEAVING_MODE_ONE_SHOT 1
141 #define TPG_VC_CFG0_NUM_FRAMES 16
142
143 #define CSID_TPG_VC_CFG1 0x608
144 #define TPG_VC_CFG1_H_BLANKING_COUNT 0
145 #define TPG_VC_CFG1_V_BLANKING_COUNT 12
146 #define TPG_VC_CFG1_V_BLANK_FRAME_WIDTH_SEL 24
147
148 #define CSID_TPG_LFSR_SEED 0x60C
149
150 #define CSID_TPG_DT_n_CFG_0(n) (0x610 + (n) * 0xC)
151 #define TPG_DT_n_CFG_0_FRAME_HEIGHT 0
152 #define TPG_DT_n_CFG_0_FRAME_WIDTH 16
153
154 #define CSID_TPG_DT_n_CFG_1(n) (0x614 + (n) * 0xC)
155 #define TPG_DT_n_CFG_1_DATA_TYPE 0
156 #define TPG_DT_n_CFG_1_ECC_XOR_MASK 8
157 #define TPG_DT_n_CFG_1_CRC_XOR_MASK 16
158
159 #define CSID_TPG_DT_n_CFG_2(n) (0x618 + (n) * 0xC)
160 #define TPG_DT_n_CFG_2_PAYLOAD_MODE 0
161 #define TPG_DT_n_CFG_2_USER_SPECIFIED_PAYLOAD 4
162 #define TPG_DT_n_CFG_2_ENCODE_FORMAT 16
163
164 #define CSID_TPG_COLOR_BARS_CFG 0x640
165 #define TPG_COLOR_BARS_CFG_UNICOLOR_BAR_EN 0
166 #define TPG_COLOR_BARS_CFG_UNICOLOR_BAR_SEL 4
167 #define TPG_COLOR_BARS_CFG_SPLIT_EN 5
168 #define TPG_COLOR_BARS_CFG_ROTATE_PERIOD 8
169
170 #define CSID_TPG_COLOR_BOX_CFG 0x644
171 #define TPG_COLOR_BOX_CFG_MODE 0
172 #define TPG_COLOR_BOX_PATTERN_SEL 2
173
__csid_configure_rx(struct csid_device * csid,struct csid_phy_config * phy,int vc)174 static void __csid_configure_rx(struct csid_device *csid,
175 struct csid_phy_config *phy, int vc)
176 {
177 u8 lane_cnt = csid->phy.lane_cnt;
178 int val;
179
180 if (!lane_cnt)
181 lane_cnt = 4;
182
183 val = (lane_cnt - 1) << CSI2_RX_CFG0_NUM_ACTIVE_LANES;
184 val |= phy->lane_assign << CSI2_RX_CFG0_DL0_INPUT_SEL;
185 val |= phy->csiphy_id << CSI2_RX_CFG0_PHY_NUM_SEL;
186 writel_relaxed(val, csid->base + CSID_CSI2_RX_CFG0);
187
188 val = 1 << CSI2_RX_CFG1_PACKET_ECC_CORRECTION_EN;
189 if (vc > 3)
190 val |= 1 << CSI2_RX_CFG1_VC_MODE;
191 val |= 1 << CSI2_RX_CFG1_MISR_EN;
192 writel_relaxed(val, csid->base + CSID_CSI2_RX_CFG1);
193 }
194
__csid_ctrl_rdi(struct csid_device * csid,int enable,u8 rdi)195 static void __csid_ctrl_rdi(struct csid_device *csid, int enable, u8 rdi)
196 {
197 int val;
198
199 if (enable)
200 val = HALT_CMD_RESUME_AT_FRAME_BOUNDARY << RDI_CTRL_HALT_CMD;
201 else
202 val = HALT_CMD_HALT_AT_FRAME_BOUNDARY << RDI_CTRL_HALT_CMD;
203 writel_relaxed(val, csid->base + CSID_RDI_CTRL(rdi));
204 }
205
__csid_configure_testgen(struct csid_device * csid,u8 enable,u8 vc)206 static void __csid_configure_testgen(struct csid_device *csid, u8 enable, u8 vc)
207 {
208 struct csid_testgen_config *tg = &csid->testgen;
209 struct v4l2_mbus_framefmt *input_format = &csid->fmt[MSM_CSID_PAD_FIRST_SRC + vc];
210 const struct csid_format_info *format = csid_get_fmt_entry(csid->res->formats->formats,
211 csid->res->formats->nformats,
212 input_format->code);
213 u8 lane_cnt = csid->phy.lane_cnt;
214 u32 val;
215
216 if (!lane_cnt)
217 lane_cnt = 4;
218
219 /* configure one DT, infinite frames */
220 val = vc << TPG_VC_CFG0_VC_NUM;
221 val |= INTELEAVING_MODE_ONE_SHOT << TPG_VC_CFG0_LINE_INTERLEAVING_MODE;
222 val |= 0 << TPG_VC_CFG0_NUM_FRAMES;
223 writel_relaxed(val, csid->base + CSID_TPG_VC_CFG0);
224
225 val = 0x740 << TPG_VC_CFG1_H_BLANKING_COUNT;
226 val |= 0x3ff << TPG_VC_CFG1_V_BLANKING_COUNT;
227 writel_relaxed(val, csid->base + CSID_TPG_VC_CFG1);
228
229 writel_relaxed(0x12345678, csid->base + CSID_TPG_LFSR_SEED);
230
231 val = (input_format->height & 0x1fff) << TPG_DT_n_CFG_0_FRAME_HEIGHT;
232 val |= (input_format->width & 0x1fff) << TPG_DT_n_CFG_0_FRAME_WIDTH;
233 writel_relaxed(val, csid->base + CSID_TPG_DT_n_CFG_0(0));
234
235 val = format->data_type << TPG_DT_n_CFG_1_DATA_TYPE;
236 writel_relaxed(val, csid->base + CSID_TPG_DT_n_CFG_1(0));
237
238 val = (tg->mode - 1) << TPG_DT_n_CFG_2_PAYLOAD_MODE;
239 val |= 0xBE << TPG_DT_n_CFG_2_USER_SPECIFIED_PAYLOAD;
240 val |= format->decode_format << TPG_DT_n_CFG_2_ENCODE_FORMAT;
241 writel_relaxed(val, csid->base + CSID_TPG_DT_n_CFG_2(0));
242
243 writel_relaxed(0, csid->base + CSID_TPG_COLOR_BARS_CFG);
244
245 writel_relaxed(0, csid->base + CSID_TPG_COLOR_BOX_CFG);
246
247 val = enable << TPG_CTRL_TEST_EN;
248 val |= 1 << TPG_CTRL_FS_PKT_EN;
249 val |= 1 << TPG_CTRL_FE_PKT_EN;
250 val |= (lane_cnt - 1) << TPG_CTRL_NUM_ACTIVE_LANES;
251 val |= 0x64 << TPG_CTRL_CYCLES_BETWEEN_PKTS;
252 val |= 0xA << TPG_CTRL_NUM_TRAIL_BYTES;
253 writel_relaxed(val, csid->base + CSID_TPG_CTRL);
254 }
255
__csid_configure_rdi_stream(struct csid_device * csid,u8 enable,u8 vc)256 static void __csid_configure_rdi_stream(struct csid_device *csid, u8 enable, u8 vc)
257 {
258 /* Source pads matching RDI channels on hardware. Pad 1 -> RDI0, Pad 2 -> RDI1, etc. */
259 struct v4l2_mbus_framefmt *input_format = &csid->fmt[MSM_CSID_PAD_FIRST_SRC + vc];
260 const struct csid_format_info *format = csid_get_fmt_entry(csid->res->formats->formats,
261 csid->res->formats->nformats,
262 input_format->code);
263 u32 val;
264
265 /*
266 * DT_ID is a two bit bitfield that is concatenated with
267 * the four least significant bits of the five bit VC
268 * bitfield to generate an internal CID value.
269 *
270 * CSID_RDI_CFG0(vc)
271 * DT_ID : 28:27
272 * VC : 26:22
273 * DT : 21:16
274 *
275 * CID : VC 3:0 << 2 | DT_ID 1:0
276 */
277 u8 dt_id = vc & 0x03;
278
279 val = 1 << RDI_CFG0_BYTE_CNTR_EN;
280 val |= 1 << RDI_CFG0_FORMAT_MEASURE_EN;
281 val |= 1 << RDI_CFG0_TIMESTAMP_EN;
282 /* note: for non-RDI path, this should be format->decode_format */
283 val |= DECODE_FORMAT_PAYLOAD_ONLY << RDI_CFG0_DECODE_FORMAT;
284 val |= format->data_type << RDI_CFG0_DATA_TYPE;
285 val |= vc << RDI_CFG0_VIRTUAL_CHANNEL;
286 val |= dt_id << RDI_CFG0_DT_ID;
287 writel_relaxed(val, csid->base + CSID_RDI_CFG0(vc));
288
289 /* CSID_TIMESTAMP_STB_POST_IRQ */
290 val = 2 << RDI_CFG1_TIMESTAMP_STB_SEL;
291 writel_relaxed(val, csid->base + CSID_RDI_CFG1(vc));
292
293 val = 1;
294 writel_relaxed(val, csid->base + CSID_RDI_FRM_DROP_PERIOD(vc));
295
296 val = 0;
297 writel_relaxed(val, csid->base + CSID_RDI_FRM_DROP_PATTERN(vc));
298
299 val = 1;
300 writel_relaxed(val, csid->base + CSID_RDI_IRQ_SUBSAMPLE_PERIOD(vc));
301
302 val = 0;
303 writel_relaxed(val, csid->base + CSID_RDI_IRQ_SUBSAMPLE_PATTERN(vc));
304
305 val = 1;
306 writel_relaxed(val, csid->base + CSID_RDI_RPP_PIX_DROP_PERIOD(vc));
307
308 val = 0;
309 writel_relaxed(val, csid->base + CSID_RDI_RPP_PIX_DROP_PATTERN(vc));
310
311 val = 1;
312 writel_relaxed(val, csid->base + CSID_RDI_RPP_LINE_DROP_PERIOD(vc));
313
314 val = 0;
315 writel_relaxed(val, csid->base + CSID_RDI_RPP_LINE_DROP_PATTERN(vc));
316
317 val = 0;
318 writel_relaxed(val, csid->base + CSID_RDI_CTRL(vc));
319
320 val = readl_relaxed(csid->base + CSID_RDI_CFG0(vc));
321 val |= enable << RDI_CFG0_ENABLE;
322 writel_relaxed(val, csid->base + CSID_RDI_CFG0(vc));
323 }
324
csid_configure_stream(struct csid_device * csid,u8 enable)325 static void csid_configure_stream(struct csid_device *csid, u8 enable)
326 {
327 struct csid_testgen_config *tg = &csid->testgen;
328 u8 i;
329 /* Loop through all enabled VCs and configure stream for each */
330 for (i = 0; i < MSM_CSID_MAX_SRC_STREAMS; i++)
331 if (csid->phy.en_vc & BIT(i)) {
332 if (tg->enabled)
333 __csid_configure_testgen(csid, enable, i);
334
335 __csid_configure_rdi_stream(csid, enable, i);
336 __csid_configure_rx(csid, &csid->phy, i);
337 __csid_ctrl_rdi(csid, enable, i);
338 }
339 }
340
csid_configure_testgen_pattern(struct csid_device * csid,s32 val)341 static int csid_configure_testgen_pattern(struct csid_device *csid, s32 val)
342 {
343 if (val > 0 && val <= csid->testgen.nmodes)
344 csid->testgen.mode = val;
345
346 return 0;
347 }
348
349 /*
350 * csid_isr - CSID module interrupt service routine
351 * @irq: Interrupt line
352 * @dev: CSID device
353 *
354 * Return IRQ_HANDLED on success
355 */
csid_isr(int irq,void * dev)356 static irqreturn_t csid_isr(int irq, void *dev)
357 {
358 struct csid_device *csid = dev;
359 u32 val;
360 u8 reset_done;
361 int i;
362
363 val = readl_relaxed(csid->base + CSID_TOP_IRQ_STATUS);
364 writel_relaxed(val, csid->base + CSID_TOP_IRQ_CLEAR);
365 reset_done = val & BIT(TOP_IRQ_STATUS_RESET_DONE);
366
367 val = readl_relaxed(csid->base + CSID_CSI2_RX_IRQ_STATUS);
368 writel_relaxed(val, csid->base + CSID_CSI2_RX_IRQ_CLEAR);
369
370 /* Read and clear IRQ status for each enabled RDI channel */
371 for (i = 0; i < MSM_CSID_MAX_SRC_STREAMS; i++)
372 if (csid->phy.en_vc & BIT(i)) {
373 val = readl_relaxed(csid->base + CSID_CSI2_RDIN_IRQ_STATUS(i));
374 writel_relaxed(val, csid->base + CSID_CSI2_RDIN_IRQ_CLEAR(i));
375 }
376
377 val = 1 << IRQ_CMD_CLEAR;
378 writel_relaxed(val, csid->base + CSID_IRQ_CMD);
379
380 if (reset_done)
381 complete(&csid->reset_complete);
382
383 return IRQ_HANDLED;
384 }
385
386 /*
387 * csid_reset - Trigger reset on CSID module and wait to complete
388 * @csid: CSID device
389 *
390 * Return 0 on success or a negative error code otherwise
391 */
csid_reset(struct csid_device * csid)392 static int csid_reset(struct csid_device *csid)
393 {
394 unsigned long time;
395 u32 val;
396
397 reinit_completion(&csid->reset_complete);
398
399 writel_relaxed(1, csid->base + CSID_TOP_IRQ_CLEAR);
400 writel_relaxed(1, csid->base + CSID_IRQ_CMD);
401 writel_relaxed(1, csid->base + CSID_TOP_IRQ_MASK);
402 writel_relaxed(1, csid->base + CSID_IRQ_CMD);
403
404 /* preserve registers */
405 val = 0x1e << RST_STROBES;
406 writel_relaxed(val, csid->base + CSID_RST_STROBES);
407
408 time = wait_for_completion_timeout(&csid->reset_complete,
409 msecs_to_jiffies(CSID_RESET_TIMEOUT_MS));
410 if (!time) {
411 dev_err(csid->camss->dev, "CSID reset timeout\n");
412 return -EIO;
413 }
414
415 return 0;
416 }
417
csid_subdev_init(struct csid_device * csid)418 static void csid_subdev_init(struct csid_device *csid)
419 {
420 csid->testgen.modes = csid_testgen_modes;
421 csid->testgen.nmodes = CSID_PAYLOAD_MODE_NUM_SUPPORTED_GEN2;
422 }
423
424 const struct csid_hw_ops csid_ops_gen2 = {
425 .configure_stream = csid_configure_stream,
426 .configure_testgen_pattern = csid_configure_testgen_pattern,
427 .hw_version = csid_hw_version,
428 .isr = csid_isr,
429 .reset = csid_reset,
430 .src_pad_code = csid_src_pad_code,
431 .subdev_init = csid_subdev_init,
432 };
433