GNU Linux-libre 6.7.9-gnu
[releases.git] / drivers / media / platform / qcom / camss / camss-csid-gen2.c
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 #define IS_LITE         (csid->id >= 2 ? 1 : 0)
25
26 #define CSID_HW_VERSION         0x0
27 #define         HW_VERSION_STEPPING     0
28 #define         HW_VERSION_REVISION     16
29 #define         HW_VERSION_GENERATION   28
30
31 #define CSID_RST_STROBES        0x10
32 #define         RST_STROBES     0
33
34 #define CSID_CSI2_RX_IRQ_STATUS 0x20
35 #define CSID_CSI2_RX_IRQ_MASK   0x24
36 #define CSID_CSI2_RX_IRQ_CLEAR  0x28
37
38 #define CSID_CSI2_RDIN_IRQ_STATUS(rdi)          ((IS_LITE ? 0x30 : 0x40) \
39                                                  + 0x10 * (rdi))
40 #define CSID_CSI2_RDIN_IRQ_MASK(rdi)            ((IS_LITE ? 0x34 : 0x44) \
41                                                  + 0x10 * (rdi))
42 #define CSID_CSI2_RDIN_IRQ_CLEAR(rdi)           ((IS_LITE ? 0x38 : 0x48) \
43                                                  + 0x10 * (rdi))
44 #define CSID_CSI2_RDIN_IRQ_SET(rdi)             ((IS_LITE ? 0x3C : 0x4C) \
45                                                  + 0x10 * (rdi))
46
47 #define CSID_TOP_IRQ_STATUS     0x70
48 #define         TOP_IRQ_STATUS_RESET_DONE 0
49 #define CSID_TOP_IRQ_MASK       0x74
50 #define CSID_TOP_IRQ_CLEAR      0x78
51 #define CSID_TOP_IRQ_SET        0x7C
52 #define CSID_IRQ_CMD            0x80
53 #define         IRQ_CMD_CLEAR   0
54 #define         IRQ_CMD_SET     4
55
56 #define CSID_CSI2_RX_CFG0       0x100
57 #define         CSI2_RX_CFG0_NUM_ACTIVE_LANES   0
58 #define         CSI2_RX_CFG0_DL0_INPUT_SEL      4
59 #define         CSI2_RX_CFG0_DL1_INPUT_SEL      8
60 #define         CSI2_RX_CFG0_DL2_INPUT_SEL      12
61 #define         CSI2_RX_CFG0_DL3_INPUT_SEL      16
62 #define         CSI2_RX_CFG0_PHY_NUM_SEL        20
63 #define         CSI2_RX_CFG0_PHY_TYPE_SEL       24
64
65 #define CSID_CSI2_RX_CFG1       0x104
66 #define         CSI2_RX_CFG1_PACKET_ECC_CORRECTION_EN           0
67 #define         CSI2_RX_CFG1_DE_SCRAMBLE_EN                     1
68 #define         CSI2_RX_CFG1_VC_MODE                            2
69 #define         CSI2_RX_CFG1_COMPLETE_STREAM_EN                 4
70 #define         CSI2_RX_CFG1_COMPLETE_STREAM_FRAME_TIMING       5
71 #define         CSI2_RX_CFG1_MISR_EN                            6
72 #define         CSI2_RX_CFG1_CGC_MODE                           7
73 #define                 CGC_MODE_DYNAMIC_GATING         0
74 #define                 CGC_MODE_ALWAYS_ON              1
75
76 #define CSID_RDI_CFG0(rdi)                      ((IS_LITE ? 0x200 : 0x300) \
77                                                  + 0x100 * (rdi))
78 #define         RDI_CFG0_BYTE_CNTR_EN           0
79 #define         RDI_CFG0_FORMAT_MEASURE_EN      1
80 #define         RDI_CFG0_TIMESTAMP_EN           2
81 #define         RDI_CFG0_DROP_H_EN              3
82 #define         RDI_CFG0_DROP_V_EN              4
83 #define         RDI_CFG0_CROP_H_EN              5
84 #define         RDI_CFG0_CROP_V_EN              6
85 #define         RDI_CFG0_MISR_EN                7
86 #define         RDI_CFG0_CGC_MODE               8
87 #define                 CGC_MODE_DYNAMIC        0
88 #define                 CGC_MODE_ALWAYS_ON      1
89 #define         RDI_CFG0_PLAIN_ALIGNMENT        9
90 #define                 PLAIN_ALIGNMENT_LSB     0
91 #define                 PLAIN_ALIGNMENT_MSB     1
92 #define         RDI_CFG0_PLAIN_FORMAT           10
93 #define         RDI_CFG0_DECODE_FORMAT          12
94 #define         RDI_CFG0_DATA_TYPE              16
95 #define         RDI_CFG0_VIRTUAL_CHANNEL        22
96 #define         RDI_CFG0_DT_ID                  27
97 #define         RDI_CFG0_EARLY_EOF_EN           29
98 #define         RDI_CFG0_PACKING_FORMAT         30
99 #define         RDI_CFG0_ENABLE                 31
100
101 #define CSID_RDI_CFG1(rdi)                      ((IS_LITE ? 0x204 : 0x304)\
102                                                 + 0x100 * (rdi))
103 #define         RDI_CFG1_TIMESTAMP_STB_SEL      0
104
105 #define CSID_RDI_CTRL(rdi)                      ((IS_LITE ? 0x208 : 0x308)\
106                                                 + 0x100 * (rdi))
107 #define         RDI_CTRL_HALT_CMD               0
108 #define                 HALT_CMD_HALT_AT_FRAME_BOUNDARY         0
109 #define                 HALT_CMD_RESUME_AT_FRAME_BOUNDARY       1
110 #define         RDI_CTRL_HALT_MODE              2
111
112 #define CSID_RDI_FRM_DROP_PATTERN(rdi)                  ((IS_LITE ? 0x20C : 0x30C)\
113                                                         + 0x100 * (rdi))
114 #define CSID_RDI_FRM_DROP_PERIOD(rdi)                   ((IS_LITE ? 0x210 : 0x310)\
115                                                         + 0x100 * (rdi))
116 #define CSID_RDI_IRQ_SUBSAMPLE_PATTERN(rdi)             ((IS_LITE ? 0x214 : 0x314)\
117                                                         + 0x100 * (rdi))
118 #define CSID_RDI_IRQ_SUBSAMPLE_PERIOD(rdi)              ((IS_LITE ? 0x218 : 0x318)\
119                                                         + 0x100 * (rdi))
120 #define CSID_RDI_RPP_PIX_DROP_PATTERN(rdi)              ((IS_LITE ? 0x224 : 0x324)\
121                                                         + 0x100 * (rdi))
122 #define CSID_RDI_RPP_PIX_DROP_PERIOD(rdi)               ((IS_LITE ? 0x228 : 0x328)\
123                                                         + 0x100 * (rdi))
124 #define CSID_RDI_RPP_LINE_DROP_PATTERN(rdi)             ((IS_LITE ? 0x22C : 0x32C)\
125                                                         + 0x100 * (rdi))
126 #define CSID_RDI_RPP_LINE_DROP_PERIOD(rdi)              ((IS_LITE ? 0x230 : 0x330)\
127                                                         + 0x100 * (rdi))
128
129 #define CSID_TPG_CTRL           0x600
130 #define         TPG_CTRL_TEST_EN                0
131 #define         TPG_CTRL_FS_PKT_EN              1
132 #define         TPG_CTRL_FE_PKT_EN              2
133 #define         TPG_CTRL_NUM_ACTIVE_LANES       4
134 #define         TPG_CTRL_CYCLES_BETWEEN_PKTS    8
135 #define         TPG_CTRL_NUM_TRAIL_BYTES        20
136
137 #define CSID_TPG_VC_CFG0        0x604
138 #define         TPG_VC_CFG0_VC_NUM                      0
139 #define         TPG_VC_CFG0_NUM_ACTIVE_SLOTS            8
140 #define                 NUM_ACTIVE_SLOTS_0_ENABLED      0
141 #define                 NUM_ACTIVE_SLOTS_0_1_ENABLED    1
142 #define                 NUM_ACTIVE_SLOTS_0_1_2_ENABLED  2
143 #define                 NUM_ACTIVE_SLOTS_0_1_3_ENABLED  3
144 #define         TPG_VC_CFG0_LINE_INTERLEAVING_MODE      10
145 #define                 INTELEAVING_MODE_INTERLEAVED    0
146 #define                 INTELEAVING_MODE_ONE_SHOT       1
147 #define         TPG_VC_CFG0_NUM_FRAMES                  16
148
149 #define CSID_TPG_VC_CFG1        0x608
150 #define         TPG_VC_CFG1_H_BLANKING_COUNT            0
151 #define         TPG_VC_CFG1_V_BLANKING_COUNT            12
152 #define         TPG_VC_CFG1_V_BLANK_FRAME_WIDTH_SEL     24
153
154 #define CSID_TPG_LFSR_SEED      0x60C
155
156 #define CSID_TPG_DT_n_CFG_0(n)  (0x610 + (n) * 0xC)
157 #define         TPG_DT_n_CFG_0_FRAME_HEIGHT     0
158 #define         TPG_DT_n_CFG_0_FRAME_WIDTH      16
159
160 #define CSID_TPG_DT_n_CFG_1(n)  (0x614 + (n) * 0xC)
161 #define         TPG_DT_n_CFG_1_DATA_TYPE        0
162 #define         TPG_DT_n_CFG_1_ECC_XOR_MASK     8
163 #define         TPG_DT_n_CFG_1_CRC_XOR_MASK     16
164
165 #define CSID_TPG_DT_n_CFG_2(n)  (0x618 + (n) * 0xC)
166 #define         TPG_DT_n_CFG_2_PAYLOAD_MODE             0
167 #define         TPG_DT_n_CFG_2_USER_SPECIFIED_PAYLOAD   4
168 #define         TPG_DT_n_CFG_2_ENCODE_FORMAT            16
169
170 #define CSID_TPG_COLOR_BARS_CFG 0x640
171 #define         TPG_COLOR_BARS_CFG_UNICOLOR_BAR_EN      0
172 #define         TPG_COLOR_BARS_CFG_UNICOLOR_BAR_SEL     4
173 #define         TPG_COLOR_BARS_CFG_SPLIT_EN             5
174 #define         TPG_COLOR_BARS_CFG_ROTATE_PERIOD        8
175
176 #define CSID_TPG_COLOR_BOX_CFG  0x644
177 #define         TPG_COLOR_BOX_CFG_MODE          0
178 #define         TPG_COLOR_BOX_PATTERN_SEL       2
179
180 static const struct csid_format csid_formats[] = {
181         {
182                 MEDIA_BUS_FMT_UYVY8_1X16,
183                 DATA_TYPE_YUV422_8BIT,
184                 DECODE_FORMAT_UNCOMPRESSED_8_BIT,
185                 8,
186                 2,
187         },
188         {
189                 MEDIA_BUS_FMT_VYUY8_1X16,
190                 DATA_TYPE_YUV422_8BIT,
191                 DECODE_FORMAT_UNCOMPRESSED_8_BIT,
192                 8,
193                 2,
194         },
195         {
196                 MEDIA_BUS_FMT_YUYV8_1X16,
197                 DATA_TYPE_YUV422_8BIT,
198                 DECODE_FORMAT_UNCOMPRESSED_8_BIT,
199                 8,
200                 2,
201         },
202         {
203                 MEDIA_BUS_FMT_YVYU8_1X16,
204                 DATA_TYPE_YUV422_8BIT,
205                 DECODE_FORMAT_UNCOMPRESSED_8_BIT,
206                 8,
207                 2,
208         },
209         {
210                 MEDIA_BUS_FMT_SBGGR8_1X8,
211                 DATA_TYPE_RAW_8BIT,
212                 DECODE_FORMAT_UNCOMPRESSED_8_BIT,
213                 8,
214                 1,
215         },
216         {
217                 MEDIA_BUS_FMT_SGBRG8_1X8,
218                 DATA_TYPE_RAW_8BIT,
219                 DECODE_FORMAT_UNCOMPRESSED_8_BIT,
220                 8,
221                 1,
222         },
223         {
224                 MEDIA_BUS_FMT_SGRBG8_1X8,
225                 DATA_TYPE_RAW_8BIT,
226                 DECODE_FORMAT_UNCOMPRESSED_8_BIT,
227                 8,
228                 1,
229         },
230         {
231                 MEDIA_BUS_FMT_SRGGB8_1X8,
232                 DATA_TYPE_RAW_8BIT,
233                 DECODE_FORMAT_UNCOMPRESSED_8_BIT,
234                 8,
235                 1,
236         },
237         {
238                 MEDIA_BUS_FMT_SBGGR10_1X10,
239                 DATA_TYPE_RAW_10BIT,
240                 DECODE_FORMAT_UNCOMPRESSED_10_BIT,
241                 10,
242                 1,
243         },
244         {
245                 MEDIA_BUS_FMT_SGBRG10_1X10,
246                 DATA_TYPE_RAW_10BIT,
247                 DECODE_FORMAT_UNCOMPRESSED_10_BIT,
248                 10,
249                 1,
250         },
251         {
252                 MEDIA_BUS_FMT_SGRBG10_1X10,
253                 DATA_TYPE_RAW_10BIT,
254                 DECODE_FORMAT_UNCOMPRESSED_10_BIT,
255                 10,
256                 1,
257         },
258         {
259                 MEDIA_BUS_FMT_SRGGB10_1X10,
260                 DATA_TYPE_RAW_10BIT,
261                 DECODE_FORMAT_UNCOMPRESSED_10_BIT,
262                 10,
263                 1,
264         },
265         {
266                 MEDIA_BUS_FMT_Y8_1X8,
267                 DATA_TYPE_RAW_8BIT,
268                 DECODE_FORMAT_UNCOMPRESSED_8_BIT,
269                 8,
270                 1,
271         },
272         {
273                 MEDIA_BUS_FMT_Y10_1X10,
274                 DATA_TYPE_RAW_10BIT,
275                 DECODE_FORMAT_UNCOMPRESSED_10_BIT,
276                 10,
277                 1,
278         },
279         {
280                 MEDIA_BUS_FMT_SBGGR12_1X12,
281                 DATA_TYPE_RAW_12BIT,
282                 DECODE_FORMAT_UNCOMPRESSED_12_BIT,
283                 12,
284                 1,
285         },
286         {
287                 MEDIA_BUS_FMT_SGBRG12_1X12,
288                 DATA_TYPE_RAW_12BIT,
289                 DECODE_FORMAT_UNCOMPRESSED_12_BIT,
290                 12,
291                 1,
292         },
293         {
294                 MEDIA_BUS_FMT_SGRBG12_1X12,
295                 DATA_TYPE_RAW_12BIT,
296                 DECODE_FORMAT_UNCOMPRESSED_12_BIT,
297                 12,
298                 1,
299         },
300         {
301                 MEDIA_BUS_FMT_SRGGB12_1X12,
302                 DATA_TYPE_RAW_12BIT,
303                 DECODE_FORMAT_UNCOMPRESSED_12_BIT,
304                 12,
305                 1,
306         },
307         {
308                 MEDIA_BUS_FMT_SBGGR14_1X14,
309                 DATA_TYPE_RAW_14BIT,
310                 DECODE_FORMAT_UNCOMPRESSED_14_BIT,
311                 14,
312                 1,
313         },
314         {
315                 MEDIA_BUS_FMT_SGBRG14_1X14,
316                 DATA_TYPE_RAW_14BIT,
317                 DECODE_FORMAT_UNCOMPRESSED_14_BIT,
318                 14,
319                 1,
320         },
321         {
322                 MEDIA_BUS_FMT_SGRBG14_1X14,
323                 DATA_TYPE_RAW_14BIT,
324                 DECODE_FORMAT_UNCOMPRESSED_14_BIT,
325                 14,
326                 1,
327         },
328         {
329                 MEDIA_BUS_FMT_SRGGB14_1X14,
330                 DATA_TYPE_RAW_14BIT,
331                 DECODE_FORMAT_UNCOMPRESSED_14_BIT,
332                 14,
333                 1,
334         },
335 };
336
337 static void __csid_configure_stream(struct csid_device *csid, u8 enable, u8 vc)
338 {
339         struct csid_testgen_config *tg = &csid->testgen;
340         u32 val;
341         u32 phy_sel = 0;
342         u8 lane_cnt = csid->phy.lane_cnt;
343         /* Source pads matching RDI channels on hardware. Pad 1 -> RDI0, Pad 2 -> RDI1, etc. */
344         struct v4l2_mbus_framefmt *input_format = &csid->fmt[MSM_CSID_PAD_FIRST_SRC + vc];
345         const struct csid_format *format = csid_get_fmt_entry(csid->formats, csid->nformats,
346                                                               input_format->code);
347
348         if (!lane_cnt)
349                 lane_cnt = 4;
350
351         if (!tg->enabled)
352                 phy_sel = csid->phy.csiphy_id;
353
354         if (enable) {
355                 /*
356                  * DT_ID is a two bit bitfield that is concatenated with
357                  * the four least significant bits of the five bit VC
358                  * bitfield to generate an internal CID value.
359                  *
360                  * CSID_RDI_CFG0(vc)
361                  * DT_ID : 28:27
362                  * VC    : 26:22
363                  * DT    : 21:16
364                  *
365                  * CID   : VC 3:0 << 2 | DT_ID 1:0
366                  */
367                 u8 dt_id = vc & 0x03;
368
369                 if (tg->enabled) {
370                         /* configure one DT, infinite frames */
371                         val = vc << TPG_VC_CFG0_VC_NUM;
372                         val |= INTELEAVING_MODE_ONE_SHOT << TPG_VC_CFG0_LINE_INTERLEAVING_MODE;
373                         val |= 0 << TPG_VC_CFG0_NUM_FRAMES;
374                         writel_relaxed(val, csid->base + CSID_TPG_VC_CFG0);
375
376                         val = 0x740 << TPG_VC_CFG1_H_BLANKING_COUNT;
377                         val |= 0x3ff << TPG_VC_CFG1_V_BLANKING_COUNT;
378                         writel_relaxed(val, csid->base + CSID_TPG_VC_CFG1);
379
380                         writel_relaxed(0x12345678, csid->base + CSID_TPG_LFSR_SEED);
381
382                         val = (input_format->height & 0x1fff) << TPG_DT_n_CFG_0_FRAME_HEIGHT;
383                         val |= (input_format->width & 0x1fff) << TPG_DT_n_CFG_0_FRAME_WIDTH;
384                         writel_relaxed(val, csid->base + CSID_TPG_DT_n_CFG_0(0));
385
386                         val = format->data_type << TPG_DT_n_CFG_1_DATA_TYPE;
387                         writel_relaxed(val, csid->base + CSID_TPG_DT_n_CFG_1(0));
388
389                         val = (tg->mode - 1) << TPG_DT_n_CFG_2_PAYLOAD_MODE;
390                         val |= 0xBE << TPG_DT_n_CFG_2_USER_SPECIFIED_PAYLOAD;
391                         val |= format->decode_format << TPG_DT_n_CFG_2_ENCODE_FORMAT;
392                         writel_relaxed(val, csid->base + CSID_TPG_DT_n_CFG_2(0));
393
394                         writel_relaxed(0, csid->base + CSID_TPG_COLOR_BARS_CFG);
395
396                         writel_relaxed(0, csid->base + CSID_TPG_COLOR_BOX_CFG);
397                 }
398
399                 val = 1 << RDI_CFG0_BYTE_CNTR_EN;
400                 val |= 1 << RDI_CFG0_FORMAT_MEASURE_EN;
401                 val |= 1 << RDI_CFG0_TIMESTAMP_EN;
402                 /* note: for non-RDI path, this should be format->decode_format */
403                 val |= DECODE_FORMAT_PAYLOAD_ONLY << RDI_CFG0_DECODE_FORMAT;
404                 val |= format->data_type << RDI_CFG0_DATA_TYPE;
405                 val |= vc << RDI_CFG0_VIRTUAL_CHANNEL;
406                 val |= dt_id << RDI_CFG0_DT_ID;
407                 writel_relaxed(val, csid->base + CSID_RDI_CFG0(vc));
408
409                 /* CSID_TIMESTAMP_STB_POST_IRQ */
410                 val = 2 << RDI_CFG1_TIMESTAMP_STB_SEL;
411                 writel_relaxed(val, csid->base + CSID_RDI_CFG1(vc));
412
413                 val = 1;
414                 writel_relaxed(val, csid->base + CSID_RDI_FRM_DROP_PERIOD(vc));
415
416                 val = 0;
417                 writel_relaxed(val, csid->base + CSID_RDI_FRM_DROP_PATTERN(vc));
418
419                 val = 1;
420                 writel_relaxed(val, csid->base + CSID_RDI_IRQ_SUBSAMPLE_PERIOD(vc));
421
422                 val = 0;
423                 writel_relaxed(val, csid->base + CSID_RDI_IRQ_SUBSAMPLE_PATTERN(vc));
424
425                 val = 1;
426                 writel_relaxed(val, csid->base + CSID_RDI_RPP_PIX_DROP_PERIOD(vc));
427
428                 val = 0;
429                 writel_relaxed(val, csid->base + CSID_RDI_RPP_PIX_DROP_PATTERN(vc));
430
431                 val = 1;
432                 writel_relaxed(val, csid->base + CSID_RDI_RPP_LINE_DROP_PERIOD(vc));
433
434                 val = 0;
435                 writel_relaxed(val, csid->base + CSID_RDI_RPP_LINE_DROP_PATTERN(vc));
436
437                 val = 0;
438                 writel_relaxed(val, csid->base + CSID_RDI_CTRL(vc));
439
440                 val = readl_relaxed(csid->base + CSID_RDI_CFG0(vc));
441                 val |=  1 << RDI_CFG0_ENABLE;
442                 writel_relaxed(val, csid->base + CSID_RDI_CFG0(vc));
443         }
444
445         if (tg->enabled) {
446                 val = enable << TPG_CTRL_TEST_EN;
447                 val |= 1 << TPG_CTRL_FS_PKT_EN;
448                 val |= 1 << TPG_CTRL_FE_PKT_EN;
449                 val |= (lane_cnt - 1) << TPG_CTRL_NUM_ACTIVE_LANES;
450                 val |= 0x64 << TPG_CTRL_CYCLES_BETWEEN_PKTS;
451                 val |= 0xA << TPG_CTRL_NUM_TRAIL_BYTES;
452                 writel_relaxed(val, csid->base + CSID_TPG_CTRL);
453         }
454
455         val = (lane_cnt - 1) << CSI2_RX_CFG0_NUM_ACTIVE_LANES;
456         val |= csid->phy.lane_assign << CSI2_RX_CFG0_DL0_INPUT_SEL;
457         val |= phy_sel << CSI2_RX_CFG0_PHY_NUM_SEL;
458         writel_relaxed(val, csid->base + CSID_CSI2_RX_CFG0);
459
460         val = 1 << CSI2_RX_CFG1_PACKET_ECC_CORRECTION_EN;
461         if (vc > 3)
462                 val |= 1 << CSI2_RX_CFG1_VC_MODE;
463         val |= 1 << CSI2_RX_CFG1_MISR_EN;
464         writel_relaxed(val, csid->base + CSID_CSI2_RX_CFG1);
465
466         if (enable)
467                 val = HALT_CMD_RESUME_AT_FRAME_BOUNDARY << RDI_CTRL_HALT_CMD;
468         else
469                 val = HALT_CMD_HALT_AT_FRAME_BOUNDARY << RDI_CTRL_HALT_CMD;
470         writel_relaxed(val, csid->base + CSID_RDI_CTRL(vc));
471 }
472
473 static void csid_configure_stream(struct csid_device *csid, u8 enable)
474 {
475         u8 i;
476         /* Loop through all enabled VCs and configure stream for each */
477         for (i = 0; i < MSM_CSID_MAX_SRC_STREAMS; i++)
478                 if (csid->phy.en_vc & BIT(i))
479                         __csid_configure_stream(csid, enable, i);
480 }
481
482 static int csid_configure_testgen_pattern(struct csid_device *csid, s32 val)
483 {
484         if (val > 0 && val <= csid->testgen.nmodes)
485                 csid->testgen.mode = val;
486
487         return 0;
488 }
489
490 /*
491  * csid_hw_version - CSID hardware version query
492  * @csid: CSID device
493  *
494  * Return HW version or error
495  */
496 static u32 csid_hw_version(struct csid_device *csid)
497 {
498         u32 hw_version;
499         u32 hw_gen;
500         u32 hw_rev;
501         u32 hw_step;
502
503         hw_version = readl_relaxed(csid->base + CSID_HW_VERSION);
504         hw_gen = (hw_version >> HW_VERSION_GENERATION) & 0xF;
505         hw_rev = (hw_version >> HW_VERSION_REVISION) & 0xFFF;
506         hw_step = (hw_version >> HW_VERSION_STEPPING) & 0xFFFF;
507         dev_dbg(csid->camss->dev, "CSID HW Version = %u.%u.%u\n",
508                 hw_gen, hw_rev, hw_step);
509
510         return hw_version;
511 }
512
513 /*
514  * csid_isr - CSID module interrupt service routine
515  * @irq: Interrupt line
516  * @dev: CSID device
517  *
518  * Return IRQ_HANDLED on success
519  */
520 static irqreturn_t csid_isr(int irq, void *dev)
521 {
522         struct csid_device *csid = dev;
523         u32 val;
524         u8 reset_done;
525         int i;
526
527         val = readl_relaxed(csid->base + CSID_TOP_IRQ_STATUS);
528         writel_relaxed(val, csid->base + CSID_TOP_IRQ_CLEAR);
529         reset_done = val & BIT(TOP_IRQ_STATUS_RESET_DONE);
530
531         val = readl_relaxed(csid->base + CSID_CSI2_RX_IRQ_STATUS);
532         writel_relaxed(val, csid->base + CSID_CSI2_RX_IRQ_CLEAR);
533
534         /* Read and clear IRQ status for each enabled RDI channel */
535         for (i = 0; i < MSM_CSID_MAX_SRC_STREAMS; i++)
536                 if (csid->phy.en_vc & BIT(i)) {
537                         val = readl_relaxed(csid->base + CSID_CSI2_RDIN_IRQ_STATUS(i));
538                         writel_relaxed(val, csid->base + CSID_CSI2_RDIN_IRQ_CLEAR(i));
539                 }
540
541         val = 1 << IRQ_CMD_CLEAR;
542         writel_relaxed(val, csid->base + CSID_IRQ_CMD);
543
544         if (reset_done)
545                 complete(&csid->reset_complete);
546
547         return IRQ_HANDLED;
548 }
549
550 /*
551  * csid_reset - Trigger reset on CSID module and wait to complete
552  * @csid: CSID device
553  *
554  * Return 0 on success or a negative error code otherwise
555  */
556 static int csid_reset(struct csid_device *csid)
557 {
558         unsigned long time;
559         u32 val;
560
561         reinit_completion(&csid->reset_complete);
562
563         writel_relaxed(1, csid->base + CSID_TOP_IRQ_CLEAR);
564         writel_relaxed(1, csid->base + CSID_IRQ_CMD);
565         writel_relaxed(1, csid->base + CSID_TOP_IRQ_MASK);
566         writel_relaxed(1, csid->base + CSID_IRQ_CMD);
567
568         /* preserve registers */
569         val = 0x1e << RST_STROBES;
570         writel_relaxed(val, csid->base + CSID_RST_STROBES);
571
572         time = wait_for_completion_timeout(&csid->reset_complete,
573                                            msecs_to_jiffies(CSID_RESET_TIMEOUT_MS));
574         if (!time) {
575                 dev_err(csid->camss->dev, "CSID reset timeout\n");
576                 return -EIO;
577         }
578
579         return 0;
580 }
581
582 static u32 csid_src_pad_code(struct csid_device *csid, u32 sink_code,
583                              unsigned int match_format_idx, u32 match_code)
584 {
585         switch (sink_code) {
586         case MEDIA_BUS_FMT_SBGGR10_1X10:
587         {
588                 u32 src_code[] = {
589                         MEDIA_BUS_FMT_SBGGR10_1X10,
590                         MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_LE,
591                 };
592
593                 return csid_find_code(src_code, ARRAY_SIZE(src_code),
594                                       match_format_idx, match_code);
595         }
596         case MEDIA_BUS_FMT_Y10_1X10:
597         {
598                 u32 src_code[] = {
599                         MEDIA_BUS_FMT_Y10_1X10,
600                         MEDIA_BUS_FMT_Y10_2X8_PADHI_LE,
601                 };
602
603                 return csid_find_code(src_code, ARRAY_SIZE(src_code),
604                                       match_format_idx, match_code);
605         }
606         default:
607                 if (match_format_idx > 0)
608                         return 0;
609
610                 return sink_code;
611         }
612 }
613
614 static void csid_subdev_init(struct csid_device *csid)
615 {
616         csid->formats = csid_formats;
617         csid->nformats = ARRAY_SIZE(csid_formats);
618         csid->testgen.modes = csid_testgen_modes;
619         csid->testgen.nmodes = CSID_PAYLOAD_MODE_NUM_SUPPORTED_GEN2;
620 }
621
622 const struct csid_hw_ops csid_ops_gen2 = {
623         .configure_stream = csid_configure_stream,
624         .configure_testgen_pattern = csid_configure_testgen_pattern,
625         .hw_version = csid_hw_version,
626         .isr = csid_isr,
627         .reset = csid_reset,
628         .src_pad_code = csid_src_pad_code,
629         .subdev_init = csid_subdev_init,
630 };