static int uni_player_parse_dt(struct platform_device *pdev, struct uniperif *player) { struct uniperif_info *info; struct device *dev = &pdev->dev; struct device_node *pnode = pdev->dev.of_node; const char *mode; /* Allocate memory for the info structure */ info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL); if (!info) return -ENOMEM; if (of_property_read_u32(pnode, "st,version", &player->ver) || player->ver == SND_ST_UNIPERIF_VERSION_UNKNOWN) { dev_err(dev, "Unknown uniperipheral version "); return -EINVAL; } /* Underflow recovery is only supported on later ip revisions */ if (player->ver >= SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0) info->underflow_enabled = 1; if (of_property_read_u32(pnode, "st,uniperiph-id", &info->id)) { dev_err(dev, "uniperipheral id not defined"); return -EINVAL; } /* Read the device mode property */ if (of_property_read_string(pnode, "st,mode", &mode)) { dev_err(dev, "uniperipheral mode not defined"); return -EINVAL; } if (strcasecmp(mode, "hdmi") == 0) info->type = SND_ST_UNIPERIF_TYPE_HDMI; else if (strcasecmp(mode, "pcm") == 0) info->type = SND_ST_UNIPERIF_TYPE_PCM; else if (strcasecmp(mode, "spdif") == 0) info->type = SND_ST_UNIPERIF_TYPE_SPDIF; else if (strcasecmp(mode, "tdm") == 0) info->type = SND_ST_UNIPERIF_TYPE_TDM; else info->type = SND_ST_UNIPERIF_TYPE_NONE; /* Save the info structure */ player->info = info; /* Get PCM_CLK_SEL & PCMP_VALID_SEL from audio-glue-ctrl SoC reg */ if (uni_player_parse_dt_audio_glue(pdev, player)) return -EINVAL; return 0; }
int uni_player_init(struct platform_device *pdev, struct uniperif *player) { int ret = 0; player->dev = &pdev->dev; player->state = UNIPERIF_STATE_STOPPED; player->dai_ops = &uni_player_dai_ops; /* Get PCM_CLK_SEL & PCMP_VALID_SEL from audio-glue-ctrl SoC reg */ ret = uni_player_parse_dt_audio_glue(pdev, player); if (ret < 0) { dev_err(player->dev, "Failed to parse DeviceTree\n"); return ret; } /* Underflow recovery is only supported on later ip revisions */ if (player->ver >= SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0) player->underflow_enabled = 1; if (UNIPERIF_TYPE_IS_TDM(player)) player->hw = &uni_tdm_hw; else player->hw = &uni_player_pcm_hw; /* Get uniperif resource */ player->clk = of_clk_get(pdev->dev.of_node, 0); if (IS_ERR(player->clk)) { dev_err(player->dev, "Failed to get clock\n"); ret = PTR_ERR(player->clk); } /* Select the frequency synthesizer clock */ if (player->clk_sel) { ret = regmap_field_write(player->clk_sel, 1); if (ret) { dev_err(player->dev, "%s: Failed to select freq synth clock\n", __func__); return ret; } } /* connect to I2S/TDM TX bus */ if (player->valid_sel && (player->id == UNIPERIF_PLAYER_I2S_OUT)) { ret = regmap_field_write(player->valid_sel, player->id); if (ret) { dev_err(player->dev, "%s: unable to connect to tdm bus\n", __func__); return ret; } } ret = devm_request_irq(&pdev->dev, player->irq, uni_player_irq_handler, IRQF_SHARED, dev_name(&pdev->dev), player); if (ret < 0) { dev_err(player->dev, "unable to request IRQ %d\n", player->irq); return ret; } mutex_init(&player->ctrl_lock); /* Ensure that disabled by default */ SET_UNIPERIF_CONFIG_BACK_STALL_REQ_DISABLE(player); SET_UNIPERIF_CTRL_ROUNDING_OFF(player); SET_UNIPERIF_CTRL_SPDIF_LAT_OFF(player); SET_UNIPERIF_CONFIG_IDLE_MOD_DISABLE(player); if (UNIPERIF_TYPE_IS_IEC958(player)) { /* Set default iec958 status bits */ /* Consumer, PCM, copyright, 2ch, mode 0 */ player->stream_settings.iec958.status[0] = 0x00; /* Broadcast reception category */ player->stream_settings.iec958.status[1] = IEC958_AES1_CON_GENERAL; /* Do not take into account source or channel number */ player->stream_settings.iec958.status[2] = IEC958_AES2_CON_SOURCE_UNSPEC; /* Sampling frequency not indicated */ player->stream_settings.iec958.status[3] = IEC958_AES3_CON_FS_NOTID; /* Max sample word 24-bit, sample word length not indicated */ player->stream_settings.iec958.status[4] = IEC958_AES4_CON_MAX_WORDLEN_24 | IEC958_AES4_CON_WORDLEN_24_20; player->num_ctrls = ARRAY_SIZE(snd_sti_iec_ctl); player->snd_ctrls = snd_sti_iec_ctl[0]; } else { player->num_ctrls = ARRAY_SIZE(snd_sti_pcm_ctl); player->snd_ctrls = snd_sti_pcm_ctl[0]; } return 0; }