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

Commit c988e261 authored by Mark Brown's avatar Mark Brown
Browse files

Merge remote-tracking branch 'asoc/topic/intel' into asoc-next

parents 35302156 b2047e99
Loading
Loading
Loading
Loading
+13 −0
Original line number Diff line number Diff line
@@ -14,6 +14,8 @@
 * @gtscap: gts capabilities pointer
 * @drsmcap: dma resume capabilities pointer
 * @hlink_list: link list of HDA links
 * @lock: lock for link mgmt
 * @cmd_dma_state: state of cmd DMAs: CORB and RIRB
 */
struct hdac_ext_bus {
	struct hdac_bus bus;
@@ -27,6 +29,9 @@ struct hdac_ext_bus {
	void __iomem *drsmcap;

	struct list_head hlink_list;

	struct mutex lock;
	bool cmd_dma_state;
};

int snd_hdac_ext_bus_init(struct hdac_ext_bus *sbus, struct device *dev,
@@ -142,6 +147,9 @@ struct hdac_ext_link {
	void __iomem *ml_addr; /* link output stream reg pointer */
	u32 lcaps;   /* link capablities */
	u16 lsdiid;  /* link sdi identifier */

	int ref_count;

	struct list_head list;
};

@@ -154,6 +162,11 @@ void snd_hdac_ext_link_set_stream_id(struct hdac_ext_link *link,
void snd_hdac_ext_link_clear_stream_id(struct hdac_ext_link *link,
				 int stream);

int snd_hdac_ext_bus_link_get(struct hdac_ext_bus *ebus,
				struct hdac_ext_link *link);
int snd_hdac_ext_bus_link_put(struct hdac_ext_bus *ebus,
				struct hdac_ext_link *link);

/* update register macro */
#define snd_hdac_updatel(addr, reg, mask, val)		\
	writel(((readl(addr + reg) & ~(mask)) | (val)), \
+1 −1
Original line number Diff line number Diff line
@@ -1002,7 +1002,7 @@ struct snd_soc_dai_link {
	 */
	const char *platform_name;
	struct device_node *platform_of_node;
	int be_id;	/* optional ID for machine driver BE identification */
	int id;	/* optional ID for machine driver link identification */

	const struct snd_soc_pcm_stream *params;
	unsigned int num_params;
+3 −0
Original line number Diff line number Diff line
@@ -105,6 +105,9 @@ int snd_hdac_ext_bus_init(struct hdac_ext_bus *ebus, struct device *dev,
	INIT_LIST_HEAD(&ebus->hlink_list);
	ebus->idx = idx++;

	mutex_init(&ebus->lock);
	ebus->cmd_dma_state = true;

	return 0;
}
EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_init);
+66 −0
Original line number Diff line number Diff line
@@ -186,6 +186,9 @@ int snd_hdac_ext_bus_get_ml_capabilities(struct hdac_ext_bus *ebus)
		hlink->lcaps  = readl(hlink->ml_addr + AZX_REG_ML_LCAP);
		hlink->lsdiid = readw(hlink->ml_addr + AZX_REG_ML_LSDIID);

		/* since link in On, update the ref */
		hlink->ref_count = 1;

		list_add_tail(&hlink->list, &ebus->hlink_list);
	}

@@ -327,3 +330,66 @@ int snd_hdac_ext_bus_link_power_down_all(struct hdac_ext_bus *ebus)
	return 0;
}
EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_link_power_down_all);

int snd_hdac_ext_bus_link_get(struct hdac_ext_bus *ebus,
				struct hdac_ext_link *link)
{
	int ret = 0;

	mutex_lock(&ebus->lock);

	/*
	 * if we move from 0 to 1, count will be 1 so power up this link
	 * as well, also check the dma status and trigger that
	 */
	if (++link->ref_count == 1) {
		if (!ebus->cmd_dma_state) {
			snd_hdac_bus_init_cmd_io(&ebus->bus);
			ebus->cmd_dma_state = true;
		}

		ret = snd_hdac_ext_bus_link_power_up(link);
	}

	mutex_unlock(&ebus->lock);
	return ret;
}
EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_link_get);

int snd_hdac_ext_bus_link_put(struct hdac_ext_bus *ebus,
				struct hdac_ext_link *link)
{
	int ret = 0;
	struct hdac_ext_link *hlink;
	bool link_up = false;

	mutex_lock(&ebus->lock);

	/*
	 * if we move from 1 to 0, count will be 0
	 * so power down this link as well
	 */
	if (--link->ref_count == 0) {
		ret = snd_hdac_ext_bus_link_power_down(link);

		/*
		 * now check if all links are off, if so turn off
		 * cmd dma as well
		 */
		list_for_each_entry(hlink, &ebus->hlink_list, list) {
			if (hlink->ref_count) {
				link_up = true;
				break;
			}
		}

		if (!link_up) {
			snd_hdac_bus_stop_cmd_io(&ebus->bus);
			ebus->cmd_dma_state = false;
		}
	}

	mutex_unlock(&ebus->lock);
	return ret;
}
EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_link_put);
+30 −2
Original line number Diff line number Diff line
@@ -1378,10 +1378,18 @@ static int hdmi_codec_probe(struct snd_soc_codec *codec)
	struct snd_soc_dapm_context *dapm =
		snd_soc_component_get_dapm(&codec->component);
	struct hdac_hdmi_pin *pin;
	struct hdac_ext_link *hlink = NULL;
	int ret;

	edev->scodec = codec;

	/*
	 * hold the ref while we probe, also no need to drop the ref on
	 * exit, we call pm_runtime_suspend() so that will do for us
	 */
	hlink = snd_hdac_ext_bus_get_link(edev->ebus, dev_name(&edev->hdac.dev));
	snd_hdac_ext_bus_link_get(edev->ebus, hlink);

	ret = create_fill_widget_route_map(dapm);
	if (ret < 0)
		return ret;
@@ -1480,9 +1488,14 @@ static int hdac_hdmi_dev_probe(struct hdac_ext_device *edev)
	struct hdac_device *codec = &edev->hdac;
	struct hdac_hdmi_priv *hdmi_priv;
	struct snd_soc_dai_driver *hdmi_dais = NULL;
	struct hdac_ext_link *hlink = NULL;
	int num_dais = 0;
	int ret = 0;

	/* hold the ref while we probe */
	hlink = snd_hdac_ext_bus_get_link(edev->ebus, dev_name(&edev->hdac.dev));
	snd_hdac_ext_bus_link_get(edev->ebus, hlink);

	hdmi_priv = devm_kzalloc(&codec->dev, sizeof(*hdmi_priv), GFP_KERNEL);
	if (hdmi_priv == NULL)
		return -ENOMEM;
@@ -1516,8 +1529,12 @@ static int hdac_hdmi_dev_probe(struct hdac_ext_device *edev)
	}

	/* ASoC specific initialization */
	return snd_soc_register_codec(&codec->dev, &hdmi_hda_codec,
	ret = snd_soc_register_codec(&codec->dev, &hdmi_hda_codec,
					hdmi_dais, num_dais);

	snd_hdac_ext_bus_link_put(edev->ebus, hlink);

	return ret;
}

static int hdac_hdmi_dev_remove(struct hdac_ext_device *edev)
@@ -1556,6 +1573,9 @@ static int hdac_hdmi_runtime_suspend(struct device *dev)
	struct hdac_ext_device *edev = to_hda_ext_device(dev);
	struct hdac_device *hdac = &edev->hdac;
	struct hdac_bus *bus = hdac->bus;
	unsigned long timeout;
	struct hdac_ext_bus *ebus = hbus_to_ebus(bus);
	struct hdac_ext_link *hlink = NULL;
	int err;

	dev_dbg(dev, "Enter: %s\n", __func__);
@@ -1579,6 +1599,9 @@ static int hdac_hdmi_runtime_suspend(struct device *dev)
		return err;
	}

	hlink = snd_hdac_ext_bus_get_link(ebus, dev_name(dev));
	snd_hdac_ext_bus_link_put(ebus, hlink);

	return 0;
}

@@ -1587,6 +1610,8 @@ static int hdac_hdmi_runtime_resume(struct device *dev)
	struct hdac_ext_device *edev = to_hda_ext_device(dev);
	struct hdac_device *hdac = &edev->hdac;
	struct hdac_bus *bus = hdac->bus;
	struct hdac_ext_bus *ebus = hbus_to_ebus(bus);
	struct hdac_ext_link *hlink = NULL;
	int err;

	dev_dbg(dev, "Enter: %s\n", __func__);
@@ -1595,6 +1620,9 @@ static int hdac_hdmi_runtime_resume(struct device *dev)
	if (!bus)
		return 0;

	hlink = snd_hdac_ext_bus_get_link(ebus, dev_name(dev));
	snd_hdac_ext_bus_link_get(ebus, hlink);

	err = snd_hdac_display_power(bus, true);
	if (err < 0) {
		dev_err(bus->dev, "Cannot turn on display power on i915\n");
Loading