]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/commitdiff
Merge branches 'topic/asoc', 'topic/misc-fixes', 'topic/ps3-csbits' and 'topic/stagin...
authorTakashi Iwai <tiwai@suse.de>
Mon, 20 Oct 2008 15:06:00 +0000 (17:06 +0200)
committerTakashi Iwai <tiwai@suse.de>
Mon, 20 Oct 2008 15:06:00 +0000 (17:06 +0200)
arch/powerpc/include/asm/ps3av.h
drivers/ps3/ps3av.c
drivers/ps3/ps3av_cmd.c
sound/core/pcm_misc.c
sound/drivers/dummy.c
sound/pci/ca0106/ca0106_main.c
sound/ppc/snd_ps3.c
sound/ppc/snd_ps3.h
sound/soc/omap/omap-mcbsp.c

index fda98715cd356a4b74a18e66c860c81ed62ee50a..5aa22cffdbd658d02c616ba822e3071ac642e3ac 100644 (file)
@@ -678,6 +678,8 @@ struct ps3av_pkt_avb_param {
        u8 buf[PS3AV_PKT_AVB_PARAM_MAX_BUF_SIZE];
 };
 
+/* channel status */
+extern u8 ps3av_mode_cs_info[];
 
 /** command status **/
 #define PS3AV_STATUS_SUCCESS                   0x0000  /* success */
@@ -735,6 +737,7 @@ extern int ps3av_get_mode(void);
 extern int ps3av_video_mode2res(u32, u32 *, u32 *);
 extern int ps3av_video_mute(int);
 extern int ps3av_audio_mute(int);
+extern int ps3av_audio_mute_analog(int);
 extern int ps3av_dev_open(void);
 extern int ps3av_dev_close(void);
 extern void ps3av_register_flip_ctl(void (*flip_ctl)(int on, void *data),
index 6f2f90ebb020db95256f2bc135414ada5ca77d83..06848b254d5752d3a5d40ad2a68b8c4bb686b01e 100644 (file)
@@ -915,6 +915,22 @@ int ps3av_video_mute(int mute)
 
 EXPORT_SYMBOL_GPL(ps3av_video_mute);
 
+/* mute analog output only */
+int ps3av_audio_mute_analog(int mute)
+{
+       int i, res;
+
+       for (i = 0; i < ps3av->av_hw_conf.num_of_avmulti; i++) {
+               res = ps3av_cmd_av_audio_mute(1,
+                       &ps3av->av_port[i + ps3av->av_hw_conf.num_of_hdmi],
+                       mute);
+               if (res < 0)
+                       return -1;
+       }
+       return 0;
+}
+EXPORT_SYMBOL_GPL(ps3av_audio_mute_analog);
+
 int ps3av_audio_mute(int mute)
 {
        return ps3av_set_audio_mute(mute ? PS3AV_CMD_MUTE_ON
index 7f880c26122f36a11b7390a14587693f10898229..11eb50318fec9ce093e6b9ef99e6fd858c4ead20 100644 (file)
@@ -660,9 +660,10 @@ u32 ps3av_cmd_set_av_audio_param(void *p, u32 port,
 }
 
 /* default cs val */
-static const u8 ps3av_mode_cs_info[] = {
+u8 ps3av_mode_cs_info[] = {
        0x00, 0x09, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00
 };
+EXPORT_SYMBOL_GPL(ps3av_mode_cs_info);
 
 #define CS_44  0x00
 #define CS_48  0x02
@@ -677,7 +678,7 @@ void ps3av_cmd_set_audio_mode(struct ps3av_pkt_audio_mode *audio, u32 avport,
                              u32 ch, u32 fs, u32 word_bits, u32 format,
                              u32 source)
 {
-       int spdif_through, spdif_bitstream;
+       int spdif_through;
        int i;
 
        if (!(ch | fs | format | word_bits | source)) {
@@ -687,7 +688,6 @@ void ps3av_cmd_set_audio_mode(struct ps3av_pkt_audio_mode *audio, u32 avport,
                format = PS3AV_CMD_AUDIO_FORMAT_PCM;
                source = PS3AV_CMD_AUDIO_SOURCE_SERIAL;
        }
-       spdif_through = spdif_bitstream = 0;    /* XXX not supported */
 
        /* audio mode */
        memset(audio, 0, sizeof(*audio));
@@ -777,16 +777,17 @@ void ps3av_cmd_set_audio_mode(struct ps3av_pkt_audio_mode *audio, u32 avport,
                break;
        }
 
+       /* non-audio bit */
+       spdif_through = audio->audio_cs_info[0] & 0x02;
+
        /* pass through setting */
        if (spdif_through &&
            (avport == PS3AV_CMD_AVPORT_SPDIF_0 ||
-            avport == PS3AV_CMD_AVPORT_SPDIF_1)) {
+            avport == PS3AV_CMD_AVPORT_SPDIF_1 ||
+            avport == PS3AV_CMD_AVPORT_HDMI_0 ||
+            avport == PS3AV_CMD_AVPORT_HDMI_1)) {
                audio->audio_word_bits = PS3AV_CMD_AUDIO_WORD_BITS_16;
-               audio->audio_source = PS3AV_CMD_AUDIO_SOURCE_SPDIF;
-               if (spdif_bitstream) {
-                       audio->audio_format = PS3AV_CMD_AUDIO_FORMAT_BITSTREAM;
-                       audio->audio_cs_info[0] |= CS_BIT;
-               }
+               audio->audio_format = PS3AV_CMD_AUDIO_FORMAT_BITSTREAM;
        }
 }
 
index 89b7f549bebd772bb62378510a541bb0b052e967..ea2bf82c93730505768c28f00174d6484ac2bcf9 100644 (file)
@@ -319,6 +319,7 @@ EXPORT_SYMBOL(snd_pcm_format_physical_width);
 /**
  * snd_pcm_format_size - return the byte size of samples on the given format
  * @format: the format to check
+ * @samples: sampling rate
  *
  * Returns the byte size of the given samples for the format, or a
  * negative error code if unknown format.
index e5e749f3e0ef08df9fea76571c6a552a2724e388..73be7e14a603d56208aec9d9bd741b48c5444750 100644 (file)
@@ -51,7 +51,7 @@ static int emu10k1_playback_constraints(struct snd_pcm_runtime *runtime)
        if (err < 0)
                return err;
        err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 256, UINT_MAX);
-       if (err) < 0)
+       if (err < 0)
                return err;
        return 0;
 }
index a7d89662acf66e200c5305ac409fd3bfd7188500..88fbf285d2b74ea6cf1ccc701398d0e730784840 100644 (file)
@@ -759,7 +759,6 @@ static int snd_ca0106_pcm_prepare_playback(struct snd_pcm_substream *substream)
                               SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC |
                               SPCS_GENERATIONSTATUS | 0x00001200 |
                               0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT );
-       }
 #endif
 
        return 0;
index 20d0e328288ab6ae4ea24abe202b6a3d0dd3d442..8f9e3859c37ca70f802fdb5c3f8f25ed75731b8d 100644 (file)
@@ -666,6 +666,7 @@ static int snd_ps3_init_avsetting(struct snd_ps3_card_info *card)
        card->avs.avs_audio_width = PS3AV_CMD_AUDIO_WORD_BITS_16;
        card->avs.avs_audio_format = PS3AV_CMD_AUDIO_FORMAT_PCM;
        card->avs.avs_audio_source = PS3AV_CMD_AUDIO_SOURCE_SERIAL;
+       memcpy(card->avs.avs_cs_info, ps3av_mode_cs_info, 8);
 
        ret = snd_ps3_change_avsetting(card);
 
@@ -685,6 +686,7 @@ static int snd_ps3_set_avsetting(struct snd_pcm_substream *substream)
 {
        struct snd_ps3_card_info *card = snd_pcm_substream_chip(substream);
        struct snd_ps3_avsetting_info avs;
+       int ret;
 
        avs = card->avs;
 
@@ -729,19 +731,92 @@ static int snd_ps3_set_avsetting(struct snd_pcm_substream *substream)
                return 1;
        }
 
-       if ((card->avs.avs_audio_width != avs.avs_audio_width) ||
-           (card->avs.avs_audio_rate != avs.avs_audio_rate)) {
-               card->avs = avs;
-               snd_ps3_change_avsetting(card);
+       memcpy(avs.avs_cs_info, ps3av_mode_cs_info, 8);
 
+       if (memcmp(&card->avs, &avs, sizeof(avs))) {
                pr_debug("%s: after freq=%d width=%d\n", __func__,
                         card->avs.avs_audio_rate, card->avs.avs_audio_width);
 
-               return 0;
+               card->avs = avs;
+               snd_ps3_change_avsetting(card);
+               ret = 0;
        } else
+               ret = 1;
+
+       /* check CS non-audio bit and mute accordingly */
+       if (avs.avs_cs_info[0] & 0x02)
+               ps3av_audio_mute_analog(1); /* mute if non-audio */
+       else
+               ps3av_audio_mute_analog(0);
+
+       return ret;
+}
+
+/*
+ * SPDIF status bits controls
+ */
+static int snd_ps3_spdif_mask_info(struct snd_kcontrol *kcontrol,
+                                  struct snd_ctl_elem_info *uinfo)
+{
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
+       uinfo->count = 1;
+       return 0;
+}
+
+/* FIXME: ps3av_set_audio_mode() assumes only consumer mode */
+static int snd_ps3_spdif_cmask_get(struct snd_kcontrol *kcontrol,
+                                  struct snd_ctl_elem_value *ucontrol)
+{
+       memset(ucontrol->value.iec958.status, 0xff, 8);
+       return 0;
+}
+
+static int snd_ps3_spdif_pmask_get(struct snd_kcontrol *kcontrol,
+                                  struct snd_ctl_elem_value *ucontrol)
+{
+       return 0;
+}
+
+static int snd_ps3_spdif_default_get(struct snd_kcontrol *kcontrol,
+                                    struct snd_ctl_elem_value *ucontrol)
+{
+       memcpy(ucontrol->value.iec958.status, ps3av_mode_cs_info, 8);
+       return 0;
+}
+
+static int snd_ps3_spdif_default_put(struct snd_kcontrol *kcontrol,
+                                    struct snd_ctl_elem_value *ucontrol)
+{
+       if (memcmp(ps3av_mode_cs_info, ucontrol->value.iec958.status, 8)) {
+               memcpy(ps3av_mode_cs_info, ucontrol->value.iec958.status, 8);
                return 1;
+       }
+       return 0;
 }
 
+static struct snd_kcontrol_new spdif_ctls[] = {
+       {
+               .access = SNDRV_CTL_ELEM_ACCESS_READ,
+               .iface = SNDRV_CTL_ELEM_IFACE_PCM,
+               .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,CON_MASK),
+               .info = snd_ps3_spdif_mask_info,
+               .get = snd_ps3_spdif_cmask_get,
+       },
+       {
+               .access = SNDRV_CTL_ELEM_ACCESS_READ,
+               .iface = SNDRV_CTL_ELEM_IFACE_PCM,
+               .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PRO_MASK),
+               .info = snd_ps3_spdif_mask_info,
+               .get = snd_ps3_spdif_pmask_get,
+       },
+       {
+               .iface = SNDRV_CTL_ELEM_IFACE_PCM,
+               .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
+               .info = snd_ps3_spdif_mask_info,
+               .get = snd_ps3_spdif_default_get,
+               .put = snd_ps3_spdif_default_put,
+       },
+};
 
 
 static int snd_ps3_map_mmio(void)
@@ -842,7 +917,7 @@ static void snd_ps3_audio_set_base_addr(uint64_t ioaddr_start)
 
 static int __init snd_ps3_driver_probe(struct ps3_system_bus_device *dev)
 {
-       int ret;
+       int i, ret;
        u64 lpar_addr, lpar_size;
 
        BUG_ON(!firmware_has_feature(FW_FEATURE_PS3_LV1));
@@ -903,6 +978,15 @@ static int __init snd_ps3_driver_probe(struct ps3_system_bus_device *dev)
        strcpy(the_card.card->driver, "PS3");
        strcpy(the_card.card->shortname, "PS3");
        strcpy(the_card.card->longname, "PS3 sound");
+
+       /* create control elements */
+       for (i = 0; i < ARRAY_SIZE(spdif_ctls); i++) {
+               ret = snd_ctl_add(the_card.card,
+                                 snd_ctl_new1(&spdif_ctls[i], &the_card));
+               if (ret < 0)
+                       goto clean_card;
+       }
+
        /* create PCM devices instance */
        /* NOTE:this driver works assuming pcm:substream = 1:1 */
        ret = snd_pcm_new(the_card.card,
index 4b7e6fbbe5005769b6dbd059d1181ec5f5d44873..326fb29e82d842e43f4159fe94372b49f49b03b8 100644 (file)
@@ -51,6 +51,7 @@ struct snd_ps3_avsetting_info {
        uint32_t avs_audio_width;
        uint32_t avs_audio_format; /* fixed */
        uint32_t avs_audio_source; /* fixed */
+       unsigned char avs_cs_info[8];
 };
 /*
  * PS3 audio 'card' instance
index 0a063a98a6613820295419a5cab10bd09a8dc338..853b33ae3435297f414eaee086b31bdf6a4b1333 100644 (file)
@@ -43,6 +43,7 @@
 struct omap_mcbsp_data {
        unsigned int                    bus_id;
        struct omap_mcbsp_reg_cfg       regs;
+       unsigned int                    fmt;
        /*
         * Flags indicating is the bus already activated and configured by
         * another substream
@@ -200,6 +201,7 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
        struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
        struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs;
        int dma, bus_id = mcbsp_data->bus_id, id = cpu_dai->id;
+       int wlen;
        unsigned long port;
 
        if (cpu_class_is_omap1()) {
@@ -244,19 +246,29 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
        switch (params_format(params)) {
        case SNDRV_PCM_FORMAT_S16_LE:
                /* Set word lengths */
+               wlen = 16;
                regs->rcr2      |= RWDLEN2(OMAP_MCBSP_WORD_16);
                regs->rcr1      |= RWDLEN1(OMAP_MCBSP_WORD_16);
                regs->xcr2      |= XWDLEN2(OMAP_MCBSP_WORD_16);
                regs->xcr1      |= XWDLEN1(OMAP_MCBSP_WORD_16);
-               /* Set FS period and length in terms of bit clock periods */
-               regs->srgr2     |= FPER(16 * 2 - 1);
-               regs->srgr1     |= FWID(16 - 1);
                break;
        default:
                /* Unsupported PCM format */
                return -EINVAL;
        }
 
+       /* Set FS period and length in terms of bit clock periods */
+       switch (mcbsp_data->fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+       case SND_SOC_DAIFMT_I2S:
+               regs->srgr2     |= FPER(wlen * 2 - 1);
+               regs->srgr1     |= FWID(wlen - 1);
+               break;
+       case SND_SOC_DAIFMT_DSP_A:
+               regs->srgr2     |= FPER(wlen * 2 - 1);
+               regs->srgr1     |= FWID(0);
+               break;
+       }
+
        omap_mcbsp_config(bus_id, &mcbsp_data->regs);
        mcbsp_data->configured = 1;
 
@@ -272,10 +284,12 @@ static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai,
 {
        struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
        struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs;
+       unsigned int temp_fmt = fmt;
 
        if (mcbsp_data->configured)
                return 0;
 
+       mcbsp_data->fmt = fmt;
        memset(regs, 0, sizeof(*regs));
        /* Generic McBSP register settings */
        regs->spcr2     |= XINTM(3) | FREE;
@@ -293,6 +307,8 @@ static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai,
                /* 0-bit data delay */
                regs->rcr2      |= RDATDLY(0);
                regs->xcr2      |= XDATDLY(0);
+               /* Invert bit clock and FS polarity configuration for DSP_A */
+               temp_fmt ^= SND_SOC_DAIFMT_IB_IF;
                break;
        default:
                /* Unsupported data format */
@@ -316,7 +332,7 @@ static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai,
        }
 
        /* Set bit clock (CLKX/CLKR) and FS polarities */
-       switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+       switch (temp_fmt & SND_SOC_DAIFMT_INV_MASK) {
        case SND_SOC_DAIFMT_NB_NF:
                /*
                 * Normal BCLK + FS.