linux/drivers/media/i2c/cx25840/cx25840-audio.c
<<
>>
Prefs
   1/* cx25840 audio functions
   2 *
   3 * This program is free software; you can redistribute it and/or
   4 * modify it under the terms of the GNU General Public License
   5 * as published by the Free Software Foundation; either version 2
   6 * of the License, or (at your option) any later version.
   7 *
   8 * This program is distributed in the hope that it will be useful,
   9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  11 * GNU General Public License for more details.
  12 *
  13 * You should have received a copy of the GNU General Public License
  14 * along with this program; if not, write to the Free Software
  15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  16 */
  17
  18
  19#include <linux/videodev2.h>
  20#include <linux/i2c.h>
  21#include <media/v4l2-common.h>
  22#include <media/cx25840.h>
  23
  24#include "cx25840-core.h"
  25
  26/*
  27 * Note: The PLL and SRC parameters are based on a reference frequency that
  28 * would ideally be:
  29 *
  30 * NTSC Color subcarrier freq * 8 = 4.5 MHz/286 * 455/2 * 8 = 28.63636363... MHz
  31 *
  32 * However, it's not the exact reference frequency that matters, only that the
  33 * firmware and modules that comprise the driver for a particular board all
  34 * use the same value (close to the ideal value).
  35 *
  36 * Comments below will note which reference frequency is assumed for various
  37 * parameters.  They will usually be one of
  38 *
  39 *      ref_freq = 28.636360 MHz
  40 *              or
  41 *      ref_freq = 28.636363 MHz
  42 */
  43
  44static int cx25840_set_audclk_freq(struct i2c_client *client, u32 freq)
  45{
  46        struct cx25840_state *state = to_state(i2c_get_clientdata(client));
  47
  48        if (state->aud_input != CX25840_AUDIO_SERIAL) {
  49                switch (freq) {
  50                case 32000:
  51                        /*
  52                         * VID_PLL Integer = 0x0f, VID_PLL Post Divider = 0x04
  53                         * AUX_PLL Integer = 0x06, AUX PLL Post Divider = 0x10
  54                         */
  55                        cx25840_write4(client, 0x108, 0x1006040f);
  56
  57                        /*
  58                         * VID_PLL Fraction (register 0x10c) = 0x2be2fe
  59                         * 28636360 * 0xf.15f17f0/4 = 108 MHz
  60                         * 432 MHz pre-postdivide
  61                         */
  62
  63                        /*
  64                         * AUX_PLL Fraction = 0x1bb39ee
  65                         * 28636363 * 0x6.dd9cf70/0x10 = 32000 * 384
  66                         * 196.6 MHz pre-postdivide
  67                         * FIXME < 200 MHz is out of specified valid range
  68                         * FIXME 28636363 ref_freq doesn't match VID PLL ref
  69                         */
  70                        cx25840_write4(client, 0x110, 0x01bb39ee);
  71
  72                        /*
  73                         * SA_MCLK_SEL = 1
  74                         * SA_MCLK_DIV = 0x10 = 384/384 * AUX_PLL post dvivider
  75                         */
  76                        cx25840_write(client, 0x127, 0x50);
  77
  78                        if (is_cx2583x(state))
  79                                break;
  80
  81                        /* src3/4/6_ctl */
  82                        /* 0x1.f77f = (4 * 28636360/8 * 2/455) / 32000 */
  83                        cx25840_write4(client, 0x900, 0x0801f77f);
  84                        cx25840_write4(client, 0x904, 0x0801f77f);
  85                        cx25840_write4(client, 0x90c, 0x0801f77f);
  86                        break;
  87
  88                case 44100:
  89                        /*
  90                         * VID_PLL Integer = 0x0f, VID_PLL Post Divider = 0x04
  91                         * AUX_PLL Integer = 0x09, AUX PLL Post Divider = 0x10
  92                         */
  93                        cx25840_write4(client, 0x108, 0x1009040f);
  94
  95                        /*
  96                         * VID_PLL Fraction (register 0x10c) = 0x2be2fe
  97                         * 28636360 * 0xf.15f17f0/4 = 108 MHz
  98                         * 432 MHz pre-postdivide
  99                         */
 100
 101                        /*
 102                         * AUX_PLL Fraction = 0x0ec6bd6
 103                         * 28636363 * 0x9.7635eb0/0x10 = 44100 * 384
 104                         * 271 MHz pre-postdivide
 105                         * FIXME 28636363 ref_freq doesn't match VID PLL ref
 106                         */
 107                        cx25840_write4(client, 0x110, 0x00ec6bd6);
 108
 109                        /*
 110                         * SA_MCLK_SEL = 1
 111                         * SA_MCLK_DIV = 0x10 = 384/384 * AUX_PLL post dvivider
 112                         */
 113                        cx25840_write(client, 0x127, 0x50);
 114
 115                        if (is_cx2583x(state))
 116                                break;
 117
 118                        /* src3/4/6_ctl */
 119                        /* 0x1.6d59 = (4 * 28636360/8 * 2/455) / 44100 */
 120                        cx25840_write4(client, 0x900, 0x08016d59);
 121                        cx25840_write4(client, 0x904, 0x08016d59);
 122                        cx25840_write4(client, 0x90c, 0x08016d59);
 123                        break;
 124
 125                case 48000:
 126                        /*
 127                         * VID_PLL Integer = 0x0f, VID_PLL Post Divider = 0x04
 128                         * AUX_PLL Integer = 0x0a, AUX PLL Post Divider = 0x10
 129                         */
 130                        cx25840_write4(client, 0x108, 0x100a040f);
 131
 132                        /*
 133                         * VID_PLL Fraction (register 0x10c) = 0x2be2fe
 134                         * 28636360 * 0xf.15f17f0/4 = 108 MHz
 135                         * 432 MHz pre-postdivide
 136                         */
 137
 138                        /*
 139                         * AUX_PLL Fraction = 0x098d6e5
 140                         * 28636363 * 0xa.4c6b728/0x10 = 48000 * 384
 141                         * 295 MHz pre-postdivide
 142                         * FIXME 28636363 ref_freq doesn't match VID PLL ref
 143                         */
 144                        cx25840_write4(client, 0x110, 0x0098d6e5);
 145
 146                        /*
 147                         * SA_MCLK_SEL = 1
 148                         * SA_MCLK_DIV = 0x10 = 384/384 * AUX_PLL post dvivider
 149                         */
 150                        cx25840_write(client, 0x127, 0x50);
 151
 152                        if (is_cx2583x(state))
 153                                break;
 154
 155                        /* src3/4/6_ctl */
 156                        /* 0x1.4faa = (4 * 28636360/8 * 2/455) / 48000 */
 157                        cx25840_write4(client, 0x900, 0x08014faa);
 158                        cx25840_write4(client, 0x904, 0x08014faa);
 159                        cx25840_write4(client, 0x90c, 0x08014faa);
 160                        break;
 161                }
 162        } else {
 163                switch (freq) {
 164                case 32000:
 165                        /*
 166                         * VID_PLL Integer = 0x0f, VID_PLL Post Divider = 0x04
 167                         * AUX_PLL Integer = 0x08, AUX PLL Post Divider = 0x1e
 168                         */
 169                        cx25840_write4(client, 0x108, 0x1e08040f);
 170
 171                        /*
 172                         * VID_PLL Fraction (register 0x10c) = 0x2be2fe
 173                         * 28636360 * 0xf.15f17f0/4 = 108 MHz
 174                         * 432 MHz pre-postdivide
 175                         */
 176
 177                        /*
 178                         * AUX_PLL Fraction = 0x12a0869
 179                         * 28636363 * 0x8.9504348/0x1e = 32000 * 256
 180                         * 246 MHz pre-postdivide
 181                         * FIXME 28636363 ref_freq doesn't match VID PLL ref
 182                         */
 183                        cx25840_write4(client, 0x110, 0x012a0869);
 184
 185                        /*
 186                         * SA_MCLK_SEL = 1
 187                         * SA_MCLK_DIV = 0x14 = 256/384 * AUX_PLL post dvivider
 188                         */
 189                        cx25840_write(client, 0x127, 0x54);
 190
 191                        if (is_cx2583x(state))
 192                                break;
 193
 194                        /* src1_ctl */
 195                        /* 0x1.0000 = 32000/32000 */
 196                        cx25840_write4(client, 0x8f8, 0x08010000);
 197
 198                        /* src3/4/6_ctl */
 199                        /* 0x2.0000 = 2 * (32000/32000) */
 200                        cx25840_write4(client, 0x900, 0x08020000);
 201                        cx25840_write4(client, 0x904, 0x08020000);
 202                        cx25840_write4(client, 0x90c, 0x08020000);
 203                        break;
 204
 205                case 44100:
 206                        /*
 207                         * VID_PLL Integer = 0x0f, VID_PLL Post Divider = 0x04
 208                         * AUX_PLL Integer = 0x09, AUX PLL Post Divider = 0x18
 209                         */
 210                        cx25840_write4(client, 0x108, 0x1809040f);
 211
 212                        /*
 213                         * VID_PLL Fraction (register 0x10c) = 0x2be2fe
 214                         * 28636360 * 0xf.15f17f0/4 = 108 MHz
 215                         * 432 MHz pre-postdivide
 216                         */
 217
 218                        /*
 219                         * AUX_PLL Fraction = 0x0ec6bd6
 220                         * 28636363 * 0x9.7635eb0/0x18 = 44100 * 256
 221                         * 271 MHz pre-postdivide
 222                         * FIXME 28636363 ref_freq doesn't match VID PLL ref
 223                         */
 224                        cx25840_write4(client, 0x110, 0x00ec6bd6);
 225
 226                        /*
 227                         * SA_MCLK_SEL = 1
 228                         * SA_MCLK_DIV = 0x10 = 256/384 * AUX_PLL post dvivider
 229                         */
 230                        cx25840_write(client, 0x127, 0x50);
 231
 232                        if (is_cx2583x(state))
 233                                break;
 234
 235                        /* src1_ctl */
 236                        /* 0x1.60cd = 44100/32000 */
 237                        cx25840_write4(client, 0x8f8, 0x080160cd);
 238
 239                        /* src3/4/6_ctl */
 240                        /* 0x1.7385 = 2 * (32000/44100) */
 241                        cx25840_write4(client, 0x900, 0x08017385);
 242                        cx25840_write4(client, 0x904, 0x08017385);
 243                        cx25840_write4(client, 0x90c, 0x08017385);
 244                        break;
 245
 246                case 48000:
 247                        /*
 248                         * VID_PLL Integer = 0x0f, VID_PLL Post Divider = 0x04
 249                         * AUX_PLL Integer = 0x0a, AUX PLL Post Divider = 0x18
 250                         */
 251                        cx25840_write4(client, 0x108, 0x180a040f);
 252
 253                        /*
 254                         * VID_PLL Fraction (register 0x10c) = 0x2be2fe
 255                         * 28636360 * 0xf.15f17f0/4 = 108 MHz
 256                         * 432 MHz pre-postdivide
 257                         */
 258
 259                        /*
 260                         * AUX_PLL Fraction = 0x098d6e5
 261                         * 28636363 * 0xa.4c6b728/0x18 = 48000 * 256
 262                         * 295 MHz pre-postdivide
 263                         * FIXME 28636363 ref_freq doesn't match VID PLL ref
 264                         */
 265                        cx25840_write4(client, 0x110, 0x0098d6e5);
 266
 267                        /*
 268                         * SA_MCLK_SEL = 1
 269                         * SA_MCLK_DIV = 0x10 = 256/384 * AUX_PLL post dvivider
 270                         */
 271                        cx25840_write(client, 0x127, 0x50);
 272
 273                        if (is_cx2583x(state))
 274                                break;
 275
 276                        /* src1_ctl */
 277                        /* 0x1.8000 = 48000/32000 */
 278                        cx25840_write4(client, 0x8f8, 0x08018000);
 279
 280                        /* src3/4/6_ctl */
 281                        /* 0x1.5555 = 2 * (32000/48000) */
 282                        cx25840_write4(client, 0x900, 0x08015555);
 283                        cx25840_write4(client, 0x904, 0x08015555);
 284                        cx25840_write4(client, 0x90c, 0x08015555);
 285                        break;
 286                }
 287        }
 288
 289        state->audclk_freq = freq;
 290
 291        return 0;
 292}
 293
 294static inline int cx25836_set_audclk_freq(struct i2c_client *client, u32 freq)
 295{
 296        return cx25840_set_audclk_freq(client, freq);
 297}
 298
 299static int cx23885_set_audclk_freq(struct i2c_client *client, u32 freq)
 300{
 301        struct cx25840_state *state = to_state(i2c_get_clientdata(client));
 302
 303        if (state->aud_input != CX25840_AUDIO_SERIAL) {
 304                switch (freq) {
 305                case 32000:
 306                case 44100:
 307                case 48000:
 308                        /* We don't have register values
 309                         * so avoid destroying registers. */
 310                        /* FIXME return -EINVAL; */
 311                        break;
 312                }
 313        } else {
 314                switch (freq) {
 315                case 32000:
 316                case 44100:
 317                        /* We don't have register values
 318                         * so avoid destroying registers. */
 319                        /* FIXME return -EINVAL; */
 320                        break;
 321
 322                case 48000:
 323                        /* src1_ctl */
 324                        /* 0x1.867c = 48000 / (2 * 28636360/8 * 2/455) */
 325                        cx25840_write4(client, 0x8f8, 0x0801867c);
 326
 327                        /* src3/4/6_ctl */
 328                        /* 0x1.4faa = (4 * 28636360/8 * 2/455) / 48000 */
 329                        cx25840_write4(client, 0x900, 0x08014faa);
 330                        cx25840_write4(client, 0x904, 0x08014faa);
 331                        cx25840_write4(client, 0x90c, 0x08014faa);
 332                        break;
 333                }
 334        }
 335
 336        state->audclk_freq = freq;
 337
 338        return 0;
 339}
 340
 341static int cx231xx_set_audclk_freq(struct i2c_client *client, u32 freq)
 342{
 343        struct cx25840_state *state = to_state(i2c_get_clientdata(client));
 344
 345        if (state->aud_input != CX25840_AUDIO_SERIAL) {
 346                switch (freq) {
 347                case 32000:
 348                        /* src3/4/6_ctl */
 349                        /* 0x1.f77f = (4 * 28636360/8 * 2/455) / 32000 */
 350                        cx25840_write4(client, 0x900, 0x0801f77f);
 351                        cx25840_write4(client, 0x904, 0x0801f77f);
 352                        cx25840_write4(client, 0x90c, 0x0801f77f);
 353                        break;
 354
 355                case 44100:
 356                        /* src3/4/6_ctl */
 357                        /* 0x1.6d59 = (4 * 28636360/8 * 2/455) / 44100 */
 358                        cx25840_write4(client, 0x900, 0x08016d59);
 359                        cx25840_write4(client, 0x904, 0x08016d59);
 360                        cx25840_write4(client, 0x90c, 0x08016d59);
 361                        break;
 362
 363                case 48000:
 364                        /* src3/4/6_ctl */
 365                        /* 0x1.4faa = (4 * 28636360/8 * 2/455) / 48000 */
 366                        cx25840_write4(client, 0x900, 0x08014faa);
 367                        cx25840_write4(client, 0x904, 0x08014faa);
 368                        cx25840_write4(client, 0x90c, 0x08014faa);
 369                        break;
 370                }
 371        } else {
 372                switch (freq) {
 373                /* FIXME These cases make different assumptions about audclk */
 374                case 32000:
 375                        /* src1_ctl */
 376                        /* 0x1.0000 = 32000/32000 */
 377                        cx25840_write4(client, 0x8f8, 0x08010000);
 378
 379                        /* src3/4/6_ctl */
 380                        /* 0x2.0000 = 2 * (32000/32000) */
 381                        cx25840_write4(client, 0x900, 0x08020000);
 382                        cx25840_write4(client, 0x904, 0x08020000);
 383                        cx25840_write4(client, 0x90c, 0x08020000);
 384                        break;
 385
 386                case 44100:
 387                        /* src1_ctl */
 388                        /* 0x1.60cd = 44100/32000 */
 389                        cx25840_write4(client, 0x8f8, 0x080160cd);
 390
 391                        /* src3/4/6_ctl */
 392                        /* 0x1.7385 = 2 * (32000/44100) */
 393                        cx25840_write4(client, 0x900, 0x08017385);
 394                        cx25840_write4(client, 0x904, 0x08017385);
 395                        cx25840_write4(client, 0x90c, 0x08017385);
 396                        break;
 397
 398                case 48000:
 399                        /* src1_ctl */
 400                        /* 0x1.867c = 48000 / (2 * 28636360/8 * 2/455) */
 401                        cx25840_write4(client, 0x8f8, 0x0801867c);
 402
 403                        /* src3/4/6_ctl */
 404                        /* 0x1.4faa = (4 * 28636360/8 * 2/455) / 48000 */
 405                        cx25840_write4(client, 0x900, 0x08014faa);
 406                        cx25840_write4(client, 0x904, 0x08014faa);
 407                        cx25840_write4(client, 0x90c, 0x08014faa);
 408                        break;
 409                }
 410        }
 411
 412        state->audclk_freq = freq;
 413
 414        return 0;
 415}
 416
 417static int set_audclk_freq(struct i2c_client *client, u32 freq)
 418{
 419        struct cx25840_state *state = to_state(i2c_get_clientdata(client));
 420
 421        if (freq != 32000 && freq != 44100 && freq != 48000)
 422                return -EINVAL;
 423
 424        if (is_cx231xx(state))
 425                return cx231xx_set_audclk_freq(client, freq);
 426
 427        if (is_cx2388x(state))
 428                return cx23885_set_audclk_freq(client, freq);
 429
 430        if (is_cx2583x(state))
 431                return cx25836_set_audclk_freq(client, freq);
 432
 433        return cx25840_set_audclk_freq(client, freq);
 434}
 435
 436void cx25840_audio_set_path(struct i2c_client *client)
 437{
 438        struct cx25840_state *state = to_state(i2c_get_clientdata(client));
 439
 440        if (!is_cx2583x(state)) {
 441                /* assert soft reset */
 442                cx25840_and_or(client, 0x810, ~0x1, 0x01);
 443
 444                /* stop microcontroller */
 445                cx25840_and_or(client, 0x803, ~0x10, 0);
 446
 447                /* Mute everything to prevent the PFFT! */
 448                cx25840_write(client, 0x8d3, 0x1f);
 449
 450                if (state->aud_input == CX25840_AUDIO_SERIAL) {
 451                        /* Set Path1 to Serial Audio Input */
 452                        cx25840_write4(client, 0x8d0, 0x01011012);
 453
 454                        /* The microcontroller should not be started for the
 455                         * non-tuner inputs: autodetection is specific for
 456                         * TV audio. */
 457                } else {
 458                        /* Set Path1 to Analog Demod Main Channel */
 459                        cx25840_write4(client, 0x8d0, 0x1f063870);
 460                }
 461        }
 462
 463        set_audclk_freq(client, state->audclk_freq);
 464
 465        if (!is_cx2583x(state)) {
 466                if (state->aud_input != CX25840_AUDIO_SERIAL) {
 467                        /* When the microcontroller detects the
 468                         * audio format, it will unmute the lines */
 469                        cx25840_and_or(client, 0x803, ~0x10, 0x10);
 470                }
 471
 472                /* deassert soft reset */
 473                cx25840_and_or(client, 0x810, ~0x1, 0x00);
 474
 475                /* Ensure the controller is running when we exit */
 476                if (is_cx2388x(state) || is_cx231xx(state))
 477                        cx25840_and_or(client, 0x803, ~0x10, 0x10);
 478        }
 479}
 480
 481static void set_volume(struct i2c_client *client, int volume)
 482{
 483        int vol;
 484
 485        /* Convert the volume to msp3400 values (0-127) */
 486        vol = volume >> 9;
 487
 488        /* now scale it up to cx25840 values
 489         * -114dB to -96dB maps to 0
 490         * this should be 19, but in my testing that was 4dB too loud */
 491        if (vol <= 23) {
 492                vol = 0;
 493        } else {
 494                vol -= 23;
 495        }
 496
 497        /* PATH1_VOLUME */
 498        cx25840_write(client, 0x8d4, 228 - (vol * 2));
 499}
 500
 501static void set_balance(struct i2c_client *client, int balance)
 502{
 503        int bal = balance >> 8;
 504        if (bal > 0x80) {
 505                /* PATH1_BAL_LEFT */
 506                cx25840_and_or(client, 0x8d5, 0x7f, 0x80);
 507                /* PATH1_BAL_LEVEL */
 508                cx25840_and_or(client, 0x8d5, ~0x7f, bal & 0x7f);
 509        } else {
 510                /* PATH1_BAL_LEFT */
 511                cx25840_and_or(client, 0x8d5, 0x7f, 0x00);
 512                /* PATH1_BAL_LEVEL */
 513                cx25840_and_or(client, 0x8d5, ~0x7f, 0x80 - bal);
 514        }
 515}
 516
 517int cx25840_s_clock_freq(struct v4l2_subdev *sd, u32 freq)
 518{
 519        struct i2c_client *client = v4l2_get_subdevdata(sd);
 520        struct cx25840_state *state = to_state(sd);
 521        int retval;
 522
 523        if (!is_cx2583x(state))
 524                cx25840_and_or(client, 0x810, ~0x1, 1);
 525        if (state->aud_input != CX25840_AUDIO_SERIAL) {
 526                cx25840_and_or(client, 0x803, ~0x10, 0);
 527                cx25840_write(client, 0x8d3, 0x1f);
 528        }
 529        retval = set_audclk_freq(client, freq);
 530        if (state->aud_input != CX25840_AUDIO_SERIAL)
 531                cx25840_and_or(client, 0x803, ~0x10, 0x10);
 532        if (!is_cx2583x(state))
 533                cx25840_and_or(client, 0x810, ~0x1, 0);
 534        return retval;
 535}
 536
 537static int cx25840_audio_s_ctrl(struct v4l2_ctrl *ctrl)
 538{
 539        struct v4l2_subdev *sd = to_sd(ctrl);
 540        struct cx25840_state *state = to_state(sd);
 541        struct i2c_client *client = v4l2_get_subdevdata(sd);
 542
 543        switch (ctrl->id) {
 544        case V4L2_CID_AUDIO_VOLUME:
 545                if (state->mute->val)
 546                        set_volume(client, 0);
 547                else
 548                        set_volume(client, state->volume->val);
 549                break;
 550        case V4L2_CID_AUDIO_BASS:
 551                /* PATH1_EQ_BASS_VOL */
 552                cx25840_and_or(client, 0x8d9, ~0x3f,
 553                                        48 - (ctrl->val * 48 / 0xffff));
 554                break;
 555        case V4L2_CID_AUDIO_TREBLE:
 556                /* PATH1_EQ_TREBLE_VOL */
 557                cx25840_and_or(client, 0x8db, ~0x3f,
 558                                        48 - (ctrl->val * 48 / 0xffff));
 559                break;
 560        case V4L2_CID_AUDIO_BALANCE:
 561                set_balance(client, ctrl->val);
 562                break;
 563        default:
 564                return -EINVAL;
 565        }
 566        return 0;
 567}
 568
 569const struct v4l2_ctrl_ops cx25840_audio_ctrl_ops = {
 570        .s_ctrl = cx25840_audio_s_ctrl,
 571};
 572