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; 785e56bceaSTakashi Iwai struct snd_array vendor_verbs; 794d75faa0STakashi Iwai bool lazy_cache:1; /* don't wake up for writes */ 80faa75f8aSTakashi Iwai bool caps_overwriting:1; /* caps overwrite being in process */ 81e3d280fcSTakashi Iwai }; 82e3d280fcSTakashi Iwai 83e3d280fcSTakashi Iwai /* device/driver type used for matching */ 84e3d280fcSTakashi Iwai enum { 85e3d280fcSTakashi Iwai HDA_DEV_CORE, 86e3d280fcSTakashi Iwai HDA_DEV_LEGACY, 87e3d280fcSTakashi Iwai }; 88e3d280fcSTakashi Iwai 897639a06cSTakashi Iwai /* direction */ 907639a06cSTakashi Iwai enum { 917639a06cSTakashi Iwai HDA_INPUT, HDA_OUTPUT 927639a06cSTakashi Iwai }; 937639a06cSTakashi Iwai 94e3d280fcSTakashi Iwai #define dev_to_hdac_dev(_dev) container_of(_dev, struct hdac_device, dev) 95e3d280fcSTakashi Iwai 967639a06cSTakashi Iwai int snd_hdac_device_init(struct hdac_device *dev, struct hdac_bus *bus, 977639a06cSTakashi Iwai const char *name, unsigned int addr); 987639a06cSTakashi Iwai void snd_hdac_device_exit(struct hdac_device *dev); 993256be65STakashi Iwai int snd_hdac_device_register(struct hdac_device *codec); 1003256be65STakashi Iwai void snd_hdac_device_unregister(struct hdac_device *codec); 1017639a06cSTakashi Iwai 1027639a06cSTakashi Iwai int snd_hdac_refresh_widgets(struct hdac_device *codec); 1037639a06cSTakashi Iwai 1047639a06cSTakashi Iwai unsigned int snd_hdac_make_cmd(struct hdac_device *codec, hda_nid_t nid, 1057639a06cSTakashi Iwai unsigned int verb, unsigned int parm); 10605852448STakashi Iwai int snd_hdac_exec_verb(struct hdac_device *codec, unsigned int cmd, 10705852448STakashi Iwai unsigned int flags, unsigned int *res); 1087639a06cSTakashi Iwai int snd_hdac_read(struct hdac_device *codec, hda_nid_t nid, 1097639a06cSTakashi Iwai unsigned int verb, unsigned int parm, unsigned int *res); 11001ed3c06STakashi Iwai int _snd_hdac_read_parm(struct hdac_device *codec, hda_nid_t nid, int parm, 11101ed3c06STakashi Iwai unsigned int *res); 1129ba17b4dSTakashi Iwai int snd_hdac_read_parm_uncached(struct hdac_device *codec, hda_nid_t nid, 1139ba17b4dSTakashi Iwai int parm); 114faa75f8aSTakashi Iwai int snd_hdac_override_parm(struct hdac_device *codec, hda_nid_t nid, 115faa75f8aSTakashi Iwai unsigned int parm, unsigned int val); 1167639a06cSTakashi Iwai int snd_hdac_get_connections(struct hdac_device *codec, hda_nid_t nid, 1177639a06cSTakashi Iwai hda_nid_t *conn_list, int max_conns); 1187639a06cSTakashi Iwai int snd_hdac_get_sub_nodes(struct hdac_device *codec, hda_nid_t nid, 1197639a06cSTakashi Iwai hda_nid_t *start_id); 1207639a06cSTakashi Iwai 12101ed3c06STakashi Iwai /** 12201ed3c06STakashi Iwai * snd_hdac_read_parm - read a codec parameter 12301ed3c06STakashi Iwai * @codec: the codec object 12401ed3c06STakashi Iwai * @nid: NID to read a parameter 12501ed3c06STakashi Iwai * @parm: parameter to read 12601ed3c06STakashi Iwai * 12701ed3c06STakashi Iwai * Returns -1 for error. If you need to distinguish the error more 12801ed3c06STakashi Iwai * strictly, use _snd_hdac_read_parm() directly. 12901ed3c06STakashi Iwai */ 13001ed3c06STakashi Iwai static inline int snd_hdac_read_parm(struct hdac_device *codec, hda_nid_t nid, 13101ed3c06STakashi Iwai int parm) 13201ed3c06STakashi Iwai { 13301ed3c06STakashi Iwai unsigned int val; 13401ed3c06STakashi Iwai 13501ed3c06STakashi Iwai return _snd_hdac_read_parm(codec, nid, parm, &val) < 0 ? -1 : val; 13601ed3c06STakashi Iwai } 13701ed3c06STakashi Iwai 1387639a06cSTakashi Iwai #ifdef CONFIG_PM 1397639a06cSTakashi Iwai void snd_hdac_power_up(struct hdac_device *codec); 1407639a06cSTakashi Iwai void snd_hdac_power_down(struct hdac_device *codec); 1417639a06cSTakashi Iwai #else 1427639a06cSTakashi Iwai static inline void snd_hdac_power_up(struct hdac_device *codec) {} 1437639a06cSTakashi Iwai static inline void snd_hdac_power_down(struct hdac_device *codec) {} 1447639a06cSTakashi Iwai #endif 1457639a06cSTakashi Iwai 146e3d280fcSTakashi Iwai /* 147e3d280fcSTakashi Iwai * HD-audio codec base driver 148e3d280fcSTakashi Iwai */ 149e3d280fcSTakashi Iwai struct hdac_driver { 150e3d280fcSTakashi Iwai struct device_driver driver; 151e3d280fcSTakashi Iwai int type; 152e3d280fcSTakashi Iwai int (*match)(struct hdac_device *dev, struct hdac_driver *drv); 153d068ebc2STakashi Iwai void (*unsol_event)(struct hdac_device *dev, unsigned int event); 154e3d280fcSTakashi Iwai }; 155e3d280fcSTakashi Iwai 156e3d280fcSTakashi Iwai #define drv_to_hdac_driver(_drv) container_of(_drv, struct hdac_driver, driver) 157e3d280fcSTakashi Iwai 158d068ebc2STakashi Iwai /* 159d068ebc2STakashi Iwai * HD-audio bus base driver 160d068ebc2STakashi Iwai */ 161d068ebc2STakashi Iwai struct hdac_bus_ops { 162d068ebc2STakashi Iwai /* send a single command */ 163d068ebc2STakashi Iwai int (*command)(struct hdac_bus *bus, unsigned int cmd); 164d068ebc2STakashi Iwai /* get a response from the last command */ 165d068ebc2STakashi Iwai int (*get_response)(struct hdac_bus *bus, unsigned int addr, 166d068ebc2STakashi Iwai unsigned int *res); 167d068ebc2STakashi Iwai }; 168d068ebc2STakashi Iwai 169d068ebc2STakashi Iwai #define HDA_UNSOL_QUEUE_SIZE 64 170d068ebc2STakashi Iwai 171d068ebc2STakashi Iwai struct hdac_bus { 172d068ebc2STakashi Iwai struct device *dev; 173d068ebc2STakashi Iwai const struct hdac_bus_ops *ops; 174d068ebc2STakashi Iwai 175d068ebc2STakashi Iwai /* codec linked list */ 176d068ebc2STakashi Iwai struct list_head codec_list; 177d068ebc2STakashi Iwai unsigned int num_codecs; 178d068ebc2STakashi Iwai 179d068ebc2STakashi Iwai /* link caddr -> codec */ 180d068ebc2STakashi Iwai struct hdac_device *caddr_tbl[HDA_MAX_CODEC_ADDRESS + 1]; 181d068ebc2STakashi Iwai 182d068ebc2STakashi Iwai /* unsolicited event queue */ 183d068ebc2STakashi Iwai u32 unsol_queue[HDA_UNSOL_QUEUE_SIZE * 2]; /* ring buffer */ 184d068ebc2STakashi Iwai unsigned int unsol_rp, unsol_wp; 185d068ebc2STakashi Iwai struct work_struct unsol_work; 186d068ebc2STakashi Iwai 187d068ebc2STakashi Iwai /* bit flags of powered codecs */ 188d068ebc2STakashi Iwai unsigned long codec_powered; 189d068ebc2STakashi Iwai 190d068ebc2STakashi Iwai /* flags */ 191d068ebc2STakashi Iwai bool sync_write:1; /* sync after verb write */ 192d068ebc2STakashi Iwai 193d068ebc2STakashi Iwai /* locks */ 194d068ebc2STakashi Iwai struct mutex cmd_mutex; 195d068ebc2STakashi Iwai }; 196d068ebc2STakashi Iwai 197d068ebc2STakashi Iwai int snd_hdac_bus_init(struct hdac_bus *bus, struct device *dev, 198d068ebc2STakashi Iwai const struct hdac_bus_ops *ops); 199d068ebc2STakashi Iwai void snd_hdac_bus_exit(struct hdac_bus *bus); 200d068ebc2STakashi Iwai int snd_hdac_bus_exec_verb(struct hdac_bus *bus, unsigned int addr, 201d068ebc2STakashi Iwai unsigned int cmd, unsigned int *res); 202d068ebc2STakashi Iwai int snd_hdac_bus_exec_verb_unlocked(struct hdac_bus *bus, unsigned int addr, 203d068ebc2STakashi Iwai unsigned int cmd, unsigned int *res); 204d068ebc2STakashi Iwai void snd_hdac_bus_queue_event(struct hdac_bus *bus, u32 res, u32 res_ex); 205d068ebc2STakashi Iwai 206d068ebc2STakashi Iwai int snd_hdac_bus_add_device(struct hdac_bus *bus, struct hdac_device *codec); 207d068ebc2STakashi Iwai void snd_hdac_bus_remove_device(struct hdac_bus *bus, 208d068ebc2STakashi Iwai struct hdac_device *codec); 209d068ebc2STakashi Iwai 2107639a06cSTakashi Iwai static inline void snd_hdac_codec_link_up(struct hdac_device *codec) 2117639a06cSTakashi Iwai { 2127639a06cSTakashi Iwai set_bit(codec->addr, &codec->bus->codec_powered); 2137639a06cSTakashi Iwai } 2147639a06cSTakashi Iwai 2157639a06cSTakashi Iwai static inline void snd_hdac_codec_link_down(struct hdac_device *codec) 2167639a06cSTakashi Iwai { 2177639a06cSTakashi Iwai clear_bit(codec->addr, &codec->bus->codec_powered); 2187639a06cSTakashi Iwai } 2197639a06cSTakashi Iwai 22071fc4c7eSTakashi Iwai /* 22171fc4c7eSTakashi Iwai * generic array helpers 22271fc4c7eSTakashi Iwai */ 22371fc4c7eSTakashi Iwai void *snd_array_new(struct snd_array *array); 22471fc4c7eSTakashi Iwai void snd_array_free(struct snd_array *array); 22571fc4c7eSTakashi Iwai static inline void snd_array_init(struct snd_array *array, unsigned int size, 22671fc4c7eSTakashi Iwai unsigned int align) 22771fc4c7eSTakashi Iwai { 22871fc4c7eSTakashi Iwai array->elem_size = size; 22971fc4c7eSTakashi Iwai array->alloc_align = align; 23071fc4c7eSTakashi Iwai } 23171fc4c7eSTakashi Iwai 23271fc4c7eSTakashi Iwai static inline void *snd_array_elem(struct snd_array *array, unsigned int idx) 23371fc4c7eSTakashi Iwai { 23471fc4c7eSTakashi Iwai return array->list + idx * array->elem_size; 23571fc4c7eSTakashi Iwai } 23671fc4c7eSTakashi Iwai 23771fc4c7eSTakashi Iwai static inline unsigned int snd_array_index(struct snd_array *array, void *ptr) 23871fc4c7eSTakashi Iwai { 23971fc4c7eSTakashi Iwai return (unsigned long)(ptr - array->list) / array->elem_size; 24071fc4c7eSTakashi Iwai } 24171fc4c7eSTakashi Iwai 242e3d280fcSTakashi Iwai #endif /* __SOUND_HDAUDIO_H */ 243