1e3d280fcSTakashi Iwai /* 2e3d280fcSTakashi Iwai * HD-audio core stuff 3e3d280fcSTakashi Iwai */ 4e3d280fcSTakashi Iwai 5e3d280fcSTakashi Iwai #ifndef __SOUND_HDAUDIO_H 6e3d280fcSTakashi Iwai #define __SOUND_HDAUDIO_H 7e3d280fcSTakashi Iwai 8e3d280fcSTakashi Iwai #include <linux/device.h> 9d068ebc2STakashi Iwai #include <sound/hda_verbs.h> 10d068ebc2STakashi Iwai 117639a06cSTakashi Iwai /* codec node id */ 127639a06cSTakashi Iwai typedef u16 hda_nid_t; 137639a06cSTakashi Iwai 14d068ebc2STakashi Iwai struct hdac_bus; 15d068ebc2STakashi Iwai struct hdac_device; 16d068ebc2STakashi Iwai struct hdac_driver; 173256be65STakashi Iwai struct hdac_widget_tree; 18e3d280fcSTakashi Iwai 19e3d280fcSTakashi Iwai /* 20e3d280fcSTakashi Iwai * exported bus type 21e3d280fcSTakashi Iwai */ 22e3d280fcSTakashi Iwai extern struct bus_type snd_hda_bus_type; 23e3d280fcSTakashi Iwai 24e3d280fcSTakashi Iwai /* 2571fc4c7eSTakashi Iwai * generic arrays 2671fc4c7eSTakashi Iwai */ 2771fc4c7eSTakashi Iwai struct snd_array { 2871fc4c7eSTakashi Iwai unsigned int used; 2971fc4c7eSTakashi Iwai unsigned int alloced; 3071fc4c7eSTakashi Iwai unsigned int elem_size; 3171fc4c7eSTakashi Iwai unsigned int alloc_align; 3271fc4c7eSTakashi Iwai void *list; 3371fc4c7eSTakashi Iwai }; 3471fc4c7eSTakashi Iwai 3571fc4c7eSTakashi Iwai /* 36e3d280fcSTakashi Iwai * HD-audio codec base device 37e3d280fcSTakashi Iwai */ 38e3d280fcSTakashi Iwai struct hdac_device { 39e3d280fcSTakashi Iwai struct device dev; 40e3d280fcSTakashi Iwai int type; 41d068ebc2STakashi Iwai struct hdac_bus *bus; 42d068ebc2STakashi Iwai unsigned int addr; /* codec address */ 43d068ebc2STakashi Iwai struct list_head list; /* list point for bus codec_list */ 447639a06cSTakashi Iwai 457639a06cSTakashi Iwai hda_nid_t afg; /* AFG node id */ 467639a06cSTakashi Iwai hda_nid_t mfg; /* MFG node id */ 477639a06cSTakashi Iwai 487639a06cSTakashi Iwai /* ids */ 497639a06cSTakashi Iwai unsigned int vendor_id; 507639a06cSTakashi Iwai unsigned int subsystem_id; 517639a06cSTakashi Iwai unsigned int revision_id; 527639a06cSTakashi Iwai unsigned int afg_function_id; 537639a06cSTakashi Iwai unsigned int mfg_function_id; 547639a06cSTakashi Iwai unsigned int afg_unsol:1; 557639a06cSTakashi Iwai unsigned int mfg_unsol:1; 567639a06cSTakashi Iwai 577639a06cSTakashi Iwai unsigned int power_caps; /* FG power caps */ 587639a06cSTakashi Iwai 597639a06cSTakashi Iwai const char *vendor_name; /* codec vendor name */ 607639a06cSTakashi Iwai const char *chip_name; /* codec chip name */ 617639a06cSTakashi Iwai 6205852448STakashi Iwai /* verb exec op override */ 6305852448STakashi Iwai int (*exec_verb)(struct hdac_device *dev, unsigned int cmd, 6405852448STakashi Iwai unsigned int flags, unsigned int *res); 6505852448STakashi Iwai 667639a06cSTakashi Iwai /* widgets */ 677639a06cSTakashi Iwai unsigned int num_nodes; 687639a06cSTakashi Iwai hda_nid_t start_nid, end_nid; 697639a06cSTakashi Iwai 707639a06cSTakashi Iwai /* misc flags */ 717639a06cSTakashi Iwai atomic_t in_pm; /* suspend/resume being performed */ 723256be65STakashi Iwai 733256be65STakashi Iwai /* sysfs */ 743256be65STakashi Iwai struct hdac_widget_tree *widgets; 754d75faa0STakashi Iwai 764d75faa0STakashi Iwai /* regmap */ 774d75faa0STakashi Iwai struct regmap *regmap; 784d75faa0STakashi Iwai bool lazy_cache:1; /* don't wake up for writes */ 79e3d280fcSTakashi Iwai }; 80e3d280fcSTakashi Iwai 81e3d280fcSTakashi Iwai /* device/driver type used for matching */ 82e3d280fcSTakashi Iwai enum { 83e3d280fcSTakashi Iwai HDA_DEV_CORE, 84e3d280fcSTakashi Iwai HDA_DEV_LEGACY, 85e3d280fcSTakashi Iwai }; 86e3d280fcSTakashi Iwai 877639a06cSTakashi Iwai /* direction */ 887639a06cSTakashi Iwai enum { 897639a06cSTakashi Iwai HDA_INPUT, HDA_OUTPUT 907639a06cSTakashi Iwai }; 917639a06cSTakashi Iwai 92e3d280fcSTakashi Iwai #define dev_to_hdac_dev(_dev) container_of(_dev, struct hdac_device, dev) 93e3d280fcSTakashi Iwai 947639a06cSTakashi Iwai int snd_hdac_device_init(struct hdac_device *dev, struct hdac_bus *bus, 957639a06cSTakashi Iwai const char *name, unsigned int addr); 967639a06cSTakashi Iwai void snd_hdac_device_exit(struct hdac_device *dev); 973256be65STakashi Iwai int snd_hdac_device_register(struct hdac_device *codec); 983256be65STakashi Iwai void snd_hdac_device_unregister(struct hdac_device *codec); 997639a06cSTakashi Iwai 1007639a06cSTakashi Iwai int snd_hdac_refresh_widgets(struct hdac_device *codec); 1017639a06cSTakashi Iwai 1027639a06cSTakashi Iwai unsigned int snd_hdac_make_cmd(struct hdac_device *codec, hda_nid_t nid, 1037639a06cSTakashi Iwai unsigned int verb, unsigned int parm); 10405852448STakashi Iwai int snd_hdac_exec_verb(struct hdac_device *codec, unsigned int cmd, 10505852448STakashi Iwai unsigned int flags, unsigned int *res); 1067639a06cSTakashi Iwai int snd_hdac_read(struct hdac_device *codec, hda_nid_t nid, 1077639a06cSTakashi Iwai unsigned int verb, unsigned int parm, unsigned int *res); 10801ed3c06STakashi Iwai int _snd_hdac_read_parm(struct hdac_device *codec, hda_nid_t nid, int parm, 10901ed3c06STakashi Iwai unsigned int *res); 1109ba17b4dSTakashi Iwai int snd_hdac_read_parm_uncached(struct hdac_device *codec, hda_nid_t nid, 1119ba17b4dSTakashi Iwai int parm); 1127639a06cSTakashi Iwai int snd_hdac_get_connections(struct hdac_device *codec, hda_nid_t nid, 1137639a06cSTakashi Iwai hda_nid_t *conn_list, int max_conns); 1147639a06cSTakashi Iwai int snd_hdac_get_sub_nodes(struct hdac_device *codec, hda_nid_t nid, 1157639a06cSTakashi Iwai hda_nid_t *start_id); 1167639a06cSTakashi Iwai 11701ed3c06STakashi Iwai /** 11801ed3c06STakashi Iwai * snd_hdac_read_parm - read a codec parameter 11901ed3c06STakashi Iwai * @codec: the codec object 12001ed3c06STakashi Iwai * @nid: NID to read a parameter 12101ed3c06STakashi Iwai * @parm: parameter to read 12201ed3c06STakashi Iwai * 12301ed3c06STakashi Iwai * Returns -1 for error. If you need to distinguish the error more 12401ed3c06STakashi Iwai * strictly, use _snd_hdac_read_parm() directly. 12501ed3c06STakashi Iwai */ 12601ed3c06STakashi Iwai static inline int snd_hdac_read_parm(struct hdac_device *codec, hda_nid_t nid, 12701ed3c06STakashi Iwai int parm) 12801ed3c06STakashi Iwai { 12901ed3c06STakashi Iwai unsigned int val; 13001ed3c06STakashi Iwai 13101ed3c06STakashi Iwai return _snd_hdac_read_parm(codec, nid, parm, &val) < 0 ? -1 : val; 13201ed3c06STakashi Iwai } 13301ed3c06STakashi Iwai 1347639a06cSTakashi Iwai #ifdef CONFIG_PM 1357639a06cSTakashi Iwai void snd_hdac_power_up(struct hdac_device *codec); 1367639a06cSTakashi Iwai void snd_hdac_power_down(struct hdac_device *codec); 1377639a06cSTakashi Iwai #else 1387639a06cSTakashi Iwai static inline void snd_hdac_power_up(struct hdac_device *codec) {} 1397639a06cSTakashi Iwai static inline void snd_hdac_power_down(struct hdac_device *codec) {} 1407639a06cSTakashi Iwai #endif 1417639a06cSTakashi Iwai 142e3d280fcSTakashi Iwai /* 143e3d280fcSTakashi Iwai * HD-audio codec base driver 144e3d280fcSTakashi Iwai */ 145e3d280fcSTakashi Iwai struct hdac_driver { 146e3d280fcSTakashi Iwai struct device_driver driver; 147e3d280fcSTakashi Iwai int type; 148e3d280fcSTakashi Iwai int (*match)(struct hdac_device *dev, struct hdac_driver *drv); 149d068ebc2STakashi Iwai void (*unsol_event)(struct hdac_device *dev, unsigned int event); 150e3d280fcSTakashi Iwai }; 151e3d280fcSTakashi Iwai 152e3d280fcSTakashi Iwai #define drv_to_hdac_driver(_drv) container_of(_drv, struct hdac_driver, driver) 153e3d280fcSTakashi Iwai 154d068ebc2STakashi Iwai /* 155d068ebc2STakashi Iwai * HD-audio bus base driver 156d068ebc2STakashi Iwai */ 157d068ebc2STakashi Iwai struct hdac_bus_ops { 158d068ebc2STakashi Iwai /* send a single command */ 159d068ebc2STakashi Iwai int (*command)(struct hdac_bus *bus, unsigned int cmd); 160d068ebc2STakashi Iwai /* get a response from the last command */ 161d068ebc2STakashi Iwai int (*get_response)(struct hdac_bus *bus, unsigned int addr, 162d068ebc2STakashi Iwai unsigned int *res); 163d068ebc2STakashi Iwai }; 164d068ebc2STakashi Iwai 165d068ebc2STakashi Iwai #define HDA_UNSOL_QUEUE_SIZE 64 166d068ebc2STakashi Iwai 167d068ebc2STakashi Iwai struct hdac_bus { 168d068ebc2STakashi Iwai struct device *dev; 169d068ebc2STakashi Iwai const struct hdac_bus_ops *ops; 170d068ebc2STakashi Iwai 171d068ebc2STakashi Iwai /* codec linked list */ 172d068ebc2STakashi Iwai struct list_head codec_list; 173d068ebc2STakashi Iwai unsigned int num_codecs; 174d068ebc2STakashi Iwai 175d068ebc2STakashi Iwai /* link caddr -> codec */ 176d068ebc2STakashi Iwai struct hdac_device *caddr_tbl[HDA_MAX_CODEC_ADDRESS + 1]; 177d068ebc2STakashi Iwai 178d068ebc2STakashi Iwai /* unsolicited event queue */ 179d068ebc2STakashi Iwai u32 unsol_queue[HDA_UNSOL_QUEUE_SIZE * 2]; /* ring buffer */ 180d068ebc2STakashi Iwai unsigned int unsol_rp, unsol_wp; 181d068ebc2STakashi Iwai struct work_struct unsol_work; 182d068ebc2STakashi Iwai 183d068ebc2STakashi Iwai /* bit flags of powered codecs */ 184d068ebc2STakashi Iwai unsigned long codec_powered; 185d068ebc2STakashi Iwai 186d068ebc2STakashi Iwai /* flags */ 187d068ebc2STakashi Iwai bool sync_write:1; /* sync after verb write */ 188d068ebc2STakashi Iwai 189d068ebc2STakashi Iwai /* locks */ 190d068ebc2STakashi Iwai struct mutex cmd_mutex; 191d068ebc2STakashi Iwai }; 192d068ebc2STakashi Iwai 193d068ebc2STakashi Iwai int snd_hdac_bus_init(struct hdac_bus *bus, struct device *dev, 194d068ebc2STakashi Iwai const struct hdac_bus_ops *ops); 195d068ebc2STakashi Iwai void snd_hdac_bus_exit(struct hdac_bus *bus); 196d068ebc2STakashi Iwai int snd_hdac_bus_exec_verb(struct hdac_bus *bus, unsigned int addr, 197d068ebc2STakashi Iwai unsigned int cmd, unsigned int *res); 198d068ebc2STakashi Iwai int snd_hdac_bus_exec_verb_unlocked(struct hdac_bus *bus, unsigned int addr, 199d068ebc2STakashi Iwai unsigned int cmd, unsigned int *res); 200d068ebc2STakashi Iwai void snd_hdac_bus_queue_event(struct hdac_bus *bus, u32 res, u32 res_ex); 201d068ebc2STakashi Iwai 202d068ebc2STakashi Iwai int snd_hdac_bus_add_device(struct hdac_bus *bus, struct hdac_device *codec); 203d068ebc2STakashi Iwai void snd_hdac_bus_remove_device(struct hdac_bus *bus, 204d068ebc2STakashi Iwai struct hdac_device *codec); 205d068ebc2STakashi Iwai 2067639a06cSTakashi Iwai static inline void snd_hdac_codec_link_up(struct hdac_device *codec) 2077639a06cSTakashi Iwai { 2087639a06cSTakashi Iwai set_bit(codec->addr, &codec->bus->codec_powered); 2097639a06cSTakashi Iwai } 2107639a06cSTakashi Iwai 2117639a06cSTakashi Iwai static inline void snd_hdac_codec_link_down(struct hdac_device *codec) 2127639a06cSTakashi Iwai { 2137639a06cSTakashi Iwai clear_bit(codec->addr, &codec->bus->codec_powered); 2147639a06cSTakashi Iwai } 2157639a06cSTakashi Iwai 21671fc4c7eSTakashi Iwai /* 21771fc4c7eSTakashi Iwai * generic array helpers 21871fc4c7eSTakashi Iwai */ 21971fc4c7eSTakashi Iwai void *snd_array_new(struct snd_array *array); 22071fc4c7eSTakashi Iwai void snd_array_free(struct snd_array *array); 22171fc4c7eSTakashi Iwai static inline void snd_array_init(struct snd_array *array, unsigned int size, 22271fc4c7eSTakashi Iwai unsigned int align) 22371fc4c7eSTakashi Iwai { 22471fc4c7eSTakashi Iwai array->elem_size = size; 22571fc4c7eSTakashi Iwai array->alloc_align = align; 22671fc4c7eSTakashi Iwai } 22771fc4c7eSTakashi Iwai 22871fc4c7eSTakashi Iwai static inline void *snd_array_elem(struct snd_array *array, unsigned int idx) 22971fc4c7eSTakashi Iwai { 23071fc4c7eSTakashi Iwai return array->list + idx * array->elem_size; 23171fc4c7eSTakashi Iwai } 23271fc4c7eSTakashi Iwai 23371fc4c7eSTakashi Iwai static inline unsigned int snd_array_index(struct snd_array *array, void *ptr) 23471fc4c7eSTakashi Iwai { 23571fc4c7eSTakashi Iwai return (unsigned long)(ptr - array->list) / array->elem_size; 23671fc4c7eSTakashi Iwai } 23771fc4c7eSTakashi Iwai 238e3d280fcSTakashi Iwai #endif /* __SOUND_HDAUDIO_H */ 239