Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ab1bcc93 authored by Takashi Iwai's avatar Takashi Iwai
Browse files

Merge branch 'topic/ac97-bus' into for-next

parents 1bce62a6 2225a3e6
Loading
Loading
Loading
Loading
+32 −0
Original line number Diff line number Diff line
Generic AC97 Device Properties

This documents describes the devicetree bindings for an ac97 controller child
node describing ac97 codecs.

Required properties:
-compatible : Must be "ac97,vendor_id1,vendor_id2
	      The ids shall be the 4 characters hexadecimal encoding, such as
	      given by "%04x" formatting of printf
-reg	    : Must be the ac97 codec number, between 0 and 3

Example:
ac97: sound@40500000 {
	compatible = "marvell,pxa270-ac97";
	reg = < 0x40500000 0x1000 >;
	interrupts = <14>;
	reset-gpios = <&gpio 95 GPIO_ACTIVE_HIGH>;
	#sound-dai-cells = <1>;
	pinctrl-names = "default";
	pinctrl-0 = < &pinctrl_ac97_default >;
	clocks = <&clks CLK_AC97>, <&clks CLK_AC97CONF>;
	clock-names = "AC97CLK", "AC97CONFCLK";

	#address-cells = <1>;
	#size-cells = <0>;
	audio-codec@0 {
		reg = <0>;
		compatible = "ac97,574d,4c13";
		clocks = <&fixed_wm9713_clock>;
		clock-names = "ac97_clk";
	}
};
+26 −0
Original line number Diff line number Diff line
@@ -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", &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;