162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * soundbus generic definitions 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright 2006 Johannes Berg <johannes@sipsolutions.net> 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci#ifndef __SOUNDBUS_H 862306a36Sopenharmony_ci#define __SOUNDBUS_H 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#include <linux/of_device.h> 1162306a36Sopenharmony_ci#include <sound/pcm.h> 1262306a36Sopenharmony_ci#include <linux/list.h> 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci/* When switching from master to slave or the other way around, 1662306a36Sopenharmony_ci * you don't want to have the codec chip acting as clock source 1762306a36Sopenharmony_ci * while the bus still is. 1862306a36Sopenharmony_ci * More importantly, while switch from slave to master, you need 1962306a36Sopenharmony_ci * to turn off the chip's master function first, but then there's 2062306a36Sopenharmony_ci * no clock for a while and other chips might reset, so we notify 2162306a36Sopenharmony_ci * their drivers after having switched. 2262306a36Sopenharmony_ci * The constants here are codec-point of view, so when we switch 2362306a36Sopenharmony_ci * the soundbus to master we tell the codec we're going to switch 2462306a36Sopenharmony_ci * and give it CLOCK_SWITCH_PREPARE_SLAVE! 2562306a36Sopenharmony_ci */ 2662306a36Sopenharmony_cienum clock_switch { 2762306a36Sopenharmony_ci CLOCK_SWITCH_PREPARE_SLAVE, 2862306a36Sopenharmony_ci CLOCK_SWITCH_PREPARE_MASTER, 2962306a36Sopenharmony_ci CLOCK_SWITCH_SLAVE, 3062306a36Sopenharmony_ci CLOCK_SWITCH_MASTER, 3162306a36Sopenharmony_ci CLOCK_SWITCH_NOTIFY, 3262306a36Sopenharmony_ci}; 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci/* information on a transfer the codec can take */ 3562306a36Sopenharmony_cistruct transfer_info { 3662306a36Sopenharmony_ci u64 formats; /* SNDRV_PCM_FMTBIT_* */ 3762306a36Sopenharmony_ci unsigned int rates; /* SNDRV_PCM_RATE_* */ 3862306a36Sopenharmony_ci /* flags */ 3962306a36Sopenharmony_ci u32 transfer_in:1, /* input = 1, output = 0 */ 4062306a36Sopenharmony_ci must_be_clock_source:1; 4162306a36Sopenharmony_ci /* for codecs to distinguish among their TIs */ 4262306a36Sopenharmony_ci int tag; 4362306a36Sopenharmony_ci}; 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_cistruct codec_info_item { 4662306a36Sopenharmony_ci struct codec_info *codec; 4762306a36Sopenharmony_ci void *codec_data; 4862306a36Sopenharmony_ci struct soundbus_dev *sdev; 4962306a36Sopenharmony_ci /* internal, to be used by the soundbus provider */ 5062306a36Sopenharmony_ci struct list_head list; 5162306a36Sopenharmony_ci}; 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ci/* for prepare, where the codecs need to know 5462306a36Sopenharmony_ci * what we're going to drive the bus with */ 5562306a36Sopenharmony_cistruct bus_info { 5662306a36Sopenharmony_ci /* see below */ 5762306a36Sopenharmony_ci int sysclock_factor; 5862306a36Sopenharmony_ci int bus_factor; 5962306a36Sopenharmony_ci}; 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci/* information on the codec itself, plus function pointers */ 6262306a36Sopenharmony_cistruct codec_info { 6362306a36Sopenharmony_ci /* the module this lives in */ 6462306a36Sopenharmony_ci struct module *owner; 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci /* supported transfer possibilities, array terminated by 6762306a36Sopenharmony_ci * formats or rates being 0. */ 6862306a36Sopenharmony_ci struct transfer_info *transfers; 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ci /* Master clock speed factor 7162306a36Sopenharmony_ci * to be used (master clock speed = sysclock_factor * sampling freq) 7262306a36Sopenharmony_ci * Unused if the soundbus provider has no such notion. 7362306a36Sopenharmony_ci */ 7462306a36Sopenharmony_ci int sysclock_factor; 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci /* Bus factor, bus clock speed = bus_factor * sampling freq) 7762306a36Sopenharmony_ci * Unused if the soundbus provider has no such notion. 7862306a36Sopenharmony_ci */ 7962306a36Sopenharmony_ci int bus_factor; 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci /* operations */ 8262306a36Sopenharmony_ci /* clock switching, see above */ 8362306a36Sopenharmony_ci int (*switch_clock)(struct codec_info_item *cii, 8462306a36Sopenharmony_ci enum clock_switch clock); 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci /* called for each transfer_info when the user 8762306a36Sopenharmony_ci * opens the pcm device to determine what the 8862306a36Sopenharmony_ci * hardware can support at this point in time. 8962306a36Sopenharmony_ci * That can depend on other user-switchable controls. 9062306a36Sopenharmony_ci * Return 1 if usable, 0 if not. 9162306a36Sopenharmony_ci * out points to another instance of a transfer_info 9262306a36Sopenharmony_ci * which is initialised to the values in *ti, and 9362306a36Sopenharmony_ci * it's format and rate values can be modified by 9462306a36Sopenharmony_ci * the callback if it is necessary to further restrict 9562306a36Sopenharmony_ci * the formats that can be used at the moment, for 9662306a36Sopenharmony_ci * example when one codec has multiple logical codec 9762306a36Sopenharmony_ci * info structs for multiple inputs. 9862306a36Sopenharmony_ci */ 9962306a36Sopenharmony_ci int (*usable)(struct codec_info_item *cii, 10062306a36Sopenharmony_ci struct transfer_info *ti, 10162306a36Sopenharmony_ci struct transfer_info *out); 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ci /* called when pcm stream is opened, probably not implemented 10462306a36Sopenharmony_ci * most of the time since it isn't too useful */ 10562306a36Sopenharmony_ci int (*open)(struct codec_info_item *cii, 10662306a36Sopenharmony_ci struct snd_pcm_substream *substream); 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_ci /* called when the pcm stream is closed, at this point 10962306a36Sopenharmony_ci * the user choices can all be unlocked (see below) */ 11062306a36Sopenharmony_ci int (*close)(struct codec_info_item *cii, 11162306a36Sopenharmony_ci struct snd_pcm_substream *substream); 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci /* if the codec must forbid some user choices because 11462306a36Sopenharmony_ci * they are not valid with the substream/transfer info, 11562306a36Sopenharmony_ci * it must do so here. Example: no digital output for 11662306a36Sopenharmony_ci * incompatible framerate, say 8KHz, on Onyx. 11762306a36Sopenharmony_ci * If the selected stuff in the substream is NOT 11862306a36Sopenharmony_ci * compatible, you have to reject this call! */ 11962306a36Sopenharmony_ci int (*prepare)(struct codec_info_item *cii, 12062306a36Sopenharmony_ci struct bus_info *bi, 12162306a36Sopenharmony_ci struct snd_pcm_substream *substream); 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_ci /* start() is called before data is pushed to the codec. 12462306a36Sopenharmony_ci * Note that start() must be atomic! */ 12562306a36Sopenharmony_ci int (*start)(struct codec_info_item *cii, 12662306a36Sopenharmony_ci struct snd_pcm_substream *substream); 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ci /* stop() is called after data is no longer pushed to the codec. 12962306a36Sopenharmony_ci * Note that stop() must be atomic! */ 13062306a36Sopenharmony_ci int (*stop)(struct codec_info_item *cii, 13162306a36Sopenharmony_ci struct snd_pcm_substream *substream); 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ci int (*suspend)(struct codec_info_item *cii, pm_message_t state); 13462306a36Sopenharmony_ci int (*resume)(struct codec_info_item *cii); 13562306a36Sopenharmony_ci}; 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci/* information on a soundbus device */ 13862306a36Sopenharmony_cistruct soundbus_dev { 13962306a36Sopenharmony_ci /* the bus it belongs to */ 14062306a36Sopenharmony_ci struct list_head onbuslist; 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_ci /* the of device it represents */ 14362306a36Sopenharmony_ci struct platform_device ofdev; 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_ci /* what modules go by */ 14662306a36Sopenharmony_ci char modalias[32]; 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_ci /* These fields must be before attach_codec can be called. 14962306a36Sopenharmony_ci * They should be set by the owner of the alsa card object 15062306a36Sopenharmony_ci * that is needed, and whoever sets them must make sure 15162306a36Sopenharmony_ci * that they are unique within that alsa card object. */ 15262306a36Sopenharmony_ci char *pcmname; 15362306a36Sopenharmony_ci int pcmid; 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_ci /* this is assigned by the soundbus provider in attach_codec */ 15662306a36Sopenharmony_ci struct snd_pcm *pcm; 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ci /* operations */ 15962306a36Sopenharmony_ci /* attach a codec to this soundbus, give the alsa 16062306a36Sopenharmony_ci * card object the PCMs for this soundbus should be in. 16162306a36Sopenharmony_ci * The 'data' pointer must be unique, it is used as the 16262306a36Sopenharmony_ci * key for detach_codec(). */ 16362306a36Sopenharmony_ci int (*attach_codec)(struct soundbus_dev *dev, struct snd_card *card, 16462306a36Sopenharmony_ci struct codec_info *ci, void *data); 16562306a36Sopenharmony_ci void (*detach_codec)(struct soundbus_dev *dev, void *data); 16662306a36Sopenharmony_ci /* TODO: suspend/resume */ 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_ci /* private for the soundbus provider */ 16962306a36Sopenharmony_ci struct list_head codec_list; 17062306a36Sopenharmony_ci u32 have_out:1, have_in:1; 17162306a36Sopenharmony_ci}; 17262306a36Sopenharmony_ci#define to_soundbus_device(d) container_of(d, struct soundbus_dev, ofdev.dev) 17362306a36Sopenharmony_ci#define of_to_soundbus_device(d) container_of(d, struct soundbus_dev, ofdev) 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_ciextern int soundbus_add_one(struct soundbus_dev *dev); 17662306a36Sopenharmony_ciextern void soundbus_remove_one(struct soundbus_dev *dev); 17762306a36Sopenharmony_ci 17862306a36Sopenharmony_ciextern struct soundbus_dev *soundbus_dev_get(struct soundbus_dev *dev); 17962306a36Sopenharmony_ciextern void soundbus_dev_put(struct soundbus_dev *dev); 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_cistruct soundbus_driver { 18262306a36Sopenharmony_ci char *name; 18362306a36Sopenharmony_ci struct module *owner; 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_ci /* we don't implement any matching at all */ 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_ci int (*probe)(struct soundbus_dev* dev); 18862306a36Sopenharmony_ci void (*remove)(struct soundbus_dev *dev); 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_ci int (*shutdown)(struct soundbus_dev* dev); 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_ci struct device_driver driver; 19362306a36Sopenharmony_ci}; 19462306a36Sopenharmony_ci#define to_soundbus_driver(drv) container_of(drv,struct soundbus_driver, driver) 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_ciextern int soundbus_register_driver(struct soundbus_driver *drv); 19762306a36Sopenharmony_ciextern void soundbus_unregister_driver(struct soundbus_driver *drv); 19862306a36Sopenharmony_ci 19962306a36Sopenharmony_ciextern struct attribute *soundbus_dev_attrs[]; 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_ci#endif /* __SOUNDBUS_H */ 202