media: rockchip: vicap: sync with kernel-5.10

Merge from kernel-5.10
	media: rockchip: vicap skip fs/fe match detect when use smartsens sensor and work with hdr mode
	media: vicap: fixed the sequence not increasing in one frame mode
	media: rockchip: vicap support soft sync mode
	media: rockchip: vicap support get timestamp for rtt_stream_on buffer
	media: rockchip: vicap support mipi/dvp reset together below rk3588
	media: rockchip: vicap fixes error of frame interval info
	media: rockchip: vicap remove interrupt flags of IRQF_SHARED for rv1106/rv1103b
	media: rockchip: vicap fixes error of buf update seconds in one frame interval
	media: rockchip: vicap fixes lack_buf_cnt error
	media: rockchip: vicap clean to_stop_dma state before start stream
	media: rockchip: vicap fixes error of rtt stream on
	media: rockchip: vicap add pipe stop stream to function of shutdown
	media: rockchip: vicap skip direct reset when size err occurs and work in online mode
	media: rockchip: vicap proc node add group info
	media: rockchip: vicap: error print of mipi csi2 add base address to distinguish device
	media: rockchip: vicap fixes error of wake up time in thundboot mode
	media: rockchip: vicap support rtt stream on
	media: rockchip: vicap make sure sequence of first frame send to isp is zero
	media: rockchip: vicap rdbk_auto mode support group sync
	media: rockchip: vicap add register debug info to proc node
	media: rockchip: vicap support online_unite with thunderboot
	media: rockchip: vicap support set csi2 quick stream on/off
	media: rockchip: vicap fixes logic of thunderboot skip
	media: rockchip: vicap clean fs intr state before set fs intr enable
	media: rockchip: vicap use addr force update to replace dma reset for chip after rk3562
	media: rockchip: vicap add complete for restart stream with aov
	media: rockchip: vicap fixes soft reset error of chips after rv1103b
	media: rockchip: vicap set capture mode to isp when resume one frame mode
	media: rockchip: vicap remove line intr disable each frame after rk3588
	media: rockchip: vicap wait fe to stop stream when stream suspend
	media: rockchip: vicap remove cif-rockit init limit
	media: rockchip: vicap add vblank check
	media: rockchip: vicap: fastboot reserved buffer count according to isp
	media: rockchip: vicap: single dev need to config toisp when resume
	media: rockchip: vicap fixes null point of cur_stream
	media: rockchip: vicap disable fs inf intr when stop dma capture to reduce unnecessary intr consume
	media: rockchip: vicap fixes error of common dual camera aov
	media: rockchip: vicap add frame skipping to ensure frame integrity when using sensor flip
	media: rockchip: vicap remove limit of x_offset/y_offset
	media: rockchip: vicap support rounding 2/4bit for rv1103b
	media: rockchip: vicap support online hdr wrap for rv1103b
	media: rockchip: vicap fixes cru rst sequence of rv1103b
	media: rockchip: vicap fixes stream off issue when restart to multi frame mode
	media: rockchip: rv1103b vicap support online unite
	media: rockchip: vicap move toisp stop operation to toisp fs for more secure
	media: rockchip: vicap fixes same error with more toisp mode
	media: rockchip: vicap change work mode according to isp
	media: rockchip: vicap support rv1103b
	media: rockchip: vicap fixes isp timeout error
	media: rockchip: vicap fixes error of multi frame mode to singgle frame
	media: rockchip: vicap: rv1106 isp_unite not support change to online
	media: rockchip: vicap: rv1106 unite fixes error of write toisp register
	media: rockchip: vicap: rv1106 unite fix loss stream frame one frame to multi frame mode
	media: rockchip: vicap support distinguish toisp on/off
	media: rockchip: vicap check dev cnt acording to rkisp sd cxonnect state
	media: rockchip: vicap fixes error call soft reset below rk3588
	media: rockchip: vicap support change to multi frame mode during capture in one frame mode
	media: rockchip: vicap add limit of rdbk_mode from app for aov
	media: rockchip: vicap fixes stream loss with rockit
	media: rockchip: vicap wait thunderboot ready when open video

Signed-off-by: Zefa Chen <zefa.chen@rock-chips.com>
Change-Id: Icc7c03e5d15bd4ea789deaa785a4534eafd53ce9
This commit is contained in:
Zefa Chen
2024-11-01 10:08:30 +08:00
committed by Tao Huang
parent 478cdcd25c
commit febc2c13b5
13 changed files with 2406 additions and 593 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -201,6 +201,8 @@ int rkcif_rockit_buf_queue(struct rockit_rkcif_cfg *input_rockit_cfg)
list_add_tail(&rkcif_buf->cif_buf.queue, &stream->rockit_buf_head);
spin_unlock_irqrestore(&stream->vbq_lock, lock_flags);
if (stream->lack_buf_cnt)
rkcif_check_buffer_update_pingpong_rockit(stream, stream->id);
return 0;
}

View File

@@ -342,8 +342,11 @@ static struct dma_buf *rkcif_shm_alloc(struct rkisp_thunderboot_shmem *shmem)
int rkcif_alloc_reserved_mem_buf(struct rkcif_device *dev, struct rkcif_rx_buffer *buf)
{
struct rkcif_dummy_buffer *dummy = &buf->dummy;
u32 reserved_mem = 0;
dummy->dma_addr = dev->resmem_pa + dummy->size * buf->buf_idx;
if (dev->pre_buf_num)
reserved_mem = SHARED_MEM_RESERVED_HEAD_SIZE;
dummy->dma_addr = reserved_mem + dev->resmem_pa + dummy->size * buf->buf_idx;
if (dummy->dma_addr + dummy->size > dev->resmem_pa + dev->resmem_size)
return -EINVAL;
buf->dbufs.dma = dummy->dma_addr;

View File

@@ -95,7 +95,7 @@ static ssize_t rkcif_store_compact_mode(struct device *dev,
return len;
}
static DEVICE_ATTR(compact_test, S_IWUSR | S_IRUSR,
static DEVICE_ATTR(compact_test, 0600,
rkcif_show_compact_mode, rkcif_store_compact_mode);
static ssize_t rkcif_show_line_int_num(struct device *dev,
@@ -132,7 +132,7 @@ static ssize_t rkcif_store_line_int_num(struct device *dev,
return len;
}
static DEVICE_ATTR(wait_line, S_IWUSR | S_IRUSR,
static DEVICE_ATTR(wait_line, 0600,
rkcif_show_line_int_num, rkcif_store_line_int_num);
static ssize_t rkcif_show_dummybuf_mode(struct device *dev,
@@ -167,7 +167,7 @@ static ssize_t rkcif_store_dummybuf_mode(struct device *dev,
return len;
}
static DEVICE_ATTR(is_use_dummybuf, S_IWUSR | S_IRUSR,
static DEVICE_ATTR(is_use_dummybuf, 0600,
rkcif_show_dummybuf_mode, rkcif_store_dummybuf_mode);
/* show the memory mode of each stream in stream index order,
@@ -228,7 +228,7 @@ static ssize_t rkcif_store_memory_mode(struct device *dev,
return len;
}
static DEVICE_ATTR(is_high_align, S_IWUSR | S_IRUSR,
static DEVICE_ATTR(is_high_align, 0600,
rkcif_show_memory_mode, rkcif_store_memory_mode);
static ssize_t rkcif_show_scale_ch0_blc(struct device *dev,
@@ -298,7 +298,7 @@ static ssize_t rkcif_store_scale_ch0_blc(struct device *dev,
return len;
}
static DEVICE_ATTR(scale_ch0_blc, S_IWUSR | S_IRUSR,
static DEVICE_ATTR(scale_ch0_blc, 0600,
rkcif_show_scale_ch0_blc, rkcif_store_scale_ch0_blc);
static ssize_t rkcif_show_scale_ch1_blc(struct device *dev,
@@ -370,7 +370,7 @@ static ssize_t rkcif_store_scale_ch1_blc(struct device *dev,
return len;
}
static DEVICE_ATTR(scale_ch1_blc, S_IWUSR | S_IRUSR,
static DEVICE_ATTR(scale_ch1_blc, 0600,
rkcif_show_scale_ch1_blc, rkcif_store_scale_ch1_blc);
static ssize_t rkcif_show_scale_ch2_blc(struct device *dev,
@@ -441,7 +441,7 @@ static ssize_t rkcif_store_scale_ch2_blc(struct device *dev,
return len;
}
static DEVICE_ATTR(scale_ch2_blc, S_IWUSR | S_IRUSR,
static DEVICE_ATTR(scale_ch2_blc, 0600,
rkcif_show_scale_ch2_blc, rkcif_store_scale_ch2_blc);
static ssize_t rkcif_show_scale_ch3_blc(struct device *dev,
@@ -513,7 +513,7 @@ static ssize_t rkcif_store_scale_ch3_blc(struct device *dev,
return len;
}
static DEVICE_ATTR(scale_ch3_blc, S_IWUSR | S_IRUSR,
static DEVICE_ATTR(scale_ch3_blc, 0600,
rkcif_show_scale_ch3_blc, rkcif_store_scale_ch3_blc);
static ssize_t rkcif_store_capture_fps(struct device *dev,
@@ -871,7 +871,7 @@ static ssize_t rkcif_store_odd_frame_id(struct device *dev,
return len;
}
static DEVICE_ATTR(odd_frame_id, S_IWUSR | S_IRUSR,
static DEVICE_ATTR(odd_frame_id, 0600,
rkcif_show_odd_frame_id, rkcif_store_odd_frame_id);
static ssize_t rkcif_show_odd_frame_fisrt(struct device *dev,
@@ -920,7 +920,7 @@ static ssize_t rkcif_store_odd_frame_fisrt(struct device *dev,
return len;
}
static DEVICE_ATTR(odd_frame_first, S_IWUSR | S_IRUSR,
static DEVICE_ATTR(odd_frame_first, 0600,
rkcif_show_odd_frame_fisrt, rkcif_store_odd_frame_fisrt);
static ssize_t rkcif_show_low_latency(struct device *dev,
@@ -973,6 +973,37 @@ static ssize_t rkcif_store_low_latency(struct device *dev,
static DEVICE_ATTR(low_latency, S_IWUSR | S_IRUSR,
rkcif_show_low_latency, rkcif_store_low_latency);
static ssize_t rkcif_show_reg_dbg(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct rkcif_device *cif_dev = (struct rkcif_device *)dev_get_drvdata(dev);
int ret;
ret = snprintf(buf, PAGE_SIZE, "%d\n",
cif_dev->reg_dbg);
return ret;
}
static ssize_t rkcif_store_reg_dbg(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t len)
{
struct rkcif_device *cif_dev = (struct rkcif_device *)dev_get_drvdata(dev);
int val = 0;
int ret = 0;
ret = kstrtoint(buf, 0, &val);
if (!ret && val >= 0 && val <= 0x3)
cif_dev->reg_dbg = val;
else
dev_info(cif_dev->dev, "set reg_dbg failed\n");
return len;
}
static DEVICE_ATTR(reg_dbg, 0600,
rkcif_show_reg_dbg, rkcif_store_reg_dbg);
static struct attribute *dev_attrs[] = {
&dev_attr_compact_test.attr,
&dev_attr_wait_line.attr,
@@ -991,6 +1022,7 @@ static struct attribute *dev_attrs[] = {
&dev_attr_sw_dbg_en.attr,
&dev_attr_use_hw_interlace.attr,
&dev_attr_low_latency.attr,
&dev_attr_reg_dbg.attr,
NULL,
};
@@ -1014,7 +1046,8 @@ void rkcif_write_register(struct rkcif_device *dev,
index <= CIF_REG_MIPI_ON_PAD) {
if (dev->chip_id == CHIP_RK3588_CIF) {
csi_offset = dev->csi_host_idx * 0x100;
} else if (dev->chip_id == CHIP_RV1106_CIF) {
} else if (dev->chip_id == CHIP_RV1106_CIF ||
dev->chip_id == CHIP_RV1103B_CIF) {
csi_offset = dev->csi_host_idx * 0x200;
} else if (dev->chip_id == CHIP_RK3562_CIF) {
if (dev->csi_host_idx < 3)
@@ -1055,7 +1088,8 @@ void rkcif_write_register_or(struct rkcif_device *dev,
index <= CIF_REG_MIPI_ON_PAD) {
if (dev->chip_id == CHIP_RK3588_CIF) {
csi_offset = dev->csi_host_idx * 0x100;
} else if (dev->chip_id == CHIP_RV1106_CIF) {
} else if (dev->chip_id == CHIP_RV1106_CIF ||
dev->chip_id == CHIP_RV1103B_CIF) {
csi_offset = dev->csi_host_idx * 0x200;
} else if (dev->chip_id == CHIP_RK3562_CIF) {
if (dev->csi_host_idx < 3)
@@ -1099,7 +1133,8 @@ void rkcif_write_register_and(struct rkcif_device *dev,
index <= CIF_REG_MIPI_ON_PAD) {
if (dev->chip_id == CHIP_RK3588_CIF) {
csi_offset = dev->csi_host_idx * 0x100;
} else if (dev->chip_id == CHIP_RV1106_CIF) {
} else if (dev->chip_id == CHIP_RV1106_CIF ||
dev->chip_id == CHIP_RV1103B_CIF) {
csi_offset = dev->csi_host_idx * 0x200;
} else if (dev->chip_id == CHIP_RK3562_CIF) {
if (dev->csi_host_idx < 3)
@@ -1144,7 +1179,8 @@ unsigned int rkcif_read_register(struct rkcif_device *dev,
index <= CIF_REG_MIPI_ON_PAD) {
if (dev->chip_id == CHIP_RK3588_CIF) {
csi_offset = dev->csi_host_idx * 0x100;
} else if (dev->chip_id == CHIP_RV1106_CIF) {
} else if (dev->chip_id == CHIP_RV1106_CIF ||
dev->chip_id == CHIP_RV1103B_CIF) {
csi_offset = dev->csi_host_idx * 0x200;
} else if (dev->chip_id == CHIP_RK3562_CIF) {
if (dev->csi_host_idx < 3)
@@ -1408,7 +1444,8 @@ static void rkcif_set_sensor_streamon_in_sync_mode(struct rkcif_device *cif_dev)
}
if (sync_config->mode == RKCIF_MASTER_MASTER ||
sync_config->mode == RKCIF_MASTER_SLAVE) {
sync_config->mode == RKCIF_MASTER_SLAVE ||
sync_config->mode == RKCIF_SOFT_SYNC) {
for (i = 0; i < sync_config->slave.count; i++) {
dev = sync_config->slave.cif_dev[i];
is_streaming = sync_config->slave.is_streaming[i];
@@ -1488,6 +1525,32 @@ static void rkcif_set_sensor_streamon_in_sync_mode(struct rkcif_device *cif_dev)
v4l2_dbg(3, rkcif_debug, &dev->v4l2_dev,
"quick stream in sync mode, int_master_dev[%d]\n", i);
}
for (i = 0; i < sync_config->soft_sync.count; i++) {
dev = sync_config->soft_sync.cif_dev[i];
is_streaming = sync_config->soft_sync.is_streaming[i];
if (!is_streaming) {
if (dev->sditf_cnt == 1) {
ret = v4l2_subdev_call(dev->terminal_sensor.sd, core, ioctl,
RKMODULE_SET_QUICK_STREAM, &on);
if (ret)
dev_info(hw->dev,
"set RKMODULE_SET_QUICK_STREAM failed\n");
} else {
for (j = 0; j < dev->sditf_cnt; j++)
ret |= v4l2_subdev_call(dev->sditf[j]->sensor_sd,
core,
ioctl,
RKMODULE_SET_QUICK_STREAM,
&on);
if (ret)
dev_info(dev->dev,
"set RKMODULE_SET_QUICK_STREAM failed\n");
}
sync_config->soft_sync.is_streaming[i] = true;
}
v4l2_dbg(3, rkcif_debug, &dev->v4l2_dev,
"quick stream in sync mode, soft_sync[%d]\n", i);
}
}
mutex_unlock(&hw->dev_lock);
}
@@ -1552,9 +1615,12 @@ static int rkcif_pipeline_set_stream(struct rkcif_pipeline *p, bool on)
cif_dev->reset_watchdog_timer.is_running = false;
cif_dev->err_state_work.last_timestamp = 0;
cif_dev->is_toisp_reset = false;
atomic_set(&cif_dev->sensor_off, 0);
for (i = 0; i < cif_dev->num_channels; i++)
cif_dev->reset_watchdog_timer.last_buf_wakeup_cnt[i] = 0;
cif_dev->reset_watchdog_timer.run_cnt = 0;
} else {
atomic_set(&cif_dev->sensor_off, 1);
}
/* phy -> sensor */
@@ -1609,6 +1675,9 @@ static int rkcif_pipeline_set_stream(struct rkcif_pipeline *p, bool on)
for (i = 0; i < cif_dev->num_channels; i++)
cif_dev->reset_watchdog_timer.last_buf_wakeup_cnt[i] = 0;
cif_dev->reset_watchdog_timer.run_cnt = 0;
atomic_set(&cif_dev->sensor_off, 0);
} else {
atomic_set(&cif_dev->sensor_off, 1);
}
/* phy -> sensor */
@@ -1623,6 +1692,8 @@ static int rkcif_pipeline_set_stream(struct rkcif_pipeline *p, bool on)
} else {
ret = v4l2_subdev_call(p->subdevs[i], video, s_stream, on);
}
if (on && i == 0 && cif_dev->is_thunderboot && cif_dev->pre_buf_num)
rkcif_set_sof(cif_dev, cif_dev->pre_buf_num);
if (on && ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV)
goto err_stream_off;
}
@@ -1694,6 +1765,9 @@ static int rkcif_pipeline_set_stream(struct rkcif_pipeline *p, bool on)
for (i = 0; i < cif_dev->num_channels; i++)
cif_dev->reset_watchdog_timer.last_buf_wakeup_cnt[i] = 0;
cif_dev->reset_watchdog_timer.run_cnt = 0;
atomic_set(&cif_dev->sensor_off, 0);
} else {
atomic_set(&cif_dev->sensor_off, 1);
}
/* phy -> sensor */
@@ -1750,7 +1824,8 @@ static int rkcif_create_link(struct rkcif_device *dev,
u32 flags, pad, id;
int pad_offset = 0;
if (dev->chip_id >= CHIP_RK3588_CIF)
if (dev->chip_id >= CHIP_RK3588_CIF &&
dev->chip_id != CHIP_RV1103B_CIF)
pad_offset = 4;
linked_sensor.lanes = sensor->lanes;
@@ -1835,7 +1910,8 @@ static int rkcif_create_link(struct rkcif_device *dev,
break;
}
}
if (dev->chip_id >= CHIP_RK3588_CIF) {
if (dev->chip_id >= CHIP_RK3588_CIF &&
dev->chip_id != CHIP_RV1103B_CIF) {
for (id = 0; id < stream_num; id++) {
source_entity = &linked_sensor.sd->entity;
sink_entity = &dev->scale_vdev[id].vnode.vdev.entity;
@@ -2167,7 +2243,8 @@ static int rkcif_register_platform_subdevs(struct rkcif_device *cif_dev)
return -EINVAL;
}
if (cif_dev->chip_id >= CHIP_RK3588_CIF) {
if (cif_dev->chip_id >= CHIP_RK3588_CIF &&
cif_dev->chip_id != CHIP_RV1103B_CIF) {
ret = rkcif_register_scale_vdevs(cif_dev, RKCIF_MAX_SCALE_CH, true);
if (ret < 0) {
@@ -2200,7 +2277,8 @@ static int rkcif_register_platform_subdevs(struct rkcif_device *cif_dev)
return 0;
err_unreg_stream_vdev:
rkcif_unregister_stream_vdevs(cif_dev, stream_num);
if (cif_dev->chip_id >= CHIP_RK3588_CIF)
if (cif_dev->chip_id >= CHIP_RK3588_CIF &&
cif_dev->chip_id != CHIP_RV1103B_CIF)
rkcif_unregister_scale_vdevs(cif_dev, RKCIF_MAX_SCALE_CH);
if (cif_dev->chip_id > CHIP_RK1808_CIF)
@@ -2369,10 +2447,16 @@ void rkcif_set_sensor_stream(struct work_struct *work)
struct rkcif_device,
sensor_work);
v4l2_subdev_call(cif_dev->terminal_sensor.sd,
core, ioctl,
RKMODULE_SET_QUICK_STREAM,
&sensor_work->on);
mutex_lock(&cif_dev->stream_lock);
if ((atomic_read(&cif_dev->sensor_off) && sensor_work->on == 0) ||
(!atomic_read(&cif_dev->sensor_off) && sensor_work->on == 1)) {
v4l2_subdev_call(cif_dev->terminal_sensor.sd,
core, ioctl,
RKMODULE_SET_QUICK_STREAM,
&sensor_work->on);
}
mutex_unlock(&cif_dev->stream_lock);
}
static void rkcif_deal_err_intr(struct work_struct *work)
@@ -2716,10 +2800,12 @@ int rkcif_plat_init(struct rkcif_device *cif_dev, struct device_node *node, int
spin_lock_init(&cif_dev->buffree_lock);
spin_lock_init(&cif_dev->reset_watchdog_timer.timer_lock);
spin_lock_init(&cif_dev->reset_watchdog_timer.csi2_err_lock);
spin_lock_init(&cif_dev->stream_spinlock);
atomic_set(&cif_dev->pipe.power_cnt, 0);
atomic_set(&cif_dev->pipe.stream_cnt, 0);
atomic_set(&cif_dev->power_cnt, 0);
atomic_set(&cif_dev->streamoff_cnt, 0);
atomic_set(&cif_dev->sensor_off, 1);
cif_dev->is_start_hdr = false;
cif_dev->pipe.open = rkcif_pipeline_open;
cif_dev->pipe.close = rkcif_pipeline_close;
@@ -2734,8 +2820,11 @@ int rkcif_plat_init(struct rkcif_device *cif_dev, struct device_node *node, int
cif_dev->is_thunderboot = false;
cif_dev->rdbk_debug = 0;
cif_dev->is_stop_skip = false;
cif_dev->is_sensor_off = false;
cif_dev->exp_dbg = 0;
cif_dev->is_thunderboot_start = false;
cif_dev->is_in_flip = false;
cif_dev->sw_reg = devm_kzalloc(cif_dev->dev, RKCIF_REG_MAX, GFP_KERNEL);
cif_dev->reg_dbg = 0;
cif_dev->resume_mode = 0;
memset(&cif_dev->channels[0].capture_info, 0, sizeof(cif_dev->channels[0].capture_info));
@@ -2746,6 +2835,7 @@ int rkcif_plat_init(struct rkcif_device *cif_dev, struct device_node *node, int
INIT_WORK(&cif_dev->sensor_work.work, rkcif_set_sensor_stream);
INIT_DELAYED_WORK(&cif_dev->work_deal_err, rkcif_deal_err_intr);
INIT_WORK(&cif_dev->exp_work, rkcif_exp_work);
INIT_DELAYED_WORK(&cif_dev->work_flip, rkcif_flip_end_wait_work);
cif_dev->exp_delay.time_delay = 2;
cif_dev->exp_delay.gain_delay = 2;
cif_dev->is_alloc_buf_user = false;
@@ -2774,7 +2864,8 @@ int rkcif_plat_init(struct rkcif_device *cif_dev, struct device_node *node, int
rkcif_stream_init(cif_dev, RKCIF_STREAM_MIPI_ID3);
}
if (cif_dev->chip_id >= CHIP_RK3588_CIF) {
if (cif_dev->chip_id >= CHIP_RK3588_CIF &&
cif_dev->chip_id != CHIP_RV1103B_CIF) {
rkcif_init_scale_vdev(cif_dev, RKCIF_SCALE_CH0);
rkcif_init_scale_vdev(cif_dev, RKCIF_SCALE_CH1);
rkcif_init_scale_vdev(cif_dev, RKCIF_SCALE_CH2);
@@ -2851,6 +2942,7 @@ int rkcif_plat_init(struct rkcif_device *cif_dev, struct device_node *node, int
list_add_tail(&cif_dev->list, &rkcif_device_list);
mutex_unlock(&rkcif_dev_mutex);
cif_dev->pre_buf_num = 0;
return 0;
err_unreg_media_dev:
@@ -2884,8 +2976,7 @@ int rkcif_plat_uninit(struct rkcif_device *cif_dev)
}
rkcif_unregister_stream_vdevs(cif_dev, stream_num);
if (cif_dev->chip_id == CHIP_RV1106_CIF)
rkcif_rockit_dev_deinit();
rkcif_rockit_dev_deinit();
return 0;
}
@@ -3024,8 +3115,7 @@ static int rkcif_plat_probe(struct platform_device *pdev)
dev_warn(dev, "dev:%s create proc failed\n", dev_name(dev));
rkcif_init_reset_monitor(cif_dev);
if (cif_dev->chip_id == CHIP_RV1106_CIF)
rkcif_rockit_dev_init(cif_dev);
rkcif_rockit_dev_init(cif_dev);
pm_runtime_enable(&pdev->dev);
return 0;
@@ -3085,7 +3175,8 @@ static int __maybe_unused rkcif_runtime_resume(struct device *dev)
mutex_lock(&cif_dev->hw_dev->dev_lock);
ret = pm_runtime_resume_and_get(cif_dev->hw_dev->dev);
mutex_unlock(&cif_dev->hw_dev->dev_lock);
rkcif_do_soft_reset(cif_dev);
if (cif_dev->chip_id >= CHIP_RK3588_CIF)
rkcif_do_soft_reset(cif_dev);
return (ret > 0) ? 0 : ret;
}

View File

@@ -40,6 +40,7 @@
#define CIF_MONITOR_PARA_NUM (5)
#define RKCIF_REG_MAX (0x900)
#define RKCIF_SINGLE_STREAM 1
#define RKCIF_STREAM_CIF 0
#define CIF_DVP_VDEV_NAME CIF_VIDEODEVICE_NAME "_dvp"
@@ -102,6 +103,16 @@
#define RKCIF_SKIP_FRAME_MAX (16)
#ifdef CONFIG_CPU_RV1106
#define SHARED_MEM_RESERVED_HEAD_SIZE (0x6000)
#endif
#ifdef CONFIG_CPU_RV1103B
#define SHARED_MEM_RESERVED_HEAD_SIZE (0x9000)
#endif
#ifndef SHARED_MEM_RESERVED_HEAD_SIZE
#define SHARED_MEM_RESERVED_HEAD_SIZE (0)
#endif
enum rkcif_workmode {
RKCIF_WORKMODE_ONEFRAME = 0x00,
RKCIF_WORKMODE_PINGPONG = 0x01,
@@ -167,6 +178,11 @@ enum rkcif_crop_src {
CROP_SRC_MAX
};
enum rkcif_reg_dbg_level {
RKCIF_REG_DBG_PART = 1, /* print current device */
RKCIF_REG_DBG_ALL = 2, /* print all register */
};
/*
* struct rkcif_pipeline - An CIF hardware pipeline
*
@@ -224,6 +240,7 @@ struct rkcif_sensor_info {
struct v4l2_subdev *sd;
struct v4l2_mbus_config mbus;
struct v4l2_subdev_frame_interval fi;
struct v4l2_subdev_frame_interval src_fi;
int lanes;
struct v4l2_rect raw_rect;
struct v4l2_subdev_selection selection;
@@ -541,6 +558,7 @@ struct rkcif_stream {
struct rkcif_buffer *next_buf;
struct rkcif_rx_buffer *curr_buf_toisp;
struct rkcif_rx_buffer *next_buf_toisp;
struct rkcif_rx_buffer *last_buf_toisp;
struct list_head rockit_buf_head;
struct rkcif_buffer *curr_buf_rockit;
struct rkcif_buffer *next_buf_rockit;
@@ -584,6 +602,7 @@ struct rkcif_stream {
int sw_dbg_en;
atomic_t buf_cnt;
struct completion stop_complete;
struct completion start_complete;
struct rkcif_toisp_buf_state toisp_buf_state;
u32 skip_frame;
u32 cur_skip_frame;
@@ -595,6 +614,7 @@ struct rkcif_stream {
struct list_head qbuf_fence_list_head;
struct list_head done_fence_list_head;
spinlock_t fence_lock;
u32 rounding_bit;
bool stopping;
bool crop_enable;
bool crop_dyn_en;
@@ -616,6 +636,10 @@ struct rkcif_stream {
bool is_wait_stop_complete;
bool interlaced_bad_frame;
bool low_latency;
bool is_finish_single_cap;
bool is_wait_single_cap;
bool is_m_online_fb_res;
bool is_fb_first_frame;
};
struct rkcif_lvds_subdev {
@@ -911,6 +935,7 @@ struct rkcif_device {
atomic_t stream_cnt;
atomic_t power_cnt;
atomic_t streamoff_cnt;
atomic_t sensor_off;
struct mutex stream_lock; /* lock between streams */
struct mutex scale_lock; /* lock between scale dev */
struct mutex tools_lock; /* lock between tools dev */
@@ -931,6 +956,7 @@ struct rkcif_device {
struct rkcif_irq_stats irq_stats;
spinlock_t hdr_lock; /* lock for hdr buf sync */
spinlock_t buffree_lock;
spinlock_t stream_spinlock;
struct rkcif_timer reset_watchdog_timer;
struct rkcif_work_struct reset_work;
int id_use_cnt;
@@ -966,9 +992,10 @@ struct rkcif_device {
bool is_toisp_reset;
bool use_hw_interlace;
bool is_stop_skip;
bool is_sensor_off;
bool is_alloc_buf_user;
bool is_camera_over_bridge;
bool is_thunderboot_start;
bool is_in_flip;
int rdbk_debug;
struct rkcif_sync_cfg sync_cfg;
int sditf_cnt;
@@ -988,6 +1015,13 @@ struct rkcif_device {
u32 other_intstat[RKMODULE_MULTI_DEV_NUM];
u32 fb_res_bufs;
int exp_dbg;
struct delayed_work work_flip;
void *sw_reg;
int reg_dbg;
struct rkcif_csi_info csi_info;
u32 pre_buf_num;
u32 pre_buf_addr[MAX_PRE_BUF_NUM];
u64 pre_buf_timestamp[MAX_PRE_BUF_NUM];
};
extern struct platform_driver rkcif_plat_drv;
@@ -1090,7 +1124,8 @@ void rkcif_free_buf_by_user_require(struct rkcif_device *dev);
static inline u64 rkcif_time_get_ns(struct rkcif_device *dev)
{
if (dev->chip_id == CHIP_RV1106_CIF)
if (dev->chip_id == CHIP_RV1106_CIF ||
dev->chip_id == CHIP_RV1103B_CIF)
return ktime_get_boottime_ns();
else
return ktime_get_ns();
@@ -1099,4 +1134,14 @@ static inline u64 rkcif_time_get_ns(struct rkcif_device *dev)
bool rkcif_check_single_dev_stream_on(struct rkcif_hw *hw);
void rkcif_dphy_quick_stream(struct rkcif_device *dev, int on);
void rkcif_check_buffer_update_pingpong_rockit(struct rkcif_stream *stream,
int channel_id);
int rkcif_quick_stream_on(struct rkcif_device *dev, bool is_intr);
void rkcif_flip_end_wait_work(struct work_struct *work);
void rkcif_reinit_right_half_config(struct rkcif_stream *stream);
void rkcif_modify_line_int(struct rkcif_stream *stream, bool en);
void rkcif_set_sof(struct rkcif_device *cif_dev, u32 seq);
#endif

View File

@@ -1080,6 +1080,86 @@ static const struct cif_reg rk3576_cif_regs[] = {
[CIF_REG_GRF_CIFIO_CON] = CIF_REG(CIF_GRF_IOC_MISC_CON1_RK3576),
};
static const char * const rv1103b_cif_clks[] = {
"aclk_cif",
"hclk_cif",
"dclk_cif",
"isp0clk_cif",
};
static const char * const rv1103b_cif_rsts[] = {
"rst_cif_a",
"rst_cif_isp0",
"rst_cif_h",
"rst_cif_d",
};
static const struct cif_reg rv1103b_cif_regs[] = {
[CIF_REG_MIPI_LVDS_ID0_CTRL0] = CIF_REG(CSI_MIPI0_ID0_CTRL0),
[CIF_REG_MIPI_LVDS_ID0_CTRL1] = CIF_REG(CSI_MIPI0_ID0_CTRL1),
[CIF_REG_MIPI_LVDS_ID1_CTRL0] = CIF_REG(CSI_MIPI0_ID1_CTRL0),
[CIF_REG_MIPI_LVDS_ID1_CTRL1] = CIF_REG(CSI_MIPI0_ID1_CTRL1),
[CIF_REG_MIPI_LVDS_ID2_CTRL0] = CIF_REG(CSI_MIPI0_ID2_CTRL0),
[CIF_REG_MIPI_LVDS_ID2_CTRL1] = CIF_REG(CSI_MIPI0_ID2_CTRL1),
[CIF_REG_MIPI_LVDS_ID3_CTRL0] = CIF_REG(CSI_MIPI0_ID3_CTRL0),
[CIF_REG_MIPI_LVDS_ID3_CTRL1] = CIF_REG(CSI_MIPI0_ID3_CTRL1),
[CIF_REG_MIPI_LVDS_CTRL] = CIF_REG(CSI_MIPI0_CTRL),
[CIF_REG_MIPI_LVDS_FRAME0_ADDR_Y_ID0] = CIF_REG(CSI_MIPI0_FRM0_ADDR_Y_ID0),
[CIF_REG_MIPI_LVDS_FRAME1_ADDR_Y_ID0] = CIF_REG(CSI_MIPI0_FRM1_ADDR_Y_ID0),
[CIF_REG_MIPI_LVDS_FRAME0_ADDR_UV_ID0] = CIF_REG(CSI_MIPI0_FRM0_ADDR_UV_ID0),
[CIF_REG_MIPI_LVDS_FRAME1_ADDR_UV_ID0] = CIF_REG(CSI_MIPI0_FRM1_ADDR_UV_ID0),
[CIF_REG_MIPI_LVDS_FRAME0_VLW_Y_ID0] = CIF_REG(CSI_MIPI0_VLW_ID0),
[CIF_REG_MIPI_LVDS_FRAME0_ADDR_Y_ID1] = CIF_REG(CSI_MIPI0_FRM0_ADDR_Y_ID1),
[CIF_REG_MIPI_LVDS_FRAME1_ADDR_Y_ID1] = CIF_REG(CSI_MIPI0_FRM1_ADDR_Y_ID1),
[CIF_REG_MIPI_LVDS_FRAME0_ADDR_UV_ID1] = CIF_REG(CSI_MIPI0_FRM0_ADDR_UV_ID1),
[CIF_REG_MIPI_LVDS_FRAME1_ADDR_UV_ID1] = CIF_REG(CSI_MIPI0_FRM1_ADDR_UV_ID1),
[CIF_REG_MIPI_LVDS_FRAME0_VLW_Y_ID1] = CIF_REG(CSI_MIPI0_VLW_ID1),
[CIF_REG_MIPI_LVDS_FRAME0_ADDR_Y_ID2] = CIF_REG(CSI_MIPI0_FRM0_ADDR_Y_ID2),
[CIF_REG_MIPI_LVDS_FRAME1_ADDR_Y_ID2] = CIF_REG(CSI_MIPI0_FRM1_ADDR_Y_ID2),
[CIF_REG_MIPI_LVDS_FRAME0_ADDR_UV_ID2] = CIF_REG(CSI_MIPI0_FRM0_ADDR_UV_ID2),
[CIF_REG_MIPI_LVDS_FRAME1_ADDR_UV_ID2] = CIF_REG(CSI_MIPI0_FRM1_ADDR_UV_ID2),
[CIF_REG_MIPI_LVDS_FRAME0_VLW_Y_ID2] = CIF_REG(CSI_MIPI0_VLW_ID2),
[CIF_REG_MIPI_LVDS_FRAME0_ADDR_Y_ID3] = CIF_REG(CSI_MIPI0_FRM0_ADDR_Y_ID3),
[CIF_REG_MIPI_LVDS_FRAME1_ADDR_Y_ID3] = CIF_REG(CSI_MIPI0_FRM1_ADDR_Y_ID3),
[CIF_REG_MIPI_LVDS_FRAME0_ADDR_UV_ID3] = CIF_REG(CSI_MIPI0_FRM0_ADDR_UV_ID3),
[CIF_REG_MIPI_LVDS_FRAME1_ADDR_UV_ID3] = CIF_REG(CSI_MIPI0_FRM1_ADDR_UV_ID3),
[CIF_REG_MIPI_LVDS_FRAME0_VLW_Y_ID3] = CIF_REG(CSI_MIPI0_VLW_ID3),
[CIF_REG_MIPI_LVDS_INTEN] = CIF_REG(CSI_MIPI0_INTEN),
[CIF_REG_MIPI_LVDS_INTSTAT] = CIF_REG(CSI_MIPI0_INTSTAT),
[CIF_REG_MIPI_LVDS_LINE_INT_NUM_ID0_1] = CIF_REG(CSI_MIPI0_LINE_INT_NUM_ID0_1_RK3576),
[CIF_REG_MIPI_LVDS_LINE_INT_NUM_ID2_3] = CIF_REG(CSI_MIPI0_LINE_INT_NUM_ID2_3_RK3576),
[CIF_REG_MIPI_LVDS_LINE_LINE_CNT_ID0_1] = CIF_REG(CSI_MIPI0_LINE_CNT_ID0_1_RK3576),
[CIF_REG_MIPI_LVDS_LINE_LINE_CNT_ID2_3] = CIF_REG(CSI_MIPI0_LINE_CNT_ID2_3_RK3576),
[CIF_REG_MIPI_LVDS_ID0_CROP_START] = CIF_REG(CSI_MIPI0_ID0_CROP_START_RK3576),
[CIF_REG_MIPI_LVDS_ID1_CROP_START] = CIF_REG(CSI_MIPI0_ID1_CROP_START_RK3576),
[CIF_REG_MIPI_LVDS_ID2_CROP_START] = CIF_REG(CSI_MIPI0_ID2_CROP_START_RK3576),
[CIF_REG_MIPI_LVDS_ID3_CROP_START] = CIF_REG(CSI_MIPI0_ID3_CROP_START_RK3576),
[CIF_REG_MIPI_FRAME_NUM_VC0] = CIF_REG(CSI_MIPI0_FRAME_NUM_VC0_RK3576),
[CIF_REG_MIPI_FRAME_NUM_VC1] = CIF_REG(CSI_MIPI0_FRAME_NUM_VC1_RK3576),
[CIF_REG_MIPI_FRAME_NUM_VC2] = CIF_REG(CSI_MIPI0_FRAME_NUM_VC2_RK3576),
[CIF_REG_MIPI_FRAME_NUM_VC3] = CIF_REG(CSI_MIPI0_FRAME_NUM_VC3_RK3576),
[CIF_REG_MIPI_EFFECT_CODE_ID0] = CIF_REG(CSI_MIPI0_EFFECT_CODE_ID0_RK3576),
[CIF_REG_MIPI_EFFECT_CODE_ID1] = CIF_REG(CSI_MIPI0_EFFECT_CODE_ID1_RK3576),
[CIF_REG_MIPI_EFFECT_CODE_ID2] = CIF_REG(CSI_MIPI0_EFFECT_CODE_ID2_RK3576),
[CIF_REG_MIPI_EFFECT_CODE_ID3] = CIF_REG(CSI_MIPI0_EFFECT_CODE_ID3_RK3576),
[CIF_REG_MIPI_ON_PAD] = CIF_REG(CSI_MIPI0_ON_PAD_RK3576),
[CIF_REG_MIPI_SET_SIZE_ID0] = CIF_REG(CSI_MIPI0_SET_FRAME_SIZE_ID0_RK3576),
[CIF_REG_MIPI_SET_SIZE_ID1] = CIF_REG(CSI_MIPI0_SET_FRAME_SIZE_ID1_RK3576),
[CIF_REG_MIPI_SET_SIZE_ID2] = CIF_REG(CSI_MIPI0_SET_FRAME_SIZE_ID2_RK3576),
[CIF_REG_MIPI_SET_SIZE_ID3] = CIF_REG(CSI_MIPI0_SET_FRAME_SIZE_ID3_RK3576),
[CIF_REG_GLB_CTRL] = CIF_REG(GLB_CTRL),
[CIF_REG_GLB_INTEN] = CIF_REG(GLB_INTEN),
[CIF_REG_GLB_INTST] = CIF_REG(GLB_INTST),
[CIF_REG_TOISP0_CTRL] = CIF_REG(TOISP0_CH_CTRL),
[CIF_REG_TOISP0_SIZE] = CIF_REG(TOISP0_CROP_SIZE),
[CIF_REG_TOISP0_CROP] = CIF_REG(TOISP0_CROP),
[CIF_REG_TOISP0_CH1_CTRL] = CIF_REG(TOISP0_CH1_CTRL),
[CIF_REG_TOISP0_CH1_SIZE] = CIF_REG(TOISP0_CH1_CROP_SIZE),
[CIF_REG_TOISP0_CH1_CROP] = CIF_REG(TOISP0_CH1_CROP),
};
static const struct rkcif_hw_match_data px30_cif_match_data = {
.chip_id = CHIP_PX30_CIF,
.clks = px30_cif_clks,
@@ -1197,6 +1277,15 @@ static const struct rkcif_hw_match_data rk3576_cif_match_data = {
.cif_regs = rk3576_cif_regs,
};
static const struct rkcif_hw_match_data rv1103b_cif_match_data = {
.chip_id = CHIP_RV1103B_CIF,
.clks = rv1103b_cif_clks,
.clks_num = ARRAY_SIZE(rv1103b_cif_clks),
.rsts = rv1103b_cif_rsts,
.rsts_num = ARRAY_SIZE(rv1103b_cif_rsts),
.cif_regs = rv1103b_cif_regs,
};
static const struct of_device_id rkcif_plat_of_match[] = {
#ifdef CONFIG_CPU_PX30
{
@@ -1273,6 +1362,12 @@ static const struct of_device_id rkcif_plat_of_match[] = {
.compatible = "rockchip,rk3576-cif",
.data = &rk3576_cif_match_data,
},
#endif
#ifdef CONFIG_CPU_RV1103B
{
.compatible = "rockchip,rv1103b-cif",
.data = &rv1103b_cif_match_data,
},
#endif
{},
};
@@ -1473,9 +1568,17 @@ static int rkcif_plat_hw_probe(struct platform_device *pdev)
if (irq < 0)
return irq;
ret = devm_request_irq(dev, irq, rkcif_irq_handler,
IRQF_SHARED,
dev_driver_string(dev), dev);
if (cif_hw->chip_id == CHIP_RV1106_CIF ||
cif_hw->chip_id == CHIP_RV1103B_CIF) {
irq_set_status_flags(irq, IRQ_NOAUTOEN);
ret = devm_request_irq(dev, irq, rkcif_irq_handler,
0,
dev_driver_string(dev), dev);
} else {
ret = devm_request_irq(dev, irq, rkcif_irq_handler,
IRQF_SHARED,
dev_driver_string(dev), dev);
}
if (ret < 0) {
dev_err(dev, "request irq failed: %d\n", ret);
return ret;
@@ -1505,6 +1608,7 @@ static int rkcif_plat_hw_probe(struct platform_device *pdev)
if (IS_ERR(cif_hw->base_addr))
return PTR_ERR(cif_hw->base_addr);
}
cif_hw->res = res;
if (of_property_read_bool(np, "rockchip,android-usb-camerahal-enable")) {
dev_info(dev, "config cif adapt to android usb camera hal!\n");
@@ -1553,7 +1657,9 @@ static int rkcif_plat_hw_probe(struct platform_device *pdev)
cif_hw->is_dma_contig = true;
mutex_init(&cif_hw->dev_lock);
spin_lock_init(&cif_hw->group_lock);
spin_lock_init(&cif_hw->reset_lock);
atomic_set(&cif_hw->power_cnt, 0);
cif_hw->is_in_reset = false;
cif_hw->iommu_en = is_iommu_enable(dev);
ret = of_reserved_mem_device_init(dev);
@@ -1624,10 +1730,14 @@ static void rkcif_hw_shutdown(struct platform_device *pdev)
if (pm_runtime_get_if_in_use(&pdev->dev) <= 0)
return;
if (cif_hw->chip_id == CHIP_RK3588_CIF ||
cif_hw->chip_id == CHIP_RV1106_CIF ||
cif_hw->chip_id == CHIP_RK3562_CIF) {
if (cif_hw->chip_id >= CHIP_RK3588_CIF) {
write_cif_reg(cif_hw->base_addr, 0, 0);
for (i = 0; i < cif_hw->dev_num; i++) {
cif_dev = cif_hw->cif_dev[i];
if (atomic_read(&cif_dev->pipe.stream_cnt))
cif_dev->pipe.set_stream(&cif_dev->pipe, false);
}
} else {
for (i = 0; i < cif_hw->dev_num; i++) {
cif_dev = cif_hw->cif_dev[i];
@@ -1640,6 +1750,7 @@ static void rkcif_hw_shutdown(struct platform_device *pdev)
rkcif_write_register(cif_dev,
CIF_REG_DVP_CTRL,
0);
cif_dev->pipe.set_stream(&cif_dev->pipe, false);
}
}
}
@@ -1656,6 +1767,10 @@ static int __maybe_unused rkcif_runtime_suspend(struct device *dev)
return 0;
rkcif_disable_sys_clk(cif_hw);
if (cif_hw->chip_id == CHIP_RV1106_CIF ||
cif_hw->chip_id == CHIP_RV1103B_CIF)
disable_irq(cif_hw->irq);
return pinctrl_pm_select_sleep_state(dev);
}
@@ -1672,6 +1787,10 @@ static int __maybe_unused rkcif_runtime_resume(struct device *dev)
rkcif_enable_sys_clk(cif_hw);
rkcif_hw_soft_reset(cif_hw, true);
if (cif_hw->chip_id == CHIP_RV1106_CIF ||
cif_hw->chip_id == CHIP_RV1103B_CIF)
enable_irq(cif_hw->irq);
return 0;
}

View File

@@ -50,6 +50,7 @@ enum rkcif_sync_mode {
RKCIF_MASTER_SLAVE,
RKCIF_EXT_MASTER,
RKCIF_EXT_SLAVE,
RKCIF_SOFT_SYNC,
};
struct rkcif_sync_dev {
@@ -62,6 +63,7 @@ struct rkcif_multi_sync_config {
struct rkcif_sync_dev int_master;
struct rkcif_sync_dev ext_master;
struct rkcif_sync_dev slave;
struct rkcif_sync_dev soft_sync;
enum rkcif_sync_mode mode;
int dev_cnt;
int streaming_cnt;
@@ -108,6 +110,7 @@ enum rkcif_chip_id {
CHIP_RV1106_CIF,
CHIP_RK3562_CIF,
CHIP_RK3576_CIF,
CHIP_RV1103B_CIF,
};
struct rkcif_hw_match_data {
@@ -129,7 +132,7 @@ struct rkcif_hw {
struct device *dev;
int irq;
void __iomem *base_addr;
void __iomem *csi_base;
struct resource *res;
struct regmap *grf;
struct clk *clks[RKCIF_MAX_BUS_CLK];
int clk_size;
@@ -145,6 +148,7 @@ struct rkcif_hw {
struct mutex dev_lock;
struct rkcif_multi_sync_config sync_config[RKCIF_MAX_GROUP];
spinlock_t group_lock;
spinlock_t reset_lock;
struct notifier_block reset_notifier; /* reset for mipi csi crc err */
struct rkcif_dummy_buffer dummy_buf;
bool iommu_en;
@@ -154,6 +158,7 @@ struct rkcif_hw {
bool adapt_to_usbcamerahal;
u64 irq_time;
bool is_rk3588s2;
bool is_in_reset;
};
void rkcif_hw_soft_reset(struct rkcif_hw *cif_hw, bool is_rst_iommu);

View File

@@ -183,6 +183,10 @@ static void csi2_enable(struct csi2_hw *csi2_hw,
int lanes = csi2->bus.num_data_lanes;
struct v4l2_mbus_config mbus;
u32 val = 0;
u32 mask1 = 0;
struct v4l2_subdev *terminal_sensor_sd = NULL;
struct rkmodule_hdr_cfg hdr_cfg = {0};
int ret = 0;
csi2_g_mbus_config(&csi2->sd, 0, &mbus);
if (mbus.type == V4L2_MBUS_CSI2_DPHY)
@@ -195,6 +199,24 @@ static void csi2_enable(struct csi2_hw *csi2_hw,
if (csi2->sw_dbg)
val |= BIT(6);
get_remote_terminal_sensor(&csi2->sd, &terminal_sensor_sd);
if (terminal_sensor_sd) {
ret = v4l2_subdev_call(terminal_sensor_sd,
core, ioctl,
RKMODULE_GET_HDR_CFG,
&hdr_cfg);
if (ret != 0)
hdr_cfg.hdr_mode = NO_HDR;
if (strstr(terminal_sensor_sd->name, "sc") &&
(hdr_cfg.hdr_mode == HDR_X2 || hdr_cfg.hdr_mode == HDR_X3)) {
mask1 = CSIHOST_ERR1_ERR_BNDRY_MATCH;
csi2->is_detect_fs_fe = false;
} else {
csi2->is_detect_fs_fe = true;
}
} else {
csi2->is_detect_fs_fe = true;
}
if (host_type == RK_DSI_RXHOST) {
val |= SW_DSI_EN(1) | SW_DATATYPE_FS(0x01) |
SW_DATATYPE_FE(0x11) | SW_DATATYPE_LS(0x21) |
@@ -208,7 +230,7 @@ static void csi2_enable(struct csi2_hw *csi2_hw,
SW_DATATYPE_FE(0x01) | SW_DATATYPE_LS(0x02) |
SW_DATATYPE_LE(0x03);
write_csihost_reg(base, CSIHOST_CONTROL, val);
write_csihost_reg(base, CSIHOST_MSK1, 0x0);
write_csihost_reg(base, CSIHOST_MSK1, mask1);
write_csihost_reg(base, CSIHOST_MSK2, 0xf000);
csi2->is_check_sot_sync = true;
}
@@ -578,6 +600,28 @@ static int rkcif_csi2_s_power(struct v4l2_subdev *sd, int on)
return 0;
}
static void csi2_quick_stream_on(struct csi2_dev *csi2)
{
int csi_idx = 0;
int i = 0;
for (i = 0; i < csi2->csi_info.csi_num; i++) {
csi_idx = csi2->csi_info.csi_idx[i];
write_csihost_reg(csi2->csi2_hw[csi_idx]->base, CSIHOST_RESETN, 1);
}
}
static void csi2_quick_stream_off(struct csi2_dev *csi2)
{
int csi_idx = 0;
int i = 0;
for (i = 0; i < csi2->csi_info.csi_num; i++) {
csi_idx = csi2->csi_info.csi_idx[i];
write_csihost_reg(csi2->csi2_hw[csi_idx]->base, CSIHOST_RESETN, 0);
}
}
static long rkcif_csi2_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
{
struct csi2_dev *csi2 = sd_to_dev(sd);
@@ -598,6 +642,12 @@ static long rkcif_csi2_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg
case RKCIF_CMD_SET_PPI_DATA_DEBUG:
csi2->sw_dbg = *((u32 *)arg);
break;
case RKMODULE_SET_QUICK_STREAM:
if (*(int *)arg)
csi2_quick_stream_on(csi2);
else
csi2_quick_stream_off(csi2);
break;
default:
ret = -ENOIOCTLCMD;
break;
@@ -808,7 +858,7 @@ static irqreturn_t rk_csirx_irq1_handler(int irq, void *ctx)
}
}
if (val & CSIHOST_ERR1_ERR_BNDRY_MATCH) {
if (val & CSIHOST_ERR1_ERR_BNDRY_MATCH && csi2->is_detect_fs_fe) {
err_list = &csi2->err_list[RK_CSI2_ERR_FS_FE_MIS];
err_list->cnt++;
csi2_find_err_vc((val >> 4) & 0xf, vc_info);
@@ -858,7 +908,7 @@ static irqreturn_t rk_csirx_irq1_handler(int irq, void *ctx)
csi2_err_strncat(err_str, cur_str);
}
pr_err("%s ERR1:0x%x %s\n", csi2_hw->dev_name, val, err_str);
pr_err("(0x%x)MIPI_CSI2 ERR1:0x%x %s\n", (u32)csi2_hw->res->start, val, err_str);
if (is_add_cnt) {
csi2->err_list[RK_CSI2_ERR_ALL].cnt++;
@@ -916,7 +966,7 @@ static irqreturn_t rk_csirx_irq2_handler(int irq, void *ctx)
csi2_err_strncat(err_str, cur_str);
}
pr_err("%s ERR2:0x%x %s\n", csi2_hw->dev_name, val, err_str);
pr_err("(0x%x)MIPI_CSI2 ERR2:0x%x %s\n", (u32)csi2_hw->res->start, val, err_str);
}
return IRQ_HANDLED;
@@ -1044,6 +1094,12 @@ static const struct csi2_match_data rk3576_csi2_match_data = {
.num_hw = 5,
};
static const struct csi2_match_data rv1103b_csi2_match_data = {
.chip_id = CHIP_RV1103B_CSI2,
.num_pads = CSI2_NUM_PADS_MAX,
.num_hw = 2,
};
static const struct of_device_id csi2_dt_ids[] = {
{
.compatible = "rockchip,rk1808-mipi-csi2",
@@ -1077,6 +1133,10 @@ static const struct of_device_id csi2_dt_ids[] = {
.compatible = "rockchip,rk3576-mipi-csi2",
.data = &rk3576_csi2_match_data,
},
{
.compatible = "rockchip,rv1103b-mipi-csi2",
.data = &rv1103b_csi2_match_data,
},
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, csi2_dt_ids);
@@ -1234,6 +1294,10 @@ static const struct csi2_hw_match_data rk3576_csi2_hw_match_data = {
.chip_id = CHIP_RK3576_CSI2,
};
static const struct csi2_hw_match_data rv1103b_csi2_hw_match_data = {
.chip_id = CHIP_RV1103B_CSI2,
};
static const struct of_device_id csi2_hw_ids[] = {
{
.compatible = "rockchip,rk1808-mipi-csi2-hw",
@@ -1267,6 +1331,10 @@ static const struct of_device_id csi2_hw_ids[] = {
.compatible = "rockchip,rk3576-mipi-csi2-hw",
.data = &rk3576_csi2_hw_match_data,
},
{
.compatible = "rockchip,rv1103b-mipi-csi2-hw",
.data = &rv1103b_csi2_hw_match_data,
},
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, csi2_hw_ids);
@@ -1311,6 +1379,7 @@ static int csi2_hw_probe(struct platform_device *pdev)
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
csi2_hw->base = devm_ioremap_resource(&pdev->dev, res);
csi2_hw->res = res;
if (IS_ERR(csi2_hw->base)) {
resource_size_t offset = res->start;
resource_size_t size = resource_size(res);

View File

@@ -95,6 +95,7 @@ enum rkcsi2_chip_id {
CHIP_RV1106_CSI2,
CHIP_RK3562_CSI2,
CHIP_RK3576_CSI2,
CHIP_RV1103B_CSI2,
};
enum csi2_pads {
@@ -161,6 +162,7 @@ struct csi2_dev {
struct v4l2_subdev *src_sd;
bool sink_linked[CSI2_NUM_SRC_PADS];
bool is_check_sot_sync;
bool is_detect_fs_fe;
struct csi2_sensor_info sensors[MAX_CSI2_SENSORS];
const struct csi2_match_data *match_data;
int num_sensors;
@@ -184,6 +186,7 @@ struct csi2_hw {
const struct csi2_hw_match_data *match_data;
void __iomem *base;
struct resource *res;
/* lock to protect all members below */
struct mutex lock;

View File

@@ -7,9 +7,13 @@
#include <linux/seq_file.h>
#include <linux/spinlock.h>
#include <linux/v4l2-mediabus.h>
#include <linux/regmap.h>
#include "dev.h"
#include "procfs.h"
#include "mipi-csi2.h"
#include "../../../../phy/rockchip/phy-rockchip-csi2-dphy-common.h"
#include "../../../../phy/rockchip/phy-rockchip-samsung-dcphy.h"
#ifdef CONFIG_PROC_FS
@@ -211,6 +215,24 @@ static const char *rkcif_get_monitor_mode(enum rkcif_monitor_mode monitor_mode)
}
}
static const char *rkcif_get_sync_mode(enum rkmodule_sync_mode sync_mode)
{
switch (sync_mode) {
case NO_SYNC_MODE:
return "no sync";
case EXTERNAL_MASTER_MODE:
return "external master";
case INTERNAL_MASTER_MODE:
return "internal master";
case SLAVE_MODE:
return "slave";
case SOFT_SYNC_MODE:
return "soft sync";
default:
return "unknown";
}
}
static void rkcif_show_mixed_info(struct rkcif_device *dev, struct seq_file *f)
{
enum rkcif_monitor_mode monitor_mode;
@@ -240,13 +262,267 @@ static void rkcif_show_clks(struct rkcif_device *dev, struct seq_file *f)
}
}
static void rkcif_show_toisp_info(struct rkcif_device *dev, struct seq_file *f)
{
struct sditf_priv *priv = dev->sditf[0];
char name_strings[32] = {0};
seq_puts(f, "\nToisp Info:\n");
seq_printf(f, "\tisp_name: %s\n", priv->mode.name);
switch (priv->mode.rdbk_mode) {
case RKISP_VICAP_ONLINE:
sprintf(name_strings, "%s", "online");
break;
case RKISP_VICAP_ONLINE_ONE_FRAME:
sprintf(name_strings, "%s", "online_one_frame");
break;
case RKISP_VICAP_ONLINE_MULTI:
sprintf(name_strings, "%s", "online_multi");
break;
case RKISP_VICAP_ONLINE_UNITE:
sprintf(name_strings, "%s", "online_unite");
break;
case RKISP_VICAP_RDBK_AIQ:
sprintf(name_strings, "%s", "rdbk_aiq");
break;
case RKISP_VICAP_RDBK_AUTO:
sprintf(name_strings, "%s", "rdbk_auto");
break;
case RKISP_VICAP_RDBK_AUTO_ONE_FRAME:
sprintf(name_strings, "%s", "rdbk_one_frame");
break;
default:
sprintf(name_strings, "%s", "error");
break;
}
seq_printf(f, "\trdbk_mode: %s\n", name_strings);
if (priv->mode.rdbk_mode > RKISP_VICAP_RDBK_AIQ)
seq_printf(f, "\treserved buf: %d\n", priv->cif_dev->fb_res_bufs);
if (priv->hdr_wrap_line)
seq_printf(f, "\twrap line: %d\n", priv->hdr_wrap_line);
if (priv->is_combine_mode)
seq_printf(f, "\tcombine num: %d\n", dev->sditf_cnt);
}
static int rkcif_get_csi_offset(struct rkcif_device *dev, int csi_host_idx)
{
int csi_offset = 0;
if (dev->chip_id == CHIP_RK3588_CIF) {
csi_offset = csi_host_idx * 0x100;
} else if (dev->chip_id == CHIP_RV1106_CIF ||
dev->chip_id == CHIP_RV1103B_CIF) {
csi_offset = csi_host_idx * 0x200;
} else if (dev->chip_id == CHIP_RK3562_CIF) {
if (csi_host_idx < 3)
csi_offset = csi_host_idx * 0x200;
else
csi_offset = 0x500;
} else if (dev->chip_id == CHIP_RK3576_CIF) {
if (csi_host_idx < 2)
csi_offset = csi_host_idx * 0x200;
else
csi_offset = 0x100 + csi_host_idx * 0x100;
}
csi_offset += 0x100;
return csi_offset;
}
static void rkcif_show_reg_vicap(struct rkcif_device *dev, struct seq_file *f)
{
void *buf = dev->sw_reg;
struct sditf_priv *priv = dev->sditf[0];
u32 *reg = NULL;
int i, j;
int csi_offset = 0;
seq_puts(f, "\nVicap reg:\n");
memcpy_fromio(buf, dev->hw_dev->base_addr, RKCIF_REG_MAX);
if (dev->reg_dbg == RKCIF_REG_DBG_PART) {
if (dev->inf_id == RKCIF_MIPI_LVDS) {
for (j = 0; j < dev->csi_info.csi_num; j++) {
seq_printf(f, "\nmipi%d reg:\n", dev->csi_info.csi_idx[j]);
csi_offset = rkcif_get_csi_offset(dev, dev->csi_info.csi_idx[j]);
reg = buf + csi_offset;
for (i = 0; i < 0x100 / 16; i++)
seq_printf(f, "0x%x: 0x%08x 0x%08x 0x%08x 0x%08x\n",
(u32)(dev->hw_dev->res->start + csi_offset + i * 16),
*(reg + i * 4), *(reg + i * 4 + 1),
*(reg + i * 4 + 2), *(reg + i * 4 + 3));
}
} else {
reg = buf;
for (i = 0; i < 0x100 / 16; i++)
seq_printf(f, "0x%x: 0x%08x 0x%08x 0x%08x 0x%08x\n",
(u32)(dev->hw_dev->res->start + i * 16),
*(reg + i * 4), *(reg + i * 4 + 1),
*(reg + i * 4 + 2), *(reg + i * 4 + 3));
}
if (priv && priv->mode.rdbk_mode < RKISP_VICAP_RDBK_AIQ) {
seq_puts(f, "\ntoisp reg:\n");
reg = buf + 0x780;
for (i = 0; i < 0x30 / 16; i++)
seq_printf(f, "0x%x: 0x%08x 0x%08x 0x%08x 0x%08x\n",
(u32)(dev->hw_dev->res->start + 0x780 + i * 16),
*(reg + i * 4), *(reg + i * 4 + 1),
*(reg + i * 4 + 2), *(reg + i * 4 + 3));
reg = buf;
seq_puts(f, "\nglobal reg:\n");
for (i = 0; i < 0x10 / 16; i++)
seq_printf(f, "0x%x: 0x%08x 0x%08x 0x%08x 0x%08x\n",
(u32)(dev->hw_dev->res->start + i * 16),
*(reg + i * 4), *(reg + i * 4 + 1),
*(reg + i * 4 + 2), *(reg + i * 4 + 3));
}
} else {
reg = buf;
for (i = 0; i < RKCIF_REG_MAX / 16; i++)
seq_printf(f, "0x%x: 0x%08x 0x%08x 0x%08x 0x%08x\n",
(u32)(dev->hw_dev->res->start + i * 16),
*(reg + i * 4), *(reg + i * 4 + 1),
*(reg + i * 4 + 2), *(reg + i * 4 + 3));
}
}
static void rkcif_show_reg_csi2(struct rkcif_device *dev, struct seq_file *f)
{
struct csi2_dev *csi2 = container_of(dev->active_sensor->sd, struct csi2_dev, sd);
struct csi2_hw *csi2_hw = NULL;
int i, j;
int csi_idx = 0;
u32 buf[20];
for (j = 0; j < csi2->csi_info.csi_num; j++) {
csi_idx = csi2->csi_info.csi_idx[j];
csi2_hw = csi2->csi2_hw[csi_idx];
seq_printf(f, "\nmipi%d csi2 reg:\n", csi_idx);
memcpy_fromio(buf, csi2_hw->base, 0x50);
for (i = 0; i < 0x50 / 16; i++)
seq_printf(f, "0x%x: 0x%08x 0x%08x 0x%08x 0x%08x\n",
(u32)(csi2_hw->res->start + i * 16),
*(buf + i * 4), *(buf + i * 4 + 1),
*(buf + i * 4 + 2), *(buf + i * 4 + 3));
}
}
static void rkcif_show_reg_dcphy(struct samsung_mipi_dcphy *dcphy, int index, struct seq_file *f)
{
u32 bias_reg[4];
char *dcphy_reg = NULL;
u32 *buf = NULL;
int i = 0;
seq_printf(f, "\ndcphy%d reg:\n", index);
regmap_bulk_read(dcphy->regmap, 0, bias_reg, 4);
seq_printf(f, "0x%x: 0x%08x 0x%08x 0x%08x 0x%08x\n",
(u32)dcphy->res->start,
bias_reg[0], bias_reg[1],
bias_reg[2], bias_reg[3]);
dcphy_reg = kzalloc(0x500, GFP_KERNEL);
if (!dcphy_reg)
return;
regmap_bulk_read(dcphy->regmap, 0xb00, dcphy_reg, 0x500 / 4);
buf = (u32 *)dcphy_reg;
for (i = 0; i < 0x500 / 16; i++)
seq_printf(f, "0x%x: 0x%08x 0x%08x 0x%08x 0x%08x\n",
(u32)(dcphy->res->start + 0xb00 + i * 16),
*(buf + i * 4), *(buf + i * 4 + 1),
*(buf + i * 4 + 2), *(buf + i * 4 + 3));
kfree(dcphy_reg);
}
static void rkcif_show_reg_dphy(struct csi2_dphy_hw *dphy_hw, int index, struct seq_file *f)
{
char *dphy_reg = NULL;
u32 *buf = NULL;
int i = 0;
seq_printf(f, "\ndphy%d reg:\n", index);
dphy_reg = kzalloc(0x900, GFP_KERNEL);
if (!dphy_reg)
return;
memcpy_fromio(dphy_reg, dphy_hw->hw_base_addr, 0x900);
buf = (u32 *)dphy_reg;
for (i = 0; i < 0x900 / 16; i++)
seq_printf(f, "0x%x: 0x%08x 0x%08x 0x%08x 0x%08x\n",
(u32)(dphy_hw->res->start + i * 16),
*(buf + i * 4), *(buf + i * 4 + 1),
*(buf + i * 4 + 2), *(buf + i * 4 + 3));
kfree(dphy_reg);
}
static void rkcif_show_reg_dphys(struct rkcif_device *dev, struct seq_file *f)
{
struct csi2_dphy *dphy = NULL;
struct csi2_dphy_hw *dphy_hw = NULL;
struct samsung_mipi_dcphy *dcphy_hw = NULL;
struct rkcif_pipeline *p = NULL;
struct v4l2_subdev *sd = NULL;
int j;
int csi_idx = 0;
p = &dev->pipe;
for (j = 0; j < p->num_subdevs; j++) {
if (p->subdevs[j] != dev->terminal_sensor.sd &&
p->subdevs[j] != dev->active_sensor->sd) {
sd = p->subdevs[j];
break;
}
}
if (!sd)
return;
dphy = container_of(sd, struct csi2_dphy, sd);
for (j = 0; j < dev->csi_info.csi_num; j++) {
csi_idx = dev->csi_info.csi_idx[j];
if (dphy->drv_data->chip_id == CHIP_ID_RK3568 ||
dphy->drv_data->chip_id == CHIP_ID_RV1106) {
dphy_hw = dphy->dphy_hw_group[0];
if (dphy_hw)
rkcif_show_reg_dphy(dphy_hw, 0, f);
} else if (dphy->drv_data->chip_id == CHIP_ID_RK3588) {
if (csi_idx < 2) {
dcphy_hw = dphy->samsung_phy_group[csi_idx];
if (dcphy_hw)
rkcif_show_reg_dcphy(dcphy_hw, csi_idx, f);
} else {
dphy_hw = dphy->dphy_hw_group[(csi_idx - 2) / 2];
if (dphy_hw)
rkcif_show_reg_dphy(dphy_hw, (csi_idx - 2) / 2, f);
}
} else {
dphy_hw = dphy->dphy_hw_group[csi_idx / 2];
if (dphy_hw)
rkcif_show_reg_dphy(dphy_hw, csi_idx / 2, f);
}
}
}
static void rkcif_show_reg_dbg(struct rkcif_device *dev, struct seq_file *f)
{
int i;
rkcif_show_reg_vicap(dev, f);
if (dev->inf_id == RKCIF_MIPI_LVDS) {
if (dev->active_sensor->mbus.type == V4L2_MBUS_CSI2_DPHY ||
dev->active_sensor->mbus.type == V4L2_MBUS_CSI2_CPHY) {
for (i = 0; i < 5; i++) {
rkcif_show_reg_csi2(dev, f);
usleep_range(2000, 4000);
}
}
rkcif_show_reg_dphys(dev, f);
}
}
static void rkcif_show_format(struct rkcif_device *dev, struct seq_file *f)
{
struct rkcif_stream *stream = &dev->stream[0];
struct rkcif_pipeline *pipe = &dev->pipe;
struct rkcif_sensor_info *sensor = &dev->terminal_sensor;
struct v4l2_rect *rect = &sensor->raw_rect;
struct v4l2_subdev_frame_interval *interval = &sensor->fi;
struct v4l2_subdev_frame_interval *interval = &sensor->src_fi;
struct v4l2_subdev_selection *sel = &sensor->selection;
u32 mbus_flags;
u64 fps, timestamp0, timestamp1;
@@ -371,9 +647,22 @@ static void rkcif_show_format(struct rkcif_device *dev, struct seq_file *f)
dev->stream[1].total_buf_num,
dev->stream[2].total_buf_num,
dev->stream[3].total_buf_num);
if (dev->sditf[0])
rkcif_show_toisp_info(dev, f);
if (dev->reg_dbg)
rkcif_show_reg_dbg(dev, f);
}
}
static void rkcif_show_group_info(struct rkcif_device *dev, struct seq_file *f)
{
seq_puts(f, "\nGroup Info:\n");
seq_printf(f, "\tSync Mode:%s\n",
rkcif_get_sync_mode(dev->sync_cfg.type));
if (dev->sync_cfg.type != NO_SYNC_MODE)
seq_printf(f, "\tGroup Id:%d\n", dev->sync_cfg.group);
}
static int rkcif_proc_show(struct seq_file *f, void *v)
{
struct rkcif_device *dev = f->private;
@@ -382,6 +671,7 @@ static int rkcif_proc_show(struct seq_file *f, void *v)
rkcif_show_mixed_info(dev, f);
rkcif_show_clks(dev, f);
rkcif_show_format(dev, f);
rkcif_show_group_info(dev, f);
} else {
seq_puts(f, "dev null\n");
}

View File

@@ -199,6 +199,18 @@ enum cif_reg_index {
CIF_REG_TOISP1_CTRL,
CIF_REG_TOISP1_SIZE,
CIF_REG_TOISP1_CROP,
CIF_REG_TOISP0_CH1_CTRL,
CIF_REG_TOISP0_CH1_SIZE,
CIF_REG_TOISP0_CH1_CROP,
CIF_REG_TOISP1_CH1_CTRL,
CIF_REG_TOISP1_CH1_SIZE,
CIF_REG_TOISP1_CH1_CROP,
CIF_REG_TOISP0_CH2_CTRL,
CIF_REG_TOISP0_CH2_SIZE,
CIF_REG_TOISP0_CH2_CROP,
CIF_REG_TOISP1_CH2_CTRL,
CIF_REG_TOISP1_CH2_SIZE,
CIF_REG_TOISP1_CH2_CROP,
CIF_REG_INDEX_MAX
};
@@ -506,6 +518,9 @@ enum cif_reg_index {
#define TOISP1_CH_CTRL 0x78C
#define TOISP1_CROP_SIZE 0x790
#define TOISP1_CROP 0x794
#define TOISP0_CH1_CTRL 0x7A0
#define TOISP0_CH1_CROP_SIZE 0x7A4
#define TOISP0_CH1_CROP 0x7A8
/* The key register bit description */
@@ -527,6 +542,7 @@ enum cif_reg_index {
#define DVP_SW_WATER_LINE_50_RK3576 (0x1 << 20)
#define DVP_SW_WATER_LINE_25_RK3576 (0x2 << 20)
#define DVP_SW_WATER_LINE_00_RK3576 (0x3 << 20)
#define DVP_SW_DMA_IDLE (0x1 << 4)
/* CIF_INTEN */
#define INTEN_DISABLE (0x0 << 0)
@@ -1149,4 +1165,10 @@ enum cif_reg_index {
#define GLB_RESET_IDI_EN_RK3576 (BIT(30))
#define SW_DPHY1_SPLIT_EN_RK3576 (BIT(25))
#define SW_DPHY2_SPLIT_EN_RK3576 (BIT(26))
#define SW_DPHY_SPLIT_EN_RV1103B (BIT(24))
/*mask for rv1103b*/
#define ROUNDING_2BIT_RV1103B (1 << 18)
#define ROUNDING_4BIT_RV1103B (2 << 18)
#endif

View File

@@ -296,6 +296,8 @@ static int sditf_init_buf(struct sditf_priv *priv)
ret |= rkcif_init_rx_buf(&cif_dev->stream[1], priv->buf_num);
} else {
ret = rkcif_init_rx_buf(&cif_dev->stream[0], priv->buf_num);
if (priv->mode.rdbk_mode == RKISP_VICAP_ONLINE_UNITE)
ret |= rkcif_init_rx_buf(&cif_dev->stream[1], priv->buf_num);
}
} else if (priv->hdr_cfg.hdr_mode == HDR_X3) {
if (priv->mode.rdbk_mode == RKISP_VICAP_RDBK_AUTO) {
@@ -311,13 +313,17 @@ static int sditf_init_buf(struct sditf_priv *priv)
} else {
ret = rkcif_init_rx_buf(&cif_dev->stream[0], priv->buf_num);
ret |= rkcif_init_rx_buf(&cif_dev->stream[1], priv->buf_num);
if (priv->mode.rdbk_mode == RKISP_VICAP_ONLINE_UNITE)
ret |= rkcif_init_rx_buf(&cif_dev->stream[2], priv->buf_num);
}
} else {
if (priv->mode.rdbk_mode == RKISP_VICAP_RDBK_AUTO)
if (priv->mode.rdbk_mode == RKISP_VICAP_RDBK_AUTO ||
priv->mode.rdbk_mode == RKISP_VICAP_ONLINE_UNITE)
ret = rkcif_init_rx_buf(&cif_dev->stream[0], priv->buf_num);
else
ret = -EINVAL;
}
priv->is_buf_init = true;
return ret;
}
@@ -341,6 +347,7 @@ static void sditf_free_buf(struct sditf_priv *priv)
cif_dev->wait_line_bak = 0;
cif_dev->is_thunderboot = false;
}
priv->is_buf_init = false;
}
static int sditf_get_selection(struct v4l2_subdev *sd,
@@ -370,7 +377,7 @@ static void sditf_reinit_mode(struct sditf_priv *priv, struct rkisp_vicap_mode *
__func__, mode->rdbk_mode, mode->name, priv->toisp_inf.link_mode);
}
static void sditf_channel_disable(struct sditf_priv *priv, int user);
static void sditf_enable_immediately(struct sditf_priv *priv);
static long sditf_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
{
struct sditf_priv *priv = to_sditf_priv(sd);
@@ -383,14 +390,27 @@ static long sditf_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
struct sditf_time *time;
struct sditf_gain *gain;
struct sditf_effect_exp *effect_exp;
int *pbuf_num = NULL;
struct rkisp_init_buf *pisp_buf_info = NULL;
int ret = 0;
int *on = NULL;
int *connect_id = NULL;
int sync_type = NO_SYNC_MODE;
switch (cmd) {
case RKISP_VICAP_CMD_MODE:
mode = (struct rkisp_vicap_mode *)arg;
if (mode->rdbk_mode == RKISP_VICAP_ONLINE_UNITE &&
priv->cif_dev->chip_id < CHIP_RV1103B_CIF)
return -EINVAL;
memcpy(&priv->mode_src, mode, sizeof(*mode));
if (cif_dev->is_thunderboot &&
cif_dev->is_thunderboot_start) {
if (mode->rdbk_mode < RKISP_VICAP_RDBK_AIQ)
cif_dev->is_rdbk_to_online = true;
else
cif_dev->is_rdbk_to_online = false;
return 0;
}
mutex_lock(&cif_dev->stream_lock);
memcpy(&priv->mode, mode, sizeof(*mode));
mutex_unlock(&cif_dev->stream_lock);
@@ -400,12 +420,31 @@ static long sditf_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
else
mode->input.merge_num = 1;
mode->input.index = priv->combine_index;
ret = v4l2_subdev_call(cif_dev->terminal_sensor.sd,
core, ioctl,
RKMODULE_GET_SYNC_MODE,
&sync_type);
if (ret || sync_type == NO_SYNC_MODE)
mode->input.multi_sync = 0;
else
mode->input.multi_sync = 1;
return 0;
case RKISP_VICAP_CMD_INIT_BUF:
pbuf_num = (int *)arg;
priv->buf_num = *pbuf_num;
pisp_buf_info = (struct rkisp_init_buf *)arg;
priv->buf_num = pisp_buf_info->buf_cnt;
priv->cif_dev->fb_res_bufs = pisp_buf_info->buf_cnt;
sditf_get_set_fmt(&priv->sd, NULL, &fmt);
ret = sditf_init_buf(priv);
if (pisp_buf_info->hdr_wrap_line <= priv->cap_info.height) {
priv->hdr_wrap_line = pisp_buf_info->hdr_wrap_line;
v4l2_dbg(1, rkcif_debug, &cif_dev->v4l2_dev, "hdr_wrap_line %d\n",
priv->hdr_wrap_line);
} else {
dev_info(priv->dev, "set hdr_wap_line failed, val %d, max %d\n",
pisp_buf_info->hdr_wrap_line, priv->cap_info.height);
}
if (!priv->is_buf_init)
ret = sditf_init_buf(priv);
return ret;
case RKMODULE_GET_HDR_CFG:
if (!cif_dev->terminal_sensor.sd)
@@ -421,20 +460,13 @@ static long sditf_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
if (*on) {
rkcif_stream_resume(cif_dev, RKCIF_RESUME_ISP);
} else {
if (priv->toisp_inf.link_mode == TOISP0) {
sditf_channel_disable(priv, 0);
} else if (priv->toisp_inf.link_mode == TOISP1) {
sditf_channel_disable(priv, 1);
} else if (priv->toisp_inf.link_mode == TOISP_UNITE) {
sditf_channel_disable(priv, 0);
if (cif_dev->chip_id == CHIP_RK3588_CIF)
sditf_channel_disable(priv, 1);
}
rkcif_stream_suspend(cif_dev, RKCIF_RESUME_ISP);
if (cif_dev->chip_id == CHIP_RV1106_CIF)
sditf_disable_immediately(priv);
}
break;
case RKISP_VICAP_CMD_SET_RESET:
if (priv->mode.rdbk_mode == RKISP_VICAP_ONLINE) {
if (priv->mode.rdbk_mode < RKISP_VICAP_RDBK_AIQ) {
cif_dev->is_toisp_reset = true;
return 0;
}
@@ -486,6 +518,15 @@ static long sditf_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
connect_id = (int *)arg;
*connect_id = priv->connect_id;
return ret;
case RKISP_VICAP_CMD_HW_LINK:
on = (int *)arg;
if (*on) {
sditf_enable_immediately(priv);
} else {
if (priv->mode.rdbk_mode != RKISP_VICAP_ONLINE_MULTI)
sditf_disable_immediately(priv);
}
return 0;
default:
break;
}
@@ -586,6 +627,11 @@ static long sditf_compat_ioctl32(struct v4l2_subdev *sd,
case RKISP_VICAP_CMD_SET_RESET:
ret = sditf_ioctl(sd, cmd, NULL);
return ret;
case RKISP_VICAP_CMD_HW_LINK:
if (copy_from_user(&on, up, sizeof(int)))
return -EFAULT;
ret = sditf_ioctl(sd, cmd, &on);
return ret;
default:
break;
}
@@ -602,6 +648,141 @@ static long sditf_compat_ioctl32(struct v4l2_subdev *sd,
}
#endif
static int sditf_channel_enable_rv1103b(struct sditf_priv *priv, int user)
{
struct rkcif_device *cif_dev = priv->cif_dev;
struct rkmodule_capture_info *capture_info = &cif_dev->channels[0].capture_info;
unsigned int ch0 = 0, ch1 = 0, ch2 = 0;
unsigned int ctrl_ch0 = 0;
unsigned int ctrl_ch1 = 0;
unsigned int ctrl_ch2 = 0;
unsigned int int_en = 0;
unsigned int offset_x = 0;
unsigned int offset_y = 0;
unsigned int width = priv->cap_info.width;
unsigned int height = priv->cap_info.height;
int csi_idx = cif_dev->csi_host_idx;
unsigned int read_ctrl_ch0 = 0;
unsigned int read_ctrl_ch1 = 0;
unsigned int read_ctrl_ch2 = 0;
if (capture_info->mode == RKMODULE_MULTI_DEV_COMBINE_ONE &&
priv->toisp_inf.link_mode == TOISP_UNITE) {
if (capture_info->multi_dev.dev_num != 2 ||
capture_info->multi_dev.pixel_offset != RKMOUDLE_UNITE_EXTEND_PIXEL) {
v4l2_err(&cif_dev->v4l2_dev,
"param error of online mode, combine dev num %d, offset %d\n",
capture_info->multi_dev.dev_num,
capture_info->multi_dev.pixel_offset);
return -EINVAL;
}
csi_idx = capture_info->multi_dev.dev_idx[user];
}
if (priv->hdr_cfg.hdr_mode == NO_HDR ||
priv->hdr_cfg.hdr_mode == HDR_COMPR) {
if (cif_dev->inf_id == RKCIF_MIPI_LVDS)
ch0 = csi_idx * 4;
else
ch0 = 24;//dvp
ctrl_ch0 = (ch0 << 3) | 0x1;
if (user == 0)
int_en = CIF_TOISP0_FS_RK3576(0) | CIF_TOISP0_FE_RK3576(0);
priv->toisp_inf.ch_info[0].is_valid = true;
priv->toisp_inf.ch_info[0].id = ch0;
} else if (priv->hdr_cfg.hdr_mode == HDR_X2) {
ch0 = cif_dev->csi_host_idx * 4 + 1;
ch1 = cif_dev->csi_host_idx * 4;
ctrl_ch0 = (ch0 << 3) | 0x1;
ctrl_ch1 = (ch1 << 3) | 0x1;
if (cif_dev->chip_id < CHIP_RK3576_CIF) {
if (user == 0)
int_en = CIF_TOISP0_FS(0) | CIF_TOISP0_FS(1) |
CIF_TOISP0_FE(0) | CIF_TOISP0_FE(1);
else
int_en = CIF_TOISP1_FS(0) | CIF_TOISP1_FS(1) |
CIF_TOISP1_FE(0) | CIF_TOISP1_FE(1);
} else {
if (user == 0)
int_en = CIF_TOISP0_FS_RK3576(0) | CIF_TOISP0_FS_RK3576(1) |
CIF_TOISP0_FE_RK3576(0) | CIF_TOISP0_FE_RK3576(1);
}
priv->toisp_inf.ch_info[0].is_valid = true;
priv->toisp_inf.ch_info[0].id = ch0;
priv->toisp_inf.ch_info[1].is_valid = true;
priv->toisp_inf.ch_info[1].id = ch1;
} else if (priv->hdr_cfg.hdr_mode == HDR_X3) {
ch0 = cif_dev->csi_host_idx * 4 + 2;
ch1 = cif_dev->csi_host_idx * 4 + 1;
ch2 = cif_dev->csi_host_idx * 4;
ctrl_ch0 = (ch0 << 3) | 0x1;
ctrl_ch1 = (ch1 << 3) | 0x1;
ctrl_ch2 = (ch2 << 3) | 0x1;
if (user == 0)
int_en = CIF_TOISP0_FS_RK3576(0) | CIF_TOISP0_FS_RK3576(1) |
CIF_TOISP0_FS_RK3576(2) | CIF_TOISP0_FE_RK3576(0) |
CIF_TOISP0_FE_RK3576(1) | CIF_TOISP0_FE_RK3576(2);
priv->toisp_inf.ch_info[0].is_valid = true;
priv->toisp_inf.ch_info[0].id = ch0;
priv->toisp_inf.ch_info[1].is_valid = true;
priv->toisp_inf.ch_info[1].id = ch1;
priv->toisp_inf.ch_info[2].is_valid = true;
priv->toisp_inf.ch_info[2].id = ch2;
}
if (!width || !height)
return -EINVAL;
rkcif_write_register_or(cif_dev, CIF_REG_GLB_INTEN, int_en);
if (user == 0) {
if (priv->mode.rdbk_mode == RKISP_VICAP_ONLINE_UNITE) {
width /= 2;
width += RKMOUDLE_UNITE_EXTEND_PIXEL;
} else if (priv->toisp_inf.link_mode == TOISP_UNITE) {
width = priv->cap_info.width / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL;
}
rkcif_write_register(cif_dev, CIF_REG_TOISP0_CTRL, ctrl_ch0);
rkcif_write_register(cif_dev, CIF_REG_TOISP0_CROP,
offset_x | (offset_y << 16));
rkcif_write_register(cif_dev, CIF_REG_TOISP0_SIZE,
width | (height << 16));
if (priv->hdr_cfg.hdr_mode != NO_HDR &&
priv->hdr_cfg.hdr_mode != HDR_COMPR) {
rkcif_write_register(cif_dev, CIF_REG_TOISP0_CH1_CTRL, ctrl_ch1);
rkcif_write_register(cif_dev, CIF_REG_TOISP0_CH1_CROP,
offset_x | (offset_y << 16));
rkcif_write_register(cif_dev, CIF_REG_TOISP0_CH1_SIZE,
width | (height << 16));
}
if (priv->hdr_cfg.hdr_mode == HDR_X3) {
rkcif_write_register(cif_dev, CIF_REG_TOISP0_CH2_CTRL, ctrl_ch2);
rkcif_write_register(cif_dev, CIF_REG_TOISP0_CH2_CROP,
offset_x | (offset_y << 16));
rkcif_write_register(cif_dev, CIF_REG_TOISP0_CH2_SIZE,
width | (height << 16));
}
}
if (priv->mode.rdbk_mode == RKISP_VICAP_ONLINE_MULTI)
rkcif_write_register_or(cif_dev, CIF_REG_MIPI_LVDS_CTRL, CSI_ENABLE_CAPTURE);
read_ctrl_ch0 = rkcif_read_register(cif_dev, CIF_REG_TOISP0_CTRL);
v4l2_dbg(3, rkcif_debug, &cif_dev->v4l2_dev, "isp%d, toisp ch0 %d, width %d, height %d, reg w:0x%x r:0x%x\n",
user, ch0, width, height, ctrl_ch0, read_ctrl_ch0);
if (priv->hdr_cfg.hdr_mode != NO_HDR) {
read_ctrl_ch1 = rkcif_read_register(cif_dev, CIF_REG_TOISP0_CH1_CTRL);
v4l2_dbg(3, rkcif_debug, &cif_dev->v4l2_dev, "isp%d, toisp ch1 %d, width %d, height %d, reg w:0x%x r:0x%x\n",
user, ch1, width, height, ctrl_ch1, read_ctrl_ch1);
}
if (priv->hdr_cfg.hdr_mode == HDR_X3) {
read_ctrl_ch2 = rkcif_read_register(cif_dev, CIF_REG_TOISP0_CH2_CTRL);
v4l2_dbg(3, rkcif_debug, &cif_dev->v4l2_dev, "isp%d, toisp ch2 %d, width %d, height %d, reg w:0x%x r:0x%x\n",
user, ch2, width, height, ctrl_ch2, read_ctrl_ch2);
}
return 0;
}
static int sditf_channel_enable(struct sditf_priv *priv, int user)
{
struct rkcif_device *cif_dev = priv->cif_dev;
@@ -665,7 +846,6 @@ static int sditf_channel_enable(struct sditf_priv *priv, int user)
}
priv->toisp_inf.ch_info[0].is_valid = true;
priv->toisp_inf.ch_info[0].id = ch0;
priv->toisp_inf.ch_info[1].is_valid = true;
priv->toisp_inf.ch_info[1].id = ch1;
} else if (priv->hdr_cfg.hdr_mode == HDR_X3) {
ch0 = cif_dev->csi_host_idx * 4 + 2;
@@ -689,9 +869,7 @@ static int sditf_channel_enable(struct sditf_priv *priv, int user)
}
priv->toisp_inf.ch_info[0].is_valid = true;
priv->toisp_inf.ch_info[0].id = ch0;
priv->toisp_inf.ch_info[1].is_valid = true;
priv->toisp_inf.ch_info[1].id = ch1;
priv->toisp_inf.ch_info[2].is_valid = true;
priv->toisp_inf.ch_info[2].id = ch2;
}
if (cif_dev->chip_id > CHIP_RK3562_CIF)
@@ -726,6 +904,8 @@ static int sditf_channel_enable(struct sditf_priv *priv, int user)
return -EINVAL;
}
}
v4l2_dbg(3, rkcif_debug, &cif_dev->v4l2_dev, "isp%d, toisp ch0 %d, width %d, height %d, reg 0x%x\n",
user, ch0, width, height, ctrl_val);
#if IS_ENABLED(CONFIG_CPU_RV1106)
rv1106_sdmmc_get_lock();
#endif
@@ -739,104 +919,118 @@ static int sditf_channel_enable(struct sditf_priv *priv, int user)
static void sditf_channel_disable(struct sditf_priv *priv, int user)
{
struct rkcif_device *cif_dev = priv->cif_dev;
unsigned int ctrl_val = 0;
u32 ctrl_val = 0x10101;
if (priv->hdr_cfg.hdr_mode == NO_HDR ||
priv->hdr_cfg.hdr_mode == HDR_COMPR) {
if (user == 0)
ctrl_val = CIF_TOISP0_FE(0);
else
ctrl_val = CIF_TOISP1_FE(0);
} else if (priv->hdr_cfg.hdr_mode == HDR_X2) {
if (user == 0)
ctrl_val = CIF_TOISP0_FE(0) | CIF_TOISP0_FE(1);
else
ctrl_val = CIF_TOISP1_FE(0) | CIF_TOISP1_FE(1);
} else if (priv->hdr_cfg.hdr_mode == HDR_X3) {
if (user == 0)
ctrl_val = CIF_TOISP0_FE(0) | CIF_TOISP0_FE(1) | CIF_TOISP0_FE(2);
else
ctrl_val = CIF_TOISP1_FE(0) | CIF_TOISP1_FE(1) | CIF_TOISP1_FE(2);
}
#if IS_ENABLED(CONFIG_CPU_RV1106)
rv1106_sdmmc_get_lock();
#endif
rkcif_write_register_or(cif_dev, CIF_REG_GLB_INTEN, ctrl_val);
#if IS_ENABLED(CONFIG_CPU_RV1106)
rv1106_sdmmc_put_lock();
#endif
priv->toisp_inf.ch_info[0].is_valid = false;
priv->toisp_inf.ch_info[1].is_valid = false;
priv->toisp_inf.ch_info[2].is_valid = false;
if (user == 0)
rkcif_write_register_and(cif_dev, CIF_REG_TOISP0_CTRL, ~ctrl_val);
else
rkcif_write_register_and(cif_dev, CIF_REG_TOISP1_CTRL, ~ctrl_val);
}
static void sditf_channel_disable_rv1103b(struct sditf_priv *priv, int user)
{
struct rkcif_device *cif_dev = priv->cif_dev;
u32 ctrl_val = 0x1;
u32 read_ctrl_ch0 = 0;
if (priv->mode.rdbk_mode == RKISP_VICAP_ONLINE_MULTI)
rkcif_write_register_and(cif_dev, CIF_REG_MIPI_LVDS_CTRL, ~CSI_ENABLE_CAPTURE);
rkcif_write_register_and(cif_dev, CIF_REG_TOISP0_CTRL, ~ctrl_val);
read_ctrl_ch0 = rkcif_read_register(cif_dev, CIF_REG_TOISP0_CTRL);
v4l2_dbg(3, rkcif_debug, &cif_dev->v4l2_dev, "isp%d, toisp disable reg w_and:0x%x r:0x%x\n",
user, ~ctrl_val, read_ctrl_ch0);
if (priv->hdr_cfg.hdr_mode != NO_HDR)
rkcif_write_register_and(cif_dev, CIF_REG_TOISP0_CH1_CTRL, ~ctrl_val);
if (priv->hdr_cfg.hdr_mode == HDR_X3)
rkcif_write_register_and(cif_dev, CIF_REG_TOISP0_CH2_CTRL, ~ctrl_val);
}
void sditf_change_to_online(struct sditf_priv *priv)
{
struct rkcif_device *cif_dev = priv->cif_dev;
struct rkcif_stream *cur_stream = NULL;
priv->mode.rdbk_mode = RKISP_VICAP_ONLINE;
if (priv->toisp_inf.link_mode == TOISP0) {
sditf_channel_enable(priv, 0);
} else if (priv->toisp_inf.link_mode == TOISP1) {
sditf_channel_enable(priv, 1);
} else if (priv->toisp_inf.link_mode == TOISP_UNITE) {
sditf_channel_enable(priv, 0);
if (cif_dev->chip_id == CHIP_RK3588_CIF)
sditf_channel_enable(priv, 1);
}
priv->mode = priv->mode_src;
if (priv->mode.rdbk_mode != RKISP_VICAP_ONLINE_UNITE &&
priv->mode.rdbk_mode != RKISP_VICAP_ONLINE_MULTI)
sditf_enable_immediately(priv);
if (cif_dev->is_thunderboot) {
if (priv->hdr_cfg.hdr_mode == NO_HDR) {
rkcif_free_rx_buf(&cif_dev->stream[0], cif_dev->stream[0].rx_buf_num);
cur_stream = &cif_dev->stream[0];
cif_dev->stream[0].is_line_wake_up = false;
} else if (priv->hdr_cfg.hdr_mode == HDR_X2) {
rkcif_free_rx_buf(&cif_dev->stream[1], cif_dev->stream[1].rx_buf_num);
cur_stream = &cif_dev->stream[1];
cif_dev->stream[0].is_line_wake_up = false;
cif_dev->stream[1].is_line_wake_up = false;
} else if (priv->hdr_cfg.hdr_mode == HDR_X3) {
rkcif_free_rx_buf(&cif_dev->stream[2], cif_dev->stream[2].rx_buf_num);
cur_stream = &cif_dev->stream[2];
cif_dev->stream[0].is_line_wake_up = false;
cif_dev->stream[1].is_line_wake_up = false;
cif_dev->stream[2].is_line_wake_up = false;
}
if (priv->mode.rdbk_mode == RKISP_VICAP_ONLINE_UNITE)
cur_stream->is_m_online_fb_res = true;
rkcif_free_rx_buf(cur_stream, cur_stream->rx_buf_num);
cif_dev->wait_line_cache = 0;
cif_dev->wait_line = 0;
cif_dev->wait_line_bak = 0;
cif_dev->is_thunderboot = false;
if (priv->mode.rdbk_mode == RKISP_VICAP_ONLINE_UNITE)
rkcif_reinit_right_half_config(cur_stream);
}
}
void sditf_disable_immediately(struct sditf_priv *priv)
{
struct rkcif_device *cif_dev = priv->cif_dev;
u32 ctrl_val = 0x10101;
if (priv->toisp_inf.link_mode == TOISP0) {
rkcif_write_register_and(cif_dev, CIF_REG_TOISP0_CTRL, ~ctrl_val);
if (priv->cif_dev->chip_id == CHIP_RV1103B_CIF)
sditf_channel_disable_rv1103b(priv, 0);
else
sditf_channel_disable(priv, 0);
} else if (priv->toisp_inf.link_mode == TOISP1) {
rkcif_write_register_and(cif_dev, CIF_REG_TOISP1_CTRL, ~ctrl_val);
if (priv->cif_dev->chip_id == CHIP_RV1103B_CIF)
sditf_channel_disable_rv1103b(priv, 1);
else
sditf_channel_disable(priv, 1);
} else if (priv->toisp_inf.link_mode == TOISP_UNITE) {
rkcif_write_register_and(cif_dev, CIF_REG_TOISP0_CTRL, ~ctrl_val);
if (cif_dev->chip_id == CHIP_RK3588_CIF)
rkcif_write_register_and(cif_dev, CIF_REG_TOISP1_CTRL, ~ctrl_val);
if (priv->cif_dev->chip_id == CHIP_RV1103B_CIF) {
sditf_channel_disable_rv1103b(priv, 0);
} else {
sditf_channel_disable(priv, 0);
if (priv->cif_dev->chip_id == CHIP_RK3588_CIF)
sditf_channel_disable(priv, 1);
}
}
priv->is_toisp_off = true;
}
static void sditf_check_capture_mode(struct rkcif_device *cif_dev)
static void sditf_enable_immediately(struct sditf_priv *priv)
{
struct rkcif_device *dev = NULL;
int i = 0;
int toisp_cnt = 0;
for (i = 0; i < cif_dev->hw_dev->dev_num; i++) {
dev = cif_dev->hw_dev->cif_dev[i];
if (dev && dev->sditf_cnt)
toisp_cnt++;
if (priv->toisp_inf.link_mode == TOISP0) {
if (priv->cif_dev->chip_id == CHIP_RV1103B_CIF)
sditf_channel_enable_rv1103b(priv, 0);
else
sditf_channel_enable(priv, 0);
} else if (priv->toisp_inf.link_mode == TOISP1) {
if (priv->cif_dev->chip_id == CHIP_RV1103B_CIF)
sditf_channel_enable_rv1103b(priv, 1);
else
sditf_channel_enable(priv, 1);
} else if (priv->toisp_inf.link_mode == TOISP_UNITE) {
if (priv->cif_dev->chip_id == CHIP_RV1103B_CIF) {
sditf_channel_enable_rv1103b(priv, 0);
} else {
sditf_channel_enable(priv, 0);
if (priv->cif_dev->chip_id == CHIP_RK3588_CIF)
sditf_channel_enable(priv, 1);
}
}
if (cif_dev->is_thunderboot && toisp_cnt == 1)
cif_dev->is_rdbk_to_online = true;
else
cif_dev->is_rdbk_to_online = false;
priv->is_toisp_off = false;
}
static int sditf_start_stream(struct sditf_priv *priv)
@@ -844,35 +1038,28 @@ static int sditf_start_stream(struct sditf_priv *priv)
struct rkcif_device *cif_dev = priv->cif_dev;
struct v4l2_subdev_format fmt;
unsigned int mode = RKCIF_STREAM_MODE_TOISP;
int stream_cnt = 0;
int i = 0;
sditf_check_capture_mode(cif_dev);
sditf_get_set_fmt(&priv->sd, NULL, &fmt);
if (priv->mode.rdbk_mode == RKISP_VICAP_ONLINE) {
if (priv->toisp_inf.link_mode == TOISP0) {
sditf_channel_enable(priv, 0);
} else if (priv->toisp_inf.link_mode == TOISP1) {
sditf_channel_enable(priv, 1);
} else if (priv->toisp_inf.link_mode == TOISP_UNITE) {
sditf_channel_enable(priv, 0);
if (cif_dev->chip_id == CHIP_RK3588_CIF)
sditf_channel_enable(priv, 1);
}
sditf_enable_immediately(priv);
mode = RKCIF_STREAM_MODE_TOISP;
} else if (priv->mode.rdbk_mode == RKISP_VICAP_RDBK_AUTO) {
mode = RKCIF_STREAM_MODE_TOISP_RDBK;
}
if (priv->hdr_cfg.hdr_mode == NO_HDR ||
priv->hdr_cfg.hdr_mode == HDR_COMPR) {
rkcif_do_start_stream(&cif_dev->stream[0], mode);
} else if (priv->hdr_cfg.hdr_mode == HDR_X2) {
rkcif_do_start_stream(&cif_dev->stream[0], mode);
rkcif_do_start_stream(&cif_dev->stream[1], mode);
} else if (priv->hdr_cfg.hdr_mode == HDR_X3) {
rkcif_do_start_stream(&cif_dev->stream[0], mode);
rkcif_do_start_stream(&cif_dev->stream[1], mode);
rkcif_do_start_stream(&cif_dev->stream[2], mode);
}
priv->hdr_cfg.hdr_mode == HDR_COMPR)
stream_cnt = 1;
else if (priv->hdr_cfg.hdr_mode == HDR_X2)
stream_cnt = 2;
else if (priv->hdr_cfg.hdr_mode == HDR_X3)
stream_cnt = 3;
cif_dev->is_thunderboot_start = true;
for (i = 0; i < stream_cnt; i++)
rkcif_do_start_stream(&cif_dev->stream[i], mode);
INIT_LIST_HEAD(&priv->buf_free_list);
return 0;
}
@@ -881,16 +1068,10 @@ static int sditf_stop_stream(struct sditf_priv *priv)
{
struct rkcif_device *cif_dev = priv->cif_dev;
unsigned int mode = RKCIF_STREAM_MODE_TOISP;
if (priv->toisp_inf.link_mode == TOISP0) {
sditf_channel_disable(priv, 0);
} else if (priv->toisp_inf.link_mode == TOISP1) {
sditf_channel_disable(priv, 1);
} else if (priv->toisp_inf.link_mode == TOISP_UNITE) {
sditf_channel_disable(priv, 0);
if (cif_dev->chip_id == CHIP_RK3588_CIF)
sditf_channel_disable(priv, 1);
}
struct rkcif_hw *hw_dev = cif_dev->hw_dev;
int stream_cnt = 0;
int i = 0;
bool toisp_off = true;
if (priv->mode.rdbk_mode == RKISP_VICAP_ONLINE)
mode = RKCIF_STREAM_MODE_TOISP;
@@ -898,16 +1079,29 @@ static int sditf_stop_stream(struct sditf_priv *priv)
mode = RKCIF_STREAM_MODE_TOISP_RDBK;
if (priv->hdr_cfg.hdr_mode == NO_HDR ||
priv->hdr_cfg.hdr_mode == HDR_COMPR) {
rkcif_do_stop_stream(&cif_dev->stream[0], mode);
} else if (priv->hdr_cfg.hdr_mode == HDR_X2) {
rkcif_do_stop_stream(&cif_dev->stream[0], mode);
rkcif_do_stop_stream(&cif_dev->stream[1], mode);
} else if (priv->hdr_cfg.hdr_mode == HDR_X3) {
rkcif_do_stop_stream(&cif_dev->stream[0], mode);
rkcif_do_stop_stream(&cif_dev->stream[1], mode);
rkcif_do_stop_stream(&cif_dev->stream[2], mode);
priv->hdr_cfg.hdr_mode == HDR_COMPR)
stream_cnt = 1;
else if (priv->hdr_cfg.hdr_mode == HDR_X2)
stream_cnt = 2;
else if (priv->hdr_cfg.hdr_mode == HDR_X3)
stream_cnt = 3;
for (i = 0; i < stream_cnt; i++)
rkcif_do_stop_stream(&cif_dev->stream[i], mode);
mutex_lock(&hw_dev->dev_lock);
for (i = 0; i < hw_dev->dev_num; i++) {
if (atomic_read(&hw_dev->cif_dev[i]->pipe.stream_cnt) != 0) {
toisp_off = false;
break;
}
}
mutex_unlock(&hw_dev->dev_lock);
if (toisp_off)
sditf_disable_immediately(priv);
priv->toisp_inf.ch_info[0].is_valid = false;
priv->toisp_inf.ch_info[1].is_valid = false;
priv->toisp_inf.ch_info[2].is_valid = false;
return 0;
}
@@ -985,11 +1179,10 @@ static int sditf_s_rx_buffer(struct v4l2_subdev *sd,
struct rkcif_stream *stream = NULL;
struct rkisp_rx_buf *dbufs;
struct rkcif_rx_buffer *rx_buf = NULL;
unsigned long flags, buffree_flags, hdr_lock_flags;
unsigned long flags, buffree_flags;
u32 diff_time = 1000000;
u32 early_time = 0;
bool is_free = false;
bool is_single_dev = false;
if (!buf) {
v4l2_err(&cif_dev->v4l2_dev, "buf is NULL\n");
@@ -1023,7 +1216,8 @@ static int sditf_s_rx_buffer(struct v4l2_subdev *sd,
if (!stream)
return -EINVAL;
if (dbufs->sequence == 0) {
if (dbufs->sequence == 0 &&
stream->thunderboot_skip_interval) {
spin_lock_irqsave(&stream->vbq_lock, flags);
cif_dev->is_stop_skip = true;
spin_unlock_irqrestore(&stream->vbq_lock, flags);
@@ -1036,14 +1230,10 @@ static int sditf_s_rx_buffer(struct v4l2_subdev *sd,
stream->last_rx_buf_idx = dbufs->sequence + 1;
atomic_inc(&stream->buf_cnt);
is_single_dev = rkcif_check_single_dev_stream_on(cif_dev->hw_dev);
if (stream->total_buf_num > cif_dev->fb_res_bufs &&
cif_dev->is_thunderboot &&
((!cif_dev->is_rtt_suspend &&
!cif_dev->is_aov_reserved) ||
!is_single_dev) &&
(dbufs->type == BUF_SHORT ||
(dbufs->type != BUF_SHORT && (!dbufs->is_switch)))) {
(dbufs->sequence > 2) &&
(!dbufs->is_switch)) {
spin_lock_irqsave(&cif_dev->buffree_lock, buffree_flags);
list_add_tail(&rx_buf->list_free, &priv->buf_free_list);
spin_unlock_irqrestore(&cif_dev->buffree_lock, buffree_flags);
@@ -1060,15 +1250,11 @@ static int sditf_s_rx_buffer(struct v4l2_subdev *sd,
if (!stream->dma_en) {
stream->to_en_dma = RKCIF_DMAEN_BY_ISP;
rkcif_enable_dma_capture(stream, true);
spin_lock_irqsave(&cif_dev->hdr_lock, hdr_lock_flags);
if (cif_dev->is_sensor_off) {
cif_dev->is_sensor_off = false;
spin_unlock_irqrestore(&cif_dev->hdr_lock, hdr_lock_flags);
if (atomic_read(&cif_dev->sensor_off)) {
atomic_set(&cif_dev->sensor_off, 0);
cif_dev->sensor_work.on = 1;
rkcif_dphy_quick_stream(stream->cifdev, cif_dev->sensor_work.on);
schedule_work(&cif_dev->sensor_work.work);
} else {
spin_unlock_irqrestore(&cif_dev->hdr_lock, hdr_lock_flags);
}
}
}
@@ -1092,15 +1278,31 @@ static int sditf_s_rx_buffer(struct v4l2_subdev *sd,
}
if (dbufs->is_switch && dbufs->type == BUF_SHORT) {
if (stream->is_in_vblank)
if (stream->is_in_vblank) {
sditf_change_to_online(priv);
else
rkcif_modify_line_int(stream, false);
stream->is_line_inten = false;
} else {
stream->is_change_toisp = true;
}
v4l2_dbg(3, rkcif_debug, &cif_dev->v4l2_dev,
"switch to online mode\n");
}
spin_unlock_irqrestore(&stream->vbq_lock, flags);
spin_lock_irqsave(&stream->cifdev->stream_spinlock, flags);
stream->is_finish_single_cap = true;
if (stream->is_wait_single_cap &&
(cif_dev->hdr.hdr_mode == NO_HDR ||
(cif_dev->hdr.hdr_mode == HDR_X2 && stream->id == 1) ||
(cif_dev->hdr.hdr_mode == HDR_X3 && stream->id == 2))) {
stream->is_wait_single_cap = false;
spin_unlock_irqrestore(&stream->cifdev->stream_spinlock, flags);
rkcif_quick_stream_on(cif_dev, true);
} else {
spin_unlock_irqrestore(&stream->cifdev->stream_spinlock, flags);
}
if (!cif_dev->is_thunderboot ||
cif_dev->is_rdbk_to_online == false)
return 0;
@@ -1113,7 +1315,8 @@ static int sditf_s_rx_buffer(struct v4l2_subdev *sd,
diff_time = 200000;
else
diff_time = 1000000;
if (dbufs->runtime_us * 1000 + cif_dev->sensor_linetime > diff_time)
if (dbufs->runtime_us * 1000 < cif_dev->sensor_linetime * sensor->raw_rect.height &&
dbufs->runtime_us * 1000 + cif_dev->sensor_linetime > diff_time)
early_time = dbufs->runtime_us * 1000 - diff_time;
else
early_time = diff_time;
@@ -1133,7 +1336,8 @@ static int sditf_s_rx_buffer(struct v4l2_subdev *sd,
diff_time = 200000;
else
diff_time = 1000000;
if (dbufs->runtime_us * 1000 + cif_dev->sensor_linetime > diff_time)
if (dbufs->runtime_us * 1000 < cif_dev->sensor_linetime * sensor->raw_rect.height &&
dbufs->runtime_us * 1000 + cif_dev->sensor_linetime > diff_time)
early_time = dbufs->runtime_us * 1000 - diff_time;
else
early_time = diff_time;
@@ -1447,6 +1651,7 @@ static int rkcif_subdev_media_init(struct sditf_priv *priv)
priv->toisp_inf.ch_info[0].is_valid = false;
priv->toisp_inf.ch_info[1].is_valid = false;
priv->toisp_inf.ch_info[2].is_valid = false;
priv->is_toisp_off = true;
if (priv->port_count > 1)
sditf_subdev_notifier(priv);
atomic_set(&priv->power_cnt, 0);
@@ -1459,6 +1664,8 @@ static int rkcif_subdev_media_init(struct sditf_priv *priv)
priv->frame_idx.cur_frame_idx = 0;
atomic_set(&priv->frm_sync_seq, 0);
mutex_init(&priv->mutex);
priv->hdr_wrap_line = 0;
priv->is_buf_init = false;
return 0;
}

View File

@@ -100,6 +100,7 @@ struct sditf_priv {
struct rkmodule_hdr_cfg hdr_cfg;
struct capture_info cap_info;
struct rkisp_vicap_mode mode;
struct rkisp_vicap_mode mode_src;
struct toisp_info toisp_inf;
struct v4l2_ctrl *pixel_rate;
struct v4l2_ctrl_handler ctrl_handler;
@@ -123,6 +124,9 @@ struct sditf_priv {
u32 cur_time;
u32 cur_gain;
int one_to_multi_id;
u32 hdr_wrap_line;
bool is_toisp_off;
bool is_buf_init;
};
extern struct platform_driver rkcif_subdev_driver;