// SPDX-License-Identifier: GPL-2.0-or-later /* * drivers/media/radio/si4713-i2c.c * * Silicon Labs Si4713 FM Radio Transmitter I2C commands. * * Copyright (c) 2009 Nokia Corporation * Contact: Eduardo Valentin <[email protected]> */ #include <linux/completion.h> #include <linux/delay.h> #include <linux/err.h> #include <linux/interrupt.h> #include <linux/i2c.h> #include <linux/slab.h> #include <linux/gpio/consumer.h> #include <linux/module.h> #include <media/v4l2-device.h> #include <media/v4l2-ioctl.h> #include <media/v4l2-common.h> #include "si4713.h" /* module parameters */ static int debug; module_param(debug, int, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(…) …; MODULE_LICENSE(…) …; MODULE_AUTHOR(…) …; MODULE_DESCRIPTION(…) …; MODULE_VERSION(…) …; #define DEFAULT_RDS_PI … #define DEFAULT_RDS_PTY … #define DEFAULT_RDS_DEVIATION … #define DEFAULT_RDS_PS_REPEAT_COUNT … #define DEFAULT_LIMITER_RTIME … #define DEFAULT_LIMITER_DEV … #define DEFAULT_PILOT_FREQUENCY … #define DEFAULT_PILOT_DEVIATION … #define DEFAULT_ACOMP_ATIME … #define DEFAULT_ACOMP_RTIME … #define DEFAULT_ACOMP_GAIN … #define DEFAULT_ACOMP_THRESHOLD … #define DEFAULT_MUTE … #define DEFAULT_POWER_LEVEL … #define DEFAULT_FREQUENCY … #define DEFAULT_PREEMPHASIS … #define DEFAULT_TUNE_RNL … #define to_si4713_device(sd) … /* frequency domain transformation (using times 10 to avoid floats) */ #define FREQDEV_UNIT … #define FREQV4L2_MULTI … #define si4713_to_v4l2(f) … #define v4l2_to_si4713(f) … #define FREQ_RANGE_LOW … #define FREQ_RANGE_HIGH … #define MAX_ARGS … #define RDS_BLOCK … #define RDS_BLOCK_CLEAR … #define RDS_BLOCK_LOAD … #define RDS_RADIOTEXT_2A … #define RDS_RADIOTEXT_BLK_SIZE … #define RDS_RADIOTEXT_INDEX_MAX … #define RDS_CARRIAGE_RETURN … #define rds_ps_nblocks(len) … #define get_status_bit(p, b, m) … #define set_bits(p, v, b, m) … #define ATTACK_TIME_UNIT … #define POWER_OFF … #define POWER_ON … #define msb(x) … #define lsb(x) … #define compose_u16(msb, lsb) … #define check_command_failed(status) … /* mute definition */ #define set_mute(p) … #ifdef DEBUG #define DBG_BUFFER … #else #define DBG_BUFFER(device, message, buffer, size) … #endif /* * Values for limiter release time (sorted by second column) * device release * value time (us) */ static long limiter_times[] = …; /* * Values for audio compression release time (sorted by second column) * device release * value time (us) */ static unsigned long acomp_rtimes[] = …; /* * Values for preemphasis (sorted by second column) * device preemphasis * value value (v4l2) */ static unsigned long preemphasis_values[] = …; static int usecs_to_dev(unsigned long usecs, unsigned long const array[], int size) { … } /* si4713_handler: IRQ handler, just complete work */ static irqreturn_t si4713_handler(int irq, void *dev) { … } /* * si4713_send_command - sends a command to si4713 and waits its response * @sdev: si4713_device structure for the device we are communicating * @command: command id * @args: command arguments we are sending (up to 7) * @argn: actual size of @args * @response: buffer to place the expected response from the device (up to 15) * @respn: actual size of @response * @usecs: amount of time to wait before reading the response (in usecs) */ static int si4713_send_command(struct si4713_device *sdev, const u8 command, const u8 args[], const int argn, u8 response[], const int respn, const int usecs) { … } /* * si4713_read_property - reads a si4713 property * @sdev: si4713_device structure for the device we are communicating * @prop: property identification number * @pv: property value to be returned on success */ static int si4713_read_property(struct si4713_device *sdev, u16 prop, u32 *pv) { … } /* * si4713_write_property - modifies a si4713 property * @sdev: si4713_device structure for the device we are communicating * @prop: property identification number * @val: new value for that property */ static int si4713_write_property(struct si4713_device *sdev, u16 prop, u16 val) { … } /* * si4713_powerup - Powers the device up * @sdev: si4713_device structure for the device we are communicating */ static int si4713_powerup(struct si4713_device *sdev) { … } /* * si4713_powerdown - Powers the device down * @sdev: si4713_device structure for the device we are communicating */ static int si4713_powerdown(struct si4713_device *sdev) { … } /* * si4713_checkrev - Checks if we are treating a device with the correct rev. * @sdev: si4713_device structure for the device we are communicating */ static int si4713_checkrev(struct si4713_device *sdev) { … } /* * si4713_wait_stc - Waits STC interrupt and clears status bits. Useful * for TX_TUNE_POWER, TX_TUNE_FREQ and TX_TUNE_MEAS * @sdev: si4713_device structure for the device we are communicating * @usecs: timeout to wait for STC interrupt signal */ static int si4713_wait_stc(struct si4713_device *sdev, const int usecs) { … } /* * si4713_tx_tune_freq - Sets the state of the RF carrier and sets the tuning * frequency between 76 and 108 MHz in 10 kHz units and * steps of 50 kHz. * @sdev: si4713_device structure for the device we are communicating * @frequency: desired frequency (76 - 108 MHz, unit 10 KHz, step 50 kHz) */ static int si4713_tx_tune_freq(struct si4713_device *sdev, u16 frequency) { … } /* * si4713_tx_tune_power - Sets the RF voltage level between 88 and 120 dBuV in * 1 dB units. A value of 0x00 indicates off. The command * also sets the antenna tuning capacitance. A value of 0 * indicates autotuning, and a value of 1 - 191 indicates * a manual override, which results in a tuning * capacitance of 0.25 pF x @antcap. * @sdev: si4713_device structure for the device we are communicating * @power: tuning power (88 - 120 dBuV, unit/step 1 dB) * @antcap: value of antenna tuning capacitor (0 - 191) */ static int si4713_tx_tune_power(struct si4713_device *sdev, u8 power, u8 antcap) { … } /* * si4713_tx_tune_measure - Enters receive mode and measures the received noise * level in units of dBuV on the selected frequency. * The Frequency must be between 76 and 108 MHz in 10 kHz * units and steps of 50 kHz. The command also sets the * antenna tuning capacitance. A value of 0 means * autotuning, and a value of 1 to 191 indicates manual * override. * @sdev: si4713_device structure for the device we are communicating * @frequency: desired frequency (76 - 108 MHz, unit 10 KHz, step 50 kHz) * @antcap: value of antenna tuning capacitor (0 - 191) */ static int si4713_tx_tune_measure(struct si4713_device *sdev, u16 frequency, u8 antcap) { … } /* * si4713_tx_tune_status- Returns the status of the tx_tune_freq, tx_tune_mea or * tx_tune_power commands. This command return the current * frequency, output voltage in dBuV, the antenna tunning * capacitance value and the received noise level. The * command also clears the stcint interrupt bit when the * first bit of its arguments is high. * @sdev: si4713_device structure for the device we are communicating * @intack: 0x01 to clear the seek/tune complete interrupt status indicator. * @frequency: returned frequency * @power: returned power * @antcap: returned antenna capacitance * @noise: returned noise level */ static int si4713_tx_tune_status(struct si4713_device *sdev, u8 intack, u16 *frequency, u8 *power, u8 *antcap, u8 *noise) { … } /* * si4713_tx_rds_buff - Loads the RDS group buffer FIFO or circular buffer. * @sdev: si4713_device structure for the device we are communicating * @mode: the buffer operation mode. * @rdsb: RDS Block B * @rdsc: RDS Block C * @rdsd: RDS Block D * @cbleft: returns the number of available circular buffer blocks minus the * number of used circular buffer blocks. */ static int si4713_tx_rds_buff(struct si4713_device *sdev, u8 mode, u16 rdsb, u16 rdsc, u16 rdsd, s8 *cbleft) { … } /* * si4713_tx_rds_ps - Loads the program service buffer. * @sdev: si4713_device structure for the device we are communicating * @psid: program service id to be loaded. * @pschar: assumed 4 size char array to be loaded into the program service */ static int si4713_tx_rds_ps(struct si4713_device *sdev, u8 psid, unsigned char *pschar) { … } static int si4713_set_power_state(struct si4713_device *sdev, u8 value) { … } static int si4713_set_mute(struct si4713_device *sdev, u16 mute) { … } static int si4713_set_rds_ps_name(struct si4713_device *sdev, char *ps_name) { … } static int si4713_set_rds_radio_text(struct si4713_device *sdev, const char *rt) { … } /* * si4713_update_tune_status - update properties from tx_tune_status * command. Must be called with sdev->mutex held. * @sdev: si4713_device structure for the device we are communicating */ static int si4713_update_tune_status(struct si4713_device *sdev) { … } static int si4713_choose_econtrol_action(struct si4713_device *sdev, u32 id, s32 *bit, s32 *mask, u16 *property, int *mul, unsigned long **table, int *size) { … } static int si4713_s_frequency(struct v4l2_subdev *sd, const struct v4l2_frequency *f); static int si4713_s_modulator(struct v4l2_subdev *sd, const struct v4l2_modulator *); /* * si4713_setup - Sets the device up with current configuration. * @sdev: si4713_device structure for the device we are communicating */ static int si4713_setup(struct si4713_device *sdev) { … } /* * si4713_initialize - Sets the device up with default configuration. * @sdev: si4713_device structure for the device we are communicating */ static int si4713_initialize(struct si4713_device *sdev) { … } /* si4713_s_ctrl - set the value of a control */ static int si4713_s_ctrl(struct v4l2_ctrl *ctrl) { … } /* si4713_ioctl - deal with private ioctls (only rnl for now) */ static long si4713_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) { … } /* si4713_g_modulator - get modulator attributes */ static int si4713_g_modulator(struct v4l2_subdev *sd, struct v4l2_modulator *vm) { … } /* si4713_s_modulator - set modulator attributes */ static int si4713_s_modulator(struct v4l2_subdev *sd, const struct v4l2_modulator *vm) { … } /* si4713_g_frequency - get tuner or modulator radio frequency */ static int si4713_g_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *f) { … } /* si4713_s_frequency - set tuner or modulator radio frequency */ static int si4713_s_frequency(struct v4l2_subdev *sd, const struct v4l2_frequency *f) { … } static const struct v4l2_ctrl_ops si4713_ctrl_ops = …; static const struct v4l2_subdev_core_ops si4713_subdev_core_ops = …; static const struct v4l2_subdev_tuner_ops si4713_subdev_tuner_ops = …; static const struct v4l2_subdev_ops si4713_subdev_ops = …; static const struct v4l2_ctrl_config si4713_alt_freqs_ctrl = …; /* * I2C driver interface */ /* si4713_probe - probe for the device */ static int si4713_probe(struct i2c_client *client) { … } /* si4713_remove - remove the device */ static void si4713_remove(struct i2c_client *client) { … } /* si4713_i2c_driver - i2c driver interface */ static const struct i2c_device_id si4713_id[] = …; MODULE_DEVICE_TABLE(i2c, si4713_id); #if IS_ENABLED(CONFIG_OF) static const struct of_device_id si4713_of_match[] = …; MODULE_DEVICE_TABLE(of, si4713_of_match); #endif static struct i2c_driver si4713_i2c_driver = …; module_i2c_driver(…) …;