[v3,1/2] ASoC: core: Add API to use DMI name in sound card long name
diff mbox

Message ID 2c6136c012b7f94dd2fb35fd5def8195abdc0113.1484030246.git.mengdong.lin@linux.intel.com
State New
Headers show

Commit Message

mengdong.lin@linux.intel.com Jan. 10, 2017, 6:42 a.m. UTC
From: Liam Girdwood <liam.r.girdwood@linux.intel.com>

Intel DSP platform drivers are used by many different devices but are
difficult for userspace to differentiate. This patch adds an API to allow
the DMI name to be used in the sound card long name, thereby helping
userspace load the correct UCM configuration. Usually machine drivers
uses their own name as the sound card name (short name), and leave the
long name and driver name blank. This API will use the DMI info like
vendor, product and board to make up the card long name. If the machine
driver has already explicitly set the long name, this API will do nothing.

This patch also allows for further differentiation as many devices that
share the same DMI name i.e. Minnowboards, UP boards may be configured
with different codecs or firmwares. The API supports flavoring the DMI
name into the card longname to provide the extra differentiation required
for these devices.

For Use Case Manager (UCM) in the user space, changing card long name by
this API is backward compatible, since the card name does not change. For
a given sound card, even if there is no device-specific UCM configuration
file that uses the card long name, UCM will fall back to load the default
configuration file that uses the card name.

Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
Signed-off-by: Mengdong Lin <mengdong.lin@linux.intel.com>

Comments

Takashi Iwai Jan. 10, 2017, 7:09 a.m. UTC | #1
On Tue, 10 Jan 2017 07:42:49 +0100,
mengdong.lin@linux.intel.com wrote:
> 
> +/**
> + * snd_soc_set_dmi_name() - Register DMI names to card
> + * @card: The card to register DMI names
> + * @flavour: The flavour "differentiator" for the card amongst its peers.
> + *
> + * An Intel machine driver may be used by many different devices but are
> + * difficult for userspace to differentiate, since machine drivers ususally
> + * use their own name as the card name (short name) and leave the card long
> + * name blank. To differentiate such devices and fix bugs due to lack of
> + * device-specific configurations, this function allows DMI info to be used
> + * as the sound card long name, in the format of
> + * "vendor.product.version.board"
> + * (Character '.' are used to separate different DMI fields here).
> + * This will help the userspace to load the correct UCM (Use Case Manager)
> + * configuration.
> + *
> + * Possible card long names may be:
> + * DellInc..XPS139343.01.0310JH
> + * ASUSTeKCOMPUTERINC..T100TA.1.0.T100TA
> + * Circuitco.MinnowboardMaxD0PLATFORM.D0.MinnowBoardMAX
> + * (Please note DMI can also include '.' like"Inc." so you may see double '.
'
> + * sometimes)

Looking at the examples above, I wonder whether the dot is the best
choice as the separator.  Might other letters (e.g. ":" or "=") would
be clearer?  The colon might be bad if it were combined with the
alsa-lib plugin syntax, but I guess it won't happen?


thanks,

Takashi
mengdong.lin@linux.intel.com Jan. 11, 2017, 6:32 a.m. UTC | #2
On 01/10/2017 03:09 PM, Takashi Iwai wrote:
> On Tue, 10 Jan 2017 07:42:49 +0100,
> mengdong.lin@linux.intel.com wrote:
>>
>> +/**
>> + * snd_soc_set_dmi_name() - Register DMI names to card
>> + * @card: The card to register DMI names
>> + * @flavour: The flavour "differentiator" for the card amongst its peers.
>> + *
>> + * An Intel machine driver may be used by many different devices but are
>> + * difficult for userspace to differentiate, since machine drivers ususally
>> + * use their own name as the card name (short name) and leave the card long
>> + * name blank. To differentiate such devices and fix bugs due to lack of
>> + * device-specific configurations, this function allows DMI info to be used
>> + * as the sound card long name, in the format of
>> + * "vendor.product.version.board"
>> + * (Character '.' are used to separate different DMI fields here).
>> + * This will help the userspace to load the correct UCM (Use Case Manager)
>> + * configuration.
>> + *
>> + * Possible card long names may be:
>> + * DellInc..XPS139343.01.0310JH
>> + * ASUSTeKCOMPUTERINC..T100TA.1.0.T100TA
>> + * Circuitco.MinnowboardMaxD0PLATFORM.D0.MinnowBoardMAX
>> + * (Please note DMI can also include '.' like"Inc." so you may see double '.
> '
>> + * sometimes)
>
> Looking at the examples above, I wonder whether the dot is the best
> choice as the separator.  Might other letters (e.g. ":" or "=") would
> be clearer?  The colon might be bad if it were combined with the
> alsa-lib plugin syntax, but I guess it won't happen?
>

Hi Takashi,

I found we cannot use ":" as separator. It's because we want to use the 
card long name as the name of the directory to store UCM configuration 
files for this card, and Autoconf cannot support ":" in the directory name.

Both "=" and "-" can work, which would you suggest to use?
I've not observed "-" or "=" in DMI fields till now, and I guess "=" is 
less likely to be used by vendors.

Thanks
Mengdong
Takashi Iwai Jan. 11, 2017, 8:03 a.m. UTC | #3
On Wed, 11 Jan 2017 07:32:11 +0100,
Mengdong Lin wrote:
> 
> 
> On 01/10/2017 03:09 PM, Takashi Iwai wrote:
> > On Tue, 10 Jan 2017 07:42:49 +0100,
> > mengdong.lin@linux.intel.com wrote:
> >>
> >> +/**
> >> + * snd_soc_set_dmi_name() - Register DMI names to card
> >> + * @card: The card to register DMI names
> >> + * @flavour: The flavour "differentiator" for the card amongst its peers.
> >> + *
> >> + * An Intel machine driver may be used by many different devices but are
> >> + * difficult for userspace to differentiate, since machine drivers ususally
> >> + * use their own name as the card name (short name) and leave the card long
> >> + * name blank. To differentiate such devices and fix bugs due to lack of
> >> + * device-specific configurations, this function allows DMI info to be used
> >> + * as the sound card long name, in the format of
> >> + * "vendor.product.version.board"
> >> + * (Character '.' are used to separate different DMI fields here).
> >> + * This will help the userspace to load the correct UCM (Use Case Manager)
> >> + * configuration.
> >> + *
> >> + * Possible card long names may be:
> >> + * DellInc..XPS139343.01.0310JH
> >> + * ASUSTeKCOMPUTERINC..T100TA.1.0.T100TA
> >> + * Circuitco.MinnowboardMaxD0PLATFORM.D0.MinnowBoardMAX
> >> + * (Please note DMI can also include '.' like"Inc." so you may see double '.
> > '
> >> + * sometimes)
> >
> > Looking at the examples above, I wonder whether the dot is the best
> > choice as the separator.  Might other letters (e.g. ":" or "=") would
> > be clearer?  The colon might be bad if it were combined with the
> > alsa-lib plugin syntax, but I guess it won't happen?
> >
> 
> Hi Takashi,
> 
> I found we cannot use ":" as separator. It's because we want to use
> the card long name as the name of the directory to store UCM
> configuration files for this card, and Autoconf cannot support ":" in
> the directory name.

OK, fair enough.

> Both "=" and "-" can work, which would you suggest to use?
> I've not observed "-" or "=" in DMI fields till now, and I guess "="
> is less likely to be used by vendors.

Yes, but OTOH, "=" would become tricky if you want to handle it in a
shell script.

One alternative is to use "." or "-" for a separator while converting
the existing such letters to a different one like "_".


thanks,

Takashi
mengdong.lin@linux.intel.com Jan. 11, 2017, 10:27 a.m. UTC | #4
On 01/11/2017 04:03 PM, Takashi Iwai wrote:
> On Wed, 11 Jan 2017 07:32:11 +0100,
> Mengdong Lin wrote:
>>
>>
>> On 01/10/2017 03:09 PM, Takashi Iwai wrote:
>>> On Tue, 10 Jan 2017 07:42:49 +0100,
>>> mengdong.lin@linux.intel.com wrote:
>>>>
>>>> +/**
>>>> + * snd_soc_set_dmi_name() - Register DMI names to card
>>>> + * @card: The card to register DMI names
>>>> + * @flavour: The flavour "differentiator" for the card amongst its peers.
>>>> + *
>>>> + * An Intel machine driver may be used by many different devices but are
>>>> + * difficult for userspace to differentiate, since machine drivers ususally
>>>> + * use their own name as the card name (short name) and leave the card long
>>>> + * name blank. To differentiate such devices and fix bugs due to lack of
>>>> + * device-specific configurations, this function allows DMI info to be used
>>>> + * as the sound card long name, in the format of
>>>> + * "vendor.product.version.board"
>>>> + * (Character '.' are used to separate different DMI fields here).
>>>> + * This will help the userspace to load the correct UCM (Use Case Manager)
>>>> + * configuration.
>>>> + *
>>>> + * Possible card long names may be:
>>>> + * DellInc..XPS139343.01.0310JH
>>>> + * ASUSTeKCOMPUTERINC..T100TA.1.0.T100TA
>>>> + * Circuitco.MinnowboardMaxD0PLATFORM.D0.MinnowBoardMAX
>>>> + * (Please note DMI can also include '.' like"Inc." so you may see double '.
>>> '
>>>> + * sometimes)
>>>
>>> Looking at the examples above, I wonder whether the dot is the best
>>> choice as the separator.  Might other letters (e.g. ":" or "=") would
>>> be clearer?  The colon might be bad if it were combined with the
>>> alsa-lib plugin syntax, but I guess it won't happen?
>>>
>>
>> Hi Takashi,
>>
>> I found we cannot use ":" as separator. It's because we want to use
>> the card long name as the name of the directory to store UCM
>> configuration files for this card, and Autoconf cannot support ":" in
>> the directory name.
>
> OK, fair enough.
>
>> Both "=" and "-" can work, which would you suggest to use?
>> I've not observed "-" or "=" in DMI fields till now, and I guess "="
>> is less likely to be used by vendors.
>
> Yes, but OTOH, "=" would become tricky if you want to handle it in a
> shell script.

Okay. So we won't use "=".

>
> One alternative is to use "." or "-" for a separator while converting
> the existing such letters to a different one like "_".
>

It looks nice. Thanks for the tips! I'll use "-" as the separator, and 
convert the the existing "-" in DMI strings to "_".

Thanks
Mengdong
Mark Brown Jan. 11, 2017, 3:01 p.m. UTC | #5
On Wed, Jan 11, 2017 at 06:27:03PM +0800, Mengdong Lin wrote:
> On 01/11/2017 04:03 PM, Takashi Iwai wrote:
> > Mengdong Lin wrote:
> > > On 01/10/2017 03:09 PM, Takashi Iwai wrote:
> > > > mengdong.lin@linux.intel.com wrote:

> > > > > + * Possible card long names may be:
> > > > > + * DellInc..XPS139343.01.0310JH
> > > > > + * ASUSTeKCOMPUTERINC..T100TA.1.0.T100TA
> > > > > + * Circuitco.MinnowboardMaxD0PLATFORM.D0.MinnowBoardMAX

> It looks nice. Thanks for the tips! I'll use "-" as the separator, and
> convert the the existing "-" in DMI strings to "_".

"nice" seems like a very strong term here :)  Not sure there's any
options that will look much better but still.
Takashi Iwai Jan. 11, 2017, 3:06 p.m. UTC | #6
On Wed, 11 Jan 2017 16:01:19 +0100,
Mark Brown wrote:
> 
> On Wed, Jan 11, 2017 at 06:27:03PM +0800, Mengdong Lin wrote:
> > On 01/11/2017 04:03 PM, Takashi Iwai wrote:
> > > Mengdong Lin wrote:
> > > > On 01/10/2017 03:09 PM, Takashi Iwai wrote:
> > > > > mengdong.lin@linux.intel.com wrote:
> 
> > > > > > + * Possible card long names may be:
> > > > > > + * DellInc..XPS139343.01.0310JH
> > > > > > + * ASUSTeKCOMPUTERINC..T100TA.1.0.T100TA
> > > > > > + * Circuitco.MinnowboardMaxD0PLATFORM.D0.MinnowBoardMAX
> 
> > It looks nice. Thanks for the tips! I'll use "-" as the separator, and
> > convert the the existing "-" in DMI strings to "_".
> 
> "nice" seems like a very strong term here :)  Not sure there's any
> options that will look much better but still.

Yeah, it's still not photogenic.  But the merit is rather that it
makes easier to parse.


Takashi

Patch
diff mbox

diff --git a/include/sound/soc.h b/include/sound/soc.h
index 795e6c4..e4f1844 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -497,6 +497,8 @@  void snd_soc_runtime_deactivate(struct snd_soc_pcm_runtime *rtd, int stream);
 int snd_soc_runtime_set_dai_fmt(struct snd_soc_pcm_runtime *rtd,
 	unsigned int dai_fmt);
 
+int snd_soc_set_dmi_name(struct snd_soc_card *card, const char *flavour);
+
 /* Utility functions to get clock rates from various things */
 int snd_soc_calc_frame_size(int sample_size, int channels, int tdm_slots);
 int snd_soc_params_to_frame_size(struct snd_pcm_hw_params *params);
@@ -1094,6 +1096,8 @@  struct snd_soc_card {
 	const char *name;
 	const char *long_name;
 	const char *driver_name;
+	char dmi_longname[80];
+
 	struct device *dev;
 	struct snd_card *snd_card;
 	struct module *owner;
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index aaab26a..c744266 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -34,6 +34,7 @@ 
 #include <linux/ctype.h>
 #include <linux/slab.h>
 #include <linux/of.h>
+#include <linux/dmi.h>
 #include <sound/core.h>
 #include <sound/jack.h>
 #include <sound/pcm.h>
@@ -1886,6 +1887,127 @@  int snd_soc_runtime_set_dai_fmt(struct snd_soc_pcm_runtime *rtd,
 }
 EXPORT_SYMBOL_GPL(snd_soc_runtime_set_dai_fmt);
 
+
+/* Only keep number and alphabet characters and a few separator characters.
+ * DMI info often has SPACE and we must trim them, since Use Case Manager in
+ * the user space expects the device-specific configuration files/directories
+ * use the same name as the card long name but Autoconf cannot support SPACE
+ * in file or directory name.
+ */
+static void trim_special_characters(char *name)
+{
+	int i, j = 0;
+
+	for (i = 0; name[i]; i++) {
+		if (isalnum(name[i]) || (name[i] == '.')
+		    || (name[i] == '-') || (name[i] == '_'))
+			name[j++] = name[i];
+	}
+
+	name[j] = '\0';
+}
+
+/**
+ * snd_soc_set_dmi_name() - Register DMI names to card
+ * @card: The card to register DMI names
+ * @flavour: The flavour "differentiator" for the card amongst its peers.
+ *
+ * An Intel machine driver may be used by many different devices but are
+ * difficult for userspace to differentiate, since machine drivers ususally
+ * use their own name as the card name (short name) and leave the card long
+ * name blank. To differentiate such devices and fix bugs due to lack of
+ * device-specific configurations, this function allows DMI info to be used
+ * as the sound card long name, in the format of
+ * "vendor.product.version.board"
+ * (Character '.' are used to separate different DMI fields here).
+ * This will help the userspace to load the correct UCM (Use Case Manager)
+ * configuration.
+ *
+ * Possible card long names may be:
+ * DellInc..XPS139343.01.0310JH
+ * ASUSTeKCOMPUTERINC..T100TA.1.0.T100TA
+ * Circuitco.MinnowboardMaxD0PLATFORM.D0.MinnowBoardMAX
+ * (Please note DMI can also include '.' like"Inc." so you may see double '.'
+ * sometimes)
+ *
+ * This function also supports flavoring the card longname to provide
+ * the extra differentiation, like "vendor.product.version.board.flavor".
+ *
+ * We only keep number and alphabet characters and a few separator characters
+ * in the card long name since UCM in the user space uses the card long names
+ * as card configuration directory names and AudoConf cannot support special
+ * charactors like SPACE.
+ *
+ * Returns 0 on success, otherwise a negative error code.
+ */
+int snd_soc_set_dmi_name(struct snd_soc_card *card, const char *flavour)
+{
+	const char *vendor, *product, *product_version, *board;
+	int len;
+
+	if (card->long_name)
+		return 0; /* long name already set by driver or from DMI */
+
+	/* make up dmi long name as: vendor.product.version.board */
+	vendor = dmi_get_system_info(DMI_BOARD_VENDOR);
+	if (!vendor) {
+		dev_warn(card->dev, "ASoC: no DMI vendor name!\n");
+		return 0;
+	}
+
+	snprintf(card->dmi_longname, sizeof(card->snd_card->longname),
+			 "%s", vendor);
+
+	product = dmi_get_system_info(DMI_PRODUCT_NAME);
+	if (product) {
+		len = strlen(card->dmi_longname);
+		snprintf(card->dmi_longname + len,
+			 sizeof(card->snd_card->longname) - len,
+			 ".%s", product);
+
+		/* some vendors like Lenovo may only put a self-explanatory
+		 * name in the product version field
+		 */
+		product_version = dmi_get_system_info(DMI_PRODUCT_VERSION);
+		if (product_version) {
+			len = strlen(card->dmi_longname);
+			snprintf(card->dmi_longname + len,
+				 sizeof(card->snd_card->longname) - len,
+				 ".%s", product_version);
+			}
+	}
+
+	board = dmi_get_system_info(DMI_BOARD_NAME);
+	if (board) {
+		len = strlen(card->dmi_longname);
+		snprintf(card->dmi_longname + len,
+			 sizeof(card->snd_card->longname) - len,
+			 ".%s", board);
+	} else if (!product) {
+		/* fall back to using legacy name */
+		dev_warn(card->dev, "ASoC: no DMI board/product name!\n");
+		return 0;
+	}
+
+	/* trim special characters to save space for flavor string */
+	trim_special_characters(card->dmi_longname);
+
+	/* Add flavour to dmi long name */
+	if (flavour) {
+		len = strlen(card->dmi_longname);
+		snprintf(card->dmi_longname + len,
+			 sizeof(card->snd_card->longname) - len,
+			 ".%s", flavour);
+		trim_special_characters(card->dmi_longname + len);
+	}
+
+	/* set the card long name */
+	card->long_name = card->dmi_longname;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(snd_soc_set_dmi_name);
+
 static int snd_soc_instantiate_card(struct snd_soc_card *card)
 {
 	struct snd_soc_codec *codec;