Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  * C-Media CMI8787 driver for the Studio Evolution SE6X
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  * Copyright (c) Clemens Ladisch <clemens@ladisch.de>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9)  * CMI8787:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11)  *   SPI    -> microcontroller (not actually used)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12)  *   GPIO 0 -> do.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13)  *   GPIO 2 -> do.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15)  *   DAC0   -> both PCM1792A (L+R, each in mono mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16)  *   ADC1  <-  1st PCM1804
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17)  *   ADC2  <-  2nd PCM1804
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18)  *   ADC3  <-  3rd PCM1804
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) #include <linux/pci.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) #include <sound/core.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) #include <sound/control.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) #include <sound/initval.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) #include <sound/pcm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) #include "oxygen.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) MODULE_DESCRIPTION("Studio Evolution SE6X driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) MODULE_LICENSE("GPL v2");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) MODULE_SUPPORTED_DEVICE("{{Studio Evolution,SE6X}}");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) module_param_array(index, int, NULL, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) MODULE_PARM_DESC(index, "card index");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) module_param_array(id, charp, NULL, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) MODULE_PARM_DESC(id, "ID string");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) module_param_array(enable, bool, NULL, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) MODULE_PARM_DESC(enable, "enable card");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) static const struct pci_device_id se6x_ids[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 	{ OXYGEN_PCI_SUBID(0x13f6, 0x8788) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 	{ }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) MODULE_DEVICE_TABLE(pci, se6x_ids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) static void se6x_init(struct oxygen *chip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 	oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, 0x005);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 	snd_component_add(chip->card, "PCM1792A");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 	snd_component_add(chip->card, "PCM1804");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) static int se6x_control_filter(struct snd_kcontrol_new *template)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 	/* no DAC volume/mute */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 	if (!strncmp(template->name, "Master Playback ", 16))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 		return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) static void se6x_cleanup(struct oxygen *chip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) static void set_pcm1792a_params(struct oxygen *chip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 				struct snd_pcm_hw_params *params)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 	/* nothing to do (the microcontroller monitors DAC_LRCK) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) static void set_pcm1804_params(struct oxygen *chip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 			       struct snd_pcm_hw_params *params)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) static unsigned int se6x_adjust_dac_routing(struct oxygen *chip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 					    unsigned int play_routing)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 	/* route the same stereo pair to DAC0 and DAC1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 	return ( play_routing       & OXYGEN_PLAY_DAC0_SOURCE_MASK) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 	       ((play_routing << 2) & OXYGEN_PLAY_DAC1_SOURCE_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) static const struct oxygen_model model_se6x = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 	.shortname = "Studio Evolution SE6X",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 	.longname = "C-Media Oxygen HD Audio",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 	.chip = "CMI8787",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 	.init = se6x_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 	.control_filter = se6x_control_filter,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 	.cleanup = se6x_cleanup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 	.set_dac_params = set_pcm1792a_params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 	.set_adc_params = set_pcm1804_params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 	.adjust_dac_routing = se6x_adjust_dac_routing,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 	.device_config = PLAYBACK_0_TO_I2S |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 			 CAPTURE_0_FROM_I2S_1 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 			 CAPTURE_2_FROM_I2S_2 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 			 CAPTURE_3_FROM_I2S_3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 	.dac_channels_pcm = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 	.function_flags = OXYGEN_FUNCTION_SPI,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 	.dac_mclks = OXYGEN_MCLKS(256, 128, 128),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 	.adc_mclks = OXYGEN_MCLKS(256, 256, 128),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 	.dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 	.adc_i2s_format = OXYGEN_I2S_FORMAT_I2S,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) static int se6x_get_model(struct oxygen *chip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 			  const struct pci_device_id *pci_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 	chip->model = model_se6x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) static int se6x_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 	static int dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 	int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 	if (dev >= SNDRV_CARDS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 		return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 	if (!enable[dev]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 		++dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 		return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 	err = oxygen_pci_probe(pci, index[dev], id[dev], THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 			       se6x_ids, se6x_get_model);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 	if (err >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 		++dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 	return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) static struct pci_driver se6x_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 	.name = KBUILD_MODNAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 	.id_table = se6x_ids,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 	.probe = se6x_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 	.remove = oxygen_pci_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) #ifdef CONFIG_PM_SLEEP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 	.driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 		.pm = &oxygen_pci_pm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 	.shutdown = oxygen_pci_shutdown,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) module_pci_driver(se6x_driver);