diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-01-17 20:05:31 (GMT) |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-01-17 20:05:31 (GMT) |
commit | a016af2e70bfca23f2f5de7d8708157b86ea374d (patch) | |
tree | bfe3c0c6ea9d52d4ec6ea021b0626a53c83e7d9f /sound/soc/intel/skylake/skl-messages.c | |
parent | e535d74bc50df2357d3253f8f3ca48c66d0d892a (diff) | |
parent | c3b1681375dc6e71d89a3ae00cc3ce9e775a8917 (diff) | |
download | linux-a016af2e70bfca23f2f5de7d8708157b86ea374d.tar.xz |
Merge tag 'sound-4.5-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound
Pull sound updates from Takashi Iwai:
"We've had quite busy weeks in this cycle. Looking at ALSA core, the
significant changes are a few fixes wrt timer and sequencer ioctls
that have been revealed by fuzzer recently. Other than that, ASoC
core got a few updates about DAI link handling, but these are rather
straightforward refactoring.
In drivers scene, ASoC received quite lots of new drivers in addition
to bunch of updates for still ongoing Intel Skylake support and
topology API. HD-audio gained a new HDMI/DP hotplug notification via
component. FireWire got a pile of code refactoring/updates with
SCS.1x driver integration.
More highlights are shown below.
[ NOTE: this contains also many commits for DRM. This is due to the
pull of drm stable branch into sound tree, as the base of i915 audio
component work for HD-audio. The highlights below don't contain
these DRM changes, as these are supposed to be pulled via drm tree
in anyway sooner or later. ]
Core:
- Handful fixes to harden ALSA timer and sequencer ioctls against
races reported by syzkaller fuzzer
- Irq description string can be unique to each card; only for
HD-audio for now
ASoC:
- Conversion of the array of DAI links to a list for supporting
dynamically adding and removing DAI links
- Topology API enhancements to make everything more component based
and being able to specify PCM links via topology
- Some more fixes for the topology code, though it is still not final
and ready for enabling in production; we really need to get to the
point where that can be done
- A pile of changes for Intel SkyLake drivers which hopefully deliver
some useful initial functionality for systems with this chipset,
though there is more work still to come
- Lots of new features and cleanups for the Renesas drivers
- ANC support for WM5110
- New drivers: Imagination Technologies IPs, Atmel class D speaker,
Cirrus CS47L24 and WM1831, Dialog DA7128, Realtek RT5659 and
RT56156, Rockchip RK3036, TI PC3168A, and AMD ACP
- Rename PCM1792a driver to be generic pcm179x
HD-Audio:
- Use audio component for i915 HDMI/DP hotplug handling
- On-demand binding with i915 driver
- bdl_pos_adj parameter adjustment for Baytrail controllers
- Enable power_save_node for CX20722; this shouldn't lead to
regression, hopefully
- Kabylake HDMI/DP codec support
- Quirks for Lenovo E50-80, Dell Latitude E-series, and other Dell
machines
- A few code refactoring
FireWire:
- Lots of code cleanup and refactoring
- Integrate the support of SCS.1x devices into snd-oxfw driver;
snd-scs1x driver is obsoleted
USB-audio:
- Fix possible NULL dereference at disconnection
- A regression fix for Native Instruments devices
Misc:
- A few code cleanups of fm801 driver"
* tag 'sound-4.5-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (722 commits)
ALSA: timer: Code cleanup
ALSA: timer: Harden slave timer list handling
ALSA: hda - Add fixup for Dell Latitidue E6540
ALSA: timer: Fix race among timer ioctls
ALSA: hda - add codec support for Kabylake display audio codec
ALSA: timer: Fix double unlink of active_list
ALSA: usb-audio: Fix mixer ctl regression of Native Instrument devices
ALSA: hda - fix the headset mic detection problem for a Dell laptop
ALSA: hda - Fix white noise on Dell Latitude E5550
ALSA: hda_intel: add card number to irq description
ALSA: seq: Fix race at timer setup and close
ALSA: seq: Fix missing NULL check at remove_events ioctl
ALSA: usb-audio: Avoid calling usb_autopm_put_interface() at disconnect
ASoC: hdac_hdmi: remove unused hdac_hdmi_query_pin_connlist
ASoC: AMD: Add missing include file
ALSA: hda - Fixup inverted internal mic for Lenovo E50-80
ALSA: usb: Add native DSD support for Oppo HA-1
ASoC: Make aux_dev more like a generic component
ASoC: bcm2835: cleanup includes by ordering them alphabetically
ASoC: AMD: Manage ACP 2.x SRAM banks power
...
Diffstat (limited to 'sound/soc/intel/skylake/skl-messages.c')
-rw-r--r-- | sound/soc/intel/skylake/skl-messages.c | 280 |
1 files changed, 153 insertions, 127 deletions
diff --git a/sound/soc/intel/skylake/skl-messages.c b/sound/soc/intel/skylake/skl-messages.c index 50a1095..de6dac4 100644 --- a/sound/soc/intel/skylake/skl-messages.c +++ b/sound/soc/intel/skylake/skl-messages.c @@ -96,7 +96,7 @@ int skl_init_dsp(struct skl *skl) } ret = skl_sst_dsp_init(bus->dev, mmio_base, irq, - loader_ops, &skl->skl_sst); + skl->fw_name, loader_ops, &skl->skl_sst); if (ret < 0) return ret; @@ -182,94 +182,6 @@ enum skl_bitdepth skl_get_bit_depth(int params) } } -static u32 skl_create_channel_map(enum skl_ch_cfg ch_cfg) -{ - u32 config; - - switch (ch_cfg) { - case SKL_CH_CFG_MONO: - config = (0xFFFFFFF0 | SKL_CHANNEL_LEFT); - break; - - case SKL_CH_CFG_STEREO: - config = (0xFFFFFF00 | SKL_CHANNEL_LEFT - | (SKL_CHANNEL_RIGHT << 4)); - break; - - case SKL_CH_CFG_2_1: - config = (0xFFFFF000 | SKL_CHANNEL_LEFT - | (SKL_CHANNEL_RIGHT << 4) - | (SKL_CHANNEL_LFE << 8)); - break; - - case SKL_CH_CFG_3_0: - config = (0xFFFFF000 | SKL_CHANNEL_LEFT - | (SKL_CHANNEL_CENTER << 4) - | (SKL_CHANNEL_RIGHT << 8)); - break; - - case SKL_CH_CFG_3_1: - config = (0xFFFF0000 | SKL_CHANNEL_LEFT - | (SKL_CHANNEL_CENTER << 4) - | (SKL_CHANNEL_RIGHT << 8) - | (SKL_CHANNEL_LFE << 12)); - break; - - case SKL_CH_CFG_QUATRO: - config = (0xFFFF0000 | SKL_CHANNEL_LEFT - | (SKL_CHANNEL_RIGHT << 4) - | (SKL_CHANNEL_LEFT_SURROUND << 8) - | (SKL_CHANNEL_RIGHT_SURROUND << 12)); - break; - - case SKL_CH_CFG_4_0: - config = (0xFFFF0000 | SKL_CHANNEL_LEFT - | (SKL_CHANNEL_CENTER << 4) - | (SKL_CHANNEL_RIGHT << 8) - | (SKL_CHANNEL_CENTER_SURROUND << 12)); - break; - - case SKL_CH_CFG_5_0: - config = (0xFFF00000 | SKL_CHANNEL_LEFT - | (SKL_CHANNEL_CENTER << 4) - | (SKL_CHANNEL_RIGHT << 8) - | (SKL_CHANNEL_LEFT_SURROUND << 12) - | (SKL_CHANNEL_RIGHT_SURROUND << 16)); - break; - - case SKL_CH_CFG_5_1: - config = (0xFF000000 | SKL_CHANNEL_CENTER - | (SKL_CHANNEL_LEFT << 4) - | (SKL_CHANNEL_RIGHT << 8) - | (SKL_CHANNEL_LEFT_SURROUND << 12) - | (SKL_CHANNEL_RIGHT_SURROUND << 16) - | (SKL_CHANNEL_LFE << 20)); - break; - - case SKL_CH_CFG_DUAL_MONO: - config = (0xFFFFFF00 | SKL_CHANNEL_LEFT - | (SKL_CHANNEL_LEFT << 4)); - break; - - case SKL_CH_CFG_I2S_DUAL_STEREO_0: - config = (0xFFFFFF00 | SKL_CHANNEL_LEFT - | (SKL_CHANNEL_RIGHT << 4)); - break; - - case SKL_CH_CFG_I2S_DUAL_STEREO_1: - config = (0xFFFF00FF | (SKL_CHANNEL_LEFT << 8) - | (SKL_CHANNEL_RIGHT << 12)); - break; - - default: - config = 0xFFFFFFFF; - break; - - } - - return config; -} - /* * Each module in DSP expects a base module configuration, which consists of * PCM format information, which we calculate in driver and resource values @@ -280,7 +192,7 @@ static void skl_set_base_module_format(struct skl_sst *ctx, struct skl_module_cfg *mconfig, struct skl_base_cfg *base_cfg) { - struct skl_module_fmt *format = &mconfig->in_fmt; + struct skl_module_fmt *format = &mconfig->in_fmt[0]; base_cfg->audio_fmt.number_of_channels = (u8)format->channels; @@ -293,14 +205,14 @@ static void skl_set_base_module_format(struct skl_sst *ctx, format->bit_depth, format->valid_bit_depth, format->ch_cfg); - base_cfg->audio_fmt.channel_map = skl_create_channel_map( - base_cfg->audio_fmt.ch_cfg); + base_cfg->audio_fmt.channel_map = format->ch_map; - base_cfg->audio_fmt.interleaving = SKL_INTERLEAVING_PER_CHANNEL; + base_cfg->audio_fmt.interleaving = format->interleaving_style; base_cfg->cps = mconfig->mcps; base_cfg->ibs = mconfig->ibs; base_cfg->obs = mconfig->obs; + base_cfg->is_pages = mconfig->mem_pages; } /* @@ -399,7 +311,7 @@ static void skl_setup_out_format(struct skl_sst *ctx, struct skl_module_cfg *mconfig, struct skl_audio_data_format *out_fmt) { - struct skl_module_fmt *format = &mconfig->out_fmt; + struct skl_module_fmt *format = &mconfig->out_fmt[0]; out_fmt->number_of_channels = (u8)format->channels; out_fmt->s_freq = format->s_freq; @@ -407,8 +319,9 @@ static void skl_setup_out_format(struct skl_sst *ctx, out_fmt->valid_bit_depth = format->valid_bit_depth; out_fmt->ch_cfg = format->ch_cfg; - out_fmt->channel_map = skl_create_channel_map(out_fmt->ch_cfg); - out_fmt->interleaving = SKL_INTERLEAVING_PER_CHANNEL; + out_fmt->channel_map = format->ch_map; + out_fmt->interleaving = format->interleaving_style; + out_fmt->sample_type = format->sample_type; dev_dbg(ctx->dev, "copier out format chan=%d fre=%d bitdepth=%d\n", out_fmt->number_of_channels, format->s_freq, format->bit_depth); @@ -423,7 +336,7 @@ static void skl_set_src_format(struct skl_sst *ctx, struct skl_module_cfg *mconfig, struct skl_src_module_cfg *src_mconfig) { - struct skl_module_fmt *fmt = &mconfig->out_fmt; + struct skl_module_fmt *fmt = &mconfig->out_fmt[0]; skl_set_base_module_format(ctx, mconfig, (struct skl_base_cfg *)src_mconfig); @@ -440,7 +353,7 @@ static void skl_set_updown_mixer_format(struct skl_sst *ctx, struct skl_module_cfg *mconfig, struct skl_up_down_mixer_cfg *mixer_mconfig) { - struct skl_module_fmt *fmt = &mconfig->out_fmt; + struct skl_module_fmt *fmt = &mconfig->out_fmt[0]; int i = 0; skl_set_base_module_format(ctx, mconfig, @@ -475,6 +388,47 @@ static void skl_set_copier_format(struct skl_sst *ctx, skl_setup_cpr_gateway_cfg(ctx, mconfig, cpr_mconfig); } +/* + * Algo module are DSP pre processing modules. Algo module take base module + * configuration and params + */ + +static void skl_set_algo_format(struct skl_sst *ctx, + struct skl_module_cfg *mconfig, + struct skl_algo_cfg *algo_mcfg) +{ + struct skl_base_cfg *base_cfg = (struct skl_base_cfg *)algo_mcfg; + + skl_set_base_module_format(ctx, mconfig, base_cfg); + + if (mconfig->formats_config.caps_size == 0) + return; + + memcpy(algo_mcfg->params, + mconfig->formats_config.caps, + mconfig->formats_config.caps_size); + +} + +/* + * Mic select module allows selecting one or many input channels, thus + * acting as a demux. + * + * Mic select module take base module configuration and out-format + * configuration + */ +static void skl_set_base_outfmt_format(struct skl_sst *ctx, + struct skl_module_cfg *mconfig, + struct skl_base_outfmt_cfg *base_outfmt_mcfg) +{ + struct skl_audio_data_format *out_fmt = &base_outfmt_mcfg->out_fmt; + struct skl_base_cfg *base_cfg = + (struct skl_base_cfg *)base_outfmt_mcfg; + + skl_set_base_module_format(ctx, mconfig, base_cfg); + skl_setup_out_format(ctx, mconfig, out_fmt); +} + static u16 skl_get_module_param_size(struct skl_sst *ctx, struct skl_module_cfg *mconfig) { @@ -492,6 +446,14 @@ static u16 skl_get_module_param_size(struct skl_sst *ctx, case SKL_MODULE_TYPE_UPDWMIX: return sizeof(struct skl_up_down_mixer_cfg); + case SKL_MODULE_TYPE_ALGO: + param_size = sizeof(struct skl_base_cfg); + param_size += mconfig->formats_config.caps_size; + return param_size; + + case SKL_MODULE_TYPE_BASE_OUTFMT: + return sizeof(struct skl_base_outfmt_cfg); + default: /* * return only base cfg when no specific module type is @@ -538,6 +500,14 @@ static int skl_set_module_format(struct skl_sst *ctx, skl_set_updown_mixer_format(ctx, module_config, *param_data); break; + case SKL_MODULE_TYPE_ALGO: + skl_set_algo_format(ctx, module_config, *param_data); + break; + + case SKL_MODULE_TYPE_BASE_OUTFMT: + skl_set_base_outfmt_format(ctx, module_config, *param_data); + break; + default: skl_set_base_module_format(ctx, module_config, *param_data); break; @@ -571,10 +541,10 @@ static int skl_get_queue_index(struct skl_module_pin *mpin, * In static, the pin_index is fixed based on module_id and instance id */ static int skl_alloc_queue(struct skl_module_pin *mpin, - struct skl_module_inst_id id, int max) + struct skl_module_cfg *tgt_cfg, int max) { int i; - + struct skl_module_inst_id id = tgt_cfg->id; /* * if pin in dynamic, find first free pin * otherwise find match module and instance id pin as topology will @@ -583,16 +553,23 @@ static int skl_alloc_queue(struct skl_module_pin *mpin, */ for (i = 0; i < max; i++) { if (mpin[i].is_dynamic) { - if (!mpin[i].in_use) { + if (!mpin[i].in_use && + mpin[i].pin_state == SKL_PIN_UNBIND) { + mpin[i].in_use = true; mpin[i].id.module_id = id.module_id; mpin[i].id.instance_id = id.instance_id; + mpin[i].tgt_mcfg = tgt_cfg; return i; } } else { if (mpin[i].id.module_id == id.module_id && - mpin[i].id.instance_id == id.instance_id) + mpin[i].id.instance_id == id.instance_id && + mpin[i].pin_state == SKL_PIN_UNBIND) { + + mpin[i].tgt_mcfg = tgt_cfg; return i; + } } } @@ -606,6 +583,28 @@ static void skl_free_queue(struct skl_module_pin *mpin, int q_index) mpin[q_index].id.module_id = 0; mpin[q_index].id.instance_id = 0; } + mpin[q_index].pin_state = SKL_PIN_UNBIND; + mpin[q_index].tgt_mcfg = NULL; +} + +/* Module state will be set to unint, if all the out pin state is UNBIND */ + +static void skl_clear_module_state(struct skl_module_pin *mpin, int max, + struct skl_module_cfg *mcfg) +{ + int i; + bool found = false; + + for (i = 0; i < max; i++) { + if (mpin[i].pin_state == SKL_PIN_UNBIND) + continue; + found = true; + break; + } + + if (!found) + mcfg->m_state = SKL_MODULE_UNINIT; + return; } /* @@ -615,7 +614,7 @@ static void skl_free_queue(struct skl_module_pin *mpin, int q_index) * invoke the DSP by sending IPC INIT_INSTANCE using ipc helper */ int skl_init_module(struct skl_sst *ctx, - struct skl_module_cfg *mconfig, char *param) + struct skl_module_cfg *mconfig) { u16 module_config_size = 0; void *param_data = NULL; @@ -682,37 +681,30 @@ int skl_unbind_modules(struct skl_sst *ctx, struct skl_module_inst_id dst_id = dst_mcfg->id; int in_max = dst_mcfg->max_in_queue; int out_max = src_mcfg->max_out_queue; - int src_index, dst_index; + int src_index, dst_index, src_pin_state, dst_pin_state; skl_dump_bind_info(ctx, src_mcfg, dst_mcfg); - if (src_mcfg->m_state != SKL_MODULE_BIND_DONE) - return 0; - - /* - * if intra module unbind, check if both modules are BIND, - * then send unbind - */ - if ((src_mcfg->pipe->ppl_id != dst_mcfg->pipe->ppl_id) && - dst_mcfg->m_state != SKL_MODULE_BIND_DONE) - return 0; - else if (src_mcfg->m_state < SKL_MODULE_INIT_DONE && - dst_mcfg->m_state < SKL_MODULE_INIT_DONE) - return 0; - /* get src queue index */ src_index = skl_get_queue_index(src_mcfg->m_out_pin, dst_id, out_max); if (src_index < 0) return -EINVAL; - msg.src_queue = src_mcfg->m_out_pin[src_index].pin_index; + msg.src_queue = src_index; /* get dst queue index */ dst_index = skl_get_queue_index(dst_mcfg->m_in_pin, src_id, in_max); if (dst_index < 0) return -EINVAL; - msg.dst_queue = dst_mcfg->m_in_pin[dst_index].pin_index; + msg.dst_queue = dst_index; + + src_pin_state = src_mcfg->m_out_pin[src_index].pin_state; + dst_pin_state = dst_mcfg->m_in_pin[dst_index].pin_state; + + if (src_pin_state != SKL_PIN_BIND_DONE || + dst_pin_state != SKL_PIN_BIND_DONE) + return 0; msg.module_id = src_mcfg->id.module_id; msg.instance_id = src_mcfg->id.instance_id; @@ -722,10 +714,15 @@ int skl_unbind_modules(struct skl_sst *ctx, ret = skl_ipc_bind_unbind(&ctx->ipc, &msg); if (!ret) { - src_mcfg->m_state = SKL_MODULE_UNINIT; /* free queue only if unbind is success */ skl_free_queue(src_mcfg->m_out_pin, src_index); skl_free_queue(dst_mcfg->m_in_pin, dst_index); + + /* + * check only if src module bind state, bind is + * always from src -> sink + */ + skl_clear_module_state(src_mcfg->m_out_pin, out_max, src_mcfg); } return ret; @@ -744,8 +741,6 @@ int skl_bind_modules(struct skl_sst *ctx, { int ret; struct skl_ipc_bind_unbind_msg msg; - struct skl_module_inst_id src_id = src_mcfg->id; - struct skl_module_inst_id dst_id = dst_mcfg->id; int in_max = dst_mcfg->max_in_queue; int out_max = src_mcfg->max_out_queue; int src_index, dst_index; @@ -756,18 +751,18 @@ int skl_bind_modules(struct skl_sst *ctx, dst_mcfg->m_state < SKL_MODULE_INIT_DONE) return 0; - src_index = skl_alloc_queue(src_mcfg->m_out_pin, dst_id, out_max); + src_index = skl_alloc_queue(src_mcfg->m_out_pin, dst_mcfg, out_max); if (src_index < 0) return -EINVAL; - msg.src_queue = src_mcfg->m_out_pin[src_index].pin_index; - dst_index = skl_alloc_queue(dst_mcfg->m_in_pin, src_id, in_max); + msg.src_queue = src_index; + dst_index = skl_alloc_queue(dst_mcfg->m_in_pin, src_mcfg, in_max); if (dst_index < 0) { skl_free_queue(src_mcfg->m_out_pin, src_index); return -EINVAL; } - msg.dst_queue = dst_mcfg->m_in_pin[dst_index].pin_index; + msg.dst_queue = dst_index; dev_dbg(ctx->dev, "src queue = %d dst queue =%d\n", msg.src_queue, msg.dst_queue); @@ -782,6 +777,8 @@ int skl_bind_modules(struct skl_sst *ctx, if (!ret) { src_mcfg->m_state = SKL_MODULE_BIND_DONE; + src_mcfg->m_out_pin[src_index].pin_state = SKL_PIN_BIND_DONE; + dst_mcfg->m_in_pin[dst_index].pin_state = SKL_PIN_BIND_DONE; } else { /* error case , if IPC fails, clear the queue index */ skl_free_queue(src_mcfg->m_out_pin, src_index); @@ -852,6 +849,8 @@ int skl_delete_pipe(struct skl_sst *ctx, struct skl_pipe *pipe) ret = skl_ipc_delete_pipeline(&ctx->ipc, pipe->ppl_id); if (ret < 0) dev_err(ctx->dev, "Failed to delete pipeline\n"); + + pipe->state = SKL_PIPE_INVALID; } return ret; @@ -916,3 +915,30 @@ int skl_stop_pipe(struct skl_sst *ctx, struct skl_pipe *pipe) return 0; } + +/* Algo parameter set helper function */ +int skl_set_module_params(struct skl_sst *ctx, u32 *params, int size, + u32 param_id, struct skl_module_cfg *mcfg) +{ + struct skl_ipc_large_config_msg msg; + + msg.module_id = mcfg->id.module_id; + msg.instance_id = mcfg->id.instance_id; + msg.param_data_size = size; + msg.large_param_id = param_id; + + return skl_ipc_set_large_config(&ctx->ipc, &msg, params); +} + +int skl_get_module_params(struct skl_sst *ctx, u32 *params, int size, + u32 param_id, struct skl_module_cfg *mcfg) +{ + struct skl_ipc_large_config_msg msg; + + msg.module_id = mcfg->id.module_id; + msg.instance_id = mcfg->id.instance_id; + msg.param_data_size = size; + msg.large_param_id = param_id; + + return skl_ipc_get_large_config(&ctx->ipc, &msg, params); +} |