18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * soundbus generic definitions 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright 2006 Johannes Berg <johannes@sipsolutions.net> 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci#ifndef __SOUNDBUS_H 88c2ecf20Sopenharmony_ci#define __SOUNDBUS_H 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#include <linux/of_device.h> 118c2ecf20Sopenharmony_ci#include <sound/pcm.h> 128c2ecf20Sopenharmony_ci#include <linux/list.h> 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ci/* When switching from master to slave or the other way around, 168c2ecf20Sopenharmony_ci * you don't want to have the codec chip acting as clock source 178c2ecf20Sopenharmony_ci * while the bus still is. 188c2ecf20Sopenharmony_ci * More importantly, while switch from slave to master, you need 198c2ecf20Sopenharmony_ci * to turn off the chip's master function first, but then there's 208c2ecf20Sopenharmony_ci * no clock for a while and other chips might reset, so we notify 218c2ecf20Sopenharmony_ci * their drivers after having switched. 228c2ecf20Sopenharmony_ci * The constants here are codec-point of view, so when we switch 238c2ecf20Sopenharmony_ci * the soundbus to master we tell the codec we're going to switch 248c2ecf20Sopenharmony_ci * and give it CLOCK_SWITCH_PREPARE_SLAVE! 258c2ecf20Sopenharmony_ci */ 268c2ecf20Sopenharmony_cienum clock_switch { 278c2ecf20Sopenharmony_ci CLOCK_SWITCH_PREPARE_SLAVE, 288c2ecf20Sopenharmony_ci CLOCK_SWITCH_PREPARE_MASTER, 298c2ecf20Sopenharmony_ci CLOCK_SWITCH_SLAVE, 308c2ecf20Sopenharmony_ci CLOCK_SWITCH_MASTER, 318c2ecf20Sopenharmony_ci CLOCK_SWITCH_NOTIFY, 328c2ecf20Sopenharmony_ci}; 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci/* information on a transfer the codec can take */ 358c2ecf20Sopenharmony_cistruct transfer_info { 368c2ecf20Sopenharmony_ci u64 formats; /* SNDRV_PCM_FMTBIT_* */ 378c2ecf20Sopenharmony_ci unsigned int rates; /* SNDRV_PCM_RATE_* */ 388c2ecf20Sopenharmony_ci /* flags */ 398c2ecf20Sopenharmony_ci u32 transfer_in:1, /* input = 1, output = 0 */ 408c2ecf20Sopenharmony_ci must_be_clock_source:1; 418c2ecf20Sopenharmony_ci /* for codecs to distinguish among their TIs */ 428c2ecf20Sopenharmony_ci int tag; 438c2ecf20Sopenharmony_ci}; 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_cistruct codec_info_item { 468c2ecf20Sopenharmony_ci struct codec_info *codec; 478c2ecf20Sopenharmony_ci void *codec_data; 488c2ecf20Sopenharmony_ci struct soundbus_dev *sdev; 498c2ecf20Sopenharmony_ci /* internal, to be used by the soundbus provider */ 508c2ecf20Sopenharmony_ci struct list_head list; 518c2ecf20Sopenharmony_ci}; 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_ci/* for prepare, where the codecs need to know 548c2ecf20Sopenharmony_ci * what we're going to drive the bus with */ 558c2ecf20Sopenharmony_cistruct bus_info { 568c2ecf20Sopenharmony_ci /* see below */ 578c2ecf20Sopenharmony_ci int sysclock_factor; 588c2ecf20Sopenharmony_ci int bus_factor; 598c2ecf20Sopenharmony_ci}; 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_ci/* information on the codec itself, plus function pointers */ 628c2ecf20Sopenharmony_cistruct codec_info { 638c2ecf20Sopenharmony_ci /* the module this lives in */ 648c2ecf20Sopenharmony_ci struct module *owner; 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci /* supported transfer possibilities, array terminated by 678c2ecf20Sopenharmony_ci * formats or rates being 0. */ 688c2ecf20Sopenharmony_ci struct transfer_info *transfers; 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ci /* Master clock speed factor 718c2ecf20Sopenharmony_ci * to be used (master clock speed = sysclock_factor * sampling freq) 728c2ecf20Sopenharmony_ci * Unused if the soundbus provider has no such notion. 738c2ecf20Sopenharmony_ci */ 748c2ecf20Sopenharmony_ci int sysclock_factor; 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ci /* Bus factor, bus clock speed = bus_factor * sampling freq) 778c2ecf20Sopenharmony_ci * Unused if the soundbus provider has no such notion. 788c2ecf20Sopenharmony_ci */ 798c2ecf20Sopenharmony_ci int bus_factor; 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci /* operations */ 828c2ecf20Sopenharmony_ci /* clock switching, see above */ 838c2ecf20Sopenharmony_ci int (*switch_clock)(struct codec_info_item *cii, 848c2ecf20Sopenharmony_ci enum clock_switch clock); 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_ci /* called for each transfer_info when the user 878c2ecf20Sopenharmony_ci * opens the pcm device to determine what the 888c2ecf20Sopenharmony_ci * hardware can support at this point in time. 898c2ecf20Sopenharmony_ci * That can depend on other user-switchable controls. 908c2ecf20Sopenharmony_ci * Return 1 if usable, 0 if not. 918c2ecf20Sopenharmony_ci * out points to another instance of a transfer_info 928c2ecf20Sopenharmony_ci * which is initialised to the values in *ti, and 938c2ecf20Sopenharmony_ci * it's format and rate values can be modified by 948c2ecf20Sopenharmony_ci * the callback if it is necessary to further restrict 958c2ecf20Sopenharmony_ci * the formats that can be used at the moment, for 968c2ecf20Sopenharmony_ci * example when one codec has multiple logical codec 978c2ecf20Sopenharmony_ci * info structs for multiple inputs. 988c2ecf20Sopenharmony_ci */ 998c2ecf20Sopenharmony_ci int (*usable)(struct codec_info_item *cii, 1008c2ecf20Sopenharmony_ci struct transfer_info *ti, 1018c2ecf20Sopenharmony_ci struct transfer_info *out); 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_ci /* called when pcm stream is opened, probably not implemented 1048c2ecf20Sopenharmony_ci * most of the time since it isn't too useful */ 1058c2ecf20Sopenharmony_ci int (*open)(struct codec_info_item *cii, 1068c2ecf20Sopenharmony_ci struct snd_pcm_substream *substream); 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_ci /* called when the pcm stream is closed, at this point 1098c2ecf20Sopenharmony_ci * the user choices can all be unlocked (see below) */ 1108c2ecf20Sopenharmony_ci int (*close)(struct codec_info_item *cii, 1118c2ecf20Sopenharmony_ci struct snd_pcm_substream *substream); 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_ci /* if the codec must forbid some user choices because 1148c2ecf20Sopenharmony_ci * they are not valid with the substream/transfer info, 1158c2ecf20Sopenharmony_ci * it must do so here. Example: no digital output for 1168c2ecf20Sopenharmony_ci * incompatible framerate, say 8KHz, on Onyx. 1178c2ecf20Sopenharmony_ci * If the selected stuff in the substream is NOT 1188c2ecf20Sopenharmony_ci * compatible, you have to reject this call! */ 1198c2ecf20Sopenharmony_ci int (*prepare)(struct codec_info_item *cii, 1208c2ecf20Sopenharmony_ci struct bus_info *bi, 1218c2ecf20Sopenharmony_ci struct snd_pcm_substream *substream); 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_ci /* start() is called before data is pushed to the codec. 1248c2ecf20Sopenharmony_ci * Note that start() must be atomic! */ 1258c2ecf20Sopenharmony_ci int (*start)(struct codec_info_item *cii, 1268c2ecf20Sopenharmony_ci struct snd_pcm_substream *substream); 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_ci /* stop() is called after data is no longer pushed to the codec. 1298c2ecf20Sopenharmony_ci * Note that stop() must be atomic! */ 1308c2ecf20Sopenharmony_ci int (*stop)(struct codec_info_item *cii, 1318c2ecf20Sopenharmony_ci struct snd_pcm_substream *substream); 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_ci int (*suspend)(struct codec_info_item *cii, pm_message_t state); 1348c2ecf20Sopenharmony_ci int (*resume)(struct codec_info_item *cii); 1358c2ecf20Sopenharmony_ci}; 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_ci/* information on a soundbus device */ 1388c2ecf20Sopenharmony_cistruct soundbus_dev { 1398c2ecf20Sopenharmony_ci /* the bus it belongs to */ 1408c2ecf20Sopenharmony_ci struct list_head onbuslist; 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_ci /* the of device it represents */ 1438c2ecf20Sopenharmony_ci struct platform_device ofdev; 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_ci /* what modules go by */ 1468c2ecf20Sopenharmony_ci char modalias[32]; 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_ci /* These fields must be before attach_codec can be called. 1498c2ecf20Sopenharmony_ci * They should be set by the owner of the alsa card object 1508c2ecf20Sopenharmony_ci * that is needed, and whoever sets them must make sure 1518c2ecf20Sopenharmony_ci * that they are unique within that alsa card object. */ 1528c2ecf20Sopenharmony_ci char *pcmname; 1538c2ecf20Sopenharmony_ci int pcmid; 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_ci /* this is assigned by the soundbus provider in attach_codec */ 1568c2ecf20Sopenharmony_ci struct snd_pcm *pcm; 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_ci /* operations */ 1598c2ecf20Sopenharmony_ci /* attach a codec to this soundbus, give the alsa 1608c2ecf20Sopenharmony_ci * card object the PCMs for this soundbus should be in. 1618c2ecf20Sopenharmony_ci * The 'data' pointer must be unique, it is used as the 1628c2ecf20Sopenharmony_ci * key for detach_codec(). */ 1638c2ecf20Sopenharmony_ci int (*attach_codec)(struct soundbus_dev *dev, struct snd_card *card, 1648c2ecf20Sopenharmony_ci struct codec_info *ci, void *data); 1658c2ecf20Sopenharmony_ci void (*detach_codec)(struct soundbus_dev *dev, void *data); 1668c2ecf20Sopenharmony_ci /* TODO: suspend/resume */ 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_ci /* private for the soundbus provider */ 1698c2ecf20Sopenharmony_ci struct list_head codec_list; 1708c2ecf20Sopenharmony_ci u32 have_out:1, have_in:1; 1718c2ecf20Sopenharmony_ci}; 1728c2ecf20Sopenharmony_ci#define to_soundbus_device(d) container_of(d, struct soundbus_dev, ofdev.dev) 1738c2ecf20Sopenharmony_ci#define of_to_soundbus_device(d) container_of(d, struct soundbus_dev, ofdev) 1748c2ecf20Sopenharmony_ci 1758c2ecf20Sopenharmony_ciextern int soundbus_add_one(struct soundbus_dev *dev); 1768c2ecf20Sopenharmony_ciextern void soundbus_remove_one(struct soundbus_dev *dev); 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_ciextern struct soundbus_dev *soundbus_dev_get(struct soundbus_dev *dev); 1798c2ecf20Sopenharmony_ciextern void soundbus_dev_put(struct soundbus_dev *dev); 1808c2ecf20Sopenharmony_ci 1818c2ecf20Sopenharmony_cistruct soundbus_driver { 1828c2ecf20Sopenharmony_ci char *name; 1838c2ecf20Sopenharmony_ci struct module *owner; 1848c2ecf20Sopenharmony_ci 1858c2ecf20Sopenharmony_ci /* we don't implement any matching at all */ 1868c2ecf20Sopenharmony_ci 1878c2ecf20Sopenharmony_ci int (*probe)(struct soundbus_dev* dev); 1888c2ecf20Sopenharmony_ci int (*remove)(struct soundbus_dev* dev); 1898c2ecf20Sopenharmony_ci 1908c2ecf20Sopenharmony_ci int (*shutdown)(struct soundbus_dev* dev); 1918c2ecf20Sopenharmony_ci 1928c2ecf20Sopenharmony_ci struct device_driver driver; 1938c2ecf20Sopenharmony_ci}; 1948c2ecf20Sopenharmony_ci#define to_soundbus_driver(drv) container_of(drv,struct soundbus_driver, driver) 1958c2ecf20Sopenharmony_ci 1968c2ecf20Sopenharmony_ciextern int soundbus_register_driver(struct soundbus_driver *drv); 1978c2ecf20Sopenharmony_ciextern void soundbus_unregister_driver(struct soundbus_driver *drv); 1988c2ecf20Sopenharmony_ci 1998c2ecf20Sopenharmony_ciextern struct attribute *soundbus_dev_attrs[]; 2008c2ecf20Sopenharmony_ci 2018c2ecf20Sopenharmony_ci#endif /* __SOUNDBUS_H */ 202