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