forked from torvalds/linux
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
AC97 is a bus for sound usage. It enables for a AC97 AC-Link to link one controller to 0 to 4 AC97 codecs. The goal of this new implementation is to implement a device/driver model for AC97, with an automatic scan of the bus and automatic discovery of AC97 codec devices. Signed-off-by: Robert Jarzmik <[email protected]> Reviewed-by: Takashi Iwai <[email protected]> Signed-off-by: Mark Brown <[email protected]>
- Loading branch information
Showing
9 changed files
with
928 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
/* | ||
* Copyright (C) 2016 Robert Jarzmik <[email protected]> | ||
* | ||
* This program is free software; you can redistribute it and/or modify | ||
* it under the terms of the GNU General Public License version 2 as | ||
* published by the Free Software Foundation. | ||
*/ | ||
#ifndef __SOUND_AC97_CODEC2_H | ||
#define __SOUND_AC97_CODEC2_H | ||
|
||
#include <linux/device.h> | ||
|
||
#define AC97_ID(vendor_id1, vendor_id2) \ | ||
((((vendor_id1) & 0xffff) << 16) | ((vendor_id2) & 0xffff)) | ||
#define AC97_DRIVER_ID(vendor_id1, vendor_id2, mask_id1, mask_id2, _data) \ | ||
{ .id = (((vendor_id1) & 0xffff) << 16) | ((vendor_id2) & 0xffff), \ | ||
.mask = (((mask_id1) & 0xffff) << 16) | ((mask_id2) & 0xffff), \ | ||
.data = (_data) } | ||
|
||
struct ac97_controller; | ||
struct clk; | ||
|
||
/** | ||
* struct ac97_id - matches a codec device and driver on an ac97 bus | ||
* @id: The significant bits if the codec vendor ID1 and ID2 | ||
* @mask: Bitmask specifying which bits of the id field are significant when | ||
* matching. A driver binds to a device when : | ||
* ((vendorID1 << 8 | vendorID2) & (mask_id1 << 8 | mask_id2)) == id. | ||
* @data: Private data used by the driver. | ||
*/ | ||
struct ac97_id { | ||
unsigned int id; | ||
unsigned int mask; | ||
void *data; | ||
}; | ||
|
||
/** | ||
* ac97_codec_device - a ac97 codec | ||
* @dev: the core device | ||
* @vendor_id: the vendor_id of the codec, as sensed on the AC-link | ||
* @num: the codec number, 0 is primary, 1 is first slave, etc ... | ||
* @clk: the clock BIT_CLK provided by the codec | ||
* @ac97_ctrl: ac97 digital controller on the same AC-link | ||
* | ||
* This is the device instantiated for each codec living on a AC-link. There are | ||
* normally 0 to 4 codec devices per AC-link, and all of them are controlled by | ||
* an AC97 digital controller. | ||
*/ | ||
struct ac97_codec_device { | ||
struct device dev; | ||
unsigned int vendor_id; | ||
unsigned int num; | ||
struct clk *clk; | ||
struct ac97_controller *ac97_ctrl; | ||
}; | ||
|
||
/** | ||
* ac97_codec_driver - a ac97 codec driver | ||
* @driver: the device driver structure | ||
* @probe: the function called when a ac97_codec_device is matched | ||
* @remove: the function called when the device is unbound/removed | ||
* @shutdown: shutdown function (might be NULL) | ||
* @id_table: ac97 vendor_id match table, { } member terminated | ||
*/ | ||
struct ac97_codec_driver { | ||
struct device_driver driver; | ||
int (*probe)(struct ac97_codec_device *); | ||
int (*remove)(struct ac97_codec_device *); | ||
void (*shutdown)(struct ac97_codec_device *); | ||
const struct ac97_id *id_table; | ||
}; | ||
|
||
static inline struct ac97_codec_device *to_ac97_device(struct device *d) | ||
{ | ||
return container_of(d, struct ac97_codec_device, dev); | ||
} | ||
|
||
static inline struct ac97_codec_driver *to_ac97_driver(struct device_driver *d) | ||
{ | ||
return container_of(d, struct ac97_codec_driver, driver); | ||
} | ||
|
||
#if IS_ENABLED(CONFIG_AC97_BUS_NEW) | ||
int snd_ac97_codec_driver_register(struct ac97_codec_driver *drv); | ||
void snd_ac97_codec_driver_unregister(struct ac97_codec_driver *drv); | ||
#else | ||
static inline int | ||
snd_ac97_codec_driver_register(struct ac97_codec_driver *drv) | ||
{ | ||
return 0; | ||
} | ||
static inline void | ||
snd_ac97_codec_driver_unregister(struct ac97_codec_driver *drv) | ||
{ | ||
} | ||
#endif | ||
|
||
|
||
static inline struct device * | ||
ac97_codec_dev2dev(struct ac97_codec_device *adev) | ||
{ | ||
return &adev->dev; | ||
} | ||
|
||
static inline void *ac97_get_drvdata(struct ac97_codec_device *adev) | ||
{ | ||
return dev_get_drvdata(ac97_codec_dev2dev(adev)); | ||
} | ||
|
||
static inline void ac97_set_drvdata(struct ac97_codec_device *adev, | ||
void *data) | ||
{ | ||
dev_set_drvdata(ac97_codec_dev2dev(adev), data); | ||
} | ||
|
||
void *snd_ac97_codec_get_platdata(const struct ac97_codec_device *adev); | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
/* | ||
* Copyright (C) 2016 Robert Jarzmik <[email protected]> | ||
* | ||
* This program is free software; you can redistribute it and/or modify | ||
* it under the terms of the GNU General Public License version 2 as | ||
* published by the Free Software Foundation. | ||
* | ||
* This file is for backward compatibility with snd_ac97 structure and its | ||
* multiple usages, such as the snd_ac97_bus and snd_ac97_build_ops. | ||
* | ||
*/ | ||
#ifndef AC97_COMPAT_H | ||
#define AC97_COMPAT_H | ||
|
||
#include <sound/ac97_codec.h> | ||
|
||
struct snd_ac97 *snd_ac97_compat_alloc(struct ac97_codec_device *adev); | ||
void snd_ac97_compat_release(struct snd_ac97 *ac97); | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
/* | ||
* Copyright (C) 2016 Robert Jarzmik <[email protected]> | ||
* | ||
* This program is free software; you can redistribute it and/or modify | ||
* it under the terms of the GNU General Public License version 2 as | ||
* published by the Free Software Foundation. | ||
*/ | ||
#ifndef AC97_CONTROLLER_H | ||
#define AC97_CONTROLLER_H | ||
|
||
#include <linux/device.h> | ||
#include <linux/list.h> | ||
|
||
#define AC97_BUS_MAX_CODECS 4 | ||
#define AC97_SLOTS_AVAILABLE_ALL 0xf | ||
|
||
struct ac97_controller_ops; | ||
|
||
/** | ||
* struct ac97_controller - The AC97 controller of the AC-Link | ||
* @ops: the AC97 operations. | ||
* @controllers: linked list of all existing controllers. | ||
* @adap: the shell device ac97-%d, ie. ac97 adapter | ||
* @nr: the number of the shell device | ||
* @slots_available: the mask of accessible/scanable codecs. | ||
* @parent: the device providing the AC97 controller. | ||
* @codecs: the 4 possible AC97 codecs (NULL if none found). | ||
* @codecs_pdata: platform_data for each codec (NULL if no pdata). | ||
* | ||
* This structure is internal to AC97 bus, and should not be used by the | ||
* controllers themselves, excepting for using @dev. | ||
*/ | ||
struct ac97_controller { | ||
const struct ac97_controller_ops *ops; | ||
struct list_head controllers; | ||
struct device adap; | ||
int nr; | ||
unsigned short slots_available; | ||
struct device *parent; | ||
struct ac97_codec_device *codecs[AC97_BUS_MAX_CODECS]; | ||
void *codecs_pdata[AC97_BUS_MAX_CODECS]; | ||
}; | ||
|
||
/** | ||
* struct ac97_controller_ops - The AC97 operations | ||
* @reset: Cold reset of the AC97 AC-Link. | ||
* @warm_reset: Warm reset of the AC97 AC-Link. | ||
* @read: Read of a single AC97 register. | ||
* Returns the register value or a negative error code. | ||
* @write: Write of a single AC97 register. | ||
* | ||
* These are the basic operation an AC97 controller must provide for an AC97 | ||
* access functions. Amongst these, all but the last 2 are mandatory. | ||
* The slot number is also known as the AC97 codec number, between 0 and 3. | ||
*/ | ||
struct ac97_controller_ops { | ||
void (*reset)(struct ac97_controller *adrv); | ||
void (*warm_reset)(struct ac97_controller *adrv); | ||
int (*write)(struct ac97_controller *adrv, int slot, | ||
unsigned short reg, unsigned short val); | ||
int (*read)(struct ac97_controller *adrv, int slot, unsigned short reg); | ||
}; | ||
|
||
#if IS_ENABLED(CONFIG_AC97_BUS_NEW) | ||
struct ac97_controller *snd_ac97_controller_register( | ||
const struct ac97_controller_ops *ops, struct device *dev, | ||
unsigned short slots_available, void **codecs_pdata); | ||
void snd_ac97_controller_unregister(struct ac97_controller *ac97_ctrl); | ||
#else | ||
static inline struct ac97_controller * | ||
snd_ac97_controller_register(const struct ac97_controller_ops *ops, | ||
struct device *dev, | ||
unsigned short slots_available, | ||
void **codecs_pdata) | ||
{ | ||
return ERR_PTR(-ENODEV); | ||
} | ||
|
||
static inline void | ||
snd_ac97_controller_unregister(struct ac97_controller *ac97_ctrl) | ||
{ | ||
} | ||
#endif | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
# | ||
# AC97 configuration | ||
# | ||
|
||
|
||
config AC97_BUS_NEW | ||
tristate | ||
select AC97 | ||
help | ||
This is the new AC97 bus type, successor of AC97_BUS. The ported | ||
drivers which benefit from the AC97 automatic probing should "select" | ||
this instead of the AC97_BUS. | ||
Say Y here if you want to have AC97 devices, which are sound oriented | ||
devices around an AC-Link. | ||
|
||
config AC97_BUS_COMPAT | ||
bool | ||
depends on AC97_BUS_NEW | ||
depends on !AC97_BUS |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
# | ||
# make for AC97 bus drivers | ||
# | ||
|
||
obj-$(CONFIG_AC97_BUS_NEW) += ac97.o | ||
|
||
ac97-y += bus.o codec.o | ||
ac97-$(CONFIG_AC97_BUS_COMPAT) += snd_ac97_compat.o |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
/* | ||
* Copyright (C) 2016 Robert Jarzmik <[email protected]> | ||
* | ||
* This program is free software; you can redistribute it and/or modify | ||
* it under the terms of the GNU General Public License version 2 as | ||
* published by the Free Software Foundation. | ||
*/ | ||
|
||
unsigned int snd_ac97_bus_scan_one(struct ac97_controller *ac97, | ||
unsigned int codec_num); | ||
|
||
static inline bool ac97_ids_match(unsigned int id1, unsigned int id2, | ||
unsigned int mask) | ||
{ | ||
return (id1 & mask) == (id2 & mask); | ||
} |
Oops, something went wrong.