sst_acpi.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * sst_acpi.c - SST (LPE) driver init file for ACPI enumeration.
  4. *
  5. * Copyright (c) 2013, Intel Corporation.
  6. *
  7. * Authors: Ramesh Babu K V <Ramesh.Babu@intel.com>
  8. * Authors: Omair Mohammed Abdullah <omair.m.abdullah@intel.com>
  9. */
  10. #include <linux/module.h>
  11. #include <linux/fs.h>
  12. #include <linux/interrupt.h>
  13. #include <linux/slab.h>
  14. #include <linux/io.h>
  15. #include <linux/platform_device.h>
  16. #include <linux/firmware.h>
  17. #include <linux/pm_qos.h>
  18. #include <linux/dmi.h>
  19. #include <linux/acpi.h>
  20. #include <asm/platform_sst_audio.h>
  21. #include <sound/core.h>
  22. #include <sound/intel-dsp-config.h>
  23. #include <sound/soc.h>
  24. #include <sound/compress_driver.h>
  25. #include <acpi/acbuffer.h>
  26. #include <acpi/platform/acenv.h>
  27. #include <acpi/platform/aclinux.h>
  28. #include <acpi/actypes.h>
  29. #include <acpi/acpi_bus.h>
  30. #include <sound/soc-acpi.h>
  31. #include <sound/soc-acpi-intel-match.h>
  32. #include "../sst-mfld-platform.h"
  33. #include "../../common/soc-intel-quirks.h"
  34. #include "sst.h"
  35. /* LPE viewpoint addresses */
  36. #define SST_BYT_IRAM_PHY_START 0xff2c0000
  37. #define SST_BYT_IRAM_PHY_END 0xff2d4000
  38. #define SST_BYT_DRAM_PHY_START 0xff300000
  39. #define SST_BYT_DRAM_PHY_END 0xff320000
  40. #define SST_BYT_IMR_VIRT_START 0xc0000000 /* virtual addr in LPE */
  41. #define SST_BYT_IMR_VIRT_END 0xc01fffff
  42. #define SST_BYT_SHIM_PHY_ADDR 0xff340000
  43. #define SST_BYT_MBOX_PHY_ADDR 0xff344000
  44. #define SST_BYT_DMA0_PHY_ADDR 0xff298000
  45. #define SST_BYT_DMA1_PHY_ADDR 0xff29c000
  46. #define SST_BYT_SSP0_PHY_ADDR 0xff2a0000
  47. #define SST_BYT_SSP2_PHY_ADDR 0xff2a2000
  48. #define BYT_FW_MOD_TABLE_OFFSET 0x80000
  49. #define BYT_FW_MOD_TABLE_SIZE 0x100
  50. #define BYT_FW_MOD_OFFSET (BYT_FW_MOD_TABLE_OFFSET + BYT_FW_MOD_TABLE_SIZE)
  51. static const struct sst_info byt_fwparse_info = {
  52. .use_elf = false,
  53. .max_streams = 25,
  54. .iram_start = SST_BYT_IRAM_PHY_START,
  55. .iram_end = SST_BYT_IRAM_PHY_END,
  56. .iram_use = true,
  57. .dram_start = SST_BYT_DRAM_PHY_START,
  58. .dram_end = SST_BYT_DRAM_PHY_END,
  59. .dram_use = true,
  60. .imr_start = SST_BYT_IMR_VIRT_START,
  61. .imr_end = SST_BYT_IMR_VIRT_END,
  62. .imr_use = true,
  63. .mailbox_start = SST_BYT_MBOX_PHY_ADDR,
  64. .num_probes = 0,
  65. .lpe_viewpt_rqd = true,
  66. };
  67. static const struct sst_ipc_info byt_ipc_info = {
  68. .ipc_offset = 0,
  69. .mbox_recv_off = 0x400,
  70. };
  71. static const struct sst_lib_dnld_info byt_lib_dnld_info = {
  72. .mod_base = SST_BYT_IMR_VIRT_START,
  73. .mod_end = SST_BYT_IMR_VIRT_END,
  74. .mod_table_offset = BYT_FW_MOD_TABLE_OFFSET,
  75. .mod_table_size = BYT_FW_MOD_TABLE_SIZE,
  76. .mod_ddr_dnld = false,
  77. };
  78. static const struct sst_res_info byt_rvp_res_info = {
  79. .shim_offset = 0x140000,
  80. .shim_size = 0x000100,
  81. .shim_phy_addr = SST_BYT_SHIM_PHY_ADDR,
  82. .ssp0_offset = 0xa0000,
  83. .ssp0_size = 0x1000,
  84. .dma0_offset = 0x98000,
  85. .dma0_size = 0x4000,
  86. .dma1_offset = 0x9c000,
  87. .dma1_size = 0x4000,
  88. .iram_offset = 0x0c0000,
  89. .iram_size = 0x14000,
  90. .dram_offset = 0x100000,
  91. .dram_size = 0x28000,
  92. .mbox_offset = 0x144000,
  93. .mbox_size = 0x1000,
  94. .acpi_lpe_res_index = 0,
  95. .acpi_ddr_index = 2,
  96. .acpi_ipc_irq_index = 5,
  97. };
  98. /* BYTCR has different BIOS from BYT */
  99. static const struct sst_res_info bytcr_res_info = {
  100. .shim_offset = 0x140000,
  101. .shim_size = 0x000100,
  102. .shim_phy_addr = SST_BYT_SHIM_PHY_ADDR,
  103. .ssp0_offset = 0xa0000,
  104. .ssp0_size = 0x1000,
  105. .dma0_offset = 0x98000,
  106. .dma0_size = 0x4000,
  107. .dma1_offset = 0x9c000,
  108. .dma1_size = 0x4000,
  109. .iram_offset = 0x0c0000,
  110. .iram_size = 0x14000,
  111. .dram_offset = 0x100000,
  112. .dram_size = 0x28000,
  113. .mbox_offset = 0x144000,
  114. .mbox_size = 0x1000,
  115. .acpi_lpe_res_index = 0,
  116. .acpi_ddr_index = 2,
  117. .acpi_ipc_irq_index = 0
  118. };
  119. /* For "LPE0F28" ACPI device found on some Android factory OS models */
  120. static const struct sst_res_info lpe8086_res_info = {
  121. .shim_offset = 0x140000,
  122. .shim_size = 0x000100,
  123. .shim_phy_addr = SST_BYT_SHIM_PHY_ADDR,
  124. .ssp0_offset = 0xa0000,
  125. .ssp0_size = 0x1000,
  126. .dma0_offset = 0x98000,
  127. .dma0_size = 0x4000,
  128. .dma1_offset = 0x9c000,
  129. .dma1_size = 0x4000,
  130. .iram_offset = 0x0c0000,
  131. .iram_size = 0x14000,
  132. .dram_offset = 0x100000,
  133. .dram_size = 0x28000,
  134. .mbox_offset = 0x144000,
  135. .mbox_size = 0x1000,
  136. .acpi_lpe_res_index = 1,
  137. .acpi_ddr_index = 0,
  138. .acpi_ipc_irq_index = 0
  139. };
  140. static struct sst_platform_info byt_rvp_platform_data = {
  141. .probe_data = &byt_fwparse_info,
  142. .ipc_info = &byt_ipc_info,
  143. .lib_info = &byt_lib_dnld_info,
  144. .res_info = &byt_rvp_res_info,
  145. .platform = "sst-mfld-platform",
  146. .streams_lost_on_suspend = true,
  147. };
  148. /* Cherryview (Cherrytrail and Braswell) uses same mrfld dpcm fw as Baytrail,
  149. * so pdata is same as Baytrail, minus the streams_lost_on_suspend quirk.
  150. */
  151. static struct sst_platform_info chv_platform_data = {
  152. .probe_data = &byt_fwparse_info,
  153. .ipc_info = &byt_ipc_info,
  154. .lib_info = &byt_lib_dnld_info,
  155. .res_info = &byt_rvp_res_info,
  156. .platform = "sst-mfld-platform",
  157. };
  158. static int sst_platform_get_resources(struct intel_sst_drv *ctx)
  159. {
  160. struct resource *rsrc;
  161. struct platform_device *pdev = to_platform_device(ctx->dev);
  162. /* All ACPI resource request here */
  163. /* Get Shim addr */
  164. rsrc = platform_get_resource(pdev, IORESOURCE_MEM,
  165. ctx->pdata->res_info->acpi_lpe_res_index);
  166. if (!rsrc) {
  167. dev_err(ctx->dev, "Invalid SHIM base from IFWI\n");
  168. return -EIO;
  169. }
  170. dev_info(ctx->dev, "LPE base: %#x size:%#x", (unsigned int) rsrc->start,
  171. (unsigned int)resource_size(rsrc));
  172. ctx->iram_base = rsrc->start + ctx->pdata->res_info->iram_offset;
  173. ctx->iram_end = ctx->iram_base + ctx->pdata->res_info->iram_size - 1;
  174. dev_info(ctx->dev, "IRAM base: %#x", ctx->iram_base);
  175. ctx->iram = devm_ioremap(ctx->dev, ctx->iram_base,
  176. ctx->pdata->res_info->iram_size);
  177. if (!ctx->iram) {
  178. dev_err(ctx->dev, "unable to map IRAM\n");
  179. return -EIO;
  180. }
  181. ctx->dram_base = rsrc->start + ctx->pdata->res_info->dram_offset;
  182. ctx->dram_end = ctx->dram_base + ctx->pdata->res_info->dram_size - 1;
  183. dev_info(ctx->dev, "DRAM base: %#x", ctx->dram_base);
  184. ctx->dram = devm_ioremap(ctx->dev, ctx->dram_base,
  185. ctx->pdata->res_info->dram_size);
  186. if (!ctx->dram) {
  187. dev_err(ctx->dev, "unable to map DRAM\n");
  188. return -EIO;
  189. }
  190. ctx->shim_phy_add = rsrc->start + ctx->pdata->res_info->shim_offset;
  191. dev_info(ctx->dev, "SHIM base: %#x", ctx->shim_phy_add);
  192. ctx->shim = devm_ioremap(ctx->dev, ctx->shim_phy_add,
  193. ctx->pdata->res_info->shim_size);
  194. if (!ctx->shim) {
  195. dev_err(ctx->dev, "unable to map SHIM\n");
  196. return -EIO;
  197. }
  198. /* reassign physical address to LPE viewpoint address */
  199. ctx->shim_phy_add = ctx->pdata->res_info->shim_phy_addr;
  200. /* Get mailbox addr */
  201. ctx->mailbox_add = rsrc->start + ctx->pdata->res_info->mbox_offset;
  202. dev_info(ctx->dev, "Mailbox base: %#x", ctx->mailbox_add);
  203. ctx->mailbox = devm_ioremap(ctx->dev, ctx->mailbox_add,
  204. ctx->pdata->res_info->mbox_size);
  205. if (!ctx->mailbox) {
  206. dev_err(ctx->dev, "unable to map mailbox\n");
  207. return -EIO;
  208. }
  209. /* reassign physical address to LPE viewpoint address */
  210. ctx->mailbox_add = ctx->info.mailbox_start;
  211. rsrc = platform_get_resource(pdev, IORESOURCE_MEM,
  212. ctx->pdata->res_info->acpi_ddr_index);
  213. if (!rsrc) {
  214. dev_err(ctx->dev, "Invalid DDR base from IFWI\n");
  215. return -EIO;
  216. }
  217. ctx->ddr_base = rsrc->start;
  218. ctx->ddr_end = rsrc->end;
  219. dev_info(ctx->dev, "DDR base: %#x", ctx->ddr_base);
  220. ctx->ddr = devm_ioremap(ctx->dev, ctx->ddr_base,
  221. resource_size(rsrc));
  222. if (!ctx->ddr) {
  223. dev_err(ctx->dev, "unable to map DDR\n");
  224. return -EIO;
  225. }
  226. /* Find the IRQ */
  227. ctx->irq_num = platform_get_irq(pdev,
  228. ctx->pdata->res_info->acpi_ipc_irq_index);
  229. if (ctx->irq_num <= 0)
  230. return ctx->irq_num < 0 ? ctx->irq_num : -EIO;
  231. return 0;
  232. }
  233. static int sst_acpi_probe(struct platform_device *pdev)
  234. {
  235. struct device *dev = &pdev->dev;
  236. int ret = 0;
  237. struct intel_sst_drv *ctx;
  238. const struct acpi_device_id *id;
  239. struct snd_soc_acpi_mach *mach;
  240. struct platform_device *mdev;
  241. struct platform_device *plat_dev;
  242. struct sst_platform_info *pdata;
  243. unsigned int dev_id;
  244. id = acpi_match_device(dev->driver->acpi_match_table, dev);
  245. if (!id)
  246. return -ENODEV;
  247. ret = snd_intel_acpi_dsp_driver_probe(dev, id->id);
  248. if (ret != SND_INTEL_DSP_DRIVER_ANY && ret != SND_INTEL_DSP_DRIVER_SST) {
  249. dev_dbg(dev, "SST ACPI driver not selected, aborting probe\n");
  250. return -ENODEV;
  251. }
  252. dev_dbg(dev, "for %s\n", id->id);
  253. mach = (struct snd_soc_acpi_mach *)id->driver_data;
  254. mach = snd_soc_acpi_find_machine(mach);
  255. if (mach == NULL) {
  256. dev_err(dev, "No matching machine driver found\n");
  257. return -ENODEV;
  258. }
  259. if (soc_intel_is_byt())
  260. mach->pdata = &byt_rvp_platform_data;
  261. else
  262. mach->pdata = &chv_platform_data;
  263. pdata = mach->pdata;
  264. if (!strcmp(id->id, "LPE0F28")) {
  265. struct resource *rsrc;
  266. /* Use regular BYT SST PCI VID:PID */
  267. dev_id = 0x80860F28;
  268. byt_rvp_platform_data.res_info = &lpe8086_res_info;
  269. /*
  270. * The "LPE0F28" ACPI device has separate IO-mem resources for:
  271. * DDR, SHIM, MBOX, IRAM, DRAM, CFG
  272. * None of which covers the entire LPE base address range.
  273. * lpe8086_res_info.acpi_lpe_res_index points to the SHIM.
  274. * Patch this to cover the entire base address range as expected
  275. * by sst_platform_get_resources().
  276. */
  277. rsrc = platform_get_resource(pdev, IORESOURCE_MEM,
  278. pdata->res_info->acpi_lpe_res_index);
  279. if (!rsrc) {
  280. dev_err(dev, "Invalid SHIM base\n");
  281. return -EIO;
  282. }
  283. rsrc->start -= pdata->res_info->shim_offset;
  284. rsrc->end = rsrc->start + 0x200000 - 1;
  285. } else {
  286. ret = kstrtouint(id->id, 16, &dev_id);
  287. if (ret < 0) {
  288. dev_err(dev, "Unique device id conversion error: %d\n", ret);
  289. return ret;
  290. }
  291. if (soc_intel_is_byt_cr(pdev))
  292. byt_rvp_platform_data.res_info = &bytcr_res_info;
  293. }
  294. dev_dbg(dev, "ACPI device id: %x\n", dev_id);
  295. ret = sst_alloc_drv_context(&ctx, dev, dev_id);
  296. if (ret < 0)
  297. return ret;
  298. /* update machine parameters */
  299. mach->mach_params.acpi_ipc_irq_index =
  300. pdata->res_info->acpi_ipc_irq_index;
  301. plat_dev = platform_device_register_data(dev, pdata->platform, -1,
  302. NULL, 0);
  303. if (IS_ERR(plat_dev)) {
  304. dev_err(dev, "Failed to create machine device: %s\n",
  305. pdata->platform);
  306. return PTR_ERR(plat_dev);
  307. }
  308. /*
  309. * Create platform device for sst machine driver,
  310. * pass machine info as pdata
  311. */
  312. mdev = platform_device_register_data(dev, mach->drv_name, -1,
  313. (const void *)mach, sizeof(*mach));
  314. if (IS_ERR(mdev)) {
  315. dev_err(dev, "Failed to create machine device: %s\n",
  316. mach->drv_name);
  317. return PTR_ERR(mdev);
  318. }
  319. /* Fill sst platform data */
  320. ctx->pdata = pdata;
  321. strcpy(ctx->firmware_name, mach->fw_filename);
  322. ret = sst_platform_get_resources(ctx);
  323. if (ret)
  324. return ret;
  325. ret = sst_context_init(ctx);
  326. if (ret < 0)
  327. return ret;
  328. sst_configure_runtime_pm(ctx);
  329. platform_set_drvdata(pdev, ctx);
  330. return ret;
  331. }
  332. /**
  333. * sst_acpi_remove - remove function
  334. *
  335. * @pdev: platform device structure
  336. *
  337. * This function is called by OS when a device is unloaded
  338. * This frees the interrupt etc
  339. */
  340. static void sst_acpi_remove(struct platform_device *pdev)
  341. {
  342. struct intel_sst_drv *ctx;
  343. ctx = platform_get_drvdata(pdev);
  344. sst_context_cleanup(ctx);
  345. platform_set_drvdata(pdev, NULL);
  346. }
  347. static const struct acpi_device_id sst_acpi_ids[] = {
  348. { "LPE0F28", (unsigned long)&snd_soc_acpi_intel_baytrail_machines},
  349. { "80860F28", (unsigned long)&snd_soc_acpi_intel_baytrail_machines},
  350. { "808622A8", (unsigned long)&snd_soc_acpi_intel_cherrytrail_machines},
  351. { },
  352. };
  353. MODULE_DEVICE_TABLE(acpi, sst_acpi_ids);
  354. static struct platform_driver sst_acpi_driver = {
  355. .driver = {
  356. .name = "intel_sst_acpi",
  357. .acpi_match_table = ACPI_PTR(sst_acpi_ids),
  358. .pm = &intel_sst_pm,
  359. },
  360. .probe = sst_acpi_probe,
  361. .remove = sst_acpi_remove,
  362. };
  363. module_platform_driver(sst_acpi_driver);
  364. MODULE_DESCRIPTION("Intel (R) SST(R) Audio Engine ACPI Driver");
  365. MODULE_AUTHOR("Ramesh Babu K V");
  366. MODULE_AUTHOR("Omair Mohammed Abdullah");
  367. MODULE_LICENSE("GPL v2");
  368. MODULE_ALIAS("sst");