root/drivers/media/pci/cx88/cx88-tvaudio.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. set_audio_registers
  2. set_audio_start
  3. set_audio_finish
  4. set_audio_standard_BTSC
  5. set_audio_standard_NICAM
  6. set_audio_standard_A2
  7. set_audio_standard_EIAJ
  8. set_audio_standard_FM
  9. cx88_detect_nicam
  10. cx88_set_tvaudio
  11. cx88_newstation
  12. cx88_get_stereo
  13. cx88_set_stereo
  14. cx88_audio_thread

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  * cx88x-audio.c - Conexant CX23880/23881 audio downstream driver driver
   4  *
   5  *  (c) 2001 Michael Eskin, Tom Zakrajsek [Windows version]
   6  *  (c) 2002 Yurij Sysoev <yurij@naturesoft.net>
   7  *  (c) 2003 Gerd Knorr <kraxel@bytesex.org>
   8  *
   9  * -----------------------------------------------------------------------
  10  *
  11  * Lot of voodoo here.  Even the data sheet doesn't help to
  12  * understand what is going on here, the documentation for the audio
  13  * part of the cx2388x chip is *very* bad.
  14  *
  15  * Some of this comes from party done linux driver sources I got from
  16  * [undocumented].
  17  *
  18  * Some comes from the dscaler sources, one of the dscaler driver guy works
  19  * for Conexant ...
  20  *
  21  * -----------------------------------------------------------------------
  22  */
  23 
  24 #include "cx88.h"
  25 
  26 #include <linux/module.h>
  27 #include <linux/errno.h>
  28 #include <linux/freezer.h>
  29 #include <linux/kernel.h>
  30 #include <linux/mm.h>
  31 #include <linux/poll.h>
  32 #include <linux/signal.h>
  33 #include <linux/ioport.h>
  34 #include <linux/types.h>
  35 #include <linux/interrupt.h>
  36 #include <linux/vmalloc.h>
  37 #include <linux/init.h>
  38 #include <linux/delay.h>
  39 #include <linux/kthread.h>
  40 
  41 static unsigned int audio_debug;
  42 module_param(audio_debug, int, 0644);
  43 MODULE_PARM_DESC(audio_debug, "enable debug messages [audio]");
  44 
  45 static unsigned int always_analog;
  46 module_param(always_analog, int, 0644);
  47 MODULE_PARM_DESC(always_analog, "force analog audio out");
  48 
  49 static unsigned int radio_deemphasis;
  50 module_param(radio_deemphasis, int, 0644);
  51 MODULE_PARM_DESC(radio_deemphasis,
  52                  "Radio deemphasis time constant, 0=None, 1=50us (elsewhere), 2=75us (USA)");
  53 
  54 #define dprintk(fmt, arg...) do {                               \
  55         if (audio_debug)                                                \
  56                 printk(KERN_DEBUG pr_fmt("%s: tvaudio:" fmt),           \
  57                         __func__, ##arg);                               \
  58 } while (0)
  59 /* ----------------------------------------------------------- */
  60 
  61 static const char * const aud_ctl_names[64] = {
  62         [EN_BTSC_FORCE_MONO] = "BTSC_FORCE_MONO",
  63         [EN_BTSC_FORCE_STEREO] = "BTSC_FORCE_STEREO",
  64         [EN_BTSC_FORCE_SAP] = "BTSC_FORCE_SAP",
  65         [EN_BTSC_AUTO_STEREO] = "BTSC_AUTO_STEREO",
  66         [EN_BTSC_AUTO_SAP] = "BTSC_AUTO_SAP",
  67         [EN_A2_FORCE_MONO1] = "A2_FORCE_MONO1",
  68         [EN_A2_FORCE_MONO2] = "A2_FORCE_MONO2",
  69         [EN_A2_FORCE_STEREO] = "A2_FORCE_STEREO",
  70         [EN_A2_AUTO_MONO2] = "A2_AUTO_MONO2",
  71         [EN_A2_AUTO_STEREO] = "A2_AUTO_STEREO",
  72         [EN_EIAJ_FORCE_MONO1] = "EIAJ_FORCE_MONO1",
  73         [EN_EIAJ_FORCE_MONO2] = "EIAJ_FORCE_MONO2",
  74         [EN_EIAJ_FORCE_STEREO] = "EIAJ_FORCE_STEREO",
  75         [EN_EIAJ_AUTO_MONO2] = "EIAJ_AUTO_MONO2",
  76         [EN_EIAJ_AUTO_STEREO] = "EIAJ_AUTO_STEREO",
  77         [EN_NICAM_FORCE_MONO1] = "NICAM_FORCE_MONO1",
  78         [EN_NICAM_FORCE_MONO2] = "NICAM_FORCE_MONO2",
  79         [EN_NICAM_FORCE_STEREO] = "NICAM_FORCE_STEREO",
  80         [EN_NICAM_AUTO_MONO2] = "NICAM_AUTO_MONO2",
  81         [EN_NICAM_AUTO_STEREO] = "NICAM_AUTO_STEREO",
  82         [EN_FMRADIO_FORCE_MONO] = "FMRADIO_FORCE_MONO",
  83         [EN_FMRADIO_FORCE_STEREO] = "FMRADIO_FORCE_STEREO",
  84         [EN_FMRADIO_AUTO_STEREO] = "FMRADIO_AUTO_STEREO",
  85 };
  86 
  87 struct rlist {
  88         u32 reg;
  89         u32 val;
  90 };
  91 
  92 static void set_audio_registers(struct cx88_core *core, const struct rlist *l)
  93 {
  94         int i;
  95 
  96         for (i = 0; l[i].reg; i++) {
  97                 switch (l[i].reg) {
  98                 case AUD_PDF_DDS_CNST_BYTE2:
  99                 case AUD_PDF_DDS_CNST_BYTE1:
 100                 case AUD_PDF_DDS_CNST_BYTE0:
 101                 case AUD_QAM_MODE:
 102                 case AUD_PHACC_FREQ_8MSB:
 103                 case AUD_PHACC_FREQ_8LSB:
 104                         cx_writeb(l[i].reg, l[i].val);
 105                         break;
 106                 default:
 107                         cx_write(l[i].reg, l[i].val);
 108                         break;
 109                 }
 110         }
 111 }
 112 
 113 static void set_audio_start(struct cx88_core *core, u32 mode)
 114 {
 115         /* mute */
 116         cx_write(AUD_VOL_CTL, (1 << 6));
 117 
 118         /* start programming */
 119         cx_write(AUD_INIT, mode);
 120         cx_write(AUD_INIT_LD, 0x0001);
 121         cx_write(AUD_SOFT_RESET, 0x0001);
 122 }
 123 
 124 static void set_audio_finish(struct cx88_core *core, u32 ctl)
 125 {
 126         u32 volume;
 127 
 128         /* restart dma; This avoids buzz in NICAM and is good in others  */
 129         cx88_stop_audio_dma(core);
 130         cx_write(AUD_RATE_THRES_DMD, 0x000000C0);
 131         cx88_start_audio_dma(core);
 132 
 133         if (core->board.mpeg & CX88_MPEG_BLACKBIRD) {
 134                 cx_write(AUD_I2SINPUTCNTL, 4);
 135                 cx_write(AUD_BAUDRATE, 1);
 136                 /*
 137                  * 'pass-thru mode': this enables the i2s
 138                  * output to the mpeg encoder
 139                  */
 140                 cx_set(AUD_CTL, EN_I2SOUT_ENABLE);
 141                 cx_write(AUD_I2SOUTPUTCNTL, 1);
 142                 cx_write(AUD_I2SCNTL, 0);
 143                 /* cx_write(AUD_APB_IN_RATE_ADJ, 0); */
 144         }
 145         if ((always_analog) || (!(core->board.mpeg & CX88_MPEG_BLACKBIRD))) {
 146                 ctl |= EN_DAC_ENABLE;
 147                 cx_write(AUD_CTL, ctl);
 148         }
 149 
 150         /* finish programming */
 151         cx_write(AUD_SOFT_RESET, 0x0000);
 152 
 153         /* unmute */
 154         volume = cx_sread(SHADOW_AUD_VOL_CTL);
 155         cx_swrite(SHADOW_AUD_VOL_CTL, AUD_VOL_CTL, volume);
 156 
 157         core->last_change = jiffies;
 158 }
 159 
 160 /* ----------------------------------------------------------- */
 161 
 162 static void set_audio_standard_BTSC(struct cx88_core *core, unsigned int sap,
 163                                     u32 mode)
 164 {
 165         static const struct rlist btsc[] = {
 166                 {AUD_AFE_12DB_EN, 0x00000001},
 167                 {AUD_OUT1_SEL, 0x00000013},
 168                 {AUD_OUT1_SHIFT, 0x00000000},
 169                 {AUD_POLY0_DDS_CONSTANT, 0x0012010c},
 170                 {AUD_DMD_RA_DDS, 0x00c3e7aa},
 171                 {AUD_DBX_IN_GAIN, 0x00004734},
 172                 {AUD_DBX_WBE_GAIN, 0x00004640},
 173                 {AUD_DBX_SE_GAIN, 0x00008d31},
 174                 {AUD_DCOC_0_SRC, 0x0000001a},
 175                 {AUD_IIR1_4_SEL, 0x00000021},
 176                 {AUD_DCOC_PASS_IN, 0x00000003},
 177                 {AUD_DCOC_0_SHIFT_IN0, 0x0000000a},
 178                 {AUD_DCOC_0_SHIFT_IN1, 0x00000008},
 179                 {AUD_DCOC_1_SHIFT_IN0, 0x0000000a},
 180                 {AUD_DCOC_1_SHIFT_IN1, 0x00000008},
 181                 {AUD_DN0_FREQ, 0x0000283b},
 182                 {AUD_DN2_SRC_SEL, 0x00000008},
 183                 {AUD_DN2_FREQ, 0x00003000},
 184                 {AUD_DN2_AFC, 0x00000002},
 185                 {AUD_DN2_SHFT, 0x00000000},
 186                 {AUD_IIR2_2_SEL, 0x00000020},
 187                 {AUD_IIR2_2_SHIFT, 0x00000000},
 188                 {AUD_IIR2_3_SEL, 0x0000001f},
 189                 {AUD_IIR2_3_SHIFT, 0x00000000},
 190                 {AUD_CRDC1_SRC_SEL, 0x000003ce},
 191                 {AUD_CRDC1_SHIFT, 0x00000000},
 192                 {AUD_CORDIC_SHIFT_1, 0x00000007},
 193                 {AUD_DCOC_1_SRC, 0x0000001b},
 194                 {AUD_DCOC1_SHIFT, 0x00000000},
 195                 {AUD_RDSI_SEL, 0x00000008},
 196                 {AUD_RDSQ_SEL, 0x00000008},
 197                 {AUD_RDSI_SHIFT, 0x00000000},
 198                 {AUD_RDSQ_SHIFT, 0x00000000},
 199                 {AUD_POLYPH80SCALEFAC, 0x00000003},
 200                 { /* end of list */ },
 201         };
 202         static const struct rlist btsc_sap[] = {
 203                 {AUD_AFE_12DB_EN, 0x00000001},
 204                 {AUD_DBX_IN_GAIN, 0x00007200},
 205                 {AUD_DBX_WBE_GAIN, 0x00006200},
 206                 {AUD_DBX_SE_GAIN, 0x00006200},
 207                 {AUD_IIR1_1_SEL, 0x00000000},
 208                 {AUD_IIR1_3_SEL, 0x00000001},
 209                 {AUD_DN1_SRC_SEL, 0x00000007},
 210                 {AUD_IIR1_4_SHIFT, 0x00000006},
 211                 {AUD_IIR2_1_SHIFT, 0x00000000},
 212                 {AUD_IIR2_2_SHIFT, 0x00000000},
 213                 {AUD_IIR3_0_SHIFT, 0x00000000},
 214                 {AUD_IIR3_1_SHIFT, 0x00000000},
 215                 {AUD_IIR3_0_SEL, 0x0000000d},
 216                 {AUD_IIR3_1_SEL, 0x0000000e},
 217                 {AUD_DEEMPH1_SRC_SEL, 0x00000014},
 218                 {AUD_DEEMPH1_SHIFT, 0x00000000},
 219                 {AUD_DEEMPH1_G0, 0x00004000},
 220                 {AUD_DEEMPH1_A0, 0x00000000},
 221                 {AUD_DEEMPH1_B0, 0x00000000},
 222                 {AUD_DEEMPH1_A1, 0x00000000},
 223                 {AUD_DEEMPH1_B1, 0x00000000},
 224                 {AUD_OUT0_SEL, 0x0000003f},
 225                 {AUD_OUT1_SEL, 0x0000003f},
 226                 {AUD_DN1_AFC, 0x00000002},
 227                 {AUD_DCOC_0_SHIFT_IN0, 0x0000000a},
 228                 {AUD_DCOC_0_SHIFT_IN1, 0x00000008},
 229                 {AUD_DCOC_1_SHIFT_IN0, 0x0000000a},
 230                 {AUD_DCOC_1_SHIFT_IN1, 0x00000008},
 231                 {AUD_IIR1_0_SEL, 0x0000001d},
 232                 {AUD_IIR1_2_SEL, 0x0000001e},
 233                 {AUD_IIR2_1_SEL, 0x00000002},
 234                 {AUD_IIR2_2_SEL, 0x00000004},
 235                 {AUD_IIR3_2_SEL, 0x0000000f},
 236                 {AUD_DCOC2_SHIFT, 0x00000001},
 237                 {AUD_IIR3_2_SHIFT, 0x00000001},
 238                 {AUD_DEEMPH0_SRC_SEL, 0x00000014},
 239                 {AUD_CORDIC_SHIFT_1, 0x00000006},
 240                 {AUD_POLY0_DDS_CONSTANT, 0x000e4db2},
 241                 {AUD_DMD_RA_DDS, 0x00f696e6},
 242                 {AUD_IIR2_3_SEL, 0x00000025},
 243                 {AUD_IIR1_4_SEL, 0x00000021},
 244                 {AUD_DN1_FREQ, 0x0000c965},
 245                 {AUD_DCOC_PASS_IN, 0x00000003},
 246                 {AUD_DCOC_0_SRC, 0x0000001a},
 247                 {AUD_DCOC_1_SRC, 0x0000001b},
 248                 {AUD_DCOC1_SHIFT, 0x00000000},
 249                 {AUD_RDSI_SEL, 0x00000009},
 250                 {AUD_RDSQ_SEL, 0x00000009},
 251                 {AUD_RDSI_SHIFT, 0x00000000},
 252                 {AUD_RDSQ_SHIFT, 0x00000000},
 253                 {AUD_POLYPH80SCALEFAC, 0x00000003},
 254                 { /* end of list */ },
 255         };
 256 
 257         mode |= EN_FMRADIO_EN_RDS;
 258 
 259         if (sap) {
 260                 dprintk("%s SAP (status: unknown)\n", __func__);
 261                 set_audio_start(core, SEL_SAP);
 262                 set_audio_registers(core, btsc_sap);
 263                 set_audio_finish(core, mode);
 264         } else {
 265                 dprintk("%s (status: known-good)\n", __func__);
 266                 set_audio_start(core, SEL_BTSC);
 267                 set_audio_registers(core, btsc);
 268                 set_audio_finish(core, mode);
 269         }
 270 }
 271 
 272 static void set_audio_standard_NICAM(struct cx88_core *core, u32 mode)
 273 {
 274         static const struct rlist nicam_l[] = {
 275                 {AUD_AFE_12DB_EN, 0x00000001},
 276                 {AUD_RATE_ADJ1, 0x00000060},
 277                 {AUD_RATE_ADJ2, 0x000000F9},
 278                 {AUD_RATE_ADJ3, 0x000001CC},
 279                 {AUD_RATE_ADJ4, 0x000002B3},
 280                 {AUD_RATE_ADJ5, 0x00000726},
 281                 {AUD_DEEMPHDENOM1_R, 0x0000F3D0},
 282                 {AUD_DEEMPHDENOM2_R, 0x00000000},
 283                 {AUD_ERRLOGPERIOD_R, 0x00000064},
 284                 {AUD_ERRINTRPTTHSHLD1_R, 0x00000FFF},
 285                 {AUD_ERRINTRPTTHSHLD2_R, 0x0000001F},
 286                 {AUD_ERRINTRPTTHSHLD3_R, 0x0000000F},
 287                 {AUD_POLYPH80SCALEFAC, 0x00000003},
 288                 {AUD_DMD_RA_DDS, 0x00C00000},
 289                 {AUD_PLL_INT, 0x0000001E},
 290                 {AUD_PLL_DDS, 0x00000000},
 291                 {AUD_PLL_FRAC, 0x0000E542},
 292                 {AUD_START_TIMER, 0x00000000},
 293                 {AUD_DEEMPHNUMER1_R, 0x000353DE},
 294                 {AUD_DEEMPHNUMER2_R, 0x000001B1},
 295                 {AUD_PDF_DDS_CNST_BYTE2, 0x06},
 296                 {AUD_PDF_DDS_CNST_BYTE1, 0x82},
 297                 {AUD_PDF_DDS_CNST_BYTE0, 0x12},
 298                 {AUD_QAM_MODE, 0x05},
 299                 {AUD_PHACC_FREQ_8MSB, 0x34},
 300                 {AUD_PHACC_FREQ_8LSB, 0x4C},
 301                 {AUD_DEEMPHGAIN_R, 0x00006680},
 302                 {AUD_RATE_THRES_DMD, 0x000000C0},
 303                 { /* end of list */ },
 304         };
 305 
 306         static const struct rlist nicam_bgdki_common[] = {
 307                 {AUD_AFE_12DB_EN, 0x00000001},
 308                 {AUD_RATE_ADJ1, 0x00000010},
 309                 {AUD_RATE_ADJ2, 0x00000040},
 310                 {AUD_RATE_ADJ3, 0x00000100},
 311                 {AUD_RATE_ADJ4, 0x00000400},
 312                 {AUD_RATE_ADJ5, 0x00001000},
 313                 {AUD_ERRLOGPERIOD_R, 0x00000fff},
 314                 {AUD_ERRINTRPTTHSHLD1_R, 0x000003ff},
 315                 {AUD_ERRINTRPTTHSHLD2_R, 0x000000ff},
 316                 {AUD_ERRINTRPTTHSHLD3_R, 0x0000003f},
 317                 {AUD_POLYPH80SCALEFAC, 0x00000003},
 318                 {AUD_DEEMPHGAIN_R, 0x000023c2},
 319                 {AUD_DEEMPHNUMER1_R, 0x0002a7bc},
 320                 {AUD_DEEMPHNUMER2_R, 0x0003023e},
 321                 {AUD_DEEMPHDENOM1_R, 0x0000f3d0},
 322                 {AUD_DEEMPHDENOM2_R, 0x00000000},
 323                 {AUD_PDF_DDS_CNST_BYTE2, 0x06},
 324                 {AUD_PDF_DDS_CNST_BYTE1, 0x82},
 325                 {AUD_QAM_MODE, 0x05},
 326                 { /* end of list */ },
 327         };
 328 
 329         static const struct rlist nicam_i[] = {
 330                 {AUD_PDF_DDS_CNST_BYTE0, 0x12},
 331                 {AUD_PHACC_FREQ_8MSB, 0x3a},
 332                 {AUD_PHACC_FREQ_8LSB, 0x93},
 333                 { /* end of list */ },
 334         };
 335 
 336         static const struct rlist nicam_default[] = {
 337                 {AUD_PDF_DDS_CNST_BYTE0, 0x16},
 338                 {AUD_PHACC_FREQ_8MSB, 0x34},
 339                 {AUD_PHACC_FREQ_8LSB, 0x4c},
 340                 { /* end of list */ },
 341         };
 342 
 343         set_audio_start(core, SEL_NICAM);
 344         switch (core->tvaudio) {
 345         case WW_L:
 346                 dprintk("%s SECAM-L NICAM (status: devel)\n", __func__);
 347                 set_audio_registers(core, nicam_l);
 348                 break;
 349         case WW_I:
 350                 dprintk("%s PAL-I NICAM (status: known-good)\n", __func__);
 351                 set_audio_registers(core, nicam_bgdki_common);
 352                 set_audio_registers(core, nicam_i);
 353                 break;
 354         case WW_NONE:
 355         case WW_BTSC:
 356         case WW_BG:
 357         case WW_DK:
 358         case WW_EIAJ:
 359         case WW_I2SPT:
 360         case WW_FM:
 361         case WW_I2SADC:
 362         case WW_M:
 363                 dprintk("%s PAL-BGDK NICAM (status: known-good)\n", __func__);
 364                 set_audio_registers(core, nicam_bgdki_common);
 365                 set_audio_registers(core, nicam_default);
 366                 break;
 367         }
 368 
 369         mode |= EN_DMTRX_LR | EN_DMTRX_BYPASS;
 370         set_audio_finish(core, mode);
 371 }
 372 
 373 static void set_audio_standard_A2(struct cx88_core *core, u32 mode)
 374 {
 375         static const struct rlist a2_bgdk_common[] = {
 376                 {AUD_ERRLOGPERIOD_R, 0x00000064},
 377                 {AUD_ERRINTRPTTHSHLD1_R, 0x00000fff},
 378                 {AUD_ERRINTRPTTHSHLD2_R, 0x0000001f},
 379                 {AUD_ERRINTRPTTHSHLD3_R, 0x0000000f},
 380                 {AUD_PDF_DDS_CNST_BYTE2, 0x06},
 381                 {AUD_PDF_DDS_CNST_BYTE1, 0x82},
 382                 {AUD_PDF_DDS_CNST_BYTE0, 0x12},
 383                 {AUD_QAM_MODE, 0x05},
 384                 {AUD_PHACC_FREQ_8MSB, 0x34},
 385                 {AUD_PHACC_FREQ_8LSB, 0x4c},
 386                 {AUD_RATE_ADJ1, 0x00000100},
 387                 {AUD_RATE_ADJ2, 0x00000200},
 388                 {AUD_RATE_ADJ3, 0x00000300},
 389                 {AUD_RATE_ADJ4, 0x00000400},
 390                 {AUD_RATE_ADJ5, 0x00000500},
 391                 {AUD_THR_FR, 0x00000000},
 392                 {AAGC_HYST, 0x0000001a},
 393                 {AUD_PILOT_BQD_1_K0, 0x0000755b},
 394                 {AUD_PILOT_BQD_1_K1, 0x00551340},
 395                 {AUD_PILOT_BQD_1_K2, 0x006d30be},
 396                 {AUD_PILOT_BQD_1_K3, 0xffd394af},
 397                 {AUD_PILOT_BQD_1_K4, 0x00400000},
 398                 {AUD_PILOT_BQD_2_K0, 0x00040000},
 399                 {AUD_PILOT_BQD_2_K1, 0x002a4841},
 400                 {AUD_PILOT_BQD_2_K2, 0x00400000},
 401                 {AUD_PILOT_BQD_2_K3, 0x00000000},
 402                 {AUD_PILOT_BQD_2_K4, 0x00000000},
 403                 {AUD_MODE_CHG_TIMER, 0x00000040},
 404                 {AUD_AFE_12DB_EN, 0x00000001},
 405                 {AUD_CORDIC_SHIFT_0, 0x00000007},
 406                 {AUD_CORDIC_SHIFT_1, 0x00000007},
 407                 {AUD_DEEMPH0_G0, 0x00000380},
 408                 {AUD_DEEMPH1_G0, 0x00000380},
 409                 {AUD_DCOC_0_SRC, 0x0000001a},
 410                 {AUD_DCOC0_SHIFT, 0x00000000},
 411                 {AUD_DCOC_0_SHIFT_IN0, 0x0000000a},
 412                 {AUD_DCOC_0_SHIFT_IN1, 0x00000008},
 413                 {AUD_DCOC_PASS_IN, 0x00000003},
 414                 {AUD_IIR3_0_SEL, 0x00000021},
 415                 {AUD_DN2_AFC, 0x00000002},
 416                 {AUD_DCOC_1_SRC, 0x0000001b},
 417                 {AUD_DCOC1_SHIFT, 0x00000000},
 418                 {AUD_DCOC_1_SHIFT_IN0, 0x0000000a},
 419                 {AUD_DCOC_1_SHIFT_IN1, 0x00000008},
 420                 {AUD_IIR3_1_SEL, 0x00000023},
 421                 {AUD_RDSI_SEL, 0x00000017},
 422                 {AUD_RDSI_SHIFT, 0x00000000},
 423                 {AUD_RDSQ_SEL, 0x00000017},
 424                 {AUD_RDSQ_SHIFT, 0x00000000},
 425                 {AUD_PLL_INT, 0x0000001e},
 426                 {AUD_PLL_DDS, 0x00000000},
 427                 {AUD_PLL_FRAC, 0x0000e542},
 428                 {AUD_POLYPH80SCALEFAC, 0x00000001},
 429                 {AUD_START_TIMER, 0x00000000},
 430                 { /* end of list */ },
 431         };
 432 
 433         static const struct rlist a2_bg[] = {
 434                 {AUD_DMD_RA_DDS, 0x002a4f2f},
 435                 {AUD_C1_UP_THR, 0x00007000},
 436                 {AUD_C1_LO_THR, 0x00005400},
 437                 {AUD_C2_UP_THR, 0x00005400},
 438                 {AUD_C2_LO_THR, 0x00003000},
 439                 { /* end of list */ },
 440         };
 441 
 442         static const struct rlist a2_dk[] = {
 443                 {AUD_DMD_RA_DDS, 0x002a4f2f},
 444                 {AUD_C1_UP_THR, 0x00007000},
 445                 {AUD_C1_LO_THR, 0x00005400},
 446                 {AUD_C2_UP_THR, 0x00005400},
 447                 {AUD_C2_LO_THR, 0x00003000},
 448                 {AUD_DN0_FREQ, 0x00003a1c},
 449                 {AUD_DN2_FREQ, 0x0000d2e0},
 450                 { /* end of list */ },
 451         };
 452 
 453         static const struct rlist a1_i[] = {
 454                 {AUD_ERRLOGPERIOD_R, 0x00000064},
 455                 {AUD_ERRINTRPTTHSHLD1_R, 0x00000fff},
 456                 {AUD_ERRINTRPTTHSHLD2_R, 0x0000001f},
 457                 {AUD_ERRINTRPTTHSHLD3_R, 0x0000000f},
 458                 {AUD_PDF_DDS_CNST_BYTE2, 0x06},
 459                 {AUD_PDF_DDS_CNST_BYTE1, 0x82},
 460                 {AUD_PDF_DDS_CNST_BYTE0, 0x12},
 461                 {AUD_QAM_MODE, 0x05},
 462                 {AUD_PHACC_FREQ_8MSB, 0x3a},
 463                 {AUD_PHACC_FREQ_8LSB, 0x93},
 464                 {AUD_DMD_RA_DDS, 0x002a4f2f},
 465                 {AUD_PLL_INT, 0x0000001e},
 466                 {AUD_PLL_DDS, 0x00000004},
 467                 {AUD_PLL_FRAC, 0x0000e542},
 468                 {AUD_RATE_ADJ1, 0x00000100},
 469                 {AUD_RATE_ADJ2, 0x00000200},
 470                 {AUD_RATE_ADJ3, 0x00000300},
 471                 {AUD_RATE_ADJ4, 0x00000400},
 472                 {AUD_RATE_ADJ5, 0x00000500},
 473                 {AUD_THR_FR, 0x00000000},
 474                 {AUD_PILOT_BQD_1_K0, 0x0000755b},
 475                 {AUD_PILOT_BQD_1_K1, 0x00551340},
 476                 {AUD_PILOT_BQD_1_K2, 0x006d30be},
 477                 {AUD_PILOT_BQD_1_K3, 0xffd394af},
 478                 {AUD_PILOT_BQD_1_K4, 0x00400000},
 479                 {AUD_PILOT_BQD_2_K0, 0x00040000},
 480                 {AUD_PILOT_BQD_2_K1, 0x002a4841},
 481                 {AUD_PILOT_BQD_2_K2, 0x00400000},
 482                 {AUD_PILOT_BQD_2_K3, 0x00000000},
 483                 {AUD_PILOT_BQD_2_K4, 0x00000000},
 484                 {AUD_MODE_CHG_TIMER, 0x00000060},
 485                 {AUD_AFE_12DB_EN, 0x00000001},
 486                 {AAGC_HYST, 0x0000000a},
 487                 {AUD_CORDIC_SHIFT_0, 0x00000007},
 488                 {AUD_CORDIC_SHIFT_1, 0x00000007},
 489                 {AUD_C1_UP_THR, 0x00007000},
 490                 {AUD_C1_LO_THR, 0x00005400},
 491                 {AUD_C2_UP_THR, 0x00005400},
 492                 {AUD_C2_LO_THR, 0x00003000},
 493                 {AUD_DCOC_0_SRC, 0x0000001a},
 494                 {AUD_DCOC0_SHIFT, 0x00000000},
 495                 {AUD_DCOC_0_SHIFT_IN0, 0x0000000a},
 496                 {AUD_DCOC_0_SHIFT_IN1, 0x00000008},
 497                 {AUD_DCOC_PASS_IN, 0x00000003},
 498                 {AUD_IIR3_0_SEL, 0x00000021},
 499                 {AUD_DN2_AFC, 0x00000002},
 500                 {AUD_DCOC_1_SRC, 0x0000001b},
 501                 {AUD_DCOC1_SHIFT, 0x00000000},
 502                 {AUD_DCOC_1_SHIFT_IN0, 0x0000000a},
 503                 {AUD_DCOC_1_SHIFT_IN1, 0x00000008},
 504                 {AUD_IIR3_1_SEL, 0x00000023},
 505                 {AUD_DN0_FREQ, 0x000035a3},
 506                 {AUD_DN2_FREQ, 0x000029c7},
 507                 {AUD_CRDC0_SRC_SEL, 0x00000511},
 508                 {AUD_IIR1_0_SEL, 0x00000001},
 509                 {AUD_IIR1_1_SEL, 0x00000000},
 510                 {AUD_IIR3_2_SEL, 0x00000003},
 511                 {AUD_IIR3_2_SHIFT, 0x00000000},
 512                 {AUD_IIR3_0_SEL, 0x00000002},
 513                 {AUD_IIR2_0_SEL, 0x00000021},
 514                 {AUD_IIR2_0_SHIFT, 0x00000002},
 515                 {AUD_DEEMPH0_SRC_SEL, 0x0000000b},
 516                 {AUD_DEEMPH1_SRC_SEL, 0x0000000b},
 517                 {AUD_POLYPH80SCALEFAC, 0x00000001},
 518                 {AUD_START_TIMER, 0x00000000},
 519                 { /* end of list */ },
 520         };
 521 
 522         static const struct rlist am_l[] = {
 523                 {AUD_ERRLOGPERIOD_R, 0x00000064},
 524                 {AUD_ERRINTRPTTHSHLD1_R, 0x00000FFF},
 525                 {AUD_ERRINTRPTTHSHLD2_R, 0x0000001F},
 526                 {AUD_ERRINTRPTTHSHLD3_R, 0x0000000F},
 527                 {AUD_PDF_DDS_CNST_BYTE2, 0x48},
 528                 {AUD_PDF_DDS_CNST_BYTE1, 0x3D},
 529                 {AUD_QAM_MODE, 0x00},
 530                 {AUD_PDF_DDS_CNST_BYTE0, 0xf5},
 531                 {AUD_PHACC_FREQ_8MSB, 0x3a},
 532                 {AUD_PHACC_FREQ_8LSB, 0x4a},
 533                 {AUD_DEEMPHGAIN_R, 0x00006680},
 534                 {AUD_DEEMPHNUMER1_R, 0x000353DE},
 535                 {AUD_DEEMPHNUMER2_R, 0x000001B1},
 536                 {AUD_DEEMPHDENOM1_R, 0x0000F3D0},
 537                 {AUD_DEEMPHDENOM2_R, 0x00000000},
 538                 {AUD_FM_MODE_ENABLE, 0x00000007},
 539                 {AUD_POLYPH80SCALEFAC, 0x00000003},
 540                 {AUD_AFE_12DB_EN, 0x00000001},
 541                 {AAGC_GAIN, 0x00000000},
 542                 {AAGC_HYST, 0x00000018},
 543                 {AAGC_DEF, 0x00000020},
 544                 {AUD_DN0_FREQ, 0x00000000},
 545                 {AUD_POLY0_DDS_CONSTANT, 0x000E4DB2},
 546                 {AUD_DCOC_0_SRC, 0x00000021},
 547                 {AUD_IIR1_0_SEL, 0x00000000},
 548                 {AUD_IIR1_0_SHIFT, 0x00000007},
 549                 {AUD_IIR1_1_SEL, 0x00000002},
 550                 {AUD_IIR1_1_SHIFT, 0x00000000},
 551                 {AUD_DCOC_1_SRC, 0x00000003},
 552                 {AUD_DCOC1_SHIFT, 0x00000000},
 553                 {AUD_DCOC_PASS_IN, 0x00000000},
 554                 {AUD_IIR1_2_SEL, 0x00000023},
 555                 {AUD_IIR1_2_SHIFT, 0x00000000},
 556                 {AUD_IIR1_3_SEL, 0x00000004},
 557                 {AUD_IIR1_3_SHIFT, 0x00000007},
 558                 {AUD_IIR1_4_SEL, 0x00000005},
 559                 {AUD_IIR1_4_SHIFT, 0x00000007},
 560                 {AUD_IIR3_0_SEL, 0x00000007},
 561                 {AUD_IIR3_0_SHIFT, 0x00000000},
 562                 {AUD_DEEMPH0_SRC_SEL, 0x00000011},
 563                 {AUD_DEEMPH0_SHIFT, 0x00000000},
 564                 {AUD_DEEMPH0_G0, 0x00007000},
 565                 {AUD_DEEMPH0_A0, 0x00000000},
 566                 {AUD_DEEMPH0_B0, 0x00000000},
 567                 {AUD_DEEMPH0_A1, 0x00000000},
 568                 {AUD_DEEMPH0_B1, 0x00000000},
 569                 {AUD_DEEMPH1_SRC_SEL, 0x00000011},
 570                 {AUD_DEEMPH1_SHIFT, 0x00000000},
 571                 {AUD_DEEMPH1_G0, 0x00007000},
 572                 {AUD_DEEMPH1_A0, 0x00000000},
 573                 {AUD_DEEMPH1_B0, 0x00000000},
 574                 {AUD_DEEMPH1_A1, 0x00000000},
 575                 {AUD_DEEMPH1_B1, 0x00000000},
 576                 {AUD_OUT0_SEL, 0x0000003F},
 577                 {AUD_OUT1_SEL, 0x0000003F},
 578                 {AUD_DMD_RA_DDS, 0x00F5C285},
 579                 {AUD_PLL_INT, 0x0000001E},
 580                 {AUD_PLL_DDS, 0x00000000},
 581                 {AUD_PLL_FRAC, 0x0000E542},
 582                 {AUD_RATE_ADJ1, 0x00000100},
 583                 {AUD_RATE_ADJ2, 0x00000200},
 584                 {AUD_RATE_ADJ3, 0x00000300},
 585                 {AUD_RATE_ADJ4, 0x00000400},
 586                 {AUD_RATE_ADJ5, 0x00000500},
 587                 {AUD_RATE_THRES_DMD, 0x000000C0},
 588                 { /* end of list */ },
 589         };
 590 
 591         static const struct rlist a2_deemph50[] = {
 592                 {AUD_DEEMPH0_G0, 0x00000380},
 593                 {AUD_DEEMPH1_G0, 0x00000380},
 594                 {AUD_DEEMPHGAIN_R, 0x000011e1},
 595                 {AUD_DEEMPHNUMER1_R, 0x0002a7bc},
 596                 {AUD_DEEMPHNUMER2_R, 0x0003023c},
 597                 { /* end of list */ },
 598         };
 599 
 600         set_audio_start(core, SEL_A2);
 601         switch (core->tvaudio) {
 602         case WW_BG:
 603                 dprintk("%s PAL-BG A1/2 (status: known-good)\n", __func__);
 604                 set_audio_registers(core, a2_bgdk_common);
 605                 set_audio_registers(core, a2_bg);
 606                 set_audio_registers(core, a2_deemph50);
 607                 break;
 608         case WW_DK:
 609                 dprintk("%s PAL-DK A1/2 (status: known-good)\n", __func__);
 610                 set_audio_registers(core, a2_bgdk_common);
 611                 set_audio_registers(core, a2_dk);
 612                 set_audio_registers(core, a2_deemph50);
 613                 break;
 614         case WW_I:
 615                 dprintk("%s PAL-I A1 (status: known-good)\n", __func__);
 616                 set_audio_registers(core, a1_i);
 617                 set_audio_registers(core, a2_deemph50);
 618                 break;
 619         case WW_L:
 620                 dprintk("%s AM-L (status: devel)\n", __func__);
 621                 set_audio_registers(core, am_l);
 622                 break;
 623         case WW_NONE:
 624         case WW_BTSC:
 625         case WW_EIAJ:
 626         case WW_I2SPT:
 627         case WW_FM:
 628         case WW_I2SADC:
 629         case WW_M:
 630                 dprintk("%s Warning: wrong value\n", __func__);
 631                 return;
 632         }
 633 
 634         mode |= EN_FMRADIO_EN_RDS | EN_DMTRX_SUMDIFF;
 635         set_audio_finish(core, mode);
 636 }
 637 
 638 static void set_audio_standard_EIAJ(struct cx88_core *core)
 639 {
 640         static const struct rlist eiaj[] = {
 641                 /* TODO: eiaj register settings are not there yet ... */
 642 
 643                 { /* end of list */ },
 644         };
 645         dprintk("%s (status: unknown)\n", __func__);
 646 
 647         set_audio_start(core, SEL_EIAJ);
 648         set_audio_registers(core, eiaj);
 649         set_audio_finish(core, EN_EIAJ_AUTO_STEREO);
 650 }
 651 
 652 static void set_audio_standard_FM(struct cx88_core *core,
 653                                   enum cx88_deemph_type deemph)
 654 {
 655         static const struct rlist fm_deemph_50[] = {
 656                 {AUD_DEEMPH0_G0, 0x0C45},
 657                 {AUD_DEEMPH0_A0, 0x6262},
 658                 {AUD_DEEMPH0_B0, 0x1C29},
 659                 {AUD_DEEMPH0_A1, 0x3FC66},
 660                 {AUD_DEEMPH0_B1, 0x399A},
 661 
 662                 {AUD_DEEMPH1_G0, 0x0D80},
 663                 {AUD_DEEMPH1_A0, 0x6262},
 664                 {AUD_DEEMPH1_B0, 0x1C29},
 665                 {AUD_DEEMPH1_A1, 0x3FC66},
 666                 {AUD_DEEMPH1_B1, 0x399A},
 667 
 668                 {AUD_POLYPH80SCALEFAC, 0x0003},
 669                 { /* end of list */ },
 670         };
 671         static const struct rlist fm_deemph_75[] = {
 672                 {AUD_DEEMPH0_G0, 0x091B},
 673                 {AUD_DEEMPH0_A0, 0x6B68},
 674                 {AUD_DEEMPH0_B0, 0x11EC},
 675                 {AUD_DEEMPH0_A1, 0x3FC66},
 676                 {AUD_DEEMPH0_B1, 0x399A},
 677 
 678                 {AUD_DEEMPH1_G0, 0x0AA0},
 679                 {AUD_DEEMPH1_A0, 0x6B68},
 680                 {AUD_DEEMPH1_B0, 0x11EC},
 681                 {AUD_DEEMPH1_A1, 0x3FC66},
 682                 {AUD_DEEMPH1_B1, 0x399A},
 683 
 684                 {AUD_POLYPH80SCALEFAC, 0x0003},
 685                 { /* end of list */ },
 686         };
 687 
 688         /*
 689          * It is enough to leave default values?
 690          *
 691          * No, it's not!  The deemphasis registers are reset to the 75us
 692          * values by default.  Analyzing the spectrum of the decoded audio
 693          * reveals that "no deemphasis" is the same as 75 us, while the 50 us
 694          * setting results in less deemphasis.
 695          */
 696         static const struct rlist fm_no_deemph[] = {
 697                 {AUD_POLYPH80SCALEFAC, 0x0003},
 698                 { /* end of list */ },
 699         };
 700 
 701         dprintk("%s (status: unknown)\n", __func__);
 702         set_audio_start(core, SEL_FMRADIO);
 703 
 704         switch (deemph) {
 705         default:
 706         case FM_NO_DEEMPH:
 707                 set_audio_registers(core, fm_no_deemph);
 708                 break;
 709 
 710         case FM_DEEMPH_50:
 711                 set_audio_registers(core, fm_deemph_50);
 712                 break;
 713 
 714         case FM_DEEMPH_75:
 715                 set_audio_registers(core, fm_deemph_75);
 716                 break;
 717         }
 718 
 719         set_audio_finish(core, EN_FMRADIO_AUTO_STEREO);
 720 }
 721 
 722 /* ----------------------------------------------------------- */
 723 
 724 static int cx88_detect_nicam(struct cx88_core *core)
 725 {
 726         int i, j = 0;
 727 
 728         dprintk("start nicam autodetect.\n");
 729 
 730         for (i = 0; i < 6; i++) {
 731                 /* if bit1=1 then nicam is detected */
 732                 j += ((cx_read(AUD_NICAM_STATUS2) & 0x02) >> 1);
 733 
 734                 if (j == 1) {
 735                         dprintk("nicam is detected.\n");
 736                         return 1;
 737                 }
 738 
 739                 /* wait a little bit for next reading status */
 740                 usleep_range(10000, 20000);
 741         }
 742 
 743         dprintk("nicam is not detected.\n");
 744         return 0;
 745 }
 746 
 747 void cx88_set_tvaudio(struct cx88_core *core)
 748 {
 749         switch (core->tvaudio) {
 750         case WW_BTSC:
 751                 set_audio_standard_BTSC(core, 0, EN_BTSC_AUTO_STEREO);
 752                 break;
 753         case WW_BG:
 754         case WW_DK:
 755         case WW_M:
 756         case WW_I:
 757         case WW_L:
 758                 /* prepare all dsp registers */
 759                 set_audio_standard_A2(core, EN_A2_FORCE_MONO1);
 760 
 761                 /*
 762                  * set nicam mode - otherwise
 763                  * AUD_NICAM_STATUS2 contains wrong values
 764                  */
 765                 set_audio_standard_NICAM(core, EN_NICAM_AUTO_STEREO);
 766                 if (cx88_detect_nicam(core) == 0) {
 767                         /* fall back to fm / am mono */
 768                         set_audio_standard_A2(core, EN_A2_FORCE_MONO1);
 769                         core->audiomode_current = V4L2_TUNER_MODE_MONO;
 770                         core->use_nicam = 0;
 771                 } else {
 772                         core->use_nicam = 1;
 773                 }
 774                 break;
 775         case WW_EIAJ:
 776                 set_audio_standard_EIAJ(core);
 777                 break;
 778         case WW_FM:
 779                 set_audio_standard_FM(core, radio_deemphasis);
 780                 break;
 781         case WW_I2SADC:
 782                 set_audio_start(core, 0x01);
 783                 /*
 784                  * Slave/Philips/Autobaud
 785                  * NB on Nova-S bit1 NPhilipsSony appears to be inverted:
 786                  *      0= Sony, 1=Philips
 787                  */
 788                 cx_write(AUD_I2SINPUTCNTL, core->board.i2sinputcntl);
 789                 /* Switch to "I2S ADC mode" */
 790                 cx_write(AUD_I2SCNTL, 0x1);
 791                 set_audio_finish(core, EN_I2SIN_ENABLE);
 792                 break;
 793         case WW_NONE:
 794         case WW_I2SPT:
 795                 pr_info("unknown tv audio mode [%d]\n", core->tvaudio);
 796                 break;
 797         }
 798 }
 799 EXPORT_SYMBOL(cx88_set_tvaudio);
 800 
 801 void cx88_newstation(struct cx88_core *core)
 802 {
 803         core->audiomode_manual = UNSET;
 804         core->last_change = jiffies;
 805 }
 806 EXPORT_SYMBOL(cx88_newstation);
 807 
 808 void cx88_get_stereo(struct cx88_core *core, struct v4l2_tuner *t)
 809 {
 810         static const char * const m[] = { "stereo", "dual mono",
 811                                           "mono",   "sap" };
 812         static const char * const p[] = { "no pilot", "pilot c1",
 813                                           "pilot c2", "?" };
 814         u32 reg, mode, pilot;
 815 
 816         reg = cx_read(AUD_STATUS);
 817         mode = reg & 0x03;
 818         pilot = (reg >> 2) & 0x03;
 819 
 820         if (core->astat != reg)
 821                 dprintk("AUD_STATUS: 0x%x [%s/%s] ctl=%s\n",
 822                         reg, m[mode], p[pilot],
 823                         aud_ctl_names[cx_read(AUD_CTL) & 63]);
 824         core->astat = reg;
 825 
 826         t->capability = V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_SAP |
 827             V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2;
 828         t->rxsubchans = UNSET;
 829         t->audmode = V4L2_TUNER_MODE_MONO;
 830 
 831         switch (mode) {
 832         case 0:
 833                 t->audmode = V4L2_TUNER_MODE_STEREO;
 834                 break;
 835         case 1:
 836                 t->audmode = V4L2_TUNER_MODE_LANG2;
 837                 break;
 838         case 2:
 839                 t->audmode = V4L2_TUNER_MODE_MONO;
 840                 break;
 841         case 3:
 842                 t->audmode = V4L2_TUNER_MODE_SAP;
 843                 break;
 844         }
 845 
 846         switch (core->tvaudio) {
 847         case WW_BTSC:
 848         case WW_BG:
 849         case WW_DK:
 850         case WW_M:
 851         case WW_EIAJ:
 852                 if (!core->use_nicam) {
 853                         t->rxsubchans = cx88_dsp_detect_stereo_sap(core);
 854                         break;
 855                 }
 856                 break;
 857         case WW_NONE:
 858         case WW_I:
 859         case WW_L:
 860         case WW_I2SPT:
 861         case WW_FM:
 862         case WW_I2SADC:
 863                 /* nothing */
 864                 break;
 865         }
 866 
 867         /* If software stereo detection is not supported... */
 868         if (t->rxsubchans == UNSET) {
 869                 t->rxsubchans = V4L2_TUNER_SUB_MONO;
 870                 /*
 871                  * If the hardware itself detected stereo, also return
 872                  * stereo as an available subchannel
 873                  */
 874                 if (t->audmode == V4L2_TUNER_MODE_STEREO)
 875                         t->rxsubchans |= V4L2_TUNER_SUB_STEREO;
 876         }
 877 }
 878 EXPORT_SYMBOL(cx88_get_stereo);
 879 
 880 
 881 void cx88_set_stereo(struct cx88_core *core, u32 mode, int manual)
 882 {
 883         u32 ctl = UNSET;
 884         u32 mask = UNSET;
 885 
 886         if (manual) {
 887                 core->audiomode_manual = mode;
 888         } else {
 889                 if (core->audiomode_manual != UNSET)
 890                         return;
 891         }
 892         core->audiomode_current = mode;
 893 
 894         switch (core->tvaudio) {
 895         case WW_BTSC:
 896                 switch (mode) {
 897                 case V4L2_TUNER_MODE_MONO:
 898                         set_audio_standard_BTSC(core, 0, EN_BTSC_FORCE_MONO);
 899                         break;
 900                 case V4L2_TUNER_MODE_LANG1:
 901                         set_audio_standard_BTSC(core, 0, EN_BTSC_AUTO_STEREO);
 902                         break;
 903                 case V4L2_TUNER_MODE_LANG2:
 904                         set_audio_standard_BTSC(core, 1, EN_BTSC_FORCE_SAP);
 905                         break;
 906                 case V4L2_TUNER_MODE_STEREO:
 907                 case V4L2_TUNER_MODE_LANG1_LANG2:
 908                         set_audio_standard_BTSC(core, 0, EN_BTSC_FORCE_STEREO);
 909                         break;
 910                 }
 911                 break;
 912         case WW_BG:
 913         case WW_DK:
 914         case WW_M:
 915         case WW_I:
 916         case WW_L:
 917                 if (core->use_nicam == 1) {
 918                         switch (mode) {
 919                         case V4L2_TUNER_MODE_MONO:
 920                         case V4L2_TUNER_MODE_LANG1:
 921                                 set_audio_standard_NICAM(core,
 922                                                          EN_NICAM_FORCE_MONO1);
 923                                 break;
 924                         case V4L2_TUNER_MODE_LANG2:
 925                                 set_audio_standard_NICAM(core,
 926                                                          EN_NICAM_FORCE_MONO2);
 927                                 break;
 928                         case V4L2_TUNER_MODE_STEREO:
 929                         case V4L2_TUNER_MODE_LANG1_LANG2:
 930                                 set_audio_standard_NICAM(core,
 931                                                          EN_NICAM_FORCE_STEREO);
 932                                 break;
 933                         }
 934                 } else {
 935                         if ((core->tvaudio == WW_I) ||
 936                             (core->tvaudio == WW_L)) {
 937                                 /* fall back to fm / am mono */
 938                                 set_audio_standard_A2(core, EN_A2_FORCE_MONO1);
 939                         } else {
 940                                 /* TODO: Add A2 autodection */
 941                                 mask = 0x3f;
 942                                 switch (mode) {
 943                                 case V4L2_TUNER_MODE_MONO:
 944                                 case V4L2_TUNER_MODE_LANG1:
 945                                         ctl = EN_A2_FORCE_MONO1;
 946                                         break;
 947                                 case V4L2_TUNER_MODE_LANG2:
 948                                         ctl = EN_A2_FORCE_MONO2;
 949                                         break;
 950                                 case V4L2_TUNER_MODE_STEREO:
 951                                 case V4L2_TUNER_MODE_LANG1_LANG2:
 952                                         ctl = EN_A2_FORCE_STEREO;
 953                                         break;
 954                                 }
 955                         }
 956                 }
 957                 break;
 958         case WW_FM:
 959                 switch (mode) {
 960                 case V4L2_TUNER_MODE_MONO:
 961                         ctl = EN_FMRADIO_FORCE_MONO;
 962                         mask = 0x3f;
 963                         break;
 964                 case V4L2_TUNER_MODE_STEREO:
 965                         ctl = EN_FMRADIO_AUTO_STEREO;
 966                         mask = 0x3f;
 967                         break;
 968                 }
 969                 break;
 970         case WW_I2SADC:
 971         case WW_NONE:
 972         case WW_EIAJ:
 973         case WW_I2SPT:
 974                 /* DO NOTHING */
 975                 break;
 976         }
 977 
 978         if (ctl != UNSET) {
 979                 dprintk("cx88_set_stereo: mask 0x%x, ctl 0x%x [status=0x%x,ctl=0x%x,vol=0x%x]\n",
 980                         mask, ctl, cx_read(AUD_STATUS),
 981                         cx_read(AUD_CTL), cx_sread(SHADOW_AUD_VOL_CTL));
 982                 cx_andor(AUD_CTL, mask, ctl);
 983         }
 984 }
 985 EXPORT_SYMBOL(cx88_set_stereo);
 986 
 987 int cx88_audio_thread(void *data)
 988 {
 989         struct cx88_core *core = data;
 990         struct v4l2_tuner t;
 991         u32 mode = 0;
 992 
 993         dprintk("cx88: tvaudio thread started\n");
 994         set_freezable();
 995         for (;;) {
 996                 msleep_interruptible(1000);
 997                 if (kthread_should_stop())
 998                         break;
 999                 try_to_freeze();
1000 
1001                 switch (core->tvaudio) {
1002                 case WW_BG:
1003                 case WW_DK:
1004                 case WW_M:
1005                 case WW_I:
1006                 case WW_L:
1007                         if (core->use_nicam)
1008                                 goto hw_autodetect;
1009 
1010                         /* just monitor the audio status for now ... */
1011                         memset(&t, 0, sizeof(t));
1012                         cx88_get_stereo(core, &t);
1013 
1014                         if (core->audiomode_manual != UNSET)
1015                                 /* manually set, don't do anything. */
1016                                 continue;
1017 
1018                         /* monitor signal and set stereo if available */
1019                         if (t.rxsubchans & V4L2_TUNER_SUB_STEREO)
1020                                 mode = V4L2_TUNER_MODE_STEREO;
1021                         else
1022                                 mode = V4L2_TUNER_MODE_MONO;
1023                         if (mode == core->audiomode_current)
1024                                 continue;
1025                         /* automatically switch to best available mode */
1026                         cx88_set_stereo(core, mode, 0);
1027                         break;
1028                 case WW_NONE:
1029                 case WW_BTSC:
1030                 case WW_EIAJ:
1031                 case WW_I2SPT:
1032                 case WW_FM:
1033                 case WW_I2SADC:
1034 hw_autodetect:
1035                         /*
1036                          * stereo autodetection is supported by hardware so
1037                          * we don't need to do it manually. Do nothing.
1038                          */
1039                         break;
1040                 }
1041         }
1042 
1043         dprintk("cx88: tvaudio thread exiting\n");
1044         return 0;
1045 }
1046 EXPORT_SYMBOL(cx88_audio_thread);

/* [<][>][^][v][top][bottom][index][help] */