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