diff --git a/Documentation/devicetree/bindings/sound/simple-card.txt b/Documentation/devicetree/bindings/sound/simple-card.txt index 131aa2ad7f1a..9b9df146fd1a 100644 --- a/Documentation/devicetree/bindings/sound/simple-card.txt +++ b/Documentation/devicetree/bindings/sound/simple-card.txt @@ -1,6 +1,6 @@ Simple-Card: -Simple-Card specifies audio DAI connection of SoC <-> codec. +Simple-Card specifies audio DAI connections of SoC <-> codec. Required properties: @@ -10,26 +10,51 @@ Optional properties: - simple-audio-card,name : User specified audio sound card name, one string property. -- simple-audio-card,format : CPU/CODEC common audio format. - "i2s", "right_j", "left_j" , "dsp_a" - "dsp_b", "ac97", "pdm", "msb", "lsb" - simple-audio-card,widgets : Please refer to widgets.txt. - simple-audio-card,routing : A list of the connections between audio components. Each entry is a pair of strings, the first being the connection's sink, the second being the connection's source. -- dai-tdm-slot-num : Please refer to tdm-slot.txt. -- dai-tdm-slot-width : Please refer to tdm-slot.txt. +Optional subnodes: -Required subnodes: +- simple-audio-card,dai-link : Container for dai-link level + properties and the CPU and CODEC + sub-nodes. This container may be + omitted when the card has only one + DAI link. See the examples and the + section bellow. -- simple-audio-card,dai-link : container for the CPU and CODEC sub-nodes - This container may be omitted when the - card has only one DAI link. - See the examples. +Dai-link subnode properties and subnodes: -- simple-audio-card,cpu : CPU sub-node -- simple-audio-card,codec : CODEC sub-node +If dai-link subnode is omitted and the subnode properties are directly +under "sound"-node the subnode property and subnode names have to be +prefixed with "simple-audio-card,"-prefix. + +Required dai-link subnodes: + +- cpu : CPU sub-node +- codec : CODEC sub-node + +Optional dai-link subnode properties: + +- format : CPU/CODEC common audio format. + "i2s", "right_j", "left_j" , "dsp_a" + "dsp_b", "ac97", "pdm", "msb", "lsb" +- frame-master : Indicates dai-link frame master. + phandle to a cpu or codec subnode. +- bitclock-master : Indicates dai-link bit clock master. + phandle to a cpu or codec subnode. +- bitclock-inversion : bool property. Add this if the + dai-link uses bit clock inversion. +- frame-inversion : bool property. Add this if the + dai-link uses frame clock inversion. + +For backward compatibility the frame-master and bitclock-master +properties can be used as booleans in codec subnode to indicate if the +codec is the dai-link frame or bit clock master. In this case there +should be no dai-link node, the same properties should not be present +at sound-node level, and the bitclock-inversion and frame-inversion +properties should also be placed in the codec node if needed. Required CPU/CODEC subnodes properties: @@ -37,29 +62,21 @@ Required CPU/CODEC subnodes properties: Optional CPU/CODEC subnodes properties: -- format : CPU/CODEC specific audio format if needed. - see simple-audio-card,format -- frame-master : bool property. add this if subnode is frame master -- bitclock-master : bool property. add this if subnode is bitclock master -- bitclock-inversion : bool property. add this if subnode has clock inversion -- frame-inversion : bool property. add this if subnode has frame inversion +- dai-tdm-slot-num : Please refer to tdm-slot.txt. +- dai-tdm-slot-width : Please refer to tdm-slot.txt. - clocks / system-clock-frequency : specify subnode's clock if needed. it can be specified via "clocks" if system has clock node (= common clock), or "system-clock-frequency" (if system doens't support common clock) -Note: - * For 'format', 'frame-master', 'bitclock-master', 'bitclock-inversion' and - 'frame-inversion', the simple card will use the settings of CODEC for both - CPU and CODEC sides as we need to keep the settings identical for both ends - of the link. - Example 1 - single DAI link: sound { compatible = "simple-audio-card"; simple-audio-card,name = "VF610-Tower-Sound-Card"; simple-audio-card,format = "left_j"; + simple-audio-card,bitclock-master = <&dailink0_master>; + simple-audio-card,frame-master = <&dailink0_master>; simple-audio-card,widgets = "Microphone", "Microphone Jack", "Headphone", "Headphone Jack", @@ -69,17 +86,12 @@ sound { "Headphone Jack", "HP_OUT", "External Speaker", "LINE_OUT"; - dai-tdm-slot-num = <2>; - dai-tdm-slot-width = <8>; - simple-audio-card,cpu { sound-dai = <&sh_fsi2 0>; }; - simple-audio-card,codec { + dailink0_master: simple-audio-card,codec { sound-dai = <&ak4648>; - bitclock-master; - frame-master; clocks = <&osc>; }; }; @@ -105,31 +117,31 @@ Example 2 - many DAI links: sound { compatible = "simple-audio-card"; simple-audio-card,name = "Cubox Audio"; - simple-audio-card,format = "i2s"; simple-audio-card,dai-link@0 { /* I2S - HDMI */ - simple-audio-card,cpu { + format = "i2s"; + cpu { sound-dai = <&audio1 0>; }; - simple-audio-card,codec { + codec { sound-dai = <&tda998x 0>; }; }; simple-audio-card,dai-link@1 { /* S/PDIF - HDMI */ - simple-audio-card,cpu { + cpu { sound-dai = <&audio1 1>; }; - simple-audio-card,codec { + codec { sound-dai = <&tda998x 1>; }; }; simple-audio-card,dai-link@2 { /* S/PDIF - S/PDIF */ - simple-audio-card,cpu { + cpu { sound-dai = <&audio1 1>; }; - simple-audio-card,codec { + codec { sound-dai = <&spdif_codec>; }; }; diff --git a/Documentation/devicetree/bindings/sound/snow.txt b/Documentation/devicetree/bindings/sound/snow.txt new file mode 100644 index 000000000000..678b191c37b8 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/snow.txt @@ -0,0 +1,17 @@ +Audio Binding for Snow boards + +Required properties: +- compatible : Can be one of the following, + "google,snow-audio-max98090" or + "google,snow-audio-max98095" +- samsung,i2s-controller: The phandle of the Samsung I2S controller +- samsung,audio-codec: The phandle of the audio codec + +Example: + +sound { + compatible = "google,snow-audio-max98095"; + + samsung,i2s-controller = <&i2s0>; + samsung,audio-codec = <&max98095>; +}; diff --git a/Documentation/devicetree/bindings/sound/st,sta350.txt b/Documentation/devicetree/bindings/sound/st,sta350.txt index 950188891abd..b7e71bf5caf4 100644 --- a/Documentation/devicetree/bindings/sound/st,sta350.txt +++ b/Documentation/devicetree/bindings/sound/st,sta350.txt @@ -25,6 +25,7 @@ Optional properties: 2: 2 Channel (Full-Bridge) Power, 1 Channel FFX 3: 1 Channel Mono-Parallel If parameter is missing, mode 0 will be enabled. + This property has to be specified as '/bits/ 8' value. - st,ch1-output-mapping: Channel 1 output mapping - st,ch2-output-mapping: Channel 2 output mapping @@ -33,6 +34,7 @@ Optional properties: 1: Channel 2 2: Channel 3 If parameter is missing, channel 1 is choosen. + This properties have to be specified as '/bits/ 8' values. - st,thermal-warning-recover: If present, thermal warning recovery is enabled. @@ -82,9 +84,31 @@ Optional properties: If not present, preset DC coefficient is used. - st,invalid-input-detect-mute: - If not present, automatic invalid input detect mute is enabled. + If present, automatic invalid input detect mute is enabled. + - st,activate-mute-output: + If present, a mute output will be activated in ase the volume will + reach a value lower than -76 dBFS. + - st,bridge-immediate-off: + If present, the bridge will be switched off immediately after the + power-down-gpio goes low. Otherwise, the bridge will wait for 13 + million clock cycles to pass before shutting down. + + - st,noise-shape-dc-cut: + If present, the noise-shaping technique on the DC cutoff filter are + enabled. + + - st,powerdown-master-volume: + If present, the power-down pin and I2C power-down functions will + act on the master volume. Otherwise, the functions will act on the + mute commands. + + - st,powerdown-delay-divider: + If present, the bridge power-down time will be divided by the provided + value. If not specified, a divider of 1 will be used. Allowed values + are 1, 2, 4, 8, 16, 32, 64 and 128. + This property has to be specified as '/bits/ 8' value. Example: @@ -93,12 +117,12 @@ codec: sta350@38 { reg = <0x1c>; reset-gpios = <&gpio1 19 0>; power-down-gpios = <&gpio1 16 0>; - st,output-conf = <0x3>; // set output to 2-channel + st,output-conf = /bits/ 8 <0x3>; // set output to 2-channel // (full-bridge) power, // 2-channel data-out - st,ch1-output-mapping = <0>; // set channel 1 output ch 1 - st,ch2-output-mapping = <0>; // set channel 2 output ch 1 - st,ch3-output-mapping = <0>; // set channel 3 output ch 1 + st,ch1-output-mapping = /bits/ 8 <0>; // set channel 1 output ch 1 + st,ch2-output-mapping = /bits/ 8 <0>; // set channel 2 output ch 1 + st,ch3-output-mapping = /bits/ 8 <0>; // set channel 3 output ch 1 st,max-power-correction; // enables power bridge // correction for THD reduction // near maximum power output diff --git a/include/sound/soc.h b/include/sound/soc.h index df7ae9ca4854..dcdcc95efd1d 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -1326,7 +1326,9 @@ int snd_soc_of_parse_tdm_slot(struct device_node *np, int snd_soc_of_parse_audio_routing(struct snd_soc_card *card, const char *propname); unsigned int snd_soc_of_parse_daifmt(struct device_node *np, - const char *prefix); + const char *prefix, + struct device_node **bitclkmaster, + struct device_node **framemaster); int snd_soc_of_get_dai_name(struct device_node *of_node, const char **dai_name); diff --git a/include/sound/sta350.h b/include/sound/sta350.h index 3a3298106b22..42edceb096a0 100644 --- a/include/sound/sta350.h +++ b/include/sound/sta350.h @@ -37,6 +37,7 @@ struct sta350_platform_data { u8 ch3_output_mapping; u8 ffx_power_output_mode; u8 drop_compensation_ns; + u8 powerdown_delay_divider; unsigned int thermal_warning_recovery:1; unsigned int thermal_warning_adjustment:1; unsigned int fault_detect_recovery:1; @@ -47,6 +48,10 @@ struct sta350_platform_data { unsigned int odd_pwm_speed_mode:1; unsigned int distortion_compensation:1; unsigned int invalid_input_detect_mute:1; + unsigned int activate_mute_output:1; + unsigned int bridge_immediate_off:1; + unsigned int noise_shape_dc_cut:1; + unsigned int powerdown_master_vol:1; }; #endif /* __LINUX_SND__STA350_H */ diff --git a/sound/soc/codecs/rt5651.c b/sound/soc/codecs/rt5651.c index f785b81238ae..9c88d89f41f0 100644 --- a/sound/soc/codecs/rt5651.c +++ b/sound/soc/codecs/rt5651.c @@ -1368,8 +1368,7 @@ static int get_clk_info(int sclk, int rate) static int rt5651_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; + struct snd_soc_codec *codec = dai->codec; struct rt5651_priv *rt5651 = snd_soc_codec_get_drvdata(codec); unsigned int val_len = 0, val_clk, mask_clk; int pre_div, bclk_ms, frame_size; diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c index b56caefcf664..9626ee0417cd 100644 --- a/sound/soc/codecs/sgtl5000.c +++ b/sound/soc/codecs/sgtl5000.c @@ -1322,7 +1322,7 @@ static int sgtl5000_enable_regulators(struct snd_soc_codec *codec) return ret; } - ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(sgtl5000->supplies), + ret = devm_regulator_bulk_get(codec->dev, ARRAY_SIZE(sgtl5000->supplies), sgtl5000->supplies); if (ret) goto err_ldo_remove; @@ -1330,16 +1330,13 @@ static int sgtl5000_enable_regulators(struct snd_soc_codec *codec) ret = regulator_bulk_enable(ARRAY_SIZE(sgtl5000->supplies), sgtl5000->supplies); if (ret) - goto err_regulator_free; + goto err_ldo_remove; /* wait for all power rails bring up */ udelay(10); return 0; -err_regulator_free: - regulator_bulk_free(ARRAY_SIZE(sgtl5000->supplies), - sgtl5000->supplies); err_ldo_remove: if (!external_vddd) ldo_regulator_remove(codec); @@ -1409,8 +1406,6 @@ static int sgtl5000_probe(struct snd_soc_codec *codec) err: regulator_bulk_disable(ARRAY_SIZE(sgtl5000->supplies), sgtl5000->supplies); - regulator_bulk_free(ARRAY_SIZE(sgtl5000->supplies), - sgtl5000->supplies); ldo_regulator_remove(codec); return ret; @@ -1424,8 +1419,6 @@ static int sgtl5000_remove(struct snd_soc_codec *codec) regulator_bulk_disable(ARRAY_SIZE(sgtl5000->supplies), sgtl5000->supplies); - regulator_bulk_free(ARRAY_SIZE(sgtl5000->supplies), - sgtl5000->supplies); ldo_regulator_remove(codec); return 0; diff --git a/sound/soc/codecs/sirf-audio-codec.c b/sound/soc/codecs/sirf-audio-codec.c index 58e7c1f23771..c5177bc5df82 100644 --- a/sound/soc/codecs/sirf-audio-codec.c +++ b/sound/soc/codecs/sirf-audio-codec.c @@ -279,13 +279,63 @@ static const struct snd_soc_dapm_route sirf_audio_codec_map[] = { {"Mic input mode mux", "Differential", "MICIN1"}, }; +static void sirf_audio_codec_tx_enable(struct sirf_audio_codec *sirf_audio_codec) +{ + regmap_update_bits(sirf_audio_codec->regmap, AUDIO_PORT_IC_TXFIFO_OP, + AUDIO_FIFO_RESET, AUDIO_FIFO_RESET); + regmap_update_bits(sirf_audio_codec->regmap, AUDIO_PORT_IC_TXFIFO_OP, + AUDIO_FIFO_RESET, ~AUDIO_FIFO_RESET); + regmap_write(sirf_audio_codec->regmap, AUDIO_PORT_IC_TXFIFO_INT_MSK, 0); + regmap_write(sirf_audio_codec->regmap, AUDIO_PORT_IC_TXFIFO_OP, 0); + regmap_update_bits(sirf_audio_codec->regmap, AUDIO_PORT_IC_TXFIFO_OP, + AUDIO_FIFO_START, AUDIO_FIFO_START); + regmap_update_bits(sirf_audio_codec->regmap, + AUDIO_PORT_IC_CODEC_TX_CTRL, IC_TX_ENABLE, IC_TX_ENABLE); +} + +static void sirf_audio_codec_tx_disable(struct sirf_audio_codec *sirf_audio_codec) +{ + regmap_write(sirf_audio_codec->regmap, AUDIO_PORT_IC_TXFIFO_OP, 0); + regmap_update_bits(sirf_audio_codec->regmap, + AUDIO_PORT_IC_CODEC_TX_CTRL, IC_TX_ENABLE, ~IC_TX_ENABLE); +} + +static void sirf_audio_codec_rx_enable(struct sirf_audio_codec *sirf_audio_codec, + int channels) +{ + regmap_update_bits(sirf_audio_codec->regmap, AUDIO_PORT_IC_RXFIFO_OP, + AUDIO_FIFO_RESET, AUDIO_FIFO_RESET); + regmap_update_bits(sirf_audio_codec->regmap, AUDIO_PORT_IC_RXFIFO_OP, + AUDIO_FIFO_RESET, ~AUDIO_FIFO_RESET); + regmap_write(sirf_audio_codec->regmap, + AUDIO_PORT_IC_RXFIFO_INT_MSK, 0); + regmap_write(sirf_audio_codec->regmap, AUDIO_PORT_IC_RXFIFO_OP, 0); + regmap_update_bits(sirf_audio_codec->regmap, AUDIO_PORT_IC_RXFIFO_OP, + AUDIO_FIFO_START, AUDIO_FIFO_START); + if (channels == 1) + regmap_update_bits(sirf_audio_codec->regmap, + AUDIO_PORT_IC_CODEC_RX_CTRL, + IC_RX_ENABLE_MONO, IC_RX_ENABLE_MONO); + else + regmap_update_bits(sirf_audio_codec->regmap, + AUDIO_PORT_IC_CODEC_RX_CTRL, + IC_RX_ENABLE_STEREO, IC_RX_ENABLE_STEREO); +} + +static void sirf_audio_codec_rx_disable(struct sirf_audio_codec *sirf_audio_codec) +{ + regmap_update_bits(sirf_audio_codec->regmap, + AUDIO_PORT_IC_CODEC_RX_CTRL, + IC_RX_ENABLE_STEREO, ~IC_RX_ENABLE_STEREO); +} + static int sirf_audio_codec_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) { - int playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; struct snd_soc_codec *codec = dai->codec; - u32 val = 0; + struct sirf_audio_codec *sirf_audio_codec = snd_soc_codec_get_drvdata(codec); + int playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; /* * This is a workaround, When stop playback, @@ -295,20 +345,28 @@ static int sirf_audio_codec_trigger(struct snd_pcm_substream *substream, case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + if (playback) { + snd_soc_update_bits(codec, AUDIO_IC_CODEC_CTRL0, + IC_HSLEN | IC_HSREN, 0); + sirf_audio_codec_tx_disable(sirf_audio_codec); + } else + sirf_audio_codec_rx_disable(sirf_audio_codec); break; case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - if (playback) - val = IC_HSLEN | IC_HSREN; + if (playback) { + sirf_audio_codec_tx_enable(sirf_audio_codec); + snd_soc_update_bits(codec, AUDIO_IC_CODEC_CTRL0, + IC_HSLEN | IC_HSREN, IC_HSLEN | IC_HSREN); + } else + sirf_audio_codec_rx_enable(sirf_audio_codec, + substream->runtime->channels); break; default: return -EINVAL; } - if (playback) - snd_soc_update_bits(codec, AUDIO_IC_CODEC_CTRL0, - IC_HSLEN | IC_HSREN, val); return 0; } @@ -392,7 +450,7 @@ static const struct regmap_config sirf_audio_codec_regmap_config = { .reg_bits = 32, .reg_stride = 4, .val_bits = 32, - .max_register = AUDIO_IC_CODEC_CTRL3, + .max_register = AUDIO_PORT_IC_RXFIFO_INT_MSK, .cache_type = REGCACHE_NONE, }; diff --git a/sound/soc/codecs/sirf-audio-codec.h b/sound/soc/codecs/sirf-audio-codec.h index d4c187b8e54a..ba1adc03839f 100644 --- a/sound/soc/codecs/sirf-audio-codec.h +++ b/sound/soc/codecs/sirf-audio-codec.h @@ -72,4 +72,54 @@ #define IC_RXPGAR 0x7B #define IC_RXPGAL 0x7B +#define AUDIO_PORT_TX_FIFO_LEVEL_CHECK_MASK 0x3F +#define AUDIO_PORT_TX_FIFO_SC_OFFSET 0 +#define AUDIO_PORT_TX_FIFO_LC_OFFSET 10 +#define AUDIO_PORT_TX_FIFO_HC_OFFSET 20 + +#define TX_FIFO_SC(x) (((x) & AUDIO_PORT_TX_FIFO_LEVEL_CHECK_MASK) \ + << AUDIO_PORT_TX_FIFO_SC_OFFSET) +#define TX_FIFO_LC(x) (((x) & AUDIO_PORT_TX_FIFO_LEVEL_CHECK_MASK) \ + << AUDIO_PORT_TX_FIFO_LC_OFFSET) +#define TX_FIFO_HC(x) (((x) & AUDIO_PORT_TX_FIFO_LEVEL_CHECK_MASK) \ + << AUDIO_PORT_TX_FIFO_HC_OFFSET) + +#define AUDIO_PORT_RX_FIFO_LEVEL_CHECK_MASK 0x0F +#define AUDIO_PORT_RX_FIFO_SC_OFFSET 0 +#define AUDIO_PORT_RX_FIFO_LC_OFFSET 10 +#define AUDIO_PORT_RX_FIFO_HC_OFFSET 20 + +#define RX_FIFO_SC(x) (((x) & AUDIO_PORT_RX_FIFO_LEVEL_CHECK_MASK) \ + << AUDIO_PORT_RX_FIFO_SC_OFFSET) +#define RX_FIFO_LC(x) (((x) & AUDIO_PORT_RX_FIFO_LEVEL_CHECK_MASK) \ + << AUDIO_PORT_RX_FIFO_LC_OFFSET) +#define RX_FIFO_HC(x) (((x) & AUDIO_PORT_RX_FIFO_LEVEL_CHECK_MASK) \ + << AUDIO_PORT_RX_FIFO_HC_OFFSET) +#define AUDIO_PORT_IC_CODEC_TX_CTRL (0x00F4) +#define AUDIO_PORT_IC_CODEC_RX_CTRL (0x00F8) + +#define AUDIO_PORT_IC_TXFIFO_OP (0x00FC) +#define AUDIO_PORT_IC_TXFIFO_LEV_CHK (0x0100) +#define AUDIO_PORT_IC_TXFIFO_STS (0x0104) +#define AUDIO_PORT_IC_TXFIFO_INT (0x0108) +#define AUDIO_PORT_IC_TXFIFO_INT_MSK (0x010C) + +#define AUDIO_PORT_IC_RXFIFO_OP (0x0110) +#define AUDIO_PORT_IC_RXFIFO_LEV_CHK (0x0114) +#define AUDIO_PORT_IC_RXFIFO_STS (0x0118) +#define AUDIO_PORT_IC_RXFIFO_INT (0x011C) +#define AUDIO_PORT_IC_RXFIFO_INT_MSK (0x0120) + +#define AUDIO_FIFO_START (1 << 0) +#define AUDIO_FIFO_RESET (1 << 1) + +#define AUDIO_FIFO_FULL (1 << 0) +#define AUDIO_FIFO_EMPTY (1 << 1) +#define AUDIO_FIFO_OFLOW (1 << 2) +#define AUDIO_FIFO_UFLOW (1 << 3) + +#define IC_TX_ENABLE (0x03) +#define IC_RX_ENABLE_MONO (0x01) +#define IC_RX_ENABLE_STEREO (0x03) + #endif /*__SIRF_AUDIO_CODEC_H*/ diff --git a/sound/soc/codecs/sta350.c b/sound/soc/codecs/sta350.c index 12ebbaf5d95f..cc97dd52aa9c 100644 --- a/sound/soc/codecs/sta350.c +++ b/sound/soc/codecs/sta350.c @@ -1020,6 +1020,29 @@ static int sta350_probe(struct snd_soc_codec *codec) pdata->ch3_output_mapping << STA350_CxCFG_OM_SHIFT); + /* miscellaneous registers */ + regmap_update_bits(sta350->regmap, STA350_MISC1, + STA350_MISC1_CPWMEN, + pdata->activate_mute_output ? + STA350_MISC1_CPWMEN : 0); + regmap_update_bits(sta350->regmap, STA350_MISC1, + STA350_MISC1_BRIDGOFF, + pdata->bridge_immediate_off ? + STA350_MISC1_BRIDGOFF : 0); + regmap_update_bits(sta350->regmap, STA350_MISC1, + STA350_MISC1_NSHHPEN, + pdata->noise_shape_dc_cut ? + STA350_MISC1_NSHHPEN : 0); + regmap_update_bits(sta350->regmap, STA350_MISC1, + STA350_MISC1_RPDNEN, + pdata->powerdown_master_vol ? + STA350_MISC1_RPDNEN: 0); + + regmap_update_bits(sta350->regmap, STA350_MISC2, + STA350_MISC2_PNDLSL_MASK, + pdata->powerdown_delay_divider + << STA350_MISC2_PNDLSL_SHIFT); + /* initialize coefficient shadow RAM with reset values */ for (i = 4; i <= 49; i += 5) sta350->coef_shadow[i] = 0x400000; @@ -1094,6 +1117,7 @@ static int sta350_probe_dt(struct device *dev, struct sta350_priv *sta350) struct sta350_platform_data *pdata; const char *ffx_power_mode; u16 tmp; + u8 tmp8; pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); if (!pdata) @@ -1158,6 +1182,27 @@ static int sta350_probe_dt(struct device *dev, struct sta350_priv *sta350) if (of_get_property(np, "st,invalid-input-detect-mute", NULL)) pdata->invalid_input_detect_mute = 1; + /* MISC */ + if (of_get_property(np, "st,activate-mute-output", NULL)) + pdata->activate_mute_output = 1; + + if (of_get_property(np, "st,bridge-immediate-off", NULL)) + pdata->bridge_immediate_off = 1; + + if (of_get_property(np, "st,noise-shape-dc-cut", NULL)) + pdata->noise_shape_dc_cut = 1; + + if (of_get_property(np, "st,powerdown-master-volume", NULL)) + pdata->powerdown_master_vol = 1; + + if (!of_property_read_u8(np, "st,powerdown-delay-divider", &tmp8)) { + if (is_power_of_2(tmp8) && tmp8 >= 1 && tmp8 <= 128) + pdata->powerdown_delay_divider = ilog2(tmp8); + else + dev_warn(dev, "Unsupported powerdown delay divider %d\n", + tmp8); + } + sta350->pdata = pdata; return 0; diff --git a/sound/soc/codecs/sta350.h b/sound/soc/codecs/sta350.h index c3248f0fad2c..fb7285290779 100644 --- a/sound/soc/codecs/sta350.h +++ b/sound/soc/codecs/sta350.h @@ -225,4 +225,14 @@ #define STA350_C3_MIX1 60 #define STA350_C3_MIX2 61 +/* miscellaneous register 1 */ +#define STA350_MISC1_CPWMEN BIT(2) +#define STA350_MISC1_BRIDGOFF BIT(5) +#define STA350_MISC1_NSHHPEN BIT(6) +#define STA350_MISC1_RPDNEN BIT(7) + +/* miscellaneous register 2 */ +#define STA350_MISC2_PNDLSL_MASK 0x1c +#define STA350_MISC2_PNDLSL_SHIFT 2 + #endif /* _ASOC_STA_350_H */ diff --git a/sound/soc/codecs/tlv320dac33.c b/sound/soc/codecs/tlv320dac33.c index 517055ab65ef..df3a7506c023 100644 --- a/sound/soc/codecs/tlv320dac33.c +++ b/sound/soc/codecs/tlv320dac33.c @@ -1540,7 +1540,7 @@ static int dac33_i2c_probe(struct i2c_client *client, for (i = 0; i < ARRAY_SIZE(dac33->supplies); i++) dac33->supplies[i].supply = dac33_supply_names[i]; - ret = regulator_bulk_get(&client->dev, ARRAY_SIZE(dac33->supplies), + ret = devm_regulator_bulk_get(&client->dev, ARRAY_SIZE(dac33->supplies), dac33->supplies); if (ret != 0) { @@ -1551,11 +1551,9 @@ static int dac33_i2c_probe(struct i2c_client *client, ret = snd_soc_register_codec(&client->dev, &soc_codec_dev_tlv320dac33, &dac33_dai, 1); if (ret < 0) - goto err_register; + goto err_get; return ret; -err_register: - regulator_bulk_free(ARRAY_SIZE(dac33->supplies), dac33->supplies); err_get: if (dac33->power_gpio >= 0) gpio_free(dac33->power_gpio); @@ -1573,8 +1571,6 @@ static int dac33_i2c_remove(struct i2c_client *client) if (dac33->power_gpio >= 0) gpio_free(dac33->power_gpio); - regulator_bulk_free(ARRAY_SIZE(dac33->supplies), dac33->supplies); - snd_soc_unregister_codec(&client->dev); return 0; } diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index 21f1ccbdf582..98f97e543c29 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -66,8 +66,7 @@ err: static int asoc_simple_card_dai_init(struct snd_soc_pcm_runtime *rtd) { - struct simple_card_data *priv = - snd_soc_card_get_drvdata(rtd->card); + struct simple_card_data *priv = snd_soc_card_get_drvdata(rtd->card); struct snd_soc_dai *codec = rtd->codec_dai; struct snd_soc_dai *cpu = rtd->cpu_dai; struct simple_dai_props *dai_props; @@ -88,7 +87,6 @@ static int asoc_simple_card_dai_init(struct snd_soc_pcm_runtime *rtd) static int asoc_simple_card_sub_parse_of(struct device_node *np, - unsigned int daifmt, struct asoc_simple_dai *dai, const struct device_node **p_node, const char **name) @@ -116,14 +114,6 @@ asoc_simple_card_sub_parse_of(struct device_node *np, if (ret) return ret; - /* - * bitclock-inversion, frame-inversion - * bitclock-master, frame-master - * and specific "format" if it has - */ - dai->fmt = snd_soc_of_parse_daifmt(np, NULL); - dai->fmt |= daifmt; - /* * dai->sysclk come from * "clocks = <&xxx>" (if system has common clock) @@ -151,37 +141,132 @@ asoc_simple_card_sub_parse_of(struct device_node *np, return 0; } -static int simple_card_cpu_codec_of(struct device_node *node, - int daifmt, - struct snd_soc_dai_link *dai_link, - struct simple_dai_props *dai_props) +static int simple_card_dai_link_of(struct device_node *node, + struct device *dev, + struct snd_soc_dai_link *dai_link, + struct simple_dai_props *dai_props) { - struct device_node *np; + struct device_node *np = NULL; + struct device_node *bitclkmaster = NULL; + struct device_node *framemaster = NULL; + unsigned int daifmt; + char *name; + char prop[128]; + char *prefix = ""; int ret; - /* CPU sub-node */ - ret = -EINVAL; - np = of_get_child_by_name(node, "simple-audio-card,cpu"); - if (np) { - ret = asoc_simple_card_sub_parse_of(np, daifmt, - &dai_props->cpu_dai, - &dai_link->cpu_of_node, - &dai_link->cpu_dai_name); - of_node_put(np); - } - if (ret < 0) - return ret; + prefix = "simple-audio-card,"; - /* CODEC sub-node */ - ret = -EINVAL; - np = of_get_child_by_name(node, "simple-audio-card,codec"); - if (np) { - ret = asoc_simple_card_sub_parse_of(np, daifmt, - &dai_props->codec_dai, - &dai_link->codec_of_node, - &dai_link->codec_dai_name); - of_node_put(np); + daifmt = snd_soc_of_parse_daifmt(node, prefix, + &bitclkmaster, &framemaster); + daifmt &= ~SND_SOC_DAIFMT_MASTER_MASK; + + snprintf(prop, sizeof(prop), "%scpu", prefix); + np = of_get_child_by_name(node, prop); + if (!np) { + ret = -EINVAL; + dev_err(dev, "%s: Can't find %s DT node\n", __func__, prop); + goto dai_link_of_err; } + + ret = asoc_simple_card_sub_parse_of(np, &dai_props->cpu_dai, + &dai_link->cpu_of_node, + &dai_link->cpu_dai_name); + if (ret < 0) + goto dai_link_of_err; + + dai_props->cpu_dai.fmt = daifmt; + switch (((np == bitclkmaster) << 4) | (np == framemaster)) { + case 0x11: + dai_props->cpu_dai.fmt |= SND_SOC_DAIFMT_CBS_CFS; + break; + case 0x10: + dai_props->cpu_dai.fmt |= SND_SOC_DAIFMT_CBS_CFM; + break; + case 0x01: + dai_props->cpu_dai.fmt |= SND_SOC_DAIFMT_CBM_CFS; + break; + default: + dai_props->cpu_dai.fmt |= SND_SOC_DAIFMT_CBM_CFM; + break; + } + + of_node_put(np); + snprintf(prop, sizeof(prop), "%scodec", prefix); + np = of_get_child_by_name(node, prop); + if (!np) { + ret = -EINVAL; + dev_err(dev, "%s: Can't find %s DT node\n", __func__, prop); + goto dai_link_of_err; + } + + ret = asoc_simple_card_sub_parse_of(np, &dai_props->codec_dai, + &dai_link->codec_of_node, + &dai_link->codec_dai_name); + if (ret < 0) + goto dai_link_of_err; + + if (strlen(prefix) && !bitclkmaster && !framemaster) { + /* No dai-link level and master setting was not found from + sound node level, revert back to legacy DT parsing and + take the settings from codec node. */ + dev_dbg(dev, "%s: Revert to legacy daifmt parsing\n", + __func__); + dai_props->cpu_dai.fmt = dai_props->codec_dai.fmt = + snd_soc_of_parse_daifmt(np, NULL, NULL, NULL) | + (daifmt & ~SND_SOC_DAIFMT_CLOCK_MASK); + } else { + dai_props->codec_dai.fmt = daifmt; + switch (((np == bitclkmaster) << 4) | (np == framemaster)) { + case 0x11: + dai_props->codec_dai.fmt |= SND_SOC_DAIFMT_CBM_CFM; + break; + case 0x10: + dai_props->codec_dai.fmt |= SND_SOC_DAIFMT_CBM_CFS; + break; + case 0x01: + dai_props->codec_dai.fmt |= SND_SOC_DAIFMT_CBS_CFM; + break; + default: + dai_props->codec_dai.fmt |= SND_SOC_DAIFMT_CBS_CFS; + break; + } + } + + if (!dai_link->cpu_dai_name || !dai_link->codec_dai_name) { + ret = -EINVAL; + goto dai_link_of_err; + } + + /* simple-card assumes platform == cpu */ + dai_link->platform_of_node = dai_link->cpu_of_node; + + /* Link name is created from CPU/CODEC dai name */ + name = devm_kzalloc(dev, + strlen(dai_link->cpu_dai_name) + + strlen(dai_link->codec_dai_name) + 2, + GFP_KERNEL); + sprintf(name, "%s-%s", dai_link->cpu_dai_name, + dai_link->codec_dai_name); + dai_link->name = dai_link->stream_name = name; + + dev_dbg(dev, "\tname : %s\n", dai_link->stream_name); + dev_dbg(dev, "\tcpu : %s / %04x / %d\n", + dai_link->cpu_dai_name, + dai_props->cpu_dai.fmt, + dai_props->cpu_dai.sysclk); + dev_dbg(dev, "\tcodec : %s / %04x / %d\n", + dai_link->codec_dai_name, + dai_props->codec_dai.fmt, + dai_props->codec_dai.sysclk); + +dai_link_of_err: + if (np) + of_node_put(np); + if (bitclkmaster) + of_node_put(bitclkmaster); + if (framemaster) + of_node_put(framemaster); return ret; } @@ -192,18 +277,11 @@ static int asoc_simple_card_parse_of(struct device_node *node, { struct snd_soc_dai_link *dai_link = priv->snd_card.dai_link; struct simple_dai_props *dai_props = priv->dai_props; - struct device_node *np; - char *name; - unsigned int daifmt; int ret; /* parsing the card name from DT */ snd_soc_of_parse_card_name(&priv->snd_card, "simple-audio-card,name"); - /* get CPU/CODEC common format via simple-audio-card,format */ - daifmt = snd_soc_of_parse_daifmt(node, "simple-audio-card,") & - (SND_SOC_DAIFMT_FORMAT_MASK | SND_SOC_DAIFMT_INV_MASK); - /* off-codec widgets */ if (of_property_read_bool(node, "simple-audio-card,widgets")) { ret = snd_soc_of_parse_audio_simple_widgets(&priv->snd_card, @@ -220,71 +298,31 @@ static int asoc_simple_card_parse_of(struct device_node *node, return ret; } - /* loop on the DAI links */ - np = NULL; - for (;;) { - if (multi) { - np = of_get_next_child(node, np); - if (!np) - break; - } + dev_dbg(dev, "New simple-card: %s\n", priv->snd_card.name ? + priv->snd_card.name : ""); - ret = simple_card_cpu_codec_of(multi ? np : node, - daifmt, dai_link, dai_props); + if (multi) { + struct device_node *np = NULL; + int i; + for (i = 0; (np = of_get_next_child(node, np)); i++) { + dev_dbg(dev, "\tlink %d:\n", i); + ret = simple_card_dai_link_of(np, dev, dai_link + i, + dai_props + i); + if (ret < 0) { + of_node_put(np); + return ret; + } + } + } else { + ret = simple_card_dai_link_of(node, dev, dai_link, dai_props); if (ret < 0) - goto err; - - /* - * overwrite cpu_dai->fmt as its DAIFMT_MASTER bit is based on CODEC - * while the other bits should be identical unless buggy SW/HW design. - */ - dai_props->cpu_dai.fmt = dai_props->codec_dai.fmt; - - if (!dai_link->cpu_dai_name || !dai_link->codec_dai_name) { - ret = -EINVAL; - goto err; - } - - /* simple-card assumes platform == cpu */ - dai_link->platform_of_node = dai_link->cpu_of_node; - - name = devm_kzalloc(dev, - strlen(dai_link->cpu_dai_name) + - strlen(dai_link->codec_dai_name) + 2, - GFP_KERNEL); - sprintf(name, "%s-%s", dai_link->cpu_dai_name, - dai_link->codec_dai_name); - dai_link->name = dai_link->stream_name = name; - - if (!multi) - break; - - dai_link++; - dai_props++; + return ret; } - /* card name is created from CPU/CODEC dai name */ - dai_link = priv->snd_card.dai_link; if (!priv->snd_card.name) - priv->snd_card.name = dai_link->name; - - dev_dbg(dev, "card-name : %s\n", priv->snd_card.name); - dev_dbg(dev, "platform : %04x\n", daifmt); - dai_props = priv->dai_props; - dev_dbg(dev, "cpu : %s / %04x / %d\n", - dai_link->cpu_dai_name, - dai_props->cpu_dai.fmt, - dai_props->cpu_dai.sysclk); - dev_dbg(dev, "codec : %s / %04x / %d\n", - dai_link->codec_dai_name, - dai_props->codec_dai.fmt, - dai_props->codec_dai.sysclk); + priv->snd_card.name = priv->snd_card.dai_link->name; return 0; - -err: - of_node_put(np); - return ret; } /* update the reference count of the devices nodes at end of probe */ @@ -378,10 +416,10 @@ static int asoc_simple_card_probe(struct platform_device *pdev) return -EINVAL; } - if (!cinfo->name || - !cinfo->codec_dai.name || - !cinfo->codec || - !cinfo->platform || + if (!cinfo->name || + !cinfo->codec_dai.name || + !cinfo->codec || + !cinfo->platform || !cinfo->cpu_dai.name) { dev_err(dev, "insufficient asoc_simple_card_info settings\n"); return -EINVAL; @@ -425,11 +463,11 @@ MODULE_DEVICE_TABLE(of, asoc_simple_of_match); static struct platform_driver asoc_simple_card = { .driver = { - .name = "asoc-simple-card", + .name = "asoc-simple-card", .owner = THIS_MODULE, .of_match_table = asoc_simple_of_match, }, - .probe = asoc_simple_card_probe, + .probe = asoc_simple_card_probe, }; module_platform_driver(asoc_simple_card); diff --git a/sound/soc/samsung/Kconfig b/sound/soc/samsung/Kconfig index 14568bedd425..753b8c93ab51 100644 --- a/sound/soc/samsung/Kconfig +++ b/sound/soc/samsung/Kconfig @@ -64,6 +64,7 @@ config SND_SOC_SAMSUNG_JIVE_WM8750 config SND_SOC_SAMSUNG_SMDK_WM8580 tristate "SoC I2S Audio support for WM8580 on SMDK" depends on SND_SOC_SAMSUNG && (MACH_SMDK6410 || MACH_SMDKC100 || MACH_SMDK6440 || MACH_SMDK6450 || MACH_SMDKV210 || MACH_SMDKC110) + depends on REGMAP_I2C select SND_SOC_WM8580 select SND_SAMSUNG_I2S help @@ -115,21 +116,21 @@ config SND_SOC_SAMSUNG_SIMTEC config SND_SOC_SAMSUNG_SIMTEC_TLV320AIC23 tristate "SoC I2S Audio support for TLV320AIC23 on Simtec boards" - depends on SND_SOC_SAMSUNG && ARCH_S3C24XX + depends on SND_SOC_SAMSUNG && ARCH_S3C24XX && I2C select SND_S3C24XX_I2S select SND_SOC_TLV320AIC23_I2C select SND_SOC_SAMSUNG_SIMTEC config SND_SOC_SAMSUNG_SIMTEC_HERMES tristate "SoC I2S Audio support for Simtec Hermes board" - depends on SND_SOC_SAMSUNG && ARCH_S3C24XX + depends on SND_SOC_SAMSUNG && ARCH_S3C24XX && I2C select SND_S3C24XX_I2S select SND_SOC_TLV320AIC3X select SND_SOC_SAMSUNG_SIMTEC config SND_SOC_SAMSUNG_H1940_UDA1380 tristate "Audio support for the HP iPAQ H1940" - depends on SND_SOC_SAMSUNG && ARCH_H1940 + depends on SND_SOC_SAMSUNG && ARCH_H1940 && I2C select SND_S3C24XX_I2S select SND_SOC_UDA1380 help @@ -137,7 +138,7 @@ config SND_SOC_SAMSUNG_H1940_UDA1380 config SND_SOC_SAMSUNG_RX1950_UDA1380 tristate "Audio support for the HP iPAQ RX1950" - depends on SND_SOC_SAMSUNG && MACH_RX1950 + depends on SND_SOC_SAMSUNG && MACH_RX1950 && I2C select SND_S3C24XX_I2S select SND_SOC_UDA1380 help @@ -178,6 +179,7 @@ config SND_SOC_SAMSUNG_SMDK_SPDIF config SND_SOC_SMDK_WM8580_PCM tristate "SoC PCM Audio support for WM8580 on SMDK" depends on SND_SOC_SAMSUNG && (MACH_SMDK6450 || MACH_SMDKV210 || MACH_SMDKC110) + depends on REGMAP_I2C select SND_SOC_WM8580 select SND_SAMSUNG_PCM help @@ -231,3 +233,13 @@ config SND_SOC_LITTLEMILL select SND_SAMSUNG_I2S select MFD_WM8994 select SND_SOC_WM8994 + +config SND_SOC_SNOW + tristate "Audio support for Google Snow boards" + depends on SND_SOC_SAMSUNG + select SND_SOC_MAX98090 + select SND_SOC_MAX98095 + select SND_SAMSUNG_I2S + help + Say Y if you want to add audio support for various Snow + boards based on Exynos5 series of SoCs. diff --git a/sound/soc/samsung/Makefile b/sound/soc/samsung/Makefile index 86715d8efee6..6d0212ba571c 100644 --- a/sound/soc/samsung/Makefile +++ b/sound/soc/samsung/Makefile @@ -34,6 +34,7 @@ snd-soc-h1940-uda1380-objs := h1940_uda1380.o snd-soc-rx1950-uda1380-objs := rx1950_uda1380.o snd-soc-smdk-wm8580-objs := smdk_wm8580.o snd-soc-smdk-wm8994-objs := smdk_wm8994.o +snd-soc-snow-objs := snow.o snd-soc-smdk-wm9713-objs := smdk_wm9713.o snd-soc-s3c64xx-smartq-wm8987-objs := smartq_wm8987.o snd-soc-goni-wm8994-objs := goni_wm8994.o @@ -58,6 +59,7 @@ obj-$(CONFIG_SND_SOC_SAMSUNG_H1940_UDA1380) += snd-soc-h1940-uda1380.o obj-$(CONFIG_SND_SOC_SAMSUNG_RX1950_UDA1380) += snd-soc-rx1950-uda1380.o obj-$(CONFIG_SND_SOC_SAMSUNG_SMDK_WM8580) += snd-soc-smdk-wm8580.o obj-$(CONFIG_SND_SOC_SAMSUNG_SMDK_WM8994) += snd-soc-smdk-wm8994.o +obj-$(CONFIG_SND_SOC_SNOW) += snd-soc-snow.o obj-$(CONFIG_SND_SOC_SAMSUNG_SMDK_WM9713) += snd-soc-smdk-wm9713.o obj-$(CONFIG_SND_SOC_SMARTQ) += snd-soc-s3c64xx-smartq-wm8987.o obj-$(CONFIG_SND_SOC_SAMSUNG_SMDK_SPDIF) += snd-soc-smdk-spdif.o diff --git a/sound/soc/samsung/ac97.c b/sound/soc/samsung/ac97.c index 76b072bd4ba2..68d9303047e8 100644 --- a/sound/soc/samsung/ac97.c +++ b/sound/soc/samsung/ac97.c @@ -433,7 +433,7 @@ static int s3c_ac97_probe(struct platform_device *pdev) goto err4; } - ret = snd_soc_register_component(&pdev->dev, &s3c_ac97_component, + ret = devm_snd_soc_register_component(&pdev->dev, &s3c_ac97_component, s3c_ac97_dai, ARRAY_SIZE(s3c_ac97_dai)); if (ret) goto err5; @@ -441,12 +441,10 @@ static int s3c_ac97_probe(struct platform_device *pdev) ret = samsung_asoc_dma_platform_register(&pdev->dev); if (ret) { dev_err(&pdev->dev, "failed to get register DMA: %d\n", ret); - goto err6; + goto err5; } return 0; -err6: - snd_soc_unregister_component(&pdev->dev); err5: free_irq(irq_res->start, NULL); err4: @@ -461,9 +459,6 @@ static int s3c_ac97_remove(struct platform_device *pdev) { struct resource *irq_res; - samsung_asoc_dma_platform_unregister(&pdev->dev); - snd_soc_unregister_component(&pdev->dev); - irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (irq_res) free_irq(irq_res->start, NULL); diff --git a/sound/soc/samsung/bells.c b/sound/soc/samsung/bells.c index 84f5d8b76679..5b21207cf551 100644 --- a/sound/soc/samsung/bells.c +++ b/sound/soc/samsung/bells.c @@ -433,22 +433,13 @@ static int bells_probe(struct platform_device *pdev) bells_cards[pdev->id].dev = &pdev->dev; - ret = snd_soc_register_card(&bells_cards[pdev->id]); - if (ret) { + ret = devm_snd_soc_register_card(&pdev->dev, &bells_cards[pdev->id]); + if (ret) dev_err(&pdev->dev, "snd_soc_register_card(%s) failed: %d\n", bells_cards[pdev->id].name, ret); - return ret; - } - return 0; -} - -static int bells_remove(struct platform_device *pdev) -{ - snd_soc_unregister_card(&bells_cards[pdev->id]); - - return 0; + return ret; } static struct platform_driver bells_driver = { @@ -458,7 +449,6 @@ static struct platform_driver bells_driver = { .pm = &snd_soc_pm_ops, }, .probe = bells_probe, - .remove = bells_remove, }; module_platform_driver(bells_driver); diff --git a/sound/soc/samsung/dma.c b/sound/soc/samsung/dma.c index dc09b71b7d9f..d9dc7bcc0336 100644 --- a/sound/soc/samsung/dma.c +++ b/sound/soc/samsung/dma.c @@ -445,16 +445,10 @@ EXPORT_SYMBOL_GPL(samsung_asoc_init_dma_data); int samsung_asoc_dma_platform_register(struct device *dev) { - return snd_soc_register_platform(dev, &samsung_asoc_platform); + return devm_snd_soc_register_platform(dev, &samsung_asoc_platform); } EXPORT_SYMBOL_GPL(samsung_asoc_dma_platform_register); -void samsung_asoc_dma_platform_unregister(struct device *dev) -{ - snd_soc_unregister_platform(dev); -} -EXPORT_SYMBOL_GPL(samsung_asoc_dma_platform_unregister); - MODULE_AUTHOR("Ben Dooks, "); MODULE_DESCRIPTION("Samsung ASoC DMA Driver"); MODULE_LICENSE("GPL"); diff --git a/sound/soc/samsung/dma.h b/sound/soc/samsung/dma.h index ad7c0f04f00d..070ab0f09609 100644 --- a/sound/soc/samsung/dma.h +++ b/sound/soc/samsung/dma.h @@ -33,6 +33,5 @@ void samsung_asoc_init_dma_data(struct snd_soc_dai *dai, struct s3c_dma_params *playback, struct s3c_dma_params *capture); int samsung_asoc_dma_platform_register(struct device *dev); -void samsung_asoc_dma_platform_unregister(struct device *dev); #endif diff --git a/sound/soc/samsung/dmaengine.c b/sound/soc/samsung/dmaengine.c index 750ce5808d9f..a0e4e7948909 100644 --- a/sound/soc/samsung/dmaengine.c +++ b/sound/soc/samsung/dmaengine.c @@ -66,18 +66,13 @@ EXPORT_SYMBOL_GPL(samsung_asoc_init_dma_data); int samsung_asoc_dma_platform_register(struct device *dev) { - return snd_dmaengine_pcm_register(dev, &samsung_dmaengine_pcm_config, - SND_DMAENGINE_PCM_FLAG_CUSTOM_CHANNEL_NAME | - SND_DMAENGINE_PCM_FLAG_COMPAT); + return devm_snd_dmaengine_pcm_register(dev, + &samsung_dmaengine_pcm_config, + SND_DMAENGINE_PCM_FLAG_CUSTOM_CHANNEL_NAME | + SND_DMAENGINE_PCM_FLAG_COMPAT); } EXPORT_SYMBOL_GPL(samsung_asoc_dma_platform_register); -void samsung_asoc_dma_platform_unregister(struct device *dev) -{ - return snd_dmaengine_pcm_unregister(dev); -} -EXPORT_SYMBOL_GPL(samsung_asoc_dma_platform_unregister); - MODULE_AUTHOR("Mark Brown "); MODULE_DESCRIPTION("Samsung dmaengine ASoC driver"); MODULE_LICENSE("GPL"); diff --git a/sound/soc/samsung/goni_wm8994.c b/sound/soc/samsung/goni_wm8994.c index 415ad81999c4..9506d7617223 100644 --- a/sound/soc/samsung/goni_wm8994.c +++ b/sound/soc/samsung/goni_wm8994.c @@ -274,8 +274,8 @@ static int __init goni_init(void) return -ENOMEM; /* register voice DAI here */ - ret = snd_soc_register_component(&goni_snd_device->dev, &voice_component, - &voice_dai, 1); + ret = devm_snd_soc_register_component(&goni_snd_device->dev, + &voice_component, &voice_dai, 1); if (ret) { platform_device_put(goni_snd_device); return ret; @@ -284,17 +284,14 @@ static int __init goni_init(void) platform_set_drvdata(goni_snd_device, &goni); ret = platform_device_add(goni_snd_device); - if (ret) { - snd_soc_unregister_component(&goni_snd_device->dev); + if (ret) platform_device_put(goni_snd_device); - } return ret; } static void __exit goni_exit(void) { - snd_soc_unregister_component(&goni_snd_device->dev); platform_device_unregister(goni_snd_device); } diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c index 048ead967199..07ff3e7cb890 100644 --- a/sound/soc/samsung/i2s.c +++ b/sound/soc/samsung/i2s.c @@ -451,6 +451,10 @@ static int i2s_set_sysclk(struct snd_soc_dai *dai, u32 mod = readl(i2s->addr + I2SMOD); switch (clk_id) { + case SAMSUNG_I2S_OPCLK: + mod &= ~MOD_OPCLK_MASK; + mod |= dir; + break; case SAMSUNG_I2S_CDCLK: /* Shouldn't matter in GATING(CLOCK_IN) mode */ if (dir == SND_SOC_CLOCK_IN) @@ -724,9 +728,6 @@ static int i2s_startup(struct snd_pcm_substream *substream, else i2s->mode |= DAI_MANAGER; - /* Enforce set_sysclk in Master mode */ - i2s->rclk_srcrate = 0; - if (!any_active(i2s) && (i2s->quirks & QUIRK_NEED_RSTCLR)) writel(CON_RSTCLR, i2s->addr + I2SCON); @@ -984,6 +985,7 @@ probe_exit: /* Reset any constraint on RFS and BFS */ i2s->rfs = 0; i2s->bfs = 0; + i2s->rclk_srcrate = 0; i2s_txctrl(i2s, 0); i2s_rxctrl(i2s, 0); i2s_fifo(i2s, FIC_TXFLUSH); @@ -1293,8 +1295,6 @@ static int samsung_i2s_remove(struct platform_device *pdev) i2s->pri_dai = NULL; i2s->sec_dai = NULL; - samsung_asoc_dma_platform_unregister(&pdev->dev); - return 0; } diff --git a/sound/soc/samsung/i2s.h b/sound/soc/samsung/i2s.h index 7966afc934db..21ff24e930db 100644 --- a/sound/soc/samsung/i2s.h +++ b/sound/soc/samsung/i2s.h @@ -18,5 +18,6 @@ #define SAMSUNG_I2S_RCLKSRC_0 0 #define SAMSUNG_I2S_RCLKSRC_1 1 #define SAMSUNG_I2S_CDCLK 2 +#define SAMSUNG_I2S_OPCLK 3 #endif /* __SND_SOC_SAMSUNG_I2S_H */ diff --git a/sound/soc/samsung/idma.c b/sound/soc/samsung/idma.c index 3d5cf1530b6f..8cc5770abb39 100644 --- a/sound/soc/samsung/idma.c +++ b/sound/soc/samsung/idma.c @@ -274,7 +274,7 @@ static irqreturn_t iis_irq(int irqno, void *dev_id) addr = readl(idma.regs + I2SLVL0ADDR) - idma.lp_tx_addr; addr += prtd->periodsz; - addr %= (prtd->end - prtd->start); + addr %= (u32)(prtd->end - prtd->start); addr += idma.lp_tx_addr; writel(addr, idma.regs + I2SLVL0ADDR); @@ -413,13 +413,7 @@ static int asoc_idma_platform_probe(struct platform_device *pdev) if (idma_irq < 0) return idma_irq; - return snd_soc_register_platform(&pdev->dev, &asoc_idma_platform); -} - -static int asoc_idma_platform_remove(struct platform_device *pdev) -{ - snd_soc_unregister_platform(&pdev->dev); - return 0; + return devm_snd_soc_register_platform(&pdev->dev, &asoc_idma_platform); } static struct platform_driver asoc_idma_driver = { @@ -429,7 +423,6 @@ static struct platform_driver asoc_idma_driver = { }, .probe = asoc_idma_platform_probe, - .remove = asoc_idma_platform_remove, }; module_platform_driver(asoc_idma_driver); diff --git a/sound/soc/samsung/littlemill.c b/sound/soc/samsung/littlemill.c index bfb91f34a22a..840787e63cb1 100644 --- a/sound/soc/samsung/littlemill.c +++ b/sound/soc/samsung/littlemill.c @@ -304,23 +304,12 @@ static int littlemill_probe(struct platform_device *pdev) card->dev = &pdev->dev; - ret = snd_soc_register_card(card); - if (ret) { + ret = devm_snd_soc_register_card(&pdev->dev, card); + if (ret) dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", ret); - return ret; - } - return 0; -} - -static int littlemill_remove(struct platform_device *pdev) -{ - struct snd_soc_card *card = platform_get_drvdata(pdev); - - snd_soc_unregister_card(card); - - return 0; + return ret; } static struct platform_driver littlemill_driver = { @@ -330,7 +319,6 @@ static struct platform_driver littlemill_driver = { .pm = &snd_soc_pm_ops, }, .probe = littlemill_probe, - .remove = littlemill_remove, }; module_platform_driver(littlemill_driver); diff --git a/sound/soc/samsung/lowland.c b/sound/soc/samsung/lowland.c index 570cf5229508..bd5f0d643a86 100644 --- a/sound/soc/samsung/lowland.c +++ b/sound/soc/samsung/lowland.c @@ -187,23 +187,12 @@ static int lowland_probe(struct platform_device *pdev) card->dev = &pdev->dev; - ret = snd_soc_register_card(card); - if (ret) { + ret = devm_snd_soc_register_card(&pdev->dev, card); + if (ret) dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", ret); - return ret; - } - return 0; -} - -static int lowland_remove(struct platform_device *pdev) -{ - struct snd_soc_card *card = platform_get_drvdata(pdev); - - snd_soc_unregister_card(card); - - return 0; + return ret; } static struct platform_driver lowland_driver = { @@ -213,7 +202,6 @@ static struct platform_driver lowland_driver = { .pm = &snd_soc_pm_ops, }, .probe = lowland_probe, - .remove = lowland_remove, }; module_platform_driver(lowland_driver); diff --git a/sound/soc/samsung/neo1973_wm8753.c b/sound/soc/samsung/neo1973_wm8753.c index b0800337b79e..9b4a09f14b6c 100644 --- a/sound/soc/samsung/neo1973_wm8753.c +++ b/sound/soc/samsung/neo1973_wm8753.c @@ -271,15 +271,8 @@ static const struct snd_kcontrol_new neo1973_wm8753_controls[] = { static int neo1973_wm8753_init(struct snd_soc_pcm_runtime *rtd) { - struct snd_soc_codec *codec = rtd->codec; struct snd_soc_card *card = rtd->card; - /* set up NC codec pins */ - snd_soc_dapm_nc_pin(&codec->dapm, "OUT3"); - snd_soc_dapm_nc_pin(&codec->dapm, "OUT4"); - snd_soc_dapm_nc_pin(&codec->dapm, "LINE1"); - snd_soc_dapm_nc_pin(&codec->dapm, "LINE2"); - /* set endpoints to default off mode */ snd_soc_dapm_disable_pin(&card->dapm, "GSM Line Out"); snd_soc_dapm_disable_pin(&card->dapm, "GSM Line In"); @@ -355,6 +348,7 @@ static struct snd_soc_card neo1973 = { .num_dapm_widgets = ARRAY_SIZE(neo1973_wm8753_dapm_widgets), .dapm_routes = neo1973_wm8753_routes, .num_dapm_routes = ARRAY_SIZE(neo1973_wm8753_routes), + .fully_routed = true, }; static struct platform_device *neo1973_snd_device; diff --git a/sound/soc/samsung/pcm.c b/sound/soc/samsung/pcm.c index ab54e297957c..a3c9c9cba3b0 100644 --- a/sound/soc/samsung/pcm.c +++ b/sound/soc/samsung/pcm.c @@ -542,7 +542,7 @@ static int s3c_pcm_dev_probe(struct platform_device *pdev) /* Default is 128fs */ pcm->sclk_per_fs = 128; - pcm->cclk = clk_get(&pdev->dev, "audio-bus"); + pcm->cclk = devm_clk_get(&pdev->dev, "audio-bus"); if (IS_ERR(pcm->cclk)) { dev_err(&pdev->dev, "failed to get audio-bus\n"); ret = PTR_ERR(pcm->cclk); @@ -567,7 +567,7 @@ static int s3c_pcm_dev_probe(struct platform_device *pdev) goto err3; } - pcm->pclk = clk_get(&pdev->dev, "pcm"); + pcm->pclk = devm_clk_get(&pdev->dev, "pcm"); if (IS_ERR(pcm->pclk)) { dev_err(&pdev->dev, "failed to get pcm_clock\n"); ret = -ENOENT; @@ -588,7 +588,7 @@ static int s3c_pcm_dev_probe(struct platform_device *pdev) pm_runtime_enable(&pdev->dev); - ret = snd_soc_register_component(&pdev->dev, &s3c_pcm_component, + ret = devm_snd_soc_register_component(&pdev->dev, &s3c_pcm_component, &s3c_pcm_dai[pdev->id], 1); if (ret != 0) { dev_err(&pdev->dev, "failed to get register DAI: %d\n", ret); @@ -598,23 +598,19 @@ static int s3c_pcm_dev_probe(struct platform_device *pdev) ret = samsung_asoc_dma_platform_register(&pdev->dev); if (ret) { dev_err(&pdev->dev, "failed to get register DMA: %d\n", ret); - goto err6; + goto err5; } return 0; -err6: - snd_soc_unregister_component(&pdev->dev); err5: clk_disable_unprepare(pcm->pclk); - clk_put(pcm->pclk); err4: iounmap(pcm->regs); err3: release_mem_region(mem_res->start, resource_size(mem_res)); err2: clk_disable_unprepare(pcm->cclk); - clk_put(pcm->cclk); err1: return ret; } @@ -624,9 +620,6 @@ static int s3c_pcm_dev_remove(struct platform_device *pdev) struct s3c_pcm_info *pcm = &s3c_pcm[pdev->id]; struct resource *mem_res; - samsung_asoc_dma_platform_unregister(&pdev->dev); - snd_soc_unregister_component(&pdev->dev); - pm_runtime_disable(&pdev->dev); iounmap(pcm->regs); @@ -636,8 +629,6 @@ static int s3c_pcm_dev_remove(struct platform_device *pdev) clk_disable_unprepare(pcm->cclk); clk_disable_unprepare(pcm->pclk); - clk_put(pcm->pclk); - clk_put(pcm->cclk); return 0; } diff --git a/sound/soc/samsung/s3c-i2s-v2.c b/sound/soc/samsung/s3c-i2s-v2.c index 79e7efb9283c..77a2ae50dc94 100644 --- a/sound/soc/samsung/s3c-i2s-v2.c +++ b/sound/soc/samsung/s3c-i2s-v2.c @@ -745,7 +745,7 @@ int s3c_i2sv2_register_component(struct device *dev, int id, dai_drv->suspend = s3c2412_i2s_suspend; dai_drv->resume = s3c2412_i2s_resume; - return snd_soc_register_component(dev, cmp_drv, dai_drv, 1); + return devm_snd_soc_register_component(dev, cmp_drv, dai_drv, 1); } EXPORT_SYMBOL_GPL(s3c_i2sv2_register_component); diff --git a/sound/soc/samsung/s3c2412-i2s.c b/sound/soc/samsung/s3c2412-i2s.c index e9bb5d7a71ee..843f315dcb3a 100644 --- a/sound/soc/samsung/s3c2412-i2s.c +++ b/sound/soc/samsung/s3c2412-i2s.c @@ -179,27 +179,14 @@ static int s3c2412_iis_dev_probe(struct platform_device *pdev) } ret = samsung_asoc_dma_platform_register(&pdev->dev); - if (ret) { + if (ret) pr_err("failed to register the DMA: %d\n", ret); - goto err; - } - return 0; -err: - snd_soc_unregister_component(&pdev->dev); return ret; } -static int s3c2412_iis_dev_remove(struct platform_device *pdev) -{ - samsung_asoc_dma_platform_unregister(&pdev->dev); - snd_soc_unregister_component(&pdev->dev); - return 0; -} - static struct platform_driver s3c2412_iis_driver = { .probe = s3c2412_iis_dev_probe, - .remove = s3c2412_iis_dev_remove, .driver = { .name = "s3c2412-iis", .owner = THIS_MODULE, diff --git a/sound/soc/samsung/s3c24xx-i2s.c b/sound/soc/samsung/s3c24xx-i2s.c index d7b8457b5650..4a6d206db222 100644 --- a/sound/soc/samsung/s3c24xx-i2s.c +++ b/sound/soc/samsung/s3c24xx-i2s.c @@ -475,35 +475,22 @@ static int s3c24xx_iis_dev_probe(struct platform_device *pdev) { int ret = 0; - ret = snd_soc_register_component(&pdev->dev, &s3c24xx_i2s_component, - &s3c24xx_i2s_dai, 1); + ret = devm_snd_soc_register_component(&pdev->dev, + &s3c24xx_i2s_component, &s3c24xx_i2s_dai, 1); if (ret) { pr_err("failed to register the dai\n"); return ret; } ret = samsung_asoc_dma_platform_register(&pdev->dev); - if (ret) { + if (ret) pr_err("failed to register the dma: %d\n", ret); - goto err; - } - return 0; -err: - snd_soc_unregister_component(&pdev->dev); return ret; } -static int s3c24xx_iis_dev_remove(struct platform_device *pdev) -{ - samsung_asoc_dma_platform_unregister(&pdev->dev); - snd_soc_unregister_component(&pdev->dev); - return 0; -} - static struct platform_driver s3c24xx_iis_driver = { .probe = s3c24xx_iis_dev_probe, - .remove = s3c24xx_iis_dev_remove, .driver = { .name = "s3c24xx-iis", .owner = THIS_MODULE, diff --git a/sound/soc/samsung/smdk_wm8580pcm.c b/sound/soc/samsung/smdk_wm8580pcm.c index 23a9204b106d..e119aaa91c28 100644 --- a/sound/soc/samsung/smdk_wm8580pcm.c +++ b/sound/soc/samsung/smdk_wm8580pcm.c @@ -164,19 +164,11 @@ static int snd_smdk_probe(struct platform_device *pdev) xtal_freq = mclk_freq = SMDK_WM8580_EXT_VOICE; smdk_pcm.dev = &pdev->dev; - ret = snd_soc_register_card(&smdk_pcm); - if (ret) { + ret = devm_snd_soc_register_card(&pdev->dev, &smdk_pcm); + if (ret) dev_err(&pdev->dev, "snd_soc_register_card failed %d\n", ret); - return ret; - } - return 0; -} - -static int snd_smdk_remove(struct platform_device *pdev) -{ - snd_soc_unregister_card(&smdk_pcm); - return 0; + return ret; } static struct platform_driver snd_smdk_driver = { @@ -185,7 +177,6 @@ static struct platform_driver snd_smdk_driver = { .name = "samsung-smdk-pcm", }, .probe = snd_smdk_probe, - .remove = snd_smdk_remove, }; module_platform_driver(snd_smdk_driver); diff --git a/sound/soc/samsung/smdk_wm8994pcm.c b/sound/soc/samsung/smdk_wm8994pcm.c index 0c84ca099612..b6c09979be1f 100644 --- a/sound/soc/samsung/smdk_wm8994pcm.c +++ b/sound/soc/samsung/smdk_wm8994pcm.c @@ -134,19 +134,11 @@ static int snd_smdk_probe(struct platform_device *pdev) int ret = 0; smdk_pcm.dev = &pdev->dev; - ret = snd_soc_register_card(&smdk_pcm); - if (ret) { + ret = devm_snd_soc_register_card(&pdev->dev, &smdk_pcm); + if (ret) dev_err(&pdev->dev, "snd_soc_register_card failed %d\n", ret); - return ret; - } - return 0; -} - -static int snd_smdk_remove(struct platform_device *pdev) -{ - snd_soc_unregister_card(&smdk_pcm); - return 0; + return ret; } static struct platform_driver snd_smdk_driver = { @@ -155,7 +147,6 @@ static struct platform_driver snd_smdk_driver = { .name = "samsung-smdk-pcm", }, .probe = snd_smdk_probe, - .remove = snd_smdk_remove, }; module_platform_driver(snd_smdk_driver); diff --git a/sound/soc/samsung/snow.c b/sound/soc/samsung/snow.c new file mode 100644 index 000000000000..014c177840ba --- /dev/null +++ b/sound/soc/samsung/snow.c @@ -0,0 +1,123 @@ +/* + * ASoC machine driver for Snow boards + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + */ + +#include +#include +#include +#include + +#include + +#include "i2s.h" + +#define FIN_PLL_RATE 24000000 + +static struct snd_soc_dai_link snow_dai[] = { + { + .name = "Primary", + .stream_name = "Primary", + .codec_dai_name = "HiFi", + .dai_fmt = SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_CBS_CFS, + }, +}; + +static int snow_late_probe(struct snd_soc_card *card) +{ + struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai; + struct snd_soc_dai *cpu_dai = card->rtd[0].cpu_dai; + int ret; + + /* Set the MCLK rate for the codec */ + ret = snd_soc_dai_set_sysclk(codec_dai, 0, + FIN_PLL_RATE, SND_SOC_CLOCK_IN); + if (ret < 0) + return ret; + + /* Select I2S Bus clock to set RCLK and BCLK */ + ret = snd_soc_dai_set_sysclk(cpu_dai, SAMSUNG_I2S_RCLKSRC_0, + 0, SND_SOC_CLOCK_IN); + if (ret < 0) + return ret; + + return 0; +} + +static struct snd_soc_card snow_snd = { + .name = "Snow-I2S", + .dai_link = snow_dai, + .num_links = ARRAY_SIZE(snow_dai), + + .late_probe = snow_late_probe, +}; + +static int snow_probe(struct platform_device *pdev) +{ + struct snd_soc_card *card = &snow_snd; + struct device_node *i2s_node, *codec_node; + int i, ret; + + i2s_node = of_parse_phandle(pdev->dev.of_node, + "samsung,i2s-controller", 0); + if (!i2s_node) { + dev_err(&pdev->dev, + "Property 'i2s-controller' missing or invalid\n"); + return -EINVAL; + } + + codec_node = of_parse_phandle(pdev->dev.of_node, + "samsung,audio-codec", 0); + if (!codec_node) { + dev_err(&pdev->dev, + "Property 'audio-codec' missing or invalid\n"); + return -EINVAL; + } + + for (i = 0; i < ARRAY_SIZE(snow_dai); i++) { + snow_dai[i].codec_of_node = codec_node; + snow_dai[i].cpu_of_node = i2s_node; + snow_dai[i].platform_of_node = i2s_node; + } + + card->dev = &pdev->dev; + + ret = devm_snd_soc_register_card(&pdev->dev, card); + if (ret) { + dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret); + return ret; + } + + return ret; +} + +static const struct of_device_id snow_of_match[] = { + { .compatible = "google,snow-audio-max98090", }, + { .compatible = "google,snow-audio-max98095", }, + {}, +}; + +static struct platform_driver snow_driver = { + .driver = { + .name = "snow-audio", + .owner = THIS_MODULE, + .pm = &snd_soc_pm_ops, + .of_match_table = snow_of_match, + }, + .probe = snow_probe, +}; + +module_platform_driver(snow_driver); + +MODULE_DESCRIPTION("ALSA SoC Audio machine driver for Snow"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/samsung/spdif.c b/sound/soc/samsung/spdif.c index cfe63b7bcc9f..e93a93e296f4 100644 --- a/sound/soc/samsung/spdif.c +++ b/sound/soc/samsung/spdif.c @@ -427,8 +427,8 @@ static int spdif_probe(struct platform_device *pdev) dev_set_drvdata(&pdev->dev, spdif); - ret = snd_soc_register_component(&pdev->dev, &samsung_spdif_component, - &samsung_spdif_dai, 1); + ret = devm_snd_soc_register_component(&pdev->dev, + &samsung_spdif_component, &samsung_spdif_dai, 1); if (ret != 0) { dev_err(&pdev->dev, "fail to register dai\n"); goto err4; @@ -444,12 +444,10 @@ static int spdif_probe(struct platform_device *pdev) ret = samsung_asoc_dma_platform_register(&pdev->dev); if (ret) { dev_err(&pdev->dev, "failed to register DMA: %d\n", ret); - goto err5; + goto err4; } return 0; -err5: - snd_soc_unregister_component(&pdev->dev); err4: iounmap(spdif->regs); err3: @@ -467,9 +465,6 @@ static int spdif_remove(struct platform_device *pdev) struct samsung_spdif_info *spdif = &spdif_info; struct resource *mem_res; - samsung_asoc_dma_platform_unregister(&pdev->dev); - snd_soc_unregister_component(&pdev->dev); - iounmap(spdif->regs); mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); diff --git a/sound/soc/samsung/speyside.c b/sound/soc/samsung/speyside.c index 57df90d6b7c1..9902efcb8ea1 100644 --- a/sound/soc/samsung/speyside.c +++ b/sound/soc/samsung/speyside.c @@ -327,23 +327,12 @@ static int speyside_probe(struct platform_device *pdev) card->dev = &pdev->dev; - ret = snd_soc_register_card(card); - if (ret) { + ret = devm_snd_soc_register_card(&pdev->dev, card); + if (ret) dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", ret); - return ret; - } - return 0; -} - -static int speyside_remove(struct platform_device *pdev) -{ - struct snd_soc_card *card = platform_get_drvdata(pdev); - - snd_soc_unregister_card(card); - - return 0; + return ret; } static struct platform_driver speyside_driver = { @@ -353,7 +342,6 @@ static struct platform_driver speyside_driver = { .pm = &snd_soc_pm_ops, }, .probe = speyside_probe, - .remove = speyside_remove, }; module_platform_driver(speyside_driver); diff --git a/sound/soc/samsung/tobermory.c b/sound/soc/samsung/tobermory.c index 1807b75ccc12..6a2b9f14d624 100644 --- a/sound/soc/samsung/tobermory.c +++ b/sound/soc/samsung/tobermory.c @@ -223,23 +223,12 @@ static int tobermory_probe(struct platform_device *pdev) card->dev = &pdev->dev; - ret = snd_soc_register_card(card); - if (ret) { + ret = devm_snd_soc_register_card(&pdev->dev, card); + if (ret) dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", ret); - return ret; - } - return 0; -} - -static int tobermory_remove(struct platform_device *pdev) -{ - struct snd_soc_card *card = platform_get_drvdata(pdev); - - snd_soc_unregister_card(card); - - return 0; + return ret; } static struct platform_driver tobermory_driver = { @@ -249,7 +238,6 @@ static struct platform_driver tobermory_driver = { .pm = &snd_soc_pm_ops, }, .probe = tobermory_probe, - .remove = tobermory_remove, }; module_platform_driver(tobermory_driver); diff --git a/sound/soc/sh/Kconfig b/sound/soc/sh/Kconfig index ff60e11ecb56..b43fdf0d08af 100644 --- a/sound/soc/sh/Kconfig +++ b/sound/soc/sh/Kconfig @@ -56,7 +56,7 @@ config SND_SH7760_AC97 config SND_SIU_MIGOR tristate "SIU sound support on Migo-R" - depends on SH_MIGOR + depends on SH_MIGOR && I2C select SND_SOC_SH4_SIU select SND_SOC_WM8978 help diff --git a/sound/soc/sirf/sirf-audio-port.c b/sound/soc/sirf/sirf-audio-port.c index b04a53f2b4f6..b4afa31b2bc1 100644 --- a/sound/soc/sirf/sirf-audio-port.c +++ b/sound/soc/sirf/sirf-audio-port.c @@ -6,60 +6,15 @@ * Licensed under GPLv2 or later. */ #include -#include -#include #include #include -#include "sirf-audio-port.h" - struct sirf_audio_port { struct regmap *regmap; struct snd_dmaengine_dai_dma_data playback_dma_data; struct snd_dmaengine_dai_dma_data capture_dma_data; }; -static void sirf_audio_port_tx_enable(struct sirf_audio_port *port) -{ - regmap_update_bits(port->regmap, AUDIO_PORT_IC_TXFIFO_OP, - AUDIO_FIFO_RESET, AUDIO_FIFO_RESET); - regmap_write(port->regmap, AUDIO_PORT_IC_TXFIFO_INT_MSK, 0); - regmap_write(port->regmap, AUDIO_PORT_IC_TXFIFO_OP, 0); - regmap_update_bits(port->regmap, AUDIO_PORT_IC_TXFIFO_OP, - AUDIO_FIFO_START, AUDIO_FIFO_START); - regmap_update_bits(port->regmap, AUDIO_PORT_IC_CODEC_TX_CTRL, - IC_TX_ENABLE, IC_TX_ENABLE); -} - -static void sirf_audio_port_tx_disable(struct sirf_audio_port *port) -{ - regmap_write(port->regmap, AUDIO_PORT_IC_TXFIFO_OP, 0); - regmap_update_bits(port->regmap, AUDIO_PORT_IC_CODEC_TX_CTRL, - IC_TX_ENABLE, ~IC_TX_ENABLE); -} - -static void sirf_audio_port_rx_enable(struct sirf_audio_port *port, - int channels) -{ - regmap_update_bits(port->regmap, AUDIO_PORT_IC_RXFIFO_OP, - AUDIO_FIFO_RESET, AUDIO_FIFO_RESET); - regmap_write(port->regmap, AUDIO_PORT_IC_RXFIFO_INT_MSK, 0); - regmap_write(port->regmap, AUDIO_PORT_IC_RXFIFO_OP, 0); - regmap_update_bits(port->regmap, AUDIO_PORT_IC_RXFIFO_OP, - AUDIO_FIFO_START, AUDIO_FIFO_START); - if (channels == 1) - regmap_update_bits(port->regmap, AUDIO_PORT_IC_CODEC_RX_CTRL, - IC_RX_ENABLE_MONO, IC_RX_ENABLE_MONO); - else - regmap_update_bits(port->regmap, AUDIO_PORT_IC_CODEC_RX_CTRL, - IC_RX_ENABLE_STEREO, IC_RX_ENABLE_STEREO); -} - -static void sirf_audio_port_rx_disable(struct sirf_audio_port *port) -{ - regmap_update_bits(port->regmap, AUDIO_PORT_IC_CODEC_RX_CTRL, - IC_RX_ENABLE_STEREO, ~IC_RX_ENABLE_STEREO); -} static int sirf_audio_port_dai_probe(struct snd_soc_dai *dai) { @@ -69,41 +24,6 @@ static int sirf_audio_port_dai_probe(struct snd_soc_dai *dai) return 0; } -static int sirf_audio_port_trigger(struct snd_pcm_substream *substream, int cmd, - struct snd_soc_dai *dai) -{ - struct sirf_audio_port *port = snd_soc_dai_get_drvdata(dai); - int playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_SUSPEND: - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - if (playback) - sirf_audio_port_tx_disable(port); - else - sirf_audio_port_rx_disable(port); - break; - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_RESUME: - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - if (playback) - sirf_audio_port_tx_enable(port); - else - sirf_audio_port_rx_enable(port, - substream->runtime->channels); - break; - default: - return -EINVAL; - } - - return 0; -} - -static const struct snd_soc_dai_ops sirf_audio_port_dai_ops = { - .trigger = sirf_audio_port_trigger, -}; - static struct snd_soc_dai_driver sirf_audio_port_dai = { .probe = sirf_audio_port_dai_probe, .name = "sirf-audio-port", @@ -120,49 +40,22 @@ static struct snd_soc_dai_driver sirf_audio_port_dai = { .rates = SNDRV_PCM_RATE_48000, .formats = SNDRV_PCM_FMTBIT_S16_LE, }, - .ops = &sirf_audio_port_dai_ops, }; static const struct snd_soc_component_driver sirf_audio_port_component = { .name = "sirf-audio-port", }; -static const struct regmap_config sirf_audio_port_regmap_config = { - .reg_bits = 32, - .reg_stride = 4, - .val_bits = 32, - .max_register = AUDIO_PORT_IC_RXFIFO_INT_MSK, - .cache_type = REGCACHE_NONE, -}; - static int sirf_audio_port_probe(struct platform_device *pdev) { int ret; struct sirf_audio_port *port; - void __iomem *base; - struct resource *mem_res; port = devm_kzalloc(&pdev->dev, sizeof(struct sirf_audio_port), GFP_KERNEL); if (!port) return -ENOMEM; - mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!mem_res) { - dev_err(&pdev->dev, "no mem resource?\n"); - return -ENODEV; - } - - base = devm_ioremap(&pdev->dev, mem_res->start, - resource_size(mem_res)); - if (base == NULL) - return -ENOMEM; - - port->regmap = devm_regmap_init_mmio(&pdev->dev, base, - &sirf_audio_port_regmap_config); - if (IS_ERR(port->regmap)) - return PTR_ERR(port->regmap); - ret = devm_snd_soc_register_component(&pdev->dev, &sirf_audio_port_component, &sirf_audio_port_dai, 1); if (ret) diff --git a/sound/soc/sirf/sirf-audio-port.h b/sound/soc/sirf/sirf-audio-port.h deleted file mode 100644 index f32dc54f4499..000000000000 --- a/sound/soc/sirf/sirf-audio-port.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * SiRF Audio port controllers define - * - * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company. - * - * Licensed under GPLv2 or later. - */ - -#ifndef _SIRF_AUDIO_PORT_H -#define _SIRF_AUDIO_PORT_H - -#define AUDIO_PORT_TX_FIFO_LEVEL_CHECK_MASK 0x3F -#define AUDIO_PORT_TX_FIFO_SC_OFFSET 0 -#define AUDIO_PORT_TX_FIFO_LC_OFFSET 10 -#define AUDIO_PORT_TX_FIFO_HC_OFFSET 20 - -#define TX_FIFO_SC(x) (((x) & AUDIO_PORT_TX_FIFO_LEVEL_CHECK_MASK) \ - << AUDIO_PORT_TX_FIFO_SC_OFFSET) -#define TX_FIFO_LC(x) (((x) & AUDIO_PORT_TX_FIFO_LEVEL_CHECK_MASK) \ - << AUDIO_PORT_TX_FIFO_LC_OFFSET) -#define TX_FIFO_HC(x) (((x) & AUDIO_PORT_TX_FIFO_LEVEL_CHECK_MASK) \ - << AUDIO_PORT_TX_FIFO_HC_OFFSET) - -#define AUDIO_PORT_RX_FIFO_LEVEL_CHECK_MASK 0x0F -#define AUDIO_PORT_RX_FIFO_SC_OFFSET 0 -#define AUDIO_PORT_RX_FIFO_LC_OFFSET 10 -#define AUDIO_PORT_RX_FIFO_HC_OFFSET 20 - -#define RX_FIFO_SC(x) (((x) & AUDIO_PORT_RX_FIFO_LEVEL_CHECK_MASK) \ - << AUDIO_PORT_RX_FIFO_SC_OFFSET) -#define RX_FIFO_LC(x) (((x) & AUDIO_PORT_RX_FIFO_LEVEL_CHECK_MASK) \ - << AUDIO_PORT_RX_FIFO_LC_OFFSET) -#define RX_FIFO_HC(x) (((x) & AUDIO_PORT_RX_FIFO_LEVEL_CHECK_MASK) \ - << AUDIO_PORT_RX_FIFO_HC_OFFSET) -#define AUDIO_PORT_IC_CODEC_TX_CTRL (0x00F4) -#define AUDIO_PORT_IC_CODEC_RX_CTRL (0x00F8) - -#define AUDIO_PORT_IC_TXFIFO_OP (0x00FC) -#define AUDIO_PORT_IC_TXFIFO_LEV_CHK (0x0100) -#define AUDIO_PORT_IC_TXFIFO_STS (0x0104) -#define AUDIO_PORT_IC_TXFIFO_INT (0x0108) -#define AUDIO_PORT_IC_TXFIFO_INT_MSK (0x010C) - -#define AUDIO_PORT_IC_RXFIFO_OP (0x0110) -#define AUDIO_PORT_IC_RXFIFO_LEV_CHK (0x0114) -#define AUDIO_PORT_IC_RXFIFO_STS (0x0118) -#define AUDIO_PORT_IC_RXFIFO_INT (0x011C) -#define AUDIO_PORT_IC_RXFIFO_INT_MSK (0x0120) - -#define AUDIO_FIFO_START (1 << 0) -#define AUDIO_FIFO_RESET (1 << 1) - -#define AUDIO_FIFO_FULL (1 << 0) -#define AUDIO_FIFO_EMPTY (1 << 1) -#define AUDIO_FIFO_OFLOW (1 << 2) -#define AUDIO_FIFO_UFLOW (1 << 3) - -#define IC_TX_ENABLE (0x03) -#define IC_RX_ENABLE_MONO (0x01) -#define IC_RX_ENABLE_STEREO (0x03) - -#endif /*__SIRF_AUDIO_PORT_H*/ diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 6e460529fc89..b87d7d882e6d 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -4613,7 +4613,9 @@ int snd_soc_of_parse_audio_routing(struct snd_soc_card *card, EXPORT_SYMBOL_GPL(snd_soc_of_parse_audio_routing); unsigned int snd_soc_of_parse_daifmt(struct device_node *np, - const char *prefix) + const char *prefix, + struct device_node **bitclkmaster, + struct device_node **framemaster) { int ret, i; char prop[128]; @@ -4696,9 +4698,13 @@ unsigned int snd_soc_of_parse_daifmt(struct device_node *np, */ snprintf(prop, sizeof(prop), "%sbitclock-master", prefix); bit = !!of_get_property(np, prop, NULL); + if (bit && bitclkmaster) + *bitclkmaster = of_parse_phandle(np, prop, 0); snprintf(prop, sizeof(prop), "%sframe-master", prefix); frame = !!of_get_property(np, prop, NULL); + if (frame && framemaster) + *framemaster = of_parse_phandle(np, prop, 0); switch ((bit << 4) + frame) { case 0x11: