Skip to content

Commit 0a7f248

Browse files
tombapopcornmix
authored andcommitted
media: rp1: csi2: Use get_frame_desc to get CSI-2 VC and DT
Use get_frame_desc pad op for asking the CSI-2 VC and DT from the source device driver, instead of hardcoding to VC 0, and getting the DT from a formats table. To keep backward compatibility with sources that do not implement get_frame_desc, implement a fallback mechanism that always uses VC 0, and gets the DT from the formats table, based on the CSI2's sink pad's format. Signed-off-by: Tomi Valkeinen <[email protected]>
1 parent 862bb15 commit 0a7f248

File tree

3 files changed

+77
-4
lines changed

3 files changed

+77
-4
lines changed

drivers/media/platform/raspberrypi/rp1_cfe/cfe.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -838,7 +838,7 @@ static void cfe_start_channel(struct cfe_node *node)
838838
* this is handled by the CSI2 AUTO_ARM mode.
839839
*/
840840
csi2_start_channel(&cfe->csi2, cfe->fe_csi2_channel,
841-
fmt->csi_dt, CSI2_MODE_FE_STREAMING,
841+
CSI2_MODE_FE_STREAMING,
842842
true, false, width, height);
843843
csi2_set_buffer(&cfe->csi2, cfe->fe_csi2_channel, 0, 0, -1);
844844
pisp_fe_start(&cfe->fe);
@@ -872,7 +872,7 @@ static void cfe_start_channel(struct cfe_node *node)
872872
}
873873
}
874874
/* Unconditionally start this CSI2 channel. */
875-
csi2_start_channel(&cfe->csi2, node->id, fmt->csi_dt,
875+
csi2_start_channel(&cfe->csi2, node->id,
876876
mode,
877877
/* Auto arm */
878878
false,

drivers/media/platform/raspberrypi/rp1_cfe/csi2.c

Lines changed: 74 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -324,12 +324,84 @@ void csi2_set_compression(struct csi2_device *csi2, unsigned int channel,
324324
csi2_reg_write(csi2, CSI2_CH_COMP_CTRL(channel), compression);
325325
}
326326

327+
static int csi2_get_vc_dt_fallback(struct csi2_device *csi2,
328+
unsigned int channel, u8 *vc, u8 *dt)
329+
{
330+
struct v4l2_subdev *sd = &csi2->sd;
331+
struct v4l2_subdev_state *state;
332+
struct v4l2_mbus_framefmt *fmt;
333+
const struct cfe_fmt *cfe_fmt;
334+
335+
state = v4l2_subdev_get_locked_active_state(sd);
336+
337+
/* Without Streams API, the channel number matches the sink pad */
338+
fmt = v4l2_subdev_get_pad_format(sd, state, channel);
339+
if (!fmt)
340+
return -EINVAL;
341+
342+
cfe_fmt = find_format_by_code(fmt->code);
343+
if (!cfe_fmt)
344+
return -EINVAL;
345+
346+
*vc = 0;
347+
*dt = cfe_fmt->csi_dt;
348+
349+
return 0;
350+
}
351+
352+
static int csi2_get_vc_dt(struct csi2_device *csi2, unsigned int channel,
353+
u8 *vc, u8 *dt)
354+
{
355+
struct v4l2_mbus_frame_desc remote_desc;
356+
const struct media_pad *remote_pad;
357+
struct v4l2_subdev *source_sd;
358+
int ret;
359+
360+
/* Without Streams API, the channel number matches the sink pad */
361+
remote_pad = media_pad_remote_pad_first(&csi2->pad[channel]);
362+
if (!remote_pad)
363+
return -EPIPE;
364+
365+
source_sd = media_entity_to_v4l2_subdev(remote_pad->entity);
366+
367+
ret = v4l2_subdev_call(source_sd, pad, get_frame_desc,
368+
remote_pad->index, &remote_desc);
369+
if (ret == -ENOIOCTLCMD) {
370+
csi2_dbg("source does not support get_frame_desc, use fallback\n");
371+
return csi2_get_vc_dt_fallback(csi2, channel, vc, dt);
372+
} else if (ret) {
373+
csi2_err("Failed to get frame descriptor\n");
374+
return ret;
375+
}
376+
377+
if (remote_desc.type != V4L2_MBUS_FRAME_DESC_TYPE_CSI2) {
378+
csi2_err("Frame descriptor does not describe CSI-2 link");
379+
return -EINVAL;
380+
}
381+
382+
if (remote_desc.num_entries != 1) {
383+
csi2_err("Frame descriptor does not have a single entry");
384+
return -EINVAL;
385+
}
386+
387+
*vc = remote_desc.entry[0].bus.csi2.vc;
388+
*dt = remote_desc.entry[0].bus.csi2.dt;
389+
390+
return 0;
391+
}
392+
327393
void csi2_start_channel(struct csi2_device *csi2, unsigned int channel,
328-
u16 dt, enum csi2_mode mode, bool auto_arm,
394+
enum csi2_mode mode, bool auto_arm,
329395
bool pack_bytes, unsigned int width,
330396
unsigned int height)
331397
{
332398
u32 ctrl;
399+
int ret;
400+
u8 vc, dt;
401+
402+
ret = csi2_get_vc_dt(csi2, channel, &vc, &dt);
403+
if (ret)
404+
return;
333405

334406
csi2_dbg("%s [%u]\n", __func__, channel);
335407

@@ -369,6 +441,7 @@ void csi2_start_channel(struct csi2_device *csi2, unsigned int channel,
369441
csi2_reg_write(csi2, CSI2_CH_FRAME_SIZE(channel), 0);
370442
}
371443

444+
set_field(&ctrl, vc, VC_MASK);
372445
set_field(&ctrl, dt, DT_MASK);
373446
csi2_reg_write(csi2, CSI2_CH_CTRL(channel), ctrl);
374447
csi2->num_lines[channel] = height;

drivers/media/platform/raspberrypi/rp1_cfe/csi2.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ void csi2_set_compression(struct csi2_device *csi2, unsigned int channel,
7979
enum csi2_compression_mode mode, unsigned int shift,
8080
unsigned int offset);
8181
void csi2_start_channel(struct csi2_device *csi2, unsigned int channel,
82-
u16 dt, enum csi2_mode mode, bool auto_arm,
82+
enum csi2_mode mode, bool auto_arm,
8383
bool pack_bytes, unsigned int width,
8484
unsigned int height);
8585
void csi2_stop_channel(struct csi2_device *csi2, unsigned int channel);

0 commit comments

Comments
 (0)