cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

vp27smpx.c (4534B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * vp27smpx - driver version 0.0.1
      4 *
      5 * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
      6 *
      7 * Based on a tvaudio patch from Takahiro Adachi <tadachi@tadachi-net.com>
      8 * and Kazuhiko Kawakami <kazz-0@mail.goo.ne.jp>
      9 */
     10
     11#include <linux/module.h>
     12#include <linux/types.h>
     13#include <linux/slab.h>
     14#include <linux/ioctl.h>
     15#include <linux/uaccess.h>
     16#include <linux/i2c.h>
     17#include <linux/videodev2.h>
     18#include <media/v4l2-device.h>
     19
     20MODULE_DESCRIPTION("vp27smpx driver");
     21MODULE_AUTHOR("Hans Verkuil");
     22MODULE_LICENSE("GPL");
     23
     24
     25/* ----------------------------------------------------------------------- */
     26
     27struct vp27smpx_state {
     28	struct v4l2_subdev sd;
     29	int radio;
     30	u32 audmode;
     31};
     32
     33static inline struct vp27smpx_state *to_state(struct v4l2_subdev *sd)
     34{
     35	return container_of(sd, struct vp27smpx_state, sd);
     36}
     37
     38static void vp27smpx_set_audmode(struct v4l2_subdev *sd, u32 audmode)
     39{
     40	struct vp27smpx_state *state = to_state(sd);
     41	struct i2c_client *client = v4l2_get_subdevdata(sd);
     42	u8 data[3] = { 0x00, 0x00, 0x04 };
     43
     44	switch (audmode) {
     45	case V4L2_TUNER_MODE_MONO:
     46	case V4L2_TUNER_MODE_LANG1:
     47		break;
     48	case V4L2_TUNER_MODE_STEREO:
     49	case V4L2_TUNER_MODE_LANG1_LANG2:
     50		data[1] = 0x01;
     51		break;
     52	case V4L2_TUNER_MODE_LANG2:
     53		data[1] = 0x02;
     54		break;
     55	}
     56
     57	if (i2c_master_send(client, data, sizeof(data)) != sizeof(data))
     58		v4l2_err(sd, "I/O error setting audmode\n");
     59	else
     60		state->audmode = audmode;
     61}
     62
     63static int vp27smpx_s_radio(struct v4l2_subdev *sd)
     64{
     65	struct vp27smpx_state *state = to_state(sd);
     66
     67	state->radio = 1;
     68	return 0;
     69}
     70
     71static int vp27smpx_s_std(struct v4l2_subdev *sd, v4l2_std_id norm)
     72{
     73	struct vp27smpx_state *state = to_state(sd);
     74
     75	state->radio = 0;
     76	return 0;
     77}
     78
     79static int vp27smpx_s_tuner(struct v4l2_subdev *sd, const struct v4l2_tuner *vt)
     80{
     81	struct vp27smpx_state *state = to_state(sd);
     82
     83	if (!state->radio)
     84		vp27smpx_set_audmode(sd, vt->audmode);
     85	return 0;
     86}
     87
     88static int vp27smpx_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
     89{
     90	struct vp27smpx_state *state = to_state(sd);
     91
     92	if (state->radio)
     93		return 0;
     94	vt->audmode = state->audmode;
     95	vt->capability = V4L2_TUNER_CAP_STEREO |
     96		V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2;
     97	vt->rxsubchans = V4L2_TUNER_SUB_MONO;
     98	return 0;
     99}
    100
    101static int vp27smpx_log_status(struct v4l2_subdev *sd)
    102{
    103	struct vp27smpx_state *state = to_state(sd);
    104
    105	v4l2_info(sd, "Audio Mode: %u%s\n", state->audmode,
    106			state->radio ? " (Radio)" : "");
    107	return 0;
    108}
    109
    110/* ----------------------------------------------------------------------- */
    111
    112static const struct v4l2_subdev_core_ops vp27smpx_core_ops = {
    113	.log_status = vp27smpx_log_status,
    114};
    115
    116static const struct v4l2_subdev_tuner_ops vp27smpx_tuner_ops = {
    117	.s_radio = vp27smpx_s_radio,
    118	.s_tuner = vp27smpx_s_tuner,
    119	.g_tuner = vp27smpx_g_tuner,
    120};
    121
    122static const struct v4l2_subdev_video_ops vp27smpx_video_ops = {
    123	.s_std = vp27smpx_s_std,
    124};
    125
    126static const struct v4l2_subdev_ops vp27smpx_ops = {
    127	.core = &vp27smpx_core_ops,
    128	.tuner = &vp27smpx_tuner_ops,
    129	.video = &vp27smpx_video_ops,
    130};
    131
    132/* ----------------------------------------------------------------------- */
    133
    134/* i2c implementation */
    135
    136/*
    137 * Generic i2c probe
    138 * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
    139 */
    140
    141static int vp27smpx_probe(struct i2c_client *client,
    142			  const struct i2c_device_id *id)
    143{
    144	struct vp27smpx_state *state;
    145	struct v4l2_subdev *sd;
    146
    147	/* Check if the adapter supports the needed features */
    148	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
    149		return -EIO;
    150
    151	v4l_info(client, "chip found @ 0x%x (%s)\n",
    152			client->addr << 1, client->adapter->name);
    153
    154	state = devm_kzalloc(&client->dev, sizeof(*state), GFP_KERNEL);
    155	if (state == NULL)
    156		return -ENOMEM;
    157	sd = &state->sd;
    158	v4l2_i2c_subdev_init(sd, client, &vp27smpx_ops);
    159	state->audmode = V4L2_TUNER_MODE_STEREO;
    160
    161	/* initialize vp27smpx */
    162	vp27smpx_set_audmode(sd, state->audmode);
    163	return 0;
    164}
    165
    166static int vp27smpx_remove(struct i2c_client *client)
    167{
    168	struct v4l2_subdev *sd = i2c_get_clientdata(client);
    169
    170	v4l2_device_unregister_subdev(sd);
    171	return 0;
    172}
    173
    174/* ----------------------------------------------------------------------- */
    175
    176static const struct i2c_device_id vp27smpx_id[] = {
    177	{ "vp27smpx", 0 },
    178	{ }
    179};
    180MODULE_DEVICE_TABLE(i2c, vp27smpx_id);
    181
    182static struct i2c_driver vp27smpx_driver = {
    183	.driver = {
    184		.name	= "vp27smpx",
    185	},
    186	.probe		= vp27smpx_probe,
    187	.remove		= vp27smpx_remove,
    188	.id_table	= vp27smpx_id,
    189};
    190
    191module_i2c_driver(vp27smpx_driver);