1// Copyright 2018 The Fuchsia Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include <digest/digest.h> 6#include <fbl/algorithm.h> 7#include <fbl/alloc_checker.h> 8#include <fbl/limits.h> 9#include <soc/aml-s912/s912-audio.h> 10 11#include "hdmitx.h" 12#include "vim-display.h" 13#include "vim-spdif-audio-stream.h" 14 15#define SHIFTED_MASK(_name) ((_name##_MASK) << (_name##_SHIFT)) 16#define SHIFTED_VAL(_name, _val) ((_val & _name##_MASK) << _name##_SHIFT) 17#define MOD_FIELD(_name, _val) SHFTED_MASK(_name), SHIFTED_VAL(_name, _val) 18 19namespace audio { 20namespace vim2 { 21 22namespace { 23// 128 bytes per frame. Why? I have no idea. This is clearly not an audio 24// frame, nor is it a SPDIF block. I suspect that it may be the amount of 25// data which the DMA engine tries to fetch each time it jumps on the bus, 26// but I don't really know for certain. 27constexpr uint32_t AIU_958_BYTES_PER_FRAME = 128; 28 29static const struct { 30 uint32_t rate; 31 uint32_t N; 32} STANDARD_FRAME_RATE_N_LUT[] = { 33 { .rate = 32000, .N = 4096 }, 34 { .rate = 48000, .N = 6144 }, 35 { .rate = 96000, .N = 12288 }, 36 { .rate = 192000, .N = 25467 }, 37 { .rate = 44100, .N = 6272 }, 38 { .rate = 88200, .N = 12544 }, 39 { .rate = 176400, .N = 28028 }, 40}; 41} // anon namespace 42 43Vim2SpdifAudioStream::Vim2SpdifAudioStream(const vim2_display* display, 44 fbl::RefPtr<Registers> regs, 45 fbl::RefPtr<RefCountedVmo> ring_buffer_vmo, 46 fzl::PinnedVmo pinned_ring_buffer, 47 uint64_t display_id) 48 : SimpleAudioStream(display->parent, false), 49 display_(display), 50 display_id_(display_id), 51 regs_(fbl::move(regs)), 52 ring_buffer_vmo_(fbl::move(ring_buffer_vmo)), 53 pinned_ring_buffer_(fbl::move(pinned_ring_buffer)) { 54} 55 56void Vim2SpdifAudioStream::ShutdownHook() { 57 vim2_display_disable_audio(display_); 58 Disable(*regs_); 59} 60 61void Vim2SpdifAudioStream::RingBufferShutdown() { 62 vim2_display_disable_audio(display_); 63} 64 65zx_status_t Vim2SpdifAudioStream::ChangeFormat(const audio_proto::StreamSetFmtReq& req) { 66 // Figure out the maximum number of audio frames we can fit into our ring 67 // buffer while still guaranteeing... 68 // 69 // 1) The buffer is a multiple of audio frame size 70 // 2) The buffer is a multiple of AIU frame size 71 // 72 ZX_DEBUG_ASSERT(frame_size_ > 0); 73 usable_buffer_size_ = fbl::round_down(static_cast<uint32_t>(pinned_ring_buffer_.region(0).size), 74 fbl::lcm(AIU_958_BYTES_PER_FRAME, frame_size_)); 75 76 // TODO(johngro): figure out the proper value for this 77 fifo_depth_ = 512; 78 79 // TODO(johngro): fill this out based on the estimate given by EDID (if any) 80 external_delay_nsec_ = 0; 81 82 // Figure out the proper values for N and CTS based on this audio mode and 83 // pixel clock. 84 // Start by going through our table of standard audio modes for standard 85 // audio clocks. If we cannot find the answer in the LUT, then fall back on 86 // computing the answer on the fly using the recommended N as a starting 87 // point to compute CTS. 88 // 89 // See section 7.2 (Audio Sample Clock Capture and Regeneration) of the HDMI 90 // 1.3a spec (or later) for details. 91 uint32_t N = 0; 92 for (const auto& entry : STANDARD_FRAME_RATE_N_LUT) { 93 if (entry.rate == req.frames_per_second) { 94 N = entry.N; 95 break; 96 } 97 } 98 99 // This should never happen (As we are not advertising any frame rates which 100 // are not in the LUT), but JiC. 101 if (!N) { 102 zxlogf(ERROR, "Failed to find starting N value for audio frame rate (%u).\n", 103 req.frames_per_second); 104 return ZX_ERR_NOT_SUPPORTED; 105 } 106 107 // Given our suggested starting value for N, CTS should be computed as... 108 // 109 // CTS = pixel_clock * N / (128 * audio_frame_rate) 110 // 111 // Since our pixel clock is already expressed in KHz, this becomes 112 // CTS = pkhz * N * 1000 / (128 * audio_frame_rate) 113 // = pkhz * N * 125 / (16 * audio_frame_rate) 114 // 115 // If our numerator is not divisible by 16 * frame_rate, then we would (in 116 // theory) need to dither the N/CTS values being sent, which is something we 117 // currently do not support. For now, if this happens, return an error 118 // instead. 119 uint64_t numer = static_cast<uint64_t>(display_->p->timings.pfreq) * N * 125; 120 uint32_t denom = req.frames_per_second << 4; 121 122 if (numer % denom) { 123 zxlogf(ERROR, "Failed to find CTS value (pclk %u, N %u, frame_rate %u)\n", 124 display_->p->timings.pfreq, N, req.frames_per_second); 125 return ZX_ERR_NOT_SUPPORTED; 126 } 127 128 uint32_t CTS = static_cast<uint32_t>(numer / denom); 129 uint32_t bits_per_sample; 130 switch (req.sample_format) { 131 case AUDIO_SAMPLE_FORMAT_16BIT: bits_per_sample = 16; break; 132 case AUDIO_SAMPLE_FORMAT_24BIT_PACKED: __FALLTHROUGH; 133 case AUDIO_SAMPLE_FORMAT_24BIT_IN32: bits_per_sample = 24; break; 134 default: 135 zxlogf(ERROR, "Unsupported requested sample format (0x%08x)!\n", req.sample_format); 136 return ZX_ERR_NOT_SUPPORTED; 137 } 138 139 // Set up the registers to match our format choice. 140 SetMode(req.frames_per_second, req.sample_format); 141 142 // Tell the HDMI driver about the mode we just configured. 143 zx_status_t res; 144 res = vim2_display_configure_audio_mode(display_, 145 N, CTS, 146 req.frames_per_second, bits_per_sample); 147 if (res != ZX_OK) { 148 zxlogf(ERROR, "Failed to configure VIM2 HDMI TX audio parameters! (res %d)\n", res); 149 return res; 150 } 151 152 return ZX_OK; 153} 154 155zx_status_t Vim2SpdifAudioStream::GetBuffer(const audio_proto::RingBufGetBufferReq& req, 156 uint32_t* out_num_rb_frames, 157 zx::vmo* out_buffer) { 158 uint32_t rb_frames = usable_buffer_size_ / frame_size_; 159 if (req.min_ring_buffer_frames > rb_frames) { 160 return ZX_ERR_OUT_OF_RANGE; 161 } 162 163 constexpr uint32_t rights = ZX_RIGHT_READ | ZX_RIGHT_WRITE | ZX_RIGHT_MAP | ZX_RIGHT_TRANSFER; 164 zx_status_t res = ring_buffer_vmo_->vmo().duplicate(rights, out_buffer); 165 if (res != ZX_OK) { 166 return res; 167 } 168 169 *out_num_rb_frames = rb_frames; 170 SetupBuffer(); 171 return ZX_OK; 172} 173 174zx_status_t Vim2SpdifAudioStream::Start(uint64_t* out_start_time) { 175 uint64_t a, b; 176 177 Mute(cur_gain_state_.cur_mute); 178 a = zx_clock_get(ZX_CLOCK_MONOTONIC); 179 Enable(); 180 b = zx_clock_get(ZX_CLOCK_MONOTONIC); 181 *out_start_time = ((b - a) >> 1) + a; 182 183 return ZX_OK; 184} 185 186zx_status_t Vim2SpdifAudioStream::Stop() { 187 Disable(*regs_); 188 Mute(false); 189 return ZX_OK; 190} 191 192zx_status_t Vim2SpdifAudioStream::SetGain(const audio_proto::SetGainReq& req) { 193 if (req.flags & AUDIO_SGF_MUTE_VALID) { 194 cur_gain_state_.cur_mute = ((req.flags & AUDIO_SGF_MUTE) != 0); 195 Mute(cur_gain_state_.cur_mute); 196 } 197 198 return ZX_OK; 199} 200 201zx_status_t Vim2SpdifAudioStream::Init() { 202 zx_status_t res; 203 204 if (!regs_ || !regs_->valid()) { 205 zxlogf(ERROR, "null or invalid registers in %s\n", __PRETTY_FUNCTION__); 206 return ZX_ERR_INVALID_ARGS; 207 } 208 209 Disable(*regs_); 210 211 if (!ring_buffer_vmo_ || !ring_buffer_vmo_->vmo().is_valid()) { 212 zxlogf(ERROR, "Bad ring buffer VMO passed to %s\n", __PRETTY_FUNCTION__); 213 return ZX_ERR_INVALID_ARGS; 214 } 215 216 // Set up the DMA addresses. 217 if ((pinned_ring_buffer_.region_count() != 1) || 218 (pinned_ring_buffer_.region(0).size < PAGE_SIZE) || 219 ((pinned_ring_buffer_.region(0).phys_addr + pinned_ring_buffer_.region(0).size) 220 >= fbl::numeric_limits<uint32_t>::max())) { 221 zxlogf(ERROR, "Bad ring buffer scatter/gather list passed to %s\n", __PRETTY_FUNCTION__); 222 return ZX_ERR_INVALID_ARGS; 223 } 224 225 res = CreateFormatList(); 226 if (res != ZX_OK) { 227 return res; 228 } 229 230 // Set our gain capabilities. 231 cur_gain_state_.cur_gain = 0.0; 232 cur_gain_state_.cur_mute = false; 233 cur_gain_state_.cur_agc = false; 234 235 cur_gain_state_.min_gain = 0.0; 236 cur_gain_state_.max_gain = 0.0; 237 cur_gain_state_.gain_step = 0.0; 238 cur_gain_state_.can_mute = true; 239 cur_gain_state_.can_agc = false; 240 241 // Set our device node name. 242 snprintf(device_name_, sizeof(device_name_), "vim2-spdif-out"); 243 244 // Create our unique ID by hashing portions of the EDID we get from our 245 // display. In particular, look for and hash... 246 // 247 // 1) The vendor/product ID. 248 // 2) The first monitor descriptor, if present. 249 // 3) The monitor serial number, if present. 250 // 251 // We deliberately do not simply hash contents the entire EDID. Timing 252 // and other configuration information can change, esp. when a device is 253 // connected to an AV receiver and changes are made to the processing 254 // configuration of the AVR. We want to focus on attempting to identify the 255 // device we are connected to, and not the mode that it is operating in. 256 // 257 // While we are parsing this information, also extract the manufacturer name 258 // (from the vendor/product ID section), and the device name (from the first 259 // monitor descriptor, if present). 260 // 261 // TODO(johngro): Someday, when this gets split into separate DAI/Codec 262 // drivers, this code belongs in the HDMI codec section of things. 263 digest::Digest sha; 264 res = sha.Init(); 265 if (res != ZX_OK) { 266 zxlogf(WARN, "Failed to initialize digest while computing unique ID. (res %d)\n", res); 267 return res; 268 } 269 270 // Seed our SHA with a constant number taken from 'uuidgen'. 271 static const uint8_t SEED[] = { 0xd8, 0x27, 0x52, 0xb7, 0x60, 0x9a, 0x46, 0xd4, 272 0xa6, 0xc4, 0xdc, 0x32, 0xf5, 0xce, 0x1b, 0x7d }; 273 sha.Update(SEED, sizeof(SEED)); 274 275 snprintf(mfr_name_, sizeof(mfr_name_), "%s", 276 strlen(display_->manufacturer_name) ? display_->manufacturer_name : "<unknown>"); 277 snprintf(prod_name_, sizeof(prod_name_), "%s", 278 strlen(display_->monitor_name) ? display_->monitor_name : "Generic HDMI"); 279 280 sha.Update(mfr_name_, strnlen(mfr_name_, sizeof(mfr_name_))); 281 sha.Update(prod_name_, strnlen(prod_name_, sizeof(prod_name_))); 282 sha.Update(display_->monitor_serial, 283 strnlen(display_->monitor_serial, sizeof(display_->monitor_serial))); 284 285 // Finish the SHA and attempt to copy as much of the results to our internal 286 // cached representation as we can. 287 uint8_t digest_out[digest::Digest::kLength]; 288 sha.Final(); 289 res = sha.CopyTo(digest_out, sizeof(digest_out)); 290 if (res != ZX_OK) { 291 zxlogf(ERROR, "Failed to copy digest while computing unique ID. (res %d)", res); 292 return res; 293 } 294 ::memset(unique_id_.data, 0, sizeof(unique_id_.data)); 295 ::memcpy(unique_id_.data, digest_out, fbl::min(sizeof(digest_out), sizeof(unique_id_.data))); 296 297 return ZX_OK; 298} 299 300void Vim2SpdifAudioStream::Disable(const Registers& regs) { 301 ZX_DEBUG_ASSERT(regs.valid()); 302 303 regs[AIU_958_DCU_FF_CTRL] = 0; // Disable the FIFO 304 regs.ClrBits(AIU_MEM_IEC958_CONTROL, 305 AIU_958_MCTRL_FILL_ENB | AIU_958_MCTRL_EMPTY_ENB); // Disable the DMA 306 regs[AIU_RST_SOFT] = AIU_RS_958_FAST_DOMAIN; // reset the unit 307} 308 309zx_status_t Vim2SpdifAudioStream::CreateFormatList() { 310 // Compute the list of audio formats that we support. To do this, we need 311 // to intersect the capabilities of the display sink we are connect to, with 312 // the capabilities of the S912 audio hardware. 313 // 314 // The DesignWare HDMI transmitter which is integrated into the S912 can be 315 // fed a couple of different ways; either from one or more I2S units acting 316 // in parallel, or one or more SPDIF units acting in parallel. Each unit 317 // can carry up to 2 channels of audio. The DesignWare block also has 318 // options to synthesize its own independent DMA engine (which would have 319 // been super convenient), but these features were not enabled when the S912 320 // was synthesized. 321 // 322 // The S912 has only 1 SPDIF unit (as well as only one I2S unit), which 323 // limits our maximum number of channels to 2. 324 // 325 // In addition, the way that the clocks are being set up on VIM2, there is 326 // no factor of 7 in the clock feeding the audio units. Because of this, we 327 // cannot generate any of the 44.1k family of audio rates. We can, however, 328 // generate clock rates up to 192KHz, and can generate 16, 20, and 24 bit audio. 329 for (unsigned i = 0; i < display_->audio_format_count; i++) { 330 audio_stream_format_range_t range; 331 zx_status_t status = display_->dc_cb->get_audio_format( 332 display_->dc_cb_ctx, display_->display_id, i, &range); 333 ZX_ASSERT(status == ZX_OK); 334 335 constexpr uint32_t SUPPORTED_FORMATS = AUDIO_SAMPLE_FORMAT_16BIT | 336 AUDIO_SAMPLE_FORMAT_24BIT_PACKED | AUDIO_SAMPLE_FORMAT_24BIT_IN32; 337 range.sample_formats = 338 static_cast<audio_sample_format_t>(range.sample_formats & SUPPORTED_FORMATS); 339 if (range.sample_formats == 0) { 340 continue; 341 } 342 343 // Require stereo 344 if (range.max_channels < 2) { 345 continue; 346 } 347 range.max_channels = fbl::min<uint8_t>(range.max_channels, 2); 348 349 constexpr uint32_t MIN_SUPPORTED_RATE = 32000; 350 constexpr uint32_t MAX_SUPPORTED_RATE = 192000; 351 range.flags &= ASF_RANGE_FLAG_FPS_48000_FAMILY; 352 if (range.flags == 0 353 || range.max_frames_per_second < MIN_SUPPORTED_RATE 354 || range.min_frames_per_second > MAX_SUPPORTED_RATE) { 355 continue; 356 } 357 range.max_frames_per_second = fbl::min(MAX_SUPPORTED_RATE, range.max_frames_per_second); 358 range.min_frames_per_second = fbl::max(MIN_SUPPORTED_RATE, range.min_frames_per_second); 359 360 fbl::AllocChecker ac; 361 supported_formats_.push_back(range, &ac); 362 if (!ac.check()) { 363 zxlogf(ERROR, "Out of memory attempting to construct supported format list.\n"); 364 return ZX_ERR_NO_MEMORY; 365 } 366 } 367 368 return ZX_OK; 369} 370 371void Vim2SpdifAudioStream::Enable() { 372 ZX_DEBUG_ASSERT((regs_ != nullptr) && regs_->valid()); 373 const auto& regs = *regs_; 374 375 regs[AIU_RST_SOFT] = AIU_RS_958_FAST_DOMAIN; // reset 376 377 // Force the next sample fetched from the FIFO to be the start of a 378 // frame by writing *any* value to the FORCE_LEFT register. 379 // 380 // Note: In the AmLogic documentation I have access to, this register is 381 // actually missing from the documentation (but mentioned briefly in the 382 // discussion of bit 13 of AIU_958_MISC). Notes left by the AM Logic driver 383 // author in other codebases seem to say that when the SPDIF serializer has 384 // been reset, that whether or not the next payload is supposed to be a left 385 // or right sample does not actually get reset. In order to get a proper 386 // sequence of marker bits transmitted, we are supposed to use the 387 // FORCE_LEFT register to reset this state as well any time we reset the 388 // SPDIF TX unit. 389 regs[AIU_958_FORCE_LEFT] = 0x00; 390 391 regs.SetBits(AIU_MEM_IEC958_CONTROL, 392 AIU_958_MCTRL_FILL_ENB | AIU_958_MCTRL_EMPTY_ENB); // Enable the DMA 393 regs.SetBits(AIU_958_DCU_FF_CTRL, AIU_958_DCU_FF_CTRL_ENB); // Enable the fifo 394} 395 396void Vim2SpdifAudioStream::SetupBuffer() { 397 ZX_DEBUG_ASSERT((regs_ != nullptr) && regs_->valid()); 398 const auto& regs = *regs_; 399 400 // Set up the DMA addresses. 401 ZX_DEBUG_ASSERT(pinned_ring_buffer_.region_count() == 1); 402 ZX_DEBUG_ASSERT(pinned_ring_buffer_.region(0).size >= 8); 403 ZX_DEBUG_ASSERT((pinned_ring_buffer_.region(0).phys_addr + 404 pinned_ring_buffer_.region(0).size - 1) 405 <= fbl::numeric_limits<uint32_t>::max()); 406 407 const auto& r = pinned_ring_buffer_.region(0); 408 ZX_DEBUG_ASSERT(usable_buffer_size_ >= AIU_958_BYTES_PER_FRAME); 409 ZX_DEBUG_ASSERT(usable_buffer_size_ <= r.size); 410 regs[AIU_MEM_IEC958_START_PTR] = static_cast<uint32_t>(r.phys_addr); 411 regs[AIU_MEM_IEC958_RD_PTR] = static_cast<uint32_t>(r.phys_addr); 412 regs[AIU_MEM_IEC958_END_PTR] = static_cast<uint32_t>(r.phys_addr + usable_buffer_size_ - 8); 413 414 // Set the masks register to all channels present, and to read from all 415 // channels. Apparently, this is the thing to do when we are operating in 416 // "split mode" 417 regs[AIU_MEM_IEC958_MASKS] = 0xFFFF; 418 419 // Now that the buffer has been set up, perform some register writes to the 420 // CONTROL and BUF_CONTROL registers in order complete the setup. 421 // 422 // Exactly what this is accomplishing is something of a mystery. 423 // Documentation for bit 0 of the MEM_CONTROL register consists of "bit 0: 424 // cntl_init". Documentation for the low 16 bits of the BUF_CNTL register 425 // consists of "bits [0:15]: level_hold". Why we need to follow this 426 // sequence, or what it is accomplishing, is not documented. 427 // 428 // This sequence is here right now because it is done by the driver written 429 // by AmLogic's engineer(s) in other code bases. They provide no 430 // real explanation for what is going on here either; so for now, this 431 // remains nothing but cargo-cult garbage. 432 regs.SetBits(AIU_MEM_IEC958_CONTROL, AIU_958_MCTRL_INIT); 433 regs.ClrBits(AIU_MEM_IEC958_CONTROL, AIU_958_MCTRL_INIT); 434 regs[AIU_MEM_IEC958_BUF_CNTL] = 1; 435 regs[AIU_MEM_IEC958_BUF_CNTL] = 0; 436} 437 438void Vim2SpdifAudioStream::SetMode(uint32_t frame_rate, audio_sample_format_t fmt) { 439 ZX_DEBUG_ASSERT((regs_ != nullptr) && regs_->valid()); 440 const auto& regs = *regs_; 441 442 // Look up our frame rate to figure out our clock divider and channel status 443 // bit. Note: clock divider values are based on a reference frame rate of 444 // 192KHz 445 static const struct { 446 uint32_t frame_rate; 447 uint32_t div_bits; 448 uint32_t ch_status_bits; 449 } RATE_LUT[] = { 450 { .frame_rate = 32000, 451 .div_bits = SHIFTED_VAL(AIU_CLK_CTRL_958_DIV, 2u) | AIU_CLK_CTRL_958_DIV_MORE, 452 .ch_status_bits = SPDIF_CS_SAMP_FREQ_32K 453 }, 454 { .frame_rate = 48000, 455 .div_bits = SHIFTED_VAL(AIU_CLK_CTRL_958_DIV, 3u), 456 .ch_status_bits = SPDIF_CS_SAMP_FREQ_48K 457 }, 458 { .frame_rate = 96000, 459 .div_bits = SHIFTED_VAL(AIU_CLK_CTRL_958_DIV, 1u), 460 .ch_status_bits = SPDIF_CS_SAMP_FREQ_96K 461 }, 462 { .frame_rate = 192000, 463 .div_bits = SHIFTED_VAL(AIU_CLK_CTRL_958_DIV, 0u), 464 .ch_status_bits = SPDIF_CS_SAMP_FREQ_192K 465 }, 466 }; 467 468 uint32_t rate_ndx; 469 for (rate_ndx = 0; rate_ndx < fbl::count_of(RATE_LUT); ++rate_ndx) { 470 if (RATE_LUT[rate_ndx].frame_rate == frame_rate) { 471 break; 472 } 473 } 474 475 // The requested frame rate should already have been validated by the code 476 // before us. If something has gone terribly wrong, log a warning and 477 // default to 48K. 478 if (rate_ndx >= fbl::count_of(RATE_LUT)) { 479 constexpr uint32_t DEFAULT_RATE_NDX = 1; 480 zxlogf(WARN, "Failed to find requested frame rate (%u) in LUT! Defaulting to 48000\n", 481 frame_rate); 482 static_assert(DEFAULT_RATE_NDX < fbl::count_of(RATE_LUT), "Invalid default rate index!"); 483 rate_ndx = DEFAULT_RATE_NDX; 484 } 485 486 const auto& RATE = RATE_LUT[rate_ndx]; 487 488 // Now go ahead and set up the clock divider. 489 constexpr uint32_t DIV_MASK = SHIFTED_MASK(AIU_CLK_CTRL_958_DIV) | AIU_CLK_CTRL_958_DIV_MORE; 490 regs.ModBits(AIU_CLK_CTRL, DIV_MASK, RATE.div_bits); 491 492 // Send a 0 for the V bit in each frame. This indicates that the audio is 493 // "valid", at least from a PCM perspective. When packing compressed audio 494 // into a SPDIF transport, apparently the thing to do is set the V bit to 1 495 // in order to prevent older SPDIF receivers from treating the data like PCM 496 // and breaking your ears. 497 regs[AIU_958_VALID_CTRL] = AIU_958_VCTRL_SEND_VBIT; 498 499 // TODO(johngro): Should the bytes per frame vary based on the size of an 500 // audio frame? In particular, should the bytes per frame be an integer 501 // multiple of the audio frame size? 502 regs[AIU_958_BPF] = AIU_958_BYTES_PER_FRAME; 503 504 // TODO(johngro): Provide some way to change the category code. Shipping 505 // products should not be sending "experimental" as their category code. 506 constexpr uint32_t CH_STATUS_BASE = SPDIF_CS_SPDIF_CONSUMER 507 | SPDIF_CS_AUD_DATA_PCM 508 | SPDIF_CS_COPY_PERMITTED 509 | SPDIF_CS_NO_PRE_EMPHASIS 510 | SPDIF_CS_CCODE_EXPERIMENTAL 511 | SPDIF_CS_CLK_ACC_100PPM; 512 constexpr uint32_t MISC_BASE = AIU_958_MISC_FORCE_LR; 513 constexpr uint32_t MCTRL_BASE = AIU_958_MCTRL_LINEAR_RAW 514 | SHIFTED_VAL(AIU_958_MCTRL_ENDIAN, 0u); 515 516 uint32_t ch_status = CH_STATUS_BASE | RATE.ch_status_bits; 517 uint32_t misc = MISC_BASE; 518 uint32_t mctrl = MCTRL_BASE; 519 520 // TODO(johngro): Figure out how to get to bits >= 32 in the channel status 521 // word. In theory, we can use bits [32, 35] to signal the number of 522 // significant bits in the encoding, as well as to indicate that the 523 // auxiliary bits are carrying audio data instead of aux signalling. 524 switch (fmt) { 525 case AUDIO_SAMPLE_FORMAT_24BIT_PACKED: 526 break; 527 528 // Notes about the 32bit shift field. 529 // The 958_MISC register has a 3-bit field in it whose documentation reads... 530 // 531 // "shift number for 32 bit mode" 532 // 533 // Experimentally, it has been determined that the SPDIF encoder expects 534 // audio to be right justified when sending data from 32 bit containers. 535 // IOW, if a user puts 24 bit samples into a 32 bit container, the SPDIF 536 // encoder expects the samples to be in bits [0, 23]. 537 // 538 // If audio is left justified instead (think 32 bit samples with the low 539 // bits zeroed out), the "shift number" bits can be used. The 32 bit words 540 // will be right shifted by this number of bits for values [0, 6], or 8 bits 541 // to the left when set to the 7. 542 // 543 // TL;DR? When sending left justified audio in a 32 bit container, set this 544 // field to 7. 545 case AUDIO_SAMPLE_FORMAT_24BIT_IN32: 546 misc |= AIU_958_MISC_32BIT_MODE | SHIFTED_VAL(AIU_958_MISC_32BIT_SHIFT, 7u); 547 break; 548 549 default: 550 zxlogf(WARN, "Unsupported format (0x%08x), defaulting to PCM16\n", fmt); 551 __FALLTHROUGH; 552 case AUDIO_SAMPLE_FORMAT_16BIT: 553 mctrl |= AIU_958_MCTRL_16BIT_MODE; 554 misc |= AIU_958_MISC_16BIT | SHIFTED_VAL(AIU_958_MISC_16BIT_ALIGN, 555 AIU_958_MISC_16BIT_ALIGN_LEFT); 556 break; 557 } 558 559 regs[AIU_958_CHSTAT_L0] = (ch_status & 0xFFFF); 560 regs[AIU_958_CHSTAT_R0] = (ch_status & 0xFFFF); 561 regs[AIU_958_CHSTAT_L1] = (ch_status >> 16); 562 regs[AIU_958_CHSTAT_R1] = (ch_status >> 16); 563 regs[AIU_958_MISC] = misc; 564 regs[AIU_MEM_IEC958_CONTROL] = mctrl; 565 566 // Set the "level hold" to zero. I have no idea why. 567 regs.ClrBits(AIU_MEM_IEC958_BUF_CNTL, SHIFTED_MASK(AIU_958_BCTRL_LEVEL_HOLD)); 568} 569 570void Vim2SpdifAudioStream::Mute(bool muted) { 571 constexpr uint32_t MUTE_BITS = AIU_958_CTRL_MUTE_LEFT 572 | AIU_958_CTRL_MUTE_RIGHT 573 | AIU_958_CTRL_FUB_ZERO; 574 const auto& regs = *regs_; 575 576 regs[AIU_958_CTRL] = muted ? MUTE_BITS : 0u; 577} 578 579} // namespace vim2 580} // namespace audio 581