diff --git a/utils/cam-configs/am62.py b/utils/cam-configs/am62.py index 497caaa..584fd5b 100644 --- a/utils/cam-configs/am62.py +++ b/utils/cam-configs/am62.py @@ -159,5 +159,5 @@ ], } -def get_configs(): +def get_configs(**kwargs): return (configurations, ['cam0']) diff --git a/utils/cam-configs/am62a-fpd.py b/utils/cam-configs/am62a-fpd.py index 7e0a3bf..5678985 100644 --- a/utils/cam-configs/am62a-fpd.py +++ b/utils/cam-configs/am62a-fpd.py @@ -261,5 +261,5 @@ def gen_ub953_tpg(port): configurations['cam2-meta'] = gen_imx219_meta(2) configurations['cam3-meta'] = gen_imx219_meta(3) -def get_configs(): +def get_configs(**kwargs): return (configurations, ['cam0', 'cam1', 'cam2', 'cam3']) diff --git a/utils/cam-configs/debix-tpg.py b/utils/cam-configs/debix-tpg.py index 20fa54e..3a85a5b 100644 --- a/utils/cam-configs/debix-tpg.py +++ b/utils/cam-configs/debix-tpg.py @@ -72,5 +72,5 @@ ], } -def get_configs(): +def get_configs(**kwargs): return (configurations, ['cam0']) diff --git a/utils/cam-configs/debix.py b/utils/cam-configs/debix.py index 80cc712..f077d20 100644 --- a/utils/cam-configs/debix.py +++ b/utils/cam-configs/debix.py @@ -68,5 +68,5 @@ ], } -def get_configs(): +def get_configs(**kwargs): return (configurations, ['cam0']) diff --git a/utils/cam-configs/desky.py b/utils/cam-configs/desky.py index fc315f6..c9a053b 100644 --- a/utils/cam-configs/desky.py +++ b/utils/cam-configs/desky.py @@ -26,5 +26,5 @@ ], } -def get_configs(): +def get_configs(**kwargs): return (configurations, ['desky']) diff --git a/utils/cam-configs/dra76-fpd.py b/utils/cam-configs/dra76-fpd.py index 5555f4f..1b1bbc7 100644 --- a/utils/cam-configs/dra76-fpd.py +++ b/utils/cam-configs/dra76-fpd.py @@ -535,5 +535,5 @@ def gen_ub953_tpg(port): configurations['cam2-meta'] = gen_ov10635_meta(2) configurations['cam3-meta'] = gen_imx219_meta(3) -def get_configs(): +def get_configs(**kwargs): return (configurations, ['cam0', 'cam1', 'cam2']) diff --git a/utils/cam-configs/dra76-ov5640.py b/utils/cam-configs/dra76-ov5640.py index c58a322..db82388 100644 --- a/utils/cam-configs/dra76-ov5640.py +++ b/utils/cam-configs/dra76-ov5640.py @@ -57,5 +57,5 @@ ], } -def get_configs(): +def get_configs(**kwargs): return (configurations, ['ov5640']) diff --git a/utils/cam-configs/j7-ov5640.py b/utils/cam-configs/j7-ov5640.py index e8f0068..3e5a61b 100644 --- a/utils/cam-configs/j7-ov5640.py +++ b/utils/cam-configs/j7-ov5640.py @@ -42,5 +42,5 @@ ], } -def get_configs(): +def get_configs(**kwargs): return (configurations, ['ov5640']) diff --git a/utils/cam-configs/lappy.py b/utils/cam-configs/lappy.py index 1df22cf..9608534 100644 --- a/utils/cam-configs/lappy.py +++ b/utils/cam-configs/lappy.py @@ -25,5 +25,5 @@ ], } -def get_configs(): +def get_configs(**kwargs): return (configurations, ['lappy']) diff --git a/utils/cam-configs/loopback.py b/utils/cam-configs/loopback.py index 55b3ada..9d34fa9 100644 --- a/utils/cam-configs/loopback.py +++ b/utils/cam-configs/loopback.py @@ -20,5 +20,5 @@ ], } -def get_configs(): +def get_configs(**kwargs): return (configurations, ['cam0']) diff --git a/utils/cam-configs/rpi4.py b/utils/cam-configs/rpi4.py index 24853a0..ad59b1f 100644 --- a/utils/cam-configs/rpi4.py +++ b/utils/cam-configs/rpi4.py @@ -104,5 +104,5 @@ ], } -def get_configs(): +def get_configs(**kwargs): return (configurations, ['cam0']) diff --git a/utils/cam-configs/rpi5-fpd.py b/utils/cam-configs/rpi5-fpd.py index 1728720..10dda3d 100644 --- a/utils/cam-configs/rpi5-fpd.py +++ b/utils/cam-configs/rpi5-fpd.py @@ -246,5 +246,5 @@ def gen_ub953_tpg(port): configurations['cam0-tpg'] = gen_ub953_tpg(0) configurations['cam1-tpg'] = gen_ub953_tpg(1) -def get_configs(): +def get_configs(**kwargs): return (configurations, ['cam0']) diff --git a/utils/cam-configs/rpi5-gmsl.py b/utils/cam-configs/rpi5-gmsl.py index dabc4c7..028e908 100644 --- a/utils/cam-configs/rpi5-gmsl.py +++ b/utils/cam-configs/rpi5-gmsl.py @@ -1,9 +1,10 @@ import v4l2 import v4l2.uapi -USE_RAW_10=False +USE_RAW_10=True MEDIA_DEVICE_NAME = ('rp1-cfe', 'model') -DESER_NAME = 'max96724 6-0027' +CSI2_NAME = 'csi2' +DESER_REGEX = '(max96724|max9296a) [0-9]+-[a-f0-9]+' # Pixel @@ -37,10 +38,9 @@ fmt_tpg = (640, 480, v4l2.PixelFormats.BGR888) -def gen_imx219_pixel(cameras, port): +def gen_imx219_pixel(des_ent, des_src_pad, ch_index, cameras, port): sensor_ent = cameras[port][1] ser_ent = cameras[port][0] - des_ent = DESER_NAME return { 'media': MEDIA_DEVICE_NAME, @@ -75,30 +75,30 @@ def gen_imx219_pixel(cameras, port): { 'entity': des_ent, 'routing': [ - { 'src': (port, 0), 'dst': (6, port) }, + { 'src': (port, 0), 'dst': (des_src_pad, port) }, ], 'pads': [ { 'pad': (port, 0), 'fmt': mbus_fmt_imx219 }, - { 'pad': (6, port), 'fmt': mbus_fmt_imx219 }, + { 'pad': (des_src_pad, port), 'fmt': mbus_fmt_imx219 }, ], }, # CSI-2 RX { - 'entity': 'csi2', + 'entity': CSI2_NAME, 'routing': [ - { 'src': (0, port), 'dst': (1 + port, 0) }, + { 'src': (0, port), 'dst': (1 + ch_index, 0) }, ], 'pads': [ { 'pad': (0, port), 'fmt': mbus_fmt_imx219 }, - { 'pad': (1 + port, 0), 'fmt': mbus_fmt_imx219 }, + { 'pad': (1 + ch_index, 0), 'fmt': mbus_fmt_imx219 }, ], }, ], 'devices': [ { - 'entity': f'rp1-cfe-csi2-ch{port}', + 'entity': f'rp1-cfe-csi2-ch{ch_index}', 'fmt': fmt_pix, 'kms-format': v4l2.PixelFormats.RGB565, }, @@ -107,15 +107,14 @@ def gen_imx219_pixel(cameras, port): 'links': [ { 'src': (sensor_ent, 0), 'dst': (ser_ent, 0) }, { 'src': (ser_ent, 1), 'dst': (des_ent, port) }, - { 'src': (des_ent, 6), 'dst': ('csi2', 0) }, - { 'src': ('csi2', 1 + port), 'dst': (f'rp1-cfe-csi2-ch{port}', 0) }, + { 'src': (des_ent, des_src_pad), 'dst': (CSI2_NAME, 0) }, + { 'src': (CSI2_NAME, 1 + ch_index), 'dst': (f'rp1-cfe-csi2-ch{ch_index}', 0) }, ], } -def gen_imx219_meta(cameras, port): +def gen_imx219_meta(des_ent, des_src_pad, ch_index, cameras, port): sensor_ent = cameras[port][1] ser_ent = cameras[port][0] - des_ent = DESER_NAME return { 'media': MEDIA_DEVICE_NAME, @@ -148,30 +147,30 @@ def gen_imx219_meta(cameras, port): { 'entity': des_ent, 'routing': [ - { 'src': (port, 1), 'dst': (6, port + 4) }, + { 'src': (port, 1), 'dst': (des_src_pad, port + 4) }, ], 'pads': [ { 'pad': (port, 1), 'fmt': mbus_fmt_imx219_meta }, - { 'pad': (6, port + 4), 'fmt': mbus_fmt_imx219_meta }, + { 'pad': (des_src_pad, port + 4), 'fmt': mbus_fmt_imx219_meta }, ], }, # CSI-2 RX { - 'entity': 'csi2', + 'entity': CSI2_NAME, 'routing': [ - { 'src': (0, port + 4), 'dst': (1 + port + 2, 0) }, + { 'src': (0, port + 4), 'dst': (1 + ch_index, 0) }, ], 'pads': [ { 'pad': (0, port + 4), 'fmt': mbus_fmt_imx219_meta }, - { 'pad': (1 + port + 2, 0), 'fmt': mbus_fmt_imx219_meta }, + { 'pad': (1 + ch_index, 0), 'fmt': mbus_fmt_imx219_meta }, ], }, ], 'devices': [ { - 'entity': f'rp1-cfe-csi2-ch{port + 2}', + 'entity': f'rp1-cfe-csi2-ch{ch_index}', 'fmt': fmt_pix_imx219_meta, 'embedded': True, 'display': False, @@ -182,14 +181,12 @@ def gen_imx219_meta(cameras, port): 'links': [ { 'src': (sensor_ent, 0), 'dst': (ser_ent, 0) }, { 'src': (ser_ent, 1), 'dst': (des_ent, port) }, - { 'src': (des_ent, 6), 'dst': ('csi2', 0) }, - { 'src': ('csi2', 1 + port + 2), 'dst': (f'rp1-cfe-csi2-ch{port + 2}', 0) }, + { 'src': (des_ent, des_src_pad), 'dst': (CSI2_NAME, 0) }, + { 'src': (CSI2_NAME, 1 + ch_index), 'dst': (f'rp1-cfe-csi2-ch{ch_index}', 0) }, ], } -def gen_des_tpg(): - des_ent = DESER_NAME - +def gen_des_tpg(des_ent, des_src_pad, ch_index): return { 'media': MEDIA_DEVICE_NAME, @@ -198,43 +195,42 @@ def gen_des_tpg(): { 'entity': des_ent, 'routing': [ - { 'src': (8, 0), 'dst': (6, 0) }, + { 'src': (8, 0), 'dst': (des_src_pad, 0) }, ], 'pads': [ { 'pad': (8, 0), 'fmt': mbus_fmt_tpg }, - { 'pad': (6, 0), 'fmt': mbus_fmt_tpg }, + { 'pad': (des_src_pad, 0), 'fmt': mbus_fmt_tpg }, ], }, # CSI-2 RX { - 'entity': 'csi2', + 'entity': CSI2_NAME, 'routing': [ - { 'src': (0, 0), 'dst': (1, 0) }, + { 'src': (0, 0), 'dst': (1 + ch_index, 0) }, ], 'pads': [ { 'pad': (0, 0), 'fmt': mbus_fmt_tpg }, - { 'pad': (1, 0), 'fmt': mbus_fmt_tpg }, + { 'pad': (1 + ch_index, 0), 'fmt': mbus_fmt_tpg }, ], }, ], 'devices': [ { - 'entity': 'rp1-cfe-csi2-ch0', + 'entity': f'rp1-cfe-csi2-ch{ch_index}', 'fmt': fmt_tpg, }, ], 'links': [ - { 'src': (des_ent, 6), 'dst': ('csi2', 0) }, - { 'src': ('csi2', 1), 'dst': ('rp1-cfe-csi2-ch0', 0) }, + { 'src': (des_ent, des_src_pad), 'dst': (CSI2_NAME, 0) }, + { 'src': (CSI2_NAME, 1 + ch_index), 'dst': (f'rp1-cfe-csi2-ch{ch_index}', 0) }, ], } -def gen_ser_tpg(cameras, port): +def gen_ser_tpg(des_ent, des_src_pad, ch_index, cameras, port): ser_ent = cameras[port][0] - des_ent = DESER_NAME return { 'media': MEDIA_DEVICE_NAME, @@ -255,23 +251,23 @@ def gen_ser_tpg(cameras, port): { 'entity': des_ent, 'routing': [ - { 'src': (port, 0), 'dst': (6, port) }, + { 'src': (port, 0), 'dst': (des_src_pad, port) }, ], 'pads': [ { 'pad': (port, 0), 'fmt': mbus_fmt_tpg }, - { 'pad': (6, port), 'fmt': mbus_fmt_tpg }, + { 'pad': (des_src_pad, port), 'fmt': mbus_fmt_tpg }, ], }, # CSI-2 RX { - 'entity': 'csi2', + 'entity': CSI2_NAME, 'routing': [ - { 'src': (0, port), 'dst': (1 + port, 0) }, + { 'src': (0, port), 'dst': (1 + ch_index, 0) }, ], 'pads': [ { 'pad': (0, port), 'fmt': mbus_fmt_tpg }, - { 'pad': (1 + port, 0), 'fmt': mbus_fmt_tpg }, + { 'pad': (1 + ch_index, 0), 'fmt': mbus_fmt_tpg }, ], }, ], @@ -285,21 +281,32 @@ def gen_ser_tpg(cameras, port): 'links': [ { 'src': (ser_ent, 1), 'dst': (des_ent, port) }, - { 'src': (des_ent, 6), 'dst': ('csi2', 0) }, - { 'src': ('csi2', 1 + port), 'dst': (f'rp1-cfe-csi2-ch{port}', 0) }, + { 'src': (des_ent, des_src_pad), 'dst': (CSI2_NAME, 0) }, + { 'src': (CSI2_NAME, 1 + ch_index), 'dst': (f'rp1-cfe-csi2-ch{ch_index}', 0) }, ], } # Find serializers and sensors connected to the deserializer -def find_devices(mdev_name, deser_name): +def find_devices(mdev_name, deser_regex): md = v4l2.MediaDevice(*mdev_name) assert md - deser = md.find_entity(deser_name) + deser = md.find_entity(regex=deser_regex) assert deser + deser_src_pad = None + for p in deser.pads: + if p.is_source and len(p.links) == 1 and \ + p.links[0].sink.entity.name == CSI2_NAME: + deser_src_pad = p.index + break + assert deser_src_pad is not None + cameras = {} - for p in [p for p in deser.pads if p.index < 4]: + for p in deser.pads: + if not p.is_sink: + continue + if len(p.links) == 0: continue @@ -310,19 +317,34 @@ def find_devices(mdev_name, deser_name): cameras[p.index] = (ser.name, sensor.name) - return cameras + return deser.name, deser_src_pad, cameras -def get_configs(): - cameras = find_devices(MEDIA_DEVICE_NAME, DESER_NAME) +def get_configs(*, config_names, **kwargs): + des_name, des_src_pad, cameras = find_devices(MEDIA_DEVICE_NAME, DESER_REGEX) num_cameras = len(cameras) configurations = {} + ch_index = 0 for i in range(num_cameras): - configurations[f'cam{i}'] = gen_imx219_pixel(cameras, i) - configurations[f'cam{i}-meta'] = gen_imx219_meta(cameras, i) - configurations[f'ser{i}-tpg'] = gen_ser_tpg(cameras, i) + cam = f'cam{i}' + cam_meta = f'cam{i}-meta' + ser_tpg = f'ser{i}-tpg' + + if cam in config_names: + configurations[cam] = gen_imx219_pixel(des_name, des_src_pad, ch_index, cameras, i) + ch_index += 1 + + if cam_meta in config_names: + configurations[cam_meta] = gen_imx219_meta(des_name, des_src_pad, ch_index, cameras, i) + ch_index += 1 + + if ser_tpg in config_names: + configurations[ser_tpg] = gen_ser_tpg(des_name, des_src_pad, ch_index, cameras, i) + ch_index += 1 - configurations['des-tpg'] = gen_des_tpg() + if 'des-tpg' in config_names: + configurations['des-tpg'] = gen_des_tpg(des_name, des_src_pad, ch_index) + ch_index += 1 - return (configurations, ['cam0']) + return (configurations, config_names) diff --git a/utils/cam-configs/rpi5.py b/utils/cam-configs/rpi5.py index 0f47b66..9050541 100644 --- a/utils/cam-configs/rpi5.py +++ b/utils/cam-configs/rpi5.py @@ -178,5 +178,5 @@ } -def get_configs(): +def get_configs(**kwargs): return (configurations, ['cam0']) diff --git a/utils/cam-configs/vimc.py b/utils/cam-configs/vimc.py index a3183d7..e8f2403 100644 --- a/utils/cam-configs/vimc.py +++ b/utils/cam-configs/vimc.py @@ -53,5 +53,5 @@ ], } -def get_configs(): +def get_configs(**kwargs): return (configurations, ['cam0']) diff --git a/utils/cam-configs/vivid.py b/utils/cam-configs/vivid.py index 1d95c52..3b21a25 100644 --- a/utils/cam-configs/vivid.py +++ b/utils/cam-configs/vivid.py @@ -21,5 +21,5 @@ ], } -def get_configs(): +def get_configs(**kwargs): return (configurations, ['cam0']) diff --git a/utils/cam-configs/xilinx-tpg.py b/utils/cam-configs/xilinx-tpg.py index 42834a8..85743b5 100644 --- a/utils/cam-configs/xilinx-tpg.py +++ b/utils/cam-configs/xilinx-tpg.py @@ -33,5 +33,5 @@ ], } -def get_configs(): +def get_configs(**kwargs): return (configurations, ['tpg']) diff --git a/utils/cam_helpers.py b/utils/cam_helpers.py index 7d7fecf..572c5af 100644 --- a/utils/cam_helpers.py +++ b/utils/cam_helpers.py @@ -112,9 +112,9 @@ def read_config(config_name, params): sys.path.append(os.path.dirname(os.path.abspath(__file__)) + '/cam-configs') if params: - configurations, default_configurations = importlib.import_module(config_file).get_configs(params) + configurations, default_configurations = importlib.import_module(config_file).get_configs(params=params, config_names=config_names) else: - configurations, default_configurations = importlib.import_module(config_file).get_configs() + configurations, default_configurations = importlib.import_module(config_file).get_configs(config_names=config_names) if len(config_names) == 0: config_names = default_configurations diff --git a/v4l2/media.py b/v4l2/media.py index 93fde81..cee8619 100644 --- a/v4l2/media.py +++ b/v4l2/media.py @@ -2,6 +2,7 @@ import ctypes import fcntl +import re import weakref import os import glob @@ -289,8 +290,14 @@ def interfaces(self): def find_id(self, id) -> MediaObject | None: return next((o for o in self.objects if o.id == id), None) - def find_entity(self, name): + def find_entity(self, name=None, regex=None): for e in self.entities: - if fnmatch.fnmatch(e.name, name): - return e + if name is not None and not fnmatch.fnmatch(e.name, name): + continue + + if regex is not None and re.match(regex, e.name) is None: + continue + + return e + return None