* [RFC PATCH 0/2] Add support for Geniatech/MyGica A681B and PT682C USB ATSC/QAM TV tuners
@ 2025-10-01 5:15 Forest Crossman
2025-10-01 5:15 ` [RFC PATCH 1/2] media: mxl692: Add configurable crystal and MPEG settings Forest Crossman
2025-10-01 5:15 ` [RFC PATCH 2/2] media: dvb-usb-v2: Add support for Geniatech/MyGica A681B and PT682C Forest Crossman
0 siblings, 2 replies; 3+ messages in thread
From: Forest Crossman @ 2025-10-01 5:15 UTC (permalink / raw)
To: mchehab, linux-media; +Cc: Forest Crossman, linux-kernel
Hello, all,
This patch series adds support for the Geniatech/MyGica A681B and
PT682C, which are USB TV tuners that support ATSC/QAM. These devices
both use the MxL692 combo tuner+demodulator IC, so adding support for
them only required adding the USB IDs and modifying the existing MxL692
driver to take some configuration parameters from the drivers that use
it.
I've sent this series as an RFC for now because I wasn't really sure how
best to pass the clock and MPEG parameters from the USB device drivers
to the MxL692 driver. I ended up just adding some extra members to the
structs and copying the parameters to the MxL692 configuration on probe,
but this feels like the wrong approach. The only other ways I could
think of to do this were:
1. Making the mxl692 module aware of the TV tuners that use it by
storing the configurations for each TV tuner in the module and
selecting between them with an enum.
2. Including mxl692_defs.h in the TV tuner drivers that use the module
and initializing the xtal and mpeg structs directly.
But I wasn't sure which option would be best, or if there was another
way that I hadn't though of. If anyone has any suggestions on how best
to handle this, I'd be happy to hear them!
This is the first change I've made to a driver that's more than just a
handful of lines adding some device IDs, so I'd appreciate any advice I
can get. And if you have any questions, please let me know!
Thanks,
Forest
P.S.: I couldn't find the MxL692 firmware image anywhere, so I wrote a
script to extract it from the driver for Windows and have posted that
script here[1]. Also, for the sake of completeness there is a newer
firmware image embedded in the Geniatech/MyGica drivers for Ubuntu
20.04, but that firmware image didn't work with the mainline driver so I
haven't bothered to publish a script to extract it.
[1]: https://gist.github.com/cyrozap/f07a8b9803d2e9e3d0ee7acf54843ab0
Forest Crossman (2):
media: mxl692: Add configurable crystal and MPEG settings
media: dvb-usb-v2: Add support for Geniatech/MyGica A681B and PT682C
drivers/media/dvb-frontends/mxl692.c | 38 ++++++++++-----
drivers/media/dvb-frontends/mxl692.h | 19 ++++++++
drivers/media/usb/dvb-usb-v2/Kconfig | 1 +
drivers/media/usb/dvb-usb-v2/dvbsky.c | 69 +++++++++++++++++++++++++++
drivers/media/usb/em28xx/em28xx-dvb.c | 9 ++++
include/media/dvb-usb-ids.h | 2 +
6 files changed, 126 insertions(+), 12 deletions(-)
--
2.51.0
^ permalink raw reply [flat|nested] 3+ messages in thread
* [RFC PATCH 1/2] media: mxl692: Add configurable crystal and MPEG settings
2025-10-01 5:15 [RFC PATCH 0/2] Add support for Geniatech/MyGica A681B and PT682C USB ATSC/QAM TV tuners Forest Crossman
@ 2025-10-01 5:15 ` Forest Crossman
2025-10-01 5:15 ` [RFC PATCH 2/2] media: dvb-usb-v2: Add support for Geniatech/MyGica A681B and PT682C Forest Crossman
1 sibling, 0 replies; 3+ messages in thread
From: Forest Crossman @ 2025-10-01 5:15 UTC (permalink / raw)
To: mchehab, linux-media; +Cc: Forest Crossman, linux-kernel
Other devices that use the MxL692 need to be able to adjust these
parameters, so add them to the mxl692_config struct to make them
configurable.
Signed-off-by: Forest Crossman <cyrozap@gmail.com>
---
drivers/media/dvb-frontends/mxl692.c | 38 ++++++++++++++++++---------
drivers/media/dvb-frontends/mxl692.h | 19 ++++++++++++++
drivers/media/usb/em28xx/em28xx-dvb.c | 9 +++++++
3 files changed, 54 insertions(+), 12 deletions(-)
diff --git a/drivers/media/dvb-frontends/mxl692.c b/drivers/media/dvb-frontends/mxl692.c
index bbc2bc778225..9ecef72263f3 100644
--- a/drivers/media/dvb-frontends/mxl692.c
+++ b/drivers/media/dvb-frontends/mxl692.c
@@ -29,6 +29,9 @@ struct mxl692_dev {
int device_type;
int seqnum;
int init_done;
+ u8 xtal_calibration_enable;
+ u8 xtal_sharing_enable;
+ struct MXL_EAGLE_MPEGOUT_PARAMS_T mpeg_params;
};
static int mxl692_i2c_write(struct mxl692_dev *dev, u8 *buffer, u16 buf_len)
@@ -879,8 +882,8 @@ static int mxl692_init(struct dvb_frontend *fe)
xtal_config.xtal_cap = 26;
xtal_config.clk_out_div_enable = 0;
xtal_config.clk_out_enable = 0;
- xtal_config.xtal_calibration_enable = 0;
- xtal_config.xtal_sharing_enable = 1;
+ xtal_config.xtal_calibration_enable = dev->xtal_calibration_enable;
+ xtal_config.xtal_sharing_enable = dev->xtal_sharing_enable;
status = mxl692_config_xtal(dev, &xtal_config);
if (status)
goto err;
@@ -949,7 +952,7 @@ static int mxl692_set_frontend(struct dvb_frontend *fe)
int status = 0;
enum MXL_EAGLE_DEMOD_TYPE_E demod_type;
- struct MXL_EAGLE_MPEGOUT_PARAMS_T mpeg_params = {};
+ struct MXL_EAGLE_MPEGOUT_PARAMS_T mpeg_params = dev->mpeg_params;
enum MXL_EAGLE_QAM_DEMOD_ANNEX_TYPE_E qam_annex = MXL_EAGLE_QAM_DEMOD_ANNEX_B;
struct MXL_EAGLE_QAM_DEMOD_PARAMS_T qam_params = {};
struct MXL_EAGLE_TUNER_CHANNEL_PARAMS_T tuner_params = {};
@@ -994,15 +997,6 @@ static int mxl692_set_frontend(struct dvb_frontend *fe)
usleep_range(20 * 1000, 30 * 1000); /* was 500! */
- mpeg_params.mpeg_parallel = 0;
- mpeg_params.msb_first = MXL_EAGLE_DATA_SERIAL_MSB_1ST;
- mpeg_params.mpeg_sync_pulse_width = MXL_EAGLE_DATA_SYNC_WIDTH_BIT;
- mpeg_params.mpeg_valid_pol = MXL_EAGLE_CLOCK_POSITIVE;
- mpeg_params.mpeg_sync_pol = MXL_EAGLE_CLOCK_POSITIVE;
- mpeg_params.mpeg_clk_pol = MXL_EAGLE_CLOCK_NEGATIVE;
- mpeg_params.mpeg3wire_mode_enable = 0;
- mpeg_params.mpeg_clk_freq = MXL_EAGLE_MPEG_CLOCK_27MHZ;
-
switch (demod_type) {
case MXL_EAGLE_DEMOD_TYPE_ATSC:
status = mxl692_i2c_writeread(dev,
@@ -1321,6 +1315,26 @@ static int mxl692_probe(struct i2c_client *client)
goto err;
}
+ dev->xtal_calibration_enable = config->xtal_calibration_enable;
+ dev->xtal_sharing_enable = config->xtal_sharing_enable;
+
+ dev->mpeg_params.mpeg_parallel = config->mpeg_parallel;
+ dev->mpeg_params.msb_first = MXL_EAGLE_DATA_SERIAL_MSB_1ST;
+ dev->mpeg_params.mpeg_sync_pulse_width = config->mpeg_sync_pulse_width;
+ dev->mpeg_params.mpeg_valid_pol = MXL_EAGLE_CLOCK_POSITIVE;
+ dev->mpeg_params.mpeg_sync_pol = MXL_EAGLE_CLOCK_POSITIVE;
+ dev->mpeg_params.mpeg_clk_pol = MXL_EAGLE_CLOCK_NEGATIVE;
+ dev->mpeg_params.mpeg3wire_mode_enable = config->mpeg3wire_mode_enable;
+ dev->mpeg_params.mpeg_clk_freq = config->mpeg_clk_freq;
+ dev->mpeg_params.mpeg_pad_drv.pad_drv_mpeg_syn =
+ config->mpeg_pad_drv.pad_drv_mpeg_syn;
+ dev->mpeg_params.mpeg_pad_drv.pad_drv_mpeg_dat =
+ config->mpeg_pad_drv.pad_drv_mpeg_dat;
+ dev->mpeg_params.mpeg_pad_drv.pad_drv_mpeg_val =
+ config->mpeg_pad_drv.pad_drv_mpeg_val;
+ dev->mpeg_params.mpeg_pad_drv.pad_drv_mpeg_clk =
+ config->mpeg_pad_drv.pad_drv_mpeg_clk;
+
memcpy(&dev->fe.ops, &mxl692_ops, sizeof(struct dvb_frontend_ops));
dev->fe.demodulator_priv = dev;
dev->i2c_client = client;
diff --git a/drivers/media/dvb-frontends/mxl692.h b/drivers/media/dvb-frontends/mxl692.h
index 77764a047c07..5aee46480982 100644
--- a/drivers/media/dvb-frontends/mxl692.h
+++ b/drivers/media/dvb-frontends/mxl692.h
@@ -16,9 +16,28 @@
#define MXL692_FIRMWARE "dvb-demod-mxl692.fw"
+struct mxl692_mpeg_pad_drv_config {
+ u8 pad_drv_mpeg_syn;
+ u8 pad_drv_mpeg_dat;
+ u8 pad_drv_mpeg_val;
+ u8 pad_drv_mpeg_clk;
+};
+
struct mxl692_config {
unsigned char id;
u8 i2c_addr;
+
+ /* xtal config */
+ u8 xtal_calibration_enable;
+ u8 xtal_sharing_enable;
+
+ /* mpeg config */
+ u8 mpeg_parallel;
+ u8 mpeg_sync_pulse_width;
+ u8 mpeg3wire_mode_enable;
+ u8 mpeg_clk_freq;
+ struct mxl692_mpeg_pad_drv_config mpeg_pad_drv;
+
/*
* frontend
* returned by driver
diff --git a/drivers/media/usb/em28xx/em28xx-dvb.c b/drivers/media/usb/em28xx/em28xx-dvb.c
index 9fce59979e3b..738fd8df475c 100644
--- a/drivers/media/usb/em28xx/em28xx-dvb.c
+++ b/drivers/media/usb/em28xx/em28xx-dvb.c
@@ -1471,6 +1471,15 @@ static int em2874_dvb_init_hauppauge_usb_quadhd(struct em28xx *dev)
/* attach demod/tuner combo */
mxl692_config.id = (dev->ts == PRIMARY_TS) ? 0 : 1;
mxl692_config.fe = &dvb->fe[0];
+
+ mxl692_config.xtal_calibration_enable = 0;
+ mxl692_config.xtal_sharing_enable = 1;
+
+ mxl692_config.mpeg_parallel = 0;
+ mxl692_config.mpeg_sync_pulse_width = 0; /* BIT */
+ mxl692_config.mpeg3wire_mode_enable = 0;
+ mxl692_config.mpeg_clk_freq = 2; /* 27MHZ */
+
addr = (dev->ts == PRIMARY_TS) ? 0x60 : 0x63;
dvb->i2c_client_demod = dvb_module_probe("mxl692", NULL,
--
2.51.0
^ permalink raw reply [flat|nested] 3+ messages in thread
* [RFC PATCH 2/2] media: dvb-usb-v2: Add support for Geniatech/MyGica A681B and PT682C
2025-10-01 5:15 [RFC PATCH 0/2] Add support for Geniatech/MyGica A681B and PT682C USB ATSC/QAM TV tuners Forest Crossman
2025-10-01 5:15 ` [RFC PATCH 1/2] media: mxl692: Add configurable crystal and MPEG settings Forest Crossman
@ 2025-10-01 5:15 ` Forest Crossman
1 sibling, 0 replies; 3+ messages in thread
From: Forest Crossman @ 2025-10-01 5:15 UTC (permalink / raw)
To: mchehab, linux-media; +Cc: Forest Crossman, linux-kernel
These devices appear to be approximately the same hardware in different
packages. They both use the MxL692 combination tuner and demodulator,
and take roughly the same configuration parameters.
I say "roughly the same" because while the PT682C needs to have its
MxL692's MPEG clock polatity set to "negative" in order to show a
picture, the Windows driver for the A681B sets the clock polarity to
"positive", and the A681B seems to work regardless of what polarity it's
set to. So since setting the clock polarity to "negative" is necessary
for the PT682C, works for both the PT682C and the A681B, and appears to
be the "popular" configuration used by devices that use this chip, I've
left it set to "negative" for all devices.
Signed-off-by: Forest Crossman <cyrozap@gmail.com>
---
drivers/media/usb/dvb-usb-v2/Kconfig | 1 +
drivers/media/usb/dvb-usb-v2/dvbsky.c | 69 +++++++++++++++++++++++++++
include/media/dvb-usb-ids.h | 2 +
3 files changed, 72 insertions(+)
diff --git a/drivers/media/usb/dvb-usb-v2/Kconfig b/drivers/media/usb/dvb-usb-v2/Kconfig
index 4eadc9539b4c..02f8d5e2cf11 100644
--- a/drivers/media/usb/dvb-usb-v2/Kconfig
+++ b/drivers/media/usb/dvb-usb-v2/Kconfig
@@ -93,6 +93,7 @@ config DVB_USB_DVBSKY
tristate "DVBSky USB support"
depends on DVB_USB_V2
select DVB_M88DS3103 if MEDIA_SUBDRV_AUTOSELECT
+ select DVB_MXL692 if MEDIA_SUBDRV_AUTOSELECT
select DVB_SI2168 if MEDIA_SUBDRV_AUTOSELECT
select DVB_TS2020 if MEDIA_SUBDRV_AUTOSELECT
select MEDIA_TUNER_SI2157 if MEDIA_SUBDRV_AUTOSELECT
diff --git a/drivers/media/usb/dvb-usb-v2/dvbsky.c b/drivers/media/usb/dvb-usb-v2/dvbsky.c
index ceac0ea21dab..4281b0f74736 100644
--- a/drivers/media/usb/dvb-usb-v2/dvbsky.c
+++ b/drivers/media/usb/dvb-usb-v2/dvbsky.c
@@ -7,6 +7,7 @@
#include "dvb_usb.h"
#include "m88ds3103.h"
+#include "mxl692.h"
#include "ts2020.h"
#include "sp2.h"
#include "si2168.h"
@@ -576,6 +577,37 @@ static int dvbsky_mygica_t230c_attach(struct dvb_usb_adapter *adap)
return 0;
}
+static int dvbsky_mygica_mxl692_attach(struct dvb_usb_adapter *adap)
+{
+ struct dvbsky_state *state = adap_to_priv(adap);
+ struct dvb_usb_device *d = adap_to_d(adap);
+ struct mxl692_config mxl692_config = {};
+
+ /* attach demod/tuner combo */
+ mxl692_config.id = 0;
+ mxl692_config.fe = &adap->fe[0];
+
+ mxl692_config.xtal_calibration_enable = 1;
+ mxl692_config.xtal_sharing_enable = 0;
+
+ mxl692_config.mpeg_parallel = 1;
+ mxl692_config.mpeg_sync_pulse_width = 1; /* BYTE */
+ mxl692_config.mpeg3wire_mode_enable = 1;
+ mxl692_config.mpeg_clk_freq = 3; /* 13_5MHZ */
+ mxl692_config.mpeg_pad_drv.pad_drv_mpeg_syn = 3; /* 4X */
+ mxl692_config.mpeg_pad_drv.pad_drv_mpeg_dat = 3;
+ mxl692_config.mpeg_pad_drv.pad_drv_mpeg_val = 3;
+ mxl692_config.mpeg_pad_drv.pad_drv_mpeg_clk = 3;
+
+ state->i2c_client_demod = dvb_module_probe("mxl692", NULL,
+ &d->i2c_adap,
+ 0x60, &mxl692_config);
+ if (!state->i2c_client_demod)
+ return -ENODEV;
+
+ return 0;
+}
+
static int dvbsky_identify_state(struct dvb_usb_device *d, const char **name)
{
@@ -587,6 +619,11 @@ static int dvbsky_identify_state(struct dvb_usb_device *d, const char **name)
msleep(100);
dvbsky_gpio_ctrl(d, 0x80, 1);
msleep(50);
+ } else if (le16_to_cpu(d->udev->descriptor.idProduct) == USB_PID_MYGICA_A681B) {
+ dvbsky_gpio_ctrl(d, 0x80, 0);
+ msleep(100);
+ dvbsky_gpio_ctrl(d, 0x80, 1);
+ msleep(100);
} else {
dvbsky_gpio_ctrl(d, 0x04, 1);
msleep(20);
@@ -756,6 +793,32 @@ static struct dvb_usb_device_properties mygica_t230c_props = {
}
};
+static struct dvb_usb_device_properties mygica_mxl692_props = {
+ .driver_name = KBUILD_MODNAME,
+ .owner = THIS_MODULE,
+ .adapter_nr = adapter_nr,
+ .size_of_priv = sizeof(struct dvbsky_state),
+
+ .generic_bulk_ctrl_endpoint = 0x01,
+ .generic_bulk_ctrl_endpoint_response = 0x81,
+ .generic_bulk_ctrl_delay = DVBSKY_MSG_DELAY,
+
+ .i2c_algo = &dvbsky_i2c_algo,
+ .frontend_attach = dvbsky_mygica_mxl692_attach,
+ .frontend_detach = dvbsky_frontend_detach,
+ .init = dvbsky_init,
+ .get_rc_config = dvbsky_get_rc_config,
+ .streaming_ctrl = dvbsky_streaming_ctrl,
+ .identify_state = dvbsky_identify_state,
+
+ .num_adapters = 1,
+ .adapter = {
+ {
+ .stream = DVB_USB_STREAM_BULK(0x82, 8, 4096),
+ }
+ }
+};
+
static const struct usb_device_id dvbsky_id_table[] = {
{ DVB_USB_DEVICE(0x0572, 0x6831,
&dvbsky_s960_props, "DVBSky S960/S860", RC_MAP_DVBSKY) },
@@ -806,6 +869,12 @@ static const struct usb_device_id dvbsky_id_table[] = {
{ DVB_USB_DEVICE(USB_VID_CONEXANT, USB_PID_MYGICA_T230A,
&mygica_t230c_props, "MyGica Mini DVB-(T/T2/C) USB Stick T230A",
NULL) },
+ { DVB_USB_DEVICE(USB_VID_GTEK, USB_PID_MYGICA_A681B,
+ &mygica_mxl692_props, "MyGica ATSC/QAM HDTV USB Stick A681B",
+ NULL) },
+ { DVB_USB_DEVICE(USB_VID_GTEK, USB_PID_MYGICA_PT682C,
+ &mygica_mxl692_props, "MyGica ATSC/QAM HDTV USB Stick PT682C",
+ NULL) },
{ }
};
MODULE_DEVICE_TABLE(usb, dvbsky_id_table);
diff --git a/include/media/dvb-usb-ids.h b/include/media/dvb-usb-ids.h
index 1b7d10f3d4aa..0ce78daa3ef9 100644
--- a/include/media/dvb-usb-ids.h
+++ b/include/media/dvb-usb-ids.h
@@ -301,7 +301,9 @@
#define USB_PID_MSI_DIGI_VOX_MINI_III 0x8807
#define USB_PID_MSI_MEGASKY580 0x5580
#define USB_PID_MSI_MEGASKY580_55801 0x5581
+#define USB_PID_MYGICA_A681B 0x692f
#define USB_PID_MYGICA_D689 0xd811
+#define USB_PID_MYGICA_PT682C 0xe691
#define USB_PID_MYGICA_T230 0xc688
#define USB_PID_MYGICA_T230A 0x689a
#define USB_PID_MYGICA_T230C 0xc689
--
2.51.0
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2025-10-01 5:18 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-10-01 5:15 [RFC PATCH 0/2] Add support for Geniatech/MyGica A681B and PT682C USB ATSC/QAM TV tuners Forest Crossman
2025-10-01 5:15 ` [RFC PATCH 1/2] media: mxl692: Add configurable crystal and MPEG settings Forest Crossman
2025-10-01 5:15 ` [RFC PATCH 2/2] media: dvb-usb-v2: Add support for Geniatech/MyGica A681B and PT682C Forest Crossman
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®