1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | Driver for SAA6588 RDS decoder |
4 | |
5 | (c) 2005 Hans J. Koch |
6 | |
7 | */ |
8 | |
9 | |
10 | #include <linux/module.h> |
11 | #include <linux/kernel.h> |
12 | #include <linux/i2c.h> |
13 | #include <linux/types.h> |
14 | #include <linux/videodev2.h> |
15 | #include <linux/init.h> |
16 | #include <linux/errno.h> |
17 | #include <linux/slab.h> |
18 | #include <linux/poll.h> |
19 | #include <linux/wait.h> |
20 | #include <linux/uaccess.h> |
21 | |
22 | #include <media/i2c/saa6588.h> |
23 | #include <media/v4l2-device.h> |
24 | |
25 | |
26 | /* insmod options */ |
27 | static unsigned int debug; |
28 | static unsigned int xtal; |
29 | static unsigned int mmbs; |
30 | static unsigned int plvl; |
31 | static unsigned int bufblocks = 100; |
32 | |
33 | module_param(debug, int, 0644); |
34 | MODULE_PARM_DESC(debug, "enable debug messages" ); |
35 | module_param(xtal, int, 0); |
36 | MODULE_PARM_DESC(xtal, "select oscillator frequency (0..3), default 0" ); |
37 | module_param(mmbs, int, 0); |
38 | MODULE_PARM_DESC(mmbs, "enable MMBS mode: 0=off (default), 1=on" ); |
39 | module_param(plvl, int, 0); |
40 | MODULE_PARM_DESC(plvl, "select pause level (0..3), default 0" ); |
41 | module_param(bufblocks, int, 0); |
42 | MODULE_PARM_DESC(bufblocks, "number of buffered blocks, default 100" ); |
43 | |
44 | MODULE_DESCRIPTION("v4l2 driver module for SAA6588 RDS decoder" ); |
45 | MODULE_AUTHOR("Hans J. Koch <koch@hjk-az.de>" ); |
46 | |
47 | MODULE_LICENSE("GPL" ); |
48 | |
49 | /* ---------------------------------------------------------------------- */ |
50 | |
51 | #define UNSET (-1U) |
52 | #define PREFIX "saa6588: " |
53 | #define dprintk if (debug) printk |
54 | |
55 | struct saa6588 { |
56 | struct v4l2_subdev sd; |
57 | struct delayed_work work; |
58 | spinlock_t lock; |
59 | unsigned char *buffer; |
60 | unsigned int buf_size; |
61 | unsigned int rd_index; |
62 | unsigned int wr_index; |
63 | unsigned int block_count; |
64 | unsigned char last_blocknum; |
65 | wait_queue_head_t read_queue; |
66 | int data_available_for_read; |
67 | u8 sync; |
68 | }; |
69 | |
70 | static inline struct saa6588 *to_saa6588(struct v4l2_subdev *sd) |
71 | { |
72 | return container_of(sd, struct saa6588, sd); |
73 | } |
74 | |
75 | /* ---------------------------------------------------------------------- */ |
76 | |
77 | /* |
78 | * SAA6588 defines |
79 | */ |
80 | |
81 | /* Initialization and mode control byte (0w) */ |
82 | |
83 | /* bit 0+1 (DAC0/DAC1) */ |
84 | #define cModeStandard 0x00 |
85 | #define cModeFastPI 0x01 |
86 | #define cModeReducedRequest 0x02 |
87 | #define cModeInvalid 0x03 |
88 | |
89 | /* bit 2 (RBDS) */ |
90 | #define cProcessingModeRDS 0x00 |
91 | #define cProcessingModeRBDS 0x04 |
92 | |
93 | /* bit 3+4 (SYM0/SYM1) */ |
94 | #define cErrCorrectionNone 0x00 |
95 | #define cErrCorrection2Bits 0x08 |
96 | #define cErrCorrection5Bits 0x10 |
97 | #define cErrCorrectionNoneRBDS 0x18 |
98 | |
99 | /* bit 5 (NWSY) */ |
100 | #define cSyncNormal 0x00 |
101 | #define cSyncRestart 0x20 |
102 | |
103 | /* bit 6 (TSQD) */ |
104 | #define cSigQualityDetectOFF 0x00 |
105 | #define cSigQualityDetectON 0x40 |
106 | |
107 | /* bit 7 (SQCM) */ |
108 | #define cSigQualityTriggered 0x00 |
109 | #define cSigQualityContinous 0x80 |
110 | |
111 | /* Pause level and flywheel control byte (1w) */ |
112 | |
113 | /* bits 0..5 (FEB0..FEB5) */ |
114 | #define cFlywheelMaxBlocksMask 0x3F |
115 | #define cFlywheelDefault 0x20 |
116 | |
117 | /* bits 6+7 (PL0/PL1) */ |
118 | #define cPauseLevel_11mV 0x00 |
119 | #define cPauseLevel_17mV 0x40 |
120 | #define cPauseLevel_27mV 0x80 |
121 | #define cPauseLevel_43mV 0xC0 |
122 | |
123 | /* Pause time/oscillator frequency/quality detector control byte (1w) */ |
124 | |
125 | /* bits 0..4 (SQS0..SQS4) */ |
126 | #define cQualityDetectSensMask 0x1F |
127 | #define cQualityDetectDefault 0x0F |
128 | |
129 | /* bit 5 (SOSC) */ |
130 | #define cSelectOscFreqOFF 0x00 |
131 | #define cSelectOscFreqON 0x20 |
132 | |
133 | /* bit 6+7 (PTF0/PTF1) */ |
134 | #define cOscFreq_4332kHz 0x00 |
135 | #define cOscFreq_8664kHz 0x40 |
136 | #define cOscFreq_12996kHz 0x80 |
137 | #define cOscFreq_17328kHz 0xC0 |
138 | |
139 | /* ---------------------------------------------------------------------- */ |
140 | |
141 | static bool block_from_buf(struct saa6588 *s, unsigned char *buf) |
142 | { |
143 | int i; |
144 | |
145 | if (s->rd_index == s->wr_index) { |
146 | if (debug > 2) |
147 | dprintk(PREFIX "Read: buffer empty.\n" ); |
148 | return false; |
149 | } |
150 | |
151 | if (debug > 2) { |
152 | dprintk(PREFIX "Read: " ); |
153 | for (i = s->rd_index; i < s->rd_index + 3; i++) |
154 | dprintk("0x%02x " , s->buffer[i]); |
155 | } |
156 | |
157 | memcpy(buf, &s->buffer[s->rd_index], 3); |
158 | |
159 | s->rd_index += 3; |
160 | if (s->rd_index >= s->buf_size) |
161 | s->rd_index = 0; |
162 | s->block_count--; |
163 | |
164 | if (debug > 2) |
165 | dprintk("%d blocks total.\n" , s->block_count); |
166 | |
167 | return true; |
168 | } |
169 | |
170 | static void read_from_buf(struct saa6588 *s, struct saa6588_command *a) |
171 | { |
172 | unsigned char __user *buf_ptr = a->buffer; |
173 | unsigned char buf[3]; |
174 | unsigned long flags; |
175 | unsigned int rd_blocks; |
176 | unsigned int i; |
177 | |
178 | a->result = 0; |
179 | if (!a->buffer) |
180 | return; |
181 | |
182 | while (!a->nonblocking && !s->data_available_for_read) { |
183 | int ret = wait_event_interruptible(s->read_queue, |
184 | s->data_available_for_read); |
185 | if (ret == -ERESTARTSYS) { |
186 | a->result = -EINTR; |
187 | return; |
188 | } |
189 | } |
190 | |
191 | rd_blocks = a->block_count; |
192 | spin_lock_irqsave(&s->lock, flags); |
193 | if (rd_blocks > s->block_count) |
194 | rd_blocks = s->block_count; |
195 | spin_unlock_irqrestore(lock: &s->lock, flags); |
196 | |
197 | if (!rd_blocks) |
198 | return; |
199 | |
200 | for (i = 0; i < rd_blocks; i++) { |
201 | bool got_block; |
202 | |
203 | spin_lock_irqsave(&s->lock, flags); |
204 | got_block = block_from_buf(s, buf); |
205 | spin_unlock_irqrestore(lock: &s->lock, flags); |
206 | if (!got_block) |
207 | break; |
208 | if (copy_to_user(to: buf_ptr, from: buf, n: 3)) { |
209 | a->result = -EFAULT; |
210 | return; |
211 | } |
212 | buf_ptr += 3; |
213 | a->result += 3; |
214 | } |
215 | spin_lock_irqsave(&s->lock, flags); |
216 | s->data_available_for_read = (s->block_count > 0); |
217 | spin_unlock_irqrestore(lock: &s->lock, flags); |
218 | } |
219 | |
220 | static void block_to_buf(struct saa6588 *s, unsigned char *blockbuf) |
221 | { |
222 | unsigned int i; |
223 | |
224 | if (debug > 3) |
225 | dprintk(PREFIX "New block: " ); |
226 | |
227 | for (i = 0; i < 3; ++i) { |
228 | if (debug > 3) |
229 | dprintk("0x%02x " , blockbuf[i]); |
230 | s->buffer[s->wr_index] = blockbuf[i]; |
231 | s->wr_index++; |
232 | } |
233 | |
234 | if (s->wr_index >= s->buf_size) |
235 | s->wr_index = 0; |
236 | |
237 | if (s->wr_index == s->rd_index) { |
238 | s->rd_index += 3; |
239 | if (s->rd_index >= s->buf_size) |
240 | s->rd_index = 0; |
241 | } else |
242 | s->block_count++; |
243 | |
244 | if (debug > 3) |
245 | dprintk("%d blocks total.\n" , s->block_count); |
246 | } |
247 | |
248 | static void saa6588_i2c_poll(struct saa6588 *s) |
249 | { |
250 | struct i2c_client *client = v4l2_get_subdevdata(sd: &s->sd); |
251 | unsigned long flags; |
252 | unsigned char tmpbuf[6]; |
253 | unsigned char blocknum; |
254 | unsigned char tmp; |
255 | |
256 | /* Although we only need 3 bytes, we have to read at least 6. |
257 | SAA6588 returns garbage otherwise. */ |
258 | if (6 != i2c_master_recv(client, buf: &tmpbuf[0], count: 6)) { |
259 | if (debug > 1) |
260 | dprintk(PREFIX "read error!\n" ); |
261 | return; |
262 | } |
263 | |
264 | s->sync = tmpbuf[0] & 0x10; |
265 | if (!s->sync) |
266 | return; |
267 | blocknum = tmpbuf[0] >> 5; |
268 | if (blocknum == s->last_blocknum) { |
269 | if (debug > 3) |
270 | dprintk("Saw block %d again.\n" , blocknum); |
271 | return; |
272 | } |
273 | |
274 | s->last_blocknum = blocknum; |
275 | |
276 | /* |
277 | Byte order according to v4l2 specification: |
278 | |
279 | Byte 0: Least Significant Byte of RDS Block |
280 | Byte 1: Most Significant Byte of RDS Block |
281 | Byte 2 Bit 7: Error bit. Indicates that an uncorrectable error |
282 | occurred during reception of this block. |
283 | Bit 6: Corrected bit. Indicates that an error was |
284 | corrected for this data block. |
285 | Bits 5-3: Same as bits 0-2. |
286 | Bits 2-0: Block number. |
287 | |
288 | SAA6588 byte order is Status-MSB-LSB, so we have to swap the |
289 | first and the last of the 3 bytes block. |
290 | */ |
291 | |
292 | swap(tmpbuf[2], tmpbuf[0]); |
293 | |
294 | /* Map 'Invalid block E' to 'Invalid Block' */ |
295 | if (blocknum == 6) |
296 | blocknum = V4L2_RDS_BLOCK_INVALID; |
297 | /* And if are not in mmbs mode, then 'Block E' is also mapped |
298 | to 'Invalid Block'. As far as I can tell MMBS is discontinued, |
299 | and if there is ever a need to support E blocks, then please |
300 | contact the linux-media mailinglist. */ |
301 | else if (!mmbs && blocknum == 5) |
302 | blocknum = V4L2_RDS_BLOCK_INVALID; |
303 | tmp = blocknum; |
304 | tmp |= blocknum << 3; /* Received offset == Offset Name (OK ?) */ |
305 | if ((tmpbuf[2] & 0x03) == 0x03) |
306 | tmp |= V4L2_RDS_BLOCK_ERROR; /* uncorrectable error */ |
307 | else if ((tmpbuf[2] & 0x03) != 0x00) |
308 | tmp |= V4L2_RDS_BLOCK_CORRECTED; /* corrected error */ |
309 | tmpbuf[2] = tmp; /* Is this enough ? Should we also check other bits ? */ |
310 | |
311 | spin_lock_irqsave(&s->lock, flags); |
312 | block_to_buf(s, blockbuf: tmpbuf); |
313 | spin_unlock_irqrestore(lock: &s->lock, flags); |
314 | s->data_available_for_read = 1; |
315 | wake_up_interruptible(&s->read_queue); |
316 | } |
317 | |
318 | static void saa6588_work(struct work_struct *work) |
319 | { |
320 | struct saa6588 *s = container_of(work, struct saa6588, work.work); |
321 | |
322 | saa6588_i2c_poll(s); |
323 | schedule_delayed_work(dwork: &s->work, delay: msecs_to_jiffies(m: 20)); |
324 | } |
325 | |
326 | static void saa6588_configure(struct saa6588 *s) |
327 | { |
328 | struct i2c_client *client = v4l2_get_subdevdata(sd: &s->sd); |
329 | unsigned char buf[3]; |
330 | int rc; |
331 | |
332 | buf[0] = cSyncRestart; |
333 | if (mmbs) |
334 | buf[0] |= cProcessingModeRBDS; |
335 | |
336 | buf[1] = cFlywheelDefault; |
337 | switch (plvl) { |
338 | case 0: |
339 | buf[1] |= cPauseLevel_11mV; |
340 | break; |
341 | case 1: |
342 | buf[1] |= cPauseLevel_17mV; |
343 | break; |
344 | case 2: |
345 | buf[1] |= cPauseLevel_27mV; |
346 | break; |
347 | case 3: |
348 | buf[1] |= cPauseLevel_43mV; |
349 | break; |
350 | default: /* nothing */ |
351 | break; |
352 | } |
353 | |
354 | buf[2] = cQualityDetectDefault | cSelectOscFreqON; |
355 | |
356 | switch (xtal) { |
357 | case 0: |
358 | buf[2] |= cOscFreq_4332kHz; |
359 | break; |
360 | case 1: |
361 | buf[2] |= cOscFreq_8664kHz; |
362 | break; |
363 | case 2: |
364 | buf[2] |= cOscFreq_12996kHz; |
365 | break; |
366 | case 3: |
367 | buf[2] |= cOscFreq_17328kHz; |
368 | break; |
369 | default: /* nothing */ |
370 | break; |
371 | } |
372 | |
373 | dprintk(PREFIX "writing: 0w=0x%02x 1w=0x%02x 2w=0x%02x\n" , |
374 | buf[0], buf[1], buf[2]); |
375 | |
376 | rc = i2c_master_send(client, buf, count: 3); |
377 | if (rc != 3) |
378 | printk(PREFIX "i2c i/o error: rc == %d (should be 3)\n" , rc); |
379 | } |
380 | |
381 | /* ---------------------------------------------------------------------- */ |
382 | |
383 | static long saa6588_command(struct v4l2_subdev *sd, unsigned int cmd, void *arg) |
384 | { |
385 | struct saa6588 *s = to_saa6588(sd); |
386 | struct saa6588_command *a = arg; |
387 | |
388 | switch (cmd) { |
389 | /* --- close() for /dev/radio --- */ |
390 | case SAA6588_CMD_CLOSE: |
391 | s->data_available_for_read = 1; |
392 | wake_up_interruptible(&s->read_queue); |
393 | s->data_available_for_read = 0; |
394 | a->result = 0; |
395 | break; |
396 | /* --- read() for /dev/radio --- */ |
397 | case SAA6588_CMD_READ: |
398 | read_from_buf(s, a); |
399 | break; |
400 | /* --- poll() for /dev/radio --- */ |
401 | case SAA6588_CMD_POLL: |
402 | a->poll_mask = 0; |
403 | if (s->data_available_for_read) |
404 | a->poll_mask |= EPOLLIN | EPOLLRDNORM; |
405 | poll_wait(filp: a->instance, wait_address: &s->read_queue, p: a->event_list); |
406 | break; |
407 | |
408 | default: |
409 | /* nothing */ |
410 | return -ENOIOCTLCMD; |
411 | } |
412 | return 0; |
413 | } |
414 | |
415 | static int saa6588_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt) |
416 | { |
417 | struct saa6588 *s = to_saa6588(sd); |
418 | |
419 | vt->capability |= V4L2_TUNER_CAP_RDS | V4L2_TUNER_CAP_RDS_BLOCK_IO; |
420 | if (s->sync) |
421 | vt->rxsubchans |= V4L2_TUNER_SUB_RDS; |
422 | return 0; |
423 | } |
424 | |
425 | static int saa6588_s_tuner(struct v4l2_subdev *sd, const struct v4l2_tuner *vt) |
426 | { |
427 | struct saa6588 *s = to_saa6588(sd); |
428 | |
429 | saa6588_configure(s); |
430 | return 0; |
431 | } |
432 | |
433 | /* ----------------------------------------------------------------------- */ |
434 | |
435 | static const struct v4l2_subdev_core_ops saa6588_core_ops = { |
436 | .command = saa6588_command, |
437 | }; |
438 | |
439 | static const struct v4l2_subdev_tuner_ops saa6588_tuner_ops = { |
440 | .g_tuner = saa6588_g_tuner, |
441 | .s_tuner = saa6588_s_tuner, |
442 | }; |
443 | |
444 | static const struct v4l2_subdev_ops saa6588_ops = { |
445 | .core = &saa6588_core_ops, |
446 | .tuner = &saa6588_tuner_ops, |
447 | }; |
448 | |
449 | /* ---------------------------------------------------------------------- */ |
450 | |
451 | static int saa6588_probe(struct i2c_client *client) |
452 | { |
453 | struct saa6588 *s; |
454 | struct v4l2_subdev *sd; |
455 | |
456 | v4l_info(client, "saa6588 found @ 0x%x (%s)\n" , |
457 | client->addr << 1, client->adapter->name); |
458 | |
459 | s = devm_kzalloc(dev: &client->dev, size: sizeof(*s), GFP_KERNEL); |
460 | if (s == NULL) |
461 | return -ENOMEM; |
462 | |
463 | s->buf_size = bufblocks * 3; |
464 | |
465 | s->buffer = devm_kzalloc(dev: &client->dev, size: s->buf_size, GFP_KERNEL); |
466 | if (s->buffer == NULL) |
467 | return -ENOMEM; |
468 | sd = &s->sd; |
469 | v4l2_i2c_subdev_init(sd, client, ops: &saa6588_ops); |
470 | spin_lock_init(&s->lock); |
471 | s->block_count = 0; |
472 | s->wr_index = 0; |
473 | s->rd_index = 0; |
474 | s->last_blocknum = 0xff; |
475 | init_waitqueue_head(&s->read_queue); |
476 | s->data_available_for_read = 0; |
477 | |
478 | saa6588_configure(s); |
479 | |
480 | /* start polling via eventd */ |
481 | INIT_DELAYED_WORK(&s->work, saa6588_work); |
482 | schedule_delayed_work(dwork: &s->work, delay: 0); |
483 | return 0; |
484 | } |
485 | |
486 | static void saa6588_remove(struct i2c_client *client) |
487 | { |
488 | struct v4l2_subdev *sd = i2c_get_clientdata(client); |
489 | struct saa6588 *s = to_saa6588(sd); |
490 | |
491 | v4l2_device_unregister_subdev(sd); |
492 | |
493 | cancel_delayed_work_sync(dwork: &s->work); |
494 | } |
495 | |
496 | /* ----------------------------------------------------------------------- */ |
497 | |
498 | static const struct i2c_device_id saa6588_id[] = { |
499 | { "saa6588" , 0 }, |
500 | { } |
501 | }; |
502 | MODULE_DEVICE_TABLE(i2c, saa6588_id); |
503 | |
504 | static struct i2c_driver saa6588_driver = { |
505 | .driver = { |
506 | .name = "saa6588" , |
507 | }, |
508 | .probe = saa6588_probe, |
509 | .remove = saa6588_remove, |
510 | .id_table = saa6588_id, |
511 | }; |
512 | |
513 | module_i2c_driver(saa6588_driver); |
514 | |