Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

ASoC: qcom: audioreach: add compress offload

Merge series from Srinivas Kandagatla <srinivas.kandagatla@linaro.org>:

This patchset adds compressed offload support to Qualcomm audioreach drivers.
Currently it supports AAC, MP3 and FALC along with gapless.

Tested this on SM8450 and sc7280.

+745 -94
+154 -92
sound/soc/qcom/qdsp6/audioreach.c
··· 732 732 return rc; 733 733 } 734 734 735 - static int audioreach_sal_limiter_enable(struct q6apm_graph *graph, 736 - struct audioreach_module *module, bool enable) 735 + int audioreach_send_u32_param(struct q6apm_graph *graph, struct audioreach_module *module, 736 + uint32_t param_id, uint32_t param_val) 737 737 { 738 738 struct apm_module_param_data *param_data; 739 - struct param_id_sal_limiter_enable *limiter_enable; 740 - int payload_size; 741 739 struct gpr_pkt *pkt; 742 - int rc; 740 + uint32_t *param; 741 + int rc, payload_size; 743 742 void *p; 744 743 745 - payload_size = sizeof(*limiter_enable) + APM_MODULE_PARAM_DATA_SIZE; 744 + payload_size = sizeof(uint32_t) + APM_MODULE_PARAM_DATA_SIZE; 745 + p = audioreach_alloc_apm_cmd_pkt(payload_size, APM_CMD_SET_CFG, 0); 746 + if (IS_ERR(p)) 747 + return -ENOMEM; 746 748 747 - pkt = audioreach_alloc_apm_cmd_pkt(payload_size, APM_CMD_SET_CFG, 0); 748 - if (IS_ERR(pkt)) 749 - return PTR_ERR(pkt); 750 - 751 - p = (void *)pkt + GPR_HDR_SIZE + APM_CMD_HDR_SIZE; 749 + pkt = p; 750 + p = p + GPR_HDR_SIZE + APM_CMD_HDR_SIZE; 752 751 753 752 param_data = p; 754 753 param_data->module_instance_id = module->instance_id; 755 754 param_data->error_code = 0; 756 - param_data->param_id = PARAM_ID_SAL_LIMITER_ENABLE; 757 - param_data->param_size = sizeof(*limiter_enable); 758 - p = p + APM_MODULE_PARAM_DATA_SIZE; 759 - limiter_enable = p; 755 + param_data->param_id = param_id; 756 + param_data->param_size = sizeof(uint32_t); 760 757 761 - limiter_enable->enable_lim = enable; 758 + p = p + APM_MODULE_PARAM_DATA_SIZE; 759 + param = p; 760 + *param = param_val; 762 761 763 762 rc = q6apm_send_cmd_sync(graph->apm, pkt, 0); 764 763 765 764 kfree(pkt); 766 765 767 766 return rc; 767 + } 768 + EXPORT_SYMBOL_GPL(audioreach_send_u32_param); 769 + 770 + static int audioreach_sal_limiter_enable(struct q6apm_graph *graph, 771 + struct audioreach_module *module, bool enable) 772 + { 773 + return audioreach_send_u32_param(graph, module, PARAM_ID_SAL_LIMITER_ENABLE, enable); 768 774 } 769 775 770 776 static int audioreach_sal_set_media_format(struct q6apm_graph *graph, 771 777 struct audioreach_module *module, 772 778 struct audioreach_module_config *cfg) 773 779 { 774 - struct apm_module_param_data *param_data; 775 - struct param_id_sal_output_config *media_format; 776 - int payload_size; 777 - struct gpr_pkt *pkt; 778 - int rc; 779 - void *p; 780 - 781 - payload_size = sizeof(*media_format) + APM_MODULE_PARAM_DATA_SIZE; 782 - 783 - pkt = audioreach_alloc_apm_cmd_pkt(payload_size, APM_CMD_SET_CFG, 0); 784 - if (IS_ERR(pkt)) 785 - return PTR_ERR(pkt); 786 - 787 - p = (void *)pkt + GPR_HDR_SIZE + APM_CMD_HDR_SIZE; 788 - 789 - param_data = p; 790 - param_data->module_instance_id = module->instance_id; 791 - param_data->error_code = 0; 792 - param_data->param_id = PARAM_ID_SAL_OUTPUT_CFG; 793 - param_data->param_size = sizeof(*media_format); 794 - p = p + APM_MODULE_PARAM_DATA_SIZE; 795 - media_format = p; 796 - 797 - media_format->bits_per_sample = cfg->bit_width; 798 - 799 - rc = q6apm_send_cmd_sync(graph->apm, pkt, 0); 800 - 801 - kfree(pkt); 802 - 803 - return rc; 780 + return audioreach_send_u32_param(graph, module, PARAM_ID_SAL_OUTPUT_CFG, cfg->bit_width); 804 781 } 805 782 806 783 static int audioreach_module_enable(struct q6apm_graph *graph, 807 784 struct audioreach_module *module, 808 785 bool enable) 809 786 { 810 - struct apm_module_param_data *param_data; 811 - struct param_id_module_enable *param; 812 - int payload_size; 813 - struct gpr_pkt *pkt; 814 - int rc; 815 - void *p; 787 + return audioreach_send_u32_param(graph, module, PARAM_ID_MODULE_ENABLE, enable); 788 + } 816 789 817 - payload_size = sizeof(*param) + APM_MODULE_PARAM_DATA_SIZE; 818 - 819 - pkt = audioreach_alloc_apm_cmd_pkt(payload_size, APM_CMD_SET_CFG, 0); 820 - if (IS_ERR(pkt)) 821 - return PTR_ERR(pkt); 822 - 823 - p = (void *)pkt + GPR_HDR_SIZE + APM_CMD_HDR_SIZE; 824 - 825 - param_data = p; 826 - param_data->module_instance_id = module->instance_id; 827 - param_data->error_code = 0; 828 - param_data->param_id = PARAM_ID_MODULE_ENABLE; 829 - param_data->param_size = sizeof(*param); 830 - p = p + APM_MODULE_PARAM_DATA_SIZE; 831 - param = p; 832 - 833 - param->enable = enable; 834 - 835 - rc = q6apm_send_cmd_sync(graph->apm, pkt, 0); 836 - 837 - kfree(pkt); 838 - 839 - return rc; 790 + static int audioreach_gapless_set_media_format(struct q6apm_graph *graph, 791 + struct audioreach_module *module, 792 + struct audioreach_module_config *cfg) 793 + { 794 + return audioreach_send_u32_param(graph, module, PARAM_ID_EARLY_EOS_DELAY, 795 + EARLY_EOS_DELAY_MS); 840 796 } 841 797 842 798 static int audioreach_mfc_set_media_format(struct q6apm_graph *graph, ··· 841 885 842 886 return rc; 843 887 } 888 + 889 + static int audioreach_set_compr_media_format(struct media_format *media_fmt_hdr, 890 + void *p, struct audioreach_module_config *mcfg) 891 + { 892 + struct payload_media_fmt_aac_t *aac_cfg; 893 + struct payload_media_fmt_pcm *mp3_cfg; 894 + struct payload_media_fmt_flac_t *flac_cfg; 895 + 896 + switch (mcfg->fmt) { 897 + case SND_AUDIOCODEC_MP3: 898 + media_fmt_hdr->data_format = DATA_FORMAT_RAW_COMPRESSED; 899 + media_fmt_hdr->fmt_id = MEDIA_FMT_ID_MP3; 900 + media_fmt_hdr->payload_size = 0; 901 + p = p + sizeof(*media_fmt_hdr); 902 + mp3_cfg = p; 903 + mp3_cfg->sample_rate = mcfg->sample_rate; 904 + mp3_cfg->bit_width = mcfg->bit_width; 905 + mp3_cfg->alignment = PCM_LSB_ALIGNED; 906 + mp3_cfg->bits_per_sample = mcfg->bit_width; 907 + mp3_cfg->q_factor = mcfg->bit_width - 1; 908 + mp3_cfg->endianness = PCM_LITTLE_ENDIAN; 909 + mp3_cfg->num_channels = mcfg->num_channels; 910 + 911 + if (mcfg->num_channels == 1) { 912 + mp3_cfg->channel_mapping[0] = PCM_CHANNEL_L; 913 + } else if (mcfg->num_channels == 2) { 914 + mp3_cfg->channel_mapping[0] = PCM_CHANNEL_L; 915 + mp3_cfg->channel_mapping[1] = PCM_CHANNEL_R; 916 + } 917 + break; 918 + case SND_AUDIOCODEC_AAC: 919 + media_fmt_hdr->data_format = DATA_FORMAT_RAW_COMPRESSED; 920 + media_fmt_hdr->fmt_id = MEDIA_FMT_ID_AAC; 921 + media_fmt_hdr->payload_size = sizeof(struct payload_media_fmt_aac_t); 922 + p = p + sizeof(*media_fmt_hdr); 923 + aac_cfg = p; 924 + aac_cfg->aac_fmt_flag = 0; 925 + aac_cfg->audio_obj_type = 5; 926 + aac_cfg->num_channels = mcfg->num_channels; 927 + aac_cfg->total_size_of_PCE_bits = 0; 928 + aac_cfg->sample_rate = mcfg->sample_rate; 929 + break; 930 + case SND_AUDIOCODEC_FLAC: 931 + media_fmt_hdr->data_format = DATA_FORMAT_RAW_COMPRESSED; 932 + media_fmt_hdr->fmt_id = MEDIA_FMT_ID_FLAC; 933 + media_fmt_hdr->payload_size = sizeof(struct payload_media_fmt_flac_t); 934 + p = p + sizeof(*media_fmt_hdr); 935 + flac_cfg = p; 936 + flac_cfg->sample_size = mcfg->codec.options.flac_d.sample_size; 937 + flac_cfg->num_channels = mcfg->num_channels; 938 + flac_cfg->min_blk_size = mcfg->codec.options.flac_d.min_blk_size; 939 + flac_cfg->max_blk_size = mcfg->codec.options.flac_d.max_blk_size; 940 + flac_cfg->sample_rate = mcfg->sample_rate; 941 + flac_cfg->min_frame_size = mcfg->codec.options.flac_d.min_frame_size; 942 + flac_cfg->max_frame_size = mcfg->codec.options.flac_d.max_frame_size; 943 + break; 944 + default: 945 + return -EINVAL; 946 + } 947 + 948 + return 0; 949 + } 950 + 951 + int audioreach_compr_set_param(struct q6apm_graph *graph, struct audioreach_module_config *mcfg) 952 + { 953 + struct media_format *header; 954 + struct gpr_pkt *pkt; 955 + int iid, payload_size, rc; 956 + void *p; 957 + 958 + payload_size = sizeof(struct apm_sh_module_media_fmt_cmd); 959 + 960 + iid = q6apm_graph_get_rx_shmem_module_iid(graph); 961 + pkt = audioreach_alloc_cmd_pkt(payload_size, DATA_CMD_WR_SH_MEM_EP_MEDIA_FORMAT, 962 + 0, graph->port->id, iid); 963 + 964 + if (IS_ERR(pkt)) 965 + return -ENOMEM; 966 + 967 + p = (void *)pkt + GPR_HDR_SIZE; 968 + header = p; 969 + rc = audioreach_set_compr_media_format(header, p, mcfg); 970 + if (rc) { 971 + kfree(pkt); 972 + return rc; 973 + } 974 + 975 + rc = gpr_send_port_pkt(graph->port, pkt); 976 + kfree(pkt); 977 + 978 + return rc; 979 + } 980 + EXPORT_SYMBOL_GPL(audioreach_compr_set_param); 844 981 845 982 static int audioreach_i2s_set_media_format(struct q6apm_graph *graph, 846 983 struct audioreach_module *module, ··· 1138 1089 p = p + APM_MODULE_PARAM_DATA_SIZE; 1139 1090 1140 1091 header = p; 1141 - header->data_format = DATA_FORMAT_FIXED_POINT; 1142 - header->fmt_id = MEDIA_FMT_ID_PCM; 1143 - header->payload_size = payload_size - sizeof(*header); 1092 + if (mcfg->fmt == SND_AUDIOCODEC_PCM) { 1093 + header->data_format = DATA_FORMAT_FIXED_POINT; 1094 + header->fmt_id = MEDIA_FMT_ID_PCM; 1095 + header->payload_size = payload_size - sizeof(*header); 1144 1096 1145 - p = p + sizeof(*header); 1146 - cfg = p; 1147 - cfg->sample_rate = mcfg->sample_rate; 1148 - cfg->bit_width = mcfg->bit_width; 1149 - cfg->alignment = PCM_LSB_ALIGNED; 1150 - cfg->bits_per_sample = mcfg->bit_width; 1151 - cfg->q_factor = mcfg->bit_width - 1; 1152 - cfg->endianness = PCM_LITTLE_ENDIAN; 1153 - cfg->num_channels = mcfg->num_channels; 1097 + p = p + sizeof(*header); 1098 + cfg = p; 1099 + cfg->sample_rate = mcfg->sample_rate; 1100 + cfg->bit_width = mcfg->bit_width; 1101 + cfg->alignment = PCM_LSB_ALIGNED; 1102 + cfg->bits_per_sample = mcfg->bit_width; 1103 + cfg->q_factor = mcfg->bit_width - 1; 1104 + cfg->endianness = PCM_LITTLE_ENDIAN; 1105 + cfg->num_channels = mcfg->num_channels; 1154 1106 1155 - if (mcfg->num_channels == 1) { 1156 - cfg->channel_mapping[0] = PCM_CHANNEL_L; 1157 - } else if (num_channels == 2) { 1158 - cfg->channel_mapping[0] = PCM_CHANNEL_L; 1159 - cfg->channel_mapping[1] = PCM_CHANNEL_R; 1107 + if (mcfg->num_channels == 1) 1108 + cfg->channel_mapping[0] = PCM_CHANNEL_L; 1109 + else if (num_channels == 2) { 1110 + cfg->channel_mapping[0] = PCM_CHANNEL_L; 1111 + cfg->channel_mapping[1] = PCM_CHANNEL_R; 1112 + } 1113 + } else { 1114 + rc = audioreach_set_compr_media_format(header, p, mcfg); 1115 + if (rc) { 1116 + kfree(pkt); 1117 + return rc; 1118 + } 1160 1119 } 1161 1120 1162 1121 rc = audioreach_graph_send_cmd_sync(graph, pkt, 0); ··· 1249 1192 case MODULE_ID_PCM_DEC: 1250 1193 case MODULE_ID_PCM_ENC: 1251 1194 case MODULE_ID_PCM_CNV: 1195 + case MODULE_ID_PLACEHOLDER_DECODER: 1196 + case MODULE_ID_PLACEHOLDER_ENCODER: 1252 1197 rc = audioreach_pcm_set_media_format(graph, module, cfg); 1253 1198 break; 1254 1199 case MODULE_ID_DISPLAY_PORT_SINK: ··· 1277 1218 break; 1278 1219 case MODULE_ID_MFC: 1279 1220 rc = audioreach_mfc_set_media_format(graph, module, cfg); 1221 + break; 1222 + case MODULE_ID_GAPLESS: 1223 + rc = audioreach_gapless_set_media_format(graph, module, cfg); 1280 1224 break; 1281 1225 default: 1282 1226 rc = 0;
+51
sound/soc/qcom/qdsp6/audioreach.h
··· 15 15 #define MODULE_ID_PCM_CNV 0x07001003 16 16 #define MODULE_ID_PCM_ENC 0x07001004 17 17 #define MODULE_ID_PCM_DEC 0x07001005 18 + #define MODULE_ID_PLACEHOLDER_ENCODER 0x07001008 19 + #define MODULE_ID_PLACEHOLDER_DECODER 0x07001009 18 20 #define MODULE_ID_SAL 0x07001010 19 21 #define MODULE_ID_MFC 0x07001015 20 22 #define MODULE_ID_CODEC_DMA_SINK 0x07001023 ··· 24 22 #define MODULE_ID_I2S_SINK 0x0700100A 25 23 #define MODULE_ID_I2S_SOURCE 0x0700100B 26 24 #define MODULE_ID_DATA_LOGGING 0x0700101A 25 + #define MODULE_ID_AAC_DEC 0x0700101F 26 + #define MODULE_ID_FLAC_DEC 0x0700102F 27 + #define MODULE_ID_MP3_DECODE 0x0700103B 28 + #define MODULE_ID_GAPLESS 0x0700104D 27 29 #define MODULE_ID_DISPLAY_PORT_SINK 0x07001069 28 30 29 31 #define APM_CMD_GET_SPF_STATE 0x01001021 ··· 149 143 } __packed; 150 144 151 145 #define DATA_FORMAT_FIXED_POINT 1 146 + #define DATA_FORMAT_GENERIC_COMPRESSED 5 147 + #define DATA_FORMAT_RAW_COMPRESSED 6 152 148 #define PCM_LSB_ALIGNED 1 153 149 #define PCM_MSB_ALIGNED 2 154 150 #define PCM_LITTLE_ENDIAN 1 155 151 #define PCM_BIT_ENDIAN 2 156 152 157 153 #define MEDIA_FMT_ID_PCM 0x09001000 154 + #define MEDIA_FMT_ID_MP3 0x09001009 158 155 #define PCM_CHANNEL_L 1 159 156 #define PCM_CHANNEL_R 2 160 157 #define SAMPLE_RATE_48K 48000 ··· 233 224 uint32_t data_format; 234 225 uint32_t fmt_id; 235 226 uint32_t payload_size; 227 + } __packed; 228 + 229 + #define MEDIA_FMT_ID_FLAC 0x09001004 230 + 231 + struct payload_media_fmt_flac_t { 232 + uint16_t num_channels; 233 + uint16_t sample_size; 234 + uint16_t min_blk_size; 235 + uint16_t max_blk_size; 236 + uint32_t sample_rate; 237 + uint32_t min_frame_size; 238 + uint32_t max_frame_size; 239 + } __packed; 240 + 241 + #define MEDIA_FMT_ID_AAC 0x09001001 242 + 243 + struct payload_media_fmt_aac_t { 244 + uint16_t aac_fmt_flag; 245 + uint16_t audio_obj_type; 246 + uint16_t num_channels; 247 + uint16_t total_size_of_PCE_bits; 248 + uint32_t sample_rate; 236 249 } __packed; 237 250 238 251 #define DATA_CMD_WR_SH_MEM_EP_EOS 0x04001002 ··· 553 522 } __packed; 554 523 555 524 #define PARAM_ID_MFC_OUTPUT_MEDIA_FORMAT 0x08001024 525 + #define PARAM_ID_EARLY_EOS_DELAY 0x0800114C 526 + #define EARLY_EOS_DELAY_MS 150 556 527 557 528 struct param_id_mfc_media_format { 558 529 uint32_t sample_rate; 559 530 uint16_t bit_width; 560 531 uint16_t num_channels; 561 532 uint16_t channel_mapping[]; 533 + } __packed; 534 + 535 + struct param_id_gapless_early_eos_delay_t { 536 + uint32_t early_eos_delay_ms; 562 537 } __packed; 563 538 564 539 struct media_format { ··· 644 607 uint16_t reserved; 645 608 } __packed; 646 609 610 + 611 + #define PARAM_ID_REMOVE_INITIAL_SILENCE 0x0800114B 612 + #define PARAM_ID_REMOVE_TRAILING_SILENCE 0x0800115D 613 + 614 + #define PARAM_ID_REAL_MODULE_ID 0x0800100B 615 + 616 + struct param_id_placeholder_real_module_id { 617 + uint32_t real_module_id; 618 + } __packed; 647 619 648 620 /* Graph */ 649 621 struct audioreach_connection { ··· 762 716 u32 channel_allocation; 763 717 u32 sd_line_mask; 764 718 int fmt; 719 + struct snd_codec codec; 765 720 u8 channel_map[AR_PCM_MAX_NUM_CHANNEL]; 766 721 }; 767 722 ··· 799 752 int audioreach_shared_memory_send_eos(struct q6apm_graph *graph); 800 753 int audioreach_gain_set_vol_ctrl(struct q6apm *apm, 801 754 struct audioreach_module *module, int vol); 755 + int audioreach_send_u32_param(struct q6apm_graph *graph, struct audioreach_module *module, 756 + uint32_t param_id, uint32_t param_val); 757 + int audioreach_compr_set_param(struct q6apm_graph *graph, struct audioreach_module_config *mcfg); 758 + 802 759 #endif /* __AUDIOREACH_H__ */
+445
sound/soc/qcom/qdsp6/q6apm-dai.c
··· 28 28 #define CAPTURE_MIN_PERIOD_SIZE 320 29 29 #define BUFFER_BYTES_MAX (PLAYBACK_MAX_NUM_PERIODS * PLAYBACK_MAX_PERIOD_SIZE) 30 30 #define BUFFER_BYTES_MIN (PLAYBACK_MIN_NUM_PERIODS * PLAYBACK_MIN_PERIOD_SIZE) 31 + #define COMPR_PLAYBACK_MAX_FRAGMENT_SIZE (128 * 1024) 32 + #define COMPR_PLAYBACK_MAX_NUM_FRAGMENTS (16 * 4) 33 + #define COMPR_PLAYBACK_MIN_FRAGMENT_SIZE (8 * 1024) 34 + #define COMPR_PLAYBACK_MIN_NUM_FRAGMENTS (4) 31 35 #define SID_MASK_DEFAULT 0xF 36 + 37 + static const struct snd_compr_codec_caps q6apm_compr_caps = { 38 + .num_descriptors = 1, 39 + .descriptor[0].max_ch = 2, 40 + .descriptor[0].sample_rates = { 8000, 11025, 12000, 16000, 22050, 41 + 24000, 32000, 44100, 48000, 88200, 42 + 96000, 176400, 192000 }, 43 + .descriptor[0].num_sample_rates = 13, 44 + .descriptor[0].bit_rate[0] = 320, 45 + .descriptor[0].bit_rate[1] = 128, 46 + .descriptor[0].num_bitrates = 2, 47 + .descriptor[0].profiles = 0, 48 + .descriptor[0].modes = SND_AUDIOCHANMODE_MP3_STEREO, 49 + .descriptor[0].formats = 0, 50 + }; 32 51 33 52 enum stream_state { 34 53 Q6APM_STREAM_IDLE = 0, ··· 58 39 struct q6apm_dai_rtd { 59 40 struct snd_pcm_substream *substream; 60 41 struct snd_compr_stream *cstream; 42 + struct snd_codec codec; 61 43 struct snd_compr_params codec_param; 62 44 struct snd_dma_buffer dma_buffer; 63 45 phys_addr_t phys; ··· 72 52 uint16_t bits_per_sample; 73 53 uint16_t source; /* Encoding source bit mask */ 74 54 uint16_t session_id; 55 + bool next_track; 75 56 enum stream_state state; 76 57 struct q6apm_graph *graph; 77 58 spinlock_t lock; 59 + uint32_t initial_samples_drop; 60 + uint32_t trailing_samples_drop; 61 + bool notify_on_drain; 78 62 }; 79 63 80 64 struct q6apm_dai_data { ··· 156 132 } 157 133 } 158 134 135 + static void event_handler_compr(uint32_t opcode, uint32_t token, 136 + uint32_t *payload, void *priv) 137 + { 138 + struct q6apm_dai_rtd *prtd = priv; 139 + struct snd_compr_stream *substream = prtd->cstream; 140 + unsigned long flags; 141 + uint32_t wflags = 0; 142 + uint64_t avail; 143 + uint32_t bytes_written, bytes_to_write; 144 + bool is_last_buffer = false; 145 + 146 + switch (opcode) { 147 + case APM_CLIENT_EVENT_CMD_EOS_DONE: 148 + spin_lock_irqsave(&prtd->lock, flags); 149 + if (prtd->notify_on_drain) { 150 + snd_compr_drain_notify(prtd->cstream); 151 + prtd->notify_on_drain = false; 152 + } else { 153 + prtd->state = Q6APM_STREAM_STOPPED; 154 + } 155 + spin_unlock_irqrestore(&prtd->lock, flags); 156 + break; 157 + case APM_CLIENT_EVENT_DATA_WRITE_DONE: 158 + spin_lock_irqsave(&prtd->lock, flags); 159 + bytes_written = token >> APM_WRITE_TOKEN_LEN_SHIFT; 160 + prtd->copied_total += bytes_written; 161 + snd_compr_fragment_elapsed(substream); 162 + 163 + if (prtd->state != Q6APM_STREAM_RUNNING) { 164 + spin_unlock_irqrestore(&prtd->lock, flags); 165 + break; 166 + } 167 + 168 + avail = prtd->bytes_received - prtd->bytes_sent; 169 + 170 + if (avail > prtd->pcm_count) { 171 + bytes_to_write = prtd->pcm_count; 172 + } else { 173 + if (substream->partial_drain || prtd->notify_on_drain) 174 + is_last_buffer = true; 175 + bytes_to_write = avail; 176 + } 177 + 178 + if (bytes_to_write) { 179 + if (substream->partial_drain && is_last_buffer) 180 + wflags |= APM_LAST_BUFFER_FLAG; 181 + 182 + q6apm_write_async(prtd->graph, 183 + bytes_to_write, 0, 0, wflags); 184 + 185 + prtd->bytes_sent += bytes_to_write; 186 + 187 + if (prtd->notify_on_drain && is_last_buffer) 188 + audioreach_shared_memory_send_eos(prtd->graph); 189 + } 190 + 191 + spin_unlock_irqrestore(&prtd->lock, flags); 192 + break; 193 + default: 194 + break; 195 + } 196 + } 197 + 159 198 static int q6apm_dai_prepare(struct snd_soc_component *component, 160 199 struct snd_pcm_substream *substream) 161 200 { ··· 242 155 cfg.sample_rate = runtime->rate; 243 156 cfg.num_channels = runtime->channels; 244 157 cfg.bit_width = prtd->bits_per_sample; 158 + cfg.fmt = SND_AUDIOCODEC_PCM; 245 159 246 160 if (prtd->state) { 247 161 /* clear the previous setup if any */ ··· 474 386 return snd_pcm_set_fixed_buffer_all(rtd->pcm, SNDRV_DMA_TYPE_DEV, component->dev, size); 475 387 } 476 388 389 + static int q6apm_dai_compr_open(struct snd_soc_component *component, 390 + struct snd_compr_stream *stream) 391 + { 392 + struct snd_soc_pcm_runtime *rtd = stream->private_data; 393 + struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); 394 + struct snd_compr_runtime *runtime = stream->runtime; 395 + struct q6apm_dai_rtd *prtd; 396 + struct q6apm_dai_data *pdata; 397 + struct device *dev = component->dev; 398 + int ret, size; 399 + int graph_id; 400 + 401 + graph_id = cpu_dai->driver->id; 402 + pdata = snd_soc_component_get_drvdata(component); 403 + if (!pdata) 404 + return -EINVAL; 405 + 406 + prtd = kzalloc(sizeof(*prtd), GFP_KERNEL); 407 + if (prtd == NULL) 408 + return -ENOMEM; 409 + 410 + prtd->cstream = stream; 411 + prtd->graph = q6apm_graph_open(dev, (q6apm_cb)event_handler_compr, prtd, graph_id); 412 + if (IS_ERR(prtd->graph)) { 413 + ret = PTR_ERR(prtd->graph); 414 + kfree(prtd); 415 + return ret; 416 + } 417 + 418 + runtime->private_data = prtd; 419 + runtime->dma_bytes = BUFFER_BYTES_MAX; 420 + size = COMPR_PLAYBACK_MAX_FRAGMENT_SIZE * COMPR_PLAYBACK_MAX_NUM_FRAGMENTS; 421 + ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, dev, size, &prtd->dma_buffer); 422 + if (ret) 423 + return ret; 424 + 425 + if (pdata->sid < 0) 426 + prtd->phys = prtd->dma_buffer.addr; 427 + else 428 + prtd->phys = prtd->dma_buffer.addr | (pdata->sid << 32); 429 + 430 + snd_compr_set_runtime_buffer(stream, &prtd->dma_buffer); 431 + spin_lock_init(&prtd->lock); 432 + 433 + q6apm_enable_compress_module(dev, prtd->graph, true); 434 + return 0; 435 + } 436 + 437 + static int q6apm_dai_compr_free(struct snd_soc_component *component, 438 + struct snd_compr_stream *stream) 439 + { 440 + struct snd_compr_runtime *runtime = stream->runtime; 441 + struct q6apm_dai_rtd *prtd = runtime->private_data; 442 + 443 + q6apm_graph_stop(prtd->graph); 444 + q6apm_unmap_memory_regions(prtd->graph, SNDRV_PCM_STREAM_PLAYBACK); 445 + q6apm_graph_close(prtd->graph); 446 + snd_dma_free_pages(&prtd->dma_buffer); 447 + prtd->graph = NULL; 448 + kfree(prtd); 449 + runtime->private_data = NULL; 450 + 451 + return 0; 452 + } 453 + 454 + static int q6apm_dai_compr_get_caps(struct snd_soc_component *component, 455 + struct snd_compr_stream *stream, 456 + struct snd_compr_caps *caps) 457 + { 458 + caps->direction = SND_COMPRESS_PLAYBACK; 459 + caps->min_fragment_size = COMPR_PLAYBACK_MIN_FRAGMENT_SIZE; 460 + caps->max_fragment_size = COMPR_PLAYBACK_MAX_FRAGMENT_SIZE; 461 + caps->min_fragments = COMPR_PLAYBACK_MIN_NUM_FRAGMENTS; 462 + caps->max_fragments = COMPR_PLAYBACK_MAX_NUM_FRAGMENTS; 463 + caps->num_codecs = 3; 464 + caps->codecs[0] = SND_AUDIOCODEC_MP3; 465 + caps->codecs[1] = SND_AUDIOCODEC_AAC; 466 + caps->codecs[2] = SND_AUDIOCODEC_FLAC; 467 + 468 + return 0; 469 + } 470 + 471 + static int q6apm_dai_compr_get_codec_caps(struct snd_soc_component *component, 472 + struct snd_compr_stream *stream, 473 + struct snd_compr_codec_caps *codec) 474 + { 475 + switch (codec->codec) { 476 + case SND_AUDIOCODEC_MP3: 477 + *codec = q6apm_compr_caps; 478 + break; 479 + default: 480 + break; 481 + } 482 + 483 + return 0; 484 + } 485 + 486 + static int q6apm_dai_compr_pointer(struct snd_soc_component *component, 487 + struct snd_compr_stream *stream, 488 + struct snd_compr_tstamp *tstamp) 489 + { 490 + struct snd_compr_runtime *runtime = stream->runtime; 491 + struct q6apm_dai_rtd *prtd = runtime->private_data; 492 + unsigned long flags; 493 + 494 + spin_lock_irqsave(&prtd->lock, flags); 495 + tstamp->copied_total = prtd->copied_total; 496 + tstamp->byte_offset = prtd->copied_total % prtd->pcm_size; 497 + spin_unlock_irqrestore(&prtd->lock, flags); 498 + 499 + return 0; 500 + } 501 + 502 + static int q6apm_dai_compr_trigger(struct snd_soc_component *component, 503 + struct snd_compr_stream *stream, int cmd) 504 + { 505 + struct snd_compr_runtime *runtime = stream->runtime; 506 + struct q6apm_dai_rtd *prtd = runtime->private_data; 507 + int ret = 0; 508 + 509 + switch (cmd) { 510 + case SNDRV_PCM_TRIGGER_START: 511 + case SNDRV_PCM_TRIGGER_RESUME: 512 + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 513 + ret = q6apm_write_async(prtd->graph, prtd->pcm_count, 0, 0, NO_TIMESTAMP); 514 + break; 515 + case SNDRV_PCM_TRIGGER_STOP: 516 + break; 517 + case SNDRV_PCM_TRIGGER_SUSPEND: 518 + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 519 + break; 520 + case SND_COMPR_TRIGGER_NEXT_TRACK: 521 + prtd->next_track = true; 522 + break; 523 + case SND_COMPR_TRIGGER_DRAIN: 524 + case SND_COMPR_TRIGGER_PARTIAL_DRAIN: 525 + prtd->notify_on_drain = true; 526 + break; 527 + default: 528 + ret = -EINVAL; 529 + break; 530 + } 531 + 532 + return ret; 533 + } 534 + 535 + static int q6apm_dai_compr_ack(struct snd_soc_component *component, struct snd_compr_stream *stream, 536 + size_t count) 537 + { 538 + struct snd_compr_runtime *runtime = stream->runtime; 539 + struct q6apm_dai_rtd *prtd = runtime->private_data; 540 + unsigned long flags; 541 + 542 + spin_lock_irqsave(&prtd->lock, flags); 543 + prtd->bytes_received += count; 544 + spin_unlock_irqrestore(&prtd->lock, flags); 545 + 546 + return count; 547 + } 548 + 549 + static int q6apm_dai_compr_set_params(struct snd_soc_component *component, 550 + struct snd_compr_stream *stream, 551 + struct snd_compr_params *params) 552 + { 553 + struct snd_compr_runtime *runtime = stream->runtime; 554 + struct q6apm_dai_rtd *prtd = runtime->private_data; 555 + struct q6apm_dai_data *pdata; 556 + struct audioreach_module_config cfg; 557 + struct snd_codec *codec = &params->codec; 558 + int dir = stream->direction; 559 + int ret; 560 + 561 + pdata = snd_soc_component_get_drvdata(component); 562 + if (!pdata) 563 + return -EINVAL; 564 + 565 + prtd->periods = runtime->fragments; 566 + prtd->pcm_count = runtime->fragment_size; 567 + prtd->pcm_size = runtime->fragments * runtime->fragment_size; 568 + prtd->bits_per_sample = 16; 569 + 570 + prtd->pos = 0; 571 + 572 + if (prtd->next_track != true) { 573 + memcpy(&prtd->codec, codec, sizeof(*codec)); 574 + 575 + ret = q6apm_set_real_module_id(component->dev, prtd->graph, codec->id); 576 + if (ret) 577 + return ret; 578 + 579 + cfg.direction = dir; 580 + cfg.sample_rate = codec->sample_rate; 581 + cfg.num_channels = 2; 582 + cfg.bit_width = prtd->bits_per_sample; 583 + cfg.fmt = codec->id; 584 + memcpy(&cfg.codec, codec, sizeof(*codec)); 585 + 586 + ret = q6apm_graph_media_format_shmem(prtd->graph, &cfg); 587 + if (ret < 0) 588 + return ret; 589 + 590 + ret = q6apm_graph_media_format_pcm(prtd->graph, &cfg); 591 + if (ret) 592 + return ret; 593 + 594 + ret = q6apm_map_memory_regions(prtd->graph, SNDRV_PCM_STREAM_PLAYBACK, 595 + prtd->phys, (prtd->pcm_size / prtd->periods), 596 + prtd->periods); 597 + if (ret < 0) 598 + return -ENOMEM; 599 + 600 + ret = q6apm_graph_prepare(prtd->graph); 601 + if (ret) 602 + return ret; 603 + 604 + ret = q6apm_graph_start(prtd->graph); 605 + if (ret) 606 + return ret; 607 + 608 + } else { 609 + cfg.direction = dir; 610 + cfg.sample_rate = codec->sample_rate; 611 + cfg.num_channels = 2; 612 + cfg.bit_width = prtd->bits_per_sample; 613 + cfg.fmt = codec->id; 614 + memcpy(&cfg.codec, codec, sizeof(*codec)); 615 + 616 + ret = audioreach_compr_set_param(prtd->graph, &cfg); 617 + if (ret < 0) 618 + return ret; 619 + } 620 + prtd->state = Q6APM_STREAM_RUNNING; 621 + 622 + return 0; 623 + } 624 + 625 + static int q6apm_dai_compr_set_metadata(struct snd_soc_component *component, 626 + struct snd_compr_stream *stream, 627 + struct snd_compr_metadata *metadata) 628 + { 629 + struct snd_compr_runtime *runtime = stream->runtime; 630 + struct q6apm_dai_rtd *prtd = runtime->private_data; 631 + int ret = 0; 632 + 633 + switch (metadata->key) { 634 + case SNDRV_COMPRESS_ENCODER_PADDING: 635 + prtd->trailing_samples_drop = metadata->value[0]; 636 + q6apm_remove_trailing_silence(component->dev, prtd->graph, 637 + prtd->trailing_samples_drop); 638 + break; 639 + case SNDRV_COMPRESS_ENCODER_DELAY: 640 + prtd->initial_samples_drop = metadata->value[0]; 641 + q6apm_remove_initial_silence(component->dev, prtd->graph, 642 + prtd->initial_samples_drop); 643 + break; 644 + default: 645 + ret = -EINVAL; 646 + break; 647 + } 648 + 649 + return ret; 650 + } 651 + 652 + static int q6apm_dai_compr_mmap(struct snd_soc_component *component, 653 + struct snd_compr_stream *stream, 654 + struct vm_area_struct *vma) 655 + { 656 + struct snd_compr_runtime *runtime = stream->runtime; 657 + struct q6apm_dai_rtd *prtd = runtime->private_data; 658 + struct device *dev = component->dev; 659 + 660 + return dma_mmap_coherent(dev, vma, prtd->dma_buffer.area, prtd->dma_buffer.addr, 661 + prtd->dma_buffer.bytes); 662 + } 663 + 664 + static int q6apm_compr_copy(struct snd_soc_component *component, 665 + struct snd_compr_stream *stream, char __user *buf, 666 + size_t count) 667 + { 668 + struct snd_compr_runtime *runtime = stream->runtime; 669 + struct q6apm_dai_rtd *prtd = runtime->private_data; 670 + void *dstn; 671 + unsigned long flags; 672 + size_t copy; 673 + u32 wflags = 0; 674 + u32 app_pointer; 675 + u32 bytes_received; 676 + uint32_t bytes_to_write; 677 + int avail, bytes_in_flight = 0; 678 + 679 + bytes_received = prtd->bytes_received; 680 + 681 + /** 682 + * Make sure that next track data pointer is aligned at 32 bit boundary 683 + * This is a Mandatory requirement from DSP data buffers alignment 684 + */ 685 + if (prtd->next_track) 686 + bytes_received = ALIGN(prtd->bytes_received, prtd->pcm_count); 687 + 688 + app_pointer = bytes_received/prtd->pcm_size; 689 + app_pointer = bytes_received - (app_pointer * prtd->pcm_size); 690 + dstn = prtd->dma_buffer.area + app_pointer; 691 + 692 + if (count < prtd->pcm_size - app_pointer) { 693 + if (copy_from_user(dstn, buf, count)) 694 + return -EFAULT; 695 + } else { 696 + copy = prtd->pcm_size - app_pointer; 697 + if (copy_from_user(dstn, buf, copy)) 698 + return -EFAULT; 699 + if (copy_from_user(prtd->dma_buffer.area, buf + copy, count - copy)) 700 + return -EFAULT; 701 + } 702 + 703 + spin_lock_irqsave(&prtd->lock, flags); 704 + bytes_in_flight = prtd->bytes_received - prtd->copied_total; 705 + 706 + if (prtd->next_track) { 707 + prtd->next_track = false; 708 + prtd->copied_total = ALIGN(prtd->copied_total, prtd->pcm_count); 709 + prtd->bytes_sent = ALIGN(prtd->bytes_sent, prtd->pcm_count); 710 + } 711 + 712 + prtd->bytes_received = bytes_received + count; 713 + 714 + /* Kick off the data to dsp if its starving!! */ 715 + if (prtd->state == Q6APM_STREAM_RUNNING && (bytes_in_flight == 0)) { 716 + bytes_to_write = prtd->pcm_count; 717 + avail = prtd->bytes_received - prtd->bytes_sent; 718 + 719 + if (avail < prtd->pcm_count) 720 + bytes_to_write = avail; 721 + 722 + q6apm_write_async(prtd->graph, bytes_to_write, 0, 0, wflags); 723 + prtd->bytes_sent += bytes_to_write; 724 + } 725 + 726 + spin_unlock_irqrestore(&prtd->lock, flags); 727 + 728 + return count; 729 + } 730 + 731 + static const struct snd_compress_ops q6apm_dai_compress_ops = { 732 + .open = q6apm_dai_compr_open, 733 + .free = q6apm_dai_compr_free, 734 + .get_caps = q6apm_dai_compr_get_caps, 735 + .get_codec_caps = q6apm_dai_compr_get_codec_caps, 736 + .pointer = q6apm_dai_compr_pointer, 737 + .trigger = q6apm_dai_compr_trigger, 738 + .ack = q6apm_dai_compr_ack, 739 + .set_params = q6apm_dai_compr_set_params, 740 + .set_metadata = q6apm_dai_compr_set_metadata, 741 + .mmap = q6apm_dai_compr_mmap, 742 + .copy = q6apm_compr_copy, 743 + }; 744 + 477 745 static const struct snd_soc_component_driver q6apm_fe_dai_component = { 478 746 .name = DRV_NAME, 479 747 .open = q6apm_dai_open, ··· 839 395 .hw_params = q6apm_dai_hw_params, 840 396 .pointer = q6apm_dai_pointer, 841 397 .trigger = q6apm_dai_trigger, 398 + .compress_ops = &q6apm_dai_compress_ops, 842 399 }; 843 400 844 401 static int q6apm_dai_probe(struct platform_device *pdev)
+68
sound/soc/qcom/qdsp6/q6apm.c
··· 298 298 } 299 299 EXPORT_SYMBOL_GPL(q6apm_unmap_memory_regions); 300 300 301 + int q6apm_remove_initial_silence(struct device *dev, struct q6apm_graph *graph, uint32_t samples) 302 + { 303 + struct audioreach_module *module; 304 + 305 + module = q6apm_find_module_by_mid(graph, MODULE_ID_PLACEHOLDER_DECODER); 306 + if (!module) 307 + return -ENODEV; 308 + 309 + return audioreach_send_u32_param(graph, module, PARAM_ID_REMOVE_INITIAL_SILENCE, samples); 310 + } 311 + EXPORT_SYMBOL_GPL(q6apm_remove_initial_silence); 312 + 313 + int q6apm_remove_trailing_silence(struct device *dev, struct q6apm_graph *graph, uint32_t samples) 314 + { 315 + struct audioreach_module *module; 316 + 317 + module = q6apm_find_module_by_mid(graph, MODULE_ID_PLACEHOLDER_DECODER); 318 + if (!module) 319 + return -ENODEV; 320 + 321 + return audioreach_send_u32_param(graph, module, PARAM_ID_REMOVE_TRAILING_SILENCE, samples); 322 + } 323 + EXPORT_SYMBOL_GPL(q6apm_remove_trailing_silence); 324 + 325 + int q6apm_enable_compress_module(struct device *dev, struct q6apm_graph *graph, bool en) 326 + { 327 + struct audioreach_module *module; 328 + 329 + module = q6apm_find_module_by_mid(graph, MODULE_ID_PLACEHOLDER_DECODER); 330 + if (!module) 331 + return -ENODEV; 332 + 333 + return audioreach_send_u32_param(graph, module, PARAM_ID_MODULE_ENABLE, en); 334 + } 335 + EXPORT_SYMBOL_GPL(q6apm_enable_compress_module); 336 + 337 + int q6apm_set_real_module_id(struct device *dev, struct q6apm_graph *graph, 338 + uint32_t codec_id) 339 + { 340 + struct audioreach_module *module; 341 + uint32_t module_id; 342 + 343 + module = q6apm_find_module_by_mid(graph, MODULE_ID_PLACEHOLDER_DECODER); 344 + if (!module) 345 + return -ENODEV; 346 + 347 + switch (codec_id) { 348 + case SND_AUDIOCODEC_MP3: 349 + module_id = MODULE_ID_MP3_DECODE; 350 + break; 351 + case SND_AUDIOCODEC_AAC: 352 + module_id = MODULE_ID_AAC_DEC; 353 + break; 354 + case SND_AUDIOCODEC_FLAC: 355 + module_id = MODULE_ID_FLAC_DEC; 356 + break; 357 + default: 358 + return -EINVAL; 359 + } 360 + 361 + return audioreach_send_u32_param(graph, module, PARAM_ID_REAL_MODULE_ID, 362 + module_id); 363 + } 364 + EXPORT_SYMBOL_GPL(q6apm_set_real_module_id); 365 + 301 366 int q6apm_graph_media_format_pcm(struct q6apm_graph *graph, struct audioreach_module_config *cfg) 302 367 { 303 368 struct audioreach_graph_info *info = graph->info; ··· 562 497 } 563 498 break; 564 499 case DATA_CMD_WR_SH_MEM_EP_EOS_RENDERED: 500 + client_event = APM_CLIENT_EVENT_CMD_EOS_DONE; 501 + if (graph->cb) 502 + graph->cb(client_event, hdr->token, data->payload, graph->priv); 565 503 break; 566 504 case GPR_BASIC_RSP_RESULT: 567 505 switch (result->opcode) {
+6
sound/soc/qcom/qdsp6/q6apm.h
··· 45 45 #define APM_WRITE_TOKEN_LEN_SHIFT 16 46 46 47 47 #define APM_MAX_SESSIONS 8 48 + #define APM_LAST_BUFFER_FLAG BIT(30) 49 + #define NO_TIMESTAMP 0xFF00 48 50 49 51 struct q6apm { 50 52 struct device *dev; ··· 149 147 150 148 bool q6apm_is_adsp_ready(void); 151 149 150 + int q6apm_enable_compress_module(struct device *dev, struct q6apm_graph *graph, bool en); 151 + int q6apm_remove_initial_silence(struct device *dev, struct q6apm_graph *graph, uint32_t samples); 152 + int q6apm_remove_trailing_silence(struct device *dev, struct q6apm_graph *graph, uint32_t samples); 153 + int q6apm_set_real_module_id(struct device *dev, struct q6apm_graph *graph, uint32_t codec_id); 152 154 #endif /* __APM_GRAPH_ */
+21 -2
sound/soc/qcom/sc7280.c
··· 14 14 #include <sound/soc.h> 15 15 #include <sound/rt5682s.h> 16 16 #include <linux/soundwire/sdw.h> 17 + #include <sound/pcm_params.h> 17 18 18 19 #include "../codecs/rt5682.h" 19 20 #include "../codecs/rt5682s.h" ··· 197 196 struct sdw_stream_runtime *sruntime; 198 197 int i; 199 198 200 - snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_CHANNELS, 2, 2); 201 - snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_RATE, 48000, 48000); 199 + if (!rtd->dai_link->no_pcm) { 200 + snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_CHANNELS, 2, 2); 201 + snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_RATE, 48000, 48000); 202 + } 202 203 203 204 switch (cpu_dai->id) { 204 205 case LPASS_CDC_DMA_TX3: ··· 361 358 SND_SOC_DAPM_MIC("Headset Mic", NULL), 362 359 }; 363 360 361 + static int sc7280_snd_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, 362 + struct snd_pcm_hw_params *params) 363 + { 364 + struct snd_interval *rate = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); 365 + struct snd_interval *channels = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); 366 + struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); 367 + 368 + rate->min = rate->max = 48000; 369 + channels->min = channels->max = 2; 370 + snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S16_LE); 371 + 372 + return 0; 373 + } 374 + 364 375 static int sc7280_snd_platform_probe(struct platform_device *pdev) 365 376 { 366 377 struct snd_soc_card *card; ··· 404 387 for_each_card_prelinks(card, i, link) { 405 388 link->init = sc7280_init; 406 389 link->ops = &sc7280_ops; 390 + if (link->no_pcm == 1) 391 + link->be_hw_params_fixup = sc7280_snd_be_hw_params_fixup; 407 392 } 408 393 409 394 return devm_snd_soc_register_card(dev, card);