From nobody Tue Dec 2 01:50:45 2025 Received: from mx.gpxsee.org (mx.gpxsee.org [37.205.14.76]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8F23D1EBA14; Thu, 20 Nov 2025 13:15:45 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=37.205.14.76 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763644549; cv=none; b=LvgQ7flh9nBKDzI/8VjkqScR2n98kqZPEFnwZ3miuMwnYZeOtqNytRIE1VziByphHfTEayj8b8/Dbbz2RSCybw1b4DfhvNBhOmouWNXX7foJpTomhAGJ8FMXfRG3kKC9+lt4KYnfiIkg+irSHP7YTTe3g5aYkzsP+B8CdhkqQ2E= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763644549; c=relaxed/simple; bh=+mPVpAouIO+JmxpJ8BK6t2Z/XXNxA452XiSeo01Kd/M=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=HTH8IccLAvQtFdjUrt9AmL7qZrmP+qdpn/9szvlWGzROwDqkr/EibuspaTfpbm+7FZoPkcCIUyOmE/pTfxmO6cmkg9IXAZQrrCw9VRZG08iO5/4Ff7bY0m6V8KYG0IXlRSXXisQ3r0xE9OUgTHvzR+ldQa1emw+HMKIlOiuTAE4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=gpxsee.org; spf=pass smtp.mailfrom=gpxsee.org; arc=none smtp.client-ip=37.205.14.76 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=gpxsee.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gpxsee.org Received: from mgb4.digiteq.red (unknown [62.77.71.229]) by mx.gpxsee.org (Postfix) with ESMTPSA id 5EACB31EBA; Thu, 20 Nov 2025 14:08:37 +0100 (CET) From: tumic@gpxsee.org To: Mauro Carvalho Chehab , Hans Verkuil Cc: linux-media@vger.kernel.org, linux-kernel@vger.kernel.org, =?UTF-8?q?Martin=20T=C5=AFma?= Subject: [PATCH v3 1/3] media: pci: mgb4: Add support for GMSL1 modules Date: Thu, 20 Nov 2025 14:08:25 +0100 Message-ID: <20251120130827.1882-2-tumic@gpxsee.org> X-Mailer: git-send-email 2.51.2 In-Reply-To: <20251120130827.1882-1-tumic@gpxsee.org> References: <20251120130827.1882-1-tumic@gpxsee.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable From: Martin T=C5=AFma Add support for GMSL1 modules. GMSL1 modules have 2 inputs, 2 outputs and require a separate FW (id #3). Signed-off-by: Martin T=C5=AFma --- drivers/media/pci/mgb4/mgb4_core.c | 22 ++++++-- drivers/media/pci/mgb4/mgb4_core.h | 9 ++-- drivers/media/pci/mgb4/mgb4_sysfs.h | 6 ++- drivers/media/pci/mgb4/mgb4_sysfs_in.c | 49 +++++++++++++---- drivers/media/pci/mgb4/mgb4_sysfs_out.c | 38 ++++++++++--- drivers/media/pci/mgb4/mgb4_vin.c | 72 ++++++++++++++++--------- drivers/media/pci/mgb4/mgb4_vout.c | 64 +++++++++++++++------- 7 files changed, 189 insertions(+), 71 deletions(-) diff --git a/drivers/media/pci/mgb4/mgb4_core.c b/drivers/media/pci/mgb4/mg= b4_core.c index 3ce6b717ca32..a7cb8dc50b53 100644 --- a/drivers/media/pci/mgb4/mgb4_core.c +++ b/drivers/media/pci/mgb4/mgb4_core.c @@ -381,6 +381,18 @@ static int get_serial_number(struct mgb4_dev *mgbdev) return 0; } =20 +static const char *module_type_str(struct mgb4_dev *mgbdev) +{ + if (MGB4_IS_FPDL3(mgbdev)) + return "FPDL3"; + else if (MGB4_IS_GMSL3(mgbdev)) + return "GMSL3"; + else if (MGB4_IS_GMSL1(mgbdev)) + return "GMSL1"; + else + return "UNKNOWN"; +} + static int get_module_version(struct mgb4_dev *mgbdev) { struct device *dev =3D &mgbdev->pdev->dev; @@ -402,19 +414,21 @@ static int get_module_version(struct mgb4_dev *mgbdev) } =20 mgbdev->module_version =3D ~((u32)version) & 0xff; - if (!(MGB4_IS_FPDL3(mgbdev) || MGB4_IS_GMSL(mgbdev))) { + if (!(MGB4_IS_FPDL3(mgbdev) || + MGB4_IS_GMSL3(mgbdev) || + MGB4_IS_GMSL1(mgbdev))) { dev_err(dev, "unknown module type\n"); return -EINVAL; } fw_version =3D mgb4_read_reg(&mgbdev->video, 0xC4) >> 24; if ((MGB4_IS_FPDL3(mgbdev) && fw_version !=3D 1) || - (MGB4_IS_GMSL(mgbdev) && fw_version !=3D 2)) { + (MGB4_IS_GMSL3(mgbdev) && fw_version !=3D 2) || + (MGB4_IS_GMSL1(mgbdev) && fw_version !=3D 3)) { dev_err(dev, "module/firmware type mismatch\n"); return -EINVAL; } =20 - dev_info(dev, "%s module detected\n", - MGB4_IS_FPDL3(mgbdev) ? "FPDL3" : "GMSL"); + dev_info(dev, "%s module detected\n", module_type_str(mgbdev)); =20 return 0; } diff --git a/drivers/media/pci/mgb4/mgb4_core.h b/drivers/media/pci/mgb4/mg= b4_core.h index cc24068400a2..06ef8bb44089 100644 --- a/drivers/media/pci/mgb4/mgb4_core.h +++ b/drivers/media/pci/mgb4/mgb4_core.h @@ -18,14 +18,17 @@ #define MGB4_VIN_DEVICES 2 #define MGB4_VOUT_DEVICES 2 =20 -#define MGB4_IS_GMSL(mgbdev) \ +#define MGB4_IS_GMSL1(mgbdev) \ + (((mgbdev)->module_version >> 4) =3D=3D 6) +#define MGB4_IS_GMSL3(mgbdev) \ ((((mgbdev)->module_version >> 4) >=3D 2) && \ (((mgbdev)->module_version >> 4) <=3D 4)) #define MGB4_IS_FPDL3(mgbdev) \ (((mgbdev)->module_version >> 4) =3D=3D 1) #define MGB4_HAS_VOUT(mgbdev) \ - ((((mgbdev)->module_version >> 4) >=3D 1) && \ - (((mgbdev)->module_version >> 4) <=3D 3)) + (((((mgbdev)->module_version >> 4) >=3D 1) && \ + (((mgbdev)->module_version >> 4) <=3D 3)) || \ + ((((mgbdev)->module_version >> 4) =3D=3D 6))) =20 struct mgb4_dma_channel { struct dma_chan *chan; diff --git a/drivers/media/pci/mgb4/mgb4_sysfs.h b/drivers/media/pci/mgb4/m= gb4_sysfs.h index 017d82c0624e..fa7fd232c2c2 100644 --- a/drivers/media/pci/mgb4/mgb4_sysfs.h +++ b/drivers/media/pci/mgb4/mgb4_sysfs.h @@ -11,8 +11,10 @@ =20 extern struct attribute *mgb4_pci_attrs[]; extern struct attribute *mgb4_fpdl3_in_attrs[]; -extern struct attribute *mgb4_gmsl_in_attrs[]; +extern struct attribute *mgb4_gmsl3_in_attrs[]; +extern struct attribute *mgb4_gmsl1_in_attrs[]; extern struct attribute *mgb4_fpdl3_out_attrs[]; -extern struct attribute *mgb4_gmsl_out_attrs[]; +extern struct attribute *mgb4_gmsl3_out_attrs[]; +extern struct attribute *mgb4_gmsl1_out_attrs[]; =20 #endif diff --git a/drivers/media/pci/mgb4/mgb4_sysfs_in.c b/drivers/media/pci/mgb= 4/mgb4_sysfs_in.c index 9626fa59e3d3..4cd4addcd0a5 100644 --- a/drivers/media/pci/mgb4/mgb4_sysfs_in.c +++ b/drivers/media/pci/mgb4/mgb4_sysfs_in.c @@ -36,10 +36,13 @@ static ssize_t oldi_lane_width_show(struct device *dev, u32 config; int ret; =20 - i2c_reg =3D MGB4_IS_GMSL(mgbdev) ? 0x1CE : 0x49; - i2c_mask =3D MGB4_IS_GMSL(mgbdev) ? 0x0E : 0x03; - i2c_single_val =3D MGB4_IS_GMSL(mgbdev) ? 0x00 : 0x02; - i2c_dual_val =3D MGB4_IS_GMSL(mgbdev) ? 0x0E : 0x00; + if (MGB4_IS_GMSL1(mgbdev)) + return sprintf(buf, "0\n"); + + i2c_reg =3D MGB4_IS_GMSL3(mgbdev) ? 0x1CE : 0x49; + i2c_mask =3D MGB4_IS_GMSL3(mgbdev) ? 0x0E : 0x03; + i2c_single_val =3D MGB4_IS_GMSL3(mgbdev) ? 0x00 : 0x02; + i2c_dual_val =3D MGB4_IS_GMSL3(mgbdev) ? 0x0E : 0x00; =20 mutex_lock(&mgbdev->i2c_lock); ret =3D mgb4_i2c_read_byte(&vindev->deser, i2c_reg); @@ -79,21 +82,24 @@ static ssize_t oldi_lane_width_store(struct device *dev, if (ret) return ret; =20 + if (MGB4_IS_GMSL1(mgbdev)) + return val ? -EINVAL : count; + switch (val) { case 0: /* single */ fpga_data =3D 0; - i2c_data =3D MGB4_IS_GMSL(mgbdev) ? 0x00 : 0x02; + i2c_data =3D MGB4_IS_GMSL3(mgbdev) ? 0x00 : 0x02; break; case 1: /* dual */ fpga_data =3D 1U << 9; - i2c_data =3D MGB4_IS_GMSL(mgbdev) ? 0x0E : 0x00; + i2c_data =3D MGB4_IS_GMSL3(mgbdev) ? 0x0E : 0x00; break; default: return -EINVAL; } =20 - i2c_reg =3D MGB4_IS_GMSL(mgbdev) ? 0x1CE : 0x49; - i2c_mask =3D MGB4_IS_GMSL(mgbdev) ? 0x0E : 0x03; + i2c_reg =3D MGB4_IS_GMSL3(mgbdev) ? 0x1CE : 0x49; + i2c_mask =3D MGB4_IS_GMSL3(mgbdev) ? 0x0E : 0x03; =20 mutex_lock(&mgbdev->i2c_lock); ret =3D mgb4_i2c_mask_byte(&vindev->deser, i2c_reg, i2c_mask, i2c_data); @@ -102,7 +108,7 @@ static ssize_t oldi_lane_width_store(struct device *dev, return -EIO; mgb4_mask_reg(&mgbdev->video, vindev->config->regs.config, 1U << 9, fpga_data); - if (MGB4_IS_GMSL(mgbdev)) { + if (MGB4_IS_GMSL3(mgbdev)) { /* reset input link */ mutex_lock(&mgbdev->i2c_lock); ret =3D mgb4_i2c_mask_byte(&vindev->deser, 0x10, 1U << 5, 1U << 5); @@ -745,7 +751,7 @@ struct attribute *mgb4_fpdl3_in_attrs[] =3D { NULL }; =20 -struct attribute *mgb4_gmsl_in_attrs[] =3D { +struct attribute *mgb4_gmsl3_in_attrs[] =3D { &dev_attr_input_id.attr, &dev_attr_link_status.attr, &dev_attr_stream_status.attr, @@ -770,3 +776,26 @@ struct attribute *mgb4_gmsl_in_attrs[] =3D { &dev_attr_gmsl_fec.attr, NULL }; + +struct attribute *mgb4_gmsl1_in_attrs[] =3D { + &dev_attr_input_id.attr, + &dev_attr_link_status.attr, + &dev_attr_stream_status.attr, + &dev_attr_video_width.attr, + &dev_attr_video_height.attr, + &dev_attr_hsync_status.attr, + &dev_attr_vsync_status.attr, + &dev_attr_oldi_lane_width.attr, + &dev_attr_color_mapping.attr, + &dev_attr_hsync_gap_length.attr, + &dev_attr_vsync_gap_length.attr, + &dev_attr_pclk_frequency.attr, + &dev_attr_hsync_width.attr, + &dev_attr_vsync_width.attr, + &dev_attr_hback_porch.attr, + &dev_attr_hfront_porch.attr, + &dev_attr_vback_porch.attr, + &dev_attr_vfront_porch.attr, + &dev_attr_frequency_range.attr, + NULL +}; diff --git a/drivers/media/pci/mgb4/mgb4_sysfs_out.c b/drivers/media/pci/mg= b4/mgb4_sysfs_out.c index 573aa61c69d4..5769f3ca6c2f 100644 --- a/drivers/media/pci/mgb4/mgb4_sysfs_out.c +++ b/drivers/media/pci/mgb4/mgb4_sysfs_out.c @@ -665,6 +665,7 @@ static ssize_t pclk_frequency_store(struct device *dev, { struct video_device *vdev =3D to_video_device(dev); struct mgb4_vout_dev *voutdev =3D video_get_drvdata(vdev); + struct mgb4_dev *mgbdev =3D voutdev->mgbdev; unsigned long val; int ret; unsigned int dp; @@ -679,14 +680,16 @@ static ssize_t pclk_frequency_store(struct device *de= v, return -EBUSY; } =20 - dp =3D (val > 50000) ? 1 : 0; + dp =3D (MGB4_IS_FPDL3(mgbdev) && val > 50000) ? 1 : 0; voutdev->freq =3D mgb4_cmt_set_vout_freq(voutdev, val >> dp) << dp; - - mgb4_mask_reg(&voutdev->mgbdev->video, voutdev->config->regs.config, - 0x10, dp << 4); - mutex_lock(&voutdev->mgbdev->i2c_lock); - ret =3D mgb4_i2c_mask_byte(&voutdev->ser, 0x4F, 1 << 6, ((~dp) & 1) << 6); - mutex_unlock(&voutdev->mgbdev->i2c_lock); + mgb4_mask_reg(&mgbdev->video, voutdev->config->regs.config, 0x10, + dp << 4); + if (MGB4_IS_FPDL3(mgbdev)) { + mutex_lock(&mgbdev->i2c_lock); + ret =3D mgb4_i2c_mask_byte(&voutdev->ser, 0x4F, 1 << 6, + ((~dp) & 1) << 6); + mutex_unlock(&mgbdev->i2c_lock); + } =20 mutex_unlock(voutdev->vdev.lock); =20 @@ -731,7 +734,7 @@ struct attribute *mgb4_fpdl3_out_attrs[] =3D { NULL }; =20 -struct attribute *mgb4_gmsl_out_attrs[] =3D { +struct attribute *mgb4_gmsl3_out_attrs[] =3D { &dev_attr_output_id.attr, &dev_attr_video_source.attr, &dev_attr_display_width.attr, @@ -739,3 +742,22 @@ struct attribute *mgb4_gmsl_out_attrs[] =3D { &dev_attr_frame_rate.attr, NULL }; + +struct attribute *mgb4_gmsl1_out_attrs[] =3D { + &dev_attr_output_id.attr, + &dev_attr_video_source.attr, + &dev_attr_display_width.attr, + &dev_attr_display_height.attr, + &dev_attr_frame_rate.attr, + &dev_attr_hsync_polarity.attr, + &dev_attr_vsync_polarity.attr, + &dev_attr_de_polarity.attr, + &dev_attr_pclk_frequency.attr, + &dev_attr_hsync_width.attr, + &dev_attr_vsync_width.attr, + &dev_attr_hback_porch.attr, + &dev_attr_hfront_porch.attr, + &dev_attr_vback_porch.attr, + &dev_attr_vfront_porch.attr, + NULL +}; diff --git a/drivers/media/pci/mgb4/mgb4_vin.c b/drivers/media/pci/mgb4/mgb= 4_vin.c index 4b38076486ff..be55491b52b2 100644 --- a/drivers/media/pci/mgb4/mgb4_vin.c +++ b/drivers/media/pci/mgb4/mgb4_vin.c @@ -32,7 +32,8 @@ #include "mgb4_vin.h" =20 ATTRIBUTE_GROUPS(mgb4_fpdl3_in); -ATTRIBUTE_GROUPS(mgb4_gmsl_in); +ATTRIBUTE_GROUPS(mgb4_gmsl3_in); +ATTRIBUTE_GROUPS(mgb4_gmsl1_in); =20 static const struct mgb4_vin_config vin_cfg[] =3D { {0, 0, 0, 6, {0x10, 0x00, 0x04, 0x08, 0x1C, 0x14, 0x18, 0x20, 0x24, 0x28,= 0xE8}}, @@ -44,23 +45,31 @@ static const struct i2c_board_info fpdl3_deser_info[] = =3D { {I2C_BOARD_INFO("deserializer2", 0x36)}, }; =20 -static const struct i2c_board_info gmsl_deser_info[] =3D { +static const struct i2c_board_info gmsl3_deser_info[] =3D { {I2C_BOARD_INFO("deserializer1", 0x4C)}, {I2C_BOARD_INFO("deserializer2", 0x2A)}, }; =20 +static const struct i2c_board_info gmsl1_deser_info[] =3D { + {I2C_BOARD_INFO("deserializer1", 0x2C)}, + {I2C_BOARD_INFO("deserializer2", 0x6C)}, +}; + static const struct mgb4_i2c_kv fpdl3_i2c[] =3D { {0x06, 0xFF, 0x04}, {0x07, 0xFF, 0x01}, {0x45, 0xFF, 0xE8}, {0x49, 0xFF, 0x00}, {0x34, 0xFF, 0x00}, {0x23, 0xFF, 0x00} }; =20 -static const struct mgb4_i2c_kv gmsl_i2c[] =3D { +static const struct mgb4_i2c_kv gmsl3_i2c[] =3D { {0x01, 0x03, 0x03}, {0x300, 0x0C, 0x0C}, {0x03, 0xC0, 0xC0}, {0x1CE, 0x0E, 0x0E}, {0x11, 0x05, 0x00}, {0x05, 0xC0, 0x40}, {0x307, 0x0F, 0x00}, {0xA0, 0x03, 0x00}, {0x3E0, 0x07, 0x07}, {0x308, 0x01, 0x01}, {0x10, 0x20, 0x20}, {0x300, 0x40, 0x40} }; =20 +static const struct mgb4_i2c_kv gmsl1_i2c[] =3D { +}; + static const struct v4l2_dv_timings_cap video_timings_cap =3D { .type =3D V4L2_DV_BT_656_1120, .bt =3D { @@ -796,22 +805,29 @@ static irqreturn_t err_handler(int irq, void *ctx) =20 static int deser_init(struct mgb4_vin_dev *vindev, int id) { - int rv, addr_size; - size_t values_count; - const struct mgb4_i2c_kv *values; - const struct i2c_board_info *info; + int rv, addr_size =3D 0; + size_t count =3D 0; + const struct mgb4_i2c_kv *values =3D NULL; + const struct i2c_board_info *info =3D NULL; struct device *dev =3D &vindev->mgbdev->pdev->dev; =20 - if (MGB4_IS_GMSL(vindev->mgbdev)) { - info =3D &gmsl_deser_info[id]; + if (MGB4_IS_GMSL3(vindev->mgbdev)) { + info =3D &gmsl3_deser_info[id]; addr_size =3D 16; - values =3D gmsl_i2c; - values_count =3D ARRAY_SIZE(gmsl_i2c); - } else { + values =3D gmsl3_i2c; + count =3D ARRAY_SIZE(gmsl3_i2c); + } else if (MGB4_IS_FPDL3(vindev->mgbdev)) { info =3D &fpdl3_deser_info[id]; addr_size =3D 8; values =3D fpdl3_i2c; - values_count =3D ARRAY_SIZE(fpdl3_i2c); + count =3D ARRAY_SIZE(fpdl3_i2c); + } else if (MGB4_IS_GMSL1(vindev->mgbdev)) { + info =3D &gmsl1_deser_info[id]; + addr_size =3D 8; + values =3D gmsl1_i2c; + count =3D ARRAY_SIZE(gmsl1_i2c); + } else { + return -EINVAL; } =20 rv =3D mgb4_i2c_init(&vindev->deser, vindev->mgbdev->i2c_adap, info, @@ -820,7 +836,7 @@ static int deser_init(struct mgb4_vin_dev *vindev, int = id) dev_err(dev, "failed to create deserializer\n"); return rv; } - rv =3D mgb4_i2c_configure(&vindev->deser, values, values_count); + rv =3D mgb4_i2c_configure(&vindev->deser, values, count); if (rv < 0) { dev_err(dev, "failed to configure deserializer\n"); goto err_i2c_dev; @@ -838,11 +854,12 @@ static void fpga_init(struct mgb4_vin_dev *vindev) { struct mgb4_regs *video =3D &vindev->mgbdev->video; const struct mgb4_vin_regs *regs =3D &vindev->config->regs; + int dp =3D MGB4_IS_GMSL1(vindev->mgbdev) ? 0 : 1; =20 mgb4_write_reg(video, regs->config, 0x00000001); mgb4_write_reg(video, regs->sync, 0x03E80002); mgb4_write_reg(video, regs->padding, 0x00000000); - mgb4_write_reg(video, regs->config, 1U << 9); + mgb4_write_reg(video, regs->config, dp << 9); } =20 static void create_debugfs(struct mgb4_vin_dev *vindev) @@ -890,10 +907,21 @@ static void create_debugfs(struct mgb4_vin_dev *vinde= v) #endif } =20 +static const struct attribute_group **module_groups(struct mgb4_dev *mgbde= v) +{ + if (MGB4_IS_FPDL3(mgbdev)) + return mgb4_fpdl3_in_groups; + else if (MGB4_IS_GMSL3(mgbdev)) + return mgb4_gmsl3_in_groups; + else if (MGB4_IS_GMSL1(mgbdev)) + return mgb4_gmsl1_in_groups; + else + return NULL; +} + struct mgb4_vin_dev *mgb4_vin_create(struct mgb4_dev *mgbdev, int id) { int rv; - const struct attribute_group **groups; struct mgb4_vin_dev *vindev; struct pci_dev *pdev =3D mgbdev->pdev; struct device *dev =3D &pdev->dev; @@ -914,14 +942,13 @@ struct mgb4_vin_dev *mgb4_vin_create(struct mgb4_dev = *mgbdev, int id) INIT_WORK(&vindev->dma_work, dma_transfer); INIT_WORK(&vindev->err_work, signal_change); =20 - /* IRQ callback */ + /* IRQ callbacks */ vin_irq =3D xdma_get_user_irq(mgbdev->xdev, vindev->config->vin_irq); rv =3D request_irq(vin_irq, vin_handler, 0, "mgb4-vin", vindev); if (rv) { dev_err(dev, "failed to register vin irq handler\n"); goto err_alloc; } - /* Error IRQ callback */ err_irq =3D xdma_get_user_irq(mgbdev->xdev, vindev->config->err_irq); rv =3D request_irq(err_irq, err_handler, 0, "mgb4-err", vindev); if (rv) { @@ -986,9 +1013,7 @@ struct mgb4_vin_dev *mgb4_vin_create(struct mgb4_dev *= mgbdev, int id) } =20 /* Module sysfs attributes */ - groups =3D MGB4_IS_GMSL(mgbdev) - ? mgb4_gmsl_in_groups : mgb4_fpdl3_in_groups; - rv =3D device_add_groups(&vindev->vdev.dev, groups); + rv =3D device_add_groups(&vindev->vdev.dev, module_groups(mgbdev)); if (rv) { dev_err(dev, "failed to create sysfs attributes\n"); goto err_video_dev; @@ -1014,7 +1039,6 @@ struct mgb4_vin_dev *mgb4_vin_create(struct mgb4_dev = *mgbdev, int id) =20 void mgb4_vin_free(struct mgb4_vin_dev *vindev) { - const struct attribute_group **groups; int vin_irq =3D xdma_get_user_irq(vindev->mgbdev->xdev, vindev->config->vin_irq); int err_irq =3D xdma_get_user_irq(vindev->mgbdev->xdev, @@ -1025,9 +1049,7 @@ void mgb4_vin_free(struct mgb4_vin_dev *vindev) free_irq(vin_irq, vindev); free_irq(err_irq, vindev); =20 - groups =3D MGB4_IS_GMSL(vindev->mgbdev) - ? mgb4_gmsl_in_groups : mgb4_fpdl3_in_groups; - device_remove_groups(&vindev->vdev.dev, groups); + device_remove_groups(&vindev->vdev.dev, module_groups(vindev->mgbdev)); =20 mgb4_i2c_free(&vindev->deser); video_unregister_device(&vindev->vdev); diff --git a/drivers/media/pci/mgb4/mgb4_vout.c b/drivers/media/pci/mgb4/mg= b4_vout.c index fd93fbbaf755..44e9565d4d06 100644 --- a/drivers/media/pci/mgb4/mgb4_vout.c +++ b/drivers/media/pci/mgb4/mgb4_vout.c @@ -25,7 +25,8 @@ #include "mgb4_vout.h" =20 ATTRIBUTE_GROUPS(mgb4_fpdl3_out); -ATTRIBUTE_GROUPS(mgb4_gmsl_out); +ATTRIBUTE_GROUPS(mgb4_gmsl3_out); +ATTRIBUTE_GROUPS(mgb4_gmsl1_out); =20 static const struct mgb4_vout_config vout_cfg[] =3D { {0, 0, 8, {0x78, 0x60, 0x64, 0x68, 0x74, 0x6C, 0x70, 0x7C, 0xE0}}, @@ -37,10 +38,18 @@ static const struct i2c_board_info fpdl3_ser_info[] =3D= { {I2C_BOARD_INFO("serializer2", 0x16)}, }; =20 +static const struct i2c_board_info gmsl1_ser_info[] =3D { + {I2C_BOARD_INFO("serializer1", 0x24)}, + {I2C_BOARD_INFO("serializer2", 0x22)}, +}; + static const struct mgb4_i2c_kv fpdl3_i2c[] =3D { {0x05, 0xFF, 0x04}, {0x06, 0xFF, 0x01}, {0xC2, 0xFF, 0x80} }; =20 +static const struct mgb4_i2c_kv gmsl1_i2c[] =3D { +}; + static const struct v4l2_dv_timings_cap video_timings_cap =3D { .type =3D V4L2_DV_BT_656_1120, .bt =3D { @@ -634,12 +643,24 @@ static irqreturn_t handler(int irq, void *ctx) =20 static int ser_init(struct mgb4_vout_dev *voutdev, int id) { - int rv; - const struct i2c_board_info *info =3D &fpdl3_ser_info[id]; struct mgb4_i2c_client *ser =3D &voutdev->ser; struct device *dev =3D &voutdev->mgbdev->pdev->dev; + const struct i2c_board_info *info =3D NULL; + const struct mgb4_i2c_kv *values =3D NULL; + size_t count =3D 0; + int rv; + + if (MGB4_IS_FPDL3(voutdev->mgbdev)) { + info =3D &fpdl3_ser_info[id]; + values =3D fpdl3_i2c; + count =3D ARRAY_SIZE(fpdl3_i2c); + } else if (MGB4_IS_GMSL1(voutdev->mgbdev)) { + info =3D &gmsl1_ser_info[id]; + values =3D gmsl1_i2c; + count =3D ARRAY_SIZE(gmsl1_i2c); + } =20 - if (MGB4_IS_GMSL(voutdev->mgbdev)) + if (!info) return 0; =20 rv =3D mgb4_i2c_init(ser, voutdev->mgbdev->i2c_adap, info, 8); @@ -647,7 +668,7 @@ static int ser_init(struct mgb4_vout_dev *voutdev, int = id) dev_err(dev, "failed to create serializer\n"); return rv; } - rv =3D mgb4_i2c_configure(ser, fpdl3_i2c, ARRAY_SIZE(fpdl3_i2c)); + rv =3D mgb4_i2c_configure(ser, values, count); if (rv < 0) { dev_err(dev, "failed to configure serializer\n"); goto err_i2c_dev; @@ -665,18 +686,19 @@ static void fpga_init(struct mgb4_vout_dev *voutdev) { struct mgb4_regs *video =3D &voutdev->mgbdev->video; const struct mgb4_vout_regs *regs =3D &voutdev->config->regs; + int dp =3D MGB4_IS_GMSL1(voutdev->mgbdev) ? 0 : 1; + u32 source =3D (voutdev->config->id + MGB4_VIN_DEVICES) << 2; =20 - mgb4_write_reg(video, regs->config, 0x00000011); + mgb4_write_reg(video, regs->config, 0x00000001); mgb4_write_reg(video, regs->resolution, (1280 << 16) | 640); mgb4_write_reg(video, regs->hsync, 0x00283232); mgb4_write_reg(video, regs->vsync, 0x40141F1E); mgb4_write_reg(video, regs->frame_limit, MGB4_HW_FREQ / 60); mgb4_write_reg(video, regs->padding, 0x00000000); =20 - voutdev->freq =3D mgb4_cmt_set_vout_freq(voutdev, 61150 >> 1) << 1; + voutdev->freq =3D mgb4_cmt_set_vout_freq(voutdev, 61150 >> dp) << dp; =20 - mgb4_write_reg(video, regs->config, - (voutdev->config->id + MGB4_VIN_DEVICES) << 2 | 1 << 4); + mgb4_write_reg(video, regs->config, source | dp << 4); } =20 static void create_debugfs(struct mgb4_vout_dev *voutdev) @@ -720,10 +742,21 @@ static void create_debugfs(struct mgb4_vout_dev *vout= dev) #endif } =20 +static const struct attribute_group **module_groups(struct mgb4_dev *mgbde= v) +{ + if (MGB4_IS_FPDL3(mgbdev)) + return mgb4_fpdl3_out_groups; + else if (MGB4_IS_GMSL3(mgbdev)) + return mgb4_gmsl3_out_groups; + else if (MGB4_IS_GMSL1(mgbdev)) + return mgb4_gmsl1_out_groups; + else + return NULL; +} + struct mgb4_vout_dev *mgb4_vout_create(struct mgb4_dev *mgbdev, int id) { int rv, irq; - const struct attribute_group **groups; struct mgb4_vout_dev *voutdev; struct pci_dev *pdev =3D mgbdev->pdev; struct device *dev =3D &pdev->dev; @@ -804,9 +837,7 @@ struct mgb4_vout_dev *mgb4_vout_create(struct mgb4_dev = *mgbdev, int id) } =20 /* Module sysfs attributes */ - groups =3D MGB4_IS_GMSL(mgbdev) - ? mgb4_gmsl_out_groups : mgb4_fpdl3_out_groups; - rv =3D device_add_groups(&voutdev->vdev.dev, groups); + rv =3D device_add_groups(&voutdev->vdev.dev, module_groups(mgbdev)); if (rv) { dev_err(dev, "failed to create sysfs attributes\n"); goto err_video_dev; @@ -830,15 +861,10 @@ struct mgb4_vout_dev *mgb4_vout_create(struct mgb4_de= v *mgbdev, int id) =20 void mgb4_vout_free(struct mgb4_vout_dev *voutdev) { - const struct attribute_group **groups; int irq =3D xdma_get_user_irq(voutdev->mgbdev->xdev, voutdev->config->irq= ); =20 free_irq(irq, voutdev); - - groups =3D MGB4_IS_GMSL(voutdev->mgbdev) - ? mgb4_gmsl_out_groups : mgb4_fpdl3_out_groups; - device_remove_groups(&voutdev->vdev.dev, groups); - + device_remove_groups(&voutdev->vdev.dev, module_groups(voutdev->mgbdev)); mgb4_i2c_free(&voutdev->ser); video_unregister_device(&voutdev->vdev); v4l2_device_unregister(&voutdev->v4l2dev); --=20 2.51.2 From nobody Tue Dec 2 01:50:45 2025 Received: from mx.gpxsee.org (mx.gpxsee.org [37.205.14.76]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8F33621257E; Thu, 20 Nov 2025 13:15:45 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=37.205.14.76 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763644548; cv=none; b=mgVz/f2qFuJuyY2eH8j3G/WtPyR1aQ19J1/MXg8equtUVRRE3fJ1SAkFyxEzaSJg5Ut8lTUt5q21AsA2q0rwHB28EOSxtIgxg/qjk9NvLDzWXuABq7DvxxgoDO1KV7sLUQCWLqb/r2r+G9j/mjqcMhIMD1XeEJa4/rDZcX80xq0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763644548; c=relaxed/simple; bh=4EnT5pVEonaN4L88qLB862FatgJev+Bn/qzfpnpxbp0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=uTK7bxprLAgn3gZn5o+bWd9kCWV71s98HvB2kGdz0CISv6DiZtgknHNBP1pJHpzHWd8yWJDDmeq30qYB9UU0C9BWK+dD4RJe2wDICw6m+xtvCboB/gABoZOnOTOKmLCrLIHt+rAjmAXoTZ5ck9+/tFPzbdEevfT0A7N8R0d+lFg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=gpxsee.org; spf=pass smtp.mailfrom=gpxsee.org; arc=none smtp.client-ip=37.205.14.76 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=gpxsee.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gpxsee.org Received: from mgb4.digiteq.red (unknown [62.77.71.229]) by mx.gpxsee.org (Postfix) with ESMTPSA id 6506734380; Thu, 20 Nov 2025 14:08:37 +0100 (CET) From: tumic@gpxsee.org To: Mauro Carvalho Chehab , Hans Verkuil Cc: linux-media@vger.kernel.org, linux-kernel@vger.kernel.org, =?UTF-8?q?Martin=20T=C5=AFma?= Subject: [PATCH v3 2/3] media: pci: mgb4: Add support for GMSL3 coaxial modules Date: Thu, 20 Nov 2025 14:08:26 +0100 Message-ID: <20251120130827.1882-3-tumic@gpxsee.org> X-Mailer: git-send-email 2.51.2 In-Reply-To: <20251120130827.1882-1-tumic@gpxsee.org> References: <20251120130827.1882-1-tumic@gpxsee.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable From: Martin T=C5=AFma Add support for GMSL3 modules with a coaxial interface, a variant of the already existing module with the id #4. The FW is the same as for all other GMSL3 modules. Signed-off-by: Martin T=C5=AFma --- drivers/media/pci/mgb4/mgb4_core.h | 7 +++++-- drivers/media/pci/mgb4/mgb4_vin.c | 27 +++++++++++++++++++++++---- 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/drivers/media/pci/mgb4/mgb4_core.h b/drivers/media/pci/mgb4/mg= b4_core.h index 06ef8bb44089..bfae75f30c7c 100644 --- a/drivers/media/pci/mgb4/mgb4_core.h +++ b/drivers/media/pci/mgb4/mgb4_core.h @@ -21,8 +21,11 @@ #define MGB4_IS_GMSL1(mgbdev) \ (((mgbdev)->module_version >> 4) =3D=3D 6) #define MGB4_IS_GMSL3(mgbdev) \ - ((((mgbdev)->module_version >> 4) >=3D 2) && \ - (((mgbdev)->module_version >> 4) <=3D 4)) + (((((mgbdev)->module_version >> 4) >=3D 2) && \ + (((mgbdev)->module_version >> 4) <=3D 4)) || \ + (((mgbdev)->module_version >> 4) =3D=3D 8)) +#define MGB4_IS_GMSL3C(mgbdev) \ + (((mgbdev)->module_version >> 4) =3D=3D 8) #define MGB4_IS_FPDL3(mgbdev) \ (((mgbdev)->module_version >> 4) =3D=3D 1) #define MGB4_HAS_VOUT(mgbdev) \ diff --git a/drivers/media/pci/mgb4/mgb4_vin.c b/drivers/media/pci/mgb4/mgb= 4_vin.c index be55491b52b2..e782db79686f 100644 --- a/drivers/media/pci/mgb4/mgb4_vin.c +++ b/drivers/media/pci/mgb4/mgb4_vin.c @@ -50,6 +50,11 @@ static const struct i2c_board_info gmsl3_deser_info[] = =3D { {I2C_BOARD_INFO("deserializer2", 0x2A)}, }; =20 +static const struct i2c_board_info gmsl3c_deser_info[] =3D { + {I2C_BOARD_INFO("deserializer1", 0x6A)}, + {I2C_BOARD_INFO("deserializer2", 0x6C)}, +}; + static const struct i2c_board_info gmsl1_deser_info[] =3D { {I2C_BOARD_INFO("deserializer1", 0x2C)}, {I2C_BOARD_INFO("deserializer2", 0x6C)}, @@ -67,6 +72,13 @@ static const struct mgb4_i2c_kv gmsl3_i2c[] =3D { {0x308, 0x01, 0x01}, {0x10, 0x20, 0x20}, {0x300, 0x40, 0x40} }; =20 +static const struct mgb4_i2c_kv gmsl3c_i2c[] =3D { + {0x01, 0x03, 0x02}, {0x300, 0x0C, 0x08}, {0x03, 0xC0, 0x00}, + {0x1CE, 0x0E, 0x0E}, {0x11, 0x05, 0x05}, {0x05, 0xC0, 0x40}, + {0x307, 0x0F, 0x00}, {0xA0, 0x03, 0x00}, {0x3E0, 0x07, 0x00}, + {0x308, 0x01, 0x00}, {0x10, 0x20, 0x20}, {0x300, 0x40, 0x40} +}; + static const struct mgb4_i2c_kv gmsl1_i2c[] =3D { }; =20 @@ -812,10 +824,17 @@ static int deser_init(struct mgb4_vin_dev *vindev, in= t id) struct device *dev =3D &vindev->mgbdev->pdev->dev; =20 if (MGB4_IS_GMSL3(vindev->mgbdev)) { - info =3D &gmsl3_deser_info[id]; - addr_size =3D 16; - values =3D gmsl3_i2c; - count =3D ARRAY_SIZE(gmsl3_i2c); + if (MGB4_IS_GMSL3C(vindev->mgbdev)) { + info =3D &gmsl3c_deser_info[id]; + addr_size =3D 16; + values =3D gmsl3c_i2c; + count =3D ARRAY_SIZE(gmsl3c_i2c); + } else { + info =3D &gmsl3_deser_info[id]; + addr_size =3D 16; + values =3D gmsl3_i2c; + count =3D ARRAY_SIZE(gmsl3_i2c); + } } else if (MGB4_IS_FPDL3(vindev->mgbdev)) { info =3D &fpdl3_deser_info[id]; addr_size =3D 8; --=20 2.51.2 From nobody Tue Dec 2 01:50:45 2025 Received: from mx.gpxsee.org (mx.gpxsee.org [37.205.14.76]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8F42022B8D0; Thu, 20 Nov 2025 13:15:45 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=37.205.14.76 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763644547; cv=none; b=OUbrKuq47GlIN8aGPa9nQbxIgj1BcEZjK5WFCf9f24iZJewDNvmgHkEsUieR2BrMYepCl6niOV1g9FOtVFJlFwzm6LLMYh//rSWGDrhg89dtAPkXnKuixvzR/oWvYEDkKjVME1YuQza2WTg7daPrQ7D277ydJbyYtc/7SQnk3QI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763644547; c=relaxed/simple; bh=rN2MIiZpEc7tvyZLRwdhaNJop8sP3ciBFaRBnYldgZg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=lodpOhwWkW15DpT7bxrWXeyCTtmaFD5Ywvm7OMZJSdXZhRvQ35WfFj/RUkzuV2IQx2awXdNtd38XRe2vQyJ7K/N27OUUCRmQOkXc3LjklW/IiUCI+aOZP/iif96Z5ETdwxCDI0H1qg1CJ2sVJqSTfR1wYCEjee6/vzk73enBEfs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=gpxsee.org; spf=pass smtp.mailfrom=gpxsee.org; arc=none smtp.client-ip=37.205.14.76 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=gpxsee.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gpxsee.org Received: from mgb4.digiteq.red (unknown [62.77.71.229]) by mx.gpxsee.org (Postfix) with ESMTPSA id 69AF434381; Thu, 20 Nov 2025 14:08:37 +0100 (CET) From: tumic@gpxsee.org To: Mauro Carvalho Chehab , Hans Verkuil Cc: linux-media@vger.kernel.org, linux-kernel@vger.kernel.org, =?UTF-8?q?Martin=20T=C5=AFma?= Subject: [PATCH v3 3/3] Documentation: admin-guide: media: mgb4: Add GMSL1 & GMSL3-coax modules info Date: Thu, 20 Nov 2025 14:08:27 +0100 Message-ID: <20251120130827.1882-4-tumic@gpxsee.org> X-Mailer: git-send-email 2.51.2 In-Reply-To: <20251120130827.1882-1-tumic@gpxsee.org> References: <20251120130827.1882-1-tumic@gpxsee.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable From: Martin T=C5=AFma Add the mgb4 GMSL1 and GMSL3-coax modules info. Signed-off-by: Martin T=C5=AFma --- Documentation/admin-guide/media/mgb4.rst | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/Documentation/admin-guide/media/mgb4.rst b/Documentation/admin= -guide/media/mgb4.rst index 5ac69b833a7a..0a8a56e837f7 100644 --- a/Documentation/admin-guide/media/mgb4.rst +++ b/Documentation/admin-guide/media/mgb4.rst @@ -31,9 +31,11 @@ Global (PCI card) parameters =20 | 0 - No module present | 1 - FPDL3 - | 2 - GMSL (one serializer, two daisy chained deserializers) - | 3 - GMSL (one serializer, two deserializers) - | 4 - GMSL (two deserializers with two daisy chain outputs) + | 2 - GMSL3 (one serializer, two daisy chained deserializers) + | 3 - GMSL3 (one serializer, two deserializers) + | 4 - GMSL3 (two deserializers with two daisy chain outputs) + | 6 - GMSL1 + | 8 - GMSL3 coax =20 **module_version** (R): Module version number. Zero in case of a missing module. @@ -42,7 +44,8 @@ Global (PCI card) parameters Firmware type. =20 | 1 - FPDL3 - | 2 - GMSL + | 2 - GMSL3 + | 3 - GMSL1 =20 **fw_version** (R): Firmware version number. --=20 2.51.2