1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Qualcomm MSM Camera Subsystem - CSID (CSI Decoder) Module 4 * 5 * Copyright (c) 2024 Qualcomm Technologies, Inc. 6 */ 7 #include <linux/completion.h> 8 #include <linux/delay.h> 9 #include <linux/interrupt.h> 10 #include <linux/io.h> 11 #include <linux/kernel.h> 12 #include <linux/of.h> 13 14 #include "camss.h" 15 #include "camss-csid.h" 16 #include "camss-csid-gen3.h" 17 18 #define CSID_IO_PATH_CFG0(csid) (0x4 * (csid)) 19 #define OUTPUT_IFE_EN 0x100 20 #define INTERNAL_CSID 1 21 22 #define CSID_RST_CFG 0xC 23 #define RST_MODE BIT(0) 24 #define RST_LOCATION BIT(4) 25 26 #define CSID_RST_CMD 0x10 27 #define SELECT_HW_RST BIT(0) 28 #define SELECT_IRQ_RST BIT(2) 29 30 #define CSID_IRQ_CMD 0x14 31 #define IRQ_CMD_CLEAR BIT(0) 32 33 #define CSID_RUP_AUP_CMD 0x18 34 #define CSID_RUP_AUP_RDI(rdi) ((BIT(4) | BIT(20)) << (rdi)) 35 36 #define CSID_TOP_IRQ_STATUS 0x7C 37 #define TOP_IRQ_STATUS_RESET_DONE BIT(0) 38 39 #define CSID_TOP_IRQ_MASK 0x80 40 #define CSID_TOP_IRQ_CLEAR 0x84 41 #define CSID_TOP_IRQ_SET 0x88 42 43 #define CSID_CSI2_RX_IRQ_STATUS 0x9C 44 #define CSID_CSI2_RX_IRQ_MASK 0xA0 45 #define CSID_CSI2_RX_IRQ_CLEAR 0xA4 46 #define CSID_CSI2_RX_IRQ_SET 0xA8 47 48 #define IS_CSID_690(csid) ((csid->camss->res->version == CAMSS_8775P) \ 49 || (csid->camss->res->version == CAMSS_8300)) 50 #define CSID_BUF_DONE_IRQ_STATUS 0x8C 51 #define BUF_DONE_IRQ_STATUS_RDI_OFFSET (csid_is_lite(csid) ?\ 52 1 : (IS_CSID_690(csid) ?\ 53 13 : 14)) 54 #define CSID_BUF_DONE_IRQ_MASK 0x90 55 #define CSID_BUF_DONE_IRQ_CLEAR 0x94 56 #define CSID_BUF_DONE_IRQ_SET 0x98 57 58 #define CSID_CSI2_RDIN_IRQ_STATUS(rdi) (0xEC + 0x10 * (rdi)) 59 #define RUP_DONE_IRQ_STATUS BIT(23) 60 61 #define CSID_CSI2_RDIN_IRQ_CLEAR(rdi) (0xF4 + 0x10 * (rdi)) 62 #define CSID_CSI2_RDIN_IRQ_SET(rdi) (0xF8 + 0x10 * (rdi)) 63 64 #define CSID_CSI2_RX_CFG0 0x200 65 #define CSI2_RX_CFG0_NUM_ACTIVE_LANES 0 66 #define CSI2_RX_CFG0_VC_MODE 3 67 #define CSI2_RX_CFG0_DL0_INPUT_SEL 4 68 #define CSI2_RX_CFG0_PHY_NUM_SEL 20 69 70 #define CSID_CSI2_RX_CFG1 0x204 71 #define CSI2_RX_CFG1_ECC_CORRECTION_EN BIT(0) 72 #define CSI2_RX_CFG1_VC_MODE BIT(2) 73 74 #define CSID_RDI_CFG0(rdi) (csid_is_lite(csid) && IS_CSID_690(csid) ?\ 75 (0x300 + 0x100 * (rdi)) :\ 76 (0x500 + 0x100 * (rdi))) 77 #define RDI_CFG0_TIMESTAMP_EN BIT(6) 78 #define RDI_CFG0_TIMESTAMP_STB_SEL BIT(8) 79 #define RDI_CFG0_DECODE_FORMAT 12 80 #define RDI_CFG0_DT 16 81 #define RDI_CFG0_VC 22 82 #define RDI_CFG0_DT_ID 27 83 #define RDI_CFG0_EN BIT(31) 84 85 #define CSID_RDI_CTRL(rdi) (csid_is_lite(csid) && IS_CSID_690(csid) ?\ 86 (0x304 + 0x100 * (rdi)) :\ 87 (0x504 + 0x100 * (rdi))) 88 #define RDI_CTRL_START_CMD BIT(0) 89 90 #define CSID_RDI_CFG1(rdi) (csid_is_lite(csid) && IS_CSID_690(csid) ?\ 91 (0x310 + 0x100 * (rdi)) :\ 92 (0x510 + 0x100 * (rdi))) 93 #define RDI_CFG1_DROP_H_EN BIT(5) 94 #define RDI_CFG1_DROP_V_EN BIT(6) 95 #define RDI_CFG1_CROP_H_EN BIT(7) 96 #define RDI_CFG1_CROP_V_EN BIT(8) 97 #define RDI_CFG1_PIX_STORE BIT(10) 98 #define RDI_CFG1_PACKING_FORMAT_MIPI BIT(15) 99 100 #define CSID_RDI_IRQ_SUBSAMPLE_PATTERN(rdi) (csid_is_lite(csid) && IS_CSID_690(csid) ?\ 101 (0x348 + 0x100 * (rdi)) :\ 102 (0x548 + 0x100 * (rdi))) 103 #define CSID_RDI_IRQ_SUBSAMPLE_PERIOD(rdi) (csid_is_lite(csid) && IS_CSID_690(csid) ?\ 104 (0x34C + 0x100 * (rdi)) :\ 105 (0x54C + 0x100 * (rdi))) 106 #define CSI2_RX_CFG0_PHY_SEL_BASE_IDX 1 107 108 static void __csid_configure_rx(struct csid_device *csid, 109 struct csid_phy_config *phy, int vc) 110 { 111 int val; 112 113 val = (phy->lane_cnt - 1) << CSI2_RX_CFG0_NUM_ACTIVE_LANES; 114 val |= phy->lane_assign << CSI2_RX_CFG0_DL0_INPUT_SEL; 115 val |= (phy->csiphy_id + CSI2_RX_CFG0_PHY_SEL_BASE_IDX) << CSI2_RX_CFG0_PHY_NUM_SEL; 116 117 writel(val, csid->base + CSID_CSI2_RX_CFG0); 118 119 val = CSI2_RX_CFG1_ECC_CORRECTION_EN; 120 if (vc > 3) 121 val |= CSI2_RX_CFG1_VC_MODE; 122 123 writel(val, csid->base + CSID_CSI2_RX_CFG1); 124 } 125 126 static void __csid_ctrl_rdi(struct csid_device *csid, int enable, u8 rdi) 127 { 128 int val = 0; 129 130 if (enable) 131 val = RDI_CTRL_START_CMD; 132 133 writel(val, csid->base + CSID_RDI_CTRL(rdi)); 134 } 135 136 static void __csid_configure_wrapper(struct csid_device *csid) 137 { 138 u32 val; 139 140 /* csid lite doesn't need to configure top register */ 141 if (csid->res->is_lite) 142 return; 143 144 val = OUTPUT_IFE_EN | INTERNAL_CSID; 145 writel(val, csid->camss->csid_wrapper_base + CSID_IO_PATH_CFG0(csid->id)); 146 } 147 148 static void __csid_configure_rdi_stream(struct csid_device *csid, u8 enable, u8 vc) 149 { 150 u32 val; 151 u8 lane_cnt = csid->phy.lane_cnt; 152 /* Source pads matching RDI channels on hardware. Pad 1 -> RDI0, Pad 2 -> RDI1, etc. */ 153 struct v4l2_mbus_framefmt *input_format = &csid->fmt[MSM_CSID_PAD_FIRST_SRC + vc]; 154 const struct csid_format_info *format = csid_get_fmt_entry(csid->res->formats->formats, 155 csid->res->formats->nformats, 156 input_format->code); 157 158 if (!lane_cnt) 159 lane_cnt = 4; 160 161 /* 162 * DT_ID is a two bit bitfield that is concatenated with 163 * the four least significant bits of the five bit VC 164 * bitfield to generate an internal CID value. 165 * 166 * CSID_RDI_CFG0(vc) 167 * DT_ID : 28:27 168 * VC : 26:22 169 * DT : 21:16 170 * 171 * CID : VC 3:0 << 2 | DT_ID 1:0 172 */ 173 u8 dt_id = vc & 0x03; 174 175 val = RDI_CFG0_TIMESTAMP_EN; 176 val |= RDI_CFG0_TIMESTAMP_STB_SEL; 177 /* note: for non-RDI path, this should be format->decode_format */ 178 val |= DECODE_FORMAT_PAYLOAD_ONLY << RDI_CFG0_DECODE_FORMAT; 179 val |= vc << RDI_CFG0_VC; 180 val |= format->data_type << RDI_CFG0_DT; 181 val |= dt_id << RDI_CFG0_DT_ID; 182 183 writel(val, csid->base + CSID_RDI_CFG0(vc)); 184 185 val = RDI_CFG1_PACKING_FORMAT_MIPI; 186 val |= RDI_CFG1_PIX_STORE; 187 val |= RDI_CFG1_DROP_H_EN; 188 val |= RDI_CFG1_DROP_V_EN; 189 val |= RDI_CFG1_CROP_H_EN; 190 val |= RDI_CFG1_CROP_V_EN; 191 192 writel(val, csid->base + CSID_RDI_CFG1(vc)); 193 194 val = 0; 195 writel(val, csid->base + CSID_RDI_IRQ_SUBSAMPLE_PERIOD(vc)); 196 197 val = 1; 198 writel(val, csid->base + CSID_RDI_IRQ_SUBSAMPLE_PATTERN(vc)); 199 200 val = 0; 201 writel(val, csid->base + CSID_RDI_CTRL(vc)); 202 203 val = readl(csid->base + CSID_RDI_CFG0(vc)); 204 205 if (enable) 206 val |= RDI_CFG0_EN; 207 writel(val, csid->base + CSID_RDI_CFG0(vc)); 208 } 209 210 static void csid_configure_stream(struct csid_device *csid, u8 enable) 211 { 212 u8 i; 213 214 __csid_configure_wrapper(csid); 215 216 /* Loop through all enabled VCs and configure stream for each */ 217 for (i = 0; i < MSM_CSID_MAX_SRC_STREAMS; i++) 218 if (csid->phy.en_vc & BIT(i)) { 219 __csid_configure_rdi_stream(csid, enable, i); 220 __csid_configure_rx(csid, &csid->phy, i); 221 __csid_ctrl_rdi(csid, enable, i); 222 } 223 } 224 225 static int csid_configure_testgen_pattern(struct csid_device *csid, s32 val) 226 { 227 return 0; 228 } 229 230 static void csid_subdev_reg_update(struct csid_device *csid, int port_id, bool clear) 231 { 232 if (clear) { 233 csid->reg_update &= ~CSID_RUP_AUP_RDI(port_id); 234 } else { 235 csid->reg_update |= CSID_RUP_AUP_RDI(port_id); 236 writel(csid->reg_update, csid->base + CSID_RUP_AUP_CMD); 237 } 238 } 239 240 /* 241 * csid_isr - CSID module interrupt service routine 242 * @irq: Interrupt line 243 * @dev: CSID device 244 * 245 * Return IRQ_HANDLED on success 246 */ 247 static irqreturn_t csid_isr(int irq, void *dev) 248 { 249 struct csid_device *csid = dev; 250 u32 val, buf_done_val; 251 u8 reset_done; 252 int i; 253 254 val = readl(csid->base + CSID_TOP_IRQ_STATUS); 255 writel(val, csid->base + CSID_TOP_IRQ_CLEAR); 256 reset_done = val & TOP_IRQ_STATUS_RESET_DONE; 257 258 val = readl(csid->base + CSID_CSI2_RX_IRQ_STATUS); 259 writel(val, csid->base + CSID_CSI2_RX_IRQ_CLEAR); 260 261 buf_done_val = readl(csid->base + CSID_BUF_DONE_IRQ_STATUS); 262 writel(buf_done_val, csid->base + CSID_BUF_DONE_IRQ_CLEAR); 263 264 /* Read and clear IRQ status for each enabled RDI channel */ 265 for (i = 0; i < MSM_CSID_MAX_SRC_STREAMS; i++) 266 if (csid->phy.en_vc & BIT(i)) { 267 val = readl(csid->base + CSID_CSI2_RDIN_IRQ_STATUS(i)); 268 writel(val, csid->base + CSID_CSI2_RDIN_IRQ_CLEAR(i)); 269 270 if (val & RUP_DONE_IRQ_STATUS) 271 /* clear the reg update bit */ 272 csid_subdev_reg_update(csid, i, true); 273 274 if (buf_done_val & BIT(BUF_DONE_IRQ_STATUS_RDI_OFFSET + i)) { 275 /* 276 * For Titan Gen3, bus done and RUP IRQ have been moved to 277 * CSID from VFE. Once CSID received bus done, need notify 278 * VFE of this event. Trigger VFE to handle bus done process. 279 */ 280 camss_buf_done(csid->camss, csid->id, i); 281 } 282 } 283 284 val = IRQ_CMD_CLEAR; 285 writel(val, csid->base + CSID_IRQ_CMD); 286 287 if (reset_done) 288 complete(&csid->reset_complete); 289 290 return IRQ_HANDLED; 291 } 292 293 /* 294 * csid_reset - Trigger reset on CSID module and wait to complete 295 * @csid: CSID device 296 * 297 * Return 0 on success or a negative error code otherwise 298 */ 299 static int csid_reset(struct csid_device *csid) 300 { 301 unsigned long time; 302 u32 val; 303 int i; 304 305 reinit_completion(&csid->reset_complete); 306 307 writel(1, csid->base + CSID_TOP_IRQ_CLEAR); 308 writel(1, csid->base + CSID_IRQ_CMD); 309 writel(1, csid->base + CSID_TOP_IRQ_MASK); 310 311 for (i = 0; i < MSM_CSID_MAX_SRC_STREAMS; i++) 312 if (csid->phy.en_vc & BIT(i)) { 313 writel(BIT(BUF_DONE_IRQ_STATUS_RDI_OFFSET + i), 314 csid->base + CSID_BUF_DONE_IRQ_CLEAR); 315 writel(IRQ_CMD_CLEAR, csid->base + CSID_IRQ_CMD); 316 writel(BIT(BUF_DONE_IRQ_STATUS_RDI_OFFSET + i), 317 csid->base + CSID_BUF_DONE_IRQ_MASK); 318 } 319 320 /* preserve registers */ 321 val = RST_LOCATION | RST_MODE; 322 writel(val, csid->base + CSID_RST_CFG); 323 324 val = SELECT_HW_RST | SELECT_IRQ_RST; 325 writel(val, csid->base + CSID_RST_CMD); 326 327 time = wait_for_completion_timeout(&csid->reset_complete, 328 msecs_to_jiffies(CSID_RESET_TIMEOUT_MS)); 329 if (!time) { 330 dev_err(csid->camss->dev, "CSID reset timeout\n"); 331 return -EIO; 332 } 333 334 return 0; 335 } 336 337 static void csid_subdev_init(struct csid_device *csid) 338 { 339 csid->testgen.nmodes = CSID_PAYLOAD_MODE_DISABLED; 340 } 341 342 const struct csid_hw_ops csid_ops_gen3 = { 343 .configure_stream = csid_configure_stream, 344 .configure_testgen_pattern = csid_configure_testgen_pattern, 345 .hw_version = csid_hw_version, 346 .isr = csid_isr, 347 .reset = csid_reset, 348 .src_pad_code = csid_src_pad_code, 349 .subdev_init = csid_subdev_init, 350 .reg_update = csid_subdev_reg_update, 351 }; 352