diff options
Diffstat (limited to 'sound/soc/fsl/imx-card.c')
-rw-r--r-- | sound/soc/fsl/imx-card.c | 77 |
1 files changed, 51 insertions, 26 deletions
diff --git a/sound/soc/fsl/imx-card.c b/sound/soc/fsl/imx-card.c index 6f06afd23b16..3f128ced4180 100644 --- a/sound/soc/fsl/imx-card.c +++ b/sound/soc/fsl/imx-card.c @@ -17,6 +17,9 @@ #include "fsl_sai.h" +#define IMX_CARD_MCLK_22P5792MHZ 22579200 +#define IMX_CARD_MCLK_24P576MHZ 24576000 + enum codec_type { CODEC_DUMMY = 0, CODEC_AK5558 = 1, @@ -115,12 +118,12 @@ struct imx_card_data { struct snd_soc_card card; int num_dapm_routes; u32 asrc_rate; - u32 asrc_format; + snd_pcm_format_t asrc_format; }; static struct imx_akcodec_fs_mul ak4458_fs_mul[] = { /* Normal, < 32kHz */ - { .rmin = 8000, .rmax = 24000, .wmin = 1024, .wmax = 1024, }, + { .rmin = 8000, .rmax = 24000, .wmin = 256, .wmax = 1024, }, /* Normal, 32kHz */ { .rmin = 32000, .rmax = 32000, .wmin = 256, .wmax = 1024, }, /* Normal */ @@ -151,8 +154,8 @@ static struct imx_akcodec_fs_mul ak4497_fs_mul[] = { * Table 7 - mapping multiplier and speed mode * Tables 8 & 9 - mapping speed mode and LRCK fs */ - { .rmin = 8000, .rmax = 32000, .wmin = 1024, .wmax = 1024, }, /* Normal, <= 32kHz */ - { .rmin = 44100, .rmax = 48000, .wmin = 512, .wmax = 512, }, /* Normal */ + { .rmin = 8000, .rmax = 32000, .wmin = 256, .wmax = 1024, }, /* Normal, <= 32kHz */ + { .rmin = 44100, .rmax = 48000, .wmin = 256, .wmax = 512, }, /* Normal */ { .rmin = 88200, .rmax = 96000, .wmin = 256, .wmax = 256, }, /* Double */ { .rmin = 176400, .rmax = 192000, .wmin = 128, .wmax = 128, }, /* Quad */ { .rmin = 352800, .rmax = 384000, .wmin = 128, .wmax = 128, }, /* Oct */ @@ -164,7 +167,7 @@ static struct imx_akcodec_fs_mul ak4497_fs_mul[] = { * (Table 4 from datasheet) */ static struct imx_akcodec_fs_mul ak5558_fs_mul[] = { - { .rmin = 8000, .rmax = 32000, .wmin = 1024, .wmax = 1024, }, + { .rmin = 8000, .rmax = 32000, .wmin = 512, .wmax = 1024, }, { .rmin = 44100, .rmax = 48000, .wmin = 512, .wmax = 512, }, { .rmin = 88200, .rmax = 96000, .wmin = 256, .wmax = 256, }, { .rmin = 176400, .rmax = 192000, .wmin = 128, .wmax = 128, }, @@ -247,13 +250,14 @@ static bool codec_is_akcodec(unsigned int type) } static unsigned long akcodec_get_mclk_rate(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) + struct snd_pcm_hw_params *params, + int slots, int slot_width) { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct imx_card_data *data = snd_soc_card_get_drvdata(rtd->card); const struct imx_card_plat_data *plat_data = data->plat_data; struct dai_link_data *link_data = &data->link_data[rtd->num]; - unsigned int width = link_data->slots * link_data->slot_width; + unsigned int width = slots * slot_width; unsigned int rate = params_rate(params); int i; @@ -316,7 +320,7 @@ static int imx_aif_hw_params(struct snd_pcm_substream *substream, } } - ret = snd_soc_dai_set_fmt(cpu_dai, fmt); + ret = snd_soc_dai_set_fmt(cpu_dai, snd_soc_daifmt_clock_provider_flipped(fmt)); if (ret && ret != -ENOTSUPP) { dev_err(dev, "failed to set cpu dai fmt: %d\n", ret); return ret; @@ -349,12 +353,17 @@ static int imx_aif_hw_params(struct snd_pcm_substream *substream, /* Set MCLK freq */ if (codec_is_akcodec(plat_data->type)) - mclk_freq = akcodec_get_mclk_rate(substream, params); + mclk_freq = akcodec_get_mclk_rate(substream, params, slots, slot_width); else mclk_freq = params_rate(params) * slots * slot_width; - /* Use the maximum freq from DSD512 (512*44100 = 22579200) */ - if (format_is_dsd(params)) - mclk_freq = 22579200; + + if (format_is_dsd(params)) { + /* Use the maximum freq from DSD512 (512*44100 = 22579200) */ + if (!(params_rate(params) % 11025)) + mclk_freq = IMX_CARD_MCLK_22P5792MHZ; + else + mclk_freq = IMX_CARD_MCLK_24P576MHZ; + } ret = snd_soc_dai_set_sysclk(cpu_dai, link_data->cpu_sysclk_id, mclk_freq, SND_SOC_CLOCK_OUT); @@ -465,7 +474,7 @@ static int be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, mask = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); snd_mask_none(mask); - snd_mask_set(mask, data->asrc_format); + snd_mask_set(mask, (__force unsigned int)data->asrc_format); return 0; } @@ -484,6 +493,7 @@ static int imx_card_parse_of(struct imx_card_data *data) struct dai_link_data *link_data; struct of_phandle_args args; int ret, num_links; + u32 asrc_fmt = 0; u32 width; ret = snd_soc_of_parse_card_name(card, "model"); @@ -553,8 +563,23 @@ static int imx_card_parse_of(struct imx_card_data *data) link_data->cpu_sysclk_id = FSL_SAI_CLK_MAST1; /* sai may support mclk/bclk = 1 */ - if (of_find_property(np, "fsl,mclk-equal-bclk", NULL)) + if (of_find_property(np, "fsl,mclk-equal-bclk", NULL)) { link_data->one2one_ratio = true; + } else { + int i; + + /* + * i.MX8MQ don't support one2one ratio, then + * with ak4497 only 16bit case is supported. + */ + for (i = 0; i < ARRAY_SIZE(ak4497_fs_mul); i++) { + if (ak4497_fs_mul[i].rmin == 705600 && + ak4497_fs_mul[i].rmax == 768000) { + ak4497_fs_mul[i].wmin = 32; + ak4497_fs_mul[i].wmax = 32; + } + } + } } link->cpus->of_node = args.np; @@ -563,9 +588,8 @@ static int imx_card_parse_of(struct imx_card_data *data) ret = snd_soc_of_get_dai_name(cpu, &link->cpus->dai_name); if (ret) { - if (ret != -EPROBE_DEFER) - dev_err(card->dev, "%s: error getting cpu dai name: %d\n", - link->name, ret); + dev_err_probe(card->dev, ret, + "%s: error getting cpu dai name\n", link->name); goto err; } @@ -573,9 +597,8 @@ static int imx_card_parse_of(struct imx_card_data *data) if (codec) { ret = snd_soc_of_get_dai_link_codecs(dev, codec, link); if (ret < 0) { - if (ret != -EPROBE_DEFER) - dev_err(dev, "%s: codec dai not found: %d\n", - link->name, ret); + dev_err_probe(dev, ret, "%s: codec dai not found\n", + link->name); goto err; } @@ -617,7 +640,8 @@ static int imx_card_parse_of(struct imx_card_data *data) goto err; } - ret = of_property_read_u32(args.np, "fsl,asrc-format", &data->asrc_format); + ret = of_property_read_u32(args.np, "fsl,asrc-format", &asrc_fmt); + data->asrc_format = (__force snd_pcm_format_t)asrc_fmt; if (ret) { /* Fallback to old binding; translate to asrc_format */ ret = of_property_read_u32(args.np, "fsl,asrc-width", &width); @@ -674,6 +698,10 @@ static int imx_card_parse_of(struct imx_card_data *data) of_node_put(cpu); of_node_put(codec); of_node_put(platform); + + cpu = NULL; + codec = NULL; + platform = NULL; } return 0; @@ -814,11 +842,8 @@ static int imx_card_probe(struct platform_device *pdev) } ret = devm_snd_soc_register_card(&pdev->dev, &data->card); - if (ret) { - if (ret != -EPROBE_DEFER) - dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret); - return ret; - } + if (ret) + return dev_err_probe(&pdev->dev, ret, "snd_soc_register_card failed\n"); return 0; } |