ASoC: Blackfin: push down SPORT settings from global variables

Now that we have multi-component support, take the time to unify the
SPORT implementations a bit and make the setup dynamic.  This kills
off the global sport_handle which was shared across all the Blackfin
machine drivers.  The pin management aspect is off loaded to platform
resources, and now multiple SPORTs can be instantiated simultaneously.

Signed-off-by: Barry Song <barry.song@analog.com>
Signed-off-by: Scott Jiang <scott.jiang@analog.com>
Signed-off-by: Mike Frysinger <vapier@gentoo.org>
Acked-by: Liam Girdwood <lrg@ti.com>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
diff --git a/sound/soc/blackfin/bf5xx-ac97.c b/sound/soc/blackfin/bf5xx-ac97.c
index ffbac26..6d21625 100644
--- a/sound/soc/blackfin/bf5xx-ac97.c
+++ b/sound/soc/blackfin/bf5xx-ac97.c
@@ -41,48 +41,7 @@
  *		anomaly does not affect blackfin sound drivers.
 */
 
-static int *cmd_count;
-static int sport_num = CONFIG_SND_BF5XX_SPORT_NUM;
-
-#define SPORT_REQ(x) \
-	[x] = {P_SPORT##x##_TFS, P_SPORT##x##_DTPRI, P_SPORT##x##_TSCLK, \
-	       P_SPORT##x##_RFS, P_SPORT##x##_DRPRI, P_SPORT##x##_RSCLK, 0}
-static u16 sport_req[][7] = {
-#ifdef SPORT0_TCR1
-	SPORT_REQ(0),
-#endif
-#ifdef SPORT1_TCR1
-	SPORT_REQ(1),
-#endif
-#ifdef SPORT2_TCR1
-	SPORT_REQ(2),
-#endif
-#ifdef SPORT3_TCR1
-	SPORT_REQ(3),
-#endif
-};
-
-#define SPORT_PARAMS(x) \
-	[x] = { \
-		.dma_rx_chan = CH_SPORT##x##_RX, \
-		.dma_tx_chan = CH_SPORT##x##_TX, \
-		.err_irq     = IRQ_SPORT##x##_ERROR, \
-		.regs        = (struct sport_register *)SPORT##x##_TCR1, \
-	}
-static struct sport_param sport_params[4] = {
-#ifdef SPORT0_TCR1
-	SPORT_PARAMS(0),
-#endif
-#ifdef SPORT1_TCR1
-	SPORT_PARAMS(1),
-#endif
-#ifdef SPORT2_TCR1
-	SPORT_PARAMS(2),
-#endif
-#ifdef SPORT3_TCR1
-	SPORT_PARAMS(3),
-#endif
-};
+static struct sport_device *ac97_sport_handle;
 
 void bf5xx_pcm_to_ac97(struct ac97_frame *dst, const __u16 *src,
 		size_t count, unsigned int chan_mask)
@@ -140,7 +99,8 @@
 
 static void enqueue_cmd(struct snd_ac97 *ac97, __u16 addr, __u16 data)
 {
-	struct sport_device *sport = sport_handle;
+	struct sport_device *sport = ac97_sport_handle;
+	int *cmd_count = sport->private_data;
 	int nextfrag = sport_tx_curr_frag(sport);
 	struct ac97_frame *nextwrite;
 
@@ -161,6 +121,7 @@
 static unsigned short bf5xx_ac97_read(struct snd_ac97 *ac97,
 	unsigned short reg)
 {
+	struct sport_device *sport_handle = ac97_sport_handle;
 	struct ac97_frame out_frame[2], in_frame[2];
 
 	pr_debug("%s enter 0x%x\n", __func__, reg);
@@ -185,6 +146,8 @@
 void bf5xx_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
 	unsigned short val)
 {
+	struct sport_device *sport_handle = ac97_sport_handle;
+
 	pr_debug("%s enter 0x%x:0x%04x\n", __func__, reg, val);
 
 	if (sport_handle->tx_run) {
@@ -203,28 +166,19 @@
 
 static void bf5xx_ac97_warm_reset(struct snd_ac97 *ac97)
 {
-#if defined(CONFIG_BF54x) || defined(CONFIG_BF561) || \
- (defined(BF537_FAMILY) && (CONFIG_SND_BF5XX_SPORT_NUM == 1))
-
-#define CONCAT(a, b, c) a ## b ## c
-#define BFIN_SPORT_RFS(x) CONCAT(P_SPORT, x, _RFS)
-
-	u16 per = BFIN_SPORT_RFS(CONFIG_SND_BF5XX_SPORT_NUM);
-	u16 gpio = P_IDENT(BFIN_SPORT_RFS(CONFIG_SND_BF5XX_SPORT_NUM));
+	struct sport_device *sport_handle = ac97_sport_handle;
+	u16 gpio = P_IDENT(sport_handle->pin_req[3]);
 
 	pr_debug("%s enter\n", __func__);
 
-	peripheral_free(per);
+	peripheral_free_list(sport_handle->pin_req);
 	gpio_request(gpio, "bf5xx-ac97");
 	gpio_direction_output(gpio, 1);
 	udelay(2);
 	gpio_set_value(gpio, 0);
 	udelay(1);
 	gpio_free(gpio);
-	peripheral_request(per, "soc-audio");
-#else
-	pr_info("%s: Not implemented\n", __func__);
-#endif
+	peripheral_request_list(sport_handle->pin_req, "soc-audio");
 }
 
 static void bf5xx_ac97_cold_reset(struct snd_ac97 *ac97)
@@ -306,18 +260,32 @@
 #define bf5xx_ac97_resume	NULL
 #endif
 
-static int bf5xx_ac97_probe(struct snd_soc_dai *dai)
-{
-	int ret = 0;
-	cmd_count = (int *)get_zeroed_page(GFP_KERNEL);
-	if (cmd_count == NULL)
-		return -ENOMEM;
+static struct snd_soc_dai_driver bfin_ac97_dai = {
+	.ac97_control = 1,
+	.suspend = bf5xx_ac97_suspend,
+	.resume = bf5xx_ac97_resume,
+	.playback = {
+		.stream_name = "AC97 Playback",
+		.channels_min = 2,
+#if defined(CONFIG_SND_BF5XX_MULTICHAN_SUPPORT)
+		.channels_max = 6,
+#else
+		.channels_max = 2,
+#endif
+		.rates = SNDRV_PCM_RATE_48000,
+		.formats = SNDRV_PCM_FMTBIT_S16_LE, },
+	.capture = {
+		.stream_name = "AC97 Capture",
+		.channels_min = 2,
+		.channels_max = 2,
+		.rates = SNDRV_PCM_RATE_48000,
+		.formats = SNDRV_PCM_FMTBIT_S16_LE, },
+};
 
-	if (peripheral_request_list(sport_req[sport_num], "soc-audio")) {
-		pr_err("Requesting Peripherals failed\n");
-		ret =  -EFAULT;
-		goto peripheral_err;
-	}
+static int __devinit asoc_bfin_ac97_probe(struct platform_device *pdev)
+{
+	struct sport_device *sport_handle;
+	int ret;
 
 #ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET
 	/* Request PB3 as reset pin */
@@ -329,12 +297,14 @@
 	}
 	gpio_direction_output(CONFIG_SND_BF5XX_RESET_GPIO_NUM, 1);
 #endif
-	sport_handle = sport_init(&sport_params[sport_num], 2, \
-			sizeof(struct ac97_frame), NULL);
+
+	sport_handle = sport_init(pdev, 2, sizeof(struct ac97_frame),
+		PAGE_SIZE);
 	if (!sport_handle) {
 		ret = -ENODEV;
 		goto sport_err;
 	}
+
 	/*SPORT works in TDM mode to simulate AC97 transfers*/
 #if defined(CONFIG_SND_BF5XX_MULTICHAN_SUPPORT)
 	ret = sport_set_multichannel(sport_handle, 16, 0x3FF, 1);
@@ -361,67 +331,37 @@
 		goto sport_config_err;
 	}
 
+	ret = snd_soc_register_dai(&pdev->dev, &bfin_ac97_dai);
+	if (ret) {
+		pr_err("Failed to register DAI: %d\n", ret);
+		goto sport_config_err;
+	}
+
+	ac97_sport_handle = sport_handle;
+
 	return 0;
 
 sport_config_err:
-	kfree(sport_handle);
+	sport_done(sport_handle);
 sport_err:
 #ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET
 	gpio_free(CONFIG_SND_BF5XX_RESET_GPIO_NUM);
 gpio_err:
 #endif
-	peripheral_free_list(sport_req[sport_num]);
-peripheral_err:
-	free_page((unsigned long)cmd_count);
-	cmd_count = NULL;
 
 	return ret;
 }
 
-static int bf5xx_ac97_remove(struct snd_soc_dai *dai)
+static int __devexit asoc_bfin_ac97_remove(struct platform_device *pdev)
 {
-	free_page((unsigned long)cmd_count);
-	cmd_count = NULL;
-	peripheral_free_list(sport_req[sport_num]);
+	struct sport_device *sport_handle = platform_get_drvdata(pdev);
+
+	snd_soc_unregister_dai(&pdev->dev);
+	sport_done(sport_handle);
 #ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET
 	gpio_free(CONFIG_SND_BF5XX_RESET_GPIO_NUM);
 #endif
-	return 0;
-}
 
-struct snd_soc_dai_driver bfin_ac97_dai = {
-	.ac97_control = 1,
-	.probe = bf5xx_ac97_probe,
-	.remove = bf5xx_ac97_remove,
-	.suspend = bf5xx_ac97_suspend,
-	.resume = bf5xx_ac97_resume,
-	.playback = {
-		.stream_name = "AC97 Playback",
-		.channels_min = 2,
-#if defined(CONFIG_SND_BF5XX_MULTICHAN_SUPPORT)
-		.channels_max = 6,
-#else
-		.channels_max = 2,
-#endif
-		.rates = SNDRV_PCM_RATE_48000,
-		.formats = SNDRV_PCM_FMTBIT_S16_LE, },
-	.capture = {
-		.stream_name = "AC97 Capture",
-		.channels_min = 2,
-		.channels_max = 2,
-		.rates = SNDRV_PCM_RATE_48000,
-		.formats = SNDRV_PCM_FMTBIT_S16_LE, },
-};
-EXPORT_SYMBOL_GPL(bfin_ac97_dai);
-
-static __devinit int asoc_bfin_ac97_probe(struct platform_device *pdev)
-{
-	return snd_soc_register_dai(&pdev->dev, &bfin_ac97_dai);
-}
-
-static int __devexit asoc_bfin_ac97_remove(struct platform_device *pdev)
-{
-	snd_soc_unregister_dai(&pdev->dev);
 	return 0;
 }