diff options
| author | Hans Verkuil <hverkuil@xs4all.nl> | 2010-05-24 09:01:58 -0400 |
|---|---|---|
| committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2010-08-08 22:43:04 -0400 |
| commit | ebc3bba5833e7021336f09767347a52448a60bc5 (patch) | |
| tree | 02639770015eadf32693d6888ebfe29316df7e8d | |
| parent | e356054337fe42a1b98725c8e68d6599764888b9 (diff) | |
V4L/DVB: msp3400: convert to the new control framework
Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
| -rw-r--r-- | drivers/media/video/msp3400-driver.c | 248 | ||||
| -rw-r--r-- | drivers/media/video/msp3400-driver.h | 18 | ||||
| -rw-r--r-- | drivers/media/video/msp3400-kthreads.c | 16 |
3 files changed, 110 insertions, 172 deletions
diff --git a/drivers/media/video/msp3400-driver.c b/drivers/media/video/msp3400-driver.c index e9df3cb02cc1..0e412131da7c 100644 --- a/drivers/media/video/msp3400-driver.c +++ b/drivers/media/video/msp3400-driver.c | |||
| @@ -283,51 +283,6 @@ void msp_set_scart(struct i2c_client *client, int in, int out) | |||
| 283 | msp_write_dem(client, 0x40, state->i2s_mode); | 283 | msp_write_dem(client, 0x40, state->i2s_mode); |
| 284 | } | 284 | } |
| 285 | 285 | ||
| 286 | void msp_set_audio(struct i2c_client *client) | ||
| 287 | { | ||
| 288 | struct msp_state *state = to_state(i2c_get_clientdata(client)); | ||
| 289 | int bal = 0, bass, treble, loudness; | ||
| 290 | int val = 0; | ||
| 291 | int reallymuted = state->muted | state->scan_in_progress; | ||
| 292 | |||
| 293 | if (!reallymuted) | ||
| 294 | val = (state->volume * 0x7f / 65535) << 8; | ||
| 295 | |||
| 296 | v4l_dbg(1, msp_debug, client, "mute=%s scanning=%s volume=%d\n", | ||
| 297 | state->muted ? "on" : "off", | ||
| 298 | state->scan_in_progress ? "yes" : "no", | ||
| 299 | state->volume); | ||
| 300 | |||
| 301 | msp_write_dsp(client, 0x0000, val); | ||
| 302 | msp_write_dsp(client, 0x0007, reallymuted ? 0x1 : (val | 0x1)); | ||
| 303 | if (state->has_scart2_out_volume) | ||
| 304 | msp_write_dsp(client, 0x0040, reallymuted ? 0x1 : (val | 0x1)); | ||
| 305 | if (state->has_headphones) | ||
| 306 | msp_write_dsp(client, 0x0006, val); | ||
| 307 | if (!state->has_sound_processing) | ||
| 308 | return; | ||
| 309 | |||
| 310 | if (val) | ||
| 311 | bal = (u8)((state->balance / 256) - 128); | ||
| 312 | bass = ((state->bass - 32768) * 0x60 / 65535) << 8; | ||
| 313 | treble = ((state->treble - 32768) * 0x60 / 65535) << 8; | ||
| 314 | loudness = state->loudness ? ((5 * 4) << 8) : 0; | ||
| 315 | |||
| 316 | v4l_dbg(1, msp_debug, client, "balance=%d bass=%d treble=%d loudness=%d\n", | ||
| 317 | state->balance, state->bass, state->treble, state->loudness); | ||
| 318 | |||
| 319 | msp_write_dsp(client, 0x0001, bal << 8); | ||
| 320 | msp_write_dsp(client, 0x0002, bass); | ||
| 321 | msp_write_dsp(client, 0x0003, treble); | ||
| 322 | msp_write_dsp(client, 0x0004, loudness); | ||
| 323 | if (!state->has_headphones) | ||
| 324 | return; | ||
| 325 | msp_write_dsp(client, 0x0030, bal << 8); | ||
| 326 | msp_write_dsp(client, 0x0031, bass); | ||
| 327 | msp_write_dsp(client, 0x0032, treble); | ||
| 328 | msp_write_dsp(client, 0x0033, loudness); | ||
| 329 | } | ||
| 330 | |||
| 331 | /* ------------------------------------------------------------------------ */ | 286 | /* ------------------------------------------------------------------------ */ |
| 332 | 287 | ||
| 333 | static void msp_wake_thread(struct i2c_client *client) | 288 | static void msp_wake_thread(struct i2c_client *client) |
| @@ -363,98 +318,73 @@ int msp_sleep(struct msp_state *state, int timeout) | |||
| 363 | 318 | ||
| 364 | /* ------------------------------------------------------------------------ */ | 319 | /* ------------------------------------------------------------------------ */ |
| 365 | 320 | ||
| 366 | static int msp_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) | 321 | static int msp_s_ctrl(struct v4l2_ctrl *ctrl) |
| 367 | { | 322 | { |
| 368 | struct msp_state *state = to_state(sd); | 323 | struct msp_state *state = ctrl_to_state(ctrl); |
| 324 | struct i2c_client *client = v4l2_get_subdevdata(&state->sd); | ||
| 325 | int val = ctrl->val; | ||
| 369 | 326 | ||
| 370 | switch (ctrl->id) { | 327 | switch (ctrl->id) { |
| 371 | case V4L2_CID_AUDIO_VOLUME: | 328 | case V4L2_CID_AUDIO_VOLUME: { |
| 372 | ctrl->value = state->volume; | 329 | /* audio volume cluster */ |
| 373 | break; | 330 | int reallymuted = state->muted->val | state->scan_in_progress; |
| 374 | 331 | ||
| 375 | case V4L2_CID_AUDIO_MUTE: | 332 | if (!reallymuted) |
| 376 | ctrl->value = state->muted; | 333 | val = (val * 0x7f / 65535) << 8; |
| 377 | break; | 334 | |
| 378 | 335 | v4l_dbg(1, msp_debug, client, "mute=%s scanning=%s volume=%d\n", | |
| 379 | case V4L2_CID_AUDIO_BALANCE: | 336 | state->muted->val ? "on" : "off", |
| 380 | if (!state->has_sound_processing) | 337 | state->scan_in_progress ? "yes" : "no", |
| 381 | return -EINVAL; | 338 | state->volume->val); |
| 382 | ctrl->value = state->balance; | 339 | |
| 383 | break; | 340 | msp_write_dsp(client, 0x0000, val); |
| 384 | 341 | msp_write_dsp(client, 0x0007, reallymuted ? 0x1 : (val | 0x1)); | |
| 385 | case V4L2_CID_AUDIO_BASS: | 342 | if (state->has_scart2_out_volume) |
| 386 | if (!state->has_sound_processing) | 343 | msp_write_dsp(client, 0x0040, reallymuted ? 0x1 : (val | 0x1)); |
| 387 | return -EINVAL; | 344 | if (state->has_headphones) |
| 388 | ctrl->value = state->bass; | 345 | msp_write_dsp(client, 0x0006, val); |
| 389 | break; | 346 | break; |
| 390 | |||
| 391 | case V4L2_CID_AUDIO_TREBLE: | ||
| 392 | if (!state->has_sound_processing) | ||
| 393 | return -EINVAL; | ||
| 394 | ctrl->value = state->treble; | ||
| 395 | break; | ||
| 396 | |||
| 397 | case V4L2_CID_AUDIO_LOUDNESS: | ||
| 398 | if (!state->has_sound_processing) | ||
| 399 | return -EINVAL; | ||
| 400 | ctrl->value = state->loudness; | ||
| 401 | break; | ||
| 402 | |||
| 403 | default: | ||
| 404 | return -EINVAL; | ||
| 405 | } | 347 | } |
| 406 | return 0; | ||
| 407 | } | ||
| 408 | |||
| 409 | static int msp_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) | ||
| 410 | { | ||
| 411 | struct msp_state *state = to_state(sd); | ||
| 412 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
| 413 | |||
| 414 | switch (ctrl->id) { | ||
| 415 | case V4L2_CID_AUDIO_VOLUME: | ||
| 416 | state->volume = ctrl->value; | ||
| 417 | if (state->volume == 0) | ||
| 418 | state->balance = 32768; | ||
| 419 | break; | ||
| 420 | |||
| 421 | case V4L2_CID_AUDIO_MUTE: | ||
| 422 | if (ctrl->value < 0 || ctrl->value >= 2) | ||
| 423 | return -ERANGE; | ||
| 424 | state->muted = ctrl->value; | ||
| 425 | break; | ||
| 426 | 348 | ||
| 427 | case V4L2_CID_AUDIO_BASS: | 349 | case V4L2_CID_AUDIO_BASS: |
| 428 | if (!state->has_sound_processing) | 350 | val = ((val - 32768) * 0x60 / 65535) << 8; |
| 429 | return -EINVAL; | 351 | msp_write_dsp(client, 0x0002, val); |
| 430 | state->bass = ctrl->value; | 352 | if (state->has_headphones) |
| 353 | msp_write_dsp(client, 0x0031, val); | ||
| 431 | break; | 354 | break; |
| 432 | 355 | ||
| 433 | case V4L2_CID_AUDIO_TREBLE: | 356 | case V4L2_CID_AUDIO_TREBLE: |
| 434 | if (!state->has_sound_processing) | 357 | val = ((val - 32768) * 0x60 / 65535) << 8; |
| 435 | return -EINVAL; | 358 | msp_write_dsp(client, 0x0003, val); |
| 436 | state->treble = ctrl->value; | 359 | if (state->has_headphones) |
| 360 | msp_write_dsp(client, 0x0032, val); | ||
| 437 | break; | 361 | break; |
| 438 | 362 | ||
| 439 | case V4L2_CID_AUDIO_LOUDNESS: | 363 | case V4L2_CID_AUDIO_LOUDNESS: |
| 440 | if (!state->has_sound_processing) | 364 | val = val ? ((5 * 4) << 8) : 0; |
| 441 | return -EINVAL; | 365 | msp_write_dsp(client, 0x0004, val); |
| 442 | state->loudness = ctrl->value; | 366 | if (state->has_headphones) |
| 367 | msp_write_dsp(client, 0x0033, val); | ||
| 443 | break; | 368 | break; |
| 444 | 369 | ||
| 445 | case V4L2_CID_AUDIO_BALANCE: | 370 | case V4L2_CID_AUDIO_BALANCE: |
| 446 | if (!state->has_sound_processing) | 371 | val = (u8)((val / 256) - 128); |
| 447 | return -EINVAL; | 372 | msp_write_dsp(client, 0x0001, val << 8); |
| 448 | state->balance = ctrl->value; | 373 | if (state->has_headphones) |
| 374 | msp_write_dsp(client, 0x0030, val << 8); | ||
| 449 | break; | 375 | break; |
| 450 | 376 | ||
| 451 | default: | 377 | default: |
| 452 | return -EINVAL; | 378 | return -EINVAL; |
| 453 | } | 379 | } |
| 454 | msp_set_audio(client); | ||
| 455 | return 0; | 380 | return 0; |
| 456 | } | 381 | } |
| 457 | 382 | ||
| 383 | void msp_update_volume(struct msp_state *state) | ||
| 384 | { | ||
| 385 | v4l2_ctrl_s_ctrl(state->volume, v4l2_ctrl_g_ctrl(state->volume)); | ||
| 386 | } | ||
| 387 | |||
| 458 | /* --- v4l2 ioctls --- */ | 388 | /* --- v4l2 ioctls --- */ |
| 459 | static int msp_s_radio(struct v4l2_subdev *sd) | 389 | static int msp_s_radio(struct v4l2_subdev *sd) |
| 460 | { | 390 | { |
| @@ -472,7 +402,7 @@ static int msp_s_radio(struct v4l2_subdev *sd) | |||
| 472 | msp3400c_set_mode(client, MSP_MODE_FM_RADIO); | 402 | msp3400c_set_mode(client, MSP_MODE_FM_RADIO); |
| 473 | msp3400c_set_carrier(client, MSP_CARRIER(10.7), | 403 | msp3400c_set_carrier(client, MSP_CARRIER(10.7), |
| 474 | MSP_CARRIER(10.7)); | 404 | MSP_CARRIER(10.7)); |
| 475 | msp_set_audio(client); | 405 | msp_update_volume(state); |
| 476 | break; | 406 | break; |
| 477 | case OPMODE_AUTODETECT: | 407 | case OPMODE_AUTODETECT: |
| 478 | case OPMODE_AUTOSELECT: | 408 | case OPMODE_AUTOSELECT: |
| @@ -592,33 +522,6 @@ static int msp_s_i2s_clock_freq(struct v4l2_subdev *sd, u32 freq) | |||
| 592 | return 0; | 522 | return 0; |
| 593 | } | 523 | } |
| 594 | 524 | ||
| 595 | static int msp_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc) | ||
| 596 | { | ||
| 597 | struct msp_state *state = to_state(sd); | ||
| 598 | |||
| 599 | switch (qc->id) { | ||
| 600 | case V4L2_CID_AUDIO_VOLUME: | ||
| 601 | return v4l2_ctrl_query_fill(qc, 0, 65535, 65535 / 100, 58880); | ||
| 602 | case V4L2_CID_AUDIO_MUTE: | ||
| 603 | return v4l2_ctrl_query_fill(qc, 0, 1, 1, 0); | ||
| 604 | default: | ||
| 605 | break; | ||
| 606 | } | ||
| 607 | if (!state->has_sound_processing) | ||
| 608 | return -EINVAL; | ||
| 609 | switch (qc->id) { | ||
| 610 | case V4L2_CID_AUDIO_LOUDNESS: | ||
| 611 | return v4l2_ctrl_query_fill(qc, 0, 1, 1, 0); | ||
| 612 | case V4L2_CID_AUDIO_BALANCE: | ||
| 613 | case V4L2_CID_AUDIO_BASS: | ||
| 614 | case V4L2_CID_AUDIO_TREBLE: | ||
| 615 | return v4l2_ctrl_query_fill(qc, 0, 65535, 65535 / 100, 32768); | ||
| 616 | default: | ||
| 617 | return -EINVAL; | ||
| 618 | } | ||
| 619 | return 0; | ||
| 620 | } | ||
| 621 | |||
| 622 | static int msp_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) | 525 | static int msp_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) |
| 623 | { | 526 | { |
| 624 | struct msp_state *state = to_state(sd); | 527 | struct msp_state *state = to_state(sd); |
| @@ -633,19 +536,14 @@ static int msp_log_status(struct v4l2_subdev *sd) | |||
| 633 | struct msp_state *state = to_state(sd); | 536 | struct msp_state *state = to_state(sd); |
| 634 | struct i2c_client *client = v4l2_get_subdevdata(sd); | 537 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
| 635 | const char *p; | 538 | const char *p; |
| 539 | char prefix[V4L2_SUBDEV_NAME_SIZE + 20]; | ||
| 636 | 540 | ||
| 637 | if (state->opmode == OPMODE_AUTOSELECT) | 541 | if (state->opmode == OPMODE_AUTOSELECT) |
| 638 | msp_detect_stereo(client); | 542 | msp_detect_stereo(client); |
| 639 | v4l_info(client, "%s rev1 = 0x%04x rev2 = 0x%04x\n", | 543 | v4l_info(client, "%s rev1 = 0x%04x rev2 = 0x%04x\n", |
| 640 | client->name, state->rev1, state->rev2); | 544 | client->name, state->rev1, state->rev2); |
| 641 | v4l_info(client, "Audio: volume %d%s\n", | 545 | snprintf(prefix, sizeof(prefix), "%s: Audio: ", sd->name); |
| 642 | state->volume, state->muted ? " (muted)" : ""); | 546 | v4l2_ctrl_handler_log_status(&state->hdl, prefix); |
| 643 | if (state->has_sound_processing) { | ||
| 644 | v4l_info(client, "Audio: balance %d bass %d treble %d loudness %s\n", | ||
| 645 | state->balance, state->bass, | ||
| 646 | state->treble, | ||
| 647 | state->loudness ? "on" : "off"); | ||
| 648 | } | ||
| 649 | switch (state->mode) { | 547 | switch (state->mode) { |
| 650 | case MSP_MODE_AM_DETECT: p = "AM (for carrier detect)"; break; | 548 | case MSP_MODE_AM_DETECT: p = "AM (for carrier detect)"; break; |
| 651 | case MSP_MODE_FM_RADIO: p = "FM Radio"; break; | 549 | case MSP_MODE_FM_RADIO: p = "FM Radio"; break; |
| @@ -695,12 +593,20 @@ static int msp_resume(struct i2c_client *client) | |||
| 695 | 593 | ||
| 696 | /* ----------------------------------------------------------------------- */ | 594 | /* ----------------------------------------------------------------------- */ |
| 697 | 595 | ||
| 596 | static const struct v4l2_ctrl_ops msp_ctrl_ops = { | ||
| 597 | .s_ctrl = msp_s_ctrl, | ||
| 598 | }; | ||
| 599 | |||
| 698 | static const struct v4l2_subdev_core_ops msp_core_ops = { | 600 | static const struct v4l2_subdev_core_ops msp_core_ops = { |
| 699 | .log_status = msp_log_status, | 601 | .log_status = msp_log_status, |
| 700 | .g_chip_ident = msp_g_chip_ident, | 602 | .g_chip_ident = msp_g_chip_ident, |
| 701 | .g_ctrl = msp_g_ctrl, | 603 | .g_ext_ctrls = v4l2_subdev_g_ext_ctrls, |
| 702 | .s_ctrl = msp_s_ctrl, | 604 | .try_ext_ctrls = v4l2_subdev_try_ext_ctrls, |
| 703 | .queryctrl = msp_queryctrl, | 605 | .s_ext_ctrls = v4l2_subdev_s_ext_ctrls, |
| 606 | .g_ctrl = v4l2_subdev_g_ctrl, | ||
| 607 | .s_ctrl = v4l2_subdev_s_ctrl, | ||
| 608 | .queryctrl = v4l2_subdev_queryctrl, | ||
| 609 | .querymenu = v4l2_subdev_querymenu, | ||
| 704 | .s_std = msp_s_std, | 610 | .s_std = msp_s_std, |
| 705 | }; | 611 | }; |
| 706 | 612 | ||
| @@ -728,6 +634,7 @@ static int msp_probe(struct i2c_client *client, const struct i2c_device_id *id) | |||
| 728 | { | 634 | { |
| 729 | struct msp_state *state; | 635 | struct msp_state *state; |
| 730 | struct v4l2_subdev *sd; | 636 | struct v4l2_subdev *sd; |
| 637 | struct v4l2_ctrl_handler *hdl; | ||
| 731 | int (*thread_func)(void *data) = NULL; | 638 | int (*thread_func)(void *data) = NULL; |
| 732 | int msp_hard; | 639 | int msp_hard; |
| 733 | int msp_family; | 640 | int msp_family; |
| @@ -752,13 +659,7 @@ static int msp_probe(struct i2c_client *client, const struct i2c_device_id *id) | |||
| 752 | 659 | ||
| 753 | state->v4l2_std = V4L2_STD_NTSC; | 660 | state->v4l2_std = V4L2_STD_NTSC; |
| 754 | state->audmode = V4L2_TUNER_MODE_STEREO; | 661 | state->audmode = V4L2_TUNER_MODE_STEREO; |
| 755 | state->volume = 58880; /* 0db gain */ | ||
| 756 | state->balance = 32768; /* 0db gain */ | ||
| 757 | state->bass = 32768; | ||
| 758 | state->treble = 32768; | ||
| 759 | state->loudness = 0; | ||
| 760 | state->input = -1; | 662 | state->input = -1; |
| 761 | state->muted = 0; | ||
| 762 | state->i2s_mode = 0; | 663 | state->i2s_mode = 0; |
| 763 | init_waitqueue_head(&state->wq); | 664 | init_waitqueue_head(&state->wq); |
| 764 | /* These are the reset input/output positions */ | 665 | /* These are the reset input/output positions */ |
| @@ -777,8 +678,6 @@ static int msp_probe(struct i2c_client *client, const struct i2c_device_id *id) | |||
| 777 | return -ENODEV; | 678 | return -ENODEV; |
| 778 | } | 679 | } |
| 779 | 680 | ||
| 780 | msp_set_audio(client); | ||
| 781 | |||
| 782 | msp_family = ((state->rev1 >> 4) & 0x0f) + 3; | 681 | msp_family = ((state->rev1 >> 4) & 0x0f) + 3; |
| 783 | msp_product = (state->rev2 >> 8) & 0xff; | 682 | msp_product = (state->rev2 >> 8) & 0xff; |
| 784 | msp_prod_hi = msp_product / 10; | 683 | msp_prod_hi = msp_product / 10; |
| @@ -849,6 +748,34 @@ static int msp_probe(struct i2c_client *client, const struct i2c_device_id *id) | |||
| 849 | state->opmode = OPMODE_MANUAL; | 748 | state->opmode = OPMODE_MANUAL; |
| 850 | } | 749 | } |
| 851 | 750 | ||
| 751 | hdl = &state->hdl; | ||
| 752 | v4l2_ctrl_handler_init(hdl, 6); | ||
| 753 | if (state->has_sound_processing) { | ||
| 754 | v4l2_ctrl_new_std(hdl, &msp_ctrl_ops, | ||
| 755 | V4L2_CID_AUDIO_BASS, 0, 65535, 65535 / 100, 32768); | ||
| 756 | v4l2_ctrl_new_std(hdl, &msp_ctrl_ops, | ||
| 757 | V4L2_CID_AUDIO_TREBLE, 0, 65535, 65535 / 100, 32768); | ||
| 758 | v4l2_ctrl_new_std(hdl, &msp_ctrl_ops, | ||
| 759 | V4L2_CID_AUDIO_LOUDNESS, 0, 1, 1, 0); | ||
| 760 | } | ||
| 761 | state->volume = v4l2_ctrl_new_std(hdl, &msp_ctrl_ops, | ||
| 762 | V4L2_CID_AUDIO_VOLUME, 0, 65535, 65535 / 100, 58880); | ||
| 763 | v4l2_ctrl_new_std(hdl, &msp_ctrl_ops, | ||
| 764 | V4L2_CID_AUDIO_BALANCE, 0, 65535, 65535 / 100, 32768); | ||
| 765 | state->muted = v4l2_ctrl_new_std(hdl, &msp_ctrl_ops, | ||
| 766 | V4L2_CID_AUDIO_MUTE, 0, 1, 1, 0); | ||
| 767 | sd->ctrl_handler = hdl; | ||
| 768 | if (hdl->error) { | ||
| 769 | int err = hdl->error; | ||
| 770 | |||
| 771 | v4l2_ctrl_handler_free(hdl); | ||
| 772 | kfree(state); | ||
| 773 | return err; | ||
| 774 | } | ||
| 775 | |||
| 776 | v4l2_ctrl_cluster(2, &state->volume); | ||
| 777 | v4l2_ctrl_handler_setup(hdl); | ||
| 778 | |||
| 852 | /* hello world :-) */ | 779 | /* hello world :-) */ |
| 853 | v4l_info(client, "MSP%d4%02d%c-%c%d found @ 0x%x (%s)\n", | 780 | v4l_info(client, "MSP%d4%02d%c-%c%d found @ 0x%x (%s)\n", |
| 854 | msp_family, msp_product, | 781 | msp_family, msp_product, |
| @@ -903,6 +830,7 @@ static int msp_remove(struct i2c_client *client) | |||
| 903 | } | 830 | } |
| 904 | msp_reset(client); | 831 | msp_reset(client); |
| 905 | 832 | ||
| 833 | v4l2_ctrl_handler_free(&state->hdl); | ||
| 906 | kfree(state); | 834 | kfree(state); |
| 907 | return 0; | 835 | return 0; |
| 908 | } | 836 | } |
diff --git a/drivers/media/video/msp3400-driver.h b/drivers/media/video/msp3400-driver.h index d6b3e6d0eef7..32a478e532f3 100644 --- a/drivers/media/video/msp3400-driver.h +++ b/drivers/media/video/msp3400-driver.h | |||
| @@ -6,6 +6,7 @@ | |||
| 6 | 6 | ||
| 7 | #include <media/msp3400.h> | 7 | #include <media/msp3400.h> |
| 8 | #include <media/v4l2-device.h> | 8 | #include <media/v4l2-device.h> |
| 9 | #include <media/v4l2-ctrls.h> | ||
| 9 | 10 | ||
| 10 | /* ---------------------------------------------------------------------- */ | 11 | /* ---------------------------------------------------------------------- */ |
| 11 | 12 | ||
| @@ -51,6 +52,7 @@ extern int msp_stereo_thresh; | |||
| 51 | 52 | ||
| 52 | struct msp_state { | 53 | struct msp_state { |
| 53 | struct v4l2_subdev sd; | 54 | struct v4l2_subdev sd; |
| 55 | struct v4l2_ctrl_handler hdl; | ||
| 54 | int rev1, rev2; | 56 | int rev1, rev2; |
| 55 | int ident; | 57 | int ident; |
| 56 | u8 has_nicam; | 58 | u8 has_nicam; |
| @@ -87,9 +89,12 @@ struct msp_state { | |||
| 87 | int audmode; | 89 | int audmode; |
| 88 | int rxsubchans; | 90 | int rxsubchans; |
| 89 | 91 | ||
| 90 | int volume, muted; | 92 | struct { |
| 91 | int balance, loudness; | 93 | /* volume cluster */ |
| 92 | int bass, treble; | 94 | struct v4l2_ctrl *volume; |
| 95 | struct v4l2_ctrl *muted; | ||
| 96 | }; | ||
| 97 | |||
| 93 | int scan_in_progress; | 98 | int scan_in_progress; |
| 94 | 99 | ||
| 95 | /* thread */ | 100 | /* thread */ |
| @@ -104,6 +109,11 @@ static inline struct msp_state *to_state(struct v4l2_subdev *sd) | |||
| 104 | return container_of(sd, struct msp_state, sd); | 109 | return container_of(sd, struct msp_state, sd); |
| 105 | } | 110 | } |
| 106 | 111 | ||
| 112 | static inline struct msp_state *ctrl_to_state(struct v4l2_ctrl *ctrl) | ||
| 113 | { | ||
| 114 | return container_of(ctrl->handler, struct msp_state, hdl); | ||
| 115 | } | ||
| 116 | |||
| 107 | /* msp3400-driver.c */ | 117 | /* msp3400-driver.c */ |
| 108 | int msp_write_dem(struct i2c_client *client, int addr, int val); | 118 | int msp_write_dem(struct i2c_client *client, int addr, int val); |
| 109 | int msp_write_dsp(struct i2c_client *client, int addr, int val); | 119 | int msp_write_dsp(struct i2c_client *client, int addr, int val); |
| @@ -111,7 +121,7 @@ int msp_read_dem(struct i2c_client *client, int addr); | |||
| 111 | int msp_read_dsp(struct i2c_client *client, int addr); | 121 | int msp_read_dsp(struct i2c_client *client, int addr); |
| 112 | int msp_reset(struct i2c_client *client); | 122 | int msp_reset(struct i2c_client *client); |
| 113 | void msp_set_scart(struct i2c_client *client, int in, int out); | 123 | void msp_set_scart(struct i2c_client *client, int in, int out); |
| 114 | void msp_set_audio(struct i2c_client *client); | 124 | void msp_update_volume(struct msp_state *state); |
| 115 | int msp_sleep(struct msp_state *state, int timeout); | 125 | int msp_sleep(struct msp_state *state, int timeout); |
| 116 | 126 | ||
| 117 | /* msp3400-kthreads.c */ | 127 | /* msp3400-kthreads.c */ |
diff --git a/drivers/media/video/msp3400-kthreads.c b/drivers/media/video/msp3400-kthreads.c index d5a69c5ee5e4..b376fcdee652 100644 --- a/drivers/media/video/msp3400-kthreads.c +++ b/drivers/media/video/msp3400-kthreads.c | |||
| @@ -496,13 +496,13 @@ restart: | |||
| 496 | v4l_dbg(1, msp_debug, client, | 496 | v4l_dbg(1, msp_debug, client, |
| 497 | "thread: no carrier scan\n"); | 497 | "thread: no carrier scan\n"); |
| 498 | state->scan_in_progress = 0; | 498 | state->scan_in_progress = 0; |
| 499 | msp_set_audio(client); | 499 | msp_update_volume(state); |
| 500 | continue; | 500 | continue; |
| 501 | } | 501 | } |
| 502 | 502 | ||
| 503 | /* mute audio */ | 503 | /* mute audio */ |
| 504 | state->scan_in_progress = 1; | 504 | state->scan_in_progress = 1; |
| 505 | msp_set_audio(client); | 505 | msp_update_volume(state); |
| 506 | 506 | ||
| 507 | msp3400c_set_mode(client, MSP_MODE_AM_DETECT); | 507 | msp3400c_set_mode(client, MSP_MODE_AM_DETECT); |
| 508 | val1 = val2 = 0; | 508 | val1 = val2 = 0; |
| @@ -634,7 +634,7 @@ no_second: | |||
| 634 | /* unmute */ | 634 | /* unmute */ |
| 635 | state->scan_in_progress = 0; | 635 | state->scan_in_progress = 0; |
| 636 | msp3400c_set_audmode(client); | 636 | msp3400c_set_audmode(client); |
| 637 | msp_set_audio(client); | 637 | msp_update_volume(state); |
| 638 | 638 | ||
| 639 | if (msp_debug) | 639 | if (msp_debug) |
| 640 | msp3400c_print_mode(client); | 640 | msp3400c_print_mode(client); |
| @@ -679,13 +679,13 @@ restart: | |||
| 679 | v4l_dbg(1, msp_debug, client, | 679 | v4l_dbg(1, msp_debug, client, |
| 680 | "thread: no carrier scan\n"); | 680 | "thread: no carrier scan\n"); |
| 681 | state->scan_in_progress = 0; | 681 | state->scan_in_progress = 0; |
| 682 | msp_set_audio(client); | 682 | msp_update_volume(state); |
| 683 | continue; | 683 | continue; |
| 684 | } | 684 | } |
| 685 | 685 | ||
| 686 | /* mute audio */ | 686 | /* mute audio */ |
| 687 | state->scan_in_progress = 1; | 687 | state->scan_in_progress = 1; |
| 688 | msp_set_audio(client); | 688 | msp_update_volume(state); |
| 689 | 689 | ||
| 690 | /* start autodetect. Note: autodetect is not supported for | 690 | /* start autodetect. Note: autodetect is not supported for |
| 691 | NTSC-M and radio, hence we force the standard in those | 691 | NTSC-M and radio, hence we force the standard in those |
| @@ -797,7 +797,7 @@ restart: | |||
| 797 | /* unmute */ | 797 | /* unmute */ |
| 798 | msp3400c_set_audmode(client); | 798 | msp3400c_set_audmode(client); |
| 799 | state->scan_in_progress = 0; | 799 | state->scan_in_progress = 0; |
| 800 | msp_set_audio(client); | 800 | msp_update_volume(state); |
| 801 | 801 | ||
| 802 | /* monitor tv audio mode, the first time don't wait | 802 | /* monitor tv audio mode, the first time don't wait |
| 803 | so long to get a quick stereo/bilingual result */ | 803 | so long to get a quick stereo/bilingual result */ |
| @@ -974,7 +974,7 @@ restart: | |||
| 974 | v4l_dbg(1, msp_debug, client, | 974 | v4l_dbg(1, msp_debug, client, |
| 975 | "thread: no carrier scan\n"); | 975 | "thread: no carrier scan\n"); |
| 976 | state->scan_in_progress = 0; | 976 | state->scan_in_progress = 0; |
| 977 | msp_set_audio(client); | 977 | msp_update_volume(state); |
| 978 | continue; | 978 | continue; |
| 979 | } | 979 | } |
| 980 | 980 | ||
| @@ -1020,7 +1020,7 @@ unmute: | |||
| 1020 | } | 1020 | } |
| 1021 | 1021 | ||
| 1022 | /* unmute: dispatch sound to scart output, set scart volume */ | 1022 | /* unmute: dispatch sound to scart output, set scart volume */ |
| 1023 | msp_set_audio(client); | 1023 | msp_update_volume(state); |
| 1024 | 1024 | ||
| 1025 | /* restore ACB */ | 1025 | /* restore ACB */ |
| 1026 | if (msp_write_dsp(client, 0x13, state->acb)) | 1026 | if (msp_write_dsp(client, 0x13, state->acb)) |
