18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
28c2ecf20Sopenharmony_ci#ifndef OXYGEN_H_INCLUDED
38c2ecf20Sopenharmony_ci#define OXYGEN_H_INCLUDED
48c2ecf20Sopenharmony_ci
58c2ecf20Sopenharmony_ci#include <linux/mutex.h>
68c2ecf20Sopenharmony_ci#include <linux/spinlock.h>
78c2ecf20Sopenharmony_ci#include <linux/wait.h>
88c2ecf20Sopenharmony_ci#include <linux/workqueue.h>
98c2ecf20Sopenharmony_ci#include "oxygen_regs.h"
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_ci/* 1 << PCM_x == OXYGEN_CHANNEL_x */
128c2ecf20Sopenharmony_ci#define PCM_A		0
138c2ecf20Sopenharmony_ci#define PCM_B		1
148c2ecf20Sopenharmony_ci#define PCM_C		2
158c2ecf20Sopenharmony_ci#define PCM_SPDIF	3
168c2ecf20Sopenharmony_ci#define PCM_MULTICH	4
178c2ecf20Sopenharmony_ci#define PCM_AC97	5
188c2ecf20Sopenharmony_ci#define PCM_COUNT	6
198c2ecf20Sopenharmony_ci
208c2ecf20Sopenharmony_ci#define OXYGEN_MCLKS(f_single, f_double, f_quad) ((MCLK_##f_single << 0) | \
218c2ecf20Sopenharmony_ci						  (MCLK_##f_double << 2) | \
228c2ecf20Sopenharmony_ci						  (MCLK_##f_quad   << 4))
238c2ecf20Sopenharmony_ci
248c2ecf20Sopenharmony_ci#define OXYGEN_IO_SIZE	0x100
258c2ecf20Sopenharmony_ci
268c2ecf20Sopenharmony_ci#define OXYGEN_EEPROM_ID	0x434d	/* "CM" */
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_ci/* model-specific configuration of outputs/inputs */
298c2ecf20Sopenharmony_ci#define PLAYBACK_0_TO_I2S	0x0001
308c2ecf20Sopenharmony_ci     /* PLAYBACK_0_TO_AC97_0		not implemented */
318c2ecf20Sopenharmony_ci#define PLAYBACK_1_TO_SPDIF	0x0004
328c2ecf20Sopenharmony_ci#define PLAYBACK_2_TO_AC97_1	0x0008
338c2ecf20Sopenharmony_ci#define CAPTURE_0_FROM_I2S_1	0x0010
348c2ecf20Sopenharmony_ci#define CAPTURE_0_FROM_I2S_2	0x0020
358c2ecf20Sopenharmony_ci     /* CAPTURE_0_FROM_AC97_0		not implemented */
368c2ecf20Sopenharmony_ci#define CAPTURE_1_FROM_SPDIF	0x0080
378c2ecf20Sopenharmony_ci#define CAPTURE_2_FROM_I2S_2	0x0100
388c2ecf20Sopenharmony_ci#define CAPTURE_2_FROM_AC97_1	0x0200
398c2ecf20Sopenharmony_ci#define CAPTURE_3_FROM_I2S_3	0x0400
408c2ecf20Sopenharmony_ci#define MIDI_OUTPUT		0x0800
418c2ecf20Sopenharmony_ci#define MIDI_INPUT		0x1000
428c2ecf20Sopenharmony_ci#define AC97_CD_INPUT		0x2000
438c2ecf20Sopenharmony_ci#define AC97_FMIC_SWITCH	0x4000
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_cienum {
468c2ecf20Sopenharmony_ci	CONTROL_SPDIF_PCM,
478c2ecf20Sopenharmony_ci	CONTROL_SPDIF_INPUT_BITS,
488c2ecf20Sopenharmony_ci	CONTROL_MIC_CAPTURE_SWITCH,
498c2ecf20Sopenharmony_ci	CONTROL_LINE_CAPTURE_SWITCH,
508c2ecf20Sopenharmony_ci	CONTROL_CD_CAPTURE_SWITCH,
518c2ecf20Sopenharmony_ci	CONTROL_AUX_CAPTURE_SWITCH,
528c2ecf20Sopenharmony_ci	CONTROL_COUNT
538c2ecf20Sopenharmony_ci};
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_ci#define OXYGEN_PCI_SUBID(sv, sd) \
568c2ecf20Sopenharmony_ci	.vendor = PCI_VENDOR_ID_CMEDIA, \
578c2ecf20Sopenharmony_ci	.device = 0x8788, \
588c2ecf20Sopenharmony_ci	.subvendor = sv, \
598c2ecf20Sopenharmony_ci	.subdevice = sd
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_ci#define BROKEN_EEPROM_DRIVER_DATA ((unsigned long)-1)
628c2ecf20Sopenharmony_ci#define OXYGEN_PCI_SUBID_BROKEN_EEPROM \
638c2ecf20Sopenharmony_ci	OXYGEN_PCI_SUBID(PCI_VENDOR_ID_CMEDIA, 0x8788), \
648c2ecf20Sopenharmony_ci	.driver_data = BROKEN_EEPROM_DRIVER_DATA
658c2ecf20Sopenharmony_ci
668c2ecf20Sopenharmony_cistruct pci_dev;
678c2ecf20Sopenharmony_cistruct pci_device_id;
688c2ecf20Sopenharmony_cistruct snd_card;
698c2ecf20Sopenharmony_cistruct snd_pcm_substream;
708c2ecf20Sopenharmony_cistruct snd_pcm_hardware;
718c2ecf20Sopenharmony_cistruct snd_pcm_hw_params;
728c2ecf20Sopenharmony_cistruct snd_kcontrol_new;
738c2ecf20Sopenharmony_cistruct snd_rawmidi;
748c2ecf20Sopenharmony_cistruct snd_info_buffer;
758c2ecf20Sopenharmony_cistruct oxygen;
768c2ecf20Sopenharmony_ci
778c2ecf20Sopenharmony_cistruct oxygen_model {
788c2ecf20Sopenharmony_ci	const char *shortname;
798c2ecf20Sopenharmony_ci	const char *longname;
808c2ecf20Sopenharmony_ci	const char *chip;
818c2ecf20Sopenharmony_ci	void (*init)(struct oxygen *chip);
828c2ecf20Sopenharmony_ci	int (*control_filter)(struct snd_kcontrol_new *template);
838c2ecf20Sopenharmony_ci	int (*mixer_init)(struct oxygen *chip);
848c2ecf20Sopenharmony_ci	void (*cleanup)(struct oxygen *chip);
858c2ecf20Sopenharmony_ci	void (*suspend)(struct oxygen *chip);
868c2ecf20Sopenharmony_ci	void (*resume)(struct oxygen *chip);
878c2ecf20Sopenharmony_ci	void (*pcm_hardware_filter)(unsigned int channel,
888c2ecf20Sopenharmony_ci				    struct snd_pcm_hardware *hardware);
898c2ecf20Sopenharmony_ci	void (*set_dac_params)(struct oxygen *chip,
908c2ecf20Sopenharmony_ci			       struct snd_pcm_hw_params *params);
918c2ecf20Sopenharmony_ci	void (*set_adc_params)(struct oxygen *chip,
928c2ecf20Sopenharmony_ci			       struct snd_pcm_hw_params *params);
938c2ecf20Sopenharmony_ci	void (*update_dac_volume)(struct oxygen *chip);
948c2ecf20Sopenharmony_ci	void (*update_dac_mute)(struct oxygen *chip);
958c2ecf20Sopenharmony_ci	void (*update_center_lfe_mix)(struct oxygen *chip, bool mixed);
968c2ecf20Sopenharmony_ci	unsigned int (*adjust_dac_routing)(struct oxygen *chip,
978c2ecf20Sopenharmony_ci					   unsigned int play_routing);
988c2ecf20Sopenharmony_ci	void (*gpio_changed)(struct oxygen *chip);
998c2ecf20Sopenharmony_ci	void (*uart_input)(struct oxygen *chip);
1008c2ecf20Sopenharmony_ci	void (*ac97_switch)(struct oxygen *chip,
1018c2ecf20Sopenharmony_ci			    unsigned int reg, unsigned int mute);
1028c2ecf20Sopenharmony_ci	void (*dump_registers)(struct oxygen *chip,
1038c2ecf20Sopenharmony_ci			       struct snd_info_buffer *buffer);
1048c2ecf20Sopenharmony_ci	const unsigned int *dac_tlv;
1058c2ecf20Sopenharmony_ci	size_t model_data_size;
1068c2ecf20Sopenharmony_ci	unsigned int device_config;
1078c2ecf20Sopenharmony_ci	u8 dac_channels_pcm;
1088c2ecf20Sopenharmony_ci	u8 dac_channels_mixer;
1098c2ecf20Sopenharmony_ci	u8 dac_volume_min;
1108c2ecf20Sopenharmony_ci	u8 dac_volume_max;
1118c2ecf20Sopenharmony_ci	u8 misc_flags;
1128c2ecf20Sopenharmony_ci	u8 function_flags;
1138c2ecf20Sopenharmony_ci	u8 dac_mclks;
1148c2ecf20Sopenharmony_ci	u8 adc_mclks;
1158c2ecf20Sopenharmony_ci	u16 dac_i2s_format;
1168c2ecf20Sopenharmony_ci	u16 adc_i2s_format;
1178c2ecf20Sopenharmony_ci};
1188c2ecf20Sopenharmony_ci
1198c2ecf20Sopenharmony_cistruct oxygen {
1208c2ecf20Sopenharmony_ci	unsigned long addr;
1218c2ecf20Sopenharmony_ci	spinlock_t reg_lock;
1228c2ecf20Sopenharmony_ci	struct mutex mutex;
1238c2ecf20Sopenharmony_ci	struct snd_card *card;
1248c2ecf20Sopenharmony_ci	struct pci_dev *pci;
1258c2ecf20Sopenharmony_ci	struct snd_rawmidi *midi;
1268c2ecf20Sopenharmony_ci	int irq;
1278c2ecf20Sopenharmony_ci	void *model_data;
1288c2ecf20Sopenharmony_ci	unsigned int interrupt_mask;
1298c2ecf20Sopenharmony_ci	u8 dac_volume[8];
1308c2ecf20Sopenharmony_ci	u8 dac_mute;
1318c2ecf20Sopenharmony_ci	u8 pcm_active;
1328c2ecf20Sopenharmony_ci	u8 pcm_running;
1338c2ecf20Sopenharmony_ci	u8 dac_routing;
1348c2ecf20Sopenharmony_ci	u8 spdif_playback_enable;
1358c2ecf20Sopenharmony_ci	u8 has_ac97_0;
1368c2ecf20Sopenharmony_ci	u8 has_ac97_1;
1378c2ecf20Sopenharmony_ci	u32 spdif_bits;
1388c2ecf20Sopenharmony_ci	u32 spdif_pcm_bits;
1398c2ecf20Sopenharmony_ci	struct snd_pcm_substream *streams[PCM_COUNT];
1408c2ecf20Sopenharmony_ci	struct snd_kcontrol *controls[CONTROL_COUNT];
1418c2ecf20Sopenharmony_ci	struct work_struct spdif_input_bits_work;
1428c2ecf20Sopenharmony_ci	struct work_struct gpio_work;
1438c2ecf20Sopenharmony_ci	wait_queue_head_t ac97_waitqueue;
1448c2ecf20Sopenharmony_ci	union {
1458c2ecf20Sopenharmony_ci		u8 _8[OXYGEN_IO_SIZE];
1468c2ecf20Sopenharmony_ci		__le16 _16[OXYGEN_IO_SIZE / 2];
1478c2ecf20Sopenharmony_ci		__le32 _32[OXYGEN_IO_SIZE / 4];
1488c2ecf20Sopenharmony_ci	} saved_registers;
1498c2ecf20Sopenharmony_ci	u16 saved_ac97_registers[2][0x40];
1508c2ecf20Sopenharmony_ci	unsigned int uart_input_count;
1518c2ecf20Sopenharmony_ci	u8 uart_input[32];
1528c2ecf20Sopenharmony_ci	struct oxygen_model model;
1538c2ecf20Sopenharmony_ci};
1548c2ecf20Sopenharmony_ci
1558c2ecf20Sopenharmony_ci/* oxygen_lib.c */
1568c2ecf20Sopenharmony_ci
1578c2ecf20Sopenharmony_ciint oxygen_pci_probe(struct pci_dev *pci, int index, char *id,
1588c2ecf20Sopenharmony_ci		     struct module *owner,
1598c2ecf20Sopenharmony_ci		     const struct pci_device_id *ids,
1608c2ecf20Sopenharmony_ci		     int (*get_model)(struct oxygen *chip,
1618c2ecf20Sopenharmony_ci				      const struct pci_device_id *id
1628c2ecf20Sopenharmony_ci				     )
1638c2ecf20Sopenharmony_ci		    );
1648c2ecf20Sopenharmony_civoid oxygen_pci_remove(struct pci_dev *pci);
1658c2ecf20Sopenharmony_ci#ifdef CONFIG_PM_SLEEP
1668c2ecf20Sopenharmony_ciextern const struct dev_pm_ops oxygen_pci_pm;
1678c2ecf20Sopenharmony_ci#endif
1688c2ecf20Sopenharmony_civoid oxygen_pci_shutdown(struct pci_dev *pci);
1698c2ecf20Sopenharmony_ci
1708c2ecf20Sopenharmony_ci/* oxygen_mixer.c */
1718c2ecf20Sopenharmony_ci
1728c2ecf20Sopenharmony_ciint oxygen_mixer_init(struct oxygen *chip);
1738c2ecf20Sopenharmony_civoid oxygen_update_dac_routing(struct oxygen *chip);
1748c2ecf20Sopenharmony_civoid oxygen_update_spdif_source(struct oxygen *chip);
1758c2ecf20Sopenharmony_ci
1768c2ecf20Sopenharmony_ci/* oxygen_pcm.c */
1778c2ecf20Sopenharmony_ci
1788c2ecf20Sopenharmony_ciint oxygen_pcm_init(struct oxygen *chip);
1798c2ecf20Sopenharmony_ci
1808c2ecf20Sopenharmony_ci/* oxygen_io.c */
1818c2ecf20Sopenharmony_ci
1828c2ecf20Sopenharmony_ciu8 oxygen_read8(struct oxygen *chip, unsigned int reg);
1838c2ecf20Sopenharmony_ciu16 oxygen_read16(struct oxygen *chip, unsigned int reg);
1848c2ecf20Sopenharmony_ciu32 oxygen_read32(struct oxygen *chip, unsigned int reg);
1858c2ecf20Sopenharmony_civoid oxygen_write8(struct oxygen *chip, unsigned int reg, u8 value);
1868c2ecf20Sopenharmony_civoid oxygen_write16(struct oxygen *chip, unsigned int reg, u16 value);
1878c2ecf20Sopenharmony_civoid oxygen_write32(struct oxygen *chip, unsigned int reg, u32 value);
1888c2ecf20Sopenharmony_civoid oxygen_write8_masked(struct oxygen *chip, unsigned int reg,
1898c2ecf20Sopenharmony_ci			  u8 value, u8 mask);
1908c2ecf20Sopenharmony_civoid oxygen_write16_masked(struct oxygen *chip, unsigned int reg,
1918c2ecf20Sopenharmony_ci			   u16 value, u16 mask);
1928c2ecf20Sopenharmony_civoid oxygen_write32_masked(struct oxygen *chip, unsigned int reg,
1938c2ecf20Sopenharmony_ci			   u32 value, u32 mask);
1948c2ecf20Sopenharmony_ci
1958c2ecf20Sopenharmony_ciu16 oxygen_read_ac97(struct oxygen *chip, unsigned int codec,
1968c2ecf20Sopenharmony_ci		     unsigned int index);
1978c2ecf20Sopenharmony_civoid oxygen_write_ac97(struct oxygen *chip, unsigned int codec,
1988c2ecf20Sopenharmony_ci		       unsigned int index, u16 data);
1998c2ecf20Sopenharmony_civoid oxygen_write_ac97_masked(struct oxygen *chip, unsigned int codec,
2008c2ecf20Sopenharmony_ci			      unsigned int index, u16 data, u16 mask);
2018c2ecf20Sopenharmony_ci
2028c2ecf20Sopenharmony_ciint oxygen_write_spi(struct oxygen *chip, u8 control, unsigned int data);
2038c2ecf20Sopenharmony_civoid oxygen_write_i2c(struct oxygen *chip, u8 device, u8 map, u8 data);
2048c2ecf20Sopenharmony_ci
2058c2ecf20Sopenharmony_civoid oxygen_reset_uart(struct oxygen *chip);
2068c2ecf20Sopenharmony_civoid oxygen_write_uart(struct oxygen *chip, u8 data);
2078c2ecf20Sopenharmony_ci
2088c2ecf20Sopenharmony_ciu16 oxygen_read_eeprom(struct oxygen *chip, unsigned int index);
2098c2ecf20Sopenharmony_civoid oxygen_write_eeprom(struct oxygen *chip, unsigned int index, u16 value);
2108c2ecf20Sopenharmony_ci
2118c2ecf20Sopenharmony_cistatic inline void oxygen_set_bits8(struct oxygen *chip,
2128c2ecf20Sopenharmony_ci				    unsigned int reg, u8 value)
2138c2ecf20Sopenharmony_ci{
2148c2ecf20Sopenharmony_ci	oxygen_write8_masked(chip, reg, value, value);
2158c2ecf20Sopenharmony_ci}
2168c2ecf20Sopenharmony_ci
2178c2ecf20Sopenharmony_cistatic inline void oxygen_set_bits16(struct oxygen *chip,
2188c2ecf20Sopenharmony_ci				     unsigned int reg, u16 value)
2198c2ecf20Sopenharmony_ci{
2208c2ecf20Sopenharmony_ci	oxygen_write16_masked(chip, reg, value, value);
2218c2ecf20Sopenharmony_ci}
2228c2ecf20Sopenharmony_ci
2238c2ecf20Sopenharmony_cistatic inline void oxygen_set_bits32(struct oxygen *chip,
2248c2ecf20Sopenharmony_ci				     unsigned int reg, u32 value)
2258c2ecf20Sopenharmony_ci{
2268c2ecf20Sopenharmony_ci	oxygen_write32_masked(chip, reg, value, value);
2278c2ecf20Sopenharmony_ci}
2288c2ecf20Sopenharmony_ci
2298c2ecf20Sopenharmony_cistatic inline void oxygen_clear_bits8(struct oxygen *chip,
2308c2ecf20Sopenharmony_ci				      unsigned int reg, u8 value)
2318c2ecf20Sopenharmony_ci{
2328c2ecf20Sopenharmony_ci	oxygen_write8_masked(chip, reg, 0, value);
2338c2ecf20Sopenharmony_ci}
2348c2ecf20Sopenharmony_ci
2358c2ecf20Sopenharmony_cistatic inline void oxygen_clear_bits16(struct oxygen *chip,
2368c2ecf20Sopenharmony_ci				       unsigned int reg, u16 value)
2378c2ecf20Sopenharmony_ci{
2388c2ecf20Sopenharmony_ci	oxygen_write16_masked(chip, reg, 0, value);
2398c2ecf20Sopenharmony_ci}
2408c2ecf20Sopenharmony_ci
2418c2ecf20Sopenharmony_cistatic inline void oxygen_clear_bits32(struct oxygen *chip,
2428c2ecf20Sopenharmony_ci				       unsigned int reg, u32 value)
2438c2ecf20Sopenharmony_ci{
2448c2ecf20Sopenharmony_ci	oxygen_write32_masked(chip, reg, 0, value);
2458c2ecf20Sopenharmony_ci}
2468c2ecf20Sopenharmony_ci
2478c2ecf20Sopenharmony_cistatic inline void oxygen_ac97_set_bits(struct oxygen *chip, unsigned int codec,
2488c2ecf20Sopenharmony_ci					unsigned int index, u16 value)
2498c2ecf20Sopenharmony_ci{
2508c2ecf20Sopenharmony_ci	oxygen_write_ac97_masked(chip, codec, index, value, value);
2518c2ecf20Sopenharmony_ci}
2528c2ecf20Sopenharmony_ci
2538c2ecf20Sopenharmony_cistatic inline void oxygen_ac97_clear_bits(struct oxygen *chip,
2548c2ecf20Sopenharmony_ci					  unsigned int codec,
2558c2ecf20Sopenharmony_ci					  unsigned int index, u16 value)
2568c2ecf20Sopenharmony_ci{
2578c2ecf20Sopenharmony_ci	oxygen_write_ac97_masked(chip, codec, index, 0, value);
2588c2ecf20Sopenharmony_ci}
2598c2ecf20Sopenharmony_ci
2608c2ecf20Sopenharmony_ci#endif
261