Commit 585a7c66 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6:
  ALSA: use linux/io.h to fix compile warnings
  ALSA: hda - Fix memory leaks in conexant jack arrays
  ASoC: CX20442: fix NULL pointer dereference
  ASoC: Amstrad Delta: fix const related build error
  ALSA: oxygen: fix output routing on Xonar DG
  sound: silent echo'ed messages in Makefile
  ASoC: Fix mask/val_mask confusion snd_soc_dapm_put_volsw()
  ASoC: DaVinci: fix kernel panic due to uninitialized platform_data
  ALSA: HDA: Fix microphone(s) on Lenovo Edge 13
  ASoC: Fix module refcount for auxiliary devices
  ALSA: HDA: cxt5066 - Use asus model for Asus U50F, select correct SPDIF output
  ALSA: HDA: Add a new model "asus" for Conexant 5066/205xx
  ALSA: HDA: Refactor some redundant code for Conexant 5066/205xx
parents 44f2c5c8 00e6a319
...@@ -296,6 +296,7 @@ Conexant 5066 ...@@ -296,6 +296,7 @@ Conexant 5066
============= =============
laptop Basic Laptop config (default) laptop Basic Laptop config (default)
hp-laptop HP laptops, e g G60 hp-laptop HP laptops, e g G60
asus Asus K52JU, Lenovo G560
dell-laptop Dell laptops dell-laptop Dell laptops
dell-vostro Dell Vostro dell-vostro Dell Vostro
olpc-xo-1_5 OLPC XO 1.5 olpc-xo-1_5 OLPC XO 1.5
......
...@@ -55,14 +55,13 @@ ...@@ -55,14 +55,13 @@
#include <linux/err.h> #include <linux/err.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/io.h>
#include <linux/moduleparam.h> #include <linux/moduleparam.h>
#include <sound/core.h> #include <sound/core.h>
#include <sound/initval.h> #include <sound/initval.h>
#include <sound/rawmidi.h> #include <sound/rawmidi.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <asm/io.h>
/* /*
* globals * globals
*/ */
......
...@@ -87,7 +87,7 @@ ifeq ($(CONFIG_PSS_HAVE_BOOT),y) ...@@ -87,7 +87,7 @@ ifeq ($(CONFIG_PSS_HAVE_BOOT),y)
$(obj)/bin2hex pss_synth < $< > $@ $(obj)/bin2hex pss_synth < $< > $@
else else
$(obj)/pss_boot.h: $(obj)/pss_boot.h:
( \ $(Q)( \
echo 'static unsigned char * pss_synth = NULL;'; \ echo 'static unsigned char * pss_synth = NULL;'; \
echo 'static int pss_synthLen = 0;'; \ echo 'static int pss_synthLen = 0;'; \
) > $@ ) > $@
...@@ -102,7 +102,7 @@ ifeq ($(CONFIG_TRIX_HAVE_BOOT),y) ...@@ -102,7 +102,7 @@ ifeq ($(CONFIG_TRIX_HAVE_BOOT),y)
$(obj)/hex2hex -i trix_boot < $< > $@ $(obj)/hex2hex -i trix_boot < $< > $@
else else
$(obj)/trix_boot.h: $(obj)/trix_boot.h:
( \ $(Q)( \
echo 'static unsigned char * trix_boot = NULL;'; \ echo 'static unsigned char * trix_boot = NULL;'; \
echo 'static int trix_boot_len = 0;'; \ echo 'static int trix_boot_len = 0;'; \
) > $@ ) > $@
......
...@@ -85,6 +85,7 @@ struct conexant_spec { ...@@ -85,6 +85,7 @@ struct conexant_spec {
unsigned int auto_mic; unsigned int auto_mic;
int auto_mic_ext; /* autocfg.inputs[] index for ext mic */ int auto_mic_ext; /* autocfg.inputs[] index for ext mic */
unsigned int need_dac_fix; unsigned int need_dac_fix;
hda_nid_t slave_dig_outs[2];
/* capture */ /* capture */
unsigned int num_adc_nids; unsigned int num_adc_nids;
...@@ -127,6 +128,7 @@ struct conexant_spec { ...@@ -127,6 +128,7 @@ struct conexant_spec {
unsigned int ideapad:1; unsigned int ideapad:1;
unsigned int thinkpad:1; unsigned int thinkpad:1;
unsigned int hp_laptop:1; unsigned int hp_laptop:1;
unsigned int asus:1;
unsigned int ext_mic_present; unsigned int ext_mic_present;
unsigned int recording; unsigned int recording;
...@@ -352,6 +354,8 @@ static int conexant_build_pcms(struct hda_codec *codec) ...@@ -352,6 +354,8 @@ static int conexant_build_pcms(struct hda_codec *codec)
info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = info->stream[SNDRV_PCM_STREAM_CAPTURE].nid =
spec->dig_in_nid; spec->dig_in_nid;
} }
if (spec->slave_dig_outs[0])
codec->slave_dig_outs = spec->slave_dig_outs;
} }
return 0; return 0;
...@@ -403,10 +407,16 @@ static int conexant_add_jack(struct hda_codec *codec, ...@@ -403,10 +407,16 @@ static int conexant_add_jack(struct hda_codec *codec,
struct conexant_spec *spec; struct conexant_spec *spec;
struct conexant_jack *jack; struct conexant_jack *jack;
const char *name; const char *name;
int err; int i, err;
spec = codec->spec; spec = codec->spec;
snd_array_init(&spec->jacks, sizeof(*jack), 32); snd_array_init(&spec->jacks, sizeof(*jack), 32);
jack = spec->jacks.list;
for (i = 0; i < spec->jacks.used; i++, jack++)
if (jack->nid == nid)
return 0 ; /* already present */
jack = snd_array_new(&spec->jacks); jack = snd_array_new(&spec->jacks);
name = (type == SND_JACK_HEADPHONE) ? "Headphone" : "Mic" ; name = (type == SND_JACK_HEADPHONE) ? "Headphone" : "Mic" ;
...@@ -2100,7 +2110,7 @@ static int patch_cxt5051(struct hda_codec *codec) ...@@ -2100,7 +2110,7 @@ static int patch_cxt5051(struct hda_codec *codec)
static hda_nid_t cxt5066_dac_nids[1] = { 0x10 }; static hda_nid_t cxt5066_dac_nids[1] = { 0x10 };
static hda_nid_t cxt5066_adc_nids[3] = { 0x14, 0x15, 0x16 }; static hda_nid_t cxt5066_adc_nids[3] = { 0x14, 0x15, 0x16 };
static hda_nid_t cxt5066_capsrc_nids[1] = { 0x17 }; static hda_nid_t cxt5066_capsrc_nids[1] = { 0x17 };
#define CXT5066_SPDIF_OUT 0x21 static hda_nid_t cxt5066_digout_pin_nids[2] = { 0x20, 0x22 };
/* OLPC's microphone port is DC coupled for use with external sensors, /* OLPC's microphone port is DC coupled for use with external sensors,
* therefore we use a 50% mic bias in order to center the input signal with * therefore we use a 50% mic bias in order to center the input signal with
...@@ -2312,6 +2322,19 @@ static void cxt5066_ideapad_automic(struct hda_codec *codec) ...@@ -2312,6 +2322,19 @@ static void cxt5066_ideapad_automic(struct hda_codec *codec)
} }
} }
/* toggle input of built-in digital mic and mic jack appropriately */
static void cxt5066_asus_automic(struct hda_codec *codec)
{
unsigned int present;
present = snd_hda_jack_detect(codec, 0x1b);
snd_printdd("CXT5066: external microphone present=%d\n", present);
snd_hda_codec_write(codec, 0x17, 0, AC_VERB_SET_CONNECT_SEL,
present ? 1 : 0);
}
/* toggle input of built-in digital mic and mic jack appropriately */ /* toggle input of built-in digital mic and mic jack appropriately */
static void cxt5066_hp_laptop_automic(struct hda_codec *codec) static void cxt5066_hp_laptop_automic(struct hda_codec *codec)
{ {
...@@ -2387,79 +2410,55 @@ static void cxt5066_hp_automute(struct hda_codec *codec) ...@@ -2387,79 +2410,55 @@ static void cxt5066_hp_automute(struct hda_codec *codec)
cxt5066_update_speaker(codec); cxt5066_update_speaker(codec);
} }
/* unsolicited event for jack sensing */ /* Dispatch the right mic autoswitch function */
static void cxt5066_olpc_unsol_event(struct hda_codec *codec, unsigned int res) static void cxt5066_automic(struct hda_codec *codec)
{ {
struct conexant_spec *spec = codec->spec; struct conexant_spec *spec = codec->spec;
snd_printdd("CXT5066: unsol event %x (%x)\n", res, res >> 26);
switch (res >> 26) {
case CONEXANT_HP_EVENT:
cxt5066_hp_automute(codec);
break;
case CONEXANT_MIC_EVENT:
/* ignore mic events in DC mode; we're always using the jack */
if (!spec->dc_enable)
cxt5066_olpc_automic(codec);
break;
}
}
/* unsolicited event for jack sensing */ if (spec->dell_vostro)
static void cxt5066_vostro_event(struct hda_codec *codec, unsigned int res)
{
snd_printdd("CXT5066_vostro: unsol event %x (%x)\n", res, res >> 26);
switch (res >> 26) {
case CONEXANT_HP_EVENT:
cxt5066_hp_automute(codec);
break;
case CONEXANT_MIC_EVENT:
cxt5066_vostro_automic(codec); cxt5066_vostro_automic(codec);
break; else if (spec->ideapad)
}
}
/* unsolicited event for jack sensing */
static void cxt5066_ideapad_event(struct hda_codec *codec, unsigned int res)
{
snd_printdd("CXT5066_ideapad: unsol event %x (%x)\n", res, res >> 26);
switch (res >> 26) {
case CONEXANT_HP_EVENT:
cxt5066_hp_automute(codec);
break;
case CONEXANT_MIC_EVENT:
cxt5066_ideapad_automic(codec); cxt5066_ideapad_automic(codec);
break; else if (spec->thinkpad)
} cxt5066_thinkpad_automic(codec);
else if (spec->hp_laptop)
cxt5066_hp_laptop_automic(codec);
else if (spec->asus)
cxt5066_asus_automic(codec);
} }
/* unsolicited event for jack sensing */ /* unsolicited event for jack sensing */
static void cxt5066_hp_laptop_event(struct hda_codec *codec, unsigned int res) static void cxt5066_olpc_unsol_event(struct hda_codec *codec, unsigned int res)
{ {
snd_printdd("CXT5066_hp_laptop: unsol event %x (%x)\n", res, res >> 26); struct conexant_spec *spec = codec->spec;
snd_printdd("CXT5066: unsol event %x (%x)\n", res, res >> 26);
switch (res >> 26) { switch (res >> 26) {
case CONEXANT_HP_EVENT: case CONEXANT_HP_EVENT:
cxt5066_hp_automute(codec); cxt5066_hp_automute(codec);
break; break;
case CONEXANT_MIC_EVENT: case CONEXANT_MIC_EVENT:
cxt5066_hp_laptop_automic(codec); /* ignore mic events in DC mode; we're always using the jack */
if (!spec->dc_enable)
cxt5066_olpc_automic(codec);
break; break;
} }
} }
/* unsolicited event for jack sensing */ /* unsolicited event for jack sensing */
static void cxt5066_thinkpad_event(struct hda_codec *codec, unsigned int res) static void cxt5066_unsol_event(struct hda_codec *codec, unsigned int res)
{ {
snd_printdd("CXT5066_thinkpad: unsol event %x (%x)\n", res, res >> 26); snd_printdd("CXT5066: unsol event %x (%x)\n", res, res >> 26);
switch (res >> 26) { switch (res >> 26) {
case CONEXANT_HP_EVENT: case CONEXANT_HP_EVENT:
cxt5066_hp_automute(codec); cxt5066_hp_automute(codec);
break; break;
case CONEXANT_MIC_EVENT: case CONEXANT_MIC_EVENT:
cxt5066_thinkpad_automic(codec); cxt5066_automic(codec);
break; break;
} }
} }
static const struct hda_input_mux cxt5066_analog_mic_boost = { static const struct hda_input_mux cxt5066_analog_mic_boost = {
.num_items = 5, .num_items = 5,
.items = { .items = {
...@@ -2633,6 +2632,27 @@ static void cxt5066_olpc_capture_cleanup(struct hda_codec *codec) ...@@ -2633,6 +2632,27 @@ static void cxt5066_olpc_capture_cleanup(struct hda_codec *codec)
spec->recording = 0; spec->recording = 0;
} }
static void conexant_check_dig_outs(struct hda_codec *codec,
hda_nid_t *dig_pins,
int num_pins)
{
struct conexant_spec *spec = codec->spec;
hda_nid_t *nid_loc = &spec->multiout.dig_out_nid;
int i;
for (i = 0; i < num_pins; i++, dig_pins++) {
unsigned int cfg = snd_hda_codec_get_pincfg(codec, *dig_pins);
if (get_defcfg_connect(cfg) == AC_JACK_PORT_NONE)
continue;
if (snd_hda_get_connections(codec, *dig_pins, nid_loc, 1) != 1)
continue;
if (spec->slave_dig_outs[0])
nid_loc++;
else
nid_loc = spec->slave_dig_outs;
}
}
static struct hda_input_mux cxt5066_capture_source = { static struct hda_input_mux cxt5066_capture_source = {
.num_items = 4, .num_items = 4,
.items = { .items = {
...@@ -3039,20 +3059,11 @@ static struct hda_verb cxt5066_init_verbs_hp_laptop[] = { ...@@ -3039,20 +3059,11 @@ static struct hda_verb cxt5066_init_verbs_hp_laptop[] = {
/* initialize jack-sensing, too */ /* initialize jack-sensing, too */
static int cxt5066_init(struct hda_codec *codec) static int cxt5066_init(struct hda_codec *codec)
{ {
struct conexant_spec *spec = codec->spec;
snd_printdd("CXT5066: init\n"); snd_printdd("CXT5066: init\n");
conexant_init(codec); conexant_init(codec);
if (codec->patch_ops.unsol_event) { if (codec->patch_ops.unsol_event) {
cxt5066_hp_automute(codec); cxt5066_hp_automute(codec);
if (spec->dell_vostro) cxt5066_automic(codec);
cxt5066_vostro_automic(codec);
else if (spec->ideapad)
cxt5066_ideapad_automic(codec);
else if (spec->thinkpad)
cxt5066_thinkpad_automic(codec);
else if (spec->hp_laptop)
cxt5066_hp_laptop_automic(codec);
} }
cxt5066_set_mic_boost(codec); cxt5066_set_mic_boost(codec);
return 0; return 0;
...@@ -3080,6 +3091,7 @@ enum { ...@@ -3080,6 +3091,7 @@ enum {
CXT5066_DELL_VOSTRO, /* Dell Vostro 1015i */ CXT5066_DELL_VOSTRO, /* Dell Vostro 1015i */
CXT5066_IDEAPAD, /* Lenovo IdeaPad U150 */ CXT5066_IDEAPAD, /* Lenovo IdeaPad U150 */
CXT5066_THINKPAD, /* Lenovo ThinkPad T410s, others? */ CXT5066_THINKPAD, /* Lenovo ThinkPad T410s, others? */
CXT5066_ASUS, /* Asus K52JU, Lenovo G560 - Int mic at 0x1a and Ext mic at 0x1b */
CXT5066_HP_LAPTOP, /* HP Laptop */ CXT5066_HP_LAPTOP, /* HP Laptop */
CXT5066_MODELS CXT5066_MODELS
}; };
...@@ -3091,6 +3103,7 @@ static const char * const cxt5066_models[CXT5066_MODELS] = { ...@@ -3091,6 +3103,7 @@ static const char * const cxt5066_models[CXT5066_MODELS] = {
[CXT5066_DELL_VOSTRO] = "dell-vostro", [CXT5066_DELL_VOSTRO] = "dell-vostro",
[CXT5066_IDEAPAD] = "ideapad", [CXT5066_IDEAPAD] = "ideapad",
[CXT5066_THINKPAD] = "thinkpad", [CXT5066_THINKPAD] = "thinkpad",
[CXT5066_ASUS] = "asus",
[CXT5066_HP_LAPTOP] = "hp-laptop", [CXT5066_HP_LAPTOP] = "hp-laptop",
}; };
...@@ -3102,7 +3115,9 @@ static struct snd_pci_quirk cxt5066_cfg_tbl[] = { ...@@ -3102,7 +3115,9 @@ static struct snd_pci_quirk cxt5066_cfg_tbl[] = {
SND_PCI_QUIRK(0x1028, 0x0402, "Dell Vostro", CXT5066_DELL_VOSTRO), SND_PCI_QUIRK(0x1028, 0x0402, "Dell Vostro", CXT5066_DELL_VOSTRO),
SND_PCI_QUIRK(0x1028, 0x0408, "Dell Inspiron One 19T", CXT5066_IDEAPAD), SND_PCI_QUIRK(0x1028, 0x0408, "Dell Inspiron One 19T", CXT5066_IDEAPAD),
SND_PCI_QUIRK(0x103c, 0x360b, "HP G60", CXT5066_HP_LAPTOP), SND_PCI_QUIRK(0x103c, 0x360b, "HP G60", CXT5066_HP_LAPTOP),
SND_PCI_QUIRK(0x1043, 0x13f3, "Asus A52J", CXT5066_HP_LAPTOP), SND_PCI_QUIRK(0x1043, 0x13f3, "Asus A52J", CXT5066_ASUS),
SND_PCI_QUIRK(0x1043, 0x1643, "Asus K52JU", CXT5066_ASUS),
SND_PCI_QUIRK(0x1043, 0x1993, "Asus U50F", CXT5066_ASUS),
SND_PCI_QUIRK(0x1179, 0xff1e, "Toshiba Satellite C650D", CXT5066_IDEAPAD), SND_PCI_QUIRK(0x1179, 0xff1e, "Toshiba Satellite C650D", CXT5066_IDEAPAD),
SND_PCI_QUIRK(0x1179, 0xff50, "Toshiba Satellite P500-PSPGSC-01800T", CXT5066_OLPC_XO_1_5), SND_PCI_QUIRK(0x1179, 0xff50, "Toshiba Satellite P500-PSPGSC-01800T", CXT5066_OLPC_XO_1_5),
SND_PCI_QUIRK(0x1179, 0xffe0, "Toshiba Satellite Pro T130-15F", CXT5066_OLPC_XO_1_5), SND_PCI_QUIRK(0x1179, 0xffe0, "Toshiba Satellite Pro T130-15F", CXT5066_OLPC_XO_1_5),
...@@ -3111,7 +3126,9 @@ static struct snd_pci_quirk cxt5066_cfg_tbl[] = { ...@@ -3111,7 +3126,9 @@ static struct snd_pci_quirk cxt5066_cfg_tbl[] = {
SND_PCI_QUIRK(0x152d, 0x0833, "OLPC XO-1.5", CXT5066_OLPC_XO_1_5), SND_PCI_QUIRK(0x152d, 0x0833, "OLPC XO-1.5", CXT5066_OLPC_XO_1_5),
SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo T400s", CXT5066_THINKPAD), SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo T400s", CXT5066_THINKPAD),
SND_PCI_QUIRK(0x17aa, 0x21c5, "Thinkpad Edge 13", CXT5066_THINKPAD), SND_PCI_QUIRK(0x17aa, 0x21c5, "Thinkpad Edge 13", CXT5066_THINKPAD),
SND_PCI_QUIRK(0x17aa, 0x21c6, "Thinkpad Edge 13", CXT5066_ASUS),
SND_PCI_QUIRK(0x17aa, 0x215e, "Lenovo Thinkpad", CXT5066_THINKPAD), SND_PCI_QUIRK(0x17aa, 0x215e, "Lenovo Thinkpad", CXT5066_THINKPAD),
SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo G560", CXT5066_ASUS),
SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo", CXT5066_IDEAPAD), /* Fallback for Lenovos without dock mic */ SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo", CXT5066_IDEAPAD), /* Fallback for Lenovos without dock mic */
{} {}
}; };
...@@ -3133,7 +3150,8 @@ static int patch_cxt5066(struct hda_codec *codec) ...@@ -3133,7 +3150,8 @@ static int patch_cxt5066(struct hda_codec *codec)
spec->multiout.max_channels = 2; spec->multiout.max_channels = 2;
spec->multiout.num_dacs = ARRAY_SIZE(cxt5066_dac_nids); spec->multiout.num_dacs = ARRAY_SIZE(cxt5066_dac_nids);
spec->multiout.dac_nids = cxt5066_dac_nids; spec->multiout.dac_nids = cxt5066_dac_nids;
spec->multiout.dig_out_nid = CXT5066_SPDIF_OUT; conexant_check_dig_outs(codec, cxt5066_digout_pin_nids,
ARRAY_SIZE(cxt5066_digout_pin_nids));
spec->num_adc_nids = 1; spec->num_adc_nids = 1;
spec->adc_nids = cxt5066_adc_nids; spec->adc_nids = cxt5066_adc_nids;
spec->capsrc_nids = cxt5066_capsrc_nids; spec->capsrc_nids = cxt5066_capsrc_nids;
...@@ -3167,16 +3185,19 @@ static int patch_cxt5066(struct hda_codec *codec) ...@@ -3167,16 +3185,19 @@ static int patch_cxt5066(struct hda_codec *codec)
spec->num_init_verbs++; spec->num_init_verbs++;
spec->dell_automute = 1; spec->dell_automute = 1;
break; break;
case CXT5066_ASUS:
case CXT5066_HP_LAPTOP: case CXT5066_HP_LAPTOP:
codec->patch_ops.init = cxt5066_init; codec->patch_ops.init = cxt5066_init;
codec->patch_ops.unsol_event = cxt5066_hp_laptop_event; codec->patch_ops.unsol_event = cxt5066_unsol_event;
spec->init_verbs[spec->num_init_verbs] = spec->init_verbs[spec->num_init_verbs] =
cxt5066_init_verbs_hp_laptop; cxt5066_init_verbs_hp_laptop;
spec->num_init_verbs++; spec->num_init_verbs++;
spec->hp_laptop = 1; spec->hp_laptop = board_config == CXT5066_HP_LAPTOP;
spec->asus = board_config == CXT5066_ASUS;
spec->mixers[spec->num_mixers++] = cxt5066_mixer_master; spec->mixers[spec->num_mixers++] = cxt5066_mixer_master;
spec->mixers[spec->num_mixers++] = cxt5066_mixers; spec->mixers[spec->num_mixers++] = cxt5066_mixers;
/* no S/PDIF out */ /* no S/PDIF out */
if (board_config == CXT5066_HP_LAPTOP)
spec->multiout.dig_out_nid = 0; spec->multiout.dig_out_nid = 0;
/* input source automatically selected */ /* input source automatically selected */
spec->input_mux = NULL; spec->input_mux = NULL;
...@@ -3207,7 +3228,7 @@ static int patch_cxt5066(struct hda_codec *codec) ...@@ -3207,7 +3228,7 @@ static int patch_cxt5066(struct hda_codec *codec)
break; break;
case CXT5066_DELL_VOSTRO: case CXT5066_DELL_VOSTRO:
codec->patch_ops.init = cxt5066_init; codec->patch_ops.init = cxt5066_init;
codec->patch_ops.unsol_event = cxt5066_vostro_event; codec->patch_ops.unsol_event = cxt5066_unsol_event;
spec->init_verbs[0] = cxt5066_init_verbs_vostro; spec->init_verbs[0] = cxt5066_init_verbs_vostro;
spec->mixers[spec->num_mixers++] = cxt5066_mixer_master_olpc; spec->mixers[spec->num_mixers++] = cxt5066_mixer_master_olpc;
spec->mixers[spec->num_mixers++] = cxt5066_mixers; spec->mixers[spec->num_mixers++] = cxt5066_mixers;
...@@ -3224,7 +3245,7 @@ static int patch_cxt5066(struct hda_codec *codec) ...@@ -3224,7 +3245,7 @@ static int patch_cxt5066(struct hda_codec *codec)
break; break;
case CXT5066_IDEAPAD: case CXT5066_IDEAPAD:
codec->patch_ops.init = cxt5066_init; codec->patch_ops.init = cxt5066_init;
codec->patch_ops.unsol_event = cxt5066_ideapad_event; codec->patch_ops.unsol_event = cxt5066_unsol_event;
spec->mixers[spec->num_mixers++] = cxt5066_mixer_master; spec->mixers[spec->num_mixers++] = cxt5066_mixer_master;
spec->mixers[spec->num_mixers++] = cxt5066_mixers; spec->mixers[spec->num_mixers++] = cxt5066_mixers;
spec->init_verbs[0] = cxt5066_init_verbs_ideapad; spec->init_verbs[0] = cxt5066_init_verbs_ideapad;
...@@ -3240,7 +3261,7 @@ static int patch_cxt5066(struct hda_codec *codec) ...@@ -3240,7 +3261,7 @@ static int patch_cxt5066(struct hda_codec *codec)
break; break;
case CXT5066_THINKPAD: case CXT5066_THINKPAD:
codec->patch_ops.init = cxt5066_init; codec->patch_ops.init = cxt5066_init;
codec->patch_ops.unsol_event = cxt5066_thinkpad_event; codec->patch_ops.unsol_event = cxt5066_unsol_event;
spec->mixers[spec->num_mixers++] = cxt5066_mixer_master; spec->mixers[spec->num_mixers++] = cxt5066_mixer_master;
spec->mixers[spec->num_mixers++] = cxt5066_mixers; spec->mixers[spec->num_mixers++] = cxt5066_mixers;
spec->init_verbs[0] = cxt5066_init_verbs_thinkpad; spec->init_verbs[0] = cxt5066_init_verbs_thinkpad;
......
...@@ -92,6 +92,8 @@ struct oxygen_model { ...@@ -92,6 +92,8 @@ struct oxygen_model {
void (*update_dac_volume)(struct oxygen *chip); void (*update_dac_volume)(struct oxygen *chip);
void (*update_dac_mute)(struct oxygen *chip); void (*update_dac_mute)(struct oxygen *chip);
void (*update_center_lfe_mix)(struct oxygen *chip, bool mixed); void (*update_center_lfe_mix)(struct oxygen *chip, bool mixed);
unsigned int (*adjust_dac_routing)(struct oxygen *chip,
unsigned int play_routing);
void (*gpio_changed)(struct oxygen *chip); void (*gpio_changed)(struct oxygen *chip);
void (*uart_input)(struct oxygen *chip); void (*uart_input)(struct oxygen *chip);
void (*ac97_switch)(struct oxygen *chip, void (*ac97_switch)(struct oxygen *chip,
......
...@@ -180,6 +180,8 @@ void oxygen_update_dac_routing(struct oxygen *chip) ...@@ -180,6 +180,8 @@ void oxygen_update_dac_routing(struct oxygen *chip)
(1 << OXYGEN_PLAY_DAC1_SOURCE_SHIFT) | (1 << OXYGEN_PLAY_DAC1_SOURCE_SHIFT) |
(2 << OXYGEN_PLAY_DAC2_SOURCE_SHIFT) | (2 << OXYGEN_PLAY_DAC2_SOURCE_SHIFT) |
(3 << OXYGEN_PLAY_DAC3_SOURCE_SHIFT); (3 << OXYGEN_PLAY_DAC3_SOURCE_SHIFT);
if (chip->model.adjust_dac_routing)
reg_value = chip->model.adjust_dac_routing(chip, reg_value);
oxygen_write16_masked(chip, OXYGEN_PLAY_ROUTING, reg_value, oxygen_write16_masked(chip, OXYGEN_PLAY_ROUTING, reg_value,
OXYGEN_PLAY_DAC0_SOURCE_MASK | OXYGEN_PLAY_DAC0_SOURCE_MASK |
OXYGEN_PLAY_DAC1_SOURCE_MASK | OXYGEN_PLAY_DAC1_SOURCE_MASK |
......
...@@ -24,6 +24,11 @@ ...@@ -24,6 +24,11 @@
* *
* SPI 0 -> CS4245 * SPI 0 -> CS4245
* *
* I²S 1 -> CS4245
* I²S 2 -> CS4361 (center/LFE)
* I²S 3 -> CS4361 (surround)
* I²S 4 -> CS4361 (front)
*
* GPIO 3 <- ? * GPIO 3 <- ?
* GPIO 4 <- headphone detect * GPIO 4 <- headphone detect
* GPIO 5 -> route input jack to line-in (0) or mic-in (1) * GPIO 5 -> route input jack to line-in (0) or mic-in (1)
...@@ -36,6 +41,7 @@ ...@@ -36,6 +41,7 @@
* input 1 <- aux * input 1 <- aux
* input 2 <- front mic * input 2 <- front mic
* input 4 <- line/mic * input 4 <- line/mic
* DAC out -> headphones
* aux out -> front panel headphones * aux out -> front panel headphones
*/ */
...@@ -207,6 +213,35 @@ static void set_cs4245_adc_params(struct oxygen *chip, ...@@ -207,6 +213,35 @@ static void set_cs4245_adc_params(struct oxygen *chip,
cs4245_write_cached(chip, CS4245_ADC_CTRL, value); cs4245_write_cached(chip, CS4245_ADC_CTRL, value);
} }
static inline unsigned int shift_bits(unsigned int value,
unsigned int shift_from,
unsigned int shift_to,
unsigned int mask)
{
if (shift_from < shift_to)
return (value << (shift_to - shift_from)) & mask;
else
return (value >> (shift_from - shift_to)) & mask;
}
static unsigned int adjust_dg_dac_routing(struct oxygen *chip,
unsigned int play_routing)
{
return (play_routing & OXYGEN_PLAY_DAC0_SOURCE_MASK) |
shift_bits(play_routing,
OXYGEN_PLAY_DAC2_SOURCE_SHIFT,
OXYGEN_PLAY_DAC1_SOURCE_SHIFT,
OXYGEN_PLAY_DAC1_SOURCE_MASK) |
shift_bits(play_routing,
OXYGEN_PLAY_DAC1_SOURCE_SHIFT,
OXYGEN_PLAY_DAC2_SOURCE_SHIFT,
OXYGEN_PLAY_DAC2_SOURCE_MASK) |
shift_bits(play_routing,
OXYGEN_PLAY_DAC0_SOURCE_SHIFT,
OXYGEN_PLAY_DAC3_SOURCE_SHIFT,
OXYGEN_PLAY_DAC3_SOURCE_MASK);
}
static int output_switch_info(struct snd_kcontrol *ctl, static int output_switch_info(struct snd_kcontrol *ctl,
struct snd_ctl_elem_info *info) struct snd_ctl_elem_info *info)
{ {
...@@ -557,6 +592,7 @@ struct oxygen_model model_xonar_dg = { ...@@ -557,6 +592,7 @@ struct oxygen_model model_xonar_dg = {
.resume = dg_resume, .resume = dg_resume,
.set_dac_params = set_cs4245_dac_params, .set_dac_params = set_cs4245_dac_params,
.set_adc_params = set_cs4245_adc_params, .set_adc_params = set_cs4245_adc_params,
.adjust_dac_routing = adjust_dg_dac_routing,
.dump_registers = dump_cs4245_registers, .dump_registers = dump_cs4245_registers,
.model_data_size = sizeof(struct dg), .model_data_size = sizeof(struct dg),
.device_config = PLAYBACK_0_TO_I2S | .device_config = PLAYBACK_0_TO_I2S |
......
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
#define __PDAUDIOCF_H #define __PDAUDIOCF_H
#include <sound/pcm.h> #include <sound/pcm.h>
#include <asm/io.h> #include <linux/io.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <pcmcia/cistpl.h> #include <pcmcia/cistpl.h>
#include <pcmcia/ds.h> #include <pcmcia/ds.h>
......
...@@ -23,8 +23,8 @@ ...@@ -23,8 +23,8 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/firmware.h> #include <linux/firmware.h>
#include <linux/io.h>
#include <sound/core.h> #include <sound/core.h>
#include <asm/io.h>
#include "vxpocket.h" #include "vxpocket.h"
......
...@@ -153,7 +153,7 @@ static int cq93vc_resume(struct snd_soc_codec *codec) ...@@ -153,7 +153,7 @@ static int cq93vc_resume(struct snd_soc_codec *codec)
static int cq93vc_probe(struct snd_soc_codec *codec) static int cq93vc_probe(struct snd_soc_codec *codec)
{ {
struct davinci_vc *davinci_vc = codec->dev->platform_data; struct davinci_vc *davinci_vc = snd_soc_codec_get_drvdata(codec);
davinci_vc->cq93vc.codec = codec; davinci_vc->cq93vc.codec = codec;
codec->control_data = davinci_vc; codec->control_data = davinci_vc;
......
...@@ -367,9 +367,12 @@ static int cx20442_codec_remove(struct snd_soc_codec *codec) ...@@ -367,9 +367,12 @@ static int cx20442_codec_remove(struct snd_soc_codec *codec)
return 0; return 0;
} }
static const u8 cx20442_reg = CX20442_TELOUT | CX20442_MIC;
static struct snd_soc_codec_driver cx20442_codec_dev = { static struct snd_soc_codec_driver cx20442_codec_dev = {
.probe = cx20442_codec_probe, .probe = cx20442_codec_probe,
.remove = cx20442_codec_remove, .remove = cx20442_codec_remove,
.reg_cache_default = &cx20442_reg,
.reg_cache_size = 1, .reg_cache_size = 1,
.reg_word_size = sizeof(u8), .reg_word_size = sizeof(u8),
.read = cx20442_read_reg_cache, .read = cx20442_read_reg_cache,
......
...@@ -507,8 +507,6 @@ static int ams_delta_cx20442_init(struct snd_soc_pcm_runtime *rtd) ...@@ -507,8 +507,6 @@ static int ams_delta_cx20442_init(struct snd_soc_pcm_runtime *rtd)
/* Set up digital mute if not provided by the codec */ /* Set up digital mute if not provided by the codec */
if (!codec_dai->driver->ops) { if (!codec_dai->driver->ops) {
codec_dai->driver->ops = &ams_delta_dai_ops; codec_dai->driver->ops = &ams_delta_dai_ops;
} else if (!codec_dai->driver->ops->digital_mute) {
codec_dai->driver->ops->digital_mute = ams_delta_digital_mute;
} else { } else {
ams_delta_ops.startup = ams_delta_startup; ams_delta_ops.startup = ams_delta_startup;
ams_delta_ops.shutdown = ams_delta_shutdown; ams_delta_ops.shutdown = ams_delta_shutdown;
......
...@@ -1664,9 +1664,6 @@ static int soc_probe_aux_dev(struct snd_soc_card *card, int num) ...@@ -1664,9 +1664,6 @@ static int soc_probe_aux_dev(struct snd_soc_card *card, int num)
goto out; goto out;
found: found:
if (!try_module_get(codec->dev->driver->owner))
return -ENODEV;
ret = soc_probe_codec(card, codec); ret = soc_probe_codec(card, codec);
if (ret < 0) if (ret < 0)
return ret; return ret;
......
...@@ -1742,7 +1742,7 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol, ...@@ -1742,7 +1742,7 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol,
int max = mc->max; int max = mc->max;
unsigned int mask = (1 << fls(max)) - 1; unsigned int mask = (1 << fls(max)) - 1;
unsigned int invert = mc->invert; unsigned int invert = mc->invert;
unsigned int val, val_mask; unsigned int val;
int connect, change; int connect, change;
struct snd_soc_dapm_update update; struct snd_soc_dapm_update update;
...@@ -1750,13 +1750,13 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol, ...@@ -1750,13 +1750,13 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol,
if (invert) if (invert)
val = max - val; val = max - val;
val_mask = mask << shift; mask = mask << shift;
val = val << shift; val = val << shift;
mutex_lock(&widget->codec->mutex); mutex_lock(&widget->codec->mutex);
widget->value = val; widget->value = val;
change = snd_soc_test_bits(widget->codec, reg, val_mask, val); change = snd_soc_test_bits(widget->codec, reg, mask, val);
if (change) { if (change) {
if (val) if (val)
/* new connection */ /* new connection */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment