diff options
author | Takashi Iwai <tiwai@suse.de> | 2018-06-25 10:03:39 +0200 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2018-06-25 10:03:39 +0200 |
commit | ab1bcc93b73dda48a618adbf9d94bef111fd15db (patch) | |
tree | 492e09e31646c04d0eb5d63210e136baad587caf /sound | |
parent | 1bce62a6e0dd85c15cbab36a0f7b9d4766cef18e (diff) | |
parent | 2225a3e6af78e605119e0f178ae957d860882b1d (diff) |
Merge branch 'topic/ac97-bus' into for-next
Diffstat (limited to 'sound')
-rw-r--r-- | sound/ac97/bus.c | 26 |
1 files changed, 26 insertions, 0 deletions
diff --git a/sound/ac97/bus.c b/sound/ac97/bus.c index 31f858eceffc..7a0dfca03a57 100644 --- a/sound/ac97/bus.c +++ b/sound/ac97/bus.c @@ -13,6 +13,7 @@ #include <linux/idr.h> #include <linux/list.h> #include <linux/mutex.h> +#include <linux/of.h> #include <linux/pm.h> #include <linux/pm_runtime.h> #include <linux/slab.h> @@ -68,6 +69,27 @@ ac97_codec_find(struct ac97_controller *ac97_ctrl, unsigned int codec_num) return ac97_ctrl->codecs[codec_num]; } +static struct device_node * +ac97_of_get_child_device(struct ac97_controller *ac97_ctrl, int idx, + unsigned int vendor_id) +{ + struct device_node *node; + u32 reg; + char compat[] = "ac97,0000,0000"; + + snprintf(compat, sizeof(compat), "ac97,%04x,%04x", + vendor_id >> 16, vendor_id & 0xffff); + + for_each_child_of_node(ac97_ctrl->parent->of_node, node) { + if ((idx != of_property_read_u32(node, "reg", ®)) || + !of_device_is_compatible(node, compat)) + continue; + return of_node_get(node); + } + + return NULL; +} + static void ac97_codec_release(struct device *dev) { struct ac97_codec_device *adev; @@ -76,6 +98,7 @@ static void ac97_codec_release(struct device *dev) adev = to_ac97_device(dev); ac97_ctrl = adev->ac97_ctrl; ac97_ctrl->codecs[adev->num] = NULL; + of_node_put(dev->of_node); kfree(adev); } @@ -98,6 +121,8 @@ static int ac97_codec_add(struct ac97_controller *ac97_ctrl, int idx, device_initialize(&codec->dev); dev_set_name(&codec->dev, "%s:%u", dev_name(ac97_ctrl->parent), idx); + codec->dev.of_node = ac97_of_get_child_device(ac97_ctrl, idx, + vendor_id); ret = device_add(&codec->dev); if (ret) @@ -105,6 +130,7 @@ static int ac97_codec_add(struct ac97_controller *ac97_ctrl, int idx, return 0; err_free_codec: + of_node_put(codec->dev.of_node); put_device(&codec->dev); kfree(codec); ac97_ctrl->codecs[idx] = NULL; |