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

ivtv-gpio.c (9766B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3    gpio functions.
      4    Merging GPIO support into driver:
      5    Copyright (C) 2004  Chris Kennedy <c@groovy.org>
      6    Copyright (C) 2005-2007  Hans Verkuil <hverkuil@xs4all.nl>
      7
      8 */
      9
     10#include "ivtv-driver.h"
     11#include "ivtv-cards.h"
     12#include "ivtv-gpio.h"
     13#include "xc2028.h"
     14#include <media/tuner.h>
     15#include <media/v4l2-ctrls.h>
     16
     17/*
     18 * GPIO assignment of Yuan MPG600/MPG160
     19 *
     20 *    bit 15  14  13  12 |  11  10   9   8 |   7   6   5   4 |   3   2   1   0
     21 * OUTPUT         IN1 IN0                                       AM3 AM2 AM1 AM0
     22 *  INPUT                   DM1         DM0
     23 *
     24 *   IN* : Input selection
     25 *          IN1 IN0
     26 *           1   1  N/A
     27 *           1   0  Line
     28 *           0   1  N/A
     29 *           0   0  Tuner
     30 *
     31 *   AM* : Audio Mode
     32 *          AM3  0: Normal        1: Mixed(Sub+Main channel)
     33 *          AM2  0: Subchannel    1: Main channel
     34 *          AM1  0: Stereo        1: Mono
     35 *          AM0  0: Normal        1: Mute
     36 *
     37 *   DM* : Detected tuner audio Mode
     38 *          DM1  0: Stereo        1: Mono
     39 *          DM0  0: Multiplex     1: Normal
     40 *
     41 * GPIO Initial Settings
     42 *           MPG600   MPG160
     43 *     DIR   0x3080   0x7080
     44 *  OUTPUT   0x000C   0x400C
     45 *
     46 *  Special thanks to Makoto Iguchi <iguchi@tahoo.org> and Mr. Anonymous
     47 *  for analyzing GPIO of MPG160.
     48 *
     49 *****************************************************************************
     50 *
     51 * GPIO assignment of Avermedia M179 (per information direct from AVerMedia)
     52 *
     53 *    bit 15  14  13  12 |  11  10   9   8 |   7   6   5   4 |   3   2   1   0
     54 * OUTPUT IN0 AM0 IN1               AM1 AM2       IN2     BR0   BR1
     55 *  INPUT
     56 *
     57 *   IN* : Input selection
     58 *          IN0 IN1 IN2
     59 *           *   1   *  Mute
     60 *           0   0   0  Line-In
     61 *           1   0   0  TV Tuner Audio
     62 *           0   0   1  FM Audio
     63 *           1   0   1  Mute
     64 *
     65 *   AM* : Audio Mode
     66 *          AM0 AM1 AM2
     67 *           0   0   0  TV Tuner Audio: L_OUT=(L+R)/2, R_OUT=SAP
     68 *           0   0   1  TV Tuner Audio: L_OUT=R_OUT=SAP   (SAP)
     69 *           0   1   0  TV Tuner Audio: L_OUT=L, R_OUT=R   (stereo)
     70 *           0   1   1  TV Tuner Audio: mute
     71 *           1   *   *  TV Tuner Audio: L_OUT=R_OUT=(L+R)/2   (mono)
     72 *
     73 *   BR* : Audio Sample Rate (BR stands for bitrate for some reason)
     74 *          BR0 BR1
     75 *           0   0   32 kHz
     76 *           0   1   44.1 kHz
     77 *           1   0   48 kHz
     78 *
     79 *   DM* : Detected tuner audio Mode
     80 *         Unknown currently
     81 *
     82 * Special thanks to AVerMedia Technologies, Inc. and Jiun-Kuei Jung at
     83 * AVerMedia for providing the GPIO information used to add support
     84 * for the M179 cards.
     85 */
     86
     87/********************* GPIO stuffs *********************/
     88
     89/* GPIO registers */
     90#define IVTV_REG_GPIO_IN    0x9008
     91#define IVTV_REG_GPIO_OUT   0x900c
     92#define IVTV_REG_GPIO_DIR   0x9020
     93
     94void ivtv_reset_ir_gpio(struct ivtv *itv)
     95{
     96	int curdir, curout;
     97
     98	if (itv->card->type != IVTV_CARD_PVR_150)
     99		return;
    100	IVTV_DEBUG_INFO("Resetting PVR150 IR\n");
    101	curout = read_reg(IVTV_REG_GPIO_OUT);
    102	curdir = read_reg(IVTV_REG_GPIO_DIR);
    103	curdir |= 0x80;
    104	write_reg(curdir, IVTV_REG_GPIO_DIR);
    105	curout = (curout & ~0xF) | 1;
    106	write_reg(curout, IVTV_REG_GPIO_OUT);
    107	/* We could use something else for smaller time */
    108	schedule_timeout_interruptible(msecs_to_jiffies(1));
    109	curout |= 2;
    110	write_reg(curout, IVTV_REG_GPIO_OUT);
    111	curdir &= ~0x80;
    112	write_reg(curdir, IVTV_REG_GPIO_DIR);
    113}
    114
    115/* Xceive tuner reset function */
    116int ivtv_reset_tuner_gpio(void *dev, int component, int cmd, int value)
    117{
    118	struct i2c_algo_bit_data *algo = dev;
    119	struct ivtv *itv = algo->data;
    120	u32 curout;
    121
    122	if (cmd != XC2028_TUNER_RESET)
    123		return 0;
    124	IVTV_DEBUG_INFO("Resetting tuner\n");
    125	curout = read_reg(IVTV_REG_GPIO_OUT);
    126	curout &= ~(1 << itv->card->xceive_pin);
    127	write_reg(curout, IVTV_REG_GPIO_OUT);
    128	schedule_timeout_interruptible(msecs_to_jiffies(1));
    129
    130	curout |= 1 << itv->card->xceive_pin;
    131	write_reg(curout, IVTV_REG_GPIO_OUT);
    132	schedule_timeout_interruptible(msecs_to_jiffies(1));
    133	return 0;
    134}
    135
    136static inline struct ivtv *sd_to_ivtv(struct v4l2_subdev *sd)
    137{
    138	return container_of(sd, struct ivtv, sd_gpio);
    139}
    140
    141static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
    142{
    143	return &container_of(ctrl->handler, struct ivtv, hdl_gpio)->sd_gpio;
    144}
    145
    146static int subdev_s_clock_freq(struct v4l2_subdev *sd, u32 freq)
    147{
    148	struct ivtv *itv = sd_to_ivtv(sd);
    149	u16 mask, data;
    150
    151	mask = itv->card->gpio_audio_freq.mask;
    152	switch (freq) {
    153	case 32000:
    154		data = itv->card->gpio_audio_freq.f32000;
    155		break;
    156	case 44100:
    157		data = itv->card->gpio_audio_freq.f44100;
    158		break;
    159	case 48000:
    160	default:
    161		data = itv->card->gpio_audio_freq.f48000;
    162		break;
    163	}
    164	if (mask)
    165		write_reg((read_reg(IVTV_REG_GPIO_OUT) & ~mask) | (data & mask), IVTV_REG_GPIO_OUT);
    166	return 0;
    167}
    168
    169static int subdev_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
    170{
    171	struct ivtv *itv = sd_to_ivtv(sd);
    172	u16 mask;
    173
    174	mask = itv->card->gpio_audio_detect.mask;
    175	if (mask == 0 || (read_reg(IVTV_REG_GPIO_IN) & mask))
    176		vt->rxsubchans = V4L2_TUNER_SUB_STEREO |
    177			V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
    178	else
    179		vt->rxsubchans = V4L2_TUNER_SUB_MONO;
    180	return 0;
    181}
    182
    183static int subdev_s_tuner(struct v4l2_subdev *sd, const struct v4l2_tuner *vt)
    184{
    185	struct ivtv *itv = sd_to_ivtv(sd);
    186	u16 mask, data;
    187
    188	mask = itv->card->gpio_audio_mode.mask;
    189	switch (vt->audmode) {
    190	case V4L2_TUNER_MODE_LANG1:
    191		data = itv->card->gpio_audio_mode.lang1;
    192		break;
    193	case V4L2_TUNER_MODE_LANG2:
    194		data = itv->card->gpio_audio_mode.lang2;
    195		break;
    196	case V4L2_TUNER_MODE_MONO:
    197		data = itv->card->gpio_audio_mode.mono;
    198		break;
    199	case V4L2_TUNER_MODE_STEREO:
    200	case V4L2_TUNER_MODE_LANG1_LANG2:
    201	default:
    202		data = itv->card->gpio_audio_mode.stereo;
    203		break;
    204	}
    205	if (mask)
    206		write_reg((read_reg(IVTV_REG_GPIO_OUT) & ~mask) | (data & mask), IVTV_REG_GPIO_OUT);
    207	return 0;
    208}
    209
    210static int subdev_s_radio(struct v4l2_subdev *sd)
    211{
    212	struct ivtv *itv = sd_to_ivtv(sd);
    213	u16 mask, data;
    214
    215	mask = itv->card->gpio_audio_input.mask;
    216	data = itv->card->gpio_audio_input.radio;
    217	if (mask)
    218		write_reg((read_reg(IVTV_REG_GPIO_OUT) & ~mask) | (data & mask), IVTV_REG_GPIO_OUT);
    219	return 0;
    220}
    221
    222static int subdev_s_audio_routing(struct v4l2_subdev *sd,
    223				  u32 input, u32 output, u32 config)
    224{
    225	struct ivtv *itv = sd_to_ivtv(sd);
    226	u16 mask, data;
    227
    228	if (input > 2)
    229		return -EINVAL;
    230	mask = itv->card->gpio_audio_input.mask;
    231	switch (input) {
    232	case 0:
    233		data = itv->card->gpio_audio_input.tuner;
    234		break;
    235	case 1:
    236		data = itv->card->gpio_audio_input.linein;
    237		break;
    238	case 2:
    239	default:
    240		data = itv->card->gpio_audio_input.radio;
    241		break;
    242	}
    243	if (mask)
    244		write_reg((read_reg(IVTV_REG_GPIO_OUT) & ~mask) | (data & mask), IVTV_REG_GPIO_OUT);
    245	return 0;
    246}
    247
    248static int subdev_s_ctrl(struct v4l2_ctrl *ctrl)
    249{
    250	struct v4l2_subdev *sd = to_sd(ctrl);
    251	struct ivtv *itv = sd_to_ivtv(sd);
    252	u16 mask, data;
    253
    254	switch (ctrl->id) {
    255	case V4L2_CID_AUDIO_MUTE:
    256		mask = itv->card->gpio_audio_mute.mask;
    257		data = ctrl->val ? itv->card->gpio_audio_mute.mute : 0;
    258		if (mask)
    259			write_reg((read_reg(IVTV_REG_GPIO_OUT) & ~mask) |
    260					(data & mask), IVTV_REG_GPIO_OUT);
    261		return 0;
    262	}
    263	return -EINVAL;
    264}
    265
    266
    267static int subdev_log_status(struct v4l2_subdev *sd)
    268{
    269	struct ivtv *itv = sd_to_ivtv(sd);
    270
    271	IVTV_INFO("GPIO status: DIR=0x%04x OUT=0x%04x IN=0x%04x\n",
    272			read_reg(IVTV_REG_GPIO_DIR), read_reg(IVTV_REG_GPIO_OUT),
    273			read_reg(IVTV_REG_GPIO_IN));
    274	v4l2_ctrl_handler_log_status(&itv->hdl_gpio, sd->name);
    275	return 0;
    276}
    277
    278static int subdev_s_video_routing(struct v4l2_subdev *sd,
    279				  u32 input, u32 output, u32 config)
    280{
    281	struct ivtv *itv = sd_to_ivtv(sd);
    282	u16 mask, data;
    283
    284	if (input > 2) /* 0:Tuner 1:Composite 2:S-Video */
    285		return -EINVAL;
    286	mask = itv->card->gpio_video_input.mask;
    287	if (input == 0)
    288		data = itv->card->gpio_video_input.tuner;
    289	else if (input == 1)
    290		data = itv->card->gpio_video_input.composite;
    291	else
    292		data = itv->card->gpio_video_input.svideo;
    293	if (mask)
    294		write_reg((read_reg(IVTV_REG_GPIO_OUT) & ~mask) | (data & mask), IVTV_REG_GPIO_OUT);
    295	return 0;
    296}
    297
    298static const struct v4l2_ctrl_ops gpio_ctrl_ops = {
    299	.s_ctrl = subdev_s_ctrl,
    300};
    301
    302static const struct v4l2_subdev_core_ops subdev_core_ops = {
    303	.log_status = subdev_log_status,
    304};
    305
    306static const struct v4l2_subdev_tuner_ops subdev_tuner_ops = {
    307	.s_radio = subdev_s_radio,
    308	.g_tuner = subdev_g_tuner,
    309	.s_tuner = subdev_s_tuner,
    310};
    311
    312static const struct v4l2_subdev_audio_ops subdev_audio_ops = {
    313	.s_clock_freq = subdev_s_clock_freq,
    314	.s_routing = subdev_s_audio_routing,
    315};
    316
    317static const struct v4l2_subdev_video_ops subdev_video_ops = {
    318	.s_routing = subdev_s_video_routing,
    319};
    320
    321static const struct v4l2_subdev_ops subdev_ops = {
    322	.core = &subdev_core_ops,
    323	.tuner = &subdev_tuner_ops,
    324	.audio = &subdev_audio_ops,
    325	.video = &subdev_video_ops,
    326};
    327
    328int ivtv_gpio_init(struct ivtv *itv)
    329{
    330	u16 pin = 0;
    331
    332	if (itv->card->xceive_pin)
    333		pin = 1 << itv->card->xceive_pin;
    334
    335	if ((itv->card->gpio_init.direction | pin) == 0)
    336		return 0;
    337
    338	IVTV_DEBUG_INFO("GPIO initial dir: %08x out: %08x\n",
    339		   read_reg(IVTV_REG_GPIO_DIR), read_reg(IVTV_REG_GPIO_OUT));
    340
    341	/* init output data then direction */
    342	write_reg(itv->card->gpio_init.initial_value | pin, IVTV_REG_GPIO_OUT);
    343	write_reg(itv->card->gpio_init.direction | pin, IVTV_REG_GPIO_DIR);
    344	v4l2_subdev_init(&itv->sd_gpio, &subdev_ops);
    345	snprintf(itv->sd_gpio.name, sizeof(itv->sd_gpio.name), "%s-gpio", itv->v4l2_dev.name);
    346	itv->sd_gpio.grp_id = IVTV_HW_GPIO;
    347	v4l2_ctrl_handler_init(&itv->hdl_gpio, 1);
    348	v4l2_ctrl_new_std(&itv->hdl_gpio, &gpio_ctrl_ops,
    349			V4L2_CID_AUDIO_MUTE, 0, 1, 1, 0);
    350	if (itv->hdl_gpio.error)
    351		return itv->hdl_gpio.error;
    352	itv->sd_gpio.ctrl_handler = &itv->hdl_gpio;
    353	v4l2_ctrl_handler_setup(&itv->hdl_gpio);
    354	return v4l2_device_register_subdev(&itv->v4l2_dev, &itv->sd_gpio);
    355}