aio-compress.c (11816B)
1// SPDX-License-Identifier: GPL-2.0 2// 3// Socionext UniPhier AIO Compress Audio driver. 4// 5// Copyright (c) 2017-2018 Socionext Inc. 6 7#include <linux/bitfield.h> 8#include <linux/circ_buf.h> 9#include <linux/dma-mapping.h> 10#include <linux/errno.h> 11#include <linux/kernel.h> 12#include <linux/module.h> 13#include <sound/core.h> 14#include <sound/pcm.h> 15#include <sound/soc.h> 16 17#include "aio.h" 18 19static int uniphier_aio_compr_prepare(struct snd_soc_component *component, 20 struct snd_compr_stream *cstream); 21static int uniphier_aio_compr_hw_free(struct snd_soc_component *component, 22 struct snd_compr_stream *cstream); 23 24static int uniphier_aio_comprdma_new(struct snd_soc_pcm_runtime *rtd) 25{ 26 struct snd_compr *compr = rtd->compr; 27 struct device *dev = compr->card->dev; 28 struct uniphier_aio *aio = uniphier_priv(asoc_rtd_to_cpu(rtd, 0)); 29 struct uniphier_aio_sub *sub = &aio->sub[compr->direction]; 30 size_t size = AUD_RING_SIZE; 31 int dma_dir = DMA_FROM_DEVICE, ret; 32 33 ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(33)); 34 if (ret) 35 return ret; 36 37 sub->compr_area = kzalloc(size, GFP_KERNEL); 38 if (!sub->compr_area) 39 return -ENOMEM; 40 41 if (sub->swm->dir == PORT_DIR_OUTPUT) 42 dma_dir = DMA_TO_DEVICE; 43 44 sub->compr_addr = dma_map_single(dev, sub->compr_area, size, dma_dir); 45 if (dma_mapping_error(dev, sub->compr_addr)) { 46 kfree(sub->compr_area); 47 sub->compr_area = NULL; 48 49 return -ENOMEM; 50 } 51 52 sub->compr_bytes = size; 53 54 return 0; 55} 56 57static int uniphier_aio_comprdma_free(struct snd_soc_pcm_runtime *rtd) 58{ 59 struct snd_compr *compr = rtd->compr; 60 struct device *dev = compr->card->dev; 61 struct uniphier_aio *aio = uniphier_priv(asoc_rtd_to_cpu(rtd, 0)); 62 struct uniphier_aio_sub *sub = &aio->sub[compr->direction]; 63 int dma_dir = DMA_FROM_DEVICE; 64 65 if (sub->swm->dir == PORT_DIR_OUTPUT) 66 dma_dir = DMA_TO_DEVICE; 67 68 dma_unmap_single(dev, sub->compr_addr, sub->compr_bytes, dma_dir); 69 kfree(sub->compr_area); 70 sub->compr_area = NULL; 71 72 return 0; 73} 74 75static int uniphier_aio_compr_open(struct snd_soc_component *component, 76 struct snd_compr_stream *cstream) 77{ 78 struct snd_soc_pcm_runtime *rtd = cstream->private_data; 79 struct uniphier_aio *aio = uniphier_priv(asoc_rtd_to_cpu(rtd, 0)); 80 struct uniphier_aio_sub *sub = &aio->sub[cstream->direction]; 81 int ret; 82 83 if (sub->cstream) 84 return -EBUSY; 85 86 sub->cstream = cstream; 87 sub->pass_through = 1; 88 sub->use_mmap = false; 89 90 ret = uniphier_aio_comprdma_new(rtd); 91 if (ret) 92 return ret; 93 94 ret = aio_init(sub); 95 if (ret) 96 return ret; 97 98 return 0; 99} 100 101static int uniphier_aio_compr_free(struct snd_soc_component *component, 102 struct snd_compr_stream *cstream) 103{ 104 struct snd_soc_pcm_runtime *rtd = cstream->private_data; 105 struct uniphier_aio *aio = uniphier_priv(asoc_rtd_to_cpu(rtd, 0)); 106 struct uniphier_aio_sub *sub = &aio->sub[cstream->direction]; 107 int ret; 108 109 ret = uniphier_aio_compr_hw_free(component, cstream); 110 if (ret) 111 return ret; 112 ret = uniphier_aio_comprdma_free(rtd); 113 if (ret) 114 return ret; 115 116 sub->cstream = NULL; 117 118 return 0; 119} 120 121static int uniphier_aio_compr_get_params(struct snd_soc_component *component, 122 struct snd_compr_stream *cstream, 123 struct snd_codec *params) 124{ 125 struct snd_soc_pcm_runtime *rtd = cstream->private_data; 126 struct uniphier_aio *aio = uniphier_priv(asoc_rtd_to_cpu(rtd, 0)); 127 struct uniphier_aio_sub *sub = &aio->sub[cstream->direction]; 128 129 *params = sub->cparams.codec; 130 131 return 0; 132} 133 134static int uniphier_aio_compr_set_params(struct snd_soc_component *component, 135 struct snd_compr_stream *cstream, 136 struct snd_compr_params *params) 137{ 138 struct snd_soc_pcm_runtime *rtd = cstream->private_data; 139 struct uniphier_aio *aio = uniphier_priv(asoc_rtd_to_cpu(rtd, 0)); 140 struct uniphier_aio_sub *sub = &aio->sub[cstream->direction]; 141 struct device *dev = &aio->chip->pdev->dev; 142 143 if (params->codec.id != SND_AUDIOCODEC_IEC61937) { 144 dev_err(dev, "Codec ID is not supported(%d)\n", 145 params->codec.id); 146 return -EINVAL; 147 } 148 if (params->codec.profile != SND_AUDIOPROFILE_IEC61937_SPDIF) { 149 dev_err(dev, "Codec profile is not supported(%d)\n", 150 params->codec.profile); 151 return -EINVAL; 152 } 153 154 /* IEC frame type will be changed after received valid data */ 155 sub->iec_pc = IEC61937_PC_AAC; 156 157 sub->cparams = *params; 158 sub->setting = 1; 159 160 aio_port_reset(sub); 161 aio_src_reset(sub); 162 163 return uniphier_aio_compr_prepare(component, cstream); 164} 165 166static int uniphier_aio_compr_hw_free(struct snd_soc_component *component, 167 struct snd_compr_stream *cstream) 168{ 169 struct snd_soc_pcm_runtime *rtd = cstream->private_data; 170 struct uniphier_aio *aio = uniphier_priv(asoc_rtd_to_cpu(rtd, 0)); 171 struct uniphier_aio_sub *sub = &aio->sub[cstream->direction]; 172 173 sub->setting = 0; 174 175 return 0; 176} 177 178static int uniphier_aio_compr_prepare(struct snd_soc_component *component, 179 struct snd_compr_stream *cstream) 180{ 181 struct snd_soc_pcm_runtime *rtd = cstream->private_data; 182 struct snd_compr_runtime *runtime = cstream->runtime; 183 struct uniphier_aio *aio = uniphier_priv(asoc_rtd_to_cpu(rtd, 0)); 184 struct uniphier_aio_sub *sub = &aio->sub[cstream->direction]; 185 int bytes = runtime->fragment_size; 186 unsigned long flags; 187 int ret; 188 189 ret = aiodma_ch_set_param(sub); 190 if (ret) 191 return ret; 192 193 spin_lock_irqsave(&sub->lock, flags); 194 ret = aiodma_rb_set_buffer(sub, sub->compr_addr, 195 sub->compr_addr + sub->compr_bytes, 196 bytes); 197 spin_unlock_irqrestore(&sub->lock, flags); 198 if (ret) 199 return ret; 200 201 ret = aio_port_set_param(sub, sub->pass_through, &sub->params); 202 if (ret) 203 return ret; 204 ret = aio_oport_set_stream_type(sub, sub->iec_pc); 205 if (ret) 206 return ret; 207 aio_port_set_enable(sub, 1); 208 209 ret = aio_if_set_param(sub, sub->pass_through); 210 if (ret) 211 return ret; 212 213 return 0; 214} 215 216static int uniphier_aio_compr_trigger(struct snd_soc_component *component, 217 struct snd_compr_stream *cstream, 218 int cmd) 219{ 220 struct snd_soc_pcm_runtime *rtd = cstream->private_data; 221 struct snd_compr_runtime *runtime = cstream->runtime; 222 struct uniphier_aio *aio = uniphier_priv(asoc_rtd_to_cpu(rtd, 0)); 223 struct uniphier_aio_sub *sub = &aio->sub[cstream->direction]; 224 struct device *dev = &aio->chip->pdev->dev; 225 int bytes = runtime->fragment_size, ret = 0; 226 unsigned long flags; 227 228 spin_lock_irqsave(&sub->lock, flags); 229 switch (cmd) { 230 case SNDRV_PCM_TRIGGER_START: 231 aiodma_rb_sync(sub, sub->compr_addr, sub->compr_bytes, bytes); 232 aiodma_ch_set_enable(sub, 1); 233 sub->running = 1; 234 235 break; 236 case SNDRV_PCM_TRIGGER_STOP: 237 sub->running = 0; 238 aiodma_ch_set_enable(sub, 0); 239 240 break; 241 default: 242 dev_warn(dev, "Unknown trigger(%d)\n", cmd); 243 ret = -EINVAL; 244 } 245 spin_unlock_irqrestore(&sub->lock, flags); 246 247 return ret; 248} 249 250static int uniphier_aio_compr_pointer(struct snd_soc_component *component, 251 struct snd_compr_stream *cstream, 252 struct snd_compr_tstamp *tstamp) 253{ 254 struct snd_soc_pcm_runtime *rtd = cstream->private_data; 255 struct snd_compr_runtime *runtime = cstream->runtime; 256 struct uniphier_aio *aio = uniphier_priv(asoc_rtd_to_cpu(rtd, 0)); 257 struct uniphier_aio_sub *sub = &aio->sub[cstream->direction]; 258 int bytes = runtime->fragment_size; 259 unsigned long flags; 260 u32 pos; 261 262 spin_lock_irqsave(&sub->lock, flags); 263 264 aiodma_rb_sync(sub, sub->compr_addr, sub->compr_bytes, bytes); 265 266 if (sub->swm->dir == PORT_DIR_OUTPUT) { 267 pos = sub->rd_offs; 268 /* Size of AIO output format is double of IEC61937 */ 269 tstamp->copied_total = sub->rd_total / 2; 270 } else { 271 pos = sub->wr_offs; 272 tstamp->copied_total = sub->rd_total; 273 } 274 tstamp->byte_offset = pos; 275 276 spin_unlock_irqrestore(&sub->lock, flags); 277 278 return 0; 279} 280 281static int aio_compr_send_to_hw(struct uniphier_aio_sub *sub, 282 char __user *buf, size_t dstsize) 283{ 284 u32 __user *srcbuf = (u32 __user *)buf; 285 u32 *dstbuf = (u32 *)(sub->compr_area + sub->wr_offs); 286 int src = 0, dst = 0, ret; 287 u32 frm, frm_a, frm_b; 288 289 while (dstsize > 0) { 290 ret = get_user(frm, srcbuf + src); 291 if (ret) 292 return ret; 293 src++; 294 295 frm_a = frm & 0xffff; 296 frm_b = (frm >> 16) & 0xffff; 297 298 if (frm == IEC61937_HEADER_SIGN) { 299 frm_a |= 0x01000000; 300 301 /* Next data is Pc and Pd */ 302 sub->iec_header = true; 303 } else { 304 u16 pc = be16_to_cpu((__be16)frm_a); 305 306 if (sub->iec_header && sub->iec_pc != pc) { 307 /* Force overwrite IEC frame type */ 308 sub->iec_pc = pc; 309 ret = aio_oport_set_stream_type(sub, pc); 310 if (ret) 311 return ret; 312 } 313 sub->iec_header = false; 314 } 315 dstbuf[dst++] = frm_a; 316 dstbuf[dst++] = frm_b; 317 318 dstsize -= sizeof(u32) * 2; 319 } 320 321 return 0; 322} 323 324static int uniphier_aio_compr_copy(struct snd_soc_component *component, 325 struct snd_compr_stream *cstream, 326 char __user *buf, size_t count) 327{ 328 struct snd_soc_pcm_runtime *rtd = cstream->private_data; 329 struct snd_compr_runtime *runtime = cstream->runtime; 330 struct device *carddev = rtd->compr->card->dev; 331 struct uniphier_aio *aio = uniphier_priv(asoc_rtd_to_cpu(rtd, 0)); 332 struct uniphier_aio_sub *sub = &aio->sub[cstream->direction]; 333 size_t cnt = min_t(size_t, count, aio_rb_space_to_end(sub) / 2); 334 int bytes = runtime->fragment_size; 335 unsigned long flags; 336 size_t s; 337 int ret; 338 339 if (cnt < sizeof(u32)) 340 return 0; 341 342 if (sub->swm->dir == PORT_DIR_OUTPUT) { 343 dma_addr_t dmapos = sub->compr_addr + sub->wr_offs; 344 345 /* Size of AIO output format is double of IEC61937 */ 346 s = cnt * 2; 347 348 dma_sync_single_for_cpu(carddev, dmapos, s, DMA_TO_DEVICE); 349 ret = aio_compr_send_to_hw(sub, buf, s); 350 dma_sync_single_for_device(carddev, dmapos, s, DMA_TO_DEVICE); 351 } else { 352 dma_addr_t dmapos = sub->compr_addr + sub->rd_offs; 353 354 s = cnt; 355 356 dma_sync_single_for_cpu(carddev, dmapos, s, DMA_FROM_DEVICE); 357 ret = copy_to_user(buf, sub->compr_area + sub->rd_offs, s); 358 dma_sync_single_for_device(carddev, dmapos, s, DMA_FROM_DEVICE); 359 } 360 if (ret) 361 return -EFAULT; 362 363 spin_lock_irqsave(&sub->lock, flags); 364 365 sub->threshold = 2 * bytes; 366 aiodma_rb_set_threshold(sub, sub->compr_bytes, 2 * bytes); 367 368 if (sub->swm->dir == PORT_DIR_OUTPUT) { 369 sub->wr_offs += s; 370 if (sub->wr_offs >= sub->compr_bytes) 371 sub->wr_offs -= sub->compr_bytes; 372 } else { 373 sub->rd_offs += s; 374 if (sub->rd_offs >= sub->compr_bytes) 375 sub->rd_offs -= sub->compr_bytes; 376 } 377 aiodma_rb_sync(sub, sub->compr_addr, sub->compr_bytes, bytes); 378 379 spin_unlock_irqrestore(&sub->lock, flags); 380 381 return cnt; 382} 383 384static int uniphier_aio_compr_get_caps(struct snd_soc_component *component, 385 struct snd_compr_stream *cstream, 386 struct snd_compr_caps *caps) 387{ 388 caps->num_codecs = 1; 389 caps->min_fragment_size = AUD_MIN_FRAGMENT_SIZE; 390 caps->max_fragment_size = AUD_MAX_FRAGMENT_SIZE; 391 caps->min_fragments = AUD_MIN_FRAGMENT; 392 caps->max_fragments = AUD_MAX_FRAGMENT; 393 caps->codecs[0] = SND_AUDIOCODEC_IEC61937; 394 395 return 0; 396} 397 398static const struct snd_compr_codec_caps caps_iec = { 399 .num_descriptors = 1, 400 .descriptor[0].max_ch = 8, 401 .descriptor[0].num_sample_rates = 0, 402 .descriptor[0].num_bitrates = 0, 403 .descriptor[0].profiles = SND_AUDIOPROFILE_IEC61937_SPDIF, 404 .descriptor[0].modes = SND_AUDIOMODE_IEC_AC3 | 405 SND_AUDIOMODE_IEC_MPEG1 | 406 SND_AUDIOMODE_IEC_MP3 | 407 SND_AUDIOMODE_IEC_DTS, 408 .descriptor[0].formats = 0, 409}; 410 411static int uniphier_aio_compr_get_codec_caps(struct snd_soc_component *component, 412 struct snd_compr_stream *stream, 413 struct snd_compr_codec_caps *codec) 414{ 415 if (codec->codec == SND_AUDIOCODEC_IEC61937) 416 *codec = caps_iec; 417 else 418 return -EINVAL; 419 420 return 0; 421} 422 423const struct snd_compress_ops uniphier_aio_compress_ops = { 424 .open = uniphier_aio_compr_open, 425 .free = uniphier_aio_compr_free, 426 .get_params = uniphier_aio_compr_get_params, 427 .set_params = uniphier_aio_compr_set_params, 428 .trigger = uniphier_aio_compr_trigger, 429 .pointer = uniphier_aio_compr_pointer, 430 .copy = uniphier_aio_compr_copy, 431 .get_caps = uniphier_aio_compr_get_caps, 432 .get_codec_caps = uniphier_aio_compr_get_codec_caps, 433};