Example #1
0
int asoc_simple_card_parse_daifmt(struct device *dev,
				  struct device_node *node,
				  struct device_node *codec,
				  char *prefix,
				  unsigned int *retfmt)
{
	struct device_node *bitclkmaster = NULL;
	struct device_node *framemaster = NULL;
	unsigned int daifmt;

	daifmt = snd_soc_of_parse_daifmt(node, prefix,
					 &bitclkmaster, &framemaster);
	daifmt &= ~SND_SOC_DAIFMT_MASTER_MASK;

	if (!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, "Revert to legacy daifmt parsing\n");

		daifmt = snd_soc_of_parse_daifmt(codec, NULL, NULL, NULL) |
			(daifmt & ~SND_SOC_DAIFMT_CLOCK_MASK);
	} else {
		if (codec == bitclkmaster)
			daifmt |= (codec == framemaster) ?
				SND_SOC_DAIFMT_CBM_CFM : SND_SOC_DAIFMT_CBM_CFS;
		else
			daifmt |= (codec == framemaster) ?
				SND_SOC_DAIFMT_CBS_CFM : SND_SOC_DAIFMT_CBS_CFS;
	}

	of_node_put(bitclkmaster);
	of_node_put(framemaster);

	*retfmt = daifmt;

	dev_dbg(dev, "format : %04x\n", daifmt);

	return 0;
}
Example #2
0
static int asoc_simple_card_parse_daifmt(struct device_node *node,
					 struct simple_card_data *priv,
					 struct device_node *codec,
					 char *prefix, int idx)
{
	struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, idx);
	struct device *dev = simple_priv_to_dev(priv);
	struct device_node *bitclkmaster = NULL;
	struct device_node *framemaster = NULL;
	unsigned int daifmt;

	daifmt = snd_soc_of_parse_daifmt(node, prefix,
					 &bitclkmaster, &framemaster);
	daifmt &= ~SND_SOC_DAIFMT_MASTER_MASK;

	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, "Revert to legacy daifmt parsing\n");

		daifmt = snd_soc_of_parse_daifmt(codec, NULL, NULL, NULL) |
			(daifmt & ~SND_SOC_DAIFMT_CLOCK_MASK);
	} else {
		if (codec == bitclkmaster)
			daifmt |= (codec == framemaster) ?
				SND_SOC_DAIFMT_CBM_CFM : SND_SOC_DAIFMT_CBM_CFS;
		else
			daifmt |= (codec == framemaster) ?
				SND_SOC_DAIFMT_CBS_CFM : SND_SOC_DAIFMT_CBS_CFS;
	}

	dai_link->dai_fmt = daifmt;

	of_node_put(bitclkmaster);
	of_node_put(framemaster);

	return 0;
}
/*
  Get sound card infos:
      audio-codec
      i2s-controller

      format

      continuous-clock

      bitclock-inversion
      frame-inversion

      bitclock-master
      frame-master

  Get audio-codec and i2s-controller in this fun,
  and get oher infos in fun snd_soc_of_parse_daifmt().

  Set in dts:
		dais {
			dai0 {
				audio-codec = <&codec_of_node>;
				i2s-controller = <&cpu_of_node>;
				format = "i2s";
				//continuous-clock;
				//bitclock-inversion;
				//frame-inversion;
				//bitclock-master;
				//frame-master;
			};

			dai1 {
				audio-codec = <&codec_of_node>;
				i2s-controller = <&cpu_of_node>;
				format = "dsp_a";
				//continuous-clock;
				bitclock-inversion;
				//frame-inversion;
				//bitclock-master;
				//frame-master;
			};
		};
 */
int rockchip_of_get_sound_card_info_(struct snd_soc_card *card,
                                     bool is_need_fmt)
{
    struct device_node *dai_node, *child_dai_node;
    int dai_num;

    dai_node = of_get_child_by_name(card->dev->of_node, "dais");
    if (!dai_node) {
        dev_err(card->dev, "%s() Can not get child: dais\n",
                __func__);
        return -EINVAL;
    }

    dai_num = 0;

    for_each_child_of_node(dai_node, child_dai_node) {

        if (is_need_fmt) {
            card->dai_link[dai_num].dai_fmt =
                snd_soc_of_parse_daifmt(child_dai_node, NULL);
            if ((card->dai_link[dai_num].dai_fmt &
                    SND_SOC_DAIFMT_MASTER_MASK) == 0) {
                dev_err(card->dev,
                        "Property 'format' missing or invalid\n");
                return -EINVAL;
            }
        }

        card->dai_link[dai_num].codec_name = NULL;
        card->dai_link[dai_num].cpu_dai_name = NULL;
        card->dai_link[dai_num].platform_name = NULL;

        card->dai_link[dai_num].codec_of_node = of_parse_phandle(
                child_dai_node,
                "audio-codec", 0);
        if (!card->dai_link[dai_num].codec_of_node) {
            dev_err(card->dev,
                    "Property 'audio-codec' missing or invalid\n");
            return -EINVAL;
        }

        card->dai_link[dai_num].cpu_of_node = of_parse_phandle(
                child_dai_node,
                "i2s-controller", 0);
        if (!card->dai_link[dai_num].cpu_of_node) {
            dev_err(card->dev,
                    "Property 'i2s-controller' missing or invalid\n");
            return -EINVAL;
        }

        card->dai_link[dai_num].platform_of_node =
            card->dai_link[dai_num].cpu_of_node;

        if (++dai_num >= card->num_links)
            break;
    }

    if (dai_num < card->num_links) {
        dev_err(card->dev, "%s() Can not get enough property for dais, dai: %d, max dai num: %d\n",
                __func__, dai_num, card->num_links);
        return -EINVAL;
    }

    return 0;
}
Example #4
0
	} else {
		clk = of_clk_get(args.np, 0);
		if (!IS_ERR(clk))
			dai->sysclk = clk_get_rate(clk);
	}

	return 0;
}

static int asoc_s;
	struct device *dev = simple_priv_to_dev(priv);
	struct device_node *bitclkmaster = NULL;
	struct device_node *framemaster = NULL;
	unsigned int daifmt;

	daifmt = snd_soc_of_parse_daifmt(node, prefix,
					 &bitclkmaster, &framemaster);
	daifmt &= ~SND_SOC_DAIFMT_MASTER_MASK;

	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, "Revert to legacy daifmt parsing\n");

		daifmt = snd_soc_of_parse_daifmt(codec, NULL, NULL, NULL) |
			(daifmt & ~SND_SOC_DAIFMT_CLOCK_MASK);
	} else {
		if (codec == bitclkmaster)
			daifmt |= (codec == framemaster) ?
Example #5
0
static int asoc_simple_card_dai_link_of(struct device_node *node,
                                        struct simple_card_data *priv,
                                        int idx,
                                        bool is_top_level_node)
{
    struct device *dev = simple_priv_to_dev(priv);
    struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, idx);
    struct simple_dai_props *dai_props = simple_priv_to_props(priv, idx);
    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_args;

    /* For single DAI link & old style of DT node */
    if (is_top_level_node)
        prefix = "simple-audio-card,";

    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,
                                        &cpu_args);
    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, NULL);
    if (ret < 0)
        goto dai_link_of_err;

    if (strlen(prefix) && !bitclkmaster && !framemaster) {
        /*
         * No DAI link level and master setting was 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;

    /* DAI 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;
    dai_link->ops = &asoc_simple_card_ops;
    dai_link->init = asoc_simple_card_dai_init;

    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);

    /*
     * In soc_bind_dai_link() will check cpu name after
     * of_node matching if dai_link has cpu_dai_name.
     * but, it will never match if name was created by
     * fmt_single_name() remove cpu_dai_name if cpu_args
     * was 0. See:
     *	fmt_single_name()
     *	fmt_multiple_name()
     */
    if (!cpu_args)
        dai_link->cpu_dai_name = NULL;

dai_link_of_err:
    if (np)
        of_node_put(np);
    if (bitclkmaster)
        of_node_put(bitclkmaster);
    if (framemaster)
        of_node_put(framemaster);
    return ret;
}