linux/drivers/media/video/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        /* assert soft reset */
 441        cx25840_and_or(client, 0x810, ~0x1, 0x01);
 442
 443        /* stop microcontroller */
 444        cx25840_and_or(client, 0x803, ~0x10, 0);
 445
 446        /* Mute everything to prevent the PFFT! */
 447        cx25840_write(client, 0x8d3, 0x1f);
 448
 449        if (state->aud_input == CX25840_AUDIO_SERIAL) {
 450                /* Set Path1 to Serial Audio Input */
 451                cx25840_write4(client, 0x8d0, 0x01011012);
 452
 453                /* The microcontroller should not be started for the
 454                 * non-tuner inputs: autodetection is specific for
 455                 * TV audio. */
 456        } else {
 457                /* Set Path1 to Analog Demod Main Channel */
 458                cx25840_write4(client, 0x8d0, 0x1f063870);
 459        }
 460
 461        set_audclk_freq(client, state->audclk_freq);
 462
 463        if (state->aud_input != CX25840_AUDIO_SERIAL) {
 464                /* When the microcontroller detects the
 465                 * audio format, it will unmute the lines */
 466                cx25840_and_or(client, 0x803, ~0x10, 0x10);
 467        }
 468
 469        /* deassert soft reset */
 470        cx25840_and_or(client, 0x810, ~0x1, 0x00);
 471
 472        /* Ensure the controller is running when we exit */
 473        if (is_cx2388x(state) || is_cx231xx(state))
 474                cx25840_and_or(client, 0x803, ~0x10, 0x10);
 475}
 476
 477static int get_volume(struct i2c_client *client)
 478{
 479        struct cx25840_state *state = to_state(i2c_get_clientdata(client));
 480        int vol;
 481
 482        if (state->unmute_volume >= 0)
 483                return state->unmute_volume;
 484
 485        /* Volume runs +18dB to -96dB in 1/2dB steps
 486         * change to fit the msp3400 -114dB to +12dB range */
 487
 488        /* check PATH1_VOLUME */
 489        vol = 228 - cx25840_read(client, 0x8d4);
 490        vol = (vol / 2) + 23;
 491        return vol << 9;
 492}
 493
 494static void set_volume(struct i2c_client *client, int volume)
 495{
 496        struct cx25840_state *state = to_state(i2c_get_clientdata(client));
 497        int vol;
 498
 499        if (state->unmute_volume >= 0) {
 500                state->unmute_volume = volume;
 501                return;
 502        }
 503
 504        /* Convert the volume to msp3400 values (0-127) */
 505        vol = volume >> 9;
 506
 507        /* now scale it up to cx25840 values
 508         * -114dB to -96dB maps to 0
 509         * this should be 19, but in my testing that was 4dB too loud */
 510        if (vol <= 23) {
 511                vol = 0;
 512        } else {
 513                vol -= 23;
 514        }
 515
 516        /* PATH1_VOLUME */
 517        cx25840_write(client, 0x8d4, 228 - (vol * 2));
 518}
 519
 520static int get_bass(struct i2c_client *client)
 521{
 522        /* bass is 49 steps +12dB to -12dB */
 523
 524        /* check PATH1_EQ_BASS_VOL */
 525        int bass = cx25840_read(client, 0x8d9) & 0x3f;
 526        bass = (((48 - bass) * 0xffff) + 47) / 48;
 527        return bass;
 528}
 529
 530static void set_bass(struct i2c_client *client, int bass)
 531{
 532        /* PATH1_EQ_BASS_VOL */
 533        cx25840_and_or(client, 0x8d9, ~0x3f, 48 - (bass * 48 / 0xffff));
 534}
 535
 536static int get_treble(struct i2c_client *client)
 537{
 538        /* treble is 49 steps +12dB to -12dB */
 539
 540        /* check PATH1_EQ_TREBLE_VOL */
 541        int treble = cx25840_read(client, 0x8db) & 0x3f;
 542        treble = (((48 - treble) * 0xffff) + 47) / 48;
 543        return treble;
 544}
 545
 546static void set_treble(struct i2c_client *client, int treble)
 547{
 548        /* PATH1_EQ_TREBLE_VOL */
 549        cx25840_and_or(client, 0x8db, ~0x3f, 48 - (treble * 48 / 0xffff));
 550}
 551
 552static int get_balance(struct i2c_client *client)
 553{
 554        /* balance is 7 bit, 0 to -96dB */
 555
 556        /* check PATH1_BAL_LEVEL */
 557        int balance = cx25840_read(client, 0x8d5) & 0x7f;
 558        /* check PATH1_BAL_LEFT */
 559        if ((cx25840_read(client, 0x8d5) & 0x80) == 0)
 560                balance = 0x80 - balance;
 561        else
 562                balance = 0x80 + balance;
 563        return balance << 8;
 564}
 565
 566static void set_balance(struct i2c_client *client, int balance)
 567{
 568        int bal = balance >> 8;
 569        if (bal > 0x80) {
 570                /* PATH1_BAL_LEFT */
 571                cx25840_and_or(client, 0x8d5, 0x7f, 0x80);
 572                /* PATH1_BAL_LEVEL */
 573                cx25840_and_or(client, 0x8d5, ~0x7f, bal & 0x7f);
 574        } else {
 575                /* PATH1_BAL_LEFT */
 576                cx25840_and_or(client, 0x8d5, 0x7f, 0x00);
 577                /* PATH1_BAL_LEVEL */
 578                cx25840_and_or(client, 0x8d5, ~0x7f, 0x80 - bal);
 579        }
 580}
 581
 582static int get_mute(struct i2c_client *client)
 583{
 584        struct cx25840_state *state = to_state(i2c_get_clientdata(client));
 585
 586        return state->unmute_volume >= 0;
 587}
 588
 589static void set_mute(struct i2c_client *client, int mute)
 590{
 591        struct cx25840_state *state = to_state(i2c_get_clientdata(client));
 592
 593        if (mute && state->unmute_volume == -1) {
 594                int vol = get_volume(client);
 595
 596                set_volume(client, 0);
 597                state->unmute_volume = vol;
 598        }
 599        else if (!mute && state->unmute_volume != -1) {
 600                int vol = state->unmute_volume;
 601
 602                state->unmute_volume = -1;
 603                set_volume(client, vol);
 604        }
 605}
 606
 607int cx25840_s_clock_freq(struct v4l2_subdev *sd, u32 freq)
 608{
 609        struct i2c_client *client = v4l2_get_subdevdata(sd);
 610        struct cx25840_state *state = to_state(sd);
 611        int retval;
 612
 613        if (!is_cx2583x(state))
 614                cx25840_and_or(client, 0x810, ~0x1, 1);
 615        if (state->aud_input != CX25840_AUDIO_SERIAL) {
 616                cx25840_and_or(client, 0x803, ~0x10, 0);
 617                cx25840_write(client, 0x8d3, 0x1f);
 618        }
 619        retval = set_audclk_freq(client, freq);
 620        if (state->aud_input != CX25840_AUDIO_SERIAL)
 621                cx25840_and_or(client, 0x803, ~0x10, 0x10);
 622        if (!is_cx2583x(state))
 623                cx25840_and_or(client, 0x810, ~0x1, 0);
 624        return retval;
 625}
 626
 627int cx25840_audio_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
 628{
 629        struct i2c_client *client = v4l2_get_subdevdata(sd);
 630
 631        switch (ctrl->id) {
 632        case V4L2_CID_AUDIO_VOLUME:
 633                ctrl->value = get_volume(client);
 634                break;
 635        case V4L2_CID_AUDIO_BASS:
 636                ctrl->value = get_bass(client);
 637                break;
 638        case V4L2_CID_AUDIO_TREBLE:
 639                ctrl->value = get_treble(client);
 640                break;
 641        case V4L2_CID_AUDIO_BALANCE:
 642                ctrl->value = get_balance(client);
 643                break;
 644        case V4L2_CID_AUDIO_MUTE:
 645                ctrl->value = get_mute(client);
 646                break;
 647        default:
 648                return -EINVAL;
 649        }
 650        return 0;
 651}
 652
 653int cx25840_audio_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
 654{
 655        struct i2c_client *client = v4l2_get_subdevdata(sd);
 656
 657        switch (ctrl->id) {
 658        case V4L2_CID_AUDIO_VOLUME:
 659                set_volume(client, ctrl->value);
 660                break;
 661        case V4L2_CID_AUDIO_BASS:
 662                set_bass(client, ctrl->value);
 663                break;
 664        case V4L2_CID_AUDIO_TREBLE:
 665                set_treble(client, ctrl->value);
 666                break;
 667        case V4L2_CID_AUDIO_BALANCE:
 668                set_balance(client, ctrl->value);
 669                break;
 670        case V4L2_CID_AUDIO_MUTE:
 671                set_mute(client, ctrl->value);
 672                break;
 673        default:
 674                return -EINVAL;
 675        }
 676        return 0;
 677}
 678