1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * PiSP Front End Driver 4 * 5 * Copyright (c) 2021-2024 Raspberry Pi Ltd. 6 */ 7 8 #include <linux/bitops.h> 9 #include <linux/delay.h> 10 #include <linux/moduleparam.h> 11 #include <linux/pm_runtime.h> 12 #include <linux/seq_file.h> 13 14 #include <media/videobuf2-dma-contig.h> 15 16 #include "cfe.h" 17 #include "pisp-fe.h" 18 19 #include "cfe-trace.h" 20 21 #define FE_VERSION 0x000 22 #define FE_CONTROL 0x004 23 #define FE_STATUS 0x008 24 #define FE_FRAME_STATUS 0x00c 25 #define FE_ERROR_STATUS 0x010 26 #define FE_OUTPUT_STATUS 0x014 27 #define FE_INT_EN 0x018 28 #define FE_INT_STATUS 0x01c 29 30 /* CONTROL */ 31 #define FE_CONTROL_QUEUE BIT(0) 32 #define FE_CONTROL_ABORT BIT(1) 33 #define FE_CONTROL_RESET BIT(2) 34 #define FE_CONTROL_LATCH_REGS BIT(3) 35 36 /* INT_EN / INT_STATUS */ 37 #define FE_INT_EOF BIT(0) 38 #define FE_INT_SOF BIT(1) 39 #define FE_INT_LINES0 BIT(8) 40 #define FE_INT_LINES1 BIT(9) 41 #define FE_INT_STATS BIT(16) 42 #define FE_INT_QREADY BIT(24) 43 44 /* STATUS */ 45 #define FE_STATUS_QUEUED BIT(0) 46 #define FE_STATUS_WAITING BIT(1) 47 #define FE_STATUS_ACTIVE BIT(2) 48 49 #define PISP_FE_CONFIG_BASE_OFFSET 0x0040 50 51 #define PISP_FE_ENABLE_STATS_CLUSTER \ 52 (PISP_FE_ENABLE_STATS_CROP | PISP_FE_ENABLE_DECIMATE | \ 53 PISP_FE_ENABLE_BLC | PISP_FE_ENABLE_CDAF_STATS | \ 54 PISP_FE_ENABLE_AWB_STATS | PISP_FE_ENABLE_RGBY | \ 55 PISP_FE_ENABLE_LSC | PISP_FE_ENABLE_AGC_STATS) 56 57 #define PISP_FE_ENABLE_OUTPUT_CLUSTER(i) \ 58 ((PISP_FE_ENABLE_CROP0 | PISP_FE_ENABLE_DOWNSCALE0 | \ 59 PISP_FE_ENABLE_COMPRESS0 | PISP_FE_ENABLE_OUTPUT0) << (4 * (i))) 60 61 struct pisp_fe_config_param { 62 u32 dirty_flags; 63 u32 dirty_flags_extra; 64 size_t offset; 65 size_t size; 66 }; 67 68 static const struct pisp_fe_config_param pisp_fe_config_map[] = { 69 /* *_dirty_flag_extra types */ 70 { 0, PISP_FE_DIRTY_GLOBAL, 71 offsetof(struct pisp_fe_config, global), 72 sizeof(struct pisp_fe_global_config) }, 73 { 0, PISP_FE_DIRTY_FLOATING, 74 offsetof(struct pisp_fe_config, floating_stats), 75 sizeof(struct pisp_fe_floating_stats_config) }, 76 { 0, PISP_FE_DIRTY_OUTPUT_AXI, 77 offsetof(struct pisp_fe_config, output_axi), 78 sizeof(struct pisp_fe_output_axi_config) }, 79 /* *_dirty_flag types */ 80 { PISP_FE_ENABLE_INPUT, 0, 81 offsetof(struct pisp_fe_config, input), 82 sizeof(struct pisp_fe_input_config) }, 83 { PISP_FE_ENABLE_DECOMPRESS, 0, 84 offsetof(struct pisp_fe_config, decompress), 85 sizeof(struct pisp_decompress_config) }, 86 { PISP_FE_ENABLE_DECOMPAND, 0, 87 offsetof(struct pisp_fe_config, decompand), 88 sizeof(struct pisp_fe_decompand_config) }, 89 { PISP_FE_ENABLE_BLA, 0, 90 offsetof(struct pisp_fe_config, bla), 91 sizeof(struct pisp_bla_config) }, 92 { PISP_FE_ENABLE_DPC, 0, 93 offsetof(struct pisp_fe_config, dpc), 94 sizeof(struct pisp_fe_dpc_config) }, 95 { PISP_FE_ENABLE_STATS_CROP, 0, 96 offsetof(struct pisp_fe_config, stats_crop), 97 sizeof(struct pisp_fe_crop_config) }, 98 { PISP_FE_ENABLE_BLC, 0, 99 offsetof(struct pisp_fe_config, blc), 100 sizeof(struct pisp_bla_config) }, 101 { PISP_FE_ENABLE_CDAF_STATS, 0, 102 offsetof(struct pisp_fe_config, cdaf_stats), 103 sizeof(struct pisp_fe_cdaf_stats_config) }, 104 { PISP_FE_ENABLE_AWB_STATS, 0, 105 offsetof(struct pisp_fe_config, awb_stats), 106 sizeof(struct pisp_fe_awb_stats_config) }, 107 { PISP_FE_ENABLE_RGBY, 0, 108 offsetof(struct pisp_fe_config, rgby), 109 sizeof(struct pisp_fe_rgby_config) }, 110 { PISP_FE_ENABLE_LSC, 0, 111 offsetof(struct pisp_fe_config, lsc), 112 sizeof(struct pisp_fe_lsc_config) }, 113 { PISP_FE_ENABLE_AGC_STATS, 0, 114 offsetof(struct pisp_fe_config, agc_stats), 115 sizeof(struct pisp_agc_statistics) }, 116 { PISP_FE_ENABLE_CROP0, 0, 117 offsetof(struct pisp_fe_config, ch[0].crop), 118 sizeof(struct pisp_fe_crop_config) }, 119 { PISP_FE_ENABLE_DOWNSCALE0, 0, 120 offsetof(struct pisp_fe_config, ch[0].downscale), 121 sizeof(struct pisp_fe_downscale_config) }, 122 { PISP_FE_ENABLE_COMPRESS0, 0, 123 offsetof(struct pisp_fe_config, ch[0].compress), 124 sizeof(struct pisp_compress_config) }, 125 { PISP_FE_ENABLE_OUTPUT0, 0, 126 offsetof(struct pisp_fe_config, ch[0].output), 127 sizeof(struct pisp_fe_output_config) }, 128 { PISP_FE_ENABLE_CROP1, 0, 129 offsetof(struct pisp_fe_config, ch[1].crop), 130 sizeof(struct pisp_fe_crop_config) }, 131 { PISP_FE_ENABLE_DOWNSCALE1, 0, 132 offsetof(struct pisp_fe_config, ch[1].downscale), 133 sizeof(struct pisp_fe_downscale_config) }, 134 { PISP_FE_ENABLE_COMPRESS1, 0, 135 offsetof(struct pisp_fe_config, ch[1].compress), 136 sizeof(struct pisp_compress_config) }, 137 { PISP_FE_ENABLE_OUTPUT1, 0, 138 offsetof(struct pisp_fe_config, ch[1].output), 139 sizeof(struct pisp_fe_output_config) }, 140 }; 141 142 #define pisp_fe_dbg(fe, fmt, arg...) dev_dbg((fe)->v4l2_dev->dev, fmt, ##arg) 143 #define pisp_fe_info(fe, fmt, arg...) dev_info((fe)->v4l2_dev->dev, fmt, ##arg) 144 #define pisp_fe_err(fe, fmt, arg...) dev_err((fe)->v4l2_dev->dev, fmt, ##arg) 145 146 static inline u32 pisp_fe_reg_read(struct pisp_fe_device *fe, u32 offset) 147 { 148 return readl(fe->base + offset); 149 } 150 151 static inline void pisp_fe_reg_write(struct pisp_fe_device *fe, u32 offset, 152 u32 val) 153 { 154 writel(val, fe->base + offset); 155 } 156 157 static inline void pisp_fe_reg_write_relaxed(struct pisp_fe_device *fe, 158 u32 offset, u32 val) 159 { 160 writel_relaxed(val, fe->base + offset); 161 } 162 163 static int pisp_fe_regs_show(struct seq_file *s, void *data) 164 { 165 struct pisp_fe_device *fe = s->private; 166 int ret; 167 168 ret = pm_runtime_resume_and_get(fe->v4l2_dev->dev); 169 if (ret) 170 return ret; 171 172 pisp_fe_reg_write(fe, FE_CONTROL, FE_CONTROL_LATCH_REGS); 173 174 #define DUMP(reg) seq_printf(s, #reg " \t0x%08x\n", pisp_fe_reg_read(fe, reg)) 175 DUMP(FE_VERSION); 176 DUMP(FE_CONTROL); 177 DUMP(FE_STATUS); 178 DUMP(FE_FRAME_STATUS); 179 DUMP(FE_ERROR_STATUS); 180 DUMP(FE_OUTPUT_STATUS); 181 DUMP(FE_INT_EN); 182 DUMP(FE_INT_STATUS); 183 #undef DUMP 184 185 pm_runtime_put(fe->v4l2_dev->dev); 186 187 return 0; 188 } 189 190 DEFINE_SHOW_ATTRIBUTE(pisp_fe_regs); 191 192 static void pisp_fe_config_write(struct pisp_fe_device *fe, 193 struct pisp_fe_config *config, 194 unsigned int start_offset, unsigned int size) 195 { 196 const unsigned int max_offset = 197 offsetof(struct pisp_fe_config, ch[PISP_FE_NUM_OUTPUTS]); 198 unsigned int end_offset; 199 u32 *cfg = (u32 *)config; 200 201 start_offset = min(start_offset, max_offset); 202 end_offset = min(start_offset + size, max_offset); 203 204 cfg += start_offset >> 2; 205 for (unsigned int i = start_offset; i < end_offset; i += 4, cfg++) 206 pisp_fe_reg_write_relaxed(fe, PISP_FE_CONFIG_BASE_OFFSET + i, 207 *cfg); 208 } 209 210 void pisp_fe_isr(struct pisp_fe_device *fe, bool *sof, bool *eof) 211 { 212 u32 status, int_status, out_status, frame_status, error_status; 213 214 pisp_fe_reg_write(fe, FE_CONTROL, FE_CONTROL_LATCH_REGS); 215 status = pisp_fe_reg_read(fe, FE_STATUS); 216 out_status = pisp_fe_reg_read(fe, FE_OUTPUT_STATUS); 217 frame_status = pisp_fe_reg_read(fe, FE_FRAME_STATUS); 218 error_status = pisp_fe_reg_read(fe, FE_ERROR_STATUS); 219 220 int_status = pisp_fe_reg_read(fe, FE_INT_STATUS); 221 pisp_fe_reg_write(fe, FE_INT_STATUS, int_status); 222 223 trace_fe_irq(status, out_status, frame_status, error_status, 224 int_status); 225 226 /* We do not report interrupts for the input/stream pad. */ 227 for (unsigned int i = 0; i < FE_NUM_PADS - 1; i++) { 228 sof[i] = !!(int_status & FE_INT_SOF); 229 eof[i] = !!(int_status & FE_INT_EOF); 230 } 231 } 232 233 static bool pisp_fe_validate_output(struct pisp_fe_config const *cfg, 234 unsigned int c, struct v4l2_format const *f) 235 { 236 unsigned int wbytes; 237 238 wbytes = cfg->ch[c].output.format.width; 239 if (cfg->ch[c].output.format.format & PISP_IMAGE_FORMAT_BPS_MASK) 240 wbytes *= 2; 241 242 /* Check output image dimensions are nonzero and not too big */ 243 if (cfg->ch[c].output.format.width < 2 || 244 cfg->ch[c].output.format.height < 2 || 245 cfg->ch[c].output.format.height > f->fmt.pix.height || 246 cfg->ch[c].output.format.stride > f->fmt.pix.bytesperline || 247 wbytes > f->fmt.pix.bytesperline) 248 return false; 249 250 /* Check for zero-sized crops, which could cause lockup */ 251 if ((cfg->global.enables & PISP_FE_ENABLE_CROP(c)) && 252 ((cfg->ch[c].crop.offset_x >= (cfg->input.format.width & ~1) || 253 cfg->ch[c].crop.offset_y >= cfg->input.format.height || 254 cfg->ch[c].crop.width < 2 || cfg->ch[c].crop.height < 2))) 255 return false; 256 257 if ((cfg->global.enables & PISP_FE_ENABLE_DOWNSCALE(c)) && 258 (cfg->ch[c].downscale.output_width < 2 || 259 cfg->ch[c].downscale.output_height < 2)) 260 return false; 261 262 return true; 263 } 264 265 static bool pisp_fe_validate_stats(struct pisp_fe_config const *cfg) 266 { 267 /* Check for zero-sized crop, which could cause lockup */ 268 return (!(cfg->global.enables & PISP_FE_ENABLE_STATS_CROP) || 269 (cfg->stats_crop.offset_x < (cfg->input.format.width & ~1) && 270 cfg->stats_crop.offset_y < cfg->input.format.height && 271 cfg->stats_crop.width >= 2 && cfg->stats_crop.height >= 2)); 272 } 273 274 int pisp_fe_validate_config(struct pisp_fe_device *fe, 275 struct pisp_fe_config *cfg, 276 struct v4l2_format const *f0, 277 struct v4l2_format const *f1) 278 { 279 /* 280 * Check the input is enabled, streaming and has nonzero size; 281 * to avoid cases where the hardware might lock up or try to 282 * read inputs from memory (which this driver doesn't support). 283 */ 284 if (!(cfg->global.enables & PISP_FE_ENABLE_INPUT) || 285 cfg->input.streaming != 1 || cfg->input.format.width < 2 || 286 cfg->input.format.height < 2) { 287 pisp_fe_err(fe, "%s: Input config not valid", __func__); 288 return -EINVAL; 289 } 290 291 for (unsigned int i = 0; i < PISP_FE_NUM_OUTPUTS; i++) { 292 if (!(cfg->global.enables & PISP_FE_ENABLE_OUTPUT(i))) { 293 if (cfg->global.enables & 294 PISP_FE_ENABLE_OUTPUT_CLUSTER(i)) { 295 pisp_fe_err(fe, "%s: Output %u not valid", 296 __func__, i); 297 return -EINVAL; 298 } 299 continue; 300 } 301 302 if (!pisp_fe_validate_output(cfg, i, i ? f1 : f0)) 303 return -EINVAL; 304 } 305 306 if ((cfg->global.enables & PISP_FE_ENABLE_STATS_CLUSTER) && 307 !pisp_fe_validate_stats(cfg)) { 308 pisp_fe_err(fe, "%s: Stats config not valid", __func__); 309 return -EINVAL; 310 } 311 312 return 0; 313 } 314 315 void pisp_fe_submit_job(struct pisp_fe_device *fe, struct vb2_buffer **vb2_bufs, 316 struct pisp_fe_config *cfg) 317 { 318 u64 addr; 319 u32 status; 320 321 /* 322 * Check output buffers exist and outputs are correctly configured. 323 * If valid, set the buffer's DMA address; otherwise disable. 324 */ 325 for (unsigned int i = 0; i < PISP_FE_NUM_OUTPUTS; i++) { 326 struct vb2_buffer *buf = vb2_bufs[FE_OUTPUT0_PAD + i]; 327 328 if (!(cfg->global.enables & PISP_FE_ENABLE_OUTPUT(i))) 329 continue; 330 331 addr = vb2_dma_contig_plane_dma_addr(buf, 0); 332 cfg->output_buffer[i].addr_lo = addr & 0xffffffff; 333 cfg->output_buffer[i].addr_hi = addr >> 32; 334 } 335 336 if (vb2_bufs[FE_STATS_PAD]) { 337 addr = vb2_dma_contig_plane_dma_addr(vb2_bufs[FE_STATS_PAD], 0); 338 cfg->stats_buffer.addr_lo = addr & 0xffffffff; 339 cfg->stats_buffer.addr_hi = addr >> 32; 340 } 341 342 /* Set up ILINES interrupts 3/4 of the way down each output */ 343 cfg->ch[0].output.ilines = 344 max(0x80u, (3u * cfg->ch[0].output.format.height) >> 2); 345 cfg->ch[1].output.ilines = 346 max(0x80u, (3u * cfg->ch[1].output.format.height) >> 2); 347 348 /* 349 * The hardware must have consumed the previous config by now. 350 * This read of status also serves as a memory barrier before the 351 * sequence of relaxed writes which follow. 352 */ 353 status = pisp_fe_reg_read(fe, FE_STATUS); 354 if (WARN_ON(status & FE_STATUS_QUEUED)) 355 return; 356 357 /* 358 * Unconditionally write buffers, global and input parameters. 359 * Write cropping and output parameters whenever they are enabled. 360 * Selectively write other parameters that have been marked as 361 * changed through the dirty flags. 362 */ 363 pisp_fe_config_write(fe, cfg, 0, 364 offsetof(struct pisp_fe_config, decompress)); 365 cfg->dirty_flags_extra &= ~PISP_FE_DIRTY_GLOBAL; 366 cfg->dirty_flags &= ~PISP_FE_ENABLE_INPUT; 367 cfg->dirty_flags |= (cfg->global.enables & 368 (PISP_FE_ENABLE_STATS_CROP | 369 PISP_FE_ENABLE_OUTPUT_CLUSTER(0) | 370 PISP_FE_ENABLE_OUTPUT_CLUSTER(1))); 371 for (unsigned int i = 0; i < ARRAY_SIZE(pisp_fe_config_map); i++) { 372 const struct pisp_fe_config_param *p = &pisp_fe_config_map[i]; 373 374 if (cfg->dirty_flags & p->dirty_flags || 375 cfg->dirty_flags_extra & p->dirty_flags_extra) 376 pisp_fe_config_write(fe, cfg, p->offset, p->size); 377 } 378 379 /* This final non-relaxed write serves as a memory barrier */ 380 pisp_fe_reg_write(fe, FE_CONTROL, FE_CONTROL_QUEUE); 381 } 382 383 void pisp_fe_start(struct pisp_fe_device *fe) 384 { 385 pisp_fe_reg_write(fe, FE_CONTROL, FE_CONTROL_RESET); 386 pisp_fe_reg_write(fe, FE_INT_STATUS, ~0); 387 pisp_fe_reg_write(fe, FE_INT_EN, FE_INT_EOF | FE_INT_SOF | 388 FE_INT_LINES0 | FE_INT_LINES1); 389 fe->inframe_count = 0; 390 } 391 392 void pisp_fe_stop(struct pisp_fe_device *fe) 393 { 394 pisp_fe_reg_write(fe, FE_INT_EN, 0); 395 pisp_fe_reg_write(fe, FE_CONTROL, FE_CONTROL_ABORT); 396 usleep_range(1000, 2000); 397 WARN_ON(pisp_fe_reg_read(fe, FE_STATUS)); 398 pisp_fe_reg_write(fe, FE_INT_STATUS, ~0); 399 } 400 401 static int pisp_fe_init_state(struct v4l2_subdev *sd, 402 struct v4l2_subdev_state *state) 403 { 404 struct v4l2_mbus_framefmt *fmt; 405 406 fmt = v4l2_subdev_state_get_format(state, FE_STREAM_PAD); 407 *fmt = cfe_default_format; 408 fmt->code = MEDIA_BUS_FMT_SRGGB16_1X16; 409 410 fmt = v4l2_subdev_state_get_format(state, FE_CONFIG_PAD); 411 fmt->code = MEDIA_BUS_FMT_FIXED; 412 fmt->width = sizeof(struct pisp_fe_config); 413 fmt->height = 1; 414 415 fmt = v4l2_subdev_state_get_format(state, FE_OUTPUT0_PAD); 416 *fmt = cfe_default_format; 417 fmt->code = MEDIA_BUS_FMT_SRGGB16_1X16; 418 419 fmt = v4l2_subdev_state_get_format(state, FE_OUTPUT1_PAD); 420 *fmt = cfe_default_format; 421 fmt->code = MEDIA_BUS_FMT_SRGGB16_1X16; 422 423 fmt = v4l2_subdev_state_get_format(state, FE_STATS_PAD); 424 fmt->code = MEDIA_BUS_FMT_FIXED; 425 fmt->width = sizeof(struct pisp_statistics); 426 fmt->height = 1; 427 428 return 0; 429 } 430 431 static int pisp_fe_pad_set_fmt(struct v4l2_subdev *sd, 432 struct v4l2_subdev_state *state, 433 struct v4l2_subdev_format *format) 434 { 435 struct v4l2_mbus_framefmt *fmt; 436 const struct cfe_fmt *cfe_fmt; 437 438 /* TODO: format propagation to source pads */ 439 /* TODO: format validation */ 440 441 switch (format->pad) { 442 case FE_STREAM_PAD: 443 cfe_fmt = find_format_by_code(format->format.code); 444 if (!cfe_fmt || !(cfe_fmt->flags & CFE_FORMAT_FLAG_FE_OUT)) 445 cfe_fmt = find_format_by_code(MEDIA_BUS_FMT_SRGGB16_1X16); 446 447 format->format.code = cfe_fmt->code; 448 format->format.field = V4L2_FIELD_NONE; 449 450 fmt = v4l2_subdev_state_get_format(state, FE_STREAM_PAD); 451 *fmt = format->format; 452 453 fmt = v4l2_subdev_state_get_format(state, FE_OUTPUT0_PAD); 454 *fmt = format->format; 455 456 fmt = v4l2_subdev_state_get_format(state, FE_OUTPUT1_PAD); 457 *fmt = format->format; 458 459 return 0; 460 461 case FE_OUTPUT0_PAD: 462 case FE_OUTPUT1_PAD: { 463 /* 464 * TODO: we should allow scaling and cropping by allowing the 465 * user to set the size here. 466 */ 467 struct v4l2_mbus_framefmt *sink_fmt, *source_fmt; 468 u32 sink_code; 469 u32 code; 470 471 cfe_fmt = find_format_by_code(format->format.code); 472 if (!cfe_fmt || !(cfe_fmt->flags & CFE_FORMAT_FLAG_FE_OUT)) 473 cfe_fmt = find_format_by_code(MEDIA_BUS_FMT_SRGGB16_1X16); 474 475 format->format.code = cfe_fmt->code; 476 477 sink_fmt = v4l2_subdev_state_get_format(state, FE_STREAM_PAD); 478 if (!sink_fmt) 479 return -EINVAL; 480 481 source_fmt = v4l2_subdev_state_get_format(state, format->pad); 482 if (!source_fmt) 483 return -EINVAL; 484 485 sink_code = sink_fmt->code; 486 code = format->format.code; 487 488 /* 489 * If the source code from the user does not match the code in 490 * the sink pad, check that the source code matches the 491 * compressed version of the sink code. 492 */ 493 494 if (code != sink_code && 495 code == cfe_find_compressed_code(sink_code)) 496 source_fmt->code = code; 497 498 return 0; 499 } 500 501 case FE_CONFIG_PAD: 502 case FE_STATS_PAD: 503 default: 504 return v4l2_subdev_get_fmt(sd, state, format); 505 } 506 } 507 508 static const struct v4l2_subdev_pad_ops pisp_fe_subdev_pad_ops = { 509 .get_fmt = v4l2_subdev_get_fmt, 510 .set_fmt = pisp_fe_pad_set_fmt, 511 .link_validate = v4l2_subdev_link_validate_default, 512 }; 513 514 static int pisp_fe_link_validate(struct media_link *link) 515 { 516 struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(link->sink->entity); 517 struct pisp_fe_device *fe = container_of(sd, struct pisp_fe_device, sd); 518 519 pisp_fe_dbg(fe, "%s: link \"%s\":%u -> \"%s\":%u\n", __func__, 520 link->source->entity->name, link->source->index, 521 link->sink->entity->name, link->sink->index); 522 523 if (link->sink->index == FE_STREAM_PAD) 524 return v4l2_subdev_link_validate(link); 525 526 if (link->sink->index == FE_CONFIG_PAD) 527 return 0; 528 529 return -EINVAL; 530 } 531 532 static const struct media_entity_operations pisp_fe_entity_ops = { 533 .link_validate = pisp_fe_link_validate, 534 }; 535 536 static const struct v4l2_subdev_ops pisp_fe_subdev_ops = { 537 .pad = &pisp_fe_subdev_pad_ops, 538 }; 539 540 static const struct v4l2_subdev_internal_ops pisp_fe_internal_ops = { 541 .init_state = pisp_fe_init_state, 542 }; 543 544 int pisp_fe_init(struct pisp_fe_device *fe, struct dentry *debugfs) 545 { 546 int ret; 547 548 debugfs_create_file("fe_regs", 0440, debugfs, fe, &pisp_fe_regs_fops); 549 550 fe->hw_revision = pisp_fe_reg_read(fe, FE_VERSION); 551 pisp_fe_info(fe, "PiSP FE HW v%u.%u\n", 552 (fe->hw_revision >> 24) & 0xff, 553 (fe->hw_revision >> 20) & 0x0f); 554 555 fe->pad[FE_STREAM_PAD].flags = 556 MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_MUST_CONNECT; 557 fe->pad[FE_CONFIG_PAD].flags = MEDIA_PAD_FL_SINK; 558 fe->pad[FE_OUTPUT0_PAD].flags = MEDIA_PAD_FL_SOURCE; 559 fe->pad[FE_OUTPUT1_PAD].flags = MEDIA_PAD_FL_SOURCE; 560 fe->pad[FE_STATS_PAD].flags = MEDIA_PAD_FL_SOURCE; 561 562 ret = media_entity_pads_init(&fe->sd.entity, ARRAY_SIZE(fe->pad), 563 fe->pad); 564 if (ret) 565 return ret; 566 567 /* Initialize subdev */ 568 v4l2_subdev_init(&fe->sd, &pisp_fe_subdev_ops); 569 fe->sd.internal_ops = &pisp_fe_internal_ops; 570 fe->sd.entity.function = MEDIA_ENT_F_PROC_VIDEO_SCALER; 571 fe->sd.entity.ops = &pisp_fe_entity_ops; 572 fe->sd.entity.name = "pisp-fe"; 573 fe->sd.flags = V4L2_SUBDEV_FL_HAS_DEVNODE; 574 fe->sd.owner = THIS_MODULE; 575 snprintf(fe->sd.name, sizeof(fe->sd.name), "pisp-fe"); 576 577 ret = v4l2_subdev_init_finalize(&fe->sd); 578 if (ret) 579 goto err_entity_cleanup; 580 581 ret = v4l2_device_register_subdev(fe->v4l2_dev, &fe->sd); 582 if (ret) { 583 pisp_fe_err(fe, "Failed register pisp fe subdev (%d)\n", ret); 584 goto err_subdev_cleanup; 585 } 586 587 /* Must be in IDLE state (STATUS == 0) here. */ 588 WARN_ON(pisp_fe_reg_read(fe, FE_STATUS)); 589 590 return 0; 591 592 err_subdev_cleanup: 593 v4l2_subdev_cleanup(&fe->sd); 594 err_entity_cleanup: 595 media_entity_cleanup(&fe->sd.entity); 596 597 return ret; 598 } 599 600 void pisp_fe_uninit(struct pisp_fe_device *fe) 601 { 602 v4l2_device_unregister_subdev(&fe->sd); 603 v4l2_subdev_cleanup(&fe->sd); 604 media_entity_cleanup(&fe->sd.entity); 605 } 606