^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");