2 * Stereo and SAP detection for cx88
4 * Copyright (c) 2009 Marton Balint <cus@fazekas.hu>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
20 #include <linux/slab.h>
21 #include <linux/kernel.h>
22 #include <linux/module.h>
23 #include <linux/jiffies.h>
24 #include <asm/div64.h>
26 #define INT_PI ((s32)(3.141592653589 * 32768.0))
28 #define compat_remainder(a, b) \
29 ((float)(((s32)((a) * 100)) % ((s32)((b) * 100))) / 100.0)
31 #define baseband_freq(carrier, srate, tone) ((s32)( \
32 (compat_remainder(carrier + tone, srate)) / srate * 2 * INT_PI))
35 * We calculate the baseband frequencies of the carrier and the pilot tones
36 * based on the the sampling rate of the audio rds fifo.
39 #define FREQ_A2_CARRIER baseband_freq(54687.5, 2689.36, 0.0)
40 #define FREQ_A2_DUAL baseband_freq(54687.5, 2689.36, 274.1)
41 #define FREQ_A2_STEREO baseband_freq(54687.5, 2689.36, 117.5)
44 * The frequencies below are from the reference driver. They probably need
45 * further adjustments, because they are not tested at all. You may even need
46 * to play a bit with the registers of the chip to select the proper signal
47 * for the input of the audio rds fifo, and measure it's sampling rate to
48 * calculate the proper baseband frequencies...
51 #define FREQ_A2M_CARRIER ((s32)(2.114516 * 32768.0))
52 #define FREQ_A2M_DUAL ((s32)(2.754916 * 32768.0))
53 #define FREQ_A2M_STEREO ((s32)(2.462326 * 32768.0))
55 #define FREQ_EIAJ_CARRIER ((s32)(1.963495 * 32768.0)) /* 5pi/8 */
56 #define FREQ_EIAJ_DUAL ((s32)(2.562118 * 32768.0))
57 #define FREQ_EIAJ_STEREO ((s32)(2.601053 * 32768.0))
59 #define FREQ_BTSC_DUAL ((s32)(1.963495 * 32768.0)) /* 5pi/8 */
60 #define FREQ_BTSC_DUAL_REF ((s32)(1.374446 * 32768.0)) /* 7pi/16 */
62 #define FREQ_BTSC_SAP ((s32)(2.471532 * 32768.0))
63 #define FREQ_BTSC_SAP_REF ((s32)(1.730072 * 32768.0))
65 /* The spectrum of the signal should be empty between these frequencies. */
66 #define FREQ_NOISE_START ((s32)(0.100000 * 32768.0))
67 #define FREQ_NOISE_END ((s32)(1.200000 * 32768.0))
69 static unsigned int dsp_debug
;
70 module_param(dsp_debug
, int, 0644);
71 MODULE_PARM_DESC(dsp_debug
, "enable audio dsp debug messages");
73 #define dprintk(level, fmt, arg...) do { \
74 if (dsp_debug >= level) \
75 printk(KERN_DEBUG pr_fmt("%s: dsp:" fmt), \
79 static s32
int_cos(u32 x
)
83 u16 period
= x
/ INT_PI
;
86 return -int_cos(x
- INT_PI
);
89 return -int_cos(INT_PI
/ 2 - (x
% (INT_PI
/ 2)));
91 * Now x is between 0 and INT_PI/2.
92 * To calculate cos(x) we use it's Taylor polinom.
94 t2
= x
* x
/ 32768 / 2;
95 t4
= t2
* x
/ 32768 * x
/ 32768 / 3 / 4;
96 t6
= t4
* x
/ 32768 * x
/ 32768 / 5 / 6;
97 t8
= t6
* x
/ 32768 * x
/ 32768 / 7 / 8;
98 ret
= 32768 - t2
+ t4
- t6
+ t8
;
102 static u32
int_goertzel(s16 x
[], u32 N
, u32 freq
)
105 * We use the Goertzel algorithm to determine the power of the
106 * given frequency in the signal
110 s32 coeff
= 2 * int_cos(freq
);
116 for (i
= 0; i
< N
; i
++) {
117 s32 s
= x
[i
] + ((s64
)coeff
* s_prev
/ 32768) - s_prev2
;
123 tmp
= (s64
)s_prev2
* s_prev2
+ (s64
)s_prev
* s_prev
-
124 (s64
)coeff
* s_prev2
* s_prev
/ 32768;
127 * XXX: N must be low enough so that N*N fits in s32.
128 * Else we need two divisions.
131 do_div(tmp
, divisor
);
136 static u32
freq_magnitude(s16 x
[], u32 N
, u32 freq
)
138 u32 sum
= int_goertzel(x
, N
, freq
);
140 return (u32
)int_sqrt(sum
);
143 static u32
noise_magnitude(s16 x
[], u32 N
, u32 freq_start
, u32 freq_end
)
151 /* The last 192 samples are enough for noise detection */
156 freq_step
= (freq_end
- freq_start
) / (samples
- 1);
158 for (i
= 0; i
< samples
; i
++) {
159 sum
+= int_goertzel(x
, N
, freq_start
);
160 freq_start
+= freq_step
;
163 return (u32
)int_sqrt(sum
/ samples
);
166 static s32
detect_a2_a2m_eiaj(struct cx88_core
*core
, s16 x
[], u32 N
)
168 s32 carrier
, stereo
, dual
, noise
;
169 s32 carrier_freq
, stereo_freq
, dual_freq
;
172 switch (core
->tvaudio
) {
175 carrier_freq
= FREQ_A2_CARRIER
;
176 stereo_freq
= FREQ_A2_STEREO
;
177 dual_freq
= FREQ_A2_DUAL
;
180 carrier_freq
= FREQ_A2M_CARRIER
;
181 stereo_freq
= FREQ_A2M_STEREO
;
182 dual_freq
= FREQ_A2M_DUAL
;
185 carrier_freq
= FREQ_EIAJ_CARRIER
;
186 stereo_freq
= FREQ_EIAJ_STEREO
;
187 dual_freq
= FREQ_EIAJ_DUAL
;
190 pr_warn("unsupported audio mode %d for %s\n",
191 core
->tvaudio
, __func__
);
195 carrier
= freq_magnitude(x
, N
, carrier_freq
);
196 stereo
= freq_magnitude(x
, N
, stereo_freq
);
197 dual
= freq_magnitude(x
, N
, dual_freq
);
198 noise
= noise_magnitude(x
, N
, FREQ_NOISE_START
, FREQ_NOISE_END
);
201 "detect a2/a2m/eiaj: carrier=%d, stereo=%d, dual=%d, noise=%d\n",
202 carrier
, stereo
, dual
, noise
);
205 ret
= V4L2_TUNER_SUB_STEREO
;
207 ret
= V4L2_TUNER_SUB_LANG1
| V4L2_TUNER_SUB_LANG2
;
209 if (core
->tvaudio
== WW_EIAJ
) {
210 /* EIAJ checks may need adjustments */
211 if ((carrier
> max(stereo
, dual
) * 2) &&
212 (carrier
< max(stereo
, dual
) * 6) &&
213 (carrier
> 20 && carrier
< 200) &&
214 (max(stereo
, dual
) > min(stereo
, dual
))) {
216 * For EIAJ the carrier is always present,
217 * so we probably don't need noise detection
222 if ((carrier
> max(stereo
, dual
) * 2) &&
223 (carrier
< max(stereo
, dual
) * 8) &&
224 (carrier
> 20 && carrier
< 200) &&
226 (max(stereo
, dual
) > min(stereo
, dual
) * 2)) {
230 return V4L2_TUNER_SUB_MONO
;
233 static s32
detect_btsc(struct cx88_core
*core
, s16 x
[], u32 N
)
235 s32 sap_ref
= freq_magnitude(x
, N
, FREQ_BTSC_SAP_REF
);
236 s32 sap
= freq_magnitude(x
, N
, FREQ_BTSC_SAP
);
237 s32 dual_ref
= freq_magnitude(x
, N
, FREQ_BTSC_DUAL_REF
);
238 s32 dual
= freq_magnitude(x
, N
, FREQ_BTSC_DUAL
);
240 dprintk(1, "detect btsc: dual_ref=%d, dual=%d, sap_ref=%d, sap=%d\n",
241 dual_ref
, dual
, sap_ref
, sap
);
242 /* FIXME: Currently not supported */
246 static s16
*read_rds_samples(struct cx88_core
*core
, u32
*N
)
248 const struct sram_channel
*srch
= &cx88_sram_channels
[SRAM_CH27
];
252 unsigned int bpl
= srch
->fifo_size
/ AUD_RDS_LINES
;
253 unsigned int spl
= bpl
/ 4;
254 unsigned int sample_count
= spl
* (AUD_RDS_LINES
- 1);
256 u32 current_address
= cx_read(srch
->ptr1_reg
);
257 u32 offset
= (current_address
- srch
->fifo_start
+ bpl
);
260 "read RDS samples: current_address=%08x (offset=%08x), sample_count=%d, aud_intstat=%08x\n",
262 current_address
- srch
->fifo_start
, sample_count
,
263 cx_read(MO_AUD_INTSTAT
));
264 samples
= kmalloc_array(sample_count
, sizeof(*samples
), GFP_KERNEL
);
270 for (i
= 0; i
< sample_count
; i
++) {
271 offset
= offset
% (AUD_RDS_LINES
* bpl
);
272 samples
[i
] = cx_read(srch
->fifo_start
+ offset
);
276 dprintk(2, "RDS samples dump: %*ph\n", sample_count
, samples
);
281 s32
cx88_dsp_detect_stereo_sap(struct cx88_core
*core
)
287 /* If audio RDS fifo is disabled, we can't read the samples */
288 if (!(cx_read(MO_AUD_DMACNTRL
) & 0x04))
290 if (!(cx_read(AUD_CTL
) & EN_FMRADIO_EN_RDS
))
293 /* Wait at least 500 ms after an audio standard change */
294 if (time_before(jiffies
, core
->last_change
+ msecs_to_jiffies(500)))
297 samples
= read_rds_samples(core
, &N
);
302 switch (core
->tvaudio
) {
307 ret
= detect_a2_a2m_eiaj(core
, samples
, N
);
310 ret
= detect_btsc(core
, samples
, N
);
324 dprintk(1, "stereo/sap detection result:%s%s%s\n",
325 (ret
& V4L2_TUNER_SUB_MONO
) ? " mono" : "",
326 (ret
& V4L2_TUNER_SUB_STEREO
) ? " stereo" : "",
327 (ret
& V4L2_TUNER_SUB_LANG2
) ? " dual" : "");
331 EXPORT_SYMBOL(cx88_dsp_detect_stereo_sap
);