aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sound/soc/soc-topology.c1
-rw-r--r--sound/soc/sti/uniperif.h1
-rw-r--r--sound/soc/sti/uniperif_player.c35
-rw-r--r--sound/soc/sti/uniperif_reader.c27
4 files changed, 49 insertions, 15 deletions
diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c
index 3e9b1c0bb1ce..058bc99c6c34 100644
--- a/sound/soc/soc-topology.c
+++ b/sound/soc/soc-topology.c
@@ -933,6 +933,7 @@ static int soc_tplg_denum_create_texts(struct soc_enum *se,
933 } 933 }
934 } 934 }
935 935
936 se->texts = (const char * const *)se->dobj.control.dtexts;
936 return 0; 937 return 0;
937 938
938err: 939err:
diff --git a/sound/soc/sti/uniperif.h b/sound/soc/sti/uniperif.h
index d487dd2ef016..cfcb0ea9d99d 100644
--- a/sound/soc/sti/uniperif.h
+++ b/sound/soc/sti/uniperif.h
@@ -1299,6 +1299,7 @@ struct uniperif {
1299 int ver; /* IP version, used by register access macros */ 1299 int ver; /* IP version, used by register access macros */
1300 struct regmap_field *clk_sel; 1300 struct regmap_field *clk_sel;
1301 struct regmap_field *valid_sel; 1301 struct regmap_field *valid_sel;
1302 spinlock_t irq_lock; /* use to prevent race condition with IRQ */
1302 1303
1303 /* capabilities */ 1304 /* capabilities */
1304 const struct snd_pcm_hardware *hw; 1305 const struct snd_pcm_hardware *hw;
diff --git a/sound/soc/sti/uniperif_player.c b/sound/soc/sti/uniperif_player.c
index 60ae31a303ab..d7e8dd46d2cc 100644
--- a/sound/soc/sti/uniperif_player.c
+++ b/sound/soc/sti/uniperif_player.c
@@ -65,10 +65,13 @@ static irqreturn_t uni_player_irq_handler(int irq, void *dev_id)
65 unsigned int status; 65 unsigned int status;
66 unsigned int tmp; 66 unsigned int tmp;
67 67
68 if (player->state == UNIPERIF_STATE_STOPPED) { 68 spin_lock(&player->irq_lock);
69 /* Unexpected IRQ: do nothing */ 69 if (!player->substream)
70 return IRQ_NONE; 70 goto irq_spin_unlock;
71 } 71
72 snd_pcm_stream_lock(player->substream);
73 if (player->state == UNIPERIF_STATE_STOPPED)
74 goto stream_unlock;
72 75
73 /* Get interrupt status & clear them immediately */ 76 /* Get interrupt status & clear them immediately */
74 status = GET_UNIPERIF_ITS(player); 77 status = GET_UNIPERIF_ITS(player);
@@ -88,9 +91,7 @@ static irqreturn_t uni_player_irq_handler(int irq, void *dev_id)
88 SET_UNIPERIF_ITM_BCLR_FIFO_ERROR(player); 91 SET_UNIPERIF_ITM_BCLR_FIFO_ERROR(player);
89 92
90 /* Stop the player */ 93 /* Stop the player */
91 snd_pcm_stream_lock(player->substream);
92 snd_pcm_stop(player->substream, SNDRV_PCM_STATE_XRUN); 94 snd_pcm_stop(player->substream, SNDRV_PCM_STATE_XRUN);
93 snd_pcm_stream_unlock(player->substream);
94 } 95 }
95 96
96 ret = IRQ_HANDLED; 97 ret = IRQ_HANDLED;
@@ -104,9 +105,7 @@ static irqreturn_t uni_player_irq_handler(int irq, void *dev_id)
104 SET_UNIPERIF_ITM_BCLR_DMA_ERROR(player); 105 SET_UNIPERIF_ITM_BCLR_DMA_ERROR(player);
105 106
106 /* Stop the player */ 107 /* Stop the player */
107 snd_pcm_stream_lock(player->substream);
108 snd_pcm_stop(player->substream, SNDRV_PCM_STATE_XRUN); 108 snd_pcm_stop(player->substream, SNDRV_PCM_STATE_XRUN);
109 snd_pcm_stream_unlock(player->substream);
110 109
111 ret = IRQ_HANDLED; 110 ret = IRQ_HANDLED;
112 } 111 }
@@ -116,7 +115,8 @@ static irqreturn_t uni_player_irq_handler(int irq, void *dev_id)
116 if (!player->underflow_enabled) { 115 if (!player->underflow_enabled) {
117 dev_err(player->dev, 116 dev_err(player->dev,
118 "unexpected Underflow recovering\n"); 117 "unexpected Underflow recovering\n");
119 return -EPERM; 118 ret = -EPERM;
119 goto stream_unlock;
120 } 120 }
121 /* Read the underflow recovery duration */ 121 /* Read the underflow recovery duration */
122 tmp = GET_UNIPERIF_STATUS_1_UNDERFLOW_DURATION(player); 122 tmp = GET_UNIPERIF_STATUS_1_UNDERFLOW_DURATION(player);
@@ -138,13 +138,16 @@ static irqreturn_t uni_player_irq_handler(int irq, void *dev_id)
138 dev_err(player->dev, "Underflow recovery failed\n"); 138 dev_err(player->dev, "Underflow recovery failed\n");
139 139
140 /* Stop the player */ 140 /* Stop the player */
141 snd_pcm_stream_lock(player->substream);
142 snd_pcm_stop(player->substream, SNDRV_PCM_STATE_XRUN); 141 snd_pcm_stop(player->substream, SNDRV_PCM_STATE_XRUN);
143 snd_pcm_stream_unlock(player->substream);
144 142
145 ret = IRQ_HANDLED; 143 ret = IRQ_HANDLED;
146 } 144 }
147 145
146stream_unlock:
147 snd_pcm_stream_unlock(player->substream);
148irq_spin_unlock:
149 spin_unlock(&player->irq_lock);
150
148 return ret; 151 return ret;
149} 152}
150 153
@@ -588,6 +591,7 @@ static int uni_player_ctl_iec958_put(struct snd_kcontrol *kcontrol,
588 struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai); 591 struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai);
589 struct uniperif *player = priv->dai_data.uni; 592 struct uniperif *player = priv->dai_data.uni;
590 struct snd_aes_iec958 *iec958 = &player->stream_settings.iec958; 593 struct snd_aes_iec958 *iec958 = &player->stream_settings.iec958;
594 unsigned long flags;
591 595
592 mutex_lock(&player->ctrl_lock); 596 mutex_lock(&player->ctrl_lock);
593 iec958->status[0] = ucontrol->value.iec958.status[0]; 597 iec958->status[0] = ucontrol->value.iec958.status[0];
@@ -596,12 +600,14 @@ static int uni_player_ctl_iec958_put(struct snd_kcontrol *kcontrol,
596 iec958->status[3] = ucontrol->value.iec958.status[3]; 600 iec958->status[3] = ucontrol->value.iec958.status[3];
597 mutex_unlock(&player->ctrl_lock); 601 mutex_unlock(&player->ctrl_lock);
598 602
603 spin_lock_irqsave(&player->irq_lock, flags);
599 if (player->substream && player->substream->runtime) 604 if (player->substream && player->substream->runtime)
600 uni_player_set_channel_status(player, 605 uni_player_set_channel_status(player,
601 player->substream->runtime); 606 player->substream->runtime);
602 else 607 else
603 uni_player_set_channel_status(player, NULL); 608 uni_player_set_channel_status(player, NULL);
604 609
610 spin_unlock_irqrestore(&player->irq_lock, flags);
605 return 0; 611 return 0;
606} 612}
607 613
@@ -686,9 +692,12 @@ static int uni_player_startup(struct snd_pcm_substream *substream,
686{ 692{
687 struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai); 693 struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai);
688 struct uniperif *player = priv->dai_data.uni; 694 struct uniperif *player = priv->dai_data.uni;
695 unsigned long flags;
689 int ret; 696 int ret;
690 697
698 spin_lock_irqsave(&player->irq_lock, flags);
691 player->substream = substream; 699 player->substream = substream;
700 spin_unlock_irqrestore(&player->irq_lock, flags);
692 701
693 player->clk_adj = 0; 702 player->clk_adj = 0;
694 703
@@ -986,12 +995,15 @@ static void uni_player_shutdown(struct snd_pcm_substream *substream,
986{ 995{
987 struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai); 996 struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai);
988 struct uniperif *player = priv->dai_data.uni; 997 struct uniperif *player = priv->dai_data.uni;
998 unsigned long flags;
989 999
1000 spin_lock_irqsave(&player->irq_lock, flags);
990 if (player->state != UNIPERIF_STATE_STOPPED) 1001 if (player->state != UNIPERIF_STATE_STOPPED)
991 /* Stop the player */ 1002 /* Stop the player */
992 uni_player_stop(player); 1003 uni_player_stop(player);
993 1004
994 player->substream = NULL; 1005 player->substream = NULL;
1006 spin_unlock_irqrestore(&player->irq_lock, flags);
995} 1007}
996 1008
997static int uni_player_parse_dt_audio_glue(struct platform_device *pdev, 1009static int uni_player_parse_dt_audio_glue(struct platform_device *pdev,
@@ -1096,6 +1108,7 @@ int uni_player_init(struct platform_device *pdev,
1096 } 1108 }
1097 1109
1098 mutex_init(&player->ctrl_lock); 1110 mutex_init(&player->ctrl_lock);
1111 spin_lock_init(&player->irq_lock);
1099 1112
1100 /* Ensure that disabled by default */ 1113 /* Ensure that disabled by default */
1101 SET_UNIPERIF_CONFIG_BACK_STALL_REQ_DISABLE(player); 1114 SET_UNIPERIF_CONFIG_BACK_STALL_REQ_DISABLE(player);
diff --git a/sound/soc/sti/uniperif_reader.c b/sound/soc/sti/uniperif_reader.c
index 5992c6ab3833..ee0055e60852 100644
--- a/sound/soc/sti/uniperif_reader.c
+++ b/sound/soc/sti/uniperif_reader.c
@@ -46,10 +46,15 @@ static irqreturn_t uni_reader_irq_handler(int irq, void *dev_id)
46 struct uniperif *reader = dev_id; 46 struct uniperif *reader = dev_id;
47 unsigned int status; 47 unsigned int status;
48 48
49 spin_lock(&reader->irq_lock);
50 if (!reader->substream)
51 goto irq_spin_unlock;
52
53 snd_pcm_stream_lock(reader->substream);
49 if (reader->state == UNIPERIF_STATE_STOPPED) { 54 if (reader->state == UNIPERIF_STATE_STOPPED) {
50 /* Unexpected IRQ: do nothing */ 55 /* Unexpected IRQ: do nothing */
51 dev_warn(reader->dev, "unexpected IRQ\n"); 56 dev_warn(reader->dev, "unexpected IRQ\n");
52 return IRQ_HANDLED; 57 goto stream_unlock;
53 } 58 }
54 59
55 /* Get interrupt status & clear them immediately */ 60 /* Get interrupt status & clear them immediately */
@@ -60,13 +65,16 @@ static irqreturn_t uni_reader_irq_handler(int irq, void *dev_id)
60 if (unlikely(status & UNIPERIF_ITS_FIFO_ERROR_MASK(reader))) { 65 if (unlikely(status & UNIPERIF_ITS_FIFO_ERROR_MASK(reader))) {
61 dev_err(reader->dev, "FIFO error detected\n"); 66 dev_err(reader->dev, "FIFO error detected\n");
62 67
63 snd_pcm_stream_lock(reader->substream);
64 snd_pcm_stop(reader->substream, SNDRV_PCM_STATE_XRUN); 68 snd_pcm_stop(reader->substream, SNDRV_PCM_STATE_XRUN);
65 snd_pcm_stream_unlock(reader->substream);
66 69
67 return IRQ_HANDLED; 70 ret = IRQ_HANDLED;
68 } 71 }
69 72
73stream_unlock:
74 snd_pcm_stream_unlock(reader->substream);
75irq_spin_unlock:
76 spin_unlock(&reader->irq_lock);
77
70 return ret; 78 return ret;
71} 79}
72 80
@@ -347,8 +355,13 @@ static int uni_reader_startup(struct snd_pcm_substream *substream,
347{ 355{
348 struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai); 356 struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai);
349 struct uniperif *reader = priv->dai_data.uni; 357 struct uniperif *reader = priv->dai_data.uni;
358 unsigned long flags;
350 int ret; 359 int ret;
351 360
361 spin_lock_irqsave(&reader->irq_lock, flags);
362 reader->substream = substream;
363 spin_unlock_irqrestore(&reader->irq_lock, flags);
364
352 if (!UNIPERIF_TYPE_IS_TDM(reader)) 365 if (!UNIPERIF_TYPE_IS_TDM(reader))
353 return 0; 366 return 0;
354 367
@@ -373,11 +386,15 @@ static void uni_reader_shutdown(struct snd_pcm_substream *substream,
373{ 386{
374 struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai); 387 struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai);
375 struct uniperif *reader = priv->dai_data.uni; 388 struct uniperif *reader = priv->dai_data.uni;
389 unsigned long flags;
376 390
391 spin_lock_irqsave(&reader->irq_lock, flags);
377 if (reader->state != UNIPERIF_STATE_STOPPED) { 392 if (reader->state != UNIPERIF_STATE_STOPPED) {
378 /* Stop the reader */ 393 /* Stop the reader */
379 uni_reader_stop(reader); 394 uni_reader_stop(reader);
380 } 395 }
396 reader->substream = NULL;
397 spin_unlock_irqrestore(&reader->irq_lock, flags);
381} 398}
382 399
383static const struct snd_soc_dai_ops uni_reader_dai_ops = { 400static const struct snd_soc_dai_ops uni_reader_dai_ops = {
@@ -412,6 +429,8 @@ int uni_reader_init(struct platform_device *pdev,
412 return -EBUSY; 429 return -EBUSY;
413 } 430 }
414 431
432 spin_lock_init(&reader->irq_lock);
433
415 return 0; 434 return 0;
416} 435}
417EXPORT_SYMBOL_GPL(uni_reader_init); 436EXPORT_SYMBOL_GPL(uni_reader_init);