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

vivid-radio-common.c (5196B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * vivid-radio-common.c - common radio rx/tx support functions.
      4 *
      5 * Copyright 2014 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
      6 */
      7
      8#include <linux/errno.h>
      9#include <linux/kernel.h>
     10#include <linux/delay.h>
     11#include <linux/videodev2.h>
     12
     13#include "vivid-core.h"
     14#include "vivid-ctrls.h"
     15#include "vivid-radio-common.h"
     16#include "vivid-rds-gen.h"
     17
     18/*
     19 * These functions are shared between the vivid receiver and transmitter
     20 * since both use the same frequency bands.
     21 */
     22
     23const struct v4l2_frequency_band vivid_radio_bands[TOT_BANDS] = {
     24	/* Band FM */
     25	{
     26		.type = V4L2_TUNER_RADIO,
     27		.index = 0,
     28		.capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO |
     29			      V4L2_TUNER_CAP_FREQ_BANDS,
     30		.rangelow   = FM_FREQ_RANGE_LOW,
     31		.rangehigh  = FM_FREQ_RANGE_HIGH,
     32		.modulation = V4L2_BAND_MODULATION_FM,
     33	},
     34	/* Band AM */
     35	{
     36		.type = V4L2_TUNER_RADIO,
     37		.index = 1,
     38		.capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_FREQ_BANDS,
     39		.rangelow   = AM_FREQ_RANGE_LOW,
     40		.rangehigh  = AM_FREQ_RANGE_HIGH,
     41		.modulation = V4L2_BAND_MODULATION_AM,
     42	},
     43	/* Band SW */
     44	{
     45		.type = V4L2_TUNER_RADIO,
     46		.index = 2,
     47		.capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_FREQ_BANDS,
     48		.rangelow   = SW_FREQ_RANGE_LOW,
     49		.rangehigh  = SW_FREQ_RANGE_HIGH,
     50		.modulation = V4L2_BAND_MODULATION_AM,
     51	},
     52};
     53
     54/*
     55 * Initialize the RDS generator. If we can loop, then the RDS generator
     56 * is set up with the values from the RDS TX controls, otherwise it
     57 * will fill in standard values using one of two alternates.
     58 */
     59void vivid_radio_rds_init(struct vivid_dev *dev)
     60{
     61	struct vivid_rds_gen *rds = &dev->rds_gen;
     62	bool alt = dev->radio_rx_rds_use_alternates;
     63
     64	/* Do nothing, blocks will be filled by the transmitter */
     65	if (dev->radio_rds_loop && !dev->radio_tx_rds_controls)
     66		return;
     67
     68	if (dev->radio_rds_loop) {
     69		v4l2_ctrl_lock(dev->radio_tx_rds_pi);
     70		rds->picode = dev->radio_tx_rds_pi->cur.val;
     71		rds->pty = dev->radio_tx_rds_pty->cur.val;
     72		rds->mono_stereo = dev->radio_tx_rds_mono_stereo->cur.val;
     73		rds->art_head = dev->radio_tx_rds_art_head->cur.val;
     74		rds->compressed = dev->radio_tx_rds_compressed->cur.val;
     75		rds->dyn_pty = dev->radio_tx_rds_dyn_pty->cur.val;
     76		rds->ta = dev->radio_tx_rds_ta->cur.val;
     77		rds->tp = dev->radio_tx_rds_tp->cur.val;
     78		rds->ms = dev->radio_tx_rds_ms->cur.val;
     79		strscpy(rds->psname,
     80			dev->radio_tx_rds_psname->p_cur.p_char,
     81			sizeof(rds->psname));
     82		strscpy(rds->radiotext,
     83			dev->radio_tx_rds_radiotext->p_cur.p_char + alt * 64,
     84			sizeof(rds->radiotext));
     85		v4l2_ctrl_unlock(dev->radio_tx_rds_pi);
     86	} else {
     87		vivid_rds_gen_fill(rds, dev->radio_rx_freq, alt);
     88	}
     89	if (dev->radio_rx_rds_controls) {
     90		v4l2_ctrl_s_ctrl(dev->radio_rx_rds_pty, rds->pty);
     91		v4l2_ctrl_s_ctrl(dev->radio_rx_rds_ta, rds->ta);
     92		v4l2_ctrl_s_ctrl(dev->radio_rx_rds_tp, rds->tp);
     93		v4l2_ctrl_s_ctrl(dev->radio_rx_rds_ms, rds->ms);
     94		v4l2_ctrl_s_ctrl_string(dev->radio_rx_rds_psname, rds->psname);
     95		v4l2_ctrl_s_ctrl_string(dev->radio_rx_rds_radiotext, rds->radiotext);
     96		if (!dev->radio_rds_loop)
     97			dev->radio_rx_rds_use_alternates = !dev->radio_rx_rds_use_alternates;
     98	}
     99	vivid_rds_generate(rds);
    100}
    101
    102/*
    103 * Calculate the emulated signal quality taking into account the frequency
    104 * the transmitter is using.
    105 */
    106static void vivid_radio_calc_sig_qual(struct vivid_dev *dev)
    107{
    108	int mod = 16000;
    109	int delta = 800;
    110	int sig_qual, sig_qual_tx = mod;
    111
    112	/*
    113	 * For SW and FM there is a channel every 1000 kHz, for AM there is one
    114	 * every 100 kHz.
    115	 */
    116	if (dev->radio_rx_freq <= AM_FREQ_RANGE_HIGH) {
    117		mod /= 10;
    118		delta /= 10;
    119	}
    120	sig_qual = (dev->radio_rx_freq + delta) % mod - delta;
    121	if (dev->has_radio_tx)
    122		sig_qual_tx = dev->radio_rx_freq - dev->radio_tx_freq;
    123	if (abs(sig_qual_tx) <= abs(sig_qual)) {
    124		sig_qual = sig_qual_tx;
    125		/*
    126		 * Zero the internal rds buffer if we are going to loop
    127		 * rds blocks.
    128		 */
    129		if (!dev->radio_rds_loop && !dev->radio_tx_rds_controls)
    130			memset(dev->rds_gen.data, 0,
    131			       sizeof(dev->rds_gen.data));
    132		dev->radio_rds_loop = dev->radio_rx_freq >= FM_FREQ_RANGE_LOW;
    133	} else {
    134		dev->radio_rds_loop = false;
    135	}
    136	if (dev->radio_rx_freq <= AM_FREQ_RANGE_HIGH)
    137		sig_qual *= 10;
    138	dev->radio_rx_sig_qual = sig_qual;
    139}
    140
    141int vivid_radio_g_frequency(struct file *file, const unsigned *pfreq, struct v4l2_frequency *vf)
    142{
    143	if (vf->tuner != 0)
    144		return -EINVAL;
    145	vf->frequency = *pfreq;
    146	return 0;
    147}
    148
    149int vivid_radio_s_frequency(struct file *file, unsigned *pfreq, const struct v4l2_frequency *vf)
    150{
    151	struct vivid_dev *dev = video_drvdata(file);
    152	unsigned freq;
    153	unsigned band;
    154
    155	if (vf->tuner != 0)
    156		return -EINVAL;
    157
    158	if (vf->frequency >= (FM_FREQ_RANGE_LOW + SW_FREQ_RANGE_HIGH) / 2)
    159		band = BAND_FM;
    160	else if (vf->frequency <= (AM_FREQ_RANGE_HIGH + SW_FREQ_RANGE_LOW) / 2)
    161		band = BAND_AM;
    162	else
    163		band = BAND_SW;
    164
    165	freq = clamp_t(u32, vf->frequency, vivid_radio_bands[band].rangelow,
    166					   vivid_radio_bands[band].rangehigh);
    167	*pfreq = freq;
    168
    169	/*
    170	 * For both receiver and transmitter recalculate the signal quality
    171	 * (since that depends on both frequencies) and re-init the rds
    172	 * generator.
    173	 */
    174	vivid_radio_calc_sig_qual(dev);
    175	vivid_radio_rds_init(dev);
    176	return 0;
    177}