14ff1fef1SKuninori Morimoto // SPDX-License-Identifier: GPL-2.0 24ff1fef1SKuninori Morimoto // 34ff1fef1SKuninori Morimoto // soc-component.c 44ff1fef1SKuninori Morimoto // 5460b42d1SKuninori Morimoto // Copyright 2009-2011 Wolfson Microelectronics PLC. 64ff1fef1SKuninori Morimoto // Copyright (C) 2019 Renesas Electronics Corp. 7460b42d1SKuninori Morimoto // 8460b42d1SKuninori Morimoto // Mark Brown <broonie@opensource.wolfsonmicro.com> 94ff1fef1SKuninori Morimoto // Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> 104ff1fef1SKuninori Morimoto // 114a81e8f3SKuninori Morimoto #include <linux/module.h> 12939a5cfbSKuninori Morimoto #include <linux/pm_runtime.h> 134ff1fef1SKuninori Morimoto #include <sound/soc.h> 148ac9e476SSrinivas Kandagatla #include <linux/bitops.h> 154ff1fef1SKuninori Morimoto 16b296997cSSrinivas Kandagatla #define soc_component_ret(dai, ret) _soc_component_ret(dai, __func__, ret, -1) 17b296997cSSrinivas Kandagatla #define soc_component_ret_reg_rw(dai, ret, reg) _soc_component_ret(dai, __func__, ret, reg) 18e2329eebSKuninori Morimoto static inline int _soc_component_ret(struct snd_soc_component *component, 19b296997cSSrinivas Kandagatla const char *func, int ret, int reg) 20e2329eebSKuninori Morimoto { 21e2329eebSKuninori Morimoto /* Positive/Zero values are not errors */ 22e2329eebSKuninori Morimoto if (ret >= 0) 23e2329eebSKuninori Morimoto return ret; 24e2329eebSKuninori Morimoto 25e2329eebSKuninori Morimoto /* Negative values might be errors */ 26e2329eebSKuninori Morimoto switch (ret) { 27e2329eebSKuninori Morimoto case -EPROBE_DEFER: 28e2329eebSKuninori Morimoto case -ENOTSUPP: 29e2329eebSKuninori Morimoto break; 30e2329eebSKuninori Morimoto default: 31b296997cSSrinivas Kandagatla if (reg == -1) 32e2329eebSKuninori Morimoto dev_err(component->dev, 33e2329eebSKuninori Morimoto "ASoC: error at %s on %s: %d\n", 34e2329eebSKuninori Morimoto func, component->name, ret); 35b296997cSSrinivas Kandagatla else 36b296997cSSrinivas Kandagatla dev_err(component->dev, 37b296997cSSrinivas Kandagatla "ASoC: error at %s on %s for register: [0x%08x] %d\n", 38b296997cSSrinivas Kandagatla func, component->name, reg, ret); 39e2329eebSKuninori Morimoto } 40e2329eebSKuninori Morimoto 41e2329eebSKuninori Morimoto return ret; 42e2329eebSKuninori Morimoto } 43e2329eebSKuninori Morimoto 441da0b989SSrinivas Kandagatla static inline int soc_component_field_shift(struct snd_soc_component *component, 451da0b989SSrinivas Kandagatla unsigned int mask) 461da0b989SSrinivas Kandagatla { 471da0b989SSrinivas Kandagatla if (!mask) { 481da0b989SSrinivas Kandagatla dev_err(component->dev, "ASoC: error field mask is zero for %s\n", 491da0b989SSrinivas Kandagatla component->name); 501da0b989SSrinivas Kandagatla return 0; 511da0b989SSrinivas Kandagatla } 521da0b989SSrinivas Kandagatla 538ac9e476SSrinivas Kandagatla return (ffs(mask) - 1); 541da0b989SSrinivas Kandagatla } 551da0b989SSrinivas Kandagatla 5651aff91aSKuninori Morimoto /* 5751aff91aSKuninori Morimoto * We might want to check substream by using list. 5851aff91aSKuninori Morimoto * In such case, we can update these macros. 5951aff91aSKuninori Morimoto */ 6051aff91aSKuninori Morimoto #define soc_component_mark_push(component, substream, tgt) ((component)->mark_##tgt = substream) 6151aff91aSKuninori Morimoto #define soc_component_mark_pop(component, substream, tgt) ((component)->mark_##tgt = NULL) 6251aff91aSKuninori Morimoto #define soc_component_mark_match(component, substream, tgt) ((component)->mark_##tgt == substream) 6351aff91aSKuninori Morimoto 64257c4dacSKuninori Morimoto void snd_soc_component_set_aux(struct snd_soc_component *component, 65257c4dacSKuninori Morimoto struct snd_soc_aux_dev *aux) 66257c4dacSKuninori Morimoto { 67257c4dacSKuninori Morimoto component->init = (aux) ? aux->init : NULL; 68257c4dacSKuninori Morimoto } 69257c4dacSKuninori Morimoto 70257c4dacSKuninori Morimoto int snd_soc_component_init(struct snd_soc_component *component) 71257c4dacSKuninori Morimoto { 72257c4dacSKuninori Morimoto int ret = 0; 73257c4dacSKuninori Morimoto 74257c4dacSKuninori Morimoto if (component->init) 75257c4dacSKuninori Morimoto ret = component->init(component); 76257c4dacSKuninori Morimoto 77257c4dacSKuninori Morimoto return soc_component_ret(component, ret); 78257c4dacSKuninori Morimoto } 79257c4dacSKuninori Morimoto 804ff1fef1SKuninori Morimoto /** 814ff1fef1SKuninori Morimoto * snd_soc_component_set_sysclk - configure COMPONENT system or master clock. 824ff1fef1SKuninori Morimoto * @component: COMPONENT 834ff1fef1SKuninori Morimoto * @clk_id: DAI specific clock ID 844ff1fef1SKuninori Morimoto * @source: Source for the clock 854ff1fef1SKuninori Morimoto * @freq: new clock frequency in Hz 864ff1fef1SKuninori Morimoto * @dir: new clock direction - input/output. 874ff1fef1SKuninori Morimoto * 884ff1fef1SKuninori Morimoto * Configures the CODEC master (MCLK) or system (SYSCLK) clocking. 894ff1fef1SKuninori Morimoto */ 904ff1fef1SKuninori Morimoto int snd_soc_component_set_sysclk(struct snd_soc_component *component, 914ff1fef1SKuninori Morimoto int clk_id, int source, unsigned int freq, 924ff1fef1SKuninori Morimoto int dir) 934ff1fef1SKuninori Morimoto { 94e2329eebSKuninori Morimoto int ret = -ENOTSUPP; 95e2329eebSKuninori Morimoto 964ff1fef1SKuninori Morimoto if (component->driver->set_sysclk) 97e2329eebSKuninori Morimoto ret = component->driver->set_sysclk(component, clk_id, source, 984ff1fef1SKuninori Morimoto freq, dir); 994ff1fef1SKuninori Morimoto 100e2329eebSKuninori Morimoto return soc_component_ret(component, ret); 1014ff1fef1SKuninori Morimoto } 1024ff1fef1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_set_sysclk); 1034ff1fef1SKuninori Morimoto 1044ff1fef1SKuninori Morimoto /* 1054ff1fef1SKuninori Morimoto * snd_soc_component_set_pll - configure component PLL. 1064ff1fef1SKuninori Morimoto * @component: COMPONENT 1074ff1fef1SKuninori Morimoto * @pll_id: DAI specific PLL ID 1084ff1fef1SKuninori Morimoto * @source: DAI specific source for the PLL 1094ff1fef1SKuninori Morimoto * @freq_in: PLL input clock frequency in Hz 1104ff1fef1SKuninori Morimoto * @freq_out: requested PLL output clock frequency in Hz 1114ff1fef1SKuninori Morimoto * 1124ff1fef1SKuninori Morimoto * Configures and enables PLL to generate output clock based on input clock. 1134ff1fef1SKuninori Morimoto */ 1144ff1fef1SKuninori Morimoto int snd_soc_component_set_pll(struct snd_soc_component *component, int pll_id, 1154ff1fef1SKuninori Morimoto int source, unsigned int freq_in, 1164ff1fef1SKuninori Morimoto unsigned int freq_out) 1174ff1fef1SKuninori Morimoto { 118e2329eebSKuninori Morimoto int ret = -EINVAL; 119e2329eebSKuninori Morimoto 1204ff1fef1SKuninori Morimoto if (component->driver->set_pll) 121e2329eebSKuninori Morimoto ret = component->driver->set_pll(component, pll_id, source, 1224ff1fef1SKuninori Morimoto freq_in, freq_out); 1234ff1fef1SKuninori Morimoto 124e2329eebSKuninori Morimoto return soc_component_ret(component, ret); 1254ff1fef1SKuninori Morimoto } 1264ff1fef1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_set_pll); 1274ff1fef1SKuninori Morimoto 1289d415fbfSKuninori Morimoto void snd_soc_component_seq_notifier(struct snd_soc_component *component, 1299d415fbfSKuninori Morimoto enum snd_soc_dapm_type type, int subseq) 1309d415fbfSKuninori Morimoto { 1319d415fbfSKuninori Morimoto if (component->driver->seq_notifier) 1329d415fbfSKuninori Morimoto component->driver->seq_notifier(component, type, subseq); 1339d415fbfSKuninori Morimoto } 1349d415fbfSKuninori Morimoto 1358e2a990dSKuninori Morimoto int snd_soc_component_stream_event(struct snd_soc_component *component, 1368e2a990dSKuninori Morimoto int event) 1378e2a990dSKuninori Morimoto { 138e2329eebSKuninori Morimoto int ret = 0; 1398e2a990dSKuninori Morimoto 140e2329eebSKuninori Morimoto if (component->driver->stream_event) 141e2329eebSKuninori Morimoto ret = component->driver->stream_event(component, event); 142e2329eebSKuninori Morimoto 143e2329eebSKuninori Morimoto return soc_component_ret(component, ret); 1448e2a990dSKuninori Morimoto } 1458e2a990dSKuninori Morimoto 1467951b146SKuninori Morimoto int snd_soc_component_set_bias_level(struct snd_soc_component *component, 1477951b146SKuninori Morimoto enum snd_soc_bias_level level) 1487951b146SKuninori Morimoto { 149e2329eebSKuninori Morimoto int ret = 0; 1507951b146SKuninori Morimoto 151e2329eebSKuninori Morimoto if (component->driver->set_bias_level) 152e2329eebSKuninori Morimoto ret = component->driver->set_bias_level(component, level); 153e2329eebSKuninori Morimoto 154e2329eebSKuninori Morimoto return soc_component_ret(component, ret); 1557951b146SKuninori Morimoto } 1567951b146SKuninori Morimoto 1574ca8701eSKuninori Morimoto int snd_soc_component_enable_pin(struct snd_soc_component *component, 1584ca8701eSKuninori Morimoto const char *pin) 1594ca8701eSKuninori Morimoto { 16031428c78SMark Brown struct snd_soc_dapm_context *dapm = 16131428c78SMark Brown snd_soc_component_get_dapm(component); 16231428c78SMark Brown return snd_soc_dapm_enable_pin(dapm, pin); 1634ca8701eSKuninori Morimoto } 1644ff1fef1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_enable_pin); 1654ff1fef1SKuninori Morimoto 1664ff1fef1SKuninori Morimoto int snd_soc_component_enable_pin_unlocked(struct snd_soc_component *component, 1674ff1fef1SKuninori Morimoto const char *pin) 1684ff1fef1SKuninori Morimoto { 16931428c78SMark Brown struct snd_soc_dapm_context *dapm = 17031428c78SMark Brown snd_soc_component_get_dapm(component); 17131428c78SMark Brown return snd_soc_dapm_enable_pin_unlocked(dapm, pin); 1724ff1fef1SKuninori Morimoto } 1734ff1fef1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_enable_pin_unlocked); 1744ff1fef1SKuninori Morimoto 1754ff1fef1SKuninori Morimoto int snd_soc_component_disable_pin(struct snd_soc_component *component, 1764ff1fef1SKuninori Morimoto const char *pin) 1774ff1fef1SKuninori Morimoto { 17831428c78SMark Brown struct snd_soc_dapm_context *dapm = 17931428c78SMark Brown snd_soc_component_get_dapm(component); 18031428c78SMark Brown return snd_soc_dapm_disable_pin(dapm, pin); 1814ff1fef1SKuninori Morimoto } 1824ff1fef1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_disable_pin); 1834ff1fef1SKuninori Morimoto 1844ff1fef1SKuninori Morimoto int snd_soc_component_disable_pin_unlocked(struct snd_soc_component *component, 1854ff1fef1SKuninori Morimoto const char *pin) 1864ff1fef1SKuninori Morimoto { 18731428c78SMark Brown struct snd_soc_dapm_context *dapm = 18831428c78SMark Brown snd_soc_component_get_dapm(component); 18931428c78SMark Brown return snd_soc_dapm_disable_pin_unlocked(dapm, pin); 1904ff1fef1SKuninori Morimoto } 1914ff1fef1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_disable_pin_unlocked); 1924ff1fef1SKuninori Morimoto 1934ff1fef1SKuninori Morimoto int snd_soc_component_nc_pin(struct snd_soc_component *component, 1944ff1fef1SKuninori Morimoto const char *pin) 1954ff1fef1SKuninori Morimoto { 19631428c78SMark Brown struct snd_soc_dapm_context *dapm = 19731428c78SMark Brown snd_soc_component_get_dapm(component); 19831428c78SMark Brown return snd_soc_dapm_nc_pin(dapm, pin); 1994ff1fef1SKuninori Morimoto } 2004ff1fef1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_nc_pin); 2014ff1fef1SKuninori Morimoto 2024ff1fef1SKuninori Morimoto int snd_soc_component_nc_pin_unlocked(struct snd_soc_component *component, 2034ff1fef1SKuninori Morimoto const char *pin) 2044ff1fef1SKuninori Morimoto { 20531428c78SMark Brown struct snd_soc_dapm_context *dapm = 20631428c78SMark Brown snd_soc_component_get_dapm(component); 20731428c78SMark Brown return snd_soc_dapm_nc_pin_unlocked(dapm, pin); 2084ff1fef1SKuninori Morimoto } 2094ff1fef1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_nc_pin_unlocked); 2104ff1fef1SKuninori Morimoto 2114ff1fef1SKuninori Morimoto int snd_soc_component_get_pin_status(struct snd_soc_component *component, 2124ff1fef1SKuninori Morimoto const char *pin) 2134ff1fef1SKuninori Morimoto { 21431428c78SMark Brown struct snd_soc_dapm_context *dapm = 21531428c78SMark Brown snd_soc_component_get_dapm(component); 21631428c78SMark Brown return snd_soc_dapm_get_pin_status(dapm, pin); 2174ff1fef1SKuninori Morimoto } 2184ff1fef1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_get_pin_status); 2194ff1fef1SKuninori Morimoto 2204ff1fef1SKuninori Morimoto int snd_soc_component_force_enable_pin(struct snd_soc_component *component, 2214ff1fef1SKuninori Morimoto const char *pin) 2224ff1fef1SKuninori Morimoto { 22331428c78SMark Brown struct snd_soc_dapm_context *dapm = 22431428c78SMark Brown snd_soc_component_get_dapm(component); 22531428c78SMark Brown return snd_soc_dapm_force_enable_pin(dapm, pin); 2264ff1fef1SKuninori Morimoto } 2274ff1fef1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_force_enable_pin); 2284ff1fef1SKuninori Morimoto 2294ff1fef1SKuninori Morimoto int snd_soc_component_force_enable_pin_unlocked( 2304ff1fef1SKuninori Morimoto struct snd_soc_component *component, 2314ff1fef1SKuninori Morimoto const char *pin) 2324ff1fef1SKuninori Morimoto { 23331428c78SMark Brown struct snd_soc_dapm_context *dapm = 23431428c78SMark Brown snd_soc_component_get_dapm(component); 23531428c78SMark Brown return snd_soc_dapm_force_enable_pin_unlocked(dapm, pin); 2364ff1fef1SKuninori Morimoto } 2374ff1fef1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_force_enable_pin_unlocked); 2384ff1fef1SKuninori Morimoto 2394ff1fef1SKuninori Morimoto /** 2404ff1fef1SKuninori Morimoto * snd_soc_component_set_jack - configure component jack. 2414ff1fef1SKuninori Morimoto * @component: COMPONENTs 2424ff1fef1SKuninori Morimoto * @jack: structure to use for the jack 2434ff1fef1SKuninori Morimoto * @data: can be used if codec driver need extra data for configuring jack 2444ff1fef1SKuninori Morimoto * 2454ff1fef1SKuninori Morimoto * Configures and enables jack detection function. 2464ff1fef1SKuninori Morimoto */ 2474ff1fef1SKuninori Morimoto int snd_soc_component_set_jack(struct snd_soc_component *component, 2484ff1fef1SKuninori Morimoto struct snd_soc_jack *jack, void *data) 2494ff1fef1SKuninori Morimoto { 250e2329eebSKuninori Morimoto int ret = -ENOTSUPP; 2514ff1fef1SKuninori Morimoto 252e2329eebSKuninori Morimoto if (component->driver->set_jack) 253e2329eebSKuninori Morimoto ret = component->driver->set_jack(component, jack, data); 254e2329eebSKuninori Morimoto 255e2329eebSKuninori Morimoto return soc_component_ret(component, ret); 2564ff1fef1SKuninori Morimoto } 2574ff1fef1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_set_jack); 2584a81e8f3SKuninori Morimoto 259*df55122bSAstrid Rost /** 260*df55122bSAstrid Rost * snd_soc_component_get_jack_type 261*df55122bSAstrid Rost * @component: COMPONENTs 262*df55122bSAstrid Rost * 263*df55122bSAstrid Rost * Returns the jack type of the component 264*df55122bSAstrid Rost * This can either be the supported type or one read from 265*df55122bSAstrid Rost * devicetree with the property: jack-type. 266*df55122bSAstrid Rost */ 267*df55122bSAstrid Rost int snd_soc_component_get_jack_type( 268*df55122bSAstrid Rost struct snd_soc_component *component) 269*df55122bSAstrid Rost { 270*df55122bSAstrid Rost int ret = -ENOTSUPP; 271*df55122bSAstrid Rost 272*df55122bSAstrid Rost if (component->driver->get_jack_type) 273*df55122bSAstrid Rost ret = component->driver->get_jack_type(component); 274*df55122bSAstrid Rost 275*df55122bSAstrid Rost return soc_component_ret(component, ret); 276*df55122bSAstrid Rost } 277*df55122bSAstrid Rost EXPORT_SYMBOL_GPL(snd_soc_component_get_jack_type); 278*df55122bSAstrid Rost 2794a81e8f3SKuninori Morimoto int snd_soc_component_module_get(struct snd_soc_component *component, 280a739fdc2SPeter Ujfalusi void *mark, int upon_open) 2814a81e8f3SKuninori Morimoto { 282e2329eebSKuninori Morimoto int ret = 0; 283e2329eebSKuninori Morimoto 2844a81e8f3SKuninori Morimoto if (component->driver->module_get_upon_open == !!upon_open && 2854a81e8f3SKuninori Morimoto !try_module_get(component->dev->driver->owner)) 286e2329eebSKuninori Morimoto ret = -ENODEV; 2874a81e8f3SKuninori Morimoto 288a739fdc2SPeter Ujfalusi /* mark module if succeeded */ 28951aff91aSKuninori Morimoto if (ret == 0) 290a739fdc2SPeter Ujfalusi soc_component_mark_push(component, mark, module); 29151aff91aSKuninori Morimoto 292e2329eebSKuninori Morimoto return soc_component_ret(component, ret); 2934a81e8f3SKuninori Morimoto } 2944a81e8f3SKuninori Morimoto 2954a81e8f3SKuninori Morimoto void snd_soc_component_module_put(struct snd_soc_component *component, 296a739fdc2SPeter Ujfalusi void *mark, int upon_open, int rollback) 2974a81e8f3SKuninori Morimoto { 298a739fdc2SPeter Ujfalusi if (rollback && !soc_component_mark_match(component, mark, module)) 29951aff91aSKuninori Morimoto return; 30051aff91aSKuninori Morimoto 3014a81e8f3SKuninori Morimoto if (component->driver->module_get_upon_open == !!upon_open) 3024a81e8f3SKuninori Morimoto module_put(component->dev->driver->owner); 30351aff91aSKuninori Morimoto 304a739fdc2SPeter Ujfalusi /* remove the mark from module */ 305a739fdc2SPeter Ujfalusi soc_component_mark_pop(component, mark, module); 3064a81e8f3SKuninori Morimoto } 307ae2f4849SKuninori Morimoto 308ae2f4849SKuninori Morimoto int snd_soc_component_open(struct snd_soc_component *component, 309ae2f4849SKuninori Morimoto struct snd_pcm_substream *substream) 310ae2f4849SKuninori Morimoto { 311e2329eebSKuninori Morimoto int ret = 0; 312e2329eebSKuninori Morimoto 313e2cb4a14SKuninori Morimoto if (component->driver->open) 314e2329eebSKuninori Morimoto ret = component->driver->open(component, substream); 315e2329eebSKuninori Morimoto 31651aff91aSKuninori Morimoto /* mark substream if succeeded */ 31751aff91aSKuninori Morimoto if (ret == 0) 31851aff91aSKuninori Morimoto soc_component_mark_push(component, substream, open); 31951aff91aSKuninori Morimoto 320e2329eebSKuninori Morimoto return soc_component_ret(component, ret); 321ae2f4849SKuninori Morimoto } 3223672beb8SKuninori Morimoto 3233672beb8SKuninori Morimoto int snd_soc_component_close(struct snd_soc_component *component, 32451aff91aSKuninori Morimoto struct snd_pcm_substream *substream, 32551aff91aSKuninori Morimoto int rollback) 3263672beb8SKuninori Morimoto { 327e2329eebSKuninori Morimoto int ret = 0; 328e2329eebSKuninori Morimoto 32951aff91aSKuninori Morimoto if (rollback && !soc_component_mark_match(component, substream, open)) 33051aff91aSKuninori Morimoto return 0; 33151aff91aSKuninori Morimoto 332e2cb4a14SKuninori Morimoto if (component->driver->close) 333e2329eebSKuninori Morimoto ret = component->driver->close(component, substream); 334e2329eebSKuninori Morimoto 33551aff91aSKuninori Morimoto /* remove marked substream */ 33651aff91aSKuninori Morimoto soc_component_mark_pop(component, substream, open); 33751aff91aSKuninori Morimoto 338e2329eebSKuninori Morimoto return soc_component_ret(component, ret); 3393672beb8SKuninori Morimoto } 3406d537233SKuninori Morimoto 34166c51573SKuninori Morimoto void snd_soc_component_suspend(struct snd_soc_component *component) 34266c51573SKuninori Morimoto { 34366c51573SKuninori Morimoto if (component->driver->suspend) 34466c51573SKuninori Morimoto component->driver->suspend(component); 34566c51573SKuninori Morimoto component->suspended = 1; 34666c51573SKuninori Morimoto } 3479a840cbaSKuninori Morimoto 3489a840cbaSKuninori Morimoto void snd_soc_component_resume(struct snd_soc_component *component) 3499a840cbaSKuninori Morimoto { 3509a840cbaSKuninori Morimoto if (component->driver->resume) 3519a840cbaSKuninori Morimoto component->driver->resume(component); 3529a840cbaSKuninori Morimoto component->suspended = 0; 3539a840cbaSKuninori Morimoto } 354e40fadbcSKuninori Morimoto 355e40fadbcSKuninori Morimoto int snd_soc_component_is_suspended(struct snd_soc_component *component) 356e40fadbcSKuninori Morimoto { 357e40fadbcSKuninori Morimoto return component->suspended; 358e40fadbcSKuninori Morimoto } 35908e837ddSKuninori Morimoto 36008e837ddSKuninori Morimoto int snd_soc_component_probe(struct snd_soc_component *component) 36108e837ddSKuninori Morimoto { 362e2329eebSKuninori Morimoto int ret = 0; 36308e837ddSKuninori Morimoto 364e2329eebSKuninori Morimoto if (component->driver->probe) 365e2329eebSKuninori Morimoto ret = component->driver->probe(component); 366e2329eebSKuninori Morimoto 367e2329eebSKuninori Morimoto return soc_component_ret(component, ret); 36808e837ddSKuninori Morimoto } 36903b34dd7SKuninori Morimoto 37003b34dd7SKuninori Morimoto void snd_soc_component_remove(struct snd_soc_component *component) 37103b34dd7SKuninori Morimoto { 37203b34dd7SKuninori Morimoto if (component->driver->remove) 37303b34dd7SKuninori Morimoto component->driver->remove(component); 37403b34dd7SKuninori Morimoto } 3752c7b1704SKuninori Morimoto 3762c7b1704SKuninori Morimoto int snd_soc_component_of_xlate_dai_id(struct snd_soc_component *component, 3772c7b1704SKuninori Morimoto struct device_node *ep) 3782c7b1704SKuninori Morimoto { 379e2329eebSKuninori Morimoto int ret = -ENOTSUPP; 3802c7b1704SKuninori Morimoto 381e2329eebSKuninori Morimoto if (component->driver->of_xlate_dai_id) 382e2329eebSKuninori Morimoto ret = component->driver->of_xlate_dai_id(component, ep); 383e2329eebSKuninori Morimoto 384e2329eebSKuninori Morimoto return soc_component_ret(component, ret); 3852c7b1704SKuninori Morimoto } 386a2a34175SKuninori Morimoto 387a2a34175SKuninori Morimoto int snd_soc_component_of_xlate_dai_name(struct snd_soc_component *component, 388933f98beSKrzysztof Kozlowski const struct of_phandle_args *args, 389a2a34175SKuninori Morimoto const char **dai_name) 390a2a34175SKuninori Morimoto { 391a2a34175SKuninori Morimoto if (component->driver->of_xlate_dai_name) 392cc4d8cebSJerome Brunet return component->driver->of_xlate_dai_name(component, 393a2a34175SKuninori Morimoto args, dai_name); 394cc4d8cebSJerome Brunet /* 395cc4d8cebSJerome Brunet * Don't use soc_component_ret here because we may not want to report 396cc4d8cebSJerome Brunet * the error just yet. If a device has more than one component, the 397cc4d8cebSJerome Brunet * first may not match and we don't want spam the log with this. 398cc4d8cebSJerome Brunet */ 399cc4d8cebSJerome Brunet return -ENOTSUPP; 400a2a34175SKuninori Morimoto } 4010035e256SKuninori Morimoto 402c7d75b59SKuninori Morimoto void snd_soc_component_setup_regmap(struct snd_soc_component *component) 403c7d75b59SKuninori Morimoto { 404c7d75b59SKuninori Morimoto int val_bytes = regmap_get_val_bytes(component->regmap); 405c7d75b59SKuninori Morimoto 406c7d75b59SKuninori Morimoto /* Errors are legitimate for non-integer byte multiples */ 407c7d75b59SKuninori Morimoto if (val_bytes > 0) 408c7d75b59SKuninori Morimoto component->val_bytes = val_bytes; 409c7d75b59SKuninori Morimoto } 410c7d75b59SKuninori Morimoto 411c7d75b59SKuninori Morimoto #ifdef CONFIG_REGMAP 412c7d75b59SKuninori Morimoto 413c7d75b59SKuninori Morimoto /** 414c7d75b59SKuninori Morimoto * snd_soc_component_init_regmap() - Initialize regmap instance for the 415c7d75b59SKuninori Morimoto * component 416c7d75b59SKuninori Morimoto * @component: The component for which to initialize the regmap instance 417c7d75b59SKuninori Morimoto * @regmap: The regmap instance that should be used by the component 418c7d75b59SKuninori Morimoto * 419c7d75b59SKuninori Morimoto * This function allows deferred assignment of the regmap instance that is 420c7d75b59SKuninori Morimoto * associated with the component. Only use this if the regmap instance is not 421c7d75b59SKuninori Morimoto * yet ready when the component is registered. The function must also be called 422c7d75b59SKuninori Morimoto * before the first IO attempt of the component. 423c7d75b59SKuninori Morimoto */ 424c7d75b59SKuninori Morimoto void snd_soc_component_init_regmap(struct snd_soc_component *component, 425c7d75b59SKuninori Morimoto struct regmap *regmap) 426c7d75b59SKuninori Morimoto { 427c7d75b59SKuninori Morimoto component->regmap = regmap; 428c7d75b59SKuninori Morimoto snd_soc_component_setup_regmap(component); 429c7d75b59SKuninori Morimoto } 430c7d75b59SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_init_regmap); 431c7d75b59SKuninori Morimoto 432c7d75b59SKuninori Morimoto /** 433c7d75b59SKuninori Morimoto * snd_soc_component_exit_regmap() - De-initialize regmap instance for the 434c7d75b59SKuninori Morimoto * component 435c7d75b59SKuninori Morimoto * @component: The component for which to de-initialize the regmap instance 436c7d75b59SKuninori Morimoto * 437c7d75b59SKuninori Morimoto * Calls regmap_exit() on the regmap instance associated to the component and 438c7d75b59SKuninori Morimoto * removes the regmap instance from the component. 439c7d75b59SKuninori Morimoto * 440c7d75b59SKuninori Morimoto * This function should only be used if snd_soc_component_init_regmap() was used 441c7d75b59SKuninori Morimoto * to initialize the regmap instance. 442c7d75b59SKuninori Morimoto */ 443c7d75b59SKuninori Morimoto void snd_soc_component_exit_regmap(struct snd_soc_component *component) 444c7d75b59SKuninori Morimoto { 445c7d75b59SKuninori Morimoto regmap_exit(component->regmap); 446c7d75b59SKuninori Morimoto component->regmap = NULL; 447c7d75b59SKuninori Morimoto } 448c7d75b59SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_exit_regmap); 449c7d75b59SKuninori Morimoto 450c7d75b59SKuninori Morimoto #endif 451c7d75b59SKuninori Morimoto 452cd46f382SPeter Ujfalusi int snd_soc_component_compr_open(struct snd_soc_component *component, 453cd46f382SPeter Ujfalusi struct snd_compr_stream *cstream) 454a4e427c5SKuninori Morimoto { 455cd46f382SPeter Ujfalusi int ret = 0; 456a4e427c5SKuninori Morimoto 457a4e427c5SKuninori Morimoto if (component->driver->compress_ops && 458cd46f382SPeter Ujfalusi component->driver->compress_ops->open) 459a4e427c5SKuninori Morimoto ret = component->driver->compress_ops->open(component, cstream); 460a4e427c5SKuninori Morimoto 461cd46f382SPeter Ujfalusi /* mark substream if succeeded */ 462cd46f382SPeter Ujfalusi if (ret == 0) 463cd46f382SPeter Ujfalusi soc_component_mark_push(component, cstream, compr_open); 464cd46f382SPeter Ujfalusi 465cd46f382SPeter Ujfalusi return soc_component_ret(component, ret); 466a4e427c5SKuninori Morimoto } 467a4e427c5SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_compr_open); 468a4e427c5SKuninori Morimoto 469cd46f382SPeter Ujfalusi void snd_soc_component_compr_free(struct snd_soc_component *component, 470cd46f382SPeter Ujfalusi struct snd_compr_stream *cstream, 471f94ba9acSKuninori Morimoto int rollback) 472dbde5e21SKuninori Morimoto { 473f94ba9acSKuninori Morimoto if (rollback && !soc_component_mark_match(component, cstream, compr_open)) 474cd46f382SPeter Ujfalusi return; 475dbde5e21SKuninori Morimoto 476dbde5e21SKuninori Morimoto if (component->driver->compress_ops && 477dbde5e21SKuninori Morimoto component->driver->compress_ops->free) 478dbde5e21SKuninori Morimoto component->driver->compress_ops->free(component, cstream); 479f94ba9acSKuninori Morimoto 480cd46f382SPeter Ujfalusi /* remove marked substream */ 481f94ba9acSKuninori Morimoto soc_component_mark_pop(component, cstream, compr_open); 482dbde5e21SKuninori Morimoto } 483dbde5e21SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_compr_free); 484dbde5e21SKuninori Morimoto 48508aee251SKuninori Morimoto int snd_soc_component_compr_trigger(struct snd_compr_stream *cstream, int cmd) 48608aee251SKuninori Morimoto { 48708aee251SKuninori Morimoto struct snd_soc_pcm_runtime *rtd = cstream->private_data; 48808aee251SKuninori Morimoto struct snd_soc_component *component; 48908aee251SKuninori Morimoto int i, ret; 49008aee251SKuninori Morimoto 49108aee251SKuninori Morimoto for_each_rtd_components(rtd, i, component) { 49208aee251SKuninori Morimoto if (component->driver->compress_ops && 49308aee251SKuninori Morimoto component->driver->compress_ops->trigger) { 49408aee251SKuninori Morimoto ret = component->driver->compress_ops->trigger( 49508aee251SKuninori Morimoto component, cstream, cmd); 49608aee251SKuninori Morimoto if (ret < 0) 49708aee251SKuninori Morimoto return soc_component_ret(component, ret); 49808aee251SKuninori Morimoto } 49908aee251SKuninori Morimoto } 50008aee251SKuninori Morimoto 50108aee251SKuninori Morimoto return 0; 50208aee251SKuninori Morimoto } 50308aee251SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_compr_trigger); 50408aee251SKuninori Morimoto 505ff08cf80SKuninori Morimoto int snd_soc_component_compr_set_params(struct snd_compr_stream *cstream, 506ff08cf80SKuninori Morimoto struct snd_compr_params *params) 507ff08cf80SKuninori Morimoto { 508ff08cf80SKuninori Morimoto struct snd_soc_pcm_runtime *rtd = cstream->private_data; 509ff08cf80SKuninori Morimoto struct snd_soc_component *component; 510ff08cf80SKuninori Morimoto int i, ret; 511ff08cf80SKuninori Morimoto 512ff08cf80SKuninori Morimoto for_each_rtd_components(rtd, i, component) { 513ff08cf80SKuninori Morimoto if (component->driver->compress_ops && 514ff08cf80SKuninori Morimoto component->driver->compress_ops->set_params) { 515ff08cf80SKuninori Morimoto ret = component->driver->compress_ops->set_params( 516ff08cf80SKuninori Morimoto component, cstream, params); 517ff08cf80SKuninori Morimoto if (ret < 0) 518ff08cf80SKuninori Morimoto return soc_component_ret(component, ret); 519ff08cf80SKuninori Morimoto } 520ff08cf80SKuninori Morimoto } 521ff08cf80SKuninori Morimoto 522ff08cf80SKuninori Morimoto return 0; 523ff08cf80SKuninori Morimoto } 524ff08cf80SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_compr_set_params); 525ff08cf80SKuninori Morimoto 52677c221ecSKuninori Morimoto int snd_soc_component_compr_get_params(struct snd_compr_stream *cstream, 52777c221ecSKuninori Morimoto struct snd_codec *params) 52877c221ecSKuninori Morimoto { 52977c221ecSKuninori Morimoto struct snd_soc_pcm_runtime *rtd = cstream->private_data; 53077c221ecSKuninori Morimoto struct snd_soc_component *component; 53177c221ecSKuninori Morimoto int i, ret; 53277c221ecSKuninori Morimoto 53377c221ecSKuninori Morimoto for_each_rtd_components(rtd, i, component) { 53477c221ecSKuninori Morimoto if (component->driver->compress_ops && 53577c221ecSKuninori Morimoto component->driver->compress_ops->get_params) { 53677c221ecSKuninori Morimoto ret = component->driver->compress_ops->get_params( 53777c221ecSKuninori Morimoto component, cstream, params); 53877c221ecSKuninori Morimoto return soc_component_ret(component, ret); 53977c221ecSKuninori Morimoto } 54077c221ecSKuninori Morimoto } 54177c221ecSKuninori Morimoto 54277c221ecSKuninori Morimoto return 0; 54377c221ecSKuninori Morimoto } 54477c221ecSKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_compr_get_params); 54577c221ecSKuninori Morimoto 546d67fcb2dSKuninori Morimoto int snd_soc_component_compr_get_caps(struct snd_compr_stream *cstream, 547d67fcb2dSKuninori Morimoto struct snd_compr_caps *caps) 548d67fcb2dSKuninori Morimoto { 549d67fcb2dSKuninori Morimoto struct snd_soc_pcm_runtime *rtd = cstream->private_data; 550d67fcb2dSKuninori Morimoto struct snd_soc_component *component; 551d67fcb2dSKuninori Morimoto int i, ret = 0; 552d67fcb2dSKuninori Morimoto 553d67fcb2dSKuninori Morimoto mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); 554d67fcb2dSKuninori Morimoto 555d67fcb2dSKuninori Morimoto for_each_rtd_components(rtd, i, component) { 556d67fcb2dSKuninori Morimoto if (component->driver->compress_ops && 557d67fcb2dSKuninori Morimoto component->driver->compress_ops->get_caps) { 558d67fcb2dSKuninori Morimoto ret = component->driver->compress_ops->get_caps( 559d67fcb2dSKuninori Morimoto component, cstream, caps); 560d67fcb2dSKuninori Morimoto break; 561d67fcb2dSKuninori Morimoto } 562d67fcb2dSKuninori Morimoto } 563d67fcb2dSKuninori Morimoto 564d67fcb2dSKuninori Morimoto mutex_unlock(&rtd->card->pcm_mutex); 565d67fcb2dSKuninori Morimoto 566d67fcb2dSKuninori Morimoto return soc_component_ret(component, ret); 567d67fcb2dSKuninori Morimoto } 568d67fcb2dSKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_compr_get_caps); 569d67fcb2dSKuninori Morimoto 5700f6fe097SKuninori Morimoto int snd_soc_component_compr_get_codec_caps(struct snd_compr_stream *cstream, 5710f6fe097SKuninori Morimoto struct snd_compr_codec_caps *codec) 5720f6fe097SKuninori Morimoto { 5730f6fe097SKuninori Morimoto struct snd_soc_pcm_runtime *rtd = cstream->private_data; 5740f6fe097SKuninori Morimoto struct snd_soc_component *component; 5750f6fe097SKuninori Morimoto int i, ret = 0; 5760f6fe097SKuninori Morimoto 5770f6fe097SKuninori Morimoto mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); 5780f6fe097SKuninori Morimoto 5790f6fe097SKuninori Morimoto for_each_rtd_components(rtd, i, component) { 5800f6fe097SKuninori Morimoto if (component->driver->compress_ops && 5810f6fe097SKuninori Morimoto component->driver->compress_ops->get_codec_caps) { 5820f6fe097SKuninori Morimoto ret = component->driver->compress_ops->get_codec_caps( 5830f6fe097SKuninori Morimoto component, cstream, codec); 5840f6fe097SKuninori Morimoto break; 5850f6fe097SKuninori Morimoto } 5860f6fe097SKuninori Morimoto } 5870f6fe097SKuninori Morimoto 5880f6fe097SKuninori Morimoto mutex_unlock(&rtd->card->pcm_mutex); 5890f6fe097SKuninori Morimoto 5900f6fe097SKuninori Morimoto return soc_component_ret(component, ret); 5910f6fe097SKuninori Morimoto } 5920f6fe097SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_compr_get_codec_caps); 5930f6fe097SKuninori Morimoto 5940506b885SKuninori Morimoto int snd_soc_component_compr_ack(struct snd_compr_stream *cstream, size_t bytes) 5950506b885SKuninori Morimoto { 5960506b885SKuninori Morimoto struct snd_soc_pcm_runtime *rtd = cstream->private_data; 5970506b885SKuninori Morimoto struct snd_soc_component *component; 5980506b885SKuninori Morimoto int i, ret; 5990506b885SKuninori Morimoto 6000506b885SKuninori Morimoto for_each_rtd_components(rtd, i, component) { 6010506b885SKuninori Morimoto if (component->driver->compress_ops && 6020506b885SKuninori Morimoto component->driver->compress_ops->ack) { 6030506b885SKuninori Morimoto ret = component->driver->compress_ops->ack( 6040506b885SKuninori Morimoto component, cstream, bytes); 6050506b885SKuninori Morimoto if (ret < 0) 6060506b885SKuninori Morimoto return soc_component_ret(component, ret); 6070506b885SKuninori Morimoto } 6080506b885SKuninori Morimoto } 6090506b885SKuninori Morimoto 6100506b885SKuninori Morimoto return 0; 6110506b885SKuninori Morimoto } 6120506b885SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_compr_ack); 6130506b885SKuninori Morimoto 61403ecea64SKuninori Morimoto int snd_soc_component_compr_pointer(struct snd_compr_stream *cstream, 61503ecea64SKuninori Morimoto struct snd_compr_tstamp *tstamp) 61603ecea64SKuninori Morimoto { 61703ecea64SKuninori Morimoto struct snd_soc_pcm_runtime *rtd = cstream->private_data; 61803ecea64SKuninori Morimoto struct snd_soc_component *component; 61903ecea64SKuninori Morimoto int i, ret; 62003ecea64SKuninori Morimoto 62103ecea64SKuninori Morimoto for_each_rtd_components(rtd, i, component) { 62203ecea64SKuninori Morimoto if (component->driver->compress_ops && 62303ecea64SKuninori Morimoto component->driver->compress_ops->pointer) { 62403ecea64SKuninori Morimoto ret = component->driver->compress_ops->pointer( 62503ecea64SKuninori Morimoto component, cstream, tstamp); 62603ecea64SKuninori Morimoto return soc_component_ret(component, ret); 62703ecea64SKuninori Morimoto } 62803ecea64SKuninori Morimoto } 62903ecea64SKuninori Morimoto 63003ecea64SKuninori Morimoto return 0; 63103ecea64SKuninori Morimoto } 63203ecea64SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_compr_pointer); 63303ecea64SKuninori Morimoto 634b5852e66SKuninori Morimoto int snd_soc_component_compr_copy(struct snd_compr_stream *cstream, 635b5852e66SKuninori Morimoto char __user *buf, size_t count) 636b5852e66SKuninori Morimoto { 637b5852e66SKuninori Morimoto struct snd_soc_pcm_runtime *rtd = cstream->private_data; 638b5852e66SKuninori Morimoto struct snd_soc_component *component; 639b5852e66SKuninori Morimoto int i, ret = 0; 640b5852e66SKuninori Morimoto 641b5852e66SKuninori Morimoto mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); 642b5852e66SKuninori Morimoto 643b5852e66SKuninori Morimoto for_each_rtd_components(rtd, i, component) { 644b5852e66SKuninori Morimoto if (component->driver->compress_ops && 645b5852e66SKuninori Morimoto component->driver->compress_ops->copy) { 646b5852e66SKuninori Morimoto ret = component->driver->compress_ops->copy( 647b5852e66SKuninori Morimoto component, cstream, buf, count); 648b5852e66SKuninori Morimoto break; 649b5852e66SKuninori Morimoto } 650b5852e66SKuninori Morimoto } 651b5852e66SKuninori Morimoto 652b5852e66SKuninori Morimoto mutex_unlock(&rtd->card->pcm_mutex); 653b5852e66SKuninori Morimoto 654b5852e66SKuninori Morimoto return soc_component_ret(component, ret); 655b5852e66SKuninori Morimoto } 656b5852e66SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_compr_copy); 657b5852e66SKuninori Morimoto 6581b308fb1SKuninori Morimoto int snd_soc_component_compr_set_metadata(struct snd_compr_stream *cstream, 6591b308fb1SKuninori Morimoto struct snd_compr_metadata *metadata) 6601b308fb1SKuninori Morimoto { 6611b308fb1SKuninori Morimoto struct snd_soc_pcm_runtime *rtd = cstream->private_data; 6621b308fb1SKuninori Morimoto struct snd_soc_component *component; 6631b308fb1SKuninori Morimoto int i, ret; 6641b308fb1SKuninori Morimoto 6651b308fb1SKuninori Morimoto for_each_rtd_components(rtd, i, component) { 6661b308fb1SKuninori Morimoto if (component->driver->compress_ops && 6671b308fb1SKuninori Morimoto component->driver->compress_ops->set_metadata) { 6681b308fb1SKuninori Morimoto ret = component->driver->compress_ops->set_metadata( 6691b308fb1SKuninori Morimoto component, cstream, metadata); 6701b308fb1SKuninori Morimoto if (ret < 0) 6711b308fb1SKuninori Morimoto return soc_component_ret(component, ret); 6721b308fb1SKuninori Morimoto } 6731b308fb1SKuninori Morimoto } 6741b308fb1SKuninori Morimoto 6751b308fb1SKuninori Morimoto return 0; 6761b308fb1SKuninori Morimoto } 6771b308fb1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_compr_set_metadata); 6781b308fb1SKuninori Morimoto 679bab78c23SKuninori Morimoto int snd_soc_component_compr_get_metadata(struct snd_compr_stream *cstream, 680bab78c23SKuninori Morimoto struct snd_compr_metadata *metadata) 681bab78c23SKuninori Morimoto { 682bab78c23SKuninori Morimoto struct snd_soc_pcm_runtime *rtd = cstream->private_data; 683bab78c23SKuninori Morimoto struct snd_soc_component *component; 684bab78c23SKuninori Morimoto int i, ret; 685bab78c23SKuninori Morimoto 686bab78c23SKuninori Morimoto for_each_rtd_components(rtd, i, component) { 687bab78c23SKuninori Morimoto if (component->driver->compress_ops && 688bab78c23SKuninori Morimoto component->driver->compress_ops->get_metadata) { 689bab78c23SKuninori Morimoto ret = component->driver->compress_ops->get_metadata( 690bab78c23SKuninori Morimoto component, cstream, metadata); 691bab78c23SKuninori Morimoto return soc_component_ret(component, ret); 692bab78c23SKuninori Morimoto } 693bab78c23SKuninori Morimoto } 694bab78c23SKuninori Morimoto 695bab78c23SKuninori Morimoto return 0; 696bab78c23SKuninori Morimoto } 697bab78c23SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_compr_get_metadata); 698bab78c23SKuninori Morimoto 699e8712315SKuninori Morimoto static unsigned int soc_component_read_no_lock( 700e8712315SKuninori Morimoto struct snd_soc_component *component, 701cf6e26c7SKuninori Morimoto unsigned int reg) 702460b42d1SKuninori Morimoto { 703460b42d1SKuninori Morimoto int ret; 704cf6e26c7SKuninori Morimoto unsigned int val = 0; 705460b42d1SKuninori Morimoto 706460b42d1SKuninori Morimoto if (component->regmap) 707cf6e26c7SKuninori Morimoto ret = regmap_read(component->regmap, reg, &val); 708460b42d1SKuninori Morimoto else if (component->driver->read) { 709460b42d1SKuninori Morimoto ret = 0; 710cf6e26c7SKuninori Morimoto val = component->driver->read(component, reg); 711460b42d1SKuninori Morimoto } 712460b42d1SKuninori Morimoto else 713460b42d1SKuninori Morimoto ret = -EIO; 714460b42d1SKuninori Morimoto 715460b42d1SKuninori Morimoto if (ret < 0) 716b296997cSSrinivas Kandagatla return soc_component_ret_reg_rw(component, ret, reg); 717460b42d1SKuninori Morimoto 718460b42d1SKuninori Morimoto return val; 719460b42d1SKuninori Morimoto } 720e8712315SKuninori Morimoto 721e8712315SKuninori Morimoto /** 722e8712315SKuninori Morimoto * snd_soc_component_read() - Read register value 723e8712315SKuninori Morimoto * @component: Component to read from 724e8712315SKuninori Morimoto * @reg: Register to read 725e8712315SKuninori Morimoto * 726e8712315SKuninori Morimoto * Return: read value 727e8712315SKuninori Morimoto */ 728e8712315SKuninori Morimoto unsigned int snd_soc_component_read(struct snd_soc_component *component, 729e8712315SKuninori Morimoto unsigned int reg) 730e8712315SKuninori Morimoto { 731e8712315SKuninori Morimoto unsigned int val; 732e8712315SKuninori Morimoto 733e8712315SKuninori Morimoto mutex_lock(&component->io_mutex); 734e8712315SKuninori Morimoto val = soc_component_read_no_lock(component, reg); 735e8712315SKuninori Morimoto mutex_unlock(&component->io_mutex); 736e8712315SKuninori Morimoto 737e8712315SKuninori Morimoto return val; 738e8712315SKuninori Morimoto } 739cf6e26c7SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_read); 740460b42d1SKuninori Morimoto 741e8712315SKuninori Morimoto static int soc_component_write_no_lock( 742e8712315SKuninori Morimoto struct snd_soc_component *component, 743e8712315SKuninori Morimoto unsigned int reg, unsigned int val) 744e8712315SKuninori Morimoto { 745e8712315SKuninori Morimoto int ret = -EIO; 746e8712315SKuninori Morimoto 747e8712315SKuninori Morimoto if (component->regmap) 748e8712315SKuninori Morimoto ret = regmap_write(component->regmap, reg, val); 749e8712315SKuninori Morimoto else if (component->driver->write) 750e8712315SKuninori Morimoto ret = component->driver->write(component, reg, val); 751e8712315SKuninori Morimoto 752b296997cSSrinivas Kandagatla return soc_component_ret_reg_rw(component, ret, reg); 753e8712315SKuninori Morimoto } 754e8712315SKuninori Morimoto 755460b42d1SKuninori Morimoto /** 756460b42d1SKuninori Morimoto * snd_soc_component_write() - Write register value 757460b42d1SKuninori Morimoto * @component: Component to write to 758460b42d1SKuninori Morimoto * @reg: Register to write 759460b42d1SKuninori Morimoto * @val: Value to write to the register 760460b42d1SKuninori Morimoto * 761460b42d1SKuninori Morimoto * Return: 0 on success, a negative error code otherwise. 762460b42d1SKuninori Morimoto */ 763460b42d1SKuninori Morimoto int snd_soc_component_write(struct snd_soc_component *component, 764460b42d1SKuninori Morimoto unsigned int reg, unsigned int val) 765460b42d1SKuninori Morimoto { 766e8712315SKuninori Morimoto int ret; 767460b42d1SKuninori Morimoto 768e8712315SKuninori Morimoto mutex_lock(&component->io_mutex); 769e8712315SKuninori Morimoto ret = soc_component_write_no_lock(component, reg, val); 770e8712315SKuninori Morimoto mutex_unlock(&component->io_mutex); 771460b42d1SKuninori Morimoto 772e8712315SKuninori Morimoto return ret; 773460b42d1SKuninori Morimoto } 774460b42d1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_write); 775460b42d1SKuninori Morimoto 776460b42d1SKuninori Morimoto static int snd_soc_component_update_bits_legacy( 777460b42d1SKuninori Morimoto struct snd_soc_component *component, unsigned int reg, 778460b42d1SKuninori Morimoto unsigned int mask, unsigned int val, bool *change) 779460b42d1SKuninori Morimoto { 780460b42d1SKuninori Morimoto unsigned int old, new; 781cf6e26c7SKuninori Morimoto int ret = 0; 782460b42d1SKuninori Morimoto 783460b42d1SKuninori Morimoto mutex_lock(&component->io_mutex); 784460b42d1SKuninori Morimoto 785e8712315SKuninori Morimoto old = soc_component_read_no_lock(component, reg); 786460b42d1SKuninori Morimoto 787460b42d1SKuninori Morimoto new = (old & ~mask) | (val & mask); 788460b42d1SKuninori Morimoto *change = old != new; 789460b42d1SKuninori Morimoto if (*change) 790e8712315SKuninori Morimoto ret = soc_component_write_no_lock(component, reg, new); 791cf6e26c7SKuninori Morimoto 792460b42d1SKuninori Morimoto mutex_unlock(&component->io_mutex); 793460b42d1SKuninori Morimoto 794b296997cSSrinivas Kandagatla return soc_component_ret_reg_rw(component, ret, reg); 795460b42d1SKuninori Morimoto } 796460b42d1SKuninori Morimoto 797460b42d1SKuninori Morimoto /** 798460b42d1SKuninori Morimoto * snd_soc_component_update_bits() - Perform read/modify/write cycle 799460b42d1SKuninori Morimoto * @component: Component to update 800460b42d1SKuninori Morimoto * @reg: Register to update 801460b42d1SKuninori Morimoto * @mask: Mask that specifies which bits to update 802460b42d1SKuninori Morimoto * @val: New value for the bits specified by mask 803460b42d1SKuninori Morimoto * 804460b42d1SKuninori Morimoto * Return: 1 if the operation was successful and the value of the register 805460b42d1SKuninori Morimoto * changed, 0 if the operation was successful, but the value did not change. 806460b42d1SKuninori Morimoto * Returns a negative error code otherwise. 807460b42d1SKuninori Morimoto */ 808460b42d1SKuninori Morimoto int snd_soc_component_update_bits(struct snd_soc_component *component, 809460b42d1SKuninori Morimoto unsigned int reg, unsigned int mask, unsigned int val) 810460b42d1SKuninori Morimoto { 811460b42d1SKuninori Morimoto bool change; 812460b42d1SKuninori Morimoto int ret; 813460b42d1SKuninori Morimoto 814460b42d1SKuninori Morimoto if (component->regmap) 815460b42d1SKuninori Morimoto ret = regmap_update_bits_check(component->regmap, reg, mask, 816460b42d1SKuninori Morimoto val, &change); 817460b42d1SKuninori Morimoto else 818460b42d1SKuninori Morimoto ret = snd_soc_component_update_bits_legacy(component, reg, 819460b42d1SKuninori Morimoto mask, val, &change); 820460b42d1SKuninori Morimoto 821460b42d1SKuninori Morimoto if (ret < 0) 822b296997cSSrinivas Kandagatla return soc_component_ret_reg_rw(component, ret, reg); 823460b42d1SKuninori Morimoto return change; 824460b42d1SKuninori Morimoto } 825460b42d1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_update_bits); 826460b42d1SKuninori Morimoto 827460b42d1SKuninori Morimoto /** 828460b42d1SKuninori Morimoto * snd_soc_component_update_bits_async() - Perform asynchronous 829460b42d1SKuninori Morimoto * read/modify/write cycle 830460b42d1SKuninori Morimoto * @component: Component to update 831460b42d1SKuninori Morimoto * @reg: Register to update 832460b42d1SKuninori Morimoto * @mask: Mask that specifies which bits to update 833460b42d1SKuninori Morimoto * @val: New value for the bits specified by mask 834460b42d1SKuninori Morimoto * 835460b42d1SKuninori Morimoto * This function is similar to snd_soc_component_update_bits(), but the update 836460b42d1SKuninori Morimoto * operation is scheduled asynchronously. This means it may not be completed 837460b42d1SKuninori Morimoto * when the function returns. To make sure that all scheduled updates have been 838460b42d1SKuninori Morimoto * completed snd_soc_component_async_complete() must be called. 839460b42d1SKuninori Morimoto * 840460b42d1SKuninori Morimoto * Return: 1 if the operation was successful and the value of the register 841460b42d1SKuninori Morimoto * changed, 0 if the operation was successful, but the value did not change. 842460b42d1SKuninori Morimoto * Returns a negative error code otherwise. 843460b42d1SKuninori Morimoto */ 844460b42d1SKuninori Morimoto int snd_soc_component_update_bits_async(struct snd_soc_component *component, 845460b42d1SKuninori Morimoto unsigned int reg, unsigned int mask, unsigned int val) 846460b42d1SKuninori Morimoto { 847460b42d1SKuninori Morimoto bool change; 848460b42d1SKuninori Morimoto int ret; 849460b42d1SKuninori Morimoto 850460b42d1SKuninori Morimoto if (component->regmap) 851460b42d1SKuninori Morimoto ret = regmap_update_bits_check_async(component->regmap, reg, 852460b42d1SKuninori Morimoto mask, val, &change); 853460b42d1SKuninori Morimoto else 854460b42d1SKuninori Morimoto ret = snd_soc_component_update_bits_legacy(component, reg, 855460b42d1SKuninori Morimoto mask, val, &change); 856460b42d1SKuninori Morimoto 857460b42d1SKuninori Morimoto if (ret < 0) 858b296997cSSrinivas Kandagatla return soc_component_ret_reg_rw(component, ret, reg); 859460b42d1SKuninori Morimoto return change; 860460b42d1SKuninori Morimoto } 861460b42d1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_update_bits_async); 862460b42d1SKuninori Morimoto 863460b42d1SKuninori Morimoto /** 8641da0b989SSrinivas Kandagatla * snd_soc_component_read_field() - Read register field value 8651da0b989SSrinivas Kandagatla * @component: Component to read from 8661da0b989SSrinivas Kandagatla * @reg: Register to read 8671da0b989SSrinivas Kandagatla * @mask: mask of the register field 8681da0b989SSrinivas Kandagatla * 8691da0b989SSrinivas Kandagatla * Return: read value of register field. 8701da0b989SSrinivas Kandagatla */ 8711da0b989SSrinivas Kandagatla unsigned int snd_soc_component_read_field(struct snd_soc_component *component, 8721da0b989SSrinivas Kandagatla unsigned int reg, unsigned int mask) 8731da0b989SSrinivas Kandagatla { 8741da0b989SSrinivas Kandagatla unsigned int val; 8751da0b989SSrinivas Kandagatla 8761da0b989SSrinivas Kandagatla val = snd_soc_component_read(component, reg); 8771da0b989SSrinivas Kandagatla 8781da0b989SSrinivas Kandagatla val = (val & mask) >> soc_component_field_shift(component, mask); 8791da0b989SSrinivas Kandagatla 8801da0b989SSrinivas Kandagatla return val; 8811da0b989SSrinivas Kandagatla } 8821da0b989SSrinivas Kandagatla EXPORT_SYMBOL_GPL(snd_soc_component_read_field); 8831da0b989SSrinivas Kandagatla 8841da0b989SSrinivas Kandagatla /** 8851da0b989SSrinivas Kandagatla * snd_soc_component_write_field() - write to register field 8861da0b989SSrinivas Kandagatla * @component: Component to write to 8871da0b989SSrinivas Kandagatla * @reg: Register to write 8881da0b989SSrinivas Kandagatla * @mask: mask of the register field to update 8891da0b989SSrinivas Kandagatla * @val: value of the field to write 8901da0b989SSrinivas Kandagatla * 8911da0b989SSrinivas Kandagatla * Return: 1 for change, otherwise 0. 8921da0b989SSrinivas Kandagatla */ 8931da0b989SSrinivas Kandagatla int snd_soc_component_write_field(struct snd_soc_component *component, 8941da0b989SSrinivas Kandagatla unsigned int reg, unsigned int mask, 8951da0b989SSrinivas Kandagatla unsigned int val) 8961da0b989SSrinivas Kandagatla { 8971da0b989SSrinivas Kandagatla 8981da0b989SSrinivas Kandagatla val = (val << soc_component_field_shift(component, mask)) & mask; 8991da0b989SSrinivas Kandagatla 9001da0b989SSrinivas Kandagatla return snd_soc_component_update_bits(component, reg, mask, val); 9011da0b989SSrinivas Kandagatla } 9021da0b989SSrinivas Kandagatla EXPORT_SYMBOL_GPL(snd_soc_component_write_field); 9031da0b989SSrinivas Kandagatla 9041da0b989SSrinivas Kandagatla /** 905460b42d1SKuninori Morimoto * snd_soc_component_async_complete() - Ensure asynchronous I/O has completed 906460b42d1SKuninori Morimoto * @component: Component for which to wait 907460b42d1SKuninori Morimoto * 908460b42d1SKuninori Morimoto * This function blocks until all asynchronous I/O which has previously been 909460b42d1SKuninori Morimoto * scheduled using snd_soc_component_update_bits_async() has completed. 910460b42d1SKuninori Morimoto */ 911460b42d1SKuninori Morimoto void snd_soc_component_async_complete(struct snd_soc_component *component) 912460b42d1SKuninori Morimoto { 913460b42d1SKuninori Morimoto if (component->regmap) 914460b42d1SKuninori Morimoto regmap_async_complete(component->regmap); 915460b42d1SKuninori Morimoto } 916460b42d1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_async_complete); 917460b42d1SKuninori Morimoto 918460b42d1SKuninori Morimoto /** 919460b42d1SKuninori Morimoto * snd_soc_component_test_bits - Test register for change 920460b42d1SKuninori Morimoto * @component: component 921460b42d1SKuninori Morimoto * @reg: Register to test 922460b42d1SKuninori Morimoto * @mask: Mask that specifies which bits to test 923460b42d1SKuninori Morimoto * @value: Value to test against 924460b42d1SKuninori Morimoto * 925460b42d1SKuninori Morimoto * Tests a register with a new value and checks if the new value is 926460b42d1SKuninori Morimoto * different from the old value. 927460b42d1SKuninori Morimoto * 928460b42d1SKuninori Morimoto * Return: 1 for change, otherwise 0. 929460b42d1SKuninori Morimoto */ 930460b42d1SKuninori Morimoto int snd_soc_component_test_bits(struct snd_soc_component *component, 931460b42d1SKuninori Morimoto unsigned int reg, unsigned int mask, unsigned int value) 932460b42d1SKuninori Morimoto { 933460b42d1SKuninori Morimoto unsigned int old, new; 934460b42d1SKuninori Morimoto 935cf6e26c7SKuninori Morimoto old = snd_soc_component_read(component, reg); 936460b42d1SKuninori Morimoto new = (old & ~mask) | value; 937460b42d1SKuninori Morimoto return old != new; 938460b42d1SKuninori Morimoto } 939460b42d1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_test_bits); 940460b42d1SKuninori Morimoto 9410035e256SKuninori Morimoto int snd_soc_pcm_component_pointer(struct snd_pcm_substream *substream) 9420035e256SKuninori Morimoto { 9430ceef681SKuninori Morimoto struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 9440035e256SKuninori Morimoto struct snd_soc_component *component; 945613fb500SKuninori Morimoto int i; 9460035e256SKuninori Morimoto 9470035e256SKuninori Morimoto /* FIXME: use 1st pointer */ 948613fb500SKuninori Morimoto for_each_rtd_components(rtd, i, component) 949e2cb4a14SKuninori Morimoto if (component->driver->pointer) 950e2cb4a14SKuninori Morimoto return component->driver->pointer(component, substream); 9510035e256SKuninori Morimoto 9520035e256SKuninori Morimoto return 0; 9530035e256SKuninori Morimoto } 95496a47908SKuninori Morimoto 955232213bdSCharles Keepax static bool snd_soc_component_is_codec_on_rtd(struct snd_soc_pcm_runtime *rtd, 956232213bdSCharles Keepax struct snd_soc_component *component) 957232213bdSCharles Keepax { 958232213bdSCharles Keepax struct snd_soc_dai *dai; 959232213bdSCharles Keepax int i; 960232213bdSCharles Keepax 961232213bdSCharles Keepax for_each_rtd_codec_dais(rtd, i, dai) { 962232213bdSCharles Keepax if (dai->component == component) 963232213bdSCharles Keepax return true; 964232213bdSCharles Keepax } 965232213bdSCharles Keepax 966232213bdSCharles Keepax return false; 967232213bdSCharles Keepax } 968232213bdSCharles Keepax 969403f830eSKuninori Morimoto void snd_soc_pcm_component_delay(struct snd_pcm_substream *substream, 970403f830eSKuninori Morimoto snd_pcm_sframes_t *cpu_delay, 971403f830eSKuninori Morimoto snd_pcm_sframes_t *codec_delay) 972403f830eSKuninori Morimoto { 973403f830eSKuninori Morimoto struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 974403f830eSKuninori Morimoto struct snd_soc_component *component; 975403f830eSKuninori Morimoto snd_pcm_sframes_t delay; 976403f830eSKuninori Morimoto int i; 977403f830eSKuninori Morimoto 978403f830eSKuninori Morimoto /* 979403f830eSKuninori Morimoto * We're looking for the delay through the full audio path so it needs to 980403f830eSKuninori Morimoto * be the maximum of the Components doing transmit and the maximum of the 981403f830eSKuninori Morimoto * Components doing receive (ie, all CPUs and all CODECs) rather than 982403f830eSKuninori Morimoto * just the maximum of all Components. 983403f830eSKuninori Morimoto */ 984403f830eSKuninori Morimoto for_each_rtd_components(rtd, i, component) { 985403f830eSKuninori Morimoto if (!component->driver->delay) 986403f830eSKuninori Morimoto continue; 987403f830eSKuninori Morimoto 988403f830eSKuninori Morimoto delay = component->driver->delay(component, substream); 989403f830eSKuninori Morimoto 990232213bdSCharles Keepax if (snd_soc_component_is_codec_on_rtd(rtd, component)) 991403f830eSKuninori Morimoto *codec_delay = max(*codec_delay, delay); 992403f830eSKuninori Morimoto else 993403f830eSKuninori Morimoto *cpu_delay = max(*cpu_delay, delay); 994403f830eSKuninori Morimoto } 995403f830eSKuninori Morimoto } 996403f830eSKuninori Morimoto 99796a47908SKuninori Morimoto int snd_soc_pcm_component_ioctl(struct snd_pcm_substream *substream, 99896a47908SKuninori Morimoto unsigned int cmd, void *arg) 99996a47908SKuninori Morimoto { 10000ceef681SKuninori Morimoto struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 100196a47908SKuninori Morimoto struct snd_soc_component *component; 1002613fb500SKuninori Morimoto int i; 100396a47908SKuninori Morimoto 100496a47908SKuninori Morimoto /* FIXME: use 1st ioctl */ 1005613fb500SKuninori Morimoto for_each_rtd_components(rtd, i, component) 1006e2cb4a14SKuninori Morimoto if (component->driver->ioctl) 1007e2329eebSKuninori Morimoto return soc_component_ret( 1008e2329eebSKuninori Morimoto component, 1009e2329eebSKuninori Morimoto component->driver->ioctl(component, 1010e2329eebSKuninori Morimoto substream, cmd, arg)); 101196a47908SKuninori Morimoto 101296a47908SKuninori Morimoto return snd_pcm_lib_ioctl(substream, cmd, arg); 101396a47908SKuninori Morimoto } 101482d81f5cSKuninori Morimoto 10151e5ddb6bSTakashi Iwai int snd_soc_pcm_component_sync_stop(struct snd_pcm_substream *substream) 10161e5ddb6bSTakashi Iwai { 10170ceef681SKuninori Morimoto struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 10181e5ddb6bSTakashi Iwai struct snd_soc_component *component; 1019613fb500SKuninori Morimoto int i, ret; 10201e5ddb6bSTakashi Iwai 1021613fb500SKuninori Morimoto for_each_rtd_components(rtd, i, component) { 1022f1861a7cSKuninori Morimoto if (component->driver->sync_stop) { 10231e5ddb6bSTakashi Iwai ret = component->driver->sync_stop(component, 10241e5ddb6bSTakashi Iwai substream); 10251e5ddb6bSTakashi Iwai if (ret < 0) 1026be75db57SShengjiu Wang return soc_component_ret(component, ret); 10271e5ddb6bSTakashi Iwai } 10281e5ddb6bSTakashi Iwai } 10291e5ddb6bSTakashi Iwai 10301e5ddb6bSTakashi Iwai return 0; 10311e5ddb6bSTakashi Iwai } 10321e5ddb6bSTakashi Iwai 103382d81f5cSKuninori Morimoto int snd_soc_pcm_component_copy_user(struct snd_pcm_substream *substream, 103482d81f5cSKuninori Morimoto int channel, unsigned long pos, 103582d81f5cSKuninori Morimoto void __user *buf, unsigned long bytes) 103682d81f5cSKuninori Morimoto { 10370ceef681SKuninori Morimoto struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 103882d81f5cSKuninori Morimoto struct snd_soc_component *component; 1039613fb500SKuninori Morimoto int i; 104082d81f5cSKuninori Morimoto 104182d81f5cSKuninori Morimoto /* FIXME. it returns 1st copy now */ 1042613fb500SKuninori Morimoto for_each_rtd_components(rtd, i, component) 1043e2cb4a14SKuninori Morimoto if (component->driver->copy_user) 1044e2329eebSKuninori Morimoto return soc_component_ret( 1045e2329eebSKuninori Morimoto component, 1046e2329eebSKuninori Morimoto component->driver->copy_user( 1047e2329eebSKuninori Morimoto component, substream, channel, 1048e2329eebSKuninori Morimoto pos, buf, bytes)); 104982d81f5cSKuninori Morimoto 105082d81f5cSKuninori Morimoto return -EINVAL; 105182d81f5cSKuninori Morimoto } 10529c712e4fSKuninori Morimoto 10539c712e4fSKuninori Morimoto struct page *snd_soc_pcm_component_page(struct snd_pcm_substream *substream, 10549c712e4fSKuninori Morimoto unsigned long offset) 10559c712e4fSKuninori Morimoto { 10560ceef681SKuninori Morimoto struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 10579c712e4fSKuninori Morimoto struct snd_soc_component *component; 10589c712e4fSKuninori Morimoto struct page *page; 1059613fb500SKuninori Morimoto int i; 10609c712e4fSKuninori Morimoto 10619c712e4fSKuninori Morimoto /* FIXME. it returns 1st page now */ 1062613fb500SKuninori Morimoto for_each_rtd_components(rtd, i, component) { 1063e2cb4a14SKuninori Morimoto if (component->driver->page) { 1064e2cb4a14SKuninori Morimoto page = component->driver->page(component, 1065e2cb4a14SKuninori Morimoto substream, offset); 1066e2cb4a14SKuninori Morimoto if (page) 1067e2cb4a14SKuninori Morimoto return page; 1068e2cb4a14SKuninori Morimoto } 10699c712e4fSKuninori Morimoto } 10709c712e4fSKuninori Morimoto 10719c712e4fSKuninori Morimoto return NULL; 10729c712e4fSKuninori Morimoto } 1073205875e1SKuninori Morimoto 1074205875e1SKuninori Morimoto int snd_soc_pcm_component_mmap(struct snd_pcm_substream *substream, 1075205875e1SKuninori Morimoto struct vm_area_struct *vma) 1076205875e1SKuninori Morimoto { 10770ceef681SKuninori Morimoto struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 1078205875e1SKuninori Morimoto struct snd_soc_component *component; 1079613fb500SKuninori Morimoto int i; 1080205875e1SKuninori Morimoto 1081205875e1SKuninori Morimoto /* FIXME. it returns 1st mmap now */ 1082613fb500SKuninori Morimoto for_each_rtd_components(rtd, i, component) 1083e2cb4a14SKuninori Morimoto if (component->driver->mmap) 1084be75db57SShengjiu Wang return soc_component_ret( 1085e2329eebSKuninori Morimoto component, 1086e2329eebSKuninori Morimoto component->driver->mmap(component, 1087e2329eebSKuninori Morimoto substream, vma)); 1088205875e1SKuninori Morimoto 1089205875e1SKuninori Morimoto return -EINVAL; 1090205875e1SKuninori Morimoto } 10917484291eSKuninori Morimoto 1092b2b2afbbSKuninori Morimoto int snd_soc_pcm_component_new(struct snd_soc_pcm_runtime *rtd) 10937484291eSKuninori Morimoto { 10947484291eSKuninori Morimoto struct snd_soc_component *component; 10957484291eSKuninori Morimoto int ret; 1096613fb500SKuninori Morimoto int i; 10977484291eSKuninori Morimoto 1098613fb500SKuninori Morimoto for_each_rtd_components(rtd, i, component) { 1099c64bfc90SKuninori Morimoto if (component->driver->pcm_construct) { 1100c64bfc90SKuninori Morimoto ret = component->driver->pcm_construct(component, rtd); 1101c64bfc90SKuninori Morimoto if (ret < 0) 1102be75db57SShengjiu Wang return soc_component_ret(component, ret); 1103c64bfc90SKuninori Morimoto } 11047484291eSKuninori Morimoto } 11057484291eSKuninori Morimoto 11067484291eSKuninori Morimoto return 0; 11077484291eSKuninori Morimoto } 110879776da0SKuninori Morimoto 1109b2b2afbbSKuninori Morimoto void snd_soc_pcm_component_free(struct snd_soc_pcm_runtime *rtd) 111079776da0SKuninori Morimoto { 111179776da0SKuninori Morimoto struct snd_soc_component *component; 1112613fb500SKuninori Morimoto int i; 111379776da0SKuninori Morimoto 11148e3366caSTakashi Iwai if (!rtd->pcm) 11158e3366caSTakashi Iwai return; 11168e3366caSTakashi Iwai 1117613fb500SKuninori Morimoto for_each_rtd_components(rtd, i, component) 1118c64bfc90SKuninori Morimoto if (component->driver->pcm_destruct) 1119b2b2afbbSKuninori Morimoto component->driver->pcm_destruct(component, rtd->pcm); 112079776da0SKuninori Morimoto } 11214f39514fSKuninori Morimoto 11224f39514fSKuninori Morimoto int snd_soc_pcm_component_prepare(struct snd_pcm_substream *substream) 11234f39514fSKuninori Morimoto { 11240ceef681SKuninori Morimoto struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 11254f39514fSKuninori Morimoto struct snd_soc_component *component; 11264f39514fSKuninori Morimoto int i, ret; 11274f39514fSKuninori Morimoto 11284f39514fSKuninori Morimoto for_each_rtd_components(rtd, i, component) { 11294f39514fSKuninori Morimoto if (component->driver->prepare) { 11304f39514fSKuninori Morimoto ret = component->driver->prepare(component, substream); 11314f39514fSKuninori Morimoto if (ret < 0) 11324f39514fSKuninori Morimoto return soc_component_ret(component, ret); 11334f39514fSKuninori Morimoto } 11344f39514fSKuninori Morimoto } 11354f39514fSKuninori Morimoto 11364f39514fSKuninori Morimoto return 0; 11374f39514fSKuninori Morimoto } 1138e1bafa82SKuninori Morimoto 1139e1bafa82SKuninori Morimoto int snd_soc_pcm_component_hw_params(struct snd_pcm_substream *substream, 11403a36a64aSKuninori Morimoto struct snd_pcm_hw_params *params) 1141e1bafa82SKuninori Morimoto { 11420ceef681SKuninori Morimoto struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 1143e1bafa82SKuninori Morimoto struct snd_soc_component *component; 1144e1bafa82SKuninori Morimoto int i, ret; 1145e1bafa82SKuninori Morimoto 1146e1bafa82SKuninori Morimoto for_each_rtd_components(rtd, i, component) { 1147e1bafa82SKuninori Morimoto if (component->driver->hw_params) { 1148e1bafa82SKuninori Morimoto ret = component->driver->hw_params(component, 1149e1bafa82SKuninori Morimoto substream, params); 11503a36a64aSKuninori Morimoto if (ret < 0) 1151e1bafa82SKuninori Morimoto return soc_component_ret(component, ret); 1152e1bafa82SKuninori Morimoto } 11533a36a64aSKuninori Morimoto /* mark substream if succeeded */ 11543a36a64aSKuninori Morimoto soc_component_mark_push(component, substream, hw_params); 1155e1bafa82SKuninori Morimoto } 1156e1bafa82SKuninori Morimoto 1157e1bafa82SKuninori Morimoto return 0; 1158e1bafa82SKuninori Morimoto } 115904751119SKuninori Morimoto 116004751119SKuninori Morimoto void snd_soc_pcm_component_hw_free(struct snd_pcm_substream *substream, 11613a36a64aSKuninori Morimoto int rollback) 116204751119SKuninori Morimoto { 11630ceef681SKuninori Morimoto struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 116404751119SKuninori Morimoto struct snd_soc_component *component; 116504751119SKuninori Morimoto int i, ret; 116604751119SKuninori Morimoto 116704751119SKuninori Morimoto for_each_rtd_components(rtd, i, component) { 11683a36a64aSKuninori Morimoto if (rollback && !soc_component_mark_match(component, substream, hw_params)) 11693a36a64aSKuninori Morimoto continue; 117004751119SKuninori Morimoto 117104751119SKuninori Morimoto if (component->driver->hw_free) { 117204751119SKuninori Morimoto ret = component->driver->hw_free(component, substream); 117304751119SKuninori Morimoto if (ret < 0) 117404751119SKuninori Morimoto soc_component_ret(component, ret); 117504751119SKuninori Morimoto } 11763a36a64aSKuninori Morimoto 11773a36a64aSKuninori Morimoto /* remove marked substream */ 11783a36a64aSKuninori Morimoto soc_component_mark_pop(component, substream, hw_params); 117904751119SKuninori Morimoto } 118004751119SKuninori Morimoto } 118132fd1204SKuninori Morimoto 11826374f493SKuninori Morimoto static int soc_component_trigger(struct snd_soc_component *component, 11836374f493SKuninori Morimoto struct snd_pcm_substream *substream, 118432fd1204SKuninori Morimoto int cmd) 118532fd1204SKuninori Morimoto { 11866374f493SKuninori Morimoto int ret = 0; 11876374f493SKuninori Morimoto 11886374f493SKuninori Morimoto if (component->driver->trigger) 11896374f493SKuninori Morimoto ret = component->driver->trigger(component, substream, cmd); 11906374f493SKuninori Morimoto 11916374f493SKuninori Morimoto return soc_component_ret(component, ret); 11926374f493SKuninori Morimoto } 11936374f493SKuninori Morimoto 11946374f493SKuninori Morimoto int snd_soc_pcm_component_trigger(struct snd_pcm_substream *substream, 11956374f493SKuninori Morimoto int cmd, int rollback) 11966374f493SKuninori Morimoto { 11970ceef681SKuninori Morimoto struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 119832fd1204SKuninori Morimoto struct snd_soc_component *component; 11996374f493SKuninori Morimoto int i, r, ret = 0; 120032fd1204SKuninori Morimoto 12016374f493SKuninori Morimoto switch (cmd) { 12026374f493SKuninori Morimoto case SNDRV_PCM_TRIGGER_START: 12036374f493SKuninori Morimoto case SNDRV_PCM_TRIGGER_RESUME: 12046374f493SKuninori Morimoto case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 120532fd1204SKuninori Morimoto for_each_rtd_components(rtd, i, component) { 12066374f493SKuninori Morimoto ret = soc_component_trigger(component, substream, cmd); 120732fd1204SKuninori Morimoto if (ret < 0) 12086374f493SKuninori Morimoto break; 12096374f493SKuninori Morimoto soc_component_mark_push(component, substream, trigger); 12106374f493SKuninori Morimoto } 12116374f493SKuninori Morimoto break; 12126374f493SKuninori Morimoto case SNDRV_PCM_TRIGGER_STOP: 12136374f493SKuninori Morimoto case SNDRV_PCM_TRIGGER_SUSPEND: 12146374f493SKuninori Morimoto case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 12156374f493SKuninori Morimoto for_each_rtd_components(rtd, i, component) { 12166374f493SKuninori Morimoto if (rollback && !soc_component_mark_match(component, substream, trigger)) 12176374f493SKuninori Morimoto continue; 12186374f493SKuninori Morimoto 12196374f493SKuninori Morimoto r = soc_component_trigger(component, substream, cmd); 12206374f493SKuninori Morimoto if (r < 0) 12216374f493SKuninori Morimoto ret = r; /* use last ret */ 12226374f493SKuninori Morimoto soc_component_mark_pop(component, substream, trigger); 122332fd1204SKuninori Morimoto } 122432fd1204SKuninori Morimoto } 122532fd1204SKuninori Morimoto 12266374f493SKuninori Morimoto return ret; 122732fd1204SKuninori Morimoto } 1228939a5cfbSKuninori Morimoto 1229939a5cfbSKuninori Morimoto int snd_soc_pcm_component_pm_runtime_get(struct snd_soc_pcm_runtime *rtd, 1230939a5cfbSKuninori Morimoto void *stream) 1231939a5cfbSKuninori Morimoto { 1232939a5cfbSKuninori Morimoto struct snd_soc_component *component; 1233500b39daSKuninori Morimoto int i; 1234939a5cfbSKuninori Morimoto 1235939a5cfbSKuninori Morimoto for_each_rtd_components(rtd, i, component) { 12360c72dbc9SPeter Ujfalusi int ret = pm_runtime_get_sync(component->dev); 12370c72dbc9SPeter Ujfalusi if (ret < 0 && ret != -EACCES) { 12380c72dbc9SPeter Ujfalusi pm_runtime_put_noidle(component->dev); 1239939a5cfbSKuninori Morimoto return soc_component_ret(component, ret); 12400c72dbc9SPeter Ujfalusi } 1241939a5cfbSKuninori Morimoto /* mark stream if succeeded */ 1242939a5cfbSKuninori Morimoto soc_component_mark_push(component, stream, pm); 1243939a5cfbSKuninori Morimoto } 1244939a5cfbSKuninori Morimoto 1245939a5cfbSKuninori Morimoto return 0; 1246939a5cfbSKuninori Morimoto } 1247939a5cfbSKuninori Morimoto 1248939a5cfbSKuninori Morimoto void snd_soc_pcm_component_pm_runtime_put(struct snd_soc_pcm_runtime *rtd, 1249939a5cfbSKuninori Morimoto void *stream, int rollback) 1250939a5cfbSKuninori Morimoto { 1251939a5cfbSKuninori Morimoto struct snd_soc_component *component; 1252939a5cfbSKuninori Morimoto int i; 1253939a5cfbSKuninori Morimoto 1254939a5cfbSKuninori Morimoto for_each_rtd_components(rtd, i, component) { 1255939a5cfbSKuninori Morimoto if (rollback && !soc_component_mark_match(component, stream, pm)) 1256939a5cfbSKuninori Morimoto continue; 1257939a5cfbSKuninori Morimoto 1258939a5cfbSKuninori Morimoto pm_runtime_mark_last_busy(component->dev); 1259939a5cfbSKuninori Morimoto pm_runtime_put_autosuspend(component->dev); 1260939a5cfbSKuninori Morimoto 1261939a5cfbSKuninori Morimoto /* remove marked stream */ 1262939a5cfbSKuninori Morimoto soc_component_mark_pop(component, stream, pm); 1263939a5cfbSKuninori Morimoto } 1264939a5cfbSKuninori Morimoto } 12658bdfc045SShengjiu Wang 12668bdfc045SShengjiu Wang int snd_soc_pcm_component_ack(struct snd_pcm_substream *substream) 12678bdfc045SShengjiu Wang { 12688bdfc045SShengjiu Wang struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 12698bdfc045SShengjiu Wang struct snd_soc_component *component; 12708bdfc045SShengjiu Wang int i; 12718bdfc045SShengjiu Wang 12728bdfc045SShengjiu Wang /* FIXME: use 1st pointer */ 12738bdfc045SShengjiu Wang for_each_rtd_components(rtd, i, component) 12748bdfc045SShengjiu Wang if (component->driver->ack) 12758bdfc045SShengjiu Wang return component->driver->ack(component, substream); 12768bdfc045SShengjiu Wang 12778bdfc045SShengjiu Wang return 0; 12788bdfc045SShengjiu Wang } 1279