// SPDX-License-Identifier: GPL-2.0-only /* * Copyright (C) 2021-2023 Digiteq Automotive * author: Martin Tuma <martin.tuma@digiteqautomotive.com> * * This module handles all the sysfs info/configuration that is related to the * v4l2 output devices.
*/
/* * Video source change may affect the buffer queue of ANY video input/output on * the card thus if any of the inputs/outputs is in use, we do not allow * the change. * * As we do not want to lock all the video devices at the same time, a two-stage * locking strategy is used. In addition to the video device locking there is * a global (PCI device) variable "io_reconfig" atomically checked/set when * the reconfiguration is running. All the video devices check the variable in * their queue_setup() functions and do not allow to start the queue when * the reconfiguration has started.
*/ static ssize_t video_source_store(struct device *dev, struct device_attribute *attr, constchar *buf, size_t count)
{ struct video_device *vdev = to_video_device(dev); struct mgb4_vout_dev *voutdev = video_get_drvdata(vdev); struct mgb4_dev *mgbdev = voutdev->mgbdev; struct mgb4_vin_dev *loopin_new = NULL, *loopin_old = NULL; unsignedlong val;
ssize_t ret;
u32 config; int i;
ret = kstrtoul(buf, 10, &val); if (ret) return ret; if (val > 3) return -EINVAL;
if (test_and_set_bit(0, &mgbdev->io_reconfig)) return -EBUSY;
ret = -EBUSY; for (i = 0; i < MGB4_VIN_DEVICES; i++) if (mgbdev->vin[i] && is_busy(&mgbdev->vin[i]->vdev)) goto end; for (i = 0; i < MGB4_VOUT_DEVICES; i++) if (mgbdev->vout[i] && is_busy(&mgbdev->vout[i]->vdev)) goto end;
return sprintf(buf, "%u\n", period ? MGB4_HW_FREQ / period : 0);
}
/* * Frame rate change is expected to be called on live streams. Video device * locking/queue check is not needed.
*/ static ssize_t frame_rate_store(struct device *dev, struct device_attribute *attr, constchar *buf,
size_t count)
{ struct video_device *vdev = to_video_device(dev); struct mgb4_vout_dev *voutdev = video_get_drvdata(vdev); unsignedlong val; 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_limit, limit);
/* * HSYNC width change is expected to be called on live streams. Video device * locking/queue check is not needed.
*/ static ssize_t hsync_width_store(struct device *dev, struct device_attribute *attr, constchar *buf,
size_t count)
{ struct video_device *vdev = to_video_device(dev); struct mgb4_vout_dev *voutdev = video_get_drvdata(vdev); unsignedlong val; int ret;
ret = kstrtoul(buf, 10, &val); if (ret) return ret; if (val > 0xFF) return -EINVAL;
mgb4_mask_reg(&voutdev->mgbdev->video, voutdev->config->regs.hsync,
0x00FF0000, val << 16);
/* * VSYNC vidth change is expected to be called on live streams. Video device * locking/queue check is not needed.
*/ static ssize_t vsync_width_store(struct device *dev, struct device_attribute *attr, constchar *buf,
size_t count)
{ struct video_device *vdev = to_video_device(dev); struct mgb4_vout_dev *voutdev = video_get_drvdata(vdev); unsignedlong val; int ret;
ret = kstrtoul(buf, 10, &val); if (ret) return ret; if (val > 0xFF) return -EINVAL;
mgb4_mask_reg(&voutdev->mgbdev->video, voutdev->config->regs.vsync,
0x00FF0000, val << 16);
/* * hback porch change is expected to be called on live streams. Video device * locking/queue check is not needed.
*/ static ssize_t hback_porch_store(struct device *dev, struct device_attribute *attr, constchar *buf,
size_t count)
{ struct video_device *vdev = to_video_device(dev); struct mgb4_vout_dev *voutdev = video_get_drvdata(vdev); unsignedlong val; int ret;
ret = kstrtoul(buf, 10, &val); if (ret) return ret; if (val > 0xFF) return -EINVAL;
mgb4_mask_reg(&voutdev->mgbdev->video, voutdev->config->regs.hsync,
0x0000FF00, val << 8);
/* * vback porch change is expected to be called on live streams. Video device * locking/queue check is not needed.
*/ static ssize_t vback_porch_store(struct device *dev, struct device_attribute *attr, constchar *buf,
size_t count)
{ struct video_device *vdev = to_video_device(dev); struct mgb4_vout_dev *voutdev = video_get_drvdata(vdev); unsignedlong val; int ret;
ret = kstrtoul(buf, 10, &val); if (ret) return ret; if (val > 0xFF) return -EINVAL;
mgb4_mask_reg(&voutdev->mgbdev->video, voutdev->config->regs.vsync,
0x0000FF00, val << 8);
/* * hfront porch change is expected to be called on live streams. Video device * locking/queue check is not needed.
*/ static ssize_t hfront_porch_store(struct device *dev, struct device_attribute *attr, constchar *buf, size_t count)
{ struct video_device *vdev = to_video_device(dev); struct mgb4_vout_dev *voutdev = video_get_drvdata(vdev); unsignedlong val; int ret;
ret = kstrtoul(buf, 10, &val); if (ret) return ret; if (val > 0xFF) return -EINVAL;
/* * vfront porch change is expected to be called on live streams. Video device * locking/queue check is not needed.
*/ static ssize_t vfront_porch_store(struct device *dev, struct device_attribute *attr, constchar *buf,
size_t count)
{ struct video_device *vdev = to_video_device(dev); struct mgb4_vout_dev *voutdev = video_get_drvdata(vdev); unsignedlong val; int ret;
ret = kstrtoul(buf, 10, &val); if (ret) return ret; if (val > 0xFF) return -EINVAL;
/* * HSYNC polarity change is expected to be called on live streams. Video device * locking/queue check is not needed.
*/ static ssize_t hsync_polarity_store(struct device *dev, struct device_attribute *attr, constchar *buf, size_t count)
{ struct video_device *vdev = to_video_device(dev); struct mgb4_vout_dev *voutdev = video_get_drvdata(vdev); unsignedlong val; int ret;
ret = kstrtoul(buf, 10, &val); if (ret) return ret; if (val > 1) return -EINVAL;
mgb4_mask_reg(&voutdev->mgbdev->video, voutdev->config->regs.hsync,
(1U << 31), val << 31);
/* * VSYNC polarity change is expected to be called on live streams. Video device * locking/queue check is not needed.
*/ static ssize_t vsync_polarity_store(struct device *dev, struct device_attribute *attr, constchar *buf, size_t count)
{ struct video_device *vdev = to_video_device(dev); struct mgb4_vout_dev *voutdev = video_get_drvdata(vdev); unsignedlong val; int ret;
ret = kstrtoul(buf, 10, &val); if (ret) return ret; if (val > 1) return -EINVAL;
mgb4_mask_reg(&voutdev->mgbdev->video, voutdev->config->regs.vsync,
(1U << 31), val << 31);
/* * DE polarity change is expected to be called on live streams. Video device * locking/queue check is not needed.
*/ static ssize_t de_polarity_store(struct device *dev, struct device_attribute *attr, constchar *buf,
size_t count)
{ struct video_device *vdev = to_video_device(dev); struct mgb4_vout_dev *voutdev = video_get_drvdata(vdev); unsignedlong val; int ret;
ret = kstrtoul(buf, 10, &val); if (ret) return ret; if (val > 1) return -EINVAL;
mgb4_mask_reg(&voutdev->mgbdev->video, voutdev->config->regs.vsync,
(1U << 30), val << 30);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.