diff options
Diffstat (limited to 'bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0470-media-i2c-add-fps-setup.patch')
-rw-r--r-- | bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0470-media-i2c-add-fps-setup.patch | 429 |
1 files changed, 429 insertions, 0 deletions
diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0470-media-i2c-add-fps-setup.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0470-media-i2c-add-fps-setup.patch new file mode 100644 index 00000000..70fac592 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0470-media-i2c-add-fps-setup.patch @@ -0,0 +1,429 @@ +From 07c0308d3c5991ff67c32329d56f14e375e3e981 Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +Date: Mon, 10 Feb 2020 18:46:46 +0300 +Subject: [PATCH] media: i2c: add fps setup + +This adds FPS setup for max9286/ti9x4 with ar0143/147 imagers + +Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +--- + drivers/media/i2c/soc_camera/ar0143.c | 66 ++++++++++++++++++++++++++++++++-- + drivers/media/i2c/soc_camera/ar0147.c | 64 +++++++++++++++++++++++++++++++-- + drivers/media/i2c/soc_camera/max9286.c | 42 ++++++++++++++++++++++ + drivers/media/i2c/soc_camera/ti9x4.c | 54 ++++++++++++++++++++++++---- + 4 files changed, 215 insertions(+), 11 deletions(-) + +diff --git a/drivers/media/i2c/soc_camera/ar0143.c b/drivers/media/i2c/soc_camera/ar0143.c +index d81871b..de4ca3c 100644 +--- a/drivers/media/i2c/soc_camera/ar0143.c ++++ b/drivers/media/i2c/soc_camera/ar0143.c +@@ -35,6 +35,8 @@ struct ar0143_priv { + struct v4l2_ctrl_handler hdl; + struct media_pad pad; + struct v4l2_rect rect; ++ int fps_numerator; ++ int fps_denominator; + int init_complete; + u8 id[6]; + int setup; +@@ -297,6 +299,61 @@ static int ar0143_g_mbus_config(struct v4l2_subdev *sd, + return 0; + } + ++static int ar0143_g_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ar0143_priv *priv = to_ar0143(client); ++ struct v4l2_captureparm *cp = &parms->parm.capture; ++ ++ if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) ++ return -EINVAL; ++ ++ memset(cp, 0, sizeof(struct v4l2_captureparm)); ++ cp->capability = V4L2_CAP_TIMEPERFRAME; ++ cp->timeperframe.numerator = priv->fps_numerator; ++ cp->timeperframe.denominator = priv->fps_denominator; ++ ++ return 0; ++} ++ ++static int ar0143_s_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ar0143_priv *priv = to_ar0143(client); ++ struct v4l2_captureparm *cp = &parms->parm.capture; ++ int ret = 0; ++ int tmp_addr; ++ ++ if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) ++ return -EINVAL; ++ if (cp->extendedmode != 0) ++ return -EINVAL; ++ ++ if (priv->fps_denominator != cp->timeperframe.denominator || ++ priv->fps_numerator != cp->timeperframe.numerator) { ++ if (priv->ti9x4_addr) ++ priv->vts = (AR0143_SENSOR_HEIGHT + 157) * 30 * cp->timeperframe.numerator / cp->timeperframe.denominator; ++ else ++ priv->vts = (AR0143_SENSOR_HEIGHT + 142) * 30 * cp->timeperframe.numerator / cp->timeperframe.denominator; ++ ++ ret = reg16_write16(client, 0x300A, priv->vts); /* FRAME_LENGTH_LINES_ */ ++ ++ tmp_addr = client->addr; ++ if (priv->max9271_addr) { ++ client->addr = priv->max9271_addr; /* Serializer I2C address */ ++ reg8_write(client, 0x58, priv->vts >> 8); /* HS count */ ++ reg8_write(client, 0x59, priv->vts & 0xff); ++ } ++ client->addr = tmp_addr; ++ ++ priv->fps_denominator = cp->timeperframe.numerator; ++ priv->fps_denominator = cp->timeperframe.denominator; ++ } ++out: ++ return ret; ++} ++ ++ + #ifdef CONFIG_VIDEO_ADV_DEBUG + static int ar0143_g_register(struct v4l2_subdev *sd, + struct v4l2_dbg_register *reg) +@@ -361,7 +418,8 @@ static int ar0143_s_ctrl(struct v4l2_ctrl *ctrl) + break; + case V4L2_CID_EXPOSURE: + /* T1 exposure */ +- ret = reg16_write16(client, 0x3012, ctrl->val); ++ if (ctrl->val < 0x400 * 30 * priv->fps_numerator / priv->fps_denominator) ++ ret = reg16_write16(client, 0x3012, ctrl->val); + break; + case V4L2_CID_HFLIP: + ret = reg16_read16(client, 0x3040, &val); +@@ -394,6 +452,8 @@ static const struct v4l2_ctrl_ops ar0143_ctrl_ops = { + static struct v4l2_subdev_video_ops ar0143_video_ops = { + .s_stream = ar0143_s_stream, + .g_mbus_config = ar0143_g_mbus_config, ++ .g_parm = ar0143_g_parm, ++ .s_parm = ar0143_s_parm, + }; + + static const struct v4l2_subdev_pad_ops ar0143_subdev_pad_ops = { +@@ -617,6 +677,8 @@ static int ar0143_probe(struct i2c_client *client, + + v4l2_i2c_subdev_init(&priv->sd, client, &ar0143_subdev_ops); + priv->sd.flags = V4L2_SUBDEV_FL_HAS_DEVNODE; ++ priv->fps_numerator = 1; ++ priv->fps_denominator = 30; + + v4l2_ctrl_handler_init(&priv->hdl, 4); + v4l2_ctrl_new_std(&priv->hdl, &ar0143_ctrl_ops, +@@ -638,7 +700,7 @@ static int ar0143_probe(struct i2c_client *client, + v4l2_ctrl_new_std(&priv->hdl, &ar0143_ctrl_ops, + V4L2_CID_ANALOGUE_GAIN, 1, 0xe, 1, 0x7); + v4l2_ctrl_new_std(&priv->hdl, &ar0143_ctrl_ops, +- V4L2_CID_EXPOSURE, 1, 0x400, 1, 0x300); ++ V4L2_CID_EXPOSURE, 1, 0x400 * 30, 1, 0x300); + v4l2_ctrl_new_std(&priv->hdl, &ar0143_ctrl_ops, + V4L2_CID_HFLIP, 0, 1, 1, 0); + v4l2_ctrl_new_std(&priv->hdl, &ar0143_ctrl_ops, +diff --git a/drivers/media/i2c/soc_camera/ar0147.c b/drivers/media/i2c/soc_camera/ar0147.c +index fc2a09e..e3ecec2 100644 +--- a/drivers/media/i2c/soc_camera/ar0147.c ++++ b/drivers/media/i2c/soc_camera/ar0147.c +@@ -36,6 +36,8 @@ struct ar0147_priv { + struct v4l2_ctrl_handler hdl; + struct media_pad pad; + struct v4l2_rect rect; ++ int fps_denominator; ++ int fps_numerator; + int init_complete; + u8 id[6]; + /* serializers */ +@@ -146,7 +148,7 @@ static int ar0147_set_regs(struct i2c_client *client, const struct ar0147_reg ** + reg16_write16(client, regs[i].reg, 1); // OP_SYS_CLK_DIV + continue; + case 0x300A: +- reg16_write16(client, regs[i].reg, AR0147_SENSOR_HEIGHT + 142); // FRAME_LENGTH_LINES_ ++ reg16_write16(client, regs[i].reg, AR0147_SENSOR_HEIGHT + 226); // FRAME_LENGTH_LINES_ + continue; + } + } +@@ -317,6 +319,57 @@ static int ar0147_g_mbus_config(struct v4l2_subdev *sd, + return 0; + } + ++static int ar0147_g_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ar0147_priv *priv = to_ar0147(client); ++ struct v4l2_captureparm *cp = &parms->parm.capture; ++ ++ if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) ++ return -EINVAL; ++ ++ memset(cp, 0, sizeof(struct v4l2_captureparm)); ++ cp->capability = V4L2_CAP_TIMEPERFRAME; ++ cp->timeperframe.numerator = priv->fps_numerator; ++ cp->timeperframe.denominator = priv->fps_denominator; ++ ++ return 0; ++} ++ ++static int ar0147_s_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ar0147_priv *priv = to_ar0147(client); ++ struct v4l2_captureparm *cp = &parms->parm.capture; ++ int ret = 0; ++ int tmp_addr; ++ ++ if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) ++ return -EINVAL; ++ if (cp->extendedmode != 0) ++ return -EINVAL; ++ ++ if (priv->fps_denominator != cp->timeperframe.denominator || ++ priv->fps_numerator != cp->timeperframe.numerator) { ++ priv->vts = (AR0147_SENSOR_HEIGHT + 226) * 30 * cp->timeperframe.numerator / cp->timeperframe.denominator; ++ ++ ret = reg16_write16(client, 0x300A, priv->vts); /* FRAME_LENGTH_LINES_ */ ++ ++ tmp_addr = client->addr; ++ if (priv->max9271_addr) { ++ client->addr = priv->max9271_addr; /* Serializer I2C address */ ++ reg8_write(client, 0x58, priv->vts >> 8); /* HS count */ ++ reg8_write(client, 0x59, priv->vts & 0xff); ++ } ++ client->addr = tmp_addr; ++ ++ priv->fps_numerator = cp->timeperframe.numerator; ++ priv->fps_denominator = cp->timeperframe.denominator; ++ } ++out: ++ return ret; ++} ++ + #ifdef CONFIG_VIDEO_ADV_DEBUG + static int ar0147_g_register(struct v4l2_subdev *sd, + struct v4l2_dbg_register *reg) +@@ -381,7 +434,8 @@ static int ar0147_s_ctrl(struct v4l2_ctrl *ctrl) + break; + case V4L2_CID_EXPOSURE: + /* T1 exposure */ +- ret = reg16_write16(client, 0x3012, ctrl->val); ++ if (ctrl->val < 0x400 * 30 * priv->fps_numerator / priv->fps_denominator) ++ ret = reg16_write16(client, 0x3012, ctrl->val); + break; + case V4L2_CID_HFLIP: + ret = reg16_read16(client, 0x3040, &val); +@@ -414,6 +468,8 @@ static const struct v4l2_ctrl_ops ar0147_ctrl_ops = { + static struct v4l2_subdev_video_ops ar0147_video_ops = { + .s_stream = ar0147_s_stream, + .g_mbus_config = ar0147_g_mbus_config, ++ .g_parm = ar0147_g_parm, ++ .s_parm = ar0147_s_parm, + }; + + static const struct v4l2_subdev_pad_ops ar0147_subdev_pad_ops = { +@@ -648,6 +704,8 @@ static int ar0147_probe(struct i2c_client *client, + + v4l2_i2c_subdev_init(&priv->sd, client, &ar0147_subdev_ops); + priv->sd.flags = V4L2_SUBDEV_FL_HAS_DEVNODE; ++ priv->fps_numerator = 1; ++ priv->fps_denominator = 30; + + v4l2_ctrl_handler_init(&priv->hdl, 4); + v4l2_ctrl_new_std(&priv->hdl, &ar0147_ctrl_ops, +@@ -669,7 +727,7 @@ static int ar0147_probe(struct i2c_client *client, + v4l2_ctrl_new_std(&priv->hdl, &ar0147_ctrl_ops, + V4L2_CID_ANALOGUE_GAIN, 1, 0xe, 1, 0x7); + v4l2_ctrl_new_std(&priv->hdl, &ar0147_ctrl_ops, +- V4L2_CID_EXPOSURE, 1, 0x400, 1, 0x300); ++ V4L2_CID_EXPOSURE, 1, 0x400 * 30, 1, 0x300); + v4l2_ctrl_new_std(&priv->hdl, &ar0147_ctrl_ops, + V4L2_CID_HFLIP, 0, 1, 1, 0); + v4l2_ctrl_new_std(&priv->hdl, &ar0147_ctrl_ops, +diff --git a/drivers/media/i2c/soc_camera/max9286.c b/drivers/media/i2c/soc_camera/max9286.c +index 0a1732a..343b8ab 100644 +--- a/drivers/media/i2c/soc_camera/max9286.c ++++ b/drivers/media/i2c/soc_camera/max9286.c +@@ -43,6 +43,8 @@ struct max9286_priv { + int csi_rate; + const char *fsync_mode; + int fsync_period; ++ int fps_numerator; ++ int fps_denominator; + int pclk; + char pclk_rising_edge; + int gpio_resetb; +@@ -650,8 +652,46 @@ static struct v4l2_subdev_core_ops max9286_subdev_core_ops = { + .registered_async = max9286_registered_async, + }; + ++static int max9286_g_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms) ++{ ++ return 0; ++} ++ ++static int max9286_s_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms) ++{ ++ struct max9286_priv *priv = v4l2_get_subdevdata(sd); ++ struct i2c_client *client = priv->client; ++ struct v4l2_captureparm *cp = &parms->parm.capture; ++ ++ if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) ++ return -EINVAL; ++ if (cp->extendedmode != 0) ++ return -EINVAL; ++ ++ if (priv->fps_denominator != cp->timeperframe.denominator || ++ priv->fps_numerator != cp->timeperframe.numerator) { ++ int f_period; ++ ++ f_period = priv->fsync_period * 30 * cp->timeperframe.numerator / cp->timeperframe.denominator; ++ reg8_write(client, 0x06, f_period & 0xff); ++ reg8_write(client, 0x07, (f_period >> 8) & 0xff); ++ reg8_write(client, 0x08, f_period >> 16); ++ ++ priv->fps_numerator = cp->timeperframe.numerator; ++ priv->fps_denominator = cp->timeperframe.denominator; ++ } ++ ++ return 0; ++} ++ ++static struct v4l2_subdev_video_ops max9286_video_ops = { ++ .g_parm = max9286_g_parm, ++ .s_parm = max9286_s_parm, ++}; ++ + static struct v4l2_subdev_ops max9286_subdev_ops = { + .core = &max9286_subdev_core_ops, ++ .video = &max9286_video_ops, + }; + + static int max9286_parse_dt(struct i2c_client *client) +@@ -926,6 +966,8 @@ static int max9286_probe(struct i2c_client *client, + priv->client = client; + atomic_set(&priv->use_count, 0); + priv->csi2_outord = 0xff; ++ priv->fps_numerator = 1; ++ priv->fps_denominator = 30; + + err = max9286_parse_dt(client); + if (err) +diff --git a/drivers/media/i2c/soc_camera/ti9x4.c b/drivers/media/i2c/soc_camera/ti9x4.c +index aa85d92..b671736 100644 +--- a/drivers/media/i2c/soc_camera/ti9x4.c ++++ b/drivers/media/i2c/soc_camera/ti9x4.c +@@ -32,6 +32,9 @@ struct ti9x4_priv { + int lanes; + int csi_rate; + const char *forwarding_mode; ++ int fs_time; ++ int fps_numerator; ++ int fps_denominator; + int is_coax; + int dvp_bus; + int dvp_lsb; +@@ -139,7 +142,6 @@ static void ti9x4_read_chipid(struct i2c_client *client) + static void ti9x4_initial_setup(struct i2c_client *client) + { + struct ti9x4_priv *priv = i2c_get_clientdata(client); +- int fs_time = 0; + + /* Initial setup */ + client->addr = priv->des_addr; /* TI9x4 I2C */ +@@ -175,20 +177,21 @@ static void ti9x4_initial_setup(struct i2c_client *client) + case 800: + case 400: + /* FrameSync setup for REFCLK=25MHz, FPS=30: period_counts=1/FPS/12mks=1/30/12e-6=2777 -> HI=2, LO=2775 */ +- fs_time = 2790; ++ priv->fs_time = 2790; + break; + case 1500: + /* FrameSync setup for REFCLK=23MHz, FPS=30: period_counts=1/FPS/13.043mks=1/30/13.043e-6=2556 -> HI=2, LO=2554 */ +- fs_time = 2570; ++ priv->fs_time = 2570; + break; + case 1450: + case 1100: + case 700: + case 350: + /* FrameSync setup for REFCLK=22.5MHz, FPS=30: period_counts=1/FPS/13.333mks=1/30/13.333e-6=2500 -> HI=2, LO=2498 */ +- fs_time = 2513; ++ priv->fs_time = 2513; + break; + default: ++ priv->fs_time = 0; + dev_err(&client->dev, "unsupported CSI rate %d\n", priv->csi_rate); + } + +@@ -213,8 +216,8 @@ static void ti9x4_initial_setup(struct i2c_client *client) + #else + reg8_write(client, 0x19, 2 >> 8); /* FrameSync high time MSB */ + reg8_write(client, 0x1a, 2 & 0xff); /* FrameSync high time LSB */ +- reg8_write(client, 0x1b, fs_time >> 8); /* FrameSync low time MSB */ +- reg8_write(client, 0x1c, fs_time & 0xff); /* FrameSync low time LSB */ ++ reg8_write(client, 0x1b, priv->fs_time >> 8); /* FrameSync low time MSB */ ++ reg8_write(client, 0x1c, priv->fs_time & 0xff); /* FrameSync low time LSB */ + reg8_write(client, 0x18, 0x01); /* Enable FrameSync, HI/LO mode, Frame clock from port0 */ + // reg8_write(client, 0x18, 0x80); /* Enable FrameSync, HI/LO mode, Frame clock from port0 */ + #endif +@@ -425,8 +428,45 @@ static struct v4l2_subdev_core_ops ti9x4_subdev_core_ops = { + .registered_async = ti9x4_registered_async, + }; + ++static int ti9x4_g_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms) ++{ ++ return 0; ++} ++ ++static int ti9x4_s_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms) ++{ ++ struct ti9x4_priv *priv = v4l2_get_subdevdata(sd); ++ struct i2c_client *client = priv->client; ++ struct v4l2_captureparm *cp = &parms->parm.capture; ++ ++ if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) ++ return -EINVAL; ++ if (cp->extendedmode != 0) ++ return -EINVAL; ++ ++ if (priv->fps_denominator != cp->timeperframe.denominator || ++ priv->fps_numerator != cp->timeperframe.numerator) { ++ int f_time; ++ ++ f_time = priv->fs_time * 30 * cp->timeperframe.numerator / cp->timeperframe.denominator; ++ reg8_write(client, 0x1b, f_time >> 8); /* FrameSync low time MSB */ ++ reg8_write(client, 0x1c, f_time & 0xff); /* FrameSync low time LSB */ ++ ++ priv->fps_denominator = cp->timeperframe.denominator; ++ priv->fps_numerator = cp->timeperframe.numerator; ++ } ++ ++ return 0; ++} ++ ++static struct v4l2_subdev_video_ops ti9x4_video_ops = { ++ .g_parm = ti9x4_g_parm, ++ .s_parm = ti9x4_s_parm, ++}; ++ + static struct v4l2_subdev_ops ti9x4_subdev_ops = { + .core = &ti9x4_subdev_core_ops, ++ .video = &ti9x4_video_ops, + }; + + static int ti9x4_parse_dt(struct i2c_client *client) +@@ -607,6 +647,8 @@ static int ti9x4_probe(struct i2c_client *client, + priv->des_addr = client->addr; + priv->client = client; + atomic_set(&priv->use_count, 0); ++ priv->fps_numerator = 1; ++ priv->fps_denominator = 30; + + err = ti9x4_parse_dt(client); + if (err) +-- +2.7.4 + |