^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * drivers/media/radio/si4713-i2c.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Silicon Labs Si4713 FM Radio Transmitter I2C commands.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Copyright (c) 2009 Nokia Corporation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Contact: Eduardo Valentin <eduardo.valentin@nokia.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/completion.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/i2c.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/gpio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <media/v4l2-device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <media/v4l2-ioctl.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <media/v4l2-common.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include "si4713.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) /* module parameters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) static int debug;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) module_param(debug, int, S_IRUGO | S_IWUSR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) MODULE_PARM_DESC(debug, "Debug level (0 - 2)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) MODULE_AUTHOR("Eduardo Valentin <eduardo.valentin@nokia.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) MODULE_DESCRIPTION("I2C driver for Si4713 FM Radio Transmitter");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) MODULE_VERSION("0.0.1");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define DEFAULT_RDS_PI 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define DEFAULT_RDS_PTY 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define DEFAULT_RDS_DEVIATION 0x00C8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define DEFAULT_RDS_PS_REPEAT_COUNT 0x0003
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define DEFAULT_LIMITER_RTIME 0x1392
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #define DEFAULT_LIMITER_DEV 0x102CA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #define DEFAULT_PILOT_FREQUENCY 0x4A38
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #define DEFAULT_PILOT_DEVIATION 0x1A5E
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #define DEFAULT_ACOMP_ATIME 0x0000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #define DEFAULT_ACOMP_RTIME 0xF4240L
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #define DEFAULT_ACOMP_GAIN 0x0F
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #define DEFAULT_ACOMP_THRESHOLD (-0x28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #define DEFAULT_MUTE 0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #define DEFAULT_POWER_LEVEL 88
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #define DEFAULT_FREQUENCY 8800
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #define DEFAULT_PREEMPHASIS FMPE_EU
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #define DEFAULT_TUNE_RNL 0xFF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #define to_si4713_device(sd) container_of(sd, struct si4713_device, sd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) /* frequency domain transformation (using times 10 to avoid floats) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #define FREQDEV_UNIT 100000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #define FREQV4L2_MULTI 625
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #define si4713_to_v4l2(f) ((f * FREQDEV_UNIT) / FREQV4L2_MULTI)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #define v4l2_to_si4713(f) ((f * FREQV4L2_MULTI) / FREQDEV_UNIT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #define FREQ_RANGE_LOW 7600
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #define FREQ_RANGE_HIGH 10800
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) #define MAX_ARGS 7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) #define RDS_BLOCK 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) #define RDS_BLOCK_CLEAR 0x03
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) #define RDS_BLOCK_LOAD 0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) #define RDS_RADIOTEXT_2A 0x20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) #define RDS_RADIOTEXT_BLK_SIZE 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) #define RDS_RADIOTEXT_INDEX_MAX 0x0F
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) #define RDS_CARRIAGE_RETURN 0x0D
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) #define rds_ps_nblocks(len) ((len / RDS_BLOCK) + (len % RDS_BLOCK ? 1 : 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) #define get_status_bit(p, b, m) (((p) & (m)) >> (b))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) #define set_bits(p, v, b, m) (((p) & ~(m)) | ((v) << (b)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) #define ATTACK_TIME_UNIT 500
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) #define POWER_OFF 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) #define POWER_ON 0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) #define msb(x) ((u8)((u16) x >> 8))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) #define lsb(x) ((u8)((u16) x & 0x00FF))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) #define compose_u16(msb, lsb) (((u16)msb << 8) | lsb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) #define check_command_failed(status) (!(status & SI4713_CTS) || \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) (status & SI4713_ERR))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) /* mute definition */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) #define set_mute(p) ((p & 1) | ((p & 1) << 1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) #ifdef DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) #define DBG_BUFFER(device, message, buffer, size) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) int i; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) char str[(size)*5]; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) for (i = 0; i < size; i++) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) sprintf(str + i * 5, " 0x%02x", buffer[i]); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) v4l2_dbg(2, debug, device, "%s:%s\n", message, str); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) #define DBG_BUFFER(device, message, buffer, size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) * Values for limiter release time (sorted by second column)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) * device release
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) * value time (us)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) static long limiter_times[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 2000, 250,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 1000, 500,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 510, 1000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 255, 2000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 170, 3000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 127, 4020,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 102, 5010,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 85, 6020,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 73, 7010,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 64, 7990,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 57, 8970,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 51, 10030,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 25, 20470,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 17, 30110,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 13, 39380,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 10, 51190,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 8, 63690,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 7, 73140,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 6, 85330,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 5, 102390,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) * Values for audio compression release time (sorted by second column)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) * device release
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) * value time (us)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) static unsigned long acomp_rtimes[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 0, 100000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 1, 200000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 2, 350000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 3, 525000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 4, 1000000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) * Values for preemphasis (sorted by second column)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) * device preemphasis
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) * value value (v4l2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) static unsigned long preemphasis_values[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) FMPE_DISABLED, V4L2_PREEMPHASIS_DISABLED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) FMPE_EU, V4L2_PREEMPHASIS_50_uS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) FMPE_USA, V4L2_PREEMPHASIS_75_uS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) static int usecs_to_dev(unsigned long usecs, unsigned long const array[],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) int size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) int rval = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) for (i = 0; i < size / 2; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) if (array[(i * 2) + 1] >= usecs) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) rval = array[i * 2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) return rval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) /* si4713_handler: IRQ handler, just complete work */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) static irqreturn_t si4713_handler(int irq, void *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) struct si4713_device *sdev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) v4l2_dbg(2, debug, &sdev->sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) "%s: sending signal to completion work.\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) complete(&sdev->work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) * si4713_send_command - sends a command to si4713 and waits its response
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) * @sdev: si4713_device structure for the device we are communicating
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) * @command: command id
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) * @args: command arguments we are sending (up to 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) * @argn: actual size of @args
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) * @response: buffer to place the expected response from the device (up to 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) * @respn: actual size of @response
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) * @usecs: amount of time to wait before reading the response (in usecs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) static int si4713_send_command(struct si4713_device *sdev, const u8 command,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) const u8 args[], const int argn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) u8 response[], const int respn, const int usecs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) struct i2c_client *client = v4l2_get_subdevdata(&sdev->sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) unsigned long until_jiffies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) u8 data1[MAX_ARGS + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) if (!client->adapter)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) /* First send the command and its arguments */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) data1[0] = command;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) memcpy(data1 + 1, args, argn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) DBG_BUFFER(&sdev->sd, "Parameters", data1, argn + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) err = i2c_master_send(client, data1, argn + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) if (err != argn + 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) v4l2_err(&sdev->sd, "Error while sending command 0x%02x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) command);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) return err < 0 ? err : -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) until_jiffies = jiffies + usecs_to_jiffies(usecs) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) /* Wait response from interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) if (client->irq) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) if (!wait_for_completion_timeout(&sdev->work,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) usecs_to_jiffies(usecs) + 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) v4l2_warn(&sdev->sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) "(%s) Device took too much time to answer.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) err = i2c_master_recv(client, response, respn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) if (err != respn) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) v4l2_err(&sdev->sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) "Error %d while reading response for command 0x%02x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) err, command);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) return err < 0 ? err : -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) DBG_BUFFER(&sdev->sd, "Response", response, respn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) if (!check_command_failed(response[0]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) if (client->irq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) if (usecs <= 1000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) usleep_range(usecs, 1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) usleep_range(1000, 2000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) } while (time_is_after_jiffies(until_jiffies));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) * si4713_read_property - reads a si4713 property
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) * @sdev: si4713_device structure for the device we are communicating
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) * @prop: property identification number
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) * @pv: property value to be returned on success
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) static int si4713_read_property(struct si4713_device *sdev, u16 prop, u32 *pv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) u8 val[SI4713_GET_PROP_NRESP];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) * .First byte = 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) * .Second byte = property's MSB
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) * .Third byte = property's LSB
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) const u8 args[SI4713_GET_PROP_NARGS] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) msb(prop),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) lsb(prop),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) err = si4713_send_command(sdev, SI4713_CMD_GET_PROPERTY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) args, ARRAY_SIZE(args), val,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) ARRAY_SIZE(val), DEFAULT_TIMEOUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) *pv = compose_u16(val[2], val[3]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) v4l2_dbg(1, debug, &sdev->sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) "%s: property=0x%02x value=0x%02x status=0x%02x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) __func__, prop, *pv, val[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) * si4713_write_property - modifies a si4713 property
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) * @sdev: si4713_device structure for the device we are communicating
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) * @prop: property identification number
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) * @val: new value for that property
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) static int si4713_write_property(struct si4713_device *sdev, u16 prop, u16 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) int rval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) u8 resp[SI4713_SET_PROP_NRESP];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) * .First byte = 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) * .Second byte = property's MSB
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) * .Third byte = property's LSB
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) * .Fourth byte = value's MSB
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) * .Fifth byte = value's LSB
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) const u8 args[SI4713_SET_PROP_NARGS] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) msb(prop),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) lsb(prop),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) msb(val),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) lsb(val),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) rval = si4713_send_command(sdev, SI4713_CMD_SET_PROPERTY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) args, ARRAY_SIZE(args),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) resp, ARRAY_SIZE(resp),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) DEFAULT_TIMEOUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) if (rval < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) return rval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) v4l2_dbg(1, debug, &sdev->sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) "%s: property=0x%02x value=0x%02x status=0x%02x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) __func__, prop, val, resp[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) * As there is no command response for SET_PROPERTY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) * wait Tcomp time to finish before proceed, in order
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) * to have property properly set.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) msleep(TIMEOUT_SET_PROPERTY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) return rval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) * si4713_powerup - Powers the device up
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) * @sdev: si4713_device structure for the device we are communicating
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) static int si4713_powerup(struct si4713_device *sdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) struct i2c_client *client = v4l2_get_subdevdata(&sdev->sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) u8 resp[SI4713_PWUP_NRESP];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) * .First byte = Enabled interrupts and boot function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) * .Second byte = Input operation mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) u8 args[SI4713_PWUP_NARGS] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) SI4713_PWUP_GPO2OEN | SI4713_PWUP_FUNC_TX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) SI4713_PWUP_OPMOD_ANALOG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) if (sdev->power_state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) if (sdev->vdd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) err = regulator_enable(sdev->vdd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) v4l2_err(&sdev->sd, "Failed to enable vdd: %d\n", err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) if (sdev->vio) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) err = regulator_enable(sdev->vio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) v4l2_err(&sdev->sd, "Failed to enable vio: %d\n", err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) if (sdev->gpio_reset) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) udelay(50);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) gpiod_set_value(sdev->gpio_reset, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) if (client->irq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) args[0] |= SI4713_PWUP_CTSIEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) err = si4713_send_command(sdev, SI4713_CMD_POWER_UP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) args, ARRAY_SIZE(args),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) resp, ARRAY_SIZE(resp),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) TIMEOUT_POWER_UP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) if (!err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) v4l2_dbg(1, debug, &sdev->sd, "Powerup response: 0x%02x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) resp[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) v4l2_dbg(1, debug, &sdev->sd, "Device in power up mode\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) sdev->power_state = POWER_ON;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) if (client->irq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) err = si4713_write_property(sdev, SI4713_GPO_IEN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) SI4713_STC_INT | SI4713_CTS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) gpiod_set_value(sdev->gpio_reset, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) if (sdev->vdd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) err = regulator_disable(sdev->vdd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) v4l2_err(&sdev->sd, "Failed to disable vdd: %d\n", err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) if (sdev->vio) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) err = regulator_disable(sdev->vio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) v4l2_err(&sdev->sd, "Failed to disable vio: %d\n", err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) * si4713_powerdown - Powers the device down
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) * @sdev: si4713_device structure for the device we are communicating
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) static int si4713_powerdown(struct si4713_device *sdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) u8 resp[SI4713_PWDN_NRESP];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) if (!sdev->power_state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) err = si4713_send_command(sdev, SI4713_CMD_POWER_DOWN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) NULL, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) resp, ARRAY_SIZE(resp),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) DEFAULT_TIMEOUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) if (!err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) v4l2_dbg(1, debug, &sdev->sd, "Power down response: 0x%02x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) resp[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) v4l2_dbg(1, debug, &sdev->sd, "Device in reset mode\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) if (sdev->gpio_reset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) gpiod_set_value(sdev->gpio_reset, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) if (sdev->vdd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) err = regulator_disable(sdev->vdd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) v4l2_err(&sdev->sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) "Failed to disable vdd: %d\n", err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) if (sdev->vio) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) err = regulator_disable(sdev->vio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) v4l2_err(&sdev->sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) "Failed to disable vio: %d\n", err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) sdev->power_state = POWER_OFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) * si4713_checkrev - Checks if we are treating a device with the correct rev.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) * @sdev: si4713_device structure for the device we are communicating
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) static int si4713_checkrev(struct si4713_device *sdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) struct i2c_client *client = v4l2_get_subdevdata(&sdev->sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) int rval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) u8 resp[SI4713_GETREV_NRESP];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) rval = si4713_send_command(sdev, SI4713_CMD_GET_REV,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) NULL, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) resp, ARRAY_SIZE(resp),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) DEFAULT_TIMEOUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) if (rval < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) return rval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) if (resp[1] == SI4713_PRODUCT_NUMBER) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) v4l2_info(&sdev->sd, "chip found @ 0x%02x (%s)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) client->addr << 1, client->adapter->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) v4l2_err(&sdev->sd, "Invalid product number 0x%X\n", resp[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) rval = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) return rval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) * si4713_wait_stc - Waits STC interrupt and clears status bits. Useful
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) * for TX_TUNE_POWER, TX_TUNE_FREQ and TX_TUNE_MEAS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) * @sdev: si4713_device structure for the device we are communicating
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) * @usecs: timeout to wait for STC interrupt signal
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) static int si4713_wait_stc(struct si4713_device *sdev, const int usecs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) struct i2c_client *client = v4l2_get_subdevdata(&sdev->sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) u8 resp[SI4713_GET_STATUS_NRESP];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) unsigned long start_jiffies = jiffies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) if (client->irq &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) !wait_for_completion_timeout(&sdev->work, usecs_to_jiffies(usecs) + 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) v4l2_warn(&sdev->sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) "(%s) Device took too much time to answer.\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) for (;;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) /* Clear status bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) err = si4713_send_command(sdev, SI4713_CMD_GET_INT_STATUS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) NULL, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) resp, ARRAY_SIZE(resp),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) DEFAULT_TIMEOUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) /* The USB device returns errors when it waits for the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) * STC bit to be set. Hence polling */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) if (err >= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) v4l2_dbg(1, debug, &sdev->sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) "%s: status bits: 0x%02x\n", __func__, resp[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) if (resp[0] & SI4713_STC_INT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) if (jiffies_to_usecs(jiffies - start_jiffies) > usecs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) return err < 0 ? err : -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) /* We sleep here for 3-4 ms in order to avoid flooding the device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) * with USB requests. The si4713 USB driver was developed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) * by reverse engineering the Windows USB driver. The windows
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) * driver also has a ~2.5 ms delay between responses. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) usleep_range(3000, 4000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) * si4713_tx_tune_freq - Sets the state of the RF carrier and sets the tuning
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) * frequency between 76 and 108 MHz in 10 kHz units and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) * steps of 50 kHz.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) * @sdev: si4713_device structure for the device we are communicating
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) * @frequency: desired frequency (76 - 108 MHz, unit 10 KHz, step 50 kHz)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) static int si4713_tx_tune_freq(struct si4713_device *sdev, u16 frequency)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) u8 val[SI4713_TXFREQ_NRESP];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) * .First byte = 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) * .Second byte = frequency's MSB
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) * .Third byte = frequency's LSB
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) const u8 args[SI4713_TXFREQ_NARGS] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) msb(frequency),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) lsb(frequency),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) err = si4713_send_command(sdev, SI4713_CMD_TX_TUNE_FREQ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) args, ARRAY_SIZE(args), val,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) ARRAY_SIZE(val), DEFAULT_TIMEOUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) v4l2_dbg(1, debug, &sdev->sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) "%s: frequency=0x%02x status=0x%02x\n", __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) frequency, val[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) err = si4713_wait_stc(sdev, TIMEOUT_TX_TUNE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) return compose_u16(args[1], args[2]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) * si4713_tx_tune_power - Sets the RF voltage level between 88 and 120 dBuV in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) * 1 dB units. A value of 0x00 indicates off. The command
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) * also sets the antenna tuning capacitance. A value of 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) * indicates autotuning, and a value of 1 - 191 indicates
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) * a manual override, which results in a tuning
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) * capacitance of 0.25 pF x @antcap.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) * @sdev: si4713_device structure for the device we are communicating
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) * @power: tuning power (88 - 120 dBuV, unit/step 1 dB)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) * @antcap: value of antenna tuning capacitor (0 - 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) static int si4713_tx_tune_power(struct si4713_device *sdev, u8 power,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) u8 antcap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) u8 val[SI4713_TXPWR_NRESP];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) * .First byte = 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) * .Second byte = 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) * .Third byte = power
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) * .Fourth byte = antcap
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) u8 args[SI4713_TXPWR_NARGS] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) power,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) antcap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) /* Map power values 1-87 to MIN_POWER (88) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) if (power > 0 && power < SI4713_MIN_POWER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) args[2] = power = SI4713_MIN_POWER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) err = si4713_send_command(sdev, SI4713_CMD_TX_TUNE_POWER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) args, ARRAY_SIZE(args), val,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) ARRAY_SIZE(val), DEFAULT_TIMEOUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) v4l2_dbg(1, debug, &sdev->sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) "%s: power=0x%02x antcap=0x%02x status=0x%02x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) __func__, power, antcap, val[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) return si4713_wait_stc(sdev, TIMEOUT_TX_TUNE_POWER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) * si4713_tx_tune_measure - Enters receive mode and measures the received noise
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) * level in units of dBuV on the selected frequency.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) * The Frequency must be between 76 and 108 MHz in 10 kHz
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) * units and steps of 50 kHz. The command also sets the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) * antenna tuning capacitance. A value of 0 means
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) * autotuning, and a value of 1 to 191 indicates manual
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) * override.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) * @sdev: si4713_device structure for the device we are communicating
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) * @frequency: desired frequency (76 - 108 MHz, unit 10 KHz, step 50 kHz)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) * @antcap: value of antenna tuning capacitor (0 - 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) static int si4713_tx_tune_measure(struct si4713_device *sdev, u16 frequency,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) u8 antcap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) u8 val[SI4713_TXMEA_NRESP];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) * .First byte = 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) * .Second byte = frequency's MSB
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) * .Third byte = frequency's LSB
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) * .Fourth byte = antcap
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) const u8 args[SI4713_TXMEA_NARGS] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) msb(frequency),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) lsb(frequency),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) antcap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) sdev->tune_rnl = DEFAULT_TUNE_RNL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) if (antcap > SI4713_MAX_ANTCAP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) return -EDOM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) err = si4713_send_command(sdev, SI4713_CMD_TX_TUNE_MEASURE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) args, ARRAY_SIZE(args), val,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) ARRAY_SIZE(val), DEFAULT_TIMEOUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) v4l2_dbg(1, debug, &sdev->sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) "%s: frequency=0x%02x antcap=0x%02x status=0x%02x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) __func__, frequency, antcap, val[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) return si4713_wait_stc(sdev, TIMEOUT_TX_TUNE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) * si4713_tx_tune_status- Returns the status of the tx_tune_freq, tx_tune_mea or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) * tx_tune_power commands. This command return the current
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) * frequency, output voltage in dBuV, the antenna tunning
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) * capacitance value and the received noise level. The
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) * command also clears the stcint interrupt bit when the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) * first bit of its arguments is high.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) * @sdev: si4713_device structure for the device we are communicating
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) * @intack: 0x01 to clear the seek/tune complete interrupt status indicator.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) * @frequency: returned frequency
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) * @power: returned power
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) * @antcap: returned antenna capacitance
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) * @noise: returned noise level
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) static int si4713_tx_tune_status(struct si4713_device *sdev, u8 intack,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) u16 *frequency, u8 *power,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) u8 *antcap, u8 *noise)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) u8 val[SI4713_TXSTATUS_NRESP];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) * .First byte = intack bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) const u8 args[SI4713_TXSTATUS_NARGS] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) intack & SI4713_INTACK_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) err = si4713_send_command(sdev, SI4713_CMD_TX_TUNE_STATUS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) args, ARRAY_SIZE(args), val,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) ARRAY_SIZE(val), DEFAULT_TIMEOUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) if (!err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) v4l2_dbg(1, debug, &sdev->sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) "%s: status=0x%02x\n", __func__, val[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) *frequency = compose_u16(val[2], val[3]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) sdev->frequency = *frequency;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) *power = val[5];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) *antcap = val[6];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) *noise = val[7];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) v4l2_dbg(1, debug, &sdev->sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) "%s: response: %d x 10 kHz (power %d, antcap %d, rnl %d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) __func__, *frequency, *power, *antcap, *noise);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) * si4713_tx_rds_buff - Loads the RDS group buffer FIFO or circular buffer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) * @sdev: si4713_device structure for the device we are communicating
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) * @mode: the buffer operation mode.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) * @rdsb: RDS Block B
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) * @rdsc: RDS Block C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) * @rdsd: RDS Block D
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) * @cbleft: returns the number of available circular buffer blocks minus the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) * number of used circular buffer blocks.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) static int si4713_tx_rds_buff(struct si4713_device *sdev, u8 mode, u16 rdsb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) u16 rdsc, u16 rdsd, s8 *cbleft)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) u8 val[SI4713_RDSBUFF_NRESP];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) const u8 args[SI4713_RDSBUFF_NARGS] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) mode & SI4713_RDSBUFF_MODE_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) msb(rdsb),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) lsb(rdsb),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) msb(rdsc),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) lsb(rdsc),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) msb(rdsd),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) lsb(rdsd),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) err = si4713_send_command(sdev, SI4713_CMD_TX_RDS_BUFF,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) args, ARRAY_SIZE(args), val,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) ARRAY_SIZE(val), DEFAULT_TIMEOUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) if (!err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) v4l2_dbg(1, debug, &sdev->sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) "%s: status=0x%02x\n", __func__, val[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) *cbleft = (s8)val[2] - val[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) v4l2_dbg(1, debug, &sdev->sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) "%s: response: interrupts 0x%02x cb avail: %d cb used %d fifo avail %d fifo used %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) __func__, val[1], val[2], val[3], val[4], val[5]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) * si4713_tx_rds_ps - Loads the program service buffer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) * @sdev: si4713_device structure for the device we are communicating
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) * @psid: program service id to be loaded.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) * @pschar: assumed 4 size char array to be loaded into the program service
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) static int si4713_tx_rds_ps(struct si4713_device *sdev, u8 psid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) unsigned char *pschar)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) u8 val[SI4713_RDSPS_NRESP];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) const u8 args[SI4713_RDSPS_NARGS] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) psid & SI4713_RDSPS_PSID_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) pschar[0],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) pschar[1],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) pschar[2],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) pschar[3],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) err = si4713_send_command(sdev, SI4713_CMD_TX_RDS_PS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) args, ARRAY_SIZE(args), val,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) ARRAY_SIZE(val), DEFAULT_TIMEOUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) v4l2_dbg(1, debug, &sdev->sd, "%s: status=0x%02x\n", __func__, val[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) static int si4713_set_power_state(struct si4713_device *sdev, u8 value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) if (value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) return si4713_powerup(sdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) return si4713_powerdown(sdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) static int si4713_set_mute(struct si4713_device *sdev, u16 mute)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) int rval = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) mute = set_mute(mute);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) if (sdev->power_state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) rval = si4713_write_property(sdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) SI4713_TX_LINE_INPUT_MUTE, mute);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) return rval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) static int si4713_set_rds_ps_name(struct si4713_device *sdev, char *ps_name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) int rval = 0, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) u8 len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) /* We want to clear the whole thing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) if (!strlen(ps_name))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) memset(ps_name, 0, MAX_RDS_PS_NAME + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) if (sdev->power_state) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) /* Write the new ps name and clear the padding */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) for (i = 0; i < MAX_RDS_PS_NAME; i += (RDS_BLOCK / 2)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) rval = si4713_tx_rds_ps(sdev, (i / (RDS_BLOCK / 2)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) ps_name + i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) if (rval < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) return rval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) /* Setup the size to be sent */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) if (strlen(ps_name))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) len = strlen(ps_name) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) len = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) rval = si4713_write_property(sdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) SI4713_TX_RDS_PS_MESSAGE_COUNT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) rds_ps_nblocks(len));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) if (rval < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) return rval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) rval = si4713_write_property(sdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) SI4713_TX_RDS_PS_REPEAT_COUNT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) DEFAULT_RDS_PS_REPEAT_COUNT * 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) if (rval < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) return rval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) return rval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) static int si4713_set_rds_radio_text(struct si4713_device *sdev, const char *rt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) static const char cr[RDS_RADIOTEXT_BLK_SIZE] = { RDS_CARRIAGE_RETURN, 0 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) int rval = 0, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) u16 t_index = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) u8 b_index = 0, cr_inserted = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) s8 left;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) if (!sdev->power_state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) return rval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) rval = si4713_tx_rds_buff(sdev, RDS_BLOCK_CLEAR, 0, 0, 0, &left);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) if (rval < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) return rval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) if (!strlen(rt))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) return rval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) /* RDS spec says that if the last block isn't used,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) * then apply a carriage return
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) if (t_index < (RDS_RADIOTEXT_INDEX_MAX * RDS_RADIOTEXT_BLK_SIZE)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) for (i = 0; i < RDS_RADIOTEXT_BLK_SIZE; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) if (!rt[t_index + i] ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) rt[t_index + i] == RDS_CARRIAGE_RETURN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) rt = cr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) cr_inserted = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) rval = si4713_tx_rds_buff(sdev, RDS_BLOCK_LOAD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) compose_u16(RDS_RADIOTEXT_2A, b_index++),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) compose_u16(rt[t_index], rt[t_index + 1]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) compose_u16(rt[t_index + 2], rt[t_index + 3]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) &left);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) if (rval < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) return rval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) t_index += RDS_RADIOTEXT_BLK_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) if (cr_inserted)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) } while (left > 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) return rval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) * si4713_update_tune_status - update properties from tx_tune_status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) * command. Must be called with sdev->mutex held.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) * @sdev: si4713_device structure for the device we are communicating
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) static int si4713_update_tune_status(struct si4713_device *sdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) int rval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) u16 f = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) u8 p = 0, a = 0, n = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) rval = si4713_tx_tune_status(sdev, 0x00, &f, &p, &a, &n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) if (rval < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) /* TODO: check that power_level and antenna_capacitor really are not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) changed by the hardware. If they are, then these controls should become
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) volatiles.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) sdev->power_level = p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) sdev->antenna_capacitor = a;*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) sdev->tune_rnl = n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) return rval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) static int si4713_choose_econtrol_action(struct si4713_device *sdev, u32 id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) s32 *bit, s32 *mask, u16 *property, int *mul,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) unsigned long **table, int *size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) s32 rval = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) switch (id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) /* FM_TX class controls */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) case V4L2_CID_RDS_TX_PI:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) *property = SI4713_TX_RDS_PI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) *mul = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) case V4L2_CID_AUDIO_COMPRESSION_THRESHOLD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) *property = SI4713_TX_ACOMP_THRESHOLD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) *mul = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) case V4L2_CID_AUDIO_COMPRESSION_GAIN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) *property = SI4713_TX_ACOMP_GAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) *mul = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) case V4L2_CID_PILOT_TONE_FREQUENCY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) *property = SI4713_TX_PILOT_FREQUENCY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) *mul = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) case V4L2_CID_AUDIO_COMPRESSION_ATTACK_TIME:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) *property = SI4713_TX_ACOMP_ATTACK_TIME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) *mul = ATTACK_TIME_UNIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) case V4L2_CID_PILOT_TONE_DEVIATION:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) *property = SI4713_TX_PILOT_DEVIATION;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) *mul = 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) case V4L2_CID_AUDIO_LIMITER_DEVIATION:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) *property = SI4713_TX_AUDIO_DEVIATION;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) *mul = 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) case V4L2_CID_RDS_TX_DEVIATION:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) *property = SI4713_TX_RDS_DEVIATION;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) *mul = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) case V4L2_CID_RDS_TX_PTY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) *property = SI4713_TX_RDS_PS_MISC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) *bit = 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) *mask = 0x1F << 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) case V4L2_CID_RDS_TX_DYNAMIC_PTY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) *property = SI4713_TX_RDS_PS_MISC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) *bit = 15;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) *mask = 1 << 15;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) case V4L2_CID_RDS_TX_COMPRESSED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) *property = SI4713_TX_RDS_PS_MISC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) *bit = 14;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) *mask = 1 << 14;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) case V4L2_CID_RDS_TX_ARTIFICIAL_HEAD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) *property = SI4713_TX_RDS_PS_MISC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) *bit = 13;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) *mask = 1 << 13;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) case V4L2_CID_RDS_TX_MONO_STEREO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) *property = SI4713_TX_RDS_PS_MISC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) *bit = 12;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) *mask = 1 << 12;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) case V4L2_CID_RDS_TX_TRAFFIC_PROGRAM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) *property = SI4713_TX_RDS_PS_MISC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) *bit = 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) *mask = 1 << 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) case V4L2_CID_RDS_TX_TRAFFIC_ANNOUNCEMENT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) *property = SI4713_TX_RDS_PS_MISC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) *bit = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) *mask = 1 << 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) case V4L2_CID_RDS_TX_MUSIC_SPEECH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) *property = SI4713_TX_RDS_PS_MISC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) *bit = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) *mask = 1 << 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) case V4L2_CID_AUDIO_LIMITER_ENABLED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) *property = SI4713_TX_ACOMP_ENABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) *bit = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) *mask = 1 << 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) case V4L2_CID_AUDIO_COMPRESSION_ENABLED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) *property = SI4713_TX_ACOMP_ENABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) *bit = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) *mask = 1 << 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) case V4L2_CID_PILOT_TONE_ENABLED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) *property = SI4713_TX_COMPONENT_ENABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) *bit = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) *mask = 1 << 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) case V4L2_CID_AUDIO_LIMITER_RELEASE_TIME:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) *property = SI4713_TX_LIMITER_RELEASE_TIME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) *table = limiter_times;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) *size = ARRAY_SIZE(limiter_times);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) case V4L2_CID_AUDIO_COMPRESSION_RELEASE_TIME:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) *property = SI4713_TX_ACOMP_RELEASE_TIME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) *table = acomp_rtimes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) *size = ARRAY_SIZE(acomp_rtimes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) case V4L2_CID_TUNE_PREEMPHASIS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) *property = SI4713_TX_PREEMPHASIS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) *table = preemphasis_values;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) *size = ARRAY_SIZE(preemphasis_values);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) rval = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) return rval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) static int si4713_s_frequency(struct v4l2_subdev *sd, const struct v4l2_frequency *f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) static int si4713_s_modulator(struct v4l2_subdev *sd, const struct v4l2_modulator *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) * si4713_setup - Sets the device up with current configuration.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) * @sdev: si4713_device structure for the device we are communicating
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) static int si4713_setup(struct si4713_device *sdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) struct v4l2_frequency f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) struct v4l2_modulator vm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) int rval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) /* Device procedure needs to set frequency first */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) f.tuner = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) f.frequency = sdev->frequency ? sdev->frequency : DEFAULT_FREQUENCY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) f.frequency = si4713_to_v4l2(f.frequency);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) rval = si4713_s_frequency(&sdev->sd, &f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) vm.index = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) if (sdev->stereo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) vm.txsubchans = V4L2_TUNER_SUB_STEREO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) vm.txsubchans = V4L2_TUNER_SUB_MONO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) if (sdev->rds_enabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) vm.txsubchans |= V4L2_TUNER_SUB_RDS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) si4713_s_modulator(&sdev->sd, &vm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) return rval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) * si4713_initialize - Sets the device up with default configuration.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) * @sdev: si4713_device structure for the device we are communicating
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) static int si4713_initialize(struct si4713_device *sdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) int rval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) rval = si4713_set_power_state(sdev, POWER_ON);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) if (rval < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) return rval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) rval = si4713_checkrev(sdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) if (rval < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) return rval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) rval = si4713_set_power_state(sdev, POWER_OFF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) if (rval < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) return rval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) sdev->frequency = DEFAULT_FREQUENCY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) sdev->stereo = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) sdev->tune_rnl = DEFAULT_TUNE_RNL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) /* si4713_s_ctrl - set the value of a control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) static int si4713_s_ctrl(struct v4l2_ctrl *ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) struct si4713_device *sdev =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) container_of(ctrl->handler, struct si4713_device, ctrl_handler);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) u32 val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) s32 bit = 0, mask = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) u16 property = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) int mul = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) unsigned long *table = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) int size = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) bool force = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) int c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) if (ctrl->id != V4L2_CID_AUDIO_MUTE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) if (ctrl->is_new) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) if (ctrl->val) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) ret = si4713_set_mute(sdev, ctrl->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) ret = si4713_set_power_state(sdev, POWER_DOWN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) ret = si4713_set_power_state(sdev, POWER_UP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) ret = si4713_set_mute(sdev, ctrl->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) ret = si4713_setup(sdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) force = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) if (!sdev->power_state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) for (c = 1; !ret && c < ctrl->ncontrols; c++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) ctrl = ctrl->cluster[c];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) if (!force && !ctrl->is_new)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) switch (ctrl->id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) case V4L2_CID_RDS_TX_PS_NAME:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) ret = si4713_set_rds_ps_name(sdev, ctrl->p_new.p_char);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) case V4L2_CID_RDS_TX_RADIO_TEXT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) ret = si4713_set_rds_radio_text(sdev, ctrl->p_new.p_char);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) case V4L2_CID_TUNE_ANTENNA_CAPACITOR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) /* don't handle this control if we force setting all
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) * controls since in that case it will be handled by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) * V4L2_CID_TUNE_POWER_LEVEL. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) if (force)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) case V4L2_CID_TUNE_POWER_LEVEL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) ret = si4713_tx_tune_power(sdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) sdev->tune_pwr_level->val, sdev->tune_ant_cap->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) if (!ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) /* Make sure we don't set this twice */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) sdev->tune_ant_cap->is_new = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) sdev->tune_pwr_level->is_new = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) case V4L2_CID_RDS_TX_ALT_FREQS_ENABLE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) case V4L2_CID_RDS_TX_ALT_FREQS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) if (sdev->rds_alt_freqs_enable->val) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) val = sdev->rds_alt_freqs->p_new.p_u32[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) val = val / 100 - 876 + 0xe101;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) val = 0xe0e0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) ret = si4713_write_property(sdev, SI4713_TX_RDS_PS_AF, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) ret = si4713_choose_econtrol_action(sdev, ctrl->id, &bit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) &mask, &property, &mul, &table, &size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) val = ctrl->val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) if (mul) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) val = val / mul;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) } else if (table) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) ret = usecs_to_dev(val, table, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) val = ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) if (mask) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) ret = si4713_read_property(sdev, property, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) val = set_bits(val, ctrl->val, bit, mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) ret = si4713_write_property(sdev, property, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) if (mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) val = ctrl->val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) /* si4713_ioctl - deal with private ioctls (only rnl for now) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) static long si4713_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) struct si4713_device *sdev = to_si4713_device(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) struct si4713_rnl *rnl = arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) u16 frequency;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) int rval = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) if (!arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) case SI4713_IOC_MEASURE_RNL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) frequency = v4l2_to_si4713(rnl->frequency);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) if (sdev->power_state) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) /* Set desired measurement frequency */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) rval = si4713_tx_tune_measure(sdev, frequency, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) if (rval < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) return rval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) /* get results from tune status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) rval = si4713_update_tune_status(sdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) if (rval < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) return rval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) rnl->rnl = sdev->tune_rnl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) /* nothing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) rval = -ENOIOCTLCMD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) return rval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) /* si4713_g_modulator - get modulator attributes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) static int si4713_g_modulator(struct v4l2_subdev *sd, struct v4l2_modulator *vm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) struct si4713_device *sdev = to_si4713_device(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) int rval = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) if (!sdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) if (vm->index > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) strscpy(vm->name, "FM Modulator", sizeof(vm->name));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) vm->capability = V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LOW |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) V4L2_TUNER_CAP_RDS | V4L2_TUNER_CAP_RDS_CONTROLS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) /* Report current frequency range limits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) vm->rangelow = si4713_to_v4l2(FREQ_RANGE_LOW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) vm->rangehigh = si4713_to_v4l2(FREQ_RANGE_HIGH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) if (sdev->power_state) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) u32 comp_en = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) rval = si4713_read_property(sdev, SI4713_TX_COMPONENT_ENABLE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) &comp_en);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) if (rval < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) return rval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) sdev->stereo = get_status_bit(comp_en, 1, 1 << 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) /* Report current audio mode: mono or stereo */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) if (sdev->stereo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) vm->txsubchans = V4L2_TUNER_SUB_STEREO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) vm->txsubchans = V4L2_TUNER_SUB_MONO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) /* Report rds feature status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) if (sdev->rds_enabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) vm->txsubchans |= V4L2_TUNER_SUB_RDS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) vm->txsubchans &= ~V4L2_TUNER_SUB_RDS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) return rval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) /* si4713_s_modulator - set modulator attributes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) static int si4713_s_modulator(struct v4l2_subdev *sd, const struct v4l2_modulator *vm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) struct si4713_device *sdev = to_si4713_device(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) int rval = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) u16 stereo, rds;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) u32 p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) if (!sdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) if (vm->index > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) /* Set audio mode: mono or stereo */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) if (vm->txsubchans & V4L2_TUNER_SUB_STEREO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) stereo = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) else if (vm->txsubchans & V4L2_TUNER_SUB_MONO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) stereo = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) rds = !!(vm->txsubchans & V4L2_TUNER_SUB_RDS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) if (sdev->power_state) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) rval = si4713_read_property(sdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) SI4713_TX_COMPONENT_ENABLE, &p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) if (rval < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) return rval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) p = set_bits(p, stereo, 1, 1 << 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) p = set_bits(p, rds, 2, 1 << 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) rval = si4713_write_property(sdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) SI4713_TX_COMPONENT_ENABLE, p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) if (rval < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) return rval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) sdev->stereo = stereo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) sdev->rds_enabled = rds;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) return rval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) /* si4713_g_frequency - get tuner or modulator radio frequency */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) static int si4713_g_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) struct si4713_device *sdev = to_si4713_device(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) int rval = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) if (f->tuner)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) if (sdev->power_state) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) u16 freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) u8 p, a, n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) rval = si4713_tx_tune_status(sdev, 0x00, &freq, &p, &a, &n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) if (rval < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) return rval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) sdev->frequency = freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) f->frequency = si4713_to_v4l2(sdev->frequency);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) return rval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) /* si4713_s_frequency - set tuner or modulator radio frequency */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) static int si4713_s_frequency(struct v4l2_subdev *sd, const struct v4l2_frequency *f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) struct si4713_device *sdev = to_si4713_device(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) int rval = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) u16 frequency = v4l2_to_si4713(f->frequency);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) if (f->tuner)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) /* Check frequency range */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) frequency = clamp_t(u16, frequency, FREQ_RANGE_LOW, FREQ_RANGE_HIGH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) if (sdev->power_state) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) rval = si4713_tx_tune_freq(sdev, frequency);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) if (rval < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) return rval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) frequency = rval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) rval = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) sdev->frequency = frequency;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) return rval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) static const struct v4l2_ctrl_ops si4713_ctrl_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) .s_ctrl = si4713_s_ctrl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) static const struct v4l2_subdev_core_ops si4713_subdev_core_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) .ioctl = si4713_ioctl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) static const struct v4l2_subdev_tuner_ops si4713_subdev_tuner_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) .g_frequency = si4713_g_frequency,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) .s_frequency = si4713_s_frequency,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) .g_modulator = si4713_g_modulator,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) .s_modulator = si4713_s_modulator,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) static const struct v4l2_subdev_ops si4713_subdev_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) .core = &si4713_subdev_core_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) .tuner = &si4713_subdev_tuner_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) static const struct v4l2_ctrl_config si4713_alt_freqs_ctrl = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) .id = V4L2_CID_RDS_TX_ALT_FREQS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) .type = V4L2_CTRL_TYPE_U32,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) .min = 87600,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) .max = 107900,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) .step = 100,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) .def = 87600,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) .dims = { 1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) .elem_size = sizeof(u32),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) * I2C driver interface
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) /* si4713_probe - probe for the device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) static int si4713_probe(struct i2c_client *client)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) struct si4713_device *sdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) struct v4l2_ctrl_handler *hdl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) struct si4713_platform_data *pdata = client->dev.platform_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) struct device_node *np = client->dev.of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) struct radio_si4713_platform_data si4713_pdev_pdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) struct platform_device *si4713_pdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) int rval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) sdev = devm_kzalloc(&client->dev, sizeof(*sdev), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) if (!sdev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) dev_err(&client->dev, "Failed to alloc video device.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) rval = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) sdev->gpio_reset = devm_gpiod_get_optional(&client->dev, "reset",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) GPIOD_OUT_LOW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) if (IS_ERR(sdev->gpio_reset)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) rval = PTR_ERR(sdev->gpio_reset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) dev_err(&client->dev, "Failed to request gpio: %d\n", rval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) sdev->vdd = devm_regulator_get_optional(&client->dev, "vdd");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) if (IS_ERR(sdev->vdd)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) rval = PTR_ERR(sdev->vdd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) if (rval == -EPROBE_DEFER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) dev_dbg(&client->dev, "no vdd regulator found: %d\n", rval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) sdev->vdd = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) sdev->vio = devm_regulator_get_optional(&client->dev, "vio");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) if (IS_ERR(sdev->vio)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) rval = PTR_ERR(sdev->vio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) if (rval == -EPROBE_DEFER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) dev_dbg(&client->dev, "no vio regulator found: %d\n", rval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) sdev->vio = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) v4l2_i2c_subdev_init(&sdev->sd, client, &si4713_subdev_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) init_completion(&sdev->work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) hdl = &sdev->ctrl_handler;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) v4l2_ctrl_handler_init(hdl, 20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) sdev->mute = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) V4L2_CID_AUDIO_MUTE, 0, 1, 1, DEFAULT_MUTE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) sdev->rds_pi = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) V4L2_CID_RDS_TX_PI, 0, 0xffff, 1, DEFAULT_RDS_PI);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) sdev->rds_pty = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) V4L2_CID_RDS_TX_PTY, 0, 31, 1, DEFAULT_RDS_PTY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) sdev->rds_compressed = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) V4L2_CID_RDS_TX_COMPRESSED, 0, 1, 1, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) sdev->rds_art_head = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) V4L2_CID_RDS_TX_ARTIFICIAL_HEAD, 0, 1, 1, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) sdev->rds_stereo = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) V4L2_CID_RDS_TX_MONO_STEREO, 0, 1, 1, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494) sdev->rds_tp = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495) V4L2_CID_RDS_TX_TRAFFIC_PROGRAM, 0, 1, 1, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) sdev->rds_ta = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) V4L2_CID_RDS_TX_TRAFFIC_ANNOUNCEMENT, 0, 1, 1, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) sdev->rds_ms = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) V4L2_CID_RDS_TX_MUSIC_SPEECH, 0, 1, 1, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) sdev->rds_dyn_pty = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) V4L2_CID_RDS_TX_DYNAMIC_PTY, 0, 1, 1, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) sdev->rds_alt_freqs_enable = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) V4L2_CID_RDS_TX_ALT_FREQS_ENABLE, 0, 1, 1, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) sdev->rds_alt_freqs = v4l2_ctrl_new_custom(hdl, &si4713_alt_freqs_ctrl, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) sdev->rds_deviation = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) V4L2_CID_RDS_TX_DEVIATION, 0, MAX_RDS_DEVIATION,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) 10, DEFAULT_RDS_DEVIATION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) * Report step as 8. From RDS spec, psname
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510) * should be 8. But there are receivers which scroll strings
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) * sized as 8xN.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513) sdev->rds_ps_name = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) V4L2_CID_RDS_TX_PS_NAME, 0, MAX_RDS_PS_NAME, 8, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) * Report step as 32 (2A block). From RDS spec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) * radio text should be 32 for 2A block. But there are receivers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) * which scroll strings sized as 32xN. Setting default to 32.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) sdev->rds_radio_text = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) V4L2_CID_RDS_TX_RADIO_TEXT, 0, MAX_RDS_RADIO_TEXT, 32, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) sdev->limiter_enabled = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) V4L2_CID_AUDIO_LIMITER_ENABLED, 0, 1, 1, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) sdev->limiter_release_time = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) V4L2_CID_AUDIO_LIMITER_RELEASE_TIME, 250,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) MAX_LIMITER_RELEASE_TIME, 10, DEFAULT_LIMITER_RTIME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) sdev->limiter_deviation = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) V4L2_CID_AUDIO_LIMITER_DEVIATION, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530) MAX_LIMITER_DEVIATION, 10, DEFAULT_LIMITER_DEV);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) sdev->compression_enabled = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533) V4L2_CID_AUDIO_COMPRESSION_ENABLED, 0, 1, 1, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) sdev->compression_gain = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535) V4L2_CID_AUDIO_COMPRESSION_GAIN, 0, MAX_ACOMP_GAIN, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) DEFAULT_ACOMP_GAIN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) sdev->compression_threshold = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538) V4L2_CID_AUDIO_COMPRESSION_THRESHOLD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) MIN_ACOMP_THRESHOLD, MAX_ACOMP_THRESHOLD, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540) DEFAULT_ACOMP_THRESHOLD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541) sdev->compression_attack_time = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542) V4L2_CID_AUDIO_COMPRESSION_ATTACK_TIME, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) MAX_ACOMP_ATTACK_TIME, 500, DEFAULT_ACOMP_ATIME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544) sdev->compression_release_time = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545) V4L2_CID_AUDIO_COMPRESSION_RELEASE_TIME, 100000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546) MAX_ACOMP_RELEASE_TIME, 100000, DEFAULT_ACOMP_RTIME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548) sdev->pilot_tone_enabled = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) V4L2_CID_PILOT_TONE_ENABLED, 0, 1, 1, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550) sdev->pilot_tone_deviation = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551) V4L2_CID_PILOT_TONE_DEVIATION, 0, MAX_PILOT_DEVIATION,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552) 10, DEFAULT_PILOT_DEVIATION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) sdev->pilot_tone_freq = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554) V4L2_CID_PILOT_TONE_FREQUENCY, 0, MAX_PILOT_FREQUENCY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555) 1, DEFAULT_PILOT_FREQUENCY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557) sdev->tune_preemphasis = v4l2_ctrl_new_std_menu(hdl, &si4713_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558) V4L2_CID_TUNE_PREEMPHASIS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559) V4L2_PREEMPHASIS_75_uS, 0, V4L2_PREEMPHASIS_50_uS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560) sdev->tune_pwr_level = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561) V4L2_CID_TUNE_POWER_LEVEL, 0, SI4713_MAX_POWER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562) 1, DEFAULT_POWER_LEVEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563) sdev->tune_ant_cap = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564) V4L2_CID_TUNE_ANTENNA_CAPACITOR, 0, SI4713_MAX_ANTCAP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565) 1, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567) if (hdl->error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568) rval = hdl->error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569) goto free_ctrls;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571) v4l2_ctrl_cluster(29, &sdev->mute);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572) sdev->sd.ctrl_handler = hdl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574) if (client->irq) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575) rval = devm_request_irq(&client->dev, client->irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576) si4713_handler, IRQF_TRIGGER_FALLING,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577) client->name, sdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578) if (rval < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579) v4l2_err(&sdev->sd, "Could not request IRQ\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580) goto free_ctrls;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582) v4l2_dbg(1, debug, &sdev->sd, "IRQ requested.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584) v4l2_warn(&sdev->sd, "IRQ not configured. Using timeouts.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587) rval = si4713_initialize(sdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588) if (rval < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589) v4l2_err(&sdev->sd, "Failed to probe device information.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590) goto free_ctrls;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593) if (!np && (!pdata || !pdata->is_platform_device))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596) si4713_pdev = platform_device_alloc("radio-si4713", -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597) if (!si4713_pdev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598) rval = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599) goto put_main_pdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602) si4713_pdev_pdata.subdev = client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603) rval = platform_device_add_data(si4713_pdev, &si4713_pdev_pdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604) sizeof(si4713_pdev_pdata));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605) if (rval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606) goto put_main_pdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608) rval = platform_device_add(si4713_pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609) if (rval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610) goto put_main_pdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612) sdev->pd = si4713_pdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616) put_main_pdev:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617) platform_device_put(si4713_pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618) v4l2_device_unregister_subdev(&sdev->sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619) free_ctrls:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620) v4l2_ctrl_handler_free(hdl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621) exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622) return rval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1624)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625) /* si4713_remove - remove the device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626) static int si4713_remove(struct i2c_client *client)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628) struct v4l2_subdev *sd = i2c_get_clientdata(client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629) struct si4713_device *sdev = to_si4713_device(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1630)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1631) platform_device_unregister(sdev->pd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1632)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1633) if (sdev->power_state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1634) si4713_set_power_state(sdev, POWER_DOWN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1635)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1636) v4l2_device_unregister_subdev(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1637) v4l2_ctrl_handler_free(sd->ctrl_handler);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1638)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1639) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1640) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1641)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1642) /* si4713_i2c_driver - i2c driver interface */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1643) static const struct i2c_device_id si4713_id[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1644) { "si4713" , 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1645) { },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1646) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1647) MODULE_DEVICE_TABLE(i2c, si4713_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1648)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1649) #if IS_ENABLED(CONFIG_OF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1650) static const struct of_device_id si4713_of_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1651) { .compatible = "silabs,si4713" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1652) { },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1653) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1654) MODULE_DEVICE_TABLE(of, si4713_of_match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1655) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1656)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1657) static struct i2c_driver si4713_i2c_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1658) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1659) .name = "si4713",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1660) .of_match_table = of_match_ptr(si4713_of_match),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1661) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1662) .probe_new = si4713_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1663) .remove = si4713_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1664) .id_table = si4713_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1665) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1666)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1667) module_i2c_driver(si4713_i2c_driver);