Commit 6951803c2402d1af0e76df051cc9b117f504550f

Authored by Lawrence Rust
Committed by Mauro Carvalho Chehab
1 parent 724dcbfa9c

[media] Add proper audio support for Nova-S Plus with wm8775 ADC

This patch adds audio DMA capture and ALSA mixer elements for the line
input jack of the Hauppauge Nova-S-plus DVB-S PCI card.  The Nova-S-plus
has a WM8775 ADC that is currently not detected.  This patch enables
this chip and exports volume, balance mute and ALC elements for ALSA
mixer controls.

[mchehab@redhat.com: Changed the patch to only talk with wm8775 if board
info says so. Also, added platform_data support, to avoid changing the
behaviour for other boards, and fixed CodingStyle]

[awalls@md.metrocast.net: Changed patch to make the WM8775_GID defintion
bridge driver private and let the bridge driver set the value of
v4l2_subdev.grp_id.]

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Signed-off-by: Andy Walls <awalls@md.metrocast.net>

Showing 7 changed files with 267 additions and 62 deletions Side-by-side Diff

drivers/media/video/cx88/cx88-alsa.c
... ... @@ -40,6 +40,7 @@
40 40 #include <sound/control.h>
41 41 #include <sound/initval.h>
42 42 #include <sound/tlv.h>
  43 +#include <media/wm8775.h>
43 44  
44 45 #include "cx88.h"
45 46 #include "cx88-reg.h"
... ... @@ -577,6 +578,35 @@
577 578 return 0;
578 579 }
579 580  
  581 +static void snd_cx88_wm8775_volume_put(struct snd_kcontrol *kcontrol,
  582 + struct snd_ctl_elem_value *value)
  583 +{
  584 + snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol);
  585 + struct cx88_core *core = chip->core;
  586 + struct v4l2_control client_ctl;
  587 + int left = value->value.integer.value[0];
  588 + int right = value->value.integer.value[1];
  589 + int v, b;
  590 +
  591 + memset(&client_ctl, 0, sizeof(client_ctl));
  592 +
  593 + /* Pass volume & balance onto any WM8775 */
  594 + if (left >= right) {
  595 + v = left << 10;
  596 + b = left ? (0x8000 * right) / left : 0x8000;
  597 + } else {
  598 + v = right << 10;
  599 + b = right ? 0xffff - (0x8000 * left) / right : 0x8000;
  600 + }
  601 + client_ctl.value = v;
  602 + client_ctl.id = V4L2_CID_AUDIO_VOLUME;
  603 + call_hw(core, WM8775_GID, core, s_ctrl, &client_ctl);
  604 +
  605 + client_ctl.value = b;
  606 + client_ctl.id = V4L2_CID_AUDIO_BALANCE;
  607 + call_hw(core, WM8775_GID, core, s_ctrl, &client_ctl);
  608 +}
  609 +
580 610 /* OK - TODO: test it */
581 611 static int snd_cx88_volume_put(struct snd_kcontrol *kcontrol,
582 612 struct snd_ctl_elem_value *value)
583 613  
584 614  
585 615  
586 616  
... ... @@ -587,25 +617,28 @@
587 617 int changed = 0;
588 618 u32 old;
589 619  
  620 + if (core->board.audio_chip == V4L2_IDENT_WM8775)
  621 + snd_cx88_wm8775_volume_put(kcontrol, value);
  622 +
590 623 left = value->value.integer.value[0] & 0x3f;
591 624 right = value->value.integer.value[1] & 0x3f;
592 625 b = right - left;
593 626 if (b < 0) {
594   - v = 0x3f - left;
595   - b = (-b) | 0x40;
  627 + v = 0x3f - left;
  628 + b = (-b) | 0x40;
596 629 } else {
597   - v = 0x3f - right;
  630 + v = 0x3f - right;
598 631 }
599 632 /* Do we really know this will always be called with IRQs on? */
600 633 spin_lock_irq(&chip->reg_lock);
601 634 old = cx_read(AUD_VOL_CTL);
602 635 if (v != (old & 0x3f)) {
603   - cx_write(AUD_VOL_CTL, (old & ~0x3f) | v);
604   - changed = 1;
  636 + cx_swrite(SHADOW_AUD_VOL_CTL, AUD_VOL_CTL, (old & ~0x3f) | v);
  637 + changed = 1;
605 638 }
606   - if (cx_read(AUD_BAL_CTL) != b) {
607   - cx_write(AUD_BAL_CTL, b);
608   - changed = 1;
  639 + if ((cx_read(AUD_BAL_CTL) & 0x7f) != b) {
  640 + cx_write(AUD_BAL_CTL, b);
  641 + changed = 1;
609 642 }
610 643 spin_unlock_irq(&chip->reg_lock);
611 644  
... ... @@ -618,7 +651,7 @@
618 651 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
619 652 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
620 653 SNDRV_CTL_ELEM_ACCESS_TLV_READ,
621   - .name = "Playback Volume",
  654 + .name = "Analog-TV Volume",
622 655 .info = snd_cx88_volume_info,
623 656 .get = snd_cx88_volume_get,
624 657 .put = snd_cx88_volume_put,
... ... @@ -649,7 +682,17 @@
649 682 vol = cx_read(AUD_VOL_CTL);
650 683 if (value->value.integer.value[0] != !(vol & bit)) {
651 684 vol ^= bit;
652   - cx_write(AUD_VOL_CTL, vol);
  685 + cx_swrite(SHADOW_AUD_VOL_CTL, AUD_VOL_CTL, vol);
  686 + /* Pass mute onto any WM8775 */
  687 + if ((core->board.audio_chip == V4L2_IDENT_WM8775) &&
  688 + ((1<<6) == bit)) {
  689 + struct v4l2_control client_ctl;
  690 +
  691 + memset(&client_ctl, 0, sizeof(client_ctl));
  692 + client_ctl.value = 0 != (vol & bit);
  693 + client_ctl.id = V4L2_CID_AUDIO_MUTE;
  694 + call_hw(core, WM8775_GID, core, s_ctrl, &client_ctl);
  695 + }
653 696 ret = 1;
654 697 }
655 698 spin_unlock_irq(&chip->reg_lock);
... ... @@ -658,7 +701,7 @@
658 701  
659 702 static const struct snd_kcontrol_new snd_cx88_dac_switch = {
660 703 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
661   - .name = "Playback Switch",
  704 + .name = "Audio-Out Switch",
662 705 .info = snd_ctl_boolean_mono_info,
663 706 .get = snd_cx88_switch_get,
664 707 .put = snd_cx88_switch_put,
665 708  
... ... @@ -667,13 +710,51 @@
667 710  
668 711 static const struct snd_kcontrol_new snd_cx88_source_switch = {
669 712 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
670   - .name = "Capture Switch",
  713 + .name = "Analog-TV Switch",
671 714 .info = snd_ctl_boolean_mono_info,
672 715 .get = snd_cx88_switch_get,
673 716 .put = snd_cx88_switch_put,
674 717 .private_value = (1<<6),
675 718 };
676 719  
  720 +static int snd_cx88_alc_get(struct snd_kcontrol *kcontrol,
  721 + struct snd_ctl_elem_value *value)
  722 +{
  723 + snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol);
  724 + struct cx88_core *core = chip->core;
  725 + struct v4l2_control client_ctl;
  726 +
  727 + memset(&client_ctl, 0, sizeof(client_ctl));
  728 + client_ctl.id = V4L2_CID_AUDIO_LOUDNESS;
  729 + call_hw(core, WM8775_GID, core, g_ctrl, &client_ctl);
  730 + value->value.integer.value[0] = client_ctl.value ? 1 : 0;
  731 +
  732 + return 0;
  733 +}
  734 +
  735 +static int snd_cx88_alc_put(struct snd_kcontrol *kcontrol,
  736 + struct snd_ctl_elem_value *value)
  737 +{
  738 + snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol);
  739 + struct cx88_core *core = chip->core;
  740 + struct v4l2_control client_ctl;
  741 +
  742 + memset(&client_ctl, 0, sizeof(client_ctl));
  743 + client_ctl.value = 0 != value->value.integer.value[0];
  744 + client_ctl.id = V4L2_CID_AUDIO_LOUDNESS;
  745 + call_hw(core, WM8775_GID, core, s_ctrl, &client_ctl);
  746 +
  747 + return 0;
  748 +}
  749 +
  750 +static struct snd_kcontrol_new snd_cx88_alc_switch = {
  751 + .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  752 + .name = "Line-In ALC Switch",
  753 + .info = snd_ctl_boolean_mono_info,
  754 + .get = snd_cx88_alc_get,
  755 + .put = snd_cx88_alc_put,
  756 +};
  757 +
677 758 /****************************************************************************
678 759 Basic Flow for Sound Devices
679 760 ****************************************************************************/
... ... @@ -724,7 +805,8 @@
724 805 static int devno;
725 806 static int __devinit snd_cx88_create(struct snd_card *card,
726 807 struct pci_dev *pci,
727   - snd_cx88_card_t **rchip)
  808 + snd_cx88_card_t **rchip,
  809 + struct cx88_core **core_ptr)
728 810 {
729 811 snd_cx88_card_t *chip;
730 812 struct cx88_core *core;
... ... @@ -750,7 +832,7 @@
750 832 if (!pci_dma_supported(pci,DMA_BIT_MASK(32))) {
751 833 dprintk(0, "%s/1: Oops: no 32bit PCI DMA ???\n",core->name);
752 834 err = -EIO;
753   - cx88_core_put(core,pci);
  835 + cx88_core_put(core, pci);
754 836 return err;
755 837 }
756 838  
... ... @@ -786,6 +868,7 @@
786 868 snd_card_set_dev(card, &pci->dev);
787 869  
788 870 *rchip = chip;
  871 + *core_ptr = core;
789 872  
790 873 return 0;
791 874 }
... ... @@ -795,6 +878,7 @@
795 878 {
796 879 struct snd_card *card;
797 880 snd_cx88_card_t *chip;
  881 + struct cx88_core *core;
798 882 int err;
799 883  
800 884 if (devno >= SNDRV_CARDS)
... ... @@ -812,7 +896,7 @@
812 896  
813 897 card->private_free = snd_cx88_dev_free;
814 898  
815   - err = snd_cx88_create(card, pci, &chip);
  899 + err = snd_cx88_create(card, pci, &chip, &core);
816 900 if (err < 0)
817 901 goto error;
818 902  
... ... @@ -829,6 +913,10 @@
829 913 err = snd_ctl_add(card, snd_ctl_new1(&snd_cx88_source_switch, chip));
830 914 if (err < 0)
831 915 goto error;
  916 +
  917 + /* If there's a wm8775 then add a Line-In ALC switch */
  918 + if (core->board.audio_chip == V4L2_IDENT_WM8775)
  919 + snd_ctl_add(card, snd_ctl_new1(&snd_cx88_alc_switch, chip));
832 920  
833 921 strcpy (card->driver, "CX88x");
834 922 sprintf(card->shortname, "Conexant CX%x", pci->device);
drivers/media/video/cx88/cx88-cards.c
... ... @@ -970,7 +970,8 @@
970 970 .radio_type = UNSET,
971 971 .tuner_addr = ADDR_UNSET,
972 972 .radio_addr = ADDR_UNSET,
973   - .audio_chip = V4L2_IDENT_WM8775,
  973 + .audio_chip = V4L2_IDENT_WM8775,
  974 + .i2sinputcntl = 2,
974 975 .input = {{
975 976 .type = CX88_VMUX_DVB,
976 977 .vmux = 0,
drivers/media/video/cx88/cx88-tvaudio.c
... ... @@ -786,8 +786,12 @@
786 786 break;
787 787 case WW_I2SADC:
788 788 set_audio_start(core, 0x01);
789   - /* Slave/Philips/Autobaud */
790   - cx_write(AUD_I2SINPUTCNTL, 0);
  789 + /*
  790 + * Slave/Philips/Autobaud
  791 + * NB on Nova-S bit1 NPhilipsSony appears to be inverted:
  792 + * 0= Sony, 1=Philips
  793 + */
  794 + cx_write(AUD_I2SINPUTCNTL, core->board.i2sinputcntl);
791 795 /* Switch to "I2S ADC mode" */
792 796 cx_write(AUD_I2SCNTL, 0x1);
793 797 set_audio_finish(core, EN_I2SIN_ENABLE);
drivers/media/video/cx88/cx88-video.c
... ... @@ -40,6 +40,7 @@
40 40 #include "cx88.h"
41 41 #include <media/v4l2-common.h>
42 42 #include <media/v4l2-ioctl.h>
  43 +#include <media/wm8775.h>
43 44  
44 45 MODULE_DESCRIPTION("v4l2 driver module for cx2388x based TV cards");
45 46 MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
... ... @@ -989,6 +990,32 @@
989 990 ctl->value = c->v.minimum;
990 991 if (ctl->value > c->v.maximum)
991 992 ctl->value = c->v.maximum;
  993 +
  994 + /* Pass changes onto any WM8775 */
  995 + if (core->board.audio_chip == V4L2_IDENT_WM8775) {
  996 + struct v4l2_control client_ctl;
  997 + memset(&client_ctl, 0, sizeof(client_ctl));
  998 + client_ctl.id = ctl->id;
  999 +
  1000 + switch (ctl->id) {
  1001 + case V4L2_CID_AUDIO_MUTE:
  1002 + client_ctl.value = ctl->value;
  1003 + break;
  1004 + case V4L2_CID_AUDIO_VOLUME:
  1005 + client_ctl.value = (ctl->value) ?
  1006 + (0x90 + ctl->value) << 8 : 0;
  1007 + break;
  1008 + case V4L2_CID_AUDIO_BALANCE:
  1009 + client_ctl.value = ctl->value << 9;
  1010 + break;
  1011 + default:
  1012 + client_ctl.id = 0;
  1013 + break;
  1014 + }
  1015 + if (client_ctl.id)
  1016 + call_hw(core, WM8775_GID, core, s_ctrl, &client_ctl);
  1017 + }
  1018 +
992 1019 mask=c->mask;
993 1020 switch (ctl->id) {
994 1021 case V4L2_CID_AUDIO_BALANCE:
... ... @@ -1526,7 +1553,9 @@
1526 1553 if (c->id < V4L2_CID_BASE ||
1527 1554 c->id >= V4L2_CID_LASTP1)
1528 1555 return -EINVAL;
1529   - if (c->id == V4L2_CID_AUDIO_MUTE) {
  1556 + if (c->id == V4L2_CID_AUDIO_MUTE ||
  1557 + c->id == V4L2_CID_AUDIO_VOLUME ||
  1558 + c->id == V4L2_CID_AUDIO_BALANCE) {
1530 1559 for (i = 0; i < CX8800_CTLS; i++) {
1531 1560 if (cx8800_ctls[i].v.id == c->id)
1532 1561 break;
... ... @@ -1856,9 +1885,24 @@
1856 1885  
1857 1886 /* load and configure helper modules */
1858 1887  
1859   - if (core->board.audio_chip == V4L2_IDENT_WM8775)
1860   - v4l2_i2c_new_subdev(&core->v4l2_dev, &core->i2c_adap,
1861   - "wm8775", 0x36 >> 1, NULL);
  1888 + if (core->board.audio_chip == V4L2_IDENT_WM8775) {
  1889 + struct i2c_board_info wm8775_info = {
  1890 + .type = "wm8775",
  1891 + .addr = 0x36 >> 1,
  1892 + .platform_data = &core->wm8775_data,
  1893 + };
  1894 + struct v4l2_subdev *sd;
  1895 +
  1896 + if (core->boardnr == CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1)
  1897 + core->wm8775_data.is_nova_s = true;
  1898 + else
  1899 + core->wm8775_data.is_nova_s = false;
  1900 +
  1901 + sd = v4l2_i2c_new_subdev_board(&core->v4l2_dev, &core->i2c_adap,
  1902 + &wm8775_info, NULL);
  1903 + if (sd != NULL)
  1904 + sd->grp_id = WM8775_GID;
  1905 + }
1862 1906  
1863 1907 if (core->board.audio_chip == V4L2_IDENT_TVAUDIO) {
1864 1908 /* This probes for a tda9874 as is used on some
drivers/media/video/cx88/cx88.h
... ... @@ -33,6 +33,7 @@
33 33 #include <media/cx2341x.h>
34 34 #include <media/videobuf-dvb.h>
35 35 #include <media/ir-kbd-i2c.h>
  36 +#include <media/wm8775.h>
36 37  
37 38 #include "btcx-risc.h"
38 39 #include "cx88-reg.h"
... ... @@ -273,6 +274,9 @@
273 274 enum cx88_board_type mpeg;
274 275 unsigned int audio_chip;
275 276 int num_frontends;
  277 +
  278 + /* Used for I2S devices */
  279 + int i2sinputcntl;
276 280 };
277 281  
278 282 struct cx88_subid {
... ... @@ -379,6 +383,7 @@
379 383  
380 384 /* I2C remote data */
381 385 struct IR_i2c_init_data init_data;
  386 + struct wm8775_platform_data wm8775_data;
382 387  
383 388 struct mutex lock;
384 389 /* various v4l controls */
385 390  
386 391  
... ... @@ -398,16 +403,20 @@
398 403 return container_of(v4l2_dev, struct cx88_core, v4l2_dev);
399 404 }
400 405  
401   -#define call_all(core, o, f, args...) \
  406 +#define WM8775_GID (1 << 0)
  407 +
  408 +#define call_hw(core, grpid, o, f, args...) \
402 409 do { \
403 410 if (!core->i2c_rc) { \
404 411 if (core->gate_ctrl) \
405 412 core->gate_ctrl(core, 1); \
406   - v4l2_device_call_all(&core->v4l2_dev, 0, o, f, ##args); \
  413 + v4l2_device_call_all(&core->v4l2_dev, grpid, o, f, ##args); \
407 414 if (core->gate_ctrl) \
408 415 core->gate_ctrl(core, 0); \
409 416 } \
410 417 } while (0)
  418 +
  419 +#define call_all(core, o, f, args...) call_hw(core, 0, o, f, ##args)
411 420  
412 421 struct cx8800_dev;
413 422 struct cx8802_dev;
drivers/media/video/wm8775.c
... ... @@ -35,6 +35,7 @@
35 35 #include <media/v4l2-device.h>
36 36 #include <media/v4l2-chip-ident.h>
37 37 #include <media/v4l2-ctrls.h>
  38 +#include <media/wm8775.h>
38 39  
39 40 MODULE_DESCRIPTION("wm8775 driver");
40 41 MODULE_AUTHOR("Ulf Eklund, Hans Verkuil");
41 42  
... ... @@ -50,10 +51,16 @@
50 51 TOT_REGS
51 52 };
52 53  
  54 +#define ALC_HOLD 0x85 /* R17: use zero cross detection, ALC hold time 42.6 ms */
  55 +#define ALC_EN 0x100 /* R17: ALC enable */
  56 +
53 57 struct wm8775_state {
54 58 struct v4l2_subdev sd;
55 59 struct v4l2_ctrl_handler hdl;
56 60 struct v4l2_ctrl *mute;
  61 + struct v4l2_ctrl *vol;
  62 + struct v4l2_ctrl *bal;
  63 + struct v4l2_ctrl *loud;
57 64 u8 input; /* Last selected input (0-0xf) */
58 65 };
59 66  
... ... @@ -85,6 +92,30 @@
85 92 return -1;
86 93 }
87 94  
  95 +static void wm8775_set_audio(struct v4l2_subdev *sd, int quietly)
  96 +{
  97 + struct wm8775_state *state = to_state(sd);
  98 + u8 vol_l, vol_r;
  99 + int muted = 0 != state->mute->val;
  100 + u16 volume = (u16)state->vol->val;
  101 + u16 balance = (u16)state->bal->val;
  102 +
  103 + /* normalize ( 65535 to 0 -> 255 to 0 (+24dB to -103dB) ) */
  104 + vol_l = (min(65536 - balance, 32768) * volume) >> 23;
  105 + vol_r = (min(balance, (u16)32768) * volume) >> 23;
  106 +
  107 + /* Mute */
  108 + if (muted || quietly)
  109 + wm8775_write(sd, R21, 0x0c0 | state->input);
  110 +
  111 + wm8775_write(sd, R14, vol_l | 0x100); /* 0x100= Left channel ADC zero cross enable */
  112 + wm8775_write(sd, R15, vol_r | 0x100); /* 0x100= Right channel ADC zero cross enable */
  113 +
  114 + /* Un-mute */
  115 + if (!muted)
  116 + wm8775_write(sd, R21, state->input);
  117 +}
  118 +
88 119 static int wm8775_s_routing(struct v4l2_subdev *sd,
89 120 u32 input, u32 output, u32 config)
90 121 {
91 122  
92 123  
93 124  
... ... @@ -102,26 +133,27 @@
102 133 state->input = input;
103 134 if (!v4l2_ctrl_g_ctrl(state->mute))
104 135 return 0;
105   - wm8775_write(sd, R21, 0x0c0);
106   - wm8775_write(sd, R14, 0x1d4);
107   - wm8775_write(sd, R15, 0x1d4);
108   - wm8775_write(sd, R21, 0x100 + state->input);
  136 + if (!v4l2_ctrl_g_ctrl(state->vol))
  137 + return 0;
  138 + if (!v4l2_ctrl_g_ctrl(state->bal))
  139 + return 0;
  140 + wm8775_set_audio(sd, 1);
109 141 return 0;
110 142 }
111 143  
112 144 static int wm8775_s_ctrl(struct v4l2_ctrl *ctrl)
113 145 {
114 146 struct v4l2_subdev *sd = to_sd(ctrl);
115   - struct wm8775_state *state = to_state(sd);
116 147  
117 148 switch (ctrl->id) {
118 149 case V4L2_CID_AUDIO_MUTE:
119   - wm8775_write(sd, R21, 0x0c0);
120   - wm8775_write(sd, R14, 0x1d4);
121   - wm8775_write(sd, R15, 0x1d4);
122   - if (!ctrl->val)
123   - wm8775_write(sd, R21, 0x100 + state->input);
  150 + case V4L2_CID_AUDIO_VOLUME:
  151 + case V4L2_CID_AUDIO_BALANCE:
  152 + wm8775_set_audio(sd, 0);
124 153 return 0;
  154 + case V4L2_CID_AUDIO_LOUDNESS:
  155 + wm8775_write(sd, R17, (ctrl->val ? ALC_EN : 0) | ALC_HOLD);
  156 + return 0;
125 157 }
126 158 return -EINVAL;
127 159 }
... ... @@ -144,16 +176,7 @@
144 176  
145 177 static int wm8775_s_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *freq)
146 178 {
147   - struct wm8775_state *state = to_state(sd);
148   -
149   - /* If I remove this, then it can happen that I have no
150   - sound the first time I tune from static to a valid channel.
151   - It's difficult to reproduce and is almost certainly related
152   - to the zero cross detect circuit. */
153   - wm8775_write(sd, R21, 0x0c0);
154   - wm8775_write(sd, R14, 0x1d4);
155   - wm8775_write(sd, R15, 0x1d4);
156   - wm8775_write(sd, R21, 0x100 + state->input);
  179 + wm8775_set_audio(sd, 0);
157 180 return 0;
158 181 }
159 182  
160 183  
... ... @@ -203,7 +226,14 @@
203 226 {
204 227 struct wm8775_state *state;
205 228 struct v4l2_subdev *sd;
  229 + int err;
  230 + bool is_nova_s = false;
206 231  
  232 + if (client->dev.platform_data) {
  233 + struct wm8775_platform_data *data = client->dev.platform_data;
  234 + is_nova_s = data->is_nova_s;
  235 + }
  236 +
207 237 /* Check if the adapter supports the needed features */
208 238 if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
209 239 return -EIO;
210 240  
211 241  
... ... @@ -218,13 +248,18 @@
218 248 v4l2_i2c_subdev_init(sd, client, &wm8775_ops);
219 249 state->input = 2;
220 250  
221   - v4l2_ctrl_handler_init(&state->hdl, 1);
  251 + v4l2_ctrl_handler_init(&state->hdl, 4);
222 252 state->mute = v4l2_ctrl_new_std(&state->hdl, &wm8775_ctrl_ops,
223 253 V4L2_CID_AUDIO_MUTE, 0, 1, 1, 0);
  254 + state->vol = v4l2_ctrl_new_std(&state->hdl, &wm8775_ctrl_ops,
  255 + V4L2_CID_AUDIO_VOLUME, 0, 65535, (65535+99)/100, 0xCF00); /* 0dB*/
  256 + state->bal = v4l2_ctrl_new_std(&state->hdl, &wm8775_ctrl_ops,
  257 + V4L2_CID_AUDIO_BALANCE, 0, 65535, (65535+99)/100, 32768);
  258 + state->loud = v4l2_ctrl_new_std(&state->hdl, &wm8775_ctrl_ops,
  259 + V4L2_CID_AUDIO_LOUDNESS, 0, 1, 1, 1);
224 260 sd->ctrl_handler = &state->hdl;
225   - if (state->hdl.error) {
226   - int err = state->hdl.error;
227   -
  261 + err = state->hdl.error;
  262 + if (err) {
228 263 v4l2_ctrl_handler_free(&state->hdl);
229 264 kfree(state);
230 265 return err;
231 266  
232 267  
... ... @@ -236,29 +271,44 @@
236 271 wm8775_write(sd, R23, 0x000);
237 272 /* Disable zero cross detect timeout */
238 273 wm8775_write(sd, R7, 0x000);
239   - /* Left justified, 24-bit mode */
  274 + /* HPF enable, left justified, 24-bit (Philips) mode */
240 275 wm8775_write(sd, R11, 0x021);
241 276 /* Master mode, clock ratio 256fs */
242 277 wm8775_write(sd, R12, 0x102);
243 278 /* Powered up */
244 279 wm8775_write(sd, R13, 0x000);
245   - /* ADC gain +2.5dB, enable zero cross */
246   - wm8775_write(sd, R14, 0x1d4);
247   - /* ADC gain +2.5dB, enable zero cross */
248   - wm8775_write(sd, R15, 0x1d4);
249   - /* ALC Stereo, ALC target level -1dB FS max gain +8dB */
250   - wm8775_write(sd, R16, 0x1bf);
251   - /* Enable gain control, use zero cross detection,
252   - ALC hold time 42.6 ms */
253   - wm8775_write(sd, R17, 0x185);
  280 +
  281 + if (!is_nova_s) {
  282 + /* ADC gain +2.5dB, enable zero cross */
  283 + wm8775_write(sd, R14, 0x1d4);
  284 + /* ADC gain +2.5dB, enable zero cross */
  285 + wm8775_write(sd, R15, 0x1d4);
  286 + /* ALC Stereo, ALC target level -1dB FS max gain +8dB */
  287 + wm8775_write(sd, R16, 0x1bf);
  288 + /* Enable gain control, use zero cross detection,
  289 + ALC hold time 42.6 ms */
  290 + wm8775_write(sd, R17, 0x185);
  291 + } else {
  292 + /* ALC stereo, ALC target level -5dB FS, ALC max gain +8dB */
  293 + wm8775_write(sd, R16, 0x1bb);
  294 + /* Set ALC mode and hold time */
  295 + wm8775_write(sd, R17, (state->loud->val ? ALC_EN : 0) | ALC_HOLD);
  296 + }
254 297 /* ALC gain ramp up delay 34 s, ALC gain ramp down delay 33 ms */
255 298 wm8775_write(sd, R18, 0x0a2);
256 299 /* Enable noise gate, threshold -72dBfs */
257 300 wm8775_write(sd, R19, 0x005);
258   - /* Transient window 4ms, lower PGA gain limit -1dB */
259   - wm8775_write(sd, R20, 0x07a);
260   - /* LRBOTH = 1, use input 2. */
261   - wm8775_write(sd, R21, 0x102);
  301 + if (!is_nova_s) {
  302 + /* Transient window 4ms, lower PGA gain limit -1dB */
  303 + wm8775_write(sd, R20, 0x07a);
  304 + /* LRBOTH = 1, use input 2. */
  305 + wm8775_write(sd, R21, 0x102);
  306 + } else {
  307 + /* Transient window 4ms, ALC min gain -5dB */
  308 + wm8775_write(sd, R20, 0x0fb);
  309 +
  310 + wm8775_set_audio(sd, 1); /* set volume/mute/mux */
  311 + }
262 312 return 0;
263 313 }
264 314  
include/media/wm8775.h
... ... @@ -32,5 +32,14 @@
32 32 #define WM8775_AIN3 4
33 33 #define WM8775_AIN4 8
34 34  
  35 +
  36 +struct wm8775_platform_data {
  37 + /*
  38 + * FIXME: Instead, we should parametrize the params
  39 + * that need different settings between ivtv, pvrusb2, and Nova-S
  40 + */
  41 + bool is_nova_s;
  42 +};
  43 +
35 44 #endif