diff options
author | Takashi Iwai <tiwai@suse.de> | 2017-11-13 09:43:04 -0500 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2017-11-13 09:43:13 -0500 |
commit | c429bda21ffafb28f02fb2eb4055b4ab6879ed58 (patch) | |
tree | 80715bf534bfa3bcb69ef77cf1dc5f9d98919b44 /sound/hda | |
parent | 75ee94b20b46459e3d29f5ac2c3af3cebdeef777 (diff) | |
parent | 9718a29d40b7e5ae4692796eb23c54f25559d35e (diff) |
Merge branch 'for-next' into for-linus
Pull 4.15 updates to take over the previous urgent fixes.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/hda')
-rw-r--r-- | sound/hda/hdac_controller.c | 3 | ||||
-rw-r--r-- | sound/hda/hdac_device.c | 43 | ||||
-rw-r--r-- | sound/hda/hdac_sysfs.c | 47 | ||||
-rw-r--r-- | sound/hda/local.h | 2 |
4 files changed, 61 insertions, 34 deletions
diff --git a/sound/hda/hdac_controller.c b/sound/hda/hdac_controller.c index f6d2985b2520..560ec0986e1a 100644 --- a/sound/hda/hdac_controller.c +++ b/sound/hda/hdac_controller.c | |||
@@ -319,7 +319,8 @@ int snd_hdac_bus_parse_capabilities(struct hdac_bus *bus) | |||
319 | break; | 319 | break; |
320 | 320 | ||
321 | default: | 321 | default: |
322 | dev_dbg(bus->dev, "Unknown capability %d\n", cur_cap); | 322 | dev_err(bus->dev, "Unknown capability %d\n", cur_cap); |
323 | cur_cap = 0; | ||
323 | break; | 324 | break; |
324 | } | 325 | } |
325 | 326 | ||
diff --git a/sound/hda/hdac_device.c b/sound/hda/hdac_device.c index 19deb306facb..06f845e293cb 100644 --- a/sound/hda/hdac_device.c +++ b/sound/hda/hdac_device.c | |||
@@ -87,7 +87,7 @@ int snd_hdac_device_init(struct hdac_device *codec, struct hdac_bus *bus, | |||
87 | 87 | ||
88 | fg = codec->afg ? codec->afg : codec->mfg; | 88 | fg = codec->afg ? codec->afg : codec->mfg; |
89 | 89 | ||
90 | err = snd_hdac_refresh_widgets(codec); | 90 | err = snd_hdac_refresh_widgets(codec, false); |
91 | if (err < 0) | 91 | if (err < 0) |
92 | goto error; | 92 | goto error; |
93 | 93 | ||
@@ -388,11 +388,12 @@ static void setup_fg_nodes(struct hdac_device *codec) | |||
388 | /** | 388 | /** |
389 | * snd_hdac_refresh_widgets - Reset the widget start/end nodes | 389 | * snd_hdac_refresh_widgets - Reset the widget start/end nodes |
390 | * @codec: the codec object | 390 | * @codec: the codec object |
391 | * @sysfs: re-initialize sysfs tree, too | ||
391 | */ | 392 | */ |
392 | int snd_hdac_refresh_widgets(struct hdac_device *codec) | 393 | int snd_hdac_refresh_widgets(struct hdac_device *codec, bool sysfs) |
393 | { | 394 | { |
394 | hda_nid_t start_nid; | 395 | hda_nid_t start_nid; |
395 | int nums; | 396 | int nums, err; |
396 | 397 | ||
397 | nums = snd_hdac_get_sub_nodes(codec, codec->afg, &start_nid); | 398 | nums = snd_hdac_get_sub_nodes(codec, codec->afg, &start_nid); |
398 | if (!start_nid || nums <= 0 || nums >= 0xff) { | 399 | if (!start_nid || nums <= 0 || nums >= 0xff) { |
@@ -401,6 +402,12 @@ int snd_hdac_refresh_widgets(struct hdac_device *codec) | |||
401 | return -EINVAL; | 402 | return -EINVAL; |
402 | } | 403 | } |
403 | 404 | ||
405 | if (sysfs) { | ||
406 | err = hda_widget_sysfs_reinit(codec, start_nid, nums); | ||
407 | if (err < 0) | ||
408 | return err; | ||
409 | } | ||
410 | |||
404 | codec->num_nodes = nums; | 411 | codec->num_nodes = nums; |
405 | codec->start_nid = start_nid; | 412 | codec->start_nid = start_nid; |
406 | codec->end_nid = start_nid + nums; | 413 | codec->end_nid = start_nid + nums; |
@@ -408,36 +415,6 @@ int snd_hdac_refresh_widgets(struct hdac_device *codec) | |||
408 | } | 415 | } |
409 | EXPORT_SYMBOL_GPL(snd_hdac_refresh_widgets); | 416 | EXPORT_SYMBOL_GPL(snd_hdac_refresh_widgets); |
410 | 417 | ||
411 | /** | ||
412 | * snd_hdac_refresh_widget_sysfs - Reset the codec widgets and reinit the | ||
413 | * codec sysfs | ||
414 | * @codec: the codec object | ||
415 | * | ||
416 | * first we need to remove sysfs, then refresh widgets and lastly | ||
417 | * recreate it | ||
418 | */ | ||
419 | int snd_hdac_refresh_widget_sysfs(struct hdac_device *codec) | ||
420 | { | ||
421 | int ret; | ||
422 | |||
423 | if (device_is_registered(&codec->dev)) | ||
424 | hda_widget_sysfs_exit(codec); | ||
425 | ret = snd_hdac_refresh_widgets(codec); | ||
426 | if (ret) { | ||
427 | dev_err(&codec->dev, "failed to refresh widget: %d\n", ret); | ||
428 | return ret; | ||
429 | } | ||
430 | if (device_is_registered(&codec->dev)) { | ||
431 | ret = hda_widget_sysfs_init(codec); | ||
432 | if (ret) { | ||
433 | dev_err(&codec->dev, "failed to init sysfs: %d\n", ret); | ||
434 | return ret; | ||
435 | } | ||
436 | } | ||
437 | return ret; | ||
438 | } | ||
439 | EXPORT_SYMBOL_GPL(snd_hdac_refresh_widget_sysfs); | ||
440 | |||
441 | /* return CONNLIST_LEN parameter of the given widget */ | 418 | /* return CONNLIST_LEN parameter of the given widget */ |
442 | static unsigned int get_num_conns(struct hdac_device *codec, hda_nid_t nid) | 419 | static unsigned int get_num_conns(struct hdac_device *codec, hda_nid_t nid) |
443 | { | 420 | { |
diff --git a/sound/hda/hdac_sysfs.c b/sound/hda/hdac_sysfs.c index 42d61bf41969..e123ba6b2e81 100644 --- a/sound/hda/hdac_sysfs.c +++ b/sound/hda/hdac_sysfs.c | |||
@@ -414,3 +414,50 @@ void hda_widget_sysfs_exit(struct hdac_device *codec) | |||
414 | { | 414 | { |
415 | widget_tree_free(codec); | 415 | widget_tree_free(codec); |
416 | } | 416 | } |
417 | |||
418 | int hda_widget_sysfs_reinit(struct hdac_device *codec, | ||
419 | hda_nid_t start_nid, int num_nodes) | ||
420 | { | ||
421 | struct hdac_widget_tree *tree; | ||
422 | hda_nid_t end_nid = start_nid + num_nodes; | ||
423 | hda_nid_t nid; | ||
424 | int i; | ||
425 | |||
426 | if (!codec->widgets) | ||
427 | return hda_widget_sysfs_init(codec); | ||
428 | |||
429 | tree = kmemdup(codec->widgets, sizeof(*tree), GFP_KERNEL); | ||
430 | if (!tree) | ||
431 | return -ENOMEM; | ||
432 | |||
433 | tree->nodes = kcalloc(num_nodes + 1, sizeof(*tree->nodes), GFP_KERNEL); | ||
434 | if (!tree->nodes) { | ||
435 | kfree(tree); | ||
436 | return -ENOMEM; | ||
437 | } | ||
438 | |||
439 | /* prune non-existing nodes */ | ||
440 | for (i = 0, nid = codec->start_nid; i < codec->num_nodes; i++, nid++) { | ||
441 | if (nid < start_nid || nid >= end_nid) | ||
442 | free_widget_node(codec->widgets->nodes[i], | ||
443 | &widget_node_group); | ||
444 | } | ||
445 | |||
446 | /* add new nodes */ | ||
447 | for (i = 0, nid = start_nid; i < num_nodes; i++, nid++) { | ||
448 | if (nid < codec->start_nid || nid >= codec->end_nid) | ||
449 | add_widget_node(tree->root, nid, &widget_node_group, | ||
450 | &tree->nodes[i]); | ||
451 | else | ||
452 | tree->nodes[i] = | ||
453 | codec->widgets->nodes[nid - codec->start_nid]; | ||
454 | } | ||
455 | |||
456 | /* replace with the new tree */ | ||
457 | kfree(codec->widgets->nodes); | ||
458 | kfree(codec->widgets); | ||
459 | codec->widgets = tree; | ||
460 | |||
461 | kobject_uevent(tree->root, KOBJ_CHANGE); | ||
462 | return 0; | ||
463 | } | ||
diff --git a/sound/hda/local.h b/sound/hda/local.h index 0d5bb159d538..c586ea62d49e 100644 --- a/sound/hda/local.h +++ b/sound/hda/local.h | |||
@@ -28,6 +28,8 @@ static inline unsigned int get_wcaps_channels(u32 wcaps) | |||
28 | 28 | ||
29 | extern const struct attribute_group *hdac_dev_attr_groups[]; | 29 | extern const struct attribute_group *hdac_dev_attr_groups[]; |
30 | int hda_widget_sysfs_init(struct hdac_device *codec); | 30 | int hda_widget_sysfs_init(struct hdac_device *codec); |
31 | int hda_widget_sysfs_reinit(struct hdac_device *codec, hda_nid_t start_nid, | ||
32 | int num_nodes); | ||
31 | void hda_widget_sysfs_exit(struct hdac_device *codec); | 33 | void hda_widget_sysfs_exit(struct hdac_device *codec); |
32 | 34 | ||
33 | #endif /* __HDAC_LOCAL_H */ | 35 | #endif /* __HDAC_LOCAL_H */ |