Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 133178
b: refs/heads/master
c: 30459d7
h: refs/heads/master
v: v3
  • Loading branch information
Clemens Ladisch authored and Takashi Iwai committed Feb 19, 2009
1 parent b00f316 commit 57a27e5
Show file tree
Hide file tree
Showing 7 changed files with 180 additions and 94 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: a69bb3c3fe0881d986ec78e253cb8a6bb9c28230
refs/heads/master: 30459d7b1843cbdea56ca120c8cac10dc5613e90
11 changes: 10 additions & 1 deletion trunk/sound/pci/oxygen/hifier.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ MODULE_PARM_DESC(enable, "enable card");
static struct pci_device_id hifier_ids[] __devinitdata = {
{ OXYGEN_PCI_SUBID(0x14c3, 0x1710) },
{ OXYGEN_PCI_SUBID(0x14c3, 0x1711) },
{ OXYGEN_PCI_SUBID_BROKEN_EEPROM },
{ }
};
MODULE_DEVICE_TABLE(pci, hifier_ids);
Expand Down Expand Up @@ -172,6 +173,13 @@ static const struct oxygen_model model_hifier = {
.adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
};

static int __devinit get_hifier_model(struct oxygen *chip,
const struct pci_device_id *id)
{
chip->model = model_hifier;
return 0;
}

static int __devinit hifier_probe(struct pci_dev *pci,
const struct pci_device_id *pci_id)
{
Expand All @@ -184,7 +192,8 @@ static int __devinit hifier_probe(struct pci_dev *pci,
++dev;
return -ENOENT;
}
err = oxygen_pci_probe(pci, index[dev], id[dev], THIS_MODULE, &model_hifier, 0);
err = oxygen_pci_probe(pci, index[dev], id[dev], THIS_MODULE,
hifier_ids, get_hifier_model);
if (err >= 0)
++dev;
return err;
Expand Down
44 changes: 24 additions & 20 deletions trunk/sound/pci/oxygen/oxygen.c
Original file line number Diff line number Diff line change
Expand Up @@ -293,29 +293,10 @@ static void set_ak5385_params(struct oxygen *chip,

static const DECLARE_TLV_DB_LINEAR(ak4396_db_scale, TLV_DB_GAIN_MUTE, 0);

static int generic_probe(struct oxygen *chip, unsigned long driver_data)
{
if (driver_data == MODEL_MERIDIAN) {
chip->model.init = meridian_init;
chip->model.resume = meridian_resume;
chip->model.set_adc_params = set_ak5385_params;
chip->model.device_config = PLAYBACK_0_TO_I2S |
PLAYBACK_1_TO_SPDIF |
CAPTURE_0_FROM_I2S_2 |
CAPTURE_1_FROM_SPDIF;
}
if (driver_data == MODEL_MERIDIAN || driver_data == MODEL_HALO) {
chip->model.misc_flags = OXYGEN_MISC_MIDI;
chip->model.device_config |= MIDI_OUTPUT | MIDI_INPUT;
}
return 0;
}

static const struct oxygen_model model_generic = {
.shortname = "C-Media CMI8788",
.longname = "C-Media Oxygen HD Audio",
.chip = "CMI8788",
.probe = generic_probe,
.init = generic_init,
.cleanup = generic_cleanup,
.resume = generic_resume,
Expand All @@ -340,6 +321,29 @@ static const struct oxygen_model model_generic = {
.adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
};

static int __devinit get_oxygen_model(struct oxygen *chip,
const struct pci_device_id *id)
{
chip->model = model_generic;
switch (id->driver_data) {
case MODEL_MERIDIAN:
chip->model.init = meridian_init;
chip->model.resume = meridian_resume;
chip->model.set_adc_params = set_ak5385_params;
chip->model.device_config = PLAYBACK_0_TO_I2S |
PLAYBACK_1_TO_SPDIF |
CAPTURE_0_FROM_I2S_2 |
CAPTURE_1_FROM_SPDIF;
break;
}
if (id->driver_data == MODEL_MERIDIAN ||
id->driver_data == MODEL_HALO) {
chip->model.misc_flags = OXYGEN_MISC_MIDI;
chip->model.device_config |= MIDI_OUTPUT | MIDI_INPUT;
}
return 0;
}

static int __devinit generic_oxygen_probe(struct pci_dev *pci,
const struct pci_device_id *pci_id)
{
Expand All @@ -353,7 +357,7 @@ static int __devinit generic_oxygen_probe(struct pci_dev *pci,
return -ENOENT;
}
err = oxygen_pci_probe(pci, index[dev], id[dev], THIS_MODULE,
&model_generic, pci_id->driver_data);
oxygen_ids, get_oxygen_model);
if (err >= 0)
++dev;
return err;
Expand Down
17 changes: 14 additions & 3 deletions trunk/sound/pci/oxygen/oxygen.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,13 @@ enum {
.subvendor = sv, \
.subdevice = sd

#define BROKEN_EEPROM_DRIVER_DATA ((unsigned long)-1)
#define OXYGEN_PCI_SUBID_BROKEN_EEPROM \
OXYGEN_PCI_SUBID(PCI_VENDOR_ID_CMEDIA, 0x8788), \
.driver_data = BROKEN_EEPROM_DRIVER_DATA

struct pci_dev;
struct pci_device_id;
struct snd_card;
struct snd_pcm_substream;
struct snd_pcm_hardware;
Expand All @@ -62,7 +68,6 @@ struct oxygen_model {
const char *shortname;
const char *longname;
const char *chip;
int (*probe)(struct oxygen *chip, unsigned long driver_data);
void (*init)(struct oxygen *chip);
int (*control_filter)(struct snd_kcontrol_new *template);
int (*mixer_init)(struct oxygen *chip);
Expand All @@ -82,6 +87,7 @@ struct oxygen_model {
void (*ac97_switch)(struct oxygen *chip,
unsigned int reg, unsigned int mute);
const unsigned int *dac_tlv;
unsigned long private_data;
size_t model_data_size;
unsigned int device_config;
u8 dac_channels;
Expand Down Expand Up @@ -134,8 +140,11 @@ struct oxygen {

int oxygen_pci_probe(struct pci_dev *pci, int index, char *id,
struct module *owner,
const struct oxygen_model *model,
unsigned long driver_data);
const struct pci_device_id *ids,
int (*get_model)(struct oxygen *chip,
const struct pci_device_id *id
)
);
void oxygen_pci_remove(struct pci_dev *pci);
#ifdef CONFIG_PM
int oxygen_pci_suspend(struct pci_dev *pci, pm_message_t state);
Expand Down Expand Up @@ -180,6 +189,8 @@ void oxygen_write_i2c(struct oxygen *chip, u8 device, u8 map, u8 data);
void oxygen_reset_uart(struct oxygen *chip);
void oxygen_write_uart(struct oxygen *chip, u8 data);

u16 oxygen_read_eeprom(struct oxygen *chip, unsigned int index);

static inline void oxygen_set_bits8(struct oxygen *chip,
unsigned int reg, u8 value)
{
Expand Down
15 changes: 15 additions & 0 deletions trunk/sound/pci/oxygen/oxygen_io.c
Original file line number Diff line number Diff line change
Expand Up @@ -254,3 +254,18 @@ void oxygen_write_uart(struct oxygen *chip, u8 data)
_write_uart(chip, 0, data);
}
EXPORT_SYMBOL(oxygen_write_uart);

u16 oxygen_read_eeprom(struct oxygen *chip, unsigned int index)
{
unsigned int timeout;

oxygen_write8(chip, OXYGEN_EEPROM_CONTROL,
index | OXYGEN_EEPROM_DIR_READ);
for (timeout = 0; timeout < 100; ++timeout) {
udelay(1);
if (!(oxygen_read8(chip, OXYGEN_EEPROM_STATUS)
& OXYGEN_EEPROM_BUSY))
break;
}
return oxygen_read16(chip, OXYGEN_EEPROM_DATA);
}
51 changes: 43 additions & 8 deletions trunk/sound/pci/oxygen/oxygen_lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,34 @@ static void oxygen_proc_init(struct oxygen *chip)
#define oxygen_proc_init(chip)
#endif

static const struct pci_device_id *
oxygen_search_pci_id(struct oxygen *chip, const struct pci_device_id ids[])
{
u16 subdevice;

/*
* Make sure the EEPROM pins are available, i.e., not used for SPI.
* (This function is called before we initialize or use SPI.)
*/
oxygen_clear_bits8(chip, OXYGEN_FUNCTION,
OXYGEN_FUNCTION_ENABLE_SPI_4_5);
/*
* Read the subsystem device ID directly from the EEPROM, because the
* chip didn't if the first EEPROM word was overwritten.
*/
subdevice = oxygen_read_eeprom(chip, 2);
/*
* We use only the subsystem device ID for searching because it is
* unique even without the subsystem vendor ID, which may have been
* overwritten in the EEPROM.
*/
for (; ids->vendor; ++ids)
if (ids->subdevice == subdevice &&
ids->driver_data != BROKEN_EEPROM_DRIVER_DATA)
return ids;
return NULL;
}

static void oxygen_init(struct oxygen *chip)
{
unsigned int i;
Expand Down Expand Up @@ -455,11 +483,15 @@ static void oxygen_card_free(struct snd_card *card)

int oxygen_pci_probe(struct pci_dev *pci, int index, char *id,
struct module *owner,
const struct oxygen_model *model,
unsigned long driver_data)
const struct pci_device_id *ids,
int (*get_model)(struct oxygen *chip,
const struct pci_device_id *id
)
)
{
struct snd_card *card;
struct oxygen *chip;
const struct pci_device_id *pci_id;
int err;

err = snd_card_create(index, id, owner, sizeof(*chip), &card);
Expand All @@ -470,7 +502,6 @@ int oxygen_pci_probe(struct pci_dev *pci, int index, char *id,
chip->card = card;
chip->pci = pci;
chip->irq = -1;
chip->model = *model;
spin_lock_init(&chip->reg_lock);
mutex_init(&chip->mutex);
INIT_WORK(&chip->spdif_input_bits_work,
Expand All @@ -496,6 +527,15 @@ int oxygen_pci_probe(struct pci_dev *pci, int index, char *id,
}
chip->addr = pci_resource_start(pci, 0);

pci_id = oxygen_search_pci_id(chip, ids);
if (!pci_id) {
err = -ENODEV;
goto err_pci_regions;
}
err = get_model(chip, pci_id);
if (err < 0)
goto err_pci_regions;

if (chip->model.model_data_size) {
chip->model_data = kmalloc(chip->model.model_data_size,
GFP_KERNEL);
Expand All @@ -509,11 +549,6 @@ int oxygen_pci_probe(struct pci_dev *pci, int index, char *id,
snd_card_set_dev(card, &pci->dev);
card->private_free = oxygen_card_free;

if (chip->model.probe) {
err = chip->model.probe(chip, driver_data);
if (err < 0)
goto err_card;
}
oxygen_init(chip);
chip->model.init(chip);

Expand Down
Loading

0 comments on commit 57a27e5

Please sign in to comment.