mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-06 10:58:48 +09:00
media: rockchip: vicap compatible with rk3588s2
Signed-off-by: Zefa Chen <zefa.chen@rock-chips.com> Change-Id: Idd8312275b97b690de378094116d558e85b4cb00
This commit is contained in:
@@ -847,10 +847,11 @@ static int get_csi_crop_align(const struct cif_input_fmt *fmt_in)
|
||||
}
|
||||
|
||||
const struct
|
||||
cif_input_fmt *get_input_fmt(struct v4l2_subdev *sd, struct v4l2_rect *rect,
|
||||
cif_input_fmt *rkcif_get_input_fmt(struct rkcif_device *dev, struct v4l2_rect *rect,
|
||||
u32 pad_id, struct csi_channel_info *csi_info)
|
||||
{
|
||||
struct v4l2_subdev_format fmt;
|
||||
struct v4l2_subdev *sd = dev->terminal_sensor.sd;
|
||||
struct rkmodule_channel_info ch_info = {0};
|
||||
struct rkmodule_capture_info capture_info;
|
||||
int ret;
|
||||
@@ -914,8 +915,22 @@ cif_input_fmt *get_input_fmt(struct v4l2_subdev *sd, struct v4l2_rect *rect,
|
||||
core, ioctl,
|
||||
RKMODULE_GET_CAPTURE_MODE,
|
||||
&capture_info);
|
||||
if (!ret)
|
||||
if (!ret) {
|
||||
if (capture_info.mode == RKMODULE_MULTI_DEV_COMBINE_ONE &&
|
||||
dev->hw_dev->is_rk3588s2) {
|
||||
for (i = 0; i < capture_info.multi_dev.dev_num; i++) {
|
||||
if (capture_info.multi_dev.dev_idx[i] == 0)
|
||||
capture_info.multi_dev.dev_idx[i] = 2;
|
||||
else if (capture_info.multi_dev.dev_idx[i] == 2)
|
||||
capture_info.multi_dev.dev_idx[i] = 4;
|
||||
else if (capture_info.multi_dev.dev_idx[i] == 3)
|
||||
capture_info.multi_dev.dev_idx[i] = 5;
|
||||
}
|
||||
}
|
||||
csi_info->capture_info = capture_info;
|
||||
} else {
|
||||
csi_info->capture_info.mode = RKMODULE_CAPTURE_MODE_NONE;
|
||||
}
|
||||
for (i = 0; i < ARRAY_SIZE(in_fmts); i++)
|
||||
if (fmt.format.code == in_fmts[i].mbus_code &&
|
||||
fmt.format.field == in_fmts[i].field)
|
||||
@@ -5362,9 +5377,9 @@ static int rkcif_sanity_check_fmt(struct rkcif_stream *stream,
|
||||
struct v4l2_rect input, *crop;
|
||||
|
||||
if (dev->terminal_sensor.sd) {
|
||||
stream->cif_fmt_in = get_input_fmt(dev->terminal_sensor.sd,
|
||||
&input, stream->id,
|
||||
&dev->channels[stream->id]);
|
||||
stream->cif_fmt_in = rkcif_get_input_fmt(dev,
|
||||
&input, stream->id,
|
||||
&dev->channels[stream->id]);
|
||||
if (!stream->cif_fmt_in) {
|
||||
v4l2_err(v4l2_dev, "Input fmt is invalid\n");
|
||||
return -EINVAL;
|
||||
@@ -6146,10 +6161,15 @@ int rkcif_do_start_stream(struct rkcif_stream *stream, unsigned int mode)
|
||||
csi_info.csi_num, RKCIF_MAX_CSI_NUM);
|
||||
goto out;
|
||||
}
|
||||
for (i = 0; i < csi_info.csi_num; i++)
|
||||
for (i = 0; i < csi_info.csi_num; i++) {
|
||||
csi_info.csi_idx[i] = dev->channels[0].capture_info.multi_dev.dev_idx[i];
|
||||
if (dev->hw_dev->is_rk3588s2)
|
||||
v4l2_info(v4l2_dev, "rk3588s2 combine mode attach to mipi%d\n",
|
||||
csi_info.csi_idx[i]);
|
||||
}
|
||||
} else {
|
||||
csi_info.csi_num = 1;
|
||||
dev->csi_host_idx = dev->csi_host_idx_def;
|
||||
csi_info.csi_idx[0] = dev->csi_host_idx;
|
||||
}
|
||||
ret = v4l2_subdev_call(dev->active_sensor->sd,
|
||||
@@ -6350,9 +6370,9 @@ int rkcif_set_fmt(struct rkcif_stream *stream,
|
||||
input_rect.height = RKCIF_DEFAULT_HEIGHT;
|
||||
|
||||
if (dev->terminal_sensor.sd) {
|
||||
cif_fmt_in = get_input_fmt(dev->terminal_sensor.sd,
|
||||
&input_rect, stream->id,
|
||||
channel_info);
|
||||
cif_fmt_in = rkcif_get_input_fmt(dev,
|
||||
&input_rect, stream->id,
|
||||
channel_info);
|
||||
stream->cif_fmt_in = cif_fmt_in;
|
||||
} else {
|
||||
v4l2_err(&stream->cifdev->v4l2_dev,
|
||||
@@ -6720,9 +6740,9 @@ static int rkcif_enum_framesizes(struct file *file, void *prov,
|
||||
input_rect.height = RKCIF_DEFAULT_HEIGHT;
|
||||
|
||||
if (dev->terminal_sensor.sd)
|
||||
get_input_fmt(dev->terminal_sensor.sd,
|
||||
&input_rect, stream->id,
|
||||
&csi_info);
|
||||
rkcif_get_input_fmt(dev,
|
||||
&input_rect, stream->id,
|
||||
&csi_info);
|
||||
|
||||
if (dev->hw_dev->adapt_to_usbcamerahal) {
|
||||
fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
|
||||
@@ -6801,7 +6821,7 @@ static int rkcif_enum_fmt_vid_cap_mplane(struct file *file, void *priv,
|
||||
return -EINVAL;
|
||||
|
||||
if (dev->terminal_sensor.sd) {
|
||||
cif_fmt_in = get_input_fmt(dev->terminal_sensor.sd,
|
||||
cif_fmt_in = rkcif_get_input_fmt(dev,
|
||||
&input_rect, stream->id,
|
||||
&dev->channels[stream->id]);
|
||||
stream->cif_fmt_in = cif_fmt_in;
|
||||
@@ -7187,8 +7207,8 @@ static long rkcif_ioctl_default(struct file *file, void *fh,
|
||||
break;
|
||||
case RKCIF_CMD_SET_CSI_MEMORY_MODE:
|
||||
if (dev->terminal_sensor.sd) {
|
||||
in_fmt = get_input_fmt(dev->terminal_sensor.sd,
|
||||
&rect, 0, &csi_info);
|
||||
in_fmt = rkcif_get_input_fmt(dev,
|
||||
&rect, 0, &csi_info);
|
||||
if (in_fmt == NULL) {
|
||||
v4l2_err(&dev->v4l2_dev, "can't get sensor input format\n");
|
||||
return -EINVAL;
|
||||
|
||||
@@ -364,8 +364,8 @@ static int rkcif_scale_enum_framesizes(struct file *file, void *prov,
|
||||
input_rect.height = RKCIF_DEFAULT_HEIGHT;
|
||||
|
||||
if (terminal_sensor && terminal_sensor->sd)
|
||||
get_input_fmt(terminal_sensor->sd,
|
||||
&input_rect, 0, &csi_info);
|
||||
rkcif_get_input_fmt(dev,
|
||||
&input_rect, 0, &csi_info);
|
||||
|
||||
switch (fsize->index) {
|
||||
case SCALE_8TIMES:
|
||||
|
||||
@@ -300,8 +300,8 @@ static int rkcif_tools_enum_framesizes(struct file *file, void *prov,
|
||||
input_rect.height = RKCIF_DEFAULT_HEIGHT;
|
||||
|
||||
if (terminal_sensor && terminal_sensor->sd)
|
||||
get_input_fmt(terminal_sensor->sd,
|
||||
&input_rect, 0, &csi_info);
|
||||
rkcif_get_input_fmt(dev,
|
||||
&input_rect, 0, &csi_info);
|
||||
|
||||
fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
|
||||
s->width = input_rect.width;
|
||||
|
||||
@@ -1998,6 +1998,17 @@ int rkcif_plat_init(struct rkcif_device *cif_dev, struct device_node *node, int
|
||||
cif_dev->csi_host_idx = of_alias_get_id(node, "rkcif_mipi_lvds");
|
||||
if (cif_dev->csi_host_idx < 0 || cif_dev->csi_host_idx > 5)
|
||||
cif_dev->csi_host_idx = 0;
|
||||
if (cif_dev->hw_dev->is_rk3588s2) {
|
||||
if (cif_dev->csi_host_idx == 0)
|
||||
cif_dev->csi_host_idx = 2;
|
||||
else if (cif_dev->csi_host_idx == 2)
|
||||
cif_dev->csi_host_idx = 4;
|
||||
else if (cif_dev->csi_host_idx == 3)
|
||||
cif_dev->csi_host_idx = 5;
|
||||
v4l2_info(&cif_dev->v4l2_dev, "rk3588s2 attach to mipi%d\n",
|
||||
cif_dev->csi_host_idx);
|
||||
}
|
||||
cif_dev->csi_host_idx_def = cif_dev->csi_host_idx;
|
||||
cif_dev->media_dev.dev = dev;
|
||||
v4l2_dev = &cif_dev->v4l2_dev;
|
||||
v4l2_dev->mdev = &cif_dev->media_dev;
|
||||
@@ -2160,7 +2171,9 @@ static int rkcif_plat_probe(struct platform_device *pdev)
|
||||
if (sysfs_create_group(&pdev->dev.kobj, &dev_attr_grp))
|
||||
return -ENODEV;
|
||||
|
||||
rkcif_attach_hw(cif_dev);
|
||||
ret = rkcif_attach_hw(cif_dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
rkcif_parse_dts(cif_dev);
|
||||
|
||||
|
||||
@@ -845,6 +845,7 @@ struct rkcif_device {
|
||||
struct rkcif_work_struct reset_work;
|
||||
int id_use_cnt;
|
||||
unsigned int csi_host_idx;
|
||||
unsigned int csi_host_idx_def;
|
||||
unsigned int dvp_sof_in_oneframe;
|
||||
unsigned int wait_line;
|
||||
unsigned int wait_line_bak;
|
||||
@@ -887,7 +888,7 @@ void rkcif_vb_done_tasklet(struct rkcif_stream *stream, struct rkcif_buffer *buf
|
||||
int rkcif_scale_start(struct rkcif_scale_vdev *scale_vdev);
|
||||
|
||||
const struct
|
||||
cif_input_fmt *get_input_fmt(struct v4l2_subdev *sd,
|
||||
cif_input_fmt *rkcif_get_input_fmt(struct rkcif_device *dev,
|
||||
struct v4l2_rect *rect,
|
||||
u32 pad_id, struct csi_channel_info *csi_info);
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <linux/delay.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/nvmem-consumer.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <linux/of_graph.h>
|
||||
@@ -1252,6 +1253,51 @@ void rkcif_hw_soft_reset(struct rkcif_hw *cif_hw, bool is_rst_iommu)
|
||||
rkcif_iommu_enable(cif_hw);
|
||||
}
|
||||
|
||||
static int rkcif_get_efuse_value(struct device_node *np, char *porp_name,
|
||||
u8 *value)
|
||||
{
|
||||
struct nvmem_cell *cell;
|
||||
unsigned char *buf;
|
||||
size_t len;
|
||||
|
||||
cell = of_nvmem_cell_get(np, porp_name);
|
||||
if (IS_ERR(cell))
|
||||
return PTR_ERR(cell);
|
||||
|
||||
buf = (unsigned char *)nvmem_cell_read(cell, &len);
|
||||
|
||||
nvmem_cell_put(cell);
|
||||
|
||||
if (IS_ERR(buf))
|
||||
return PTR_ERR(buf);
|
||||
|
||||
*value = buf[0];
|
||||
|
||||
kfree(buf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rkcif_get_speciand_package_number(struct device_node *np)
|
||||
{
|
||||
u8 spec = 0, package = 0, low = 0, high = 0;
|
||||
|
||||
if (rkcif_get_efuse_value(np, "specification", &spec))
|
||||
return -EINVAL;
|
||||
if (rkcif_get_efuse_value(np, "package_low", &low))
|
||||
return -EINVAL;
|
||||
if (rkcif_get_efuse_value(np, "package_high", &high))
|
||||
return -EINVAL;
|
||||
|
||||
package = ((high & 0x1) << 3) | low;
|
||||
|
||||
/* RK3588S */
|
||||
if (spec == 0x13)
|
||||
return package;
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int rkcif_plat_hw_probe(struct platform_device *pdev)
|
||||
{
|
||||
const struct of_device_id *match;
|
||||
@@ -1265,6 +1311,7 @@ static int rkcif_plat_hw_probe(struct platform_device *pdev)
|
||||
int i, ret, irq;
|
||||
bool is_mem_reserved = false;
|
||||
struct notifier_block *notifier;
|
||||
int package = 0;
|
||||
|
||||
match = of_match_node(rkcif_plat_of_match, node);
|
||||
if (IS_ERR(match))
|
||||
@@ -1278,6 +1325,13 @@ static int rkcif_plat_hw_probe(struct platform_device *pdev)
|
||||
dev_set_drvdata(dev, cif_hw);
|
||||
cif_hw->dev = dev;
|
||||
|
||||
package = rkcif_get_speciand_package_number(node);
|
||||
if (package == 0x2) {
|
||||
cif_hw->is_rk3588s2 = true;
|
||||
dev_info(dev, "attach rk3588s2\n");
|
||||
} else {
|
||||
cif_hw->is_rk3588s2 = false;
|
||||
}
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
if (irq < 0)
|
||||
return irq;
|
||||
|
||||
@@ -150,6 +150,7 @@ struct rkcif_hw {
|
||||
bool is_dma_contig;
|
||||
bool adapt_to_usbcamerahal;
|
||||
u64 irq_time;
|
||||
bool is_rk3588s2;
|
||||
};
|
||||
|
||||
void rkcif_hw_soft_reset(struct rkcif_hw *cif_hw, bool is_rst_iommu);
|
||||
|
||||
Reference in New Issue
Block a user