From patchwork Tue Dec 19 09:19:17 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Ughreja, Rakesh A" X-Patchwork-Id: 10122815 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 5467B6019C for ; Tue, 19 Dec 2017 09:19:33 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 4890929101 for ; Tue, 19 Dec 2017 09:19:33 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 3BC3A29107; Tue, 19 Dec 2017 09:19:33 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-1.9 required=2.0 tests=BAYES_00, RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.1 Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id E85F329101 for ; Tue, 19 Dec 2017 09:19:31 +0000 (UTC) Received: from alsa0.perex.cz (localhost [127.0.0.1]) by alsa0.perex.cz (Postfix) with ESMTP id 4A34E267600; Tue, 19 Dec 2017 10:19:28 +0100 (CET) X-Original-To: alsa-devel@alsa-project.org Delivered-To: alsa-devel@alsa-project.org Received: by alsa0.perex.cz (Postfix, from userid 1000) id B7FE9267612; Tue, 19 Dec 2017 10:19:27 +0100 (CET) Received: from mga09.intel.com (mga09.intel.com [134.134.136.24]) by alsa0.perex.cz (Postfix) with ESMTP id 47FC5266D71 for ; Tue, 19 Dec 2017 10:19:23 +0100 (CET) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga002.jf.intel.com ([10.7.209.21]) by orsmga102.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 19 Dec 2017 01:19:21 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.45,425,1508828400"; d="scan'208";a="19475356" Received: from fmsmsx107.amr.corp.intel.com ([10.18.124.205]) by orsmga002.jf.intel.com with ESMTP; 19 Dec 2017 01:19:21 -0800 Received: from BGSMSX107.gar.corp.intel.com (10.223.4.191) by fmsmsx107.amr.corp.intel.com (10.18.124.205) with Microsoft SMTP Server (TLS) id 14.3.319.2; Tue, 19 Dec 2017 01:19:21 -0800 Received: from bgsmsx104.gar.corp.intel.com ([169.254.5.23]) by BGSMSX107.gar.corp.intel.com ([169.254.9.78]) with mapi id 14.03.0319.002; Tue, 19 Dec 2017 14:49:18 +0530 From: "Ughreja, Rakesh A" To: Takashi Iwai Thread-Topic: [RFC v3 06/11] ASoC: hdac_hda: add ASoC based HDA codec driver Thread-Index: AQHTdZeTk2T5+d0r6kWQWPrpxXe91qND6vyAgABlZkD//+BGgIABY4ng///AugCAAypUgIAB5kaw Date: Tue, 19 Dec 2017 09:19:17 +0000 Message-ID: <85DFEED57DC57344B2483EF7BF8CB60579ADCE9A@BGSMSX104.gar.corp.intel.com> References: <1513337448-31685-1-git-send-email-rakesh.a.ughreja@intel.com> <1513337448-31685-7-git-send-email-rakesh.a.ughreja@intel.com> <85DFEED57DC57344B2483EF7BF8CB60579ADA90D@BGSMSX104.gar.corp.intel.com> <85DFEED57DC57344B2483EF7BF8CB60579ADAF8C@BGSMSX104.gar.corp.intel.com> <85DFEED57DC57344B2483EF7BF8CB60579ADB65F@BGSMSX104.gar.corp.intel.com> In-Reply-To: <85DFEED57DC57344B2483EF7BF8CB60579ADB65F@BGSMSX104.gar.corp.intel.com> Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-ctpclassification: CTP_IC x-titus-metadata-40: eyJDYXRlZ29yeUxhYmVscyI6IiIsIk1ldGFkYXRhIjp7Im5zIjoiaHR0cDpcL1wvd3d3LnRpdHVzLmNvbVwvbnNcL0ludGVsMyIsImlkIjoiZDk1NTQ4MzYtMzgwOS00YjQ2LWI4NmEtNjdlYWFkMWEzMzNkIiwicHJvcHMiOlt7Im4iOiJDVFBDbGFzc2lmaWNhdGlvbiIsInZhbHMiOlt7InZhbHVlIjoiQ1RQX0lDIn1dfV19LCJTdWJqZWN0TGFiZWxzIjpbXSwiVE1DVmVyc2lvbiI6IjE3LjIuNS4xOCIsIlRydXN0ZWRMYWJlbEhhc2giOiJTUVwvdDRJTnVNWXh5WVwvN0kwVnkwSHZBMmtNZnBaUVJKZnpFTm5LWUh6dG5cL3VWZ3lnSndPcVB5TkVJUWIwOWJjIn0= dlp-product: dlpe-windows dlp-version: 11.0.0.116 dlp-reaction: no-action x-originating-ip: [10.223.10.10] MIME-Version: 1.0 Cc: "alsa-devel@alsa-project.org" , "Koul, Vinod" , "pierre-louis.bossart@linux.intel.com" , "liam.r.girdwood@linux.intel.com" , Patches Audio , "broonie@kernel.org" Subject: Re: [alsa-devel] [RFC v3 06/11] ASoC: hdac_hda: add ASoC based HDA codec driver X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: alsa-devel-bounces@alsa-project.org Sender: alsa-devel-bounces@alsa-project.org X-Virus-Scanned: ClamAV using ClamSMTP >-----Original Message----- >From: Ughreja, Rakesh A >Sent: Monday, December 18, 2017 9:36 AM >To: Takashi Iwai >Cc: alsa-devel@alsa-project.org; broonie@kernel.org; >liam.r.girdwood@linux.intel.com; pierre-louis.bossart@linux.intel.com; Koul, >Vinod ; Patches Audio >Subject: RE: [RFC v3 06/11] ASoC: hdac_hda: add ASoC based HDA codec >driver > > > >>-----Original Message----- >>From: Takashi Iwai [mailto:tiwai@suse.de] >>Sent: Saturday, December 16, 2017 2:44 PM >>To: Ughreja, Rakesh A >>Cc: alsa-devel@alsa-project.org; broonie@kernel.org; >>liam.r.girdwood@linux.intel.com; pierre-louis.bossart@linux.intel.com; Koul, >Vinod >>; Patches Audio >>Subject: Re: [RFC v3 06/11] ASoC: hdac_hda: add ASoC based HDA codec >driver >> > >>> I am not sure if I understand you fully, so asking some follow up >>> Questions. >>> >>> I am assuming you are asking me to implement something like following. >>> Where I have to implement snd_hda_get_mode() function which would >>> return "true" if we need to register the driver as "asoc" driver. >>> >>> Is that right understanding ? >>> >>> int __hda_codec_driver_register(struct hda_codec_driver *drv, const char >>*name, >>> struct module *owner) >>> { >>> /* >>> * check if we need to register ASoC HDA driver >>> */ >>> #if IS_ENABLED(CONFIG_SND_SOC_HDAC_HDA) >>> int asoc_mode = snd_hda_get_mode(); >>> if (asoc_mode) { >>> drv->core.id_table = drv->id; >>> return __hdac_hda_codec_driver_register(&drv->core, name, >owner); >>> } >>> #endif >>> return __hda_legacy_codec_driver_register(drv, name, owner); >>> } >>> >>> If above is true then the follow up question is, what are the criteria to >determine >>> the mode. Since I cannot assume that the bus instance is already created at >the >>> time of driver registration, I am not sure how to determine what kind of >platform >>> driver would be loaded in future. >> >>My assumption is that there is only one hda_codec_driver_register(). >>The legacy code needs to be rewritten to implement the standard >>probe/remove as preliminary. Any the rest differentiation is done via >>additional callbacks at probe/remove time. >> > >Oh I see. Let me work on this and may ask you some additional clarifications. > >Regards, >Rakesh Hi Takashi, I worked on the concept that you proposed and here is the patch with main code change. Basically I wrote common driver handlers for HDA Driver snd_hdac_drv_probe, snd_hdac_drv_remove, snd_hdac_drv_shutdown, snd_hdac_drv_match, snd_hdac_drv_unsol_event etc. Once the common driver is probed it checks what kind of bus it is enumerated on by calling the bus API. If it is ASOC bus type it calls the ASOC driver registered callbacks and if it is LEGACY bus type it calls the Legacy driver registered callbacks. ASoC based platform drivers would create ASOC bus type while the legacy controller drivers would create LEGACY bus type. I added the bus_type as a part of hdac_bus, which gets set during snd_hdac_bus_init or snd_hdac_ext_bus_init. hdac_device->type and hdac_driver->type are set the HDA_DEV_CORE during registrations and enumeration. Also I have kept these routines as part of codec library, so that all the other drivers can use it without duplicating the code. Let me know if you are okay, I can include these changes as part of my next series. Regards, Rakesh --- patch-- This patch adds common enumeration functions for HDA codec drivers. Once the codec is enumerated on the hdac_bus, the bus_type is checked before the corresponding callback functions are called. Signed-off-by: Rakesh Ughreja --- sound/pci/hda/hda_bind.c | 252 ++++++++++++++++++++++++++++++++++++++++------ sound/pci/hda/hda_codec.h | 22 ++-- 2 files changed, 231 insertions(+), 43 deletions(-) diff --git a/sound/pci/hda/hda_bind.c b/sound/pci/hda/hda_bind.c index d8715a1..7d8d54c 100644 --- a/sound/pci/hda/hda_bind.c +++ b/sound/pci/hda/hda_bind.c @@ -11,6 +11,7 @@ #include #include #include +#include #include "hda_codec.h" #include "hda_local.h" @@ -74,10 +75,10 @@ int snd_hda_codec_set_name(struct hda_codec *codec, const char *name) } EXPORT_SYMBOL_GPL(snd_hda_codec_set_name); -static int hda_codec_driver_probe(struct device *dev) +static int hda_codec_driver_probe(struct hdac_device *hdev) { - struct hda_codec *codec = dev_to_hda_codec(dev); - struct module *owner = dev->driver->owner; + struct hda_codec *codec = dev_to_hda_codec(&hdev->dev); + struct module *owner = hdev->dev.driver->owner; hda_codec_patch_t patch; int err; @@ -130,48 +131,25 @@ static int hda_codec_driver_probe(struct device *dev) return err; } -static int hda_codec_driver_remove(struct device *dev) +static int hda_codec_driver_remove(struct hdac_device *hdev) { - struct hda_codec *codec = dev_to_hda_codec(dev); + struct hda_codec *codec = dev_to_hda_codec(&hdev->dev); if (codec->patch_ops.free) codec->patch_ops.free(codec); snd_hda_codec_cleanup_for_unbind(codec); - module_put(dev->driver->owner); + module_put(hdev->dev.driver->owner); return 0; } -static void hda_codec_driver_shutdown(struct device *dev) +static void hda_codec_driver_shutdown(struct hdac_device *hdev) { - struct hda_codec *codec = dev_to_hda_codec(dev); + struct hda_codec *codec = dev_to_hda_codec(&hdev->dev); - if (!pm_runtime_suspended(dev) && codec->patch_ops.reboot_notify) + if (!pm_runtime_suspended(&hdev->dev) && codec->patch_ops.reboot_notify) codec->patch_ops.reboot_notify(codec); } -int __hda_legacy_codec_driver_register(struct hda_codec_driver *drv, - const char *name, struct module *owner) -{ - drv->core.driver.name = name; - drv->core.driver.owner = owner; - drv->core.driver.bus = &snd_hda_bus_type; - drv->core.driver.probe = hda_codec_driver_probe; - drv->core.driver.remove = hda_codec_driver_remove; - drv->core.driver.shutdown = hda_codec_driver_shutdown; - drv->core.driver.pm = &hda_codec_driver_pm; - drv->core.type = HDA_DEV_LEGACY; - drv->core.match = hda_codec_match; - drv->core.unsol_event = hda_codec_unsol_event; - return driver_register(&drv->core.driver); -} -EXPORT_SYMBOL_GPL(__hda_legacy_codec_driver_register); - -void hda_legacy_codec_driver_unregister(struct hda_codec_driver *drv) -{ - driver_unregister(&drv->core.driver); -} -EXPORT_SYMBOL_GPL(hda_legacy_codec_driver_unregister); - static inline bool codec_probed(struct hda_codec *codec) { return device_attach(hda_codec_dev(codec)) > 0 && codec->preset; @@ -305,3 +283,213 @@ int snd_hda_codec_configure(struct hda_codec *codec) return err; } EXPORT_SYMBOL_GPL(snd_hda_codec_configure); + + +/* + * Newly implemented functions for common routines + */ +static struct hdac_driver *snd_hdac_drvs[2]; + +int snd_hdac_drv_probe(struct hdac_device *hdev) +{ + int bus_type; + struct hdac_driver *drv; + + bus_type = snd_hdac_get_bus_type(hdev->bus); + bus_type --; + + dev_dbg(&hdev->dev, "%s: entry ..%d\n", __func__, bus_type); + + drv = snd_hdac_drvs[bus_type]; + if (drv->probe) + return drv->probe(hdev); + return 0; +} +EXPORT_SYMBOL_GPL(snd_hdac_drv_probe); + +int snd_hdac_drv_remove(struct hdac_device *hdev) +{ + int bus_type; + struct hdac_driver *drv; + + bus_type = snd_hdac_get_bus_type(hdev->bus); + bus_type --; + + dev_dbg(&hdev->dev, "%s: entry ..%d\n", __func__, bus_type); + + drv = snd_hdac_drvs[bus_type]; + if (drv->remove) + return drv->remove(hdev); + return 0; +} +EXPORT_SYMBOL_GPL(snd_hdac_drv_remove); + +void snd_hdac_drv_shutdown(struct hdac_device *hdev) +{ + int bus_type; + struct hdac_driver *drv; + + bus_type = snd_hdac_get_bus_type(hdev->bus); + bus_type --; + + dev_dbg(&hdev->dev, "%s: entry ..%d\n", __func__, bus_type); + + drv = snd_hdac_drvs[bus_type]; + if (drv->shutdown) + return drv->shutdown(hdev); +} +EXPORT_SYMBOL_GPL(snd_hdac_drv_shutdown); + +int snd_hdac_drv_match(struct hdac_device *hdev, struct hdac_driver *drv) +{ + int bus_type; + struct hdac_driver *cdrv; + + bus_type = snd_hdac_get_bus_type(hdev->bus); + bus_type --; + + dev_dbg(&hdev->dev, "%s: entry ..%d\n", __func__, bus_type); + + cdrv = snd_hdac_drvs[bus_type]; + if (cdrv->match) + return cdrv->match(hdev, drv); + return 0; +} +EXPORT_SYMBOL_GPL(snd_hdac_drv_match); + +void snd_hdac_drv_unsol_event(struct hdac_device *hdev, unsigned int event) +{ + int bus_type; + struct hdac_driver *drv; + + bus_type = snd_hdac_get_bus_type(hdev->bus); + bus_type --; + + dev_dbg(&hdev->dev, "%s: entry ..%d\n", __func__, bus_type); + + drv = snd_hdac_drvs[bus_type]; + if (drv->unsol_event) + return drv->unsol_event(hdev, event); +} +EXPORT_SYMBOL_GPL(snd_hdac_drv_unsol_event); + +int snd_hdac_runtime_suspend(struct device *dev) +{ + + int bus_type; + struct hdac_driver *drv; + struct hdac_device *hdev = dev_to_hdac_dev(dev); + + bus_type = snd_hdac_get_bus_type(hdev->bus); + bus_type --; + + dev_dbg(&hdev->dev, "%s: entry ..%d\n", __func__, bus_type); + + drv = snd_hdac_drvs[bus_type]; + if (drv->driver.pm->runtime_suspend) + return drv->driver.pm->runtime_suspend(dev); + + return 0; +} + +int snd_hdac_runtime_resume(struct device *dev) +{ + + int bus_type; + struct hdac_driver *drv; + struct hdac_device *hdev = dev_to_hdac_dev(dev); + + bus_type = snd_hdac_get_bus_type(hdev->bus); + bus_type --; + + dev_dbg(&hdev->dev, "%s: entry ..%d\n", __func__, bus_type); + + drv = snd_hdac_drvs[bus_type]; + if (drv->driver.pm->runtime_resume) + return drv->driver.pm->runtime_resume(dev); + + return 0; +} + +const struct dev_pm_ops snd_hdac_drv_pm = { + SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, + pm_runtime_force_resume) + SET_RUNTIME_PM_OPS(snd_hdac_runtime_suspend, snd_hdac_runtime_resume, + NULL) +}; + +int snd_hdac_callback_register(struct hdac_driver *drv) +{ + int idx; + + if(drv->type != HDA_DEV_LEGACY && drv->type != HDA_DEV_ASOC) + return -EINVAL; + + printk("%s: registered callback %d\n", drv->driver.name, drv->type); + idx = drv->type - 1; + if (!snd_hdac_drvs[idx]) + snd_hdac_drvs[idx] = drv; + + return 0; +} +EXPORT_SYMBOL_GPL(snd_hdac_callback_register); + +int snd_hdac_callback_unregister(struct hdac_driver *drv) +{ + int idx; + + if(drv->type != HDA_DEV_LEGACY && drv->type != HDA_DEV_ASOC) + return -EINVAL; + + idx = drv->type - 1; + snd_hdac_drvs[idx] = NULL; + + return 0; +} +EXPORT_SYMBOL_GPL(snd_hdac_callback_unregister); + +static struct hdac_driver hdac_legacy_driver = { + .type = HDA_DEV_LEGACY, + .match = hda_codec_match, + .unsol_event = hda_codec_unsol_event, + .probe = hda_codec_driver_probe, + .remove = hda_codec_driver_remove, + .shutdown = hda_codec_driver_shutdown, + .driver.pm = &hda_codec_driver_pm, +}; + +int __snd_hdac_driver_register(struct hda_codec_driver *drv, const char *name, + struct module *owner) +{ + int ret; + struct hdac_driver *core = &drv->core; + + printk("%s: entry ..%s\n", __func__, name); + + core->id_table = drv->id; + core->driver.name = name; + core->driver.owner = owner; + core->driver.bus = &snd_hda_bus_type; + core->driver.pm = &snd_hdac_drv_pm; + core->type = HDA_DEV_CORE; + core->probe = snd_hdac_drv_probe; + core->remove = snd_hdac_drv_remove; + core->shutdown = snd_hdac_drv_shutdown; + core->match = snd_hdac_drv_match; + core->unsol_event = snd_hdac_drv_unsol_event; + + ret = snd_hdac_callback_register(&hdac_legacy_driver); + if (ret < 0) + return ret; + + return snd_hda_ext_driver_register(core); + + +} +EXPORT_SYMBOL_GPL(__snd_hdac_driver_register); + +void snd_hdac_driver_unregister(struct hda_codec_driver *drv) +{ + snd_hda_ext_driver_unregister(&drv->core); +} +EXPORT_SYMBOL_GPL(snd_hdac_driver_unregister); diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h index dda8401..0a3b56e 100644 --- a/sound/pci/hda/hda_codec.h +++ b/sound/pci/hda/hda_codec.h @@ -99,18 +99,18 @@ struct hda_codec_driver { const struct hda_device_id *id; }; -int __hda_codec_driver_register(struct hda_codec_driver *drv, const char *name, - struct module *owner); -#define hda_codec_driver_register(drv) \ - __hda_codec_driver_register(drv, KBUILD_MODNAME, THIS_MODULE) -void hda_codec_driver_unregister(struct hda_codec_driver *drv); +int __snd_hdac_driver_register(struct hda_codec_driver *drv, const char *name, + struct module *owner); +#define snd_hdac_driver_register(drv) \ + __snd_hdac_driver_register(drv, KBUILD_MODNAME, THIS_MODULE) +void snd_hdac_driver_unregister(struct hda_codec_driver *drv); + #define module_hda_codec_driver(drv) \ - module_driver(drv, hda_codec_driver_register, \ - hda_codec_driver_unregister) + module_driver(drv, snd_hdac_driver_register, \ + snd_hdac_driver_unregister) + +int snd_hdac_callback_register(struct hdac_driver *drv); +int snd_hdac_callback_unregister(struct hdac_driver *drv); /* ops set by the preset patch */ struct hda_codec_ops { -- 2.7.4