source: src/linux/universal/linux-4.9/sound/soc/intel/atom/sst/sst_acpi.c @ 31859

Last change on this file since 31859 was 31859, checked in by brainslayer, 3 months ago

kernel update

File size: 14.1 KB
Line 
1/*
2 * sst_acpi.c - SST (LPE) driver init file for ACPI enumeration.
3 *
4 * Copyright (c) 2013, Intel Corporation.
5 *
6 *  Authors:    Ramesh Babu K V <Ramesh.Babu@intel.com>
7 *  Authors:    Omair Mohammed Abdullah <omair.m.abdullah@intel.com>
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms and conditions of the GNU General Public License,
11 * version 2, as published by the Free Software Foundation.
12 *
13 * This program is distributed in the hope it will be useful, but WITHOUT
14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
16 * more details.
17 *
18 *
19 */
20
21#include <linux/module.h>
22#include <linux/fs.h>
23#include <linux/interrupt.h>
24#include <linux/slab.h>
25#include <linux/io.h>
26#include <linux/miscdevice.h>
27#include <linux/platform_device.h>
28#include <linux/firmware.h>
29#include <linux/pm_runtime.h>
30#include <linux/pm_qos.h>
31#include <linux/dmi.h>
32#include <linux/acpi.h>
33#include <asm/platform_sst_audio.h>
34#include <sound/core.h>
35#include <sound/soc.h>
36#include <sound/compress_driver.h>
37#include <acpi/acbuffer.h>
38#include <acpi/platform/acenv.h>
39#include <acpi/platform/aclinux.h>
40#include <acpi/actypes.h>
41#include <acpi/acpi_bus.h>
42#include <asm/cpu_device_id.h>
43#include <asm/iosf_mbi.h>
44#include "../sst-mfld-platform.h"
45#include "../../common/sst-dsp.h"
46#include "../../common/sst-acpi.h"
47#include "sst.h"
48
49/* LPE viewpoint addresses */
50#define SST_BYT_IRAM_PHY_START  0xff2c0000
51#define SST_BYT_IRAM_PHY_END    0xff2d4000
52#define SST_BYT_DRAM_PHY_START  0xff300000
53#define SST_BYT_DRAM_PHY_END    0xff320000
54#define SST_BYT_IMR_VIRT_START  0xc0000000 /* virtual addr in LPE */
55#define SST_BYT_IMR_VIRT_END    0xc01fffff
56#define SST_BYT_SHIM_PHY_ADDR   0xff340000
57#define SST_BYT_MBOX_PHY_ADDR   0xff344000
58#define SST_BYT_DMA0_PHY_ADDR   0xff298000
59#define SST_BYT_DMA1_PHY_ADDR   0xff29c000
60#define SST_BYT_SSP0_PHY_ADDR   0xff2a0000
61#define SST_BYT_SSP2_PHY_ADDR   0xff2a2000
62
63#define BYT_FW_MOD_TABLE_OFFSET 0x80000
64#define BYT_FW_MOD_TABLE_SIZE   0x100
65#define BYT_FW_MOD_OFFSET       (BYT_FW_MOD_TABLE_OFFSET + BYT_FW_MOD_TABLE_SIZE)
66
67static const struct sst_info byt_fwparse_info = {
68        .use_elf        = false,
69        .max_streams    = 25,
70        .iram_start     = SST_BYT_IRAM_PHY_START,
71        .iram_end       = SST_BYT_IRAM_PHY_END,
72        .iram_use       = true,
73        .dram_start     = SST_BYT_DRAM_PHY_START,
74        .dram_end       = SST_BYT_DRAM_PHY_END,
75        .dram_use       = true,
76        .imr_start      = SST_BYT_IMR_VIRT_START,
77        .imr_end        = SST_BYT_IMR_VIRT_END,
78        .imr_use        = true,
79        .mailbox_start  = SST_BYT_MBOX_PHY_ADDR,
80        .num_probes     = 0,
81        .lpe_viewpt_rqd  = true,
82};
83
84static const struct sst_ipc_info byt_ipc_info = {
85        .ipc_offset = 0,
86        .mbox_recv_off = 0x400,
87};
88
89static const struct sst_lib_dnld_info  byt_lib_dnld_info = {
90        .mod_base           = SST_BYT_IMR_VIRT_START,
91        .mod_end            = SST_BYT_IMR_VIRT_END,
92        .mod_table_offset   = BYT_FW_MOD_TABLE_OFFSET,
93        .mod_table_size     = BYT_FW_MOD_TABLE_SIZE,
94        .mod_ddr_dnld       = false,
95};
96
97static const struct sst_res_info byt_rvp_res_info = {
98        .shim_offset = 0x140000,
99        .shim_size = 0x000100,
100        .shim_phy_addr = SST_BYT_SHIM_PHY_ADDR,
101        .ssp0_offset = 0xa0000,
102        .ssp0_size = 0x1000,
103        .dma0_offset = 0x98000,
104        .dma0_size = 0x4000,
105        .dma1_offset = 0x9c000,
106        .dma1_size = 0x4000,
107        .iram_offset = 0x0c0000,
108        .iram_size = 0x14000,
109        .dram_offset = 0x100000,
110        .dram_size = 0x28000,
111        .mbox_offset = 0x144000,
112        .mbox_size = 0x1000,
113        .acpi_lpe_res_index = 0,
114        .acpi_ddr_index = 2,
115        .acpi_ipc_irq_index = 5,
116};
117
118/* BYTCR has different BIOS from BYT */
119static const struct sst_res_info bytcr_res_info = {
120        .shim_offset = 0x140000,
121        .shim_size = 0x000100,
122        .shim_phy_addr = SST_BYT_SHIM_PHY_ADDR,
123        .ssp0_offset = 0xa0000,
124        .ssp0_size = 0x1000,
125        .dma0_offset = 0x98000,
126        .dma0_size = 0x4000,
127        .dma1_offset = 0x9c000,
128        .dma1_size = 0x4000,
129        .iram_offset = 0x0c0000,
130        .iram_size = 0x14000,
131        .dram_offset = 0x100000,
132        .dram_size = 0x28000,
133        .mbox_offset = 0x144000,
134        .mbox_size = 0x1000,
135        .acpi_lpe_res_index = 0,
136        .acpi_ddr_index = 2,
137        .acpi_ipc_irq_index = 0
138};
139
140static 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};
147
148/* Cherryview (Cherrytrail and Braswell) uses same mrfld dpcm fw as Baytrail,
149 * so pdata is same as Baytrail.
150 */
151static 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
159static int sst_platform_get_resources(struct intel_sst_drv *ctx)
160{
161        struct resource *rsrc;
162        struct platform_device *pdev = to_platform_device(ctx->dev);
163
164        /* All ACPI resource request here */
165        /* Get Shim addr */
166        rsrc = platform_get_resource(pdev, IORESOURCE_MEM,
167                                        ctx->pdata->res_info->acpi_lpe_res_index);
168        if (!rsrc) {
169                dev_err(ctx->dev, "Invalid SHIM base from IFWI\n");
170                return -EIO;
171        }
172        dev_info(ctx->dev, "LPE base: %#x size:%#x", (unsigned int) rsrc->start,
173                                        (unsigned int)resource_size(rsrc));
174
175        ctx->iram_base = rsrc->start + ctx->pdata->res_info->iram_offset;
176        ctx->iram_end =  ctx->iram_base + ctx->pdata->res_info->iram_size - 1;
177        dev_info(ctx->dev, "IRAM base: %#x", ctx->iram_base);
178        ctx->iram = devm_ioremap_nocache(ctx->dev, ctx->iram_base,
179                                         ctx->pdata->res_info->iram_size);
180        if (!ctx->iram) {
181                dev_err(ctx->dev, "unable to map IRAM\n");
182                return -EIO;
183        }
184
185        ctx->dram_base = rsrc->start + ctx->pdata->res_info->dram_offset;
186        ctx->dram_end = ctx->dram_base + ctx->pdata->res_info->dram_size - 1;
187        dev_info(ctx->dev, "DRAM base: %#x", ctx->dram_base);
188        ctx->dram = devm_ioremap_nocache(ctx->dev, ctx->dram_base,
189                                         ctx->pdata->res_info->dram_size);
190        if (!ctx->dram) {
191                dev_err(ctx->dev, "unable to map DRAM\n");
192                return -EIO;
193        }
194
195        ctx->shim_phy_add = rsrc->start + ctx->pdata->res_info->shim_offset;
196        dev_info(ctx->dev, "SHIM base: %#x", ctx->shim_phy_add);
197        ctx->shim = devm_ioremap_nocache(ctx->dev, ctx->shim_phy_add,
198                                        ctx->pdata->res_info->shim_size);
199        if (!ctx->shim) {
200                dev_err(ctx->dev, "unable to map SHIM\n");
201                return -EIO;
202        }
203
204        /* reassign physical address to LPE viewpoint address */
205        ctx->shim_phy_add = ctx->pdata->res_info->shim_phy_addr;
206
207        /* Get mailbox addr */
208        ctx->mailbox_add = rsrc->start + ctx->pdata->res_info->mbox_offset;
209        dev_info(ctx->dev, "Mailbox base: %#x", ctx->mailbox_add);
210        ctx->mailbox = devm_ioremap_nocache(ctx->dev, ctx->mailbox_add,
211                                            ctx->pdata->res_info->mbox_size);
212        if (!ctx->mailbox) {
213                dev_err(ctx->dev, "unable to map mailbox\n");
214                return -EIO;
215        }
216
217        /* reassign physical address to LPE viewpoint address */
218        ctx->mailbox_add = ctx->info.mailbox_start;
219
220        rsrc = platform_get_resource(pdev, IORESOURCE_MEM,
221                                        ctx->pdata->res_info->acpi_ddr_index);
222        if (!rsrc) {
223                dev_err(ctx->dev, "Invalid DDR base from IFWI\n");
224                return -EIO;
225        }
226        ctx->ddr_base = rsrc->start;
227        ctx->ddr_end = rsrc->end;
228        dev_info(ctx->dev, "DDR base: %#x", ctx->ddr_base);
229        ctx->ddr = devm_ioremap_nocache(ctx->dev, ctx->ddr_base,
230                                        resource_size(rsrc));
231        if (!ctx->ddr) {
232                dev_err(ctx->dev, "unable to map DDR\n");
233                return -EIO;
234        }
235
236        /* Find the IRQ */
237        ctx->irq_num = platform_get_irq(pdev,
238                                ctx->pdata->res_info->acpi_ipc_irq_index);
239        return 0;
240}
241
242
243static int is_byt_cr(struct device *dev, bool *bytcr)
244{
245        int status = 0;
246
247        if (IS_ENABLED(CONFIG_IOSF_MBI)) {
248                static const struct x86_cpu_id cpu_ids[] = {
249                        { X86_VENDOR_INTEL, 6, 55 }, /* Valleyview, Bay Trail */
250                        {}
251                };
252                u32 bios_status;
253
254                if (!x86_match_cpu(cpu_ids) || !iosf_mbi_available()) {
255                        /* bail silently */
256                        return status;
257                }
258
259                status = iosf_mbi_read(BT_MBI_UNIT_PMC, /* 0x04 PUNIT */
260                                       MBI_REG_READ, /* 0x10 */
261                                       0x006, /* BIOS_CONFIG */
262                                       &bios_status);
263
264                if (status) {
265                        dev_err(dev, "could not read PUNIT BIOS_CONFIG\n");
266                } else {
267                        /* bits 26:27 mirror PMIC options */
268                        bios_status = (bios_status >> 26) & 3;
269
270                        if ((bios_status == 1) || (bios_status == 3))
271                                *bytcr = true;
272                        else
273                                dev_info(dev, "BYT-CR not detected\n");
274                }
275        } else {
276                dev_info(dev, "IOSF_MBI not enabled, no BYT-CR detection\n");
277        }
278        return status;
279}
280
281
282static int sst_acpi_probe(struct platform_device *pdev)
283{
284        struct device *dev = &pdev->dev;
285        int ret = 0;
286        struct intel_sst_drv *ctx;
287        const struct acpi_device_id *id;
288        struct sst_acpi_mach *mach;
289        struct platform_device *mdev;
290        struct platform_device *plat_dev;
291        struct sst_platform_info *pdata;
292        unsigned int dev_id;
293        bool bytcr = false;
294
295        id = acpi_match_device(dev->driver->acpi_match_table, dev);
296        if (!id)
297                return -ENODEV;
298        dev_dbg(dev, "for %s\n", id->id);
299
300        mach = (struct sst_acpi_mach *)id->driver_data;
301        mach = sst_acpi_find_machine(mach);
302        if (mach == NULL) {
303                dev_err(dev, "No matching machine driver found\n");
304                return -ENODEV;
305        }
306        if (mach->machine_quirk)
307                mach = mach->machine_quirk(mach);
308
309        pdata = mach->pdata;
310
311        ret = kstrtouint(id->id, 16, &dev_id);
312        if (ret < 0) {
313                dev_err(dev, "Unique device id conversion error: %d\n", ret);
314                return ret;
315        }
316
317        dev_dbg(dev, "ACPI device id: %x\n", dev_id);
318
319        ret = sst_alloc_drv_context(&ctx, dev, dev_id);
320        if (ret < 0)
321                return ret;
322
323        ret = is_byt_cr(dev, &bytcr);
324        if (!((ret < 0) || (bytcr == false))) {
325                dev_info(dev, "Detected Baytrail-CR platform\n");
326
327                /* override resource info */
328                byt_rvp_platform_data.res_info = &bytcr_res_info;
329        }
330
331        plat_dev = platform_device_register_data(dev, pdata->platform, -1,
332                                                NULL, 0);
333        if (IS_ERR(plat_dev)) {
334                dev_err(dev, "Failed to create machine device: %s\n",
335                        pdata->platform);
336                return PTR_ERR(plat_dev);
337        }
338
339        /*
340         * Create platform device for sst machine driver,
341         * pass machine info as pdata
342         */
343        mdev = platform_device_register_data(dev, mach->drv_name, -1,
344                                        (const void *)mach, sizeof(*mach));
345        if (IS_ERR(mdev)) {
346                dev_err(dev, "Failed to create machine device: %s\n",
347                        mach->drv_name);
348                return PTR_ERR(mdev);
349        }
350
351        /* Fill sst platform data */
352        ctx->pdata = pdata;
353        strcpy(ctx->firmware_name, mach->fw_filename);
354
355        ret = sst_platform_get_resources(ctx);
356        if (ret)
357                return ret;
358
359        ret = sst_context_init(ctx);
360        if (ret < 0)
361                return ret;
362
363        /* need to save shim registers in BYT */
364        ctx->shim_regs64 = devm_kzalloc(ctx->dev, sizeof(*ctx->shim_regs64),
365                                        GFP_KERNEL);
366        if (!ctx->shim_regs64) {
367                ret = -ENOMEM;
368                goto do_sst_cleanup;
369        }
370
371        sst_configure_runtime_pm(ctx);
372        platform_set_drvdata(pdev, ctx);
373        return ret;
374
375do_sst_cleanup:
376        sst_context_cleanup(ctx);
377        platform_set_drvdata(pdev, NULL);
378        dev_err(ctx->dev, "failed with %d\n", ret);
379        return ret;
380}
381
382/**
383* intel_sst_remove - remove function
384*
385* @pdev:        platform device structure
386*
387* This function is called by OS when a device is unloaded
388* This frees the interrupt etc
389*/
390static int sst_acpi_remove(struct platform_device *pdev)
391{
392        struct intel_sst_drv *ctx;
393
394        ctx = platform_get_drvdata(pdev);
395        sst_context_cleanup(ctx);
396        platform_set_drvdata(pdev, NULL);
397        return 0;
398}
399
400static unsigned long cht_machine_id;
401
402#define CHT_SURFACE_MACH 1
403#define BYT_THINKPAD_10  2
404
405static int cht_surface_quirk_cb(const struct dmi_system_id *id)
406{
407        cht_machine_id = CHT_SURFACE_MACH;
408        return 1;
409}
410
411static int byt_thinkpad10_quirk_cb(const struct dmi_system_id *id)
412{
413        cht_machine_id = BYT_THINKPAD_10;
414        return 1;
415}
416
417
418static const struct dmi_system_id byt_table[] = {
419        {
420                .callback = byt_thinkpad10_quirk_cb,
421                .matches = {
422                        DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
423                        DMI_MATCH(DMI_PRODUCT_NAME, "20C3001VHH"),
424                },
425        },
426        { }
427};
428
429static const struct dmi_system_id cht_table[] = {
430        {
431                .callback = cht_surface_quirk_cb,
432                .matches = {
433                        DMI_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
434                        DMI_MATCH(DMI_PRODUCT_NAME, "Surface 3"),
435                },
436        },
437        { }
438};
439
440
441static struct sst_acpi_mach cht_surface_mach = {
442        "10EC5640", "cht-bsw-rt5645", "intel/fw_sst_22a8.bin", "cht-bsw", NULL,
443                                                                &chv_platform_data };
444
445static struct sst_acpi_mach byt_thinkpad_10 = {
446        "10EC5640", "cht-bsw-rt5672", "intel/fw_sst_0f28.bin", "cht-bsw", NULL,
447                                                                &byt_rvp_platform_data };
448
449static struct sst_acpi_mach *cht_quirk(void *arg)
450{
451        struct sst_acpi_mach *mach = arg;
452
453        dmi_check_system(cht_table);
454
455        if (cht_machine_id == CHT_SURFACE_MACH)
456                return &cht_surface_mach;
457        else
458                return mach;
459}
460
461static struct sst_acpi_mach *byt_quirk(void *arg)
462{
463        struct sst_acpi_mach *mach = arg;
464
465        dmi_check_system(byt_table);
466
467        if (cht_machine_id == BYT_THINKPAD_10)
468                return &byt_thinkpad_10;
469        else
470                return mach;
471}
472
473
474static struct sst_acpi_mach sst_acpi_bytcr[] = {
475        {"10EC5640", "bytcr_rt5640", "intel/fw_sst_0f28.bin", "bytcr_rt5640", byt_quirk,
476                                                &byt_rvp_platform_data },
477        {"10EC5642", "bytcr_rt5640", "intel/fw_sst_0f28.bin", "bytcr_rt5640", NULL,
478                                                &byt_rvp_platform_data },
479        {"INTCCFFD", "bytcr_rt5640", "intel/fw_sst_0f28.bin", "bytcr_rt5640", NULL,
480                                                &byt_rvp_platform_data },
481        {"10EC5651", "bytcr_rt5651", "intel/fw_sst_0f28.bin", "bytcr_rt5651", NULL,
482                                                &byt_rvp_platform_data },
483        {},
484};
485
486/* Cherryview-based platforms: CherryTrail and Braswell */
487static struct sst_acpi_mach sst_acpi_chv[] = {
488        {"10EC5670", "cht-bsw-rt5672", "intel/fw_sst_22a8.bin", "cht-bsw", NULL,
489                                                &chv_platform_data },
490        {"10EC5645", "cht-bsw-rt5645", "intel/fw_sst_22a8.bin", "cht-bsw", NULL,
491                                                &chv_platform_data },
492        {"10EC5650", "cht-bsw-rt5645", "intel/fw_sst_22a8.bin", "cht-bsw", NULL,
493                                                &chv_platform_data },
494        {"193C9890", "cht-bsw-max98090", "intel/fw_sst_22a8.bin", "cht-bsw", NULL,
495                                                &chv_platform_data },
496        /* some CHT-T platforms rely on RT5640, use Baytrail machine driver */
497        {"10EC5640", "bytcr_rt5640", "intel/fw_sst_22a8.bin", "bytcr_rt5640", cht_quirk,
498                                                &chv_platform_data },
499
500        {},
501};
502
503static const struct acpi_device_id sst_acpi_ids[] = {
504        { "80860F28", (unsigned long)&sst_acpi_bytcr},
505        { "808622A8", (unsigned long) &sst_acpi_chv},
506        { },
507};
508
509MODULE_DEVICE_TABLE(acpi, sst_acpi_ids);
510
511static struct platform_driver sst_acpi_driver = {
512        .driver = {
513                .name                   = "intel_sst_acpi",
514                .acpi_match_table       = ACPI_PTR(sst_acpi_ids),
515                .pm                     = &intel_sst_pm,
516        },
517        .probe  = sst_acpi_probe,
518        .remove = sst_acpi_remove,
519};
520
521module_platform_driver(sst_acpi_driver);
522
523MODULE_DESCRIPTION("Intel (R) SST(R) Audio Engine ACPI Driver");
524MODULE_AUTHOR("Ramesh Babu K V");
525MODULE_AUTHOR("Omair Mohammed Abdullah");
526MODULE_LICENSE("GPL v2");
527MODULE_ALIAS("sst");
Note: See TracBrowser for help on using the repository browser.