Path: blob/master/drivers/media/radio/si4713-i2c.c
15112 views
/*1* drivers/media/radio/si4713-i2c.c2*3* Silicon Labs Si4713 FM Radio Transmitter I2C commands.4*5* Copyright (c) 2009 Nokia Corporation6* Contact: Eduardo Valentin <[email protected]>7*8* This program is free software; you can redistribute it and/or modify9* it under the terms of the GNU General Public License as published by10* the Free Software Foundation; either version 2 of the License, or11* (at your option) any later version.12*13* This program is distributed in the hope that it will be useful,14* but WITHOUT ANY WARRANTY; without even the implied warranty of15* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the16* GNU General Public License for more details.17*18* You should have received a copy of the GNU General Public License19* along with this program; if not, write to the Free Software20* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA21*/2223#include <linux/mutex.h>24#include <linux/completion.h>25#include <linux/delay.h>26#include <linux/interrupt.h>27#include <linux/i2c.h>28#include <linux/slab.h>29#include <linux/gpio.h>30#include <linux/regulator/consumer.h>31#include <media/v4l2-device.h>32#include <media/v4l2-ioctl.h>33#include <media/v4l2-common.h>3435#include "si4713-i2c.h"3637/* module parameters */38static int debug;39module_param(debug, int, S_IRUGO | S_IWUSR);40MODULE_PARM_DESC(debug, "Debug level (0 - 2)");4142MODULE_LICENSE("GPL");43MODULE_AUTHOR("Eduardo Valentin <[email protected]>");44MODULE_DESCRIPTION("I2C driver for Si4713 FM Radio Transmitter");45MODULE_VERSION("0.0.1");4647static const char *si4713_supply_names[SI4713_NUM_SUPPLIES] = {48"vio",49"vdd",50};5152#define DEFAULT_RDS_PI 0x0053#define DEFAULT_RDS_PTY 0x0054#define DEFAULT_RDS_PS_NAME ""55#define DEFAULT_RDS_RADIO_TEXT DEFAULT_RDS_PS_NAME56#define DEFAULT_RDS_DEVIATION 0x00C857#define DEFAULT_RDS_PS_REPEAT_COUNT 0x000358#define DEFAULT_LIMITER_RTIME 0x139259#define DEFAULT_LIMITER_DEV 0x102CA60#define DEFAULT_PILOT_FREQUENCY 0x4A3861#define DEFAULT_PILOT_DEVIATION 0x1A5E62#define DEFAULT_ACOMP_ATIME 0x000063#define DEFAULT_ACOMP_RTIME 0xF4240L64#define DEFAULT_ACOMP_GAIN 0x0F65#define DEFAULT_ACOMP_THRESHOLD (-0x28)66#define DEFAULT_MUTE 0x0167#define DEFAULT_POWER_LEVEL 8868#define DEFAULT_FREQUENCY 880069#define DEFAULT_PREEMPHASIS FMPE_EU70#define DEFAULT_TUNE_RNL 0xFF7172#define to_si4713_device(sd) container_of(sd, struct si4713_device, sd)7374/* frequency domain transformation (using times 10 to avoid floats) */75#define FREQDEV_UNIT 10000076#define FREQV4L2_MULTI 62577#define si4713_to_v4l2(f) ((f * FREQDEV_UNIT) / FREQV4L2_MULTI)78#define v4l2_to_si4713(f) ((f * FREQV4L2_MULTI) / FREQDEV_UNIT)79#define FREQ_RANGE_LOW 760080#define FREQ_RANGE_HIGH 108008182#define MAX_ARGS 78384#define RDS_BLOCK 885#define RDS_BLOCK_CLEAR 0x0386#define RDS_BLOCK_LOAD 0x0487#define RDS_RADIOTEXT_2A 0x2088#define RDS_RADIOTEXT_BLK_SIZE 489#define RDS_RADIOTEXT_INDEX_MAX 0x0F90#define RDS_CARRIAGE_RETURN 0x0D9192#define rds_ps_nblocks(len) ((len / RDS_BLOCK) + (len % RDS_BLOCK ? 1 : 0))9394#define get_status_bit(p, b, m) (((p) & (m)) >> (b))95#define set_bits(p, v, b, m) (((p) & ~(m)) | ((v) << (b)))9697#define ATTACK_TIME_UNIT 5009899#define POWER_OFF 0x00100#define POWER_ON 0x01101102#define msb(x) ((u8)((u16) x >> 8))103#define lsb(x) ((u8)((u16) x & 0x00FF))104#define compose_u16(msb, lsb) (((u16)msb << 8) | lsb)105#define check_command_failed(status) (!(status & SI4713_CTS) || \106(status & SI4713_ERR))107/* mute definition */108#define set_mute(p) ((p & 1) | ((p & 1) << 1));109#define get_mute(p) (p & 0x01)110111#ifdef DEBUG112#define DBG_BUFFER(device, message, buffer, size) \113{ \114int i; \115char str[(size)*5]; \116for (i = 0; i < size; i++) \117sprintf(str + i * 5, " 0x%02x", buffer[i]); \118v4l2_dbg(2, debug, device, "%s:%s\n", message, str); \119}120#else121#define DBG_BUFFER(device, message, buffer, size)122#endif123124/*125* Values for limiter release time (sorted by second column)126* device release127* value time (us)128*/129static long limiter_times[] = {1302000, 250,1311000, 500,132510, 1000,133255, 2000,134170, 3000,135127, 4020,136102, 5010,13785, 6020,13873, 7010,13964, 7990,14057, 8970,14151, 10030,14225, 20470,14317, 30110,14413, 39380,14510, 51190,1468, 63690,1477, 73140,1486, 85330,1495, 102390,150};151152/*153* Values for audio compression release time (sorted by second column)154* device release155* value time (us)156*/157static unsigned long acomp_rtimes[] = {1580, 100000,1591, 200000,1602, 350000,1613, 525000,1624, 1000000,163};164165/*166* Values for preemphasis (sorted by second column)167* device preemphasis168* value value (v4l2)169*/170static unsigned long preemphasis_values[] = {171FMPE_DISABLED, V4L2_PREEMPHASIS_DISABLED,172FMPE_EU, V4L2_PREEMPHASIS_50_uS,173FMPE_USA, V4L2_PREEMPHASIS_75_uS,174};175176static int usecs_to_dev(unsigned long usecs, unsigned long const array[],177int size)178{179int i;180int rval = -EINVAL;181182for (i = 0; i < size / 2; i++)183if (array[(i * 2) + 1] >= usecs) {184rval = array[i * 2];185break;186}187188return rval;189}190191static unsigned long dev_to_usecs(int value, unsigned long const array[],192int size)193{194int i;195int rval = -EINVAL;196197for (i = 0; i < size / 2; i++)198if (array[i * 2] == value) {199rval = array[(i * 2) + 1];200break;201}202203return rval;204}205206/* si4713_handler: IRQ handler, just complete work */207static irqreturn_t si4713_handler(int irq, void *dev)208{209struct si4713_device *sdev = dev;210211v4l2_dbg(2, debug, &sdev->sd,212"%s: sending signal to completion work.\n", __func__);213complete(&sdev->work);214215return IRQ_HANDLED;216}217218/*219* si4713_send_command - sends a command to si4713 and waits its response220* @sdev: si4713_device structure for the device we are communicating221* @command: command id222* @args: command arguments we are sending (up to 7)223* @argn: actual size of @args224* @response: buffer to place the expected response from the device (up to 15)225* @respn: actual size of @response226* @usecs: amount of time to wait before reading the response (in usecs)227*/228static int si4713_send_command(struct si4713_device *sdev, const u8 command,229const u8 args[], const int argn,230u8 response[], const int respn, const int usecs)231{232struct i2c_client *client = v4l2_get_subdevdata(&sdev->sd);233u8 data1[MAX_ARGS + 1];234int err;235236if (!client->adapter)237return -ENODEV;238239/* First send the command and its arguments */240data1[0] = command;241memcpy(data1 + 1, args, argn);242DBG_BUFFER(&sdev->sd, "Parameters", data1, argn + 1);243244err = i2c_master_send(client, data1, argn + 1);245if (err != argn + 1) {246v4l2_err(&sdev->sd, "Error while sending command 0x%02x\n",247command);248return (err > 0) ? -EIO : err;249}250251/* Wait response from interrupt */252if (!wait_for_completion_timeout(&sdev->work,253usecs_to_jiffies(usecs) + 1))254v4l2_warn(&sdev->sd,255"(%s) Device took too much time to answer.\n",256__func__);257258/* Then get the response */259err = i2c_master_recv(client, response, respn);260if (err != respn) {261v4l2_err(&sdev->sd,262"Error while reading response for command 0x%02x\n",263command);264return (err > 0) ? -EIO : err;265}266267DBG_BUFFER(&sdev->sd, "Response", response, respn);268if (check_command_failed(response[0]))269return -EBUSY;270271return 0;272}273274/*275* si4713_read_property - reads a si4713 property276* @sdev: si4713_device structure for the device we are communicating277* @prop: property identification number278* @pv: property value to be returned on success279*/280static int si4713_read_property(struct si4713_device *sdev, u16 prop, u32 *pv)281{282int err;283u8 val[SI4713_GET_PROP_NRESP];284/*285* .First byte = 0286* .Second byte = property's MSB287* .Third byte = property's LSB288*/289const u8 args[SI4713_GET_PROP_NARGS] = {2900x00,291msb(prop),292lsb(prop),293};294295err = si4713_send_command(sdev, SI4713_CMD_GET_PROPERTY,296args, ARRAY_SIZE(args), val,297ARRAY_SIZE(val), DEFAULT_TIMEOUT);298299if (err < 0)300return err;301302*pv = compose_u16(val[2], val[3]);303304v4l2_dbg(1, debug, &sdev->sd,305"%s: property=0x%02x value=0x%02x status=0x%02x\n",306__func__, prop, *pv, val[0]);307308return err;309}310311/*312* si4713_write_property - modifies a si4713 property313* @sdev: si4713_device structure for the device we are communicating314* @prop: property identification number315* @val: new value for that property316*/317static int si4713_write_property(struct si4713_device *sdev, u16 prop, u16 val)318{319int rval;320u8 resp[SI4713_SET_PROP_NRESP];321/*322* .First byte = 0323* .Second byte = property's MSB324* .Third byte = property's LSB325* .Fourth byte = value's MSB326* .Fifth byte = value's LSB327*/328const u8 args[SI4713_SET_PROP_NARGS] = {3290x00,330msb(prop),331lsb(prop),332msb(val),333lsb(val),334};335336rval = si4713_send_command(sdev, SI4713_CMD_SET_PROPERTY,337args, ARRAY_SIZE(args),338resp, ARRAY_SIZE(resp),339DEFAULT_TIMEOUT);340341if (rval < 0)342return rval;343344v4l2_dbg(1, debug, &sdev->sd,345"%s: property=0x%02x value=0x%02x status=0x%02x\n",346__func__, prop, val, resp[0]);347348/*349* As there is no command response for SET_PROPERTY,350* wait Tcomp time to finish before proceed, in order351* to have property properly set.352*/353msleep(TIMEOUT_SET_PROPERTY);354355return rval;356}357358/*359* si4713_powerup - Powers the device up360* @sdev: si4713_device structure for the device we are communicating361*/362static int si4713_powerup(struct si4713_device *sdev)363{364int err;365u8 resp[SI4713_PWUP_NRESP];366/*367* .First byte = Enabled interrupts and boot function368* .Second byte = Input operation mode369*/370const u8 args[SI4713_PWUP_NARGS] = {371SI4713_PWUP_CTSIEN | SI4713_PWUP_GPO2OEN | SI4713_PWUP_FUNC_TX,372SI4713_PWUP_OPMOD_ANALOG,373};374375if (sdev->power_state)376return 0;377378err = regulator_bulk_enable(ARRAY_SIZE(sdev->supplies),379sdev->supplies);380if (err) {381v4l2_err(&sdev->sd, "Failed to enable supplies: %d\n", err);382return err;383}384if (gpio_is_valid(sdev->gpio_reset)) {385udelay(50);386gpio_set_value(sdev->gpio_reset, 1);387}388389err = si4713_send_command(sdev, SI4713_CMD_POWER_UP,390args, ARRAY_SIZE(args),391resp, ARRAY_SIZE(resp),392TIMEOUT_POWER_UP);393394if (!err) {395v4l2_dbg(1, debug, &sdev->sd, "Powerup response: 0x%02x\n",396resp[0]);397v4l2_dbg(1, debug, &sdev->sd, "Device in power up mode\n");398sdev->power_state = POWER_ON;399400err = si4713_write_property(sdev, SI4713_GPO_IEN,401SI4713_STC_INT | SI4713_CTS);402} else {403if (gpio_is_valid(sdev->gpio_reset))404gpio_set_value(sdev->gpio_reset, 0);405err = regulator_bulk_disable(ARRAY_SIZE(sdev->supplies),406sdev->supplies);407if (err)408v4l2_err(&sdev->sd,409"Failed to disable supplies: %d\n", err);410}411412return err;413}414415/*416* si4713_powerdown - Powers the device down417* @sdev: si4713_device structure for the device we are communicating418*/419static int si4713_powerdown(struct si4713_device *sdev)420{421int err;422u8 resp[SI4713_PWDN_NRESP];423424if (!sdev->power_state)425return 0;426427err = si4713_send_command(sdev, SI4713_CMD_POWER_DOWN,428NULL, 0,429resp, ARRAY_SIZE(resp),430DEFAULT_TIMEOUT);431432if (!err) {433v4l2_dbg(1, debug, &sdev->sd, "Power down response: 0x%02x\n",434resp[0]);435v4l2_dbg(1, debug, &sdev->sd, "Device in reset mode\n");436if (gpio_is_valid(sdev->gpio_reset))437gpio_set_value(sdev->gpio_reset, 0);438err = regulator_bulk_disable(ARRAY_SIZE(sdev->supplies),439sdev->supplies);440if (err)441v4l2_err(&sdev->sd,442"Failed to disable supplies: %d\n", err);443sdev->power_state = POWER_OFF;444}445446return err;447}448449/*450* si4713_checkrev - Checks if we are treating a device with the correct rev.451* @sdev: si4713_device structure for the device we are communicating452*/453static int si4713_checkrev(struct si4713_device *sdev)454{455struct i2c_client *client = v4l2_get_subdevdata(&sdev->sd);456int rval;457u8 resp[SI4713_GETREV_NRESP];458459mutex_lock(&sdev->mutex);460461rval = si4713_send_command(sdev, SI4713_CMD_GET_REV,462NULL, 0,463resp, ARRAY_SIZE(resp),464DEFAULT_TIMEOUT);465466if (rval < 0)467goto unlock;468469if (resp[1] == SI4713_PRODUCT_NUMBER) {470v4l2_info(&sdev->sd, "chip found @ 0x%02x (%s)\n",471client->addr << 1, client->adapter->name);472} else {473v4l2_err(&sdev->sd, "Invalid product number\n");474rval = -EINVAL;475}476477unlock:478mutex_unlock(&sdev->mutex);479return rval;480}481482/*483* si4713_wait_stc - Waits STC interrupt and clears status bits. Useful484* for TX_TUNE_POWER, TX_TUNE_FREQ and TX_TUNE_MEAS485* @sdev: si4713_device structure for the device we are communicating486* @usecs: timeout to wait for STC interrupt signal487*/488static int si4713_wait_stc(struct si4713_device *sdev, const int usecs)489{490int err;491u8 resp[SI4713_GET_STATUS_NRESP];492493/* Wait response from STC interrupt */494if (!wait_for_completion_timeout(&sdev->work,495usecs_to_jiffies(usecs) + 1))496v4l2_warn(&sdev->sd,497"%s: device took too much time to answer (%d usec).\n",498__func__, usecs);499500/* Clear status bits */501err = si4713_send_command(sdev, SI4713_CMD_GET_INT_STATUS,502NULL, 0,503resp, ARRAY_SIZE(resp),504DEFAULT_TIMEOUT);505506if (err < 0)507goto exit;508509v4l2_dbg(1, debug, &sdev->sd,510"%s: status bits: 0x%02x\n", __func__, resp[0]);511512if (!(resp[0] & SI4713_STC_INT))513err = -EIO;514515exit:516return err;517}518519/*520* si4713_tx_tune_freq - Sets the state of the RF carrier and sets the tuning521* frequency between 76 and 108 MHz in 10 kHz units and522* steps of 50 kHz.523* @sdev: si4713_device structure for the device we are communicating524* @frequency: desired frequency (76 - 108 MHz, unit 10 KHz, step 50 kHz)525*/526static int si4713_tx_tune_freq(struct si4713_device *sdev, u16 frequency)527{528int err;529u8 val[SI4713_TXFREQ_NRESP];530/*531* .First byte = 0532* .Second byte = frequency's MSB533* .Third byte = frequency's LSB534*/535const u8 args[SI4713_TXFREQ_NARGS] = {5360x00,537msb(frequency),538lsb(frequency),539};540541err = si4713_send_command(sdev, SI4713_CMD_TX_TUNE_FREQ,542args, ARRAY_SIZE(args), val,543ARRAY_SIZE(val), DEFAULT_TIMEOUT);544545if (err < 0)546return err;547548v4l2_dbg(1, debug, &sdev->sd,549"%s: frequency=0x%02x status=0x%02x\n", __func__,550frequency, val[0]);551552err = si4713_wait_stc(sdev, TIMEOUT_TX_TUNE);553if (err < 0)554return err;555556return compose_u16(args[1], args[2]);557}558559/*560* si4713_tx_tune_power - Sets the RF voltage level between 88 and 115 dBuV in561* 1 dB units. A value of 0x00 indicates off. The command562* also sets the antenna tuning capacitance. A value of 0563* indicates autotuning, and a value of 1 - 191 indicates564* a manual override, which results in a tuning565* capacitance of 0.25 pF x @antcap.566* @sdev: si4713_device structure for the device we are communicating567* @power: tuning power (88 - 115 dBuV, unit/step 1 dB)568* @antcap: value of antenna tuning capacitor (0 - 191)569*/570static int si4713_tx_tune_power(struct si4713_device *sdev, u8 power,571u8 antcap)572{573int err;574u8 val[SI4713_TXPWR_NRESP];575/*576* .First byte = 0577* .Second byte = 0578* .Third byte = power579* .Fourth byte = antcap580*/581const u8 args[SI4713_TXPWR_NARGS] = {5820x00,5830x00,584power,585antcap,586};587588if (((power > 0) && (power < SI4713_MIN_POWER)) ||589power > SI4713_MAX_POWER || antcap > SI4713_MAX_ANTCAP)590return -EDOM;591592err = si4713_send_command(sdev, SI4713_CMD_TX_TUNE_POWER,593args, ARRAY_SIZE(args), val,594ARRAY_SIZE(val), DEFAULT_TIMEOUT);595596if (err < 0)597return err;598599v4l2_dbg(1, debug, &sdev->sd,600"%s: power=0x%02x antcap=0x%02x status=0x%02x\n",601__func__, power, antcap, val[0]);602603return si4713_wait_stc(sdev, TIMEOUT_TX_TUNE_POWER);604}605606/*607* si4713_tx_tune_measure - Enters receive mode and measures the received noise608* level in units of dBuV on the selected frequency.609* The Frequency must be between 76 and 108 MHz in 10 kHz610* units and steps of 50 kHz. The command also sets the611* antenna tuning capacitance. A value of 0 means612* autotuning, and a value of 1 to 191 indicates manual613* override.614* @sdev: si4713_device structure for the device we are communicating615* @frequency: desired frequency (76 - 108 MHz, unit 10 KHz, step 50 kHz)616* @antcap: value of antenna tuning capacitor (0 - 191)617*/618static int si4713_tx_tune_measure(struct si4713_device *sdev, u16 frequency,619u8 antcap)620{621int err;622u8 val[SI4713_TXMEA_NRESP];623/*624* .First byte = 0625* .Second byte = frequency's MSB626* .Third byte = frequency's LSB627* .Fourth byte = antcap628*/629const u8 args[SI4713_TXMEA_NARGS] = {6300x00,631msb(frequency),632lsb(frequency),633antcap,634};635636sdev->tune_rnl = DEFAULT_TUNE_RNL;637638if (antcap > SI4713_MAX_ANTCAP)639return -EDOM;640641err = si4713_send_command(sdev, SI4713_CMD_TX_TUNE_MEASURE,642args, ARRAY_SIZE(args), val,643ARRAY_SIZE(val), DEFAULT_TIMEOUT);644645if (err < 0)646return err;647648v4l2_dbg(1, debug, &sdev->sd,649"%s: frequency=0x%02x antcap=0x%02x status=0x%02x\n",650__func__, frequency, antcap, val[0]);651652return si4713_wait_stc(sdev, TIMEOUT_TX_TUNE);653}654655/*656* si4713_tx_tune_status- Returns the status of the tx_tune_freq, tx_tune_mea or657* tx_tune_power commands. This command return the current658* frequency, output voltage in dBuV, the antenna tunning659* capacitance value and the received noise level. The660* command also clears the stcint interrupt bit when the661* first bit of its arguments is high.662* @sdev: si4713_device structure for the device we are communicating663* @intack: 0x01 to clear the seek/tune complete interrupt status indicator.664* @frequency: returned frequency665* @power: returned power666* @antcap: returned antenna capacitance667* @noise: returned noise level668*/669static int si4713_tx_tune_status(struct si4713_device *sdev, u8 intack,670u16 *frequency, u8 *power,671u8 *antcap, u8 *noise)672{673int err;674u8 val[SI4713_TXSTATUS_NRESP];675/*676* .First byte = intack bit677*/678const u8 args[SI4713_TXSTATUS_NARGS] = {679intack & SI4713_INTACK_MASK,680};681682err = si4713_send_command(sdev, SI4713_CMD_TX_TUNE_STATUS,683args, ARRAY_SIZE(args), val,684ARRAY_SIZE(val), DEFAULT_TIMEOUT);685686if (!err) {687v4l2_dbg(1, debug, &sdev->sd,688"%s: status=0x%02x\n", __func__, val[0]);689*frequency = compose_u16(val[2], val[3]);690sdev->frequency = *frequency;691*power = val[5];692*antcap = val[6];693*noise = val[7];694v4l2_dbg(1, debug, &sdev->sd, "%s: response: %d x 10 kHz "695"(power %d, antcap %d, rnl %d)\n", __func__,696*frequency, *power, *antcap, *noise);697}698699return err;700}701702/*703* si4713_tx_rds_buff - Loads the RDS group buffer FIFO or circular buffer.704* @sdev: si4713_device structure for the device we are communicating705* @mode: the buffer operation mode.706* @rdsb: RDS Block B707* @rdsc: RDS Block C708* @rdsd: RDS Block D709* @cbleft: returns the number of available circular buffer blocks minus the710* number of used circular buffer blocks.711*/712static int si4713_tx_rds_buff(struct si4713_device *sdev, u8 mode, u16 rdsb,713u16 rdsc, u16 rdsd, s8 *cbleft)714{715int err;716u8 val[SI4713_RDSBUFF_NRESP];717718const u8 args[SI4713_RDSBUFF_NARGS] = {719mode & SI4713_RDSBUFF_MODE_MASK,720msb(rdsb),721lsb(rdsb),722msb(rdsc),723lsb(rdsc),724msb(rdsd),725lsb(rdsd),726};727728err = si4713_send_command(sdev, SI4713_CMD_TX_RDS_BUFF,729args, ARRAY_SIZE(args), val,730ARRAY_SIZE(val), DEFAULT_TIMEOUT);731732if (!err) {733v4l2_dbg(1, debug, &sdev->sd,734"%s: status=0x%02x\n", __func__, val[0]);735*cbleft = (s8)val[2] - val[3];736v4l2_dbg(1, debug, &sdev->sd, "%s: response: interrupts"737" 0x%02x cb avail: %d cb used %d fifo avail"738" %d fifo used %d\n", __func__, val[1],739val[2], val[3], val[4], val[5]);740}741742return err;743}744745/*746* si4713_tx_rds_ps - Loads the program service buffer.747* @sdev: si4713_device structure for the device we are communicating748* @psid: program service id to be loaded.749* @pschar: assumed 4 size char array to be loaded into the program service750*/751static int si4713_tx_rds_ps(struct si4713_device *sdev, u8 psid,752unsigned char *pschar)753{754int err;755u8 val[SI4713_RDSPS_NRESP];756757const u8 args[SI4713_RDSPS_NARGS] = {758psid & SI4713_RDSPS_PSID_MASK,759pschar[0],760pschar[1],761pschar[2],762pschar[3],763};764765err = si4713_send_command(sdev, SI4713_CMD_TX_RDS_PS,766args, ARRAY_SIZE(args), val,767ARRAY_SIZE(val), DEFAULT_TIMEOUT);768769if (err < 0)770return err;771772v4l2_dbg(1, debug, &sdev->sd, "%s: status=0x%02x\n", __func__, val[0]);773774return err;775}776777static int si4713_set_power_state(struct si4713_device *sdev, u8 value)778{779int rval;780781mutex_lock(&sdev->mutex);782783if (value)784rval = si4713_powerup(sdev);785else786rval = si4713_powerdown(sdev);787788mutex_unlock(&sdev->mutex);789return rval;790}791792static int si4713_set_mute(struct si4713_device *sdev, u16 mute)793{794int rval = 0;795796mute = set_mute(mute);797798mutex_lock(&sdev->mutex);799800if (sdev->power_state)801rval = si4713_write_property(sdev,802SI4713_TX_LINE_INPUT_MUTE, mute);803804if (rval >= 0)805sdev->mute = get_mute(mute);806807mutex_unlock(&sdev->mutex);808809return rval;810}811812static int si4713_set_rds_ps_name(struct si4713_device *sdev, char *ps_name)813{814int rval = 0, i;815u8 len = 0;816817/* We want to clear the whole thing */818if (!strlen(ps_name))819memset(ps_name, 0, MAX_RDS_PS_NAME + 1);820821mutex_lock(&sdev->mutex);822823if (sdev->power_state) {824/* Write the new ps name and clear the padding */825for (i = 0; i < MAX_RDS_PS_NAME; i += (RDS_BLOCK / 2)) {826rval = si4713_tx_rds_ps(sdev, (i / (RDS_BLOCK / 2)),827ps_name + i);828if (rval < 0)829goto unlock;830}831832/* Setup the size to be sent */833if (strlen(ps_name))834len = strlen(ps_name) - 1;835else836len = 1;837838rval = si4713_write_property(sdev,839SI4713_TX_RDS_PS_MESSAGE_COUNT,840rds_ps_nblocks(len));841if (rval < 0)842goto unlock;843844rval = si4713_write_property(sdev,845SI4713_TX_RDS_PS_REPEAT_COUNT,846DEFAULT_RDS_PS_REPEAT_COUNT * 2);847if (rval < 0)848goto unlock;849}850851strncpy(sdev->rds_info.ps_name, ps_name, MAX_RDS_PS_NAME);852853unlock:854mutex_unlock(&sdev->mutex);855return rval;856}857858static int si4713_set_rds_radio_text(struct si4713_device *sdev, char *rt)859{860int rval = 0, i;861u16 t_index = 0;862u8 b_index = 0, cr_inserted = 0;863s8 left;864865mutex_lock(&sdev->mutex);866867if (!sdev->power_state)868goto copy;869870rval = si4713_tx_rds_buff(sdev, RDS_BLOCK_CLEAR, 0, 0, 0, &left);871if (rval < 0)872goto unlock;873874if (!strlen(rt))875goto copy;876877do {878/* RDS spec says that if the last block isn't used,879* then apply a carriage return880*/881if (t_index < (RDS_RADIOTEXT_INDEX_MAX *882RDS_RADIOTEXT_BLK_SIZE)) {883for (i = 0; i < RDS_RADIOTEXT_BLK_SIZE; i++) {884if (!rt[t_index + i] || rt[t_index + i] ==885RDS_CARRIAGE_RETURN) {886rt[t_index + i] = RDS_CARRIAGE_RETURN;887cr_inserted = 1;888break;889}890}891}892893rval = si4713_tx_rds_buff(sdev, RDS_BLOCK_LOAD,894compose_u16(RDS_RADIOTEXT_2A, b_index++),895compose_u16(rt[t_index], rt[t_index + 1]),896compose_u16(rt[t_index + 2], rt[t_index + 3]),897&left);898if (rval < 0)899goto unlock;900901t_index += RDS_RADIOTEXT_BLK_SIZE;902903if (cr_inserted)904break;905} while (left > 0);906907copy:908strncpy(sdev->rds_info.radio_text, rt, MAX_RDS_RADIO_TEXT);909910unlock:911mutex_unlock(&sdev->mutex);912return rval;913}914915static int si4713_choose_econtrol_action(struct si4713_device *sdev, u32 id,916u32 **shadow, s32 *bit, s32 *mask, u16 *property, int *mul,917unsigned long **table, int *size)918{919s32 rval = 0;920921switch (id) {922/* FM_TX class controls */923case V4L2_CID_RDS_TX_PI:924*property = SI4713_TX_RDS_PI;925*mul = 1;926*shadow = &sdev->rds_info.pi;927break;928case V4L2_CID_AUDIO_COMPRESSION_THRESHOLD:929*property = SI4713_TX_ACOMP_THRESHOLD;930*mul = 1;931*shadow = &sdev->acomp_info.threshold;932break;933case V4L2_CID_AUDIO_COMPRESSION_GAIN:934*property = SI4713_TX_ACOMP_GAIN;935*mul = 1;936*shadow = &sdev->acomp_info.gain;937break;938case V4L2_CID_PILOT_TONE_FREQUENCY:939*property = SI4713_TX_PILOT_FREQUENCY;940*mul = 1;941*shadow = &sdev->pilot_info.frequency;942break;943case V4L2_CID_AUDIO_COMPRESSION_ATTACK_TIME:944*property = SI4713_TX_ACOMP_ATTACK_TIME;945*mul = ATTACK_TIME_UNIT;946*shadow = &sdev->acomp_info.attack_time;947break;948case V4L2_CID_PILOT_TONE_DEVIATION:949*property = SI4713_TX_PILOT_DEVIATION;950*mul = 10;951*shadow = &sdev->pilot_info.deviation;952break;953case V4L2_CID_AUDIO_LIMITER_DEVIATION:954*property = SI4713_TX_AUDIO_DEVIATION;955*mul = 10;956*shadow = &sdev->limiter_info.deviation;957break;958case V4L2_CID_RDS_TX_DEVIATION:959*property = SI4713_TX_RDS_DEVIATION;960*mul = 1;961*shadow = &sdev->rds_info.deviation;962break;963964case V4L2_CID_RDS_TX_PTY:965*property = SI4713_TX_RDS_PS_MISC;966*bit = 5;967*mask = 0x1F << 5;968*shadow = &sdev->rds_info.pty;969break;970case V4L2_CID_AUDIO_LIMITER_ENABLED:971*property = SI4713_TX_ACOMP_ENABLE;972*bit = 1;973*mask = 1 << 1;974*shadow = &sdev->limiter_info.enabled;975break;976case V4L2_CID_AUDIO_COMPRESSION_ENABLED:977*property = SI4713_TX_ACOMP_ENABLE;978*bit = 0;979*mask = 1 << 0;980*shadow = &sdev->acomp_info.enabled;981break;982case V4L2_CID_PILOT_TONE_ENABLED:983*property = SI4713_TX_COMPONENT_ENABLE;984*bit = 0;985*mask = 1 << 0;986*shadow = &sdev->pilot_info.enabled;987break;988989case V4L2_CID_AUDIO_LIMITER_RELEASE_TIME:990*property = SI4713_TX_LIMITER_RELEASE_TIME;991*table = limiter_times;992*size = ARRAY_SIZE(limiter_times);993*shadow = &sdev->limiter_info.release_time;994break;995case V4L2_CID_AUDIO_COMPRESSION_RELEASE_TIME:996*property = SI4713_TX_ACOMP_RELEASE_TIME;997*table = acomp_rtimes;998*size = ARRAY_SIZE(acomp_rtimes);999*shadow = &sdev->acomp_info.release_time;1000break;1001case V4L2_CID_TUNE_PREEMPHASIS:1002*property = SI4713_TX_PREEMPHASIS;1003*table = preemphasis_values;1004*size = ARRAY_SIZE(preemphasis_values);1005*shadow = &sdev->preemphasis;1006break;10071008default:1009rval = -EINVAL;1010};10111012return rval;1013}10141015static int si4713_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc);10161017/* write string property */1018static int si4713_write_econtrol_string(struct si4713_device *sdev,1019struct v4l2_ext_control *control)1020{1021struct v4l2_queryctrl vqc;1022int len;1023s32 rval = 0;10241025vqc.id = control->id;1026rval = si4713_queryctrl(&sdev->sd, &vqc);1027if (rval < 0)1028goto exit;10291030switch (control->id) {1031case V4L2_CID_RDS_TX_PS_NAME: {1032char ps_name[MAX_RDS_PS_NAME + 1];10331034len = control->size - 1;1035if (len < 0 || len > MAX_RDS_PS_NAME) {1036rval = -ERANGE;1037goto exit;1038}1039rval = copy_from_user(ps_name, control->string, len);1040if (rval) {1041rval = -EFAULT;1042goto exit;1043}1044ps_name[len] = '\0';10451046if (strlen(ps_name) % vqc.step) {1047rval = -ERANGE;1048goto exit;1049}10501051rval = si4713_set_rds_ps_name(sdev, ps_name);1052}1053break;10541055case V4L2_CID_RDS_TX_RADIO_TEXT: {1056char radio_text[MAX_RDS_RADIO_TEXT + 1];10571058len = control->size - 1;1059if (len < 0 || len > MAX_RDS_RADIO_TEXT) {1060rval = -ERANGE;1061goto exit;1062}1063rval = copy_from_user(radio_text, control->string, len);1064if (rval) {1065rval = -EFAULT;1066goto exit;1067}1068radio_text[len] = '\0';10691070if (strlen(radio_text) % vqc.step) {1071rval = -ERANGE;1072goto exit;1073}10741075rval = si4713_set_rds_radio_text(sdev, radio_text);1076}1077break;10781079default:1080rval = -EINVAL;1081break;1082};10831084exit:1085return rval;1086}10871088static int validate_range(struct v4l2_subdev *sd,1089struct v4l2_ext_control *control)1090{1091struct v4l2_queryctrl vqc;1092int rval;10931094vqc.id = control->id;1095rval = si4713_queryctrl(sd, &vqc);1096if (rval < 0)1097goto exit;10981099if (control->value < vqc.minimum || control->value > vqc.maximum)1100rval = -ERANGE;11011102exit:1103return rval;1104}11051106/* properties which use tx_tune_power*/1107static int si4713_write_econtrol_tune(struct si4713_device *sdev,1108struct v4l2_ext_control *control)1109{1110s32 rval = 0;1111u8 power, antcap;11121113rval = validate_range(&sdev->sd, control);1114if (rval < 0)1115goto exit;11161117mutex_lock(&sdev->mutex);11181119switch (control->id) {1120case V4L2_CID_TUNE_POWER_LEVEL:1121power = control->value;1122antcap = sdev->antenna_capacitor;1123break;1124case V4L2_CID_TUNE_ANTENNA_CAPACITOR:1125power = sdev->power_level;1126antcap = control->value;1127break;1128default:1129rval = -EINVAL;1130goto unlock;1131};11321133if (sdev->power_state)1134rval = si4713_tx_tune_power(sdev, power, antcap);11351136if (rval == 0) {1137sdev->power_level = power;1138sdev->antenna_capacitor = antcap;1139}11401141unlock:1142mutex_unlock(&sdev->mutex);1143exit:1144return rval;1145}11461147static int si4713_write_econtrol_integers(struct si4713_device *sdev,1148struct v4l2_ext_control *control)1149{1150s32 rval;1151u32 *shadow = NULL, val = 0;1152s32 bit = 0, mask = 0;1153u16 property = 0;1154int mul = 0;1155unsigned long *table = NULL;1156int size = 0;11571158rval = validate_range(&sdev->sd, control);1159if (rval < 0)1160goto exit;11611162rval = si4713_choose_econtrol_action(sdev, control->id, &shadow, &bit,1163&mask, &property, &mul, &table, &size);1164if (rval < 0)1165goto exit;11661167val = control->value;1168if (mul) {1169val = control->value / mul;1170} else if (table) {1171rval = usecs_to_dev(control->value, table, size);1172if (rval < 0)1173goto exit;1174val = rval;1175rval = 0;1176}11771178mutex_lock(&sdev->mutex);11791180if (sdev->power_state) {1181if (mask) {1182rval = si4713_read_property(sdev, property, &val);1183if (rval < 0)1184goto unlock;1185val = set_bits(val, control->value, bit, mask);1186}11871188rval = si4713_write_property(sdev, property, val);1189if (rval < 0)1190goto unlock;1191if (mask)1192val = control->value;1193}11941195if (mul) {1196*shadow = val * mul;1197} else if (table) {1198rval = dev_to_usecs(val, table, size);1199if (rval < 0)1200goto unlock;1201*shadow = rval;1202rval = 0;1203} else {1204*shadow = val;1205}12061207unlock:1208mutex_unlock(&sdev->mutex);1209exit:1210return rval;1211}12121213static int si4713_s_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *f);1214static int si4713_s_modulator(struct v4l2_subdev *sd, struct v4l2_modulator *);1215/*1216* si4713_setup - Sets the device up with current configuration.1217* @sdev: si4713_device structure for the device we are communicating1218*/1219static int si4713_setup(struct si4713_device *sdev)1220{1221struct v4l2_ext_control ctrl;1222struct v4l2_frequency f;1223struct v4l2_modulator vm;1224struct si4713_device *tmp;1225int rval = 0;12261227tmp = kmalloc(sizeof(*tmp), GFP_KERNEL);1228if (!tmp)1229return -ENOMEM;12301231/* Get a local copy to avoid race */1232mutex_lock(&sdev->mutex);1233memcpy(tmp, sdev, sizeof(*sdev));1234mutex_unlock(&sdev->mutex);12351236ctrl.id = V4L2_CID_RDS_TX_PI;1237ctrl.value = tmp->rds_info.pi;1238rval |= si4713_write_econtrol_integers(sdev, &ctrl);12391240ctrl.id = V4L2_CID_AUDIO_COMPRESSION_THRESHOLD;1241ctrl.value = tmp->acomp_info.threshold;1242rval |= si4713_write_econtrol_integers(sdev, &ctrl);12431244ctrl.id = V4L2_CID_AUDIO_COMPRESSION_GAIN;1245ctrl.value = tmp->acomp_info.gain;1246rval |= si4713_write_econtrol_integers(sdev, &ctrl);12471248ctrl.id = V4L2_CID_PILOT_TONE_FREQUENCY;1249ctrl.value = tmp->pilot_info.frequency;1250rval |= si4713_write_econtrol_integers(sdev, &ctrl);12511252ctrl.id = V4L2_CID_AUDIO_COMPRESSION_ATTACK_TIME;1253ctrl.value = tmp->acomp_info.attack_time;1254rval |= si4713_write_econtrol_integers(sdev, &ctrl);12551256ctrl.id = V4L2_CID_PILOT_TONE_DEVIATION;1257ctrl.value = tmp->pilot_info.deviation;1258rval |= si4713_write_econtrol_integers(sdev, &ctrl);12591260ctrl.id = V4L2_CID_AUDIO_LIMITER_DEVIATION;1261ctrl.value = tmp->limiter_info.deviation;1262rval |= si4713_write_econtrol_integers(sdev, &ctrl);12631264ctrl.id = V4L2_CID_RDS_TX_DEVIATION;1265ctrl.value = tmp->rds_info.deviation;1266rval |= si4713_write_econtrol_integers(sdev, &ctrl);12671268ctrl.id = V4L2_CID_RDS_TX_PTY;1269ctrl.value = tmp->rds_info.pty;1270rval |= si4713_write_econtrol_integers(sdev, &ctrl);12711272ctrl.id = V4L2_CID_AUDIO_LIMITER_ENABLED;1273ctrl.value = tmp->limiter_info.enabled;1274rval |= si4713_write_econtrol_integers(sdev, &ctrl);12751276ctrl.id = V4L2_CID_AUDIO_COMPRESSION_ENABLED;1277ctrl.value = tmp->acomp_info.enabled;1278rval |= si4713_write_econtrol_integers(sdev, &ctrl);12791280ctrl.id = V4L2_CID_PILOT_TONE_ENABLED;1281ctrl.value = tmp->pilot_info.enabled;1282rval |= si4713_write_econtrol_integers(sdev, &ctrl);12831284ctrl.id = V4L2_CID_AUDIO_LIMITER_RELEASE_TIME;1285ctrl.value = tmp->limiter_info.release_time;1286rval |= si4713_write_econtrol_integers(sdev, &ctrl);12871288ctrl.id = V4L2_CID_AUDIO_COMPRESSION_RELEASE_TIME;1289ctrl.value = tmp->acomp_info.release_time;1290rval |= si4713_write_econtrol_integers(sdev, &ctrl);12911292ctrl.id = V4L2_CID_TUNE_PREEMPHASIS;1293ctrl.value = tmp->preemphasis;1294rval |= si4713_write_econtrol_integers(sdev, &ctrl);12951296ctrl.id = V4L2_CID_RDS_TX_PS_NAME;1297rval |= si4713_set_rds_ps_name(sdev, tmp->rds_info.ps_name);12981299ctrl.id = V4L2_CID_RDS_TX_RADIO_TEXT;1300rval |= si4713_set_rds_radio_text(sdev, tmp->rds_info.radio_text);13011302/* Device procedure needs to set frequency first */1303f.frequency = tmp->frequency ? tmp->frequency : DEFAULT_FREQUENCY;1304f.frequency = si4713_to_v4l2(f.frequency);1305rval |= si4713_s_frequency(&sdev->sd, &f);13061307ctrl.id = V4L2_CID_TUNE_POWER_LEVEL;1308ctrl.value = tmp->power_level;1309rval |= si4713_write_econtrol_tune(sdev, &ctrl);13101311ctrl.id = V4L2_CID_TUNE_ANTENNA_CAPACITOR;1312ctrl.value = tmp->antenna_capacitor;1313rval |= si4713_write_econtrol_tune(sdev, &ctrl);13141315vm.index = 0;1316if (tmp->stereo)1317vm.txsubchans = V4L2_TUNER_SUB_STEREO;1318else1319vm.txsubchans = V4L2_TUNER_SUB_MONO;1320if (tmp->rds_info.enabled)1321vm.txsubchans |= V4L2_TUNER_SUB_RDS;1322si4713_s_modulator(&sdev->sd, &vm);13231324kfree(tmp);13251326return rval;1327}13281329/*1330* si4713_initialize - Sets the device up with default configuration.1331* @sdev: si4713_device structure for the device we are communicating1332*/1333static int si4713_initialize(struct si4713_device *sdev)1334{1335int rval;13361337rval = si4713_set_power_state(sdev, POWER_ON);1338if (rval < 0)1339goto exit;13401341rval = si4713_checkrev(sdev);1342if (rval < 0)1343goto exit;13441345rval = si4713_set_power_state(sdev, POWER_OFF);1346if (rval < 0)1347goto exit;13481349mutex_lock(&sdev->mutex);13501351sdev->rds_info.pi = DEFAULT_RDS_PI;1352sdev->rds_info.pty = DEFAULT_RDS_PTY;1353sdev->rds_info.deviation = DEFAULT_RDS_DEVIATION;1354strlcpy(sdev->rds_info.ps_name, DEFAULT_RDS_PS_NAME, MAX_RDS_PS_NAME);1355strlcpy(sdev->rds_info.radio_text, DEFAULT_RDS_RADIO_TEXT,1356MAX_RDS_RADIO_TEXT);1357sdev->rds_info.enabled = 1;13581359sdev->limiter_info.release_time = DEFAULT_LIMITER_RTIME;1360sdev->limiter_info.deviation = DEFAULT_LIMITER_DEV;1361sdev->limiter_info.enabled = 1;13621363sdev->pilot_info.deviation = DEFAULT_PILOT_DEVIATION;1364sdev->pilot_info.frequency = DEFAULT_PILOT_FREQUENCY;1365sdev->pilot_info.enabled = 1;13661367sdev->acomp_info.release_time = DEFAULT_ACOMP_RTIME;1368sdev->acomp_info.attack_time = DEFAULT_ACOMP_ATIME;1369sdev->acomp_info.threshold = DEFAULT_ACOMP_THRESHOLD;1370sdev->acomp_info.gain = DEFAULT_ACOMP_GAIN;1371sdev->acomp_info.enabled = 1;13721373sdev->frequency = DEFAULT_FREQUENCY;1374sdev->preemphasis = DEFAULT_PREEMPHASIS;1375sdev->mute = DEFAULT_MUTE;1376sdev->power_level = DEFAULT_POWER_LEVEL;1377sdev->antenna_capacitor = 0;1378sdev->stereo = 1;1379sdev->tune_rnl = DEFAULT_TUNE_RNL;13801381mutex_unlock(&sdev->mutex);13821383exit:1384return rval;1385}13861387/* read string property */1388static int si4713_read_econtrol_string(struct si4713_device *sdev,1389struct v4l2_ext_control *control)1390{1391s32 rval = 0;13921393switch (control->id) {1394case V4L2_CID_RDS_TX_PS_NAME:1395if (strlen(sdev->rds_info.ps_name) + 1 > control->size) {1396control->size = MAX_RDS_PS_NAME + 1;1397rval = -ENOSPC;1398goto exit;1399}1400rval = copy_to_user(control->string, sdev->rds_info.ps_name,1401strlen(sdev->rds_info.ps_name) + 1);1402if (rval)1403rval = -EFAULT;1404break;14051406case V4L2_CID_RDS_TX_RADIO_TEXT:1407if (strlen(sdev->rds_info.radio_text) + 1 > control->size) {1408control->size = MAX_RDS_RADIO_TEXT + 1;1409rval = -ENOSPC;1410goto exit;1411}1412rval = copy_to_user(control->string, sdev->rds_info.radio_text,1413strlen(sdev->rds_info.radio_text) + 1);1414if (rval)1415rval = -EFAULT;1416break;14171418default:1419rval = -EINVAL;1420break;1421};14221423exit:1424return rval;1425}14261427/*1428* si4713_update_tune_status - update properties from tx_tune_status1429* command. Must be called with sdev->mutex held.1430* @sdev: si4713_device structure for the device we are communicating1431*/1432static int si4713_update_tune_status(struct si4713_device *sdev)1433{1434int rval;1435u16 f = 0;1436u8 p = 0, a = 0, n = 0;14371438rval = si4713_tx_tune_status(sdev, 0x00, &f, &p, &a, &n);14391440if (rval < 0)1441goto exit;14421443sdev->power_level = p;1444sdev->antenna_capacitor = a;1445sdev->tune_rnl = n;14461447exit:1448return rval;1449}14501451/* properties which use tx_tune_status */1452static int si4713_read_econtrol_tune(struct si4713_device *sdev,1453struct v4l2_ext_control *control)1454{1455s32 rval = 0;14561457mutex_lock(&sdev->mutex);14581459if (sdev->power_state) {1460rval = si4713_update_tune_status(sdev);1461if (rval < 0)1462goto unlock;1463}14641465switch (control->id) {1466case V4L2_CID_TUNE_POWER_LEVEL:1467control->value = sdev->power_level;1468break;1469case V4L2_CID_TUNE_ANTENNA_CAPACITOR:1470control->value = sdev->antenna_capacitor;1471break;1472default:1473rval = -EINVAL;1474};14751476unlock:1477mutex_unlock(&sdev->mutex);1478return rval;1479}14801481static int si4713_read_econtrol_integers(struct si4713_device *sdev,1482struct v4l2_ext_control *control)1483{1484s32 rval;1485u32 *shadow = NULL, val = 0;1486s32 bit = 0, mask = 0;1487u16 property = 0;1488int mul = 0;1489unsigned long *table = NULL;1490int size = 0;14911492rval = si4713_choose_econtrol_action(sdev, control->id, &shadow, &bit,1493&mask, &property, &mul, &table, &size);1494if (rval < 0)1495goto exit;14961497mutex_lock(&sdev->mutex);14981499if (sdev->power_state) {1500rval = si4713_read_property(sdev, property, &val);1501if (rval < 0)1502goto unlock;15031504/* Keep negative values for threshold */1505if (control->id == V4L2_CID_AUDIO_COMPRESSION_THRESHOLD)1506*shadow = (s16)val;1507else if (mask)1508*shadow = get_status_bit(val, bit, mask);1509else if (mul)1510*shadow = val * mul;1511else1512*shadow = dev_to_usecs(val, table, size);1513}15141515control->value = *shadow;15161517unlock:1518mutex_unlock(&sdev->mutex);1519exit:1520return rval;1521}15221523/*1524* Video4Linux Subdev Interface1525*/1526/* si4713_s_ext_ctrls - set extended controls value */1527static int si4713_s_ext_ctrls(struct v4l2_subdev *sd,1528struct v4l2_ext_controls *ctrls)1529{1530struct si4713_device *sdev = to_si4713_device(sd);1531int i;15321533if (ctrls->ctrl_class != V4L2_CTRL_CLASS_FM_TX)1534return -EINVAL;15351536for (i = 0; i < ctrls->count; i++) {1537int err;15381539switch ((ctrls->controls + i)->id) {1540case V4L2_CID_RDS_TX_PS_NAME:1541case V4L2_CID_RDS_TX_RADIO_TEXT:1542err = si4713_write_econtrol_string(sdev,1543ctrls->controls + i);1544break;1545case V4L2_CID_TUNE_ANTENNA_CAPACITOR:1546case V4L2_CID_TUNE_POWER_LEVEL:1547err = si4713_write_econtrol_tune(sdev,1548ctrls->controls + i);1549break;1550default:1551err = si4713_write_econtrol_integers(sdev,1552ctrls->controls + i);1553}15541555if (err < 0) {1556ctrls->error_idx = i;1557return err;1558}1559}15601561return 0;1562}15631564/* si4713_g_ext_ctrls - get extended controls value */1565static int si4713_g_ext_ctrls(struct v4l2_subdev *sd,1566struct v4l2_ext_controls *ctrls)1567{1568struct si4713_device *sdev = to_si4713_device(sd);1569int i;15701571if (ctrls->ctrl_class != V4L2_CTRL_CLASS_FM_TX)1572return -EINVAL;15731574for (i = 0; i < ctrls->count; i++) {1575int err;15761577switch ((ctrls->controls + i)->id) {1578case V4L2_CID_RDS_TX_PS_NAME:1579case V4L2_CID_RDS_TX_RADIO_TEXT:1580err = si4713_read_econtrol_string(sdev,1581ctrls->controls + i);1582break;1583case V4L2_CID_TUNE_ANTENNA_CAPACITOR:1584case V4L2_CID_TUNE_POWER_LEVEL:1585err = si4713_read_econtrol_tune(sdev,1586ctrls->controls + i);1587break;1588default:1589err = si4713_read_econtrol_integers(sdev,1590ctrls->controls + i);1591}15921593if (err < 0) {1594ctrls->error_idx = i;1595return err;1596}1597}15981599return 0;1600}16011602/* si4713_queryctrl - enumerate control items */1603static int si4713_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc)1604{1605int rval = 0;16061607switch (qc->id) {1608/* User class controls */1609case V4L2_CID_AUDIO_MUTE:1610rval = v4l2_ctrl_query_fill(qc, 0, 1, 1, DEFAULT_MUTE);1611break;1612/* FM_TX class controls */1613case V4L2_CID_RDS_TX_PI:1614rval = v4l2_ctrl_query_fill(qc, 0, 0xFFFF, 1, DEFAULT_RDS_PI);1615break;1616case V4L2_CID_RDS_TX_PTY:1617rval = v4l2_ctrl_query_fill(qc, 0, 31, 1, DEFAULT_RDS_PTY);1618break;1619case V4L2_CID_RDS_TX_DEVIATION:1620rval = v4l2_ctrl_query_fill(qc, 0, MAX_RDS_DEVIATION,162110, DEFAULT_RDS_DEVIATION);1622break;1623case V4L2_CID_RDS_TX_PS_NAME:1624/*1625* Report step as 8. From RDS spec, psname1626* should be 8. But there are receivers which scroll strings1627* sized as 8xN.1628*/1629rval = v4l2_ctrl_query_fill(qc, 0, MAX_RDS_PS_NAME, 8, 0);1630break;1631case V4L2_CID_RDS_TX_RADIO_TEXT:1632/*1633* Report step as 32 (2A block). From RDS spec,1634* radio text should be 32 for 2A block. But there are receivers1635* which scroll strings sized as 32xN. Setting default to 32.1636*/1637rval = v4l2_ctrl_query_fill(qc, 0, MAX_RDS_RADIO_TEXT, 32, 0);1638break;16391640case V4L2_CID_AUDIO_LIMITER_ENABLED:1641rval = v4l2_ctrl_query_fill(qc, 0, 1, 1, 1);1642break;1643case V4L2_CID_AUDIO_LIMITER_RELEASE_TIME:1644rval = v4l2_ctrl_query_fill(qc, 250, MAX_LIMITER_RELEASE_TIME,164550, DEFAULT_LIMITER_RTIME);1646break;1647case V4L2_CID_AUDIO_LIMITER_DEVIATION:1648rval = v4l2_ctrl_query_fill(qc, 0, MAX_LIMITER_DEVIATION,164910, DEFAULT_LIMITER_DEV);1650break;16511652case V4L2_CID_AUDIO_COMPRESSION_ENABLED:1653rval = v4l2_ctrl_query_fill(qc, 0, 1, 1, 1);1654break;1655case V4L2_CID_AUDIO_COMPRESSION_GAIN:1656rval = v4l2_ctrl_query_fill(qc, 0, MAX_ACOMP_GAIN, 1,1657DEFAULT_ACOMP_GAIN);1658break;1659case V4L2_CID_AUDIO_COMPRESSION_THRESHOLD:1660rval = v4l2_ctrl_query_fill(qc, MIN_ACOMP_THRESHOLD,1661MAX_ACOMP_THRESHOLD, 1,1662DEFAULT_ACOMP_THRESHOLD);1663break;1664case V4L2_CID_AUDIO_COMPRESSION_ATTACK_TIME:1665rval = v4l2_ctrl_query_fill(qc, 0, MAX_ACOMP_ATTACK_TIME,1666500, DEFAULT_ACOMP_ATIME);1667break;1668case V4L2_CID_AUDIO_COMPRESSION_RELEASE_TIME:1669rval = v4l2_ctrl_query_fill(qc, 100000, MAX_ACOMP_RELEASE_TIME,1670100000, DEFAULT_ACOMP_RTIME);1671break;16721673case V4L2_CID_PILOT_TONE_ENABLED:1674rval = v4l2_ctrl_query_fill(qc, 0, 1, 1, 1);1675break;1676case V4L2_CID_PILOT_TONE_DEVIATION:1677rval = v4l2_ctrl_query_fill(qc, 0, MAX_PILOT_DEVIATION,167810, DEFAULT_PILOT_DEVIATION);1679break;1680case V4L2_CID_PILOT_TONE_FREQUENCY:1681rval = v4l2_ctrl_query_fill(qc, 0, MAX_PILOT_FREQUENCY,16821, DEFAULT_PILOT_FREQUENCY);1683break;16841685case V4L2_CID_TUNE_PREEMPHASIS:1686rval = v4l2_ctrl_query_fill(qc, V4L2_PREEMPHASIS_DISABLED,1687V4L2_PREEMPHASIS_75_uS, 1,1688V4L2_PREEMPHASIS_50_uS);1689break;1690case V4L2_CID_TUNE_POWER_LEVEL:1691rval = v4l2_ctrl_query_fill(qc, 0, 120, 1, DEFAULT_POWER_LEVEL);1692break;1693case V4L2_CID_TUNE_ANTENNA_CAPACITOR:1694rval = v4l2_ctrl_query_fill(qc, 0, 191, 1, 0);1695break;1696default:1697rval = -EINVAL;1698break;1699};17001701return rval;1702}17031704/* si4713_g_ctrl - get the value of a control */1705static int si4713_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)1706{1707struct si4713_device *sdev = to_si4713_device(sd);1708int rval = 0;17091710if (!sdev)1711return -ENODEV;17121713mutex_lock(&sdev->mutex);17141715if (sdev->power_state) {1716rval = si4713_read_property(sdev, SI4713_TX_LINE_INPUT_MUTE,1717&sdev->mute);17181719if (rval < 0)1720goto unlock;1721}17221723switch (ctrl->id) {1724case V4L2_CID_AUDIO_MUTE:1725ctrl->value = get_mute(sdev->mute);1726break;1727}17281729unlock:1730mutex_unlock(&sdev->mutex);1731return rval;1732}17331734/* si4713_s_ctrl - set the value of a control */1735static int si4713_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)1736{1737struct si4713_device *sdev = to_si4713_device(sd);1738int rval = 0;17391740if (!sdev)1741return -ENODEV;17421743switch (ctrl->id) {1744case V4L2_CID_AUDIO_MUTE:1745if (ctrl->value) {1746rval = si4713_set_mute(sdev, ctrl->value);1747if (rval < 0)1748goto exit;17491750rval = si4713_set_power_state(sdev, POWER_DOWN);1751} else {1752rval = si4713_set_power_state(sdev, POWER_UP);1753if (rval < 0)1754goto exit;17551756rval = si4713_setup(sdev);1757if (rval < 0)1758goto exit;17591760rval = si4713_set_mute(sdev, ctrl->value);1761}1762break;1763}17641765exit:1766return rval;1767}17681769/* si4713_ioctl - deal with private ioctls (only rnl for now) */1770long si4713_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)1771{1772struct si4713_device *sdev = to_si4713_device(sd);1773struct si4713_rnl *rnl = arg;1774u16 frequency;1775int rval = 0;17761777if (!arg)1778return -EINVAL;17791780mutex_lock(&sdev->mutex);1781switch (cmd) {1782case SI4713_IOC_MEASURE_RNL:1783frequency = v4l2_to_si4713(rnl->frequency);17841785if (sdev->power_state) {1786/* Set desired measurement frequency */1787rval = si4713_tx_tune_measure(sdev, frequency, 0);1788if (rval < 0)1789goto unlock;1790/* get results from tune status */1791rval = si4713_update_tune_status(sdev);1792if (rval < 0)1793goto unlock;1794}1795rnl->rnl = sdev->tune_rnl;1796break;17971798default:1799/* nothing */1800rval = -ENOIOCTLCMD;1801}18021803unlock:1804mutex_unlock(&sdev->mutex);1805return rval;1806}18071808static const struct v4l2_subdev_core_ops si4713_subdev_core_ops = {1809.queryctrl = si4713_queryctrl,1810.g_ext_ctrls = si4713_g_ext_ctrls,1811.s_ext_ctrls = si4713_s_ext_ctrls,1812.g_ctrl = si4713_g_ctrl,1813.s_ctrl = si4713_s_ctrl,1814.ioctl = si4713_ioctl,1815};18161817/* si4713_g_modulator - get modulator attributes */1818static int si4713_g_modulator(struct v4l2_subdev *sd, struct v4l2_modulator *vm)1819{1820struct si4713_device *sdev = to_si4713_device(sd);1821int rval = 0;18221823if (!sdev) {1824rval = -ENODEV;1825goto exit;1826}18271828if (vm->index > 0) {1829rval = -EINVAL;1830goto exit;1831}18321833strncpy(vm->name, "FM Modulator", 32);1834vm->capability = V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LOW |1835V4L2_TUNER_CAP_RDS | V4L2_TUNER_CAP_RDS_CONTROLS;18361837/* Report current frequency range limits */1838vm->rangelow = si4713_to_v4l2(FREQ_RANGE_LOW);1839vm->rangehigh = si4713_to_v4l2(FREQ_RANGE_HIGH);18401841mutex_lock(&sdev->mutex);18421843if (sdev->power_state) {1844u32 comp_en = 0;18451846rval = si4713_read_property(sdev, SI4713_TX_COMPONENT_ENABLE,1847&comp_en);1848if (rval < 0)1849goto unlock;18501851sdev->stereo = get_status_bit(comp_en, 1, 1 << 1);1852sdev->rds_info.enabled = get_status_bit(comp_en, 2, 1 << 2);1853}18541855/* Report current audio mode: mono or stereo */1856if (sdev->stereo)1857vm->txsubchans = V4L2_TUNER_SUB_STEREO;1858else1859vm->txsubchans = V4L2_TUNER_SUB_MONO;18601861/* Report rds feature status */1862if (sdev->rds_info.enabled)1863vm->txsubchans |= V4L2_TUNER_SUB_RDS;1864else1865vm->txsubchans &= ~V4L2_TUNER_SUB_RDS;18661867unlock:1868mutex_unlock(&sdev->mutex);1869exit:1870return rval;1871}18721873/* si4713_s_modulator - set modulator attributes */1874static int si4713_s_modulator(struct v4l2_subdev *sd, struct v4l2_modulator *vm)1875{1876struct si4713_device *sdev = to_si4713_device(sd);1877int rval = 0;1878u16 stereo, rds;1879u32 p;18801881if (!sdev)1882return -ENODEV;18831884if (vm->index > 0)1885return -EINVAL;18861887/* Set audio mode: mono or stereo */1888if (vm->txsubchans & V4L2_TUNER_SUB_STEREO)1889stereo = 1;1890else if (vm->txsubchans & V4L2_TUNER_SUB_MONO)1891stereo = 0;1892else1893return -EINVAL;18941895rds = !!(vm->txsubchans & V4L2_TUNER_SUB_RDS);18961897mutex_lock(&sdev->mutex);18981899if (sdev->power_state) {1900rval = si4713_read_property(sdev,1901SI4713_TX_COMPONENT_ENABLE, &p);1902if (rval < 0)1903goto unlock;19041905p = set_bits(p, stereo, 1, 1 << 1);1906p = set_bits(p, rds, 2, 1 << 2);19071908rval = si4713_write_property(sdev,1909SI4713_TX_COMPONENT_ENABLE, p);1910if (rval < 0)1911goto unlock;1912}19131914sdev->stereo = stereo;1915sdev->rds_info.enabled = rds;19161917unlock:1918mutex_unlock(&sdev->mutex);1919return rval;1920}19211922/* si4713_g_frequency - get tuner or modulator radio frequency */1923static int si4713_g_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *f)1924{1925struct si4713_device *sdev = to_si4713_device(sd);1926int rval = 0;19271928f->type = V4L2_TUNER_RADIO;19291930mutex_lock(&sdev->mutex);19311932if (sdev->power_state) {1933u16 freq;1934u8 p, a, n;19351936rval = si4713_tx_tune_status(sdev, 0x00, &freq, &p, &a, &n);1937if (rval < 0)1938goto unlock;19391940sdev->frequency = freq;1941}19421943f->frequency = si4713_to_v4l2(sdev->frequency);19441945unlock:1946mutex_unlock(&sdev->mutex);1947return rval;1948}19491950/* si4713_s_frequency - set tuner or modulator radio frequency */1951static int si4713_s_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *f)1952{1953struct si4713_device *sdev = to_si4713_device(sd);1954int rval = 0;1955u16 frequency = v4l2_to_si4713(f->frequency);19561957/* Check frequency range */1958if (frequency < FREQ_RANGE_LOW || frequency > FREQ_RANGE_HIGH)1959return -EDOM;19601961mutex_lock(&sdev->mutex);19621963if (sdev->power_state) {1964rval = si4713_tx_tune_freq(sdev, frequency);1965if (rval < 0)1966goto unlock;1967frequency = rval;1968rval = 0;1969}1970sdev->frequency = frequency;1971f->frequency = si4713_to_v4l2(frequency);19721973unlock:1974mutex_unlock(&sdev->mutex);1975return rval;1976}19771978static const struct v4l2_subdev_tuner_ops si4713_subdev_tuner_ops = {1979.g_frequency = si4713_g_frequency,1980.s_frequency = si4713_s_frequency,1981.g_modulator = si4713_g_modulator,1982.s_modulator = si4713_s_modulator,1983};19841985static const struct v4l2_subdev_ops si4713_subdev_ops = {1986.core = &si4713_subdev_core_ops,1987.tuner = &si4713_subdev_tuner_ops,1988};19891990/*1991* I2C driver interface1992*/1993/* si4713_probe - probe for the device */1994static int si4713_probe(struct i2c_client *client,1995const struct i2c_device_id *id)1996{1997struct si4713_device *sdev;1998struct si4713_platform_data *pdata = client->dev.platform_data;1999int rval, i;20002001sdev = kzalloc(sizeof *sdev, GFP_KERNEL);2002if (!sdev) {2003dev_err(&client->dev, "Failed to alloc video device.\n");2004rval = -ENOMEM;2005goto exit;2006}20072008sdev->gpio_reset = -1;2009if (pdata && gpio_is_valid(pdata->gpio_reset)) {2010rval = gpio_request(pdata->gpio_reset, "si4713 reset");2011if (rval) {2012dev_err(&client->dev,2013"Failed to request gpio: %d\n", rval);2014goto free_sdev;2015}2016sdev->gpio_reset = pdata->gpio_reset;2017gpio_direction_output(sdev->gpio_reset, 0);2018}20192020for (i = 0; i < ARRAY_SIZE(sdev->supplies); i++)2021sdev->supplies[i].supply = si4713_supply_names[i];20222023rval = regulator_bulk_get(&client->dev, ARRAY_SIZE(sdev->supplies),2024sdev->supplies);2025if (rval) {2026dev_err(&client->dev, "Cannot get regulators: %d\n", rval);2027goto free_gpio;2028}20292030v4l2_i2c_subdev_init(&sdev->sd, client, &si4713_subdev_ops);20312032mutex_init(&sdev->mutex);2033init_completion(&sdev->work);20342035if (client->irq) {2036rval = request_irq(client->irq,2037si4713_handler, IRQF_TRIGGER_FALLING | IRQF_DISABLED,2038client->name, sdev);2039if (rval < 0) {2040v4l2_err(&sdev->sd, "Could not request IRQ\n");2041goto put_reg;2042}2043v4l2_dbg(1, debug, &sdev->sd, "IRQ requested.\n");2044} else {2045v4l2_warn(&sdev->sd, "IRQ not configured. Using timeouts.\n");2046}20472048rval = si4713_initialize(sdev);2049if (rval < 0) {2050v4l2_err(&sdev->sd, "Failed to probe device information.\n");2051goto free_irq;2052}20532054return 0;20552056free_irq:2057if (client->irq)2058free_irq(client->irq, sdev);2059put_reg:2060regulator_bulk_free(ARRAY_SIZE(sdev->supplies), sdev->supplies);2061free_gpio:2062if (gpio_is_valid(sdev->gpio_reset))2063gpio_free(sdev->gpio_reset);2064free_sdev:2065kfree(sdev);2066exit:2067return rval;2068}20692070/* si4713_remove - remove the device */2071static int si4713_remove(struct i2c_client *client)2072{2073struct v4l2_subdev *sd = i2c_get_clientdata(client);2074struct si4713_device *sdev = to_si4713_device(sd);20752076if (sdev->power_state)2077si4713_set_power_state(sdev, POWER_DOWN);20782079if (client->irq > 0)2080free_irq(client->irq, sdev);20812082v4l2_device_unregister_subdev(sd);2083regulator_bulk_free(ARRAY_SIZE(sdev->supplies), sdev->supplies);2084if (gpio_is_valid(sdev->gpio_reset))2085gpio_free(sdev->gpio_reset);2086kfree(sdev);20872088return 0;2089}20902091/* si4713_i2c_driver - i2c driver interface */2092static const struct i2c_device_id si4713_id[] = {2093{ "si4713" , 0 },2094{ },2095};2096MODULE_DEVICE_TABLE(i2c, si4713_id);20972098static struct i2c_driver si4713_i2c_driver = {2099.driver = {2100.name = "si4713",2101},2102.probe = si4713_probe,2103.remove = si4713_remove,2104.id_table = si4713_id,2105};21062107/* Module Interface */2108static int __init si4713_module_init(void)2109{2110return i2c_add_driver(&si4713_i2c_driver);2111}21122113static void __exit si4713_module_exit(void)2114{2115i2c_del_driver(&si4713_i2c_driver);2116}21172118module_init(si4713_module_init);2119module_exit(si4713_module_exit);2120212121222123