Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: (GPL-2.0 OR MIT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3) // Copyright (c) 2018 BayLibre, SAS.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4) // Author: Jerome Brunet <jbrunet@baylibre.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6) #include <linux/clk.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8) #include <linux/of_platform.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) #include <linux/regmap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) #include <linux/reset.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) #include <sound/soc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) #include "axg-tdm-formatter.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) struct axg_tdm_formatter {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) 	struct list_head list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) 	struct axg_tdm_stream *stream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) 	const struct axg_tdm_formatter_driver *drv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) 	struct clk *pclk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) 	struct clk *sclk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) 	struct clk *lrclk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) 	struct clk *sclk_sel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) 	struct clk *lrclk_sel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) 	struct reset_control *reset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) 	bool enabled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) 	struct regmap *map;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) int axg_tdm_formatter_set_channel_masks(struct regmap *map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) 					struct axg_tdm_stream *ts,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) 					unsigned int offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) 	unsigned int val, ch = ts->channels;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 	unsigned long mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) 	int i, j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) 	 * Distribute the channels of the stream over the available slots
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 	 * of each TDM lane
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 	for (i = 0; i < AXG_TDM_NUM_LANES; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 		val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 		mask = ts->mask[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 		for (j = find_first_bit(&mask, 32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 		     (j < 32) && ch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 		     j = find_next_bit(&mask, 32, j + 1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 			val |= 1 << j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 			ch -= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 		regmap_write(map, offset, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 		offset += regmap_get_reg_stride(map);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 	 * If we still have channel left at the end of the process, it means
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 	 * the stream has more channels than we can accommodate and we should
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 	 * have caught this earlier.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 	if (WARN_ON(ch != 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 		pr_err("channel mask error\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) EXPORT_SYMBOL_GPL(axg_tdm_formatter_set_channel_masks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) static int axg_tdm_formatter_enable(struct axg_tdm_formatter *formatter)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 	struct axg_tdm_stream *ts = formatter->stream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 	bool invert;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 	/* Do nothing if the formatter is already enabled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 	if (formatter->enabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 	 * On the g12a (and possibly other SoCs), when a stream using
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 	 * multiple lanes is restarted, it will sometimes not start
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 	 * from the first lane, but randomly from another used one.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 	 * The result is an unexpected and random channel shift.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 	 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 	 * The hypothesis is that an HW counter is not properly reset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 	 * and the formatter simply starts on the lane it stopped
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 	 * before. Unfortunately, there does not seems to be a way to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 	 * reset this through the registers of the block.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 	 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 	 * However, the g12a has indenpendent reset lines for each audio
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 	 * devices. Using this reset before each start solves the issue.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 	ret = reset_control_reset(formatter->reset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 	 * If sclk is inverted, it means the bit should latched on the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 	 * rising edge which is what our HW expects. If not, we need to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 	 * invert it before the formatter.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 	invert = axg_tdm_sclk_invert(ts->iface->fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 	ret = clk_set_phase(formatter->sclk, invert ? 0 : 180);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 	/* Setup the stream parameter in the formatter */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 	ret = formatter->drv->ops->prepare(formatter->map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 					   formatter->drv->quirks,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 					   formatter->stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 	/* Enable the signal clocks feeding the formatter */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 	ret = clk_prepare_enable(formatter->sclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 	ret = clk_prepare_enable(formatter->lrclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 	if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 		clk_disable_unprepare(formatter->sclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 	/* Finally, actually enable the formatter */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 	formatter->drv->ops->enable(formatter->map);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 	formatter->enabled = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) static void axg_tdm_formatter_disable(struct axg_tdm_formatter *formatter)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 	/* Do nothing if the formatter is already disabled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 	if (!formatter->enabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 	formatter->drv->ops->disable(formatter->map);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 	clk_disable_unprepare(formatter->lrclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 	clk_disable_unprepare(formatter->sclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 	formatter->enabled = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) static int axg_tdm_formatter_attach(struct axg_tdm_formatter *formatter)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 	struct axg_tdm_stream *ts = formatter->stream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 	int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 	mutex_lock(&ts->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 	/* Catch up if the stream is already running when we attach */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 	if (ts->ready) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 		ret = axg_tdm_formatter_enable(formatter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 		if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 			pr_err("failed to enable formatter\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 			goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 	list_add_tail(&formatter->list, &ts->formatter_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 	mutex_unlock(&ts->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) static void axg_tdm_formatter_dettach(struct axg_tdm_formatter *formatter)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 	struct axg_tdm_stream *ts = formatter->stream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 	mutex_lock(&ts->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 	list_del(&formatter->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 	mutex_unlock(&ts->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 	axg_tdm_formatter_disable(formatter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) static int axg_tdm_formatter_power_up(struct axg_tdm_formatter *formatter,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 				      struct snd_soc_dapm_widget *w)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 	struct axg_tdm_stream *ts = formatter->drv->ops->get_stream(w);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 	 * If we don't get a stream at this stage, it would mean that the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 	 * widget is powering up but is not attached to any backend DAI.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 	 * It should not happen, ever !
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 	if (WARN_ON(!ts))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 		return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 	/* Clock our device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 	ret = clk_prepare_enable(formatter->pclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 	/* Reparent the bit clock to the TDM interface */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 	ret = clk_set_parent(formatter->sclk_sel, ts->iface->sclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 		goto disable_pclk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 	/* Reparent the sample clock to the TDM interface */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 	ret = clk_set_parent(formatter->lrclk_sel, ts->iface->lrclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 		goto disable_pclk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 	formatter->stream = ts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 	ret = axg_tdm_formatter_attach(formatter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 		goto disable_pclk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) disable_pclk:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 	clk_disable_unprepare(formatter->pclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) static void axg_tdm_formatter_power_down(struct axg_tdm_formatter *formatter)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 	axg_tdm_formatter_dettach(formatter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 	clk_disable_unprepare(formatter->pclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 	formatter->stream = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) int axg_tdm_formatter_event(struct snd_soc_dapm_widget *w,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 			    struct snd_kcontrol *control,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 			    int event)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 	struct snd_soc_component *c = snd_soc_dapm_to_component(w->dapm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 	struct axg_tdm_formatter *formatter = snd_soc_component_get_drvdata(c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 	int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 	switch (event) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 	case SND_SOC_DAPM_PRE_PMU:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 		ret = axg_tdm_formatter_power_up(formatter, w);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 	case SND_SOC_DAPM_PRE_PMD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 		axg_tdm_formatter_power_down(formatter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 		dev_err(c->dev, "Unexpected event %d\n", event);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) EXPORT_SYMBOL_GPL(axg_tdm_formatter_event);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) int axg_tdm_formatter_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 	struct device *dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 	const struct axg_tdm_formatter_driver *drv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 	struct axg_tdm_formatter *formatter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 	void __iomem *regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 	drv = of_device_get_match_data(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 	if (!drv) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 		dev_err(dev, "failed to match device\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 		return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 	formatter = devm_kzalloc(dev, sizeof(*formatter), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 	if (!formatter)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 	platform_set_drvdata(pdev, formatter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 	formatter->drv = drv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 	regs = devm_platform_ioremap_resource(pdev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 	if (IS_ERR(regs))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 		return PTR_ERR(regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 	formatter->map = devm_regmap_init_mmio(dev, regs, drv->regmap_cfg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 	if (IS_ERR(formatter->map)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 		dev_err(dev, "failed to init regmap: %ld\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 			PTR_ERR(formatter->map));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 		return PTR_ERR(formatter->map);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 	/* Peripharal clock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 	formatter->pclk = devm_clk_get(dev, "pclk");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 	if (IS_ERR(formatter->pclk)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 		ret = PTR_ERR(formatter->pclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 		if (ret != -EPROBE_DEFER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 			dev_err(dev, "failed to get pclk: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 	/* Formatter bit clock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 	formatter->sclk = devm_clk_get(dev, "sclk");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 	if (IS_ERR(formatter->sclk)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) 		ret = PTR_ERR(formatter->sclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 		if (ret != -EPROBE_DEFER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 			dev_err(dev, "failed to get sclk: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) 	/* Formatter sample clock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) 	formatter->lrclk = devm_clk_get(dev, "lrclk");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 	if (IS_ERR(formatter->lrclk)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 		ret = PTR_ERR(formatter->lrclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 		if (ret != -EPROBE_DEFER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 			dev_err(dev, "failed to get lrclk: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) 	/* Formatter bit clock input multiplexer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 	formatter->sclk_sel = devm_clk_get(dev, "sclk_sel");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 	if (IS_ERR(formatter->sclk_sel)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) 		ret = PTR_ERR(formatter->sclk_sel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 		if (ret != -EPROBE_DEFER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) 			dev_err(dev, "failed to get sclk_sel: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) 	/* Formatter sample clock input multiplexer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) 	formatter->lrclk_sel = devm_clk_get(dev, "lrclk_sel");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) 	if (IS_ERR(formatter->lrclk_sel)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) 		ret = PTR_ERR(formatter->lrclk_sel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) 		if (ret != -EPROBE_DEFER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) 			dev_err(dev, "failed to get lrclk_sel: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) 	/* Formatter dedicated reset line */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) 	formatter->reset = devm_reset_control_get_optional_exclusive(dev, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) 	if (IS_ERR(formatter->reset)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) 		ret = PTR_ERR(formatter->reset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) 		if (ret != -EPROBE_DEFER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) 			dev_err(dev, "failed to get reset: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) 	return devm_snd_soc_register_component(dev, drv->component_drv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) 					       NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) EXPORT_SYMBOL_GPL(axg_tdm_formatter_probe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) int axg_tdm_stream_start(struct axg_tdm_stream *ts)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) 	struct axg_tdm_formatter *formatter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) 	int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) 	mutex_lock(&ts->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) 	ts->ready = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) 	/* Start all the formatters attached to the stream */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) 	list_for_each_entry(formatter, &ts->formatter_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) 		ret = axg_tdm_formatter_enable(formatter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) 		if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) 			pr_err("failed to start tdm stream\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) 			goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) 	mutex_unlock(&ts->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) EXPORT_SYMBOL_GPL(axg_tdm_stream_start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) void axg_tdm_stream_stop(struct axg_tdm_stream *ts)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) 	struct axg_tdm_formatter *formatter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) 	mutex_lock(&ts->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) 	ts->ready = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) 	/* Stop all the formatters attached to the stream */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) 	list_for_each_entry(formatter, &ts->formatter_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) 		axg_tdm_formatter_disable(formatter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) 	mutex_unlock(&ts->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) EXPORT_SYMBOL_GPL(axg_tdm_stream_stop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) struct axg_tdm_stream *axg_tdm_stream_alloc(struct axg_tdm_iface *iface)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) 	struct axg_tdm_stream *ts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) 	ts = kzalloc(sizeof(*ts), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) 	if (ts) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) 		INIT_LIST_HEAD(&ts->formatter_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) 		mutex_init(&ts->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) 		ts->iface = iface;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) 	return ts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) EXPORT_SYMBOL_GPL(axg_tdm_stream_alloc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) void axg_tdm_stream_free(struct axg_tdm_stream *ts)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) 	 * If the list is not empty, it would mean that one of the formatter
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) 	 * widget is still powered and attached to the interface while we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) 	 * are removing the TDM DAI. It should not be possible
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) 	WARN_ON(!list_empty(&ts->formatter_list));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) 	mutex_destroy(&ts->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) 	kfree(ts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) EXPORT_SYMBOL_GPL(axg_tdm_stream_free);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) MODULE_DESCRIPTION("Amlogic AXG TDM formatter driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) MODULE_AUTHOR("Jerome Brunet <jbrunet@baylibre.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) MODULE_LICENSE("GPL v2");