summaryrefslogtreecommitdiff
path: root/sound_card_init/max98390d/src/lib.rs
blob: 7e445c598e7902088801859a814189d4e198fb26 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
// Copyright 2020 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//! `max98390d` crate implements the required initialization workflows.
//! It currently supports boot time calibration for amplifiers.
#![deny(missing_docs)]
mod amp_calibration;
mod datastore;
mod error;
mod settings;
mod vpd;

use std::path::Path;

use cros_alsa::Card;
use sys_util::error;

use crate::amp_calibration::{AmpCalibration, VolumeMode};
use crate::error::{Error, Result};
use crate::settings::DeviceSettings;

/// Performs max98390d boot time calibration.
///
///
/// # Arguments
///
/// * `snd_card` - The sound card name, ex: sofcmlmax98390d.
/// * `conf` - The `DeviceSettings` in yaml format.
///
/// # Errors
///
/// If any amplifiers fail to complete the calibration.
pub fn run_max98390d(snd_card: &str, conf: &str) -> Result<()> {
    let settings = DeviceSettings::from_yaml_str(conf)?;
    let mut card = Card::new(snd_card)?;

    if !Path::new(&settings.dsm_param).exists() {
        for s in &settings.amp_calibrations {
            let mut amp_calib = match AmpCalibration::new(&mut card, s.clone()) {
                Ok(amp) => amp,
                Err(e) => {
                    error!("{}.", e);
                    continue;
                }
            };
            if let Err(e) = amp_calib.set_volume(VolumeMode::Low) {
                error!("failed to set volume to low: {}.", e);
            }
        }
        return Err(Error::MissingDSMParam);
    }
    // If some error occurs during the calibration, the iteration will continue running the
    // calibration for the next amp.
    let results: Vec<Result<()>> = settings
        .amp_calibrations
        .into_iter()
        .map(|s| {
            let mut amp_calib = AmpCalibration::new(&mut card, s)?;
            amp_calib.set_volume(VolumeMode::Low)?;
            amp_calib.run()?;
            amp_calib.set_volume(VolumeMode::High)?;
            Ok(())
        })
        .filter_map(|res| res.err())
        .map(|e| {
            error!("calibration error: {}. volume remains low.", e);
            Err(e)
        })
        .collect();

    if !results.is_empty() {
        return Err(Error::CalibrationFailed);
    }

    Ok(())
}