ASoC: ABE HAL: Allow flexible firmware loading

In preparation for ABE firmware loading from userspace,
allow ABE HAL API to receive the memory address storing
the firmware.

Change-Id: I1d0f9d7c81090eb4a67e04bf8f7f94c467fdbe71
Signed-off-by: Misael Lopez Cruz <misael.lopez@ti.com>
diff --git a/sound/soc/omap/abe/abe_api.h b/sound/soc/omap/abe/abe_api.h
index 6c497c2..430aa5b 100644
--- a/sound/soc/omap/abe/abe_api.h
+++ b/sound/soc/omap/abe/abe_api.h
@@ -137,15 +137,6 @@
  */
 abehal_status abe_load_fw_param(u32 *FW);
 /**
- * abe_reload_fw - Reload ABE Firmware after OFF mode
- */
-abehal_status abe_reload_fw(void);
-/**
- * abe_load_fw - Load ABE Firmware and initialize memories
- *
- */
-abehal_status abe_load_fw(void);
-/**
  * abe_irq_processing - Process ABE interrupt
  *
  * This subroutine is call upon reception of "MA_IRQ_99 ABE_MPU_IRQ" Audio
diff --git a/sound/soc/omap/abe/abe_ini.c b/sound/soc/omap/abe/abe_ini.c
index 6875026..288a3d3 100644
--- a/sound/soc/omap/abe/abe_ini.c
+++ b/sound/soc/omap/abe/abe_ini.c
@@ -174,10 +174,10 @@
  * @abe: Pointer on abe handle
  *
  */
-int omap_abe_load_fw(struct omap_abe *abe)
+int omap_abe_load_fw(struct omap_abe *abe, u32 *firmware)
 {
 	_log(ABE_ID_LOAD_FW, 0, 0, 0);
-	abe_load_fw_param((u32 *) abe_firmware_array);
+	abe_load_fw_param(firmware);
 	omap_abe_reset_all_ports(abe);
 	omap_abe_build_scheduler_table(abe);
 	omap_abe_reset_all_sequence(abe);
@@ -189,10 +189,10 @@
 /**
  * abe_reload_fw - Reload ABE Firmware after OFF mode
  */
-int abe_reload_fw(void)
+int omap_abe_reload_fw(struct omap_abe *abe, u32 *firmware)
 {
 	abe->warm_boot = 0;
-	abe_load_fw_param((u32 *) abe_firmware_array);
+	abe_load_fw_param(firmware);
 	omap_abe_build_scheduler_table(abe);
 	omap_abe_dbg_reset(&abe->dbg);
 	/* IRQ circular read pointer in DMEM */
@@ -212,7 +212,17 @@
 			    RAMP_5MS, GAIN_RIGHT_OFFSET);
 	return 0;
 }
-EXPORT_SYMBOL(abe_reload_fw);
+EXPORT_SYMBOL(omap_abe_reload_fw);
+
+/**
+ * omap_abe_get_default_fw
+ *
+ * Get default ABE firmware
+ */
+u32 *omap_abe_get_default_fw(struct omap_abe *abe)
+{
+	return (u32 *)abe_firmware_array;
+}
 
 /**
  * abe_build_scheduler_table
diff --git a/sound/soc/omap/abe/abe_main.c b/sound/soc/omap/abe/abe_main.c
index 1e874e6..86e969e 100644
--- a/sound/soc/omap/abe/abe_main.c
+++ b/sound/soc/omap/abe/abe_main.c
@@ -97,7 +97,9 @@
 				 struct omap_abe_dma *dma2);
 
 int omap_abe_reset_hal(struct omap_abe *abe);
-int omap_abe_load_fw(struct omap_abe *abe);
+int omap_abe_load_fw(struct omap_abe *abe, u32 *firmware);
+int omap_abe_reload_fw(struct omap_abe *abe, u32 *firmware);
+u32* omap_abe_get_default_fw(struct omap_abe *abe);
 int omap_abe_wakeup(struct omap_abe *abe);
 int omap_abe_irq_processing(struct omap_abe *abe);
 int omap_abe_clear_irq(struct omap_abe *abe);
@@ -205,14 +207,31 @@
  * abe_load_fw - Load ABE Firmware and initialize memories
  *
  */
-u32 abe_load_fw(void)
+u32 abe_load_fw(u32 *firmware)
 {
-	omap_abe_load_fw(abe);
+	omap_abe_load_fw(abe, firmware);
 	return 0;
 }
 EXPORT_SYMBOL(abe_load_fw);
 
 /**
+ * abe_reload_fw - Reload ABE Firmware and initialize memories
+ *
+ */
+u32 abe_reload_fw(u32 *firmware)
+{
+	omap_abe_reload_fw(abe, firmware);
+	return 0;
+}
+EXPORT_SYMBOL(abe_reload_fw);
+
+u32* abe_get_default_fw(void)
+{
+	return omap_abe_get_default_fw(abe);
+}
+EXPORT_SYMBOL(abe_get_default_fw);
+
+/**
  * abe_wakeup - Wakeup ABE
  *
  * Wakeup ABE in case of retention
diff --git a/sound/soc/omap/abe/abe_main.h b/sound/soc/omap/abe/abe_main.h
index 15f23cc..cf18376 100644
--- a/sound/soc/omap/abe/abe_main.h
+++ b/sound/soc/omap/abe/abe_main.h
@@ -615,8 +615,9 @@
 
 void abe_init_mem(void __iomem **_io_base);
 u32 abe_reset_hal(void);
-u32 abe_load_fw(void);
-u32 abe_reload_fw(void);
+int abe_load_fw(u32 *firmware);
+int abe_reload_fw(u32 *firmware);
+u32 *abe_get_default_fw(void);
 u32 abe_wakeup(void);
 u32 abe_irq_processing(void);
 u32 abe_clear_irq(void);
diff --git a/sound/soc/omap/omap-abe-dsp.c b/sound/soc/omap/omap-abe-dsp.c
index b5e0d6a..9d3d93a 100644
--- a/sound/soc/omap/omap-abe-dsp.c
+++ b/sound/soc/omap/omap-abe-dsp.c
@@ -120,6 +120,7 @@
 
 	/* coefficients */
 	struct fw_header hdr;
+	u32 *firmware;
 	s32 *equ[ABE_MAX_EQU];
 	int equ_profile[ABE_MAX_EQU];
 	struct soc_enum equalizer_enum[ABE_MAX_EQU];
@@ -1848,7 +1849,7 @@
 		loss_count = pdata->get_context_loss_count(abe->dev);
 
 	if  (loss_count != the_abe->loss_count)
-	        abe_reload_fw();
+	        abe_reload_fw(abe->firmware);
 
 	/* TODO: Find a better way to save/retore gains after dor OFF mode */
 	abe_unmute_gain(MIXSDT, MIX_SDT_INPUT_UP_MIXER);
@@ -2256,7 +2257,16 @@
 		abe->equ[i] = abe->equ[i - 1] +
 			abe->equ_texts[i - 1].count * abe->equ_texts[i - 1].coeff * sizeof(s32);
 	}
+
+	/* store ABE firmware for later context restore */
+	abe->firmware = kzalloc(abe->hdr.firmware_size, GFP_KERNEL);
+	memcpy(abe->firmware,
+		fw->data + sizeof(struct fw_header) + abe->hdr.coeff_size,
+		abe->hdr.firmware_size);
+#else
+	abe->firmware = abe_get_default_fw();
 #endif
+
 	ret = request_irq(abe->irq, abe_irq_handler, 0, "ABE", (void *)abe);
 	if (ret) {
 		dev_err(platform->dev, "request for ABE IRQ %d failed %d\n",
@@ -2273,12 +2283,8 @@
 
 	abe_reset_hal();
 
-#if 0
-#warning fixup load fw args
-	//abe_load_fw(fw->data + sizeof(struct fw_header) + abe->hdr.coeff_size);
-#else
-	abe_load_fw();
-#endif
+	abe_load_fw(abe->firmware);
+
 	/* Config OPP 100 for now */
 	abe_set_opp_processing(ABE_OPP100);
 
@@ -2297,6 +2303,7 @@
 	return ret;
 
 err_texts:
+	kfree(abe->firmware);
 #if defined(CONFIG_SND_OMAP_SOC_ABE_DSP_MODULE)
 	for (i = 0; i < abe->hdr.num_equ; i++)
 		kfree(abe->equalizer_enum[i].texts);
@@ -2323,6 +2330,8 @@
 	kfree(abe->equ[0]);
 	kfree(abe->equ_texts);
 #endif
+	kfree(abe->firmware);
+
 	pm_runtime_disable(abe->dev);
 
 	return 0;