[PATCH v5 3/4] media: mgb4: Fixed signal frame rate limit handling

From: tumic
Date: Fri Apr 26 2024 - 10:26:11 EST


From: Martin Tůma <martin.tuma@xxxxxxxxxxxxxxxxxxxxx>

Change the default DV timings for the outputs to produce a better signal less
"crippled" by the frame rate limiting. While the individual values are now
different, the resulting signal still matches the same default display as before.

Additionaly fix the corner case when the frame rate limit is set to zero causing
a "divide by zero" kernel panic.

Signed-off-by: Martin Tůma <martin.tuma@xxxxxxxxxxxxxxxxxxxxx>
---
drivers/media/pci/mgb4/mgb4_sysfs_out.c | 9 +++++----
drivers/media/pci/mgb4/mgb4_vout.c | 12 ++++++------
drivers/media/pci/mgb4/mgb4_vout.h | 2 +-
3 files changed, 12 insertions(+), 11 deletions(-)

diff --git a/drivers/media/pci/mgb4/mgb4_sysfs_out.c b/drivers/media/pci/mgb4/mgb4_sysfs_out.c
index f67ff2a48329..573aa61c69d4 100644
--- a/drivers/media/pci/mgb4/mgb4_sysfs_out.c
+++ b/drivers/media/pci/mgb4/mgb4_sysfs_out.c
@@ -229,9 +229,9 @@ static ssize_t frame_rate_show(struct device *dev,
struct video_device *vdev = to_video_device(dev);
struct mgb4_vout_dev *voutdev = video_get_drvdata(vdev);
u32 period = mgb4_read_reg(&voutdev->mgbdev->video,
- voutdev->config->regs.frame_period);
+ voutdev->config->regs.frame_limit);

- return sprintf(buf, "%u\n", MGB4_HW_FREQ / period);
+ return sprintf(buf, "%u\n", period ? MGB4_HW_FREQ / period : 0);
}

/*
@@ -245,14 +245,15 @@ static ssize_t frame_rate_store(struct device *dev,
struct video_device *vdev = to_video_device(dev);
struct mgb4_vout_dev *voutdev = video_get_drvdata(vdev);
unsigned long val;
- int ret;
+ int limit, ret;

ret = kstrtoul(buf, 10, &val);
if (ret)
return ret;

+ limit = val ? MGB4_HW_FREQ / val : 0;
mgb4_write_reg(&voutdev->mgbdev->video,
- voutdev->config->regs.frame_period, MGB4_HW_FREQ / val);
+ voutdev->config->regs.frame_limit, limit);

return count;
}
diff --git a/drivers/media/pci/mgb4/mgb4_vout.c b/drivers/media/pci/mgb4/mgb4_vout.c
index d98b6e87d71f..998edcbd9723 100644
--- a/drivers/media/pci/mgb4/mgb4_vout.c
+++ b/drivers/media/pci/mgb4/mgb4_vout.c
@@ -665,12 +665,12 @@ static void fpga_init(struct mgb4_vout_dev *voutdev)
mgb4_write_reg(video, regs->config, 0x00000011);
mgb4_write_reg(video, regs->resolution,
(DEFAULT_WIDTH << 16) | DEFAULT_HEIGHT);
- mgb4_write_reg(video, regs->hsync, 0x00102020);
- mgb4_write_reg(video, regs->vsync, 0x40020202);
- mgb4_write_reg(video, regs->frame_period, DEFAULT_PERIOD);
+ mgb4_write_reg(video, regs->hsync, 0x00283232);
+ mgb4_write_reg(video, regs->vsync, 0x40141F1E);
+ mgb4_write_reg(video, regs->frame_limit, DEFAULT_PERIOD);
mgb4_write_reg(video, regs->padding, 0x00000000);

- voutdev->freq = mgb4_cmt_set_vout_freq(voutdev, 70000 >> 1) << 1;
+ voutdev->freq = mgb4_cmt_set_vout_freq(voutdev, 61150 >> 1) << 1;

mgb4_write_reg(video, regs->config,
(voutdev->config->id + MGB4_VIN_DEVICES) << 2 | 1 << 4);
@@ -696,8 +696,8 @@ static void debugfs_init(struct mgb4_vout_dev *voutdev)
voutdev->regs[3].offset = voutdev->config->regs.hsync;
voutdev->regs[4].name = "VIDEO_PARAMS_2";
voutdev->regs[4].offset = voutdev->config->regs.vsync;
- voutdev->regs[5].name = "FRAME_PERIOD";
- voutdev->regs[5].offset = voutdev->config->regs.frame_period;
+ voutdev->regs[5].name = "FRAME_LIMIT";
+ voutdev->regs[5].offset = voutdev->config->regs.frame_limit;
voutdev->regs[6].name = "PADDING_PIXELS";
voutdev->regs[6].offset = voutdev->config->regs.padding;
if (has_timeperframe(video)) {
diff --git a/drivers/media/pci/mgb4/mgb4_vout.h b/drivers/media/pci/mgb4/mgb4_vout.h
index ab9b58b1deb7..adc8fe1e7ae6 100644
--- a/drivers/media/pci/mgb4/mgb4_vout.h
+++ b/drivers/media/pci/mgb4/mgb4_vout.h
@@ -19,7 +19,7 @@ struct mgb4_vout_regs {
u32 config;
u32 status;
u32 resolution;
- u32 frame_period;
+ u32 frame_limit;
u32 hsync;
u32 vsync;
u32 padding;
--
2.44.0