xref: /openbmc/linux/sound/pci/oxygen/se6x.c (revision 762f99f4f3cb41a775b5157dd761217beba65873)
1*b67eb152SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
253c098bfSClemens Ladisch /*
353c098bfSClemens Ladisch  * C-Media CMI8787 driver for the Studio Evolution SE6X
453c098bfSClemens Ladisch  *
553c098bfSClemens Ladisch  * Copyright (c) Clemens Ladisch <clemens@ladisch.de>
653c098bfSClemens Ladisch  */
753c098bfSClemens Ladisch 
853c098bfSClemens Ladisch /*
953c098bfSClemens Ladisch  * CMI8787:
1053c098bfSClemens Ladisch  *
1153c098bfSClemens Ladisch  *   SPI    -> microcontroller (not actually used)
1253c098bfSClemens Ladisch  *   GPIO 0 -> do.
1353c098bfSClemens Ladisch  *   GPIO 2 -> do.
1453c098bfSClemens Ladisch  *
1553c098bfSClemens Ladisch  *   DAC0   -> both PCM1792A (L+R, each in mono mode)
1653c098bfSClemens Ladisch  *   ADC1  <-  1st PCM1804
1753c098bfSClemens Ladisch  *   ADC2  <-  2nd PCM1804
1853c098bfSClemens Ladisch  *   ADC3  <-  3rd PCM1804
1953c098bfSClemens Ladisch  */
2053c098bfSClemens Ladisch 
2153c098bfSClemens Ladisch #include <linux/pci.h>
2253c098bfSClemens Ladisch #include <linux/module.h>
2353c098bfSClemens Ladisch #include <sound/core.h>
2453c098bfSClemens Ladisch #include <sound/control.h>
2553c098bfSClemens Ladisch #include <sound/initval.h>
2653c098bfSClemens Ladisch #include <sound/pcm.h>
2753c098bfSClemens Ladisch #include "oxygen.h"
2853c098bfSClemens Ladisch 
2953c098bfSClemens Ladisch MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
3053c098bfSClemens Ladisch MODULE_DESCRIPTION("Studio Evolution SE6X driver");
3153c098bfSClemens Ladisch MODULE_LICENSE("GPL v2");
3253c098bfSClemens Ladisch 
3353c098bfSClemens Ladisch static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
3453c098bfSClemens Ladisch static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
3553c098bfSClemens Ladisch static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
3653c098bfSClemens Ladisch 
3753c098bfSClemens Ladisch module_param_array(index, int, NULL, 0444);
3853c098bfSClemens Ladisch MODULE_PARM_DESC(index, "card index");
3953c098bfSClemens Ladisch module_param_array(id, charp, NULL, 0444);
4053c098bfSClemens Ladisch MODULE_PARM_DESC(id, "ID string");
4153c098bfSClemens Ladisch module_param_array(enable, bool, NULL, 0444);
4253c098bfSClemens Ladisch MODULE_PARM_DESC(enable, "enable card");
4353c098bfSClemens Ladisch 
4453c098bfSClemens Ladisch static const struct pci_device_id se6x_ids[] = {
4553c098bfSClemens Ladisch 	{ OXYGEN_PCI_SUBID(0x13f6, 0x8788) },
4653c098bfSClemens Ladisch 	{ }
4753c098bfSClemens Ladisch };
4853c098bfSClemens Ladisch MODULE_DEVICE_TABLE(pci, se6x_ids);
4953c098bfSClemens Ladisch 
se6x_init(struct oxygen * chip)5053c098bfSClemens Ladisch static void se6x_init(struct oxygen *chip)
5153c098bfSClemens Ladisch {
5253c098bfSClemens Ladisch 	oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, 0x005);
5353c098bfSClemens Ladisch 
5453c098bfSClemens Ladisch 	snd_component_add(chip->card, "PCM1792A");
5553c098bfSClemens Ladisch 	snd_component_add(chip->card, "PCM1804");
5653c098bfSClemens Ladisch }
5753c098bfSClemens Ladisch 
se6x_control_filter(struct snd_kcontrol_new * template)5853c098bfSClemens Ladisch static int se6x_control_filter(struct snd_kcontrol_new *template)
5953c098bfSClemens Ladisch {
6053c098bfSClemens Ladisch 	/* no DAC volume/mute */
6153c098bfSClemens Ladisch 	if (!strncmp(template->name, "Master Playback ", 16))
6253c098bfSClemens Ladisch 		return 1;
6353c098bfSClemens Ladisch 	return 0;
6453c098bfSClemens Ladisch }
6553c098bfSClemens Ladisch 
se6x_cleanup(struct oxygen * chip)6653c098bfSClemens Ladisch static void se6x_cleanup(struct oxygen *chip)
6753c098bfSClemens Ladisch {
6853c098bfSClemens Ladisch }
6953c098bfSClemens Ladisch 
set_pcm1792a_params(struct oxygen * chip,struct snd_pcm_hw_params * params)7053c098bfSClemens Ladisch static void set_pcm1792a_params(struct oxygen *chip,
7153c098bfSClemens Ladisch 				struct snd_pcm_hw_params *params)
7253c098bfSClemens Ladisch {
7353c098bfSClemens Ladisch 	/* nothing to do (the microcontroller monitors DAC_LRCK) */
7453c098bfSClemens Ladisch }
7553c098bfSClemens Ladisch 
set_pcm1804_params(struct oxygen * chip,struct snd_pcm_hw_params * params)7653c098bfSClemens Ladisch static void set_pcm1804_params(struct oxygen *chip,
7753c098bfSClemens Ladisch 			       struct snd_pcm_hw_params *params)
7853c098bfSClemens Ladisch {
7953c098bfSClemens Ladisch }
8053c098bfSClemens Ladisch 
se6x_adjust_dac_routing(struct oxygen * chip,unsigned int play_routing)8153c098bfSClemens Ladisch static unsigned int se6x_adjust_dac_routing(struct oxygen *chip,
8253c098bfSClemens Ladisch 					    unsigned int play_routing)
8353c098bfSClemens Ladisch {
8453c098bfSClemens Ladisch 	/* route the same stereo pair to DAC0 and DAC1 */
8553c098bfSClemens Ladisch 	return ( play_routing       & OXYGEN_PLAY_DAC0_SOURCE_MASK) |
8653c098bfSClemens Ladisch 	       ((play_routing << 2) & OXYGEN_PLAY_DAC1_SOURCE_MASK);
8753c098bfSClemens Ladisch }
8853c098bfSClemens Ladisch 
8953c098bfSClemens Ladisch static const struct oxygen_model model_se6x = {
9053c098bfSClemens Ladisch 	.shortname = "Studio Evolution SE6X",
9153c098bfSClemens Ladisch 	.longname = "C-Media Oxygen HD Audio",
9253c098bfSClemens Ladisch 	.chip = "CMI8787",
9353c098bfSClemens Ladisch 	.init = se6x_init,
9453c098bfSClemens Ladisch 	.control_filter = se6x_control_filter,
9553c098bfSClemens Ladisch 	.cleanup = se6x_cleanup,
9653c098bfSClemens Ladisch 	.set_dac_params = set_pcm1792a_params,
9753c098bfSClemens Ladisch 	.set_adc_params = set_pcm1804_params,
9853c098bfSClemens Ladisch 	.adjust_dac_routing = se6x_adjust_dac_routing,
9953c098bfSClemens Ladisch 	.device_config = PLAYBACK_0_TO_I2S |
10053c098bfSClemens Ladisch 			 CAPTURE_0_FROM_I2S_1 |
10153c098bfSClemens Ladisch 			 CAPTURE_2_FROM_I2S_2 |
10253c098bfSClemens Ladisch 			 CAPTURE_3_FROM_I2S_3,
10353c098bfSClemens Ladisch 	.dac_channels_pcm = 2,
10453c098bfSClemens Ladisch 	.function_flags = OXYGEN_FUNCTION_SPI,
10553c098bfSClemens Ladisch 	.dac_mclks = OXYGEN_MCLKS(256, 128, 128),
10653c098bfSClemens Ladisch 	.adc_mclks = OXYGEN_MCLKS(256, 256, 128),
10753c098bfSClemens Ladisch 	.dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
10853c098bfSClemens Ladisch 	.adc_i2s_format = OXYGEN_I2S_FORMAT_I2S,
10953c098bfSClemens Ladisch };
11053c098bfSClemens Ladisch 
se6x_get_model(struct oxygen * chip,const struct pci_device_id * pci_id)11153c098bfSClemens Ladisch static int se6x_get_model(struct oxygen *chip,
11253c098bfSClemens Ladisch 			  const struct pci_device_id *pci_id)
11353c098bfSClemens Ladisch {
11453c098bfSClemens Ladisch 	chip->model = model_se6x;
11553c098bfSClemens Ladisch 	return 0;
11653c098bfSClemens Ladisch }
11753c098bfSClemens Ladisch 
se6x_probe(struct pci_dev * pci,const struct pci_device_id * pci_id)11853c098bfSClemens Ladisch static int se6x_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
11953c098bfSClemens Ladisch {
12053c098bfSClemens Ladisch 	static int dev;
12153c098bfSClemens Ladisch 	int err;
12253c098bfSClemens Ladisch 
12353c098bfSClemens Ladisch 	if (dev >= SNDRV_CARDS)
12453c098bfSClemens Ladisch 		return -ENODEV;
12553c098bfSClemens Ladisch 	if (!enable[dev]) {
12653c098bfSClemens Ladisch 		++dev;
12753c098bfSClemens Ladisch 		return -ENOENT;
12853c098bfSClemens Ladisch 	}
12953c098bfSClemens Ladisch 	err = oxygen_pci_probe(pci, index[dev], id[dev], THIS_MODULE,
13053c098bfSClemens Ladisch 			       se6x_ids, se6x_get_model);
13153c098bfSClemens Ladisch 	if (err >= 0)
13253c098bfSClemens Ladisch 		++dev;
13353c098bfSClemens Ladisch 	return err;
13453c098bfSClemens Ladisch }
13553c098bfSClemens Ladisch 
13653c098bfSClemens Ladisch static struct pci_driver se6x_driver = {
13753c098bfSClemens Ladisch 	.name = KBUILD_MODNAME,
13853c098bfSClemens Ladisch 	.id_table = se6x_ids,
13953c098bfSClemens Ladisch 	.probe = se6x_probe,
14053c098bfSClemens Ladisch #ifdef CONFIG_PM_SLEEP
14153c098bfSClemens Ladisch 	.driver = {
14253c098bfSClemens Ladisch 		.pm = &oxygen_pci_pm,
14353c098bfSClemens Ladisch 	},
14453c098bfSClemens Ladisch #endif
14553c098bfSClemens Ladisch 	.shutdown = oxygen_pci_shutdown,
14653c098bfSClemens Ladisch };
14753c098bfSClemens Ladisch 
14853c098bfSClemens Ladisch module_pci_driver(se6x_driver);
149