···11+* Allwinner A10 Codec22+33+Required properties:44+- compatible: must be either "allwinner,sun4i-a10-codec" or55+ "allwinner,sun7i-a20-codec"66+- reg: must contain the registers location and length77+- interrupts: must contain the codec interrupt88+- dmas: DMA channels for tx and rx dma. See the DMA client binding,99+ Documentation/devicetree/bindings/dma/dma.txt1010+- dma-names: should include "tx" and "rx".1111+- clocks: a list of phandle + clock-specifer pairs, one for each entry1212+ in clock-names.1313+- clock-names: should contain followings:1414+ - "apb": the parent APB clock for this controller1515+ - "codec": the parent module clock1616+- routing : A list of the connections between audio components. Each1717+ entry is a pair of strings, the first being the connection's sink,1818+ the second being the connection's source.1919+2020+2121+Example:2222+codec: codec@01c22c00 {2323+ #sound-dai-cells = <0>;2424+ compatible = "allwinner,sun7i-a20-codec";2525+ reg = <0x01c22c00 0x40>;2626+ interrupts = <0 30 4>;2727+ clocks = <&apb0_gates 0>, <&codec_clk>;2828+ clock-names = "apb", "codec";2929+ dmas = <&dma 0 19>, <&dma 0 19>;3030+ dma-names = "rx", "tx";3131+ routing = "Headphone Jack", "HP Right",3232+ "Headphone Jack", "HP Left";3333+};
···4455TDM slot properties:66dai-tdm-slot-num : Number of slots in use.77-dai-tdm-slot-width : Width in bits for each slot.77+dai-tdm-slot-width : Width in bits for each slot.88+dai-tdm-slot-tx-mask : Transmit direction slot mask, optional99+dai-tdm-slot-rx-mask : Receive direction slot mask, optional810911For instance:1012 dai-tdm-slot-num = <2>;1113 dai-tdm-slot-width = <8>;1414+ dai-tdm-slot-tx-mask = <0 1>;1515+ dai-tdm-slot-rx-mask = <1 0>;12161317And for each spcified driver, there could be one .of_xlate_tdm_slot_mask()1418to specify a explicit mapping of the channels and the slots. If it's absent···2218For snd_soc_of_xlate_tdm_slot_mask(), the tx and rx masks will use a 1 bit2319for an active slot as default, and the default active bits are at the LSB of2420the masks.2121+2222+The explicit masks are given as array of integers, where the first2323+number presents bit-0 (LSB), second presents bit-1, etc. Any non zero2424+number is considered 1 and 0 is 0. snd_soc_of_xlate_tdm_slot_mask()2525+does not do anything, if either mask is set non zero value.
+2
include/sound/simple_card.h
···1919 unsigned int sysclk;2020 int slots;2121 int slot_width;2222+ unsigned int tx_slot_mask;2323+ unsigned int rx_slot_mask;2224 struct clk *clk;2325};2426
+2
include/sound/soc.h
···16131613int snd_soc_of_parse_audio_simple_widgets(struct snd_soc_card *card,16141614 const char *propname);16151615int snd_soc_of_parse_tdm_slot(struct device_node *np,16161616+ unsigned int *tx_mask,16171617+ unsigned int *rx_mask,16161618 unsigned int *slots,16171619 unsigned int *slot_width);16181620void snd_soc_of_parse_audio_prefix(struct snd_soc_card *card,
···8080 unsigned int sysclk;8181 unsigned int dai_fmt;8282 unsigned int tdm_delay;8383+ unsigned int slot_width;8384 struct list_head list;8485 int master;8586 int gpio_reset;···10261025 u8 data, j, r, p, pll_q, pll_p = 1, pll_r = 1, pll_j = 1;10271026 u16 d, pll_d = 1;10281027 int clk;10281028+ int width = aic3x->slot_width;10291029+10301030+ if (!width)10311031+ width = params_width(params);1029103210301033 /* select data word length */10311034 data = snd_soc_read(codec, AIC3X_ASD_INTF_CTRLB) & (~(0x3 << 4));10321032- switch (params_width(params)) {10351035+ switch (width) {10331036 case 16:10341037 break;10351038 case 20:···11751170 struct snd_soc_codec *codec = dai->codec;11761171 struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec);11771172 int delay = 0;11731173+ int width = aic3x->slot_width;11741174+11751175+ if (!width)11761176+ width = substream->runtime->sample_bits;1178117711791178 /* TDM slot selection only valid in DSP_A/_B mode */11801179 if (aic3x->dai_fmt == SND_SOC_DAIFMT_DSP_A)11811181- delay += (aic3x->tdm_delay + 1);11801180+ delay += (aic3x->tdm_delay*width + 1);11821181 else if (aic3x->dai_fmt == SND_SOC_DAIFMT_DSP_B)11831183- delay += aic3x->tdm_delay;11821182+ delay += aic3x->tdm_delay*width;1184118311851184 /* Configure data delay */11861185 snd_soc_write(codec, AIC3X_ASD_INTF_CTRLC, delay);···13051296 return -EINVAL;13061297 }1307129813081308- aic3x->tdm_delay = lsb * slot_width;12991299+ switch (slot_width) {13001300+ case 16:13011301+ case 20:13021302+ case 24:13031303+ case 32:13041304+ break;13051305+ default:13061306+ dev_err(codec->dev, "Unsupported slot width %d\n", slot_width);13071307+ return -EINVAL;13081308+ }13091309+13101310+13111311+ aic3x->tdm_delay = lsb;13121312+ aic3x->slot_width = slot_width;1309131313101314 /* DOUT in high-impedance on inactive bit clocks */13111315 snd_soc_update_bits(codec, AIC3X_ASD_INTF_CTRLA,
+6-2
sound/soc/generic/simple-card.c
···151151 }152152153153 if (set->slots) {154154- ret = snd_soc_dai_set_tdm_slot(dai, 0, 0,154154+ ret = snd_soc_dai_set_tdm_slot(dai,155155+ set->tx_slot_mask,156156+ set->rx_slot_mask,155157 set->slots,156158 set->slot_width);157159 if (ret && ret != -ENOTSUPP) {···245243 return ret;246244247245 /* Parse TDM slot */248248- ret = snd_soc_of_parse_tdm_slot(np, &dai->slots, &dai->slot_width);246246+ ret = snd_soc_of_parse_tdm_slot(np, &dai->tx_slot_mask,247247+ &dai->rx_slot_mask,248248+ &dai->slots, &dai->slot_width);249249 if (ret)250250 return ret;251251
+24-61
sound/soc/sh/siu_dai.c
···738738 struct siu_info *info;739739 int ret;740740741741- info = kmalloc(sizeof(*info), GFP_KERNEL);741741+ info = devm_kmalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);742742 if (!info)743743 return -ENOMEM;744744 siu_i2s_data = info;···746746747747 ret = request_firmware(&fw_entry, "siu_spb.bin", &pdev->dev);748748 if (ret)749749- goto ereqfw;749749+ return ret;750750751751 /*752752 * Loaded firmware is "const" - read only, but we have to modify it in···757757 release_firmware(fw_entry);758758759759 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);760760- if (!res) {761761- ret = -ENODEV;762762- goto egetres;763763- }760760+ if (!res)761761+ return -ENODEV;764762765765- region = request_mem_region(res->start, resource_size(res),766766- pdev->name);763763+ region = devm_request_mem_region(&pdev->dev, res->start,764764+ resource_size(res), pdev->name);767765 if (!region) {768766 dev_err(&pdev->dev, "SIU region already claimed\n");769769- ret = -EBUSY;770770- goto ereqmemreg;767767+ return -EBUSY;771768 }772769773773- ret = -ENOMEM;774774- info->pram = ioremap(res->start, PRAM_SIZE);770770+ info->pram = devm_ioremap(&pdev->dev, res->start, PRAM_SIZE);775771 if (!info->pram)776776- goto emappram;777777- info->xram = ioremap(res->start + XRAM_OFFSET, XRAM_SIZE);772772+ return -ENOMEM;773773+ info->xram = devm_ioremap(&pdev->dev, res->start + XRAM_OFFSET,774774+ XRAM_SIZE);778775 if (!info->xram)779779- goto emapxram;780780- info->yram = ioremap(res->start + YRAM_OFFSET, YRAM_SIZE);776776+ return -ENOMEM;777777+ info->yram = devm_ioremap(&pdev->dev, res->start + YRAM_OFFSET,778778+ YRAM_SIZE);781779 if (!info->yram)782782- goto emapyram;783783- info->reg = ioremap(res->start + REG_OFFSET, resource_size(res) -784784- REG_OFFSET);780780+ return -ENOMEM;781781+ info->reg = devm_ioremap(&pdev->dev, res->start + REG_OFFSET,782782+ resource_size(res) - REG_OFFSET);785783 if (!info->reg)786786- goto emapreg;784784+ return -ENOMEM;787785788786 dev_set_drvdata(&pdev->dev, info);789787790788 /* register using ARRAY version so we can keep dai name */791791- ret = snd_soc_register_component(&pdev->dev, &siu_i2s_component,792792- &siu_i2s_dai, 1);789789+ ret = devm_snd_soc_register_component(&pdev->dev, &siu_i2s_component,790790+ &siu_i2s_dai, 1);793791 if (ret < 0)794794- goto edaiinit;792792+ return ret;795793796796- ret = snd_soc_register_platform(&pdev->dev, &siu_platform);794794+ ret = devm_snd_soc_register_platform(&pdev->dev, &siu_platform);797795 if (ret < 0)798798- goto esocregp;796796+ return ret;799797800798 pm_runtime_enable(&pdev->dev);801799802802- return ret;803803-804804-esocregp:805805- snd_soc_unregister_component(&pdev->dev);806806-edaiinit:807807- iounmap(info->reg);808808-emapreg:809809- iounmap(info->yram);810810-emapyram:811811- iounmap(info->xram);812812-emapxram:813813- iounmap(info->pram);814814-emappram:815815- release_mem_region(res->start, resource_size(res));816816-ereqmemreg:817817-egetres:818818-ereqfw:819819- kfree(info);820820-821821- return ret;800800+ return 0;822801}823802824803static int siu_remove(struct platform_device *pdev)825804{826826- struct siu_info *info = dev_get_drvdata(&pdev->dev);827827- struct resource *res;828828-829805 pm_runtime_disable(&pdev->dev);830830-831831- snd_soc_unregister_platform(&pdev->dev);832832- snd_soc_unregister_component(&pdev->dev);833833-834834- iounmap(info->reg);835835- iounmap(info->yram);836836- iounmap(info->xram);837837- iounmap(info->pram);838838- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);839839- if (res)840840- release_mem_region(res->start, resource_size(res));841841- kfree(info);842842-843806 return 0;844807}845808
+25
sound/soc/soc-core.c
···32913291}32923292EXPORT_SYMBOL_GPL(snd_soc_of_parse_audio_simple_widgets);3293329332943294+static int snd_soc_of_get_slot_mask(struct device_node *np,32953295+ const char *prop_name,32963296+ unsigned int *mask)32973297+{32983298+ u32 val;32993299+ const __be32 *of_slot_mask = of_get_property(np, prop_name, &val);33003300+ int i;33013301+33023302+ if (!of_slot_mask)33033303+ return 0;33043304+ val /= sizeof(u32);33053305+ for (i = 0; i < val; i++)33063306+ if (be32_to_cpup(&of_slot_mask[i]))33073307+ *mask |= (1 << i);33083308+33093309+ return val;33103310+}33113311+32943312int snd_soc_of_parse_tdm_slot(struct device_node *np,33133313+ unsigned int *tx_mask,33143314+ unsigned int *rx_mask,32953315 unsigned int *slots,32963316 unsigned int *slot_width)32973317{32983318 u32 val;32993319 int ret;33203320+33213321+ if (tx_mask)33223322+ snd_soc_of_get_slot_mask(np, "dai-tdm-slot-tx-mask", tx_mask);33233323+ if (rx_mask)33243324+ snd_soc_of_get_slot_mask(np, "dai-tdm-slot-rx-mask", rx_mask);3300332533013326 if (of_property_read_bool(np, "dai-tdm-slot-num")) {33023327 ret = of_property_read_u32(np, "dai-tdm-slot-num", &val);
+11
sound/soc/sunxi/Kconfig
···11+menu "Allwinner SoC Audio support"22+33+config SND_SUN4I_CODEC44+ tristate "Allwinner A10 Codec Support"55+ select SND_SOC_GENERIC_DMAENGINE_PCM66+ select REGMAP_MMIO77+ help88+ Select Y or M to add support for the Codec embedded in the Allwinner99+ A10 and affiliated SoCs.1010+1111+endmenu