From 4f7e1db593a64719f32c8193e16de44d4e4e378a Mon Sep 17 00:00:00 2001 From: Zefa Chen Date: Mon, 20 Jan 2025 17:41:01 +0800 Subject: [PATCH 1/6] media: rockchip: vicap support use switch device to switch sensor connect to one dphy Signed-off-by: Zefa Chen Change-Id: I7940fcb2a9dc6cb2506d1e1692da034d2b6a0503 --- drivers/media/platform/rockchip/cif/capture.c | 516 +++++++++++------- drivers/media/platform/rockchip/cif/dev.c | 29 +- drivers/media/platform/rockchip/cif/dev.h | 20 +- drivers/media/platform/rockchip/cif/hw.c | 29 +- drivers/media/platform/rockchip/cif/hw.h | 5 + .../media/platform/rockchip/cif/mipi-csi2.c | 54 +- .../media/platform/rockchip/cif/mipi-csi2.h | 1 + drivers/media/platform/rockchip/cif/regs.h | 6 + .../media/platform/rockchip/cif/subdev-itf.c | 71 ++- 9 files changed, 512 insertions(+), 219 deletions(-) diff --git a/drivers/media/platform/rockchip/cif/capture.c b/drivers/media/platform/rockchip/cif/capture.c index 7bf312c49ca1..8f19b4ad44db 100644 --- a/drivers/media/platform/rockchip/cif/capture.c +++ b/drivers/media/platform/rockchip/cif/capture.c @@ -26,6 +26,7 @@ #include #include #include +#include #include "dev.h" #include "mipi-csi2.h" @@ -1893,6 +1894,12 @@ static void rkcif_s_rx_buffer(struct rkcif_stream *stream, struct rkisp_rx_buf * return; rx_buf = to_cif_rx_buf(dbufs); stream->last_buf_toisp = rx_buf; + if (dev->switch_info.is_use_switch) { + if (!rx_buf->is_init[dev->csi_host_idx_def]) { + dbufs->is_init = false; + rx_buf->is_init[dev->csi_host_idx_def] = true; + } + } if ((dev->rdbk_debug && dbufs->sequence < 15) || rkcif_debug == 3) @@ -2187,6 +2194,7 @@ static void rkcif_assign_new_buffer_init_toisp(struct rkcif_stream *stream, struct rkcif_rx_buffer *rx_buf; struct v4l2_mbus_config *mbus_cfg = &dev->active_sensor->mbus; struct rkmodule_capture_info *capture_info = &dev->channels[channel_id].capture_info; + struct rkcif_stream *buf_stream = stream; u32 frm0_addr_y; u32 frm1_addr_y; u32 buff_addr_y; @@ -2202,67 +2210,70 @@ static void rkcif_assign_new_buffer_init_toisp(struct rkcif_stream *stream, frm1_addr_y = get_dvp_reg_index_of_frm1_y_addr(channel_id); } - spin_lock_irqsave(&stream->vbq_lock, flags); + spin_lock_irqsave(&buf_stream->vbq_lock, flags); + if (dev->switch_info.is_use_switch && + dev->switch_info.switch_dev->switch_info.is_init_buf) + buf_stream = &dev->switch_info.switch_dev->stream[stream->id]; - if (!stream->curr_buf_toisp) { - if (!list_empty(&stream->rx_buf_head)) { - rx_buf = list_first_entry(&stream->rx_buf_head, + if (!buf_stream->curr_buf_toisp) { + if (!list_empty(&buf_stream->rx_buf_head)) { + rx_buf = list_first_entry(&buf_stream->rx_buf_head, struct rkcif_rx_buffer, list); if (rx_buf) { list_del(&rx_buf->list); - stream->curr_buf_toisp = rx_buf; + buf_stream->curr_buf_toisp = rx_buf; } } } - if (stream->curr_buf_toisp) { - buff_addr_y = stream->curr_buf_toisp->dummy.dma_addr; + if (buf_stream->curr_buf_toisp) { + buff_addr_y = buf_stream->curr_buf_toisp->dummy.dma_addr; if (capture_info->mode == RKMODULE_MULTI_DEV_COMBINE_ONE) { - rkcif_write_buff_addr_multi_dev_combine(stream, frm0_addr_y, 0, + rkcif_write_buff_addr_multi_dev_combine(buf_stream, frm0_addr_y, 0, buff_addr_y, 0, false); } else { rkcif_write_register(dev, frm0_addr_y, buff_addr_y); } } else { - if (stream->lack_buf_cnt < 2) - stream->lack_buf_cnt++; - stream->toisp_buf_state.state = RKCIF_TOISP_BUF_LOSS; + if (buf_stream->lack_buf_cnt < 2) + buf_stream->lack_buf_cnt++; + buf_stream->toisp_buf_state.state = RKCIF_TOISP_BUF_LOSS; } - if (!stream->next_buf_toisp) { - if (!list_empty(&stream->rx_buf_head)) { - rx_buf = list_first_entry(&stream->rx_buf_head, + if (!buf_stream->next_buf_toisp) { + if (!list_empty(&buf_stream->rx_buf_head)) { + rx_buf = list_first_entry(&buf_stream->rx_buf_head, struct rkcif_rx_buffer, list); if (rx_buf) { list_del(&rx_buf->list); - stream->next_buf_toisp = rx_buf; + buf_stream->next_buf_toisp = rx_buf; } else { - stream->next_buf_toisp = stream->curr_buf_toisp; + buf_stream->next_buf_toisp = buf_stream->curr_buf_toisp; } - } else if (stream->curr_buf_toisp) { - stream->next_buf_toisp = stream->curr_buf_toisp; - stream->toisp_buf_state.state = RKCIF_TOISP_BUF_THESAME; - if (stream->lack_buf_cnt < 2) - stream->lack_buf_cnt++; + } else if (buf_stream->curr_buf_toisp) { + buf_stream->next_buf_toisp = buf_stream->curr_buf_toisp; + buf_stream->toisp_buf_state.state = RKCIF_TOISP_BUF_THESAME; + if (buf_stream->lack_buf_cnt < 2) + buf_stream->lack_buf_cnt++; } } - if (stream->next_buf_toisp) { - buff_addr_y = stream->next_buf_toisp->dummy.dma_addr; + if (buf_stream->next_buf_toisp) { + buff_addr_y = buf_stream->next_buf_toisp->dummy.dma_addr; if (capture_info->mode == RKMODULE_MULTI_DEV_COMBINE_ONE) { - rkcif_write_buff_addr_multi_dev_combine(stream, frm1_addr_y, 0, + rkcif_write_buff_addr_multi_dev_combine(buf_stream, frm1_addr_y, 0, buff_addr_y, 0, false); } else { rkcif_write_register(dev, frm1_addr_y, buff_addr_y); } } else { - if (stream->lack_buf_cnt < 2) - stream->lack_buf_cnt++; + if (buf_stream->lack_buf_cnt < 2) + buf_stream->lack_buf_cnt++; } - spin_unlock_irqrestore(&stream->vbq_lock, flags); - stream->buf_owner = RKCIF_DMAEN_BY_ISP; + spin_unlock_irqrestore(&buf_stream->vbq_lock, flags); + buf_stream->buf_owner = RKCIF_DMAEN_BY_ISP; } void rkcif_dphy_quick_stream(struct rkcif_device *dev, int on) @@ -2296,16 +2307,20 @@ static int rkcif_assign_new_buffer_update_toisp(struct rkcif_stream *stream, struct rkcif_rx_buffer *buffer = NULL; struct rkcif_rx_buffer *active_buf = NULL; struct sditf_priv *priv = dev->sditf[0]; + struct rkcif_stream *buf_stream = stream; u32 frm_addr_y, buff_addr_y; unsigned long flags; - spin_lock_irqsave(&stream->vbq_lock, flags); + if (dev->switch_info.is_use_switch && + dev->switch_info.switch_dev->switch_info.is_init_buf) + buf_stream = &dev->switch_info.switch_dev->stream[stream->id]; + spin_lock_irqsave(&buf_stream->vbq_lock, flags); if (dev->is_stop_skip) { dev->is_stop_skip = false; if (((stream->frame_idx - 1) % stream->thunderboot_skip_interval) != 0) { stream->thunderboot_skip_interval = 0; stream->frame_idx = stream->sequence + 1; - spin_unlock_irqrestore(&stream->vbq_lock, flags); + spin_unlock_irqrestore(&buf_stream->vbq_lock, flags); return 0; } else { stream->thunderboot_skip_interval = 0; @@ -2315,7 +2330,7 @@ static int rkcif_assign_new_buffer_update_toisp(struct rkcif_stream *stream, if (dev->is_thunderboot && stream->thunderboot_skip_interval && ((stream->frame_idx - 1) % stream->thunderboot_skip_interval) != 0) { - spin_unlock_irqrestore(&stream->vbq_lock, flags); + spin_unlock_irqrestore(&buf_stream->vbq_lock, flags); return 0; } if (stream->thunderboot_skip_interval) { @@ -2333,7 +2348,7 @@ static int rkcif_assign_new_buffer_update_toisp(struct rkcif_stream *stream, stream->id, stream->sequence, stream->frame_idx - 1); - spin_unlock_irqrestore(&stream->vbq_lock, flags); + spin_unlock_irqrestore(&buf_stream->vbq_lock, flags); if (mbus_cfg->type == V4L2_MBUS_CSI2_DPHY || mbus_cfg->type == V4L2_MBUS_CSI2_CPHY || @@ -2350,21 +2365,21 @@ static int rkcif_assign_new_buffer_update_toisp(struct rkcif_stream *stream, spin_lock_irqsave(&stream->vbq_lock, flags); if (stream->cur_skip_frame) goto out_get_buf; - memset(&stream->toisp_buf_state, 0, sizeof(stream->toisp_buf_state)); - if (!list_empty(&stream->rx_buf_head)) { - if (stream->curr_buf_toisp && stream->next_buf_toisp && - stream->curr_buf_toisp != stream->next_buf_toisp) - stream->toisp_buf_state.state = RKCIF_TOISP_BUF_ROTATE; + memset(&buf_stream->toisp_buf_state, 0, sizeof(stream->toisp_buf_state)); + if (!list_empty(&buf_stream->rx_buf_head)) { + if (buf_stream->curr_buf_toisp && buf_stream->next_buf_toisp && + buf_stream->curr_buf_toisp != buf_stream->next_buf_toisp) + buf_stream->toisp_buf_state.state = RKCIF_TOISP_BUF_ROTATE; else - stream->toisp_buf_state.state = RKCIF_TOISP_BUF_LOSS; + buf_stream->toisp_buf_state.state = RKCIF_TOISP_BUF_LOSS; if (stream->frame_phase == CIF_CSI_FRAME0_READY) { - active_buf = stream->curr_buf_toisp; + active_buf = buf_stream->curr_buf_toisp; - buffer = list_first_entry(&stream->rx_buf_head, + buffer = list_first_entry(&buf_stream->rx_buf_head, struct rkcif_rx_buffer, list); if (buffer) { list_del(&buffer->list); - stream->curr_buf_toisp = buffer; + buf_stream->curr_buf_toisp = buffer; } if (priv && (priv->mode.rdbk_mode == RKISP_VICAP_RDBK_AUTO || priv->mode.rdbk_mode == RKISP_VICAP_RDBK_AUTO_ONE_FRAME)) { @@ -2398,12 +2413,12 @@ static int rkcif_assign_new_buffer_update_toisp(struct rkcif_stream *stream, rkcif_rdbk_with_tools(stream, active_buf); } } else if (stream->frame_phase == CIF_CSI_FRAME1_READY) { - active_buf = stream->next_buf_toisp; - buffer = list_first_entry(&stream->rx_buf_head, + active_buf = buf_stream->next_buf_toisp; + buffer = list_first_entry(&buf_stream->rx_buf_head, struct rkcif_rx_buffer, list); if (buffer) { list_del(&buffer->list); - stream->next_buf_toisp = buffer; + buf_stream->next_buf_toisp = buffer; } if (priv && (priv->mode.rdbk_mode == RKISP_VICAP_RDBK_AUTO || priv->mode.rdbk_mode == RKISP_VICAP_RDBK_AUTO_ONE_FRAME)) { @@ -2437,42 +2452,42 @@ static int rkcif_assign_new_buffer_update_toisp(struct rkcif_stream *stream, rkcif_rdbk_with_tools(stream, active_buf); } } - if (stream->lack_buf_cnt) - stream->lack_buf_cnt--; + if (buf_stream->lack_buf_cnt) + buf_stream->lack_buf_cnt--; } else { if (priv->mode.rdbk_mode < RKISP_VICAP_RDBK_AIQ) goto out_get_buf; - if (stream->lack_buf_cnt < 2) - stream->lack_buf_cnt++; + if (buf_stream->lack_buf_cnt < 2) + buf_stream->lack_buf_cnt++; if (dev->hw_dev->dummy_buf.vaddr) { if (stream->frame_phase == CIF_CSI_FRAME0_READY) { - active_buf = stream->curr_buf_toisp; + active_buf = buf_stream->curr_buf_toisp; } else { - active_buf = stream->next_buf_toisp; + active_buf = buf_stream->next_buf_toisp; } - } else if (stream->curr_buf_toisp && stream->next_buf_toisp && - stream->curr_buf_toisp != stream->next_buf_toisp) { + } else if (buf_stream->curr_buf_toisp && buf_stream->next_buf_toisp && + buf_stream->curr_buf_toisp != buf_stream->next_buf_toisp) { if (stream->frame_phase == CIF_CSI_FRAME0_READY) { - active_buf = stream->curr_buf_toisp; - stream->curr_buf_toisp = stream->next_buf_toisp; - buffer = stream->next_buf_toisp; + active_buf = buf_stream->curr_buf_toisp; + buf_stream->curr_buf_toisp = buf_stream->next_buf_toisp; + buffer = buf_stream->next_buf_toisp; } else if (stream->frame_phase == CIF_CSI_FRAME1_READY) { - active_buf = stream->next_buf_toisp; - stream->next_buf_toisp = stream->curr_buf_toisp; - buffer = stream->curr_buf_toisp; + active_buf = buf_stream->next_buf_toisp; + buf_stream->next_buf_toisp = buf_stream->curr_buf_toisp; + buffer = buf_stream->curr_buf_toisp; } - stream->toisp_buf_state.state = RKCIF_TOISP_BUF_THESAME; + buf_stream->toisp_buf_state.state = RKCIF_TOISP_BUF_THESAME; if (stream->cifdev->rdbk_debug) v4l2_info(&stream->cifdev->v4l2_dev, "stream[%d] hold buf %x\n", stream->id, - (u32)stream->next_buf_toisp->dummy.dma_addr); + (u32)buf_stream->next_buf_toisp->dummy.dma_addr); } else { - stream->toisp_buf_state.state = RKCIF_TOISP_BUF_LOSS; + buf_stream->toisp_buf_state.state = RKCIF_TOISP_BUF_LOSS; - active_buf = stream->curr_buf_toisp; - stream->curr_buf_toisp = NULL; - stream->next_buf_toisp = NULL; + active_buf = buf_stream->curr_buf_toisp; + buf_stream->curr_buf_toisp = NULL; + buf_stream->next_buf_toisp = NULL; } @@ -2507,7 +2522,7 @@ static int rkcif_assign_new_buffer_update_toisp(struct rkcif_stream *stream, rkcif_rdbk_with_tools(stream, active_buf); } out_get_buf: - stream->frame_phase_cache = stream->frame_phase; + buf_stream->frame_phase_cache = stream->frame_phase; if (buffer) { buff_addr_y = buffer->dummy.dma_addr; if (capture_info->mode == RKMODULE_MULTI_DEV_COMBINE_ONE) { @@ -2533,7 +2548,7 @@ out_get_buf: rkcif_write_register(dev, frm_addr_y, buff_addr_y); } } - spin_unlock_irqrestore(&stream->vbq_lock, flags); + spin_unlock_irqrestore(&buf_stream->vbq_lock, flags); return 0; } @@ -2555,29 +2570,34 @@ void rkcif_assign_check_buffer_update_toisp(struct rkcif_stream *stream) struct v4l2_mbus_config *mbus_cfg = &dev->active_sensor->mbus; struct rkcif_rx_buffer *buffer = NULL; struct rkmodule_capture_info *capture_info = &dev->channels[stream->id].capture_info; + struct rkcif_stream *buf_stream = stream; u32 frm_addr_y, buff_addr_y; int frame_phase = 0; int frame_phase_next = 0; bool is_dual_update = false; uint32_t cur_dma_addr = 0, next_dma_addr = 0; - if (stream->toisp_buf_state.state == RKCIF_TOISP_BUF_ROTATE || - (stream->toisp_buf_state.state == RKCIF_TOISP_BUF_THESAME && - stream->toisp_buf_state.check_cnt >= 1) || - (stream->toisp_buf_state.state == RKCIF_TOISP_BUF_LOSS && - stream->toisp_buf_state.check_cnt >= 2)) { + if (dev->switch_info.is_use_switch && + dev->switch_info.switch_dev->switch_info.is_init_buf) + buf_stream = &dev->switch_info.switch_dev->stream[stream->id]; + + if (buf_stream->toisp_buf_state.state == RKCIF_TOISP_BUF_ROTATE || + (buf_stream->toisp_buf_state.state == RKCIF_TOISP_BUF_THESAME && + buf_stream->toisp_buf_state.check_cnt >= 1) || + (buf_stream->toisp_buf_state.state == RKCIF_TOISP_BUF_LOSS && + buf_stream->toisp_buf_state.check_cnt >= 2)) { if ((dev->rdbk_debug > 2 && stream->frame_idx < 15) || rkcif_debug == 3) { - if (stream->curr_buf_toisp) - cur_dma_addr = stream->curr_buf_toisp->dummy.dma_addr; - if (stream->next_buf_toisp) - next_dma_addr = stream->next_buf_toisp->dummy.dma_addr; + if (buf_stream->curr_buf_toisp) + cur_dma_addr = buf_stream->curr_buf_toisp->dummy.dma_addr; + if (buf_stream->next_buf_toisp) + next_dma_addr = buf_stream->next_buf_toisp->dummy.dma_addr; v4l2_info(&dev->v4l2_dev, "stream[%d] addr check not equal 0x%x 0x%x state %d chech_cnt %d\n", stream->id, cur_dma_addr, - next_dma_addr, stream->toisp_buf_state.state, stream->toisp_buf_state.check_cnt); + next_dma_addr, buf_stream->toisp_buf_state.state, buf_stream->toisp_buf_state.check_cnt); } return; } @@ -2585,20 +2605,20 @@ void rkcif_assign_check_buffer_update_toisp(struct rkcif_stream *stream) "stream[%d] addr check 0x%x 0x%x state %d chech_cnt %d\n", stream->id, cur_dma_addr, - next_dma_addr, stream->toisp_buf_state.state, stream->toisp_buf_state.check_cnt); + next_dma_addr, buf_stream->toisp_buf_state.state, buf_stream->toisp_buf_state.check_cnt); if (stream->frame_phase == 0) stream->frame_phase = CIF_CSI_FRAME0_READY; frame_phase = stream->frame_phase; - if (stream->toisp_buf_state.state == RKCIF_TOISP_BUF_LOSS && - stream->toisp_buf_state.check_cnt == 0) + if (buf_stream->toisp_buf_state.state == RKCIF_TOISP_BUF_LOSS && + buf_stream->toisp_buf_state.check_cnt == 0) is_dual_update = true; if (dev->rdbk_debug > 2 && stream->frame_idx < 15) v4l2_info(&dev->v4l2_dev, "stream[%d] check update, lack_buf %d\n", - stream->id, stream->lack_buf_cnt); + stream->id, buf_stream->lack_buf_cnt); if (mbus_cfg->type == V4L2_MBUS_CSI2_DPHY || mbus_cfg->type == V4L2_MBUS_CSI2_CPHY || mbus_cfg->type == V4L2_MBUS_CCP2) { @@ -2610,14 +2630,14 @@ void rkcif_assign_check_buffer_update_toisp(struct rkcif_stream *stream) get_dvp_reg_index_of_frm0_y_addr(stream->id) : get_dvp_reg_index_of_frm1_y_addr(stream->id); } - if (!list_empty(&stream->rx_buf_head)) { + if (!list_empty(&buf_stream->rx_buf_head)) { if (frame_phase == CIF_CSI_FRAME0_READY) { - buffer = list_first_entry(&stream->rx_buf_head, + buffer = list_first_entry(&buf_stream->rx_buf_head, struct rkcif_rx_buffer, list); if (buffer) { list_del(&buffer->list); - stream->curr_buf_toisp = buffer; - buff_addr_y = stream->curr_buf_toisp->dummy.dma_addr; + buf_stream->curr_buf_toisp = buffer; + buff_addr_y = buf_stream->curr_buf_toisp->dummy.dma_addr; if (capture_info->mode == RKMODULE_MULTI_DEV_COMBINE_ONE) { rkcif_write_buff_addr_multi_dev_combine(stream, frm_addr_y, 0, @@ -2632,15 +2652,15 @@ void rkcif_assign_check_buffer_update_toisp(struct rkcif_stream *stream) "stream[%d] check update, seq %d, addr 0x%x, buf 0x%x\n", stream->id, stream->frame_idx - 1, frm_addr_y, - (u32)stream->curr_buf_toisp->dummy.dma_addr); + (u32)buf_stream->curr_buf_toisp->dummy.dma_addr); } } else if (frame_phase == CIF_CSI_FRAME1_READY) { - buffer = list_first_entry(&stream->rx_buf_head, + buffer = list_first_entry(&buf_stream->rx_buf_head, struct rkcif_rx_buffer, list); if (buffer) { list_del(&buffer->list); - stream->next_buf_toisp = buffer; - buff_addr_y = stream->next_buf_toisp->dummy.dma_addr; + buf_stream->next_buf_toisp = buffer; + buff_addr_y = buf_stream->next_buf_toisp->dummy.dma_addr; if (capture_info->mode == RKMODULE_MULTI_DEV_COMBINE_ONE) { rkcif_write_buff_addr_multi_dev_combine(stream, frm_addr_y, 0, @@ -2655,11 +2675,11 @@ void rkcif_assign_check_buffer_update_toisp(struct rkcif_stream *stream) "stream[%d] check update, seq %d, addr 0x%x, buf 0x%x\n", stream->id, stream->frame_idx - 1, frm_addr_y, - (u32)stream->next_buf_toisp->dummy.dma_addr); + (u32)buf_stream->next_buf_toisp->dummy.dma_addr); } } - if (stream->lack_buf_cnt) - stream->lack_buf_cnt--; + if (buf_stream->lack_buf_cnt) + buf_stream->lack_buf_cnt--; } if (is_dual_update) { frame_phase_next = frame_phase & CIF_CSI_FRAME0_READY ? @@ -2683,10 +2703,10 @@ void rkcif_assign_check_buffer_update_toisp(struct rkcif_stream *stream) get_dvp_reg_index_of_frm1_y_addr(stream->id); } if (frame_phase == CIF_CSI_FRAME0_READY) - stream->next_buf_toisp = stream->curr_buf_toisp; + buf_stream->next_buf_toisp = buf_stream->curr_buf_toisp; else - stream->curr_buf_toisp = stream->next_buf_toisp; - buff_addr_y = stream->curr_buf_toisp->dummy.dma_addr; + buf_stream->curr_buf_toisp = buf_stream->next_buf_toisp; + buff_addr_y = buf_stream->curr_buf_toisp->dummy.dma_addr; if (capture_info->mode == RKMODULE_MULTI_DEV_COMBINE_ONE) { rkcif_write_buff_addr_multi_dev_combine(stream, frm_addr_y, 0, buff_addr_y, 0, false); @@ -2694,7 +2714,7 @@ void rkcif_assign_check_buffer_update_toisp(struct rkcif_stream *stream) rkcif_write_register(dev, frm_addr_y, buff_addr_y); } } - stream->toisp_buf_state.check_cnt++; + buf_stream->toisp_buf_state.check_cnt++; } static void rkcif_assign_new_buffer_init(struct rkcif_stream *stream, @@ -4647,7 +4667,7 @@ static u32 rkcif_get_split_dphy_mask_rv1103b(struct rkcif_device *dev) { u32 val = 0; - if (dev->hw_dev->dev_num == 2) + if (dev->hw_dev->dev_num >= 2) val = SW_DPHY_SPLIT_EN_RV1103B; return val; } @@ -4781,6 +4801,9 @@ static int rkcif_csi_channel_set_v1(struct rkcif_stream *stream, dev->chip_id < CHIP_RK3576_CIF ? CSI_START_INTEN(channel->id) : CSI_START_INTEN_RK3576(channel->id)); + if (dev->chip_id >= CHIP_RK3576_CIF) + rkcif_write_register_or(dev, CIF_REG_MIPI_LVDS_INTEN, + CSI_INF_END_INTEN_RK3576(channel->id)); if ((!priv || (priv && priv->mode.rdbk_mode >= RKISP_VICAP_RDBK_AIQ)) && detect_stream->is_line_wake_up) { @@ -4796,7 +4819,7 @@ static int rkcif_csi_channel_set_v1(struct rkcif_stream *stream, rkcif_write_register_or(dev, CIF_REG_MIPI_LVDS_INTEN, CSI_DMA_END_INTEN(channel->id)); } - if (stream->cifdev->id_use_cnt == 0) { + if (atomic_read(&stream->cifdev->id_use_cnt) == 0) { if (dev->chip_id > CHIP_RK3562_CIF) { val = CIF_MIPI_LVDS_SW_WATER_LINE_ENABLE | (CIF_MIPI_LVDS_SW_WATER_LINE_25 << 19); @@ -5003,9 +5026,9 @@ static int rkcif_csi_channel_set_v1(struct rkcif_stream *stream, rkcif_modify_frame_skip_config(stream); if (capture_info->mode == RKMODULE_MULTI_DEV_COMBINE_ONE) { if (index == (capture_info->multi_dev.dev_num - 1)) - stream->cifdev->id_use_cnt++; + atomic_inc(&stream->cifdev->id_use_cnt); } else { - stream->cifdev->id_use_cnt++; + atomic_inc(&stream->cifdev->id_use_cnt); } if (!(capture_info->mode == RKMODULE_MULTI_DEV_COMBINE_ONE && index < capture_info->multi_dev.dev_num - 1)) { @@ -5072,7 +5095,7 @@ static int rkcif_csi_channel_set_rv1126b(struct rkcif_stream *stream, rkcif_write_register_or(dev, CIF_REG_MIPI_LVDS_INTEN, CSI_DMA_END_INTEN(channel->id)); } - if (stream->cifdev->id_use_cnt == 0) { + if (atomic_read(&stream->cifdev->id_use_cnt) == 0) { val = (CIF_MIPI_LVDS_SW_WATER_LINE_25 << 19) | (dev->csi_host_idx << 1) | CSI_ENABLE_CAPTURE; if (stream->sw_dbg_en) { @@ -5213,9 +5236,9 @@ static int rkcif_csi_channel_set_rv1126b(struct rkcif_stream *stream, rkcif_modify_frame_skip_config(stream); if (capture_info->mode == RKMODULE_MULTI_DEV_COMBINE_ONE) { if (index == (capture_info->multi_dev.dev_num - 1)) - stream->cifdev->id_use_cnt++; + atomic_inc(&stream->cifdev->id_use_cnt); } else { - stream->cifdev->id_use_cnt++; + atomic_inc(&stream->cifdev->id_use_cnt); } if (!(capture_info->mode == RKMODULE_MULTI_DEV_COMBINE_ONE && index < capture_info->multi_dev.dev_num - 1)) { @@ -5338,7 +5361,9 @@ static int rkcif_csi_stream_start(struct rkcif_stream *stream, unsigned int mode rkcif_csi_channel_set_v1(stream, channel, mbus_type, mode, i); } } else { - rkcif_csi_channel_set_v1(stream, channel, mbus_type, mode, 0); + if (!dev->switch_info.is_use_switch || + atomic_inc_return(&dev->hw_dev->switch_stream_cnt[dev->switch_info.host_idx]) == 1) + rkcif_csi_channel_set_v1(stream, channel, mbus_type, mode, 0); } } else { rkcif_csi_channel_set_rv1126b(stream, channel, mbus_type, mode, 0); @@ -5384,8 +5409,19 @@ static void rkcif_stream_stop(struct rkcif_stream *stream) u32 val; int id; int i = 0; + int ret = 0; + + if (cif_dev->switch_info.is_use_switch) { + ret = atomic_dec_if_positive(&cif_dev->hw_dev->switch_stream_cnt[cif_dev->switch_info.host_idx]); + if (ret) { + stream->state = RKCIF_STATE_READY; + stream->dma_en = 0; + return; + } + } + + atomic_dec_if_positive(&stream->cifdev->id_use_cnt); - stream->cifdev->id_use_cnt--; if (mbus_cfg->type == V4L2_MBUS_CSI2_DPHY || mbus_cfg->type == V4L2_MBUS_CSI2_CPHY || mbus_cfg->type == V4L2_MBUS_CCP2) { @@ -5436,7 +5472,7 @@ static void rkcif_stream_stop(struct rkcif_stream *stream) rkcif_write_register_and(cif_dev, CIF_REG_MIPI_LVDS_INTEN, ~CSI_ALL_ERROR_INTEN); } else { - if (stream->cifdev->id_use_cnt == 0) { + if (atomic_read(&stream->cifdev->id_use_cnt) == 0) { rkcif_write_register_and(cif_dev, CIF_REG_MIPI_LVDS_INTEN, ~CSI_ALL_ERROR_INTEN_V1); if (cif_dev->channels[id].capture_info.mode == RKMODULE_MULTI_DEV_COMBINE_ONE) { @@ -6739,11 +6775,10 @@ void rkcif_do_stop_stream(struct rkcif_stream *stream, cur_time = rkcif_time_get_ns(dev); if (cur_time > fs_time && cur_time - fs_time < (frame_time_ns - 10000000) && - stream->is_in_vblank) { + stream->is_in_vblank) rkcif_stream_stop(stream); - } else { + else stream->stopping = true; - } } else { stream->stopping = true; } @@ -6917,6 +6952,7 @@ void rkcif_do_stop_stream(struct rkcif_stream *stream, } stream->crop_mask = 0; stream->frame_loss = 0; + stream->is_fb_first_frame = true; } if (mode == RKCIF_STREAM_MODE_CAPTURE) { tasklet_disable(&stream->vb_done_tasklet); @@ -8495,7 +8531,8 @@ int rkcif_do_start_stream(struct rkcif_stream *stream, enum rkcif_stream_mode mo } } else { csi_info.csi_num = 1; - dev->csi_host_idx = dev->csi_host_idx_def; + if (!dev->switch_info.is_use_switch) + dev->csi_host_idx = dev->csi_host_idx_def; csi_info.csi_idx[0] = dev->csi_host_idx; } dev->csi_info = csi_info; @@ -9730,6 +9767,8 @@ int rkcif_quick_stream_on(struct rkcif_device *dev, bool is_intr) for (i = 0; i < stream_num; i++) dev->stream[i].cur_skip_frame = dev->stream[i].skip_frame; dev->sditf[0]->mode.rdbk_mode = dev->sditf[0]->mode_src.rdbk_mode; + if (dev->switch_info.is_use_switch) + atomic_inc(&dev->hw_dev->switch_stream_cnt[dev->switch_info.host_idx]); if (dev->sditf[0]->mode.rdbk_mode < RKISP_VICAP_RDBK_AIQ) { for (i = 0; i < stream_num; i++) { stream = &dev->stream[i]; @@ -10052,6 +10091,8 @@ static long rkcif_ioctl_default(struct file *file, void *fh, cur_stream->to_en_dma = RKCIF_DMAEN_BY_VICAP; rkcif_enable_dma_capture(cur_stream, true); } + if (dev->switch_info.is_use_switch) + atomic_inc(&dev->hw_dev->switch_stream_cnt[dev->switch_info.host_idx]); } mutex_lock(&stream->cifdev->stream_lock); on = 1; @@ -13902,6 +13943,12 @@ static void rkcif_deal_sof(struct rkcif_device *cif_dev) struct v4l2_subdev *sd = NULL; struct rkisp_vicap_sof sof = {0}; + detect_stream->fs_cnt_in_single_frame++; + if ((!cif_dev->sditf[0] || + cif_dev->sditf[0]->mode.rdbk_mode >= RKISP_VICAP_RDBK_AIQ) && + detect_stream->fs_cnt_in_single_frame > 1) + return; + spin_lock_irqsave(&detect_stream->fps_lock, flags); detect_stream->readout.fs_timestamp = rkcif_time_get_ns(cif_dev); spin_unlock_irqrestore(&detect_stream->fps_lock, flags); @@ -13922,7 +13969,8 @@ static void rkcif_deal_sof(struct rkcif_device *cif_dev) (!detect_stream->dma_en) && cif_dev->chip_id < CHIP_RK3576_CIF) return; if (cif_dev->sync_cfg.type != NO_SYNC_MODE && - cif_dev->sync_cfg.type != SOFT_SYNC_MODE) { + cif_dev->sync_cfg.type != SOFT_SYNC_MODE && + cif_dev->is_detect_group_sync) { struct rkcif_multi_sync_config *sync_config; sync_config = &hw->sync_config[cif_dev->sync_cfg.group]; @@ -14002,9 +14050,9 @@ static void rkcif_deal_sof(struct rkcif_device *cif_dev) detect_stream->id, rkcif_get_sof(cif_dev), detect_stream->frame_idx); + if (rkcif_check_frame_active(cif_dev)) + detect_stream->frame_idx++; } - if (rkcif_check_frame_active(cif_dev)) - detect_stream->frame_idx++; spin_unlock_irqrestore(&detect_stream->vbq_lock, flags); if (detect_stream->cifdev->rdbk_debug && detect_stream->frame_idx < 15 && @@ -14067,7 +14115,6 @@ static bool rkcif_check_buffer_prepare(struct rkcif_stream *stream) v4l2_err(&cif_dev->v4l2_dev, "ERR: loss long frame in readback mode\n"); } - spin_unlock_irqrestore(&cif_dev->hw_dev->group_lock, flags); return is_update; } @@ -14364,9 +14411,62 @@ out_suspend: return 0; } +static void rkcif_clean_buffer_state(struct rkcif_stream *stream) +{ + struct sditf_priv *priv = stream->cifdev->sditf[0]; + unsigned long flags; + + spin_lock_irqsave(&stream->vbq_lock, flags); + if (!priv || priv->mode.rdbk_mode == RKISP_VICAP_RDBK_AIQ) { + if (rkcif_get_interlace_mode(stream) == RKCIF_INTERLACE_SOFT || + rkcif_get_interlace_mode(stream) == RKCIF_INTERLACE_SOFT_AUTO) { + if (stream->curr_buf == stream->next_buf) { + if (stream->curr_buf) + list_add_tail(&stream->curr_buf->queue, &stream->buf_head); + } else { + if (stream->curr_buf) + list_add_tail(&stream->curr_buf->queue, &stream->buf_head); + if (stream->next_buf) + list_add_tail(&stream->next_buf->queue, &stream->buf_head); + } + stream->curr_buf = NULL; + stream->next_buf = NULL; + } + } else { + if (priv->mode.rdbk_mode < RKISP_VICAP_RDBK_AIQ) { + if (stream->curr_buf_toisp == stream->next_buf_toisp) { + if (stream->curr_buf_toisp) + list_add_tail(&stream->curr_buf_toisp->list, &stream->rx_buf_head); + } else { + if (stream->curr_buf_toisp) + list_add_tail(&stream->curr_buf_toisp->list, &stream->rx_buf_head); + if (stream->next_buf_toisp) + list_add_tail(&stream->next_buf_toisp->list, &stream->rx_buf_head); + } + stream->curr_buf_toisp = NULL; + stream->next_buf_toisp = NULL; + } else { + if (stream->curr_buf_toisp == stream->next_buf_toisp) { + if (stream->curr_buf_toisp) + list_add_tail(&stream->curr_buf_toisp->list, &stream->rx_buf_head); + } else { + if (stream->curr_buf_toisp) + list_add_tail(&stream->curr_buf_toisp->list, &stream->rx_buf_head); + if (stream->next_buf_toisp) + list_add_tail(&stream->next_buf_toisp->list, &stream->rx_buf_head); + } + stream->curr_buf_toisp = NULL; + stream->next_buf_toisp = NULL; + } + } + + spin_unlock_irqrestore(&stream->vbq_lock, flags); +} + int rkcif_stream_resume(struct rkcif_device *cif_dev, int mode) { struct rkcif_stream *stream = NULL; + struct rkcif_stream *tmp_stream = NULL; struct sditf_priv *priv = cif_dev->sditf[0]; struct v4l2_subdev *sd = NULL; int ret = 0; @@ -14446,52 +14546,17 @@ int rkcif_stream_resume(struct rkcif_device *cif_dev, int mode) stream->is_wait_single_cap = false; spin_unlock_irqrestore(&stream->cifdev->stream_spinlock, flags); } - spin_lock_irqsave(&stream->vbq_lock, flags); - if (!priv || priv->mode.rdbk_mode == RKISP_VICAP_RDBK_AIQ) { - if (rkcif_get_interlace_mode(stream) == RKCIF_INTERLACE_SOFT || - rkcif_get_interlace_mode(stream) == RKCIF_INTERLACE_SOFT_AUTO) { - if (stream->curr_buf == stream->next_buf) { - if (stream->curr_buf) - list_add_tail(&stream->curr_buf->queue, &stream->buf_head); - } else { - if (stream->curr_buf) - list_add_tail(&stream->curr_buf->queue, &stream->buf_head); - if (stream->next_buf) - list_add_tail(&stream->next_buf->queue, &stream->buf_head); - } - stream->curr_buf = NULL; - stream->next_buf = NULL; + if (cif_dev->switch_info.is_use_switch) { + if (atomic_read(&cif_dev->hw_dev->switch_stream_cnt[cif_dev->switch_info.host_idx]) == 0) { + tmp_stream = stream; + if (cif_dev->switch_info.switch_dev->switch_info.is_init_buf) + tmp_stream = &cif_dev->switch_info.switch_dev->stream[stream->id]; + rkcif_clean_buffer_state(tmp_stream); } } else { - if (priv->mode.rdbk_mode < RKISP_VICAP_RDBK_AIQ) { - if (stream->curr_buf_toisp == stream->next_buf_toisp) { - if (stream->curr_buf_toisp) - list_add_tail(&stream->curr_buf_toisp->list, &stream->rx_buf_head); - } else { - if (stream->curr_buf_toisp) - list_add_tail(&stream->curr_buf_toisp->list, &stream->rx_buf_head); - if (stream->next_buf_toisp) - list_add_tail(&stream->next_buf_toisp->list, &stream->rx_buf_head); - } - stream->curr_buf_toisp = NULL; - stream->next_buf_toisp = NULL; - } else { - if (stream->curr_buf_toisp == stream->next_buf_toisp) { - if (stream->curr_buf_toisp) - list_add_tail(&stream->curr_buf_toisp->list, &stream->rx_buf_head); - } else { - if (stream->curr_buf_toisp) - list_add_tail(&stream->curr_buf_toisp->list, &stream->rx_buf_head); - if (stream->next_buf_toisp) - list_add_tail(&stream->next_buf_toisp->list, &stream->rx_buf_head); - } - stream->curr_buf_toisp = NULL; - stream->next_buf_toisp = NULL; - } + rkcif_clean_buffer_state(stream); } - spin_unlock_irqrestore(&stream->vbq_lock, flags); - is_single_dev = rkcif_check_single_dev_stream_on(cif_dev->hw_dev); if (priv) { if (stream->is_single_cap && stream->id == 0) { @@ -14526,7 +14591,8 @@ int rkcif_stream_resume(struct rkcif_device *cif_dev, int mode) if (cif_dev->chip_id == CHIP_RV1106_CIF || is_single_dev) sditf_disable_immediately(priv); if (!stream->rx_buf_num && - capture_mode == RKCIF_STREAM_MODE_TOISP_RDBK) { + capture_mode == RKCIF_STREAM_MODE_TOISP_RDBK && + (!cif_dev->switch_info.is_use_switch)) { if (cif_dev->resume_mode == RKISP_RTT_MODE_ONE_FRAME) rkcif_init_rx_buf(stream, 1); else @@ -14851,11 +14917,19 @@ static void rkcif_check_one_to_multi_sub_stream_stop_state(struct rkcif_device * } } +void rkcif_switch_change(struct rkcif_device *cif_dev, bool is_switch) +{ + if (is_switch) { + gpiod_direction_output_raw(cif_dev->switch_info.gpio_pin, 1); + } else { + gpiod_direction_output_raw(cif_dev->switch_info.gpio_pin, 0); + } +} + /* pingpong irq for rk3588 and next */ void rkcif_irq_pingpong_v1(struct rkcif_device *cif_dev) { struct rkcif_stream *stream; - struct rkcif_stream *detect_stream = &cif_dev->stream[0]; struct v4l2_mbus_config *mbus; struct csi_channel_info *channel = &cif_dev->channels[0]; unsigned int intstat, i = 0xff; @@ -14955,7 +15029,24 @@ void rkcif_irq_pingpong_v1(struct rkcif_device *cif_dev) if (mipi_id < 0) continue; - stream = &cif_dev->stream[mipi_id]; + if (cif_dev->switch_info.is_use_switch) { + if (cif_dev->switch_info.is_active) { + cif_dev->switch_info.is_active = false; + cif_dev->switch_info.switch_dev->switch_info.is_active = true; + stream = &cif_dev->stream[mipi_id]; + if (cif_dev->switch_info.switch_dev->stream[0].state == RKCIF_STATE_STREAMING) + rkcif_switch_change(cif_dev, !!cif_dev->switch_info.switch_dev->switch_info.gpio_val); + } else { + cif_dev->switch_info.is_active = true; + cif_dev->switch_info.switch_dev->switch_info.is_active = false; + stream = &cif_dev->switch_info.switch_dev->stream[mipi_id]; + if (cif_dev->stream[0].state == RKCIF_STATE_STREAMING) + rkcif_switch_change(cif_dev, !!cif_dev->switch_info.gpio_val); + } + + } else { + stream = &cif_dev->stream[mipi_id]; + } if (!cif_dev->sditf[0] || cif_dev->sditf[0]->mode.rdbk_mode >= RKISP_VICAP_RDBK_AIQ) stream->buf_wake_up_cnt++; @@ -15026,7 +15117,8 @@ void rkcif_irq_pingpong_v1(struct rkcif_device *cif_dev) } if (stream->dma_en & RKCIF_DMAEN_BY_VICAP) { if (cif_dev->sync_cfg.type == NO_SYNC_MODE || - cif_dev->sync_cfg.type == SOFT_SYNC_MODE) + cif_dev->sync_cfg.type == SOFT_SYNC_MODE || + !cif_dev->is_detect_group_sync) is_update = true; else is_update = rkcif_check_buffer_prepare(stream); @@ -15044,7 +15136,8 @@ void rkcif_irq_pingpong_v1(struct rkcif_device *cif_dev) "dma capture by isp, dma_en 0x%x\n", stream->dma_en); if (cif_dev->sync_cfg.type == NO_SYNC_MODE || - cif_dev->sync_cfg.type == SOFT_SYNC_MODE) + cif_dev->sync_cfg.type == SOFT_SYNC_MODE || + !cif_dev->is_detect_group_sync) is_update = true; else is_update = rkcif_check_buffer_prepare(stream); @@ -15060,35 +15153,53 @@ void rkcif_irq_pingpong_v1(struct rkcif_device *cif_dev) if (stream->is_single_cap && !stream->cur_skip_frame) { stream->is_single_cap = false; spin_unlock_irqrestore(&stream->cifdev->stream_spinlock, flags); - if (stream->dma_en & RKCIF_DMAEN_BY_ISP) - stream->to_stop_dma = RKCIF_DMAEN_BY_ISP; - else if (stream->dma_en & RKCIF_DMAEN_BY_VICAP) - stream->to_stop_dma = RKCIF_DMAEN_BY_VICAP; - else if (stream->dma_en & RKCIF_DMAEN_BY_ROCKIT) - stream->to_stop_dma = RKCIF_DMAEN_BY_ROCKIT; - rkcif_stop_dma_capture(stream); + if (cif_dev->switch_info.is_use_switch && + atomic_dec_if_positive(&cif_dev->hw_dev->switch_stream_cnt[cif_dev->switch_info.host_idx])) { + if (stream->dma_en & RKCIF_DMAEN_BY_ISP) + stream->dma_en &= ~RKCIF_DMAEN_BY_ISP; + else if (stream->dma_en & RKCIF_DMAEN_BY_VICAP) + stream->dma_en &= ~RKCIF_DMAEN_BY_VICAP; + else if (stream->dma_en & RKCIF_DMAEN_BY_ROCKIT) + stream->dma_en &= ~RKCIF_DMAEN_BY_ROCKIT; + atomic_inc(&stream->cifdev->streamoff_cnt); + v4l2_dbg(4, rkcif_debug, &cif_dev->v4l2_dev, + "%s %d, switch stream %d\n", __func__, __LINE__, + atomic_read(&cif_dev->hw_dev->switch_stream_cnt[cif_dev->switch_info.host_idx])); + } else { + if (stream->dma_en & RKCIF_DMAEN_BY_ISP) + stream->to_stop_dma = RKCIF_DMAEN_BY_ISP; + else if (stream->dma_en & RKCIF_DMAEN_BY_VICAP) + stream->to_stop_dma = RKCIF_DMAEN_BY_VICAP; + else if (stream->dma_en & RKCIF_DMAEN_BY_ROCKIT) + stream->to_stop_dma = RKCIF_DMAEN_BY_ROCKIT; + rkcif_stop_dma_capture(stream); + } if (cif_dev->hdr.hdr_mode == HDR_X2) - last_stream = &cif_dev->stream[1]; + last_stream = &stream->cifdev->stream[1]; else if (cif_dev->hdr.hdr_mode == HDR_X3) - last_stream = &cif_dev->stream[2]; + last_stream = &stream->cifdev->stream[2]; else last_stream = stream; spin_lock_irqsave(&stream->cifdev->stream_spinlock, flags); if (!last_stream->is_wait_single_cap) { spin_unlock_irqrestore(&stream->cifdev->stream_spinlock, flags); - if ((cif_dev->hdr.hdr_mode == NO_HDR && atomic_read(&cif_dev->streamoff_cnt) == 1) || - (cif_dev->hdr.hdr_mode == HDR_X2 && atomic_read(&cif_dev->streamoff_cnt) == 2) || - (cif_dev->hdr.hdr_mode == HDR_X3 && atomic_read(&cif_dev->streamoff_cnt) == 3)) { - rkcif_dphy_quick_stream(stream->cifdev, on); - cif_dev->sensor_work.on = 0; + if ((last_stream->cifdev->hdr.hdr_mode == NO_HDR && atomic_read(&last_stream->cifdev->streamoff_cnt) == 1) || + (last_stream->cifdev->hdr.hdr_mode == HDR_X2 && atomic_read(&last_stream->cifdev->streamoff_cnt) == 2) || + (last_stream->cifdev->hdr.hdr_mode == HDR_X3 && atomic_read(&last_stream->cifdev->streamoff_cnt) == 3)) { + if (!cif_dev->switch_info.is_use_switch || + atomic_read(&cif_dev->hw_dev->switch_stream_cnt[cif_dev->switch_info.host_idx]) == 0) + rkcif_dphy_quick_stream(stream->cifdev, on); + stream->cifdev->sensor_work.on = 0; atomic_inc(&stream->cifdev->sensor_off); - schedule_work(&cif_dev->sensor_work.work); + schedule_work(&stream->cifdev->sensor_work.work); } } else { last_stream->is_wait_single_cap = false; cif_dev->resume_mode = RKISP_RTT_MODE_MULTI_FRAME; complete(&stream->start_complete); spin_unlock_irqrestore(&stream->cifdev->stream_spinlock, flags); + if (cif_dev->switch_info.is_use_switch) + atomic_inc(&cif_dev->hw_dev->switch_stream_cnt[cif_dev->switch_info.host_idx]); } } else if (stream->lack_buf_cnt == 2 && !stream->cur_skip_frame) { spin_unlock_irqrestore(&stream->cifdev->stream_spinlock, flags); @@ -15122,26 +15233,34 @@ void rkcif_irq_pingpong_v1(struct rkcif_device *cif_dev) rkcif_scale_start(stream->scale_vdev); } rkcif_detect_wake_up_mode_change(stream); - if (cif_dev->chip_id < CHIP_RK3588_CIF && - mipi_id == RKCIF_STREAM_MIPI_ID0) { - if ((intstat & (CSI_FRAME1_START_ID0 | CSI_FRAME0_START_ID0)) == 0 && - detect_stream->fs_cnt_in_single_frame > 1) { - cif_dev->err_state |= RKCIF_ERR_ID0_MULTI_FS; - detect_stream->is_fs_fe_not_paired = true; - detect_stream->fs_cnt_in_single_frame = 0; + if (mipi_id == RKCIF_STREAM_MIPI_ID0) { + if (stream->fs_cnt_in_single_frame > 1) { + if (cif_dev->chip_id < CHIP_RK3588_CIF) { + cif_dev->err_state |= RKCIF_ERR_ID0_MULTI_FS; + stream->is_fs_fe_not_paired = true; + } + stream->fs_cnt_in_single_frame = 0; } else { - detect_stream->fs_cnt_in_single_frame--; + stream->fs_cnt_in_single_frame--; } } rkcif_monitor_reset_event(cif_dev); cif_dev->irq_stats.frm_end_cnt[stream->id]++; rkcif_check_one_to_multi_sub_stream_stop_state(cif_dev); } - for (i = 0; i < RKCIF_MAX_STREAM_MIPI; i++) { if (intstat & (cif_dev->chip_id < CHIP_RK3576_CIF ? CSI_START_INTSTAT(i) : CSI_START_INTSTAT_RK3576(i))) { - stream = &cif_dev->stream[i]; + if (cif_dev->switch_info.is_use_switch) { + if (cif_dev->switch_info.is_active) + stream = &cif_dev->stream[i]; + else + stream = &cif_dev->switch_info.switch_dev->stream[i]; + } else { + stream = &cif_dev->stream[i]; + } + if (stream->state != RKCIF_STATE_STREAMING) + continue; spin_lock_irqsave(&stream->vbq_lock, flags); if (stream->stopping && stream->dma_en) { if (stream->dma_en & RKCIF_DMAEN_BY_VICAP) @@ -15151,11 +15270,17 @@ void rkcif_irq_pingpong_v1(struct rkcif_device *cif_dev) stream->is_stop_capture = true; } if (stream->to_stop_dma) { - ret = rkcif_stop_dma_capture(stream); - if (!ret) { + if (cif_dev->switch_info.is_use_switch && + atomic_dec_if_positive(&cif_dev->hw_dev->switch_stream_cnt[cif_dev->switch_info.host_idx])) { + stream->to_stop_dma = 0; stream->is_finish_stop_dma = true; - if (stream->is_wait_stop_complete) - stream->is_pause_stream = true; + } else { + ret = rkcif_stop_dma_capture(stream); + if (!ret) { + stream->is_finish_stop_dma = true; + if (stream->is_wait_stop_complete) + stream->is_pause_stream = true; + } } } spin_unlock_irqrestore(&stream->vbq_lock, flags); @@ -15165,7 +15290,7 @@ void rkcif_irq_pingpong_v1(struct rkcif_device *cif_dev) spin_lock_irqsave(&stream->vbq_lock, flags); if (!stream->cur_skip_frame && (!cif_dev->is_in_flip)) { spin_unlock_irqrestore(&stream->vbq_lock, flags); - rkcif_deal_sof(cif_dev); + rkcif_deal_sof(stream->cifdev); } else { spin_unlock_irqrestore(&stream->vbq_lock, flags); } @@ -15189,7 +15314,16 @@ void rkcif_irq_pingpong_v1(struct rkcif_device *cif_dev) rkcif_check_mipi_interlaced_frame_id(stream); } if (intstat & CSI_LINE_INTSTAT_V1(i)) { - stream = &cif_dev->stream[i]; + if (cif_dev->switch_info.is_use_switch) { + if (cif_dev->switch_info.is_active) + stream = &cif_dev->stream[i]; + else + stream = &cif_dev->switch_info.switch_dev->stream[i]; + } else { + stream = &cif_dev->stream[i]; + } + if (stream->state != RKCIF_STATE_STREAMING) + continue; if (stream->is_line_inten) { stream->line_int_cnt++; if (cif_dev->rdbk_debug > 1 && diff --git a/drivers/media/platform/rockchip/cif/dev.c b/drivers/media/platform/rockchip/cif/dev.c index 27d7a3da08ca..4d450a11acfc 100644 --- a/drivers/media/platform/rockchip/cif/dev.c +++ b/drivers/media/platform/rockchip/cif/dev.c @@ -2882,7 +2882,7 @@ int rkcif_plat_init(struct rkcif_device *cif_dev, struct device_node *node, int cif_dev->pipe.close = rkcif_pipeline_close; cif_dev->pipe.set_stream = rkcif_pipeline_set_stream; cif_dev->isr_hdl = rkcif_irq_handler; - cif_dev->id_use_cnt = 0; + atomic_set(&cif_dev->id_use_cnt, 0); memset(&cif_dev->sync_cfg, 0, sizeof(cif_dev->sync_cfg)); cif_dev->sditf_cnt = 0; cif_dev->is_notifier_isp = false; @@ -3090,6 +3090,27 @@ static void rkcif_parse_pins_group(struct rkcif_device *cif_dev) dev_info(cif_dev->dev, "rkcif pins used group %d\n", cif_dev->dvp_pin_group); } +static void rkcif_parse_switch_info(struct rkcif_device *cif_dev) +{ + int ret = 0; + struct device_node *node = cif_dev->dev->of_node; + + memset(&cif_dev->switch_info, 0, sizeof(cif_dev->switch_info)); + ret = of_property_read_u32(node, + OF_CIF_SWITCH_HOST_IDX, + &cif_dev->switch_info.host_idx); + if (ret == 0) { + cif_dev->switch_info.is_use_switch = true; + cif_dev->switch_info.gpio_pin = devm_gpiod_get(cif_dev->dev, "switch", GPIOD_OUT_LOW); + if (IS_ERR(cif_dev->switch_info.gpio_pin)) + dev_err(cif_dev->dev, "get switch gpio failed\n"); + ret = of_property_read_u32(node, + OF_CIF_SWITCH_GPIO_VAL, + &cif_dev->switch_info.gpio_val); + dev_info(cif_dev->dev, "switch gpio val %d\n", cif_dev->switch_info.gpio_val); + } +} + static void rkcif_parse_dts(struct rkcif_device *cif_dev) { int ret = 0; @@ -3112,6 +3133,12 @@ static void rkcif_parse_dts(struct rkcif_device *cif_dev) else cif_dev->is_camera_over_bridge = false; rkcif_parse_pins_group(cif_dev); + rkcif_parse_switch_info(cif_dev); + if (device_property_read_bool(cif_dev->dev, "no-detect-group-sync")) + cif_dev->is_detect_group_sync = false; + else + cif_dev->is_detect_group_sync = true; + dev_err(cif_dev->dev, "rkcif is_detect_group_sync %d\n", cif_dev->is_detect_group_sync); } static int rkcif_get_reserved_mem(struct rkcif_device *cif_dev) diff --git a/drivers/media/platform/rockchip/cif/dev.h b/drivers/media/platform/rockchip/cif/dev.h index 4e453927e537..92cf438c9ce5 100644 --- a/drivers/media/platform/rockchip/cif/dev.h +++ b/drivers/media/platform/rockchip/cif/dev.h @@ -38,6 +38,8 @@ #define OF_CIF_WAIT_LINE "wait-line" #define OF_CIF_FASTBOOT_RESERVED_BUFS "fastboot-reserved-bufs" #define OF_CIF_PINS_GROUP "cif-pins-group" +#define OF_CIF_SWITCH_HOST_IDX "switch-host-idx" +#define OF_CIF_SWITCH_GPIO_VAL "switch-gpio-val" #define CIF_MONITOR_PARA_NUM (5) @@ -93,6 +95,7 @@ #define RKCIF_EXP_NUM_MAX (8) +#define RKCIF_MAX_DEV (8) /* * for distinguishing cropping from senosr or usr */ @@ -480,6 +483,7 @@ struct rkcif_rx_buffer { struct rkcif_dummy_buffer dummy; struct rkisp_thunderboot_shmem shmem; u64 fe_timestamp; + bool is_init[RKCIF_MAX_DEV]; }; enum rkcif_dma_en_mode { @@ -938,6 +942,17 @@ struct rkcif_stream_info { struct sditf_priv *priv; }; +struct rkcif_switch_info { + bool is_use_switch; + bool is_active; + bool is_init; + bool is_init_buf; + int host_idx; + int gpio_val; + struct gpio_desc *gpio_pin; + struct rkcif_device *switch_dev; +}; + /* * struct rkcif_device - ISP platform device * @base_addr: base register address @@ -992,7 +1007,7 @@ struct rkcif_device { spinlock_t stream_spinlock; struct rkcif_timer reset_watchdog_timer; struct rkcif_work_struct reset_work; - int id_use_cnt; + atomic_t id_use_cnt; unsigned int csi_host_idx; unsigned int csi_host_idx_def; unsigned int dvp_sof_in_oneframe; @@ -1030,6 +1045,7 @@ struct rkcif_device { bool is_thunderboot_start; bool is_in_flip; bool is_support_get_exp; + bool is_detect_group_sync; int rdbk_debug; struct rkcif_sync_cfg sync_cfg; int sditf_cnt; @@ -1057,6 +1073,7 @@ struct rkcif_device { u32 pre_buf_addr[MAX_PRE_BUF_NUM]; u64 pre_buf_timestamp[MAX_PRE_BUF_NUM]; u32 dvp_pin_group; + struct rkcif_switch_info switch_info; }; extern struct platform_driver rkcif_plat_drv; @@ -1182,5 +1199,6 @@ void rkcif_set_sof(struct rkcif_device *cif_dev, u32 seq); void rkcif_set_sensor_streamon_in_sync_mode(struct rkcif_device *cif_dev); int rkcif_sensor_set_power(struct rkcif_stream *stream, int on); +void rkcif_switch_change(struct rkcif_device *cif_dev, bool is_switch); #endif diff --git a/drivers/media/platform/rockchip/cif/hw.c b/drivers/media/platform/rockchip/cif/hw.c index 20c6d9adb727..f4207b56b352 100644 --- a/drivers/media/platform/rockchip/cif/hw.c +++ b/drivers/media/platform/rockchip/cif/hw.c @@ -1331,6 +1331,7 @@ static const struct rkcif_hw_match_data px30_cif_match_data = { .rsts = px30_cif_rsts, .rsts_num = ARRAY_SIZE(px30_cif_rsts), .cif_regs = px30_cif_regs, + .max_hw = 1, }; static const struct rkcif_hw_match_data rk1808_cif_match_data = { @@ -1340,6 +1341,7 @@ static const struct rkcif_hw_match_data rk1808_cif_match_data = { .rsts = rk1808_cif_rsts, .rsts_num = ARRAY_SIZE(rk1808_cif_rsts), .cif_regs = rk1808_cif_regs, + .max_hw = 1, }; static const struct rkcif_hw_match_data rk3128_cif_match_data = { @@ -1349,6 +1351,7 @@ static const struct rkcif_hw_match_data rk3128_cif_match_data = { .rsts = rk3128_cif_rsts, .rsts_num = ARRAY_SIZE(rk3128_cif_rsts), .cif_regs = rk3128_cif_regs, + .max_hw = 1, }; static const struct rkcif_hw_match_data rk3288_cif_match_data = { @@ -1358,6 +1361,7 @@ static const struct rkcif_hw_match_data rk3288_cif_match_data = { .rsts = rk3288_cif_rsts, .rsts_num = ARRAY_SIZE(rk3288_cif_rsts), .cif_regs = rk3288_cif_regs, + .max_hw = 1, }; static const struct rkcif_hw_match_data rk3328_cif_match_data = { @@ -1367,6 +1371,7 @@ static const struct rkcif_hw_match_data rk3328_cif_match_data = { .rsts = rk3328_cif_rsts, .rsts_num = ARRAY_SIZE(rk3328_cif_rsts), .cif_regs = rk3328_cif_regs, + .max_hw = 1, }; static const struct rkcif_hw_match_data rk3368_cif_match_data = { @@ -1376,6 +1381,7 @@ static const struct rkcif_hw_match_data rk3368_cif_match_data = { .rsts = rk3368_cif_rsts, .rsts_num = ARRAY_SIZE(rk3368_cif_rsts), .cif_regs = rk3368_cif_regs, + .max_hw = 1, }; static const struct rkcif_hw_match_data rv1126_cif_match_data = { @@ -1385,6 +1391,7 @@ static const struct rkcif_hw_match_data rv1126_cif_match_data = { .rsts = rv1126_cif_rsts, .rsts_num = ARRAY_SIZE(rv1126_cif_rsts), .cif_regs = rv1126_cif_regs, + .max_hw = 2, }; static const struct rkcif_hw_match_data rv1126_cif_lite_match_data = { @@ -1394,6 +1401,7 @@ static const struct rkcif_hw_match_data rv1126_cif_lite_match_data = { .rsts = rv1126_cif_lite_rsts, .rsts_num = ARRAY_SIZE(rv1126_cif_lite_rsts), .cif_regs = rv1126_cif_lite_regs, + .max_hw = 1, }; static const struct rkcif_hw_match_data rk3568_cif_match_data = { @@ -1403,6 +1411,7 @@ static const struct rkcif_hw_match_data rk3568_cif_match_data = { .rsts = rk3568_cif_rsts, .rsts_num = ARRAY_SIZE(rk3568_cif_rsts), .cif_regs = rk3568_cif_regs, + .max_hw = 2, }; static const struct rkcif_hw_match_data rk3588_cif_match_data = { @@ -1412,6 +1421,7 @@ static const struct rkcif_hw_match_data rk3588_cif_match_data = { .rsts = rk3588_cif_rsts, .rsts_num = ARRAY_SIZE(rk3588_cif_rsts), .cif_regs = rk3588_cif_regs, + .max_hw = 7, }; static const struct rkcif_hw_match_data rv1106_cif_match_data = { @@ -1421,6 +1431,7 @@ static const struct rkcif_hw_match_data rv1106_cif_match_data = { .rsts = rv1106_cif_rsts, .rsts_num = ARRAY_SIZE(rv1106_cif_rsts), .cif_regs = rv1106_cif_regs, + .max_hw = 3, }; static const struct rkcif_hw_match_data rk3562_cif_match_data = { @@ -1430,6 +1441,7 @@ static const struct rkcif_hw_match_data rk3562_cif_match_data = { .rsts = rk3562_cif_rsts, .rsts_num = ARRAY_SIZE(rk3562_cif_rsts), .cif_regs = rk3562_cif_regs, + .max_hw = 4, }; static const struct rkcif_hw_match_data rk3576_cif_match_data = { @@ -1439,6 +1451,7 @@ static const struct rkcif_hw_match_data rk3576_cif_match_data = { .rsts = rk3576_cif_rsts, .rsts_num = ARRAY_SIZE(rk3576_cif_rsts), .cif_regs = rk3576_cif_regs, + .max_hw = 6, }; static const struct rkcif_hw_match_data rv1103b_cif_match_data = { @@ -1448,6 +1461,7 @@ static const struct rkcif_hw_match_data rv1103b_cif_match_data = { .rsts = rv1103b_cif_rsts, .rsts_num = ARRAY_SIZE(rv1103b_cif_rsts), .cif_regs = rv1103b_cif_regs, + .max_hw = 2, }; static const struct rkcif_hw_match_data rv1126b_cif_match_data = { @@ -1457,6 +1471,7 @@ static const struct rkcif_hw_match_data rv1126b_cif_match_data = { .rsts = rv1126b_cif_rsts, .rsts_num = ARRAY_SIZE(rv1126b_cif_rsts), .cif_regs = rv1126b_cif_regs, + .max_hw = 5, }; static const struct of_device_id rkcif_plat_of_match[] = { @@ -1567,7 +1582,7 @@ static irqreturn_t rkcif_irq_handler(int irq, void *ctx) } for (i = 0; i < cif_hw->dev_num; i++) { - if (cif_hw->cif_dev[i]->isr_hdl) { + if (cif_hw->cif_dev[i]->isr_hdl && i < cif_hw->match_data->max_hw) { cif_hw->cif_dev[i]->isr_hdl(irq, cif_hw->cif_dev[i]); if (cif_hw->cif_dev[i]->err_state && (!work_busy(&cif_hw->cif_dev[i]->err_state_work.work))) { @@ -1575,10 +1590,10 @@ static irqreturn_t rkcif_irq_handler(int irq, void *ctx) cif_hw->cif_dev[i]->err_state = 0; schedule_work(&cif_hw->cif_dev[i]->err_state_work.work); } - if (cif_hw->chip_id >= CHIP_RK3588_CIF && intstat_glb) { - rkcif_irq_handle_toisp(cif_hw->cif_dev[i], intstat_glb); - rkcif_irq_handle_scale(cif_hw->cif_dev[i], intstat_glb); - } + } + if (cif_hw->chip_id >= CHIP_RK3588_CIF && intstat_glb) { + rkcif_irq_handle_toisp(cif_hw->cif_dev[i], intstat_glb); + rkcif_irq_handle_scale(cif_hw->cif_dev[i], intstat_glb); } } irq_stop = ktime_get_ns(); @@ -1838,6 +1853,10 @@ static int rkcif_plat_hw_probe(struct platform_device *pdev) spin_lock_init(&cif_hw->group_lock); spin_lock_init(&cif_hw->reset_lock); atomic_set(&cif_hw->power_cnt, 0); + for (i = 0; i < RKCIF_MAX_SWITCH_GROUP; i++) { + atomic_set(&cif_hw->switch_stream_cnt[i], 0); + mutex_init(&cif_hw->switch_mutex_lock[i]); + } cif_hw->is_in_reset = false; cif_hw->iommu_en = is_iommu_enable(dev); diff --git a/drivers/media/platform/rockchip/cif/hw.h b/drivers/media/platform/rockchip/cif/hw.h index b346e186da9d..537dc154b329 100644 --- a/drivers/media/platform/rockchip/cif/hw.h +++ b/drivers/media/platform/rockchip/cif/hw.h @@ -26,6 +26,7 @@ #define RKCIF_MAX_RESET 15 #define RKCIF_MAX_GROUP 4 +#define RKCIF_MAX_SWITCH_GROUP 2 #define write_cif_reg(base, addr, val) \ writel(val, (addr) + (base)) @@ -121,6 +122,7 @@ struct rkcif_hw_match_data { int clks_num; int rsts_num; const struct cif_reg *cif_regs; + int max_hw; }; /* @@ -145,11 +147,14 @@ struct rkcif_hw { struct rkcif_device *cif_dev[RKCIF_DEV_MAX]; int dev_num; atomic_t power_cnt; + atomic_t switch_stream_cnt[RKCIF_MAX_SWITCH_GROUP]; const struct rkcif_hw_match_data *match_data; struct mutex dev_lock; + struct mutex switch_mutex_lock[RKCIF_MAX_SWITCH_GROUP]; struct rkcif_multi_sync_config sync_config[RKCIF_MAX_GROUP]; spinlock_t group_lock; spinlock_t reset_lock; + spinlock_t switch_lock; struct notifier_block reset_notifier; /* reset for mipi csi crc err */ struct rkcif_dummy_buffer dummy_buf; bool iommu_en; diff --git a/drivers/media/platform/rockchip/cif/mipi-csi2.c b/drivers/media/platform/rockchip/cif/mipi-csi2.c index 1de4cd09a1dd..bc74726c94c1 100644 --- a/drivers/media/platform/rockchip/cif/mipi-csi2.c +++ b/drivers/media/platform/rockchip/cif/mipi-csi2.c @@ -234,10 +234,39 @@ static void csi2_enable(struct csi2_hw *csi2_hw, write_csihost_reg(base, CSIHOST_RESETN, 1); } +static int csi2_hw_start(struct csi2_hw *csi2_hw, enum host_type_t host_type) +{ + int ret = 0; + + if (atomic_inc_return(&csi2_hw->stream_count) > 1) + return ret; + csi2_hw_do_reset(csi2_hw); + ret = csi2_enable_clks(csi2_hw); + if (ret) { + dev_err(csi2_hw->dev, "%s: enable clks failed, %s\n", + __func__, csi2_hw->dev_name); + return ret; + } + enable_irq(csi2_hw->irq1); + enable_irq(csi2_hw->irq2); + csi2_enable(csi2_hw, host_type); + return ret; +} + +static void csi2_hw_stop(struct csi2_hw *csi2_hw) +{ + if (atomic_dec_return(&csi2_hw->stream_count) > 0) + return; + disable_irq(csi2_hw->irq1); + disable_irq(csi2_hw->irq2); + csi2_disable(csi2_hw); + csi2_disable_clks(csi2_hw); +} + static int csi2_start(struct csi2_dev *csi2) { enum host_type_t host_type; - int ret, i; + int ret = 0, i; int csi_idx = 0; atomic_set(&csi2->frm_sync_seq, 0); @@ -255,16 +284,7 @@ static int csi2_start(struct csi2_dev *csi2) for (i = 0; i < csi2->csi_info.csi_num; i++) { csi_idx = csi2->csi_info.csi_idx[i]; - csi2_hw_do_reset(csi2->csi2_hw[csi_idx]); - ret = csi2_enable_clks(csi2->csi2_hw[csi_idx]); - if (ret) { - v4l2_err(&csi2->sd, "%s: enable clks failed, index %d\n", - __func__, csi_idx); - return ret; - } - enable_irq(csi2->csi2_hw[csi_idx]->irq1); - enable_irq(csi2->csi2_hw[csi_idx]->irq2); - csi2_enable(csi2->csi2_hw[csi_idx], host_type); + ret |= csi2_hw_start(csi2->csi2_hw[csi_idx], host_type); } pr_debug("stream sd: %s\n", csi2->src_sd->name); @@ -281,10 +301,7 @@ static int csi2_start(struct csi2_dev *csi2) err_assert_reset: for (i = 0; i < csi2->csi_info.csi_num; i++) { csi_idx = csi2->csi_info.csi_idx[i]; - disable_irq(csi2->csi2_hw[csi_idx]->irq1); - disable_irq(csi2->csi2_hw[csi_idx]->irq2); - csi2_disable(csi2->csi2_hw[csi_idx]); - csi2_disable_clks(csi2->csi2_hw[csi_idx]); + csi2_hw_stop(csi2->csi2_hw[csi_idx]); } return ret; @@ -304,11 +321,7 @@ static void csi2_stop(struct csi2_dev *csi2) for (i = 0; i < csi2->csi_info.csi_num; i++) { csi_idx = csi2->csi_info.csi_idx[i]; - disable_irq(csi2->csi2_hw[csi_idx]->irq1); - disable_irq(csi2->csi2_hw[csi_idx]->irq2); - csi2_disable(csi2->csi2_hw[csi_idx]); - csi2_hw_do_reset(csi2->csi2_hw[csi_idx]); - csi2_disable_clks(csi2->csi2_hw[csi_idx]); + csi2_hw_stop(csi2->csi2_hw[csi_idx]); } } @@ -1486,6 +1499,7 @@ static int csi2_hw_probe(struct platform_device *pdev) dev_err(&pdev->dev, "No found irq csi-intr2\n"); } platform_set_drvdata(pdev, csi2_hw); + atomic_set(&csi2_hw->stream_count, 0); dev_info(&pdev->dev, "probe success, v4l2_dev:%s!\n", csi2_hw->dev_name); return 0; diff --git a/drivers/media/platform/rockchip/cif/mipi-csi2.h b/drivers/media/platform/rockchip/cif/mipi-csi2.h index 6cfd9f217d47..026b48ff552f 100644 --- a/drivers/media/platform/rockchip/cif/mipi-csi2.h +++ b/drivers/media/platform/rockchip/cif/mipi-csi2.h @@ -195,6 +195,7 @@ struct csi2_hw { int irq1; int irq2; const char *dev_name; + atomic_t stream_count; }; u32 rkcif_csi2_get_sof(struct csi2_dev *csi2_dev); diff --git a/drivers/media/platform/rockchip/cif/regs.h b/drivers/media/platform/rockchip/cif/regs.h index 91126488f15b..eea73b3ced40 100644 --- a/drivers/media/platform/rockchip/cif/regs.h +++ b/drivers/media/platform/rockchip/cif/regs.h @@ -1171,6 +1171,7 @@ enum cif_reg_index { #define CSI_START_INTEN(id) (0x3 << ((id) * 2)) #define CSI_START_INTEN_RK3576(id) (0x1 << id) +#define CSI_INF_END_INTEN_RK3576(id) (0x10 << id) #define CSI_DMA_END_INTEN(id) (0x3 << ((id) * 2 + 8)) #define CSI_LINE_INTEN(id) (0x1 << ((id) + 21)) #define CSI_LINE_INTEN_RK3588(id) (0x1 << ((id) + 20)) @@ -1214,6 +1215,11 @@ enum cif_reg_index { #define CSI_SIZE_ERR_ID2 (0x1 << 26) #define CSI_SIZE_ERR_ID3 (0x1 << 27) +#define CSI_INF_FRAME_END_ID0 (0x1 << 4) +#define CSI_INF_FRAME_END_ID1 (0x1 << 5) +#define CSI_INF_FRAME_END_ID2 (0x1 << 6) +#define CSI_INF_FRAME_END_ID3 (0x1 << 7) + #define CSI_FRAME_START_ID0 (CSI_FRAME0_START_ID0 |\ CSI_FRAME1_START_ID0) #define CSI_FRAME_START_ID1 (CSI_FRAME0_START_ID1 |\ diff --git a/drivers/media/platform/rockchip/cif/subdev-itf.c b/drivers/media/platform/rockchip/cif/subdev-itf.c index 2f3e8c902010..26a6423d88f2 100644 --- a/drivers/media/platform/rockchip/cif/subdev-itf.c +++ b/drivers/media/platform/rockchip/cif/subdev-itf.c @@ -282,6 +282,16 @@ static int sditf_init_buf(struct sditf_priv *priv) struct rkcif_device *cif_dev = priv->cif_dev; int ret = 0; + mutex_lock(&cif_dev->hw_dev->switch_mutex_lock[cif_dev->switch_info.host_idx]); + if (cif_dev->switch_info.is_use_switch) { + if (cif_dev->switch_info.is_init_buf || + cif_dev->switch_info.switch_dev->switch_info.is_init_buf) { + mutex_unlock(&cif_dev->hw_dev->switch_mutex_lock[cif_dev->switch_info.host_idx]); + return 0; + } + cif_dev->switch_info.is_init_buf = true; + } + if (priv->hdr_cfg.hdr_mode == HDR_X2) { if (priv->mode.rdbk_mode == RKISP_VICAP_RDBK_AUTO) { if (cif_dev->is_thunderboot) @@ -320,6 +330,7 @@ static int sditf_init_buf(struct sditf_priv *priv) ret = -EINVAL; } priv->is_buf_init = true; + mutex_unlock(&cif_dev->hw_dev->switch_mutex_lock[cif_dev->switch_info.host_idx]); return ret; } @@ -344,6 +355,8 @@ static void sditf_free_buf(struct sditf_priv *priv) cif_dev->is_thunderboot = false; } priv->is_buf_init = false; + if (cif_dev->switch_info.is_use_switch) + cif_dev->switch_info.is_init_buf = false; } static int sditf_get_selection(struct v4l2_subdev *sd, @@ -446,6 +459,47 @@ static void sditf_select_sensor_setting_for_thunderboot(struct sditf_priv *priv) } #endif +static struct rkcif_device *rkcif_get_switch_dev(struct rkcif_device *cif_dev) +{ + int i = 0; + + for (i = 0; i < cif_dev->hw_dev->dev_num; i++) { + if (cif_dev->switch_info.host_idx == cif_dev->hw_dev->cif_dev[i]->switch_info.host_idx && + cif_dev != cif_dev->hw_dev->cif_dev[i]) + return cif_dev->hw_dev->cif_dev[i]; + } + return NULL; +} + +static int rkcif_init_switch_info(struct rkcif_device *cif_dev) +{ + cif_dev->csi_host_idx = cif_dev->switch_info.host_idx; + cif_dev->switch_info.is_init = true; + cif_dev->switch_info.switch_dev = rkcif_get_switch_dev(cif_dev); + if (!cif_dev->switch_info.switch_dev) + return -EINVAL; + if (IS_ERR(cif_dev->switch_info.gpio_pin)) + cif_dev->switch_info.gpio_pin = cif_dev->switch_info.switch_dev->switch_info.gpio_pin; + return 0; +} + +static int rkcif_init_switch_infos(struct rkcif_device *cif_dev) +{ + int ret = 0; + + mutex_lock(&cif_dev->hw_dev->switch_mutex_lock[cif_dev->switch_info.host_idx]); + if (!cif_dev->switch_info.is_init) { + cif_dev->switch_info.is_active = true; + ret = rkcif_init_switch_info(cif_dev); + if (!ret) + ret = rkcif_init_switch_info(cif_dev->switch_info.switch_dev); + if (cif_dev->sditf[0]->mode_src.rdbk_mode > RKISP_VICAP_RDBK_AIQ) + rkcif_switch_change(cif_dev, !!cif_dev->switch_info.gpio_val); + } + mutex_unlock(&cif_dev->hw_dev->switch_mutex_lock[cif_dev->switch_info.host_idx]); + return ret; +} + static void sditf_enable_immediately(struct sditf_priv *priv); static long sditf_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) { @@ -481,6 +535,10 @@ static long sditf_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) else mode->input.multi_sync = 1; memcpy(&priv->mode_src, mode, sizeof(*mode)); + + if (cif_dev->switch_info.is_use_switch) + ret = rkcif_init_switch_infos(cif_dev); + if (cif_dev->is_thunderboot && cif_dev->is_thunderboot_start) { if (mode->rdbk_mode < RKISP_VICAP_RDBK_AIQ) @@ -1114,6 +1172,8 @@ void sditf_disable_immediately(struct sditf_priv *priv) } } priv->is_toisp_off = true; + if (priv->cif_dev->switch_info.is_use_switch) + priv->cif_dev->switch_info.is_active = false; } static void sditf_enable_immediately(struct sditf_priv *priv) @@ -1137,6 +1197,10 @@ static void sditf_enable_immediately(struct sditf_priv *priv) sditf_channel_enable(priv, 1); } } + if (priv->cif_dev->switch_info.is_use_switch) { + rkcif_switch_change(priv->cif_dev, !!priv->cif_dev->switch_info.gpio_val); + priv->cif_dev->switch_info.is_active = true; + } priv->is_toisp_off = false; } @@ -1284,6 +1348,7 @@ static int sditf_s_rx_buffer(struct v4l2_subdev *sd, struct sditf_priv *priv = to_sditf_priv(sd); struct rkcif_device *cif_dev = priv->cif_dev; struct rkcif_stream *stream = NULL; + struct rkcif_stream *buf_stream = NULL; struct rkisp_rx_buf *dbufs; struct rkcif_rx_buffer *rx_buf = NULL; unsigned long flags, buffree_flags; @@ -1322,6 +1387,10 @@ static int sditf_s_rx_buffer(struct v4l2_subdev *sd, if (!stream) return -EINVAL; + buf_stream = stream; + if (cif_dev->switch_info.is_use_switch && + cif_dev->switch_info.switch_dev->switch_info.is_init_buf) + buf_stream = &cif_dev->switch_info.switch_dev->stream[stream->id]; if (dbufs->sequence == 0 && stream->thunderboot_skip_interval) { @@ -1351,7 +1420,7 @@ static int sditf_s_rx_buffer(struct v4l2_subdev *sd, } if (!is_free && (!dbufs->is_switch) && stream->state == RKCIF_STATE_STREAMING) { - list_add_tail(&rx_buf->list, &stream->rx_buf_head); + list_add_tail(&rx_buf->list, &buf_stream->rx_buf_head); rkcif_assign_check_buffer_update_toisp(stream); if (cif_dev->resume_mode != RKISP_RTT_MODE_ONE_FRAME && (!stream->is_pause_stream)) { From 98c569358a4bcd0c7379680debff064a128d0842 Mon Sep 17 00:00:00 2001 From: Algea Cao Date: Mon, 26 May 2025 09:36:21 +0800 Subject: [PATCH 2/6] phy: rockchip: inno-hdmi: Subdivide rk3528 phy cfg table Add phy configuration of tmds clk corresponding to 10-bit color depth at different resolutions (such as 1080p60 10-bit). Change-Id: I8792d950dca2a51572314359044c2bea437a71a8 Signed-off-by: Algea Cao --- .../phy/rockchip/phy-rockchip-inno-hdmi-phy.c | 37 ++++++++++--------- 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/drivers/phy/rockchip/phy-rockchip-inno-hdmi-phy.c b/drivers/phy/rockchip/phy-rockchip-inno-hdmi-phy.c index 34dc8278f8a3..4c474c596247 100644 --- a/drivers/phy/rockchip/phy-rockchip-inno-hdmi-phy.c +++ b/drivers/phy/rockchip/phy-rockchip-inno-hdmi-phy.c @@ -347,17 +347,27 @@ static const struct phy_config rk3328_phy_cfg[] = { static const struct phy_config rk3528_phy_cfg[] = { /* tmdsclk bias-clk bias-data voltage-clk voltage-data pre-emphasis-data */ { 165000000, { - 0x03, 0x04, 0x0c, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x04, 0x0f, 0x0f, 0x00, 0x76, 0x83, 0x0a, 0x0a, + 0x00, 0x00, 0x00, 0x00, 0x00, + }, + }, { + 185625000, { + 0x02, 0x0b, 0x0f, 0x0f, 0x00, 0x76, 0x83, 0x0a, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, }, }, { 340000000, { - 0x03, 0x04, 0x0c, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x04, 0x0c, 0x12, 0x00, 0x76, 0x83, 0x00, 0x0f, + 0x00, 0x00, 0x00, 0x00, 0x00, + }, + }, { + 371250000, { + 0x02, 0x0b, 0x0d, 0x18, 0x00, 0x76, 0x83, 0x0a, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, }, }, { 594000000, { - 0x02, 0x08, 0x0d, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x0b, 0x0d, 0x18, 0x00, 0x76, 0x83, 0x0a, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, }, }, { @@ -1182,21 +1192,12 @@ inno_hdmi_phy_rk3528_power_on(struct inno_hdmi_phy *inno, } /* set termination resistance */ - if (phy_cfg->tmdsclock > 340000000) { - inno_write(inno, 0xc7, 0x76); - inno_write(inno, 0xc5, 0x83); - inno_write(inno, 0xc8, 0x00); - inno_write(inno, 0xc9, 0x2f); - inno_write(inno, 0xca, 0x2f); - inno_write(inno, 0xcb, 0x2f); - } else { - inno_write(inno, 0xc7, 0x76); - inno_write(inno, 0xc5, 0x83); - inno_write(inno, 0xc8, 0x00); - inno_write(inno, 0xc9, 0x0f); - inno_write(inno, 0xca, 0x0f); - inno_write(inno, 0xcb, 0x0f); - } + inno_write(inno, 0xc7, phy_cfg->regs[5]); + inno_write(inno, 0xc5, phy_cfg->regs[6]); + inno_write(inno, 0xc8, phy_cfg->regs[7]); + inno_write(inno, 0xc9, phy_cfg->regs[8]); + inno_write(inno, 0xca, phy_cfg->regs[8]); + inno_write(inno, 0xcb, phy_cfg->regs[8]); /* set TMDS sync detection counter length */ temp = 47520000000; From cd348ae871c92d8d6077c7a745d467ac945e4549 Mon Sep 17 00:00:00 2001 From: Shawn Lin Date: Thu, 15 May 2025 15:01:25 +0800 Subject: [PATCH 3/6] PCI: rockchip: dw: Fix link fail in s2r Delaying link training need the irq to help set dly2_done which couldn't come true in resume due to the noirq phase. If the training is still going but the EP issues a hot reset request, the LTSSM will be stuck and the link never be back even if we reset the EP. The only way is to reset the whole controller, which is unacceptable. The issue is very difficult to be reproduced but finally we spot the key point from fifo status of ltssm. From the designe point of view, the only way to make ltssm from 0x0(DETECT_QUIET) to 0x5(PRE_DETECT_QUIET) is core_rst_n be active and dly logic taking over client settings. [816669.085768][ T2707] rk-pcie fe180000.pcie: fifo_status = 0xf0009 [816669.085775][ T2707] rk-pcie fe180000.pcie: fifo_status = 0xe000a [816669.085783][ T2707] rk-pcie fe180000.pcie: fifo_status = 0xd000b [816669.085790][ T2707] rk-pcie fe180000.pcie: fifo_status = 0xc000c [816669.085797][ T2707] rk-pcie fe180000.pcie: fifo_status = 0xb0011 [816669.085804][ T2707] rk-pcie fe180000.pcie: fifo_status = 0xa000d [816669.085811][ T2707] rk-pcie fe180000.pcie: fifo_status = 0x9000f [816669.085818][ T2707] rk-pcie fe180000.pcie: fifo_status = 0x8000e [816669.085826][ T2707] rk-pcie fe180000.pcie: fifo_status = 0x107000d [816669.085833][ T2707] rk-pcie fe180000.pcie: fifo_status = 0x106000e [816669.085840][ T2707] rk-pcie fe180000.pcie: fifo_status = 0x5000d [816669.085847][ T2707] rk-pcie fe180000.pcie: fifo_status = 0x40005 [816669.085854][ T2707] rk-pcie fe180000.pcie: fifo_status = 0x30000 [816669.085861][ T2707] rk-pcie fe180000.pcie: fifo_status = 0x20005 [816669.085868][ T2707] rk-pcie fe180000.pcie: fifo_status = 0x10000 Given dly2_done is slef-clear bit, so we can't set it in advance but have to disable dly2_en when linking in resume and enable it later. Fixes: 679557456b2d ("PCIe: dw: rockchip: Delaying the link training after hot reset") Signed-off-by: Shawn Lin Change-Id: I85c24c7d7ea4c5f6718bcbdfbd7bf328d9a7f170 --- drivers/pci/controller/dwc/pcie-dw-rockchip.c | 26 +++++++++++++++---- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/drivers/pci/controller/dwc/pcie-dw-rockchip.c b/drivers/pci/controller/dwc/pcie-dw-rockchip.c index 1f87e2607564..a08fab7c9790 100644 --- a/drivers/pci/controller/dwc/pcie-dw-rockchip.c +++ b/drivers/pci/controller/dwc/pcie-dw-rockchip.c @@ -930,14 +930,21 @@ static const struct dw_pcie_ops dw_pcie_ops = { .link_up = rk_pcie_link_up, }; -static void rk_pcie_fast_link_setup(struct rk_pcie *rk_pcie) +static void rk_pcie_fast_link_setup(struct rk_pcie *rk_pcie, bool enable_dly2_en) { u32 val; /* LTSSM EN ctrl mode */ val = rk_pcie_readl_apb(rk_pcie, PCIE_CLIENT_HOT_RESET_CTRL); - val |= (PCIE_LTSSM_ENABLE_ENHANCE | PCIE_LTSSM_APP_DLY2_EN) - | ((PCIE_LTSSM_APP_DLY2_EN | PCIE_LTSSM_ENABLE_ENHANCE) << 16); + val |= PCIE_LTSSM_ENABLE_ENHANCE | (PCIE_LTSSM_ENABLE_ENHANCE << 16); + + if (enable_dly2_en) { + val |= PCIE_LTSSM_APP_DLY2_EN | (PCIE_LTSSM_APP_DLY2_EN << 16); + } else { + val &= ~PCIE_LTSSM_APP_DLY2_EN; + val |= PCIE_LTSSM_APP_DLY2_EN << 16; + } + rk_pcie_writel_apb(rk_pcie, PCIE_CLIENT_HOT_RESET_CTRL, val); } @@ -1339,7 +1346,7 @@ static int rk_pcie_slot_enable(struct gpio_hotplug_slot *slot) dev_info(rk_pcie->pci->dev, "%s\n", __func__); rk_pcie->hp_no_link = true; rk_pcie_enable_power(rk_pcie); - rk_pcie_fast_link_setup(rk_pcie); + rk_pcie_fast_link_setup(rk_pcie, true); ret = rk_pcie_establish_link(rk_pcie->pci); if (ret) dev_err(rk_pcie->pci->dev, "fail to enable slot\n"); @@ -1494,6 +1501,7 @@ static int rk_pcie_hardware_io_config(struct rk_pcie *rk_pcie) phy_power_on(rk_pcie->phy); + /* Release resets after PHY is working */ reset_control_deassert(rk_pcie->rsts); ret = phy_calibrate(rk_pcie->phy); @@ -1585,7 +1593,14 @@ static int rk_pcie_host_config(struct rk_pcie *rk_pcie) dw_pcie_writel_dbi(rk_pcie->pci, rk_pcie->linkcap_off, val); } - rk_pcie_fast_link_setup(rk_pcie); + /* + * S2R is in noirq phase which couldn't ack hot reset or link down event. + * But we need to deal with dly2_en enable case, otherwise the ltssm will + * be stuck waiting for dlye_done. We could set dly2_done in advance, + * however, it's slef-clear. So the only option here is to disable dly2_en + * when resuming. + */ + rk_pcie_fast_link_setup(rk_pcie, !rk_pcie->in_suspend); rk_pcie_set_power_limit(rk_pcie); @@ -2034,6 +2049,7 @@ static int __maybe_unused rockchip_dw_pcie_resume(struct device *dev) dw_pcie_dbi_ro_wr_dis(pci); rk_pcie->in_suspend = false; + rk_pcie_fast_link_setup(rk_pcie, true); return 0; From 4502ce6f66703fe432b00429b03c8970ca3b9503 Mon Sep 17 00:00:00 2001 From: Ye Zhang Date: Fri, 16 May 2025 18:28:25 +0800 Subject: [PATCH 4/6] arm64: dts: rockchip: add dedicated pinconf DTSI for RV1126B This commit introduces a chip-specific pinconf DTSI for RV1126B to handle its extended drive-strength levels. New levels add intermediate level. Below is the migration guide: Old Level to New Level Mapping (Same Register Value): ----------------------------------------------------- | Old Name | New Name | Register | |---------------|-----------------------|-----------| | drv_level_0 | drv_level_0_25 | 0x01 | | drv_level_1 | drv_level_0_75 | 0x03 | | drv_level_2 | drv_level_1_75 | 0x07 | | drv_level_3 | drv_level_2_75 | 0x0F | | drv_level_4 | drv_level_3_75 | 0x1F | | drv_level_5 | drv_level_5_75 | 0x3F | ----------------------------------------------------- Signed-off-by: Ye Zhang Change-Id: Ic15ba802bdeac765c684d6906047523d914d01b1 --- .../boot/dts/rockchip/rv1126b-pinconf.dtsi | 660 ++++++++++++++++++ .../boot/dts/rockchip/rv1126b-pinctrl.dtsi | 74 +- 2 files changed, 697 insertions(+), 37 deletions(-) create mode 100644 arch/arm64/boot/dts/rockchip/rv1126b-pinconf.dtsi diff --git a/arch/arm64/boot/dts/rockchip/rv1126b-pinconf.dtsi b/arch/arm64/boot/dts/rockchip/rv1126b-pinconf.dtsi new file mode 100644 index 000000000000..0eacbf17a5fe --- /dev/null +++ b/arch/arm64/boot/dts/rockchip/rv1126b-pinconf.dtsi @@ -0,0 +1,660 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +&pinctrl { + /omit-if-no-ref/ + pcfg_pull_up: pcfg-pull-up { + bias-pull-up; + }; + + /omit-if-no-ref/ + pcfg_pull_down: pcfg-pull-down { + bias-pull-down; + }; + + /omit-if-no-ref/ + pcfg_pull_none: pcfg-pull-none { + bias-disable; + }; + + /omit-if-no-ref/ + pcfg_pull_none_drv_level_0_25: pcfg-pull-none-drv-level-0-25 { + bias-disable; + drive-strength = <0x01>; + }; + + /omit-if-no-ref/ + pcfg_pull_none_drv_level_0_50: pcfg-pull-none-drv-level-0-50 { + bias-disable; + drive-strength = <0x02>; + }; + + /omit-if-no-ref/ + pcfg_pull_none_drv_level_0_75: pcfg-pull-none-drv-level-0-75 { + bias-disable; + drive-strength = <0x03>; + }; + + /omit-if-no-ref/ + pcfg_pull_none_drv_level_1_00: pcfg-pull-none-drv-level-1-00 { + bias-disable; + drive-strength = <0x04>; + }; + + /omit-if-no-ref/ + pcfg_pull_none_drv_level_1_25: pcfg-pull-none-drv-level-1-25 { + bias-disable; + drive-strength = <0x05>; + }; + + /omit-if-no-ref/ + pcfg_pull_none_drv_level_1_50: pcfg-pull-none-drv-level-1-50 { + bias-disable; + drive-strength = <0x06>; + }; + + /omit-if-no-ref/ + pcfg_pull_none_drv_level_1_75: pcfg-pull-none-drv-level-1-75 { + bias-disable; + drive-strength = <0x07>; + }; + + /omit-if-no-ref/ + pcfg_pull_none_drv_level_2_00: pcfg-pull-none-drv-level-2-00 { + bias-disable; + drive-strength = <0x0c>; + }; + + /omit-if-no-ref/ + pcfg_pull_none_drv_level_2_25: pcfg-pull-none-drv-level-2-25 { + bias-disable; + drive-strength = <0x0d>; + }; + + /omit-if-no-ref/ + pcfg_pull_none_drv_level_2_50: pcfg-pull-none-drv-level-2-50 { + bias-disable; + drive-strength = <0x0e>; + }; + + /omit-if-no-ref/ + pcfg_pull_none_drv_level_2_75: pcfg-pull-none-drv-level-2-75 { + bias-disable; + drive-strength = <0x0f>; + }; + + /omit-if-no-ref/ + pcfg_pull_none_drv_level_3_00: pcfg-pull-none-drv-level-3-00 { + bias-disable; + drive-strength = <0x1c>; + }; + + /omit-if-no-ref/ + pcfg_pull_none_drv_level_3_25: pcfg-pull-none-drv-level-3-25 { + bias-disable; + drive-strength = <0x1d>; + }; + + /omit-if-no-ref/ + pcfg_pull_none_drv_level_3_50: pcfg-pull-none-drv-level-3-50 { + bias-disable; + drive-strength = <0x1e>; + }; + + /omit-if-no-ref/ + pcfg_pull_none_drv_level_3_75: pcfg-pull-none-drv-level-3-75 { + bias-disable; + drive-strength = <0x1f>; + }; + + /omit-if-no-ref/ + pcfg_pull_none_drv_level_4_00: pcfg-pull-none-drv-level-4-00 { + bias-disable; + drive-strength = <0x2c>; + }; + + /omit-if-no-ref/ + pcfg_pull_none_drv_level_4_25: pcfg-pull-none-drv-level-4-25 { + bias-disable; + drive-strength = <0x2d>; + }; + + /omit-if-no-ref/ + pcfg_pull_none_drv_level_4_50: pcfg-pull-none-drv-level-4-50 { + bias-disable; + drive-strength = <0x2e>; + }; + + /omit-if-no-ref/ + pcfg_pull_none_drv_level_4_75: pcfg-pull-none-drv-level-4-75 { + bias-disable; + drive-strength = <0x2f>; + }; + + /omit-if-no-ref/ + pcfg_pull_none_drv_level_5_00: pcfg-pull-none-drv-level-5-00 { + bias-disable; + drive-strength = <0x3c>; + }; + + /omit-if-no-ref/ + pcfg_pull_none_drv_level_5_25: pcfg-pull-none-drv-level-5-25 { + bias-disable; + drive-strength = <0x3d>; + }; + + /omit-if-no-ref/ + pcfg_pull_none_drv_level_5_50: pcfg-pull-none-drv-level-5-50 { + bias-disable; + drive-strength = <0x3e>; + }; + + /omit-if-no-ref/ + pcfg_pull_none_drv_level_5_75: pcfg-pull-none-drv-level-5-75 { + bias-disable; + drive-strength = <0x3f>; + }; + + /omit-if-no-ref/ + pcfg_pull_up_drv_level_0_25: pcfg-pull-up-drv-level-0-25 { + bias-pull-up; + drive-strength = <0x01>; + }; + + /omit-if-no-ref/ + pcfg_pull_up_drv_level_0_50: pcfg-pull-up-drv-level-0-50 { + bias-pull-up; + drive-strength = <0x02>; + }; + + /omit-if-no-ref/ + pcfg_pull_up_drv_level_0_75: pcfg-pull-up-drv-level-0-75 { + bias-pull-up; + drive-strength = <0x03>; + }; + + /omit-if-no-ref/ + pcfg_pull_up_drv_level_1_00: pcfg-pull-up-drv-level-1-00 { + bias-pull-up; + drive-strength = <0x04>; + }; + + /omit-if-no-ref/ + pcfg_pull_up_drv_level_1_25: pcfg-pull-up-drv-level-1-25 { + bias-pull-up; + drive-strength = <0x05>; + }; + + /omit-if-no-ref/ + pcfg_pull_up_drv_level_1_50: pcfg-pull-up-drv-level-1-50 { + bias-pull-up; + drive-strength = <0x06>; + }; + + /omit-if-no-ref/ + pcfg_pull_up_drv_level_1_75: pcfg-pull-up-drv-level-1-75 { + bias-pull-up; + drive-strength = <0x07>; + }; + + /omit-if-no-ref/ + pcfg_pull_up_drv_level_2_00: pcfg-pull-up-drv-level-2-00 { + bias-pull-up; + drive-strength = <0x0c>; + }; + + /omit-if-no-ref/ + pcfg_pull_up_drv_level_2_25: pcfg-pull-up-drv-level-2-25 { + bias-pull-up; + drive-strength = <0x0d>; + }; + + /omit-if-no-ref/ + pcfg_pull_up_drv_level_2_50: pcfg-pull-up-drv-level-2-50 { + bias-pull-up; + drive-strength = <0x0e>; + }; + + /omit-if-no-ref/ + pcfg_pull_up_drv_level_2_75: pcfg-pull-up-drv-level-2-75 { + bias-pull-up; + drive-strength = <0x0f>; + }; + + /omit-if-no-ref/ + pcfg_pull_up_drv_level_3_00: pcfg-pull-up-drv-level-3-00 { + bias-pull-up; + drive-strength = <0x1c>; + }; + + /omit-if-no-ref/ + pcfg_pull_up_drv_level_3_25: pcfg-pull-up-drv-level-3-25 { + bias-pull-up; + drive-strength = <0x1d>; + }; + + /omit-if-no-ref/ + pcfg_pull_up_drv_level_3_50: pcfg-pull-up-drv-level-3-50 { + bias-pull-up; + drive-strength = <0x1e>; + }; + + /omit-if-no-ref/ + pcfg_pull_up_drv_level_3_75: pcfg-pull-up-drv-level-3-75 { + bias-pull-up; + drive-strength = <0x1f>; + }; + + /omit-if-no-ref/ + pcfg_pull_up_drv_level_4_00: pcfg-pull-up-drv-level-4-00 { + bias-pull-up; + drive-strength = <0x2c>; + }; + + /omit-if-no-ref/ + pcfg_pull_up_drv_level_4_25: pcfg-pull-up-drv-level-4-25 { + bias-pull-up; + drive-strength = <0x2d>; + }; + + /omit-if-no-ref/ + pcfg_pull_up_drv_level_4_50: pcfg-pull-up-drv-level-4-50 { + bias-pull-up; + drive-strength = <0x2e>; + }; + + /omit-if-no-ref/ + pcfg_pull_up_drv_level_4_75: pcfg-pull-up-drv-level-4-75 { + bias-pull-up; + drive-strength = <0x2f>; + }; + + /omit-if-no-ref/ + pcfg_pull_up_drv_level_5_00: pcfg-pull-up-drv-level-5-00 { + bias-pull-up; + drive-strength = <0x3c>; + }; + + /omit-if-no-ref/ + pcfg_pull_up_drv_level_5_25: pcfg-pull-up-drv-level-5-25 { + bias-pull-up; + drive-strength = <0x3d>; + }; + + /omit-if-no-ref/ + pcfg_pull_up_drv_level_5_50: pcfg-pull-up-drv-level-5-50 { + bias-pull-up; + drive-strength = <0x3e>; + }; + + /omit-if-no-ref/ + pcfg_pull_up_drv_level_5_75: pcfg-pull-up-drv-level-5-75 { + bias-pull-up; + drive-strength = <0x3f>; + }; + + /omit-if-no-ref/ + pcfg_pull_down_drv_level_0_25: pcfg-pull-down-drv-level-0-25 { + bias-pull-down; + drive-strength = <0x01>; + }; + + /omit-if-no-ref/ + pcfg_pull_down_drv_level_0_50: pcfg-pull-down-drv-level-0-50 { + bias-pull-down; + drive-strength = <0x02>; + }; + + /omit-if-no-ref/ + pcfg_pull_down_drv_level_0_75: pcfg-pull-down-drv-level-0-75 { + bias-pull-down; + drive-strength = <0x03>; + }; + + /omit-if-no-ref/ + pcfg_pull_down_drv_level_1_00: pcfg-pull-down-drv-level-1-00 { + bias-pull-down; + drive-strength = <0x04>; + }; + + /omit-if-no-ref/ + pcfg_pull_down_drv_level_1_25: pcfg-pull-down-drv-level-1-25 { + bias-pull-down; + drive-strength = <0x05>; + }; + + /omit-if-no-ref/ + pcfg_pull_down_drv_level_1_50: pcfg-pull-down-drv-level-1-50 { + bias-pull-down; + drive-strength = <0x06>; + }; + + /omit-if-no-ref/ + pcfg_pull_down_drv_level_1_75: pcfg-pull-down-drv-level-1-75 { + bias-pull-down; + drive-strength = <0x07>; + }; + + /omit-if-no-ref/ + pcfg_pull_down_drv_level_2_00: pcfg-pull-down-drv-level-2-00 { + bias-pull-down; + drive-strength = <0x0c>; + }; + + /omit-if-no-ref/ + pcfg_pull_down_drv_level_2_25: pcfg-pull-down-drv-level-2-25 { + bias-pull-down; + drive-strength = <0x0d>; + }; + + /omit-if-no-ref/ + pcfg_pull_down_drv_level_2_50: pcfg-pull-down-drv-level-2-50 { + bias-pull-down; + drive-strength = <0x0e>; + }; + + /omit-if-no-ref/ + pcfg_pull_down_drv_level_2_75: pcfg-pull-down-drv-level-2-75 { + bias-pull-down; + drive-strength = <0x0f>; + }; + + /omit-if-no-ref/ + pcfg_pull_down_drv_level_3_00: pcfg-pull-down-drv-level-3-00 { + bias-pull-down; + drive-strength = <0x1c>; + }; + + /omit-if-no-ref/ + pcfg_pull_down_drv_level_3_25: pcfg-pull-down-drv-level-3-25 { + bias-pull-down; + drive-strength = <0x1d>; + }; + + /omit-if-no-ref/ + pcfg_pull_down_drv_level_3_50: pcfg-pull-down-drv-level-3-50 { + bias-pull-down; + drive-strength = <0x1e>; + }; + + /omit-if-no-ref/ + pcfg_pull_down_drv_level_3_75: pcfg-pull-down-drv-level-3-75 { + bias-pull-down; + drive-strength = <0x1f>; + }; + + /omit-if-no-ref/ + pcfg_pull_down_drv_level_4_00: pcfg-pull-down-drv-level-4-00 { + bias-pull-down; + drive-strength = <0x2c>; + }; + + /omit-if-no-ref/ + pcfg_pull_down_drv_level_4_25: pcfg-pull-down-drv-level-4-25 { + bias-pull-down; + drive-strength = <0x2d>; + }; + + /omit-if-no-ref/ + pcfg_pull_down_drv_level_4_50: pcfg-pull-down-drv-level-4-50 { + bias-pull-down; + drive-strength = <0x2e>; + }; + + /omit-if-no-ref/ + pcfg_pull_down_drv_level_4_75: pcfg-pull-down-drv-level-4-75 { + bias-pull-down; + drive-strength = <0x2f>; + }; + + /omit-if-no-ref/ + pcfg_pull_down_drv_level_5_00: pcfg-pull-down-drv-level-5-00 { + bias-pull-down; + drive-strength = <0x3c>; + }; + + /omit-if-no-ref/ + pcfg_pull_down_drv_level_5_25: pcfg-pull-down-drv-level-5-25 { + bias-pull-down; + drive-strength = <0x3d>; + }; + + /omit-if-no-ref/ + pcfg_pull_down_drv_level_5_50: pcfg-pull-down-drv-level-5-50 { + bias-pull-down; + drive-strength = <0x3e>; + }; + + /omit-if-no-ref/ + pcfg_pull_down_drv_level_5_75: pcfg-pull-down-drv-level-5-75 { + bias-pull-down; + drive-strength = <0x3f>; + }; + + /omit-if-no-ref/ + pcfg_pull_up_smt: pcfg-pull-up-smt { + bias-pull-up; + input-schmitt-enable; + }; + + /omit-if-no-ref/ + pcfg_pull_down_smt: pcfg-pull-down-smt { + bias-pull-down; + input-schmitt-enable; + }; + + /omit-if-no-ref/ + pcfg_pull_none_smt: pcfg-pull-none-smt { + bias-disable; + input-schmitt-enable; + }; + + /omit-if-no-ref/ + pcfg_pull_none_drv_level_0_25_smt: pcfg-pull-none-drv-level-0-25-smt { + bias-disable; + drive-strength = <0x01>; + input-schmitt-enable; + }; + + /omit-if-no-ref/ + pcfg_pull_none_drv_level_0_50_smt: pcfg-pull-none-drv-level-0-50-smt { + bias-disable; + drive-strength = <0x02>; + input-schmitt-enable; + }; + + /omit-if-no-ref/ + pcfg_pull_none_drv_level_0_75_smt: pcfg-pull-none-drv-level-0-75-smt { + bias-disable; + drive-strength = <0x03>; + input-schmitt-enable; + }; + + /omit-if-no-ref/ + pcfg_pull_none_drv_level_1_00_smt: pcfg-pull-none-drv-level-1-00-smt { + bias-disable; + drive-strength = <0x04>; + input-schmitt-enable; + }; + + /omit-if-no-ref/ + pcfg_pull_none_drv_level_1_25_smt: pcfg-pull-none-drv-level-1-25-smt { + bias-disable; + drive-strength = <0x05>; + input-schmitt-enable; + }; + + /omit-if-no-ref/ + pcfg_pull_none_drv_level_1_50_smt: pcfg-pull-none-drv-level-1-50-smt { + bias-disable; + drive-strength = <0x06>; + input-schmitt-enable; + }; + + /omit-if-no-ref/ + pcfg_pull_none_drv_level_1_75_smt: pcfg-pull-none-drv-level-1-75-smt { + bias-disable; + drive-strength = <0x07>; + input-schmitt-enable; + }; + + /omit-if-no-ref/ + pcfg_pull_none_drv_level_2_00_smt: pcfg-pull-none-drv-level-2-00-smt { + bias-disable; + drive-strength = <0x0c>; + input-schmitt-enable; + }; + + /omit-if-no-ref/ + pcfg_pull_none_drv_level_2_25_smt: pcfg-pull-none-drv-level-2-25-smt { + bias-disable; + drive-strength = <0x0d>; + input-schmitt-enable; + }; + + /omit-if-no-ref/ + pcfg_pull_none_drv_level_2_50_smt: pcfg-pull-none-drv-level-2-50-smt { + bias-disable; + drive-strength = <0x0e>; + input-schmitt-enable; + }; + + /omit-if-no-ref/ + pcfg_pull_none_drv_level_2_75_smt: pcfg-pull-none-drv-level-2-75-smt { + bias-disable; + drive-strength = <0x0f>; + input-schmitt-enable; + }; + + /omit-if-no-ref/ + pcfg_pull_none_drv_level_3_00_smt: pcfg-pull-none-drv-level-3-00-smt { + bias-disable; + drive-strength = <0x1c>; + input-schmitt-enable; + }; + + /omit-if-no-ref/ + pcfg_pull_none_drv_level_3_25_smt: pcfg-pull-none-drv-level-3-25-smt { + bias-disable; + drive-strength = <0x1d>; + input-schmitt-enable; + }; + + /omit-if-no-ref/ + pcfg_pull_none_drv_level_3_50_smt: pcfg-pull-none-drv-level-3-50-smt { + bias-disable; + drive-strength = <0x1e>; + input-schmitt-enable; + }; + + /omit-if-no-ref/ + pcfg_pull_none_drv_level_3_75_smt: pcfg-pull-none-drv-level-3-75-smt { + bias-disable; + drive-strength = <0x1f>; + input-schmitt-enable; + }; + + /omit-if-no-ref/ + pcfg_pull_none_drv_level_4_00_smt: pcfg-pull-none-drv-level-4-00-smt { + bias-disable; + drive-strength = <0x2c>; + input-schmitt-enable; + }; + + /omit-if-no-ref/ + pcfg_pull_none_drv_level_4_25_smt: pcfg-pull-none-drv-level-4-25-smt { + bias-disable; + drive-strength = <0x2d>; + input-schmitt-enable; + }; + + /omit-if-no-ref/ + pcfg_pull_none_drv_level_4_50_smt: pcfg-pull-none-drv-level-4-50-smt { + bias-disable; + drive-strength = <0x2e>; + input-schmitt-enable; + }; + + /omit-if-no-ref/ + pcfg_pull_none_drv_level_4_75_smt: pcfg-pull-none-drv-level-4-75-smt { + bias-disable; + drive-strength = <0x2f>; + input-schmitt-enable; + }; + + /omit-if-no-ref/ + pcfg_pull_none_drv_level_5_00_smt: pcfg-pull-none-drv-level-5-00-smt { + bias-disable; + drive-strength = <0x3c>; + input-schmitt-enable; + }; + + /omit-if-no-ref/ + pcfg_pull_none_drv_level_5_25_smt: pcfg-pull-none-drv-level-5-25-smt { + bias-disable; + drive-strength = <0x3d>; + input-schmitt-enable; + }; + + /omit-if-no-ref/ + pcfg_pull_none_drv_level_5_50_smt: pcfg-pull-none-drv-level-5-50-smt { + bias-disable; + drive-strength = <0x3e>; + input-schmitt-enable; + }; + + /omit-if-no-ref/ + pcfg_pull_none_drv_level_5_75_smt: pcfg-pull-none-drv-level-5-75-smt { + bias-disable; + drive-strength = <0x3f>; + input-schmitt-enable; + }; + + /omit-if-no-ref/ + pcfg_output_high: pcfg-output-high { + output-high; + }; + + /omit-if-no-ref/ + pcfg_output_high_pull_up: pcfg-output-high-pull-up { + output-high; + bias-pull-up; + }; + + /omit-if-no-ref/ + pcfg_output_high_pull_down: pcfg-output-high-pull-down { + output-high; + bias-pull-down; + }; + + /omit-if-no-ref/ + pcfg_output_high_pull_none: pcfg-output-high-pull-none { + output-high; + bias-disable; + }; + + /omit-if-no-ref/ + pcfg_output_low: pcfg-output-low { + output-low; + }; + + /omit-if-no-ref/ + pcfg_output_low_pull_up: pcfg-output-low-pull-up { + output-low; + bias-pull-up; + }; + + /omit-if-no-ref/ + pcfg_output_low_pull_down: pcfg-output-low-pull-down { + output-low; + bias-pull-down; + }; + + /omit-if-no-ref/ + pcfg_output_low_pull_none: pcfg-output-low-pull-none { + output-low; + bias-disable; + }; +}; diff --git a/arch/arm64/boot/dts/rockchip/rv1126b-pinctrl.dtsi b/arch/arm64/boot/dts/rockchip/rv1126b-pinctrl.dtsi index a20a1987dac4..d2aa7ff395b9 100644 --- a/arch/arm64/boot/dts/rockchip/rv1126b-pinctrl.dtsi +++ b/arch/arm64/boot/dts/rockchip/rv1126b-pinctrl.dtsi @@ -4,7 +4,7 @@ */ #include -#include "rockchip-pinconf.dtsi" +#include "rv1126b-pinconf.dtsi" /* * This file is auto generated by pin2dts tool, please keep these code @@ -1767,27 +1767,27 @@ sdmmc0_bus4_pins: sdmmc0-bus4-pins { rockchip,pins = /* sdmmc0_d0 */ - <2 RK_PA0 1 &pcfg_pull_up_drv_level_3>, + <2 RK_PA0 1 &pcfg_pull_up_drv_level_2_75>, /* sdmmc0_d1 */ - <2 RK_PA1 1 &pcfg_pull_up_drv_level_3>, + <2 RK_PA1 1 &pcfg_pull_up_drv_level_2_75>, /* sdmmc0_d2 */ - <2 RK_PA2 1 &pcfg_pull_up_drv_level_3>, + <2 RK_PA2 1 &pcfg_pull_up_drv_level_2_75>, /* sdmmc0_d3 */ - <2 RK_PA3 1 &pcfg_pull_up_drv_level_3>; + <2 RK_PA3 1 &pcfg_pull_up_drv_level_2_75>; }; /omit-if-no-ref/ sdmmc0_cmd_pins: sdmmc0-cmd-pins { rockchip,pins = /* sdmmc0_cmd */ - <2 RK_PA5 1 &pcfg_pull_up_drv_level_3>; + <2 RK_PA5 1 &pcfg_pull_up_drv_level_2_75>; }; /omit-if-no-ref/ sdmmc0_clk_pins: sdmmc0-clk-pins { rockchip,pins = /* sdmmc0_clk */ - <2 RK_PA4 1 &pcfg_pull_up_drv_level_3>; + <2 RK_PA4 1 &pcfg_pull_up_drv_level_2_75>; }; /omit-if-no-ref/ @@ -1839,72 +1839,72 @@ spi0m0_clk_pins: spi0m0-clk-pins { rockchip,pins = /* spi0_clk_m0 */ - <0 RK_PB2 2 &pcfg_pull_none_drv_level_3>, + <0 RK_PB2 2 &pcfg_pull_none_drv_level_2_75>, /* spi0_miso_m0 */ - <0 RK_PB1 2 &pcfg_pull_none_drv_level_3>, + <0 RK_PB1 2 &pcfg_pull_none_drv_level_2_75>, /* spi0_mosi_m0 */ - <0 RK_PB0 2 &pcfg_pull_none_drv_level_3>; + <0 RK_PB0 2 &pcfg_pull_none_drv_level_2_75>; }; /omit-if-no-ref/ spi0m0_csn0_pins: spi0m0-csn0-pins { rockchip,pins = /* spi0m0_csn0 */ - <0 RK_PA7 2 &pcfg_pull_none_drv_level_3>; + <0 RK_PA7 2 &pcfg_pull_none_drv_level_2_75>; }; /omit-if-no-ref/ spi0m0_csn1_pins: spi0m0-csn1-pins { rockchip,pins = /* spi0m0_csn1 */ - <0 RK_PA6 2 &pcfg_pull_none_drv_level_3>; + <0 RK_PA6 2 &pcfg_pull_none_drv_level_2_75>; }; /omit-if-no-ref/ spi0m1_clk_pins: spi0m1-clk-pins { rockchip,pins = /* spi0_clk_m1 */ - <4 RK_PA7 1 &pcfg_pull_none_drv_level_3>, + <4 RK_PA7 1 &pcfg_pull_none_drv_level_2_75>, /* spi0_miso_m1 */ - <4 RK_PA5 1 &pcfg_pull_none_drv_level_3>, + <4 RK_PA5 1 &pcfg_pull_none_drv_level_2_75>, /* spi0_mosi_m1 */ - <4 RK_PA4 1 &pcfg_pull_none_drv_level_3>; + <4 RK_PA4 1 &pcfg_pull_none_drv_level_2_75>; }; /omit-if-no-ref/ spi0m1_csn0_pins: spi0m1-csn0-pins { rockchip,pins = /* spi0m1_csn0 */ - <4 RK_PA6 1 &pcfg_pull_none_drv_level_3>; + <4 RK_PA6 1 &pcfg_pull_none_drv_level_2_75>; }; /omit-if-no-ref/ spi0m1_csn1_pins: spi0m1-csn1-pins { rockchip,pins = /* spi0m1_csn1 */ - <4 RK_PA3 1 &pcfg_pull_none_drv_level_3>; + <4 RK_PA3 1 &pcfg_pull_none_drv_level_2_75>; }; /omit-if-no-ref/ spi0m2_clk_pins: spi0m2-clk-pins { rockchip,pins = /* spi0_clk_m2 */ - <5 RK_PA6 2 &pcfg_pull_none_drv_level_3>, + <5 RK_PA6 2 &pcfg_pull_none_drv_level_2_75>, /* spi0_miso_m2 */ - <5 RK_PA5 2 &pcfg_pull_none_drv_level_3>, + <5 RK_PA5 2 &pcfg_pull_none_drv_level_2_75>, /* spi0_mosi_m2 */ - <5 RK_PA4 2 &pcfg_pull_none_drv_level_3>; + <5 RK_PA4 2 &pcfg_pull_none_drv_level_2_75>; }; /omit-if-no-ref/ spi0m2_csn0_pins: spi0m2-csn0-pins { rockchip,pins = /* spi0m2_csn0 */ - <5 RK_PA3 2 &pcfg_pull_none_drv_level_3>; + <5 RK_PA3 2 &pcfg_pull_none_drv_level_2_75>; }; /omit-if-no-ref/ spi0m2_csn1_pins: spi0m2-csn1-pins { rockchip,pins = /* spi0m2_csn1 */ - <5 RK_PA7 2 &pcfg_pull_none_drv_level_3>; + <5 RK_PA7 2 &pcfg_pull_none_drv_level_2_75>; }; }; @@ -1913,72 +1913,72 @@ spi1m0_clk_pins: spi1m0-clk-pins { rockchip,pins = /* spi1_clk_m0 */ - <6 RK_PB4 3 &pcfg_pull_none_drv_level_3>, + <6 RK_PB4 3 &pcfg_pull_none_drv_level_2_75>, /* spi1_miso_m0 */ - <6 RK_PB3 3 &pcfg_pull_none_drv_level_3>, + <6 RK_PB3 3 &pcfg_pull_none_drv_level_2_75>, /* spi1_mosi_m0 */ - <6 RK_PB2 3 &pcfg_pull_none_drv_level_3>; + <6 RK_PB2 3 &pcfg_pull_none_drv_level_2_75>; }; /omit-if-no-ref/ spi1m0_csn0_pins: spi1m0-csn0-pins { rockchip,pins = /* spi1m0_csn0 */ - <6 RK_PB1 3 &pcfg_pull_none_drv_level_3>; + <6 RK_PB1 3 &pcfg_pull_none_drv_level_2_75>; }; /omit-if-no-ref/ spi1m0_csn1_pins: spi1m0-csn1-pins { rockchip,pins = /* spi1m0_csn1 */ - <6 RK_PB0 3 &pcfg_pull_none_drv_level_3>; + <6 RK_PB0 3 &pcfg_pull_none_drv_level_2_75>; }; /omit-if-no-ref/ spi1m1_clk_pins: spi1m1-clk-pins { rockchip,pins = /* spi1_clk_m1 */ - <3 RK_PB4 1 &pcfg_pull_none_drv_level_3>, + <3 RK_PB4 1 &pcfg_pull_none_drv_level_2_75>, /* spi1_miso_m1 */ - <3 RK_PB3 1 &pcfg_pull_none_drv_level_3>, + <3 RK_PB3 1 &pcfg_pull_none_drv_level_2_75>, /* spi1_mosi_m1 */ - <3 RK_PB2 1 &pcfg_pull_none_drv_level_3>; + <3 RK_PB2 1 &pcfg_pull_none_drv_level_2_75>; }; /omit-if-no-ref/ spi1m1_csn0_pins: spi1m1-csn0-pins { rockchip,pins = /* spi1m1_csn0 */ - <3 RK_PB5 1 &pcfg_pull_none_drv_level_3>; + <3 RK_PB5 1 &pcfg_pull_none_drv_level_2_75>; }; /omit-if-no-ref/ spi1m1_csn1_pins: spi1m1-csn1-pins { rockchip,pins = /* spi1m1_csn1 */ - <3 RK_PB6 1 &pcfg_pull_none_drv_level_3>; + <3 RK_PB6 1 &pcfg_pull_none_drv_level_2_75>; }; /omit-if-no-ref/ spi1m2_clk_pins: spi1m2-clk-pins { rockchip,pins = /* spi1_clk_m2 */ - <5 RK_PD1 2 &pcfg_pull_none_drv_level_3>, + <5 RK_PD1 2 &pcfg_pull_none_drv_level_2_75>, /* spi1_miso_m2 */ - <5 RK_PD3 2 &pcfg_pull_none_drv_level_3>, + <5 RK_PD3 2 &pcfg_pull_none_drv_level_2_75>, /* spi1_mosi_m2 */ - <5 RK_PD2 2 &pcfg_pull_none_drv_level_3>; + <5 RK_PD2 2 &pcfg_pull_none_drv_level_2_75>; }; /omit-if-no-ref/ spi1m2_csn0_pins: spi1m2-csn0-pins { rockchip,pins = /* spi1m2_csn0 */ - <5 RK_PD0 2 &pcfg_pull_none_drv_level_3>; + <5 RK_PD0 2 &pcfg_pull_none_drv_level_2_75>; }; /omit-if-no-ref/ spi1m2_csn1_pins: spi1m2-csn1-pins { rockchip,pins = /* spi1m2_csn1 */ - <5 RK_PD4 2 &pcfg_pull_none_drv_level_3>; + <5 RK_PD4 2 &pcfg_pull_none_drv_level_2_75>; }; }; From b7b90f1ca91abaecac138a52f4b8f2657eda8298 Mon Sep 17 00:00:00 2001 From: Ye Zhang Date: Fri, 16 May 2025 17:51:55 +0800 Subject: [PATCH 5/6] pinctrl: rockchip: refine drive strength levels for RV1126B This commit has refined the driver strength configuration of the RV1126B from 6 levels to 23 levels Signed-off-by: Ye Zhang Change-Id: I61cee294cbb194366909acc70dec3d41a0a1e961 --- drivers/pinctrl/pinctrl-rockchip.c | 51 +++++++++++++++++------------- 1 file changed, 29 insertions(+), 22 deletions(-) diff --git a/drivers/pinctrl/pinctrl-rockchip.c b/drivers/pinctrl/pinctrl-rockchip.c index ffcd4ef04121..1b9e48d529c1 100644 --- a/drivers/pinctrl/pinctrl-rockchip.c +++ b/drivers/pinctrl/pinctrl-rockchip.c @@ -316,19 +316,12 @@ #define RK3588_PIN_BANK_FLAGS(ID, PIN, LABEL, M, P) \ PIN_BANK_IOMUX_FLAGS_PULL_FLAGS(ID, PIN, LABEL, M, M, M, M, P, P, P, P) -#define PIN_BANK_IOMUX_4_OFFSET_DRV_8(id, pins, label, offset0, \ - offset1, offset2, offset3) \ - PIN_BANK_IOMUX_FLAGS_OFFSET_DRV_FLAGS(id, pins, label, \ - IOMUX_WIDTH_4BIT, \ - IOMUX_WIDTH_4BIT, \ - IOMUX_WIDTH_4BIT, \ - IOMUX_WIDTH_4BIT, \ - offset0, offset1, \ - offset2, offset3, \ - DRV_TYPE_IO_LEVEL_8_BIT, \ - DRV_TYPE_IO_LEVEL_8_BIT, \ - DRV_TYPE_IO_LEVEL_8_BIT, \ - DRV_TYPE_IO_LEVEL_8_BIT) +#define PIN_BANK_IOMUX_4_OFFSET(id, pins, label, offset0, \ + offset1, offset2, offset3) \ + PIN_BANK_IOMUX_FLAGS_OFFSET(id, pins, label, \ + IOMUX_WIDTH_4BIT, IOMUX_WIDTH_4BIT, \ + IOMUX_WIDTH_4BIT, IOMUX_WIDTH_4BIT, \ + offset0, offset1, offset2, offset3) static struct pinctrl_dev *g_pctldev; static DEFINE_MUTEX(iomux_lock); @@ -3624,6 +3617,17 @@ static int rockchip_get_drive_perpin(struct rockchip_pin_bank *bank, if (ret) return ret; + if (ctrl->type == RV1126B) { + rmask_bits = RV1126B_DRV_BITS_PER_PIN; + ret = regmap_read(regmap, reg, &data); + if (ret) + return ret; + data >>= bit; + data &= (1 << rmask_bits) - 1; + + return data; + } + switch (drv_type) { case DRV_TYPE_IO_1V8_3V0_AUTO: case DRV_TYPE_IO_3V3_ONLY: @@ -3745,7 +3749,6 @@ static int rockchip_set_drive_perpin(struct rockchip_pin_bank *bank, ret = strength; goto config; } else if (ctrl->type == RV1106 || - ctrl->type == RV1126B || ctrl->type == RK3506 || ctrl->type == RK3528 || ctrl->type == RK3562 || @@ -3757,6 +3760,10 @@ static int rockchip_set_drive_perpin(struct rockchip_pin_bank *bank, rmask_bits = RK3576_DRV_BITS_PER_PIN; ret = ((strength & BIT(2)) >> 2) | ((strength & BIT(0)) << 2) | (strength & BIT(1)); goto config; + } else if (ctrl->type == RV1126B) { + rmask_bits = RV1126B_DRV_BITS_PER_PIN; + ret = strength; + goto config; } ret = -EINVAL; @@ -5312,21 +5319,21 @@ static struct rockchip_pin_ctrl rv1126_pin_ctrl __maybe_unused = { }; static struct rockchip_pin_bank rv1126b_pin_banks[] = { - PIN_BANK_IOMUX_4_OFFSET_DRV_8(0, 32, "gpio0", + PIN_BANK_IOMUX_4_OFFSET(0, 32, "gpio0", 0x0, 0x8, 0x8010, 0x8018), - PIN_BANK_IOMUX_4_OFFSET_DRV_8(1, 32, "gpio1", + PIN_BANK_IOMUX_4_OFFSET(1, 32, "gpio1", 0x10020, 0x10028, 0x10030, 0x10038), - PIN_BANK_IOMUX_4_OFFSET_DRV_8(2, 32, "gpio2", + PIN_BANK_IOMUX_4_OFFSET(2, 32, "gpio2", 0x18040, 0x18048, 0x18050, 0x18058), - PIN_BANK_IOMUX_4_OFFSET_DRV_8(3, 32, "gpio3", + PIN_BANK_IOMUX_4_OFFSET(3, 32, "gpio3", 0x20060, 0x20068, 0x20070, 0x20078), - PIN_BANK_IOMUX_4_OFFSET_DRV_8(4, 32, "gpio4", + PIN_BANK_IOMUX_4_OFFSET(4, 32, "gpio4", 0x28080, 0x28088, 0x28090, 0x28098), - PIN_BANK_IOMUX_4_OFFSET_DRV_8(5, 32, "gpio5", + PIN_BANK_IOMUX_4_OFFSET(5, 32, "gpio5", 0x300a0, 0x300a8, 0x300b0, 0x300b8), - PIN_BANK_IOMUX_4_OFFSET_DRV_8(6, 32, "gpio6", + PIN_BANK_IOMUX_4_OFFSET(6, 32, "gpio6", 0x380c0, 0x380c8, 0x380d0, 0x380d8), - PIN_BANK_IOMUX_4_OFFSET_DRV_8(7, 32, "gpio7", + PIN_BANK_IOMUX_4_OFFSET(7, 32, "gpio7", 0x400e0, 0x400e8, 0x400f0, 0x400f8), }; From ff148eedd4c9194ebffe9e26d405a75120dd2d74 Mon Sep 17 00:00:00 2001 From: Yu Qiaowei Date: Mon, 26 May 2025 15:45:28 +0800 Subject: [PATCH 6/6] video: rockchip: rga3: RGA2 scale mode add default config When the task is not submitted from the librga im2d API, the scale mode may be default, so additional default configuration is required. Change-Id: Ie5966308ad1af09a6a7eec489126670dc1085dac Signed-off-by: Yu Qiaowei --- drivers/video/rockchip/rga3/rga2_reg_info.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/video/rockchip/rga3/rga2_reg_info.c b/drivers/video/rockchip/rga3/rga2_reg_info.c index 886d4f33961e..8e3d18f4dad1 100644 --- a/drivers/video/rockchip/rga3/rga2_reg_info.c +++ b/drivers/video/rockchip/rga3/rga2_reg_info.c @@ -439,11 +439,20 @@ static void RGA2_set_reg_src_info(u8 *base, struct rga2_req *msg) case RGA_INTERP_LINEAR: vsp_scale_mode = 1; break; + case RGA_INTERP_DEFAULT: + if (((scale_w_flag == RGA2_SCALE_DOWN) && (dw < RGA2_VSP_BICUBIC_LIMIT)) || + (sw < RGA2_VSP_BICUBIC_LIMIT)) { + vsp_scale_mode = 0x0; + } else { + vsp_scale_mode = 0x1; + } + break; } } else if (scale_h_flag == RGA2_SCALE_DOWN) { switch (msg->interp.verti) { case RGA_INTERP_AVERAGE: + case RGA_INTERP_DEFAULT: vsd_scale_mode = 0; break; case RGA_INTERP_LINEAR: @@ -456,6 +465,7 @@ static void RGA2_set_reg_src_info(u8 *base, struct rga2_req *msg) if (scale_w_flag == RGA2_SCALE_UP) { switch (msg->interp.horiz) { case RGA_INTERP_BICUBIC: + case RGA_INTERP_DEFAULT: hsp_scale_mode = 0; break; case RGA_INTERP_LINEAR: @@ -465,6 +475,7 @@ static void RGA2_set_reg_src_info(u8 *base, struct rga2_req *msg) } else if (scale_w_flag == RGA2_SCALE_DOWN) { switch (msg->interp.horiz) { case RGA_INTERP_AVERAGE: + case RGA_INTERP_DEFAULT: hsd_scale_mode = 0; break; case RGA_INTERP_LINEAR: