linux_dsm_epyc7002/drivers/media/radio/si4713/radio-platform-si4713.c
Mauro Carvalho Chehab 5800571960 Linux 5.2-rc4
-----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>
2019-06-11 12:09:28 -04:00

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);