162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * cx88x-audio.c - Conexant CX23880/23881 audio downstream driver driver 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * (c) 2001 Michael Eskin, Tom Zakrajsek [Windows version] 662306a36Sopenharmony_ci * (c) 2002 Yurij Sysoev <yurij@naturesoft.net> 762306a36Sopenharmony_ci * (c) 2003 Gerd Knorr <kraxel@bytesex.org> 862306a36Sopenharmony_ci * 962306a36Sopenharmony_ci * ----------------------------------------------------------------------- 1062306a36Sopenharmony_ci * 1162306a36Sopenharmony_ci * Lot of voodoo here. Even the data sheet doesn't help to 1262306a36Sopenharmony_ci * understand what is going on here, the documentation for the audio 1362306a36Sopenharmony_ci * part of the cx2388x chip is *very* bad. 1462306a36Sopenharmony_ci * 1562306a36Sopenharmony_ci * Some of this comes from party done linux driver sources I got from 1662306a36Sopenharmony_ci * [undocumented]. 1762306a36Sopenharmony_ci * 1862306a36Sopenharmony_ci * Some comes from the dscaler sources, one of the dscaler driver guy works 1962306a36Sopenharmony_ci * for Conexant ... 2062306a36Sopenharmony_ci * 2162306a36Sopenharmony_ci * ----------------------------------------------------------------------- 2262306a36Sopenharmony_ci */ 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci#include "cx88.h" 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ci#include <linux/module.h> 2762306a36Sopenharmony_ci#include <linux/errno.h> 2862306a36Sopenharmony_ci#include <linux/freezer.h> 2962306a36Sopenharmony_ci#include <linux/kernel.h> 3062306a36Sopenharmony_ci#include <linux/mm.h> 3162306a36Sopenharmony_ci#include <linux/poll.h> 3262306a36Sopenharmony_ci#include <linux/signal.h> 3362306a36Sopenharmony_ci#include <linux/ioport.h> 3462306a36Sopenharmony_ci#include <linux/types.h> 3562306a36Sopenharmony_ci#include <linux/interrupt.h> 3662306a36Sopenharmony_ci#include <linux/vmalloc.h> 3762306a36Sopenharmony_ci#include <linux/init.h> 3862306a36Sopenharmony_ci#include <linux/delay.h> 3962306a36Sopenharmony_ci#include <linux/kthread.h> 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_cistatic unsigned int audio_debug; 4262306a36Sopenharmony_cimodule_param(audio_debug, int, 0644); 4362306a36Sopenharmony_ciMODULE_PARM_DESC(audio_debug, "enable debug messages [audio]"); 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_cistatic unsigned int always_analog; 4662306a36Sopenharmony_cimodule_param(always_analog, int, 0644); 4762306a36Sopenharmony_ciMODULE_PARM_DESC(always_analog, "force analog audio out"); 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_cistatic unsigned int radio_deemphasis; 5062306a36Sopenharmony_cimodule_param(radio_deemphasis, int, 0644); 5162306a36Sopenharmony_ciMODULE_PARM_DESC(radio_deemphasis, 5262306a36Sopenharmony_ci "Radio deemphasis time constant, 0=None, 1=50us (elsewhere), 2=75us (USA)"); 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci#define dprintk(fmt, arg...) do { \ 5562306a36Sopenharmony_ci if (audio_debug) \ 5662306a36Sopenharmony_ci printk(KERN_DEBUG pr_fmt("%s: tvaudio:" fmt), \ 5762306a36Sopenharmony_ci __func__, ##arg); \ 5862306a36Sopenharmony_ci} while (0) 5962306a36Sopenharmony_ci/* ----------------------------------------------------------- */ 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_cistatic const char * const aud_ctl_names[64] = { 6262306a36Sopenharmony_ci [EN_BTSC_FORCE_MONO] = "BTSC_FORCE_MONO", 6362306a36Sopenharmony_ci [EN_BTSC_FORCE_STEREO] = "BTSC_FORCE_STEREO", 6462306a36Sopenharmony_ci [EN_BTSC_FORCE_SAP] = "BTSC_FORCE_SAP", 6562306a36Sopenharmony_ci [EN_BTSC_AUTO_STEREO] = "BTSC_AUTO_STEREO", 6662306a36Sopenharmony_ci [EN_BTSC_AUTO_SAP] = "BTSC_AUTO_SAP", 6762306a36Sopenharmony_ci [EN_A2_FORCE_MONO1] = "A2_FORCE_MONO1", 6862306a36Sopenharmony_ci [EN_A2_FORCE_MONO2] = "A2_FORCE_MONO2", 6962306a36Sopenharmony_ci [EN_A2_FORCE_STEREO] = "A2_FORCE_STEREO", 7062306a36Sopenharmony_ci [EN_A2_AUTO_MONO2] = "A2_AUTO_MONO2", 7162306a36Sopenharmony_ci [EN_A2_AUTO_STEREO] = "A2_AUTO_STEREO", 7262306a36Sopenharmony_ci [EN_EIAJ_FORCE_MONO1] = "EIAJ_FORCE_MONO1", 7362306a36Sopenharmony_ci [EN_EIAJ_FORCE_MONO2] = "EIAJ_FORCE_MONO2", 7462306a36Sopenharmony_ci [EN_EIAJ_FORCE_STEREO] = "EIAJ_FORCE_STEREO", 7562306a36Sopenharmony_ci [EN_EIAJ_AUTO_MONO2] = "EIAJ_AUTO_MONO2", 7662306a36Sopenharmony_ci [EN_EIAJ_AUTO_STEREO] = "EIAJ_AUTO_STEREO", 7762306a36Sopenharmony_ci [EN_NICAM_FORCE_MONO1] = "NICAM_FORCE_MONO1", 7862306a36Sopenharmony_ci [EN_NICAM_FORCE_MONO2] = "NICAM_FORCE_MONO2", 7962306a36Sopenharmony_ci [EN_NICAM_FORCE_STEREO] = "NICAM_FORCE_STEREO", 8062306a36Sopenharmony_ci [EN_NICAM_AUTO_MONO2] = "NICAM_AUTO_MONO2", 8162306a36Sopenharmony_ci [EN_NICAM_AUTO_STEREO] = "NICAM_AUTO_STEREO", 8262306a36Sopenharmony_ci [EN_FMRADIO_FORCE_MONO] = "FMRADIO_FORCE_MONO", 8362306a36Sopenharmony_ci [EN_FMRADIO_FORCE_STEREO] = "FMRADIO_FORCE_STEREO", 8462306a36Sopenharmony_ci [EN_FMRADIO_AUTO_STEREO] = "FMRADIO_AUTO_STEREO", 8562306a36Sopenharmony_ci}; 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_cistruct rlist { 8862306a36Sopenharmony_ci u32 reg; 8962306a36Sopenharmony_ci u32 val; 9062306a36Sopenharmony_ci}; 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_cistatic void set_audio_registers(struct cx88_core *core, const struct rlist *l) 9362306a36Sopenharmony_ci{ 9462306a36Sopenharmony_ci int i; 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci for (i = 0; l[i].reg; i++) { 9762306a36Sopenharmony_ci switch (l[i].reg) { 9862306a36Sopenharmony_ci case AUD_PDF_DDS_CNST_BYTE2: 9962306a36Sopenharmony_ci case AUD_PDF_DDS_CNST_BYTE1: 10062306a36Sopenharmony_ci case AUD_PDF_DDS_CNST_BYTE0: 10162306a36Sopenharmony_ci case AUD_QAM_MODE: 10262306a36Sopenharmony_ci case AUD_PHACC_FREQ_8MSB: 10362306a36Sopenharmony_ci case AUD_PHACC_FREQ_8LSB: 10462306a36Sopenharmony_ci cx_writeb(l[i].reg, l[i].val); 10562306a36Sopenharmony_ci break; 10662306a36Sopenharmony_ci default: 10762306a36Sopenharmony_ci cx_write(l[i].reg, l[i].val); 10862306a36Sopenharmony_ci break; 10962306a36Sopenharmony_ci } 11062306a36Sopenharmony_ci } 11162306a36Sopenharmony_ci} 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_cistatic void set_audio_start(struct cx88_core *core, u32 mode) 11462306a36Sopenharmony_ci{ 11562306a36Sopenharmony_ci /* mute */ 11662306a36Sopenharmony_ci cx_write(AUD_VOL_CTL, (1 << 6)); 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci /* start programming */ 11962306a36Sopenharmony_ci cx_write(AUD_INIT, mode); 12062306a36Sopenharmony_ci cx_write(AUD_INIT_LD, 0x0001); 12162306a36Sopenharmony_ci cx_write(AUD_SOFT_RESET, 0x0001); 12262306a36Sopenharmony_ci} 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_cistatic void set_audio_finish(struct cx88_core *core, u32 ctl) 12562306a36Sopenharmony_ci{ 12662306a36Sopenharmony_ci u32 volume; 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ci /* restart dma; This avoids buzz in NICAM and is good in others */ 12962306a36Sopenharmony_ci cx88_stop_audio_dma(core); 13062306a36Sopenharmony_ci cx_write(AUD_RATE_THRES_DMD, 0x000000C0); 13162306a36Sopenharmony_ci cx88_start_audio_dma(core); 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ci if (core->board.mpeg & CX88_MPEG_BLACKBIRD) { 13462306a36Sopenharmony_ci cx_write(AUD_I2SINPUTCNTL, 4); 13562306a36Sopenharmony_ci cx_write(AUD_BAUDRATE, 1); 13662306a36Sopenharmony_ci /* 13762306a36Sopenharmony_ci * 'pass-thru mode': this enables the i2s 13862306a36Sopenharmony_ci * output to the mpeg encoder 13962306a36Sopenharmony_ci */ 14062306a36Sopenharmony_ci cx_set(AUD_CTL, EN_I2SOUT_ENABLE); 14162306a36Sopenharmony_ci cx_write(AUD_I2SOUTPUTCNTL, 1); 14262306a36Sopenharmony_ci cx_write(AUD_I2SCNTL, 0); 14362306a36Sopenharmony_ci /* cx_write(AUD_APB_IN_RATE_ADJ, 0); */ 14462306a36Sopenharmony_ci } 14562306a36Sopenharmony_ci if ((always_analog) || (!(core->board.mpeg & CX88_MPEG_BLACKBIRD))) { 14662306a36Sopenharmony_ci ctl |= EN_DAC_ENABLE; 14762306a36Sopenharmony_ci cx_write(AUD_CTL, ctl); 14862306a36Sopenharmony_ci } 14962306a36Sopenharmony_ci 15062306a36Sopenharmony_ci /* finish programming */ 15162306a36Sopenharmony_ci cx_write(AUD_SOFT_RESET, 0x0000); 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci /* unmute */ 15462306a36Sopenharmony_ci volume = cx_sread(SHADOW_AUD_VOL_CTL); 15562306a36Sopenharmony_ci cx_swrite(SHADOW_AUD_VOL_CTL, AUD_VOL_CTL, volume); 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_ci core->last_change = jiffies; 15862306a36Sopenharmony_ci} 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_ci/* ----------------------------------------------------------- */ 16162306a36Sopenharmony_ci 16262306a36Sopenharmony_cistatic void set_audio_standard_BTSC(struct cx88_core *core, unsigned int sap, 16362306a36Sopenharmony_ci u32 mode) 16462306a36Sopenharmony_ci{ 16562306a36Sopenharmony_ci static const struct rlist btsc[] = { 16662306a36Sopenharmony_ci {AUD_AFE_12DB_EN, 0x00000001}, 16762306a36Sopenharmony_ci {AUD_OUT1_SEL, 0x00000013}, 16862306a36Sopenharmony_ci {AUD_OUT1_SHIFT, 0x00000000}, 16962306a36Sopenharmony_ci {AUD_POLY0_DDS_CONSTANT, 0x0012010c}, 17062306a36Sopenharmony_ci {AUD_DMD_RA_DDS, 0x00c3e7aa}, 17162306a36Sopenharmony_ci {AUD_DBX_IN_GAIN, 0x00004734}, 17262306a36Sopenharmony_ci {AUD_DBX_WBE_GAIN, 0x00004640}, 17362306a36Sopenharmony_ci {AUD_DBX_SE_GAIN, 0x00008d31}, 17462306a36Sopenharmony_ci {AUD_DCOC_0_SRC, 0x0000001a}, 17562306a36Sopenharmony_ci {AUD_IIR1_4_SEL, 0x00000021}, 17662306a36Sopenharmony_ci {AUD_DCOC_PASS_IN, 0x00000003}, 17762306a36Sopenharmony_ci {AUD_DCOC_0_SHIFT_IN0, 0x0000000a}, 17862306a36Sopenharmony_ci {AUD_DCOC_0_SHIFT_IN1, 0x00000008}, 17962306a36Sopenharmony_ci {AUD_DCOC_1_SHIFT_IN0, 0x0000000a}, 18062306a36Sopenharmony_ci {AUD_DCOC_1_SHIFT_IN1, 0x00000008}, 18162306a36Sopenharmony_ci {AUD_DN0_FREQ, 0x0000283b}, 18262306a36Sopenharmony_ci {AUD_DN2_SRC_SEL, 0x00000008}, 18362306a36Sopenharmony_ci {AUD_DN2_FREQ, 0x00003000}, 18462306a36Sopenharmony_ci {AUD_DN2_AFC, 0x00000002}, 18562306a36Sopenharmony_ci {AUD_DN2_SHFT, 0x00000000}, 18662306a36Sopenharmony_ci {AUD_IIR2_2_SEL, 0x00000020}, 18762306a36Sopenharmony_ci {AUD_IIR2_2_SHIFT, 0x00000000}, 18862306a36Sopenharmony_ci {AUD_IIR2_3_SEL, 0x0000001f}, 18962306a36Sopenharmony_ci {AUD_IIR2_3_SHIFT, 0x00000000}, 19062306a36Sopenharmony_ci {AUD_CRDC1_SRC_SEL, 0x000003ce}, 19162306a36Sopenharmony_ci {AUD_CRDC1_SHIFT, 0x00000000}, 19262306a36Sopenharmony_ci {AUD_CORDIC_SHIFT_1, 0x00000007}, 19362306a36Sopenharmony_ci {AUD_DCOC_1_SRC, 0x0000001b}, 19462306a36Sopenharmony_ci {AUD_DCOC1_SHIFT, 0x00000000}, 19562306a36Sopenharmony_ci {AUD_RDSI_SEL, 0x00000008}, 19662306a36Sopenharmony_ci {AUD_RDSQ_SEL, 0x00000008}, 19762306a36Sopenharmony_ci {AUD_RDSI_SHIFT, 0x00000000}, 19862306a36Sopenharmony_ci {AUD_RDSQ_SHIFT, 0x00000000}, 19962306a36Sopenharmony_ci {AUD_POLYPH80SCALEFAC, 0x00000003}, 20062306a36Sopenharmony_ci { /* end of list */ }, 20162306a36Sopenharmony_ci }; 20262306a36Sopenharmony_ci static const struct rlist btsc_sap[] = { 20362306a36Sopenharmony_ci {AUD_AFE_12DB_EN, 0x00000001}, 20462306a36Sopenharmony_ci {AUD_DBX_IN_GAIN, 0x00007200}, 20562306a36Sopenharmony_ci {AUD_DBX_WBE_GAIN, 0x00006200}, 20662306a36Sopenharmony_ci {AUD_DBX_SE_GAIN, 0x00006200}, 20762306a36Sopenharmony_ci {AUD_IIR1_1_SEL, 0x00000000}, 20862306a36Sopenharmony_ci {AUD_IIR1_3_SEL, 0x00000001}, 20962306a36Sopenharmony_ci {AUD_DN1_SRC_SEL, 0x00000007}, 21062306a36Sopenharmony_ci {AUD_IIR1_4_SHIFT, 0x00000006}, 21162306a36Sopenharmony_ci {AUD_IIR2_1_SHIFT, 0x00000000}, 21262306a36Sopenharmony_ci {AUD_IIR2_2_SHIFT, 0x00000000}, 21362306a36Sopenharmony_ci {AUD_IIR3_0_SHIFT, 0x00000000}, 21462306a36Sopenharmony_ci {AUD_IIR3_1_SHIFT, 0x00000000}, 21562306a36Sopenharmony_ci {AUD_IIR3_0_SEL, 0x0000000d}, 21662306a36Sopenharmony_ci {AUD_IIR3_1_SEL, 0x0000000e}, 21762306a36Sopenharmony_ci {AUD_DEEMPH1_SRC_SEL, 0x00000014}, 21862306a36Sopenharmony_ci {AUD_DEEMPH1_SHIFT, 0x00000000}, 21962306a36Sopenharmony_ci {AUD_DEEMPH1_G0, 0x00004000}, 22062306a36Sopenharmony_ci {AUD_DEEMPH1_A0, 0x00000000}, 22162306a36Sopenharmony_ci {AUD_DEEMPH1_B0, 0x00000000}, 22262306a36Sopenharmony_ci {AUD_DEEMPH1_A1, 0x00000000}, 22362306a36Sopenharmony_ci {AUD_DEEMPH1_B1, 0x00000000}, 22462306a36Sopenharmony_ci {AUD_OUT0_SEL, 0x0000003f}, 22562306a36Sopenharmony_ci {AUD_OUT1_SEL, 0x0000003f}, 22662306a36Sopenharmony_ci {AUD_DN1_AFC, 0x00000002}, 22762306a36Sopenharmony_ci {AUD_DCOC_0_SHIFT_IN0, 0x0000000a}, 22862306a36Sopenharmony_ci {AUD_DCOC_0_SHIFT_IN1, 0x00000008}, 22962306a36Sopenharmony_ci {AUD_DCOC_1_SHIFT_IN0, 0x0000000a}, 23062306a36Sopenharmony_ci {AUD_DCOC_1_SHIFT_IN1, 0x00000008}, 23162306a36Sopenharmony_ci {AUD_IIR1_0_SEL, 0x0000001d}, 23262306a36Sopenharmony_ci {AUD_IIR1_2_SEL, 0x0000001e}, 23362306a36Sopenharmony_ci {AUD_IIR2_1_SEL, 0x00000002}, 23462306a36Sopenharmony_ci {AUD_IIR2_2_SEL, 0x00000004}, 23562306a36Sopenharmony_ci {AUD_IIR3_2_SEL, 0x0000000f}, 23662306a36Sopenharmony_ci {AUD_DCOC2_SHIFT, 0x00000001}, 23762306a36Sopenharmony_ci {AUD_IIR3_2_SHIFT, 0x00000001}, 23862306a36Sopenharmony_ci {AUD_DEEMPH0_SRC_SEL, 0x00000014}, 23962306a36Sopenharmony_ci {AUD_CORDIC_SHIFT_1, 0x00000006}, 24062306a36Sopenharmony_ci {AUD_POLY0_DDS_CONSTANT, 0x000e4db2}, 24162306a36Sopenharmony_ci {AUD_DMD_RA_DDS, 0x00f696e6}, 24262306a36Sopenharmony_ci {AUD_IIR2_3_SEL, 0x00000025}, 24362306a36Sopenharmony_ci {AUD_IIR1_4_SEL, 0x00000021}, 24462306a36Sopenharmony_ci {AUD_DN1_FREQ, 0x0000c965}, 24562306a36Sopenharmony_ci {AUD_DCOC_PASS_IN, 0x00000003}, 24662306a36Sopenharmony_ci {AUD_DCOC_0_SRC, 0x0000001a}, 24762306a36Sopenharmony_ci {AUD_DCOC_1_SRC, 0x0000001b}, 24862306a36Sopenharmony_ci {AUD_DCOC1_SHIFT, 0x00000000}, 24962306a36Sopenharmony_ci {AUD_RDSI_SEL, 0x00000009}, 25062306a36Sopenharmony_ci {AUD_RDSQ_SEL, 0x00000009}, 25162306a36Sopenharmony_ci {AUD_RDSI_SHIFT, 0x00000000}, 25262306a36Sopenharmony_ci {AUD_RDSQ_SHIFT, 0x00000000}, 25362306a36Sopenharmony_ci {AUD_POLYPH80SCALEFAC, 0x00000003}, 25462306a36Sopenharmony_ci { /* end of list */ }, 25562306a36Sopenharmony_ci }; 25662306a36Sopenharmony_ci 25762306a36Sopenharmony_ci mode |= EN_FMRADIO_EN_RDS; 25862306a36Sopenharmony_ci 25962306a36Sopenharmony_ci if (sap) { 26062306a36Sopenharmony_ci dprintk("%s SAP (status: unknown)\n", __func__); 26162306a36Sopenharmony_ci set_audio_start(core, SEL_SAP); 26262306a36Sopenharmony_ci set_audio_registers(core, btsc_sap); 26362306a36Sopenharmony_ci set_audio_finish(core, mode); 26462306a36Sopenharmony_ci } else { 26562306a36Sopenharmony_ci dprintk("%s (status: known-good)\n", __func__); 26662306a36Sopenharmony_ci set_audio_start(core, SEL_BTSC); 26762306a36Sopenharmony_ci set_audio_registers(core, btsc); 26862306a36Sopenharmony_ci set_audio_finish(core, mode); 26962306a36Sopenharmony_ci } 27062306a36Sopenharmony_ci} 27162306a36Sopenharmony_ci 27262306a36Sopenharmony_cistatic void set_audio_standard_NICAM(struct cx88_core *core, u32 mode) 27362306a36Sopenharmony_ci{ 27462306a36Sopenharmony_ci static const struct rlist nicam_l[] = { 27562306a36Sopenharmony_ci {AUD_AFE_12DB_EN, 0x00000001}, 27662306a36Sopenharmony_ci {AUD_RATE_ADJ1, 0x00000060}, 27762306a36Sopenharmony_ci {AUD_RATE_ADJ2, 0x000000F9}, 27862306a36Sopenharmony_ci {AUD_RATE_ADJ3, 0x000001CC}, 27962306a36Sopenharmony_ci {AUD_RATE_ADJ4, 0x000002B3}, 28062306a36Sopenharmony_ci {AUD_RATE_ADJ5, 0x00000726}, 28162306a36Sopenharmony_ci {AUD_DEEMPHDENOM1_R, 0x0000F3D0}, 28262306a36Sopenharmony_ci {AUD_DEEMPHDENOM2_R, 0x00000000}, 28362306a36Sopenharmony_ci {AUD_ERRLOGPERIOD_R, 0x00000064}, 28462306a36Sopenharmony_ci {AUD_ERRINTRPTTHSHLD1_R, 0x00000FFF}, 28562306a36Sopenharmony_ci {AUD_ERRINTRPTTHSHLD2_R, 0x0000001F}, 28662306a36Sopenharmony_ci {AUD_ERRINTRPTTHSHLD3_R, 0x0000000F}, 28762306a36Sopenharmony_ci {AUD_POLYPH80SCALEFAC, 0x00000003}, 28862306a36Sopenharmony_ci {AUD_DMD_RA_DDS, 0x00C00000}, 28962306a36Sopenharmony_ci {AUD_PLL_INT, 0x0000001E}, 29062306a36Sopenharmony_ci {AUD_PLL_DDS, 0x00000000}, 29162306a36Sopenharmony_ci {AUD_PLL_FRAC, 0x0000E542}, 29262306a36Sopenharmony_ci {AUD_START_TIMER, 0x00000000}, 29362306a36Sopenharmony_ci {AUD_DEEMPHNUMER1_R, 0x000353DE}, 29462306a36Sopenharmony_ci {AUD_DEEMPHNUMER2_R, 0x000001B1}, 29562306a36Sopenharmony_ci {AUD_PDF_DDS_CNST_BYTE2, 0x06}, 29662306a36Sopenharmony_ci {AUD_PDF_DDS_CNST_BYTE1, 0x82}, 29762306a36Sopenharmony_ci {AUD_PDF_DDS_CNST_BYTE0, 0x12}, 29862306a36Sopenharmony_ci {AUD_QAM_MODE, 0x05}, 29962306a36Sopenharmony_ci {AUD_PHACC_FREQ_8MSB, 0x34}, 30062306a36Sopenharmony_ci {AUD_PHACC_FREQ_8LSB, 0x4C}, 30162306a36Sopenharmony_ci {AUD_DEEMPHGAIN_R, 0x00006680}, 30262306a36Sopenharmony_ci {AUD_RATE_THRES_DMD, 0x000000C0}, 30362306a36Sopenharmony_ci { /* end of list */ }, 30462306a36Sopenharmony_ci }; 30562306a36Sopenharmony_ci 30662306a36Sopenharmony_ci static const struct rlist nicam_bgdki_common[] = { 30762306a36Sopenharmony_ci {AUD_AFE_12DB_EN, 0x00000001}, 30862306a36Sopenharmony_ci {AUD_RATE_ADJ1, 0x00000010}, 30962306a36Sopenharmony_ci {AUD_RATE_ADJ2, 0x00000040}, 31062306a36Sopenharmony_ci {AUD_RATE_ADJ3, 0x00000100}, 31162306a36Sopenharmony_ci {AUD_RATE_ADJ4, 0x00000400}, 31262306a36Sopenharmony_ci {AUD_RATE_ADJ5, 0x00001000}, 31362306a36Sopenharmony_ci {AUD_ERRLOGPERIOD_R, 0x00000fff}, 31462306a36Sopenharmony_ci {AUD_ERRINTRPTTHSHLD1_R, 0x000003ff}, 31562306a36Sopenharmony_ci {AUD_ERRINTRPTTHSHLD2_R, 0x000000ff}, 31662306a36Sopenharmony_ci {AUD_ERRINTRPTTHSHLD3_R, 0x0000003f}, 31762306a36Sopenharmony_ci {AUD_POLYPH80SCALEFAC, 0x00000003}, 31862306a36Sopenharmony_ci {AUD_DEEMPHGAIN_R, 0x000023c2}, 31962306a36Sopenharmony_ci {AUD_DEEMPHNUMER1_R, 0x0002a7bc}, 32062306a36Sopenharmony_ci {AUD_DEEMPHNUMER2_R, 0x0003023e}, 32162306a36Sopenharmony_ci {AUD_DEEMPHDENOM1_R, 0x0000f3d0}, 32262306a36Sopenharmony_ci {AUD_DEEMPHDENOM2_R, 0x00000000}, 32362306a36Sopenharmony_ci {AUD_PDF_DDS_CNST_BYTE2, 0x06}, 32462306a36Sopenharmony_ci {AUD_PDF_DDS_CNST_BYTE1, 0x82}, 32562306a36Sopenharmony_ci {AUD_QAM_MODE, 0x05}, 32662306a36Sopenharmony_ci { /* end of list */ }, 32762306a36Sopenharmony_ci }; 32862306a36Sopenharmony_ci 32962306a36Sopenharmony_ci static const struct rlist nicam_i[] = { 33062306a36Sopenharmony_ci {AUD_PDF_DDS_CNST_BYTE0, 0x12}, 33162306a36Sopenharmony_ci {AUD_PHACC_FREQ_8MSB, 0x3a}, 33262306a36Sopenharmony_ci {AUD_PHACC_FREQ_8LSB, 0x93}, 33362306a36Sopenharmony_ci { /* end of list */ }, 33462306a36Sopenharmony_ci }; 33562306a36Sopenharmony_ci 33662306a36Sopenharmony_ci static const struct rlist nicam_default[] = { 33762306a36Sopenharmony_ci {AUD_PDF_DDS_CNST_BYTE0, 0x16}, 33862306a36Sopenharmony_ci {AUD_PHACC_FREQ_8MSB, 0x34}, 33962306a36Sopenharmony_ci {AUD_PHACC_FREQ_8LSB, 0x4c}, 34062306a36Sopenharmony_ci { /* end of list */ }, 34162306a36Sopenharmony_ci }; 34262306a36Sopenharmony_ci 34362306a36Sopenharmony_ci set_audio_start(core, SEL_NICAM); 34462306a36Sopenharmony_ci switch (core->tvaudio) { 34562306a36Sopenharmony_ci case WW_L: 34662306a36Sopenharmony_ci dprintk("%s SECAM-L NICAM (status: devel)\n", __func__); 34762306a36Sopenharmony_ci set_audio_registers(core, nicam_l); 34862306a36Sopenharmony_ci break; 34962306a36Sopenharmony_ci case WW_I: 35062306a36Sopenharmony_ci dprintk("%s PAL-I NICAM (status: known-good)\n", __func__); 35162306a36Sopenharmony_ci set_audio_registers(core, nicam_bgdki_common); 35262306a36Sopenharmony_ci set_audio_registers(core, nicam_i); 35362306a36Sopenharmony_ci break; 35462306a36Sopenharmony_ci case WW_NONE: 35562306a36Sopenharmony_ci case WW_BTSC: 35662306a36Sopenharmony_ci case WW_BG: 35762306a36Sopenharmony_ci case WW_DK: 35862306a36Sopenharmony_ci case WW_EIAJ: 35962306a36Sopenharmony_ci case WW_I2SPT: 36062306a36Sopenharmony_ci case WW_FM: 36162306a36Sopenharmony_ci case WW_I2SADC: 36262306a36Sopenharmony_ci case WW_M: 36362306a36Sopenharmony_ci dprintk("%s PAL-BGDK NICAM (status: known-good)\n", __func__); 36462306a36Sopenharmony_ci set_audio_registers(core, nicam_bgdki_common); 36562306a36Sopenharmony_ci set_audio_registers(core, nicam_default); 36662306a36Sopenharmony_ci break; 36762306a36Sopenharmony_ci } 36862306a36Sopenharmony_ci 36962306a36Sopenharmony_ci mode |= EN_DMTRX_LR | EN_DMTRX_BYPASS; 37062306a36Sopenharmony_ci set_audio_finish(core, mode); 37162306a36Sopenharmony_ci} 37262306a36Sopenharmony_ci 37362306a36Sopenharmony_cistatic void set_audio_standard_A2(struct cx88_core *core, u32 mode) 37462306a36Sopenharmony_ci{ 37562306a36Sopenharmony_ci static const struct rlist a2_bgdk_common[] = { 37662306a36Sopenharmony_ci {AUD_ERRLOGPERIOD_R, 0x00000064}, 37762306a36Sopenharmony_ci {AUD_ERRINTRPTTHSHLD1_R, 0x00000fff}, 37862306a36Sopenharmony_ci {AUD_ERRINTRPTTHSHLD2_R, 0x0000001f}, 37962306a36Sopenharmony_ci {AUD_ERRINTRPTTHSHLD3_R, 0x0000000f}, 38062306a36Sopenharmony_ci {AUD_PDF_DDS_CNST_BYTE2, 0x06}, 38162306a36Sopenharmony_ci {AUD_PDF_DDS_CNST_BYTE1, 0x82}, 38262306a36Sopenharmony_ci {AUD_PDF_DDS_CNST_BYTE0, 0x12}, 38362306a36Sopenharmony_ci {AUD_QAM_MODE, 0x05}, 38462306a36Sopenharmony_ci {AUD_PHACC_FREQ_8MSB, 0x34}, 38562306a36Sopenharmony_ci {AUD_PHACC_FREQ_8LSB, 0x4c}, 38662306a36Sopenharmony_ci {AUD_RATE_ADJ1, 0x00000100}, 38762306a36Sopenharmony_ci {AUD_RATE_ADJ2, 0x00000200}, 38862306a36Sopenharmony_ci {AUD_RATE_ADJ3, 0x00000300}, 38962306a36Sopenharmony_ci {AUD_RATE_ADJ4, 0x00000400}, 39062306a36Sopenharmony_ci {AUD_RATE_ADJ5, 0x00000500}, 39162306a36Sopenharmony_ci {AUD_THR_FR, 0x00000000}, 39262306a36Sopenharmony_ci {AAGC_HYST, 0x0000001a}, 39362306a36Sopenharmony_ci {AUD_PILOT_BQD_1_K0, 0x0000755b}, 39462306a36Sopenharmony_ci {AUD_PILOT_BQD_1_K1, 0x00551340}, 39562306a36Sopenharmony_ci {AUD_PILOT_BQD_1_K2, 0x006d30be}, 39662306a36Sopenharmony_ci {AUD_PILOT_BQD_1_K3, 0xffd394af}, 39762306a36Sopenharmony_ci {AUD_PILOT_BQD_1_K4, 0x00400000}, 39862306a36Sopenharmony_ci {AUD_PILOT_BQD_2_K0, 0x00040000}, 39962306a36Sopenharmony_ci {AUD_PILOT_BQD_2_K1, 0x002a4841}, 40062306a36Sopenharmony_ci {AUD_PILOT_BQD_2_K2, 0x00400000}, 40162306a36Sopenharmony_ci {AUD_PILOT_BQD_2_K3, 0x00000000}, 40262306a36Sopenharmony_ci {AUD_PILOT_BQD_2_K4, 0x00000000}, 40362306a36Sopenharmony_ci {AUD_MODE_CHG_TIMER, 0x00000040}, 40462306a36Sopenharmony_ci {AUD_AFE_12DB_EN, 0x00000001}, 40562306a36Sopenharmony_ci {AUD_CORDIC_SHIFT_0, 0x00000007}, 40662306a36Sopenharmony_ci {AUD_CORDIC_SHIFT_1, 0x00000007}, 40762306a36Sopenharmony_ci {AUD_DEEMPH0_G0, 0x00000380}, 40862306a36Sopenharmony_ci {AUD_DEEMPH1_G0, 0x00000380}, 40962306a36Sopenharmony_ci {AUD_DCOC_0_SRC, 0x0000001a}, 41062306a36Sopenharmony_ci {AUD_DCOC0_SHIFT, 0x00000000}, 41162306a36Sopenharmony_ci {AUD_DCOC_0_SHIFT_IN0, 0x0000000a}, 41262306a36Sopenharmony_ci {AUD_DCOC_0_SHIFT_IN1, 0x00000008}, 41362306a36Sopenharmony_ci {AUD_DCOC_PASS_IN, 0x00000003}, 41462306a36Sopenharmony_ci {AUD_IIR3_0_SEL, 0x00000021}, 41562306a36Sopenharmony_ci {AUD_DN2_AFC, 0x00000002}, 41662306a36Sopenharmony_ci {AUD_DCOC_1_SRC, 0x0000001b}, 41762306a36Sopenharmony_ci {AUD_DCOC1_SHIFT, 0x00000000}, 41862306a36Sopenharmony_ci {AUD_DCOC_1_SHIFT_IN0, 0x0000000a}, 41962306a36Sopenharmony_ci {AUD_DCOC_1_SHIFT_IN1, 0x00000008}, 42062306a36Sopenharmony_ci {AUD_IIR3_1_SEL, 0x00000023}, 42162306a36Sopenharmony_ci {AUD_RDSI_SEL, 0x00000017}, 42262306a36Sopenharmony_ci {AUD_RDSI_SHIFT, 0x00000000}, 42362306a36Sopenharmony_ci {AUD_RDSQ_SEL, 0x00000017}, 42462306a36Sopenharmony_ci {AUD_RDSQ_SHIFT, 0x00000000}, 42562306a36Sopenharmony_ci {AUD_PLL_INT, 0x0000001e}, 42662306a36Sopenharmony_ci {AUD_PLL_DDS, 0x00000000}, 42762306a36Sopenharmony_ci {AUD_PLL_FRAC, 0x0000e542}, 42862306a36Sopenharmony_ci {AUD_POLYPH80SCALEFAC, 0x00000001}, 42962306a36Sopenharmony_ci {AUD_START_TIMER, 0x00000000}, 43062306a36Sopenharmony_ci { /* end of list */ }, 43162306a36Sopenharmony_ci }; 43262306a36Sopenharmony_ci 43362306a36Sopenharmony_ci static const struct rlist a2_bg[] = { 43462306a36Sopenharmony_ci {AUD_DMD_RA_DDS, 0x002a4f2f}, 43562306a36Sopenharmony_ci {AUD_C1_UP_THR, 0x00007000}, 43662306a36Sopenharmony_ci {AUD_C1_LO_THR, 0x00005400}, 43762306a36Sopenharmony_ci {AUD_C2_UP_THR, 0x00005400}, 43862306a36Sopenharmony_ci {AUD_C2_LO_THR, 0x00003000}, 43962306a36Sopenharmony_ci { /* end of list */ }, 44062306a36Sopenharmony_ci }; 44162306a36Sopenharmony_ci 44262306a36Sopenharmony_ci static const struct rlist a2_dk[] = { 44362306a36Sopenharmony_ci {AUD_DMD_RA_DDS, 0x002a4f2f}, 44462306a36Sopenharmony_ci {AUD_C1_UP_THR, 0x00007000}, 44562306a36Sopenharmony_ci {AUD_C1_LO_THR, 0x00005400}, 44662306a36Sopenharmony_ci {AUD_C2_UP_THR, 0x00005400}, 44762306a36Sopenharmony_ci {AUD_C2_LO_THR, 0x00003000}, 44862306a36Sopenharmony_ci {AUD_DN0_FREQ, 0x00003a1c}, 44962306a36Sopenharmony_ci {AUD_DN2_FREQ, 0x0000d2e0}, 45062306a36Sopenharmony_ci { /* end of list */ }, 45162306a36Sopenharmony_ci }; 45262306a36Sopenharmony_ci 45362306a36Sopenharmony_ci static const struct rlist a1_i[] = { 45462306a36Sopenharmony_ci {AUD_ERRLOGPERIOD_R, 0x00000064}, 45562306a36Sopenharmony_ci {AUD_ERRINTRPTTHSHLD1_R, 0x00000fff}, 45662306a36Sopenharmony_ci {AUD_ERRINTRPTTHSHLD2_R, 0x0000001f}, 45762306a36Sopenharmony_ci {AUD_ERRINTRPTTHSHLD3_R, 0x0000000f}, 45862306a36Sopenharmony_ci {AUD_PDF_DDS_CNST_BYTE2, 0x06}, 45962306a36Sopenharmony_ci {AUD_PDF_DDS_CNST_BYTE1, 0x82}, 46062306a36Sopenharmony_ci {AUD_PDF_DDS_CNST_BYTE0, 0x12}, 46162306a36Sopenharmony_ci {AUD_QAM_MODE, 0x05}, 46262306a36Sopenharmony_ci {AUD_PHACC_FREQ_8MSB, 0x3a}, 46362306a36Sopenharmony_ci {AUD_PHACC_FREQ_8LSB, 0x93}, 46462306a36Sopenharmony_ci {AUD_DMD_RA_DDS, 0x002a4f2f}, 46562306a36Sopenharmony_ci {AUD_PLL_INT, 0x0000001e}, 46662306a36Sopenharmony_ci {AUD_PLL_DDS, 0x00000004}, 46762306a36Sopenharmony_ci {AUD_PLL_FRAC, 0x0000e542}, 46862306a36Sopenharmony_ci {AUD_RATE_ADJ1, 0x00000100}, 46962306a36Sopenharmony_ci {AUD_RATE_ADJ2, 0x00000200}, 47062306a36Sopenharmony_ci {AUD_RATE_ADJ3, 0x00000300}, 47162306a36Sopenharmony_ci {AUD_RATE_ADJ4, 0x00000400}, 47262306a36Sopenharmony_ci {AUD_RATE_ADJ5, 0x00000500}, 47362306a36Sopenharmony_ci {AUD_THR_FR, 0x00000000}, 47462306a36Sopenharmony_ci {AUD_PILOT_BQD_1_K0, 0x0000755b}, 47562306a36Sopenharmony_ci {AUD_PILOT_BQD_1_K1, 0x00551340}, 47662306a36Sopenharmony_ci {AUD_PILOT_BQD_1_K2, 0x006d30be}, 47762306a36Sopenharmony_ci {AUD_PILOT_BQD_1_K3, 0xffd394af}, 47862306a36Sopenharmony_ci {AUD_PILOT_BQD_1_K4, 0x00400000}, 47962306a36Sopenharmony_ci {AUD_PILOT_BQD_2_K0, 0x00040000}, 48062306a36Sopenharmony_ci {AUD_PILOT_BQD_2_K1, 0x002a4841}, 48162306a36Sopenharmony_ci {AUD_PILOT_BQD_2_K2, 0x00400000}, 48262306a36Sopenharmony_ci {AUD_PILOT_BQD_2_K3, 0x00000000}, 48362306a36Sopenharmony_ci {AUD_PILOT_BQD_2_K4, 0x00000000}, 48462306a36Sopenharmony_ci {AUD_MODE_CHG_TIMER, 0x00000060}, 48562306a36Sopenharmony_ci {AUD_AFE_12DB_EN, 0x00000001}, 48662306a36Sopenharmony_ci {AAGC_HYST, 0x0000000a}, 48762306a36Sopenharmony_ci {AUD_CORDIC_SHIFT_0, 0x00000007}, 48862306a36Sopenharmony_ci {AUD_CORDIC_SHIFT_1, 0x00000007}, 48962306a36Sopenharmony_ci {AUD_C1_UP_THR, 0x00007000}, 49062306a36Sopenharmony_ci {AUD_C1_LO_THR, 0x00005400}, 49162306a36Sopenharmony_ci {AUD_C2_UP_THR, 0x00005400}, 49262306a36Sopenharmony_ci {AUD_C2_LO_THR, 0x00003000}, 49362306a36Sopenharmony_ci {AUD_DCOC_0_SRC, 0x0000001a}, 49462306a36Sopenharmony_ci {AUD_DCOC0_SHIFT, 0x00000000}, 49562306a36Sopenharmony_ci {AUD_DCOC_0_SHIFT_IN0, 0x0000000a}, 49662306a36Sopenharmony_ci {AUD_DCOC_0_SHIFT_IN1, 0x00000008}, 49762306a36Sopenharmony_ci {AUD_DCOC_PASS_IN, 0x00000003}, 49862306a36Sopenharmony_ci {AUD_IIR3_0_SEL, 0x00000021}, 49962306a36Sopenharmony_ci {AUD_DN2_AFC, 0x00000002}, 50062306a36Sopenharmony_ci {AUD_DCOC_1_SRC, 0x0000001b}, 50162306a36Sopenharmony_ci {AUD_DCOC1_SHIFT, 0x00000000}, 50262306a36Sopenharmony_ci {AUD_DCOC_1_SHIFT_IN0, 0x0000000a}, 50362306a36Sopenharmony_ci {AUD_DCOC_1_SHIFT_IN1, 0x00000008}, 50462306a36Sopenharmony_ci {AUD_IIR3_1_SEL, 0x00000023}, 50562306a36Sopenharmony_ci {AUD_DN0_FREQ, 0x000035a3}, 50662306a36Sopenharmony_ci {AUD_DN2_FREQ, 0x000029c7}, 50762306a36Sopenharmony_ci {AUD_CRDC0_SRC_SEL, 0x00000511}, 50862306a36Sopenharmony_ci {AUD_IIR1_0_SEL, 0x00000001}, 50962306a36Sopenharmony_ci {AUD_IIR1_1_SEL, 0x00000000}, 51062306a36Sopenharmony_ci {AUD_IIR3_2_SEL, 0x00000003}, 51162306a36Sopenharmony_ci {AUD_IIR3_2_SHIFT, 0x00000000}, 51262306a36Sopenharmony_ci {AUD_IIR3_0_SEL, 0x00000002}, 51362306a36Sopenharmony_ci {AUD_IIR2_0_SEL, 0x00000021}, 51462306a36Sopenharmony_ci {AUD_IIR2_0_SHIFT, 0x00000002}, 51562306a36Sopenharmony_ci {AUD_DEEMPH0_SRC_SEL, 0x0000000b}, 51662306a36Sopenharmony_ci {AUD_DEEMPH1_SRC_SEL, 0x0000000b}, 51762306a36Sopenharmony_ci {AUD_POLYPH80SCALEFAC, 0x00000001}, 51862306a36Sopenharmony_ci {AUD_START_TIMER, 0x00000000}, 51962306a36Sopenharmony_ci { /* end of list */ }, 52062306a36Sopenharmony_ci }; 52162306a36Sopenharmony_ci 52262306a36Sopenharmony_ci static const struct rlist am_l[] = { 52362306a36Sopenharmony_ci {AUD_ERRLOGPERIOD_R, 0x00000064}, 52462306a36Sopenharmony_ci {AUD_ERRINTRPTTHSHLD1_R, 0x00000FFF}, 52562306a36Sopenharmony_ci {AUD_ERRINTRPTTHSHLD2_R, 0x0000001F}, 52662306a36Sopenharmony_ci {AUD_ERRINTRPTTHSHLD3_R, 0x0000000F}, 52762306a36Sopenharmony_ci {AUD_PDF_DDS_CNST_BYTE2, 0x48}, 52862306a36Sopenharmony_ci {AUD_PDF_DDS_CNST_BYTE1, 0x3D}, 52962306a36Sopenharmony_ci {AUD_QAM_MODE, 0x00}, 53062306a36Sopenharmony_ci {AUD_PDF_DDS_CNST_BYTE0, 0xf5}, 53162306a36Sopenharmony_ci {AUD_PHACC_FREQ_8MSB, 0x3a}, 53262306a36Sopenharmony_ci {AUD_PHACC_FREQ_8LSB, 0x4a}, 53362306a36Sopenharmony_ci {AUD_DEEMPHGAIN_R, 0x00006680}, 53462306a36Sopenharmony_ci {AUD_DEEMPHNUMER1_R, 0x000353DE}, 53562306a36Sopenharmony_ci {AUD_DEEMPHNUMER2_R, 0x000001B1}, 53662306a36Sopenharmony_ci {AUD_DEEMPHDENOM1_R, 0x0000F3D0}, 53762306a36Sopenharmony_ci {AUD_DEEMPHDENOM2_R, 0x00000000}, 53862306a36Sopenharmony_ci {AUD_FM_MODE_ENABLE, 0x00000007}, 53962306a36Sopenharmony_ci {AUD_POLYPH80SCALEFAC, 0x00000003}, 54062306a36Sopenharmony_ci {AUD_AFE_12DB_EN, 0x00000001}, 54162306a36Sopenharmony_ci {AAGC_GAIN, 0x00000000}, 54262306a36Sopenharmony_ci {AAGC_HYST, 0x00000018}, 54362306a36Sopenharmony_ci {AAGC_DEF, 0x00000020}, 54462306a36Sopenharmony_ci {AUD_DN0_FREQ, 0x00000000}, 54562306a36Sopenharmony_ci {AUD_POLY0_DDS_CONSTANT, 0x000E4DB2}, 54662306a36Sopenharmony_ci {AUD_DCOC_0_SRC, 0x00000021}, 54762306a36Sopenharmony_ci {AUD_IIR1_0_SEL, 0x00000000}, 54862306a36Sopenharmony_ci {AUD_IIR1_0_SHIFT, 0x00000007}, 54962306a36Sopenharmony_ci {AUD_IIR1_1_SEL, 0x00000002}, 55062306a36Sopenharmony_ci {AUD_IIR1_1_SHIFT, 0x00000000}, 55162306a36Sopenharmony_ci {AUD_DCOC_1_SRC, 0x00000003}, 55262306a36Sopenharmony_ci {AUD_DCOC1_SHIFT, 0x00000000}, 55362306a36Sopenharmony_ci {AUD_DCOC_PASS_IN, 0x00000000}, 55462306a36Sopenharmony_ci {AUD_IIR1_2_SEL, 0x00000023}, 55562306a36Sopenharmony_ci {AUD_IIR1_2_SHIFT, 0x00000000}, 55662306a36Sopenharmony_ci {AUD_IIR1_3_SEL, 0x00000004}, 55762306a36Sopenharmony_ci {AUD_IIR1_3_SHIFT, 0x00000007}, 55862306a36Sopenharmony_ci {AUD_IIR1_4_SEL, 0x00000005}, 55962306a36Sopenharmony_ci {AUD_IIR1_4_SHIFT, 0x00000007}, 56062306a36Sopenharmony_ci {AUD_IIR3_0_SEL, 0x00000007}, 56162306a36Sopenharmony_ci {AUD_IIR3_0_SHIFT, 0x00000000}, 56262306a36Sopenharmony_ci {AUD_DEEMPH0_SRC_SEL, 0x00000011}, 56362306a36Sopenharmony_ci {AUD_DEEMPH0_SHIFT, 0x00000000}, 56462306a36Sopenharmony_ci {AUD_DEEMPH0_G0, 0x00007000}, 56562306a36Sopenharmony_ci {AUD_DEEMPH0_A0, 0x00000000}, 56662306a36Sopenharmony_ci {AUD_DEEMPH0_B0, 0x00000000}, 56762306a36Sopenharmony_ci {AUD_DEEMPH0_A1, 0x00000000}, 56862306a36Sopenharmony_ci {AUD_DEEMPH0_B1, 0x00000000}, 56962306a36Sopenharmony_ci {AUD_DEEMPH1_SRC_SEL, 0x00000011}, 57062306a36Sopenharmony_ci {AUD_DEEMPH1_SHIFT, 0x00000000}, 57162306a36Sopenharmony_ci {AUD_DEEMPH1_G0, 0x00007000}, 57262306a36Sopenharmony_ci {AUD_DEEMPH1_A0, 0x00000000}, 57362306a36Sopenharmony_ci {AUD_DEEMPH1_B0, 0x00000000}, 57462306a36Sopenharmony_ci {AUD_DEEMPH1_A1, 0x00000000}, 57562306a36Sopenharmony_ci {AUD_DEEMPH1_B1, 0x00000000}, 57662306a36Sopenharmony_ci {AUD_OUT0_SEL, 0x0000003F}, 57762306a36Sopenharmony_ci {AUD_OUT1_SEL, 0x0000003F}, 57862306a36Sopenharmony_ci {AUD_DMD_RA_DDS, 0x00F5C285}, 57962306a36Sopenharmony_ci {AUD_PLL_INT, 0x0000001E}, 58062306a36Sopenharmony_ci {AUD_PLL_DDS, 0x00000000}, 58162306a36Sopenharmony_ci {AUD_PLL_FRAC, 0x0000E542}, 58262306a36Sopenharmony_ci {AUD_RATE_ADJ1, 0x00000100}, 58362306a36Sopenharmony_ci {AUD_RATE_ADJ2, 0x00000200}, 58462306a36Sopenharmony_ci {AUD_RATE_ADJ3, 0x00000300}, 58562306a36Sopenharmony_ci {AUD_RATE_ADJ4, 0x00000400}, 58662306a36Sopenharmony_ci {AUD_RATE_ADJ5, 0x00000500}, 58762306a36Sopenharmony_ci {AUD_RATE_THRES_DMD, 0x000000C0}, 58862306a36Sopenharmony_ci { /* end of list */ }, 58962306a36Sopenharmony_ci }; 59062306a36Sopenharmony_ci 59162306a36Sopenharmony_ci static const struct rlist a2_deemph50[] = { 59262306a36Sopenharmony_ci {AUD_DEEMPH0_G0, 0x00000380}, 59362306a36Sopenharmony_ci {AUD_DEEMPH1_G0, 0x00000380}, 59462306a36Sopenharmony_ci {AUD_DEEMPHGAIN_R, 0x000011e1}, 59562306a36Sopenharmony_ci {AUD_DEEMPHNUMER1_R, 0x0002a7bc}, 59662306a36Sopenharmony_ci {AUD_DEEMPHNUMER2_R, 0x0003023c}, 59762306a36Sopenharmony_ci { /* end of list */ }, 59862306a36Sopenharmony_ci }; 59962306a36Sopenharmony_ci 60062306a36Sopenharmony_ci set_audio_start(core, SEL_A2); 60162306a36Sopenharmony_ci switch (core->tvaudio) { 60262306a36Sopenharmony_ci case WW_BG: 60362306a36Sopenharmony_ci dprintk("%s PAL-BG A1/2 (status: known-good)\n", __func__); 60462306a36Sopenharmony_ci set_audio_registers(core, a2_bgdk_common); 60562306a36Sopenharmony_ci set_audio_registers(core, a2_bg); 60662306a36Sopenharmony_ci set_audio_registers(core, a2_deemph50); 60762306a36Sopenharmony_ci break; 60862306a36Sopenharmony_ci case WW_DK: 60962306a36Sopenharmony_ci dprintk("%s PAL-DK A1/2 (status: known-good)\n", __func__); 61062306a36Sopenharmony_ci set_audio_registers(core, a2_bgdk_common); 61162306a36Sopenharmony_ci set_audio_registers(core, a2_dk); 61262306a36Sopenharmony_ci set_audio_registers(core, a2_deemph50); 61362306a36Sopenharmony_ci break; 61462306a36Sopenharmony_ci case WW_I: 61562306a36Sopenharmony_ci dprintk("%s PAL-I A1 (status: known-good)\n", __func__); 61662306a36Sopenharmony_ci set_audio_registers(core, a1_i); 61762306a36Sopenharmony_ci set_audio_registers(core, a2_deemph50); 61862306a36Sopenharmony_ci break; 61962306a36Sopenharmony_ci case WW_L: 62062306a36Sopenharmony_ci dprintk("%s AM-L (status: devel)\n", __func__); 62162306a36Sopenharmony_ci set_audio_registers(core, am_l); 62262306a36Sopenharmony_ci break; 62362306a36Sopenharmony_ci case WW_NONE: 62462306a36Sopenharmony_ci case WW_BTSC: 62562306a36Sopenharmony_ci case WW_EIAJ: 62662306a36Sopenharmony_ci case WW_I2SPT: 62762306a36Sopenharmony_ci case WW_FM: 62862306a36Sopenharmony_ci case WW_I2SADC: 62962306a36Sopenharmony_ci case WW_M: 63062306a36Sopenharmony_ci dprintk("%s Warning: wrong value\n", __func__); 63162306a36Sopenharmony_ci return; 63262306a36Sopenharmony_ci } 63362306a36Sopenharmony_ci 63462306a36Sopenharmony_ci mode |= EN_FMRADIO_EN_RDS | EN_DMTRX_SUMDIFF; 63562306a36Sopenharmony_ci set_audio_finish(core, mode); 63662306a36Sopenharmony_ci} 63762306a36Sopenharmony_ci 63862306a36Sopenharmony_cistatic void set_audio_standard_EIAJ(struct cx88_core *core) 63962306a36Sopenharmony_ci{ 64062306a36Sopenharmony_ci static const struct rlist eiaj[] = { 64162306a36Sopenharmony_ci /* TODO: eiaj register settings are not there yet ... */ 64262306a36Sopenharmony_ci 64362306a36Sopenharmony_ci { /* end of list */ }, 64462306a36Sopenharmony_ci }; 64562306a36Sopenharmony_ci dprintk("%s (status: unknown)\n", __func__); 64662306a36Sopenharmony_ci 64762306a36Sopenharmony_ci set_audio_start(core, SEL_EIAJ); 64862306a36Sopenharmony_ci set_audio_registers(core, eiaj); 64962306a36Sopenharmony_ci set_audio_finish(core, EN_EIAJ_AUTO_STEREO); 65062306a36Sopenharmony_ci} 65162306a36Sopenharmony_ci 65262306a36Sopenharmony_cistatic void set_audio_standard_FM(struct cx88_core *core, 65362306a36Sopenharmony_ci enum cx88_deemph_type deemph) 65462306a36Sopenharmony_ci{ 65562306a36Sopenharmony_ci static const struct rlist fm_deemph_50[] = { 65662306a36Sopenharmony_ci {AUD_DEEMPH0_G0, 0x0C45}, 65762306a36Sopenharmony_ci {AUD_DEEMPH0_A0, 0x6262}, 65862306a36Sopenharmony_ci {AUD_DEEMPH0_B0, 0x1C29}, 65962306a36Sopenharmony_ci {AUD_DEEMPH0_A1, 0x3FC66}, 66062306a36Sopenharmony_ci {AUD_DEEMPH0_B1, 0x399A}, 66162306a36Sopenharmony_ci 66262306a36Sopenharmony_ci {AUD_DEEMPH1_G0, 0x0D80}, 66362306a36Sopenharmony_ci {AUD_DEEMPH1_A0, 0x6262}, 66462306a36Sopenharmony_ci {AUD_DEEMPH1_B0, 0x1C29}, 66562306a36Sopenharmony_ci {AUD_DEEMPH1_A1, 0x3FC66}, 66662306a36Sopenharmony_ci {AUD_DEEMPH1_B1, 0x399A}, 66762306a36Sopenharmony_ci 66862306a36Sopenharmony_ci {AUD_POLYPH80SCALEFAC, 0x0003}, 66962306a36Sopenharmony_ci { /* end of list */ }, 67062306a36Sopenharmony_ci }; 67162306a36Sopenharmony_ci static const struct rlist fm_deemph_75[] = { 67262306a36Sopenharmony_ci {AUD_DEEMPH0_G0, 0x091B}, 67362306a36Sopenharmony_ci {AUD_DEEMPH0_A0, 0x6B68}, 67462306a36Sopenharmony_ci {AUD_DEEMPH0_B0, 0x11EC}, 67562306a36Sopenharmony_ci {AUD_DEEMPH0_A1, 0x3FC66}, 67662306a36Sopenharmony_ci {AUD_DEEMPH0_B1, 0x399A}, 67762306a36Sopenharmony_ci 67862306a36Sopenharmony_ci {AUD_DEEMPH1_G0, 0x0AA0}, 67962306a36Sopenharmony_ci {AUD_DEEMPH1_A0, 0x6B68}, 68062306a36Sopenharmony_ci {AUD_DEEMPH1_B0, 0x11EC}, 68162306a36Sopenharmony_ci {AUD_DEEMPH1_A1, 0x3FC66}, 68262306a36Sopenharmony_ci {AUD_DEEMPH1_B1, 0x399A}, 68362306a36Sopenharmony_ci 68462306a36Sopenharmony_ci {AUD_POLYPH80SCALEFAC, 0x0003}, 68562306a36Sopenharmony_ci { /* end of list */ }, 68662306a36Sopenharmony_ci }; 68762306a36Sopenharmony_ci 68862306a36Sopenharmony_ci /* 68962306a36Sopenharmony_ci * It is enough to leave default values? 69062306a36Sopenharmony_ci * 69162306a36Sopenharmony_ci * No, it's not! The deemphasis registers are reset to the 75us 69262306a36Sopenharmony_ci * values by default. Analyzing the spectrum of the decoded audio 69362306a36Sopenharmony_ci * reveals that "no deemphasis" is the same as 75 us, while the 50 us 69462306a36Sopenharmony_ci * setting results in less deemphasis. 69562306a36Sopenharmony_ci */ 69662306a36Sopenharmony_ci static const struct rlist fm_no_deemph[] = { 69762306a36Sopenharmony_ci {AUD_POLYPH80SCALEFAC, 0x0003}, 69862306a36Sopenharmony_ci { /* end of list */ }, 69962306a36Sopenharmony_ci }; 70062306a36Sopenharmony_ci 70162306a36Sopenharmony_ci dprintk("%s (status: unknown)\n", __func__); 70262306a36Sopenharmony_ci set_audio_start(core, SEL_FMRADIO); 70362306a36Sopenharmony_ci 70462306a36Sopenharmony_ci switch (deemph) { 70562306a36Sopenharmony_ci default: 70662306a36Sopenharmony_ci case FM_NO_DEEMPH: 70762306a36Sopenharmony_ci set_audio_registers(core, fm_no_deemph); 70862306a36Sopenharmony_ci break; 70962306a36Sopenharmony_ci 71062306a36Sopenharmony_ci case FM_DEEMPH_50: 71162306a36Sopenharmony_ci set_audio_registers(core, fm_deemph_50); 71262306a36Sopenharmony_ci break; 71362306a36Sopenharmony_ci 71462306a36Sopenharmony_ci case FM_DEEMPH_75: 71562306a36Sopenharmony_ci set_audio_registers(core, fm_deemph_75); 71662306a36Sopenharmony_ci break; 71762306a36Sopenharmony_ci } 71862306a36Sopenharmony_ci 71962306a36Sopenharmony_ci set_audio_finish(core, EN_FMRADIO_AUTO_STEREO); 72062306a36Sopenharmony_ci} 72162306a36Sopenharmony_ci 72262306a36Sopenharmony_ci/* ----------------------------------------------------------- */ 72362306a36Sopenharmony_ci 72462306a36Sopenharmony_cistatic int cx88_detect_nicam(struct cx88_core *core) 72562306a36Sopenharmony_ci{ 72662306a36Sopenharmony_ci int i, j = 0; 72762306a36Sopenharmony_ci 72862306a36Sopenharmony_ci dprintk("start nicam autodetect.\n"); 72962306a36Sopenharmony_ci 73062306a36Sopenharmony_ci for (i = 0; i < 6; i++) { 73162306a36Sopenharmony_ci /* if bit1=1 then nicam is detected */ 73262306a36Sopenharmony_ci j += ((cx_read(AUD_NICAM_STATUS2) & 0x02) >> 1); 73362306a36Sopenharmony_ci 73462306a36Sopenharmony_ci if (j == 1) { 73562306a36Sopenharmony_ci dprintk("nicam is detected.\n"); 73662306a36Sopenharmony_ci return 1; 73762306a36Sopenharmony_ci } 73862306a36Sopenharmony_ci 73962306a36Sopenharmony_ci /* wait a little bit for next reading status */ 74062306a36Sopenharmony_ci usleep_range(10000, 20000); 74162306a36Sopenharmony_ci } 74262306a36Sopenharmony_ci 74362306a36Sopenharmony_ci dprintk("nicam is not detected.\n"); 74462306a36Sopenharmony_ci return 0; 74562306a36Sopenharmony_ci} 74662306a36Sopenharmony_ci 74762306a36Sopenharmony_civoid cx88_set_tvaudio(struct cx88_core *core) 74862306a36Sopenharmony_ci{ 74962306a36Sopenharmony_ci switch (core->tvaudio) { 75062306a36Sopenharmony_ci case WW_BTSC: 75162306a36Sopenharmony_ci set_audio_standard_BTSC(core, 0, EN_BTSC_AUTO_STEREO); 75262306a36Sopenharmony_ci break; 75362306a36Sopenharmony_ci case WW_BG: 75462306a36Sopenharmony_ci case WW_DK: 75562306a36Sopenharmony_ci case WW_M: 75662306a36Sopenharmony_ci case WW_I: 75762306a36Sopenharmony_ci case WW_L: 75862306a36Sopenharmony_ci /* prepare all dsp registers */ 75962306a36Sopenharmony_ci set_audio_standard_A2(core, EN_A2_FORCE_MONO1); 76062306a36Sopenharmony_ci 76162306a36Sopenharmony_ci /* 76262306a36Sopenharmony_ci * set nicam mode - otherwise 76362306a36Sopenharmony_ci * AUD_NICAM_STATUS2 contains wrong values 76462306a36Sopenharmony_ci */ 76562306a36Sopenharmony_ci set_audio_standard_NICAM(core, EN_NICAM_AUTO_STEREO); 76662306a36Sopenharmony_ci if (cx88_detect_nicam(core) == 0) { 76762306a36Sopenharmony_ci /* fall back to fm / am mono */ 76862306a36Sopenharmony_ci set_audio_standard_A2(core, EN_A2_FORCE_MONO1); 76962306a36Sopenharmony_ci core->audiomode_current = V4L2_TUNER_MODE_MONO; 77062306a36Sopenharmony_ci core->use_nicam = 0; 77162306a36Sopenharmony_ci } else { 77262306a36Sopenharmony_ci core->use_nicam = 1; 77362306a36Sopenharmony_ci } 77462306a36Sopenharmony_ci break; 77562306a36Sopenharmony_ci case WW_EIAJ: 77662306a36Sopenharmony_ci set_audio_standard_EIAJ(core); 77762306a36Sopenharmony_ci break; 77862306a36Sopenharmony_ci case WW_FM: 77962306a36Sopenharmony_ci set_audio_standard_FM(core, radio_deemphasis); 78062306a36Sopenharmony_ci break; 78162306a36Sopenharmony_ci case WW_I2SADC: 78262306a36Sopenharmony_ci set_audio_start(core, 0x01); 78362306a36Sopenharmony_ci /* 78462306a36Sopenharmony_ci * Slave/Philips/Autobaud 78562306a36Sopenharmony_ci * NB on Nova-S bit1 NPhilipsSony appears to be inverted: 78662306a36Sopenharmony_ci * 0= Sony, 1=Philips 78762306a36Sopenharmony_ci */ 78862306a36Sopenharmony_ci cx_write(AUD_I2SINPUTCNTL, core->board.i2sinputcntl); 78962306a36Sopenharmony_ci /* Switch to "I2S ADC mode" */ 79062306a36Sopenharmony_ci cx_write(AUD_I2SCNTL, 0x1); 79162306a36Sopenharmony_ci set_audio_finish(core, EN_I2SIN_ENABLE); 79262306a36Sopenharmony_ci break; 79362306a36Sopenharmony_ci case WW_NONE: 79462306a36Sopenharmony_ci case WW_I2SPT: 79562306a36Sopenharmony_ci pr_info("unknown tv audio mode [%d]\n", core->tvaudio); 79662306a36Sopenharmony_ci break; 79762306a36Sopenharmony_ci } 79862306a36Sopenharmony_ci} 79962306a36Sopenharmony_ciEXPORT_SYMBOL(cx88_set_tvaudio); 80062306a36Sopenharmony_ci 80162306a36Sopenharmony_civoid cx88_newstation(struct cx88_core *core) 80262306a36Sopenharmony_ci{ 80362306a36Sopenharmony_ci core->audiomode_manual = UNSET; 80462306a36Sopenharmony_ci core->last_change = jiffies; 80562306a36Sopenharmony_ci} 80662306a36Sopenharmony_ciEXPORT_SYMBOL(cx88_newstation); 80762306a36Sopenharmony_ci 80862306a36Sopenharmony_civoid cx88_get_stereo(struct cx88_core *core, struct v4l2_tuner *t) 80962306a36Sopenharmony_ci{ 81062306a36Sopenharmony_ci static const char * const m[] = { "stereo", "dual mono", 81162306a36Sopenharmony_ci "mono", "sap" }; 81262306a36Sopenharmony_ci static const char * const p[] = { "no pilot", "pilot c1", 81362306a36Sopenharmony_ci "pilot c2", "?" }; 81462306a36Sopenharmony_ci u32 reg, mode, pilot; 81562306a36Sopenharmony_ci 81662306a36Sopenharmony_ci reg = cx_read(AUD_STATUS); 81762306a36Sopenharmony_ci mode = reg & 0x03; 81862306a36Sopenharmony_ci pilot = (reg >> 2) & 0x03; 81962306a36Sopenharmony_ci 82062306a36Sopenharmony_ci if (core->astat != reg) 82162306a36Sopenharmony_ci dprintk("AUD_STATUS: 0x%x [%s/%s] ctl=%s\n", 82262306a36Sopenharmony_ci reg, m[mode], p[pilot], 82362306a36Sopenharmony_ci aud_ctl_names[cx_read(AUD_CTL) & 63]); 82462306a36Sopenharmony_ci core->astat = reg; 82562306a36Sopenharmony_ci 82662306a36Sopenharmony_ci t->capability = V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_SAP | 82762306a36Sopenharmony_ci V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2; 82862306a36Sopenharmony_ci t->rxsubchans = UNSET; 82962306a36Sopenharmony_ci t->audmode = V4L2_TUNER_MODE_MONO; 83062306a36Sopenharmony_ci 83162306a36Sopenharmony_ci switch (mode) { 83262306a36Sopenharmony_ci case 0: 83362306a36Sopenharmony_ci t->audmode = V4L2_TUNER_MODE_STEREO; 83462306a36Sopenharmony_ci break; 83562306a36Sopenharmony_ci case 1: 83662306a36Sopenharmony_ci t->audmode = V4L2_TUNER_MODE_LANG2; 83762306a36Sopenharmony_ci break; 83862306a36Sopenharmony_ci case 2: 83962306a36Sopenharmony_ci t->audmode = V4L2_TUNER_MODE_MONO; 84062306a36Sopenharmony_ci break; 84162306a36Sopenharmony_ci case 3: 84262306a36Sopenharmony_ci t->audmode = V4L2_TUNER_MODE_SAP; 84362306a36Sopenharmony_ci break; 84462306a36Sopenharmony_ci } 84562306a36Sopenharmony_ci 84662306a36Sopenharmony_ci switch (core->tvaudio) { 84762306a36Sopenharmony_ci case WW_BTSC: 84862306a36Sopenharmony_ci case WW_BG: 84962306a36Sopenharmony_ci case WW_DK: 85062306a36Sopenharmony_ci case WW_M: 85162306a36Sopenharmony_ci case WW_EIAJ: 85262306a36Sopenharmony_ci if (!core->use_nicam) { 85362306a36Sopenharmony_ci t->rxsubchans = cx88_dsp_detect_stereo_sap(core); 85462306a36Sopenharmony_ci break; 85562306a36Sopenharmony_ci } 85662306a36Sopenharmony_ci break; 85762306a36Sopenharmony_ci case WW_NONE: 85862306a36Sopenharmony_ci case WW_I: 85962306a36Sopenharmony_ci case WW_L: 86062306a36Sopenharmony_ci case WW_I2SPT: 86162306a36Sopenharmony_ci case WW_FM: 86262306a36Sopenharmony_ci case WW_I2SADC: 86362306a36Sopenharmony_ci /* nothing */ 86462306a36Sopenharmony_ci break; 86562306a36Sopenharmony_ci } 86662306a36Sopenharmony_ci 86762306a36Sopenharmony_ci /* If software stereo detection is not supported... */ 86862306a36Sopenharmony_ci if (t->rxsubchans == UNSET) { 86962306a36Sopenharmony_ci t->rxsubchans = V4L2_TUNER_SUB_MONO; 87062306a36Sopenharmony_ci /* 87162306a36Sopenharmony_ci * If the hardware itself detected stereo, also return 87262306a36Sopenharmony_ci * stereo as an available subchannel 87362306a36Sopenharmony_ci */ 87462306a36Sopenharmony_ci if (t->audmode == V4L2_TUNER_MODE_STEREO) 87562306a36Sopenharmony_ci t->rxsubchans |= V4L2_TUNER_SUB_STEREO; 87662306a36Sopenharmony_ci } 87762306a36Sopenharmony_ci} 87862306a36Sopenharmony_ciEXPORT_SYMBOL(cx88_get_stereo); 87962306a36Sopenharmony_ci 88062306a36Sopenharmony_ci 88162306a36Sopenharmony_civoid cx88_set_stereo(struct cx88_core *core, u32 mode, int manual) 88262306a36Sopenharmony_ci{ 88362306a36Sopenharmony_ci u32 ctl = UNSET; 88462306a36Sopenharmony_ci u32 mask = UNSET; 88562306a36Sopenharmony_ci 88662306a36Sopenharmony_ci if (manual) { 88762306a36Sopenharmony_ci core->audiomode_manual = mode; 88862306a36Sopenharmony_ci } else { 88962306a36Sopenharmony_ci if (core->audiomode_manual != UNSET) 89062306a36Sopenharmony_ci return; 89162306a36Sopenharmony_ci } 89262306a36Sopenharmony_ci core->audiomode_current = mode; 89362306a36Sopenharmony_ci 89462306a36Sopenharmony_ci switch (core->tvaudio) { 89562306a36Sopenharmony_ci case WW_BTSC: 89662306a36Sopenharmony_ci switch (mode) { 89762306a36Sopenharmony_ci case V4L2_TUNER_MODE_MONO: 89862306a36Sopenharmony_ci set_audio_standard_BTSC(core, 0, EN_BTSC_FORCE_MONO); 89962306a36Sopenharmony_ci break; 90062306a36Sopenharmony_ci case V4L2_TUNER_MODE_LANG1: 90162306a36Sopenharmony_ci set_audio_standard_BTSC(core, 0, EN_BTSC_AUTO_STEREO); 90262306a36Sopenharmony_ci break; 90362306a36Sopenharmony_ci case V4L2_TUNER_MODE_LANG2: 90462306a36Sopenharmony_ci set_audio_standard_BTSC(core, 1, EN_BTSC_FORCE_SAP); 90562306a36Sopenharmony_ci break; 90662306a36Sopenharmony_ci case V4L2_TUNER_MODE_STEREO: 90762306a36Sopenharmony_ci case V4L2_TUNER_MODE_LANG1_LANG2: 90862306a36Sopenharmony_ci set_audio_standard_BTSC(core, 0, EN_BTSC_FORCE_STEREO); 90962306a36Sopenharmony_ci break; 91062306a36Sopenharmony_ci } 91162306a36Sopenharmony_ci break; 91262306a36Sopenharmony_ci case WW_BG: 91362306a36Sopenharmony_ci case WW_DK: 91462306a36Sopenharmony_ci case WW_M: 91562306a36Sopenharmony_ci case WW_I: 91662306a36Sopenharmony_ci case WW_L: 91762306a36Sopenharmony_ci if (core->use_nicam == 1) { 91862306a36Sopenharmony_ci switch (mode) { 91962306a36Sopenharmony_ci case V4L2_TUNER_MODE_MONO: 92062306a36Sopenharmony_ci case V4L2_TUNER_MODE_LANG1: 92162306a36Sopenharmony_ci set_audio_standard_NICAM(core, 92262306a36Sopenharmony_ci EN_NICAM_FORCE_MONO1); 92362306a36Sopenharmony_ci break; 92462306a36Sopenharmony_ci case V4L2_TUNER_MODE_LANG2: 92562306a36Sopenharmony_ci set_audio_standard_NICAM(core, 92662306a36Sopenharmony_ci EN_NICAM_FORCE_MONO2); 92762306a36Sopenharmony_ci break; 92862306a36Sopenharmony_ci case V4L2_TUNER_MODE_STEREO: 92962306a36Sopenharmony_ci case V4L2_TUNER_MODE_LANG1_LANG2: 93062306a36Sopenharmony_ci set_audio_standard_NICAM(core, 93162306a36Sopenharmony_ci EN_NICAM_FORCE_STEREO); 93262306a36Sopenharmony_ci break; 93362306a36Sopenharmony_ci } 93462306a36Sopenharmony_ci } else { 93562306a36Sopenharmony_ci if ((core->tvaudio == WW_I) || 93662306a36Sopenharmony_ci (core->tvaudio == WW_L)) { 93762306a36Sopenharmony_ci /* fall back to fm / am mono */ 93862306a36Sopenharmony_ci set_audio_standard_A2(core, EN_A2_FORCE_MONO1); 93962306a36Sopenharmony_ci } else { 94062306a36Sopenharmony_ci /* TODO: Add A2 autodection */ 94162306a36Sopenharmony_ci mask = 0x3f; 94262306a36Sopenharmony_ci switch (mode) { 94362306a36Sopenharmony_ci case V4L2_TUNER_MODE_MONO: 94462306a36Sopenharmony_ci case V4L2_TUNER_MODE_LANG1: 94562306a36Sopenharmony_ci ctl = EN_A2_FORCE_MONO1; 94662306a36Sopenharmony_ci break; 94762306a36Sopenharmony_ci case V4L2_TUNER_MODE_LANG2: 94862306a36Sopenharmony_ci ctl = EN_A2_FORCE_MONO2; 94962306a36Sopenharmony_ci break; 95062306a36Sopenharmony_ci case V4L2_TUNER_MODE_STEREO: 95162306a36Sopenharmony_ci case V4L2_TUNER_MODE_LANG1_LANG2: 95262306a36Sopenharmony_ci ctl = EN_A2_FORCE_STEREO; 95362306a36Sopenharmony_ci break; 95462306a36Sopenharmony_ci } 95562306a36Sopenharmony_ci } 95662306a36Sopenharmony_ci } 95762306a36Sopenharmony_ci break; 95862306a36Sopenharmony_ci case WW_FM: 95962306a36Sopenharmony_ci switch (mode) { 96062306a36Sopenharmony_ci case V4L2_TUNER_MODE_MONO: 96162306a36Sopenharmony_ci ctl = EN_FMRADIO_FORCE_MONO; 96262306a36Sopenharmony_ci mask = 0x3f; 96362306a36Sopenharmony_ci break; 96462306a36Sopenharmony_ci case V4L2_TUNER_MODE_STEREO: 96562306a36Sopenharmony_ci ctl = EN_FMRADIO_AUTO_STEREO; 96662306a36Sopenharmony_ci mask = 0x3f; 96762306a36Sopenharmony_ci break; 96862306a36Sopenharmony_ci } 96962306a36Sopenharmony_ci break; 97062306a36Sopenharmony_ci case WW_I2SADC: 97162306a36Sopenharmony_ci case WW_NONE: 97262306a36Sopenharmony_ci case WW_EIAJ: 97362306a36Sopenharmony_ci case WW_I2SPT: 97462306a36Sopenharmony_ci /* DO NOTHING */ 97562306a36Sopenharmony_ci break; 97662306a36Sopenharmony_ci } 97762306a36Sopenharmony_ci 97862306a36Sopenharmony_ci if (ctl != UNSET) { 97962306a36Sopenharmony_ci dprintk("cx88_set_stereo: mask 0x%x, ctl 0x%x [status=0x%x,ctl=0x%x,vol=0x%x]\n", 98062306a36Sopenharmony_ci mask, ctl, cx_read(AUD_STATUS), 98162306a36Sopenharmony_ci cx_read(AUD_CTL), cx_sread(SHADOW_AUD_VOL_CTL)); 98262306a36Sopenharmony_ci cx_andor(AUD_CTL, mask, ctl); 98362306a36Sopenharmony_ci } 98462306a36Sopenharmony_ci} 98562306a36Sopenharmony_ciEXPORT_SYMBOL(cx88_set_stereo); 98662306a36Sopenharmony_ci 98762306a36Sopenharmony_ciint cx88_audio_thread(void *data) 98862306a36Sopenharmony_ci{ 98962306a36Sopenharmony_ci struct cx88_core *core = data; 99062306a36Sopenharmony_ci struct v4l2_tuner t; 99162306a36Sopenharmony_ci u32 mode = 0; 99262306a36Sopenharmony_ci 99362306a36Sopenharmony_ci dprintk("cx88: tvaudio thread started\n"); 99462306a36Sopenharmony_ci set_freezable(); 99562306a36Sopenharmony_ci for (;;) { 99662306a36Sopenharmony_ci msleep_interruptible(1000); 99762306a36Sopenharmony_ci if (kthread_should_stop()) 99862306a36Sopenharmony_ci break; 99962306a36Sopenharmony_ci try_to_freeze(); 100062306a36Sopenharmony_ci 100162306a36Sopenharmony_ci switch (core->tvaudio) { 100262306a36Sopenharmony_ci case WW_BG: 100362306a36Sopenharmony_ci case WW_DK: 100462306a36Sopenharmony_ci case WW_M: 100562306a36Sopenharmony_ci case WW_I: 100662306a36Sopenharmony_ci case WW_L: 100762306a36Sopenharmony_ci if (core->use_nicam) 100862306a36Sopenharmony_ci goto hw_autodetect; 100962306a36Sopenharmony_ci 101062306a36Sopenharmony_ci /* just monitor the audio status for now ... */ 101162306a36Sopenharmony_ci memset(&t, 0, sizeof(t)); 101262306a36Sopenharmony_ci cx88_get_stereo(core, &t); 101362306a36Sopenharmony_ci 101462306a36Sopenharmony_ci if (core->audiomode_manual != UNSET) 101562306a36Sopenharmony_ci /* manually set, don't do anything. */ 101662306a36Sopenharmony_ci continue; 101762306a36Sopenharmony_ci 101862306a36Sopenharmony_ci /* monitor signal and set stereo if available */ 101962306a36Sopenharmony_ci if (t.rxsubchans & V4L2_TUNER_SUB_STEREO) 102062306a36Sopenharmony_ci mode = V4L2_TUNER_MODE_STEREO; 102162306a36Sopenharmony_ci else 102262306a36Sopenharmony_ci mode = V4L2_TUNER_MODE_MONO; 102362306a36Sopenharmony_ci if (mode == core->audiomode_current) 102462306a36Sopenharmony_ci continue; 102562306a36Sopenharmony_ci /* automatically switch to best available mode */ 102662306a36Sopenharmony_ci cx88_set_stereo(core, mode, 0); 102762306a36Sopenharmony_ci break; 102862306a36Sopenharmony_ci case WW_NONE: 102962306a36Sopenharmony_ci case WW_BTSC: 103062306a36Sopenharmony_ci case WW_EIAJ: 103162306a36Sopenharmony_ci case WW_I2SPT: 103262306a36Sopenharmony_ci case WW_FM: 103362306a36Sopenharmony_ci case WW_I2SADC: 103462306a36Sopenharmony_cihw_autodetect: 103562306a36Sopenharmony_ci /* 103662306a36Sopenharmony_ci * stereo autodetection is supported by hardware so 103762306a36Sopenharmony_ci * we don't need to do it manually. Do nothing. 103862306a36Sopenharmony_ci */ 103962306a36Sopenharmony_ci break; 104062306a36Sopenharmony_ci } 104162306a36Sopenharmony_ci } 104262306a36Sopenharmony_ci 104362306a36Sopenharmony_ci dprintk("cx88: tvaudio thread exiting\n"); 104462306a36Sopenharmony_ci return 0; 104562306a36Sopenharmony_ci} 104662306a36Sopenharmony_ciEXPORT_SYMBOL(cx88_audio_thread); 1047