]> git.ipfire.org Git - thirdparty/openwrt.git/blob
7fef00f5d3d3adfc0bdf2f6d81fd204264ebe42f
[thirdparty/openwrt.git] /
1 From 01b54d6f1393f19c7a2676e5e443e0c96fb6ac38 Mon Sep 17 00:00:00 2001
2 From: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
3 Date: Thu, 21 Sep 2023 15:28:20 +0300
4 Subject: [PATCH 0778/1085] media: rp1: csi2: Use get_frame_desc to get CSI-2
5 VC and DT
6
7 Use get_frame_desc pad op for asking the CSI-2 VC and DT from the source
8 device driver, instead of hardcoding to VC 0, and getting the DT from a
9 formats table. To keep backward compatibility with sources that do not
10 implement get_frame_desc, implement a fallback mechanism that always
11 uses VC 0, and gets the DT from the formats table, based on the CSI2's
12 sink pad's format.
13
14 Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
15 ---
16 .../media/platform/raspberrypi/rp1_cfe/cfe.c | 4 +-
17 .../media/platform/raspberrypi/rp1_cfe/csi2.c | 75 ++++++++++++++++++-
18 .../media/platform/raspberrypi/rp1_cfe/csi2.h | 2 +-
19 3 files changed, 77 insertions(+), 4 deletions(-)
20
21 --- a/drivers/media/platform/raspberrypi/rp1_cfe/cfe.c
22 +++ b/drivers/media/platform/raspberrypi/rp1_cfe/cfe.c
23 @@ -838,7 +838,7 @@ static void cfe_start_channel(struct cfe
24 * this is handled by the CSI2 AUTO_ARM mode.
25 */
26 csi2_start_channel(&cfe->csi2, cfe->fe_csi2_channel,
27 - fmt->csi_dt, CSI2_MODE_FE_STREAMING,
28 + CSI2_MODE_FE_STREAMING,
29 true, false, width, height);
30 csi2_set_buffer(&cfe->csi2, cfe->fe_csi2_channel, 0, 0, -1);
31 pisp_fe_start(&cfe->fe);
32 @@ -872,7 +872,7 @@ static void cfe_start_channel(struct cfe
33 }
34 }
35 /* Unconditionally start this CSI2 channel. */
36 - csi2_start_channel(&cfe->csi2, node->id, fmt->csi_dt,
37 + csi2_start_channel(&cfe->csi2, node->id,
38 mode,
39 /* Auto arm */
40 false,
41 --- a/drivers/media/platform/raspberrypi/rp1_cfe/csi2.c
42 +++ b/drivers/media/platform/raspberrypi/rp1_cfe/csi2.c
43 @@ -324,12 +324,84 @@ void csi2_set_compression(struct csi2_de
44 csi2_reg_write(csi2, CSI2_CH_COMP_CTRL(channel), compression);
45 }
46
47 +static int csi2_get_vc_dt_fallback(struct csi2_device *csi2,
48 + unsigned int channel, u8 *vc, u8 *dt)
49 +{
50 + struct v4l2_subdev *sd = &csi2->sd;
51 + struct v4l2_subdev_state *state;
52 + struct v4l2_mbus_framefmt *fmt;
53 + const struct cfe_fmt *cfe_fmt;
54 +
55 + state = v4l2_subdev_get_locked_active_state(sd);
56 +
57 + /* Without Streams API, the channel number matches the sink pad */
58 + fmt = v4l2_subdev_get_pad_format(sd, state, channel);
59 + if (!fmt)
60 + return -EINVAL;
61 +
62 + cfe_fmt = find_format_by_code(fmt->code);
63 + if (!cfe_fmt)
64 + return -EINVAL;
65 +
66 + *vc = 0;
67 + *dt = cfe_fmt->csi_dt;
68 +
69 + return 0;
70 +}
71 +
72 +static int csi2_get_vc_dt(struct csi2_device *csi2, unsigned int channel,
73 + u8 *vc, u8 *dt)
74 +{
75 + struct v4l2_mbus_frame_desc remote_desc;
76 + const struct media_pad *remote_pad;
77 + struct v4l2_subdev *source_sd;
78 + int ret;
79 +
80 + /* Without Streams API, the channel number matches the sink pad */
81 + remote_pad = media_pad_remote_pad_first(&csi2->pad[channel]);
82 + if (!remote_pad)
83 + return -EPIPE;
84 +
85 + source_sd = media_entity_to_v4l2_subdev(remote_pad->entity);
86 +
87 + ret = v4l2_subdev_call(source_sd, pad, get_frame_desc,
88 + remote_pad->index, &remote_desc);
89 + if (ret == -ENOIOCTLCMD) {
90 + csi2_dbg("source does not support get_frame_desc, use fallback\n");
91 + return csi2_get_vc_dt_fallback(csi2, channel, vc, dt);
92 + } else if (ret) {
93 + csi2_err("Failed to get frame descriptor\n");
94 + return ret;
95 + }
96 +
97 + if (remote_desc.type != V4L2_MBUS_FRAME_DESC_TYPE_CSI2) {
98 + csi2_err("Frame descriptor does not describe CSI-2 link");
99 + return -EINVAL;
100 + }
101 +
102 + if (remote_desc.num_entries != 1) {
103 + csi2_err("Frame descriptor does not have a single entry");
104 + return -EINVAL;
105 + }
106 +
107 + *vc = remote_desc.entry[0].bus.csi2.vc;
108 + *dt = remote_desc.entry[0].bus.csi2.dt;
109 +
110 + return 0;
111 +}
112 +
113 void csi2_start_channel(struct csi2_device *csi2, unsigned int channel,
114 - u16 dt, enum csi2_mode mode, bool auto_arm,
115 + enum csi2_mode mode, bool auto_arm,
116 bool pack_bytes, unsigned int width,
117 unsigned int height)
118 {
119 u32 ctrl;
120 + int ret;
121 + u8 vc, dt;
122 +
123 + ret = csi2_get_vc_dt(csi2, channel, &vc, &dt);
124 + if (ret)
125 + return;
126
127 csi2_dbg("%s [%u]\n", __func__, channel);
128
129 @@ -369,6 +441,7 @@ void csi2_start_channel(struct csi2_devi
130 csi2_reg_write(csi2, CSI2_CH_FRAME_SIZE(channel), 0);
131 }
132
133 + set_field(&ctrl, vc, VC_MASK);
134 set_field(&ctrl, dt, DT_MASK);
135 csi2_reg_write(csi2, CSI2_CH_CTRL(channel), ctrl);
136 csi2->num_lines[channel] = height;
137 --- a/drivers/media/platform/raspberrypi/rp1_cfe/csi2.h
138 +++ b/drivers/media/platform/raspberrypi/rp1_cfe/csi2.h
139 @@ -79,7 +79,7 @@ void csi2_set_compression(struct csi2_de
140 enum csi2_compression_mode mode, unsigned int shift,
141 unsigned int offset);
142 void csi2_start_channel(struct csi2_device *csi2, unsigned int channel,
143 - u16 dt, enum csi2_mode mode, bool auto_arm,
144 + enum csi2_mode mode, bool auto_arm,
145 bool pack_bytes, unsigned int width,
146 unsigned int height);
147 void csi2_stop_channel(struct csi2_device *csi2, unsigned int channel);