1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
|
From a58b6fe91b46f2e06ad59e80768d5bf548d0b539 Mon Sep 17 00:00:00 2001
From: Vladimir Barinov <vladimir.barinov@cogentembedded.com>
Date: Thu, 13 Feb 2020 16:47:36 +0300
Subject: [PATCH] media: i2c: imx390: add fps setup
This adds FPS setup support on IMX390 imager
Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com>
---
drivers/media/i2c/soc_camera/imx390.c | 69 +++++++++++++++++++++++++++++++++--
drivers/media/i2c/soc_camera/imx390.h | 9 +++--
2 files changed, 72 insertions(+), 6 deletions(-)
diff --git a/drivers/media/i2c/soc_camera/imx390.c b/drivers/media/i2c/soc_camera/imx390.c
index 9d970b1..4f3d730 100644
--- a/drivers/media/i2c/soc_camera/imx390.c
+++ b/drivers/media/i2c/soc_camera/imx390.c
@@ -35,6 +35,8 @@ struct imx390_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];
int exposure;
@@ -46,6 +48,7 @@ struct imx390_priv {
int port;
int gpio_resetb;
int gpio_fsin;
+ int vts;
};
static inline struct imx390_priv *to_imx390(const struct i2c_client *client)
@@ -208,6 +211,62 @@ static int imx390_g_mbus_config(struct v4l2_subdev *sd,
return 0;
}
+static int imx390_g_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct imx390_priv *priv = to_imx390(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 imx390_s_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct imx390_priv *priv = to_imx390(client);
+ struct v4l2_captureparm *cp = &parms->parm.capture;
+ int ret = 0, timeout;
+ u8 val;
+
+ 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 = (IMX390_SENSOR_HEIGHT + 29) * 30 * cp->timeperframe.numerator / cp->timeperframe.denominator;
+
+ reg16_write(client, 0x0, 1);
+ for (timeout = 100; timeout > 0; timeout--) {
+ reg16_read(client, 0x5001, &val);
+ if (val == 1)
+ break;
+ mdelay(1);
+ }
+ if (!timeout)
+ dev_err(&client->dev, "timeout enter standby\n");
+
+ reg16_write(client, 0x2008, priv->vts & 0xff);
+ reg16_write(client, 0x2009, (priv->vts >> 8) & 0xff);
+ reg16_write(client, 0x200A, priv->vts >> 16);
+ ret = reg16_write(client, 0x0, 0);
+
+ priv->fps_numerator = cp->timeperframe.numerator;
+ priv->fps_denominator = cp->timeperframe.denominator;
+ }
+
+ return ret;
+}
+
#ifdef CONFIG_VIDEO_ADV_DEBUG
static int imx390_g_register(struct v4l2_subdev *sd,
struct v4l2_dbg_register *reg)
@@ -299,9 +358,9 @@ static int imx390_s_ctrl(struct v4l2_ctrl *ctrl)
break;
case V4L2_CID_EXPOSURE:
val = 0xfff - ctrl->val;
- ret = reg16_write(client, 0x0c, val); /* LSB */
- ret |= reg16_write(client, 0x0d, val >> 8);
-// ret |= reg16_write(client, 0x0e, ctrl->val >> 16); /* MSB */
+ reg16_write(client, 0x0c, val); /* LSB */
+ reg16_write(client, 0x0d, val >> 8);
+ ret = reg16_write(client, 0x0e, val >> 16); /* MSB */
break;
case V4L2_CID_HFLIP:
/* hflip */
@@ -349,6 +408,8 @@ static const struct v4l2_ctrl_ops imx390_ctrl_ops = {
static struct v4l2_subdev_video_ops imx390_video_ops = {
.s_stream = imx390_s_stream,
.g_mbus_config = imx390_g_mbus_config,
+ .g_parm = imx390_g_parm,
+ .s_parm = imx390_s_parm,
};
static const struct v4l2_subdev_pad_ops imx390_subdev_pad_ops = {
@@ -509,6 +570,8 @@ static int imx390_probe(struct i2c_client *client,
v4l2_i2c_subdev_init(&priv->sd, client, &imx390_subdev_ops);
priv->sd.flags = V4L2_SUBDEV_FL_HAS_DEVNODE;
+ priv->fps_numerator = 1;
+ priv->fps_denominator = 30;
priv->exposure = 0x100;
priv->gain = 0;
diff --git a/drivers/media/i2c/soc_camera/imx390.h b/drivers/media/i2c/soc_camera/imx390.h
index efd75a7..e9d9808 100644
--- a/drivers/media/i2c/soc_camera/imx390.h
+++ b/drivers/media/i2c/soc_camera/imx390.h
@@ -14,6 +14,9 @@
#define IMX390_MAX_WIDTH 1920
#define IMX390_MAX_HEIGHT 1080
+#define IMX390_SENSOR_WIDTH 1936
+#define IMX390_SENSOR_HEIGHT 1096
+
#define IMX390_DELAY 0xffff
#define IMX390_DT 0x2c /* MIPI Data Type RAW12 */
@@ -244,9 +247,9 @@ static const struct imx390_reg imx390_regs_wizard[] = {
{0x2002, 0x55},
{0x2003, 0x05},
{0x2004, 0x02},
-{0x2008, 0x65},
-{0x2009, 0x04},
-{0x200A, 0x00},
+{0x2008, (IMX390_SENSOR_HEIGHT + 29) & 0xff},
+{0x2009, ((IMX390_SENSOR_HEIGHT + 29) >> 8) & 0xff},
+{0x200A, (IMX390_SENSOR_HEIGHT + 29) >> 16},
{0x200C, 0x30},
{0x200D, 0x11},
{0x2010, 0x04},
--
2.7.4
|