This case involves some changes to the AC'97 interfaces delivered as part of PSARC 2008/318. However, since these interfaces are Consolidation Private, backwards compatibility is supplied, and since the original interfaces were never fully specified in the materials for PSARC 2008/318 (due to an error on my part, oops!) despite having been delivered, I believe that it is reasonable for this case to qualify as self review.
This case contains the full details for both the already delivered interfaces, as well as the changes we are proposing. While there is not a specific business need for an self-review case, I'd like to get these changes into the next build. That said, if anyone believes this case warrants promotion to a fast track, please let me know. - Garrett Template Version: @(#)sac_nextcase 1.68 02/23/09 SMI This information is Copyright 2009 Sun Microsystems 1. Introduction 1.1. Project/Component Working Name: AC'97 DDI Update 1.2. Name of Document Author/Supplier: Author: Garrett D'Amore 1.3 Date of This Document: 27 August, 2009 4. Technical Description Problem: -------- The interfaces that were originally supplied as part of the Boomer case (PSARC 2008/318) for AC'97 have proven to be limiting for some devices, which use AC'97 codecs in "unconventional ways". Such devices may have more than one AC'97 codec, or may use AC'97 only for a particular purpose. (For example, Creative Audigy LS devices use AC'97 only to manage the capture data; I2S DACs are used for playback.) For these situations, we need an update to the AC'97 DDI so that devices have more control over which audio controls an AC'97 codec supports are exposed through the Boomer framework. We would also like devices to be able to access the underlying AC'97 controls so that they can use, or extend, them without necessarily exposing them directly to Boomer. Furthermore, due to an oversight, the AC'97 DDI details were never supplied as part of the original Boomer case, although it was listed as Consolidation Private in the interface table. Despite this, a number of existing drivers make use of the AC'97 DDI. Solution -------- We propose a new AC'97 DDI, which is free from the limitations of the first AC'97 DDI. The previous DDI will remain supported (as Obsolete Consolidation Private) until the drivers can be updated to the new one. New AC'97 DDI ------------- The new AC'97 DDI is as follows: typedef struct ac97 ac97_t; typedef void (*ac97_wr_t)(void *, uint8_t, uint16_t); typedef uint16_t (*ac97_rd_t)(void *, uint8_t); typedef struct ac97_ctrl ac97_ctrl_t; typedef boolean_t (*ac97_ctrl_walk_t)(ac97_ctrl_t *, void *); ac97_t *ac97_allocate(audio_dev_t *, dev_info_t *, ac97_rd_t, ac97_wr_t, void *); This function allocates a new AC'97 handle for the given audio device and devinfo node. The register access functions are supplied. The last void * argument is a pointer to the driver's private state, which will be passed to the register access routines. void ac97_probe_controls(ac97_t *); This function must be called during attach. It initializes the hardware and probes for the various AC'97 controls that might be present on the codec. It can only be called once, and must be called before the driver calls audio_dev_register(), and after ac97_allocate(). void ac97_register_controls(ac97_t *); This function can only be called once, after ac97_probe_controls() is called, and before audio_dev_register() is called. If used, it will register all of the codec controls with the audio framework. (A driver need not execute this if it wants more fine grained control over which controls are exposed to the framework.) void ac97_unregister_controls(ac97_t *); This function unregisters all controls from the audio framework. Its use is optional, as ac97_free() also performs this step. It should only be called during detach() processing. void ac97_walk_controls(ac97_t *, ac97_ctrl_walk_t, void *); This function walks a list of all controls known to the codec. The walk function is executed once for each control, until the end of the list of controls is reached, or the walk function returns B_FALSE. ac97_ctrl_t *ac97_control_find(ac97_t *, const char *); This function is used to find a named control (using the control's name such as AUDIO_CTRL_ID_VOLUME). void ac97_control_register(ac97_ctrl_t *); This function may be used to individually register a provided control with the audio framework. It should only be called once for a given control, and its use is mutually exclusive with ac97_register_controls(). void ac97_control_unregister(ac97_ctrl_t *); This function may be used to individually unregister a provided control from the audio framework. Few, if any, drivers are likely to need this. void ac97_control_remove(ac97_ctrl_t *); This function removes a control entirely. It will also unregister the control if it has already been registered. The best use of this function is to eliminate controls *before* calling ac97_register_controls(). It may *only* be called during attach or detach processing, when the driver is otherwise single threaded. (It will safely unregister the control from the audio framework though, so the driver need not be concerned about accesses originating from the audio framework itself.) This function is implicitly executed for each control by ac97_free(). const char *ac97_control_name(ac97_ctrl_t *); This function returns the name of a control, such as AUDIO_CTRL_ID_VOLUME. This wll be most useful in conjunction with ac97_walk_controls(). int ac97_control_get(ac97_ctrl_t *, uint64_t *); int ac97_control_set(ac97_ctrl_t *, uint64_t); These functions are used to retrieve or change the value associated with the control. void ac97_free(ac97_t *); This function is used to tear down and free all state associated with the AC'97 codec. The driver must be single threaded when it calls this function. void ac97_suspend(ac97_t *); This function is to be called during DDI_SUSPEND handling. After it returns, changes to control values will be deferred until the device is resumed. (Control changes will be made to shadowed state, which will be "replayed" when ac97_resume is called.) void ac97_resume(ac97_t *); This restores all codec settings and resumes normal operation as part of DDI_RESUME handling. void ac97_reset(ac97_t *); This is used to perform a master reset of the codec. int ac97_num_channels(ac97_t *); This returns the number of channels (2, 4, 6, or even 8) that the codec supports. This can be useful for drivers to avoid allocating resources for more channels than the codec can support. It can only be executed after ac97_probe_controls() has finished. Obsolete Interfaces ------------------- These interfaces are left in place for now, to avoid changing the the half dozen or so drivers that still use them. Eventually those drivers will be updated and these interfaces can be removed. They are now Obsolete Consolidation Private. ac97_t *ac97_alloc(dev_info_t *, ac97_rd_t, ac97_wr_t, void *); This function is almost identical to ac97_allocate(), except that the audio_dev is elided. It is supplied with the ac97_init() call instead. int ac97_init(ac97_t *, audio_dev_t *); This function sets up the audio_dev pointer, and performs the logical equivalent of ac97_probe_controls() followed immediately by ac97_register_controls(). Its use is incompatible with any direct access to the list of controls or to controls themselves by device drivers. Interface Tables ---------------- _____________________________________________________________________________ | Interfaces Exported | |_________________________|_______________________|__________________________| |Interface | Classification | Comments | |_________________________|_______________________|__________________________| |ac97_alloc | Obs. Consol. Private | Old DDI | |ac97_init | Obs. Consol. Private | " " | |ac97_allocate | Consolidation Private | New DDI | |ac97_probe_controls | " " | " " | |ac97_register_controls | " " | " " | |ac97_unregister_controls | " " | " " | |ac97_walk_controls | " " | " " | |ac97_control_register | " " | " " | |ac97_control_unregister | " " | " " | |ac97_control_find | " " | " " | |ac97_control_name | " " | " " | |ac97_control_set | " " | " " | |ac97_control_get | " " | " " | |ac97_control_remove | " " | " " | |ac97_free | " " | Unchanged DDI | |ac97_suspend | " " | " " | |ac97_resume | " " | " " | |ac97_num_channels | " " | " " | |ac97_t | " " | Codec handle (unchanged) | |ac97_rd_t, ac97_wr_t | " " | Reg access funcs (unchg) | |ac97_ctrl_t | " " | Control handle (new) | |ac97_walk_t | " " | Walk function (new) | |_________________________|_______________________|__________________________| ______________________________________________________________________________ | Interfaces Imported | |_________________________|_______________________|__________________________| |Interface | Classification | Comments | |_________________________|_______________________|__________________________| |audio_dev_t | Consolidation Private | PSARC 2008/318 | |audio_ctrl_t | " " | " " | |audio_ctrl_desc_t | " " | " " | |audio_dev_warn | " " | " " | |audio_dev_add_control | " " | " " | |audio_dev_del_control | " " | " " | |Control names | " " | " " | |_________________________|_______________________|__________________________| 6. Resources and Schedule 6.4. Steering Committee requested information 6.4.1. Consolidation C-team Name: ON 6.5. ARC review type: Automatic 6.6. ARC Exposure: open