Merge branch 'for-next' into for-linus

This commit is contained in:
Takashi Iwai 2017-02-20 08:52:50 +01:00
commit fc0e23fad3
83 changed files with 3399 additions and 395 deletions

View File

@ -144,6 +144,15 @@ High Definition Audio
.. kernel-doc:: include/drm/i915_component.h
:internal:
Intel HDMI LPE Audio Support
----------------------------
.. kernel-doc:: drivers/gpu/drm/i915/intel_lpe_audio.c
:doc: LPE Audio integration for HDMI or DP playback
.. kernel-doc:: drivers/gpu/drm/i915/intel_lpe_audio.c
:internal:
Panel Self Refresh PSR (PSR/SRD)
--------------------------------

View File

@ -122,6 +122,9 @@ i915-y += intel_gvt.o
include $(src)/gvt/Makefile
endif
# LPE Audio for VLV and CHT
i915-y += intel_lpe_audio.o
obj-$(CONFIG_DRM_I915) += i915.o
CFLAGS_i915_trace_points.o := -I$(src)

View File

@ -1138,7 +1138,7 @@ static void i915_driver_register(struct drm_i915_private *dev_priv)
if (IS_GEN5(dev_priv))
intel_gpu_ips_init(dev_priv);
i915_audio_component_init(dev_priv);
intel_audio_init(dev_priv);
/*
* Some ports require correctly set-up hpd registers for detection to
@ -1156,7 +1156,7 @@ static void i915_driver_register(struct drm_i915_private *dev_priv)
*/
static void i915_driver_unregister(struct drm_i915_private *dev_priv)
{
i915_audio_component_cleanup(dev_priv);
intel_audio_deinit(dev_priv);
intel_gpu_ips_teardown();
acpi_video_unregister();

View File

@ -2140,6 +2140,12 @@ struct drm_i915_private {
/* Used to save the pipe-to-encoder mapping for audio */
struct intel_encoder *av_enc_map[I915_MAX_PIPES];
/* necessary resource sharing with HDMI LPE audio driver. */
struct {
struct platform_device *platdev;
int irq;
} lpe_audio;
/*
* NOTE: This is the dri1/ums dungeon, don't add stuff here. Your patch
* will be rejected. Instead look for a better place.
@ -3387,6 +3393,14 @@ extern int i915_restore_state(struct drm_device *dev);
void i915_setup_sysfs(struct drm_i915_private *dev_priv);
void i915_teardown_sysfs(struct drm_i915_private *dev_priv);
/* intel_lpe_audio.c */
int intel_lpe_audio_init(struct drm_i915_private *dev_priv);
void intel_lpe_audio_teardown(struct drm_i915_private *dev_priv);
void intel_lpe_audio_irq_handler(struct drm_i915_private *dev_priv);
void intel_lpe_audio_notify(struct drm_i915_private *dev_priv,
void *eld, int port, int pipe, int tmds_clk_speed,
bool dp_output, int link_rate);
/* intel_i2c.c */
extern int intel_setup_gmbus(struct drm_device *dev);
extern void intel_teardown_gmbus(struct drm_device *dev);

View File

@ -1893,6 +1893,10 @@ static irqreturn_t valleyview_irq_handler(int irq, void *arg)
* signalled in iir */
valleyview_pipestat_irq_ack(dev_priv, iir, pipe_stats);
if (iir & (I915_LPE_PIPE_A_INTERRUPT |
I915_LPE_PIPE_B_INTERRUPT))
intel_lpe_audio_irq_handler(dev_priv);
/*
* VLV_IIR is single buffered, and reflects the level
* from PIPESTAT/PORT_HOTPLUG_STAT, hence clear it last.
@ -1973,6 +1977,11 @@ static irqreturn_t cherryview_irq_handler(int irq, void *arg)
* signalled in iir */
valleyview_pipestat_irq_ack(dev_priv, iir, pipe_stats);
if (iir & (I915_LPE_PIPE_A_INTERRUPT |
I915_LPE_PIPE_B_INTERRUPT |
I915_LPE_PIPE_C_INTERRUPT))
intel_lpe_audio_irq_handler(dev_priv);
/*
* VLV_IIR is single buffered, and reflects the level
* from PIPESTAT/PORT_HOTPLUG_STAT, hence clear it last.
@ -2914,6 +2923,7 @@ static void vlv_display_irq_postinstall(struct drm_i915_private *dev_priv)
u32 pipestat_mask;
u32 enable_mask;
enum pipe pipe;
u32 val;
pipestat_mask = PLANE_FLIP_DONE_INT_STATUS_VLV |
PIPE_CRC_DONE_INTERRUPT_STATUS;
@ -2930,6 +2940,12 @@ static void vlv_display_irq_postinstall(struct drm_i915_private *dev_priv)
WARN_ON(dev_priv->irq_mask != ~0);
val = (I915_LPE_PIPE_A_INTERRUPT |
I915_LPE_PIPE_B_INTERRUPT |
I915_LPE_PIPE_C_INTERRUPT);
enable_mask |= val;
dev_priv->irq_mask = ~enable_mask;
GEN5_IRQ_INIT(VLV_, dev_priv->irq_mask, enable_mask);

View File

@ -2058,6 +2058,22 @@ enum skl_disp_power_wells {
#define I915_ASLE_INTERRUPT (1<<0)
#define I915_BSD_USER_INTERRUPT (1<<25)
#define I915_HDMI_LPE_AUDIO_BASE (VLV_DISPLAY_BASE + 0x65000)
#define I915_HDMI_LPE_AUDIO_SIZE 0x1000
/* DisplayPort Audio w/ LPE */
#define VLV_AUD_CHICKEN_BIT_REG _MMIO(VLV_DISPLAY_BASE + 0x62F38)
#define VLV_CHICKEN_BIT_DBG_ENABLE (1 << 0)
#define _VLV_AUD_PORT_EN_B_DBG (VLV_DISPLAY_BASE + 0x62F20)
#define _VLV_AUD_PORT_EN_C_DBG (VLV_DISPLAY_BASE + 0x62F30)
#define _VLV_AUD_PORT_EN_D_DBG (VLV_DISPLAY_BASE + 0x62F34)
#define VLV_AUD_PORT_EN_DBG(port) _MMIO_PORT3((port) - PORT_B, \
_VLV_AUD_PORT_EN_B_DBG, \
_VLV_AUD_PORT_EN_C_DBG, \
_VLV_AUD_PORT_EN_D_DBG)
#define VLV_AMP_MUTE (1 << 1)
#define GEN6_BSD_RNCID _MMIO(0x12198)
#define GEN7_FF_THREAD_MODE _MMIO(0x20a0)

View File

@ -24,6 +24,7 @@
#include <linux/kernel.h>
#include <linux/component.h>
#include <drm/i915_component.h>
#include <drm/intel_lpe_audio.h>
#include "intel_drv.h"
#include <drm/drmP.h>
@ -623,13 +624,28 @@ void intel_audio_codec_enable(struct intel_encoder *intel_encoder,
dev_priv->av_enc_map[pipe] = intel_encoder;
mutex_unlock(&dev_priv->av_mutex);
/* audio drivers expect pipe = -1 to indicate Non-MST cases */
if (intel_encoder->type != INTEL_OUTPUT_DP_MST)
pipe = -1;
if (acomp && acomp->audio_ops && acomp->audio_ops->pin_eld_notify)
if (acomp && acomp->audio_ops && acomp->audio_ops->pin_eld_notify) {
/* audio drivers expect pipe = -1 to indicate Non-MST cases */
if (intel_encoder->type != INTEL_OUTPUT_DP_MST)
pipe = -1;
acomp->audio_ops->pin_eld_notify(acomp->audio_ops->audio_ptr,
(int) port, (int) pipe);
}
switch (intel_encoder->type) {
case INTEL_OUTPUT_HDMI:
intel_lpe_audio_notify(dev_priv, connector->eld, port, pipe,
crtc_state->port_clock,
false, 0);
break;
case INTEL_OUTPUT_DP:
intel_lpe_audio_notify(dev_priv, connector->eld, port, pipe,
adjusted_mode->crtc_clock,
true, crtc_state->port_clock);
break;
default:
break;
}
}
/**
@ -656,13 +672,15 @@ void intel_audio_codec_disable(struct intel_encoder *intel_encoder)
dev_priv->av_enc_map[pipe] = NULL;
mutex_unlock(&dev_priv->av_mutex);
/* audio drivers expect pipe = -1 to indicate Non-MST cases */
if (intel_encoder->type != INTEL_OUTPUT_DP_MST)
pipe = -1;
if (acomp && acomp->audio_ops && acomp->audio_ops->pin_eld_notify)
if (acomp && acomp->audio_ops && acomp->audio_ops->pin_eld_notify) {
/* audio drivers expect pipe = -1 to indicate Non-MST cases */
if (intel_encoder->type != INTEL_OUTPUT_DP_MST)
pipe = -1;
acomp->audio_ops->pin_eld_notify(acomp->audio_ops->audio_ptr,
(int) port, (int) pipe);
}
intel_lpe_audio_notify(dev_priv, NULL, port, pipe, 0, false, 0);
}
/**
@ -931,3 +949,28 @@ void i915_audio_component_cleanup(struct drm_i915_private *dev_priv)
component_del(dev_priv->drm.dev, &i915_audio_component_bind_ops);
dev_priv->audio_component_registered = false;
}
/**
* intel_audio_init() - Initialize the audio driver either using
* component framework or using lpe audio bridge
* @dev_priv: the i915 drm device private data
*
*/
void intel_audio_init(struct drm_i915_private *dev_priv)
{
if (intel_lpe_audio_init(dev_priv) < 0)
i915_audio_component_init(dev_priv);
}
/**
* intel_audio_deinit() - deinitialize the audio driver
* @dev_priv: the i915 drm device private data
*
*/
void intel_audio_deinit(struct drm_i915_private *dev_priv)
{
if ((dev_priv)->lpe_audio.platdev != NULL)
intel_lpe_audio_teardown(dev_priv);
else
i915_audio_component_cleanup(dev_priv);
}

View File

@ -1196,6 +1196,8 @@ void intel_audio_codec_enable(struct intel_encoder *encoder,
void intel_audio_codec_disable(struct intel_encoder *encoder);
void i915_audio_component_init(struct drm_i915_private *dev_priv);
void i915_audio_component_cleanup(struct drm_i915_private *dev_priv);
void intel_audio_init(struct drm_i915_private *dev_priv);
void intel_audio_deinit(struct drm_i915_private *dev_priv);
/* intel_display.c */
enum transcoder intel_crtc_pch_transcoder(struct intel_crtc *crtc);

View File

@ -36,6 +36,7 @@
#include <drm/drm_edid.h>
#include "intel_drv.h"
#include <drm/i915_drm.h>
#include <drm/intel_lpe_audio.h>
#include "i915_drv.h"
static struct drm_device *intel_hdmi_to_dev(struct intel_hdmi *intel_hdmi)

View File

@ -0,0 +1,392 @@
/*
* Copyright © 2016 Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*
* Authors:
* Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
* Jerome Anand <jerome.anand@intel.com>
* based on VED patches
*
*/
/**
* DOC: LPE Audio integration for HDMI or DP playback
*
* Motivation:
* Atom platforms (e.g. valleyview and cherryTrail) integrates a DMA-based
* interface as an alternative to the traditional HDaudio path. While this
* mode is unrelated to the LPE aka SST audio engine, the documentation refers
* to this mode as LPE so we keep this notation for the sake of consistency.
*
* The interface is handled by a separate standalone driver maintained in the
* ALSA subsystem for simplicity. To minimize the interaction between the two
* subsystems, a bridge is setup between the hdmi-lpe-audio and i915:
* 1. Create a platform device to share MMIO/IRQ resources
* 2. Make the platform device child of i915 device for runtime PM.
* 3. Create IRQ chip to forward the LPE audio irqs.
* the hdmi-lpe-audio driver probes the lpe audio device and creates a new
* sound card
*
* Threats:
* Due to the restriction in Linux platform device model, user need manually
* uninstall the hdmi-lpe-audio driver before uninstalling i915 module,
* otherwise we might run into use-after-free issues after i915 removes the
* platform device: even though hdmi-lpe-audio driver is released, the modules
* is still in "installed" status.
*
* Implementation:
* The MMIO/REG platform resources are created according to the registers
* specification.
* When forwarding LPE audio irqs, the flow control handler selection depends
* on the platform, for example on valleyview handle_simple_irq is enough.
*
*/
#include <linux/acpi.h>
#include <linux/device.h>
#include <linux/pci.h>
#include "i915_drv.h"
#include <linux/delay.h>
#include <drm/intel_lpe_audio.h>
#define HAS_LPE_AUDIO(dev_priv) ((dev_priv)->lpe_audio.platdev != NULL)
static struct platform_device *
lpe_audio_platdev_create(struct drm_i915_private *dev_priv)
{
int ret;
struct drm_device *dev = &dev_priv->drm;
struct platform_device_info pinfo = {};
struct resource *rsc;
struct platform_device *platdev;
struct intel_hdmi_lpe_audio_pdata *pdata;
pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
if (!pdata)
return ERR_PTR(-ENOMEM);
rsc = kcalloc(2, sizeof(*rsc), GFP_KERNEL);
if (!rsc) {
kfree(pdata);
return ERR_PTR(-ENOMEM);
}
rsc[0].start = rsc[0].end = dev_priv->lpe_audio.irq;
rsc[0].flags = IORESOURCE_IRQ;
rsc[0].name = "hdmi-lpe-audio-irq";
rsc[1].start = pci_resource_start(dev->pdev, 0) +
I915_HDMI_LPE_AUDIO_BASE;
rsc[1].end = pci_resource_start(dev->pdev, 0) +
I915_HDMI_LPE_AUDIO_BASE + I915_HDMI_LPE_AUDIO_SIZE - 1;
rsc[1].flags = IORESOURCE_MEM;
rsc[1].name = "hdmi-lpe-audio-mmio";
pinfo.parent = dev->dev;
pinfo.name = "hdmi-lpe-audio";
pinfo.id = -1;
pinfo.res = rsc;
pinfo.num_res = 2;
pinfo.data = pdata;
pinfo.size_data = sizeof(*pdata);
pinfo.dma_mask = DMA_BIT_MASK(32);
spin_lock_init(&pdata->lpe_audio_slock);
platdev = platform_device_register_full(&pinfo);
if (IS_ERR(platdev)) {
ret = PTR_ERR(platdev);
DRM_ERROR("Failed to allocate LPE audio platform device\n");
goto err;
}
kfree(rsc);
return platdev;
err:
kfree(rsc);
kfree(pdata);
return ERR_PTR(ret);
}
static void lpe_audio_platdev_destroy(struct drm_i915_private *dev_priv)
{
platform_device_unregister(dev_priv->lpe_audio.platdev);
kfree(dev_priv->lpe_audio.platdev->dev.dma_mask);
}
static void lpe_audio_irq_unmask(struct irq_data *d)
{
struct drm_i915_private *dev_priv = d->chip_data;
unsigned long irqflags;
u32 val = (I915_LPE_PIPE_A_INTERRUPT |
I915_LPE_PIPE_B_INTERRUPT);
if (IS_CHERRYVIEW(dev_priv))
val |= I915_LPE_PIPE_C_INTERRUPT;
spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
dev_priv->irq_mask &= ~val;
I915_WRITE(VLV_IIR, val);
I915_WRITE(VLV_IIR, val);
I915_WRITE(VLV_IMR, dev_priv->irq_mask);
POSTING_READ(VLV_IMR);
spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
}
static void lpe_audio_irq_mask(struct irq_data *d)
{
struct drm_i915_private *dev_priv = d->chip_data;
unsigned long irqflags;
u32 val = (I915_LPE_PIPE_A_INTERRUPT |
I915_LPE_PIPE_B_INTERRUPT);
if (IS_CHERRYVIEW(dev_priv))
val |= I915_LPE_PIPE_C_INTERRUPT;
spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
dev_priv->irq_mask |= val;
I915_WRITE(VLV_IMR, dev_priv->irq_mask);
I915_WRITE(VLV_IIR, val);
I915_WRITE(VLV_IIR, val);
POSTING_READ(VLV_IIR);
spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
}
static struct irq_chip lpe_audio_irqchip = {
.name = "hdmi_lpe_audio_irqchip",
.irq_mask = lpe_audio_irq_mask,
.irq_unmask = lpe_audio_irq_unmask,
};
static int lpe_audio_irq_init(struct drm_i915_private *dev_priv)
{
int irq = dev_priv->lpe_audio.irq;
WARN_ON(!intel_irqs_enabled(dev_priv));
irq_set_chip_and_handler_name(irq,
&lpe_audio_irqchip,
handle_simple_irq,
"hdmi_lpe_audio_irq_handler");
return irq_set_chip_data(irq, dev_priv);
}
static bool lpe_audio_detect(struct drm_i915_private *dev_priv)
{
int lpe_present = false;
if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
static const struct pci_device_id atom_hdaudio_ids[] = {
/* Baytrail */
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0f04)},
/* Braswell */
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2284)},
{}
};
if (!pci_dev_present(atom_hdaudio_ids)) {
DRM_INFO("%s\n", "HDaudio controller not detected, using LPE audio instead\n");
lpe_present = true;
}
}
return lpe_present;
}
static int lpe_audio_setup(struct drm_i915_private *dev_priv)
{
int ret;
dev_priv->lpe_audio.irq = irq_alloc_desc(0);
if (dev_priv->lpe_audio.irq < 0) {
DRM_ERROR("Failed to allocate IRQ desc: %d\n",
dev_priv->lpe_audio.irq);
ret = dev_priv->lpe_audio.irq;
goto err;
}
DRM_DEBUG("irq = %d\n", dev_priv->lpe_audio.irq);
ret = lpe_audio_irq_init(dev_priv);
if (ret) {
DRM_ERROR("Failed to initialize irqchip for lpe audio: %d\n",
ret);
goto err_free_irq;
}
dev_priv->lpe_audio.platdev = lpe_audio_platdev_create(dev_priv);
if (IS_ERR(dev_priv->lpe_audio.platdev)) {
ret = PTR_ERR(dev_priv->lpe_audio.platdev);
DRM_ERROR("Failed to create lpe audio platform device: %d\n",
ret);
goto err_free_irq;
}
/* enable chicken bit; at least this is required for Dell Wyse 3040
* with DP outputs (but only sometimes by some reason!)
*/
I915_WRITE(VLV_AUD_CHICKEN_BIT_REG, VLV_CHICKEN_BIT_DBG_ENABLE);
return 0;
err_free_irq:
irq_free_desc(dev_priv->lpe_audio.irq);
err:
dev_priv->lpe_audio.irq = -1;
dev_priv->lpe_audio.platdev = NULL;
return ret;
}
/**
* intel_lpe_audio_irq_handler() - forwards the LPE audio irq
* @dev_priv: the i915 drm device private data
*
* the LPE Audio irq is forwarded to the irq handler registered by LPE audio
* driver.
*/
void intel_lpe_audio_irq_handler(struct drm_i915_private *dev_priv)
{
int ret;
if (!HAS_LPE_AUDIO(dev_priv))
return;
ret = generic_handle_irq(dev_priv->lpe_audio.irq);
if (ret)
DRM_ERROR_RATELIMITED("error handling LPE audio irq: %d\n",
ret);
}
/**
* intel_lpe_audio_init() - detect and setup the bridge between HDMI LPE Audio
* driver and i915
* @dev_priv: the i915 drm device private data
*
* Return: 0 if successful. non-zero if detection or
* llocation/initialization fails
*/
int intel_lpe_audio_init(struct drm_i915_private *dev_priv)
{
int ret = -ENODEV;
if (lpe_audio_detect(dev_priv)) {
ret = lpe_audio_setup(dev_priv);
if (ret < 0)
DRM_ERROR("failed to setup LPE Audio bridge\n");
}
return ret;
}
/**
* intel_lpe_audio_teardown() - destroy the bridge between HDMI LPE
* audio driver and i915
* @dev_priv: the i915 drm device private data
*
* release all the resources for LPE audio <-> i915 bridge.
*/
void intel_lpe_audio_teardown(struct drm_i915_private *dev_priv)
{
struct irq_desc *desc;
if (!HAS_LPE_AUDIO(dev_priv))
return;
desc = irq_to_desc(dev_priv->lpe_audio.irq);
lpe_audio_irq_mask(&desc->irq_data);
lpe_audio_platdev_destroy(dev_priv);
irq_free_desc(dev_priv->lpe_audio.irq);
}
/**
* intel_lpe_audio_notify() - notify lpe audio event
* audio driver and i915
* @dev_priv: the i915 drm device private data
* @eld : ELD data
* @port: port id
* @tmds_clk_speed: tmds clock frequency in Hz
*
* Notify lpe audio driver of eld change.
*/
void intel_lpe_audio_notify(struct drm_i915_private *dev_priv,
void *eld, int port, int pipe, int tmds_clk_speed,
bool dp_output, int link_rate)
{
unsigned long irq_flags;
struct intel_hdmi_lpe_audio_pdata *pdata = NULL;
u32 audio_enable;
if (!HAS_LPE_AUDIO(dev_priv))
return;
pdata = dev_get_platdata(
&(dev_priv->lpe_audio.platdev->dev));
spin_lock_irqsave(&pdata->lpe_audio_slock, irq_flags);
audio_enable = I915_READ(VLV_AUD_PORT_EN_DBG(port));
if (eld != NULL) {
memcpy(pdata->eld.eld_data, eld,
HDMI_MAX_ELD_BYTES);
pdata->eld.port_id = port;
pdata->eld.pipe_id = pipe;
pdata->hdmi_connected = true;
pdata->dp_output = dp_output;
if (tmds_clk_speed)
pdata->tmds_clock_speed = tmds_clk_speed;
if (link_rate)
pdata->link_rate = link_rate;
/* Unmute the amp for both DP and HDMI */
I915_WRITE(VLV_AUD_PORT_EN_DBG(port),
audio_enable & ~VLV_AMP_MUTE);
} else {
memset(pdata->eld.eld_data, 0,
HDMI_MAX_ELD_BYTES);
pdata->hdmi_connected = false;
pdata->dp_output = false;
/* Mute the amp for both DP and HDMI */
I915_WRITE(VLV_AUD_PORT_EN_DBG(port),
audio_enable | VLV_AMP_MUTE);
}
if (pdata->notify_audio_lpe)
pdata->notify_audio_lpe(dev_priv->lpe_audio.platdev);
else
pdata->notify_pending = true;
spin_unlock_irqrestore(&pdata->lpe_audio_slock,
irq_flags);
}

View File

@ -0,0 +1,51 @@
/*
* Copyright © 2016 Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#ifndef _INTEL_LPE_AUDIO_H_
#define _INTEL_LPE_AUDIO_H_
#include <linux/types.h>
#include <linux/spinlock_types.h>
struct platform_device;
#define HDMI_MAX_ELD_BYTES 128
struct intel_hdmi_lpe_audio_eld {
int port_id;
int pipe_id;
unsigned char eld_data[HDMI_MAX_ELD_BYTES];
};
struct intel_hdmi_lpe_audio_pdata {
bool notify_pending;
int tmds_clock_speed;
bool hdmi_connected;
bool dp_output;
int link_rate;
struct intel_hdmi_lpe_audio_eld eld;
void (*notify_audio_lpe)(struct platform_device *pdev);
spinlock_t lpe_audio_slock;
};
#endif /* _I915_LPE_AUDIO_H_ */

View File

@ -570,6 +570,15 @@ int snd_pcm_stop_xrun(struct snd_pcm_substream *substream);
#ifdef CONFIG_PM
int snd_pcm_suspend(struct snd_pcm_substream *substream);
int snd_pcm_suspend_all(struct snd_pcm *pcm);
#else
static inline int snd_pcm_suspend(struct snd_pcm_substream *substream)
{
return 0;
}
static inline int snd_pcm_suspend_all(struct snd_pcm *pcm)
{
return 0;
}
#endif
int snd_pcm_kernel_ioctl(struct snd_pcm_substream *substream, unsigned int cmd, void *arg);
int snd_pcm_open_substream(struct snd_pcm *pcm, int stream, struct file *file,

View File

@ -103,7 +103,7 @@ struct snd_rawmidi_substream {
struct snd_rawmidi_runtime *runtime;
struct pid *pid;
/* hardware layer */
struct snd_rawmidi_ops *ops;
const struct snd_rawmidi_ops *ops;
};
struct snd_rawmidi_file {
@ -155,7 +155,7 @@ int snd_rawmidi_new(struct snd_card *card, char *id, int device,
int output_count, int input_count,
struct snd_rawmidi **rmidi);
void snd_rawmidi_set_ops(struct snd_rawmidi *rmidi, int stream,
struct snd_rawmidi_ops *ops);
const struct snd_rawmidi_ops *ops);
/* callbacks */

View File

@ -37,8 +37,8 @@ struct _snd_wavefront_midi {
#define MPU_ACK 0xFE
#define UART_MODE_ON 0x3F
extern struct snd_rawmidi_ops snd_wavefront_midi_output;
extern struct snd_rawmidi_ops snd_wavefront_midi_input;
extern const struct snd_rawmidi_ops snd_wavefront_midi_output;
extern const struct snd_rawmidi_ops snd_wavefront_midi_input;
extern void snd_wavefront_midi_enable_virtual (snd_wavefront_card_t *);
extern void snd_wavefront_midi_disable_virtual (snd_wavefront_card_t *);

View File

@ -108,6 +108,8 @@ source "sound/parisc/Kconfig"
source "sound/soc/Kconfig"
source "sound/x86/Kconfig"
endif # SND
menuconfig SOUND_PRIME

View File

@ -5,7 +5,7 @@ obj-$(CONFIG_SOUND) += soundcore.o
obj-$(CONFIG_SOUND_PRIME) += oss/
obj-$(CONFIG_DMASOUND) += oss/
obj-$(CONFIG_SND) += core/ i2c/ drivers/ isa/ pci/ ppc/ arm/ sh/ synth/ usb/ \
firewire/ sparc/ spi/ parisc/ pcmcia/ mips/ soc/ atmel/ hda/
firewire/ sparc/ spi/ parisc/ pcmcia/ mips/ soc/ atmel/ hda/ x86/
obj-$(CONFIG_SND_AOA) += aoa/
# This one must be compilable even if sound is configured out

View File

@ -1749,7 +1749,7 @@ static int snd_rawmidi_dev_disconnect(struct snd_device *device)
* Sets the rawmidi operators for the given stream direction.
*/
void snd_rawmidi_set_ops(struct snd_rawmidi *rmidi, int stream,
struct snd_rawmidi_ops *ops)
const struct snd_rawmidi_ops *ops)
{
struct snd_rawmidi_substream *substream;

View File

@ -349,13 +349,13 @@ static int snd_virmidi_unuse(void *private_data,
* Register functions
*/
static struct snd_rawmidi_ops snd_virmidi_input_ops = {
static const struct snd_rawmidi_ops snd_virmidi_input_ops = {
.open = snd_virmidi_input_open,
.close = snd_virmidi_input_close,
.trigger = snd_virmidi_input_trigger,
};
static struct snd_rawmidi_ops snd_virmidi_output_ops = {
static const struct snd_rawmidi_ops snd_virmidi_output_ops = {
.open = snd_virmidi_output_open,
.close = snd_virmidi_output_close,
.trigger = snd_virmidi_output_trigger,

View File

@ -481,14 +481,14 @@ snd_mpu401_uart_output_trigger(struct snd_rawmidi_substream *substream, int up)
*/
static struct snd_rawmidi_ops snd_mpu401_uart_output =
static const struct snd_rawmidi_ops snd_mpu401_uart_output =
{
.open = snd_mpu401_uart_output_open,
.close = snd_mpu401_uart_output_close,
.trigger = snd_mpu401_uart_output_trigger,
};
static struct snd_rawmidi_ops snd_mpu401_uart_input =
static const struct snd_rawmidi_ops snd_mpu401_uart_input =
{
.open = snd_mpu401_uart_input_open,
.close = snd_mpu401_uart_input_close,

View File

@ -600,13 +600,13 @@ static int snd_mtpav_get_ISA(struct mtpav *mcard)
/*
*/
static struct snd_rawmidi_ops snd_mtpav_output = {
static const struct snd_rawmidi_ops snd_mtpav_output = {
.open = snd_mtpav_output_open,
.close = snd_mtpav_output_close,
.trigger = snd_mtpav_output_trigger,
};
static struct snd_rawmidi_ops snd_mtpav_input = {
static const struct snd_rawmidi_ops snd_mtpav_input = {
.open = snd_mtpav_input_open,
.close = snd_mtpav_input_close,
.trigger = snd_mtpav_input_trigger,

View File

@ -749,13 +749,13 @@ static void snd_mts64_rawmidi_input_trigger(struct snd_rawmidi_substream *substr
spin_unlock_irqrestore(&mts->lock, flags);
}
static struct snd_rawmidi_ops snd_mts64_rawmidi_output_ops = {
static const struct snd_rawmidi_ops snd_mts64_rawmidi_output_ops = {
.open = snd_mts64_rawmidi_open,
.close = snd_mts64_rawmidi_close,
.trigger = snd_mts64_rawmidi_output_trigger
};
static struct snd_rawmidi_ops snd_mts64_rawmidi_input_ops = {
static const struct snd_rawmidi_ops snd_mts64_rawmidi_input_ops = {
.open = snd_mts64_rawmidi_open,
.close = snd_mts64_rawmidi_close,
.trigger = snd_mts64_rawmidi_input_trigger

View File

@ -546,13 +546,13 @@ static void snd_portman_midi_output_trigger(struct snd_rawmidi_substream *substr
spin_unlock_irqrestore(&pm->reg_lock, flags);
}
static struct snd_rawmidi_ops snd_portman_midi_output = {
static const struct snd_rawmidi_ops snd_portman_midi_output = {
.open = snd_portman_midi_open,
.close = snd_portman_midi_close,
.trigger = snd_portman_midi_output_trigger,
};
static struct snd_rawmidi_ops snd_portman_midi_input = {
static const struct snd_rawmidi_ops snd_portman_midi_input = {
.open = snd_portman_midi_open,
.close = snd_portman_midi_close,
.trigger = snd_portman_midi_input_trigger,

View File

@ -752,14 +752,14 @@ static void snd_uart16550_output_trigger(struct snd_rawmidi_substream *substream
snd_uart16550_output_write(substream);
}
static struct snd_rawmidi_ops snd_uart16550_output =
static const struct snd_rawmidi_ops snd_uart16550_output =
{
.open = snd_uart16550_output_open,
.close = snd_uart16550_output_close,
.trigger = snd_uart16550_output_trigger,
};
static struct snd_rawmidi_ops snd_uart16550_input =
static const struct snd_rawmidi_ops snd_uart16550_input =
{
.open = snd_uart16550_input_open,
.close = snd_uart16550_input_close,

View File

@ -1015,7 +1015,7 @@ static void vx_pcm_capture_update(struct vx_core *chip, struct snd_pcm_substream
int size, space, count;
struct snd_pcm_runtime *runtime = subs->runtime;
if (! pipe->prepared || (chip->chip_status & VX_STAT_IS_STALE))
if (!pipe->running || (chip->chip_status & VX_STAT_IS_STALE))
return;
size = runtime->buffer_size - snd_pcm_capture_avail(runtime);
@ -1048,8 +1048,10 @@ static void vx_pcm_capture_update(struct vx_core *chip, struct snd_pcm_substream
/* ok, let's accelerate! */
int align = pipe->align * 3;
space = (count / align) * align;
vx_pseudo_dma_read(chip, runtime, pipe, space);
count -= space;
if (space > 0) {
vx_pseudo_dma_read(chip, runtime, pipe, space);
count -= space;
}
}
/* read the rest of bytes */
while (count > 0) {

View File

@ -34,6 +34,7 @@ config SND_OXFW
* LaCie Firewire Speakers
* Behringer F-Control Audio 202
* Mackie(Loud) Onyx-i series (former models)
* Mackie(Loud) Onyx 1640i (former model)
* Mackie(Loud) Onyx Satellite
* Mackie(Loud) Tapco Link.Firewire
* Mackie(Loud) d.2 pro/d.4 pro

View File

@ -172,16 +172,15 @@ hwdep_compat_ioctl(struct snd_hwdep *hwdep, struct file *file,
#define hwdep_compat_ioctl NULL
#endif
static const struct snd_hwdep_ops hwdep_ops = {
.read = hwdep_read,
.release = hwdep_release,
.poll = hwdep_poll,
.ioctl = hwdep_ioctl,
.ioctl_compat = hwdep_compat_ioctl,
};
int snd_bebob_create_hwdep_device(struct snd_bebob *bebob)
{
static const struct snd_hwdep_ops ops = {
.read = hwdep_read,
.release = hwdep_release,
.poll = hwdep_poll,
.ioctl = hwdep_ioctl,
.ioctl_compat = hwdep_compat_ioctl,
};
struct snd_hwdep *hwdep;
int err;
@ -190,7 +189,7 @@ int snd_bebob_create_hwdep_device(struct snd_bebob *bebob)
goto end;
strcpy(hwdep->name, "BeBoB");
hwdep->iface = SNDRV_HWDEP_IFACE_FW_BEBOB;
hwdep->ops = hwdep_ops;
hwdep->ops = ops;
hwdep->private_data = bebob;
hwdep->exclusive = true;
end:

View File

@ -106,18 +106,6 @@ static void midi_playback_trigger(struct snd_rawmidi_substream *substrm, int up)
spin_unlock_irqrestore(&bebob->lock, flags);
}
static struct snd_rawmidi_ops midi_capture_ops = {
.open = midi_capture_open,
.close = midi_capture_close,
.trigger = midi_capture_trigger,
};
static struct snd_rawmidi_ops midi_playback_ops = {
.open = midi_playback_open,
.close = midi_playback_close,
.trigger = midi_playback_trigger,
};
static void set_midi_substream_names(struct snd_bebob *bebob,
struct snd_rawmidi_str *str)
{
@ -132,6 +120,16 @@ static void set_midi_substream_names(struct snd_bebob *bebob,
int snd_bebob_create_midi_devices(struct snd_bebob *bebob)
{
static const struct snd_rawmidi_ops capture_ops = {
.open = midi_capture_open,
.close = midi_capture_close,
.trigger = midi_capture_trigger,
};
static const struct snd_rawmidi_ops playback_ops = {
.open = midi_playback_open,
.close = midi_playback_close,
.trigger = midi_playback_trigger,
};
struct snd_rawmidi *rmidi;
struct snd_rawmidi_str *str;
int err;
@ -151,7 +149,7 @@ int snd_bebob_create_midi_devices(struct snd_bebob *bebob)
rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT;
snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT,
&midi_capture_ops);
&capture_ops);
str = &rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT];
@ -162,7 +160,7 @@ int snd_bebob_create_midi_devices(struct snd_bebob *bebob)
rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT;
snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT,
&midi_playback_ops);
&playback_ops);
str = &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT];

View File

@ -359,32 +359,31 @@ pcm_playback_pointer(struct snd_pcm_substream *sbstrm)
return amdtp_stream_pcm_pointer(&bebob->rx_stream);
}
static const struct snd_pcm_ops pcm_capture_ops = {
.open = pcm_open,
.close = pcm_close,
.ioctl = snd_pcm_lib_ioctl,
.hw_params = pcm_capture_hw_params,
.hw_free = pcm_capture_hw_free,
.prepare = pcm_capture_prepare,
.trigger = pcm_capture_trigger,
.pointer = pcm_capture_pointer,
.page = snd_pcm_lib_get_vmalloc_page,
};
static const struct snd_pcm_ops pcm_playback_ops = {
.open = pcm_open,
.close = pcm_close,
.ioctl = snd_pcm_lib_ioctl,
.hw_params = pcm_playback_hw_params,
.hw_free = pcm_playback_hw_free,
.prepare = pcm_playback_prepare,
.trigger = pcm_playback_trigger,
.pointer = pcm_playback_pointer,
.page = snd_pcm_lib_get_vmalloc_page,
.mmap = snd_pcm_lib_mmap_vmalloc,
};
int snd_bebob_create_pcm_devices(struct snd_bebob *bebob)
{
static const struct snd_pcm_ops capture_ops = {
.open = pcm_open,
.close = pcm_close,
.ioctl = snd_pcm_lib_ioctl,
.hw_params = pcm_capture_hw_params,
.hw_free = pcm_capture_hw_free,
.prepare = pcm_capture_prepare,
.trigger = pcm_capture_trigger,
.pointer = pcm_capture_pointer,
.page = snd_pcm_lib_get_vmalloc_page,
};
static const struct snd_pcm_ops playback_ops = {
.open = pcm_open,
.close = pcm_close,
.ioctl = snd_pcm_lib_ioctl,
.hw_params = pcm_playback_hw_params,
.hw_free = pcm_playback_hw_free,
.prepare = pcm_playback_prepare,
.trigger = pcm_playback_trigger,
.pointer = pcm_playback_pointer,
.page = snd_pcm_lib_get_vmalloc_page,
.mmap = snd_pcm_lib_mmap_vmalloc,
};
struct snd_pcm *pcm;
int err;
@ -395,8 +394,8 @@ int snd_bebob_create_pcm_devices(struct snd_bebob *bebob)
pcm->private_data = bebob;
snprintf(pcm->name, sizeof(pcm->name),
"%s PCM", bebob->card->shortname);
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &pcm_playback_ops);
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &pcm_capture_ops);
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &playback_ops);
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &capture_ops);
end:
return err;
}

View File

@ -251,6 +251,7 @@
/*
* The speed at which the packets are sent, SCODE_100-_400; read/write.
* SCODE_800 is only available in Dice III.
*/
#define TX_SPEED 0x014

View File

@ -78,18 +78,6 @@ static void midi_playback_trigger(struct snd_rawmidi_substream *substrm, int up)
spin_unlock_irqrestore(&dice->lock, flags);
}
static struct snd_rawmidi_ops capture_ops = {
.open = midi_open,
.close = midi_close,
.trigger = midi_capture_trigger,
};
static struct snd_rawmidi_ops playback_ops = {
.open = midi_open,
.close = midi_close,
.trigger = midi_playback_trigger,
};
static void set_midi_substream_names(struct snd_dice *dice,
struct snd_rawmidi_str *str)
{
@ -103,6 +91,16 @@ static void set_midi_substream_names(struct snd_dice *dice,
int snd_dice_create_midi(struct snd_dice *dice)
{
static const struct snd_rawmidi_ops capture_ops = {
.open = midi_open,
.close = midi_close,
.trigger = midi_capture_trigger,
};
static const struct snd_rawmidi_ops playback_ops = {
.open = midi_open,
.close = midi_close,
.trigger = midi_playback_trigger,
};
__be32 reg;
struct snd_rawmidi *rmidi;
struct snd_rawmidi_str *str;

View File

@ -195,6 +195,7 @@ static int start_streams(struct snd_dice *dice, enum amdtp_stream_direction dir,
unsigned int i, pcm_chs, midi_ports;
struct amdtp_stream *streams;
struct fw_iso_resources *resources;
struct fw_device *fw_dev = fw_parent_device(dice->unit);
int err = 0;
if (dir == AMDTP_IN_STREAM) {
@ -237,8 +238,17 @@ static int start_streams(struct snd_dice *dice, enum amdtp_stream_direction dir,
if (err < 0)
return err;
if (dir == AMDTP_IN_STREAM) {
reg[0] = cpu_to_be32(fw_dev->max_speed);
err = snd_dice_transaction_write_tx(dice,
params->size * i + TX_SPEED,
reg, sizeof(reg[0]));
if (err < 0)
return err;
}
err = amdtp_stream_start(&streams[i], resources[i].channel,
fw_parent_device(dice->unit)->max_speed);
fw_dev->max_speed);
if (err < 0)
return err;
}

View File

@ -173,16 +173,15 @@ static int hwdep_compat_ioctl(struct snd_hwdep *hwdep, struct file *file,
#define hwdep_compat_ioctl NULL
#endif
static const struct snd_hwdep_ops hwdep_ops = {
.read = hwdep_read,
.release = hwdep_release,
.poll = hwdep_poll,
.ioctl = hwdep_ioctl,
.ioctl_compat = hwdep_compat_ioctl,
};
int snd_dg00x_create_hwdep_device(struct snd_dg00x *dg00x)
{
static const struct snd_hwdep_ops ops = {
.read = hwdep_read,
.release = hwdep_release,
.poll = hwdep_poll,
.ioctl = hwdep_ioctl,
.ioctl_compat = hwdep_compat_ioctl,
};
struct snd_hwdep *hwdep;
int err;
@ -192,7 +191,7 @@ int snd_dg00x_create_hwdep_device(struct snd_dg00x *dg00x)
strcpy(hwdep->name, "Digi00x");
hwdep->iface = SNDRV_HWDEP_IFACE_FW_DIGI00X;
hwdep->ops = hwdep_ops;
hwdep->ops = ops;
hwdep->private_data = dg00x;
hwdep->exclusive = true;

View File

@ -76,18 +76,6 @@ static void midi_phys_playback_trigger(struct snd_rawmidi_substream *substream,
spin_unlock_irqrestore(&dg00x->lock, flags);
}
static struct snd_rawmidi_ops midi_phys_capture_ops = {
.open = midi_phys_open,
.close = midi_phys_close,
.trigger = midi_phys_capture_trigger,
};
static struct snd_rawmidi_ops midi_phys_playback_ops = {
.open = midi_phys_open,
.close = midi_phys_close,
.trigger = midi_phys_playback_trigger,
};
static int midi_ctl_open(struct snd_rawmidi_substream *substream)
{
/* Do nothing. */
@ -139,18 +127,6 @@ static void midi_ctl_playback_trigger(struct snd_rawmidi_substream *substream,
spin_unlock_irqrestore(&dg00x->lock, flags);
}
static struct snd_rawmidi_ops midi_ctl_capture_ops = {
.open = midi_ctl_open,
.close = midi_ctl_capture_close,
.trigger = midi_ctl_capture_trigger,
};
static struct snd_rawmidi_ops midi_ctl_playback_ops = {
.open = midi_ctl_open,
.close = midi_ctl_playback_close,
.trigger = midi_ctl_playback_trigger,
};
static void set_midi_substream_names(struct snd_dg00x *dg00x,
struct snd_rawmidi_str *str,
bool is_ctl)
@ -172,6 +148,26 @@ static void set_midi_substream_names(struct snd_dg00x *dg00x,
int snd_dg00x_create_midi_devices(struct snd_dg00x *dg00x)
{
static const struct snd_rawmidi_ops phys_capture_ops = {
.open = midi_phys_open,
.close = midi_phys_close,
.trigger = midi_phys_capture_trigger,
};
static const struct snd_rawmidi_ops phys_playback_ops = {
.open = midi_phys_open,
.close = midi_phys_close,
.trigger = midi_phys_playback_trigger,
};
static const struct snd_rawmidi_ops ctl_capture_ops = {
.open = midi_ctl_open,
.close = midi_ctl_capture_close,
.trigger = midi_ctl_capture_trigger,
};
static const struct snd_rawmidi_ops ctl_playback_ops = {
.open = midi_ctl_open,
.close = midi_ctl_playback_close,
.trigger = midi_ctl_playback_trigger,
};
struct snd_rawmidi *rmidi[2];
struct snd_rawmidi_str *str;
unsigned int i;
@ -187,9 +183,9 @@ int snd_dg00x_create_midi_devices(struct snd_dg00x *dg00x)
"%s MIDI", dg00x->card->shortname);
snd_rawmidi_set_ops(rmidi[0], SNDRV_RAWMIDI_STREAM_INPUT,
&midi_phys_capture_ops);
&phys_capture_ops);
snd_rawmidi_set_ops(rmidi[0], SNDRV_RAWMIDI_STREAM_OUTPUT,
&midi_phys_playback_ops);
&phys_playback_ops);
/* Add a pair of control midi ports. */
err = snd_rawmidi_new(dg00x->card, dg00x->card->driver, 1,
@ -201,9 +197,9 @@ int snd_dg00x_create_midi_devices(struct snd_dg00x *dg00x)
"%s control", dg00x->card->shortname);
snd_rawmidi_set_ops(rmidi[1], SNDRV_RAWMIDI_STREAM_INPUT,
&midi_ctl_capture_ops);
&ctl_capture_ops);
snd_rawmidi_set_ops(rmidi[1], SNDRV_RAWMIDI_STREAM_OUTPUT,
&midi_ctl_playback_ops);
&ctl_playback_ops);
for (i = 0; i < ARRAY_SIZE(rmidi); i++) {
rmidi[i]->private_data = dg00x;

View File

@ -329,33 +329,31 @@ static snd_pcm_uframes_t pcm_playback_pointer(struct snd_pcm_substream *sbstrm)
return amdtp_stream_pcm_pointer(&dg00x->rx_stream);
}
static const struct snd_pcm_ops pcm_capture_ops = {
.open = pcm_open,
.close = pcm_close,
.ioctl = snd_pcm_lib_ioctl,
.hw_params = pcm_capture_hw_params,
.hw_free = pcm_capture_hw_free,
.prepare = pcm_capture_prepare,
.trigger = pcm_capture_trigger,
.pointer = pcm_capture_pointer,
.page = snd_pcm_lib_get_vmalloc_page,
};
static const struct snd_pcm_ops pcm_playback_ops = {
.open = pcm_open,
.close = pcm_close,
.ioctl = snd_pcm_lib_ioctl,
.hw_params = pcm_playback_hw_params,
.hw_free = pcm_playback_hw_free,
.prepare = pcm_playback_prepare,
.trigger = pcm_playback_trigger,
.pointer = pcm_playback_pointer,
.page = snd_pcm_lib_get_vmalloc_page,
.mmap = snd_pcm_lib_mmap_vmalloc,
};
int snd_dg00x_create_pcm_devices(struct snd_dg00x *dg00x)
{
static const struct snd_pcm_ops capture_ops = {
.open = pcm_open,
.close = pcm_close,
.ioctl = snd_pcm_lib_ioctl,
.hw_params = pcm_capture_hw_params,
.hw_free = pcm_capture_hw_free,
.prepare = pcm_capture_prepare,
.trigger = pcm_capture_trigger,
.pointer = pcm_capture_pointer,
.page = snd_pcm_lib_get_vmalloc_page,
};
static const struct snd_pcm_ops playback_ops = {
.open = pcm_open,
.close = pcm_close,
.ioctl = snd_pcm_lib_ioctl,
.hw_params = pcm_playback_hw_params,
.hw_free = pcm_playback_hw_free,
.prepare = pcm_playback_prepare,
.trigger = pcm_playback_trigger,
.pointer = pcm_playback_pointer,
.page = snd_pcm_lib_get_vmalloc_page,
.mmap = snd_pcm_lib_mmap_vmalloc,
};
struct snd_pcm *pcm;
int err;
@ -366,8 +364,8 @@ int snd_dg00x_create_pcm_devices(struct snd_dg00x *dg00x)
pcm->private_data = dg00x;
snprintf(pcm->name, sizeof(pcm->name),
"%s PCM", dg00x->card->shortname);
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &pcm_playback_ops);
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &pcm_capture_ops);
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &playback_ops);
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &capture_ops);
return 0;
}

View File

@ -303,17 +303,16 @@ hwdep_compat_ioctl(struct snd_hwdep *hwdep, struct file *file,
#define hwdep_compat_ioctl NULL
#endif
static const struct snd_hwdep_ops hwdep_ops = {
.read = hwdep_read,
.write = hwdep_write,
.release = hwdep_release,
.poll = hwdep_poll,
.ioctl = hwdep_ioctl,
.ioctl_compat = hwdep_compat_ioctl,
};
int snd_efw_create_hwdep_device(struct snd_efw *efw)
{
static const struct snd_hwdep_ops ops = {
.read = hwdep_read,
.write = hwdep_write,
.release = hwdep_release,
.poll = hwdep_poll,
.ioctl = hwdep_ioctl,
.ioctl_compat = hwdep_compat_ioctl,
};
struct snd_hwdep *hwdep;
int err;
@ -322,7 +321,7 @@ int snd_efw_create_hwdep_device(struct snd_efw *efw)
goto end;
strcpy(hwdep->name, "Fireworks");
hwdep->iface = SNDRV_HWDEP_IFACE_FW_FIREWORKS;
hwdep->ops = hwdep_ops;
hwdep->ops = ops;
hwdep->private_data = efw;
hwdep->exclusive = true;
end:

View File

@ -107,18 +107,6 @@ static void midi_playback_trigger(struct snd_rawmidi_substream *substrm, int up)
spin_unlock_irqrestore(&efw->lock, flags);
}
static struct snd_rawmidi_ops midi_capture_ops = {
.open = midi_capture_open,
.close = midi_capture_close,
.trigger = midi_capture_trigger,
};
static struct snd_rawmidi_ops midi_playback_ops = {
.open = midi_playback_open,
.close = midi_playback_close,
.trigger = midi_playback_trigger,
};
static void set_midi_substream_names(struct snd_efw *efw,
struct snd_rawmidi_str *str)
{
@ -132,6 +120,16 @@ static void set_midi_substream_names(struct snd_efw *efw,
int snd_efw_create_midi_devices(struct snd_efw *efw)
{
static const struct snd_rawmidi_ops capture_ops = {
.open = midi_capture_open,
.close = midi_capture_close,
.trigger = midi_capture_trigger,
};
static const struct snd_rawmidi_ops playback_ops = {
.open = midi_playback_open,
.close = midi_playback_close,
.trigger = midi_playback_trigger,
};
struct snd_rawmidi *rmidi;
struct snd_rawmidi_str *str;
int err;
@ -151,7 +149,7 @@ int snd_efw_create_midi_devices(struct snd_efw *efw)
rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT;
snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT,
&midi_capture_ops);
&capture_ops);
str = &rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT];
@ -162,7 +160,7 @@ int snd_efw_create_midi_devices(struct snd_efw *efw)
rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT;
snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT,
&midi_playback_ops);
&playback_ops);
str = &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT];

View File

@ -383,33 +383,31 @@ static snd_pcm_uframes_t pcm_playback_pointer(struct snd_pcm_substream *sbstrm)
return amdtp_stream_pcm_pointer(&efw->rx_stream);
}
static const struct snd_pcm_ops pcm_capture_ops = {
.open = pcm_open,
.close = pcm_close,
.ioctl = snd_pcm_lib_ioctl,
.hw_params = pcm_capture_hw_params,
.hw_free = pcm_capture_hw_free,
.prepare = pcm_capture_prepare,
.trigger = pcm_capture_trigger,
.pointer = pcm_capture_pointer,
.page = snd_pcm_lib_get_vmalloc_page,
};
static const struct snd_pcm_ops pcm_playback_ops = {
.open = pcm_open,
.close = pcm_close,
.ioctl = snd_pcm_lib_ioctl,
.hw_params = pcm_playback_hw_params,
.hw_free = pcm_playback_hw_free,
.prepare = pcm_playback_prepare,
.trigger = pcm_playback_trigger,
.pointer = pcm_playback_pointer,
.page = snd_pcm_lib_get_vmalloc_page,
.mmap = snd_pcm_lib_mmap_vmalloc,
};
int snd_efw_create_pcm_devices(struct snd_efw *efw)
{
static const struct snd_pcm_ops capture_ops = {
.open = pcm_open,
.close = pcm_close,
.ioctl = snd_pcm_lib_ioctl,
.hw_params = pcm_capture_hw_params,
.hw_free = pcm_capture_hw_free,
.prepare = pcm_capture_prepare,
.trigger = pcm_capture_trigger,
.pointer = pcm_capture_pointer,
.page = snd_pcm_lib_get_vmalloc_page,
};
static const struct snd_pcm_ops playback_ops = {
.open = pcm_open,
.close = pcm_close,
.ioctl = snd_pcm_lib_ioctl,
.hw_params = pcm_playback_hw_params,
.hw_free = pcm_playback_hw_free,
.prepare = pcm_playback_prepare,
.trigger = pcm_playback_trigger,
.pointer = pcm_playback_pointer,
.page = snd_pcm_lib_get_vmalloc_page,
.mmap = snd_pcm_lib_mmap_vmalloc,
};
struct snd_pcm *pcm;
int err;
@ -419,8 +417,8 @@ int snd_efw_create_pcm_devices(struct snd_efw *efw)
pcm->private_data = efw;
snprintf(pcm->name, sizeof(pcm->name), "%s PCM", efw->card->shortname);
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &pcm_playback_ops);
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &pcm_capture_ops);
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &playback_ops);
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &capture_ops);
end:
return err;
}

View File

@ -116,18 +116,6 @@ static void midi_playback_trigger(struct snd_rawmidi_substream *substrm, int up)
spin_unlock_irqrestore(&oxfw->lock, flags);
}
static struct snd_rawmidi_ops midi_capture_ops = {
.open = midi_capture_open,
.close = midi_capture_close,
.trigger = midi_capture_trigger,
};
static struct snd_rawmidi_ops midi_playback_ops = {
.open = midi_playback_open,
.close = midi_playback_close,
.trigger = midi_playback_trigger,
};
static void set_midi_substream_names(struct snd_oxfw *oxfw,
struct snd_rawmidi_str *str)
{
@ -142,6 +130,16 @@ static void set_midi_substream_names(struct snd_oxfw *oxfw,
int snd_oxfw_create_midi(struct snd_oxfw *oxfw)
{
static const struct snd_rawmidi_ops capture_ops = {
.open = midi_capture_open,
.close = midi_capture_close,
.trigger = midi_capture_trigger,
};
static const struct snd_rawmidi_ops playback_ops = {
.open = midi_playback_open,
.close = midi_playback_close,
.trigger = midi_playback_trigger,
};
struct snd_rawmidi *rmidi;
struct snd_rawmidi_str *str;
int err;
@ -164,7 +162,7 @@ int snd_oxfw_create_midi(struct snd_oxfw *oxfw)
rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT;
snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT,
&midi_capture_ops);
&capture_ops);
str = &rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT];
@ -175,7 +173,7 @@ int snd_oxfw_create_midi(struct snd_oxfw *oxfw)
rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT;
snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT,
&midi_playback_ops);
&playback_ops);
str = &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT];

View File

@ -297,7 +297,7 @@ static void midi_capture_trigger(struct snd_rawmidi_substream *stream, int up)
}
}
static struct snd_rawmidi_ops midi_capture_ops = {
static const struct snd_rawmidi_ops midi_capture_ops = {
.open = midi_capture_open,
.close = midi_capture_close,
.trigger = midi_capture_trigger,
@ -338,12 +338,6 @@ static void midi_playback_drain(struct snd_rawmidi_substream *stream)
wait_event(scs->idle_wait, scs->output_idle);
}
static struct snd_rawmidi_ops midi_playback_ops = {
.open = midi_playback_open,
.close = midi_playback_close,
.trigger = midi_playback_trigger,
.drain = midi_playback_drain,
};
static int register_address(struct snd_oxfw *oxfw)
{
struct fw_scs1x *scs = oxfw->spec;
@ -369,6 +363,12 @@ void snd_oxfw_scs1x_update(struct snd_oxfw *oxfw)
int snd_oxfw_scs1x_add(struct snd_oxfw *oxfw)
{
static const struct snd_rawmidi_ops midi_playback_ops = {
.open = midi_playback_open,
.close = midi_playback_close,
.trigger = midi_playback_trigger,
.drain = midi_playback_drain,
};
struct snd_rawmidi *rmidi;
struct fw_scs1x *scs;
int err;

View File

@ -43,6 +43,7 @@ static bool detect_loud_models(struct fw_unit *unit)
const char *const models[] = {
"Onyxi",
"Onyx-i",
"Onyx 1640i",
"d.Pro",
"Mackie Onyx Satellite",
"Tapco LINK.firewire 4x6",

View File

@ -163,16 +163,15 @@ static int hwdep_compat_ioctl(struct snd_hwdep *hwdep, struct file *file,
#define hwdep_compat_ioctl NULL
#endif
static const struct snd_hwdep_ops hwdep_ops = {
.read = hwdep_read,
.release = hwdep_release,
.poll = hwdep_poll,
.ioctl = hwdep_ioctl,
.ioctl_compat = hwdep_compat_ioctl,
};
int snd_tscm_create_hwdep_device(struct snd_tscm *tscm)
{
static const struct snd_hwdep_ops ops = {
.read = hwdep_read,
.release = hwdep_release,
.poll = hwdep_poll,
.ioctl = hwdep_ioctl,
.ioctl_compat = hwdep_compat_ioctl,
};
struct snd_hwdep *hwdep;
int err;
@ -182,7 +181,7 @@ int snd_tscm_create_hwdep_device(struct snd_tscm *tscm)
strcpy(hwdep->name, "Tascam");
hwdep->iface = SNDRV_HWDEP_IFACE_FW_TASCAM;
hwdep->ops = hwdep_ops;
hwdep->ops = ops;
hwdep->private_data = tscm;
hwdep->exclusive = true;

View File

@ -68,20 +68,18 @@ static void midi_playback_trigger(struct snd_rawmidi_substream *substrm, int up)
spin_unlock_irqrestore(&tscm->lock, flags);
}
static struct snd_rawmidi_ops midi_capture_ops = {
.open = midi_capture_open,
.close = midi_capture_close,
.trigger = midi_capture_trigger,
};
static struct snd_rawmidi_ops midi_playback_ops = {
.open = midi_playback_open,
.close = midi_playback_close,
.trigger = midi_playback_trigger,
};
int snd_tscm_create_midi_devices(struct snd_tscm *tscm)
{
static const struct snd_rawmidi_ops capture_ops = {
.open = midi_capture_open,
.close = midi_capture_close,
.trigger = midi_capture_trigger,
};
static const struct snd_rawmidi_ops playback_ops = {
.open = midi_playback_open,
.close = midi_playback_close,
.trigger = midi_playback_trigger,
};
struct snd_rawmidi *rmidi;
struct snd_rawmidi_str *stream;
struct snd_rawmidi_substream *subs;
@ -100,7 +98,7 @@ int snd_tscm_create_midi_devices(struct snd_tscm *tscm)
rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT;
snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT,
&midi_capture_ops);
&capture_ops);
stream = &rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT];
/* Set port names for MIDI input. */
@ -116,7 +114,7 @@ int snd_tscm_create_midi_devices(struct snd_tscm *tscm)
rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT;
snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT,
&midi_playback_ops);
&playback_ops);
stream = &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT];
/* Set port names for MIDI ourput. */

View File

@ -268,33 +268,31 @@ static snd_pcm_uframes_t pcm_playback_pointer(struct snd_pcm_substream *sbstrm)
return amdtp_stream_pcm_pointer(&tscm->rx_stream);
}
static const struct snd_pcm_ops pcm_capture_ops = {
.open = pcm_open,
.close = pcm_close,
.ioctl = snd_pcm_lib_ioctl,
.hw_params = pcm_capture_hw_params,
.hw_free = pcm_capture_hw_free,
.prepare = pcm_capture_prepare,
.trigger = pcm_capture_trigger,
.pointer = pcm_capture_pointer,
.page = snd_pcm_lib_get_vmalloc_page,
};
static const struct snd_pcm_ops pcm_playback_ops = {
.open = pcm_open,
.close = pcm_close,
.ioctl = snd_pcm_lib_ioctl,
.hw_params = pcm_playback_hw_params,
.hw_free = pcm_playback_hw_free,
.prepare = pcm_playback_prepare,
.trigger = pcm_playback_trigger,
.pointer = pcm_playback_pointer,
.page = snd_pcm_lib_get_vmalloc_page,
.mmap = snd_pcm_lib_mmap_vmalloc,
};
int snd_tscm_create_pcm_devices(struct snd_tscm *tscm)
{
static const struct snd_pcm_ops capture_ops = {
.open = pcm_open,
.close = pcm_close,
.ioctl = snd_pcm_lib_ioctl,
.hw_params = pcm_capture_hw_params,
.hw_free = pcm_capture_hw_free,
.prepare = pcm_capture_prepare,
.trigger = pcm_capture_trigger,
.pointer = pcm_capture_pointer,
.page = snd_pcm_lib_get_vmalloc_page,
};
static const struct snd_pcm_ops playback_ops = {
.open = pcm_open,
.close = pcm_close,
.ioctl = snd_pcm_lib_ioctl,
.hw_params = pcm_playback_hw_params,
.hw_free = pcm_playback_hw_free,
.prepare = pcm_playback_prepare,
.trigger = pcm_playback_trigger,
.pointer = pcm_playback_pointer,
.page = snd_pcm_lib_get_vmalloc_page,
.mmap = snd_pcm_lib_mmap_vmalloc,
};
struct snd_pcm *pcm;
int err;
@ -305,8 +303,8 @@ int snd_tscm_create_pcm_devices(struct snd_tscm *tscm)
pcm->private_data = tscm;
snprintf(pcm->name, sizeof(pcm->name),
"%s PCM", tscm->card->shortname);
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &pcm_playback_ops);
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &pcm_capture_ops);
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &playback_ops);
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &capture_ops);
return 0;
}

View File

@ -227,14 +227,14 @@ static void snd_gf1_uart_output_trigger(struct snd_rawmidi_substream *substream,
spin_unlock_irqrestore(&gus->uart_cmd_lock, flags);
}
static struct snd_rawmidi_ops snd_gf1_uart_output =
static const struct snd_rawmidi_ops snd_gf1_uart_output =
{
.open = snd_gf1_uart_output_open,
.close = snd_gf1_uart_output_close,
.trigger = snd_gf1_uart_output_trigger,
};
static struct snd_rawmidi_ops snd_gf1_uart_input =
static const struct snd_rawmidi_ops snd_gf1_uart_input =
{
.open = snd_gf1_uart_input_open,
.close = snd_gf1_uart_input_close,

View File

@ -142,7 +142,7 @@ void snd_msndmidi_input_read(void *mpuv)
}
EXPORT_SYMBOL(snd_msndmidi_input_read);
static struct snd_rawmidi_ops snd_msndmidi_input = {
static const struct snd_rawmidi_ops snd_msndmidi_input = {
.open = snd_msndmidi_input_open,
.close = snd_msndmidi_input_close,
.trigger = snd_msndmidi_input_trigger,

View File

@ -247,14 +247,14 @@ static void snd_sb8dsp_midi_output_trigger(struct snd_rawmidi_substream *substre
snd_sb8dsp_midi_output_write(substream);
}
static struct snd_rawmidi_ops snd_sb8dsp_midi_output =
static const struct snd_rawmidi_ops snd_sb8dsp_midi_output =
{
.open = snd_sb8dsp_midi_output_open,
.close = snd_sb8dsp_midi_output_close,
.trigger = snd_sb8dsp_midi_output_trigger,
};
static struct snd_rawmidi_ops snd_sb8dsp_midi_input =
static const struct snd_rawmidi_ops snd_sb8dsp_midi_input =
{
.open = snd_sb8dsp_midi_input_open,
.close = snd_sb8dsp_midi_input_close,

View File

@ -559,14 +559,14 @@ snd_wavefront_midi_start (snd_wavefront_card_t *card)
return 0;
}
struct snd_rawmidi_ops snd_wavefront_midi_output =
const struct snd_rawmidi_ops snd_wavefront_midi_output =
{
.open = snd_wavefront_midi_output_open,
.close = snd_wavefront_midi_output_close,
.trigger = snd_wavefront_midi_output_trigger,
};
struct snd_rawmidi_ops snd_wavefront_midi_input =
const struct snd_rawmidi_ops snd_wavefront_midi_input =
{
.open = snd_wavefront_midi_input_open,
.close = snd_wavefront_midi_input_close,

View File

@ -219,6 +219,8 @@ static int hal2_gain_get(struct snd_kcontrol *kcontrol,
l = (tmp >> H2I_C2_L_GAIN_SHIFT) & 15;
r = (tmp >> H2I_C2_R_GAIN_SHIFT) & 15;
break;
default:
return -EINVAL;
}
ucontrol->value.integer.value[0] = l;
ucontrol->value.integer.value[1] = r;
@ -256,6 +258,8 @@ static int hal2_gain_put(struct snd_kcontrol *kcontrol,
new |= (r << H2I_C2_R_GAIN_SHIFT);
hal2_i_write32(hal2, H2I_ADC_C2, new);
break;
default:
return -EINVAL;
}
return old != new;
}

View File

@ -121,11 +121,6 @@ static bool deskpro_xl;
static bool deskpro_m;
static bool soundpro;
static volatile signed char irq2dev[17] = {
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1
};
#ifndef EXCLUDE_TIMERS
static int timer_installed = -1;
#endif
@ -2060,7 +2055,7 @@ int ad1848_init (char *name, struct resource *ports, int irq, int dma_playback,
else
devc->irq_ok = 1; /* Couldn't test. assume it's OK */
} else if (irq < 0)
irq2dev[-irq] = devc->dev_no = my_dev;
devc->dev_no = my_dev;
#ifndef EXCLUDE_TIMERS
if ((capabilities[devc->model].flags & CAP_F_TIMER) &&

View File

@ -255,14 +255,14 @@ static void ca_midi_output_trigger(struct snd_rawmidi_substream *substream, int
}
}
static struct snd_rawmidi_ops ca_midi_output =
static const struct snd_rawmidi_ops ca_midi_output =
{
.open = ca_midi_output_open,
.close = ca_midi_output_close,
.trigger = ca_midi_output_trigger,
};
static struct snd_rawmidi_ops ca_midi_input =
static const struct snd_rawmidi_ops ca_midi_input =
{
.open = ca_midi_input_open,
.close = ca_midi_input_close,

View File

@ -1767,14 +1767,14 @@ static void snd_cs4281_midi_output_trigger(struct snd_rawmidi_substream *substre
spin_unlock_irqrestore(&chip->reg_lock, flags);
}
static struct snd_rawmidi_ops snd_cs4281_midi_output =
static const struct snd_rawmidi_ops snd_cs4281_midi_output =
{
.open = snd_cs4281_midi_output_open,
.close = snd_cs4281_midi_output_close,
.trigger = snd_cs4281_midi_output_trigger,
};
static struct snd_rawmidi_ops snd_cs4281_midi_input =
static const struct snd_rawmidi_ops snd_cs4281_midi_input =
{
.open = snd_cs4281_midi_input_open,
.close = snd_cs4281_midi_input_close,

View File

@ -72,18 +72,18 @@
static void amp_voyetra(struct snd_cs46xx *chip, int change);
#ifdef CONFIG_SND_CS46XX_NEW_DSP
static struct snd_pcm_ops snd_cs46xx_playback_rear_ops;
static struct snd_pcm_ops snd_cs46xx_playback_indirect_rear_ops;
static struct snd_pcm_ops snd_cs46xx_playback_clfe_ops;
static struct snd_pcm_ops snd_cs46xx_playback_indirect_clfe_ops;
static struct snd_pcm_ops snd_cs46xx_playback_iec958_ops;
static struct snd_pcm_ops snd_cs46xx_playback_indirect_iec958_ops;
static const struct snd_pcm_ops snd_cs46xx_playback_rear_ops;
static const struct snd_pcm_ops snd_cs46xx_playback_indirect_rear_ops;
static const struct snd_pcm_ops snd_cs46xx_playback_clfe_ops;
static const struct snd_pcm_ops snd_cs46xx_playback_indirect_clfe_ops;
static const struct snd_pcm_ops snd_cs46xx_playback_iec958_ops;
static const struct snd_pcm_ops snd_cs46xx_playback_indirect_iec958_ops;
#endif
static struct snd_pcm_ops snd_cs46xx_playback_ops;
static struct snd_pcm_ops snd_cs46xx_playback_indirect_ops;
static struct snd_pcm_ops snd_cs46xx_capture_ops;
static struct snd_pcm_ops snd_cs46xx_capture_indirect_ops;
static const struct snd_pcm_ops snd_cs46xx_playback_ops;
static const struct snd_pcm_ops snd_cs46xx_playback_indirect_ops;
static const struct snd_pcm_ops snd_cs46xx_capture_ops;
static const struct snd_pcm_ops snd_cs46xx_capture_indirect_ops;
static unsigned short snd_cs46xx_codec_read(struct snd_cs46xx *chip,
unsigned short reg,
@ -1654,7 +1654,7 @@ static int snd_cs46xx_capture_close(struct snd_pcm_substream *substream)
}
#ifdef CONFIG_SND_CS46XX_NEW_DSP
static struct snd_pcm_ops snd_cs46xx_playback_rear_ops = {
static const struct snd_pcm_ops snd_cs46xx_playback_rear_ops = {
.open = snd_cs46xx_playback_open_rear,
.close = snd_cs46xx_playback_close,
.ioctl = snd_pcm_lib_ioctl,
@ -1665,7 +1665,7 @@ static struct snd_pcm_ops snd_cs46xx_playback_rear_ops = {
.pointer = snd_cs46xx_playback_direct_pointer,
};
static struct snd_pcm_ops snd_cs46xx_playback_indirect_rear_ops = {
static const struct snd_pcm_ops snd_cs46xx_playback_indirect_rear_ops = {
.open = snd_cs46xx_playback_open_rear,
.close = snd_cs46xx_playback_close,
.ioctl = snd_pcm_lib_ioctl,
@ -1677,7 +1677,7 @@ static struct snd_pcm_ops snd_cs46xx_playback_indirect_rear_ops = {
.ack = snd_cs46xx_playback_transfer,
};
static struct snd_pcm_ops snd_cs46xx_playback_clfe_ops = {
static const struct snd_pcm_ops snd_cs46xx_playback_clfe_ops = {
.open = snd_cs46xx_playback_open_clfe,
.close = snd_cs46xx_playback_close,
.ioctl = snd_pcm_lib_ioctl,
@ -1688,7 +1688,7 @@ static struct snd_pcm_ops snd_cs46xx_playback_clfe_ops = {
.pointer = snd_cs46xx_playback_direct_pointer,
};
static struct snd_pcm_ops snd_cs46xx_playback_indirect_clfe_ops = {
static const struct snd_pcm_ops snd_cs46xx_playback_indirect_clfe_ops = {
.open = snd_cs46xx_playback_open_clfe,
.close = snd_cs46xx_playback_close,
.ioctl = snd_pcm_lib_ioctl,
@ -1700,7 +1700,7 @@ static struct snd_pcm_ops snd_cs46xx_playback_indirect_clfe_ops = {
.ack = snd_cs46xx_playback_transfer,
};
static struct snd_pcm_ops snd_cs46xx_playback_iec958_ops = {
static const struct snd_pcm_ops snd_cs46xx_playback_iec958_ops = {
.open = snd_cs46xx_playback_open_iec958,
.close = snd_cs46xx_playback_close_iec958,
.ioctl = snd_pcm_lib_ioctl,
@ -1711,7 +1711,7 @@ static struct snd_pcm_ops snd_cs46xx_playback_iec958_ops = {
.pointer = snd_cs46xx_playback_direct_pointer,
};
static struct snd_pcm_ops snd_cs46xx_playback_indirect_iec958_ops = {
static const struct snd_pcm_ops snd_cs46xx_playback_indirect_iec958_ops = {
.open = snd_cs46xx_playback_open_iec958,
.close = snd_cs46xx_playback_close_iec958,
.ioctl = snd_pcm_lib_ioctl,
@ -1725,7 +1725,7 @@ static struct snd_pcm_ops snd_cs46xx_playback_indirect_iec958_ops = {
#endif
static struct snd_pcm_ops snd_cs46xx_playback_ops = {
static const struct snd_pcm_ops snd_cs46xx_playback_ops = {
.open = snd_cs46xx_playback_open,
.close = snd_cs46xx_playback_close,
.ioctl = snd_pcm_lib_ioctl,
@ -1736,7 +1736,7 @@ static struct snd_pcm_ops snd_cs46xx_playback_ops = {
.pointer = snd_cs46xx_playback_direct_pointer,
};
static struct snd_pcm_ops snd_cs46xx_playback_indirect_ops = {
static const struct snd_pcm_ops snd_cs46xx_playback_indirect_ops = {
.open = snd_cs46xx_playback_open,
.close = snd_cs46xx_playback_close,
.ioctl = snd_pcm_lib_ioctl,
@ -1748,7 +1748,7 @@ static struct snd_pcm_ops snd_cs46xx_playback_indirect_ops = {
.ack = snd_cs46xx_playback_transfer,
};
static struct snd_pcm_ops snd_cs46xx_capture_ops = {
static const struct snd_pcm_ops snd_cs46xx_capture_ops = {
.open = snd_cs46xx_capture_open,
.close = snd_cs46xx_capture_close,
.ioctl = snd_pcm_lib_ioctl,
@ -1759,7 +1759,7 @@ static struct snd_pcm_ops snd_cs46xx_capture_ops = {
.pointer = snd_cs46xx_capture_direct_pointer,
};
static struct snd_pcm_ops snd_cs46xx_capture_indirect_ops = {
static const struct snd_pcm_ops snd_cs46xx_capture_indirect_ops = {
.open = snd_cs46xx_capture_open,
.close = snd_cs46xx_capture_close,
.ioctl = snd_pcm_lib_ioctl,
@ -2683,14 +2683,14 @@ static void snd_cs46xx_midi_output_trigger(struct snd_rawmidi_substream *substre
spin_unlock_irqrestore(&chip->reg_lock, flags);
}
static struct snd_rawmidi_ops snd_cs46xx_midi_output =
static const struct snd_rawmidi_ops snd_cs46xx_midi_output =
{
.open = snd_cs46xx_midi_output_open,
.close = snd_cs46xx_midi_output_close,
.trigger = snd_cs46xx_midi_output_trigger,
};
static struct snd_rawmidi_ops snd_cs46xx_midi_input =
static const struct snd_rawmidi_ops snd_cs46xx_midi_input =
{
.open = snd_cs46xx_midi_input_open,
.close = snd_cs46xx_midi_input_close,

View File

@ -55,7 +55,7 @@ static void snd_cs5535audio_stop_hardware(struct cs5535audio *cs5535au)
}
static int snd_cs5535audio_suspend(struct device *dev)
static int __maybe_unused snd_cs5535audio_suspend(struct device *dev)
{
struct snd_card *card = dev_get_drvdata(dev);
struct cs5535audio *cs5535au = card->private_data;
@ -74,7 +74,7 @@ static int snd_cs5535audio_suspend(struct device *dev)
return 0;
}
static int snd_cs5535audio_resume(struct device *dev)
static int __maybe_unused snd_cs5535audio_resume(struct device *dev)
{
struct snd_card *card = dev_get_drvdata(dev);
struct cs5535audio *cs5535au = card->private_data;

View File

@ -288,13 +288,13 @@ static int snd_echo_midi_output_close(struct snd_rawmidi_substream *substream)
static struct snd_rawmidi_ops snd_echo_midi_input = {
static const struct snd_rawmidi_ops snd_echo_midi_input = {
.open = snd_echo_midi_input_open,
.close = snd_echo_midi_input_close,
.trigger = snd_echo_midi_input_trigger,
};
static struct snd_rawmidi_ops snd_echo_midi_output = {
static const struct snd_rawmidi_ops snd_echo_midi_output = {
.open = snd_echo_midi_output_open,
.close = snd_echo_midi_output_close,
.trigger = snd_echo_midi_output_trigger,

View File

@ -61,7 +61,7 @@ static void set_filterQ(struct snd_emu10k1 *hw, struct snd_emux_voice *vp);
/*
* set up operators
*/
static struct snd_emux_operators emu10k1_ops = {
static const struct snd_emux_operators emu10k1_ops = {
.owner = THIS_MODULE,
.get_voice = get_voice,
.prepare = start_voice,

View File

@ -1486,14 +1486,14 @@ static void snd_emu10k1x_midi_output_trigger(struct snd_rawmidi_substream *subst
*/
static struct snd_rawmidi_ops snd_emu10k1x_midi_output =
static const struct snd_rawmidi_ops snd_emu10k1x_midi_output =
{
.open = snd_emu10k1x_midi_output_open,
.close = snd_emu10k1x_midi_output_close,
.trigger = snd_emu10k1x_midi_output_trigger,
};
static struct snd_rawmidi_ops snd_emu10k1x_midi_input =
static const struct snd_rawmidi_ops snd_emu10k1x_midi_input =
{
.open = snd_emu10k1x_midi_input_open,
.close = snd_emu10k1x_midi_input_close,

View File

@ -308,14 +308,14 @@ static void snd_emu10k1_midi_output_trigger(struct snd_rawmidi_substream *substr
*/
static struct snd_rawmidi_ops snd_emu10k1_midi_output =
static const struct snd_rawmidi_ops snd_emu10k1_midi_output =
{
.open = snd_emu10k1_midi_output_open,
.close = snd_emu10k1_midi_output_close,
.trigger = snd_emu10k1_midi_output_trigger,
};
static struct snd_rawmidi_ops snd_emu10k1_midi_input =
static const struct snd_rawmidi_ops snd_emu10k1_midi_input =
{
.open = snd_emu10k1_midi_input_open,
.close = snd_emu10k1_midi_input_close,

View File

@ -2317,14 +2317,14 @@ static void snd_ensoniq_midi_output_trigger(struct snd_rawmidi_substream *substr
spin_unlock_irqrestore(&ensoniq->reg_lock, flags);
}
static struct snd_rawmidi_ops snd_ensoniq_midi_output =
static const struct snd_rawmidi_ops snd_ensoniq_midi_output =
{
.open = snd_ensoniq_midi_output_open,
.close = snd_ensoniq_midi_output_close,
.trigger = snd_ensoniq_midi_output_trigger,
};
static struct snd_rawmidi_ops snd_ensoniq_midi_input =
static const struct snd_rawmidi_ops snd_ensoniq_midi_input =
{
.open = snd_ensoniq_midi_input_open,
.close = snd_ensoniq_midi_input_close,

View File

@ -861,6 +861,10 @@ static int azx_rirb_get_response(struct hdac_bus *bus, unsigned int addr,
return -EIO;
}
/* no fallback mechanism? */
if (!chip->fallback_to_single_cmd)
return -EIO;
/* a fatal communication error; need either to reset or to fallback
* to the single_cmd mode
*/

View File

@ -150,6 +150,7 @@ struct azx {
int bdl_pos_adj;
int poll_count;
unsigned int running:1;
unsigned int fallback_to_single_cmd:1;
unsigned int single_cmd:1;
unsigned int polling_mode:1;
unsigned int msi:1;

View File

@ -128,7 +128,7 @@ static int bdl_pos_adj[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = -1};
static int probe_mask[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = -1};
static int probe_only[SNDRV_CARDS];
static int jackpoll_ms[SNDRV_CARDS];
static bool single_cmd;
static int single_cmd = -1;
static int enable_msi = -1;
#ifdef CONFIG_SND_HDA_PATCH_LOADER
static char *patch[SNDRV_CARDS];
@ -157,7 +157,7 @@ module_param_array(probe_only, int, NULL, 0444);
MODULE_PARM_DESC(probe_only, "Only probing and no codec initialization.");
module_param_array(jackpoll_ms, int, NULL, 0444);
MODULE_PARM_DESC(jackpoll_ms, "Ms between polling for jack events (default = 0, using unsol events only)");
module_param(single_cmd, bool, 0444);
module_param(single_cmd, bint, 0444);
MODULE_PARM_DESC(single_cmd, "Use single command to communicate with codecs "
"(for debugging only).");
module_param(enable_msi, bint, 0444);
@ -1596,7 +1596,11 @@ static int azx_create(struct snd_card *card, struct pci_dev *pci,
check_probe_mask(chip, dev);
chip->single_cmd = single_cmd;
if (single_cmd < 0) /* allow fallback to single_cmd at errors */
chip->fallback_to_single_cmd = 1;
else /* explicitly set to single_cmd or not */
chip->single_cmd = single_cmd;
azx_check_snoop_available(chip);
if (bdl_pos_adj[dev] < 0)
@ -1774,6 +1778,14 @@ static int azx_first_init(struct azx *chip)
chip->playback_index_offset = chip->capture_streams;
chip->num_streams = chip->playback_streams + chip->capture_streams;
/* sanity check for the SDxCTL.STRM field overflow */
if (chip->num_streams > 15 &&
(chip->driver_caps & AZX_DCAPS_SEPARATE_STREAM_TAG) == 0) {
dev_warn(chip->card->dev, "number of I/O streams is %d, "
"forcing separate stream tags", chip->num_streams);
chip->driver_caps |= AZX_DCAPS_SEPARATE_STREAM_TAG;
}
/* initialize streams */
err = azx_init_streams(chip);
if (err < 0)
@ -2155,7 +2167,20 @@ static void azx_remove(struct pci_dev *pci)
/* cancel the pending probing work */
chip = card->private_data;
hda = container_of(chip, struct hda_intel, chip);
/* FIXME: below is an ugly workaround.
* Both device_release_driver() and driver_probe_device()
* take *both* the device's and its parent's lock before
* calling the remove() and probe() callbacks. The codec
* probe takes the locks of both the codec itself and its
* parent, i.e. the PCI controller dev. Meanwhile, when
* the PCI controller is unbound, it takes its lock, too
* ==> ouch, a deadlock!
* As a workaround, we unlock temporarily here the controller
* device during cancel_work_sync() call.
*/
device_unlock(&pci->dev);
cancel_work_sync(&hda->probe_work);
device_lock(&pci->dev);
snd_card_free(card);
}
@ -2197,9 +2222,9 @@ static const struct pci_device_id azx_ids[] = {
.driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH },
/* Lewisburg */
{ PCI_DEVICE(0x8086, 0xa1f0),
.driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH },
.driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_SKYLAKE },
{ PCI_DEVICE(0x8086, 0xa270),
.driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH },
.driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_SKYLAKE },
/* Lynx Point-LP */
{ PCI_DEVICE(0x8086, 0x9c20),
.driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH },

View File

@ -1482,6 +1482,9 @@ static int dspio_scp(struct hda_codec *codec,
} else if (ret_size != reply_data_size) {
codec_dbg(codec, "RetLen and HdrLen .NE.\n");
return -EINVAL;
} else if (!reply) {
codec_dbg(codec, "NULL reply\n");
return -EINVAL;
} else {
*reply_len = ret_size*sizeof(unsigned int);
memcpy(reply, scp_reply.data, *reply_len);

View File

@ -337,6 +337,7 @@ static void alc_fill_eapd_coef(struct hda_codec *codec)
case 0x10ec0288:
case 0x10ec0295:
case 0x10ec0298:
case 0x10ec0299:
alc_update_coef_idx(codec, 0x10, 1<<9, 0);
break;
case 0x10ec0285:
@ -379,6 +380,7 @@ static void alc_fill_eapd_coef(struct hda_codec *codec)
break;
case 0x10ec0899:
case 0x10ec0900:
case 0x10ec1220:
alc_update_coef_idx(codec, 0x7, 1<<1, 0);
break;
}
@ -912,6 +914,7 @@ static struct alc_codec_rename_pci_table rename_pci_tbl[] = {
{ 0x10ec0256, 0x1028, 0, "ALC3246" },
{ 0x10ec0225, 0x1028, 0, "ALC3253" },
{ 0x10ec0295, 0x1028, 0, "ALC3254" },
{ 0x10ec0299, 0x1028, 0, "ALC3271" },
{ 0x10ec0670, 0x1025, 0, "ALC669X" },
{ 0x10ec0676, 0x1025, 0, "ALC679X" },
{ 0x10ec0282, 0x1043, 0, "ALC3229" },
@ -2309,6 +2312,7 @@ static int patch_alc882(struct hda_codec *codec)
case 0x10ec0882:
case 0x10ec0885:
case 0x10ec0900:
case 0x10ec1220:
break;
default:
/* ALC883 and variants */
@ -3717,6 +3721,7 @@ static void alc_headset_mode_unplugged(struct hda_codec *codec)
break;
case 0x10ec0225:
case 0x10ec0295:
case 0x10ec0299:
alc_process_coef_fw(codec, coef0225);
break;
case 0x10ec0867:
@ -3812,6 +3817,7 @@ static void alc_headset_mode_mic_in(struct hda_codec *codec, hda_nid_t hp_pin,
case 0x10ec0867:
alc_update_coefex_idx(codec, 0x57, 0x5, 0, 1<<14);
/* fallthru */
case 0x10ec0221:
case 0x10ec0662:
snd_hda_set_pin_ctl_cache(codec, hp_pin, 0);
snd_hda_set_pin_ctl_cache(codec, mic_pin, PIN_VREF50);
@ -3824,6 +3830,7 @@ static void alc_headset_mode_mic_in(struct hda_codec *codec, hda_nid_t hp_pin,
break;
case 0x10ec0225:
case 0x10ec0295:
case 0x10ec0299:
alc_update_coef_idx(codec, 0x45, 0x3f<<10, 0x31<<10);
snd_hda_set_pin_ctl_cache(codec, hp_pin, 0);
alc_process_coef_fw(codec, coef0225);
@ -3882,6 +3889,7 @@ static void alc_headset_mode_default(struct hda_codec *codec)
switch (codec->core.vendor_id) {
case 0x10ec0225:
case 0x10ec0295:
case 0x10ec0299:
alc_process_coef_fw(codec, coef0225);
break;
case 0x10ec0255:
@ -3997,6 +4005,7 @@ static void alc_headset_mode_ctia(struct hda_codec *codec)
break;
case 0x10ec0225:
case 0x10ec0295:
case 0x10ec0299:
alc_process_coef_fw(codec, coef0225);
break;
case 0x10ec0867:
@ -4090,6 +4099,7 @@ static void alc_headset_mode_omtp(struct hda_codec *codec)
break;
case 0x10ec0225:
case 0x10ec0295:
case 0x10ec0299:
alc_process_coef_fw(codec, coef0225);
break;
}
@ -4174,6 +4184,7 @@ static void alc_determine_headset_type(struct hda_codec *codec)
break;
case 0x10ec0225:
case 0x10ec0295:
case 0x10ec0299:
alc_process_coef_fw(codec, coef0225);
msleep(800);
val = alc_read_coef_idx(codec, 0x46);
@ -4401,7 +4412,7 @@ static void alc_no_shutup(struct hda_codec *codec)
static void alc_fixup_no_shutup(struct hda_codec *codec,
const struct hda_fixup *fix, int action)
{
if (action == HDA_FIXUP_ACT_PRE_PROBE) {
if (action == HDA_FIXUP_ACT_PROBE) {
struct alc_spec *spec = codec->spec;
spec->shutup = alc_no_shutup;
}
@ -4857,6 +4868,8 @@ enum {
ALC292_FIXUP_TPT460,
ALC298_FIXUP_SPK_VOLUME,
ALC256_FIXUP_DELL_INSPIRON_7559_SUBWOOFER,
ALC269_FIXUP_ATIV_BOOK_8,
ALC221_FIXUP_HP_MIC_NO_PRESENCE,
};
static const struct hda_fixup alc269_fixups[] = {
@ -5529,6 +5542,22 @@ static const struct hda_fixup alc269_fixups[] = {
.chained = true,
.chain_id = ALC255_FIXUP_DELL1_MIC_NO_PRESENCE
},
[ALC269_FIXUP_ATIV_BOOK_8] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc_fixup_auto_mute_via_amp,
.chained = true,
.chain_id = ALC269_FIXUP_NO_SHUTUP
},
[ALC221_FIXUP_HP_MIC_NO_PRESENCE] = {
.type = HDA_FIXUP_PINS,
.v.pins = (const struct hda_pintbl[]) {
{ 0x18, 0x01a1913c }, /* use as headset mic, without its own jack detect */
{ 0x1a, 0x01a1913d }, /* use as headphone mic, without its own jack detect */
{ }
},
.chained = true,
.chain_id = ALC269_FIXUP_HEADSET_MODE
},
};
static const struct snd_pci_quirk alc269_fixup_tbl[] = {
@ -5639,6 +5668,8 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x103c, 0x2337, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
SND_PCI_QUIRK(0x103c, 0x221c, "HP EliteBook 755 G2", ALC280_FIXUP_HP_HEADSET_MIC),
SND_PCI_QUIRK(0x103c, 0x8256, "HP", ALC221_FIXUP_HP_FRONT_MIC),
SND_PCI_QUIRK(0x103c, 0x82bf, "HP", ALC221_FIXUP_HP_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x103c, 0x82c0, "HP", ALC221_FIXUP_HP_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1043, 0x103f, "ASUS TX300", ALC282_FIXUP_ASUS_TX300),
SND_PCI_QUIRK(0x1043, 0x106d, "Asus K53BE", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
SND_PCI_QUIRK(0x1043, 0x115d, "Asus 1015E", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
@ -5665,6 +5696,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x10cf, 0x1757, "Lifebook E752", ALC269_FIXUP_LIFEBOOK_HP_PIN),
SND_PCI_QUIRK(0x10cf, 0x1845, "Lifebook U904", ALC269_FIXUP_LIFEBOOK_EXTMIC),
SND_PCI_QUIRK(0x144d, 0xc109, "Samsung Ativ book 9 (NP900X3G)", ALC269_FIXUP_INV_DMIC),
SND_PCI_QUIRK(0x144d, 0xc740, "Samsung Ativ book 8 (NP870Z5G)", ALC269_FIXUP_ATIV_BOOK_8),
SND_PCI_QUIRK(0x1458, 0xfa53, "Gigabyte BXBT-2807", ALC283_FIXUP_HEADSET_MIC),
SND_PCI_QUIRK(0x1462, 0xb120, "MSI Cubi MS-B120", ALC283_FIXUP_HEADSET_MIC),
SND_PCI_QUIRK(0x17aa, 0x20f2, "Thinkpad SL410/510", ALC269_FIXUP_SKU_IGNORE),
@ -6065,6 +6097,12 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = {
SND_HDA_PIN_QUIRK(0x10ec0298, 0x1028, "Dell", ALC298_FIXUP_DELL1_MIC_NO_PRESENCE,
ALC298_STANDARD_PINS,
{0x17, 0x90170150}),
SND_HDA_PIN_QUIRK(0x10ec0298, 0x1028, "Dell", ALC298_FIXUP_SPK_VOLUME,
{0x12, 0xb7a60140},
{0x13, 0xb7a60150},
{0x17, 0x90170110},
{0x1a, 0x03011020},
{0x21, 0x03211030}),
{}
};
@ -6212,6 +6250,7 @@ static int patch_alc269(struct hda_codec *codec)
break;
case 0x10ec0225:
case 0x10ec0295:
case 0x10ec0299:
spec->codec_variant = ALC269_TYPE_ALC225;
break;
case 0x10ec0234:
@ -7250,6 +7289,7 @@ static const struct hda_device_id snd_hda_id_realtek[] = {
HDA_CODEC_ENTRY(0x10ec0294, "ALC294", patch_alc269),
HDA_CODEC_ENTRY(0x10ec0295, "ALC295", patch_alc269),
HDA_CODEC_ENTRY(0x10ec0298, "ALC298", patch_alc269),
HDA_CODEC_ENTRY(0x10ec0299, "ALC299", patch_alc269),
HDA_CODEC_REV_ENTRY(0x10ec0861, 0x100340, "ALC660", patch_alc861),
HDA_CODEC_ENTRY(0x10ec0660, "ALC660-VD", patch_alc861vd),
HDA_CODEC_ENTRY(0x10ec0861, "ALC861", patch_alc861),
@ -7281,6 +7321,7 @@ static const struct hda_device_id snd_hda_id_realtek[] = {
HDA_CODEC_ENTRY(0x10ec0892, "ALC892", patch_alc662),
HDA_CODEC_ENTRY(0x10ec0899, "ALC898", patch_alc882),
HDA_CODEC_ENTRY(0x10ec0900, "ALC1150", patch_alc882),
HDA_CODEC_ENTRY(0x10ec1220, "ALC1220", patch_alc882),
{} /* terminator */
};
MODULE_DEVICE_TABLE(hdaudio, snd_hda_id_realtek);

View File

@ -166,6 +166,7 @@ enum {
STAC_D965_VERBS,
STAC_DELL_3ST,
STAC_DELL_BIOS,
STAC_NEMO_DEFAULT,
STAC_DELL_BIOS_AMIC,
STAC_DELL_BIOS_SPDIF,
STAC_927X_DELL_DMIC,
@ -1360,6 +1361,27 @@ static const struct hda_pintbl oqo9200_pin_configs[] = {
{}
};
/*
* STAC 92HD700
* 18881000 Amigaone X1000
*/
static const struct hda_pintbl nemo_pin_configs[] = {
{ 0x0a, 0x02214020 }, /* Front panel HP socket */
{ 0x0b, 0x02a19080 }, /* Front Mic */
{ 0x0c, 0x0181304e }, /* Line in */
{ 0x0d, 0x01014010 }, /* Line out */
{ 0x0e, 0x01a19040 }, /* Rear Mic */
{ 0x0f, 0x01011012 }, /* Rear speakers */
{ 0x10, 0x01016011 }, /* Center speaker */
{ 0x11, 0x01012014 }, /* Side speakers (7.1) */
{ 0x12, 0x103301f0 }, /* Motherboard CD line in connector */
{ 0x13, 0x411111f0 }, /* Unused */
{ 0x14, 0x411111f0 }, /* Unused */
{ 0x21, 0x01442170 }, /* S/PDIF line out */
{ 0x22, 0x411111f0 }, /* Unused */
{ 0x23, 0x411111f0 }, /* Unused */
{}
};
static void stac9200_fixup_panasonic(struct hda_codec *codec,
const struct hda_fixup *fix, int action)
@ -3883,6 +3905,10 @@ static const struct hda_fixup stac927x_fixups[] = {
.type = HDA_FIXUP_PINS,
.v.pins = d965_5st_no_fp_pin_configs,
},
[STAC_NEMO_DEFAULT] = {
.type = HDA_FIXUP_PINS,
.v.pins = nemo_pin_configs,
},
[STAC_DELL_3ST] = {
.type = HDA_FIXUP_PINS,
.v.pins = dell_3st_pin_configs,
@ -3939,6 +3965,7 @@ static const struct hda_model_fixup stac927x_models[] = {
{ .id = STAC_D965_5ST_NO_FP, .name = "5stack-no-fp" },
{ .id = STAC_DELL_3ST, .name = "dell-3stack" },
{ .id = STAC_DELL_BIOS, .name = "dell-bios" },
{ .id = STAC_NEMO_DEFAULT, .name = "nemo-default" },
{ .id = STAC_DELL_BIOS_AMIC, .name = "dell-bios-amic" },
{ .id = STAC_927X_VOLKNOB, .name = "volknob" },
{}
@ -3977,6 +4004,8 @@ static const struct snd_pci_quirk stac927x_fixup_tbl[] = {
"Intel D965", STAC_D965_5ST),
SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_INTEL, 0xff00, 0x2500,
"Intel D965", STAC_D965_5ST),
/* Nemo */
SND_PCI_QUIRK(0x1888, 0x1000, "AmigaOne X1000", STAC_NEMO_DEFAULT),
/* volume-knob fixes */
SND_PCI_QUIRK_VENDOR(0x10cf, "FSC", STAC_927X_VOLKNOB),
{} /* terminator */
@ -5036,6 +5065,7 @@ static const struct hda_device_id snd_hda_id_sigmatel[] = {
HDA_CODEC_ENTRY(0x83847683, "STAC9221D A2", patch_stac922x),
HDA_CODEC_ENTRY(0x83847618, "STAC9227", patch_stac927x),
HDA_CODEC_ENTRY(0x83847619, "STAC9227", patch_stac927x),
HDA_CODEC_ENTRY(0x83847638, "STAC92HD700", patch_stac927x),
HDA_CODEC_ENTRY(0x83847616, "STAC9228", patch_stac927x),
HDA_CODEC_ENTRY(0x83847617, "STAC9228", patch_stac927x),
HDA_CODEC_ENTRY(0x83847614, "STAC9229", patch_stac927x),

View File

@ -367,7 +367,7 @@ static void vt1724_midi_output_drain(struct snd_rawmidi_substream *s)
} while (time_after(timeout, jiffies));
}
static struct snd_rawmidi_ops vt1724_midi_output_ops = {
static const struct snd_rawmidi_ops vt1724_midi_output_ops = {
.open = vt1724_midi_output_open,
.close = vt1724_midi_output_close,
.trigger = vt1724_midi_output_trigger,
@ -402,7 +402,7 @@ static void vt1724_midi_input_trigger(struct snd_rawmidi_substream *s, int up)
spin_unlock_irqrestore(&ice->reg_lock, flags);
}
static struct snd_rawmidi_ops vt1724_midi_input_ops = {
static const struct snd_rawmidi_ops vt1724_midi_input_ops = {
.open = vt1724_midi_input_open,
.close = vt1724_midi_input_close,
.trigger = vt1724_midi_input_trigger,

View File

@ -86,7 +86,7 @@ struct mixart_mgr {
u32 msg_fifo[MSG_FIFO_SIZE];
int msg_fifo_readptr;
int msg_fifo_writeptr;
atomic_t msg_processed; /* number of messages to be processed in takslet */
atomic_t msg_processed; /* number of messages to be processed in tasklet */
struct mutex lock; /* interrupt lock */
struct mutex msg_lock; /* mailbox lock */

View File

@ -1510,14 +1510,14 @@ static int snd_hdsp_midi_output_close(struct snd_rawmidi_substream *substream)
return 0;
}
static struct snd_rawmidi_ops snd_hdsp_midi_output =
static const struct snd_rawmidi_ops snd_hdsp_midi_output =
{
.open = snd_hdsp_midi_output_open,
.close = snd_hdsp_midi_output_close,
.trigger = snd_hdsp_midi_output_trigger,
};
static struct snd_rawmidi_ops snd_hdsp_midi_input =
static const struct snd_rawmidi_ops snd_hdsp_midi_input =
{
.open = snd_hdsp_midi_input_open,
.close = snd_hdsp_midi_input_close,

View File

@ -2043,14 +2043,14 @@ static int snd_hdspm_midi_output_close(struct snd_rawmidi_substream *substream)
return 0;
}
static struct snd_rawmidi_ops snd_hdspm_midi_output =
static const struct snd_rawmidi_ops snd_hdspm_midi_output =
{
.open = snd_hdspm_midi_output_open,
.close = snd_hdspm_midi_output_close,
.trigger = snd_hdspm_midi_output_trigger,
};
static struct snd_rawmidi_ops snd_hdspm_midi_input =
static const struct snd_rawmidi_ops snd_hdspm_midi_input =
{
.open = snd_hdspm_midi_input_open,
.close = snd_hdspm_midi_input_close,

View File

@ -269,12 +269,12 @@ static void vx2_dma_write(struct vx_core *chip, struct snd_pcm_runtime *runtime,
/* Transfer using pseudo-dma.
*/
if (offset + count > pipe->buffer_bytes) {
if (offset + count >= pipe->buffer_bytes) {
int length = pipe->buffer_bytes - offset;
count -= length;
length >>= 2; /* in 32bit words */
/* Transfer using pseudo-dma. */
while (length-- > 0) {
for (; length > 0; length--) {
outl(cpu_to_le32(*addr), port);
addr++;
}
@ -284,7 +284,7 @@ static void vx2_dma_write(struct vx_core *chip, struct snd_pcm_runtime *runtime,
pipe->hw_ptr += count;
count >>= 2; /* in 32bit words */
/* Transfer using pseudo-dma. */
while (count-- > 0) {
for (; count > 0; count--) {
outl(cpu_to_le32(*addr), port);
addr++;
}
@ -307,12 +307,12 @@ static void vx2_dma_read(struct vx_core *chip, struct snd_pcm_runtime *runtime,
vx2_setup_pseudo_dma(chip, 0);
/* Transfer using pseudo-dma.
*/
if (offset + count > pipe->buffer_bytes) {
if (offset + count >= pipe->buffer_bytes) {
int length = pipe->buffer_bytes - offset;
count -= length;
length >>= 2; /* in 32bit words */
/* Transfer using pseudo-dma. */
while (length-- > 0)
for (; length > 0; length--)
*addr++ = le32_to_cpu(inl(port));
addr = (u32 *)runtime->dma_area;
pipe->hw_ptr = 0;
@ -320,7 +320,7 @@ static void vx2_dma_read(struct vx_core *chip, struct snd_pcm_runtime *runtime,
pipe->hw_ptr += count;
count >>= 2; /* in 32bit words */
/* Transfer using pseudo-dma. */
while (count-- > 0)
for (; count > 0; count--)
*addr++ = le32_to_cpu(inl(port));
vx2_release_pseudo_dma(chip);

View File

@ -369,12 +369,12 @@ static void vxp_dma_write(struct vx_core *chip, struct snd_pcm_runtime *runtime,
unsigned short *addr = (unsigned short *)(runtime->dma_area + offset);
vx_setup_pseudo_dma(chip, 1);
if (offset + count > pipe->buffer_bytes) {
if (offset + count >= pipe->buffer_bytes) {
int length = pipe->buffer_bytes - offset;
count -= length;
length >>= 1; /* in 16bit words */
/* Transfer using pseudo-dma. */
while (length-- > 0) {
for (; length > 0; length--) {
outw(cpu_to_le16(*addr), port);
addr++;
}
@ -384,7 +384,7 @@ static void vxp_dma_write(struct vx_core *chip, struct snd_pcm_runtime *runtime,
pipe->hw_ptr += count;
count >>= 1; /* in 16bit words */
/* Transfer using pseudo-dma. */
while (count-- > 0) {
for (; count > 0; count--) {
outw(cpu_to_le16(*addr), port);
addr++;
}
@ -411,12 +411,12 @@ static void vxp_dma_read(struct vx_core *chip, struct snd_pcm_runtime *runtime,
if (snd_BUG_ON(count % 2))
return;
vx_setup_pseudo_dma(chip, 0);
if (offset + count > pipe->buffer_bytes) {
if (offset + count >= pipe->buffer_bytes) {
int length = pipe->buffer_bytes - offset;
count -= length;
length >>= 1; /* in 16bit words */
/* Transfer using pseudo-dma. */
while (length-- > 0)
for (; length > 0; length--)
*addr++ = le16_to_cpu(inw(port));
addr = (unsigned short *)runtime->dma_area;
pipe->hw_ptr = 0;
@ -424,7 +424,7 @@ static void vxp_dma_read(struct vx_core *chip, struct snd_pcm_runtime *runtime,
pipe->hw_ptr += count;
count >>= 1; /* in 16bit words */
/* Transfer using pseudo-dma. */
while (count-- > 1)
for (; count > 1; count--)
*addr++ = le16_to_cpu(inw(port));
/* Disable DMA */
pchip->regDIALOG &= ~VXP_DLG_DMAREAD_SEL_MASK;

View File

@ -33,13 +33,13 @@ static int snd_emux_unuse(void *private_data, struct snd_seq_port_subscribe *inf
* MIDI emulation operators
*/
static struct snd_midi_op emux_ops = {
snd_emux_note_on,
snd_emux_note_off,
snd_emux_key_press,
snd_emux_terminate_note,
snd_emux_control,
snd_emux_nrpn,
snd_emux_sysex,
.note_on = snd_emux_note_on,
.note_off = snd_emux_note_off,
.key_press = snd_emux_key_press,
.note_terminate = snd_emux_terminate_note,
.control = snd_emux_control,
.nrpn = snd_emux_nrpn,
.sysex = snd_emux_sysex,
};

View File

@ -139,14 +139,14 @@ static void usb6fire_midi_in_trigger(
spin_unlock_irqrestore(&rt->in_lock, flags);
}
static struct snd_rawmidi_ops out_ops = {
static const struct snd_rawmidi_ops out_ops = {
.open = usb6fire_midi_out_open,
.close = usb6fire_midi_out_close,
.trigger = usb6fire_midi_out_trigger,
.drain = usb6fire_midi_out_drain
};
static struct snd_rawmidi_ops in_ops = {
static const struct snd_rawmidi_ops in_ops = {
.open = usb6fire_midi_in_open,
.close = usb6fire_midi_in_close,
.trigger = usb6fire_midi_in_trigger

View File

@ -252,13 +252,13 @@ static void bcd2000_input_complete(struct urb *urb)
__func__, ret);
}
static struct snd_rawmidi_ops bcd2000_midi_output = {
static const struct snd_rawmidi_ops bcd2000_midi_output = {
.open = bcd2000_midi_output_open,
.close = bcd2000_midi_output_close,
.trigger = bcd2000_midi_output_trigger,
};
static struct snd_rawmidi_ops bcd2000_midi_input = {
static const struct snd_rawmidi_ops bcd2000_midi_input = {
.open = bcd2000_midi_input_open,
.close = bcd2000_midi_input_close,
.trigger = bcd2000_midi_input_trigger,

View File

@ -102,14 +102,14 @@ static void snd_usb_caiaq_midi_output_trigger(struct snd_rawmidi_substream *subs
}
static struct snd_rawmidi_ops snd_usb_caiaq_midi_output =
static const struct snd_rawmidi_ops snd_usb_caiaq_midi_output =
{
.open = snd_usb_caiaq_midi_output_open,
.close = snd_usb_caiaq_midi_output_close,
.trigger = snd_usb_caiaq_midi_output_trigger,
};
static struct snd_rawmidi_ops snd_usb_caiaq_midi_input =
static const struct snd_rawmidi_ops snd_usb_caiaq_midi_input =
{
.open = snd_usb_caiaq_midi_input_open,
.close = snd_usb_caiaq_midi_input_close,

View File

@ -492,42 +492,46 @@ static void line6_destruct(struct snd_card *card)
usb_put_dev(usbdev);
}
/* get data from endpoint descriptor (see usb_maxpacket): */
static void line6_get_interval(struct usb_line6 *line6)
static void line6_get_usb_properties(struct usb_line6 *line6)
{
struct usb_device *usbdev = line6->usbdev;
const struct line6_properties *properties = line6->properties;
int pipe;
struct usb_host_endpoint *ep;
struct usb_host_endpoint *ep = NULL;
if (properties->capabilities & LINE6_CAP_CONTROL_MIDI) {
pipe =
usb_rcvintpipe(line6->usbdev, line6->properties->ep_ctrl_r);
} else {
pipe =
usb_rcvbulkpipe(line6->usbdev, line6->properties->ep_ctrl_r);
if (properties->capabilities & LINE6_CAP_CONTROL) {
if (properties->capabilities & LINE6_CAP_CONTROL_MIDI) {
pipe = usb_rcvintpipe(line6->usbdev,
line6->properties->ep_ctrl_r);
} else {
pipe = usb_rcvbulkpipe(line6->usbdev,
line6->properties->ep_ctrl_r);
}
ep = usbdev->ep_in[usb_pipeendpoint(pipe)];
}
ep = usbdev->ep_in[usb_pipeendpoint(pipe)];
/* Control data transfer properties */
if (ep) {
line6->interval = ep->desc.bInterval;
if (usbdev->speed == USB_SPEED_LOW) {
line6->intervals_per_second = USB_LOW_INTERVALS_PER_SECOND;
line6->iso_buffers = USB_LOW_ISO_BUFFERS;
} else {
line6->intervals_per_second = USB_HIGH_INTERVALS_PER_SECOND;
line6->iso_buffers = USB_HIGH_ISO_BUFFERS;
}
line6->max_packet_size = le16_to_cpu(ep->desc.wMaxPacketSize);
} else {
dev_err(line6->ifcdev,
"endpoint not available, using fallback values");
if (properties->capabilities & LINE6_CAP_CONTROL) {
dev_err(line6->ifcdev,
"endpoint not available, using fallback values");
}
line6->interval = LINE6_FALLBACK_INTERVAL;
line6->max_packet_size = LINE6_FALLBACK_MAXPACKETSIZE;
}
}
/* Isochronous transfer properties */
if (usbdev->speed == USB_SPEED_LOW) {
line6->intervals_per_second = USB_LOW_INTERVALS_PER_SECOND;
line6->iso_buffers = USB_LOW_ISO_BUFFERS;
} else {
line6->intervals_per_second = USB_HIGH_INTERVALS_PER_SECOND;
line6->iso_buffers = USB_HIGH_ISO_BUFFERS;
}
}
/* Enable buffering of incoming messages, flush the buffer */
static int line6_hwdep_open(struct snd_hwdep *hw, struct file *file)
@ -754,7 +758,7 @@ int line6_probe(struct usb_interface *interface,
goto error;
}
line6_get_interval(line6);
line6_get_usb_properties(line6);
if (properties->capabilities & LINE6_CAP_CONTROL) {
ret = line6_init_cap_control(line6);

View File

@ -200,14 +200,14 @@ static void line6_midi_input_trigger(struct snd_rawmidi_substream *substream,
line6->line6midi->substream_receive = NULL;
}
static struct snd_rawmidi_ops line6_midi_output_ops = {
static const struct snd_rawmidi_ops line6_midi_output_ops = {
.open = line6_midi_output_open,
.close = line6_midi_output_close,
.trigger = line6_midi_output_trigger,
.drain = line6_midi_output_drain,
};
static struct snd_rawmidi_ops line6_midi_input_ops = {
static const struct snd_rawmidi_ops line6_midi_input_ops = {
.open = line6_midi_input_open,
.close = line6_midi_input_close,
.trigger = line6_midi_input_trigger,

View File

@ -1234,14 +1234,14 @@ static void snd_usbmidi_input_trigger(struct snd_rawmidi_substream *substream,
clear_bit(substream->number, &umidi->input_triggered);
}
static struct snd_rawmidi_ops snd_usbmidi_output_ops = {
static const struct snd_rawmidi_ops snd_usbmidi_output_ops = {
.open = snd_usbmidi_output_open,
.close = snd_usbmidi_output_close,
.trigger = snd_usbmidi_output_trigger,
.drain = snd_usbmidi_output_drain,
};
static struct snd_rawmidi_ops snd_usbmidi_input_ops = {
static const struct snd_rawmidi_ops snd_usbmidi_input_ops = {
.open = snd_usbmidi_input_open,
.close = snd_usbmidi_input_close,
.trigger = snd_usbmidi_input_trigger

View File

@ -1360,6 +1360,21 @@ u64 snd_usb_interface_dsd_format_quirks(struct snd_usb_audio *chip,
if (fp->altsetting == 3)
return SNDRV_PCM_FMTBIT_DSD_U32_BE;
break;
/* Amanero Combo384 USB interface with native DSD support */
case USB_ID(0x16d0, 0x071a):
if (fp->altsetting == 2) {
switch (chip->dev->descriptor.bcdDevice) {
case 0x199:
return SNDRV_PCM_FMTBIT_DSD_U32_LE;
case 0x19b:
return SNDRV_PCM_FMTBIT_DSD_U32_BE;
default:
break;
}
}
break;
default:
break;
}

15
sound/x86/Kconfig Normal file
View File

@ -0,0 +1,15 @@
menuconfig SND_X86
tristate "X86 sound devices"
depends on X86
---help---
X86 sound devices that don't fall under SoC or PCI categories
if SND_X86
config HDMI_LPE_AUDIO
tristate "HDMI audio without HDaudio on Intel Atom platforms"
depends on DRM_I915
help
Choose this option to support HDMI LPE Audio mode
endif # SND_X86

4
sound/x86/Makefile Normal file
View File

@ -0,0 +1,4 @@
snd-hdmi-lpe-audio-objs += \
intel_hdmi_audio.o
obj-$(CONFIG_HDMI_LPE_AUDIO) += snd-hdmi-lpe-audio.o

1851
sound/x86/intel_hdmi_audio.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,136 @@
/*
* Copyright (C) 2016 Intel Corporation
* Authors: Sailaja Bandarupalli <sailaja.bandarupalli@intel.com>
* Ramesh Babu K V <ramesh.babu@intel.com>
* Vaibhav Agarwal <vaibhav.agarwal@intel.com>
* Jerome Anand <jerome.anand@intel.com>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial
* portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef _INTEL_HDMI_AUDIO_H_
#define _INTEL_HDMI_AUDIO_H_
#include "intel_hdmi_lpe_audio.h"
#define PCM_INDEX 0
#define MAX_PB_STREAMS 1
#define MAX_CAP_STREAMS 0
#define BYTES_PER_WORD 0x4
#define INTEL_HAD "HdmiLpeAudio"
/*
* CEA speaker placement:
*
* FL FLC FC FRC FR
*
* LFE
*
* RL RLC RC RRC RR
*
* The Left/Right Surround channel _notions_ LS/RS in SMPTE 320M
* corresponds to CEA RL/RR; The SMPTE channel _assignment_ C/LFE is
* swapped to CEA LFE/FC.
*/
enum cea_speaker_placement {
FL = (1 << 0), /* Front Left */
FC = (1 << 1), /* Front Center */
FR = (1 << 2), /* Front Right */
FLC = (1 << 3), /* Front Left Center */
FRC = (1 << 4), /* Front Right Center */
RL = (1 << 5), /* Rear Left */
RC = (1 << 6), /* Rear Center */
RR = (1 << 7), /* Rear Right */
RLC = (1 << 8), /* Rear Left Center */
RRC = (1 << 9), /* Rear Right Center */
LFE = (1 << 10), /* Low Frequency Effect */
};
struct cea_channel_speaker_allocation {
int ca_index;
int speakers[8];
/* derived values, just for convenience */
int channels;
int spk_mask;
};
struct channel_map_table {
unsigned char map; /* ALSA API channel map position */
unsigned char cea_slot; /* CEA slot value */
int spk_mask; /* speaker position bit mask */
};
struct pcm_stream_info {
struct snd_pcm_substream *substream;
int substream_refcount;
};
/*
* struct snd_intelhad - intelhad driver structure
*
* @card: ptr to hold card details
* @connected: the monitor connection status
* @stream_info: stream information
* @eld: holds ELD info
* @curr_buf: pointer to hold current active ring buf
* @valid_buf_cnt: ring buffer count for stream
* @had_spinlock: driver lock
* @aes_bits: IEC958 status bits
* @buff_done: id of current buffer done intr
* @dev: platoform device handle
* @chmap: holds channel map info
*/
struct snd_intelhad {
struct snd_card *card;
bool connected;
struct pcm_stream_info stream_info;
unsigned char eld[HDMI_MAX_ELD_BYTES];
bool dp_output;
unsigned int aes_bits;
spinlock_t had_spinlock;
struct device *dev;
struct snd_pcm_chmap *chmap;
int tmds_clock_speed;
int link_rate;
/* ring buffer (BD) position index */
unsigned int bd_head;
/* PCM buffer position indices */
unsigned int pcmbuf_head; /* being processed */
unsigned int pcmbuf_filled; /* to be filled */
unsigned int num_bds; /* number of BDs */
unsigned int period_bytes; /* PCM period size in bytes */
/* internal stuff */
int irq;
void __iomem *mmio_start;
unsigned int had_config_offset;
union aud_cfg aud_config; /* AUD_CONFIG reg value cache */
struct work_struct hdmi_audio_wq;
struct mutex mutex; /* for protecting chmap and eld */
bool need_reset;
struct snd_jack *jack;
};
#endif /* _INTEL_HDMI_AUDIO_ */

View File

@ -0,0 +1,328 @@
/*
* intel_hdmi_lpe_audio.h - Intel HDMI LPE audio driver
*
* Copyright (C) 2016 Intel Corp
* Authors: Sailaja Bandarupalli <sailaja.bandarupalli@intel.com>
* Ramesh Babu K V <ramesh.babu@intel.com>
* Vaibhav Agarwal <vaibhav.agarwal@intel.com>
* Jerome Anand <jerome.anand@intel.com>
* Aravind Siddappaji <aravindx.siddappaji@intel.com>
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/
#ifndef __INTEL_HDMI_LPE_AUDIO_H
#define __INTEL_HDMI_LPE_AUDIO_H
#define HAD_MIN_CHANNEL 2
#define HAD_MAX_CHANNEL 8
#define HAD_NUM_OF_RING_BUFS 4
/* max 20bit address, aligned to 64 */
#define HAD_MAX_BUFFER ((1024 * 1024 - 1) & ~0x3f)
#define HAD_DEFAULT_BUFFER (600 * 1024) /* default prealloc size */
#define HAD_MAX_PERIODS 256 /* arbitrary, but should suffice */
#define HAD_MIN_PERIODS 1
#define HAD_MAX_PERIOD_BYTES ((HAD_MAX_BUFFER / HAD_MIN_PERIODS) & ~0x3f)
#define HAD_MIN_PERIOD_BYTES 1024 /* might be smaller */
#define HAD_FIFO_SIZE 0 /* fifo not being used */
#define MAX_SPEAKERS 8
#define AUD_SAMPLE_RATE_32 32000
#define AUD_SAMPLE_RATE_44_1 44100
#define AUD_SAMPLE_RATE_48 48000
#define AUD_SAMPLE_RATE_88_2 88200
#define AUD_SAMPLE_RATE_96 96000
#define AUD_SAMPLE_RATE_176_4 176400
#define AUD_SAMPLE_RATE_192 192000
#define HAD_MIN_RATE AUD_SAMPLE_RATE_32
#define HAD_MAX_RATE AUD_SAMPLE_RATE_192
#define DIS_SAMPLE_RATE_25_2 25200
#define DIS_SAMPLE_RATE_27 27000
#define DIS_SAMPLE_RATE_54 54000
#define DIS_SAMPLE_RATE_74_25 74250
#define DIS_SAMPLE_RATE_148_5 148500
#define HAD_REG_WIDTH 0x08
#define HAD_MAX_DIP_WORDS 16
/* DP Link Rates */
#define DP_2_7_GHZ 270000
#define DP_1_62_GHZ 162000
/* Maud Values */
#define AUD_SAMPLE_RATE_32_DP_2_7_MAUD_VAL 1988
#define AUD_SAMPLE_RATE_44_1_DP_2_7_MAUD_VAL 2740
#define AUD_SAMPLE_RATE_48_DP_2_7_MAUD_VAL 2982
#define AUD_SAMPLE_RATE_88_2_DP_2_7_MAUD_VAL 5480
#define AUD_SAMPLE_RATE_96_DP_2_7_MAUD_VAL 5965
#define AUD_SAMPLE_RATE_176_4_DP_2_7_MAUD_VAL 10961
#define HAD_MAX_RATE_DP_2_7_MAUD_VAL 11930
#define AUD_SAMPLE_RATE_32_DP_1_62_MAUD_VAL 3314
#define AUD_SAMPLE_RATE_44_1_DP_1_62_MAUD_VAL 4567
#define AUD_SAMPLE_RATE_48_DP_1_62_MAUD_VAL 4971
#define AUD_SAMPLE_RATE_88_2_DP_1_62_MAUD_VAL 9134
#define AUD_SAMPLE_RATE_96_DP_1_62_MAUD_VAL 9942
#define AUD_SAMPLE_RATE_176_4_DP_1_62_MAUD_VAL 18268
#define HAD_MAX_RATE_DP_1_62_MAUD_VAL 19884
/* Naud Value */
#define DP_NAUD_VAL 32768
/* HDMI Controller register offsets - audio domain common */
/* Base address for below regs = 0x65000 */
enum hdmi_ctrl_reg_offset_common {
AUDIO_HDMI_CONFIG_A = 0x000,
AUDIO_HDMI_CONFIG_B = 0x800,
AUDIO_HDMI_CONFIG_C = 0x900,
};
/* HDMI controller register offsets */
enum hdmi_ctrl_reg_offset {
AUD_CONFIG = 0x0,
AUD_CH_STATUS_0 = 0x08,
AUD_CH_STATUS_1 = 0x0C,
AUD_HDMI_CTS = 0x10,
AUD_N_ENABLE = 0x14,
AUD_SAMPLE_RATE = 0x18,
AUD_BUF_CONFIG = 0x20,
AUD_BUF_CH_SWAP = 0x24,
AUD_BUF_A_ADDR = 0x40,
AUD_BUF_A_LENGTH = 0x44,
AUD_BUF_B_ADDR = 0x48,
AUD_BUF_B_LENGTH = 0x4c,
AUD_BUF_C_ADDR = 0x50,
AUD_BUF_C_LENGTH = 0x54,
AUD_BUF_D_ADDR = 0x58,
AUD_BUF_D_LENGTH = 0x5c,
AUD_CNTL_ST = 0x60,
AUD_HDMI_STATUS = 0x64, /* v2 */
AUD_HDMIW_INFOFR = 0x68, /* v2 */
};
/* Audio configuration */
union aud_cfg {
struct {
u32 aud_en:1;
u32 layout:1; /* LAYOUT[01], see below */
u32 fmt:2;
u32 num_ch:3;
u32 set:1;
u32 flat:1;
u32 val_bit:1;
u32 user_bit:1;
u32 underrun:1; /* 0: send null packets,
* 1: send silence stream
*/
u32 packet_mode:1; /* 0: 32bit container, 1: 16bit */
u32 left_align:1; /* 0: MSB bits 0-23, 1: bits 8-31 */
u32 bogus_sample:1; /* bogus sample for odd channels */
u32 dp_modei:1; /* 0: HDMI, 1: DP */
u32 rsvd:16;
} regx;
u32 regval;
};
#define AUD_CONFIG_VALID_BIT (1 << 9)
#define AUD_CONFIG_DP_MODE (1 << 15)
#define AUD_CONFIG_CH_MASK 0x70
#define LAYOUT0 0 /* interleaved stereo */
#define LAYOUT1 1 /* for channels > 2 */
/* Audio Channel Status 0 Attributes */
union aud_ch_status_0 {
struct {
u32 ch_status:1;
u32 lpcm_id:1;
u32 cp_info:1;
u32 format:3;
u32 mode:2;
u32 ctg_code:8;
u32 src_num:4;
u32 ch_num:4;
u32 samp_freq:4; /* CH_STATUS_MAP_XXX */
u32 clk_acc:2;
u32 rsvd:2;
} regx;
u32 regval;
};
/* samp_freq values - Sampling rate as per IEC60958 Ver 3 */
#define CH_STATUS_MAP_32KHZ 0x3
#define CH_STATUS_MAP_44KHZ 0x0
#define CH_STATUS_MAP_48KHZ 0x2
#define CH_STATUS_MAP_88KHZ 0x8
#define CH_STATUS_MAP_96KHZ 0xA
#define CH_STATUS_MAP_176KHZ 0xC
#define CH_STATUS_MAP_192KHZ 0xE
/* Audio Channel Status 1 Attributes */
union aud_ch_status_1 {
struct {
u32 max_wrd_len:1;
u32 wrd_len:3;
u32 rsvd:28;
} regx;
u32 regval;
};
#define MAX_SMPL_WIDTH_20 0x0
#define MAX_SMPL_WIDTH_24 0x1
#define SMPL_WIDTH_16BITS 0x1
#define SMPL_WIDTH_24BITS 0x5
/* CTS register */
union aud_hdmi_cts {
struct {
u32 cts_val:24;
u32 en_cts_prog:1;
u32 rsvd:7;
} regx;
u32 regval;
};
/* N register */
union aud_hdmi_n_enable {
struct {
u32 n_val:24;
u32 en_n_prog:1;
u32 rsvd:7;
} regx;
u32 regval;
};
/* Audio Buffer configurations */
union aud_buf_config {
struct {
u32 audio_fifo_watermark:8;
u32 dma_fifo_watermark:3;
u32 rsvd0:5;
u32 aud_delay:8;
u32 rsvd1:8;
} regx;
u32 regval;
};
#define FIFO_THRESHOLD 0xFE
#define DMA_FIFO_THRESHOLD 0x7
/* Audio Sample Swapping offset */
union aud_buf_ch_swap {
struct {
u32 first_0:3;
u32 second_0:3;
u32 first_1:3;
u32 second_1:3;
u32 first_2:3;
u32 second_2:3;
u32 first_3:3;
u32 second_3:3;
u32 rsvd:8;
} regx;
u32 regval;
};
#define SWAP_LFE_CENTER 0x00fac4c8 /* octal 76543210 */
/* Address for Audio Buffer */
union aud_buf_addr {
struct {
u32 valid:1;
u32 intr_en:1;
u32 rsvd:4;
u32 addr:26;
} regx;
u32 regval;
};
#define AUD_BUF_VALID (1U << 0)
#define AUD_BUF_INTR_EN (1U << 1)
/* Length of Audio Buffer */
union aud_buf_len {
struct {
u32 buf_len:20;
u32 rsvd:12;
} regx;
u32 regval;
};
/* Audio Control State Register offset */
union aud_ctrl_st {
struct {
u32 ram_addr:4;
u32 eld_ack:1;
u32 eld_addr:4;
u32 eld_buf_size:5;
u32 eld_valid:1;
u32 cp_ready:1;
u32 dip_freq:2;
u32 dip_idx:3;
u32 dip_en_sta:4;
u32 rsvd:7;
} regx;
u32 regval;
};
/* Audio HDMI Widget Data Island Packet offset */
union aud_info_frame1 {
struct {
u32 pkt_type:8;
u32 ver_num:8;
u32 len:5;
u32 rsvd:11;
} regx;
u32 regval;
};
#define HDMI_INFO_FRAME_WORD1 0x000a0184
#define DP_INFO_FRAME_WORD1 0x00441b84
/* DIP frame 2 */
union aud_info_frame2 {
struct {
u32 chksum:8;
u32 chnl_cnt:3;
u32 rsvd0:1;
u32 coding_type:4;
u32 smpl_size:2;
u32 smpl_freq:3;
u32 rsvd1:3;
u32 format:8;
} regx;
u32 regval;
};
/* DIP frame 3 */
union aud_info_frame3 {
struct {
u32 chnl_alloc:8;
u32 rsvd0:3;
u32 lsv:4;
u32 dm_inh:1;
u32 rsvd1:16;
} regx;
u32 regval;
};
#define VALID_DIP_WORDS 3
/* AUD_HDMI_STATUS bits */
#define HDMI_AUDIO_UNDERRUN (1U << 31)
#define HDMI_AUDIO_BUFFER_DONE (1U << 29)
/* AUD_HDMI_STATUS register mask */
#define AUD_HDMI_STATUS_MASK_UNDERRUN 0xC0000000
#define AUD_HDMI_STATUS_MASK_SRDBG 0x00000002
#define AUD_HDMI_STATUSG_MASK_FUNCRST 0x00000001
#endif