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