Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

media: qcom: camss: Split testgen, RDI and RX for CSID 170

Split the RAW interface (RDI), the CSID receiver (RX)
and test pattern generator (testgen), configurations
for CSID on Titan 170

Signed-off-by: Milen Mitkov <quic_mmitkov@quicinc.com>
Signed-off-by: Gjorgji Rosikopulos <quic_grosikop@quicinc.com>
Reviewed-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
Tested-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> # sc8280xp/sm8250/sdm845/apq8016
Acked-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
[hverkuil: folded https://lore.kernel.org/linux-media/20240626074730.85-1-quic_grosikop@quicinc.com/ into this patch]

authored by

Milen Mitkov and committed by
Hans Verkuil
729fc005 ad458cb9

+138 -117
+138 -117
drivers/media/platform/qcom/camss/camss-csid-gen2.c
··· 176 176 #define TPG_COLOR_BOX_CFG_MODE 0 177 177 #define TPG_COLOR_BOX_PATTERN_SEL 2 178 178 179 - static void __csid_configure_stream(struct csid_device *csid, u8 enable, u8 vc) 179 + static void __csid_configure_rx(struct csid_device *csid, 180 + struct csid_phy_config *phy, int vc) 180 181 { 181 - struct csid_testgen_config *tg = &csid->testgen; 182 - u32 val; 183 - u32 phy_sel = 0; 184 182 u8 lane_cnt = csid->phy.lane_cnt; 185 - /* Source pads matching RDI channels on hardware. Pad 1 -> RDI0, Pad 2 -> RDI1, etc. */ 186 - struct v4l2_mbus_framefmt *input_format = &csid->fmt[MSM_CSID_PAD_FIRST_SRC + vc]; 187 - const struct csid_format_info *format = csid_get_fmt_entry(csid->res->formats->formats, 188 - csid->res->formats->nformats, 189 - input_format->code); 183 + int val; 190 184 191 185 if (!lane_cnt) 192 186 lane_cnt = 4; 193 187 194 - if (!tg->enabled) 195 - phy_sel = csid->phy.csiphy_id; 196 - 197 - if (enable) { 198 - /* 199 - * DT_ID is a two bit bitfield that is concatenated with 200 - * the four least significant bits of the five bit VC 201 - * bitfield to generate an internal CID value. 202 - * 203 - * CSID_RDI_CFG0(vc) 204 - * DT_ID : 28:27 205 - * VC : 26:22 206 - * DT : 21:16 207 - * 208 - * CID : VC 3:0 << 2 | DT_ID 1:0 209 - */ 210 - u8 dt_id = vc & 0x03; 211 - 212 - if (tg->enabled) { 213 - /* configure one DT, infinite frames */ 214 - val = vc << TPG_VC_CFG0_VC_NUM; 215 - val |= INTELEAVING_MODE_ONE_SHOT << TPG_VC_CFG0_LINE_INTERLEAVING_MODE; 216 - val |= 0 << TPG_VC_CFG0_NUM_FRAMES; 217 - writel_relaxed(val, csid->base + CSID_TPG_VC_CFG0); 218 - 219 - val = 0x740 << TPG_VC_CFG1_H_BLANKING_COUNT; 220 - val |= 0x3ff << TPG_VC_CFG1_V_BLANKING_COUNT; 221 - writel_relaxed(val, csid->base + CSID_TPG_VC_CFG1); 222 - 223 - writel_relaxed(0x12345678, csid->base + CSID_TPG_LFSR_SEED); 224 - 225 - val = (input_format->height & 0x1fff) << TPG_DT_n_CFG_0_FRAME_HEIGHT; 226 - val |= (input_format->width & 0x1fff) << TPG_DT_n_CFG_0_FRAME_WIDTH; 227 - writel_relaxed(val, csid->base + CSID_TPG_DT_n_CFG_0(0)); 228 - 229 - val = format->data_type << TPG_DT_n_CFG_1_DATA_TYPE; 230 - writel_relaxed(val, csid->base + CSID_TPG_DT_n_CFG_1(0)); 231 - 232 - val = (tg->mode - 1) << TPG_DT_n_CFG_2_PAYLOAD_MODE; 233 - val |= 0xBE << TPG_DT_n_CFG_2_USER_SPECIFIED_PAYLOAD; 234 - val |= format->decode_format << TPG_DT_n_CFG_2_ENCODE_FORMAT; 235 - writel_relaxed(val, csid->base + CSID_TPG_DT_n_CFG_2(0)); 236 - 237 - writel_relaxed(0, csid->base + CSID_TPG_COLOR_BARS_CFG); 238 - 239 - writel_relaxed(0, csid->base + CSID_TPG_COLOR_BOX_CFG); 240 - } 241 - 242 - val = 1 << RDI_CFG0_BYTE_CNTR_EN; 243 - val |= 1 << RDI_CFG0_FORMAT_MEASURE_EN; 244 - val |= 1 << RDI_CFG0_TIMESTAMP_EN; 245 - /* note: for non-RDI path, this should be format->decode_format */ 246 - val |= DECODE_FORMAT_PAYLOAD_ONLY << RDI_CFG0_DECODE_FORMAT; 247 - val |= format->data_type << RDI_CFG0_DATA_TYPE; 248 - val |= vc << RDI_CFG0_VIRTUAL_CHANNEL; 249 - val |= dt_id << RDI_CFG0_DT_ID; 250 - writel_relaxed(val, csid->base + CSID_RDI_CFG0(vc)); 251 - 252 - /* CSID_TIMESTAMP_STB_POST_IRQ */ 253 - val = 2 << RDI_CFG1_TIMESTAMP_STB_SEL; 254 - writel_relaxed(val, csid->base + CSID_RDI_CFG1(vc)); 255 - 256 - val = 1; 257 - writel_relaxed(val, csid->base + CSID_RDI_FRM_DROP_PERIOD(vc)); 258 - 259 - val = 0; 260 - writel_relaxed(val, csid->base + CSID_RDI_FRM_DROP_PATTERN(vc)); 261 - 262 - val = 1; 263 - writel_relaxed(val, csid->base + CSID_RDI_IRQ_SUBSAMPLE_PERIOD(vc)); 264 - 265 - val = 0; 266 - writel_relaxed(val, csid->base + CSID_RDI_IRQ_SUBSAMPLE_PATTERN(vc)); 267 - 268 - val = 1; 269 - writel_relaxed(val, csid->base + CSID_RDI_RPP_PIX_DROP_PERIOD(vc)); 270 - 271 - val = 0; 272 - writel_relaxed(val, csid->base + CSID_RDI_RPP_PIX_DROP_PATTERN(vc)); 273 - 274 - val = 1; 275 - writel_relaxed(val, csid->base + CSID_RDI_RPP_LINE_DROP_PERIOD(vc)); 276 - 277 - val = 0; 278 - writel_relaxed(val, csid->base + CSID_RDI_RPP_LINE_DROP_PATTERN(vc)); 279 - 280 - val = 0; 281 - writel_relaxed(val, csid->base + CSID_RDI_CTRL(vc)); 282 - 283 - val = readl_relaxed(csid->base + CSID_RDI_CFG0(vc)); 284 - val |= 1 << RDI_CFG0_ENABLE; 285 - writel_relaxed(val, csid->base + CSID_RDI_CFG0(vc)); 286 - } 287 - 288 - if (tg->enabled) { 289 - val = enable << TPG_CTRL_TEST_EN; 290 - val |= 1 << TPG_CTRL_FS_PKT_EN; 291 - val |= 1 << TPG_CTRL_FE_PKT_EN; 292 - val |= (lane_cnt - 1) << TPG_CTRL_NUM_ACTIVE_LANES; 293 - val |= 0x64 << TPG_CTRL_CYCLES_BETWEEN_PKTS; 294 - val |= 0xA << TPG_CTRL_NUM_TRAIL_BYTES; 295 - writel_relaxed(val, csid->base + CSID_TPG_CTRL); 296 - } 297 - 298 188 val = (lane_cnt - 1) << CSI2_RX_CFG0_NUM_ACTIVE_LANES; 299 - val |= csid->phy.lane_assign << CSI2_RX_CFG0_DL0_INPUT_SEL; 300 - val |= phy_sel << CSI2_RX_CFG0_PHY_NUM_SEL; 189 + val |= phy->lane_assign << CSI2_RX_CFG0_DL0_INPUT_SEL; 190 + val |= phy->csiphy_id << CSI2_RX_CFG0_PHY_NUM_SEL; 301 191 writel_relaxed(val, csid->base + CSID_CSI2_RX_CFG0); 302 192 303 193 val = 1 << CSI2_RX_CFG1_PACKET_ECC_CORRECTION_EN; ··· 195 305 val |= 1 << CSI2_RX_CFG1_VC_MODE; 196 306 val |= 1 << CSI2_RX_CFG1_MISR_EN; 197 307 writel_relaxed(val, csid->base + CSID_CSI2_RX_CFG1); 308 + } 309 + 310 + static void __csid_ctrl_rdi(struct csid_device *csid, int enable, u8 rdi) 311 + { 312 + int val; 198 313 199 314 if (enable) 200 315 val = HALT_CMD_RESUME_AT_FRAME_BOUNDARY << RDI_CTRL_HALT_CMD; 201 316 else 202 317 val = HALT_CMD_HALT_AT_FRAME_BOUNDARY << RDI_CTRL_HALT_CMD; 318 + writel_relaxed(val, csid->base + CSID_RDI_CTRL(rdi)); 319 + } 320 + 321 + static void __csid_configure_testgen(struct csid_device *csid, u8 enable, u8 vc) 322 + { 323 + struct csid_testgen_config *tg = &csid->testgen; 324 + struct v4l2_mbus_framefmt *input_format = &csid->fmt[MSM_CSID_PAD_FIRST_SRC + vc]; 325 + const struct csid_format_info *format = csid_get_fmt_entry(csid->res->formats->formats, 326 + csid->res->formats->nformats, 327 + input_format->code); 328 + u8 lane_cnt = csid->phy.lane_cnt; 329 + u32 val; 330 + 331 + if (!lane_cnt) 332 + lane_cnt = 4; 333 + 334 + /* configure one DT, infinite frames */ 335 + val = vc << TPG_VC_CFG0_VC_NUM; 336 + val |= INTELEAVING_MODE_ONE_SHOT << TPG_VC_CFG0_LINE_INTERLEAVING_MODE; 337 + val |= 0 << TPG_VC_CFG0_NUM_FRAMES; 338 + writel_relaxed(val, csid->base + CSID_TPG_VC_CFG0); 339 + 340 + val = 0x740 << TPG_VC_CFG1_H_BLANKING_COUNT; 341 + val |= 0x3ff << TPG_VC_CFG1_V_BLANKING_COUNT; 342 + writel_relaxed(val, csid->base + CSID_TPG_VC_CFG1); 343 + 344 + writel_relaxed(0x12345678, csid->base + CSID_TPG_LFSR_SEED); 345 + 346 + val = (input_format->height & 0x1fff) << TPG_DT_n_CFG_0_FRAME_HEIGHT; 347 + val |= (input_format->width & 0x1fff) << TPG_DT_n_CFG_0_FRAME_WIDTH; 348 + writel_relaxed(val, csid->base + CSID_TPG_DT_n_CFG_0(0)); 349 + 350 + val = format->data_type << TPG_DT_n_CFG_1_DATA_TYPE; 351 + writel_relaxed(val, csid->base + CSID_TPG_DT_n_CFG_1(0)); 352 + 353 + val = (tg->mode - 1) << TPG_DT_n_CFG_2_PAYLOAD_MODE; 354 + val |= 0xBE << TPG_DT_n_CFG_2_USER_SPECIFIED_PAYLOAD; 355 + val |= format->decode_format << TPG_DT_n_CFG_2_ENCODE_FORMAT; 356 + writel_relaxed(val, csid->base + CSID_TPG_DT_n_CFG_2(0)); 357 + 358 + writel_relaxed(0, csid->base + CSID_TPG_COLOR_BARS_CFG); 359 + 360 + writel_relaxed(0, csid->base + CSID_TPG_COLOR_BOX_CFG); 361 + 362 + val = enable << TPG_CTRL_TEST_EN; 363 + val |= 1 << TPG_CTRL_FS_PKT_EN; 364 + val |= 1 << TPG_CTRL_FE_PKT_EN; 365 + val |= (lane_cnt - 1) << TPG_CTRL_NUM_ACTIVE_LANES; 366 + val |= 0x64 << TPG_CTRL_CYCLES_BETWEEN_PKTS; 367 + val |= 0xA << TPG_CTRL_NUM_TRAIL_BYTES; 368 + writel_relaxed(val, csid->base + CSID_TPG_CTRL); 369 + } 370 + 371 + static void __csid_configure_rdi_stream(struct csid_device *csid, u8 enable, u8 vc) 372 + { 373 + /* Source pads matching RDI channels on hardware. Pad 1 -> RDI0, Pad 2 -> RDI1, etc. */ 374 + struct v4l2_mbus_framefmt *input_format = &csid->fmt[MSM_CSID_PAD_FIRST_SRC + vc]; 375 + const struct csid_format_info *format = csid_get_fmt_entry(csid->res->formats->formats, 376 + csid->res->formats->nformats, 377 + input_format->code); 378 + u32 val; 379 + 380 + /* 381 + * DT_ID is a two bit bitfield that is concatenated with 382 + * the four least significant bits of the five bit VC 383 + * bitfield to generate an internal CID value. 384 + * 385 + * CSID_RDI_CFG0(vc) 386 + * DT_ID : 28:27 387 + * VC : 26:22 388 + * DT : 21:16 389 + * 390 + * CID : VC 3:0 << 2 | DT_ID 1:0 391 + */ 392 + u8 dt_id = vc & 0x03; 393 + 394 + val = 1 << RDI_CFG0_BYTE_CNTR_EN; 395 + val |= 1 << RDI_CFG0_FORMAT_MEASURE_EN; 396 + val |= 1 << RDI_CFG0_TIMESTAMP_EN; 397 + /* note: for non-RDI path, this should be format->decode_format */ 398 + val |= DECODE_FORMAT_PAYLOAD_ONLY << RDI_CFG0_DECODE_FORMAT; 399 + val |= format->data_type << RDI_CFG0_DATA_TYPE; 400 + val |= vc << RDI_CFG0_VIRTUAL_CHANNEL; 401 + val |= dt_id << RDI_CFG0_DT_ID; 402 + writel_relaxed(val, csid->base + CSID_RDI_CFG0(vc)); 403 + 404 + /* CSID_TIMESTAMP_STB_POST_IRQ */ 405 + val = 2 << RDI_CFG1_TIMESTAMP_STB_SEL; 406 + writel_relaxed(val, csid->base + CSID_RDI_CFG1(vc)); 407 + 408 + val = 1; 409 + writel_relaxed(val, csid->base + CSID_RDI_FRM_DROP_PERIOD(vc)); 410 + 411 + val = 0; 412 + writel_relaxed(val, csid->base + CSID_RDI_FRM_DROP_PATTERN(vc)); 413 + 414 + val = 1; 415 + writel_relaxed(val, csid->base + CSID_RDI_IRQ_SUBSAMPLE_PERIOD(vc)); 416 + 417 + val = 0; 418 + writel_relaxed(val, csid->base + CSID_RDI_IRQ_SUBSAMPLE_PATTERN(vc)); 419 + 420 + val = 1; 421 + writel_relaxed(val, csid->base + CSID_RDI_RPP_PIX_DROP_PERIOD(vc)); 422 + 423 + val = 0; 424 + writel_relaxed(val, csid->base + CSID_RDI_RPP_PIX_DROP_PATTERN(vc)); 425 + 426 + val = 1; 427 + writel_relaxed(val, csid->base + CSID_RDI_RPP_LINE_DROP_PERIOD(vc)); 428 + 429 + val = 0; 430 + writel_relaxed(val, csid->base + CSID_RDI_RPP_LINE_DROP_PATTERN(vc)); 431 + 432 + val = 0; 203 433 writel_relaxed(val, csid->base + CSID_RDI_CTRL(vc)); 434 + 435 + val = readl_relaxed(csid->base + CSID_RDI_CFG0(vc)); 436 + val |= enable << RDI_CFG0_ENABLE; 437 + writel_relaxed(val, csid->base + CSID_RDI_CFG0(vc)); 204 438 } 205 439 206 440 static void csid_configure_stream(struct csid_device *csid, u8 enable) 207 441 { 442 + struct csid_testgen_config *tg = &csid->testgen; 208 443 u8 i; 209 444 /* Loop through all enabled VCs and configure stream for each */ 210 445 for (i = 0; i < MSM_CSID_MAX_SRC_STREAMS; i++) 211 - if (csid->phy.en_vc & BIT(i)) 212 - __csid_configure_stream(csid, enable, i); 446 + if (csid->phy.en_vc & BIT(i)) { 447 + if (tg->enabled) 448 + __csid_configure_testgen(csid, enable, i); 449 + 450 + __csid_configure_rdi_stream(csid, enable, i); 451 + __csid_configure_rx(csid, &csid->phy, i); 452 + __csid_ctrl_rdi(csid, enable, i); 453 + } 213 454 } 214 455 215 456 static int csid_configure_testgen_pattern(struct csid_device *csid, s32 val)