Changeset 1912b45 in mainline for uspace/drv/audio/sb16/mixer.c


Ignore:
Timestamp:
2013-04-10T20:52:26Z (12 years ago)
Author:
Jan Vesely <jano.vesely@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
5b77efc
Parents:
8a7d78cc
Message:

Make pcm control iface generic

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/audio/sb16/mixer.c

    r8a7d78cc r1912b45  
    4545} channel_t;
    4646
    47 typedef struct volume_item {
    48         const char *description;
    49         uint8_t channels;
    50         const channel_t *channel_table;
    51 } volume_item_t;
    52 
    5347/* CT1335 channels */
    5448static const channel_t channels_table_ct1335[] = {
    55         { "Mono", 0x02, 1, 8, false }, /* Master, Mono, 3bit volume level */
    56         { "Mono", 0x06, 1, 8, false }, /* Midi, Mono, 3bit volume level */
    57         { "Mono", 0x08, 1, 8, false }, /* CD, Mono, 3bit volume level */
    58         { "Mono", 0x0a, 1, 4, false }, /* Voice, Mono, 2bit volume level */
     49        { "Master", 0x02, 1, 8, false }, /* Master, Mono, 3bit volume level */
     50        { "Midi", 0x06, 1, 8, false }, /* Midi, Mono, 3bit volume level */
     51        { "CD", 0x08, 1, 8, false }, /* CD, Mono, 3bit volume level */
     52        { "Voice", 0x0a, 1, 4, false }, /* Voice, Mono, 2bit volume level */
    5953};
    6054
    6155/* CT1345 channels */
    6256static const channel_t channels_table_ct1345[] = {
    63         { "Left", 0x22, 5, 8, true }, /* Master, Left, 3bit volume level */
    64         { "Right", 0x22, 1, 8, true }, /* Master, Right, 3bit volume level */
    65         { "Left", 0x26, 5, 8, true }, /* Midi, Left, 3bit volume level */
    66         { "Right", 0x26, 1, 8, true }, /* Midi, Right, 3bit volume level */
    67         { "Left", 0x28, 5, 8, true }, /* CD, Left, 3bit volume level */
    68         { "Right", 0x28, 1, 8, true }, /* CD, Right, 3bit volume level */
    69         { "Left", 0x2e, 5, 8, true }, /* Line, Left, 3bit volume level */
    70         { "Right", 0x2e, 1, 8, true }, /* Line, Right, 3bit volume level */
    71         { "Left", 0x04, 5, 8, true }, /* Voice, Left, 3bit volume level */
    72         { "Right", 0x04, 1, 8, true }, /* Voice, Right, 3bit volume level */
    73         { "Mono", 0x0a, 1, 4, false }, /* Mic, Mono, 2bit volume level */
     57        { "Master Left", 0x22, 5, 8, true }, /* Master, Left, 3bit volume level */
     58        { "Master Right", 0x22, 1, 8, true }, /* Master, Right, 3bit volume level */
     59        { "MIDI Left", 0x26, 5, 8, true }, /* Midi, Left, 3bit volume level */
     60        { "MIDI Right", 0x26, 1, 8, true }, /* Midi, Right, 3bit volume level */
     61        { "CD Left", 0x28, 5, 8, true }, /* CD, Left, 3bit volume level */
     62        { "CD Right", 0x28, 1, 8, true }, /* CD, Right, 3bit volume level */
     63        { "Line In Left", 0x2e, 5, 8, true }, /* Line, Left, 3bit volume level */
     64        { "Line In Right", 0x2e, 1, 8, true }, /* Line, Right, 3bit volume level */
     65        { "Voice Left", 0x04, 5, 8, true }, /* Voice, Left, 3bit volume level */
     66        { "Voice Right", 0x04, 1, 8, true }, /* Voice, Right, 3bit volume level */
     67        { "Mic", 0x0a, 1, 4, false }, /* Mic, Mono, 2bit volume level */
    7468};
    7569
    7670/* CT1745 channels */
    7771static const channel_t channels_table_ct1745[] = {
    78         { "Left", 0x30, 3, 32, false },  /* Master, Left, 5bit volume level */
    79         { "Right", 0x31, 3, 32, false }, /* Master, Right, 5bit volume level */
    80         { "Left", 0x32, 3, 32, false },  /* Voice, Left, 5bit volume level */
    81         { "Right", 0x33, 3, 32, false }, /* Voice, Right, 5bit volume level */
    82         { "Left", 0x34, 3, 32, false }, /* MIDI, Left, 5bit volume level */
    83         { "Right", 0x35, 3, 32, false }, /* MIDI, Right, 5bit volume level */
    84         { "Left", 0x36, 3, 32, false }, /* CD, Left, 5bit volume level */
    85         { "Right", 0x37, 3, 32, false }, /* CD, Right, 5bit volume level */
    86         { "Left", 0x38, 3, 32, false }, /* Line, Left, 5bit volume level */
    87         { "Right", 0x39, 3, 32, false }, /* Line, Right, 5bit volume level */
    88         { "Mono", 0x3a, 3, 32, false }, /* Mic, Mono, 5bit volume level */
    89         { "Mono", 0x3b, 6, 4, false }, /* PC speaker, Mono, 2bit level */
    90         { "Left", 0x3f, 6, 4, false }, /* Input Gain, Left, 2bit level */
    91         { "Right", 0x40, 6, 4, false }, /* Input Gain, Right, 2bit level */
    92         { "Left", 0x41, 6, 4, false }, /* Output Gain, Left, 2bit level */
    93         { "Right", 0x42, 6, 4, false }, /* Output Gain, Right, 2bit level */
    94         { "Left", 0x44, 4, 16, false }, /* Treble, Left, 4bit volume level */
    95         { "Right", 0x45, 4, 16, false }, /* Treble, Right, 4bit volume level */
    96         { "Left", 0x46, 4, 16, false }, /* Bass, Left, 4bit volume level */
    97         { "Right", 0x47, 4, 16, false }, /* Bass, Right, 4bit volume level */
    98 };
    99 
    100 static const volume_item_t volume_ct1335[] = {
    101         { "Master", 1, &channels_table_ct1335[0] },
    102         { "MIDI", 1, &channels_table_ct1335[1] },
    103         { "CD", 1, &channels_table_ct1335[2] },
    104         { "Voice", 1, &channels_table_ct1335[3] },
    105 };
    106 
    107 static const volume_item_t volume_ct1345[] = {
    108         { "Master", 2, &channels_table_ct1345[0] },
    109         { "Voice", 2, &channels_table_ct1345[8] },
    110         { "Mic", 1, &channels_table_ct1345[10] },
    111         { "MIDI", 2, &channels_table_ct1345[2] },
    112         { "CD", 2, &channels_table_ct1345[4] },
    113         { "Line", 2, &channels_table_ct1345[6] },
    114 };
    115 
    116 static const volume_item_t volume_ct1745[] = {
    117         { "Master", 2, &channels_table_ct1745[0] },
    118         { "Voice", 2, &channels_table_ct1745[2] },
    119         { "MIDI", 2, &channels_table_ct1745[4] },
    120         { "CD", 2, &channels_table_ct1745[6] },
    121         { "Line", 2, &channels_table_ct1745[8] },
    122         { "Mic", 1, &channels_table_ct1745[10] },
    123         { "PC Speaker", 1, &channels_table_ct1745[11] },
    124         { "Input Gain", 2, &channels_table_ct1745[12] },
    125         { "Output Gain", 2, &channels_table_ct1745[14] },
    126         { "Treble", 2, &channels_table_ct1745[16] },
    127         { "Bass", 2, &channels_table_ct1745[18] },
     72        { "Master Left", 0x30, 3, 32, false },  /* Master, Left, 5bit volume level */
     73        { "Master Right", 0x31, 3, 32, false }, /* Master, Right, 5bit volume level */
     74        { "Voice Left", 0x32, 3, 32, false },  /* Voice, Left, 5bit volume level */
     75        { "Voice Right", 0x33, 3, 32, false }, /* Voice, Right, 5bit volume level */
     76        { "MIDI Left", 0x34, 3, 32, false }, /* MIDI, Left, 5bit volume level */
     77        { "MIDI Right", 0x35, 3, 32, false }, /* MIDI, Right, 5bit volume level */
     78        { "CD Left", 0x36, 3, 32, false }, /* CD, Left, 5bit volume level */
     79        { "CD Right", 0x37, 3, 32, false }, /* CD, Right, 5bit volume level */
     80        { "Line In Left", 0x38, 3, 32, false }, /* Line, Left, 5bit volume level */
     81        { "Line In Right", 0x39, 3, 32, false }, /* Line, Right, 5bit volume level */
     82        { "Mic", 0x3a, 3, 32, false }, /* Mic, Mono, 5bit volume level */
     83        { "PC Speaker", 0x3b, 6, 4, false }, /* PC speaker, Mono, 2bit level */
     84        { "Input Gain Left", 0x3f, 6, 4, false }, /* Input Gain, Left, 2bit level */
     85        { "Input Gain Right", 0x40, 6, 4, false }, /* Input Gain, Right, 2bit level */
     86        { "Output Gain Left", 0x41, 6, 4, false }, /* Output Gain, Left, 2bit level */
     87        { "Output Gain Right", 0x42, 6, 4, false }, /* Output Gain, Right, 2bit level */
     88        { "Treble Left", 0x44, 4, 16, false }, /* Treble, Left, 4bit volume level */
     89        { "Treble Right", 0x45, 4, 16, false }, /* Treble, Right, 4bit volume level */
     90        { "Bass Left", 0x46, 4, 16, false }, /* Bass, Left, 4bit volume level */
     91        { "Bass Right", 0x47, 4, 16, false }, /* Bass, Right, 4bit volume level */
    12892};
    12993
    13094static const struct {
    131         const volume_item_t *table;
     95        const channel_t *table;
    13296        size_t count;
    13397} volume_table[] = {
    13498        [SB_MIXER_NONE] = { NULL, 0 },
    13599        [SB_MIXER_UNKNOWN] = { NULL, 0 },
    136         [SB_MIXER_CT1335] = { volume_ct1335, ARRAY_SIZE(volume_ct1335) },
    137         [SB_MIXER_CT1345] = { volume_ct1345, ARRAY_SIZE(volume_ct1345) },
    138         [SB_MIXER_CT1745] = { volume_ct1745, ARRAY_SIZE(volume_ct1745) },
     100        [SB_MIXER_CT1335] = {
     101            channels_table_ct1335,
     102            ARRAY_SIZE(channels_table_ct1335),
     103        },
     104        [SB_MIXER_CT1345] = {
     105            channels_table_ct1345,
     106            ARRAY_SIZE(channels_table_ct1345),
     107        },
     108        [SB_MIXER_CT1745] = {
     109            channels_table_ct1745,
     110            ARRAY_SIZE(channels_table_ct1745),
     111        },
    139112};
    140113
     
    177150}
    178151
    179 int sb_mixer_get_control_item_info(const sb_mixer_t *mixer, unsigned index,
    180     const char** name, unsigned *channels)
    181 {
    182         assert(mixer);
    183         if (index > volume_table[mixer->type].count)
     152int sb_mixer_get_control_item_info(const sb_mixer_t *mixer, unsigned item,
     153    const char** name, unsigned *levels)
     154{
     155        assert(mixer);
     156        if (item > volume_table[mixer->type].count)
    184157                return ENOENT;
    185158
    186         const volume_item_t *item = &volume_table[mixer->type].table[index];
     159        const channel_t *ch = &volume_table[mixer->type].table[item];
    187160        if (name)
    188                 *name = item->description;
    189         if (channels)
    190                 *channels = item->channels;
    191         return EOK;
    192 }
    193 
    194 int sb_mixer_get_channel_info(const sb_mixer_t *mixer, unsigned index,
    195     unsigned channel, const char **name, unsigned *levels)
    196 {
    197         assert(mixer);
    198         if (index > volume_table[mixer->type].count)
     161                *name = ch->name;
     162        if (levels)
     163                *levels = ch->volume_levels;
     164        return EOK;
     165}
     166
     167/**
     168 * Write new volume level from mixer registers.
     169 * @param mixer SB Mixer to use.
     170 * @param index Control item(channel) index.
     171 * @param value New volume level.
     172 * @return Error code.
     173 */
     174int sb_mixer_get_control_item_value(const sb_mixer_t *mixer, unsigned item,
     175    unsigned *value)
     176{
     177        assert(mixer);
     178        if (!value)
     179                return EBADMEM;
     180        if (item > volume_table[mixer->type].count)
    199181                return ENOENT;
    200182
    201         const volume_item_t *item = &volume_table[mixer->type].table[index];
    202         if (channel > item->channels)
     183        const channel_t *chan = &volume_table[mixer->type].table[item];
     184        pio_write_8(&mixer->regs->mixer_address, chan->address);
     185        *value = (pio_read_8(&mixer->regs->mixer_data) >> chan->shift)
     186            & (chan->volume_levels - 1);
     187        return EOK;
     188}
     189
     190/**
     191 * Write new volume level to mixer registers.
     192 * @param mixer SB Mixer to use.
     193 * @param index Control item(channel) index.
     194 * @param value New volume level.
     195 * @return Error code.
     196 */
     197int sb_mixer_set_control_item_value(const sb_mixer_t *mixer, unsigned item,
     198    unsigned value)
     199{
     200        assert(mixer);
     201        if (item > volume_table[mixer->type].count)
    203202                return ENOENT;
    204203
    205         const channel_t *chan = &item->channel_table[channel];
    206         if (name)
    207                 *name = chan->name;
    208         if (levels)
    209                 *levels = chan->volume_levels;
    210         return EOK;
    211 }
    212 
    213 int sb_mixer_set_volume_level(const sb_mixer_t *mixer,
    214     unsigned index, unsigned channel, unsigned level)
    215 {
    216         if (mixer->type == SB_MIXER_UNKNOWN || mixer->type == SB_MIXER_NONE)
    217                 return ENOTSUP;
    218         if (index >= volume_table[mixer->type].count)
    219                 return ENOENT;
    220         if (channel >= volume_table[mixer->type].table[index].channels)
    221                 return ENOENT;
    222 
    223         const channel_t *chan =
    224             &volume_table[mixer->type].table[index].channel_table[channel];
    225 
    226         if (level >= chan->volume_levels)
    227                 level = chan->volume_levels - 1;
     204        const channel_t *chan = &volume_table[mixer->type].table[item];
     205        if (value >= chan->volume_levels)
     206                value = chan->volume_levels - 1;
    228207
    229208        pio_write_8(&mixer->regs->mixer_address, chan->address);
    230209
    231         uint8_t value = 0;
     210        uint8_t regv = 0;
    232211        if (chan->preserve_bits) {
    233                 value = pio_read_8(&mixer->regs->mixer_data);
    234                 value &= ~(uint8_t)((chan->volume_levels - 1) << chan->shift);
     212                regv = pio_read_8(&mixer->regs->mixer_data);
     213                regv &= ~(uint8_t)((chan->volume_levels - 1) << chan->shift);
    235214        }
    236215
    237         value |= level << chan->shift;
    238         pio_write_8(&mixer->regs->mixer_data, value);
    239         ddf_log_note("Channel %s %s volume set to: %u.",
    240             volume_table[mixer->type].table[index].description,
    241             chan->name, level);
    242         return EOK;
    243 }
    244 
    245 unsigned sb_mixer_get_volume_level(const sb_mixer_t *mixer, unsigned index,
    246     unsigned channel)
    247 {
    248         assert(mixer);
    249         if (mixer->type == SB_MIXER_UNKNOWN
    250             || mixer->type == SB_MIXER_NONE
    251             || (index >= volume_table[mixer->type].count)
    252             || (channel >= volume_table[mixer->type].table[index].channels))
    253                 return 0;
    254 
    255         const channel_t *chan =
    256             &volume_table[mixer->type].table[index].channel_table[channel];
    257 
    258         pio_write_8(&mixer->regs->mixer_address, chan->address);
    259         return (pio_read_8(&mixer->regs->mixer_data) >> chan->shift)
    260             & (chan->volume_levels - 1);
    261 }
     216        regv |= value << chan->shift;
     217        pio_write_8(&mixer->regs->mixer_data, regv);
     218        ddf_log_note("Item %s new value is: %u.",
     219            volume_table[mixer->type].table[item].name, value);
     220        return EOK;
     221}
Note: See TracChangeset for help on using the changeset viewer.