@@ -1550,6 +1550,34 @@ static bool update_eld(struct hda_codec *codec,
1550
1550
return eld_changed ;
1551
1551
}
1552
1552
1553
+ static struct snd_jack * pin_idx_to_pcm_jack (struct hda_codec * codec ,
1554
+ struct hdmi_spec_per_pin * per_pin )
1555
+ {
1556
+ struct hdmi_spec * spec = codec -> spec ;
1557
+ struct snd_jack * jack = NULL ;
1558
+ struct hda_jack_tbl * jack_tbl ;
1559
+
1560
+ /* if !dyn_pcm_assign, get jack from hda_jack_tbl
1561
+ * in !dyn_pcm_assign case, spec->pcm_rec[].jack is not
1562
+ * NULL even after snd_hda_jack_tbl_clear() is called to
1563
+ * free snd_jack. This may cause access invalid memory
1564
+ * when calling snd_jack_report
1565
+ */
1566
+ if (per_pin -> pcm_idx >= 0 && spec -> dyn_pcm_assign ) {
1567
+ jack = spec -> pcm_rec [per_pin -> pcm_idx ].jack ;
1568
+ } else if (!spec -> dyn_pcm_assign ) {
1569
+ /*
1570
+ * jack tbl doesn't support DP MST
1571
+ * DP MST will use dyn_pcm_assign,
1572
+ * so DP MST will never come here
1573
+ */
1574
+ jack_tbl = snd_hda_jack_tbl_get_mst (codec , per_pin -> pin_nid ,
1575
+ per_pin -> dev_id );
1576
+ if (jack_tbl )
1577
+ jack = jack_tbl -> jack ;
1578
+ }
1579
+ return jack ;
1580
+ }
1553
1581
/* update ELD and jack state via HD-audio verbs */
1554
1582
static bool hdmi_present_sense_via_verbs (struct hdmi_spec_per_pin * per_pin ,
1555
1583
int repoll )
@@ -1571,6 +1599,7 @@ static bool hdmi_present_sense_via_verbs(struct hdmi_spec_per_pin *per_pin,
1571
1599
int present ;
1572
1600
bool ret ;
1573
1601
bool do_repoll = false;
1602
+ struct snd_jack * pcm_jack = NULL ;
1574
1603
1575
1604
present = snd_hda_jack_pin_sense (codec , pin_nid , dev_id );
1576
1605
@@ -1598,10 +1627,19 @@ static bool hdmi_present_sense_via_verbs(struct hdmi_spec_per_pin *per_pin,
1598
1627
do_repoll = true;
1599
1628
}
1600
1629
1601
- if (do_repoll )
1630
+ if (do_repoll ) {
1602
1631
schedule_delayed_work (& per_pin -> work , msecs_to_jiffies (300 ));
1603
- else
1632
+ } else {
1633
+ /*
1634
+ * pcm_idx >=0 before update_eld() means it is in monitor
1635
+ * disconnected event. Jack must be fetched before
1636
+ * update_eld().
1637
+ */
1638
+ pcm_jack = pin_idx_to_pcm_jack (codec , per_pin );
1604
1639
update_eld (codec , per_pin , eld );
1640
+ if (!pcm_jack )
1641
+ pcm_jack = pin_idx_to_pcm_jack (codec , per_pin );
1642
+ }
1605
1643
1606
1644
ret = !repoll || !eld -> monitor_present || eld -> eld_valid ;
1607
1645
@@ -1610,38 +1648,32 @@ static bool hdmi_present_sense_via_verbs(struct hdmi_spec_per_pin *per_pin,
1610
1648
jack -> block_report = !ret ;
1611
1649
jack -> pin_sense = (eld -> monitor_present && eld -> eld_valid ) ?
1612
1650
AC_PINSENSE_PRESENCE : 0 ;
1613
- }
1614
- mutex_unlock (& per_pin -> lock );
1615
- return ret ;
1616
- }
1617
1651
1618
- static struct snd_jack * pin_idx_to_jack (struct hda_codec * codec ,
1619
- struct hdmi_spec_per_pin * per_pin )
1620
- {
1621
- struct hdmi_spec * spec = codec -> spec ;
1622
- struct snd_jack * jack = NULL ;
1623
- struct hda_jack_tbl * jack_tbl ;
1652
+ if (spec -> dyn_pcm_assign && pcm_jack && !do_repoll ) {
1653
+ int state = 0 ;
1654
+
1655
+ if (jack -> pin_sense & AC_PINSENSE_PRESENCE )
1656
+ state = SND_JACK_AVOUT ;
1657
+ snd_jack_report (pcm_jack , state );
1658
+ }
1624
1659
1625
- /* if !dyn_pcm_assign, get jack from hda_jack_tbl
1626
- * in !dyn_pcm_assign case, spec->pcm_rec[].jack is not
1627
- * NULL even after snd_hda_jack_tbl_clear() is called to
1628
- * free snd_jack. This may cause access invalid memory
1629
- * when calling snd_jack_report
1630
- */
1631
- if (per_pin -> pcm_idx >= 0 && spec -> dyn_pcm_assign )
1632
- jack = spec -> pcm_rec [per_pin -> pcm_idx ].jack ;
1633
- else if (!spec -> dyn_pcm_assign ) {
1634
1660
/*
1635
- * jack tbl doesn't support DP MST
1636
- * DP MST will use dyn_pcm_assign,
1637
- * so DP MST will never come here
1661
+ * snd_hda_jack_pin_sense() call at the beginning of this
1662
+ * function, updates jack->pins_sense and clears
1663
+ * jack->jack_dirty, therefore snd_hda_jack_report_sync() will
1664
+ * not override the jack->pin_sense.
1665
+ *
1666
+ * snd_hda_jack_report_sync() is superfluous for dyn_pcm_assign
1667
+ * case. The jack->pin_sense update was already performed, and
1668
+ * hda_jack->jack is NULL for dyn_pcm_assign.
1669
+ *
1670
+ * Don't call snd_hda_jack_report_sync() for
1671
+ * dyn_pcm_assign.
1638
1672
*/
1639
- jack_tbl = snd_hda_jack_tbl_get_mst (codec , per_pin -> pin_nid ,
1640
- per_pin -> dev_id );
1641
- if (jack_tbl )
1642
- jack = jack_tbl -> jack ;
1673
+ ret = ret && !spec -> dyn_pcm_assign ;
1643
1674
}
1644
- return jack ;
1675
+ mutex_unlock (& per_pin -> lock );
1676
+ return ret ;
1645
1677
}
1646
1678
1647
1679
/* update ELD and jack state via audio component */
@@ -1677,10 +1709,10 @@ static void sync_eld_via_acomp(struct hda_codec *codec,
1677
1709
/* pcm_idx >=0 before update_eld() means it is in monitor
1678
1710
* disconnected event. Jack must be fetched before update_eld()
1679
1711
*/
1680
- jack = pin_idx_to_jack (codec , per_pin );
1712
+ jack = pin_idx_to_pcm_jack (codec , per_pin );
1681
1713
changed = update_eld (codec , per_pin , eld );
1682
1714
if (jack == NULL )
1683
- jack = pin_idx_to_jack (codec , per_pin );
1715
+ jack = pin_idx_to_pcm_jack (codec , per_pin );
1684
1716
if (changed && jack )
1685
1717
snd_jack_report (jack ,
1686
1718
(eld -> monitor_present && eld -> eld_valid ) ?
0 commit comments