mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-24 06:36:09 +07:00
5800571960
-----BEGIN PGP SIGNATURE----- iQFSBAABCAA8FiEEq68RxlopcLEwq+PEeb4+QwBBGIYFAlz8fAYeHHRvcnZhbGRz QGxpbnV4LWZvdW5kYXRpb24ub3JnAAoJEHm+PkMAQRiG1asH/3ySguxqtqL1MCBa 4/SZ37PHeWKMerfX6ZyJdgEqK3B+PWlmuLiOMNK5h2bPLzeQQQAmHU/mfKmpXqgB dHwUbG9yNnyUtTfsfRqAnCA6vpuw9Yb1oIzTCVQrgJLSWD0j7scBBvmzYqguOkto ThwigLUq3AILr8EfR4rh+GM+5Dn9OTEFAxwil9fPHQo7QoczwZxpURhScT6Co9TB DqLA3fvXbBvLs/CZy/S5vKM9hKzC+p39ApFTURvFPrelUVnythAM0dPDJg3pIn5u g+/+gDxDFa+7ANxvxO2ng1sJPDqJMeY/xmjJYlYyLpA33B7zLNk2vDHhAP06VTtr XCMhQ9s= =cb80 -----END PGP SIGNATURE----- Merge tag 'v5.2-rc4' into media/master There are some conflicts due to SPDX changes. We also have more patches being merged via media tree touching them. So, let's merge back from upstream and address those. Linux 5.2-rc4 * tag 'v5.2-rc4': (767 commits) Linux 5.2-rc4 MAINTAINERS: Karthikeyan Ramasubramanian is MIA i2c: xiic: Add max_read_len quirk lockref: Limit number of cmpxchg loop retries uaccess: add noop untagged_addr definition x86/insn-eval: Fix use-after-free access to LDT entry kbuild: use more portable 'command -v' for cc-cross-prefix s390/unwind: correct stack switching during unwind block, bfq: add weight symlink to the bfq.weight cgroup parameter cgroup: let a symlink too be created with a cftype file drm/nouveau/secboot/gp10[2467]: support newer FW to fix SEC2 failures on some boards drm/nouveau/secboot: enable loading of versioned LS PMU/SEC2 ACR msgqueue FW drm/nouveau/secboot: split out FW version-specific LS function pointers drm/nouveau/secboot: pass max supported FW version to LS load funcs drm/nouveau/core: support versioned firmware loading drm/nouveau/core: pass subdev into nvkm_firmware_get, rather than device block: free sched's request pool in blk_cleanup_queue pktgen: do not sleep with the thread lock held. net: mvpp2: Use strscpy to handle stat strings net: rds: fix memory leak in rds_ib_flush_mr_pool ... Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
214 lines
6.2 KiB
C
214 lines
6.2 KiB
C
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
/*
|
|
* drivers/media/radio/radio-si4713.c
|
|
*
|
|
* Platform Driver for Silicon Labs Si4713 FM Radio Transmitter:
|
|
*
|
|
* Copyright (c) 2008 Instituto Nokia de Tecnologia - INdT
|
|
* Contact: Eduardo Valentin <eduardo.valentin@nokia.com>
|
|
*/
|
|
|
|
#include <linux/kernel.h>
|
|
#include <linux/module.h>
|
|
#include <linux/init.h>
|
|
#include <linux/platform_device.h>
|
|
#include <linux/i2c.h>
|
|
#include <linux/videodev2.h>
|
|
#include <linux/slab.h>
|
|
#include <media/v4l2-device.h>
|
|
#include <media/v4l2-common.h>
|
|
#include <media/v4l2-ioctl.h>
|
|
#include <media/v4l2-fh.h>
|
|
#include <media/v4l2-ctrls.h>
|
|
#include <media/v4l2-event.h>
|
|
#include "si4713.h"
|
|
|
|
/* module parameters */
|
|
static int radio_nr = -1; /* radio device minor (-1 ==> auto assign) */
|
|
module_param(radio_nr, int, 0);
|
|
MODULE_PARM_DESC(radio_nr,
|
|
"Minor number for radio device (-1 ==> auto assign)");
|
|
|
|
MODULE_LICENSE("GPL v2");
|
|
MODULE_AUTHOR("Eduardo Valentin <eduardo.valentin@nokia.com>");
|
|
MODULE_DESCRIPTION("Platform driver for Si4713 FM Radio Transmitter");
|
|
MODULE_VERSION("0.0.1");
|
|
MODULE_ALIAS("platform:radio-si4713");
|
|
|
|
/* Driver state struct */
|
|
struct radio_si4713_device {
|
|
struct v4l2_device v4l2_dev;
|
|
struct video_device radio_dev;
|
|
struct mutex lock;
|
|
};
|
|
|
|
/* radio_si4713_fops - file operations interface */
|
|
static const struct v4l2_file_operations radio_si4713_fops = {
|
|
.owner = THIS_MODULE,
|
|
.open = v4l2_fh_open,
|
|
.release = v4l2_fh_release,
|
|
.poll = v4l2_ctrl_poll,
|
|
/* Note: locking is done at the subdev level in the i2c driver. */
|
|
.unlocked_ioctl = video_ioctl2,
|
|
};
|
|
|
|
/* Video4Linux Interface */
|
|
|
|
/* radio_si4713_querycap - query device capabilities */
|
|
static int radio_si4713_querycap(struct file *file, void *priv,
|
|
struct v4l2_capability *capability)
|
|
{
|
|
strscpy(capability->driver, "radio-si4713", sizeof(capability->driver));
|
|
strscpy(capability->card, "Silicon Labs Si4713 Modulator",
|
|
sizeof(capability->card));
|
|
strscpy(capability->bus_info, "platform:radio-si4713",
|
|
sizeof(capability->bus_info));
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* v4l2 ioctl call backs.
|
|
* we are just a wrapper for v4l2_sub_devs.
|
|
*/
|
|
static inline struct v4l2_device *get_v4l2_dev(struct file *file)
|
|
{
|
|
return &((struct radio_si4713_device *)video_drvdata(file))->v4l2_dev;
|
|
}
|
|
|
|
static int radio_si4713_g_modulator(struct file *file, void *p,
|
|
struct v4l2_modulator *vm)
|
|
{
|
|
return v4l2_device_call_until_err(get_v4l2_dev(file), 0, tuner,
|
|
g_modulator, vm);
|
|
}
|
|
|
|
static int radio_si4713_s_modulator(struct file *file, void *p,
|
|
const struct v4l2_modulator *vm)
|
|
{
|
|
return v4l2_device_call_until_err(get_v4l2_dev(file), 0, tuner,
|
|
s_modulator, vm);
|
|
}
|
|
|
|
static int radio_si4713_g_frequency(struct file *file, void *p,
|
|
struct v4l2_frequency *vf)
|
|
{
|
|
return v4l2_device_call_until_err(get_v4l2_dev(file), 0, tuner,
|
|
g_frequency, vf);
|
|
}
|
|
|
|
static int radio_si4713_s_frequency(struct file *file, void *p,
|
|
const struct v4l2_frequency *vf)
|
|
{
|
|
return v4l2_device_call_until_err(get_v4l2_dev(file), 0, tuner,
|
|
s_frequency, vf);
|
|
}
|
|
|
|
static long radio_si4713_default(struct file *file, void *p,
|
|
bool valid_prio, unsigned int cmd, void *arg)
|
|
{
|
|
return v4l2_device_call_until_err(get_v4l2_dev(file), 0, core,
|
|
ioctl, cmd, arg);
|
|
}
|
|
|
|
static struct v4l2_ioctl_ops radio_si4713_ioctl_ops = {
|
|
.vidioc_querycap = radio_si4713_querycap,
|
|
.vidioc_g_modulator = radio_si4713_g_modulator,
|
|
.vidioc_s_modulator = radio_si4713_s_modulator,
|
|
.vidioc_g_frequency = radio_si4713_g_frequency,
|
|
.vidioc_s_frequency = radio_si4713_s_frequency,
|
|
.vidioc_log_status = v4l2_ctrl_log_status,
|
|
.vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
|
|
.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
|
|
.vidioc_default = radio_si4713_default,
|
|
};
|
|
|
|
/* radio_si4713_vdev_template - video device interface */
|
|
static const struct video_device radio_si4713_vdev_template = {
|
|
.fops = &radio_si4713_fops,
|
|
.name = "radio-si4713",
|
|
.release = video_device_release_empty,
|
|
.ioctl_ops = &radio_si4713_ioctl_ops,
|
|
.vfl_dir = VFL_DIR_TX,
|
|
};
|
|
|
|
/* Platform driver interface */
|
|
/* radio_si4713_pdriver_probe - probe for the device */
|
|
static int radio_si4713_pdriver_probe(struct platform_device *pdev)
|
|
{
|
|
struct radio_si4713_platform_data *pdata = pdev->dev.platform_data;
|
|
struct radio_si4713_device *rsdev;
|
|
struct v4l2_subdev *sd;
|
|
int rval = 0;
|
|
|
|
if (!pdata) {
|
|
dev_err(&pdev->dev, "Cannot proceed without platform data.\n");
|
|
rval = -EINVAL;
|
|
goto exit;
|
|
}
|
|
|
|
rsdev = devm_kzalloc(&pdev->dev, sizeof(*rsdev), GFP_KERNEL);
|
|
if (!rsdev) {
|
|
dev_err(&pdev->dev, "Failed to alloc video device.\n");
|
|
rval = -ENOMEM;
|
|
goto exit;
|
|
}
|
|
mutex_init(&rsdev->lock);
|
|
|
|
rval = v4l2_device_register(&pdev->dev, &rsdev->v4l2_dev);
|
|
if (rval) {
|
|
dev_err(&pdev->dev, "Failed to register v4l2 device.\n");
|
|
goto exit;
|
|
}
|
|
|
|
sd = i2c_get_clientdata(pdata->subdev);
|
|
rval = v4l2_device_register_subdev(&rsdev->v4l2_dev, sd);
|
|
if (rval) {
|
|
dev_err(&pdev->dev, "Cannot get v4l2 subdevice\n");
|
|
goto unregister_v4l2_dev;
|
|
}
|
|
|
|
rsdev->radio_dev = radio_si4713_vdev_template;
|
|
rsdev->radio_dev.v4l2_dev = &rsdev->v4l2_dev;
|
|
rsdev->radio_dev.ctrl_handler = sd->ctrl_handler;
|
|
/* Serialize all access to the si4713 */
|
|
rsdev->radio_dev.lock = &rsdev->lock;
|
|
rsdev->radio_dev.device_caps = V4L2_CAP_MODULATOR | V4L2_CAP_RDS_OUTPUT;
|
|
video_set_drvdata(&rsdev->radio_dev, rsdev);
|
|
if (video_register_device(&rsdev->radio_dev, VFL_TYPE_RADIO, radio_nr)) {
|
|
dev_err(&pdev->dev, "Could not register video device.\n");
|
|
rval = -EIO;
|
|
goto unregister_v4l2_dev;
|
|
}
|
|
dev_info(&pdev->dev, "New device successfully probed\n");
|
|
|
|
goto exit;
|
|
|
|
unregister_v4l2_dev:
|
|
v4l2_device_unregister(&rsdev->v4l2_dev);
|
|
exit:
|
|
return rval;
|
|
}
|
|
|
|
/* radio_si4713_pdriver_remove - remove the device */
|
|
static int radio_si4713_pdriver_remove(struct platform_device *pdev)
|
|
{
|
|
struct v4l2_device *v4l2_dev = platform_get_drvdata(pdev);
|
|
struct radio_si4713_device *rsdev;
|
|
|
|
rsdev = container_of(v4l2_dev, struct radio_si4713_device, v4l2_dev);
|
|
video_unregister_device(&rsdev->radio_dev);
|
|
v4l2_device_unregister(&rsdev->v4l2_dev);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static struct platform_driver radio_si4713_pdriver = {
|
|
.driver = {
|
|
.name = "radio-si4713",
|
|
},
|
|
.probe = radio_si4713_pdriver_probe,
|
|
.remove = radio_si4713_pdriver_remove,
|
|
};
|
|
|
|
module_platform_driver(radio_si4713_pdriver);
|