root/sound/ppc/daca.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. daca_init_client
  2. daca_set_volume
  3. daca_get_deemphasis
  4. daca_put_deemphasis
  5. daca_info_volume
  6. daca_get_volume
  7. daca_put_volume
  8. daca_get_amp
  9. daca_put_amp
  10. daca_resume
  11. daca_cleanup
  12. snd_pmac_daca_init

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  * PMac DACA lowlevel functions
   4  *
   5  * Copyright (c) by Takashi Iwai <tiwai@suse.de>
   6  */
   7 
   8 
   9 #include <linux/init.h>
  10 #include <linux/i2c.h>
  11 #include <linux/kmod.h>
  12 #include <linux/slab.h>
  13 #include <sound/core.h>
  14 #include "pmac.h"
  15 
  16 /* i2c address */
  17 #define DACA_I2C_ADDR   0x4d
  18 
  19 /* registers */
  20 #define DACA_REG_SR     0x01
  21 #define DACA_REG_AVOL   0x02
  22 #define DACA_REG_GCFG   0x03
  23 
  24 /* maximum volume value */
  25 #define DACA_VOL_MAX    0x38
  26 
  27 
  28 struct pmac_daca {
  29         struct pmac_keywest i2c;
  30         int left_vol, right_vol;
  31         unsigned int deemphasis : 1;
  32         unsigned int amp_on : 1;
  33 };
  34 
  35 
  36 /*
  37  * initialize / detect DACA
  38  */
  39 static int daca_init_client(struct pmac_keywest *i2c)
  40 {
  41         unsigned short wdata = 0x00;
  42         /* SR: no swap, 1bit delay, 32-48kHz */
  43         /* GCFG: power amp inverted, DAC on */
  44         if (i2c_smbus_write_byte_data(i2c->client, DACA_REG_SR, 0x08) < 0 ||
  45             i2c_smbus_write_byte_data(i2c->client, DACA_REG_GCFG, 0x05) < 0)
  46                 return -EINVAL;
  47         return i2c_smbus_write_block_data(i2c->client, DACA_REG_AVOL,
  48                                           2, (unsigned char*)&wdata);
  49 }
  50 
  51 /*
  52  * update volume
  53  */
  54 static int daca_set_volume(struct pmac_daca *mix)
  55 {
  56         unsigned char data[2];
  57   
  58         if (! mix->i2c.client)
  59                 return -ENODEV;
  60   
  61         if (mix->left_vol > DACA_VOL_MAX)
  62                 data[0] = DACA_VOL_MAX;
  63         else
  64                 data[0] = mix->left_vol;
  65         if (mix->right_vol > DACA_VOL_MAX)
  66                 data[1] = DACA_VOL_MAX;
  67         else
  68                 data[1] = mix->right_vol;
  69         data[1] |= mix->deemphasis ? 0x40 : 0;
  70         if (i2c_smbus_write_block_data(mix->i2c.client, DACA_REG_AVOL,
  71                                        2, data) < 0) {
  72                 snd_printk(KERN_ERR "failed to set volume \n");
  73                 return -EINVAL;
  74         }
  75         return 0;
  76 }
  77 
  78 
  79 /* deemphasis switch */
  80 #define daca_info_deemphasis            snd_ctl_boolean_mono_info
  81 
  82 static int daca_get_deemphasis(struct snd_kcontrol *kcontrol,
  83                                struct snd_ctl_elem_value *ucontrol)
  84 {
  85         struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
  86         struct pmac_daca *mix;
  87         if (! (mix = chip->mixer_data))
  88                 return -ENODEV;
  89         ucontrol->value.integer.value[0] = mix->deemphasis ? 1 : 0;
  90         return 0;
  91 }
  92 
  93 static int daca_put_deemphasis(struct snd_kcontrol *kcontrol,
  94                                struct snd_ctl_elem_value *ucontrol)
  95 {
  96         struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
  97         struct pmac_daca *mix;
  98         int change;
  99 
 100         if (! (mix = chip->mixer_data))
 101                 return -ENODEV;
 102         change = mix->deemphasis != ucontrol->value.integer.value[0];
 103         if (change) {
 104                 mix->deemphasis = !!ucontrol->value.integer.value[0];
 105                 daca_set_volume(mix);
 106         }
 107         return change;
 108 }
 109 
 110 /* output volume */
 111 static int daca_info_volume(struct snd_kcontrol *kcontrol,
 112                             struct snd_ctl_elem_info *uinfo)
 113 {
 114         uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
 115         uinfo->count = 2;
 116         uinfo->value.integer.min = 0;
 117         uinfo->value.integer.max = DACA_VOL_MAX;
 118         return 0;
 119 }
 120 
 121 static int daca_get_volume(struct snd_kcontrol *kcontrol,
 122                            struct snd_ctl_elem_value *ucontrol)
 123 {
 124         struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
 125         struct pmac_daca *mix;
 126         if (! (mix = chip->mixer_data))
 127                 return -ENODEV;
 128         ucontrol->value.integer.value[0] = mix->left_vol;
 129         ucontrol->value.integer.value[1] = mix->right_vol;
 130         return 0;
 131 }
 132 
 133 static int daca_put_volume(struct snd_kcontrol *kcontrol,
 134                            struct snd_ctl_elem_value *ucontrol)
 135 {
 136         struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
 137         struct pmac_daca *mix;
 138         unsigned int vol[2];
 139         int change;
 140 
 141         if (! (mix = chip->mixer_data))
 142                 return -ENODEV;
 143         vol[0] = ucontrol->value.integer.value[0];
 144         vol[1] = ucontrol->value.integer.value[1];
 145         if (vol[0] > DACA_VOL_MAX || vol[1] > DACA_VOL_MAX)
 146                 return -EINVAL;
 147         change = mix->left_vol != vol[0] ||
 148                 mix->right_vol != vol[1];
 149         if (change) {
 150                 mix->left_vol = vol[0];
 151                 mix->right_vol = vol[1];
 152                 daca_set_volume(mix);
 153         }
 154         return change;
 155 }
 156 
 157 /* amplifier switch */
 158 #define daca_info_amp   daca_info_deemphasis
 159 
 160 static int daca_get_amp(struct snd_kcontrol *kcontrol,
 161                         struct snd_ctl_elem_value *ucontrol)
 162 {
 163         struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
 164         struct pmac_daca *mix;
 165         if (! (mix = chip->mixer_data))
 166                 return -ENODEV;
 167         ucontrol->value.integer.value[0] = mix->amp_on ? 1 : 0;
 168         return 0;
 169 }
 170 
 171 static int daca_put_amp(struct snd_kcontrol *kcontrol,
 172                         struct snd_ctl_elem_value *ucontrol)
 173 {
 174         struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
 175         struct pmac_daca *mix;
 176         int change;
 177 
 178         if (! (mix = chip->mixer_data))
 179                 return -ENODEV;
 180         change = mix->amp_on != ucontrol->value.integer.value[0];
 181         if (change) {
 182                 mix->amp_on = !!ucontrol->value.integer.value[0];
 183                 i2c_smbus_write_byte_data(mix->i2c.client, DACA_REG_GCFG,
 184                                           mix->amp_on ? 0x05 : 0x04);
 185         }
 186         return change;
 187 }
 188 
 189 static struct snd_kcontrol_new daca_mixers[] = {
 190         { .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 191           .name = "Deemphasis Switch",
 192           .info = daca_info_deemphasis,
 193           .get = daca_get_deemphasis,
 194           .put = daca_put_deemphasis
 195         },
 196         { .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 197           .name = "Master Playback Volume",
 198           .info = daca_info_volume,
 199           .get = daca_get_volume,
 200           .put = daca_put_volume
 201         },
 202         { .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 203           .name = "Power Amplifier Switch",
 204           .info = daca_info_amp,
 205           .get = daca_get_amp,
 206           .put = daca_put_amp
 207         },
 208 };
 209 
 210 
 211 #ifdef CONFIG_PM
 212 static void daca_resume(struct snd_pmac *chip)
 213 {
 214         struct pmac_daca *mix = chip->mixer_data;
 215         i2c_smbus_write_byte_data(mix->i2c.client, DACA_REG_SR, 0x08);
 216         i2c_smbus_write_byte_data(mix->i2c.client, DACA_REG_GCFG,
 217                                   mix->amp_on ? 0x05 : 0x04);
 218         daca_set_volume(mix);
 219 }
 220 #endif /* CONFIG_PM */
 221 
 222 
 223 static void daca_cleanup(struct snd_pmac *chip)
 224 {
 225         struct pmac_daca *mix = chip->mixer_data;
 226         if (! mix)
 227                 return;
 228         snd_pmac_keywest_cleanup(&mix->i2c);
 229         kfree(mix);
 230         chip->mixer_data = NULL;
 231 }
 232 
 233 /* exported */
 234 int snd_pmac_daca_init(struct snd_pmac *chip)
 235 {
 236         int i, err;
 237         struct pmac_daca *mix;
 238 
 239         request_module("i2c-powermac");
 240 
 241         mix = kzalloc(sizeof(*mix), GFP_KERNEL);
 242         if (! mix)
 243                 return -ENOMEM;
 244         chip->mixer_data = mix;
 245         chip->mixer_free = daca_cleanup;
 246         mix->amp_on = 1; /* default on */
 247 
 248         mix->i2c.addr = DACA_I2C_ADDR;
 249         mix->i2c.init_client = daca_init_client;
 250         mix->i2c.name = "DACA";
 251         if ((err = snd_pmac_keywest_init(&mix->i2c)) < 0)
 252                 return err;
 253 
 254         /*
 255          * build mixers
 256          */
 257         strcpy(chip->card->mixername, "PowerMac DACA");
 258 
 259         for (i = 0; i < ARRAY_SIZE(daca_mixers); i++) {
 260                 if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&daca_mixers[i], chip))) < 0)
 261                         return err;
 262         }
 263 
 264 #ifdef CONFIG_PM
 265         chip->resume = daca_resume;
 266 #endif
 267 
 268         return 0;
 269 }

/* [<][>][^][v][top][bottom][index][help] */