summaryrefslogtreecommitdiffstats
path: root/kernel/Documentation/video4linux/si4713.txt
blob: 2e7392a4fee1a736dcd6135f6f08341b38505e3b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
Driver for I2C radios for the Silicon Labs Si4713 FM Radio Transmitters

Copyright (c) 2009 Nokia Corporation
Contact: Eduardo Valentin <eduardo.valentin@nokia.com>


Information about the Device
============================
This chip is a Silicon Labs product. It is a I2C device, currently on 0x63 address.
Basically, it has transmission and signal noise level measurement features.

The Si4713 integrates transmit functions for FM broadcast stereo transmission.
The chip also allows integrated receive power scanning to identify low signal
power FM channels.

The chip is programmed using commands and responses. There are also several
properties which can change the behavior of this chip.

Users must comply with local regulations on radio frequency (RF) transmission.

Device driver description
=========================
There are two modules to handle this device. One is a I2C device driver
and the other is a platform driver.

The I2C device driver exports a v4l2-subdev interface to the kernel.
All properties can also be accessed by v4l2 extended controls interface, by
using the v4l2-subdev calls (g_ext_ctrls, s_ext_ctrls).

The platform device driver exports a v4l2 radio device interface to user land.
So, it uses the I2C device driver as a sub device in order to send the user
commands to the actual device. Basically it is a wrapper to the I2C device driver.

Applications can use v4l2 radio API to specify frequency of operation, mute state,
etc. But mostly of its properties will be present in the extended controls.

When the v4l2 mute property is set to 1 (true), the driver will turn the chip off.

Properties description
======================

The properties can be accessed using v4l2 extended controls.
Here is an output from v4l2-ctl util:
/ # v4l2-ctl -d /dev/radio0 --all -L
Driver Info:
	Driver name   : radio-si4713
	Card type     : Silicon Labs Si4713 Modulator
	Bus info      :
	Driver version: 0
	Capabilities  : 0x00080800
		RDS Output
		Modulator
Audio output: 0 (FM Modulator Audio Out)
Frequency: 1408000 (88.000000 MHz)
Video Standard = 0x00000000
Modulator:
	Name                 : FM Modulator
	Capabilities         : 62.5 Hz stereo rds
	Frequency range      : 76.0 MHz - 108.0 MHz
	Subchannel modulation: stereo+rds

User Controls

			   mute (bool) : default=1 value=0

FM Radio Modulator Controls

	   rds_signal_deviation (int)  : min=0 max=90000 step=10 default=200 value=200 flags=slider
		 rds_program_id (int)  : min=0 max=65535 step=1 default=0 value=0
	       rds_program_type (int)  : min=0 max=31 step=1 default=0 value=0
		    rds_ps_name (str)  : min=0 max=96 step=8 value='si4713  '
		 rds_radio_text (str)  : min=0 max=384 step=32 value=''
  audio_limiter_feature_enabled (bool) : default=1 value=1
     audio_limiter_release_time (int)  : min=250 max=102390 step=50 default=5010 value=5010 flags=slider
	audio_limiter_deviation (int)  : min=0 max=90000 step=10 default=66250 value=66250 flags=slider
audio_compression_feature_enabl (bool) : default=1 value=1
	 audio_compression_gain (int)  : min=0 max=20 step=1 default=15 value=15 flags=slider
    audio_compression_threshold (int)  : min=-40 max=0 step=1 default=-40 value=-40 flags=slider
  audio_compression_attack_time (int)  : min=0 max=5000 step=500 default=0 value=0 flags=slider
 audio_compression_release_time (int)  : min=100000 max=1000000 step=100000 default=1000000 value=1000000 flags=slider
     pilot_tone_feature_enabled (bool) : default=1 value=1
	   pilot_tone_deviation (int)  : min=0 max=90000 step=10 default=6750 value=6750 flags=slider
	   pilot_tone_frequency (int)  : min=0 max=19000 step=1 default=19000 value=19000 flags=slider
	  pre_emphasis_settings (menu) : min=0 max=2 default=1 value=1
	       tune_power_level (int)  : min=0 max=120 step=1 default=88 value=88 flags=slider
	 tune_antenna_capacitor (int)  : min=0 max=191 step=1 default=0 value=110 flags=slider
/ #

Here is a summary of them:

* Pilot is an audible tone sent by the device.

pilot_frequency - Configures the frequency of the stereo pilot tone.
pilot_deviation - Configures pilot tone frequency deviation level.
pilot_enabled - Enables or disables the pilot tone feature.

* The si4713 device is capable of applying audio compression to the transmitted signal.

acomp_enabled - Enables or disables the audio dynamic range control feature.
acomp_gain - Sets the gain for audio dynamic range control.
acomp_threshold - Sets the threshold level for audio dynamic range control.
acomp_attack_time - Sets the attack time for audio dynamic range control.
acomp_release_time - Sets the release time for audio dynamic range control.

* Limiter setups audio deviation limiter feature. Once a over deviation occurs,
it is possible to adjust the front-end gain of the audio input and always
prevent over deviation.

limiter_enabled - Enables or disables the limiter feature.
limiter_deviation - Configures audio frequency deviation level.
limiter_release_time - Sets the limiter release time.

* Tuning power

power_level - Sets the output power level for signal transmission.
antenna_capacitor - This selects the value of antenna tuning capacitor manually
or automatically if set to zero.

* RDS related

rds_ps_name - Sets the RDS ps name field for transmission.
rds_radio_text - Sets the RDS radio text for transmission.
rds_pi - Sets the RDS PI field for transmission.
rds_pty - Sets the RDS PTY field for transmission.

* Region related

preemphasis - sets the preemphasis to be applied for transmission.

RNL
===

This device also has an interface to measure received noise level. To do that, you should
ioctl the device node. Here is an code of example:

int main (int argc, char *argv[])
{
	struct si4713_rnl rnl;
	int fd = open("/dev/radio0", O_RDWR);
	int rval;

	if (argc < 2)
		return -EINVAL;

	if (fd < 0)
		return fd;

	sscanf(argv[1], "%d", &rnl.frequency);

	rval = ioctl(fd, SI4713_IOC_MEASURE_RNL, &rnl);
	if (rval < 0)
		return rval;

	printf("received noise level: %d\n", rnl.rnl);

	close(fd);
}

The struct si4713_rnl and SI4713_IOC_MEASURE_RNL are defined under
include/media/si4713.h.

Stereo/Mono and RDS subchannels
===============================

The device can also be configured using the available sub channels for
transmission. To do that use S/G_MODULATOR ioctl and configure txsubchans properly.
Refer to the V4L2 API specification for proper use of this ioctl.

Testing
=======
Testing is usually done with v4l2-ctl utility for managing FM tuner cards.
The tool can be found in v4l-dvb repository under v4l2-apps/util directory.

Example for setting rds ps name:
# v4l2-ctl -d /dev/radio0 --set-ctrl=rds_ps_name="Dummy"
class="c1"># # All rights reserved. This program and the accompanying materials # are made available under the terms of the Apache License, Version 2.0 # which accompanies this distribution, and is available at # http://www.apache.org/licenses/LICENSE-2.0 # import argparse import json import logging import logging.config import os import re import subprocess import sys import fileinput import yaml import functest.utils.functest_utils as ft_utils import functest.utils.openstack_utils as os_utils from functest.utils.constants import CONST from opnfv.utils import constants as opnfv_constants from opnfv.deployment import factory actions = ['start', 'check'] """ logging configuration """ logger = logging.getLogger('functest.ci.prepare_env') handler = None # set the architecture to default pod_arch = None arch_filter = ['aarch64'] CONFIG_FUNCTEST_PATH = CONST.__getattribute__('CONFIG_FUNCTEST_YAML') CONFIG_PATCH_PATH = os.path.join(os.path.dirname( CONFIG_FUNCTEST_PATH), "config_patch.yaml") CONFIG_AARCH64_PATCH_PATH = os.path.join(os.path.dirname( CONFIG_FUNCTEST_PATH), "config_aarch64_patch.yaml") RALLY_CONF_PATH = os.path.join("/etc/rally/rally.conf") RALLY_AARCH64_PATCH_PATH = os.path.join(os.path.dirname( CONFIG_FUNCTEST_PATH), "rally_aarch64_patch.conf") class PrepareEnvParser(object): def __init__(self): self.parser = argparse.ArgumentParser() self.parser.add_argument("action", help="Possible actions are: " "'{d[0]}|{d[1]}' ".format(d=actions), choices=actions) self.parser.add_argument("-d", "--debug", help="Debug mode", action="store_true") def parse_args(self, argv=[]): return vars(self.parser.parse_args(argv)) def print_separator(): logger.info("==============================================") def check_env_variables(): print_separator() logger.info("Checking environment variables...") if CONST.__getattribute__('INSTALLER_TYPE') is None: logger.warning("The env variable 'INSTALLER_TYPE' is not defined.") CONST.__setattr__('INSTALLER_TYPE', 'undefined') else: if (CONST.__getattribute__('INSTALLER_TYPE') not in opnfv_constants.INSTALLERS): logger.warning("INSTALLER_TYPE=%s is not a valid OPNFV installer. " "Available OPNFV Installers are : %s. " "Setting INSTALLER_TYPE=undefined." % (CONST.__getattribute__('INSTALLER_TYPE'), opnfv_constants.INSTALLERS)) CONST.__setattr__('INSTALLER_TYPE', 'undefined') else: logger.info(" INSTALLER_TYPE=%s" % CONST.__getattribute__('INSTALLER_TYPE')) if CONST.__getattribute__('INSTALLER_IP') is None: logger.warning("The env variable 'INSTALLER_IP' is not defined. " "It is needed to fetch the OpenStack credentials. " "If the credentials are not provided to the " "container as a volume, please add this env variable " "to the 'docker run' command.") else: logger.info(" INSTALLER_IP=%s" % CONST.__getattribute__('INSTALLER_IP')) if CONST.__getattribute__('DEPLOY_SCENARIO') is None: logger.warning("The env variable 'DEPLOY_SCENARIO' is not defined. " "Setting CI_SCENARIO=undefined.") CONST.__setattr__('DEPLOY_SCENARIO', 'undefined') else: logger.info(" DEPLOY_SCENARIO=%s" % CONST.__getattribute__('DEPLOY_SCENARIO')) if CONST.__getattribute__('CI_DEBUG'): logger.info(" CI_DEBUG=%s" % CONST.__getattribute__('CI_DEBUG')) if CONST.__getattribute__('NODE_NAME'): logger.info(" NODE_NAME=%s" % CONST.__getattribute__('NODE_NAME')) if CONST.__getattribute__('BUILD_TAG'): logger.info(" BUILD_TAG=%s" % CONST.__getattribute__('BUILD_TAG')) if CONST.__getattribute__('IS_CI_RUN'): logger.info(" IS_CI_RUN=%s" % CONST.__getattribute__('IS_CI_RUN')) def get_deployment_handler(): global handler global pod_arch installer_params_yaml = os.path.join( CONST.__getattribute__('dir_repo_functest'), 'functest/ci/installer_params.yaml') if (CONST.__getattribute__('INSTALLER_IP') and CONST.__getattribute__('INSTALLER_TYPE') and CONST.__getattribute__('INSTALLER_TYPE') in opnfv_constants.INSTALLERS): try: installer_params = ft_utils.get_parameter_from_yaml( CONST.__getattribute__('INSTALLER_TYPE'), installer_params_yaml) except ValueError as e: logger.debug('Printing deployment info is not supported for %s' % CONST.__getattribute__('INSTALLER_TYPE')) logger.debug(e) else: user = installer_params.get('user', None) password = installer_params.get('password', None) pkey = installer_params.get('pkey', None) try: handler = factory.Factory.get_handler( installer=CONST.__getattribute__('INSTALLER_TYPE'), installer_ip=CONST.__getattribute__('INSTALLER_IP'), installer_user=user, installer_pwd=password, pkey_file=pkey) if handler: pod_arch = handler.get_arch() except Exception as e: logger.debug("Cannot get deployment information. %s" % e) def create_directories(): print_separator() logger.info("Creating needed directories...") if not os.path.exists(CONST.__getattribute__('dir_functest_conf')): os.makedirs(CONST.__getattribute__('dir_functest_conf')) logger.info(" %s created." % CONST.__getattribute__('dir_functest_conf')) else: logger.debug(" %s already exists." % CONST.__getattribute__('dir_functest_conf')) if not os.path.exists(CONST.__getattribute__('dir_functest_data')): os.makedirs(CONST.__getattribute__('dir_functest_data')) logger.info(" %s created." % CONST.__getattribute__('dir_functest_data')) else: logger.debug(" %s already exists." % CONST.__getattribute__('dir_functest_data')) def source_rc_file(): print_separator() logger.info("Fetching RC file...") if CONST.__getattribute__('openstack_creds') is None: logger.warning("The environment variable 'creds' must be set and" "pointing to the local RC file. Using default: " "/home/opnfv/functest/conf/openstack.creds ...") os.path.join( CONST.__getattribute__('dir_functest_conf'), 'openstack.creds') if not os.path.isfile(CONST.__getattribute__('openstack_creds')): logger.info("RC file not provided. " "Fetching it from the installer...") if CONST.__getattribute__('INSTALLER_IP')is None: logger.error("The env variable 'INSTALLER_IP' must be provided in" " order to fetch the credentials from the installer.") raise Exception("Missing CI_INSTALLER_IP.") if (CONST.__getattribute__('INSTALLER_TYPE') not in opnfv_constants.INSTALLERS): logger.error("Cannot fetch credentials. INSTALLER_TYPE=%s is " "not a valid OPNFV installer. Available " "installers are : %s." % (CONST.__getattribute__('INSTALLER_TYPE'), opnfv_constants.INSTALLERS)) raise Exception("Wrong INSTALLER_TYPE.") cmd = ("/home/opnfv/repos/releng/utils/fetch_os_creds.sh " "-d %s -i %s -a %s" % (CONST.__getattribute__('openstack_creds'), CONST.__getattribute__('INSTALLER_TYPE'), CONST.__getattribute__('INSTALLER_IP'))) logger.debug("Executing command: %s" % cmd) p = subprocess.Popen(cmd.split(), stdout=subprocess.PIPE) output = p.communicate()[0] logger.debug("\n%s" % output) if p.returncode != 0: raise Exception("Failed to fetch credentials from installer.") else: logger.info("RC file provided in %s." % CONST.__getattribute__('openstack_creds')) if os.path.getsize(CONST.__getattribute__('openstack_creds')) == 0: raise Exception("The file %s is empty." % CONST.__getattribute__('openstack_creds')) logger.info("Sourcing the OpenStack RC file...") os_utils.source_credentials(CONST.__getattribute__('openstack_creds')) for key, value in os.environ.iteritems(): if re.search("OS_", key): if key == 'OS_AUTH_URL': CONST.__setattr__('OS_AUTH_URL', value) elif key == 'OS_USERNAME': CONST.__setattr__('OS_USERNAME', value) elif key == 'OS_TENANT_NAME': CONST.__setattr__('OS_TENANT_NAME', value) elif key == 'OS_PASSWORD': CONST.__setattr__('OS_PASSWORD', value) def patch_config_file(): patch_file(CONFIG_PATCH_PATH) if pod_arch and pod_arch in arch_filter: patch_file(CONFIG_AARCH64_PATCH_PATH) def patch_file(patch_file_path): logger.debug('Updating file: %s', patch_file_path) with open(patch_file_path) as f: patch_file = yaml.safe_load(f) updated = False for key in patch_file: if key in CONST.__getattribute__('DEPLOY_SCENARIO'): new_functest_yaml = dict(ft_utils.merge_dicts( ft_utils.get_functest_yaml(), patch_file[key])) updated = True if updated: os.remove(CONFIG_FUNCTEST_PATH) with open(CONFIG_FUNCTEST_PATH, "w") as f: f.write(yaml.dump(new_functest_yaml, default_style='"')) f.close() def verify_deployment(): print_separator() logger.info("Verifying OpenStack services...") cmd = ("%s/functest/ci/check_os.sh" % CONST.__getattribute__('dir_repo_functest')) logger.debug("Executing command: %s" % cmd) p = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True) while p.poll() is None: line = p.stdout.readline().rstrip() if "ERROR" in line: logger.error(line) raise Exception("Problem while running 'check_os.sh'.") logger.info(line) def install_rally(): print_separator() if pod_arch and pod_arch in arch_filter: logger.info("Apply aarch64 specific to rally config...") with open(RALLY_AARCH64_PATCH_PATH, "r") as f: rally_patch_conf = f.read() for line in fileinput.input(RALLY_CONF_PATH, inplace=1): print line, if "cirros|testvm" in line: print rally_patch_conf logger.info("Creating Rally environment...") cmd = "rally deployment destroy opnfv-rally" ft_utils.execute_command(cmd, error_msg=( "Deployment %s does not exist." % CONST.__getattribute__('rally_deployment_name')), verbose=False) rally_conf = os_utils.get_credentials_for_rally() with open('rally_conf.json', 'w') as fp: json.dump(rally_conf, fp) cmd = ("rally deployment create " "--file=rally_conf.json --name={0}" .format(CONST.__getattribute__('rally_deployment_name'))) error_msg = "Problem while creating Rally deployment" ft_utils.execute_command_raise(cmd, error_msg=error_msg) cmd = "rally deployment check" error_msg = "OpenStack not responding or faulty Rally deployment." ft_utils.execute_command_raise(cmd, error_msg=error_msg) cmd = "rally deployment list" ft_utils.execute_command(cmd, error_msg=("Problem while listing " "Rally deployment.")) cmd = "rally plugin list | head -5" ft_utils.execute_command(cmd, error_msg=("Problem while showing " "Rally plugins.")) def install_tempest(): logger.info("Installing tempest from existing repo...") cmd = ("rally verify list-verifiers | " "grep '{0}' | wc -l".format( CONST.__getattribute__('tempest_deployment_name'))) p = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True) while p.poll() is None: line = p.stdout.readline().rstrip() if str(line) == '0': logger.debug("Tempest %s does not exist" % CONST.__getattribute__('tempest_deployment_name')) cmd = ("rally verify create-verifier --source {0} " "--name {1} --type tempest --system-wide" .format(CONST.__getattribute__('dir_repo_tempest'), CONST.__getattribute__('tempest_deployment_name'))) error_msg = "Problem while installing Tempest." ft_utils.execute_command_raise(cmd, error_msg=error_msg) def create_flavor(): _, flavor_id = os_utils.get_or_create_flavor('m1.tiny', '512', '1', '1', public=True) if flavor_id is None: raise Exception('Failed to create flavor') def check_environment(): msg_not_active = "The Functest environment is not installed." if not os.path.isfile(CONST.__getattribute__('env_active')): raise Exception(msg_not_active) with open(CONST.__getattribute__('env_active'), "r") as env_file: s = env_file.read() if not re.search("1", s): raise Exception(msg_not_active) logger.info("Functest environment is installed.") def print_deployment_info(): if handler: logger.info('\n\nDeployment information:\n%s' % handler.get_deployment_info()) def main(**kwargs): try: if not (kwargs['action'] in actions): logger.error('Argument not valid.') return -1 elif kwargs['action'] == "start": logger.info("######### Preparing Functest environment #########\n") check_env_variables() get_deployment_handler() create_directories() source_rc_file() patch_config_file() verify_deployment() install_rally() install_tempest() create_flavor() with open(CONST.__getattribute__('env_active'), "w") as env_file: env_file.write("1") check_environment() print_deployment_info() elif kwargs['action'] == "check": check_environment() except Exception as e: logger.error(e) return -1 return 0 if __name__ == '__main__': logging.config.fileConfig( CONST.__getattribute__('dir_functest_logging_cfg')) parser = PrepareEnvParser() args = parser.parse_args(sys.argv[1:]) sys.exit(main(**args))