summaryrefslogtreecommitdiffstats
path: root/sound/hda
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2017-11-13 09:43:04 -0500
committerTakashi Iwai <tiwai@suse.de>2017-11-13 09:43:13 -0500
commitc429bda21ffafb28f02fb2eb4055b4ab6879ed58 (patch)
tree80715bf534bfa3bcb69ef77cf1dc5f9d98919b44 /sound/hda
parent75ee94b20b46459e3d29f5ac2c3af3cebdeef777 (diff)
parent9718a29d40b7e5ae4692796eb23c54f25559d35e (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.c3
-rw-r--r--sound/hda/hdac_device.c43
-rw-r--r--sound/hda/hdac_sysfs.c47
-rw-r--r--sound/hda/local.h2
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 */
392int snd_hdac_refresh_widgets(struct hdac_device *codec) 393int 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}
409EXPORT_SYMBOL_GPL(snd_hdac_refresh_widgets); 416EXPORT_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 */
419int 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}
439EXPORT_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 */
442static unsigned int get_num_conns(struct hdac_device *codec, hda_nid_t nid) 419static 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
418int 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
29extern const struct attribute_group *hdac_dev_attr_groups[]; 29extern const struct attribute_group *hdac_dev_attr_groups[];
30int hda_widget_sysfs_init(struct hdac_device *codec); 30int hda_widget_sysfs_init(struct hdac_device *codec);
31int hda_widget_sysfs_reinit(struct hdac_device *codec, hda_nid_t start_nid,
32 int num_nodes);
31void hda_widget_sysfs_exit(struct hdac_device *codec); 33void hda_widget_sysfs_exit(struct hdac_device *codec);
32 34
33#endif /* __HDAC_LOCAL_H */ 35#endif /* __HDAC_LOCAL_H */