-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
ALSA: hda - Move hda_i915.c from sound/pci/hda to sound/hda
The file is moved to hda core and renamed to hdac_i915.c, so can be used by both legacy HDA driver and new Skylake audio driver. - Add snd_hdac_ prefix to the public APIs. - The i915 audio component is moved to core bus and dynamically allocated. - A static pointer hdac_acomp is used to help bind/unbind callbacks to get this component, because the sound card's private_data is used by the azx chip pointer, which is a legacy structure. It could be removed if private _data changes to some core structure which can be extended to find the bus. - snd_hdac_get_display_clk() is added to get the display core clock for HSW/BDW. - haswell_set_bclk() is moved to hda_intel.c because it needs to write the controller registers EM4/EM5, and only legacy HD-A needs it for HSW/BDW. - Move definition of HSW/BDW-specific registers EM4/EM5 to hda_register.h and rename them to HSW_EM4/HSW_EM5, because other HD-A controllers have different layout for the extended mode registers. Signed-off-by: Mengdong Lin <mengdong.lin@intel.com> Signed-off-by: Takashi Iwai <tiwai@suse.de>
- Loading branch information
Mengdong Lin
authored and
Takashi Iwai
committed
May 20, 2015
1 parent
4214c53
commit 98d8fc6
Showing
11 changed files
with
313 additions
and
280 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
/* | ||
* HD-Audio helpers to sync with i915 driver | ||
*/ | ||
#ifndef __SOUND_HDA_I915_H | ||
#define __SOUND_HDA_I915_H | ||
|
||
#ifdef CONFIG_SND_HDA_I915 | ||
int snd_hdac_set_codec_wakeup(struct hdac_bus *bus, bool enable); | ||
int snd_hdac_display_power(struct hdac_bus *bus, bool enable); | ||
int snd_hdac_get_display_clk(struct hdac_bus *bus); | ||
int snd_hdac_i915_init(struct hdac_bus *bus); | ||
int snd_hdac_i915_exit(struct hdac_bus *bus); | ||
#else | ||
static int snd_hdac_set_codec_wakeup(struct hdac_bus *bus, bool enable) | ||
{ | ||
return 0; | ||
} | ||
static inline int snd_hdac_display_power(struct hdac_bus *bus, bool enable) | ||
{ | ||
return 0; | ||
} | ||
static inline int snd_hdac_get_display_clk(struct hdac_bus *bus) | ||
{ | ||
return 0; | ||
} | ||
static inline int snd_hdac_i915_init(struct hdac_bus *bus) | ||
{ | ||
return -ENODEV; | ||
} | ||
static inline int snd_hdac_i915_exit(struct hdac_bus *bus) | ||
{ | ||
return 0; | ||
} | ||
#endif | ||
|
||
#endif /* __SOUND_HDA_I915_H */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,193 @@ | ||
/* | ||
* hdac_i915.c - routines for sync between HD-A core and i915 display driver | ||
* | ||
* This program is free software; you can redistribute it and/or modify it | ||
* under the terms of the GNU General Public License as published by the Free | ||
* Software Foundation; either version 2 of the License, or (at your option) | ||
* any later version. | ||
* | ||
* This program is distributed in the hope that it will be useful, but | ||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | ||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | ||
* for more details. | ||
*/ | ||
|
||
#include <linux/init.h> | ||
#include <linux/module.h> | ||
#include <linux/pci.h> | ||
#include <linux/component.h> | ||
#include <drm/i915_component.h> | ||
#include <sound/core.h> | ||
#include <sound/hdaudio.h> | ||
#include <sound/hda_i915.h> | ||
|
||
static struct i915_audio_component *hdac_acomp; | ||
|
||
int snd_hdac_set_codec_wakeup(struct hdac_bus *bus, bool enable) | ||
{ | ||
struct i915_audio_component *acomp = bus->audio_component; | ||
|
||
if (!acomp->ops) | ||
return -ENODEV; | ||
|
||
if (!acomp->ops->codec_wake_override) { | ||
dev_warn(bus->dev, | ||
"Invalid codec wake callback\n"); | ||
return 0; | ||
} | ||
|
||
dev_dbg(bus->dev, "%s codec wakeup\n", | ||
enable ? "enable" : "disable"); | ||
|
||
acomp->ops->codec_wake_override(acomp->dev, enable); | ||
|
||
return 0; | ||
} | ||
EXPORT_SYMBOL_GPL(snd_hdac_set_codec_wakeup); | ||
|
||
int snd_hdac_display_power(struct hdac_bus *bus, bool enable) | ||
{ | ||
struct i915_audio_component *acomp = bus->audio_component; | ||
|
||
if (!acomp->ops) | ||
return -ENODEV; | ||
|
||
dev_dbg(bus->dev, "display power %s\n", | ||
enable ? "enable" : "disable"); | ||
|
||
if (enable) { | ||
if (!bus->i915_power_refcount++) | ||
acomp->ops->get_power(acomp->dev); | ||
} else { | ||
WARN_ON(!bus->i915_power_refcount); | ||
if (!--bus->i915_power_refcount) | ||
acomp->ops->put_power(acomp->dev); | ||
} | ||
|
||
return 0; | ||
} | ||
EXPORT_SYMBOL_GPL(snd_hdac_display_power); | ||
|
||
int snd_hdac_get_display_clk(struct hdac_bus *bus) | ||
{ | ||
struct i915_audio_component *acomp = bus->audio_component; | ||
|
||
if (!acomp->ops) | ||
return -ENODEV; | ||
|
||
return acomp->ops->get_cdclk_freq(acomp->dev); | ||
} | ||
EXPORT_SYMBOL_GPL(snd_hdac_get_display_clk); | ||
|
||
static int hdac_component_master_bind(struct device *dev) | ||
{ | ||
struct i915_audio_component *acomp = hdac_acomp; | ||
int ret; | ||
|
||
ret = component_bind_all(dev, acomp); | ||
if (ret < 0) | ||
return ret; | ||
|
||
if (WARN_ON(!(acomp->dev && acomp->ops && acomp->ops->get_power && | ||
acomp->ops->put_power && acomp->ops->get_cdclk_freq))) { | ||
ret = -EINVAL; | ||
goto out_unbind; | ||
} | ||
|
||
/* | ||
* Atm, we don't support dynamic unbinding initiated by the child | ||
* component, so pin its containing module until we unbind. | ||
*/ | ||
if (!try_module_get(acomp->ops->owner)) { | ||
ret = -ENODEV; | ||
goto out_unbind; | ||
} | ||
|
||
return 0; | ||
|
||
out_unbind: | ||
component_unbind_all(dev, acomp); | ||
|
||
return ret; | ||
} | ||
|
||
static void hdac_component_master_unbind(struct device *dev) | ||
{ | ||
struct i915_audio_component *acomp = hdac_acomp; | ||
|
||
module_put(acomp->ops->owner); | ||
component_unbind_all(dev, acomp); | ||
WARN_ON(acomp->ops || acomp->dev); | ||
} | ||
|
||
static const struct component_master_ops hdac_component_master_ops = { | ||
.bind = hdac_component_master_bind, | ||
.unbind = hdac_component_master_unbind, | ||
}; | ||
|
||
static int hdac_component_master_match(struct device *dev, void *data) | ||
{ | ||
/* i915 is the only supported component */ | ||
return !strcmp(dev->driver->name, "i915"); | ||
} | ||
|
||
int snd_hdac_i915_init(struct hdac_bus *bus) | ||
{ | ||
struct component_match *match = NULL; | ||
struct device *dev = bus->dev; | ||
struct i915_audio_component *acomp; | ||
int ret; | ||
|
||
acomp = kzalloc(sizeof(*acomp), GFP_KERNEL); | ||
if (!acomp) | ||
return -ENOMEM; | ||
bus->audio_component = acomp; | ||
hdac_acomp = acomp; | ||
|
||
component_match_add(dev, &match, hdac_component_master_match, bus); | ||
ret = component_master_add_with_match(dev, &hdac_component_master_ops, | ||
match); | ||
if (ret < 0) | ||
goto out_err; | ||
|
||
/* | ||
* Atm, we don't support deferring the component binding, so make sure | ||
* i915 is loaded and that the binding successfully completes. | ||
*/ | ||
request_module("i915"); | ||
|
||
if (!acomp->ops) { | ||
ret = -ENODEV; | ||
goto out_master_del; | ||
} | ||
dev_dbg(dev, "bound to i915 component master\n"); | ||
|
||
return 0; | ||
out_master_del: | ||
component_master_del(dev, &hdac_component_master_ops); | ||
out_err: | ||
kfree(acomp); | ||
bus->audio_component = NULL; | ||
dev_err(dev, "failed to add i915 component master (%d)\n", ret); | ||
|
||
return ret; | ||
} | ||
EXPORT_SYMBOL_GPL(snd_hdac_i915_init); | ||
|
||
int snd_hdac_i915_exit(struct hdac_bus *bus) | ||
{ | ||
struct device *dev = bus->dev; | ||
struct i915_audio_component *acomp = bus->audio_component; | ||
|
||
WARN_ON(bus->i915_power_refcount); | ||
if (bus->i915_power_refcount > 0 && acomp && acomp->ops) | ||
acomp->ops->put_power(acomp->dev); | ||
|
||
component_master_del(dev, &hdac_component_master_ops); | ||
|
||
kfree(acomp); | ||
bus->audio_component = NULL; | ||
|
||
return 0; | ||
} | ||
EXPORT_SYMBOL_GPL(snd_hdac_i915_exit); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.