struct reset_control *rstc;
struct device_link *pd_link;
+ /* Mutex for accessing port_driver of foreign clusters */
+ struct mutex port_mutex;
+
int nclusters;
struct mca_cluster clusters[];
};
struct mca_cluster *be_cl;
int stream, i;
+ mutex_lock(&mca->port_mutex);
for (i = 0; i < mca->nclusters; i++) {
be_cl = &mca->clusters[i];
if (be_cl->port_driver != cl->no)
continue;
- for_each_pcm_streams(stream)
- if (be_cl->clocks_in_use[stream])
+ for_each_pcm_streams(stream) {
+ if (be_cl->clocks_in_use[stream]) {
+ mutex_unlock(&mca->port_mutex);
return true;
+ }
+ }
}
+ mutex_unlock(&mca->port_mutex);
return false;
}
if (cl->port_driver < 0)
return -EINVAL;
+ /*
+ * We are operating on a foreign cluster here, but since we
+ * belong to the same PCM, accesses should have been
+ * synchronized at ASoC level.
+ */
fe_cl = &mca->clusters[cl->port_driver];
if (!mca_fe_clocks_in_use(fe_cl))
return 0; /* Nothing to do */
cl->base + REG_PORT_CLOCK_SEL);
writel_relaxed(PORT_DATA_SEL_TXA(fe_cl->no),
cl->base + REG_PORT_DATA_SEL);
+ mutex_lock(&mca->port_mutex);
cl->port_driver = fe_cl->no;
+ mutex_unlock(&mca->port_mutex);
cl->port_started[substream->stream] = true;
return 0;
struct snd_soc_dai *dai)
{
struct mca_cluster *cl = mca_dai_to_cluster(dai);
+ struct mca_data *mca = cl->host;
cl->port_started[substream->stream] = false;
*/
writel_relaxed(0, cl->base + REG_PORT_ENABLES);
writel_relaxed(0, cl->base + REG_PORT_DATA_SEL);
+ mutex_lock(&mca->port_mutex);
cl->port_driver = -1;
+ mutex_unlock(&mca->port_mutex);
}
}
return -ENOMEM;
mca->dev = &pdev->dev;
mca->nclusters = nclusters;
+ mutex_init(&mca->port_mutex);
platform_set_drvdata(pdev, mca);
clusters = mca->clusters;