458 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * cx18 ADEC audio functions4 *5 * Derived from cx25840-audio.c6 *7 * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>8 * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net>9 */10 11#include "cx18-driver.h"12 13static int set_audclk_freq(struct cx18 *cx, u32 freq)14{15 struct cx18_av_state *state = &cx->av_state;16 17 if (freq != 32000 && freq != 44100 && freq != 48000)18 return -EINVAL;19 20 /*21 * The PLL parameters are based on the external crystal frequency that22 * would ideally be:23 *24 * NTSC Color subcarrier freq * 8 =25 * 4.5 MHz/286 * 455/2 * 8 = 28.63636363... MHz26 *27 * The accidents of history and rationale that explain from where this28 * combination of magic numbers originate can be found in:29 *30 * [1] Abrahams, I. C., "Choice of Chrominance Subcarrier Frequency in31 * the NTSC Standards", Proceedings of the I-R-E, January 1954, pp 79-8032 *33 * [2] Abrahams, I. C., "The 'Frequency Interleaving' Principle in the34 * NTSC Standards", Proceedings of the I-R-E, January 1954, pp 81-8335 *36 * As Mike Bradley has rightly pointed out, it's not the exact crystal37 * frequency that matters, only that all parts of the driver and38 * firmware are using the same value (close to the ideal value).39 *40 * Since I have a strong suspicion that, if the firmware ever assumes a41 * crystal value at all, it will assume 28.636360 MHz, the crystal42 * freq used in calculations in this driver will be:43 *44 * xtal_freq = 28.636360 MHz45 *46 * an error of less than 0.13 ppm which is way, way better than any off47 * the shelf crystal will have for accuracy anyway.48 *49 * Below I aim to run the PLLs' VCOs near 400 MHz to minimize error.50 *51 * Many thanks to Jeff Campbell and Mike Bradley for their extensive52 * investigation, experimentation, testing, and suggested solutions of53 * audio/video sync problems with SVideo and CVBS captures.54 */55 56 if (state->aud_input > CX18_AV_AUDIO_SERIAL2) {57 switch (freq) {58 case 32000:59 /*60 * VID_PLL Integer = 0x0f, VID_PLL Post Divider = 0x0461 * AUX_PLL Integer = 0x0d, AUX PLL Post Divider = 0x2062 */63 cx18_av_write4(cx, 0x108, 0x200d040f);64 65 /* VID_PLL Fraction = 0x2be2fe */66 /* xtal * 0xf.15f17f0/4 = 108 MHz: 432 MHz pre-postdiv*/67 cx18_av_write4(cx, 0x10c, 0x002be2fe);68 69 /* AUX_PLL Fraction = 0x176740c */70 /* xtal * 0xd.bb3a060/0x20 = 32000 * 384: 393 MHz p-pd*/71 cx18_av_write4(cx, 0x110, 0x0176740c);72 73 /* src3/4/6_ctl */74 /* 0x1.f77f = (4 * xtal/8*2/455) / 32000 */75 cx18_av_write4(cx, 0x900, 0x0801f77f);76 cx18_av_write4(cx, 0x904, 0x0801f77f);77 cx18_av_write4(cx, 0x90c, 0x0801f77f);78 79 /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x20 */80 cx18_av_write(cx, 0x127, 0x60);81 82 /* AUD_COUNT = 0x2fff = 8 samples * 4 * 384 - 1 */83 cx18_av_write4(cx, 0x12c, 0x11202fff);84 85 /*86 * EN_AV_LOCK = 087 * VID_COUNT = 0x0d2ef8 = 107999.000 * 8 =88 * ((8 samples/32,000) * (13,500,000 * 8) * 4 - 1) * 889 */90 cx18_av_write4(cx, 0x128, 0xa00d2ef8);91 break;92 93 case 44100:94 /*95 * VID_PLL Integer = 0x0f, VID_PLL Post Divider = 0x0496 * AUX_PLL Integer = 0x0e, AUX PLL Post Divider = 0x1897 */98 cx18_av_write4(cx, 0x108, 0x180e040f);99 100 /* VID_PLL Fraction = 0x2be2fe */101 /* xtal * 0xf.15f17f0/4 = 108 MHz: 432 MHz pre-postdiv*/102 cx18_av_write4(cx, 0x10c, 0x002be2fe);103 104 /* AUX_PLL Fraction = 0x062a1f2 */105 /* xtal * 0xe.3150f90/0x18 = 44100 * 384: 406 MHz p-pd*/106 cx18_av_write4(cx, 0x110, 0x0062a1f2);107 108 /* src3/4/6_ctl */109 /* 0x1.6d59 = (4 * xtal/8*2/455) / 44100 */110 cx18_av_write4(cx, 0x900, 0x08016d59);111 cx18_av_write4(cx, 0x904, 0x08016d59);112 cx18_av_write4(cx, 0x90c, 0x08016d59);113 114 /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x18 */115 cx18_av_write(cx, 0x127, 0x58);116 117 /* AUD_COUNT = 0x92ff = 49 samples * 2 * 384 - 1 */118 cx18_av_write4(cx, 0x12c, 0x112092ff);119 120 /*121 * EN_AV_LOCK = 0122 * VID_COUNT = 0x1d4bf8 = 239999.000 * 8 =123 * ((49 samples/44,100) * (13,500,000 * 8) * 2 - 1) * 8124 */125 cx18_av_write4(cx, 0x128, 0xa01d4bf8);126 break;127 128 case 48000:129 /*130 * VID_PLL Integer = 0x0f, VID_PLL Post Divider = 0x04131 * AUX_PLL Integer = 0x0e, AUX PLL Post Divider = 0x16132 */133 cx18_av_write4(cx, 0x108, 0x160e040f);134 135 /* VID_PLL Fraction = 0x2be2fe */136 /* xtal * 0xf.15f17f0/4 = 108 MHz: 432 MHz pre-postdiv*/137 cx18_av_write4(cx, 0x10c, 0x002be2fe);138 139 /* AUX_PLL Fraction = 0x05227ad */140 /* xtal * 0xe.2913d68/0x16 = 48000 * 384: 406 MHz p-pd*/141 cx18_av_write4(cx, 0x110, 0x005227ad);142 143 /* src3/4/6_ctl */144 /* 0x1.4faa = (4 * xtal/8*2/455) / 48000 */145 cx18_av_write4(cx, 0x900, 0x08014faa);146 cx18_av_write4(cx, 0x904, 0x08014faa);147 cx18_av_write4(cx, 0x90c, 0x08014faa);148 149 /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x16 */150 cx18_av_write(cx, 0x127, 0x56);151 152 /* AUD_COUNT = 0x5fff = 4 samples * 16 * 384 - 1 */153 cx18_av_write4(cx, 0x12c, 0x11205fff);154 155 /*156 * EN_AV_LOCK = 0157 * VID_COUNT = 0x1193f8 = 143999.000 * 8 =158 * ((4 samples/48,000) * (13,500,000 * 8) * 16 - 1) * 8159 */160 cx18_av_write4(cx, 0x128, 0xa01193f8);161 break;162 }163 } else {164 switch (freq) {165 case 32000:166 /*167 * VID_PLL Integer = 0x0f, VID_PLL Post Divider = 0x04168 * AUX_PLL Integer = 0x0d, AUX PLL Post Divider = 0x30169 */170 cx18_av_write4(cx, 0x108, 0x300d040f);171 172 /* VID_PLL Fraction = 0x2be2fe */173 /* xtal * 0xf.15f17f0/4 = 108 MHz: 432 MHz pre-postdiv*/174 cx18_av_write4(cx, 0x10c, 0x002be2fe);175 176 /* AUX_PLL Fraction = 0x176740c */177 /* xtal * 0xd.bb3a060/0x30 = 32000 * 256: 393 MHz p-pd*/178 cx18_av_write4(cx, 0x110, 0x0176740c);179 180 /* src1_ctl */181 /* 0x1.0000 = 32000/32000 */182 cx18_av_write4(cx, 0x8f8, 0x08010000);183 184 /* src3/4/6_ctl */185 /* 0x2.0000 = 2 * (32000/32000) */186 cx18_av_write4(cx, 0x900, 0x08020000);187 cx18_av_write4(cx, 0x904, 0x08020000);188 cx18_av_write4(cx, 0x90c, 0x08020000);189 190 /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x30 */191 cx18_av_write(cx, 0x127, 0x70);192 193 /* AUD_COUNT = 0x1fff = 8 samples * 4 * 256 - 1 */194 cx18_av_write4(cx, 0x12c, 0x11201fff);195 196 /*197 * EN_AV_LOCK = 0198 * VID_COUNT = 0x0d2ef8 = 107999.000 * 8 =199 * ((8 samples/32,000) * (13,500,000 * 8) * 4 - 1) * 8200 */201 cx18_av_write4(cx, 0x128, 0xa00d2ef8);202 break;203 204 case 44100:205 /*206 * VID_PLL Integer = 0x0f, VID_PLL Post Divider = 0x04207 * AUX_PLL Integer = 0x0e, AUX PLL Post Divider = 0x24208 */209 cx18_av_write4(cx, 0x108, 0x240e040f);210 211 /* VID_PLL Fraction = 0x2be2fe */212 /* xtal * 0xf.15f17f0/4 = 108 MHz: 432 MHz pre-postdiv*/213 cx18_av_write4(cx, 0x10c, 0x002be2fe);214 215 /* AUX_PLL Fraction = 0x062a1f2 */216 /* xtal * 0xe.3150f90/0x24 = 44100 * 256: 406 MHz p-pd*/217 cx18_av_write4(cx, 0x110, 0x0062a1f2);218 219 /* src1_ctl */220 /* 0x1.60cd = 44100/32000 */221 cx18_av_write4(cx, 0x8f8, 0x080160cd);222 223 /* src3/4/6_ctl */224 /* 0x1.7385 = 2 * (32000/44100) */225 cx18_av_write4(cx, 0x900, 0x08017385);226 cx18_av_write4(cx, 0x904, 0x08017385);227 cx18_av_write4(cx, 0x90c, 0x08017385);228 229 /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x24 */230 cx18_av_write(cx, 0x127, 0x64);231 232 /* AUD_COUNT = 0x61ff = 49 samples * 2 * 256 - 1 */233 cx18_av_write4(cx, 0x12c, 0x112061ff);234 235 /*236 * EN_AV_LOCK = 0237 * VID_COUNT = 0x1d4bf8 = 239999.000 * 8 =238 * ((49 samples/44,100) * (13,500,000 * 8) * 2 - 1) * 8239 */240 cx18_av_write4(cx, 0x128, 0xa01d4bf8);241 break;242 243 case 48000:244 /*245 * VID_PLL Integer = 0x0f, VID_PLL Post Divider = 0x04246 * AUX_PLL Integer = 0x0d, AUX PLL Post Divider = 0x20247 */248 cx18_av_write4(cx, 0x108, 0x200d040f);249 250 /* VID_PLL Fraction = 0x2be2fe */251 /* xtal * 0xf.15f17f0/4 = 108 MHz: 432 MHz pre-postdiv*/252 cx18_av_write4(cx, 0x10c, 0x002be2fe);253 254 /* AUX_PLL Fraction = 0x176740c */255 /* xtal * 0xd.bb3a060/0x20 = 48000 * 256: 393 MHz p-pd*/256 cx18_av_write4(cx, 0x110, 0x0176740c);257 258 /* src1_ctl */259 /* 0x1.8000 = 48000/32000 */260 cx18_av_write4(cx, 0x8f8, 0x08018000);261 262 /* src3/4/6_ctl */263 /* 0x1.5555 = 2 * (32000/48000) */264 cx18_av_write4(cx, 0x900, 0x08015555);265 cx18_av_write4(cx, 0x904, 0x08015555);266 cx18_av_write4(cx, 0x90c, 0x08015555);267 268 /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x20 */269 cx18_av_write(cx, 0x127, 0x60);270 271 /* AUD_COUNT = 0x3fff = 4 samples * 16 * 256 - 1 */272 cx18_av_write4(cx, 0x12c, 0x11203fff);273 274 /*275 * EN_AV_LOCK = 0276 * VID_COUNT = 0x1193f8 = 143999.000 * 8 =277 * ((4 samples/48,000) * (13,500,000 * 8) * 16 - 1) * 8278 */279 cx18_av_write4(cx, 0x128, 0xa01193f8);280 break;281 }282 }283 284 state->audclk_freq = freq;285 286 return 0;287}288 289void cx18_av_audio_set_path(struct cx18 *cx)290{291 struct cx18_av_state *state = &cx->av_state;292 u8 v;293 294 /* stop microcontroller */295 v = cx18_av_read(cx, 0x803) & ~0x10;296 cx18_av_write_expect(cx, 0x803, v, v, 0x1f);297 298 /* assert soft reset */299 v = cx18_av_read(cx, 0x810) | 0x01;300 cx18_av_write_expect(cx, 0x810, v, v, 0x0f);301 302 /* Mute everything to prevent the PFFT! */303 cx18_av_write(cx, 0x8d3, 0x1f);304 305 if (state->aud_input <= CX18_AV_AUDIO_SERIAL2) {306 /* Set Path1 to Serial Audio Input */307 cx18_av_write4(cx, 0x8d0, 0x01011012);308 309 /* The microcontroller should not be started for the310 * non-tuner inputs: autodetection is specific for311 * TV audio. */312 } else {313 /* Set Path1 to Analog Demod Main Channel */314 cx18_av_write4(cx, 0x8d0, 0x1f063870);315 }316 317 set_audclk_freq(cx, state->audclk_freq);318 319 /* deassert soft reset */320 v = cx18_av_read(cx, 0x810) & ~0x01;321 cx18_av_write_expect(cx, 0x810, v, v, 0x0f);322 323 if (state->aud_input > CX18_AV_AUDIO_SERIAL2) {324 /* When the microcontroller detects the325 * audio format, it will unmute the lines */326 v = cx18_av_read(cx, 0x803) | 0x10;327 cx18_av_write_expect(cx, 0x803, v, v, 0x1f);328 }329}330 331static void set_volume(struct cx18 *cx, int volume)332{333 /* First convert the volume to msp3400 values (0-127) */334 int vol = volume >> 9;335 /* now scale it up to cx18_av values336 * -114dB to -96dB maps to 0337 * this should be 19, but in my testing that was 4dB too loud */338 if (vol <= 23)339 vol = 0;340 else341 vol -= 23;342 343 /* PATH1_VOLUME */344 cx18_av_write(cx, 0x8d4, 228 - (vol * 2));345}346 347static void set_bass(struct cx18 *cx, int bass)348{349 /* PATH1_EQ_BASS_VOL */350 cx18_av_and_or(cx, 0x8d9, ~0x3f, 48 - (bass * 48 / 0xffff));351}352 353static void set_treble(struct cx18 *cx, int treble)354{355 /* PATH1_EQ_TREBLE_VOL */356 cx18_av_and_or(cx, 0x8db, ~0x3f, 48 - (treble * 48 / 0xffff));357}358 359static void set_balance(struct cx18 *cx, int balance)360{361 int bal = balance >> 8;362 if (bal > 0x80) {363 /* PATH1_BAL_LEFT */364 cx18_av_and_or(cx, 0x8d5, 0x7f, 0x80);365 /* PATH1_BAL_LEVEL */366 cx18_av_and_or(cx, 0x8d5, ~0x7f, bal & 0x7f);367 } else {368 /* PATH1_BAL_LEFT */369 cx18_av_and_or(cx, 0x8d5, 0x7f, 0x00);370 /* PATH1_BAL_LEVEL */371 cx18_av_and_or(cx, 0x8d5, ~0x7f, 0x80 - bal);372 }373}374 375static void set_mute(struct cx18 *cx, int mute)376{377 struct cx18_av_state *state = &cx->av_state;378 u8 v;379 380 if (state->aud_input > CX18_AV_AUDIO_SERIAL2) {381 /* Must turn off microcontroller in order to mute sound.382 * Not sure if this is the best method, but it does work.383 * If the microcontroller is running, then it will undo any384 * changes to the mute register. */385 v = cx18_av_read(cx, 0x803);386 if (mute) {387 /* disable microcontroller */388 v &= ~0x10;389 cx18_av_write_expect(cx, 0x803, v, v, 0x1f);390 cx18_av_write(cx, 0x8d3, 0x1f);391 } else {392 /* enable microcontroller */393 v |= 0x10;394 cx18_av_write_expect(cx, 0x803, v, v, 0x1f);395 }396 } else {397 /* SRC1_MUTE_EN */398 cx18_av_and_or(cx, 0x8d3, ~0x2, mute ? 0x02 : 0x00);399 }400}401 402int cx18_av_s_clock_freq(struct v4l2_subdev *sd, u32 freq)403{404 struct cx18 *cx = v4l2_get_subdevdata(sd);405 struct cx18_av_state *state = &cx->av_state;406 int retval;407 u8 v;408 409 if (state->aud_input > CX18_AV_AUDIO_SERIAL2) {410 v = cx18_av_read(cx, 0x803) & ~0x10;411 cx18_av_write_expect(cx, 0x803, v, v, 0x1f);412 cx18_av_write(cx, 0x8d3, 0x1f);413 }414 v = cx18_av_read(cx, 0x810) | 0x1;415 cx18_av_write_expect(cx, 0x810, v, v, 0x0f);416 417 retval = set_audclk_freq(cx, freq);418 419 v = cx18_av_read(cx, 0x810) & ~0x1;420 cx18_av_write_expect(cx, 0x810, v, v, 0x0f);421 if (state->aud_input > CX18_AV_AUDIO_SERIAL2) {422 v = cx18_av_read(cx, 0x803) | 0x10;423 cx18_av_write_expect(cx, 0x803, v, v, 0x1f);424 }425 return retval;426}427 428static int cx18_av_audio_s_ctrl(struct v4l2_ctrl *ctrl)429{430 struct v4l2_subdev *sd = to_sd(ctrl);431 struct cx18 *cx = v4l2_get_subdevdata(sd);432 433 switch (ctrl->id) {434 case V4L2_CID_AUDIO_VOLUME:435 set_volume(cx, ctrl->val);436 break;437 case V4L2_CID_AUDIO_BASS:438 set_bass(cx, ctrl->val);439 break;440 case V4L2_CID_AUDIO_TREBLE:441 set_treble(cx, ctrl->val);442 break;443 case V4L2_CID_AUDIO_BALANCE:444 set_balance(cx, ctrl->val);445 break;446 case V4L2_CID_AUDIO_MUTE:447 set_mute(cx, ctrl->val);448 break;449 default:450 return -EINVAL;451 }452 return 0;453}454 455const struct v4l2_ctrl_ops cx18_av_audio_ctrl_ops = {456 .s_ctrl = cx18_av_audio_s_ctrl,457};458