| .. | .. |
|---|
| 37 | 37 | #include <media/v4l2-mediabus.h> |
|---|
| 38 | 38 | #include <linux/delay.h> |
|---|
| 39 | 39 | #include <linux/pm_runtime.h> |
|---|
| 40 | | -#include <dt-bindings/soc/rockchip-system-status.h> |
|---|
| 41 | 40 | #include <soc/rockchip/rockchip-system-status.h> |
|---|
| 42 | 41 | #include <linux/phy/phy.h> |
|---|
| 43 | 42 | #include <linux/uaccess.h> |
|---|
| .. | .. |
|---|
| 2266 | 2265 | return index; |
|---|
| 2267 | 2266 | } |
|---|
| 2268 | 2267 | |
|---|
| 2268 | +static enum cif_reg_index get_reg_index_of_frm_num(int channel_id) |
|---|
| 2269 | +{ |
|---|
| 2270 | + enum cif_reg_index index; |
|---|
| 2271 | + |
|---|
| 2272 | + switch (channel_id) { |
|---|
| 2273 | + case 0: |
|---|
| 2274 | + index = CIF_REG_MIPI_FRAME_NUM_VC0; |
|---|
| 2275 | + break; |
|---|
| 2276 | + case 1: |
|---|
| 2277 | + index = CIF_REG_MIPI_FRAME_NUM_VC1; |
|---|
| 2278 | + break; |
|---|
| 2279 | + case 2: |
|---|
| 2280 | + index = CIF_REG_MIPI_FRAME_NUM_VC2; |
|---|
| 2281 | + break; |
|---|
| 2282 | + case 3: |
|---|
| 2283 | + index = CIF_REG_MIPI_FRAME_NUM_VC3; |
|---|
| 2284 | + break; |
|---|
| 2285 | + default: |
|---|
| 2286 | + index = CIF_REG_MIPI_FRAME_NUM_VC0; |
|---|
| 2287 | + break; |
|---|
| 2288 | + } |
|---|
| 2289 | + |
|---|
| 2290 | + return index; |
|---|
| 2291 | +} |
|---|
| 2292 | + |
|---|
| 2269 | 2293 | static enum cif_reg_index get_reg_index_of_frm1_y_addr(int channel_id) |
|---|
| 2270 | 2294 | { |
|---|
| 2271 | 2295 | enum cif_reg_index index; |
|---|
| .. | .. |
|---|
| 2758 | 2782 | VEHICLE_DG("%s, LINE=%d, channel->fmt_val = 0x%x", __func__, __LINE__, channel->fmt_val); |
|---|
| 2759 | 2783 | if (cfg->input_format == CIF_INPUT_FORMAT_PAL || |
|---|
| 2760 | 2784 | cfg->input_format == CIF_INPUT_FORMAT_NTSC) { |
|---|
| 2761 | | - VEHICLE_DG("CVBS IN PAL or NTSC config."); |
|---|
| 2785 | + VEHICLE_INFO("CVBS IN PAL or NTSC config."); |
|---|
| 2762 | 2786 | channel->virtual_width *= 2; |
|---|
| 2763 | 2787 | cif->interlaced_enable = true; |
|---|
| 2764 | 2788 | cif->interlaced_offset = channel->width; |
|---|
| 2765 | 2789 | cif->interlaced_counts = 0; |
|---|
| 2766 | 2790 | cif->interlaced_buffer = 0; |
|---|
| 2767 | 2791 | channel->height /= 2; |
|---|
| 2768 | | - VEHICLE_DG("do denterlaced.\n"); |
|---|
| 2792 | + VEHICLE_INFO("do denterlaced.\n"); |
|---|
| 2769 | 2793 | } |
|---|
| 2770 | 2794 | |
|---|
| 2771 | 2795 | channel->data_type = get_data_type(cfg->mbus_code, |
|---|
| .. | .. |
|---|
| 3930 | 3954 | static unsigned long temp_y_addr, temp_uv_addr; |
|---|
| 3931 | 3955 | int commit_buf = 0; |
|---|
| 3932 | 3956 | struct vehicle_rkcif_dummy_buffer *dummy_buf = &cif->dummy_buf; |
|---|
| 3933 | | - |
|---|
| 3957 | + u32 frm_num_reg, frame_id = 0; |
|---|
| 3934 | 3958 | VEHICLE_DG("@%s, enter, mipi_id(%d)\n", __func__, mipi_id); |
|---|
| 3935 | 3959 | |
|---|
| 3936 | 3960 | if ((frame_ready > 1) || (cif->cif_cfg.buf_num < 2) || |
|---|
| .. | .. |
|---|
| 3946 | 3970 | frm0_addr_uv = get_reg_index_of_frm0_uv_addr(mipi_id); |
|---|
| 3947 | 3971 | frm1_addr_y = get_reg_index_of_frm1_y_addr(mipi_id); |
|---|
| 3948 | 3972 | frm1_addr_uv = get_reg_index_of_frm1_uv_addr(mipi_id); |
|---|
| 3973 | + frm_num_reg = get_reg_index_of_frm_num(mipi_id); |
|---|
| 3974 | + frame_id = rkcif_read_reg(cif, frm_num_reg); |
|---|
| 3975 | + VEHICLE_DG("@%s, frm_num_reg(0x%x), frame_id:0x%x\n", __func__, |
|---|
| 3976 | + frm_num_reg, frame_id); |
|---|
| 3949 | 3977 | } else { |
|---|
| 3950 | 3978 | frm0_addr_y = get_dvp_reg_index_of_frm0_y_addr(mipi_id); |
|---|
| 3951 | 3979 | frm0_addr_uv = get_dvp_reg_index_of_frm0_uv_addr(mipi_id); |
|---|
| .. | .. |
|---|
| 3979 | 4007 | uv_addr = temp_uv_addr; |
|---|
| 3980 | 4008 | commit_buf = 0; |
|---|
| 3981 | 4009 | } else { |
|---|
| 3982 | | - if ((cif->interlaced_counts % 2) == 0) { |
|---|
| 4010 | + if ((frame_id != 0 && (frame_id & 0xffff) % 2 == 0) || |
|---|
| 4011 | + (frame_id == 0 && (cif->interlaced_counts % 2 == 0))) { |
|---|
| 3983 | 4012 | temp_y_addr = vehicle_flinger_request_cif_buffer(); |
|---|
| 3984 | 4013 | if (temp_y_addr == 0) { |
|---|
| 3985 | | - VEHICLE_INFO("%s,warnning request buffer failed\n", __func__); |
|---|
| 4014 | + VEHICLE_DGERR("%s,warnning request buffer failed\n", __func__); |
|---|
| 3986 | 4015 | spin_unlock(&cif->vbq_lock); |
|---|
| 3987 | 4016 | return -1; |
|---|
| 3988 | 4017 | } |
|---|
| .. | .. |
|---|
| 3995 | 4024 | //uv_addr = temp_uv_addr; |
|---|
| 3996 | 4025 | uv_addr = temp_uv_addr + cif->interlaced_offset; |
|---|
| 3997 | 4026 | commit_buf = 0; //even & odd field add |
|---|
| 4027 | + if (temp_y_addr == 0) { |
|---|
| 4028 | + VEHICLE_DGERR("%s,warnning temp_y_addr is NULL!\n", __func__); |
|---|
| 4029 | + spin_unlock(&cif->vbq_lock); |
|---|
| 4030 | + return -1; |
|---|
| 4031 | + } |
|---|
| 3998 | 4032 | } |
|---|
| 3999 | 4033 | WARN_ON(y_addr == cif->interlaced_offset); |
|---|
| 4000 | 4034 | WARN_ON(uv_addr == cif->interlaced_offset); |
|---|
| .. | .. |
|---|
| 4453 | 4487 | return IRQ_HANDLED; |
|---|
| 4454 | 4488 | } |
|---|
| 4455 | 4489 | |
|---|
| 4490 | +#define vehicle_csi2_err_strncat(dst_str, src_str) {\ |
|---|
| 4491 | + if (strlen(dst_str) + strlen(src_str) < CSI_ERRSTR_LEN)\ |
|---|
| 4492 | + strncat(dst_str, src_str, strlen(src_str)); } |
|---|
| 4493 | + |
|---|
| 4494 | +static void vehicle_csi2_find_err_vc(int val, char *vc_info) |
|---|
| 4495 | +{ |
|---|
| 4496 | + int i; |
|---|
| 4497 | + char cur_str[CSI_VCINFO_LEN] = {0}; |
|---|
| 4498 | + |
|---|
| 4499 | + memset(vc_info, 0, sizeof(*vc_info)); |
|---|
| 4500 | + for (i = 0; i < 4; i++) { |
|---|
| 4501 | + if ((val >> i) & 0x1) { |
|---|
| 4502 | + snprintf(cur_str, CSI_VCINFO_LEN, " %d", i); |
|---|
| 4503 | + if (strlen(vc_info) + strlen(cur_str) < CSI_VCINFO_LEN) |
|---|
| 4504 | + strncat(vc_info, cur_str, strlen(cur_str)); |
|---|
| 4505 | + } |
|---|
| 4506 | + } |
|---|
| 4507 | +} |
|---|
| 4508 | + |
|---|
| 4509 | +static void vehicle_csi2_err_print_work(struct work_struct *work) |
|---|
| 4510 | +{ |
|---|
| 4511 | + struct vehicle_csi2_err_state_work *err_state = container_of(work, |
|---|
| 4512 | + struct vehicle_csi2_err_state_work, |
|---|
| 4513 | + work); |
|---|
| 4514 | + |
|---|
| 4515 | + pr_err("mipi_csi2: ERR%d:0x%x %s\n", err_state->err_num, |
|---|
| 4516 | + err_state->err_val, err_state->err_str); |
|---|
| 4517 | + if (err_state->err_num == 1) |
|---|
| 4518 | + pr_info("mipi_csi2: err_stat:0x%x\n", err_state->err_stat); |
|---|
| 4519 | +} |
|---|
| 4520 | + |
|---|
| 4456 | 4521 | static irqreturn_t vehicle_csirx_irq1(int irq, void *data) |
|---|
| 4457 | 4522 | { |
|---|
| 4458 | 4523 | struct vehicle_cif *cif = (struct vehicle_cif *)data; |
|---|
| .. | .. |
|---|
| 4460 | 4525 | struct csi2_err_stats *err_list = NULL; |
|---|
| 4461 | 4526 | unsigned long err_stat = 0; |
|---|
| 4462 | 4527 | u32 val; |
|---|
| 4528 | + char err_str[CSI_ERRSTR_LEN] = {0}; |
|---|
| 4529 | + char cur_str[CSI_ERRSTR_LEN] = {0}; |
|---|
| 4530 | + char vc_info[CSI_VCINFO_LEN] = {0}; |
|---|
| 4463 | 4531 | |
|---|
| 4464 | 4532 | val = read_reg(hw->csi2_base, CSIHOST_ERR1); |
|---|
| 4465 | 4533 | if (val) { |
|---|
| .. | .. |
|---|
| 4469 | 4537 | if (val & CSIHOST_ERR1_PHYERR_SPTSYNCHS) { |
|---|
| 4470 | 4538 | err_list = &hw->err_list[RK_CSI2_ERR_SOTSYN]; |
|---|
| 4471 | 4539 | err_list->cnt++; |
|---|
| 4472 | | - VEHICLE_DGERR( |
|---|
| 4473 | | - "ERR1: start of transmission error, reg: 0x%x,cnt:%d\n", |
|---|
| 4474 | | - val, err_list->cnt); |
|---|
| 4540 | + |
|---|
| 4541 | + vehicle_csi2_find_err_vc(val & 0xf, vc_info); |
|---|
| 4542 | + snprintf(cur_str, CSI_ERRSTR_LEN, "(sot sync,lane:%s) ", vc_info); |
|---|
| 4543 | + vehicle_csi2_err_strncat(err_str, cur_str); |
|---|
| 4475 | 4544 | } |
|---|
| 4476 | 4545 | |
|---|
| 4477 | 4546 | if (val & CSIHOST_ERR1_ERR_BNDRY_MATCH) { |
|---|
| 4478 | 4547 | err_list = &hw->err_list[RK_CSI2_ERR_FS_FE_MIS]; |
|---|
| 4479 | 4548 | err_list->cnt++; |
|---|
| 4480 | | - VEHICLE_DGERR( |
|---|
| 4481 | | - "ERR1: error matching frame start with frame end, reg: 0x%x,cnt:%d\n", |
|---|
| 4482 | | - val, err_list->cnt); |
|---|
| 4549 | + vehicle_csi2_find_err_vc((val >> 4) & 0xf, vc_info); |
|---|
| 4550 | + snprintf(cur_str, CSI_ERRSTR_LEN, "(fs/fe miss,vc:%s) ", vc_info); |
|---|
| 4551 | + vehicle_csi2_err_strncat(err_str, cur_str); |
|---|
| 4552 | + |
|---|
| 4483 | 4553 | } |
|---|
| 4484 | 4554 | |
|---|
| 4485 | 4555 | if (val & CSIHOST_ERR1_ERR_SEQ) { |
|---|
| 4486 | 4556 | err_list = &hw->err_list[RK_CSI2_ERR_FRM_SEQ_ERR]; |
|---|
| 4487 | 4557 | err_list->cnt++; |
|---|
| 4488 | | - VEHICLE_DGERR("ERR1: incorrect frame sequence detected, reg: 0x%x,cnt:%d\n", |
|---|
| 4489 | | - val, err_list->cnt); |
|---|
| 4558 | + vehicle_csi2_find_err_vc((val >> 8) & 0xf, vc_info); |
|---|
| 4559 | + snprintf(cur_str, CSI_ERRSTR_LEN, "(f_seq,vc:%s) ", vc_info); |
|---|
| 4560 | + vehicle_csi2_err_strncat(err_str, cur_str); |
|---|
| 4561 | + |
|---|
| 4490 | 4562 | } |
|---|
| 4491 | 4563 | |
|---|
| 4492 | 4564 | if (val & CSIHOST_ERR1_ERR_FRM_DATA) { |
|---|
| 4493 | 4565 | err_list = &hw->err_list[RK_CSI2_ERR_CRC_ONCE]; |
|---|
| 4494 | 4566 | err_list->cnt++; |
|---|
| 4495 | | - VEHICLE_DGERR("ERR1: at least one crc error, reg: 0x%x\n,cnt:%d", |
|---|
| 4496 | | - val, err_list->cnt); |
|---|
| 4567 | + vehicle_csi2_find_err_vc((val >> 12) & 0xf, vc_info); |
|---|
| 4568 | + snprintf(cur_str, CSI_ERRSTR_LEN, "(err_data,vc:%s) ", vc_info); |
|---|
| 4569 | + vehicle_csi2_err_strncat(err_str, cur_str); |
|---|
| 4570 | + |
|---|
| 4497 | 4571 | } |
|---|
| 4498 | 4572 | |
|---|
| 4499 | 4573 | if (val & CSIHOST_ERR1_ERR_CRC) { |
|---|
| 4500 | 4574 | err_list = &hw->err_list[RK_CSI2_ERR_CRC]; |
|---|
| 4501 | 4575 | err_list->cnt++; |
|---|
| 4502 | | - VEHICLE_DGERR("ERR1: crc errors, reg: 0x%x, cnt:%d\n", |
|---|
| 4503 | | - val, err_list->cnt); |
|---|
| 4576 | + vehicle_csi2_find_err_vc((val >> 24) & 0xf, vc_info); |
|---|
| 4577 | + snprintf(cur_str, CSI_ERRSTR_LEN, "(crc,vc:%s) ", vc_info); |
|---|
| 4578 | + vehicle_csi2_err_strncat(err_str, cur_str); |
|---|
| 4579 | + |
|---|
| 4504 | 4580 | } |
|---|
| 4505 | 4581 | |
|---|
| 4506 | 4582 | if (val & CSIHOST_ERR1_ERR_ECC2) { |
|---|
| 4507 | 4583 | err_list = &hw->err_list[RK_CSI2_ERR_CRC]; |
|---|
| 4508 | 4584 | err_list->cnt++; |
|---|
| 4509 | | - VEHICLE_DGERR("ERR1: ecc errors, reg: 0x%x, cnt:%d\n", |
|---|
| 4510 | | - val, err_list->cnt); |
|---|
| 4511 | | - } |
|---|
| 4512 | | - if (val & CSIHOST_ERR1_ERR_CTRL) |
|---|
| 4513 | | - VEHICLE_DGERR("ERR1: ctrl errors, reg: 0x%x\n", val); |
|---|
| 4585 | + snprintf(cur_str, CSI_ERRSTR_LEN, "(ecc2) "); |
|---|
| 4586 | + vehicle_csi2_err_strncat(err_str, cur_str); |
|---|
| 4514 | 4587 | |
|---|
| 4588 | + } |
|---|
| 4589 | + if (val & CSIHOST_ERR1_ERR_CTRL) { |
|---|
| 4590 | + vehicle_csi2_find_err_vc((val >> 16) & 0xf, vc_info); |
|---|
| 4591 | + snprintf(cur_str, CSI_ERRSTR_LEN, "(ctrl,vc:%s) ", vc_info); |
|---|
| 4592 | + vehicle_csi2_err_strncat(err_str, cur_str); |
|---|
| 4593 | + } |
|---|
| 4515 | 4594 | hw->err_list[RK_CSI2_ERR_ALL].cnt++; |
|---|
| 4516 | 4595 | err_stat = ((hw->err_list[RK_CSI2_ERR_FS_FE_MIS].cnt & 0xff) << 8) | |
|---|
| 4517 | 4596 | ((hw->err_list[RK_CSI2_ERR_ALL].cnt) & 0xff); |
|---|
| 4518 | | - VEHICLE_INFO("%s: err_stat: %x\n", err_stat); |
|---|
| 4597 | + |
|---|
| 4598 | + cif->err_state.err_val = val; |
|---|
| 4599 | + cif->err_state.err_num = 1; |
|---|
| 4600 | + cif->err_state.err_stat = err_stat; |
|---|
| 4601 | + strscpy(cif->err_state.err_str, err_str, CSI_ERRSTR_LEN); |
|---|
| 4602 | + queue_work(cif->err_state.err_print_wq, &cif->err_state.work); |
|---|
| 4519 | 4603 | |
|---|
| 4520 | 4604 | } |
|---|
| 4521 | 4605 | |
|---|
| .. | .. |
|---|
| 4527 | 4611 | struct vehicle_cif *cif = (struct vehicle_cif *)data; |
|---|
| 4528 | 4612 | struct csi2_dphy_hw *hw = cif->dphy_hw; |
|---|
| 4529 | 4613 | u32 val; |
|---|
| 4614 | + char cur_str[CSI_ERRSTR_LEN] = {0}; |
|---|
| 4615 | + char err_str[CSI_ERRSTR_LEN] = {0}; |
|---|
| 4616 | + char vc_info[CSI_VCINFO_LEN] = {0}; |
|---|
| 4530 | 4617 | |
|---|
| 4531 | 4618 | val = read_reg(hw->csi2_base, CSIHOST_ERR2); |
|---|
| 4532 | 4619 | if (val) { |
|---|
| 4533 | | - if (val & CSIHOST_ERR2_PHYERR_ESC) |
|---|
| 4534 | | - VEHICLE_DGERR("ERR2: escape entry error(ULPM), reg: 0x%x\n", val); |
|---|
| 4535 | | - if (val & CSIHOST_ERR2_PHYERR_SOTHS) |
|---|
| 4536 | | - VEHICLE_DGERR( |
|---|
| 4537 | | - "ERR2: start of transmission error, reg: 0x%x\n", val); |
|---|
| 4538 | | - if (val & CSIHOST_ERR2_ECC_CORRECTED) |
|---|
| 4539 | | - VEHICLE_DGERR( |
|---|
| 4540 | | - "ERR2: header error detected and corrected, reg: 0x%x\n", val); |
|---|
| 4541 | | - if (val & CSIHOST_ERR2_ERR_ID) |
|---|
| 4542 | | - VEHICLE_DGERR( |
|---|
| 4543 | | - "ERR2: unrecognized data type detected, reg: 0x%x\n", val); |
|---|
| 4544 | | - if (val & CSIHOST_ERR2_PHYERR_CODEHS) |
|---|
| 4545 | | - VEHICLE_DGERR("ERR2: receive error code, reg: 0x%x\n", val); |
|---|
| 4620 | + if (val & CSIHOST_ERR2_PHYERR_ESC) { |
|---|
| 4621 | + vehicle_csi2_find_err_vc(val & 0xf, vc_info); |
|---|
| 4622 | + snprintf(cur_str, CSI_ERRSTR_LEN, "(ULPM,lane:%s) ", vc_info); |
|---|
| 4623 | + vehicle_csi2_err_strncat(err_str, cur_str); |
|---|
| 4624 | + } |
|---|
| 4625 | + if (val & CSIHOST_ERR2_PHYERR_SOTHS) { |
|---|
| 4626 | + vehicle_csi2_find_err_vc((val >> 4) & 0xf, vc_info); |
|---|
| 4627 | + snprintf(cur_str, CSI_ERRSTR_LEN, "(sot,lane:%s) ", vc_info); |
|---|
| 4628 | + vehicle_csi2_err_strncat(err_str, cur_str); |
|---|
| 4629 | + } |
|---|
| 4630 | + if (val & CSIHOST_ERR2_ECC_CORRECTED) { |
|---|
| 4631 | + vehicle_csi2_find_err_vc((val >> 8) & 0xf, vc_info); |
|---|
| 4632 | + snprintf(cur_str, CSI_ERRSTR_LEN, "(ecc,vc:%s) ", vc_info); |
|---|
| 4633 | + vehicle_csi2_err_strncat(err_str, cur_str); |
|---|
| 4634 | + } |
|---|
| 4635 | + if (val & CSIHOST_ERR2_ERR_ID) { |
|---|
| 4636 | + vehicle_csi2_find_err_vc((val >> 12) & 0xf, vc_info); |
|---|
| 4637 | + snprintf(cur_str, CSI_ERRSTR_LEN, "(err id,vc:%s) ", vc_info); |
|---|
| 4638 | + vehicle_csi2_err_strncat(err_str, cur_str); |
|---|
| 4639 | + } |
|---|
| 4640 | + if (val & CSIHOST_ERR2_PHYERR_CODEHS) { |
|---|
| 4641 | + snprintf(cur_str, CSI_ERRSTR_LEN, "(err code) "); |
|---|
| 4642 | + vehicle_csi2_err_strncat(err_str, cur_str); |
|---|
| 4643 | + } |
|---|
| 4644 | + cif->err_state.err_val = val; |
|---|
| 4645 | + cif->err_state.err_num = 2; |
|---|
| 4646 | + strscpy(cif->err_state.err_str, err_str, CSI_ERRSTR_LEN); |
|---|
| 4647 | + queue_work(cif->err_state.err_print_wq, &cif->err_state.work); |
|---|
| 4648 | + |
|---|
| 4546 | 4649 | } |
|---|
| 4547 | 4650 | |
|---|
| 4548 | 4651 | return IRQ_HANDLED; |
|---|
| .. | .. |
|---|
| 4661 | 4764 | cif->stopping = true; |
|---|
| 4662 | 4765 | cancel_delayed_work_sync(&(cif->work)); |
|---|
| 4663 | 4766 | flush_delayed_work(&(cif->work)); |
|---|
| 4767 | + cancel_work_sync(&cif->err_state.work); |
|---|
| 4664 | 4768 | |
|---|
| 4665 | 4769 | ret = wait_event_timeout(cif->wq_stopped, |
|---|
| 4666 | 4770 | cif->state != RKCIF_STATE_STREAMING, |
|---|
| .. | .. |
|---|
| 5118 | 5222 | if (inf_id == RKCIF_MIPI_LVDS) { |
|---|
| 5119 | 5223 | /* 5. set csi2-mipi-dphy reg */ |
|---|
| 5120 | 5224 | if (cif->dphy_hw->chip_id == CHIP_ID_RK3588 || |
|---|
| 5225 | + cif->dphy_hw->chip_id == CHIP_ID_RK3568 || |
|---|
| 5121 | 5226 | cif->dphy_hw->chip_id == CHIP_ID_RK3562) |
|---|
| 5122 | 5227 | cif->dphy_hw->csi2_dphy_base = cif->csi2_dphy_base; |
|---|
| 5123 | 5228 | |
|---|
| .. | .. |
|---|
| 5140 | 5245 | init_waitqueue_head(&cif->wq_stopped); |
|---|
| 5141 | 5246 | |
|---|
| 5142 | 5247 | spin_lock_init(&cif->vbq_lock); |
|---|
| 5248 | + |
|---|
| 5249 | + INIT_WORK(&cif->err_state.work, vehicle_csi2_err_print_work); |
|---|
| 5250 | + cif->err_state.err_print_wq = create_workqueue("cis2_err_print_queue"); |
|---|
| 5251 | + if (cif->err_state.err_print_wq == NULL) { |
|---|
| 5252 | + dev_err(dev, "%s: %s create failed.\n", __func__, |
|---|
| 5253 | + "csi2_err_print_wq"); |
|---|
| 5254 | + } |
|---|
| 5143 | 5255 | |
|---|
| 5144 | 5256 | return 0; |
|---|
| 5145 | 5257 | } |
|---|
| .. | .. |
|---|
| 5211 | 5323 | free_irq(cif->csi2_irq1, cif); |
|---|
| 5212 | 5324 | free_irq(cif->csi2_irq2, cif); |
|---|
| 5213 | 5325 | } |
|---|
| 5326 | + if (cif->err_state.err_print_wq) { |
|---|
| 5327 | + flush_workqueue(cif->err_state.err_print_wq); |
|---|
| 5328 | + destroy_workqueue(cif->err_state.err_print_wq); |
|---|
| 5329 | + } |
|---|
| 5214 | 5330 | |
|---|
| 5215 | 5331 | return 0; |
|---|
| 5216 | 5332 | } |
|---|