0001
0002
0003
0004
0005
0006 #include <sound/pcm_params.h>
0007
0008 #include "virtio_card.h"
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040 struct virtsnd_a2v_format {
0041 snd_pcm_format_t alsa_bit;
0042 unsigned int vio_bit;
0043 };
0044
0045 static const struct virtsnd_a2v_format g_a2v_format_map[] = {
0046 { SNDRV_PCM_FORMAT_IMA_ADPCM, VIRTIO_SND_PCM_FMT_IMA_ADPCM },
0047 { SNDRV_PCM_FORMAT_MU_LAW, VIRTIO_SND_PCM_FMT_MU_LAW },
0048 { SNDRV_PCM_FORMAT_A_LAW, VIRTIO_SND_PCM_FMT_A_LAW },
0049 { SNDRV_PCM_FORMAT_S8, VIRTIO_SND_PCM_FMT_S8 },
0050 { SNDRV_PCM_FORMAT_U8, VIRTIO_SND_PCM_FMT_U8 },
0051 { SNDRV_PCM_FORMAT_S16_LE, VIRTIO_SND_PCM_FMT_S16 },
0052 { SNDRV_PCM_FORMAT_U16_LE, VIRTIO_SND_PCM_FMT_U16 },
0053 { SNDRV_PCM_FORMAT_S18_3LE, VIRTIO_SND_PCM_FMT_S18_3 },
0054 { SNDRV_PCM_FORMAT_U18_3LE, VIRTIO_SND_PCM_FMT_U18_3 },
0055 { SNDRV_PCM_FORMAT_S20_3LE, VIRTIO_SND_PCM_FMT_S20_3 },
0056 { SNDRV_PCM_FORMAT_U20_3LE, VIRTIO_SND_PCM_FMT_U20_3 },
0057 { SNDRV_PCM_FORMAT_S24_3LE, VIRTIO_SND_PCM_FMT_S24_3 },
0058 { SNDRV_PCM_FORMAT_U24_3LE, VIRTIO_SND_PCM_FMT_U24_3 },
0059 { SNDRV_PCM_FORMAT_S20_LE, VIRTIO_SND_PCM_FMT_S20 },
0060 { SNDRV_PCM_FORMAT_U20_LE, VIRTIO_SND_PCM_FMT_U20 },
0061 { SNDRV_PCM_FORMAT_S24_LE, VIRTIO_SND_PCM_FMT_S24 },
0062 { SNDRV_PCM_FORMAT_U24_LE, VIRTIO_SND_PCM_FMT_U24 },
0063 { SNDRV_PCM_FORMAT_S32_LE, VIRTIO_SND_PCM_FMT_S32 },
0064 { SNDRV_PCM_FORMAT_U32_LE, VIRTIO_SND_PCM_FMT_U32 },
0065 { SNDRV_PCM_FORMAT_FLOAT_LE, VIRTIO_SND_PCM_FMT_FLOAT },
0066 { SNDRV_PCM_FORMAT_FLOAT64_LE, VIRTIO_SND_PCM_FMT_FLOAT64 },
0067 { SNDRV_PCM_FORMAT_DSD_U8, VIRTIO_SND_PCM_FMT_DSD_U8 },
0068 { SNDRV_PCM_FORMAT_DSD_U16_LE, VIRTIO_SND_PCM_FMT_DSD_U16 },
0069 { SNDRV_PCM_FORMAT_DSD_U32_LE, VIRTIO_SND_PCM_FMT_DSD_U32 },
0070 { SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE,
0071 VIRTIO_SND_PCM_FMT_IEC958_SUBFRAME }
0072 };
0073
0074
0075 struct virtsnd_a2v_rate {
0076 unsigned int rate;
0077 unsigned int vio_bit;
0078 };
0079
0080 static const struct virtsnd_a2v_rate g_a2v_rate_map[] = {
0081 { 5512, VIRTIO_SND_PCM_RATE_5512 },
0082 { 8000, VIRTIO_SND_PCM_RATE_8000 },
0083 { 11025, VIRTIO_SND_PCM_RATE_11025 },
0084 { 16000, VIRTIO_SND_PCM_RATE_16000 },
0085 { 22050, VIRTIO_SND_PCM_RATE_22050 },
0086 { 32000, VIRTIO_SND_PCM_RATE_32000 },
0087 { 44100, VIRTIO_SND_PCM_RATE_44100 },
0088 { 48000, VIRTIO_SND_PCM_RATE_48000 },
0089 { 64000, VIRTIO_SND_PCM_RATE_64000 },
0090 { 88200, VIRTIO_SND_PCM_RATE_88200 },
0091 { 96000, VIRTIO_SND_PCM_RATE_96000 },
0092 { 176400, VIRTIO_SND_PCM_RATE_176400 },
0093 { 192000, VIRTIO_SND_PCM_RATE_192000 }
0094 };
0095
0096 static int virtsnd_pcm_sync_stop(struct snd_pcm_substream *substream);
0097
0098
0099
0100
0101
0102
0103
0104
0105 static int virtsnd_pcm_open(struct snd_pcm_substream *substream)
0106 {
0107 struct virtio_pcm *vpcm = snd_pcm_substream_chip(substream);
0108 struct virtio_pcm_stream *vs = &vpcm->streams[substream->stream];
0109 struct virtio_pcm_substream *vss = vs->substreams[substream->number];
0110
0111 substream->runtime->hw = vss->hw;
0112 substream->private_data = vss;
0113
0114 snd_pcm_hw_constraint_integer(substream->runtime,
0115 SNDRV_PCM_HW_PARAM_PERIODS);
0116
0117 vss->stopped = !!virtsnd_pcm_msg_pending_num(vss);
0118 vss->suspended = false;
0119
0120
0121
0122
0123
0124
0125 return virtsnd_pcm_sync_stop(substream);
0126 }
0127
0128
0129
0130
0131
0132
0133
0134
0135 static int virtsnd_pcm_close(struct snd_pcm_substream *substream)
0136 {
0137 return 0;
0138 }
0139
0140
0141
0142
0143
0144
0145
0146
0147
0148
0149
0150
0151
0152
0153 static int virtsnd_pcm_dev_set_params(struct virtio_pcm_substream *vss,
0154 unsigned int buffer_bytes,
0155 unsigned int period_bytes,
0156 unsigned int channels,
0157 snd_pcm_format_t format,
0158 unsigned int rate)
0159 {
0160 struct virtio_snd_msg *msg;
0161 struct virtio_snd_pcm_set_params *request;
0162 unsigned int i;
0163 int vformat = -1;
0164 int vrate = -1;
0165
0166 for (i = 0; i < ARRAY_SIZE(g_a2v_format_map); ++i)
0167 if (g_a2v_format_map[i].alsa_bit == format) {
0168 vformat = g_a2v_format_map[i].vio_bit;
0169
0170 break;
0171 }
0172
0173 for (i = 0; i < ARRAY_SIZE(g_a2v_rate_map); ++i)
0174 if (g_a2v_rate_map[i].rate == rate) {
0175 vrate = g_a2v_rate_map[i].vio_bit;
0176
0177 break;
0178 }
0179
0180 if (vformat == -1 || vrate == -1)
0181 return -EINVAL;
0182
0183 msg = virtsnd_pcm_ctl_msg_alloc(vss, VIRTIO_SND_R_PCM_SET_PARAMS,
0184 GFP_KERNEL);
0185 if (!msg)
0186 return -ENOMEM;
0187
0188 request = virtsnd_ctl_msg_request(msg);
0189 request->buffer_bytes = cpu_to_le32(buffer_bytes);
0190 request->period_bytes = cpu_to_le32(period_bytes);
0191 request->channels = channels;
0192 request->format = vformat;
0193 request->rate = vrate;
0194
0195 if (vss->features & (1U << VIRTIO_SND_PCM_F_MSG_POLLING))
0196 request->features |=
0197 cpu_to_le32(1U << VIRTIO_SND_PCM_F_MSG_POLLING);
0198
0199 if (vss->features & (1U << VIRTIO_SND_PCM_F_EVT_XRUNS))
0200 request->features |=
0201 cpu_to_le32(1U << VIRTIO_SND_PCM_F_EVT_XRUNS);
0202
0203 return virtsnd_ctl_msg_send_sync(vss->snd, msg);
0204 }
0205
0206
0207
0208
0209
0210
0211
0212
0213
0214 static int virtsnd_pcm_hw_params(struct snd_pcm_substream *substream,
0215 struct snd_pcm_hw_params *hw_params)
0216 {
0217 struct virtio_pcm_substream *vss = snd_pcm_substream_chip(substream);
0218 struct virtio_device *vdev = vss->snd->vdev;
0219 int rc;
0220
0221 if (virtsnd_pcm_msg_pending_num(vss)) {
0222 dev_err(&vdev->dev, "SID %u: invalid I/O queue state\n",
0223 vss->sid);
0224 return -EBADFD;
0225 }
0226
0227 rc = virtsnd_pcm_dev_set_params(vss, params_buffer_bytes(hw_params),
0228 params_period_bytes(hw_params),
0229 params_channels(hw_params),
0230 params_format(hw_params),
0231 params_rate(hw_params));
0232 if (rc)
0233 return rc;
0234
0235
0236
0237
0238
0239 virtsnd_pcm_msg_free(vss);
0240
0241 return virtsnd_pcm_msg_alloc(vss, params_periods(hw_params),
0242 params_period_bytes(hw_params));
0243 }
0244
0245
0246
0247
0248
0249
0250
0251
0252 static int virtsnd_pcm_hw_free(struct snd_pcm_substream *substream)
0253 {
0254 struct virtio_pcm_substream *vss = snd_pcm_substream_chip(substream);
0255
0256
0257 if (!virtsnd_pcm_msg_pending_num(vss))
0258 virtsnd_pcm_msg_free(vss);
0259
0260 return 0;
0261 }
0262
0263
0264
0265
0266
0267
0268
0269
0270 static int virtsnd_pcm_prepare(struct snd_pcm_substream *substream)
0271 {
0272 struct virtio_pcm_substream *vss = snd_pcm_substream_chip(substream);
0273 struct virtio_device *vdev = vss->snd->vdev;
0274 struct virtio_snd_msg *msg;
0275
0276 if (!vss->suspended) {
0277 if (virtsnd_pcm_msg_pending_num(vss)) {
0278 dev_err(&vdev->dev, "SID %u: invalid I/O queue state\n",
0279 vss->sid);
0280 return -EBADFD;
0281 }
0282
0283 vss->buffer_bytes = snd_pcm_lib_buffer_bytes(substream);
0284 vss->hw_ptr = 0;
0285 vss->msg_last_enqueued = -1;
0286 } else {
0287 struct snd_pcm_runtime *runtime = substream->runtime;
0288 unsigned int buffer_bytes = snd_pcm_lib_buffer_bytes(substream);
0289 unsigned int period_bytes = snd_pcm_lib_period_bytes(substream);
0290 int rc;
0291
0292 rc = virtsnd_pcm_dev_set_params(vss, buffer_bytes, period_bytes,
0293 runtime->channels,
0294 runtime->format, runtime->rate);
0295 if (rc)
0296 return rc;
0297 }
0298
0299 vss->xfer_xrun = false;
0300 vss->suspended = false;
0301 vss->msg_count = 0;
0302
0303 msg = virtsnd_pcm_ctl_msg_alloc(vss, VIRTIO_SND_R_PCM_PREPARE,
0304 GFP_KERNEL);
0305 if (!msg)
0306 return -ENOMEM;
0307
0308 return virtsnd_ctl_msg_send_sync(vss->snd, msg);
0309 }
0310
0311
0312
0313
0314
0315
0316
0317
0318
0319
0320 static int virtsnd_pcm_trigger(struct snd_pcm_substream *substream, int command)
0321 {
0322 struct virtio_pcm_substream *vss = snd_pcm_substream_chip(substream);
0323 struct virtio_snd *snd = vss->snd;
0324 struct virtio_snd_queue *queue;
0325 struct virtio_snd_msg *msg;
0326 unsigned long flags;
0327 int rc;
0328
0329 switch (command) {
0330 case SNDRV_PCM_TRIGGER_START:
0331 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
0332 queue = virtsnd_pcm_queue(vss);
0333
0334 spin_lock_irqsave(&queue->lock, flags);
0335 spin_lock(&vss->lock);
0336 rc = virtsnd_pcm_msg_send(vss);
0337 if (!rc)
0338 vss->xfer_enabled = true;
0339 spin_unlock(&vss->lock);
0340 spin_unlock_irqrestore(&queue->lock, flags);
0341 if (rc)
0342 return rc;
0343
0344 msg = virtsnd_pcm_ctl_msg_alloc(vss, VIRTIO_SND_R_PCM_START,
0345 GFP_KERNEL);
0346 if (!msg) {
0347 spin_lock_irqsave(&vss->lock, flags);
0348 vss->xfer_enabled = false;
0349 spin_unlock_irqrestore(&vss->lock, flags);
0350
0351 return -ENOMEM;
0352 }
0353
0354 return virtsnd_ctl_msg_send_sync(snd, msg);
0355 case SNDRV_PCM_TRIGGER_SUSPEND:
0356 vss->suspended = true;
0357 fallthrough;
0358 case SNDRV_PCM_TRIGGER_STOP:
0359 vss->stopped = true;
0360 fallthrough;
0361 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
0362 spin_lock_irqsave(&vss->lock, flags);
0363 vss->xfer_enabled = false;
0364 spin_unlock_irqrestore(&vss->lock, flags);
0365
0366 msg = virtsnd_pcm_ctl_msg_alloc(vss, VIRTIO_SND_R_PCM_STOP,
0367 GFP_KERNEL);
0368 if (!msg)
0369 return -ENOMEM;
0370
0371 return virtsnd_ctl_msg_send_sync(snd, msg);
0372 default:
0373 return -EINVAL;
0374 }
0375 }
0376
0377
0378
0379
0380
0381
0382
0383
0384
0385
0386
0387 static int virtsnd_pcm_sync_stop(struct snd_pcm_substream *substream)
0388 {
0389 struct virtio_pcm_substream *vss = snd_pcm_substream_chip(substream);
0390 struct virtio_snd *snd = vss->snd;
0391 struct virtio_snd_msg *msg;
0392 unsigned int js = msecs_to_jiffies(virtsnd_msg_timeout_ms);
0393 int rc;
0394
0395 cancel_work_sync(&vss->elapsed_period);
0396
0397 if (!vss->stopped)
0398 return 0;
0399
0400 msg = virtsnd_pcm_ctl_msg_alloc(vss, VIRTIO_SND_R_PCM_RELEASE,
0401 GFP_KERNEL);
0402 if (!msg)
0403 return -ENOMEM;
0404
0405 rc = virtsnd_ctl_msg_send_sync(snd, msg);
0406 if (rc)
0407 return rc;
0408
0409
0410
0411
0412
0413
0414
0415 rc = wait_event_interruptible_timeout(vss->msg_empty,
0416 !virtsnd_pcm_msg_pending_num(vss),
0417 js);
0418 if (rc <= 0) {
0419 dev_warn(&snd->vdev->dev, "SID %u: failed to flush I/O queue\n",
0420 vss->sid);
0421
0422 return !rc ? -ETIMEDOUT : rc;
0423 }
0424
0425 vss->stopped = false;
0426
0427 return 0;
0428 }
0429
0430
0431
0432
0433
0434
0435
0436
0437
0438 static snd_pcm_uframes_t
0439 virtsnd_pcm_pointer(struct snd_pcm_substream *substream)
0440 {
0441 struct virtio_pcm_substream *vss = snd_pcm_substream_chip(substream);
0442 snd_pcm_uframes_t hw_ptr = SNDRV_PCM_POS_XRUN;
0443 unsigned long flags;
0444
0445 spin_lock_irqsave(&vss->lock, flags);
0446 if (!vss->xfer_xrun)
0447 hw_ptr = bytes_to_frames(substream->runtime, vss->hw_ptr);
0448 spin_unlock_irqrestore(&vss->lock, flags);
0449
0450 return hw_ptr;
0451 }
0452
0453
0454 const struct snd_pcm_ops virtsnd_pcm_ops = {
0455 .open = virtsnd_pcm_open,
0456 .close = virtsnd_pcm_close,
0457 .ioctl = snd_pcm_lib_ioctl,
0458 .hw_params = virtsnd_pcm_hw_params,
0459 .hw_free = virtsnd_pcm_hw_free,
0460 .prepare = virtsnd_pcm_prepare,
0461 .trigger = virtsnd_pcm_trigger,
0462 .sync_stop = virtsnd_pcm_sync_stop,
0463 .pointer = virtsnd_pcm_pointer,
0464 };