diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-07-09 21:48:37 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-07-09 21:48:37 -0400 |
commit | af3c8d98508d37541d4bf57f13a984a7f73a328c (patch) | |
tree | e8dd974d6ebccd38b1e373be8a5e4a2f8bf3c6ce /sound/x86 | |
parent | d3e3b7eac886fb1383db2f22b81550fa6d87f62f (diff) | |
parent | 00fc2c26bc46a64545cdf95a1511461ea9acecb4 (diff) |
Merge tag 'drm-for-v4.13' of git://people.freedesktop.org/~airlied/linux
Pull drm updates from Dave Airlie:
"This is the main pull request for the drm, I think I've got one later
driver pull for mediatek SoC driver, I'm undecided on if it needs to
go to you yet.
Otherwise summary below:
Core drm:
- Atomic add driver private objects
- Deprecate preclose hook in modern drivers
- MST bandwidth tracking
- Use kvmalloc in more places
- Add mode_valid hook for crtc/encoder/bridge
- Reduce sync_file construction time
- Documentation updates
- New DRM synchronisation object support
New drivers:
- pl111 - pl111 CLCD display controller
Panel:
- Innolux P079ZCA panel driver
- Add NL12880B20-05, NL192108AC18-02D, P320HVN03 panels
- panel-samsung-s6e3ha2: Add s6e3hf2 panel support
i915:
- SKL+ watermark fixes
- G4x/G33 reset improvements
- DP AUX backlight improvements
- Buffer based GuC/host communication
- New getparam for (sub)slice infomation
- Cannonlake and Coffeelake initial patches
- Execbuf optimisations
radeon/amdgpu:
- Lots of Vega10 bug fixes
- Preliminary raven support
- KIQ support for compute rings
- MEC queue management rework
- DCE6 Audio support
- SR-IOV improvements
- Better radeon/amdgpu selection support
nouveau:
- HDMI stereoscopic support
- Display code rework for >= GM20x GPUs
msm:
- GEM rework for fine-grained locking
- Per-process pagetable work
- HDMI fixes for Snapdragon 820.
vc4:
- Remove 256MB CMA limit from vc4
- Add out-fence support
- Add support for cygnus
- Get/set tiling ioctls support
- Add T-format tiling support for scanout
zte:
- add VGA support.
etnaviv:
- Thermal throttle support for newer GPUs
- Restore userspace buffer cache performance
- dma-buf sync fix
stm:
- add stm32f429 display support
exynos:
- Rework vblank handling
- Fixup sw-trigger code
sun4i:
- V3s display engine support
- HDMI support for older SoCs
- Preliminary work on dual-pipeline SoCs.
rcar-du:
- VSP work
imx-drm:
- Remove counter load enable from PRE
- Double read/write reduction flag support
tegra:
- Documentation for the host1x and drm driver.
- Lots of staging ioctl fixes due to grate project work.
omapdrm:
- dma-buf fence support
- TILER rotation fixes"
* tag 'drm-for-v4.13' of git://people.freedesktop.org/~airlied/linux: (1270 commits)
drm: Remove unused drm_file parameter to drm_syncobj_replace_fence()
drm/amd/powerplay: fix bug fail to remove sysfs when rmmod amdgpu.
amdgpu: Set cik/si_support to 1 by default if radeon isn't built
drm/amdgpu/gfx9: fix driver reload with KIQ
drm/amdgpu/gfx8: fix driver reload with KIQ
drm/amdgpu: Don't call amd_powerplay_destroy() if we don't have powerplay
drm/ttm: Fix use-after-free in ttm_bo_clean_mm
drm/amd/amdgpu: move get memory type function from early init to sw init
drm/amdgpu/cgs: always set reference clock in mode_info
drm/amdgpu: fix vblank_time when displays are off
drm/amd/powerplay: power value format change for Vega10
drm/amdgpu/gfx9: support the amdgpu.disable_cu option
drm/amd/powerplay: change PPSMC_MSG_GetCurrPkgPwr for Vega10
drm/amdgpu: Make amdgpu_cs_parser_init static (v2)
drm/amdgpu/cs: fix a typo in a comment
drm/amdgpu: Fix the exported always on CU bitmap
drm/amdgpu/gfx9: gfx_v9_0_enable_gfx_static_mg_power_gating() can be static
drm/amdgpu/psp: upper_32_bits/lower_32_bits for address setup
drm/amd/powerplay/cz: print message if smc message fails
drm/amdgpu: fix typo in amdgpu_debugfs_test_ib_init
...
Diffstat (limited to 'sound/x86')
-rw-r--r-- | sound/x86/intel_hdmi_audio.c | 324 | ||||
-rw-r--r-- | sound/x86/intel_hdmi_audio.h | 20 |
2 files changed, 216 insertions, 128 deletions
diff --git a/sound/x86/intel_hdmi_audio.c b/sound/x86/intel_hdmi_audio.c index 37f06ffdf1e6..a0951505c7f5 100644 --- a/sound/x86/intel_hdmi_audio.c +++ b/sound/x86/intel_hdmi_audio.c | |||
@@ -42,6 +42,11 @@ | |||
42 | #include <drm/intel_lpe_audio.h> | 42 | #include <drm/intel_lpe_audio.h> |
43 | #include "intel_hdmi_audio.h" | 43 | #include "intel_hdmi_audio.h" |
44 | 44 | ||
45 | #define for_each_pipe(card_ctx, pipe) \ | ||
46 | for ((pipe) = 0; (pipe) < (card_ctx)->num_pipes; (pipe)++) | ||
47 | #define for_each_port(card_ctx, port) \ | ||
48 | for ((port) = 0; (port) < (card_ctx)->num_ports; (port)++) | ||
49 | |||
45 | /*standard module options for ALSA. This module supports only one card*/ | 50 | /*standard module options for ALSA. This module supports only one card*/ |
46 | static int hdmi_card_index = SNDRV_DEFAULT_IDX1; | 51 | static int hdmi_card_index = SNDRV_DEFAULT_IDX1; |
47 | static char *hdmi_card_id = SNDRV_DEFAULT_STR1; | 52 | static char *hdmi_card_id = SNDRV_DEFAULT_STR1; |
@@ -189,15 +194,30 @@ static void had_substream_put(struct snd_intelhad *intelhaddata) | |||
189 | spin_unlock_irqrestore(&intelhaddata->had_spinlock, flags); | 194 | spin_unlock_irqrestore(&intelhaddata->had_spinlock, flags); |
190 | } | 195 | } |
191 | 196 | ||
197 | static u32 had_config_offset(int pipe) | ||
198 | { | ||
199 | switch (pipe) { | ||
200 | default: | ||
201 | case 0: | ||
202 | return AUDIO_HDMI_CONFIG_A; | ||
203 | case 1: | ||
204 | return AUDIO_HDMI_CONFIG_B; | ||
205 | case 2: | ||
206 | return AUDIO_HDMI_CONFIG_C; | ||
207 | } | ||
208 | } | ||
209 | |||
192 | /* Register access functions */ | 210 | /* Register access functions */ |
193 | static u32 had_read_register_raw(struct snd_intelhad *ctx, u32 reg) | 211 | static u32 had_read_register_raw(struct snd_intelhad_card *card_ctx, |
212 | int pipe, u32 reg) | ||
194 | { | 213 | { |
195 | return ioread32(ctx->mmio_start + ctx->had_config_offset + reg); | 214 | return ioread32(card_ctx->mmio_start + had_config_offset(pipe) + reg); |
196 | } | 215 | } |
197 | 216 | ||
198 | static void had_write_register_raw(struct snd_intelhad *ctx, u32 reg, u32 val) | 217 | static void had_write_register_raw(struct snd_intelhad_card *card_ctx, |
218 | int pipe, u32 reg, u32 val) | ||
199 | { | 219 | { |
200 | iowrite32(val, ctx->mmio_start + ctx->had_config_offset + reg); | 220 | iowrite32(val, card_ctx->mmio_start + had_config_offset(pipe) + reg); |
201 | } | 221 | } |
202 | 222 | ||
203 | static void had_read_register(struct snd_intelhad *ctx, u32 reg, u32 *val) | 223 | static void had_read_register(struct snd_intelhad *ctx, u32 reg, u32 *val) |
@@ -205,13 +225,13 @@ static void had_read_register(struct snd_intelhad *ctx, u32 reg, u32 *val) | |||
205 | if (!ctx->connected) | 225 | if (!ctx->connected) |
206 | *val = 0; | 226 | *val = 0; |
207 | else | 227 | else |
208 | *val = had_read_register_raw(ctx, reg); | 228 | *val = had_read_register_raw(ctx->card_ctx, ctx->pipe, reg); |
209 | } | 229 | } |
210 | 230 | ||
211 | static void had_write_register(struct snd_intelhad *ctx, u32 reg, u32 val) | 231 | static void had_write_register(struct snd_intelhad *ctx, u32 reg, u32 val) |
212 | { | 232 | { |
213 | if (ctx->connected) | 233 | if (ctx->connected) |
214 | had_write_register_raw(ctx, reg, val); | 234 | had_write_register_raw(ctx->card_ctx, ctx->pipe, reg, val); |
215 | } | 235 | } |
216 | 236 | ||
217 | /* | 237 | /* |
@@ -1358,6 +1378,9 @@ static void had_process_hot_plug(struct snd_intelhad *intelhaddata) | |||
1358 | return; | 1378 | return; |
1359 | } | 1379 | } |
1360 | 1380 | ||
1381 | /* Disable Audio */ | ||
1382 | had_enable_audio(intelhaddata, false); | ||
1383 | |||
1361 | intelhaddata->connected = true; | 1384 | intelhaddata->connected = true; |
1362 | dev_dbg(intelhaddata->dev, | 1385 | dev_dbg(intelhaddata->dev, |
1363 | "%s @ %d:DEBUG PLUG/UNPLUG : HAD_DRV_CONNECTED\n", | 1386 | "%s @ %d:DEBUG PLUG/UNPLUG : HAD_DRV_CONNECTED\n", |
@@ -1519,22 +1542,32 @@ static const struct snd_kcontrol_new had_controls[] = { | |||
1519 | */ | 1542 | */ |
1520 | static irqreturn_t display_pipe_interrupt_handler(int irq, void *dev_id) | 1543 | static irqreturn_t display_pipe_interrupt_handler(int irq, void *dev_id) |
1521 | { | 1544 | { |
1522 | struct snd_intelhad *ctx = dev_id; | 1545 | struct snd_intelhad_card *card_ctx = dev_id; |
1523 | u32 audio_stat; | 1546 | u32 audio_stat[3] = {}; |
1547 | int pipe, port; | ||
1548 | |||
1549 | for_each_pipe(card_ctx, pipe) { | ||
1550 | /* use raw register access to ack IRQs even while disconnected */ | ||
1551 | audio_stat[pipe] = had_read_register_raw(card_ctx, pipe, | ||
1552 | AUD_HDMI_STATUS) & | ||
1553 | (HDMI_AUDIO_UNDERRUN | HDMI_AUDIO_BUFFER_DONE); | ||
1554 | |||
1555 | if (audio_stat[pipe]) | ||
1556 | had_write_register_raw(card_ctx, pipe, | ||
1557 | AUD_HDMI_STATUS, audio_stat[pipe]); | ||
1558 | } | ||
1524 | 1559 | ||
1525 | /* use raw register access to ack IRQs even while disconnected */ | 1560 | for_each_port(card_ctx, port) { |
1526 | audio_stat = had_read_register_raw(ctx, AUD_HDMI_STATUS); | 1561 | struct snd_intelhad *ctx = &card_ctx->pcm_ctx[port]; |
1562 | int pipe = ctx->pipe; | ||
1527 | 1563 | ||
1528 | if (audio_stat & HDMI_AUDIO_UNDERRUN) { | 1564 | if (pipe < 0) |
1529 | had_write_register_raw(ctx, AUD_HDMI_STATUS, | 1565 | continue; |
1530 | HDMI_AUDIO_UNDERRUN); | ||
1531 | had_process_buffer_underrun(ctx); | ||
1532 | } | ||
1533 | 1566 | ||
1534 | if (audio_stat & HDMI_AUDIO_BUFFER_DONE) { | 1567 | if (audio_stat[pipe] & HDMI_AUDIO_BUFFER_DONE) |
1535 | had_write_register_raw(ctx, AUD_HDMI_STATUS, | 1568 | had_process_buffer_done(ctx); |
1536 | HDMI_AUDIO_BUFFER_DONE); | 1569 | if (audio_stat[pipe] & HDMI_AUDIO_UNDERRUN) |
1537 | had_process_buffer_done(ctx); | 1570 | had_process_buffer_underrun(ctx); |
1538 | } | 1571 | } |
1539 | 1572 | ||
1540 | return IRQ_HANDLED; | 1573 | return IRQ_HANDLED; |
@@ -1543,9 +1576,10 @@ static irqreturn_t display_pipe_interrupt_handler(int irq, void *dev_id) | |||
1543 | /* | 1576 | /* |
1544 | * monitor plug/unplug notification from i915; just kick off the work | 1577 | * monitor plug/unplug notification from i915; just kick off the work |
1545 | */ | 1578 | */ |
1546 | static void notify_audio_lpe(struct platform_device *pdev) | 1579 | static void notify_audio_lpe(struct platform_device *pdev, int port) |
1547 | { | 1580 | { |
1548 | struct snd_intelhad *ctx = platform_get_drvdata(pdev); | 1581 | struct snd_intelhad_card *card_ctx = platform_get_drvdata(pdev); |
1582 | struct snd_intelhad *ctx = &card_ctx->pcm_ctx[port]; | ||
1549 | 1583 | ||
1550 | schedule_work(&ctx->hdmi_audio_wq); | 1584 | schedule_work(&ctx->hdmi_audio_wq); |
1551 | } | 1585 | } |
@@ -1556,47 +1590,51 @@ static void had_audio_wq(struct work_struct *work) | |||
1556 | struct snd_intelhad *ctx = | 1590 | struct snd_intelhad *ctx = |
1557 | container_of(work, struct snd_intelhad, hdmi_audio_wq); | 1591 | container_of(work, struct snd_intelhad, hdmi_audio_wq); |
1558 | struct intel_hdmi_lpe_audio_pdata *pdata = ctx->dev->platform_data; | 1592 | struct intel_hdmi_lpe_audio_pdata *pdata = ctx->dev->platform_data; |
1593 | struct intel_hdmi_lpe_audio_port_pdata *ppdata = &pdata->port[ctx->port]; | ||
1559 | 1594 | ||
1560 | pm_runtime_get_sync(ctx->dev); | 1595 | pm_runtime_get_sync(ctx->dev); |
1561 | mutex_lock(&ctx->mutex); | 1596 | mutex_lock(&ctx->mutex); |
1562 | if (!pdata->hdmi_connected) { | 1597 | if (ppdata->pipe < 0) { |
1563 | dev_dbg(ctx->dev, "%s: Event: HAD_NOTIFY_HOT_UNPLUG\n", | 1598 | dev_dbg(ctx->dev, "%s: Event: HAD_NOTIFY_HOT_UNPLUG : port = %d\n", |
1564 | __func__); | 1599 | __func__, ctx->port); |
1600 | |||
1565 | memset(ctx->eld, 0, sizeof(ctx->eld)); /* clear the old ELD */ | 1601 | memset(ctx->eld, 0, sizeof(ctx->eld)); /* clear the old ELD */ |
1602 | |||
1603 | ctx->dp_output = false; | ||
1604 | ctx->tmds_clock_speed = 0; | ||
1605 | ctx->link_rate = 0; | ||
1606 | |||
1607 | /* Shut down the stream */ | ||
1566 | had_process_hot_unplug(ctx); | 1608 | had_process_hot_unplug(ctx); |
1567 | } else { | ||
1568 | struct intel_hdmi_lpe_audio_eld *eld = &pdata->eld; | ||
1569 | 1609 | ||
1610 | ctx->pipe = -1; | ||
1611 | } else { | ||
1570 | dev_dbg(ctx->dev, "%s: HAD_NOTIFY_ELD : port = %d, tmds = %d\n", | 1612 | dev_dbg(ctx->dev, "%s: HAD_NOTIFY_ELD : port = %d, tmds = %d\n", |
1571 | __func__, eld->port_id, pdata->tmds_clock_speed); | 1613 | __func__, ctx->port, ppdata->ls_clock); |
1572 | |||
1573 | switch (eld->pipe_id) { | ||
1574 | case 0: | ||
1575 | ctx->had_config_offset = AUDIO_HDMI_CONFIG_A; | ||
1576 | break; | ||
1577 | case 1: | ||
1578 | ctx->had_config_offset = AUDIO_HDMI_CONFIG_B; | ||
1579 | break; | ||
1580 | case 2: | ||
1581 | ctx->had_config_offset = AUDIO_HDMI_CONFIG_C; | ||
1582 | break; | ||
1583 | default: | ||
1584 | dev_dbg(ctx->dev, "Invalid pipe %d\n", | ||
1585 | eld->pipe_id); | ||
1586 | break; | ||
1587 | } | ||
1588 | 1614 | ||
1589 | memcpy(ctx->eld, eld->eld_data, sizeof(ctx->eld)); | 1615 | memcpy(ctx->eld, ppdata->eld, sizeof(ctx->eld)); |
1590 | 1616 | ||
1591 | ctx->dp_output = pdata->dp_output; | 1617 | ctx->dp_output = ppdata->dp_output; |
1592 | ctx->tmds_clock_speed = pdata->tmds_clock_speed; | 1618 | if (ctx->dp_output) { |
1593 | ctx->link_rate = pdata->link_rate; | 1619 | ctx->tmds_clock_speed = 0; |
1620 | ctx->link_rate = ppdata->ls_clock; | ||
1621 | } else { | ||
1622 | ctx->tmds_clock_speed = ppdata->ls_clock; | ||
1623 | ctx->link_rate = 0; | ||
1624 | } | ||
1594 | 1625 | ||
1626 | /* | ||
1627 | * Shut down the stream before we change | ||
1628 | * the pipe assignment for this pcm device | ||
1629 | */ | ||
1595 | had_process_hot_plug(ctx); | 1630 | had_process_hot_plug(ctx); |
1596 | 1631 | ||
1597 | /* Process mode change if stream is active */ | 1632 | ctx->pipe = ppdata->pipe; |
1633 | |||
1634 | /* Restart the stream if necessary */ | ||
1598 | had_process_mode_change(ctx); | 1635 | had_process_mode_change(ctx); |
1599 | } | 1636 | } |
1637 | |||
1600 | mutex_unlock(&ctx->mutex); | 1638 | mutex_unlock(&ctx->mutex); |
1601 | pm_runtime_mark_last_busy(ctx->dev); | 1639 | pm_runtime_mark_last_busy(ctx->dev); |
1602 | pm_runtime_put_autosuspend(ctx->dev); | 1640 | pm_runtime_put_autosuspend(ctx->dev); |
@@ -1605,11 +1643,17 @@ static void had_audio_wq(struct work_struct *work) | |||
1605 | /* | 1643 | /* |
1606 | * Jack interface | 1644 | * Jack interface |
1607 | */ | 1645 | */ |
1608 | static int had_create_jack(struct snd_intelhad *ctx) | 1646 | static int had_create_jack(struct snd_intelhad *ctx, |
1647 | struct snd_pcm *pcm) | ||
1609 | { | 1648 | { |
1649 | char hdmi_str[32]; | ||
1610 | int err; | 1650 | int err; |
1611 | 1651 | ||
1612 | err = snd_jack_new(ctx->card, "HDMI/DP", SND_JACK_AVOUT, &ctx->jack, | 1652 | snprintf(hdmi_str, sizeof(hdmi_str), |
1653 | "HDMI/DP,pcm=%d", pcm->device); | ||
1654 | |||
1655 | err = snd_jack_new(ctx->card_ctx->card, hdmi_str, | ||
1656 | SND_JACK_AVOUT, &ctx->jack, | ||
1613 | true, false); | 1657 | true, false); |
1614 | if (err < 0) | 1658 | if (err < 0) |
1615 | return err; | 1659 | return err; |
@@ -1623,13 +1667,18 @@ static int had_create_jack(struct snd_intelhad *ctx) | |||
1623 | 1667 | ||
1624 | static int hdmi_lpe_audio_runtime_suspend(struct device *dev) | 1668 | static int hdmi_lpe_audio_runtime_suspend(struct device *dev) |
1625 | { | 1669 | { |
1626 | struct snd_intelhad *ctx = dev_get_drvdata(dev); | 1670 | struct snd_intelhad_card *card_ctx = dev_get_drvdata(dev); |
1627 | struct snd_pcm_substream *substream; | 1671 | int port; |
1628 | 1672 | ||
1629 | substream = had_substream_get(ctx); | 1673 | for_each_port(card_ctx, port) { |
1630 | if (substream) { | 1674 | struct snd_intelhad *ctx = &card_ctx->pcm_ctx[port]; |
1631 | snd_pcm_suspend(substream); | 1675 | struct snd_pcm_substream *substream; |
1632 | had_substream_put(ctx); | 1676 | |
1677 | substream = had_substream_get(ctx); | ||
1678 | if (substream) { | ||
1679 | snd_pcm_suspend(substream); | ||
1680 | had_substream_put(ctx); | ||
1681 | } | ||
1633 | } | 1682 | } |
1634 | 1683 | ||
1635 | return 0; | 1684 | return 0; |
@@ -1637,12 +1686,12 @@ static int hdmi_lpe_audio_runtime_suspend(struct device *dev) | |||
1637 | 1686 | ||
1638 | static int __maybe_unused hdmi_lpe_audio_suspend(struct device *dev) | 1687 | static int __maybe_unused hdmi_lpe_audio_suspend(struct device *dev) |
1639 | { | 1688 | { |
1640 | struct snd_intelhad *ctx = dev_get_drvdata(dev); | 1689 | struct snd_intelhad_card *card_ctx = dev_get_drvdata(dev); |
1641 | int err; | 1690 | int err; |
1642 | 1691 | ||
1643 | err = hdmi_lpe_audio_runtime_suspend(dev); | 1692 | err = hdmi_lpe_audio_runtime_suspend(dev); |
1644 | if (!err) | 1693 | if (!err) |
1645 | snd_power_change_state(ctx->card, SNDRV_CTL_POWER_D3hot); | 1694 | snd_power_change_state(card_ctx->card, SNDRV_CTL_POWER_D3hot); |
1646 | return err; | 1695 | return err; |
1647 | } | 1696 | } |
1648 | 1697 | ||
@@ -1654,24 +1703,34 @@ static int hdmi_lpe_audio_runtime_resume(struct device *dev) | |||
1654 | 1703 | ||
1655 | static int __maybe_unused hdmi_lpe_audio_resume(struct device *dev) | 1704 | static int __maybe_unused hdmi_lpe_audio_resume(struct device *dev) |
1656 | { | 1705 | { |
1657 | struct snd_intelhad *ctx = dev_get_drvdata(dev); | 1706 | struct snd_intelhad_card *card_ctx = dev_get_drvdata(dev); |
1658 | 1707 | ||
1659 | hdmi_lpe_audio_runtime_resume(dev); | 1708 | hdmi_lpe_audio_runtime_resume(dev); |
1660 | snd_power_change_state(ctx->card, SNDRV_CTL_POWER_D0); | 1709 | snd_power_change_state(card_ctx->card, SNDRV_CTL_POWER_D0); |
1661 | return 0; | 1710 | return 0; |
1662 | } | 1711 | } |
1663 | 1712 | ||
1664 | /* release resources */ | 1713 | /* release resources */ |
1665 | static void hdmi_lpe_audio_free(struct snd_card *card) | 1714 | static void hdmi_lpe_audio_free(struct snd_card *card) |
1666 | { | 1715 | { |
1667 | struct snd_intelhad *ctx = card->private_data; | 1716 | struct snd_intelhad_card *card_ctx = card->private_data; |
1717 | struct intel_hdmi_lpe_audio_pdata *pdata = card_ctx->dev->platform_data; | ||
1718 | int port; | ||
1719 | |||
1720 | spin_lock_irq(&pdata->lpe_audio_slock); | ||
1721 | pdata->notify_audio_lpe = NULL; | ||
1722 | spin_unlock_irq(&pdata->lpe_audio_slock); | ||
1668 | 1723 | ||
1669 | cancel_work_sync(&ctx->hdmi_audio_wq); | 1724 | for_each_port(card_ctx, port) { |
1725 | struct snd_intelhad *ctx = &card_ctx->pcm_ctx[port]; | ||
1670 | 1726 | ||
1671 | if (ctx->mmio_start) | 1727 | cancel_work_sync(&ctx->hdmi_audio_wq); |
1672 | iounmap(ctx->mmio_start); | 1728 | } |
1673 | if (ctx->irq >= 0) | 1729 | |
1674 | free_irq(ctx->irq, ctx); | 1730 | if (card_ctx->mmio_start) |
1731 | iounmap(card_ctx->mmio_start); | ||
1732 | if (card_ctx->irq >= 0) | ||
1733 | free_irq(card_ctx->irq, card_ctx); | ||
1675 | } | 1734 | } |
1676 | 1735 | ||
1677 | /* | 1736 | /* |
@@ -1683,12 +1742,12 @@ static void hdmi_lpe_audio_free(struct snd_card *card) | |||
1683 | static int hdmi_lpe_audio_probe(struct platform_device *pdev) | 1742 | static int hdmi_lpe_audio_probe(struct platform_device *pdev) |
1684 | { | 1743 | { |
1685 | struct snd_card *card; | 1744 | struct snd_card *card; |
1686 | struct snd_intelhad *ctx; | 1745 | struct snd_intelhad_card *card_ctx; |
1687 | struct snd_pcm *pcm; | 1746 | struct snd_pcm *pcm; |
1688 | struct intel_hdmi_lpe_audio_pdata *pdata; | 1747 | struct intel_hdmi_lpe_audio_pdata *pdata; |
1689 | int irq; | 1748 | int irq; |
1690 | struct resource *res_mmio; | 1749 | struct resource *res_mmio; |
1691 | int i, ret; | 1750 | int port, ret; |
1692 | 1751 | ||
1693 | pdata = pdev->dev.platform_data; | 1752 | pdata = pdev->dev.platform_data; |
1694 | if (!pdata) { | 1753 | if (!pdata) { |
@@ -1711,39 +1770,30 @@ static int hdmi_lpe_audio_probe(struct platform_device *pdev) | |||
1711 | 1770 | ||
1712 | /* create a card instance with ALSA framework */ | 1771 | /* create a card instance with ALSA framework */ |
1713 | ret = snd_card_new(&pdev->dev, hdmi_card_index, hdmi_card_id, | 1772 | ret = snd_card_new(&pdev->dev, hdmi_card_index, hdmi_card_id, |
1714 | THIS_MODULE, sizeof(*ctx), &card); | 1773 | THIS_MODULE, sizeof(*card_ctx), &card); |
1715 | if (ret) | 1774 | if (ret) |
1716 | return ret; | 1775 | return ret; |
1717 | 1776 | ||
1718 | ctx = card->private_data; | 1777 | card_ctx = card->private_data; |
1719 | spin_lock_init(&ctx->had_spinlock); | 1778 | card_ctx->dev = &pdev->dev; |
1720 | mutex_init(&ctx->mutex); | 1779 | card_ctx->card = card; |
1721 | ctx->connected = false; | ||
1722 | ctx->dev = &pdev->dev; | ||
1723 | ctx->card = card; | ||
1724 | ctx->aes_bits = SNDRV_PCM_DEFAULT_CON_SPDIF; | ||
1725 | strcpy(card->driver, INTEL_HAD); | 1780 | strcpy(card->driver, INTEL_HAD); |
1726 | strcpy(card->shortname, "Intel HDMI/DP LPE Audio"); | 1781 | strcpy(card->shortname, "Intel HDMI/DP LPE Audio"); |
1727 | strcpy(card->longname, "Intel HDMI/DP LPE Audio"); | 1782 | strcpy(card->longname, "Intel HDMI/DP LPE Audio"); |
1728 | 1783 | ||
1729 | ctx->irq = -1; | 1784 | card_ctx->irq = -1; |
1730 | ctx->tmds_clock_speed = DIS_SAMPLE_RATE_148_5; | ||
1731 | INIT_WORK(&ctx->hdmi_audio_wq, had_audio_wq); | ||
1732 | 1785 | ||
1733 | card->private_free = hdmi_lpe_audio_free; | 1786 | card->private_free = hdmi_lpe_audio_free; |
1734 | 1787 | ||
1735 | /* assume pipe A as default */ | 1788 | platform_set_drvdata(pdev, card_ctx); |
1736 | ctx->had_config_offset = AUDIO_HDMI_CONFIG_A; | ||
1737 | |||
1738 | platform_set_drvdata(pdev, ctx); | ||
1739 | 1789 | ||
1740 | dev_dbg(&pdev->dev, "%s: mmio_start = 0x%x, mmio_end = 0x%x\n", | 1790 | dev_dbg(&pdev->dev, "%s: mmio_start = 0x%x, mmio_end = 0x%x\n", |
1741 | __func__, (unsigned int)res_mmio->start, | 1791 | __func__, (unsigned int)res_mmio->start, |
1742 | (unsigned int)res_mmio->end); | 1792 | (unsigned int)res_mmio->end); |
1743 | 1793 | ||
1744 | ctx->mmio_start = ioremap_nocache(res_mmio->start, | 1794 | card_ctx->mmio_start = ioremap_nocache(res_mmio->start, |
1745 | (size_t)(resource_size(res_mmio))); | 1795 | (size_t)(resource_size(res_mmio))); |
1746 | if (!ctx->mmio_start) { | 1796 | if (!card_ctx->mmio_start) { |
1747 | dev_err(&pdev->dev, "Could not get ioremap\n"); | 1797 | dev_err(&pdev->dev, "Could not get ioremap\n"); |
1748 | ret = -EACCES; | 1798 | ret = -EACCES; |
1749 | goto err; | 1799 | goto err; |
@@ -1751,54 +1801,79 @@ static int hdmi_lpe_audio_probe(struct platform_device *pdev) | |||
1751 | 1801 | ||
1752 | /* setup interrupt handler */ | 1802 | /* setup interrupt handler */ |
1753 | ret = request_irq(irq, display_pipe_interrupt_handler, 0, | 1803 | ret = request_irq(irq, display_pipe_interrupt_handler, 0, |
1754 | pdev->name, ctx); | 1804 | pdev->name, card_ctx); |
1755 | if (ret < 0) { | 1805 | if (ret < 0) { |
1756 | dev_err(&pdev->dev, "request_irq failed\n"); | 1806 | dev_err(&pdev->dev, "request_irq failed\n"); |
1757 | goto err; | 1807 | goto err; |
1758 | } | 1808 | } |
1759 | 1809 | ||
1760 | ctx->irq = irq; | 1810 | card_ctx->irq = irq; |
1761 | |||
1762 | ret = snd_pcm_new(card, INTEL_HAD, PCM_INDEX, MAX_PB_STREAMS, | ||
1763 | MAX_CAP_STREAMS, &pcm); | ||
1764 | if (ret) | ||
1765 | goto err; | ||
1766 | |||
1767 | /* setup private data which can be retrieved when required */ | ||
1768 | pcm->private_data = ctx; | ||
1769 | pcm->info_flags = 0; | ||
1770 | strncpy(pcm->name, card->shortname, strlen(card->shortname)); | ||
1771 | /* setup the ops for playabck */ | ||
1772 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &had_pcm_ops); | ||
1773 | 1811 | ||
1774 | /* only 32bit addressable */ | 1812 | /* only 32bit addressable */ |
1775 | dma_set_mask(&pdev->dev, DMA_BIT_MASK(32)); | 1813 | dma_set_mask(&pdev->dev, DMA_BIT_MASK(32)); |
1776 | dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); | 1814 | dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); |
1777 | 1815 | ||
1778 | /* allocate dma pages; | 1816 | init_channel_allocations(); |
1779 | * try to allocate 600k buffer as default which is large enough | ||
1780 | */ | ||
1781 | snd_pcm_lib_preallocate_pages_for_all(pcm, | ||
1782 | SNDRV_DMA_TYPE_DEV, NULL, | ||
1783 | HAD_DEFAULT_BUFFER, HAD_MAX_BUFFER); | ||
1784 | 1817 | ||
1785 | /* create controls */ | 1818 | card_ctx->num_pipes = pdata->num_pipes; |
1786 | for (i = 0; i < ARRAY_SIZE(had_controls); i++) { | 1819 | card_ctx->num_ports = pdata->num_ports; |
1787 | ret = snd_ctl_add(card, snd_ctl_new1(&had_controls[i], ctx)); | 1820 | |
1788 | if (ret < 0) | 1821 | for_each_port(card_ctx, port) { |
1822 | struct snd_intelhad *ctx = &card_ctx->pcm_ctx[port]; | ||
1823 | int i; | ||
1824 | |||
1825 | ctx->card_ctx = card_ctx; | ||
1826 | ctx->dev = card_ctx->dev; | ||
1827 | ctx->port = port; | ||
1828 | ctx->pipe = -1; | ||
1829 | |||
1830 | INIT_WORK(&ctx->hdmi_audio_wq, had_audio_wq); | ||
1831 | |||
1832 | ret = snd_pcm_new(card, INTEL_HAD, port, MAX_PB_STREAMS, | ||
1833 | MAX_CAP_STREAMS, &pcm); | ||
1834 | if (ret) | ||
1789 | goto err; | 1835 | goto err; |
1790 | } | ||
1791 | 1836 | ||
1792 | init_channel_allocations(); | 1837 | /* setup private data which can be retrieved when required */ |
1838 | pcm->private_data = ctx; | ||
1839 | pcm->info_flags = 0; | ||
1840 | strncpy(pcm->name, card->shortname, strlen(card->shortname)); | ||
1841 | /* setup the ops for playabck */ | ||
1842 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &had_pcm_ops); | ||
1793 | 1843 | ||
1794 | /* Register channel map controls */ | 1844 | /* allocate dma pages; |
1795 | ret = had_register_chmap_ctls(ctx, pcm); | 1845 | * try to allocate 600k buffer as default which is large enough |
1796 | if (ret < 0) | 1846 | */ |
1797 | goto err; | 1847 | snd_pcm_lib_preallocate_pages_for_all(pcm, |
1848 | SNDRV_DMA_TYPE_DEV, NULL, | ||
1849 | HAD_DEFAULT_BUFFER, HAD_MAX_BUFFER); | ||
1850 | |||
1851 | /* create controls */ | ||
1852 | for (i = 0; i < ARRAY_SIZE(had_controls); i++) { | ||
1853 | struct snd_kcontrol *kctl; | ||
1854 | |||
1855 | kctl = snd_ctl_new1(&had_controls[i], ctx); | ||
1856 | if (!kctl) { | ||
1857 | ret = -ENOMEM; | ||
1858 | goto err; | ||
1859 | } | ||
1798 | 1860 | ||
1799 | ret = had_create_jack(ctx); | 1861 | kctl->id.device = pcm->device; |
1800 | if (ret < 0) | 1862 | |
1801 | goto err; | 1863 | ret = snd_ctl_add(card, kctl); |
1864 | if (ret < 0) | ||
1865 | goto err; | ||
1866 | } | ||
1867 | |||
1868 | /* Register channel map controls */ | ||
1869 | ret = had_register_chmap_ctls(ctx, pcm); | ||
1870 | if (ret < 0) | ||
1871 | goto err; | ||
1872 | |||
1873 | ret = had_create_jack(ctx, pcm); | ||
1874 | if (ret < 0) | ||
1875 | goto err; | ||
1876 | } | ||
1802 | 1877 | ||
1803 | ret = snd_card_register(card); | 1878 | ret = snd_card_register(card); |
1804 | if (ret) | 1879 | if (ret) |
@@ -1806,7 +1881,6 @@ static int hdmi_lpe_audio_probe(struct platform_device *pdev) | |||
1806 | 1881 | ||
1807 | spin_lock_irq(&pdata->lpe_audio_slock); | 1882 | spin_lock_irq(&pdata->lpe_audio_slock); |
1808 | pdata->notify_audio_lpe = notify_audio_lpe; | 1883 | pdata->notify_audio_lpe = notify_audio_lpe; |
1809 | pdata->notify_pending = false; | ||
1810 | spin_unlock_irq(&pdata->lpe_audio_slock); | 1884 | spin_unlock_irq(&pdata->lpe_audio_slock); |
1811 | 1885 | ||
1812 | pm_runtime_use_autosuspend(&pdev->dev); | 1886 | pm_runtime_use_autosuspend(&pdev->dev); |
@@ -1814,7 +1888,11 @@ static int hdmi_lpe_audio_probe(struct platform_device *pdev) | |||
1814 | pm_runtime_set_active(&pdev->dev); | 1888 | pm_runtime_set_active(&pdev->dev); |
1815 | 1889 | ||
1816 | dev_dbg(&pdev->dev, "%s: handle pending notification\n", __func__); | 1890 | dev_dbg(&pdev->dev, "%s: handle pending notification\n", __func__); |
1817 | schedule_work(&ctx->hdmi_audio_wq); | 1891 | for_each_port(card_ctx, port) { |
1892 | struct snd_intelhad *ctx = &card_ctx->pcm_ctx[port]; | ||
1893 | |||
1894 | schedule_work(&ctx->hdmi_audio_wq); | ||
1895 | } | ||
1818 | 1896 | ||
1819 | return 0; | 1897 | return 0; |
1820 | 1898 | ||
@@ -1830,9 +1908,9 @@ err: | |||
1830 | */ | 1908 | */ |
1831 | static int hdmi_lpe_audio_remove(struct platform_device *pdev) | 1909 | static int hdmi_lpe_audio_remove(struct platform_device *pdev) |
1832 | { | 1910 | { |
1833 | struct snd_intelhad *ctx = platform_get_drvdata(pdev); | 1911 | struct snd_intelhad_card *card_ctx = platform_get_drvdata(pdev); |
1834 | 1912 | ||
1835 | snd_card_free(ctx->card); | 1913 | snd_card_free(card_ctx->card); |
1836 | return 0; | 1914 | return 0; |
1837 | } | 1915 | } |
1838 | 1916 | ||
diff --git a/sound/x86/intel_hdmi_audio.h b/sound/x86/intel_hdmi_audio.h index 2d3e389f76b3..0d91bb5dbab7 100644 --- a/sound/x86/intel_hdmi_audio.h +++ b/sound/x86/intel_hdmi_audio.h | |||
@@ -32,7 +32,6 @@ | |||
32 | 32 | ||
33 | #include "intel_hdmi_lpe_audio.h" | 33 | #include "intel_hdmi_lpe_audio.h" |
34 | 34 | ||
35 | #define PCM_INDEX 0 | ||
36 | #define MAX_PB_STREAMS 1 | 35 | #define MAX_PB_STREAMS 1 |
37 | #define MAX_CAP_STREAMS 0 | 36 | #define MAX_CAP_STREAMS 0 |
38 | #define BYTES_PER_WORD 0x4 | 37 | #define BYTES_PER_WORD 0x4 |
@@ -101,7 +100,7 @@ struct pcm_stream_info { | |||
101 | * @chmap: holds channel map info | 100 | * @chmap: holds channel map info |
102 | */ | 101 | */ |
103 | struct snd_intelhad { | 102 | struct snd_intelhad { |
104 | struct snd_card *card; | 103 | struct snd_intelhad_card *card_ctx; |
105 | bool connected; | 104 | bool connected; |
106 | struct pcm_stream_info stream_info; | 105 | struct pcm_stream_info stream_info; |
107 | unsigned char eld[HDMI_MAX_ELD_BYTES]; | 106 | unsigned char eld[HDMI_MAX_ELD_BYTES]; |
@@ -112,6 +111,8 @@ struct snd_intelhad { | |||
112 | struct snd_pcm_chmap *chmap; | 111 | struct snd_pcm_chmap *chmap; |
113 | int tmds_clock_speed; | 112 | int tmds_clock_speed; |
114 | int link_rate; | 113 | int link_rate; |
114 | int port; /* fixed */ | ||
115 | int pipe; /* can change dynamically */ | ||
115 | 116 | ||
116 | /* ring buffer (BD) position index */ | 117 | /* ring buffer (BD) position index */ |
117 | unsigned int bd_head; | 118 | unsigned int bd_head; |
@@ -123,9 +124,6 @@ struct snd_intelhad { | |||
123 | unsigned int period_bytes; /* PCM period size in bytes */ | 124 | unsigned int period_bytes; /* PCM period size in bytes */ |
124 | 125 | ||
125 | /* internal stuff */ | 126 | /* internal stuff */ |
126 | int irq; | ||
127 | void __iomem *mmio_start; | ||
128 | unsigned int had_config_offset; | ||
129 | union aud_cfg aud_config; /* AUD_CONFIG reg value cache */ | 127 | union aud_cfg aud_config; /* AUD_CONFIG reg value cache */ |
130 | struct work_struct hdmi_audio_wq; | 128 | struct work_struct hdmi_audio_wq; |
131 | struct mutex mutex; /* for protecting chmap and eld */ | 129 | struct mutex mutex; /* for protecting chmap and eld */ |
@@ -133,4 +131,16 @@ struct snd_intelhad { | |||
133 | struct snd_jack *jack; | 131 | struct snd_jack *jack; |
134 | }; | 132 | }; |
135 | 133 | ||
134 | struct snd_intelhad_card { | ||
135 | struct snd_card *card; | ||
136 | struct device *dev; | ||
137 | |||
138 | /* internal stuff */ | ||
139 | int irq; | ||
140 | void __iomem *mmio_start; | ||
141 | int num_pipes; | ||
142 | int num_ports; | ||
143 | struct snd_intelhad pcm_ctx[3]; /* one for each port */ | ||
144 | }; | ||
145 | |||
136 | #endif /* _INTEL_HDMI_AUDIO_ */ | 146 | #endif /* _INTEL_HDMI_AUDIO_ */ |